84 lines
3.2 KiB
C#
84 lines
3.2 KiB
C#
using PkmnLib.Dynamic.Models.Choices;
|
|
using PkmnLib.Dynamic.ScriptHandling;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Dynamic.Models.BattleFlow;
|
|
|
|
public static class TurnRunner
|
|
{
|
|
public static void RunTurn(this IBattle battle)
|
|
{
|
|
var queue = battle.ChoiceQueue;
|
|
if (queue == null)
|
|
throw new ArgumentNullException(nameof(battle.ChoiceQueue),
|
|
"The battle's choice queue must be set before running a turn.");
|
|
|
|
// We are now at the very beginning of a turn. We have assigned speeds and priorities to all
|
|
// choices, and put them in the correct order.
|
|
|
|
// The first thing to do is to run the on_before_turn script hook on every choice. This script hook
|
|
// is primarily intended to be used to reset variables on a script (for example scripts that need
|
|
// to check whether a Pokémon was hit this turn. By resetting here, and setting a variable to true
|
|
// they can then know this later on.)
|
|
foreach (var choice in queue.GetChoices().WhereNotNull())
|
|
{
|
|
choice.RunScriptHook(script => script.OnBeforeTurnStart(choice));
|
|
}
|
|
|
|
// Now we can properly begin executing choices.
|
|
// One by one dequeue the turns, and run them. If the battle has ended we do not want to
|
|
// continue running.
|
|
while (queue.HasNext() && !battle.HasEnded)
|
|
{
|
|
var next = queue.Dequeue();
|
|
if (next == null)
|
|
continue;
|
|
ExecuteChoice(battle, next);
|
|
}
|
|
|
|
// If the battle is not ended, we have arrived at the normal end of a turn. and thus want
|
|
// to run the end turn scripts.
|
|
|
|
// As we want all scripts to run exactly once, including those on the sides and battles,
|
|
// we can't just use the default script hook on each Pokémon. Instead, manually call
|
|
// the script functions on every script.
|
|
if (!battle.HasEnded)
|
|
{
|
|
var scripts = new List<IEnumerable<ScriptContainer>>(10);
|
|
foreach (var side in battle.Sides)
|
|
{
|
|
foreach (var pokemon in side.Pokemon.WhereNotNull())
|
|
{
|
|
scripts.Clear();
|
|
pokemon.GetOwnScripts(scripts);
|
|
scripts.RunScriptHook(x => x.OnEndTurn());
|
|
}
|
|
scripts.Clear();
|
|
side.GetOwnScripts(scripts);
|
|
scripts.RunScriptHook(x => x.OnEndTurn());
|
|
}
|
|
scripts.Clear();
|
|
battle.GetOwnScripts(scripts);
|
|
scripts.RunScriptHook(x => x.OnEndTurn());
|
|
}
|
|
}
|
|
|
|
private static void ExecuteChoice(IBattle battle, ITurnChoice choice)
|
|
{
|
|
if (choice is IPassChoice)
|
|
return;
|
|
if (battle.HasEnded)
|
|
return;
|
|
if (!choice.User.IsUsable)
|
|
return;
|
|
if (choice.User.BattleData?.IsOnBattlefield != true)
|
|
return;
|
|
switch (choice)
|
|
{
|
|
case IMoveChoice moveChoice:
|
|
MoveTurnExecutor.ExecuteMoveChoice(battle, moveChoice);
|
|
break;
|
|
// TODO: Implement other choice types
|
|
}
|
|
}
|
|
} |