Implements more abilities
All checks were successful
Build / Build (push) Successful in 47s

This commit is contained in:
2025-06-09 12:10:25 +02:00
parent af0126e413
commit 00005aa4bf
50 changed files with 80425 additions and 20485 deletions

View File

@@ -77,7 +77,7 @@
"chlorophyll": {
"effect": "speed_modifier_in_weather",
"parameters": {
"weather": "sunny",
"weather": "harsh_sunlight",
"modifier": 2.0
}
},
@@ -131,26 +131,55 @@
"defiant": {
"effect": "defiant"
},
"delta_stream": {},
"desolate_land": {},
"delta_stream": {
"effect": "delta_stream"
},
"desolate_land": {
"effect": "desolate_land"
},
"disguise": {
"effect": "disguise",
"canBeChanged": false,
"flags": [
"cant_be_copied"
]
},
"download": {},
"drizzle": {},
"drought": {},
"dry_skin": {},
"early_bird": {},
"effect_spore": {},
"electric_surge": {},
"emergency_exit": {},
"fairy_aura": {},
"filter": {},
"flame_body": {},
"flare_boost": {},
"download": {
"effect": "download"
},
"drizzle": {
"effect": "drizzle"
},
"drought": {
"effect": "drought"
},
"dry_skin": {
"effect": "dry_skin"
},
"early_bird": {
"effect": "early_bird"
},
"effect_spore": {
"effect": "effect_spore"
},
"electric_surge": {
"effect": "electric_surge"
},
"emergency_exit": {
"effect": "emergency_exit"
},
"fairy_aura": {
"effect": "fairy_aura"
},
"filter": {
"effect": "filter"
},
"flame_body": {
"effect": "flame_body"
},
"flare_boost": {
"effect": "flare_boost"
},
"flash_fire": {},
"flower_gift": {
"flags": [

View File

@@ -4669,11 +4669,7 @@
"snatch"
],
"effect": {
"name": "change_multiple_user_stat_boosts",
"parameters": {
"attack": 1,
"specialAttack": 1
}
"name": "growth"
}
},
{
@@ -11208,7 +11204,7 @@
"effect": {
"name": "set_weather",
"parameters": {
"weather": "sunny"
"weather": "harsh_sunlight"
}
}
},

File diff suppressed because it is too large Load Diff

View File

@@ -3,4 +3,5 @@ global using PkmnLib.Dynamic.ScriptHandling.Registry;
global using PkmnLib.Dynamic.Events;
global using PkmnLib.Dynamic.Models;
global using PkmnLib.Dynamic.Models.Choices;
global using PkmnLib.Static;
global using PkmnLib.Static;
global using PkmnLib.Static.Utils;

View File

@@ -155,6 +155,8 @@ public class Gen7DamageCalculator(Gen7PluginConfiguration configuration) : IDama
executingMove.RunScriptHook(script =>
script.ChangeDamageModifier(executingMove, target, hitNumber, ref modifier));
target.RunScriptHook(script =>
script.ChangeIncomingMoveDamageModifier(executingMove, target, hitNumber, ref modifier));
return modifier;
}

View File

@@ -0,0 +1,27 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Delta Stream is an ability that creates strong winds when the Pokémon enters battle.
/// These winds weaken the power of super-effective Flying-type moves and prevent other weather conditions.
/// This ability is exclusive to Mega Rayquaza.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Delta_Stream_(Ability)">Bulbapedia - Delta Stream</see>
/// </summary>
[Script(ScriptCategory.Ability, "delta_stream")]
public class DeltaStreamAbility : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battle = pokemon.BattleData?.Battle;
if (battle == null)
return;
battle.SetWeather(ScriptUtils.ResolveName<Weather.StrongWinds>(), -1);
if (battle.WeatherName == ScriptUtils.ResolveName<Weather.StrongWinds>())
{
((Weather.StrongWinds)battle.WeatherScript.Script!).MarkAsPlaced(pokemon);
battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
}
}
}

