More abilities, implemented support for form inheritance
All checks were successful
Build / Build (push) Successful in 49s

This commit is contained in:
2025-06-13 12:24:03 +02:00
parent 6d71de375e
commit 8363b955af
16 changed files with 504 additions and 11 deletions

View File

@@ -369,17 +369,34 @@
"misty_surge": {
"effect": "misty_surge"
},
"mold_breaker": {},
"moody": {},
"motor_drive": {},
"moxie": {},
"multiscale": {},
"multitype": {
"canBeChanged": false
"mold_breaker": {
"effect": "mold_breaker"
},
"moody": {
"effect": "moody"
},
"motor_drive": {
"effect": "motor_drive"
},
"moxie": {
"effect": "moxie"
},
"multiscale": {
"effect": "multiscale"
},
"multitype": {
"canBeChanged": false,
"effect": "multitype"
},
"mummy": {
"effect": "mummy"
},
"natural_cure": {
"effect": "natural_cure"
},
"no_guard": {
"effect": "no_guard"
},
"mummy": {},
"natural_cure": {},
"no_guard": {},
"normalize": {},
"oblivious": {},
"overcoat": {},

View File

@@ -4450,6 +4450,108 @@
],
"formeChange": []
}
},
"arceus_fighting": {
"inheritFrom": "default",
"types": [
"fighting"
]
},
"arceus_flying": {
"inheritFrom": "default",
"types": [
"flying"
]
},
"arceus_bug": {
"inheritFrom": "default",
"types": [
"bug"
]
},
"arceus_dark": {
"inheritFrom": "default",
"types": [
"dark"
]
},
"arceus_dragon": {
"inheritFrom": "default",
"types": [
"dragon"
]
},
"arceus_electric": {
"inheritFrom": "default",
"types": [
"electric"
]
},
"arceus_fairy": {
"inheritFrom": "default",
"types": [
"fairy"
]
},
"arceus_fire": {
"inheritFrom": "default",
"types": [
"fire"
]
},
"arceus_ghost": {
"inheritFrom": "default",
"types": [
"ghost"
]
},
"arceus_grass": {
"inheritFrom": "default",
"types": [
"grass"
]
},
"arceus_ground": {
"inheritFrom": "default",
"types": [
"ground"
]
},
"arceus_ice": {
"inheritFrom": "default",
"types": [
"ice"
]
},
"arceus_poison": {
"inheritFrom": "default",
"types": [
"poison"
]
},
"arceus_psychic": {
"inheritFrom": "default",
"types": [
"psychic"
]
},
"arceus_rock": {
"inheritFrom": "default",
"types": [
"rock"
]
},
"arceus_steel": {
"inheritFrom": "default",
"types": [
"steel"
]
},
"arceus_water": {
"inheritFrom": "default",
"types": [
"water"
]
}
},
"evolutions": []

View File

@@ -0,0 +1,17 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Mold Breaker is an ability that allows moves to ignore the target's abilities.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Mold_Breaker_(Ability)">Bulbapedia - Mold Breaker</see>
/// </summary>
[Script(ScriptCategory.Ability, "mold_breaker")]
public class MoldBreaker : Script
{
/// <inheritdoc />
public override void OnBeforeAnyHookInvoked(ref List<ScriptCategory>? suppressedCategories)
{
suppressedCategories ??= [];
suppressedCategories.Add(ScriptCategory.Ability);
}
}

View File

