Move all battle state from IPokemon to an ephemeral IBattlePokemon wrapper

This commit is contained in:
2026-08-28 15:20:26 +02:00
parent 942be8eaeb
commit 8a2733a0a9
859 changed files with 4408 additions and 5331 deletions

View File

@@ -15,7 +15,7 @@ public static class MoveTurnExecutor
{
internal static void ExecuteMoveChoice(IBattle battle, IMoveChoice moveChoice)
{
moveChoice.User.BattleData!.LastMoveChoice = moveChoice;
moveChoice.User.LastMoveChoice = moveChoice;
var chosenMove = moveChoice.ChosenMove;
var useMove = chosenMove.MoveData;
@@ -126,7 +126,7 @@ public static class MoveTurnExecutor
private static readonly ThreadLocal<List<TypeIdentifier>> TypeListCache = new(() => []);
private static void ExecuteMoveChoiceForTarget(IBattle battle, IExecutingMove executingMove, IPokemon target)
private static void ExecuteMoveChoiceForTarget(IBattle battle, IExecutingMove executingMove, IBattlePokemon target)
{
var failed = false;
target.RunScriptHook<IScriptFailIncomingMove>(x => x.FailIncomingMove(executingMove, target, ref failed));

View File

@@ -11,7 +11,8 @@ public static class TargetResolver
/// <summary>
/// Get the targets of a move based on the target type, and the selected side and position to target.
/// </summary>
public static IReadOnlyList<IPokemon?> ResolveTargets(IBattle battle, byte side, byte position, MoveTarget target)
public static IReadOnlyList<IBattlePokemon?> ResolveTargets(IBattle battle, byte side, byte position,
MoveTarget target)
{
return target switch
{
@@ -29,13 +30,10 @@ public static class TargetResolver
/// <summary>
/// Validates whether a given target is valid for a move choice. Returns true if the target is valid.
/// </summary>
public static bool IsValidTarget(byte side, byte position, MoveTarget target, IPokemon user)
public static bool IsValidTarget(byte side, byte position, MoveTarget target, IBattlePokemon user)
{
var userBattleData = user.BattleData;
if (userBattleData == null)
throw new ArgumentNullException(nameof(user.BattleData));
var userSide = userBattleData.SideIndex;
var userPosition = userBattleData.Position;
var userSide = user.SideIndex;
var userPosition = user.Position;
switch (target)
{
@@ -80,7 +78,7 @@ public static class TargetResolver
throw new ArgumentOutOfRangeException(nameof(target), target, null);
}
private static IReadOnlyList<IPokemon?> GetAllTargets(IBattle battle) =>
private static IReadOnlyList<IBattlePokemon?> GetAllTargets(IBattle battle) =>
battle.Sides.SelectMany(x => x.Pokemon).ToList();
private static byte GetOppositeSide(byte side) => side == 0 ? (byte)1 : (byte)0;
@@ -89,7 +87,7 @@ public static class TargetResolver
/// Gets all Pokémon that are adjacent to of directly opposite of a Pokémon. This means the target,
/// the Pokémon left of it, the Pokémon right of it, and the Pokémon opposite of it.
/// </summary>
private static IReadOnlyList<IPokemon?> GetAllAdjacentAndOpponent(IBattle battle, byte side, byte position)
private static IReadOnlyList<IBattlePokemon?> GetAllAdjacentAndOpponent(IBattle battle, byte side, byte position)
{
var left = position - 1;
var right = position + 1;
@@ -123,7 +121,7 @@ public static class TargetResolver
];
}
private static IReadOnlyList<IPokemon?> GetAllAdjacent(IBattle battle, byte side, byte position)
private static IReadOnlyList<IBattlePokemon?> GetAllAdjacent(IBattle battle, byte side, byte position)
{
var left = position - 1;
var right = position + 1;

View File

@@ -85,7 +85,7 @@ public static class TurnRunner
return;
if (!choice.User.IsUsable)
return;
if (choice.User.BattleData?.IsOnBattlefield != true)
if (!choice.User.IsOnBattlefield)
return;
switch (choice)
{
@@ -108,9 +108,6 @@ public static class TurnRunner
private static void ExecuteSwitchChoice(IBattle battle, ISwitchChoice fleeChoice)
{
var user = fleeChoice.User;
var battleData = user.BattleData;
if (battleData == null)
return;
var preventSwitch = false;
fleeChoice.RunScriptHook<IScriptPreventSelfSwitch>(script =>
script.PreventSelfSwitch(fleeChoice, ref preventSwitch));
@@ -118,7 +115,7 @@ public static class TurnRunner
return;
foreach (var side in battle.Sides)
{
if (side.Index == battleData.SideIndex)
if (side.Index == user.SideIndex)
continue;
foreach (var pokemon in side.Pokemon.WhereNotNull())
{
@@ -129,16 +126,12 @@ public static class TurnRunner
}
}
user.Volatile.Clear();
var userSide = battle.Sides[battleData.SideIndex];
userSide.SwapPokemon(battleData.Position, fleeChoice.SwitchTo);
user.BattleSide.SwapPokemon(user.Position, fleeChoice.SwitchTo);
}
private static void ExecuteFleeChoice(IBattle battle, IFleeChoice fleeChoice)
{
var user = fleeChoice.User;
var battleData = user.BattleData;
if (battleData == null)
return;
if (!battle.CanFlee)
return;
@@ -150,7 +143,7 @@ public static class TurnRunner
foreach (var side in battle.Sides)
{
if (side.Index == battleData.SideIndex)
if (side.Index == user.SideIndex)
continue;
foreach (var pokemon in side.Pokemon.WhereNotNull())
{
@@ -167,8 +160,7 @@ public static class TurnRunner
return;
}
var userSide = battle.Sides[battleData.SideIndex];
userSide.MarkAsFled();
user.BattleSide.MarkAsFled();
battle.EventHook.Invoke(new FleeEvent(user, true));
battle.ValidateBattleState();
}
@@ -176,9 +168,6 @@ public static class TurnRunner
private static void ExecuteItemChoice(IBattle battle, IItemChoice itemChoice)
{
var user = itemChoice.User;
var battleData = user.BattleData;
if (battleData == null)
return;
var target = itemChoice.GetTargetPokemon(battle);
battle.EventHook.Invoke(new ItemUseEvent(user, itemChoice.Item));
itemChoice.Item.RunItemScript(battle.Library.ScriptResolver, target ?? user, user, battle, battle.EventHook);