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

@@ -5,11 +5,11 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "aroma_veil")]
public class AromaVeilEffect : Script, IScriptFailIncomingMove, IScriptPreventIncomingSecondaryEffect
{
private HashSet<IPokemon> _placers = new();
private HashSet<IBattlePokemon> _placers = new();
public void PlacerActivated(IPokemon placer) => _placers.Add(placer);
public void PlacerActivated(IBattlePokemon placer) => _placers.Add(placer);
public void PlacerDeactivated(IPokemon placer)
public void PlacerDeactivated(IBattlePokemon placer)
{
_placers.Remove(placer);
if (_placers.Count == 0)
@@ -17,14 +17,14 @@ public class AromaVeilEffect : Script, IScriptFailIncomingMove, IScriptPreventIn
}
/// <inheritdoc />
public void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail)
public void FailIncomingMove(IExecutingMove move, IBattlePokemon target, ref bool fail)
{
if (move.UseMove.HasFlag(MoveFlags.Mental) && move.UseMove.Category == MoveCategory.Status)
fail = true;
}
/// <inheritdoc />
public void PreventIncomingSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
public void PreventIncomingSecondaryEffect(IExecutingMove move, IBattlePokemon target, byte hit, ref bool prevent)
{
if (move.UseMove.HasFlag(MoveFlags.Mental))
prevent = true;

View File

@@ -46,17 +46,14 @@ public class AuroraVeilEffect : Script, IScriptChangeIncomingMoveDamage, IScript
}
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
public void ChangeIncomingMoveDamage(IExecutingMove move, IBattlePokemon target, byte hit, ref uint damage)
{
var hitData = move.GetHitData(target, hit);
if (hitData.IsCritical)
return;
if (move.User.BattleData?.SideIndex == target.BattleData?.SideIndex)
if (move.User.SideIndex == target.SideIndex)
return;
var targetSide = target.BattleData?.SideIndex;
if (targetSide == null)
return;
var side = move.User.BattleData!.Battle.Sides[targetSide.Value];
var side = move.User.Battle.Sides[target.SideIndex];
switch (move.UseMove.Category)
{
case MoveCategory.Physical when side.VolatileScripts.Contains(ScriptUtils.ResolveName<ReflectEffect>()):
@@ -65,7 +62,7 @@ public class AuroraVeilEffect : Script, IScriptChangeIncomingMoveDamage, IScript
}
var modifier = 0.5f;
if (target.BattleData!.Battle.PositionsPerSide > 1)
if (target.Battle.PositionsPerSide > 1)
modifier = 2732f / 4096f;
damage = (uint)(damage * modifier);
}

View File

