From ec8681eaa99bf2e78c56ea75056f10a0cbbafcea Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 15 Jun 2025 13:05:52 +0200 Subject: [PATCH] More abilities --- .../BattleFlow/MoveTurnExecutor.cs | 1 + PkmnLib.Dynamic/BattleFlow/TurnRunner.cs | 1 + PkmnLib.Dynamic/ScriptHandling/Script.cs | 8 ++ .../PkmnLib.Plugin.Gen7/Data/Abilities.jsonc | 87 ++++++++++++++----- .../Scripts/Abilities/Overgrow.cs | 17 ---- .../Abilities/PowerUpTypeAtLowHealth.cs | 2 +- .../Scripts/Abilities/Swarm.cs | 20 ----- .../Scripts/Abilities/TangledFeet.cs | 20 +++++ .../Scripts/Abilities/TanglingHair.cs | 24 +++++ .../Scripts/Abilities/Technician.cs | 19 ++++ .../Scripts/Abilities/Telepathy.cs | 17 ++++ .../Scripts/Abilities/Teravolt.cs | 41 +++++++++ .../Scripts/Abilities/ThickFat.cs | 20 +++++ .../Scripts/Abilities/TintedLens.cs | 19 ++++ .../Scripts/Abilities/ToughClaws.cs | 19 ++++ .../Scripts/Abilities/ToxicBoost.cs | 20 +++++ .../Scripts/Side/TeravoltEffect.cs | 18 ++++ 17 files changed, 294 insertions(+), 59 deletions(-) delete mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Overgrow.cs delete mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Swarm.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TangledFeet.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TanglingHair.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Technician.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Telepathy.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Teravolt.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ThickFat.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TintedLens.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToughClaws.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToxicBoost.cs create mode 100644 Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/TeravoltEffect.cs diff --git a/PkmnLib.Dynamic/BattleFlow/MoveTurnExecutor.cs b/PkmnLib.Dynamic/BattleFlow/MoveTurnExecutor.cs index 044cec5..03c2b2b 100644 --- a/PkmnLib.Dynamic/BattleFlow/MoveTurnExecutor.cs +++ b/PkmnLib.Dynamic/BattleFlow/MoveTurnExecutor.cs @@ -46,6 +46,7 @@ public static class MoveTurnExecutor moveChoice.Script.Clear(); } } + moveChoice.RunScriptHook(x => x.OnBeforeMoveChoice(moveChoice)); var targetType = useMove.Target; var targets = diff --git a/PkmnLib.Dynamic/BattleFlow/TurnRunner.cs b/PkmnLib.Dynamic/BattleFlow/TurnRunner.cs index 1e9f605..defd738 100644 --- a/PkmnLib.Dynamic/BattleFlow/TurnRunner.cs +++ b/PkmnLib.Dynamic/BattleFlow/TurnRunner.cs @@ -89,6 +89,7 @@ public static class TurnRunner { case IMoveChoice moveChoice: MoveTurnExecutor.ExecuteMoveChoice(battle, moveChoice); + moveChoice.RunScriptHook(script => script.OnAfterMoveChoice(moveChoice)); break; case ISwitchChoice switchChoice: ExecuteSwitchChoice(battle, switchChoice); diff --git a/PkmnLib.Dynamic/ScriptHandling/Script.cs b/PkmnLib.Dynamic/ScriptHandling/Script.cs index a991219..f3525e8 100644 --- a/PkmnLib.Dynamic/ScriptHandling/Script.cs +++ b/PkmnLib.Dynamic/ScriptHandling/Script.cs @@ -843,4 +843,12 @@ public abstract class Script : IDeepCloneable public virtual void ModifyPPUsedForIncomingMove(IExecutingMove executingMove, ref byte ppUsed) { } + + public virtual void OnBeforeMoveChoice(IMoveChoice moveChoice) + { + } + + public virtual void OnAfterMoveChoice(IMoveChoice moveChoice) + { + } } \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc index 415b074..acfdc04 100755 --- a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc +++ b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc @@ -407,7 +407,11 @@ "effect": "overcoat" }, "overgrow": { - "effect": "overgrow" + "effect": "power_up_type_at_low_health", + "parameters": { + "type": "grass", + "threshold": 0.33333 + } }, "own_tempo": { "effect": "own_tempo" @@ -625,26 +629,67 @@ "storm_drain": { "effect": "storm_drain" }, - "strong_jaw": {}, - "sturdy": {}, - "suction_cups": {}, - "super_luck": {}, - "surge_surfer": {}, - "swarm": {}, - "sweet_veil": {}, - "swift_swim": {}, - "symbiosis": {}, - "synchronize": {}, - "tangled_feet": {}, - "tangling_hair": {}, - "technician": {}, - "telepathy": {}, - "teravolt": {}, - "thick_fat": {}, - "tinted_lens": {}, - "torrent": {}, - "tough_claws": {}, - "toxic_boost": {}, + "strong_jaw": { + "effect": "strong_jaw" + }, + "sturdy": { + "effect": "sturdy" + }, + "suction_cups": { + "effect": "suction_cups" + }, + "super_luck": { + "effect": "super_luck" + }, + "surge_surfer": { + "effect": "surge_surfer" + }, + "swarm": { + "effect": "power_up_type_at_low_health", + "parameters": { + "type": "bug", + "threshold": 0.33333 + } + }, + "sweet_veil": { + "effect": "sweet_veil" + }, + "swift_swim": { + "effect": "swift_swim" + }, + "symbiosis": { + "effect": "symbiosis" + }, + "synchronize": { + "effect": "synchronize" + }, + "tangled_feet": { + "effect": "tangled_feet" + }, + "tangling_hair": { + "effect": "tangling_hair" + }, + "technician": { + "effect": "technician" + }, + "telepathy": { + "effect": "telepathy" + }, + "teravolt": { + "effect": "teravolt" + }, + "thick_fat": { + "effect": "thick_fat" + }, + "tinted_lens": { + "effect": "tinted_lens" + }, + "tough_claws": { + "effect": "tough_claws" + }, + "toxic_boost": { + "effect": "toxic_boost" + }, "trace": { "flags": [ "cant_be_copied" diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Overgrow.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Overgrow.cs deleted file mode 100644 index b305efe..0000000 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Overgrow.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; - -/// -/// Overgrow is an ability that boosts the power of Grass-type moves when the Pokémon's HP is low. -/// -/// Bulbapedia - Overgrow -/// -[Script(ScriptCategory.Ability, "overgrow")] -public class Overgrow : Script -{ - /// - public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower) - { - if (move.GetHitData(target, hit).Type?.Name == "grass" && target.CurrentHealth <= target.BoostedStats.Hp / 3) - basePower = basePower.MultiplyOrMax(1.5f); - } -} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PowerUpTypeAtLowHealth.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PowerUpTypeAtLowHealth.cs index b3a7d14..daa7684 100644 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PowerUpTypeAtLowHealth.cs +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PowerUpTypeAtLowHealth.cs @@ -27,7 +27,7 @@ public class PowerUpTypeAtLowHealth : Script if (!parameters.TryGetValue("threshold", out var threshold) || threshold is not float thresholdValue) throw new ArgumentException("Parameter 'threshold' is required and must be a float.", nameof(parameters)); - if (thresholdValue < 0 || thresholdValue > 1) + if (thresholdValue is < 0 or > 1) throw new ArgumentOutOfRangeException(nameof(threshold), "Threshold must be between 0 and 1."); _type = typeName; diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Swarm.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Swarm.cs deleted file mode 100644 index 68f187b..0000000 --- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Swarm.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; - -/// -/// Swarm is an ability that powers up Bug-type moves when the Pokémon's HP is low. -/// -/// Bulbapedia - Swarm -/// -[Script(ScriptCategory.Ability, "swarm")] -public class Swarm : Script -{ - /// - public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat, - ImmutableStatisticSet targetStats, Statistic stat, ref uint value) - { - if (move.GetHitData(target, hit).Type?.Name == "bug" && target.CurrentHealth <= target.MaxHealth / 3) - { - value = value.MultiplyOrMax(1.5f); - } - } -} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TangledFeet.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TangledFeet.cs new file mode 100644 index 0000000..a2029a1 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TangledFeet.cs @@ -0,0 +1,20 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Tangled Feet is an ability that raises evasion if the Pokémon is confused. +/// +/// Bulbapedia - Tangled Feet +/// +[Script(ScriptCategory.Ability, "tangled_feet")] +public class TangledFeet : Script +{ + /// + public override void ChangeIncomingAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex, + ref int modifiedAccuracy) + { + if (modifiedAccuracy != 255 && target.Volatile.Contains()) + { + modifiedAccuracy /= 2; + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TanglingHair.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TanglingHair.cs new file mode 100644 index 0000000..e07e077 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TanglingHair.cs @@ -0,0 +1,24 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Tangling Hair is an ability that lowers the Speed of attackers making contact. +/// +/// Bulbapedia - Tangling Hair +/// +[Script(ScriptCategory.Ability, "tangling_hair")] +public class TanglingHair : Script +{ + /// + public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit) + { + if (!move.GetHitData(target, hit).IsContact) + return; + + EventBatchId batchId = new(); + move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target) + { + BatchId = batchId, + }); + move.User.ChangeStatBoost(Statistic.Speed, -1, false, false, batchId); + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Technician.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Technician.cs new file mode 100644 index 0000000..515a71e --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Technician.cs @@ -0,0 +1,19 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Technician is an ability that boosts the power of the Pokémon's weaker moves. +/// +/// Bulbapedia - Technician +/// +[Script(ScriptCategory.Ability, "technician")] +public class Technician : Script +{ + /// + public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower) + { + if (move.UseMove.BasePower <= 60) + { + basePower = basePower.MultiplyOrMax(1.5f); + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Telepathy.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Telepathy.cs new file mode 100644 index 0000000..a5d59e8 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Telepathy.cs @@ -0,0 +1,17 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Telepathy is an ability that prevents damage from allies' moves. +/// +/// Bulbapedia - Telepathy +/// +[Script(ScriptCategory.Ability, "telepathy")] +public class Telepathy : Script +{ + /// + public override void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable) + { + if (move.User.BattleData?.BattleSide == target.BattleData?.BattleSide) + invulnerable = true; + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Teravolt.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Teravolt.cs new file mode 100644 index 0000000..2710738 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Teravolt.cs @@ -0,0 +1,41 @@ +using PkmnLib.Plugin.Gen7.Scripts.Pokemon; +using PkmnLib.Plugin.Gen7.Scripts.Side; + +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Teravolt is an ability that allows moves to ignore the target's abilities if they could hinder or prevent the move. +/// +/// Bulbapedia - Teravolt +/// +[Script(ScriptCategory.Ability, "teravolt")] +public class Teravolt : Script +{ + /// + public override void OnBeforeMoveChoice(IMoveChoice moveChoice) + { + var battleData = moveChoice.User.BattleData; + if (battleData is null) + return; + + var sides = battleData.Battle.Sides.Where(x => x != battleData.BattleSide); + foreach (var side in sides) + { + side.VolatileScripts.Add(new TeravoltEffect()); + } + } + + /// + public override void OnAfterMoveChoice(IMoveChoice move) + { + var battleData = move.User.BattleData; + if (battleData is null) + return; + + var sides = battleData.Battle.Sides.Where(x => x != battleData.BattleSide); + foreach (var side in sides) + { + side.VolatileScripts.Remove(); + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ThickFat.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ThickFat.cs new file mode 100644 index 0000000..e942fa8 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ThickFat.cs @@ -0,0 +1,20 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Thick Fat is an ability that halves the damage taken from Fire- and Ice-type moves. +/// +/// Bulbapedia - Thick Fat +/// +[Script(ScriptCategory.Ability, "thick_fat")] +public class ThickFat : Script +{ + /// + public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) + { + var type = move.GetHitData(target, hit).Type; + if (type is not null && (type.Value.Name == "ice" || type.Value.Name == "fire")) + { + damage /= 2; + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TintedLens.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TintedLens.cs new file mode 100644 index 0000000..5c8e021 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/TintedLens.cs @@ -0,0 +1,19 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Tinted Lens is an ability that doubles the damage of not very effective moves. +/// +/// Bulbapedia - Tinted Lens +/// +[Script(ScriptCategory.Ability, "tinted_lens")] +public class TintedLens : Script +{ + /// + public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) + { + if (move.GetHitData(target, hit).Effectiveness < 1.0f) + { + damage = damage.MultiplyOrMax(2); + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToughClaws.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToughClaws.cs new file mode 100644 index 0000000..52d6f59 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToughClaws.cs @@ -0,0 +1,19 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Tough Claws is an ability that boosts the power of contact moves. +/// +/// Bulbapedia - Tough Claws +/// +[Script(ScriptCategory.Ability, "tough_claws")] +public class ToughClaws : Script +{ + /// + public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) + { + if (move.GetHitData(target, hit).IsContact) + { + damage = damage.MultiplyOrMax(5325 / 4096f); + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToxicBoost.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToxicBoost.cs new file mode 100644 index 0000000..e19b33d --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ToxicBoost.cs @@ -0,0 +1,20 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Abilities; + +/// +/// Toxic Boost is an ability that increases Attack when the Pokémon is poisoned. +/// +/// Bulbapedia - Toxic Boost +/// +[Script(ScriptCategory.Ability, "toxic_boost")] +public class ToxicBoost : Script +{ + /// + public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) + { + if (move.User.HasStatus(ScriptUtils.ResolveName()) || + move.User.HasStatus(ScriptUtils.ResolveName())) + { + damage = damage.MultiplyOrMax(1.5f); + } + } +} \ No newline at end of file diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/TeravoltEffect.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/TeravoltEffect.cs new file mode 100644 index 0000000..b197fc5 --- /dev/null +++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Side/TeravoltEffect.cs @@ -0,0 +1,18 @@ +namespace PkmnLib.Plugin.Gen7.Scripts.Side; + +[Script(ScriptCategory.Side, "teravolt")] +public class TeravoltEffect : Script +{ + /// + public override void OnBeforeAnyHookInvoked(ref List? suppressedCategories) + { + suppressedCategories ??= []; + suppressedCategories.Add(ScriptCategory.Ability); + } + + /// + public override void OnEndTurn(IScriptSource owner, IBattle battle) + { + RemoveSelf(); + } +} \ No newline at end of file