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

BattleManager

MonoBehaviour, который управляет отдельным боем монстров. BattleManager — это тонкий координатор: реальная работа распределена между 15+ модулями (каждый — собственный MonoBehaviour на том же GameObject), а поток ходов ведёт BattleStateMachine. Это карта уровня Source этой архитектуры.

Namespace: OpenMon.MCE.Battle

Поверхность SDK против Source

В большинстве интеграций вы не работаете с BattleManager напрямую — вы наблюдаете за боями через доступный только для чтения интерфейс SDK IBattleSystem (события, текущее состояние). Приведённые ниже члены — internal (акцессоры модулей) или конкретный API BattleManager, используемый внутри сборки движка (OpenMon.MCE.Runtime), то есть уровень Source. Используйте их, когда расширяете логику боя, а не для чтения состояния из кода вашей игры.

Форма класса​

[RequireComponent(typeof(BattleStateMachine))]
[RequireComponent(typeof(BattleManagerBattlersModule))]
// ...один RequireComponent на модуль...
public class BattleManager : OpenMonBehaviour<BattleManager>, IBattleManager, IPlayerDataReceiver
{
// Акцессоры модулей (internal — разрешаются из соседних компонентов):
internal BattleManagerBattlersModule Battlers { get; }
internal BattleManagerHealthModule BattlerHealth { get; }
internal BattleManagerMovesModule Moves { get; }
internal BattleManagerCaptureModule Capture { get; }
internal BattleManagerAIModule AI { get; }
// ...BattlerStats, BattlerSwitch, Rosters, Scenario, Statuses,
// Characters, Animation, Audio, Megas...

// Публичное состояние боя:
public BattleType BattleType;
public EnemyType EnemyType;
public bool IsBattleOver;
public int TurnCounter { get; }
public byte BattleSpeed { get; }
public bool CanPlayerRun { get; }

public void SubscribeToBattleInitialized(Action callback);
public void SubscribeToBattleFinished(Action<BattleResultParameters> callback);
public void TickTurn();
public void FinishBattle();
public BattleMonsterSprite GetMonsterSprite(BattlerType type, int index);
}

Каждый модуль наследуется от общего базового класса BattleManagerModule<T>, который предоставляет тот же набор акцессоров к соседним модулям, чтобы модули могли вызывать друг друга:

public abstract class BattleManagerModule<T> : OpenMonBehaviour<T>
where T : BattleManagerModule<T>
{
protected BattleManager BattleManager { get; }
protected BattleManagerBattlersModule Battlers { get; }
protected BattleManagerHealthModule BattlerHealth { get; }
// ...те же акцессоры, что и у BattleManager...
}

Указатель модулей​

Каждое поведение боя — это один MonoBehaviour рядом с BattleManager, обязательный через [RequireComponent]. Пять ниже — те, к которым вы обращаетесь при расширении боёв; остальные отвечают за представление и учёт.

МодульАкцессорОтветственность
BattleManagerBattlersModuleBattlersПоиск бойцов, спрайты, формы, побег
BattleManagerHealthModuleBattlerHealthИзменение HP, обнаружение и обработка обморока
BattleManagerMovesModuleMovesВыполнение приёмов, точность
BattleManagerCaptureModuleCaptureПопытки поимки
BattleManagerAIModuleAIИИ по ростеру
BattleManagerBattlerStatsModuleBattlerStatsСтадии характеристик, дружба в начале
BattleManagerBattlerSwitchModuleBattleManagerBattlerSwitchВвод/вывод бойцов
BattleManagerRostersModuleRostersПодготовка ростеров, проверка обморока
BattleManagerScenariosModuleScenarioПогода, местность, настройка сценария
BattleManagerStatusesModuleStatusesСтатусные состояния
BattleManagerCharactersModuleCharactersПерсонажи-тренеры
BattleManagerAnimationModuleAnimationАнимация вступления/потока боя
BattleManagerAudioModuleAudioЗвук боя
BattleManagerMegaModuleMegasМега/гига смены формы

