Replace all raw string comparisons with StringKey, source generator that creates cache keys for all names for Gen7 plugin
All checks were successful
Build / Build (push) Successful in 2m21s

This commit is contained in:
2026-08-27 18:30:57 +02:00
parent 3a58f55bbf
commit 942be8eaeb
160 changed files with 1035 additions and 491 deletions

View File

@@ -27,7 +27,7 @@ public static class AIDamageFunctions
{
score += 10;
if ((option.Move.Move.HasFlag(MoveFlags.MultiHit) && target.CurrentHealth == target.MaxHealth &&
target.ActiveAbility?.Name == "sturdy") || target.HasHeldItem("focus_sash"))
target.ActiveAbility?.Name == AbilityNames.Sturdy) || target.HasHeldItem(ItemNames.FocusSash))
{
score += 8;
}

View File

@@ -17,7 +17,7 @@ public static class AIHelperFunctions
if (move.User.BattleData?.SideIndex != target.BattleData?.SideIndex)
desireMult = -1;
if (!ignoreContrary && !fixedChange && target.ActiveAbility?.Name == "contrary")
if (!ignoreContrary && !fixedChange && target.ActiveAbility?.Name == AbilityNames.Contrary)
{
if (desireMult > 0 && wholeEffect)
{
@@ -39,10 +39,10 @@ public static class AIHelperFunctions
if (expectedEndOfTurnDamage >= target.CurrentHealth)
return wholeEffect ? ExplicitAI.MoveUselessScore : score;
if (!move.User.HasMoveWithEffect("power_trip"))
if (!move.User.HasMoveWithEffect(MoveEffectNames.PowerTrip))
{
var foeIsAware = target.BattleData?.BattleSide.Pokemon.Any(x => x?.ActiveAbility?.Name == "unaware") !=
true;
var foeIsAware =
target.BattleData?.BattleSide.Pokemon.Any(x => x?.ActiveAbility?.Name == AbilityNames.Unaware) != true;
if (!foeIsAware)
{
return wholeEffect ? ExplicitAI.MoveUselessScore : score;
@@ -56,7 +56,7 @@ public static class AIHelperFunctions
{
continue;
}
if (!fixedChange && target.ActiveAbility?.Name == "simple")
if (!fixedChange && target.ActiveAbility?.Name == AbilityNames.Simple)
{
increment *= 2;
}
@@ -88,7 +88,7 @@ public static class AIHelperFunctions
var desireMult = -1;
if (move.User.BattleData?.SideIndex == target.BattleData?.SideIndex)
desireMult = 1;
if (!ignoreContrary && !fixedChange && target.ActiveAbility?.Name == "contrary")
if (!ignoreContrary && !fixedChange && target.ActiveAbility?.Name == AbilityNames.Contrary)
{
if (desireMult > 0 && wholeEffect)
{
@@ -109,7 +109,7 @@ public static class AIHelperFunctions
return wholeEffect ? ExplicitAI.MoveUselessScore : score;
var foeIsAware = false;
if (target.BattleData?.BattleSide.Pokemon.All(x => x?.ActiveAbility?.Name != "unaware") == true)
if (target.BattleData?.BattleSide.Pokemon.All(x => x?.ActiveAbility?.Name != AbilityNames.Unaware) == true)
{
foeIsAware = true;
}
@@ -125,7 +125,7 @@ public static class AIHelperFunctions
{
continue;
}
if (!fixedChange && target.ActiveAbility?.Name == "simple")
if (!fixedChange && target.ActiveAbility?.Name == AbilityNames.Simple)
{
decrement *= 2;
}
@@ -152,7 +152,7 @@ public static class AIHelperFunctions
{
if (!fixedChange && pokemon.StatBoost.GetStatistic(stat) == StatBoostStatisticSet.MaxStatBoost)
return false;
if (!pokemon.HasMoveWithEffect("power_trip", "baton_pass"))
if (!pokemon.HasMoveWithEffect(MoveEffectNames.PowerTrip, MoveEffectNames.BatonPass))
return true;
switch (stat)
@@ -160,7 +160,8 @@ public static class AIHelperFunctions
case Statistic.Attack:
{
if (!pokemon.Moves.WhereNotNull().Any(x => x.MoveData.Category == MoveCategory.Physical &&
x.MoveData.SecondaryEffect?.Name != "foul_play"))
x.MoveData.SecondaryEffect?.Name !=
MoveEffectNames.FoulPlay))
{
return false;
}
@@ -170,7 +171,8 @@ public static class AIHelperFunctions
{
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
return opponentSide.Pokemon.WhereNotNull().Any(x => x.Moves.WhereNotNull().Any(y =>
y.MoveData.Category == MoveCategory.Physical || y.MoveData.SecondaryEffect?.Name == "psyshock"));
y.MoveData.Category == MoveCategory.Physical ||
y.MoveData.SecondaryEffect?.Name == MoveEffectNames.Psyshock));
}
case Statistic.SpecialAttack:
{
@@ -184,11 +186,12 @@ public static class AIHelperFunctions
{
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
return opponentSide.Pokemon.WhereNotNull().Any(x => x.Moves.WhereNotNull().Any(y =>
y.MoveData.Category == MoveCategory.Special && y.MoveData.SecondaryEffect?.Name != "psyshock"));
y.MoveData.Category == MoveCategory.Special &&
y.MoveData.SecondaryEffect?.Name != MoveEffectNames.Psyshock));
}
case Statistic.Speed:
{
if (!pokemon.HasMoveWithEffect("electro_ball", "power_trip"))
if (!pokemon.HasMoveWithEffect(MoveEffectNames.ElectroBall, MoveEffectNames.PowerTrip))
{
var targetSpeed = pokemon.BoostedStats.Speed;
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
@@ -228,13 +231,15 @@ public static class AIHelperFunctions
case Statistic.Attack:
{
return pokemon.Moves.WhereNotNull().Any(x => x.MoveData.Category == MoveCategory.Physical &&
x.MoveData.SecondaryEffect?.Name != FoulPlayAbilityName);
x.MoveData.SecondaryEffect?.Name !=
MoveEffectNames.FoulPlay);
}
case Statistic.Defense:
{
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
return opponentSide.Pokemon.WhereNotNull().Any(x => x.Moves.WhereNotNull().Any(y =>
y.MoveData.Category == MoveCategory.Physical || y.MoveData.SecondaryEffect?.Name == "psyshock"));
y.MoveData.Category == MoveCategory.Physical ||
y.MoveData.SecondaryEffect?.Name == MoveEffectNames.Psyshock));
}
case Statistic.SpecialAttack:
{
@@ -244,11 +249,12 @@ public static class AIHelperFunctions
{
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
return opponentSide.Pokemon.WhereNotNull().Any(x => x.Moves.WhereNotNull().Any(y =>
y.MoveData.Category == MoveCategory.Special && y.MoveData.SecondaryEffect?.Name != "psyshock"));
y.MoveData.Category == MoveCategory.Special &&
y.MoveData.SecondaryEffect?.Name != MoveEffectNames.Psyshock));
}
case Statistic.Speed:
{
if (!pokemon.HasMoveWithEffect("electro_ball"))
if (!pokemon.HasMoveWithEffect(MoveEffectNames.ElectroBall))
{
var targetSpeed = pokemon.BoostedStats.Speed;
var opponentSide = pokemon.BattleData!.Battle.Sides.First(x => x != pokemon.BattleData.BattleSide);
@@ -266,8 +272,6 @@ public static class AIHelperFunctions
return true;
}
private static readonly StringKey FoulPlayAbilityName = "foul_play";
private static void GetTargetStatRaiseScoreOne(ref int score, IPokemon target, Statistic stat, sbyte increment,
AIMoveState move, float desireMult = 1)
{
@@ -311,7 +315,7 @@ public static class AIHelperFunctions
{
var hasPhysicalMoves = target.Moves.WhereNotNull().Any(x =>
x.MoveData.Category == MoveCategory.Physical &&
x.MoveData.SecondaryEffect?.Name != FoulPlayAbilityName);
x.MoveData.SecondaryEffect?.Name != MoveEffectNames.FoulPlay);
var inc = hasPhysicalMoves ? 8 : 12;
score += (int)(inc * incMult);
}
@@ -340,15 +344,15 @@ public static class AIHelperFunctions
else
score += (int)(8 * incMult);
}
if (target.HasMoveWithEffect("electro_ball", "power_trip"))
if (target.HasMoveWithEffect(MoveEffectNames.ElectroBall, MoveEffectNames.PowerTrip))
{
score += (int)(5 * incMult);
}
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect("gyro_ball")))
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect(MoveEffectNames.GyroBall)))
{
score -= (int)(5 * incMult);
}
if (target.ActiveAbility?.Name == "speed_boost")
if (target.ActiveAbility?.Name == AbilityNames.SpeedBoost)
{
score -= (int)(15 * (target.Opposes(move.User) ? 1 : desireMult));
}
@@ -393,11 +397,11 @@ public static class AIHelperFunctions
break;
}
}
if (target.HasMoveWithEffect("power_trip"))
if (target.HasMoveWithEffect(MoveEffectNames.PowerTrip))
{
score += (int)(5 * increment * desireMult);
}
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect("punishment")))
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect(MoveEffectNames.Punishment)))
{
score -= (int)(5 * increment * desireMult);
}
@@ -445,7 +449,7 @@ public static class AIHelperFunctions
{
var hasPhysicalMoves = target.Moves.WhereNotNull().Any(x =>
x.MoveData.Category == MoveCategory.Physical &&
x.MoveData.SecondaryEffect?.Name != FoulPlayAbilityName);
x.MoveData.SecondaryEffect?.Name != MoveEffectNames.FoulPlay);
var dec = hasPhysicalMoves ? 8 : 12;
score += (int)(dec * decMult);
}
@@ -475,11 +479,11 @@ public static class AIHelperFunctions
score += (int)(8 * decMult);
break;
}
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect("electro_ball")))
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect(MoveEffectNames.ElectroBall)))
{
score += (int)(5 * decMult);
}
if (target.ActiveAbility?.Name == "speed_boost")
if (target.ActiveAbility?.Name == AbilityNames.SpeedBoost)
{
score -= (int)(15 * (target.Opposes(move.User) ? 1 : desireMult));
}
@@ -502,11 +506,11 @@ public static class AIHelperFunctions
break;
}
}
if (target.HasMoveWithEffect("power_trip"))
if (target.HasMoveWithEffect(MoveEffectNames.PowerTrip))
{
score += (int)(5 * decrement * desireMult);
}
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect("punishment")))
if (opponentSide.Pokemon.WhereNotNull().Any(x => x.HasMoveWithEffect(MoveEffectNames.Punishment)))
{
score -= (int)(5 * decrement * desireMult);
}
@@ -545,13 +549,13 @@ public static class AIHelperFunctions
{
if (move.Move.SecondaryEffect is null)
return 0;
if (move.User.ActiveAbility?.Name == "sheer_force")
if (move.User.ActiveAbility?.Name == AbilityNames.SheerForce)
return -999;
if (target is not null && target.BattleData?.Position != move.User.BattleData?.Position &&
target.ActiveAbility?.Name == "shield_dust")
target.ActiveAbility?.Name == AbilityNames.ShieldDust)
return -999;
if ((move.Move.SecondaryEffect.Chance < 100 && move.User.ActiveAbility?.Name == "serene_grace") ||
if ((move.Move.SecondaryEffect.Chance < 100 && move.User.ActiveAbility?.Name == AbilityNames.SereneGrace) ||
move.User.BattleData?.BattleSide.VolatileScripts.Contains<RainbowEffect>() == true)
{
return 5;
@@ -574,38 +578,38 @@ public static class AIHelperFunctions
return true;
if (pokemon.ActiveAbility != null)
{
if (pokemon.ActiveAbility.Name == "guts" && status != ScriptUtils.ResolveName<Sleep>() &&
if (pokemon.ActiveAbility.Name == AbilityNames.Guts && status != ScriptUtils.ResolveName<Sleep>() &&
status != ScriptUtils.ResolveName<Frozen>() &&
IsStatRaiseWorthwhile(pokemon, Statistic.Attack, 1, true))
{
return true;
}
if (pokemon.ActiveAbility.Name == "marvel_scale" &&
if (pokemon.ActiveAbility.Name == AbilityNames.MarvelScale &&
IsStatRaiseWorthwhile(pokemon, Statistic.Defense, 1, true))
{
return true;
}
if (pokemon.ActiveAbility.Name == "quick_feet" && status != ScriptUtils.ResolveName<Sleep>() &&
if (pokemon.ActiveAbility.Name == AbilityNames.QuickFeet && status != ScriptUtils.ResolveName<Sleep>() &&
status != ScriptUtils.ResolveName<Frozen>() && IsStatRaiseWorthwhile(pokemon, Statistic.Speed, 1, true))
{
return true;
}
if (pokemon.ActiveAbility.Name == "flare_boost" && status == ScriptUtils.ResolveName<Burned>() &&
if (pokemon.ActiveAbility.Name == AbilityNames.FlareBoost && status == ScriptUtils.ResolveName<Burned>() &&
IsStatRaiseWorthwhile(pokemon, Statistic.SpecialAttack, 1, true))
{
return true;
}
if (pokemon.ActiveAbility.Name == "toxic_boost" &&
if (pokemon.ActiveAbility.Name == AbilityNames.ToxicBoost &&
(status == ScriptUtils.ResolveName<Poisoned>() || status == ScriptUtils.ResolveName<BadlyPoisoned>()) &&
IsStatRaiseWorthwhile(pokemon, Statistic.Attack, 1, true))
{
return true;
}
if (pokemon.ActiveAbility.Name == "poison_heal" && status == ScriptUtils.ResolveName<Poisoned>())
if (pokemon.ActiveAbility.Name == AbilityNames.PoisonHeal && status == ScriptUtils.ResolveName<Poisoned>())
{
return true;
}
if (pokemon.ActiveAbility.Name == "magic_guard")
if (pokemon.ActiveAbility.Name == AbilityNames.MagicGuard)
{
if (status != ScriptUtils.ResolveName<Poisoned>() &&
status != ScriptUtils.ResolveName<BadlyPoisoned>() && status != ScriptUtils.ResolveName<Burned>())

View File

@@ -26,8 +26,6 @@ public static class AISwitchFunctions
return effect.Turns <= 1;
}
private static readonly StringKey PoisonHealAbilityName = "poison_heal";
/// <summary>
/// Switch out if the Pokémon is expected to take significant end-of-turn damage.
/// </summary>
@@ -50,7 +48,7 @@ public static class AISwitchFunctions
return true;
var statusScript = pokemon.StatusScript.Script;
if (statusScript is BadlyPoisoned { Turns: > 0 } badlyPoisoned &&
pokemon.ActiveAbility?.Name != PoisonHealAbilityName)
pokemon.ActiveAbility?.Name != AbilityNames.PoisonHeal)
{
var poisonDamage = pokemon.MaxHealth / 8;
var nextToxicDamage = pokemon.MaxHealth * badlyPoisoned.GetPoisonMultiplier();
@@ -92,28 +90,18 @@ public static class AISwitchFunctions
return bigThreat;
}
private static readonly StringKey ImmunityAbilityName = "immunity";
private static readonly StringKey InsomniaAbilityName = "insomnia";
private static readonly StringKey LimberAbilityName = "limber";
private static readonly StringKey MagmaArmorAbilityName = "magma_armor";
private static readonly StringKey VitalSpiritAbilityName = "vital_spirit";
private static readonly StringKey WaterBubbleAbilityName = "water_bubble";
private static readonly StringKey WaterVeilAbilityName = "water_veil";
private static readonly StringKey NaturalCureAbilityName = "natural_cure";
private static readonly StringKey RegeneratorAbilityName = "regenerator";
private static readonly Dictionary<StringKey, List<StringKey>> StatusCureAbilities = new()
{
{
ImmunityAbilityName,
AbilityNames.Immunity,
[ScriptUtils.ResolveName<Poisoned>(), ScriptUtils.ResolveName<BadlyPoisoned>()]
},
{ InsomniaAbilityName, [ScriptUtils.ResolveName<Sleep>()] },
{ LimberAbilityName, [ScriptUtils.ResolveName<Paralyzed>()] },
{ MagmaArmorAbilityName, [ScriptUtils.ResolveName<Frozen>()] },
{ VitalSpiritAbilityName, [ScriptUtils.ResolveName<Sleep>()] },
{ WaterBubbleAbilityName, [ScriptUtils.ResolveName<Burned>()] },
{ WaterVeilAbilityName, [ScriptUtils.ResolveName<Burned>()] },
{ AbilityNames.Insomnia, [ScriptUtils.ResolveName<Sleep>()] },
{ AbilityNames.Limber, [ScriptUtils.ResolveName<Paralyzed>()] },
{ AbilityNames.MagmaArmor, [ScriptUtils.ResolveName<Frozen>()] },
{ AbilityNames.VitalSpirit, [ScriptUtils.ResolveName<Sleep>()] },
{ AbilityNames.WaterBubble, [ScriptUtils.ResolveName<Burned>()] },
{ AbilityNames.WaterVeil, [ScriptUtils.ResolveName<Burned>()] },
};
/// <summary>
@@ -138,7 +126,7 @@ public static class AISwitchFunctions
// Check abilities that cure specific status conditions
var canCureStatus = false;
if (abilityName == NaturalCureAbilityName)
if (abilityName == AbilityNames.NaturalCure)
{
canCureStatus = true;
}
@@ -161,7 +149,7 @@ public static class AISwitchFunctions
// Don't bother curing a poisoning if Toxic Spikes will just re-poison
if (pokemon.StatusScript.Script is Poisoned or BadlyPoisoned &&
!reserves.Any(p => p.Types.Any(t => t.Name == "poison")))
!reserves.Any(p => p.Types.Any(t => t.Name == TypeNames.Poison)))
{
if (pokemon.BattleData!.BattleSide.VolatileScripts.TryGet<ToxicSpikesEffect>(out _))
{
@@ -177,7 +165,7 @@ public static class AISwitchFunctions
if (ai.Random.GetInt(100) < 70)
return true;
}
else if (abilityName == RegeneratorAbilityName)
else if (abilityName == AbilityNames.Regenerator)
{
// Not worth healing if battler would lose more HP from switching back in later
if (entryHazardDamage >= pokemon.MaxHealth / 3)

View File

@@ -1,39 +0,0 @@
namespace PkmnLib.Plugin.Gen7.Common;
public static class MoveFlags
{
public static readonly StringKey Ballistics = "ballistics";
public static readonly StringKey Bite = "bite";
public static readonly StringKey CantRepeat = "cant_repeat";
public static readonly StringKey Charge = "charge";
public static readonly StringKey Contact = "contact";
public static readonly StringKey Dance = "dance";
public static readonly StringKey Defrost = "defrost";
public static readonly StringKey Distance = "distance";
public static readonly StringKey EffectiveAgainstFly = "effective_against_fly";
public static readonly StringKey EffectiveAgainstUnderground = "effective_against_underground";
public static readonly StringKey EffectiveAgainstUnderwater = "effective_against_underwater";
public static readonly StringKey Gravity = "gravity";
public static readonly StringKey Heal = "heal";
public static readonly StringKey HitFlying = "hit_flying";
public static readonly StringKey HitUnderground = "hit_underground";
public static readonly StringKey HitUnderwater = "hit_underwater";
public static readonly StringKey IgnoreSubstitute = "ignore_substitute";
public static readonly StringKey LimitMoveChoice = "limit_move_choice";
public static readonly StringKey Mental = "mental";
public static readonly StringKey Mirror = "mirror";
public static readonly StringKey MultiHit = "multi_hit";
public static readonly StringKey NoRedirection = "no_redirection";
public static readonly StringKey NonSkyBattle = "non_sky_battle";
public static readonly StringKey NotSketchable = "not_sketchable";
public static readonly StringKey Powder = "powder";
public static readonly StringKey Protect = "protect";
public static readonly StringKey Pulse = "pulse";
public static readonly StringKey Punch = "punch";
public static readonly StringKey Recoil = "recoil";
public static readonly StringKey Recharge = "recharge";
public static readonly StringKey Reflectable = "reflectable";
public static readonly StringKey Snatch = "snatch";
public static readonly StringKey Sound = "sound";
public static readonly StringKey UsableWhileAsleep = "usable_while_asleep";
}

View File

@@ -7,9 +7,12 @@
<ItemGroup>
<ProjectReference Include="..\..\PkmnLib.Dynamic\PkmnLib.Dynamic.csproj"/>
<ProjectReference Include="..\..\PkmnLib.Static\PkmnLib.Static.csproj"/>
<ProjectReference Include="..\PkmnLib.Plugin.Gen7.SourceGen\PkmnLib.Plugin.Gen7.SourceGen.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Data\*.*"/>
<AdditionalFiles Include="Data\*.*"/>
</ItemGroup>
</Project>

View File

@@ -9,8 +9,6 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
[Script(ScriptCategory.Ability, "aftermath")]
public class Aftermath : Script, IScriptOnIncomingHit, IScriptOnFaint
{
private static readonly StringKey DampAbilityName = new("damp");
private IExecutingMove? _lastAttack;
/// <inheritdoc />
@@ -35,7 +33,7 @@ public class Aftermath : Script, IScriptOnIncomingHit, IScriptOnFaint
// Aftermath does not trigger if a Pokémon with Damp is on the field
var battle = user.BattleData.Battle;
var hasDamp = battle.Sides.SelectMany(side => side.Pokemon).WhereNotNull()
.Any(p => p.ActiveAbility?.Name == DampAbilityName);
.Any(p => p.ActiveAbility?.Name == AbilityNames.Damp);
if (hasDamp)
return;

View File

@@ -30,10 +30,10 @@ public class Anticipation : Script, IScriptOnOpponentSwitchIn
// Either the move is super effective against the owner or
typeLibrary.GetEffectiveness(move.MoveData.MoveType, _owner.Types) > 1.0f ||
// the move is a OHKO move
move.MoveData.SecondaryEffect?.Name == "one_hit_ko" ||
move.MoveData.SecondaryEffect?.Name == MoveEffectNames.OneHitKo ||
// the move is a self-destruct move
move.MoveData.SecondaryEffect?.Name == "self_destruct" ||
move.MoveData.SecondaryEffect?.Name == "explosion");
move.MoveData.SecondaryEffect?.Name == MoveEffectNames.SelfDestruct ||
move.MoveData.SecondaryEffect?.Name == MoveEffectNames.Explosion);
if (relevantMoves)
{

View File

@@ -16,7 +16,7 @@ public class AuraBreak : Script, IScriptCustomTrigger
return;
var typeName = auraArgs.Move.UseMove.MoveType.Name;
if (typeName == "dark" || typeName == "fairy")
if (typeName == TypeNames.Dark || typeName == TypeNames.Fairy)
{
// Reverse the aura effect by reducing power by 25%
auraArgs.AuraEffect *= 0.75f;

View File

@@ -12,8 +12,8 @@ public class BattleBond : Script, IScriptChangeNumberOfHits, IScriptOnOpponentFa
/// <inheritdoc />
public void OnOpponentFaints(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Species.Name == "greninja" && move.User.Form.Name != "ash" &&
move.User.Species.TryGetForm("ash", out var ashForm))
if (move.User.Species.Name == SpeciesNames.Greninja && move.User.Form.Name != FormNames.Ash &&
move.User.Species.TryGetForm(FormNames.Ash, out var ashForm))
{
move.User.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
move.User.ChangeForm(ashForm);
@@ -23,14 +23,14 @@ public class BattleBond : Script, IScriptChangeNumberOfHits, IScriptOnOpponentFa
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.UseMove.Name == "water_shuriken" && move.User.Form.Name == "ash")
if (move.UseMove.Name == MoveNames.WaterShuriken && move.User.Form.Name == FormNames.Ash)
basePower = 20;
}
/// <inheritdoc />
public void ChangeNumberOfHits(IMoveChoice choice, ref byte numberOfHits)
{
if (choice.ChosenMove.MoveData.Name == "water_shuriken" && choice.User.Form.Name == "ash")
if (choice.ChosenMove.MoveData.Name == MoveNames.WaterShuriken && choice.User.Form.Name == FormNames.Ash)
{
numberOfHits = 3;
}

View File

@@ -13,7 +13,7 @@ public class Damp : Script, IScriptFailIncomingMove
/// <inheritdoc />
public void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail)
{
if (move.UseMove.Name == "self_destruct" || move.UseMove.Name == "explosion")
if (move.UseMove.Name == MoveNames.SelfDestruct || move.UseMove.Name == MoveNames.Explosion)
{
fail = true;
}

View File

@@ -12,7 +12,7 @@ public class DarkAura : Script, IScriptChangeDamageModifier
/// <inheritdoc />
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (move.GetHitData(target, hit).Type?.Name == "dark")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Dark)
{
var auraModifier = 5448f / 4096f;
var args = new CustomTriggers.ModifyAuraEffectArgs(move, target, hit, auraModifier);

View File

@@ -19,17 +19,17 @@ public class Disguise : Script, IScriptChangeIncomingDamage
return;
if (source is not DamageSource.MoveDamage and not DamageSource.Confusion)
return;
if (pokemon.Form.Name == "busted" || pokemon.Form.Name == "totem-busted")
if (pokemon.Form.Name == FormNames.Busted || pokemon.Form.Name == FormNames.TotemBusted)
return;
IForm form;
if (pokemon.Form.Name == "default")
if (pokemon.Form.Name == FormNames.Default)
{
if (!pokemon.Species.TryGetForm("busted", out form!))
if (!pokemon.Species.TryGetForm(FormNames.Busted, out form!))
return;
}
else if (pokemon.Form.Name == "totem-disguised")
else if (pokemon.Form.Name == FormNames.TotemDisguised)
{
if (!pokemon.Species.TryGetForm("totem-busted", out form!))
if (!pokemon.Species.TryGetForm(FormNames.TotemBusted, out form!))
return;
}
else

View File

@@ -26,11 +26,11 @@ public class DrySkin : Script, IScriptChangeDamageModifier, IScriptOnEndTurn, IA
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
var hitType = move.GetHitData(target, hit).Type;
if (hitType?.Name == "fire")
if (hitType?.Name == TypeNames.Fire)
{
modifier *= 1.25f;
}
else if (hitType?.Name == "water")
else if (hitType?.Name == TypeNames.Water)
{
modifier = 0;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -13,11 +13,11 @@ public class EffectSpore : Script, IScriptOnIncomingHit
/// <inheritdoc />
public void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Types.Any(x => x.Name == "grass"))
if (move.User.Types.Any(x => x.Name == TypeNames.Grass))
return;
if (move.User.ActiveAbility?.Name == "effect_spore")
if (move.User.ActiveAbility?.Name == AbilityNames.EffectSpore)
return;
if (move.User.HasHeldItem("safety_goggles"))
if (move.User.HasHeldItem(ItemNames.SafetyGoggles))
return;
if (!move.GetHitData(target, hit).IsContact)
return;

View File

@@ -13,7 +13,7 @@ public class FairyAura : Script, IScriptChangeDamageModifier
/// <inheritdoc />
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (move.GetHitData(target, hit).Type?.Name == "fairy")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Fairy)
{
var auraModifier = 5448f / 4096f;
var args = new CustomTriggers.ModifyAuraEffectArgs(move, target, hit, auraModifier);

View File

@@ -16,7 +16,7 @@ public class FlashFire : Script, IScriptChangeIncomingEffectiveness
public void ChangeIncomingEffectiveness(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref float effectiveness)
{
if (executingMove.GetHitData(target, hitIndex).Type?.Name != "fire")
if (executingMove.GetHitData(target, hitIndex).Type?.Name != TypeNames.Fire)
return;
effectiveness = 0f;

View File

@@ -28,10 +28,10 @@ public class FlowerGift : Script, IScriptOnWeatherChange
return;
if (weatherName != ScriptUtils.ResolveName<Weather.HarshSunlight>())
return;
if (_pokemon.Species.Name != "cherrim")
if (_pokemon.Species.Name != SpeciesNames.Cherrim)
return;
EventBatchId batchId = new();
if (_pokemon.Species.TryGetForm("sunshine", out var form) && _pokemon.Form != form)
if (_pokemon.Species.TryGetForm(FormNames.Sunshine, out var form) && _pokemon.Form != form)
{
_pokemon.ChangeForm(form, batchId);
}
@@ -47,7 +47,7 @@ public class FlowerGift : Script, IScriptOnWeatherChange
script.OnRemoved(_pokemon);
}
if (_pokemon.Species.Name != "cherrim")
if (_pokemon.Species.Name != SpeciesNames.Cherrim)
return;
EventBatchId batchId = new();

View File

@@ -12,7 +12,7 @@ public class Fluffy : Script, IScriptChangeDamageModifier
/// <inheritdoc />
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (move.GetHitData(target, hit).Type?.Name == "fire")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Fire)
{
modifier *= 2f;
}

View File

@@ -45,21 +45,21 @@ public class Forecast : Script, IScriptOnSwitchIn, IScriptOnWeatherChange
private static void ChangeForm(IPokemon pokemon, StringKey? weather)
{
if (pokemon.Species.Name != "castform")
if (pokemon.Species.Name != SpeciesNames.Castform)
return;
if (weather == ScriptUtils.ResolveName<Weather.HarshSunlight>() &&
pokemon.Species.TryGetForm("sunny", out var sunnyForm) && pokemon.Form != sunnyForm)
pokemon.Species.TryGetForm(FormNames.Sunny, out var sunnyForm) && pokemon.Form != sunnyForm)
{
pokemon.ChangeForm(sunnyForm);
}
else if (weather == ScriptUtils.ResolveName<Weather.Rain>() &&
pokemon.Species.TryGetForm("rainy", out var rainyForm) && pokemon.Form != rainyForm)
pokemon.Species.TryGetForm(FormNames.Rainy, out var rainyForm) && pokemon.Form != rainyForm)
{
pokemon.ChangeForm(rainyForm);
}
else if (weather == ScriptUtils.ResolveName<Weather.Hail>() &&
pokemon.Species.TryGetForm("snowy", out var snowyForm) && pokemon.Form != snowyForm)
pokemon.Species.TryGetForm(FormNames.Snowy, out var snowyForm) && pokemon.Form != snowyForm)
{
pokemon.ChangeForm(snowyForm);
}

View File

@@ -37,28 +37,64 @@ public class Forewarn : Script, IScriptOnSwitchIn
});
}
private static readonly Dictionary<StringKey, byte> FixedBasePowers = new()
{
// 150 BP: Specific moves
[MoveNames.BlastBurn] = 150,
[MoveNames.Eruption] = 150,
[MoveNames.WaterSpout] = 150,
[MoveNames.Fissure] = 150,
[MoveNames.Guillotine] = 150,
[MoveNames.HornDrill] = 150,
[MoveNames.SheerCold] = 150,
// 120 BP: Counter, Metal Burst, Mirror Coat
[MoveNames.Counter] = 120,
[MoveNames.MetalBurst] = 120,
[MoveNames.MirrorCoat] = 120,
// 80 BP: List of variable power and fixed-damage moves
[MoveNames.CrushGrip] = 80,
[MoveNames.DragonRage] = 80,
[MoveNames.ElectroBall] = 80,
[MoveNames.Endeavor] = 80,
[MoveNames.FinalGambit] = 80,
[MoveNames.Flail] = 80,
[MoveNames.Fling] = 80,
[MoveNames.Frustration] = 80,
[MoveNames.GrassKnot] = 80,
[MoveNames.GuardianOfAlola] = 80,
[MoveNames.GyroBall] = 80,
[MoveNames.HeatCrash] = 80,
[MoveNames.HeavySlam] = 80,
[MoveNames.HiddenPower] = 80,
[MoveNames.LowKick] = 80,
[MoveNames.NaturalGift] = 80,
[MoveNames.NaturesMadness] = 80,
[MoveNames.NightShade] = 80,
[MoveNames.Present] = 80,
[MoveNames.Psywave] = 80,
[MoveNames.Punishment] = 80,
[MoveNames.Return] = 80,
[MoveNames.Reversal] = 80,
[MoveNames.SeismicToss] = 80,
[MoveNames.SonicBoom] = 80,
[MoveNames.SpitUp] = 80,
[MoveNames.SuperFang] = 80,
[MoveNames.TrumpCard] = 80,
[MoveNames.WringOut] = 80,
// 20 BP: Stored Power, Power Trip
[MoveNames.StoredPower] = 20,
[MoveNames.PowerTrip] = 20,
};
private static byte GetBasePower(IMoveData moveData)
{
// OHKO moves (handled by secondary effect)
if (moveData.SecondaryEffect?.Name == "one_hit_ko")
if (moveData.SecondaryEffect?.Name == MoveEffectNames.OneHitKo)
return 150;
return moveData.Name.ToString() switch
{
// 150 BP: Specific moves
"blast_burn" or "eruption" or "water_spout" or "fissure" or "guillotine" or "horn_drill"
or "sheer_cold" => 150,
// 120 BP: Counter, Metal Burst, Mirror Coat
"counter" or "metal_burst" or "mirror_coat" => 120,
// 80 BP: List of variable power and fixed-damage moves
"crush_grip" or "dragon_rage" or "electro_ball" or "endeavor" or "final_gambit" or "flail" or "fling"
or "frustration" or "grass_knot" or "guardian_of_alola" or "gyro_ball" or "heat_crash" or "heavy_slam"
or "hidden_power" or "low_kick" or "natural_gift" or "natures_madness" or "night_shade" or "present"
or "psywave" or "punishment" or "return" or "reversal" or "seismic_toss" or "sonic_boom" or "spit_up"
or "super_fang" or "trump_card" or "wring_out" => 80,
// 20 BP: Stored Power, Power Trip
"stored_power" or "power_trip" => 20,
_ => moveData.BasePower == 0 ? (byte)1 : moveData.BasePower,
};
if (FixedBasePowers.TryGetValue(moveData.Name, out var fixedBasePower))
return fixedBasePower;
return moveData.BasePower == 0 ? (byte)1 : moveData.BasePower;
}
}

View File

@@ -12,8 +12,8 @@ public class Galvanize : Script, IScriptChangeMoveType, IScriptChangeDamageModif
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
{
if (typeIdentifier?.Name == "normal" &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("electric", out var electricType))
if (typeIdentifier?.Name == TypeNames.Normal &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Electric, out var electricType))
{
typeIdentifier = electricType;
}
@@ -22,7 +22,7 @@ public class Galvanize : Script, IScriptChangeMoveType, IScriptChangeDamageModif
/// <inheritdoc />
public void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
if (move.GetHitData(target, hit).Type?.Name == "electric")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Electric)
modifier *= 1.2f;
}
}

