Many more tests and fixes
All checks were successful
Build / Build (push) Successful in 3m12s

This commit is contained in:
2026-08-27 17:11:12 +02:00
parent 32b3ef9c4a
commit d2a82b5fe3
204 changed files with 20255 additions and 242 deletions

View File

@@ -8,6 +8,9 @@ public class ChargeBounceEffect : Script, IScriptForceTurnSelection, IScriptChan
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public ChargeBounceEffect(IPokemon owner)
{
_owner = owner;

View File

@@ -8,6 +8,9 @@ public class ChargeFlyEffect : Script, IScriptForceTurnSelection, IScriptChangeI
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public ChargeFlyEffect(IPokemon owner)
{
_owner = owner;
@@ -30,7 +33,7 @@ public class ChargeFlyEffect : Script, IScriptForceTurnSelection, IScriptChangeI
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (!move.UseMove.HasFlag(MoveFlags.EffectiveAgainstFly))
if (move.UseMove.HasFlag(MoveFlags.EffectiveAgainstFly))
damage *= 2;
}

View File

@@ -8,6 +8,9 @@ public class ChargeSkyDropEffect : Script, IScriptForceTurnSelection, IScriptCha
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public ChargeSkyDropEffect(IPokemon owner)
{
_owner = owner;

View File

@@ -73,6 +73,9 @@ public class Confusion : Script, IScriptStopBeforeMove
/// <inheritdoc />
public uint Damage { get; } = 0;
/// <inheritdoc />
public bool HasExecuted => true;
/// <inheritdoc />
public TypeIdentifier? Type => null;

View File

@@ -0,0 +1,14 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "defense_curl")]
public class DefenseCurlEffect : Script, IScriptChangeBasePower
{
private static StringKey RolloutName = "rollout";
private static StringKey IceBallName = "ice_ball";
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.UseMove.Name == RolloutName || move.UseMove.Name == IceBallName)
basePower = basePower.MultiplyOrMax(2);
}
}

View File

@@ -8,6 +8,9 @@ public class DigEffect : Script, IScriptForceTurnSelection, IScriptChangeIncomin
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public DigEffect(IPokemon owner)
{
_owner = owner;

View File

@@ -8,6 +8,9 @@ public class DiveEffect : Script, IScriptForceTurnSelection, IScriptChangeIncomi
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public DiveEffect(IPokemon owner)
{
_owner = owner;

View File

@@ -5,27 +5,42 @@ public class FireSpinEffect : Script, IScriptOnEndTurn, IScriptPreventSelfRunAwa
IAIInfoScriptExpectedEndOfTurnDamage
{
private readonly IPokemon _owner;
private int _turns;
private readonly float _modifier;
public FireSpinEffect(IPokemon owner)
public FireSpinEffect(IPokemon owner, int turns, IPokemon user)
{
_owner = owner;
_turns = turns;
_modifier = user.HasHeldItem("binding_band") ? 6f : 8f;
}
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
_owner.Damage(_owner.BoostedStats.Hp / 8, DamageSource.Misc);
_owner.Damage((uint)(_owner.BoostedStats.Hp / _modifier), DamageSource.Misc);
_turns--;
if (_turns == 0)
RemoveSelf();
}
/// <inheritdoc />
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void ExpectedEndOfTurnDamage(IPokemon pokemon, ref int damage)
{
damage += (int)(pokemon.MaxHealth / 8f);
damage += (int)(pokemon.MaxHealth / _modifier);
}
}

View File

@@ -0,0 +1,15 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "increased_critical_stage")]
public class FocusEnergyEffect : Script, IScriptChangeCriticalStage
{
public void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
{
if (stage == byte.MaxValue)
{
move.GetHitData(target, hit).Fail();
return;
}
stage = (byte)Math.Min(stage + 2, byte.MaxValue);
}
}

View File

