Перейти к основному содержимому

Архитектура боевой системы

Боевая система MCE построена на модульной компонентной архитектуре. BattleManager находится на одном GameObject вместе с 15 специализированными модулями, каждый из которых отвечает за один аспект боя. BattleStateMachine управляет циклом ходов, а вся система связана через внедрение зависимостей Zenject.

Сражение в процессе

Всё на этом экране — отчёт отдельного модуля: две полосы здоровья, меню действий, спрайты и анимация их появления, а также порядок ходов, определивший, кто ходит первым. BattleManager ничем из этого не владеет напрямую — он по очереди обращается к каждому модулю, а цикл сражения решает, что будет дальше.

Обзор архитектуры​

BattleLauncher (ScriptableObject, loads the battle scene)
└─ BattleManager (orchestrator, on the battle scene's GameObject)
├─ BattleStateMachine (turn loop)
├─ BattleManagerBattlersModule (battler lookup, sprites, forms)
├─ BattleManagerHealthModule (HP, fainting)
├─ BattleManagerMovesModule (move execution)
├─ BattleManagerItemsModule (in-battle items)
├─ BattleManagerCaptureModule (catch mechanics)
├─ BattleManagerAIModule (enemy decisions)
├─ BattleManagerAnimationModule (intro and flow animations)
├─ BattleManagerAudioModule (music, SFX)
├─ BattleManagerStatusesModule (burn, poison, sleep, field effects...)
├─ BattleManagerBattlerStatsModule (stat stages)
├─ BattleManagerBattlerSwitchModule (party switching)
├─ BattleManagerRostersModule (party management)
├─ BattleManagerScenariosModule (weather, terrain, scenario setup)
├─ BattleManagerMegaModule (Mega Evolution)
└─ BattleManagerCharactersModule (trainer characters and sprites)

BattleManager​

BattleManager — центральный координатор. Он сам не содержит боевой логики, а делегирует её своим модулям. Его обязанности:

  • Инициализировать все модули в начале сражения.
  • Предоставлять общую точку отсчёта для взаимодействия модулей (каждый модуль обращается к соседям через него).
  • Принимать команды от интерфейса (действия игрока) и от ИИ (действия противника).
  • Сигнализировать о событиях начала и конца сражения.

BattleManager реализует IBattleManager. Он предоставляет BattleType (SingleBattle или DoubleBattle) и EnemyType (Wild или Trainer) текущего сражения. Его члены описаны в API BattleManager.

BattleStateMachine​

BattleStateMachine — это один цикл-корутина. Каждый ход он:

Update which battlers have fought
→ Request actions (the player's menu, the AI of every other roster)
→ Determine the order (move priority, then speed)
→ Perform the actions
→ After-turn callbacks (before and after the status countdown)
→ Status countdown (weather, burn, poison...)
→ Check and process fainted battlers (XP, replacements)
→ [next turn]

пока не наступит IsBattleOver. Затем он проигрывает конечную анимацию, выдаёт призовые деньги (или забирает деньги за поражение) и запускает обратные вызовы конца сражения. Когда сражение серверно-авторитетно (MCE Online), ход разрешает сервер, а не локальная сторона: цикл отправляет действия и показывает то, что вернулось.

Подробно о боевых модулях​

BattleManagerBattlersModule​

Управляет экземплярами Battler обеих сторон. Battler расширяет MonsterInstance состоянием в сражении:

  • Ступени характеристик (StatStage, BattleStatStage), ступень критического удара, заместитель, изменчивые статусы.
  • Список бойцов, с которыми он сражался, потреблённые предметы, последний применённый и полученный приём.
  • Эффективные характеристики (база + IV + EV + характер + ступени характеристик) через MonsterMathHelper.

BattleManagerHealthModule​

Обрабатывает все изменения HP через ChangeLife (урон и лечение, с анимацией и звуком удара), а также обнаружение и обработку потерявших сознание бойцов.

BattleManagerMovesModule​

Выполняет приёмы (PerformMove): проверки точности и уклонения, эффекты приёма и его анимацию. Сам урон вычисляется приёмом (DamageMove) по формуле из раздела Приёмы.

BattleManagerItemsModule​

Использование предметов в сражении — лечебные предметы, снятие статусов, предметы X — с расходом из сумки игрока. У тренеров есть собственная Bag.

BattleManagerCaptureModule​

Поимка диких монстров (TryCaptureMonster):

  • Расчёт шанса поимки на основе коэффициента поимки вида, текущего HP, статусного состояния и мяча (BattleUtils.CalculateShakeProbability).
  • Анимация покачивания мяча с несколькими проверками покачивания перед поимкой или побегом.
  • Добавляет пойманного монстра в команду или хранилище игрока.

BattleManagerAIModule​

Хранит по одной подключаемой стратегии BattleAI на каждую команду:

  • Получает текущее состояние сражения.
  • Возвращает BattleAction (применить приём, сменить, использовать предмет, убежать).
  • Встроенные стратегии и способы их объединения или написания — в разделе ИИ сражений.

BattleManagerStatusesModule​

Управляет всеми видами статусов:

  • Статусные состояния (по одному на бойца): ожог, заморозка, паралич, яд, сильный яд, сон.
  • Изменчивые статусы (VolatileStatus, на бойце): замешательство, вздрагивание, ловушка и другие.
  • Статусы стороны (SideStatus) и глобальные статусы (GlobalStatus) для эффектов, покрывающих одну сторону поля или всё поле. Погода и местность сражения относятся к сценарию (BattleManagerScenariosModule).

Каждый статус применяет свои эффекты в нужный момент хода через TriggerStatusesCountdown и обратные вызовы вокруг него (например, урон от ожога в конце хода, паралич перед приёмом).

BattleManagerBattlerStatsModule​

Обрабатывает изменения ступеней характеристик:

  • Ступени характеристик лежат в диапазоне от -6 до +6.
  • Ступени Атаки, Защиты, Спец. атаки, Спец. защиты и Скорости применяют множитель: +1 = 1,5x, +2 = 2,0x, ... +6 = 4,0x и -1 = 0,67x, -2 = 0,5x, ... -6 = 0,25x. Точность и уклонение используют собственную таблицу.
  • Способности могут реагировать на изменения ступеней (у Battler есть хуки OnStatChange и AfterStatChanged).

BattleManagerMegaModule​

Поддержка Мега-эволюции:

  • Проверяет, доступна ли у вида бойца форма Mega (CanSwitchToMegaForm).
  • Разрешает одну Мега-эволюцию на команду за сражение.
  • Проигрывает смену формы и применяет данные формы Mega.

BattleManagerCharactersModule​

Предоставляет каждой стороне её персонажей: спрайты тренеров (BattleTrainerSprite), призовые деньги и деньги за поражение. О том, как рисуется и анимируется спина игрока, см. Спрайты тренера со спины и бросок.

Пример хода сражения​

Вот что происходит, когда игрок выбирает «Fight» и указывает приём:

  1. Request actions -- Игрок выбирает приём на панели приёмов, а ИИ выбирает за другую команду.
  2. Порядок -- Все действия сортируются по приоритету приёма, затем по Скорости (выше — раньше, со случайным разрешением ничьей).
  3. Выполнение приёма (для более быстрого бойца):
    • Проверка точности — попадает ли приём?
    • Расчёт урона (если приём наносит урон): ((2*Level/5+2) * Power * Atk/Def) / 50 + 2
    • Применение множителей: число целей, погода, местность, критический удар, случайный бросок (0,85-1,0), STAB, эффективность типа, статус и добавки от способностей, предметов и статусов стороны.
    • Применение побочных эффектов (изменения характеристик, статусные состояния).
  4. Выполнение приёма (для более медленного бойца, если он ещё стоит).
  5. Обратные вызовы конца хода и обратный отсчёт статусов -- Урон от погоды и статусов, эффекты удерживаемых предметов, срабатывание способностей.
  6. Обработка потери сознания -- Если у бойца 0 HP, обрабатывается потеря сознания (выдача XP/EV, проверка эволюции) и запрашиваются замены.

Дикие сражения и сражения с тренерами​

АспектДикое сражениеСражение с тренером
EnemyTypeWildTrainer
ПоимкаДаНет
БегствоДа, если ни один сражающийся противник не является альфой (CanPlayerRun)Нет
Призовые деньгиНетДа
ИИИИ лаунчера по умолчанию, если сражение не приносит свойТот же
РеваншСлучайная встречаСкриптовый (CommandGraph)

Боевая башня и анонимные тренеры​

Battle Tower в меню паузы (TowerController) запускает бесконечную PvE-прогрессию: она проверяет команду игрока по TowerRuleSet, запускает сражение со сгенерированным противником с ИИ через IBattleLauncher, а из собственного обратного вызова конца этого сражения применяет результат и запускает следующий бой — до первого поражения. Игровой процесс и баланс по умолчанию описаны в руководстве Секретные базы и залы игрока.

Противники башни анонимны: они генерируются из ссылок на команду игрока, у них нет ни CharacterData, ни Bag. Боевая система терпит таких тренеров, а не выбрасывает исключение:

  • BattleManagerCharactersModule защищает набор спрайтов вражеского тренера — null в CharacterData означает, что команда по-прежнему сражается, просто без спрайта тренера (и не приносит призовых денег).
  • BattleManagerItemsModule подставляет пустую Bag вместо null-сумки противника, так что ИИ получает допустимую сумку без предметов.

Именно это позволяет сгенерированному противнику без сцены и без личности сражаться точно так же, как созданному вручную тренеру.

Конфигурация сражения​

Сражения настраивают два слоя:

  • BattleConfigurationFile (Create > MCE > Battle > Configuration) хранит боевые настройки для игрока: Battle Style и Battle Animation Speed Up (от 1 до 8). Он читается через BattleManager.Configuration, и отсюда берётся BattleSpeed.
  • Ассет BattleLauncher хранит сцену сражения, боевую музыку диких сражений и сражений с тренерами, а также Default AI.

Правила сложности поимки и опыта находятся в ассете MCESettings и глобальных данных игры.

Подписка на события сражения​

Без исходного кода​

Лаунчер сражений привязан во внедрении зависимостей и уведомляет, когда сражение запущено, вот-вот выгрузится и завершилось:

[Inject] private IBattleLauncher battleLauncher;

battleLauncher.SubscribeToBattleLaunched(() => Debug.Log("Battle launched"));
battleLauncher.SubscribeToBattleEnded(result => Debug.Log($"Battle ended, won: {result.PlayerWon}"));

IBattleSystem (engine.Battle, с OnBattleStarted и OnBattleEnded) — собственный контракт SDK, но движок пока его не питает: см. IBattleSystem.

С исходным кодом (редакции Source и Studio)​

С доступом к исходному коду можно подписаться через BattleManager.SubscribeToBattleInitialized и SubscribeToBattleFinished или добавить собственный модуль рядом с BattleManager (см. Внутреннее устройство сражений).