Even more abilities
All checks were successful
Build / Build (push) Successful in 51s

This commit is contained in:
Deukhoofd 2025-06-14 13:21:23 +02:00
parent 4b07f36176
commit 5961bb746e
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
31 changed files with 787 additions and 157 deletions

View File

@ -255,8 +255,11 @@ public static class MoveTurnExecutor
if (secondaryEffect != null)
{
var preventSecondary = false;
target.RunScriptHook(x =>
executingMove.RunScriptHook(x =>
x.PreventSecondaryEffect(executingMove, target, hitIndex, ref preventSecondary));
target.RunScriptHook(x =>
x.PreventIncomingSecondaryEffect(executingMove, target, hitIndex,
ref preventSecondary));
if (!preventSecondary)
{

View File

@ -450,12 +450,21 @@ public abstract class Script : IDeepCloneable
{
}
/// <summary>
/// This function allows a script to prevent a secondary effect of a move from being applied.
/// This means the move will still hit and do damage, but not trigger its secondary effect. Note that this
/// function is not called for status moves.
/// </summary>
public virtual void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
{
}
/// <summary>
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
/// secondary effect. This means the move will still hit and do damage, but not trigger its
/// secondary effect. Note that this function is not called for status moves.
/// </summary>
public virtual void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
public virtual void PreventIncomingSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
{
}

View File

@ -502,31 +502,71 @@
"canBeChanged": false,
"effect": "rks_system"
},
"rock_head": {},
"rough_skin": {},
"run_away": {},
"sand_force": {},
"sand_rush": {},
"sand_stream": {},
"sand_veil": {},
"sap_sipper": {},
"rock_head": {
"effect": "rock_head"
},
"rough_skin": {
"effect": "rough_skin"
},
"run_away": {
"effect": "run_away"
},
"sand_force": {
"effect": "sand_force"
},
"sand_rush": {
"effect": "sand_rush"
},
"sand_stream": {
"effect": "sand_stream"
},
"sand_veil": {
"effect": "sand_veil"
},
"sap_sipper": {
"effect": "sap_sipper"
},
"schooling": {
"effect": "schooling",
"canBeChanged": false
},
"scrappy": {},
"serene_grace": {},
"shadow_shield": {},
"shadow_tag": {},
"shed_skin": {},
"sheer_force": {},
"shell_armor": {},
"shield_dust": {},
"scrappy": {
"effect": "scrappy"
},
"serene_grace": {
"effect": "serene_grace"
},
"shadow_shield": {
"effect": "shadow_shield"
},
"shadow_tag": {
"effect": "shadow_tag"
},
"shed_skin": {
"effect": "shed_skin"
},
"sheer_force": {
"effect": "sheer_force"
},
"shell_armor": {
"effect": "shell_armor"
},
"shield_dust": {
"effect": "shield_dust"
},
"shields_down": {
"effect": "shields_down",
"canBeChanged": false
},
"simple": {},
"skill_link": {},
"slow_start": {},
"simple": {
"effect": "simple"
},
"skill_link": {
"effect": "skill_link"
},
"slow_start": {
"effect": "slow_start"
},
"slush_rush": {},
"sniper": {},
"snow_cloak": {},

View File

@ -81395,7 +81395,7 @@
"eggCycles": 25,
"flags": [],
"formes": {
"blue": {
"default": {
"abilities": [
"shields_down"
],
@ -81526,136 +81526,7 @@
}
},
"blue-meteor": {
"abilities": [
"shields_down"
],
"hiddenAbilities": [],
"baseStats": {
"attack": 60,
"defense": 100,
"hp": 60,
"specialAttack": 60,
"specialDefense": 100,
"speed": 60
},
"evReward": {
"defense": 1,
"specialDefense": 1
},
"types": [
"rock",
"flying"
],
"height": 0.3,
"weight": 40,
"baseExp": 154,
"moves": {
"levelMoves": [
{
"name": "tackle",
"level": 1
},
{
"name": "defense_curl",
"level": 3
},
{
"name": "rollout",
"level": 8
},
{
"name": "confuse_ray",
"level": 10
},
{
"name": "swift",
"level": 15
},
{
"name": "ancient_power",
"level": 17
},
{
"name": "self_destruct",
"level": 22
},
{
"name": "stealth_rock",
"level": 24
},
{
"name": "take_down",
"level": 29
},
{
"name": "autotomize",
"level": 31
},
{
"name": "cosmic_power",
"level": 36
},
{
"name": "power_gem",
"level": 38
},
{
"name": "double_edge",
"level": 43
},
{
"name": "shell_smash",
"level": 45
},
{
"name": "explosion",
"level": 50
}
],
"eggMoves": [],
"tutorMoves": [],
"machine": [
"hyper_beam",
"solar_beam",
"earthquake",
"toxic",
"psychic",
"double_team",
"light_screen",
"reflect",
"explosion",
"rest",
"rock_slide",
"substitute",
"protect",
"sandstorm",
"swagger",
"attract",
"sleep_talk",
"return",
"frustration",
"safeguard",
"hidden_power",
"psych_up",
"facade",
"rock_tomb",
"calm_mind",
"gyro_ball",
"u_turn",
"rock_polish",
"giga_impact",
"stone_edge",
"charge_beam",
"round",
"acrobatics",
"bulldoze",
"confide",
"dazzling_gleam"
],
"formeChange": []
}
},
"default": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -81916,6 +81787,7 @@
}
},
"green-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -82176,6 +82048,7 @@
}
},
"indigo-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -82436,6 +82309,7 @@
}
},
"orange-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -82695,6 +82569,137 @@
"formeChange": []
}
},
"red-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
"hiddenAbilities": [],
"baseStats": {
"attack": 60,
"defense": 100,
"hp": 60,
"specialAttack": 60,
"specialDefense": 100,
"speed": 60
},
"evReward": {
"defense": 1,
"specialDefense": 1
},
"types": [
"rock",
"flying"
],
"height": 0.3,
"weight": 40,
"baseExp": 154,
"moves": {
"levelMoves": [
{
"name": "tackle",
"level": 1
},
{
"name": "defense_curl",
"level": 3
},
{
"name": "rollout",
"level": 8
},
{
"name": "confuse_ray",
"level": 10
},
{
"name": "swift",
"level": 15
},
{
"name": "ancient_power",
"level": 17
},
{
"name": "self_destruct",
"level": 22
},
{
"name": "stealth_rock",
"level": 24
},
{
"name": "take_down",
"level": 29
},
{
"name": "autotomize",
"level": 31
},
{
"name": "cosmic_power",
"level": 36
},
{
"name": "power_gem",
"level": 38
},
{
"name": "double_edge",
"level": 43
},
{
"name": "shell_smash",
"level": 45
},
{
"name": "explosion",
"level": 50
}
],
"eggMoves": [],
"tutorMoves": [],
"machine": [
"hyper_beam",
"solar_beam",
"earthquake",
"toxic",
"psychic",
"double_team",
"light_screen",
"reflect",
"explosion",
"rest",
"rock_slide",
"substitute",
"protect",
"sandstorm",
"swagger",
"attract",
"sleep_talk",
"return",
"frustration",
"safeguard",
"hidden_power",
"psych_up",
"facade",
"rock_tomb",
"calm_mind",
"gyro_ball",
"u_turn",
"rock_polish",
"giga_impact",
"stone_edge",
"charge_beam",
"round",
"acrobatics",
"bulldoze",
"confide",
"dazzling_gleam"
],
"formeChange": []
}
},
"violet": {
"abilities": [
"shields_down"
@ -82826,6 +82831,7 @@
}
},
"violet-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -83086,6 +83092,7 @@
}
},
"yellow-meteor": {
"isBattleOnly": true,
"abilities": [
"shields_down"
],
@ -141638,6 +141645,7 @@
}
},
"school": {
"isBattleOnly": true,
"abilities": [
"schooling"
],

View File

@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Rock Head is an ability that prevents the Pokémon from taking recoil damage from most moves.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Rock_Head_(Ability)">Bulbapedia - Rock Head</see>
/// </summary>
[Script(ScriptCategory.Ability, "rock_head")]
public class RockHead : Script
{
/// <inheritdoc />
public override void CustomTrigger(StringKey eventName, ICustomTriggerArgs args)
{
if (eventName != CustomTriggers.ModifyRecoil)
return;
if (args is CustomTriggers.ModifyRecoilArgs recoilArgs)
{
recoilArgs.Prevent = true;
}
}
}

View File

@ -0,0 +1,19 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Rough Skin is an ability that damages attackers using contact moves.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Rough_Skin_(Ability)">Bulbapedia - Rough Skin</see>
/// </summary>
[Script(ScriptCategory.Ability, "rough_skin")]
public class RoughSkin : Script
{
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.GetHitData(target, hit).IsContact)
{
move.User.Damage(move.User.MaxHealth / 8, DamageSource.Misc);
}
}
}