@@ -1,3 +1,5 @@
using PkmnLib.Plugin.Gen7.Scripts.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "focus_punch")]
@@ -8,6 +10,8 @@ public class FocusPunchEffect : Script, IScriptOnIncomingHit
/// <inheritdoc />
public void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.UseMove.SecondaryEffect?.Name == "one_hit_ko")
return;
WasHit = true;
target.BattleData?.Battle.EventHook.Invoke(new DialogEvent("focus_punch_lost_focus",
new Dictionary<string, object>

View File

@@ -0,0 +1,15 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
/// <summary>
/// Simple marker script to indicate forests curse or trick-or-treat has been used,
/// </summary>
[Script(ScriptCategory.Pokemon, "has_had_type_added_effect")]
public class HasHadTypeAddedEffect : Script
{
public TypeIdentifier TypeIdentifier { get; }
public HasHadTypeAddedEffect(TypeIdentifier typeIdentifier)
{
TypeIdentifier = typeIdentifier;
}
}

View File

@@ -1,12 +1,19 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "helping_hand")]
public class HelpingHandEffect : Script, IScriptChangeBasePower, IScriptOnEndTurn
public class HelpingHandEffect : Script, IScriptChangeBasePower, IScriptOnEndTurn, IScriptStack
{
private int _stacks = 1;
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower) =>
basePower = basePower.MultiplyOrMax(1.5f);
basePower = basePower.MultiplyOrMax((float)Math.Pow(1.5f, _stacks));
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle) => RemoveSelf();
public void Stack()
{
_stacks++;
}
}

View File

@@ -13,6 +13,9 @@ public class ImprisonEffect : Script, IScriptPreventMoveSelection
/// <inheritdoc />
public void PreventMoveSelection(IMoveChoice choice, ref bool prevent)
{
if (choice.User.BattleData?.BattleSide == _user.BattleData?.BattleSide)
return;
if (_user.Moves.WhereNotNull().Any(x => x.MoveData.Name == choice.ChosenMove.MoveData.Name))
prevent = true;
}

View File

@@ -6,11 +6,13 @@ public class InfestationEffect : Script, IScriptOnEndTurn, IScriptPreventSelfSwi
{
private readonly IPokemon _owner;
private int _turns;
private readonly float _bindDamage;
public InfestationEffect(IPokemon owner, int turns)
public InfestationEffect(IPokemon owner, int turns, float bindDamage)
{
_owner = owner;
_turns = turns;
_bindDamage = bindDamage;
}
/// <inheritdoc />
@@ -22,8 +24,8 @@ public class InfestationEffect : Script, IScriptOnEndTurn, IScriptPreventSelfSwi
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
var damage = _owner.BoostedStats.Hp / 8;
_owner.Damage(damage, DamageSource.Misc);
var damage = _owner.BoostedStats.Hp * _bindDamage;
_owner.Damage((uint)damage, DamageSource.Misc);
_turns--;
if (_turns <= 0)
@@ -35,6 +37,6 @@ public class InfestationEffect : Script, IScriptOnEndTurn, IScriptPreventSelfSwi
/// <inheritdoc />
public void ExpectedEndOfTurnDamage(IPokemon pokemon, ref int damage)
{
damage += (int)(_owner.MaxHealth / 8f);
damage += (int)(_owner.MaxHealth * _bindDamage);
}
}

View File

@@ -12,10 +12,18 @@ public class IngrainEffect : Script, IScriptFailIncomingMove, IScriptOnEndTurn,
}
/// <inheritdoc />
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)

View File

@@ -3,16 +3,19 @@ using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "kings_shield")]
public class KingsShield : ProtectionEffectScript
public class KingsShieldEffect : ProtectionEffectScript
{
/// <inheritdoc />
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
// Kings Shield doesnt protect from status moves
if (executingMove.UseMove.Category == MoveCategory.Status)
return;
base.BlockIncomingHit(executingMove, target, hitIndex, ref block);
if (executingMove.UseMove.Category != MoveCategory.Status &&
executingMove.GetHitData(target, hitIndex).IsContact)
if (block && executingMove.GetHitData(target, hitIndex).IsContact)
{
executingMove.User.ChangeStatBoost(Statistic.Accuracy, -2, false, false);
executingMove.User.ChangeStatBoost(Statistic.Attack, -2, false, false);
}
}
}

View File