View File

@@ -0,0 +1,27 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Desolate Land is an ability that creates extremely harsh sunlight when the Pokémon enters battle.
/// This sunlight is so intense that it prevents other weather conditions and makes Water-type moves fail.
/// This ability is exclusive to Primal Groudon.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Desolate_Land_(Ability)">Bulbapedia - Desolate Land</see>
/// </summary>
[Script(ScriptCategory.Ability, "desolate_land")]
public class DesolateLandAbility : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battle = pokemon.BattleData?.Battle;
if (battle == null)
return;
battle.SetWeather(ScriptUtils.ResolveName<Weather.DesolateLands>(), -1);
if (battle.WeatherName == ScriptUtils.ResolveName<Weather.DesolateLands>())
{
((Weather.DesolateLands)battle.WeatherScript.Script!).MarkAsPlaced(pokemon);
battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
}
}
}

View File

@@ -0,0 +1,50 @@
using PkmnLib.Static.Species;
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Disguise is an ability that allows the Pokémon to avoid damage from one attack.
/// After being hit, the disguise is broken and the Pokémon's appearance changes.
/// This ability is exclusive to Mimikyu.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Disguise_(Ability)">Bulbapedia - Disguise</see>
/// </summary>
[Script(ScriptCategory.Ability, "disguise")]
public class Disguise : Script
{
/// <inheritdoc />
public override void ChangeIncomingDamage(IPokemon pokemon, DamageSource source, ref uint damage)
{
if (pokemon.BattleData == null)
return;
if (source is not DamageSource.MoveDamage and not DamageSource.Confusion)
return;
if (pokemon.Form.Name == "busted" || pokemon.Form.Name == "totem-busted")
return;
IForm form;
if (pokemon.Form.Name == "default")
{
if (!pokemon.Species.TryGetForm("busted", out form!))
return;
}
else if (pokemon.Form.Name == "totem-disguised")
{
if (!pokemon.Species.TryGetForm("totem-busted", out form!))
return;
}
else
{
return;
}
EventBatchId batchId = new();
pokemon.BattleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
{
BatchId = batchId,
});
pokemon.ChangeForm(form, batchId);
damage = 0;
}
}

View File

@@ -0,0 +1,36 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Download is an ability that raises the Pokémon's Attack or Special Attack stat when it enters battle,
/// depending on which stat is lower on the opposing Pokémon.
/// This ability is commonly associated with Porygon and its evolutions.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Download_(Ability)">Bulbapedia - Download</see>
/// </summary>
[Script(ScriptCategory.Ability, "download")]
public class Download : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battleData = pokemon.BattleData;
if (battleData == null)
return;
var opponents = battleData.Battle.Sides.Where(x => x != battleData.BattleSide).SelectMany(x => x.Pokemon)
.WhereNotNull().ToArray();
if (opponents.Length == 0)
return;
var opponentAverageDefense = opponents.Average(x => x.BoostedStats.Defense);
var opponentAverageSpecialDefense = opponents.Average(x => x.BoostedStats.SpecialDefense);
EventBatchId batchId = new();
battleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
{
BatchId = batchId,
});
pokemon.ChangeStatBoost(
opponentAverageDefense < opponentAverageSpecialDefense ? Statistic.Attack : Statistic.SpecialAttack, 1,
true, batchId);
}
}

View File

@@ -0,0 +1,27 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Drizzle is an ability that creates rain when the Pokémon enters battle.
/// This rain boosts Water-type moves and weakens Fire-type moves.
/// This ability is commonly associated with Kyogre and Politoed.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Drizzle_(Ability)">Bulbapedia - Drizzle</see>
/// </summary>
[Script(ScriptCategory.Ability, "drizzle")]
public class Drizzle : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battleData = pokemon.BattleData;
if (battleData == null)
return;
EventBatchId batchId = new();
battleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
{
BatchId = batchId,
});
battleData.Battle.SetWeather(ScriptUtils.ResolveName<Weather.Rain>(), 5, batchId);
}
}