View File

@ -0,0 +1,12 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Run Away is an ability that guarantees escape from wild battles.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Run_Away_(Ability)">Bulbapedia - Run Away</see>
/// </summary>
[Script(ScriptCategory.Ability, "run_away")]
public class RunAway : Script
{
// No effect in battle
}

View File

@ -0,0 +1,26 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sand Force is an ability that boosts the power of Rock, Ground, and Steel-type moves in a sandstorm.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sand_Force_(Ability)">Bulbapedia - Sand Force</see>
/// </summary>
[Script(ScriptCategory.Ability, "sand_force")]
public class SandForce : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.Battle.WeatherName == ScriptUtils.ResolveName<Weather.Sandstorm>())
{
var type = move.GetHitData(target, hit).Type;
if (type != null &&
(type.Value.Name == "rock" || type.Value.Name == "ground" || type.Value.Name == "steel"))
{
basePower = basePower.MultiplyOrMax(1.3f);
}
}
}
// TODO: Prevent sandstorm damage.
}

View File

@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sand Rush is an ability that doubles the Pokémon's Speed during a sandstorm.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sand_Rush_(Ability)">Bulbapedia - Sand Rush</see>
/// </summary>
[Script(ScriptCategory.Ability, "sand_rush")]
public class SandRush : Script
{
/// <inheritdoc />
public override void ChangeSpeed(ITurnChoice choice, ref uint speed)
{
if (choice.User.BattleData?.Battle.WeatherName == ScriptUtils.ResolveName<Weather.Sandstorm>())
{
speed = speed.MultiplyOrMax(2);
}
}
// TODO: Prevent sandstorm damage.
}