Публичное состояние и колбэки​

BattleType​

Вид текущего боя (одиночный, двойной и т. д.).

Тип: BattleType

EnemyType​

Против кого бой — Wild (дикие) монстры или Trainer (тренер).

Тип: EnemyType

IsBattleOver​

true, когда бой разрешён.

Тип: bool

TurnCounter​

Число прошедших ходов в этом бою.

Тип: int (только чтение)

BattleSpeed​

Коэффициент ускорения анимации для этого боя, взятый из конфигурации боя.

Тип: byte (только чтение)

CanPlayerRun​

true, когда противник Wild и ни один сражающийся вражеский боец не является альфой.

Тип: bool (только чтение)

SubscribeToBattleInitialized(Action callback)​

Регистрирует колбэк, срабатывающий по завершении инициализации боя.

SubscribeToBattleFinished(Action<BattleResultParameters> callback)​

Регистрирует колбэк, срабатывающий по окончании боя и получающий BattleResultParameters (тип боя, кто победил, пойманный монстр, флаг возрождения).

TickTurn()​

Продвигает счётчик ходов и очищает LastSuccessfulMoveThisTurn. Вызывается машиной состояний в начале каждого хода.

FinishBattle()​

Строит BattleResultParameters и вызывает колбэк завершения боя.

GetMonsterSprite(BattlerType type, int index)​

Получает экранный BattleMonsterSprite для слота бойца. Перегрузки принимают Battler или кортеж (BattlerType, int).

Возвращает: BattleMonsterSprite.

Модуль Battlers​

BattleManagerBattlersModule — разрешение бойцов в/из индексов и их спрайты.

GetBattlerFromBattleIndex(BattlerType type, int battleIndex)​

Получает Battler по боевому индексу для стороны.

Возвращает: Battler.

GetTypeAndIndexOfBattler(Battler battler)​

Обратный поиск: (BattlerType Type, int Index) бойца.

Возвращает: (BattlerType Type, int Index).

GetBattlersFighting(BattlerType type)​

Все сражающиеся бойцы на стороне. Перегрузка без параметров возвращает обе стороны.

Возвращает: List<Battler>.

IsBattlerFighting(BattlerType type, int battlerIndex)​

Есть ли в данном слоте активно сражающийся боец.

Возвращает: bool.

ChangeForm(BattlerType battlerType, int index, ...)​

Корутина, меняющая форму бойца во время боя (региональная/мега/трансформация). Существует несколько перегрузок для разных триггеров смены формы.

Возвращает: IEnumerator.

RunAway(BattlerType type, int index, bool playAnimation, bool bypassAllyChances = false)​

Корутина, пытающаяся сбежать из боя.

Возвращает: IEnumerator.

Модуль Health​

BattleManagerHealthModule — изменение HP и обработка обморока.

ChangeLife(Battler battler, Battler user, int amount, Move userMove = null, bool playAudio = true, bool forceSurvive = false, bool isSecondaryDamage = false, bool ignoreAbilities = false, Action<int, bool> finished = null)​

Канонический способ применить урон или лечение к бойцу в бою. Проигрывает анимацию и звук попадания, запускает способности и сообщает (применённоеКоличество, обморок) через finished. Есть перегрузки, принимающие индексы бойцов вместо ссылок Battler.

Возвращает: IEnumerator.

CheckFaintedBattlers()​

Корутина, обнаруживающая бойцов, чьё HP достигло нуля на этом шаге.

Возвращает: IEnumerator.

ProcessFaintedBattlers()​

Корутина, проигрывающая анимации обморока и разрешающая упавших в обморок бойцов.

Возвращает: IEnumerator.

GetNumberOfFainted(BattlerType battlerType, int battlerIndex)​

Количество монстров в обмороке в ростере.

Возвращает: int.

Модуль Moves​