View File

@@ -0,0 +1,27 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Drought is an ability that creates harsh sunlight when the Pokémon enters battle.
/// This sunlight boosts Fire-type moves and weakens Water-type moves.
/// This ability is commonly associated with Groudon and Ninetales.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Drought_(Ability)">Bulbapedia - Drought</see>
/// </summary>
[Script(ScriptCategory.Ability, "drought")]
public class Drought : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battleData = pokemon.BattleData;
if (battleData == null)
return;
EventBatchId batchId = new();
battleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
{
BatchId = batchId,
});
battleData.Battle.SetWeather(ScriptUtils.ResolveName<Weather.HarshSunlight>(), 5, batchId);
}
}

View File

@@ -0,0 +1,58 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Dry Skin is an ability that makes the Pokémon take more damage from Fire-type moves,
/// heal from Water-type moves, heal in rain, and take damage in harsh sunlight.
/// This ability is commonly associated with Paras and Toxicroak.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Dry_Skin_(Ability)">Bulbapedia - Dry Skin</see>
/// </summary>
[Script(ScriptCategory.Ability, "dry_skin")]
public class DrySkin : Script
{
private IPokemon? _owningPokemon;
/// <inheritdoc />
public override void OnAddedToParent(IScriptSource source)
{
if (source is not IPokemon pokemon)
{
throw new ArgumentException("DrySkin script must be added to a Pokemon.", nameof(source));
}
_owningPokemon = pokemon;
}
/// <inheritdoc />
public override void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
var hitType = move.GetHitData(target, hit).Type;
if (hitType?.Name == "fire")
{
modifier *= 1.25f;
}
else if (hitType?.Name == "water")
{
modifier = 0;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
target.Heal(target.MaxHealth / 4);
}
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
if (_owningPokemon == null)
return;
var weather = battle.WeatherName;
if (weather == ScriptUtils.ResolveName<Weather.Rain>())
{
_owningPokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(_owningPokemon));
_owningPokemon.Heal(_owningPokemon.MaxHealth / 8);
}
else if (weather == ScriptUtils.ResolveName<Weather.HarshSunlight>())
{
_owningPokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(_owningPokemon));
_owningPokemon.Damage(_owningPokemon.MaxHealth / 8, DamageSource.Weather);
}
}
}

View File

@@ -0,0 +1,25 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Early Bird is an ability that allows the Pokémon to wake up from sleep twice as fast.
/// This means the number of turns the Pokémon stays asleep is halved, rounded down.
/// This ability is commonly associated with Kangaskhan and Dodrio.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Early_Bird_(Ability)">Bulbapedia - Early Bird</see>
/// </summary>
[Script(ScriptCategory.Ability, "early_bird")]
public class EarlyBird : Script
{
/// <inheritdoc />
public override void CustomTrigger(StringKey eventName, IDictionary<StringKey, object?>? parameters)
{
if (eventName != CustomTriggers.ModifySleepTurns)
return;
if (parameters == null)
return;
if (parameters.TryGetValue("turns", out var turnsObj) && turnsObj is int turns)
{
parameters["turns"] = turns / 2;
}
}
}

View File

@@ -0,0 +1,49 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Effect Spore is an ability that has a 30% chance of inflicting a status condition on the attacker
/// when hit by a contact move. The status condition can be poison (9%), paralysis (10%), or sleep (11%).
/// This ability is commonly associated with Paras and Shroomish.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Effect_Spore_(Ability)">Bulbapedia - Effect Spore</see>
/// </summary>
[Script(ScriptCategory.Ability, "effect_spore")]
public class EffectSpore : Script
{
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Types.Any(x => x.Name == "grass"))
return;
if (move.User.ActiveAbility?.Name == "effect_spore")
return;
if (move.User.HasHeldItem("safety_goggles"))
return;
if (!move.UseMove.HasFlag("contact"))
return;
var rng = move.Battle.Random;
var chance = rng.GetInt(0, 100);
EventBatchId batchId = new();
if (chance < 30)
{
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target)
{
BatchId = batchId,
});
}
switch (chance)
{
case < 9:
move.User.SetStatus(ScriptUtils.ResolveName<Status.Poisoned>(), batchId);
break;
case < 19:
move.User.SetStatus(ScriptUtils.ResolveName<Status.Paralyzed>(), batchId);
break;
case < 30:
move.User.SetStatus(ScriptUtils.ResolveName<Status.Sleep>(), batchId);
break;
}
}
}