View File

@@ -11,7 +11,7 @@ public class Heatproof : Script, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.GetHitData(target, hit).Type?.Name == "fire")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Fire)
{
basePower = (ushort)(basePower / 2);
}

View File

@@ -11,7 +11,7 @@ public class Justified : Script, IScriptOnIncomingHit
/// <inheritdoc />
public void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.GetHitData(target, hit).Type?.Name != "dark")
if (move.GetHitData(target, hit).Type?.Name != TypeNames.Dark)
return;
EventBatchId batchId = new();

View File

@@ -11,7 +11,7 @@ public class LightningRod : Script, IScriptChangeIncomingTargets, IScriptChangeE
/// <inheritdoc />
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
{
if (moveChoice.ChosenMove.MoveData.MoveType.Name == "electric" && targets.Count == 1)
if (moveChoice.ChosenMove.MoveData.MoveType.Name == TypeNames.Electric && targets.Count == 1)
{
targets = [moveChoice.User];
}
@@ -20,7 +20,7 @@ public class LightningRod : Script, IScriptChangeIncomingTargets, IScriptChangeE
/// <inheritdoc />
public void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
{
if (move.GetHitData(target, hit).Type?.Name != "electric")
if (move.GetHitData(target, hit).Type?.Name != TypeNames.Electric)
return;
effectiveness = 0f;

View File

@@ -12,7 +12,7 @@ public class LiquidVoice : Script, IScriptChangeMoveType
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
{
if (move.UseMove.HasFlag(MoveFlags.Sound) &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("water", out var waterType))
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Water, out var waterType))
{
typeIdentifier = waterType;
}

View File

@@ -11,14 +11,14 @@ public class MagnetPull : Script, IScriptPreventOpponentRunAway, IScriptPreventO
/// <inheritdoc />
public void PreventOpponentRunAway(IFleeChoice choice, ref bool prevent)
{
if (choice.User.Types.Any(x => x.Name == "steel"))
if (choice.User.Types.Any(x => x.Name == TypeNames.Steel))
prevent = true;
}
/// <inheritdoc />
public void PreventOpponentSwitch(ISwitchChoice choice, ref bool prevent)
{
if (choice.User.Types.Any(x => x.Name == "steel"))
if (choice.User.Types.Any(x => x.Name == TypeNames.Steel))
prevent = true;
}
}