BattleManagerMovesModule — выполнение приёмов.

PerformMove(BattlerType type, int index, List<(BattlerType Type, int Index)> targets, int moveIndex)​

Выполняет приём в слоте moveIndex (0–3 для четырёх слотов приёмов, 4 для Борьбы) против заданных целей, прогоняя весь конвейер эффектов.

Возвращает: IEnumerator.

ForcePerformMove(BattlerType type, int index, ...)​

Принудительно выполняет конкретный приём (используется эффектами, вызывающими другие приёмы).

Возвращает: IEnumerator.

LastSuccessfullyPerformedMove​

Последний успешно разрешённый приём.

Тип: Move

Модуль Capture​

BattleManagerCaptureModule — поимка диких монстров.

TryCaptureMonster(int index, Ball ball)​

Корутина, выполняющая попытку поимки вражеского бойца по index заданным Ball. Ничего не делает (и логирует ошибку) против тренеров или когда сражается более одного противника.

Возвращает: IEnumerator.

Модуль AI​

BattleManagerAIModule — подключаемый ИИ по ростеру.

PlayerControlsFirstRoster​

Управляет ли игрок-человек первым союзным ростером.

Тип: bool

AllyAIs / EnemyAIs​

Стратегия BattleAI, назначенная каждому ростеру на каждой стороне.

Тип: List<BattleAI>

GetAI(BattlerType type, int index)​

Получает BattleAI, управляющий данным ростером.

Возвращает: BattleAI.

BattleAI (база стратегии)​

Стратегии ИИ наследуются от абстрактного ScriptableObject BattleAI (OpenMon.MCE.Battle.AI). Встроенные стратегии включают RandomBattleAI, PerformEffectiveMove, PerformRandomMove и MLBattleAI (управляемую ML-Agents).

public abstract class BattleAI : MonsterDatabaseScriptable<BattleAI>
{
public abstract IEnumerator RequestPerformAction(MCESettings settings,
BattleManager battleManager, BattlerType type, int inBattleIndex,
Action<BattleAction> callback);

public abstract int RequestNewMonster(MCESettings settings,
BattleManager battleManager, BattlerType type, int inBattleIndex,
List<Battler> forbiddenBattlers);

public virtual void OnBattlerFainted(BattleManager battleManager,
BattlerType ownType, int ownIndex, BattlerType faintedType, int faintedIndex);

public virtual void OnBattleEnded(BattlerType ownType, int ownIndex,
BattlerType winners, BattleManager battleManager);
}

Чтобы добавить свой ИИ, унаследуйтесь от BattleAI, реализуйте RequestPerformAction (выбор действия на ход) и RequestNewMonster (выбор замены после обморока), затем назначьте ассет шаблону боя.

BattleStateMachine​

BattleStateMachine (соседний [RequireComponent]) ведёт цикл ходов. BattleManager.Construct запускает инициализацию боя; когда всё готово, вызывает:

GetCachedComponent<BattleStateMachine>().StartBattleLoop();

StartBattleLoop()​

Запускает корутину, прогоняющую упорядоченный цикл ходов (сбор действий → упорядочивание по приоритету → разрешение → проверка обмороков → следующий ход) до IsBattleOver.

Расширение боя​

using System.Collections;
using OpenMon.MCE.Battle;
using OpenMon.Foundation.Behaviours;

namespace MyGame.Battle
{
// Собственный модуль живёт на том же GameObject, что и BattleManager, и достигает
// другие модули через общий базовый класс.
public class MyBattleHookModule : BattleManagerModule<MyBattleHookModule>
{
public IEnumerator HalveEnemyLead()
{
Battler lead = Battlers.GetBattlerFromBattleIndex(BattlerType.Enemy, 0);
int damage = (int)(lead.CurrentHP / 2);

// Направляем HP через модуль здоровья, чтобы анимации/способности отрабатывали.
yield return BattlerHealth.ChangeLife(lead, lead, -damage);
}
}
}