Решили: на Ристалище игрок распоряжается ОБЕИМИ сторонами, в PvP — только своей; разницу решает единственный флаг мероприятия. «Начать бой» стало общим согласием: действие происходит, когда его подтвердили все игроки сессии, и кнопка показывает «(N/M)». После боя на площадке — выбор «Продолжить тем же составом» или «В главное меню».

Почему: временный режим Ристалища и PvP описан Максом так, что различаются они ровно правами на расстановку — а ActivitySetup уже нёс ровно эти два флага (OwnUnitsOnly, HideOpponent) с 02.08.2026, когда было решено не заводить PvP отдельным видом. Оба флага не читал никто: расстановка жёстко знала «команда 0» в семи местах, и PvP был неотличим от Ристалища ни в чём, кроме имени. Заводить второй режим было незачем — надо было подключить то, что уже описано.

Согласие сделано ОБЩИМ механизмом, а не деталью PvP: его требуют и «Начать», и «Продолжить», и то же понадобится в кампании. Три похожих счётчика разошлись бы, а расхождение здесь читается как зависшая кнопка.

Сказано: «В ристалище - мы можем двигать веселлы из каждой команды, мы можем надевать на них сами релики и тд / В пвп - аналогично, но лишь свою команду … Также различные действия “Начать бой” или “Продолжить” должны требоввать нажатия всех игроков в сессии.» (03.08.2026, сессия 272cfad5). «4 base релика. У нас ведь так и есть в кампании» — про состав по умолчанию, там же.

Грабли:

  • Ассет расклада вернулся, но ПОСЛЕДНИМ. 02.08.2026 его убрали не за расклад, а за то, что он срабатывал первым и перебивал заказанный дев-срезом состав. Порядок «заказ → расклад этого захода → ассет» держит оба требования разом; поставь ассет обратно первым — вернётся ровно прежний баг.
  • Слоты появились и у противника, и это чуть не сломало пересборку. Превью собиралось из ВСЕХ слотов в одну сторону: перетаскивание врага отправило бы его в команду 0 и превратило бой в восемь своих. Разбор по командам обязателен и в пересборке, и в сопоставлении живых юнитов.
  • Согласие сбрасывается при любой правке расстановки. Иначе второй игрок подтверждает один строй, а в бой уходит другой.
  • Уход игрока не подвешивает кнопку: вышедший перестаёт быть участником, и оставшиеся тут же оказываются «всеми». Кнопка, которую нельзя нажать из-за вышедшего, зависает без видимой причины.
  • Счёт едет сообщением, а не подпиской на гейт. Гейт живёт в сеансе и умирает вместе с ним, а топбар переживает несколько сеансов: подписка на объект короче собственной жизни — либо утечка, либо отписка в чужой момент.
  • «Продолжить» и закрытие экрана — разные исходы. Слить их значило бы уводить в меню того, кто хотел переиграть.

Владелец правды: DeploymentController (CanCommand, StageProvingGrounds, BindLiveUnits, ShowGroundsOutcome), HostReadyGate / GuestReadyGate, IReadyGate, ProvingGroundsConfig.asset, тесты ReadyGateTests.