View File

@@ -15,7 +15,8 @@ public class Minus : Script, IScriptChangeOffensiveStatValue
var battleData = move.User.BattleData;
if (battleData is null)
return;
if (battleData.BattleSide.Pokemon.WhereNotNull().Any(x => x.IsUsable && x.ActiveAbility?.Name == "plus"))
if (battleData.BattleSide.Pokemon.WhereNotNull()
.Any(x => x.IsUsable && x.ActiveAbility?.Name == AbilityNames.Plus))
{
value = value.MultiplyOrMax(1.5f);
}

View File

@@ -11,7 +11,7 @@ public class MotorDrive : Script, IScriptIsInvulnerableToMove
/// <inheritdoc />
public void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.UseMove.MoveType.Name != "electric")
if (move.UseMove.MoveType.Name != TypeNames.Electric)
return;
invulnerable = true;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -8,72 +8,40 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
[Script(ScriptCategory.Ability, "multitype")]
public class Multitype : Script, IScriptOnAfterHeldItemChange
{
private static readonly Dictionary<StringKey, StringKey> PlateForms = new()
{
[ItemNames.FistPlate] = FormNames.ArceusFighting,
[ItemNames.FlamePlate] = FormNames.ArceusFire,
[ItemNames.ZapPlate] = FormNames.ArceusElectric,
[ItemNames.DracoPlate] = FormNames.ArceusDragon,
[ItemNames.DreadPlate] = FormNames.ArceusDark,
[ItemNames.EarthPlate] = FormNames.ArceusGround,
[ItemNames.IciclePlate] = FormNames.ArceusIce,
[ItemNames.InsectPlate] = FormNames.ArceusBug,
[ItemNames.IronPlate] = FormNames.ArceusSteel,
[ItemNames.MeadowPlate] = FormNames.ArceusGrass,
[ItemNames.MindPlate] = FormNames.ArceusPsychic,
[ItemNames.PixiePlate] = FormNames.ArceusFairy,
[ItemNames.SkyPlate] = FormNames.ArceusFlying,
[ItemNames.SplashPlate] = FormNames.ArceusWater,
[ItemNames.SpookyPlate] = FormNames.ArceusGhost,
[ItemNames.StonePlate] = FormNames.ArceusRock,
[ItemNames.ToxicPlate] = FormNames.ArceusPoison,
};
/// <inheritdoc />
public void OnAfterHeldItemChange(IPokemon pokemon, IItem? previous, IItem? item)
{
if (pokemon.Species.Name != "arceus")
if (pokemon.Species.Name != SpeciesNames.Arceus)
return;
if (item is null && pokemon.Form.Name != "default")
if (item is null && pokemon.Form.Name != FormNames.Default)
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}
else if (item is not null && item.Name.ToString().EndsWith("_plate", StringComparison.OrdinalIgnoreCase))
else if (item is not null && PlateForms.TryGetValue(item.Name, out var formName) &&
pokemon.Species.TryGetForm(formName, out var form))
{
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;
}
pokemon.ChangeForm(form);
}
}
}