View File

@ -0,0 +1,25 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sand Stream is an ability that creates a sandstorm when the Pokémon enters battle.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sand_Stream_(Ability)">Bulbapedia - Sand Stream</see>
/// </summary>
[Script(ScriptCategory.Ability, "sand_stream")]
public class SandStream : Script
{
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
var battleData = pokemon.BattleData;
if (battleData == null)
return;
if (battleData.Battle.WeatherName == ScriptUtils.ResolveName<Weather.Sandstorm>())
return;
EventBatchId batchId = new();
battleData.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
battleData.Battle.SetWeather(ScriptUtils.ResolveName<Weather.Sandstorm>(), 5, batchId);
}
}

View File

@ -0,0 +1,22 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sand Veil is an ability that raises the Pokémon's evasion during a sandstorm.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sand_Veil_(Ability)">Bulbapedia - Sand Veil</see>
/// </summary>
[Script(ScriptCategory.Ability, "sand_veil")]
public class SandVeil : Script
{
/// <inheritdoc />
public override void ChangeIncomingAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
if (executingMove.Battle.WeatherName != ScriptUtils.ResolveName<Weather.Sandstorm>())
return;
modifiedAccuracy = (int)(modifiedAccuracy * (3277f / 4096f));
}
// TODO: Prevent sandstorm damage.
}

View File

@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sap Sipper is an ability that grants immunity to Grass-type moves and raises Attack when hit by one.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sap_Sipper_(Ability)">Bulbapedia - Sap Sipper</see>
/// </summary>
[Script(ScriptCategory.Ability, "sap_sipper")]
public class SapSipper : Script
{
/// <inheritdoc />
public override void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.GetHitData(target, 0).Type?.Name == "grass")
{
invulnerable = true;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
target.ChangeStatBoost(Statistic.Attack, 1, true, false);
}
}
}

View File

