diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs
index 09b0ea1..5fb8cbb 100644
--- a/PkmnLib.Dynamic/Models/Pokemon.cs
+++ b/PkmnLib.Dynamic/Models/Pokemon.cs
@@ -1256,6 +1256,8 @@ public class PokemonImpl : ScriptSource, IPokemon
{
ChangeForm(battleData.OriginalSpecies == Species ? battleData.OriginalForm : Species.GetDefaultForm());
}
+ DisplaySpecies = null;
+ DisplayForm = null;
}
///
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
index 75d4d21..dbae696 100755
--- a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
+++ b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
@@ -288,15 +288,33 @@
"infiltrator": {
"effect": "infiltrator"
},
- "innards_out": {},
- "inner_focus": {},
- "insomnia": {},
- "intimidate": {},
- "iron_barbs": {},
- "iron_fist": {},
- "justified": {},
- "keen_eye": {},
- "klutz": {},
+ "innards_out": {
+ "effect": "innards_out"
+ },
+ "inner_focus": {
+ "effect": "inner_focus"
+ },
+ "insomnia": {
+ "effect": "insomnia"
+ },
+ "intimidate": {
+ "effect": "intimidate"
+ },
+ "iron_barbs": {
+ "effect": "iron_barbs"
+ },
+ "iron_fist": {
+ "effect": "iron_fist"
+ },
+ "justified": {
+ "effect": "justified"
+ },
+ "keen_eye": {
+ "effect": "keen_eye"
+ },
+ "klutz": {
+ "effect": "klutz"
+ },
"leaf_guard": {},
"levitate": {},
"light_metal": {},
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnardsOut.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnardsOut.cs
new file mode 100644
index 0000000..5d52206
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnardsOut.cs
@@ -0,0 +1,35 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Innards Out is an ability that deals damage to the attacker equal to the amount of HP lost when the Pokémon with this ability faints.
+///
+/// Bulbapedia - Innards Out
+///
+[Script(ScriptCategory.Ability, "innards_out")]
+public class InnardsOut : Script
+{
+ private IPokemon? _lastPokemonToHit;
+
+ ///
+ public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
+ {
+ _lastPokemonToHit = move.User;
+ }
+
+ ///
+ public override void OnDamage(IPokemon pokemon, DamageSource source, uint oldHealth, uint newHealth)
+ {
+ if (newHealth != 0 || source is not DamageSource.MoveDamage)
+ return;
+ if (_lastPokemonToHit is null || !_lastPokemonToHit.IsUsable)
+ return;
+
+ EventBatchId batchId = new();
+
+ pokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
+ {
+ BatchId = batchId,
+ });
+ _lastPokemonToHit.Damage(oldHealth, DamageSource.Misc, batchId);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnerFocus.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnerFocus.cs
new file mode 100644
index 0000000..1bdd4c7
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/InnerFocus.cs
@@ -0,0 +1,31 @@
+using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
+
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Inner Focus is an ability that prevents the Pokémon from flinching.
+///
+/// Bulbapedia - Inner Focus
+///
+[Script(ScriptCategory.Ability, "inner_focus")]
+public class InnerFocus : Script
+{
+ private IPokemon? _pokemon;
+
+ ///
+ public override void OnAddedToParent(IScriptSource source)
+ {
+ if (source is not IPokemon pokemon)
+ throw new InvalidOperationException("Illusion can only be added to a Pokemon script source.");
+ _pokemon = pokemon;
+ }
+
+ ///
+ public override void PreventVolatileAdd(Script script, ref bool preventVolatileAdd)
+ {
+ if (script is not FlinchEffect)
+ return;
+ _pokemon?.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(_pokemon));
+ preventVolatileAdd = true;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Insomnia.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Insomnia.cs
new file mode 100644
index 0000000..d835d28
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Insomnia.cs
@@ -0,0 +1,20 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Insomnia is an ability that prevents the Pokémon from falling asleep.
+///
+/// Bulbapedia - Insomnia
+///
+[Script(ScriptCategory.Ability, "insomnia")]
+public class Insomnia : Script
+{
+ ///
+ public override void PreventStatusChange(IPokemon pokemon, StringKey status, bool selfInflicted,
+ ref bool preventStatus)
+ {
+ if (status != ScriptUtils.ResolveName())
+ return;
+ pokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
+ preventStatus = true;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Intimidate.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Intimidate.cs
new file mode 100644
index 0000000..fff2199
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Intimidate.cs
@@ -0,0 +1,28 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Intimidate is an ability that lowers the opposing Pokémon's Attack stat when the Pokémon enters battle.
+///
+/// Bulbapedia - Intimidate
+///
+[Script(ScriptCategory.Ability, "intimidate")]
+public class Intimidate : Script
+{
+ ///
+ public override void OnSwitchIn(IPokemon pokemon, byte position)
+ {
+ var battle = pokemon.BattleData?.Battle;
+ if (battle is null)
+ return;
+
+ var opponents = battle.Sides.Where(side => side != pokemon.BattleData?.BattleSide)
+ .SelectMany(side => side.Pokemon).WhereNotNull().Where(opponent => opponent.IsUsable);
+ EventBatchId batchId = new();
+
+ battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
+ foreach (var opponent in opponents)
+ {
+ opponent.ChangeStatBoost(Statistic.Attack, -1, true, true, batchId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronBarbs.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronBarbs.cs
new file mode 100644
index 0000000..5f7afd3
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronBarbs.cs
@@ -0,0 +1,19 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Iron Barbs is an ability that damages attackers making contact with the Pokémon.
+///
+/// Bulbapedia - Iron Barbs
+///
+[Script(ScriptCategory.Ability, "iron_barbs")]
+public class IronBarbs : Script
+{
+ ///
+ public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
+ {
+ if (move.UseMove.HasFlag("contact"))
+ {
+ move.User.Damage(move.User.MaxHealth / 8, DamageSource.Misc);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronFist.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronFist.cs
new file mode 100644
index 0000000..1af61aa
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/IronFist.cs
@@ -0,0 +1,17 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Iron Fist is an ability that increases the power of punching moves.
+///
+/// Bulbapedia - Iron Fist
+///
+[Script(ScriptCategory.Ability, "iron_fist")]
+public class IronFist : Script
+{
+ ///
+ public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
+ {
+ if (move.UseMove.HasFlag("punch"))
+ basePower = basePower.MultiplyOrMax(1.2f);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Justified.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Justified.cs
new file mode 100644
index 0000000..2b7add1
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Justified.cs
@@ -0,0 +1,25 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Justified is an ability that raises the Pokémon's Attack stat when hit by a Dark-type move.
+///
+/// Bulbapedia - Justified
+///
+[Script(ScriptCategory.Ability, "justified")]
+public class Justified : Script
+{
+ ///
+ public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
+ {
+ if (move.GetHitData(target, hit).Type?.Name != "dark")
+ return;
+
+ EventBatchId batchId = new();
+
+ move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target)
+ {
+ BatchId = batchId,
+ });
+ target.ChangeStatBoost(Statistic.Attack, 1, true, false, batchId);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/KeenEye.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/KeenEye.cs
new file mode 100644
index 0000000..8c25e9e
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/KeenEye.cs
@@ -0,0 +1,18 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Keen Eye is an ability that prevents the Pokémon's accuracy from being lowered.
+///
+/// Bulbapedia - Keen Eye
+///
+[Script(ScriptCategory.Ability, "keen_eye")]
+public class KeenEye : Script
+{
+ ///
+ public override void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
+ ref bool prevent)
+ {
+ if (stat == Statistic.Accuracy && amount < 0)
+ prevent = true;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Klutz.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Klutz.cs
new file mode 100644
index 0000000..52ef179
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Klutz.cs
@@ -0,0 +1,23 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Klutz is an ability that prevents the Pokémon from using its held item in battle.
+///
+/// Bulbapedia - Klutz
+///
+[Script(ScriptCategory.Ability, "klutz")]
+public class Klutz : Script
+{
+ ///
+ public override void OnBeforeAnyHookInvoked(ref List? suppressedCategories)
+ {
+ suppressedCategories ??= new List();
+ suppressedCategories.Add(ScriptCategory.ItemBattleTrigger);
+ }
+
+ ///
+ public override void PreventHeldItemConsume(IPokemon pokemon, IItem heldItem, ref bool prevented)
+ {
+ prevented = true;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs
index 21ee145..fd1f54a 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/Rest.cs
@@ -18,6 +18,12 @@ public class Rest : Script
move.GetHitData(target, hit).Fail();
return;
}
+ if (move.User.ActiveAbility?.Effect == ScriptUtils.ResolveName())
+ {
+ move.GetHitData(target, hit).Fail();
+ return;
+ }
+
if (move.User.SetStatus(ScriptUtils.ResolveName(), true) && move.User.StatusScript.Script is Sleep sleep)
sleep.Turns = 2;
}