View File

@@ -11,8 +11,8 @@ public class Mummy : Script, IScriptOnIncomingHit
/// <inheritdoc />
public 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))
if (!move.GetHitData(target, hit).IsContact || move.User.ActiveAbility?.Name == AbilityNames.Mummy ||
!move.Battle.Library.StaticLibrary.Abilities.TryGet(AbilityNames.Mummy, out var mummyAbility))
return;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -11,14 +11,14 @@ public class Normalize : Script, IScriptChangeMoveType, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
{
if (move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("normal", out var normalType))
if (move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Normal, out var normalType))
typeIdentifier = normalType;
}
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.GetHitData(target, hit).Type?.Name == "normal")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Normal)
basePower = (ushort)(basePower * 1.2f); // Boost Normal-type moves by 30%
}
}

View File

@@ -11,15 +11,15 @@ public class Pixilate : Script, IScriptChangeMoveType, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
{
if (typeIdentifier?.Name == "normal" &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("fairy", out var fairyType))
if (typeIdentifier?.Name == TypeNames.Normal &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Fairy, out var fairyType))
typeIdentifier = fairyType;
}
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.GetHitData(target, hit).Type?.Name == "fairy")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Fairy)
basePower = (ushort)(basePower * 1.2f); // Boost Normal-type moves by 30%
}
}

View File

@@ -15,7 +15,8 @@ public class Plus : Script, IScriptChangeOffensiveStatValue
var battleData = move.User.BattleData;
if (battleData is null)
return;
if (battleData.BattleSide.Pokemon.WhereNotNull().Any(x => x.IsUsable && x.ActiveAbility?.Name == "minus"))
if (battleData.BattleSide.Pokemon.WhereNotNull()
.Any(x => x.IsUsable && x.ActiveAbility?.Name == AbilityNames.Minus))
{
value = value.MultiplyOrMax(1.5f);
}

View File

