From 85b513092af0d5f4bf6927fc2fa67139328c917f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Fri, 21 Mar 2025 13:35:12 +0100 Subject: [PATCH] More moves --- PkmnLib.Dynamic/Models/Pokemon.cs | 5 +++ PkmnLib.Tests/Data/Moves.json | 36 ++++++++++++++++--- .../Libraries/Gen7BattleStatCalculator.cs | 2 ++ .../Scripts/CustomTriggers.cs | 4 +++ .../Scripts/Moves/LeechSeed.cs | 19 ++++++++++ .../Scripts/Moves/LightScreen.cs | 28 +++++++++++++++ .../Scripts/Pokemon/LeechSeedEffect.cs | 28 +++++++++++++++ .../Scripts/Side/LightScreenEffect.cs | 29 +++++++++++++-- .../Scripts/Weather/Hail.cs | 9 ++--- 9 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LeechSeed.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LightScreen.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/LeechSeedEffect.cs diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs index 94e2ed6..6e5ee65 100644 --- a/PkmnLib.Dynamic/Models/Pokemon.cs +++ b/PkmnLib.Dynamic/Models/Pokemon.cs @@ -450,6 +450,8 @@ public interface IPokemonBattleData : IDeepCloneable void MarkItemAsConsumed(IItem itemName); uint SwitchInTurn { get; internal set; } + + IBattleSide BattleSide { get; } } /// @@ -1254,4 +1256,7 @@ public class PokemonBattleDataImpl : IPokemonBattleData /// public uint SwitchInTurn { get; set; } + + /// + public IBattleSide BattleSide => Battle.Sides[SideIndex]; } \ No newline at end of file diff --git a/PkmnLib.Tests/Data/Moves.json b/PkmnLib.Tests/Data/Moves.json index 5680291..8a9fccd 100755 --- a/PkmnLib.Tests/Data/Moves.json +++ b/PkmnLib.Tests/Data/Moves.json @@ -6178,7 +6178,10 @@ "protect", "reflectable", "mirror" - ] + ], + "effect": { + "name": "leech_seed" + } }, { "name": "leer", @@ -6215,7 +6218,14 @@ "contact", "protect", "mirror" - ] + ], + "effect": { + "name": "set_status", + "chance": 30, + "parameters": { + "status": "paralyzed" + } + } }, { "name": "light_of_ruin", @@ -6229,7 +6239,13 @@ "flags": [ "protect", "mirror" - ] + ], + "effect": { + "name": "recoil", + "parameters": { + "recoil_percentage": 0.5 + } + } }, { "name": "light_screen", @@ -6242,7 +6258,10 @@ "category": "status", "flags": [ "snatch" - ] + ], + "effect": { + "name": "light_screen" + } }, { "name": "liquidation", @@ -6257,7 +6276,14 @@ "contact", "protect", "mirror" - ] + ], + "effect": { + "name": "change_target_defense", + "chance": 20, + "parameters": { + "amount": -1 + } + } }, { "name": "lock_on", diff --git a/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7BattleStatCalculator.cs b/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7BattleStatCalculator.cs index 8b7cb00..fa05f16 100644 --- a/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7BattleStatCalculator.cs +++ b/Plugins/PkmnLib.Plugin.Gen7/Libraries/Gen7BattleStatCalculator.cs @@ -58,6 +58,8 @@ public class Gen7BattleStatCalculator : IBattleStatCalculator x => x.ChangeAccuracyModifier(executingMove, target, hitIndex, ref accuracyModifier)); var modifiedAccuracy = (int)(moveAccuracy * accuracyModifier); executingMove.RunScriptHook(x => x.ChangeAccuracy(executingMove, target, hitIndex, ref modifiedAccuracy)); + if (modifiedAccuracy == 255) + return 255; var targetEvasion = target.StatBoost.Evasion; var ignoreEvasion = false; executingMove.RunScriptHook(x => x.BypassEvasionStatBoosts(executingMove, target, hitIndex, ref ignoreEvasion)); diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/CustomTriggers.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/CustomTriggers.cs index 4083fdd..392d3f8 100644 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/CustomTriggers.cs +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/CustomTriggers.cs @@ -9,4 +9,8 @@ public static class CustomTriggers public static readonly StringKey BindNumberOfTurns = "bind_number_of_turns"; public static readonly StringKey BindPercentOfMaxHealth = "bind_percent_of_max_health"; + + public static readonly StringKey IgnoreHail = "ignores_hail"; + + public static readonly StringKey LightScreenNumberOfTurns = "light_screen_number_of_turns"; } \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LeechSeed.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LeechSeed.cs new file mode 100644 index 0000000..9ed2893 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LeechSeed.cs @@ -0,0 +1,19 @@ +using System.Linq; +using PkmnLib.Plugin.Gen7.Scripts.Pokemon; + +namespace PkmnLib.Plugin.Gen7.Scripts.Moves; + +[Script(ScriptCategory.Move, "leech_seed")] +public class LeechSeed : Script +{ + /// + public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit) + { + if (target.Types.Any(x => x.Name == "grass")) + { + move.GetHitData(target, hit).Fail(); + return; + } + target.Volatile.Add(new LeechSeedEffect(target, move.User)); + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LightScreen.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LightScreen.cs new file mode 100644 index 0000000..13f97a3 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/LightScreen.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using PkmnLib.Plugin.Gen7.Scripts.Side; +using PkmnLib.Static.Utils; + +namespace PkmnLib.Plugin.Gen7.Scripts.Moves; + +[Script(ScriptCategory.Move, "light_screen")] +public class LightScreen : Script +{ + /// + public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit) + { + var battleData = move.User.BattleData; + if (battleData == null) + return; + + var turns = 5; + var dict = new Dictionary() + { + { "duration", turns }, + }; + move.RunScriptHook(x => x.CustomTrigger(CustomTriggers.LightScreenNumberOfTurns, dict)); + turns = (int)dict.GetOrDefault("duration", turns)!; + + battleData.BattleSide.VolatileScripts.StackOrAdd(ScriptUtils.ResolveName(), + () => new LightScreenEffect(turns)); + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/LeechSeedEffect.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/LeechSeedEffect.cs new file mode 100644 index 0000000..ce59aaa --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Pokemon/LeechSeedEffect.cs @@ -0,0 +1,28 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon; + +[Script(ScriptCategory.Pokemon, "leech_seed")] +public class LeechSeedEffect : Script +{ + private readonly IPokemon _owner; + private readonly IPokemon _placer; + + public LeechSeedEffect(IPokemon owner, IPokemon placer) + { + _owner = owner; + _placer = placer; + } + + /// + public override void OnEndTurn(IBattle battle) + { + var damage = _owner.BoostedStats.Hp / 8; + if (_owner.CurrentHealth <= damage) + damage = _owner.CurrentHealth; + + _owner.Damage(damage, DamageSource.Misc); + if (_owner.ActiveAbility?.Name == "liquid_ooze") + _placer.Damage(damage, DamageSource.Misc); + else + _placer.Heal(damage); + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/LightScreenEffect.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/LightScreenEffect.cs index a363d02..d1b238b 100644 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/LightScreenEffect.cs +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/LightScreenEffect.cs @@ -1,7 +1,32 @@ +using PkmnLib.Static.Moves; + namespace PkmnLib.Plugin.Gen7.Scripts.Side; [Script(ScriptCategory.Side, "light_screen")] -public class LightScreenEffect : Script +public class LightScreenEffect(int turns) : Script { - // TODO: Implement LightScreenEffect + private int _turns = turns; + + /// + public override void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon 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; + // If not a 1v1 battle, damage reduction is only 1/3rd. + if (battleData?.Battle.PositionsPerSide > 1) + damage = (uint)(damage * (2.0f / 3.0f)); + else + damage = (uint)(damage * 0.5f); + } + + /// + public override void OnEndTurn(IBattle battle) + { + _turns -= 1; + if (_turns <= 0) + RemoveSelf(); + } } \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Hail.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Hail.cs index fbdc70b..79d421b 100644 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Hail.cs +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Hail.cs @@ -32,10 +32,11 @@ public class Hail : Script, IWeatherScript if (pokemon.Types.Contains(iceType)) continue; var ignoresHail = false; - pokemon.RunScriptHook(x => x.CustomTrigger("ignores_hail", new Dictionary() - { - { "ignoresHail", ignoresHail }, - })); + pokemon.RunScriptHook(x => x.CustomTrigger(CustomTriggers.IgnoreHail, + new Dictionary() + { + { "ignoresHail", ignoresHail }, + })); if (ignoresHail) continue;