View File

@@ -0,0 +1,29 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Electric Surge is an ability that creates Electric Terrain when the Pokémon enters battle.
/// This terrain prevents grounded Pokémon from falling asleep and boosts Electric-type moves.
/// This ability is exclusive to Tapu Koko.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Electric_Surge_(Ability)">Bulbapedia - Electric Surge</see>
/// </summary>
[Script(ScriptCategory.Ability, "electric_surge")]
public class ElectricSurge : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battleData = pokemon.BattleData;
if (battleData == null)
return;
EventBatchId batchId = new();
battleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon)
{
BatchId = batchId,
});
battleData.Battle.SetTerrain(ScriptUtils.ResolveName<Terrain.ElectricTerrain>(), batchId);
}
}

View File

@@ -0,0 +1,32 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Emergency Exit is an ability that makes the Pokémon switch out when its HP drops below half.
/// This ability is similar to Wimp Out and is exclusive to Golisopod.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Emergency_Exit_(Ability)">Bulbapedia - Emergency Exit</see>
/// </summary>
[Script(ScriptCategory.Ability, "emergency_exit")]
public class EmergencyExit : Script
{
/// <inheritdoc />
public override void OnDamage(IPokemon pokemon, DamageSource source, uint oldHealth, uint newHealth)
{
if (pokemon.BattleData is null)
return;
if (source is DamageSource.Confusion)
return;
var oldHealthFraction = (float)oldHealth / pokemon.MaxHealth;
var newHealthFraction = (float)newHealth / pokemon.MaxHealth;
if (!(oldHealthFraction >= 0.5f) || !(newHealthFraction < 0.5f))
return;
if (pokemon.BattleData.Battle.IsWildBattle)
{
pokemon.BattleData.Battle.ForceEndBattle();
return;
}
pokemon.BattleData.BattleSide.SwapPokemon(pokemon.BattleData.Position, null);
}
}

View File

@@ -0,0 +1,34 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Fairy Aura is an ability that increases the power of Fairy-type moves by 33% for all Pokémon on the field.
/// The effect can be modified by other abilities (such as Aura Break) via a custom script hook.
/// This ability is exclusive to Xerneas.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Fairy_Aura_(Ability)">Bulbapedia - Fairy Aura</see>
/// </summary>
[Script(ScriptCategory.Ability, "fairy_aura")]
public class FairyAura : Script
{
/// <inheritdoc />
public override void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (move.GetHitData(target, hit).Type?.Name == "fairy")
{
var auraModifier = 5448f / 4096f;
var parameters = new Dictionary<StringKey, object?>
{
["aura_type"] = "fairy",
["modifier"] = auraModifier,
};
move.Battle.Sides.SelectMany(side => side.Pokemon).WhereNotNull()
.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifyAuraEffect, parameters));
if (parameters.TryGetValue("modifier", out var modObj) && modObj is float modValue)
{
auraModifier = modValue;
}
modifier *= auraModifier;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
}
}
}

View File

@@ -0,0 +1,22 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Filter is an ability that reduces the damage taken from super-effective moves by 25%.
/// This ability is similar to Solid Rock, but is exclusive to certain Pokémon like Mr. Mime.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Filter_(Ability)">Bulbapedia - Filter</see>
/// </summary>
[Script(ScriptCategory.Ability, "filter")]
public class Filter : Script
{
/// <inheritdoc />
public override void ChangeIncomingMoveDamageModifier(IExecutingMove move, IPokemon target, byte hit,
ref float modifier)
{
if (move.GetHitData(target, hit).Effectiveness >= 2.0f)
{
modifier *= 0.75f;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
}
}
}