@@ -0,0 +1,55 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Moody is an ability that raises one stat and lowers another at the end of each turn.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Moody_(Ability)">Bulbapedia - Moody</see>
/// </summary>
[Script(ScriptCategory.Ability, "moody")]
public class Moody : Script
{
private IPokemon? _pokemon;
/// <inheritdoc />
public override void OnAddedToParent(IScriptSource source)
{
if (source is not IPokemon pokemon)
throw new InvalidOperationException("Moody script must be attached to a Pokemon.");
_pokemon = pokemon;
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
if (_pokemon == null)
return;
var stats = _pokemon.StatBoost;
Statistic? raiseStat = null;
var possibleStatsToRaise = stats.Where(x => x is
{ value: < 6, statistic: not Statistic.Accuracy and not Statistic.Evasion and not Statistic.Hp })
.Select(x => x.statistic).ToList();
if (possibleStatsToRaise.Count > 0)
{
raiseStat = possibleStatsToRaise[battle.Random.GetInt(possibleStatsToRaise.Count)];
}
Statistic? lowerStat = null;
var possibleStatsToLower = stats.Where(x => x is
{
value: > -6,
statistic: not Statistic.Accuracy and not Statistic.Evasion and not Statistic.Hp,
} && x.statistic != raiseStat).Select(x => x.statistic).ToList();
if (possibleStatsToLower.Count > 0)
{
lowerStat = possibleStatsToLower[battle.Random.GetInt(possibleStatsToLower.Count)];
}
if (raiseStat != null)
_pokemon.ChangeStatBoost(raiseStat.Value, 1, true, false);
if (lowerStat != null)
_pokemon.ChangeStatBoost(lowerStat.Value, -1, true, false);
}
}

View File

@@ -0,0 +1,20 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Motor Drive is an ability that grants immunity to Electric-type moves and raises Speed when hit by one.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Motor_Drive_(Ability)">Bulbapedia - Motor Drive</see>
/// </summary>
[Script(ScriptCategory.Ability, "motor_drive")]
public class MotorDrive : Script
{
/// <inheritdoc />
public override void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.UseMove.MoveType.Name != "electric")
return;
invulnerable = true;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
target.ChangeStatBoost(Statistic.Speed, 1, true, false);
}
}

View File

@@ -0,0 +1,16 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Moxie is an ability that raises the user's Attack stat after knocking out a Pokémon.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Moxie_(Ability)">Bulbapedia - Moxie</see>
/// </summary>
[Script(ScriptCategory.Ability, "moxie")]
public class Moxie : Script
{
/// <inheritdoc />
public override void OnOpponentFaints(IExecutingMove move, IPokemon target, byte hit)
{
move.User.ChangeStatBoost(Statistic.Attack, 1, true, false);
}
}

View File

@@ -0,0 +1,19 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Multiscale is an ability that reduces damage taken when at full HP.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Multiscale_(Ability)">Bulbapedia - Multiscale</see>
/// </summary>
[Script(ScriptCategory.Ability, "multiscale")]
public class Multiscale : 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);
}
}
}

View File