@@ -23,13 +23,13 @@ public class PowerConstruct : Script, IScriptOnEndTurn
{
if (_pokemon?.BattleData?.Battle == null)
return;
if (_pokemon.Species.Name != "zygarde")
if (_pokemon.Species.Name != SpeciesNames.Zygarde)
return;
if (_pokemon.CurrentHealth > _pokemon.BoostedStats.Hp / 2)
return;
if (_pokemon.Form.Name != "10" || _pokemon.Form.Name != "50")
if (_pokemon.Form.Name != FormNames._10 || _pokemon.Form.Name != FormNames._50)
return;
if (!_pokemon.Species.TryGetForm("complete", out var completeForm))
if (!_pokemon.Species.TryGetForm(FormNames.Complete, out var completeForm))
return;
_pokemon.ChangeForm(completeForm);

View File

@@ -13,7 +13,7 @@ public class QuickFeet : Script, IScriptChangeSpeed
{
if (choice.User.StatusScript.IsEmpty)
return;
if (choice.User.StatusScript.Script?.Name == "paralyzed")
if (choice.User.StatusScript.Script?.Name == ScriptUtils.ResolveName<Status.Paralyzed>())
speed = speed.MultiplyOrMax(2);
speed = speed.MultiplyOrMax(1.5f);
}

View File

@@ -11,9 +11,9 @@ public class RksSystem : Script, IScriptOnAfterHeldItemChange
/// <inheritdoc />
public void OnAfterHeldItemChange(IPokemon pokemon, IItem? previous, IItem? item)
{
if (pokemon.Species.Name != "silvally")
if (pokemon.Species.Name != SpeciesNames.Silvally)
return;
if (item is null && pokemon.Form.Name != "default")
if (item is null && pokemon.Form.Name != FormNames.Default)
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}

View File

@@ -14,7 +14,7 @@ public class Rattled : Script, IScriptOnIncomingHit
var type = move.GetHitData(target, hit).Type;
if (type is null)
return;
if (type.Value.Name != "bug" && type.Value.Name != "ghost" && type.Value.Name != "dark")
if (type.Value.Name != TypeNames.Bug && type.Value.Name != TypeNames.Ghost && type.Value.Name != TypeNames.Dark)
return;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
target.ChangeStatBoost(Statistic.Speed, 1, true, false);

View File

@@ -11,15 +11,15 @@ public class Refrigerate : Script, IScriptChangeMoveType, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier)
{
if (typeIdentifier?.Name == "normal" &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("ice", out var iceType))
if (typeIdentifier?.Name == TypeNames.Normal &&
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Ice, out var iceType))
typeIdentifier = iceType;
}
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.GetHitData(target, hit).Type?.Name == "ice")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Ice)
basePower = (ushort)(basePower * 1.2f); // Boost Normal-type moves by 30%
}
}

View File

@@ -14,8 +14,8 @@ public class SandForce : Script, IScriptChangeBasePower, IScriptCustomTrigger
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"))
if (type != null && (type.Value.Name == TypeNames.Rock || type.Value.Name == TypeNames.Ground ||
type.Value.Name == TypeNames.Steel))
{
basePower = basePower.MultiplyOrMax(1.3f);
}

View File

@@ -11,7 +11,7 @@ public class SapSipper : Script, IScriptIsInvulnerableToMove
/// <inheritdoc />
public void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.GetHitData(target, 0).Type?.Name == "grass")
if (move.GetHitData(target, 0).Type?.Name == TypeNames.Grass)
{
invulnerable = true;
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -29,15 +29,15 @@ public class Schooling : Script, IScriptOnEndTurn, IScriptOnSwitchIn
if (pokemon is null)
return;
if (pokemon.Species.Name != "wishiwashi" || pokemon.BattleData?.Battle == null)
if (pokemon.Species.Name != SpeciesNames.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")
if (pokemon.CurrentHealth < pokemon.MaxHealth / 4 && pokemon.Form.Name != FormNames.Default)
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 4 && pokemon.Form.Name != "school" &&
pokemon.Species.TryGetForm("school", out var schoolForm))
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 4 && pokemon.Form.Name != FormNames.School &&
pokemon.Species.TryGetForm(FormNames.School, out var schoolForm))
{
pokemon.ChangeForm(schoolForm);
}

View File

@@ -13,9 +13,9 @@ public class Scrappy : Script, IScriptChangeTypesForMove
IList<TypeIdentifier> types)
{
var hitType = executingMove.GetHitData(target, hitIndex).Type;
if (hitType?.Name != "normal" && hitType?.Name != "fighting")
if (hitType?.Name != TypeNames.Normal && hitType?.Name != TypeNames.Fighting)
return;
if (types.Any(x => x.Name == "ghost"))
types.RemoveAll(x => x.Name == "ghost");
if (types.Any(x => x.Name == TypeNames.Ghost))
types.RemoveAll(x => x.Name == TypeNames.Ghost);
}
}

View File

@@ -19,7 +19,7 @@ public class ShieldsDown : Script, IScriptOnEndTurn, IScriptOnSwitchIn
if (pokemon is null)
return;
if (pokemon.Species.Name != "minior" || pokemon.BattleData?.Battle == null)
if (pokemon.Species.Name != SpeciesNames.Minior || pokemon.BattleData?.Battle == null)
return;
if (pokemon.CurrentHealth < pokemon.MaxHealth / 2 && pokemon.Form.Name.ToString().EndsWith("-meteor"))
{
@@ -35,7 +35,7 @@ public class ShieldsDown : Script, IScriptOnEndTurn, IScriptOnSwitchIn
pokemon.Form.Name.ToString().EndsWith("-meteor") == false)
{
var baseFormName = pokemon.Form.Name;
if (baseFormName == "default")
if (baseFormName == FormNames.Default)
baseFormName = "blue";
var meteorFormName = baseFormName + "-meteor";
if (pokemon.Species.TryGetForm(meteorFormName, out var meteorFormData))

View File

@@ -13,11 +13,11 @@ public class StanceChange : Script, IScriptOnBeforeMove
/// <inheritdoc />
public void OnBeforeMove(IExecutingMove move)
{
if (move.User.Species.Name != "aegislash")
if (move.User.Species.Name != SpeciesNames.Aegislash)
return;
if (move.UseMove.Category is not (MoveCategory.Physical or MoveCategory.Special) ||
move.User.Form.Name == "blade" || !move.User.Species.TryGetForm("blade", out var bladeForm))
move.User.Form.Name == FormNames.Blade || !move.User.Species.TryGetForm(FormNames.Blade, out var bladeForm))
return;
EventBatchId batchId = new();
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User)

View File

@@ -12,7 +12,7 @@ public class Steelworker : Script, IScriptChangeOffensiveStatValue
public void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint defensiveStat,
ImmutableStatisticSet<uint> targetStats, Statistic stat, ref uint value)
{
if (move.GetHitData(target, hit).Type?.Name == "steel")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Steel)
{
value = value.MultiplyOrMax(1.5f);
}

View File

@@ -11,7 +11,7 @@ public class StormDrain : Script, IScriptChangeIncomingTargets, IScriptChangeEff
/// <inheritdoc />
public void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
{
if (moveChoice.ChosenMove.MoveData.MoveType.Name == "water" && targets.Count == 1)
if (moveChoice.ChosenMove.MoveData.MoveType.Name == TypeNames.Water && targets.Count == 1)
{
targets = [moveChoice.User];
}
@@ -20,7 +20,7 @@ public class StormDrain : Script, IScriptChangeIncomingTargets, IScriptChangeEff
/// <inheritdoc />
public void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
{
if (move.GetHitData(target, hit).Type?.Name != "water")
if (move.GetHitData(target, hit).Type?.Name != TypeNames.Water)
return;
effectiveness = 0f;

View File

@@ -12,7 +12,7 @@ public class ThickFat : Script, IScriptChangeMoveDamage
public void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
var type = move.GetHitData(target, hit).Type;
if (type is not null && (type.Value.Name == "ice" || type.Value.Name == "fire"))
if (type is not null && (type.Value.Name == TypeNames.Ice || type.Value.Name == TypeNames.Fire))
{
damage /= 2;
}

View File

@@ -11,7 +11,7 @@ public class VoltAbsorb : Script, IScriptIsInvulnerableToMove
/// <inheritdoc />
public void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.GetHitData(target, 0).Type?.Name != "electric")
if (move.GetHitData(target, 0).Type?.Name != TypeNames.Electric)
return;
invulnerable = true;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -11,7 +11,7 @@ public class WaterAbsorb : Script, IScriptIsInvulnerableToMove
/// <inheritdoc />
public void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
if (move.GetHitData(target, 0).Type?.Name != "water")
if (move.GetHitData(target, 0).Type?.Name != TypeNames.Water)
return;
invulnerable = true;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));

View File

@@ -18,14 +18,14 @@ public class WaterBubble : Script, IScriptChangeIncomingMoveDamage, IScriptChang
/// <inheritdoc />
public void ChangeIncomingMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (move.GetHitData(target, hit).Type?.Name == "fire")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Fire)
damage /= 2;
}
/// <inheritdoc />
public void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (move.GetHitData(target, hit).Type?.Name == "water")
if (move.GetHitData(target, hit).Type?.Name == TypeNames.Water)
damage *= 2;
}
}

View File

@@ -11,7 +11,7 @@ public class WaterCompaction : Script, IScriptOnIncomingHit
/// <inheritdoc />
public void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.GetHitData(target, hit).Type?.Name != "water")
if (move.GetHitData(target, hit).Type?.Name != TypeNames.Water)
return;
target.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
target.ChangeStatBoost(Statistic.Defense, 2, true, false);

View File

@@ -19,14 +19,14 @@ public class ZenMode : Script, IScriptOnEndTurn, IScriptOnSwitchIn
if (pokemon is null)
return;
if (pokemon.Species.Name != "darmanitan" || pokemon.BattleData?.Battle == null)
if (pokemon.Species.Name != SpeciesNames.Darmanitan || pokemon.BattleData?.Battle == null)
return;
if (pokemon.CurrentHealth < pokemon.MaxHealth / 2 && pokemon.Form.Name != "zen" &&
pokemon.Species.TryGetForm("zen", out var zenForm))
if (pokemon.CurrentHealth < pokemon.MaxHealth / 2 && pokemon.Form.Name != FormNames.Zen &&
pokemon.Species.TryGetForm(FormNames.Zen, out var zenForm))
{
pokemon.ChangeForm(zenForm);
}
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 2 && pokemon.Form.Name == "zen")
else if (pokemon.CurrentHealth >= pokemon.MaxHealth / 2 && pokemon.Form.Name == FormNames.Zen)
{
pokemon.ChangeForm(pokemon.Species.GetDefaultForm());
}

View File