View File

@@ -0,0 +1,25 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Flame Body is an ability that has a 30% chance of burning the attacker when hit by a contact move.
/// This ability is similar to Effect Spore and Static, but inflicts burn instead of other status conditions.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Flame_Body_(Ability)">Bulbapedia - Flame Body</see>
/// </summary>
[Script(ScriptCategory.Ability, "flame_body")]
public class FlameBody : Script
{
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (!move.UseMove.HasFlag("contact"))
return;
var rng = move.Battle.Random;
if (rng.GetInt(0, 100) >= 30) // 30% chance
return;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
move.User.SetStatus(ScriptUtils.ResolveName<Status.Burned>());
}
}

View File

@@ -0,0 +1,23 @@
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Flare Boost is an ability that increases the power of special moves by 50% when the Pokémon is burned.
/// This ability is exclusive to Drifblim.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Flare_Boost_(Ability)">Bulbapedia - Flare Boost</see>
/// </summary>
[Script(ScriptCategory.Ability, "flare_boost")]
public class FlareBoost : Script
{
/// <inheritdoc />
public override void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (!move.User.HasStatus(ScriptUtils.ResolveName<Status.Burned>()))
return;
if (move.UseMove.Category == MoveCategory.Special)
modifier *= 1.5f;
}
}

View File

@@ -0,0 +1,29 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Flash Fire is an ability that makes the Pokémon immune to Fire-type moves.
/// When hit by a Fire-type move, the ability activates and increases the power of the Pokémon's Fire-type moves by 50%.
/// This ability is commonly associated with Ninetales and Arcanine.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Flash_Fire_(Ability)">Bulbapedia - Flash Fire</see>
/// </summary>
[Script(ScriptCategory.Ability, "flash_fire")]
public class FlashFire : Script
{
/// <inheritdoc />
public override void ChangeIncomingEffectiveness(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref float effectiveness)
{
if (executingMove.GetHitData(target, hitIndex).Type?.Name == "fire")
{
effectiveness = 0f;
if (target.Volatile.Contains<FlashFireEffect>())
return;
target.Volatile.Add(new FlashFireEffect());
executingMove.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
}
}
}

View File

@@ -1,5 +1,3 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts;
public static class CustomTriggers
@@ -21,4 +19,8 @@ public static class CustomTriggers
public static readonly StringKey Whirlpool = "whirlpool";
public static readonly StringKey ModifyAuraEffect = "modify_aura_effect";
public static readonly StringKey BypassChargeMove = "bypass_charge_move";
public static readonly StringKey ModifySleepTurns = "modify_sleep_turns";
}

View File

@@ -7,6 +7,14 @@ public class ChargeMove : Script
{
public override void PreventMove(IExecutingMove move, ref bool prevent)
{
var bypassCharge = false;
var parameters = new Dictionary<StringKey, object?>
{
{ "move", move },
{ "bypassCharge", bypassCharge },
};
move.RunScriptHook(script => script.CustomTrigger(CustomTriggers.BypassChargeMove, parameters));
var chargeMoveEffect = move.User.Volatile.Get<ChargeMoveEffect>();
if (chargeMoveEffect != null && chargeMoveEffect.MoveName == move.UseMove.Name)
return;

View File

@@ -0,0 +1,18 @@
using PkmnLib.Plugin.Gen7.Scripts.Weather;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "growth")]
public class Growth : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId batchId = new();
sbyte amount = 1;
if (move.Battle.WeatherName == ScriptUtils.ResolveName<HarshSunlight>())
amount = 2;
move.User.ChangeStatBoost(Statistic.Attack, amount, true, batchId);
move.User.ChangeStatBoost(Statistic.SpecialAttack, amount, true, batchId);
}
}

View File