@@ -1,12 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "laser_focus")]
public class LaserFocusEffect : Script, IScriptChangeCriticalStage
public class LaserFocusEffect : Script, IScriptChangeCriticalStage, IScriptOnEndTurn
{
private bool _hasHadEndTurn;
/// <inheritdoc />
public void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
{
stage = 100;
RemoveSelf();
}
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
if (_hasHadEndTurn)
RemoveSelf();
else
_hasHadEndTurn = true;
}
}

View File

@@ -1,19 +1,20 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "lock_on")]
public class LockOnEffect : Script, IScriptOnEndTurn, IScriptChangeAccuracy
public class LockOnEffect : Script, IScriptOnEndTurn, IScriptChangeIncomingAccuracy
{
private readonly IPokemon _placer;
private bool _hasHadEndTurn;
public LockOnEffect(IPokemon placer)
{
_placer = placer;
}
/// <inheritdoc />
public void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref int modifiedAccuracy)
public void ChangeIncomingAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
if (_placer != target)
if (_placer != executingMove.User)
return;
modifiedAccuracy = 255;
}
@@ -21,6 +22,9 @@ public class LockOnEffect : Script, IScriptOnEndTurn, IScriptChangeAccuracy
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
RemoveSelf();
if (_hasHadEndTurn)
RemoveSelf();
else
_hasHadEndTurn = true;
}
}

View File

@@ -1,22 +0,0 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "lucky_chant")]
public class LuckyChantEffect : Script, IScriptBlockCriticalHit, IScriptOnEndTurn
{
private int _turnsLeft = 5;
/// <inheritdoc />
public void BlockCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block)
{
block = true;
}
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
_turnsLeft--;
if (_turnsLeft > 0)
return;
RemoveSelf();
}
}

View File

@@ -5,27 +5,45 @@ public class MagmaStormEffect : Script, IScriptOnEndTurn, IScriptPreventSelfRunA
IAIInfoScriptExpectedEndOfTurnDamage
{
private readonly IPokemon _owner;
private int _turns;
private readonly float _percentOfMaxHealth;
public MagmaStormEffect(IPokemon owner)
public MagmaStormEffect(IPokemon owner, int turns, float percentOfMaxHealth)
{
_owner = owner;
_turns = turns;
_percentOfMaxHealth = percentOfMaxHealth;
}
/// <inheritdoc />
public void OnEndTurn(IScriptSource owner, IBattle battle)
{
_owner.Damage(_owner.BoostedStats.Hp / 16, DamageSource.Misc);
if (_turns > 0)
{
_turns--;
_owner.Damage((uint)(_owner.MaxHealth * _percentOfMaxHealth), DamageSource.Misc);
}
if (_turns <= 0)
RemoveSelf();
}
/// <inheritdoc />
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent) => prevent = true;
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
prevent = true;
}
/// <inheritdoc />
public void ExpectedEndOfTurnDamage(IPokemon pokemon, ref int damage)
{
damage += (int)(pokemon.MaxHealth / 16f);
damage += (int)(pokemon.MaxHealth * _percentOfMaxHealth);
}
}

View File

@@ -3,11 +3,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "magnet_rise")]
public class MagnetRiseEffect : Script, IScriptChangeEffectiveness, IScriptOnEndTurn
{
private int _turnsRemaining = 5;
private int _turnsRemaining = 4;
private static readonly StringKey IronBallName = "iron_ball";
/// <inheritdoc />
public void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
{
if (move.User.HasHeldItem(IronBallName))
return;
if (move.UseMove.MoveType.Name == "ground")
{
effectiveness = 0.0f;

View File

@@ -7,6 +7,9 @@ public class PhantomForceCharge : Script, IScriptForceTurnSelection, IScriptBloc
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public PhantomForceCharge(IPokemon owner)
{
_owner = owner;

View File

@@ -7,6 +7,9 @@ public class ShadowForceCharge : Script, IScriptForceTurnSelection, IScriptBlock
{
private readonly IPokemon _owner;
/// <inheritdoc />
public override bool IsSemiInvulnerableTurn => true;
public ShadowForceCharge(IPokemon owner)
{
_owner = owner;