@ -0,0 +1,45 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Schooling is an ability that changes Wishiwashi's form in battle.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Schooling_(Ability)">Bulbapedia - Schooling</see>
/// </summary>
[Script(ScriptCategory.Ability, "schooling")]
public class Schooling : Script
{
private IPokemon? _owningPokemon;
/// <inheritdoc />
public override void OnAddedToParent(IScriptSource source)
{
if (source is not IPokemon pokemon)
throw new ArgumentException("Schooling script must be added to a Pokemon.", nameof(source));
_owningPokemon = pokemon;
}
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position) => ChangeFormIfNeeded(pokemon);
/// <inheritdoc />
public override void OnEndTurn(IBattle battle) => ChangeFormIfNeeded(_owningPokemon);
private static void ChangeFormIfNeeded(IPokemon? pokemon)
{
if (pokemon is null)
return;
if (pokemon.Species.Name != "wishiwashi" || pokemon.BattleData?.Battle == null)
return;
// If Wishiwashi has less than 25% health, change to Solo form
if (pokemon.CurrentHealth < pokemon.MaxHealth / 4 && pokemon.Form.Name != "default")
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 4 && pokemon.Form.Name != "school" &&
pokemon.Species.TryGetForm("school", out var schoolForm))
{
pokemon.ChangeForm(schoolForm);
}
}
}

View File

@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Scrappy is an ability that allows the Pokémon to hit Ghost-type Pokémon with Normal- and Fighting-type moves.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Scrappy_(Ability)">Bulbapedia - Scrappy</see>
/// </summary>
[Script(ScriptCategory.Ability, "scrappy")]
public class Scrappy : Script
{
/// <inheritdoc />
public override void ChangeTypesForMove(IExecutingMove executingMove, IPokemon target, byte hitIndex,
IList<TypeIdentifier> types)
{
var hitType = executingMove.GetHitData(target, hitIndex).Type;
if (hitType?.Name != "normal" && hitType?.Name != "fighting")
return;
if (types.Any(x => x.Name == "ghost"))
types.RemoveAll(x => x.Name == "ghost");
}
}

View File

@ -0,0 +1,16 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Serene Grace is an ability that doubles the chance of additional effects occurring when attacking.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Serene_Grace_(Ability)">Bulbapedia - Serene Grace</see>
/// </summary>
[Script(ScriptCategory.Ability, "serene_grace")]
public class SereneGrace : Script
{
/// <inheritdoc />
public override void ChangeEffectChance(IExecutingMove move, IPokemon target, byte hit, ref float chance)
{
chance *= 2;
}
}

View File

@ -0,0 +1,28 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shadow Shield is an ability that reduces damage taken when at full HP.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shadow_Shield_(Ability)">Bulbapedia - Shadow Shield</see>
/// </summary>
[Script(ScriptCategory.Ability, "shadow_shield")]
public class ShadowShield : Script
{
/// <inheritdoc />
public override void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (target.CurrentHealth == target.BoostedStats.Hp)
{
damage = (uint)(damage * 0.5);
}
}
/// <inheritdoc />
public override void OnBeforeAnyHookInvoked(ref List<ScriptCategory>? suppressedCategories)
{
// Shadow Shield can not be suppressed by any other script, so we remove it from the list of suppressed categories
// if it was added.
if (suppressedCategories != null && suppressedCategories.Contains(ScriptCategory.Ability))
suppressedCategories.Remove(ScriptCategory.Ability);
}
}

View File

@ -0,0 +1,16 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shadow Tag is an ability that prevents opposing Pokémon from fleeing or switching out.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shadow_Tag_(Ability)">Bulbapedia - Shadow Tag</see>
/// </summary>
[Script(ScriptCategory.Ability, "shadow_tag")]
public class ShadowTag : Script
{
/// <inheritdoc />
public override void PreventOpponentRunAway(IFleeChoice choice, ref bool prevent) => prevent = true;
/// <inheritdoc />
public override void PreventOpponentSwitch(ISwitchChoice choice, ref bool prevent) => prevent = true;
}

View File

@ -0,0 +1,37 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shed Skin is an ability that gives the Pokémon a chance to heal from a status condition at the end of each turn.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shed_Skin_(Ability)">Bulbapedia - Shed Skin</see>
/// </summary>
[Script(ScriptCategory.Ability, "shed_skin")]
public class ShedSkin : Script
{
private IPokemon? _owningPokemon;
/// <inheritdoc />
public override void OnAddedToParent(IScriptSource source)
{
if (source is not IPokemon pokemon)
throw new ArgumentException("ShedSkin script must be added to a Pokemon.", nameof(source));
_owningPokemon = pokemon;
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
if (_owningPokemon is null || _owningPokemon.StatusScript.IsEmpty)
return;
if (battle.Random.GetInt(3) == 0)
{
EventBatchId batchId = new();
battle.EventHook.Invoke(new AbilityTriggerEvent(_owningPokemon)
{
BatchId = batchId,
});
_owningPokemon.ClearStatus(batchId);
}
}
}