@@ -5,11 +5,11 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "battery")]
public class BatteryAbilityEffect : Script, IScriptChangeDamageModifier
{
private HashSet<IPokemon> _placers = new();
private HashSet<IBattlePokemon> _placers = new();
public void PlacerActivated(IPokemon placer) => _placers.Add(placer);
public void PlacerActivated(IBattlePokemon placer) => _placers.Add(placer);
public void PlacerDeactivated(IPokemon placer)
public void PlacerDeactivated(IBattlePokemon placer)
{
_placers.Remove(placer);
if (_placers.Count == 0)
@@ -17,7 +17,7 @@ public class BatteryAbilityEffect : Script, IScriptChangeDamageModifier
}
/// <inheritdoc />
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
public void ChangeDamageModifier(IExecutingMove move, IBattlePokemon target, byte hit, ref float modifier)
{
if (move.UseMove.Category == MoveCategory.Special)
{

View File

@@ -3,7 +3,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "double_power_if_target_damaged_in_turn_data")]
public class DoublePowerIfTargetDamagedInTurnData : Script, IScriptOnEndTurn, IScriptOnDamage
{
public readonly HashSet<IPokemon> HitPokemon = [];
public readonly HashSet<IBattlePokemon> HitPokemon = [];
/// <param name="owner"></param>
/// <param name="battle"></param>
@@ -14,7 +14,7 @@ public class DoublePowerIfTargetDamagedInTurnData : Script, IScriptOnEndTurn, IS
}
/// <inheritdoc />
public void OnDamage(IPokemon pokemon, DamageSource source, uint oldHealth, uint newHealth)
public void OnDamage(IBattlePokemon pokemon, DamageSource source, uint oldHealth, uint newHealth)
{
HitPokemon.Add(pokemon);
}

View File

@@ -3,14 +3,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "flower_gift")]
public class FlowerGiftEffect : Script, IScriptChangeOffensiveStatValue
{
private readonly HashSet<IPokemon> _placerPokemon = [];
private readonly HashSet<IBattlePokemon> _placerPokemon = [];
public void OnAdded(IPokemon placer)
public void OnAdded(IBattlePokemon placer)
{
_placerPokemon.Add(placer);
}
public void OnRemoved(IPokemon placer)
public void OnRemoved(IBattlePokemon placer)
{
_placerPokemon.Remove(placer);
if (_placerPokemon.Count == 0)
@@ -20,7 +20,7 @@ public class FlowerGiftEffect : Script, IScriptChangeOffensiveStatValue
}
/// <inheritdoc />
public void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
public void ChangeOffensiveStatValue(IExecutingMove move, IBattlePokemon target, byte hit, uint defensiveStat,
ImmutableStatisticSet<uint> targetStats, Statistic stat, ref uint value)
{
if (move.Battle.WeatherName != ScriptUtils.ResolveName<Weather.HarshSunlight>())

View File

@@ -3,14 +3,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "flower_veil")]
public class FlowerVeilEffect : Script, IScriptPreventStatBoostChange, IScriptPreventStatusChange
{
private readonly HashSet<IPokemon> _placerPokemon = [];
private readonly HashSet<IBattlePokemon> _placerPokemon = [];
public void OnAdded(IPokemon placer)
public void OnAdded(IBattlePokemon placer)
{
_placerPokemon.Add(placer);
}
public void OnRemoved(IPokemon placer)
public void OnRemoved(IBattlePokemon placer)
{
_placerPokemon.Remove(placer);
if (_placerPokemon.Count == 0)
@@ -20,7 +20,7 @@ public class FlowerVeilEffect : Script, IScriptPreventStatBoostChange, IScriptPr
}
/// <inheritdoc />
public void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
public void PreventStatBoostChange(IBattlePokemon target, Statistic stat, sbyte amount, bool selfInflicted,
ref bool prevent)
{
if (selfInflicted)
@@ -36,7 +36,8 @@ public class FlowerVeilEffect : Script, IScriptPreventStatBoostChange, IScriptPr
}
/// <inheritdoc />
public void PreventStatusChange(IPokemon pokemon, StringKey status, bool selfInflicted, ref bool preventStatus)
public void PreventStatusChange(IBattlePokemon pokemon, StringKey status, bool selfInflicted,
ref bool preventStatus)
{
if (selfInflicted)
return;

View File

@@ -3,22 +3,22 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Side, "follow_me")]
public class FollowMeEffect : Script, IScriptChangeIncomingTargets, IScriptOnEndTurn, IScriptOnFaint, IScriptOnSwitchOut
{
private readonly IPokemon _user;
private readonly IBattlePokemon _user;
public FollowMeEffect(IPokemon user)
public FollowMeEffect(IBattlePokemon user)
{
_user = user;
}
/// <inheritdoc />
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IBattlePokemon?> targets)
{
if (targets.Count != 1)
return;
if (moveChoice.ChosenMove.MoveData.HasFlag(MoveFlags.NoRedirection))
return;
if (moveChoice.User.BattleData?.SideIndex == _user.BattleData?.SideIndex)
if (moveChoice.User.SideIndex == _user.SideIndex)
return;
targets = [_user];
}
@@ -28,13 +28,13 @@ public class FollowMeEffect : Script, IScriptChangeIncomingTargets, IScriptOnEnd
RemoveSelf();
}
public void OnFaint(IPokemon pokemon, DamageSource source)
public void OnFaint(IBattlePokemon pokemon, DamageSource source)
{
if (pokemon == _user)
RemoveSelf();
}
public void OnSwitchOut(IPokemon oldPokemon, byte position)
public void OnSwitchOut(IBattlePokemon oldPokemon, byte position)
{
if (oldPokemon == _user)
RemoveSelf();

View File

@@ -3,14 +3,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "friend_guard")]
public class FriendGuardEffect : Script, IScriptChangeIncomingMoveDamage
{
private readonly HashSet<IPokemon> _placerPokemon = [];
private readonly HashSet<IBattlePokemon> _placerPokemon = [];
public void OnAdded(IPokemon placer)
public void OnAdded(IBattlePokemon placer)
{
_placerPokemon.Add(placer);
}
public void OnRemoved(IPokemon placer)
public void OnRemoved(IBattlePokemon placer)
{
_placerPokemon.Remove(placer);
if (_placerPokemon.Count == 0)
@@ -20,7 +20,7 @@ public class FriendGuardEffect : Script, IScriptChangeIncomingMoveDamage
}
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
public void ChangeIncomingMoveDamage(IExecutingMove move, IBattlePokemon target, byte hit, ref uint damage)
{
var modifier = Math.Pow(0.75f, _placerPokemon.Count);
damage = (uint)(damage * modifier);

View File

@@ -11,7 +11,7 @@ public class HealingWishEffect : Script, IScriptOnSwitchIn
}
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position)
public void OnSwitchIn(IBattlePokemon pokemon, byte position)
{
if (position == _position)
{

View File

@@ -8,13 +8,13 @@ public class LightScreenEffect(int turns) : Script, IScriptChangeIncomingMoveDam
private int _turns = turns;
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
public void ChangeIncomingMoveDamage(IExecutingMove move, IBattlePokemon target, byte hit, ref uint damage)
{
if (move.UseMove.Category != MoveCategory.Special ||
// Critical hits are not affected by the barrier
move.GetHitData(target, hit).IsCritical)
return;
var battleData = target.BattleData;
var battleData = target;
// If not a 1v1 battle, damage reduction is only 1/3rd.
if (battleData?.Battle.PositionsPerSide > 1)
damage = (uint)(damage * (2.0f / 3.0f));

View File

@@ -14,7 +14,7 @@ public class LuckyChantEffect : Script, IScriptBlockIncomingCriticalHit, IScript
RemoveSelf();
}
public void BlockIncomingCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block)
public void BlockIncomingCriticalHit(IExecutingMove move, IBattlePokemon target, byte hit, ref bool block)
{
block = true;
}

View File

@@ -4,7 +4,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class LunarDanceEffect(byte position) : Script, IScriptOnSwitchIn
{
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position1)
public void OnSwitchIn(IBattlePokemon pokemon, byte position1)
{
if (position != position1)
return;

View File

@@ -6,7 +6,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class MatBlockEffect : Script, IScriptOnEndTurn, IScriptBlockIncomingHit
{
/// <inheritdoc />
public void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
public void BlockIncomingHit(IExecutingMove executingMove, IBattlePokemon target, byte hitIndex, ref bool block)
{
if (executingMove.UseMove.Category != MoveCategory.Status)
block = true;

View File

@@ -6,7 +6,7 @@ public class MistEffect : Script, IScriptPreventStatBoostChange, IScriptOnEndTur
private int _turnsRemaining = 5;
/// <inheritdoc />
public void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
public void PreventStatBoostChange(IBattlePokemon target, Statistic stat, sbyte amount, bool selfInflicted,
ref bool prevent)
{
if (selfInflicted)

View File

@@ -5,7 +5,7 @@ public class QuickGuardEffect : Script, IScriptIsInvulnerableToMove, IScriptOnEn
{
/// <inheritdoc />
/// <inheritdoc />
public void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
public void IsInvulnerableToMove(IExecutingMove move, IBattlePokemon target, ref bool invulnerable)
{
if (move.UseMove.Priority > 0)
invulnerable = true;

View File

@@ -3,15 +3,15 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "rage_powder")]
public class RagePowderEffect : Script, IScriptChangeIncomingTargets, IScriptOnEndTurn
{
public IPokemon User { get; set; }
public IBattlePokemon User { get; set; }
public RagePowderEffect(IPokemon user)
public RagePowderEffect(IBattlePokemon user)
{
User = user;
}
/// <inheritdoc />
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IBattlePokemon?> targets)
{
// Ignore multi-hit moves
if (targets.Count != 1)

View File

@@ -6,7 +6,7 @@ public class RainbowEffect : Script, IScriptChangeEffectChance, IScriptOnEndTurn
private int _turns = 4;
/// <inheritdoc />
public void ChangeEffectChance(IExecutingMove move, IPokemon target, byte hit, ref float chance)
public void ChangeEffectChance(IExecutingMove move, IBattlePokemon target, byte hit, ref float chance)
{
chance *= 2;
}

View File

@@ -8,7 +8,7 @@ public class ReflectEffect(int turns) : Script, IScriptChangeIncomingMoveDamage,
private int _turns = turns;
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
public void ChangeIncomingMoveDamage(IExecutingMove move, IBattlePokemon target, byte hit, ref uint damage)
{
var hitData = move.GetHitData(target, hit);
if (move.UseMove.Category != MoveCategory.Physical)

View File

@@ -6,7 +6,8 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class SafeguardEffect : Script, IScriptPreventStatusChange, IScriptPreventVolatileAdd
{
/// <inheritdoc />
public void PreventStatusChange(IPokemon pokemon, StringKey status, bool selfInflicted, ref bool preventStatus)
public void PreventStatusChange(IBattlePokemon pokemon, StringKey status, bool selfInflicted,
ref bool preventStatus)
{
preventStatus = true;
}

View File

@@ -13,7 +13,7 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack, IAIInfoScri
}
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position)
public void OnSwitchIn(IBattlePokemon pokemon, byte position)
{
if (pokemon.IsFloating)
return;
@@ -22,7 +22,7 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack, IAIInfoScri
EventBatchId eventBatch = new();
pokemon.Damage(damage, DamageSource.Misc, eventBatch);
pokemon.BattleData?.Battle.EventHook.Invoke(new DialogEvent("spikes_damage", new Dictionary<string, object>
pokemon.Battle.EventHook.Invoke(new DialogEvent("spikes_damage", new Dictionary<string, object>
{
{ "pokemon", pokemon },
})
@@ -31,7 +31,7 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack, IAIInfoScri
});
}
private uint CalculateDamage(IPokemon pokemon)
private uint CalculateDamage(IBattlePokemon pokemon)
{
var modifier = _layers switch
{
@@ -45,7 +45,7 @@ public class SpikesEffect : Script, IScriptOnSwitchIn, IScriptStack, IAIInfoScri
}
/// <inheritdoc />
public void ExpectedEntryDamage(IPokemon pokemon, ref uint damage)
public void ExpectedEntryDamage(IBattlePokemon pokemon, ref uint damage)
{
if (pokemon.IsFloating)
return;

View File

@@ -15,7 +15,7 @@ public class SpotlightEffect : Script, IScriptChangeIncomingTargets, IScriptOnEn
}
/// <inheritdoc />
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IBattlePokemon?> targets)
{
if (!TargetResolver.IsValidTarget(_side.Index, _position, moveChoice.ChosenMove.MoveData.Target,
moveChoice.User))

View File

@@ -4,19 +4,18 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class StealthRockEffect : Script, IScriptOnSwitchIn, IAIInfoScriptExpectedEntryDamage
{
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position)
public void OnSwitchIn(IBattlePokemon pokemon, byte position)
{
var damage = CalculateStealthRockDamage(pokemon);
EventBatchId batchId = new();
pokemon.Damage(damage, DamageSource.Misc, batchId);
pokemon.BattleData?.Battle.EventHook.Invoke(new DialogEvent("stealth_rock_damage",
new Dictionary<string, object>
{
{ "pokemon", pokemon },
}));
pokemon.Battle.EventHook.Invoke(new DialogEvent("stealth_rock_damage", new Dictionary<string, object>
{
{ "pokemon", pokemon },
}));
}
private static uint CalculateStealthRockDamage(IPokemon pokemon)
private static uint CalculateStealthRockDamage(IBattlePokemon pokemon)
{
var typeLibrary = pokemon.Library.StaticLibrary.Types;
var effectiveness = 1.0f;
@@ -28,7 +27,7 @@ public class StealthRockEffect : Script, IScriptOnSwitchIn, IAIInfoScriptExpecte
}
/// <inheritdoc />
public void ExpectedEntryDamage(IPokemon pokemon, ref uint damage)
public void ExpectedEntryDamage(IBattlePokemon pokemon, ref uint damage)
{
damage += CalculateStealthRockDamage(pokemon);
}

View File

@@ -4,7 +4,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class StickyWebEffect : Script, IScriptOnSwitchIn
{
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position)
public void OnSwitchIn(IBattlePokemon pokemon, byte position)
{
if (pokemon.IsFloating)
return;

View File

@@ -4,7 +4,7 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Side;
public class ToxicSpikesEffect : Script, IScriptOnSwitchIn
{
/// <inheritdoc />
public void OnSwitchIn(IPokemon pokemon, byte position)
public void OnSwitchIn(IBattlePokemon pokemon, byte position)
{
if (pokemon.IsFloating)
return;

View File

@@ -19,14 +19,14 @@ public class WideGuardEffect : Script, IScriptChangeTargets, IScriptOnEndTurn
}
/// <inheritdoc />
public void ChangeTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
public void ChangeTargets(IMoveChoice moveChoice, ref IReadOnlyList<IBattlePokemon?> targets)
{
if (_side == null)
return;
if (targets.Count > 1)
{
targets = targets.Where(x => x?.BattleData?.BattleSide != _side).ToList();
targets = targets.Where(x => x?.BattleSide != _side).ToList();
}
}