@@ -15,7 +15,7 @@ public class Moonlight : Script
var fraction = 0.5f;
var weather = battleData.Battle.WeatherName;
if (weather == ScriptUtils.ResolveName<Sunny>())
if (weather == ScriptUtils.ResolveName<HarshSunlight>())
fraction = 2f / 3f;
else if (weather == ScriptUtils.ResolveName<Rain>() || weather == ScriptUtils.ResolveName<Hail>() ||
weather == ScriptUtils.ResolveName<Sandstorm>())

View File

@@ -8,7 +8,7 @@ public class Synthesis : Script
{
var healModifier = 0.5f;
var weatherName = target.BattleData?.Battle.WeatherName;
if (weatherName == ScriptUtils.ResolveName<Weather.Sunny>())
if (weatherName == ScriptUtils.ResolveName<Weather.HarshSunlight>())
healModifier = 2 / 3f;
else if (weatherName == ScriptUtils.ResolveName<Weather.Rain>() ||
weatherName == ScriptUtils.ResolveName<Weather.Hail>() ||

View File

@@ -23,7 +23,7 @@ public class WeatherBall : Script
if (weather is null)
return;
if (weather == ScriptUtils.ResolveName<Weather.Sunny>() &&
if (weather == ScriptUtils.ResolveName<Weather.HarshSunlight>() &&
typeLibrary.TryGetTypeIdentifier("fire", out var fireType))
typeIdentifier = fireType;
else if (weather == ScriptUtils.ResolveName<Weather.Rain>() &&

View File

@@ -0,0 +1,15 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "flash_fire_effect")]
public class FlashFireEffect : Script
{
/// <inheritdoc />
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
ImmutableStatisticSet<uint> targetStats, ref uint value)
{
if (move.GetHitData(target, hit).Type?.Name == "fire")
{
value = value.MultiplyOrMax(1.5f);
}
}
}

View File

@@ -22,6 +22,13 @@ public class Sleep : Script
{
// 1-3 turns of sleep
Turns = battleData.Battle.Random.GetInt(1, 4);
source.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifySleepTurns,
new Dictionary<StringKey, object?>
{
{ "pokemon", pokemon },
{ "turns", Turns },
}));
Turns = Math.Max(1, Turns);
}
}

View File

@@ -0,0 +1,36 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "desolate_lands")]
public class DesolateLands : HarshSunlight
{
private readonly HashSet<IPokemon> _placers = [];
public void MarkAsPlaced(IPokemon pokemon)
{
_placers.Add(pokemon);
}
/// <inheritdoc />
public override void OnSwitchOut(IPokemon oldPokemon, byte position)
{
_placers.Remove(oldPokemon);
if (_placers.Count == 0)
oldPokemon.BattleData?.Battle.SetWeather(null, 0);
}
/// <inheritdoc />
public override void PreventWeatherChange(StringKey? weatherName, ref bool preventWeatherChange)
{
if (weatherName == ScriptUtils.ResolveName<PrimordialSea>() ||
weatherName == ScriptUtils.ResolveName<StrongWinds>())
return;
preventWeatherChange = true;
}
/// <inheritdoc />
public override void FailMove(IExecutingMove move, ref bool fail)
{
if (move.UseMove.MoveType.Name == "water")
fail = true;
}
}

View File