View File

@ -0,0 +1,22 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Sheer Force is an ability that increases the power of moves with secondary effects, but removes those effects.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sheer_Force_(Ability)">Bulbapedia - Sheer Force</see>
/// </summary>
[Script(ScriptCategory.Ability, "sheer_force")]
public class SheerForce : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
basePower = basePower.MultiplyOrMax(5325f / 4096f);
}
/// <inheritdoc />
public override void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
{
prevent = true;
}
}

View File

@ -0,0 +1,16 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shell Armor is an ability that prevents the Pokémon from receiving critical hits.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shell_Armor_(Ability)">Bulbapedia - Shell Armor</see>
/// </summary>
[Script(ScriptCategory.Ability, "shell_armor")]
public class ShellArmor : Script
{
/// <inheritdoc />
public override void BlockIncomingCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block)
{
block = true;
}
}

View File

@ -0,0 +1,17 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shield Dust is an ability that blocks the additional effects of attacks taken.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shield_Dust_(Ability)">Bulbapedia - Shield Dust</see>
/// </summary>
[Script(ScriptCategory.Ability, "shield_dust")]
public class ShieldDust : Script
{
/// <inheritdoc />
public override void PreventIncomingSecondaryEffect(IExecutingMove move, IPokemon target, byte hit,
ref bool prevent)
{
prevent = true;
}
}

View File

@ -0,0 +1,57 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Shields Down is an ability that changes Minior's form depending on its HP.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Shields_Down_(Ability)">Bulbapedia - Shields Down</see>
/// </summary>
[Script(ScriptCategory.Ability, "shields_down")]
public class ShieldsDown : Script
{
private IPokemon? _owningPokemon;
/// <inheritdoc />
public override void OnAddedToParent(IScriptSource source)
{
if (source is not IPokemon pokemon)
throw new ArgumentException("ShieldsDown script must be added to a Pokemon.", nameof(source));
_owningPokemon = pokemon;
}
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position) => ChangeFormIfNeeded(pokemon);
/// <inheritdoc />
public override void OnEndTurn(IBattle battle) => ChangeFormIfNeeded(_owningPokemon);
private static void ChangeFormIfNeeded(IPokemon? pokemon)
{
if (pokemon is null)
return;
if (pokemon.Species.Name != "minior" || pokemon.BattleData?.Battle == null)
return;
if (pokemon.CurrentHealth < pokemon.MaxHealth / 2 && pokemon.Form.Name.ToString().EndsWith("-meteor"))
{
var coreForm = pokemon.Form.Name.ToString().Replace("-meteor", "");
if (coreForm == "blue")
coreForm = "default";
if (pokemon.Species.TryGetForm(coreForm, out var coreFormData))
{
pokemon.ChangeForm(coreFormData);
}
}
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 2 &&
pokemon.Form.Name.ToString().EndsWith("-meteor") == false)
{
var baseFormName = pokemon.Form.Name;
if (baseFormName == "default")
baseFormName = "blue";
var meteorFormName = baseFormName + "-meteor";
if (pokemon.Species.TryGetForm(meteorFormName, out var meteorFormData))
{
pokemon.ChangeForm(meteorFormData);
}
}
}
}

View File

@ -0,0 +1,16 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Simple is an ability that doubles the effect of stat changes.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Simple_(Ability)">Bulbapedia - Simple</see>
/// </summary>
[Script(ScriptCategory.Ability, "simple")]
public class Simple : Script
{
/// <inheritdoc />
public override void ChangeStatBoostChange(IPokemon target, Statistic stat, bool selfInflicted, ref sbyte amount)
{
amount = amount.MultiplyOrMax(2);
}
}

View File

@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Skill Link is an ability that makes multi-strike moves always hit the maximum number of times.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Skill_Link_(Ability)">Bulbapedia - Skill Link</see>
/// </summary>
[Script(ScriptCategory.Ability, "skill_link")]
public class SkillLink : Script
{
/// <inheritdoc />
public override void CustomTrigger(StringKey eventName, ICustomTriggerArgs args)
{
if (eventName != CustomTriggers.Modify2_5HitMove)
return;
if (args is CustomTriggers.Modify2_5HitMoveArgs triggerArgs)
{
triggerArgs.NumberOfHits = 5;
}
}
}

