diff --git a/PkmnLib.Dynamic/Models/Pokemon.cs b/PkmnLib.Dynamic/Models/Pokemon.cs
index eac1629..217cb4b 100644
--- a/PkmnLib.Dynamic/Models/Pokemon.cs
+++ b/PkmnLib.Dynamic/Models/Pokemon.cs
@@ -263,6 +263,11 @@ public interface IPokemon : IScriptSource, IDeepCloneable
///
bool ConsumeHeldItem();
+ ///
+ /// Uses an item on the Pokemon.
+ ///
+ void UseItem(IItem item);
+
///
/// Change a boosted stat by a certain amount.
///
@@ -805,8 +810,15 @@ public class PokemonImpl : ScriptSource, IPokemon
BattleData.MarkItemAsConsumed(HeldItem);
}
+ UseItem(SetHeldItem(null)!);
+ return true;
+ }
+
+ public void UseItem(IItem item)
+ {
// TODO: actually consume the item
- throw new NotImplementedException();
+
+ this.RunScriptHook(x => x.OnAfterItemConsume(this, item));
}
///
diff --git a/PkmnLib.Dynamic/ScriptHandling/Script.cs b/PkmnLib.Dynamic/ScriptHandling/Script.cs
index c1e0928..e6ec591 100644
--- a/PkmnLib.Dynamic/ScriptHandling/Script.cs
+++ b/PkmnLib.Dynamic/ScriptHandling/Script.cs
@@ -557,7 +557,7 @@ public abstract class Script : IDeepCloneable
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
/// held item it had.
///
- public virtual void OnAfterHeldItemConsume(IPokemon pokemon, IItem item)
+ public virtual void OnAfterItemConsume(IPokemon pokemon, IItem item)
{
}
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.json b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
similarity index 95%
rename from Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.json
rename to Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
index f4fb4f9..74b9deb 100755
--- a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.json
+++ b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
@@ -72,22 +72,24 @@
"effect": "bulletproof"
},
"cheek_pouch": {
- "effect": "CheekPouch"
+ "effect": "cheek_pouch"
},
"chlorophyll": {
- "effect": "DoubleSpeedInWeather",
+ "effect": "speed_modifier_in_weather",
"parameters": {
- "weather": "HarshSunlight"
+ "weather": "sunny",
+ "modifier": 2.0
}
},
"clear_body": {
- "effect": "PreventStatLowering"
+ "effect": "prevent_stat_lowering"
+ // By not specifying a stat, it applies to all stats
},
"cloud_nine": {
- "effect": "SuppressWeather"
+ "effect": "suppress_weather"
},
"color_change": {
- "effect": "ColorChange"
+ "effect": "color_change"
},
"comatose": {
"canBeChanged": false
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Gen7Plugin.cs b/Plugins/PkmnLib.Plugin.Gen7/Gen7Plugin.cs
index 44ebec7..a7c2442 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Gen7Plugin.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Gen7Plugin.cs
@@ -69,7 +69,7 @@ public class Gen7Plugin : Plugin, IResourceProvider
typeof(Gen7Plugin).Assembly),
ResourceFileType.Items => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Items.json",
typeof(Gen7Plugin).Assembly),
- ResourceFileType.Abilities => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Abilities.json",
+ ResourceFileType.Abilities => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.Abilities.jsonc",
typeof(Gen7Plugin).Assembly),
ResourceFileType.GrowthRates => new AssemblyResourceResult("PkmnLib.Plugin.Gen7.Data.GrowthRates.json",
typeof(Gen7Plugin).Assembly),
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/CheekPouch.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/CheekPouch.cs
new file mode 100644
index 0000000..a845a78
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/CheekPouch.cs
@@ -0,0 +1,15 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+[Script(ScriptCategory.Ability, "cheek_pouch")]
+public class CheekPouch : Script
+{
+ ///
+ public override void OnAfterItemConsume(IPokemon pokemon, IItem item)
+ {
+ if (item.Category == ItemCategory.Berry)
+ {
+ pokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
+ pokemon.Heal(pokemon.MaxHealth / 3);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ColorChange.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ColorChange.cs
new file mode 100644
index 0000000..f589c90
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ColorChange.cs
@@ -0,0 +1,16 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+[Script(ScriptCategory.Ability, "color_change")]
+public class ColorChange : Script
+{
+ ///
+ public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
+ {
+ var hitData = move.GetHitData(target, hit);
+ if (hitData.Type != null && (hitData.Type != target.Types.FirstOrDefault() || target.Types.Count > 1))
+ {
+ target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
+ target.SetTypes([hitData.Type.Value]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PreventStatLowering.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PreventStatLowering.cs
index e501b83..719f6fb 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PreventStatLowering.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PreventStatLowering.cs
@@ -5,26 +5,37 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
[Script(ScriptCategory.Ability, "prevent_stat_lowering")]
public class PreventStatLowering : Script
{
- private Statistic _statistic;
+ ///
+ /// The statistic that this ability prevents from being lowered.
+ /// Null means it prevents all stat lowering.
+ ///
+ private Statistic? _statistic;
///
public override void OnInitialize(IReadOnlyDictionary? parameters)
{
if (parameters is null)
throw new ArgumentNullException(nameof(parameters), "Parameters cannot be null.");
- if (!parameters.TryGetValue("stat", out var statObj) || statObj is not string statStr)
- throw new ArgumentException("Parameter 'stat' is required and must be a string.", nameof(parameters));
- if (!Enum.TryParse(statStr, true, out Statistic stat))
- throw new ArgumentException($"Invalid statistic '{statStr}' provided.", nameof(statStr));
-
- _statistic = stat;
+ if (parameters.TryGetValue("stat", out var statObj) && statObj is string statStr)
+ {
+ if (!Enum.TryParse(statStr, true, out Statistic stat))
+ throw new ArgumentException($"Invalid statistic '{statStr}' provided.", nameof(statStr));
+ _statistic = stat;
+ }
}
///
public override void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
ref bool prevent)
{
+ if (_statistic is not null && _statistic != stat)
+ return;
+ if (amount >= 0)
+ return;
if (!selfInflicted)
- prevent = false;
+ {
+ target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
+ prevent = true;
+ }
}
}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/SpeedModifierInWeather.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/SpeedModifierInWeather.cs
new file mode 100644
index 0000000..52ee809
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/SpeedModifierInWeather.cs
@@ -0,0 +1,41 @@
+using PkmnLib.Static.Utils;
+
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+[Script(ScriptCategory.Ability, "speed_modifier_in_weather")]
+public class SpeedModifierInWeather : Script
+{
+ private StringKey _weather;
+ private float _modifier;
+
+ ///
+ public override void OnInitialize(IReadOnlyDictionary? parameters)
+ {
+ if (parameters is null)
+ throw new ArgumentNullException(nameof(parameters));
+
+ if (!parameters.TryGetValue("weather", out var weatherObj) || weatherObj is not string weatherStr)
+ throw new ArgumentException("Parameter 'weather' is required and must be a string.", nameof(parameters));
+ if (!parameters.TryGetValue("modifier", out var modifierObj))
+ throw new ArgumentException("Parameter 'modifier' is required", nameof(parameters));
+ if (modifierObj is not float modifier && modifierObj is not int)
+ throw new ArgumentException("Parameter 'modifier' must be a float or int.", nameof(parameters));
+ var weatherModifier = modifierObj is float modFloat ? modFloat : (int)modifierObj;
+
+ _weather = weatherStr;
+ _modifier = weatherModifier;
+ }
+
+ ///
+ public override void ChangeSpeed(ITurnChoice choice, ref uint speed)
+ {
+ var battle = choice.User.BattleData?.Battle;
+ if (battle is null)
+ return;
+ var weather = battle.WeatherName;
+ if (weather == _weather)
+ {
+ speed = speed.MultiplyOrMax(_modifier);
+ }
+ }
+}
\ No newline at end of file