@@ -8,14 +8,14 @@ public class FairyLockEffect : Script, IScriptOnEndTurn, IScriptPreventSelfRunAw
/// <inheritdoc />
public void PreventSelfRunAway(IFleeChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
if (choice.User.Types.All(x => x.Name != TypeNames.Ghost))
prevent = true;
}
/// <inheritdoc />
public void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent)
{
if (choice.User.Types.All(x => x.Name != "ghost"))
if (choice.User.Types.All(x => x.Name != TypeNames.Ghost))
prevent = true;
}

View File

@@ -12,7 +12,7 @@ public class Gravity : Script, IScriptFailIncomingMove, IScriptOnEndTurn, IScrip
{
var typeLibrary = target.Library.StaticLibrary.Types;
if (executingMove.UseMove.MoveType.Name != "ground")
if (executingMove.UseMove.MoveType.Name != TypeNames.Ground)
return;
// Remove all types that are immune to ground moves
types.RemoveAll(x => typeLibrary.GetSingleEffectiveness(executingMove.UseMove.MoveType, x) == 0);

View File

@@ -6,8 +6,8 @@ public class IonDelugeEffect : Script, IScriptChangeMoveType, IScriptOnEndTurn
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
{
if (moveType?.Name == "normal" &&
target.Library.StaticLibrary.Types.TryGetTypeIdentifier("electric", out var electricType))
if (moveType?.Name == TypeNames.Normal &&
target.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Electric, out var electricType))
{
moveType = electricType;
}

View File

@@ -8,7 +8,7 @@ public class MudSportEffect : Script, IScriptChangeBasePower, IScriptOnEndTurn
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (move.UseMove.MoveType.Name == "electric")
if (move.UseMove.MoveType.Name == TypeNames.Electric)
{
basePower = basePower.MultiplyOrMax(1352 / 4096f);
}

View File

@@ -32,7 +32,7 @@ public class UproarEffect : Script, IScriptOnBeforeTurnStart, IScriptOnSecondary
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User == _placer && move.UseMove.Name == "uproar")
if (move.User == _placer && move.UseMove.Name == MoveNames.Uproar)
_hasUsedUproar = true;
}

View File

@@ -8,7 +8,7 @@ public class WaterSportEffect : Script, IScriptChangeMoveDamage, IScriptOnSwitch
/// <inheritdoc />
public void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (move.UseMove.MoveType.Name == "fire")
if (move.UseMove.MoveType.Name == TypeNames.Fire)
{
damage = damage / 2;
}

View File

@@ -17,8 +17,8 @@ public class MoonBall : PokeballScript
{
switch (x)
{
case ItemUseEvolution itemUseEvolution when itemUseEvolution.Item == "moon_ball":
case ItemGenderEvolution itemGenderEvolution when itemGenderEvolution.Item == "moon_ball":
case ItemUseEvolution itemUseEvolution when itemUseEvolution.Item == ItemNames.MoonBall:
case ItemGenderEvolution itemGenderEvolution when itemGenderEvolution.Item == ItemNames.MoonBall:
return true;
default:
return false;

View File

@@ -8,13 +8,10 @@ public class NetBall : PokeballScript
{
}
private static readonly StringKey WaterType = "water";
private static readonly StringKey BugType = "bug";
/// <inheritdoc />
public override void ChangeCatchRate(IPokemon target, ref byte catchRate)
{
if (target.Types.Any(x => x.Name == WaterType || x.Name == BugType))
if (target.Types.Any(x => x.Name == TypeNames.Water || x.Name == TypeNames.Bug))
{
catchRate = catchRate.MultiplyOrMax(3.5f);
}

View File

@@ -5,12 +5,10 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "block")]
public class Block : Script, IScriptOnSecondaryEffect
{
private static StringKey GhostTypeName => new("ghost");
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.Types.Any(x => x.Name == GhostTypeName))
if (target.Types.Any(x => x.Name == TypeNames.Ghost))
return;
target.Volatile.Add(new BlockEffect());
}

View File

@@ -35,7 +35,7 @@ public class Bounce : Script, IScriptPreventMove, IScriptOnBeforeMove, IScriptOn
var random = battle.Random;
if (random.EffectChance(30, move, target, hit))
{
target.SetStatus("paralyzed", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Paralyzed>(), move.User);
}
}
}

View File

@@ -10,7 +10,7 @@ public class BurnUp : Script, IScriptOnSecondaryEffect
if (battleData == null)
return;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("fire", out var fireType))
if (!typeLibrary.TryGetTypeIdentifier(TypeNames.Fire, out var fireType))
return;
if (!move.User.Types.Contains(fireType))
{
@@ -18,7 +18,7 @@ public class BurnUp : Script, IScriptOnSecondaryEffect
return;
}
if (move.User.HasStatus("frozen"))
if (move.User.HasStatus(ScriptUtils.ResolveName<Status.Frozen>()))
move.User.ClearStatus();
move.User.RemoveType(fireType);
}

View File

@@ -20,23 +20,23 @@ public class Camouflage : Script, IScriptOnSecondaryEffect
var environmentCategory = battle.GetEnvironmentCategory();
return environmentCategory switch
{
EnvironmentHelper.EnvironmentCategory.Electric when typesLibrary.TryGetTypeIdentifier("electric",
EnvironmentHelper.EnvironmentCategory.Electric when typesLibrary.TryGetTypeIdentifier(TypeNames.Electric,
out var electricType) => electricType,
EnvironmentHelper.EnvironmentCategory.Fairy when typesLibrary.TryGetTypeIdentifier("fairy",
EnvironmentHelper.EnvironmentCategory.Fairy when typesLibrary.TryGetTypeIdentifier(TypeNames.Fairy,
out var fairyType) => fairyType,
EnvironmentHelper.EnvironmentCategory.Grass when typesLibrary.TryGetTypeIdentifier("grass",
EnvironmentHelper.EnvironmentCategory.Grass when typesLibrary.TryGetTypeIdentifier(TypeNames.Grass,
out var grassType) => grassType,
EnvironmentHelper.EnvironmentCategory.Psychic when typesLibrary.TryGetTypeIdentifier("psychic",
EnvironmentHelper.EnvironmentCategory.Psychic when typesLibrary.TryGetTypeIdentifier(TypeNames.Psychic,
out var psychicType) => psychicType,
EnvironmentHelper.EnvironmentCategory.Rock when typesLibrary.TryGetTypeIdentifier("rock", out var rockType)
=> rockType,
EnvironmentHelper.EnvironmentCategory.Ground when typesLibrary.TryGetTypeIdentifier("ground",
EnvironmentHelper.EnvironmentCategory.Rock when typesLibrary.TryGetTypeIdentifier(TypeNames.Rock,
out var rockType) => rockType,
EnvironmentHelper.EnvironmentCategory.Ground when typesLibrary.TryGetTypeIdentifier(TypeNames.Ground,
out var groundType) => groundType,
EnvironmentHelper.EnvironmentCategory.Ice when typesLibrary.TryGetTypeIdentifier("ice", out var iceType) =>
iceType,
EnvironmentHelper.EnvironmentCategory.Water when typesLibrary.TryGetTypeIdentifier("water",
EnvironmentHelper.EnvironmentCategory.Ice when typesLibrary.TryGetTypeIdentifier(TypeNames.Ice,
out var iceType) => iceType,
EnvironmentHelper.EnvironmentCategory.Water when typesLibrary.TryGetTypeIdentifier(TypeNames.Water,
out var waterType) => waterType,
EnvironmentHelper.EnvironmentCategory.Normal when typesLibrary.TryGetTypeIdentifier("normal",
EnvironmentHelper.EnvironmentCategory.Normal when typesLibrary.TryGetTypeIdentifier(TypeNames.Normal,
out var normalType) => normalType,
_ => null,
};

View File

@@ -14,7 +14,7 @@ public class Captivate : Script, IScriptOnSecondaryEffect
move.GetHitData(target, hit).Fail();
return;
}
if (target.ActiveAbility?.Name == "oblivious")
if (target.ActiveAbility?.Name == AbilityNames.Oblivious)
{
move.GetHitData(target, hit).Fail();
return;

View File

@@ -3,11 +3,14 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "conversion_2")]
public class Conversion2 : Script, IScriptOnSecondaryEffect
{
// The typeless "none" type is not part of the type data, so no generated constant exists for it.
private static readonly StringKey NoneTypeName = "none";
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var lastMoveByTarget = target.BattleData?.LastMoveChoice;
if (lastMoveByTarget == null || lastMoveByTarget.ChosenMove.MoveData.MoveType.Name == "none")
if (lastMoveByTarget == null || lastMoveByTarget.ChosenMove.MoveData.MoveType.Name == NoneTypeName)
{
move.GetHitData(target, hit).Fail();
return;

View File

@@ -12,7 +12,7 @@ public class Curse : Script, IScriptOnSecondaryEffect
if (battleData == null)
return;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("ghost", out var ghostType))
if (!typeLibrary.TryGetTypeIdentifier(TypeNames.Ghost, out var ghostType))
return;
if (move.User.Types.Contains(ghostType))
{

View File

@@ -19,7 +19,7 @@ public class Drain : Script, IScriptOnInitialize, IScriptOnSecondaryEffect
var user = move.User;
var damage = move.GetHitData(target, hit).Damage;
var healed = (uint)(damage * DrainModifier);
if (move.User.HasHeldItem("big_root"))
if (move.User.HasHeldItem(ItemNames.BigRoot))
healed = (uint)(healed * 1.3f);
var invert = false;

View File

@@ -3,13 +3,11 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "dream_eater")]
public class DreamEater : Script, IScriptOnSecondaryEffect, IScriptBlockOutgoingHit
{
private static readonly StringKey AsleepStatus = new("asleep");
private static readonly StringKey ComatoseAbility = new("comatose");
/// <inheritdoc />
public void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
if (!target.HasStatus(AsleepStatus) && target.ActiveAbility?.Name != ComatoseAbility)
if (!target.HasStatus(ScriptUtils.ResolveName<Status.Sleep>()) &&
target.ActiveAbility?.Name != AbilityNames.Comatose)
block = true;
}
@@ -19,7 +17,7 @@ public class DreamEater : Script, IScriptOnSecondaryEffect, IScriptBlockOutgoing
var user = move.User;
var damage = move.GetHitData(target, hit).Damage;
var healed = (uint)(damage * 0.5f);
if (move.User.HasHeldItem("big_root"))
if (move.User.HasHeldItem(ItemNames.BigRoot))
healed = (uint)(healed * 1.3f);
var args = new CustomTriggers.ModifyDrainArgs(move, target, hit, damage, healed, false);

View File

@@ -14,7 +14,7 @@ public class FireFang : Script, IScriptOnSecondaryEffect
var random = battleData.Battle.Random;
if (random.EffectChance(10, move, target, hit))
{
target.SetStatus("burned", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Burned>(), move.User);
}
// It also has an independent 10% chance of causing the target to flinch, if the user attacks before the target.

View File

@@ -16,18 +16,19 @@ public class FirePledge : Script, IScriptStopBeforeMove
var pledgeMove = (IMoveChoice?)move.Battle.ChoiceQueue?.FirstOrDefault(x =>
x is IMoveChoice mc && mc.User.BattleData?.SideIndex == move.User.BattleData?.SideIndex &&
(mc.ChosenMove.MoveData.Name == "water_pledge" || mc.ChosenMove.MoveData.Name == "grass_pledge"));
(mc.ChosenMove.MoveData.Name == MoveNames.WaterPledge ||
mc.ChosenMove.MoveData.Name == MoveNames.GrassPledge));
if (pledgeMove is null)
return;
// If a pledge move is already queued, we stop the current move.
stop = true;
if (pledgeMove.ChosenMove.MoveData.Name == "water_pledge")
if (pledgeMove.ChosenMove.MoveData.Name == MoveNames.WaterPledge)
{
pledgeMove.Volatile.Add(new FireWaterPledgeMove());
}
else if (pledgeMove.ChosenMove.MoveData.Name == "grass_pledge")
else if (pledgeMove.ChosenMove.MoveData.Name == MoveNames.GrassPledge)
{
pledgeMove.Volatile.Add(new FireGrassPledgeMove());
}

View File

@@ -19,14 +19,14 @@ public class FlameWheel : Script, IScriptOnInitialize, IScriptOnSecondaryEffect
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.HasStatus("frozen"))
if (move.User.HasStatus(ScriptUtils.ResolveName<Status.Frozen>()))
{
move.User.ClearStatus();
}
if (move.Battle.Random.EffectChance(_burnChance, move, target, hit))
{
target.SetStatus("burned", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Burned>(), move.User);
}
}
}

View File

@@ -15,7 +15,7 @@ public class FlareBlitz : Script, IScriptOnSecondaryEffect
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
{
target.SetStatus("burned", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Burned>(), move.User);
}
var triggerArgs = new CustomTriggers.ModifyRecoilArgs(move, target, hit, hitData.Damage, (uint)recoilDamage);

View File

@@ -11,7 +11,7 @@ public class FlowerShield : Script, IScriptOnSecondaryEffect
var battleData = target.BattleData;
if (battleData == null)
return;
if (!battleData.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("grass", out var grassType))
if (!battleData.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier(TypeNames.Grass, out var grassType))
return;
var batchId = new EventBatchId();

View File

@@ -8,7 +8,7 @@ public class FlyingPress : Script, IScriptChangeTypesForMove
IList<TypeIdentifier> types)
{
var typeLibrary = executingMove.User.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("flying", out var flyingType))
if (!typeLibrary.TryGetTypeIdentifier(TypeNames.Flying, out var flyingType))
return;
types.Add(flyingType);
}