View File

@ -0,0 +1,27 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Slow Start is an ability that halves the user's Attack and Speed for five turns after entering battle.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Slow_Start_(Ability)">Bulbapedia - Slow Start</see>
/// </summary>
[Script(ScriptCategory.Ability, "slow_start")]
public class SlowStart : Script
{
private IPokemon? _pokemon;
/// <inheritdoc />
public override void OnSwitchIn(IPokemon pokemon, byte position)
{
_pokemon = pokemon;
pokemon.Volatile.Add(new SlowStartEffect());
}
/// <inheritdoc />
public override void OnRemove()
{
_pokemon?.Volatile.Remove<SlowStartEffect>();
}
}

View File

@ -116,4 +116,20 @@ public static class CustomTriggers
public uint Damage { get; set; } = Damage;
public bool Invert { get; set; } = false;
}
public static readonly StringKey ModifyRecoil = "modify_recoil";
public record ModifyRecoilArgs(IExecutingMove Move, IPokemon Target, byte Hit, uint Damage, uint Recoil)
: ICustomTriggerArgs
{
public uint Recoil { get; set; } = Recoil;
public bool Prevent { get; set; } = false;
}
public static readonly StringKey Modify2_5HitMove = "modify_2_5_hit_move";
public record Modify2_5HitMoveArgs(IMoveChoice moveChoice, byte NumberOfHits) : ICustomTriggerArgs
{
public byte NumberOfHits { get; set; } = NumberOfHits;
}
}

View File

@ -10,13 +10,19 @@ public class FlareBlitz : Script
if (battleData == null)
return;
var hitData = move.GetHitData(target, hit);
var recoilDamage = hitData.Damage * (1 / 3);
var triggerArgs = new CustomTriggers.ModifyRecoilArgs(move, target, hit, hitData.Damage, recoilDamage);
move.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifyRecoil, triggerArgs));
if (triggerArgs.Prevent)
return;
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
{
target.SetStatus("burned", false);
}
var hitData = move.GetHitData(target, hit);
var recoilDamage = hitData.Damage * (1 / 3);
move.User.Damage(recoilDamage, DamageSource.Misc);
}
}

View File

@ -19,6 +19,10 @@ public class MultiHitMove : Script
< 85 => 4,
_ => 5,
};
var triggerArgs = new CustomTriggers.Modify2_5HitMoveArgs(choice, (byte)newHits);
choice.RunScriptHook(x => x.CustomTrigger(CustomTriggers.Modify2_5HitMove, triggerArgs));
newHits = triggerArgs.NumberOfHits;
numberOfHits = (byte)newHits;
}
}

View File

@ -1,5 +1,3 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "recoil")]
@ -23,6 +21,12 @@ public class Recoil : Script
return;
var hitData = move.GetHitData(target, hit);
var recoilDamage = (uint)(hitData.Damage * _recoilPercentage);
var triggerArgs = new CustomTriggers.ModifyRecoilArgs(move, target, hit, hitData.Damage, recoilDamage);
move.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifyRecoil, triggerArgs));
if (triggerArgs.Prevent)
return;
move.User.Damage(recoilDamage, DamageSource.Misc);
}
}

View File

@ -0,0 +1,33 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "slow_start")]
public class SlowStartEffect : Script
{
private int _turnsRemaining = 5;
/// <inheritdoc />
public override void ChangeSpeed(ITurnChoice choice, ref uint speed)
{
speed /= 2;
}
/// <inheritdoc />
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
ImmutableStatisticSet<uint> targetStats, Statistic stat, ref uint value)
{
if (stat == Statistic.Attack)
value /= 2;
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
if (_turnsRemaining <= 0)
return;
_turnsRemaining--;
if (_turnsRemaining == 0)
{
RemoveSelf();
}
}
}

View File

@ -24,7 +24,8 @@ public class AromaVeilEffect : Script
}
/// <inheritdoc />
public override void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
public override void PreventIncomingSecondaryEffect(IExecutingMove move, IPokemon target, byte hit,
ref bool prevent)
{
if (move.UseMove.HasFlag("mental"))
prevent = true;