Решили: гейт готовности объявляет срабатывание отдельным признаком (Fired) и вместе с ключом
действия — по шине и по проводу. Экран итога боя закрывается по этому признаку, а не по нажатию
кнопки; сама кнопка показывает «Продолжить (N/M)».
Почему: счёт обнуляется в двух совершенно разных случаях — когда согласие собралось и действие произошло, и когда его сбросили (кто-то переставил бойца). Вывести одно из другого нельзя, а разница видимая: на первом экран обязан закрыться, на втором — остаться. Ключ едет рядом, потому что счёт одного действия не должен рисоваться на кнопке другого.
Грабли:
- Экран закрывался по нажатию, и вдвоём это оставляло игрока ни с чем. Подтвердивший первым терял экран, а расстановка ещё не вернулась: ни кнопок, ни экрана, только поле с трупами. В соло дефект невидим полностью — он существует ровно при двух игроках.
- Первое объявление счёта приходит раньше, чем экран заказан: гейт объявляет его в момент привязки действия. Подписка на время показа это объявление пропускала, и кнопка открывалась без «(N/M)», получая счёт только со второго нажатия. Поэтому подписка живёт столько же, сколько роутер, и он же помнит последнее объявление. Тот же класс, что «заказ раньше своего адресата».
- Тест на «сброс — не срабатывание» нельзя писать в соло: там любое согласие срабатывает мгновенно, и отличить одно от другого на таком материале невозможно в принципе. Проверяется на двух участниках.
- Поле, которое только присваивается, — дефект по нашим же правилам. Подписка роутера заставила
сделать его
IDisposable; вызывает Dispose контейнер, своей строки вызова нет.
Владелец правды: ReadyGateChangedEvent, HostReadyGate.Announce, MenuRouter.ShowOutcomeAsync,
OutcomeScreenView.SetContinueCount, тест ReadyGateTests.Firing_IsAnnouncedApartFromReset.