Решили: дуэли за меню собираются из реликвий напрямую (RelicData : UnitData — реликвия и есть боец), состав приезжает заказом ProvingGroundsSetupRequest после рождения скоупа, а пресет играет роль НОСИТЕЛЯ: даёт арену и DeploymentMode.Fixed, без которого бой остался бы на паузе расстановки. Десять пар зеркальны по ролям (танк+дальний против танк+дальний и так далее), треш-киты исключены.

Почему: «самые равные» без прогона бенча даёт именно зеркало ролей — базу стат-каскада несёт боевой класс, поэтому две стороны одного ролевого набора близки по силе по построению. Отвергнут состав через _roster самого пресета: тогда на каждую дуэль нужен свой пресет, то есть десять ассетов вместо десяти строк в одном.

Сказано: «просто сделай дуэли 2х2 у уникальных реликов. 10 таких вот 2х2 дуэлей… Самые близкие 2х2 дуэли между реликами хорошего качества (а не треш)» (04.08.2026, сессия ca460396).

Грабли:

  • Боевой скоуп НЕ самодостаточен. DeploymentController внутри него резолвит IBattleSession, а та живёт в скоупе мероприятия. Подъём боя мимо мероприятия даёт VContainerException: No such registration of type IBattleSession — и арена остаётся пустой без единой ошибки в игровой логике. Лечится регистрацией BattleSession прямо в дочернем скоупе.
  • Ассет держит СТАРУЮ схему, пока Unity не пересобрал класс. После правки полей SO FindProperty("_carrierPreset") возвращает null, а запись падает NullReferenceException — сначала refresh_unity(compile), потом правка ассета.
  • Заказ состава публикуется ПОСЛЕ рождения скоупа — расстановка подписывается внутри него. Обратный порядок и есть та самая готча «заказ раньше адресата»: сообщение уходит в пустоту, а площадка встаёт раскладом из своего ассета.

Владелец правды: Data/Definitions/MenuBattleConfig.cs, Game/Flow/MenuBattleDirector.cs, ассеты ScriptableObjects/Configs/MenuBattleConfig.asset и BattlePresets/PresetMenuDuel.asset.