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

@@ -19,7 +19,8 @@ public static class AISwitchFunctions
/// <summary>
/// Switch out if the Perish Song effect is about to cause the Pokémon to faint.
/// </summary>
private static bool PerishSong(IExplicitAI ai, IPokemon pokemon, IBattle battle, IReadOnlyList<IPokemon> reserves)
private static bool PerishSong(IExplicitAI ai, IBattlePokemon pokemon, IBattle battle,
IReadOnlyList<IBattlePokemon> reserves)
{
if (!pokemon.Volatile.TryGet<PerishSongEffect>(out var effect))
return false;
@@ -29,8 +30,8 @@ public static class AISwitchFunctions
/// <summary>
/// Switch out if the Pokémon is expected to take significant end-of-turn damage.
/// </summary>
private static bool SignificantEndOfTurnDamage(IExplicitAI ai, IPokemon pokemon, IBattle battle,
IReadOnlyList<IPokemon> reserves)
private static bool SignificantEndOfTurnDamage(IExplicitAI ai, IBattlePokemon pokemon, IBattle battle,
IReadOnlyList<IBattlePokemon> reserves)
{
var eorDamage = 0;
pokemon.RunScriptHook<IAIInfoScriptExpectedEndOfTurnDamage>(x =>
@@ -61,21 +62,20 @@ public static class AISwitchFunctions
return false;
}
private static bool HighDamageFromFoe(IExplicitAI ai, IPokemon pokemon, IBattle battle,
IReadOnlyList<IPokemon> reserves)
private static bool HighDamageFromFoe(IExplicitAI ai, IBattlePokemon pokemon, IBattle battle,
IReadOnlyList<IBattlePokemon> reserves)
{
if (!ai.TrainerHighSkill)
return false;
if (pokemon.CurrentHealth >= pokemon.MaxHealth / 2)
return false;
var bigThreat = false;
var opponents = battle.Sides.Where(x => x != pokemon.BattleData?.BattleSide)
.SelectMany(x => x.Pokemon.WhereNotNull());
var opponents = battle.Sides.Where(x => x != pokemon.BattleSide).SelectMany(x => x.Pokemon.WhereNotNull());
foreach (var opponent in opponents)
{
if (Math.Abs(opponent.Level - pokemon.Level) > 5)
continue;
var lastMoveUsed = opponent.BattleData?.LastMoveChoice;
var lastMoveUsed = opponent.LastMoveChoice;
if (lastMoveUsed is null)
continue;
var moveData = lastMoveUsed.ChosenMove.MoveData;
@@ -107,15 +107,15 @@ public static class AISwitchFunctions
/// <summary>
/// Switch out to cure a status problem or heal HP with abilities like Natural Cure or Regenerator.
/// </summary>
private static bool CureStatusProblemBySwitchingOut(IExplicitAI ai, IPokemon pokemon, IBattle battle,
IReadOnlyList<IPokemon> reserves)
private static bool CureStatusProblemBySwitchingOut(IExplicitAI ai, IBattlePokemon pokemon, IBattle battle,
IReadOnlyList<IBattlePokemon> reserves)
{
if (pokemon.ActiveAbility == null)
return false;
// Don't try to cure a status problem/heal a bit of HP if entry hazards will
// KO the battler if it switches back in
var entryHazardDamage = ExplicitAI.CalculateEntryHazardDamage(pokemon, pokemon.BattleData!.BattleSide);
var entryHazardDamage = ExplicitAI.CalculateEntryHazardDamage(pokemon, pokemon.BattleSide);
if (entryHazardDamage >= pokemon.CurrentHealth)
return false;
if (pokemon.StatusScript.Script is null)
@@ -151,7 +151,7 @@ public static class AISwitchFunctions
if (pokemon.StatusScript.Script is Poisoned or BadlyPoisoned &&
!reserves.Any(p => p.Types.Any(t => t.Name == TypeNames.Poison)))
{
if (pokemon.BattleData!.BattleSide.VolatileScripts.TryGet<ToxicSpikesEffect>(out _))
if (pokemon.BattleSide.VolatileScripts.TryGet<ToxicSpikesEffect>(out _))
{
return false;
}
@@ -179,7 +179,7 @@ public static class AISwitchFunctions
var hasDamagingMove = pokemon.Moves.Any(m => m?.MoveData.Category != MoveCategory.Status);
if (hasDamagingMove)
{
var opponents = battle.Sides.Where(x => x != pokemon.BattleData?.BattleSide)
var opponents = battle.Sides.Where(x => x != pokemon.BattleSide)
.SelectMany(x => x.Pokemon.WhereNotNull());
var weakFoe = opponents.Any(opponent => opponent.CurrentHealth < opponent.MaxHealth / 3);
if (weakFoe)