View File

@@ -12,7 +12,7 @@ public class ForestsCurse : Script, IScriptOnSecondaryEffect
if (battleData == null)
return;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("grass", out var grassType) || target.Types.Contains(grassType))
if (!typeLibrary.TryGetTypeIdentifier(TypeNames.Grass, out var grassType) || target.Types.Contains(grassType))
{
move.GetHitData(target, hit).Fail();
return;

View File

@@ -11,7 +11,7 @@ public class FreezeDry : Script, IScriptChangeEffectiveness, IScriptOnSecondaryE
return;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("water", out var waterType))
if (!typeLibrary.TryGetTypeIdentifier(TypeNames.Water, out var waterType))
return;
var hitDataType = move.GetHitData(target, hit).Type;
@@ -32,7 +32,7 @@ public class FreezeDry : Script, IScriptChangeEffectiveness, IScriptOnSecondaryE
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
{
target.SetStatus("frozen", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Frozen>(), move.User);
}
}
}

View File

@@ -17,7 +17,7 @@ public class FreezeShock : BaseChargeMove<RequireChargeEffect>
if (battleData.Battle.Random.EffectChance(30, move, target, hit))
{
target.SetStatus("paralyzed", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Paralyzed>(), move.User);
}
}
}

View File

@@ -16,7 +16,7 @@ public class FusionBolt : Script, IScriptChangeDamageModifier
.OfType<MoveChoice>().LastOrDefault(x => !x.HasFailed);
// If Fusion Flare was used immediately preceding, Fusion Bolt's power is doubled.
if (choice is not null && choice.ChosenMove.MoveData.Name == "fusion_flare")
if (choice is not null && choice.ChosenMove.MoveData.Name == MoveNames.FusionFlare)
{
modifier *= 2;
}

View File

@@ -16,7 +16,7 @@ public class FusionFlare : Script, IScriptChangeDamageModifier
.OfType<MoveChoice>().LastOrDefault(x => !x.HasFailed);
// If Fusion Bolt was used immediately preceding, Fusion Flare's power is doubled.
if (choice is not null && choice.ChosenMove.MoveData.Name == "fusion_bolt")
if (choice is not null && choice.ChosenMove.MoveData.Name == MoveNames.FusionBolt)
{
modifier *= 2;
}

View File

@@ -15,7 +15,7 @@ public class GearUp : Script, IScriptOnSecondaryEffect
foreach (var pokemon in side.Pokemon.WhereNotNull())
{
var ability = pokemon.ActiveAbility?.Name;
if (ability != "plus" && ability != "minus")
if (ability != AbilityNames.Plus && ability != AbilityNames.Minus)
continue;
pokemon.ChangeStatBoost(Statistic.Attack, 1, pokemon == move.User, false, evtBatchId);
pokemon.ChangeStatBoost(Statistic.SpecialAttack, 1, pokemon == move.User, false, evtBatchId);

View File

@@ -16,18 +16,19 @@ public class GrassPledge : Script, IScriptStopBeforeMove
var pledgeMove = (IMoveChoice?)move.Battle.ChoiceQueue?.FirstOrDefault(x =>
x is IMoveChoice mc && mc.User.BattleData?.SideIndex == move.User.BattleData?.SideIndex &&
(mc.ChosenMove.MoveData.Name == "water_pledge" || mc.ChosenMove.MoveData.Name == "fire_pledge"));
(mc.ChosenMove.MoveData.Name == MoveNames.WaterPledge ||
mc.ChosenMove.MoveData.Name == MoveNames.FirePledge));
if (pledgeMove is null)
return;
// If a pledge move is already queued, we stop the current move.
stop = true;
if (pledgeMove.ChosenMove.MoveData.Name == "water_pledge")
if (pledgeMove.ChosenMove.MoveData.Name == MoveNames.WaterPledge)
{
pledgeMove.Volatile.Add(new GrassWaterPledgeMove());
}
else if (pledgeMove.ChosenMove.MoveData.Name == "fire_pledge")
else if (pledgeMove.ChosenMove.MoveData.Name == MoveNames.FirePledge)
{
pledgeMove.Volatile.Add(new FireGrassPledgeMove());
}

View File

@@ -14,7 +14,7 @@ public class HealBell : Script, IScriptOnSecondaryEffect
foreach (var pokemon in party.Party.WhereNotNull())
{
if (pokemon.BattleData?.IsOnBattlefield == true && pokemon.ActiveAbility?.Name == "soundproof")
if (pokemon.BattleData?.IsOnBattlefield == true && pokemon.ActiveAbility?.Name == AbilityNames.Soundproof)
continue;
pokemon.ClearStatus();
}

View File

@@ -6,7 +6,7 @@ public class Hex : Script, IScriptChangeBasePower
/// <inheritdoc />
public void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
if (!target.StatusScript.IsEmpty || target.ActiveAbility?.Name == "comatose")
if (!target.StatusScript.IsEmpty || target.ActiveAbility?.Name == AbilityNames.Comatose)
{
basePower = basePower.MultiplyOrMax(2);
}

View File

@@ -21,12 +21,9 @@ public class HyperspaceFury : Script, IScriptFailMove, IScriptOnSecondaryEffect
move.User.ChangeStatBoost(Statistic.Defense, -1, true, false);
}
private static StringKey HoopaName = "hoopa";
private static StringKey UnboundName = "unbound";
public void FailMove(IExecutingMove move, ref bool fail)
{
if (move.User.Species.Name != HoopaName || move.User.Form.Name != UnboundName)
if (move.User.Species.Name != SpeciesNames.Hoopa || move.User.Form.Name != FormNames.Unbound)
{
fail = true;
}

View File

@@ -17,7 +17,7 @@ public class IceBurn : BaseChargeMove<RequireChargeEffect>
if (battleData.Battle.Random.EffectChance(30, move, target, hit))
{
target.SetStatus("burned", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Burned>(), move.User);
}
}
}

View File

@@ -14,7 +14,7 @@ public class IceFang : Script, IScriptOnSecondaryEffect
var random = battleData.Battle.Random;
if (random.EffectChance(10, move, target, hit))
{
target.SetStatus("frozen", move.User);
target.SetStatus(ScriptUtils.ResolveName<Status.Frozen>(), move.User);
}
// It also has an independent 10% chance of causing the target to flinch, if the user attacks before the target.

View File

