diff --git a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
index c229176..189ea87 100755
--- a/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
+++ b/Plugins/PkmnLib.Plugin.Gen7/Data/Abilities.jsonc
@@ -437,9 +437,13 @@
"effect": "poison_touch"
},
"power_construct": {
+ "canBeChanged": false,
"effect": "power_construct"
},
"power_of_alchemy": {
+ "flags": [
+ "cant_be_copied"
+ ],
"effect": "power_of_alchemy"
},
"prankster": {
@@ -448,13 +452,27 @@
"pressure": {
"effect": "pressure"
},
- "primordial_sea": {},
- "prism_armor": {},
- "protean": {},
- "psychic_surge": {},
- "pure_power": {},
- "queenly_majesty": {},
- "quick_feet": {},
+ "primordial_sea": {
+ "effect": "primordial_sea"
+ },
+ "prism_armor": {
+ "effect": "prism_armor"
+ },
+ "protean": {
+ "effect": "protean"
+ },
+ "psychic_surge": {
+ "effect": "psychic_surge"
+ },
+ "pure_power": {
+ "effect": "pure_power"
+ },
+ "queenly_majesty": {
+ "effect": "queenly_majesty"
+ },
+ "quick_feet": {
+ "effect": "quick_feet"
+ },
"rain_dish": {},
"rattled": {},
"receiver": {
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ParentalBond.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ParentalBond.cs
index 2a7c2ef..8e82aba 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ParentalBond.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/ParentalBond.cs
@@ -8,5 +8,17 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
[Script(ScriptCategory.Ability, "parental_bond")]
public class ParentalBond : Script
{
- // TODO: Implement Parental Bond effect.
+ ///
+ public override void ChangeNumberOfHits(IMoveChoice choice, ref byte numberOfHits)
+ {
+ if (numberOfHits == 1)
+ numberOfHits = 2;
+ }
+
+ ///
+ public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
+ {
+ if (hit == 1)
+ basePower = (ushort)(basePower / 4);
+ }
}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrimordialSeaAbility.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrimordialSeaAbility.cs
new file mode 100644
index 0000000..e3a3b5f
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrimordialSeaAbility.cs
@@ -0,0 +1,25 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Primordial Sea is an ability that creates heavy rain when the Pokémon enters battle and prevents Fire-type moves from being used.
+///
+/// Bulbapedia - Primordial Sea
+///
+[Script(ScriptCategory.Ability, "primordial_sea")]
+public class PrimordialSeaAbility : Script
+{
+ ///
+ public override void OnSwitchIn(IPokemon pokemon, byte position)
+ {
+ var battle = pokemon.BattleData?.Battle;
+ if (battle == null)
+ return;
+
+ battle.SetWeather(ScriptUtils.ResolveName(), -1);
+ if (battle.WeatherName == ScriptUtils.ResolveName())
+ {
+ ((Weather.PrimordialSea)battle.WeatherScript.Script!).MarkAsPlaced(pokemon);
+ battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrismArmor.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrismArmor.cs
new file mode 100644
index 0000000..cac72a5
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PrismArmor.cs
@@ -0,0 +1,17 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Prism Armor is an ability that reduces the damage taken from super effective moves.
+///
+/// Bulbapedia - Prism Armor
+///
+[Script(ScriptCategory.Ability, "prism_armor")]
+public class PrismArmor : Script
+{
+ ///
+ public override void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
+ {
+ if (move.GetHitData(target, hit).Effectiveness >= 2)
+ damage = (uint)(damage * 0.75);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Protean.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Protean.cs
new file mode 100644
index 0000000..4fd6eff
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Protean.cs
@@ -0,0 +1,19 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Protean is an ability that changes the Pokémon's type to the type of the move it is about to use.
+///
+/// Bulbapedia - Protean
+///
+[Script(ScriptCategory.Ability, "protean")]
+public class Protean : Script
+{
+ ///
+ public override void OnBeforeMove(IExecutingMove move)
+ {
+ if (move.User.Types.Count == 1 && move.User.Types[0] == move.UseMove.MoveType)
+ return;
+ move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
+ move.User.SetTypes([move.UseMove.MoveType]);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PsychicSurge.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PsychicSurge.cs
new file mode 100644
index 0000000..75ea46d
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PsychicSurge.cs
@@ -0,0 +1,28 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Psychic Surge is an ability that creates Psychic Terrain when the Pokémon enters battle.
+///
+/// Bulbapedia - Psychic Surge
+///
+[Script(ScriptCategory.Ability, "psychic_surge")]
+public class PsychicSurge : Script
+{
+ ///
+ public override void OnSwitchIn(IPokemon pokemon, byte position)
+ {
+ if (pokemon.BattleData?.Battle is null)
+ return;
+
+ var terrainName = ScriptUtils.ResolveName();
+ if (pokemon.BattleData.Battle.TerrainName == terrainName)
+ return;
+
+ EventBatchId batchId = new();
+ pokemon.BattleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
+ {
+ BatchId = batchId,
+ });
+ pokemon.BattleData.Battle.SetTerrain(terrainName, batchId);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PurePower.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PurePower.cs
new file mode 100644
index 0000000..bd50db2
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/PurePower.cs
@@ -0,0 +1,20 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Pure Power is an ability that doubles the Pokémon's Attack stat.
+///
+/// Bulbapedia - Pure Power
+///
+[Script(ScriptCategory.Ability, "pure_power")]
+public class PurePower : Script
+{
+ ///
+ public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
+ ImmutableStatisticSet targetStats, Statistic stat, ref uint value)
+ {
+ if (stat == Statistic.Attack)
+ {
+ value = value.MultiplyOrMax(2);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QueenlyMajesty.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QueenlyMajesty.cs
new file mode 100644
index 0000000..2acbdfa
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QueenlyMajesty.cs
@@ -0,0 +1,22 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Queenly Majesty is an ability that prevents priority moves from being used against the Pokémon.
+///
+/// Bulbapedia - Queenly Majesty
+///
+[Script(ScriptCategory.Ability, "queenly_majesty")]
+public class QueenlyMajesty : Script
+{
+ ///
+ public override void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail)
+ {
+ if (move.Targets.Count != 1)
+ return;
+
+ if (move.MoveChoice.Priority > 0)
+ {
+ fail = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QuickFeet.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QuickFeet.cs
new file mode 100644
index 0000000..fd836ee
--- /dev/null
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/QuickFeet.cs
@@ -0,0 +1,20 @@
+namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
+
+///
+/// Quick Feet is an ability that boosts Speed when the Pokémon has a status condition.
+///
+/// Bulbapedia - Quick Feet
+///
+[Script(ScriptCategory.Ability, "quick_feet")]
+public class QuickFeet : Script
+{
+ ///
+ public override void ChangeSpeed(ITurnChoice choice, ref uint speed)
+ {
+ if (choice.User.StatusScript.IsEmpty)
+ return;
+ if (choice.User.StatusScript.Script?.Name == "paralyzed")
+ speed = speed.MultiplyOrMax(2);
+ speed = speed.MultiplyOrMax(1.5f);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/DesolateLands.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/DesolateLands.cs
index 995d536..6afc004 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/DesolateLands.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/DesolateLands.cs
@@ -33,4 +33,10 @@ public class DesolateLands : HarshSunlight
if (move.UseMove.MoveType.Name == "water")
fail = true;
}
+
+ ///
+ public override void OnEndTurn(IBattle battle)
+ {
+ // We don't want to call base.OnEndTurn here, as we want to prevent the weather from ending
+ }
}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/HarshSunlight.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/HarshSunlight.cs
index db0d8c7..e32b7d2 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/HarshSunlight.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/HarshSunlight.cs
@@ -6,8 +6,29 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
/// Bulbapedia - Harsh Sunlight
///
[Script(ScriptCategory.Weather, "harsh_sunlight")]
-public class HarshSunlight : Script
+public class HarshSunlight : Script, ILimitedTurnsScript
{
+ private int? _duration;
+
+ ///
+ public int TurnsRemaining => _duration ?? 0;
+
+ ///
+ public void SetTurns(int turns)
+ {
+ _duration = turns;
+ }
+
+ ///
+ public override void OnEndTurn(IBattle battle)
+ {
+ _duration--;
+ if (_duration <= 0)
+ {
+ battle.SetWeather(null, 0);
+ }
+ }
+
///
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/PrimordialSea.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/PrimordialSea.cs
index 7d42bbe..a47224f 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/PrimordialSea.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/PrimordialSea.cs
@@ -1,7 +1,7 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "primordial_sea")]
-public class PrimordialSea : Script
+public class PrimordialSea : Rain
{
private HashSet _placers = new();
@@ -26,4 +26,16 @@ public class PrimordialSea : Script
return;
preventWeatherChange = true;
}
+
+ public override void FailMove(IExecutingMove move, ref bool fail)
+ {
+ if (move.UseMove.MoveType.Name == "fire")
+ fail = true;
+ }
+
+ ///
+ public override void OnEndTurn(IBattle battle)
+ {
+ // We don't want to call base.OnEndTurn here, as we want to prevent the weather from ending
+ }
}
\ No newline at end of file
diff --git a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Rain.cs b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Rain.cs
index 5851366..c228075 100644
--- a/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Rain.cs
+++ b/Plugins/PkmnLib.Plugin.Gen7/Scripts/Weather/Rain.cs
@@ -1,7 +1,53 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "rain")]
-public class Rain : Script
+public class Rain : Script, ILimitedTurnsScript
{
- // TODO: Implement Rain
+ private int? _duration;
+
+ ///
+ public int TurnsRemaining => _duration ?? 0;
+
+ ///
+ public void SetTurns(int turns)
+ {
+ _duration = turns;
+ }
+
+ ///
+ public override void OnEndTurn(IBattle battle)
+ {
+ _duration--;
+ if (_duration <= 0)
+ {
+ battle.SetWeather(null, 0);
+ }
+ }
+
+ ///
+ public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
+ {
+ var hitType = move.GetHitData(target, hit).Type;
+ if (hitType?.Name == "water")
+ {
+ // Increase Water-type move power by 50% in rain
+ basePower = (ushort)(basePower * 1.5);
+ }
+ else if (hitType?.Name == "fire")
+ {
+ // Decrease Fire-type move power by 50% in rain
+ basePower = (ushort)(basePower * 0.5);
+ }
+ }
+
+ ///
+ public override void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
+ ref int modifiedAccuracy)
+ {
+ modifiedAccuracy = executingMove.UseMove.Name.ToString() switch
+ {
+ "thunder" or "hurricane" or "bleakwind_storm" or "windbolt_storm" or "sandsear_storm" => 1000,
+ _ => modifiedAccuracy,
+ };
+ }
}
\ No newline at end of file