@@ -1,5 +1,3 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "hail")]
@@ -7,6 +5,9 @@ public class Hail : Script, ILimitedTurnsScript
{
private int? _duration;
/// <inheritdoc />
public int TurnsRemaining => _duration ?? 0;
/// <inheritdoc />
public void SetTurns(int turns)
{

View File

@@ -0,0 +1,59 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
/// <summary>
/// HarshSunlight is a weather condition that intensifies the effects of sunlight.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Harsh_sunlight">Bulbapedia - Harsh Sunlight</see>
/// </summary>
[Script(ScriptCategory.Weather, "harsh_sunlight")]
public class HarshSunlight : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
var hitType = move.GetHitData(target, hit).Type;
if (hitType?.Name == "fire" || move.UseMove.Name == "hydro_steam")
{
// Increase Fire-type move power by 50% in harsh sunlight
basePower = (ushort)(basePower * 1.5);
}
else if (hitType?.Name == "water")
{
basePower = (ushort)(basePower * 0.5);
}
}
/// <inheritdoc />
public override void CustomTrigger(StringKey eventName, IDictionary<StringKey, object?>? parameters)
{
if (eventName == CustomTriggers.BypassChargeMove)
{
if (parameters == null || !parameters.TryGetValue("move", out var moveObj) ||
moveObj is not IExecutingMove move)
return;
if (move.UseMove.Name == "solar_beam" || move.UseMove.Name == "solar_blade")
{
parameters["bypassCharge"] = true;
}
}
}
/// <inheritdoc />
public override void PreventStatusChange(IPokemon pokemonImpl, StringKey status, ref bool preventStatus)
{
if (status == ScriptUtils.ResolveName<Status.Frozen>())
{
preventStatus = true;
}
}
/// <inheritdoc />
public override void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
if (executingMove.UseMove.Name == "thunder" || executingMove.UseMove.Name == "hurricane")
{
modifiedAccuracy = (int)(modifiedAccuracy * 0.5);
}
}
}

View File

@@ -0,0 +1,29 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "primordial_sea")]
public class PrimordialSea : Script
{
private HashSet<IPokemon> _placers = new();
public void MarkAsPlaced(IPokemon pokemon)
{
_placers.Add(pokemon);
}
/// <inheritdoc />
public override void OnSwitchOut(IPokemon oldPokemon, byte position)
{
_placers.Remove(oldPokemon);
if (_placers.Count == 0)
oldPokemon.BattleData?.Battle.SetWeather(null, 0);
}
/// <inheritdoc />
public override void PreventWeatherChange(StringKey? weatherName, ref bool preventWeatherChange)
{
if (weatherName == ScriptUtils.ResolveName<DesolateLands>() ||
weatherName == ScriptUtils.ResolveName<StrongWinds>())
return;
preventWeatherChange = true;
}
}

View File

@@ -0,0 +1,50 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
/// <summary>
/// StrongWinds is a weather condition that represents strong winds in battle.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Strong_winds">Bulbapedia - Strong Winds</see>
/// </summary>
[Script(ScriptCategory.Weather, "strong_winds")]
public class StrongWinds : Script
{
private HashSet<IPokemon> _placers = new();
public void MarkAsPlaced(IPokemon pokemon)
{
_placers.Add(pokemon);
}
/// <inheritdoc />
public override void OnSwitchOut(IPokemon oldPokemon, byte position)
{
_placers.Remove(oldPokemon);
if (_placers.Count == 0)
oldPokemon.BattleData?.Battle.SetWeather(null, 0);
}
/// <inheritdoc />
public override void PreventWeatherChange(StringKey? weatherName, ref bool preventWeatherChange)
{
if (weatherName == ScriptUtils.ResolveName<DesolateLands>() ||
weatherName == ScriptUtils.ResolveName<PrimordialSea>())
return;
preventWeatherChange = true;
}
/// <inheritdoc />
public override void ChangeTypesForMove(IExecutingMove executingMove, IPokemon target, byte hitIndex,
IList<TypeIdentifier> types)
{
var flyingType = types.FirstOrDefault(x => x.Name == "flying");
if (flyingType != null)
{
var typeLibrary = executingMove.Battle.Library.StaticLibrary.Types;
var hitData = executingMove.GetHitData(target, hitIndex);
if (hitData.Type != null && typeLibrary.GetSingleEffectiveness(hitData.Type.Value, flyingType) > 1)
{
types.Remove(flyingType);
}
}
}
}

View File

@@ -1,7 +0,0 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Weather;
[Script(ScriptCategory.Weather, "sunny")]
public class Sunny : Script
{
// TODO: Implement Sunny
}