@@ -5,6 +5,27 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "judgement")]
public class Judgement : Script, IScriptChangeMoveType
{
private static readonly Dictionary<StringKey, StringKey> PlateTypes = new()
{
{ ItemNames.DreadPlate, TypeNames.Dark },
{ ItemNames.EarthPlate, TypeNames.Ground },
{ ItemNames.FistPlate, TypeNames.Fighting },
{ ItemNames.FlamePlate, TypeNames.Fire },
{ ItemNames.IciclePlate, TypeNames.Ice },
{ ItemNames.InsectPlate, TypeNames.Bug },
{ ItemNames.IronPlate, TypeNames.Steel },
{ ItemNames.MeadowPlate, TypeNames.Grass },
{ ItemNames.MindPlate, TypeNames.Psychic },
{ ItemNames.PixiePlate, TypeNames.Fairy },
{ ItemNames.SkyPlate, TypeNames.Flying },
{ ItemNames.SpookyPlate, TypeNames.Ghost },
{ ItemNames.StonePlate, TypeNames.Rock },
{ ItemNames.ToxicPlate, TypeNames.Poison },
{ ItemNames.ZapPlate, TypeNames.Electric },
{ ItemNames.DracoPlate, TypeNames.Dragon },
{ ItemNames.SplashPlate, TypeNames.Water },
};
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
{
@@ -19,26 +40,10 @@ public class Judgement : Script, IScriptChangeMoveType
return;
var typeLibrary = target.Library.StaticLibrary.Types;
moveType = heldItem.Name.ToString().ToLowerInvariant() switch
if (PlateTypes.TryGetValue(heldItem.Name, out var typeName) &&
typeLibrary.TryGetTypeIdentifier(typeName, out var type))
{
"dread_plate" when typeLibrary.TryGetTypeIdentifier("dark", out var dark) => dark,
"earth_plate" when typeLibrary.TryGetTypeIdentifier("ground", out var ground) => ground,
"fist_plate" when typeLibrary.TryGetTypeIdentifier("fighting", out var fighting) => fighting,
"flame_plate" when typeLibrary.TryGetTypeIdentifier("fire", out var fire) => fire,
"icicle_plate" when typeLibrary.TryGetTypeIdentifier("ice", out var ice) => ice,
"insect_plate" when typeLibrary.TryGetTypeIdentifier("bug", out var bug) => bug,
"iron_plate" when typeLibrary.TryGetTypeIdentifier("steel", out var steel) => steel,
"meadow_plate" when typeLibrary.TryGetTypeIdentifier("grass", out var grass) => grass,
"mind_plate" when typeLibrary.TryGetTypeIdentifier("psychic", out var psychic) => psychic,
"pixie_plate" when typeLibrary.TryGetTypeIdentifier("fairy", out var fairy) => fairy,
"sky_plate" when typeLibrary.TryGetTypeIdentifier("flying", out var flying) => flying,
"spooky_plate" when typeLibrary.TryGetTypeIdentifier("ghost", out var ghost) => ghost,
"stone_plate" when typeLibrary.TryGetTypeIdentifier("rock", out var rock) => rock,
"toxic_plate" when typeLibrary.TryGetTypeIdentifier("poison", out var poison) => poison,
"zap_plate" when typeLibrary.TryGetTypeIdentifier("electric", out var electric) => electric,
"draco_plate" when typeLibrary.TryGetTypeIdentifier("dragon", out var dragon) => dragon,
"splash_plate" when typeLibrary.TryGetTypeIdentifier("water", out var water) => water,
_ => moveType,
};
moveType = type;
}
}
}

View File

@@ -14,7 +14,7 @@ public class KingsShield : ProtectionScript
if (move.GetHitData(target, hit).HasFailed)
return;
// Default form is shield form
if (move.User.Species.Name == "aegislash" && move.User.Form.Name != "default")
if (move.User.Species.Name == SpeciesNames.Aegislash && move.User.Form.Name != FormNames.Default)
{
move.User.ChangeForm(move.User.Species.GetDefaultForm());
}

View File

@@ -12,7 +12,7 @@ public class LastResort : Script, IScriptPreventMoveSelection
prevent = true;
return;
}
var userMoves = choice.User.Moves.WhereNotNull().Where(x => x.MoveData.Name != "last_resort").ToList();
var userMoves = choice.User.Moves.WhereNotNull().Where(x => x.MoveData.Name != MoveNames.LastResort).ToList();
if (userMoves.Count == 0)
{
prevent = true;

View File

@@ -8,7 +8,7 @@ public class LeechSeed : Script, IScriptOnSecondaryEffect
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.Types.Any(x => x.Name == "grass"))
if (target.Types.Any(x => x.Name == TypeNames.Grass))
{
move.GetHitData(target, hit).Fail();
return;

View File

@@ -9,7 +9,7 @@ public class MagnetRise : Script, IScriptOnSecondaryEffect
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Volatile.Contains(ScriptUtils.ResolveName<IngrainEffect>()) ||
move.User.ActiveAbility?.Name == "levitate" || move.User.Volatile.Contains<MagnetRiseEffect>())
move.User.ActiveAbility?.Name == AbilityNames.Levitate || move.User.Volatile.Contains<MagnetRiseEffect>())
{
move.GetHitData(target, hit).Fail();
return;

View File

@@ -12,7 +12,7 @@ public class MagneticFlux : Script, IScriptOnSecondaryEffect
foreach (var pokemon in battleData.BattleSide.Pokemon.WhereNotNull())
{
if (pokemon.ActiveAbility?.Name != "plus" && pokemon.ActiveAbility?.Name != "minus")
if (pokemon.ActiveAbility?.Name != AbilityNames.Plus && pokemon.ActiveAbility?.Name != AbilityNames.Minus)
continue;
EventBatchId batch = new();

View File

@@ -28,7 +28,8 @@ public class MeFirst : Script, IScriptChangeMove
choice.Fail();
return;
}
if (!targetMove.ChosenMove.MoveData.CanCopyMove() || targetMove.ChosenMove.MoveData.Name == "metal_burst" ||
if (!targetMove.ChosenMove.MoveData.CanCopyMove() ||
targetMove.ChosenMove.MoveData.Name == MoveNames.MetalBurst ||
battleData.Battle.Library.MiscLibrary.IsReplacementChoice(targetMove))
{
choice.Fail();

View File

@@ -5,12 +5,10 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "mean_look")]
public class MeanLook : Script, IScriptOnSecondaryEffect
{
private static StringKey GhostTypeName => new("ghost");
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.Types.Any(x => x.Name == GhostTypeName))
if (target.Types.Any(x => x.Name == TypeNames.Ghost))
return;
var targetEffect = target.Volatile.Add(new MeanLookEffectTarget());
if (targetEffect == null)

View File

@@ -8,7 +8,7 @@ public class MultiAttack : Script, IScriptChangeMoveType
/// <inheritdoc />
public void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? moveType)
{
if (move.User.ActiveAbility?.Name == "klutz")
if (move.User.ActiveAbility?.Name == AbilityNames.Klutz)
return;
if (move.Battle.Volatile.Contains<MagicRoomEffect>())
return;

View File

@@ -26,24 +26,24 @@ public class NaturePower : Script, IScriptChangeMove
var environmentCategory = battle.GetEnvironmentCategory();
var moveName = environmentCategory switch
{
EnvironmentHelper.EnvironmentCategory.Electric when movesLibrary.TryGet("thunderbolt",
EnvironmentHelper.EnvironmentCategory.Electric when movesLibrary.TryGet(MoveNames.Thunderbolt,
out var thunderboltMove) => (StringKey?)thunderboltMove.Name,
EnvironmentHelper.EnvironmentCategory.Fairy when movesLibrary.TryGet("moonblast", out var moonblastMove) =>
moonblastMove.Name,
EnvironmentHelper.EnvironmentCategory.Grass when movesLibrary.TryGet("energy_ball", out var energyballMove)
=> energyballMove.Name,
EnvironmentHelper.EnvironmentCategory.Psychic when movesLibrary.TryGet("psychic", out var psychicMove) =>
psychicMove.Name,
EnvironmentHelper.EnvironmentCategory.Rock when movesLibrary.TryGet("power_gem", out var rockMove) =>
EnvironmentHelper.EnvironmentCategory.Fairy when movesLibrary.TryGet(MoveNames.Moonblast,
out var moonblastMove) => moonblastMove.Name,
EnvironmentHelper.EnvironmentCategory.Grass when movesLibrary.TryGet(MoveNames.EnergyBall,
out var energyballMove) => energyballMove.Name,
EnvironmentHelper.EnvironmentCategory.Psychic when movesLibrary.TryGet(MoveNames.Psychic,
out var psychicMove) => psychicMove.Name,
EnvironmentHelper.EnvironmentCategory.Rock when movesLibrary.TryGet(MoveNames.PowerGem, out var rockMove) =>
rockMove.Name,
EnvironmentHelper.EnvironmentCategory.Ground when movesLibrary.TryGet("earth_power", out var groundMove) =>
groundMove.Name,
EnvironmentHelper.EnvironmentCategory.Ice when movesLibrary.TryGet("ice_beam", out var iceMove) => iceMove
.Name,
EnvironmentHelper.EnvironmentCategory.Water when movesLibrary.TryGet("hydro_pump", out var waterMove) =>
waterMove.Name,
EnvironmentHelper.EnvironmentCategory.Normal when movesLibrary.TryGet("tri_attack", out var normalMove) =>
normalMove.Name,
EnvironmentHelper.EnvironmentCategory.Ground when movesLibrary.TryGet(MoveNames.EarthPower,
out var groundMove) => groundMove.Name,
EnvironmentHelper.EnvironmentCategory.Ice when movesLibrary.TryGet(MoveNames.IceBeam, out var iceMove) =>
iceMove.Name,
EnvironmentHelper.EnvironmentCategory.Water when movesLibrary.TryGet(MoveNames.HydroPump, out var waterMove)
=> waterMove.Name,
EnvironmentHelper.EnvironmentCategory.Normal when movesLibrary.TryGet(MoveNames.TriAttack,
out var normalMove) => normalMove.Name,
_ => null,
};
return moveName;

View File

@@ -1,23 +1,27 @@
using PkmnLib.Plugin.Gen7.Scripts.Status;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "refresh")]
public class Refresh : Script, IScriptOnSecondaryEffect
{
private static readonly StringKey[] CurableStatuses =
[
ScriptUtils.ResolveName<Paralyzed>(), ScriptUtils.ResolveName<Burned>(),
ScriptUtils.ResolveName<Poisoned>(), ScriptUtils.ResolveName<BadlyPoisoned>(),
];
/// <inheritdoc />
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var userStatus = move.User.StatusScript;
switch (userStatus.Script?.Name)
if (userStatus.Script is { } statusScript && CurableStatuses.Contains(statusScript.Name))
{
case "paralyzed":
case "burned":
case "poisoned":
case "badly_poisoned":
move.User.ClearStatus();
break;
default:
move.GetHitData(target, hit).Fail();
break;
move.User.ClearStatus();
}
else
{
move.GetHitData(target, hit).Fail();
}
}
}

View File

@@ -7,7 +7,7 @@ public class Rototiller : Script, IScriptOnSecondaryEffect
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var pokemon = move.Battle.Sides.SelectMany(x => x.Pokemon).WhereNotNull()
.Where(x => x.Types.Any(y => y.Name == "grass"));
.Where(x => x.Types.Any(y => y.Name == TypeNames.Grass));
EventBatchId batchId = new();
foreach (var pkmn in pokemon)
{

View File

@@ -14,8 +14,9 @@ public class Round : Script, IScriptOnAfterMove
return;
}
var otherRoundMoves = choiceQueue.Where(x => x is IMoveChoice mc && mc.ChosenMove.MoveData.Name == "round")
.Cast<IMoveChoice>().ToList();
var otherRoundMoves = choiceQueue
.Where(x => x is IMoveChoice mc && mc.ChosenMove.MoveData.Name == MoveNames.Round).Cast<IMoveChoice>()
.ToList();
// We reverse the order here, as we're constantly pushing the choices to the front of the queue.
// By reversing the order, we ensure that the first choice is the one that is up next.

Some files were not shown because too many files have changed in this diff Show More