@@ -0,0 +1,79 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Multitype is an ability that changes the Pokémon's type based on its held Plate or Z-Crystal.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Multitype_(Ability)">Bulbapedia - Multitype</see>
/// </summary>
[Script(ScriptCategory.Ability, "multitype")]
public class Multitype : Script
{
/// <inheritdoc />
public override void OnAfterHeldItemChange(IPokemon pokemon, IItem? previous, IItem? item)
{
if (pokemon.Species.Name != "arceus")
return;
if (item is null && pokemon.Form.Name != "default")
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}
else if (item is not null && item.Name.ToString().EndsWith("_plate", StringComparison.OrdinalIgnoreCase))
{
var platePrefix = item.Name.ToString().Replace("_plate", string.Empty, StringComparison.OrdinalIgnoreCase);
switch (platePrefix)
{
case "fist" when pokemon.Species.TryGetForm("arceus_fighting", out var fightingForm):
pokemon.ChangeForm(fightingForm);
break;
case "flame" when pokemon.Species.TryGetForm("arceus_fire", out var fireForm):
pokemon.ChangeForm(fireForm);
break;
case "shock" when pokemon.Species.TryGetForm("arceus_electric", out var electricForm):
pokemon.ChangeForm(electricForm);
break;
case "draco" when pokemon.Species.TryGetForm("arceus_dragon", out var dragonForm):
pokemon.ChangeForm(dragonForm);
break;
case "dread" when pokemon.Species.TryGetForm("arceus_dark", out var darkForm):
pokemon.ChangeForm(darkForm);
break;
case "earth" when pokemon.Species.TryGetForm("arceus_ground", out var groundForm):
pokemon.ChangeForm(groundForm);
break;
case "icicle" when pokemon.Species.TryGetForm("arceus_ice", out var iceForm):
pokemon.ChangeForm(iceForm);
break;
case "insect" when pokemon.Species.TryGetForm("arceus_bug", out var bugForm):
pokemon.ChangeForm(bugForm);
break;
case "iron" when pokemon.Species.TryGetForm("arceus_steel", out var steelForm):
pokemon.ChangeForm(steelForm);
break;
case "meadow" when pokemon.Species.TryGetForm("arceus_grass", out var grassForm):
pokemon.ChangeForm(grassForm);
break;
case "mind" when pokemon.Species.TryGetForm("arceus_psychic", out var psychicForm):
pokemon.ChangeForm(psychicForm);
break;
case "pixie" when pokemon.Species.TryGetForm("arceus_fairy", out var fairyForm):
pokemon.ChangeForm(fairyForm);
break;
case "sky" when pokemon.Species.TryGetForm("arceus_flying", out var flyingForm):
pokemon.ChangeForm(flyingForm);
break;
case "splash" when pokemon.Species.TryGetForm("arceus_water", out var waterForm):
pokemon.ChangeForm(waterForm);
break;
case "spooky" when pokemon.Species.TryGetForm("arceus_ghost", out var ghostForm):
pokemon.ChangeForm(ghostForm);
break;
case "stone" when pokemon.Species.TryGetForm("arceus_rock", out var rockForm):
pokemon.ChangeForm(rockForm);
break;
case "toxic" when pokemon.Species.TryGetForm("arceus_poison", out var poisonForm):
pokemon.ChangeForm(poisonForm);
break;
}
}
}
}

View File

@@ -0,0 +1,21 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Mummy is an ability that changes the attacker's ability to Mummy if it makes contact.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Mummy_(Ability)">Bulbapedia - Mummy</see>
/// </summary>
[Script(ScriptCategory.Ability, "mummy")]
public class Mummy : Script
{
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (!move.GetHitData(target, hit).IsContact || move.User.ActiveAbility?.Name == "mummy" ||
!move.Battle.Library.StaticLibrary.Abilities.TryGet("mummy", out var mummyAbility))
return;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
move.User.ChangeAbility(mummyAbility);
}
}

View File

@@ -0,0 +1,20 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// Natural Cure is an ability that heals status conditions when switching out.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Natural_Cure_(Ability)">Bulbapedia - Natural Cure</see>
/// </summary>
[Script(ScriptCategory.Ability, "natural_cure")]
public class NaturalCure : Script
{
/// <inheritdoc />
public override void OnSwitchOut(IPokemon oldPokemon, byte position)
{
if (!oldPokemon.StatusScript.IsEmpty)
{
oldPokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(oldPokemon));
oldPokemon.ClearStatus();
}
}
}

View File

@@ -0,0 +1,24 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
/// <summary>
/// No Guard is an ability that ensures all moves used by and against the Pokémon hit without fail.
///
/// <see href="https://bulbapedia.bulbagarden.net/wiki/No_Guard_(Ability)">Bulbapedia - No Guard</see>
/// </summary>
[Script(ScriptCategory.Ability, "no_guard")]
public class NoGuard : Script
{
/// <inheritdoc />
public override void ChangeIncomingAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
modifiedAccuracy = 2000;
}
/// <inheritdoc />
public override void ChangeAccuracy(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref int modifiedAccuracy)
{
modifiedAccuracy = 2000;
}
}