Implements a bunch more moves

This commit is contained in:
2025-03-08 14:39:50 +01:00
parent 8f262cb4a6
commit 77f1ab243b
33 changed files with 935 additions and 57 deletions

View File

@@ -1,4 +1,6 @@
using System;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
@@ -12,7 +14,8 @@ public class FuryCutter : Script
if (userEffect == null)
return;
userEffect.TurnCount++;
basePower = (byte)(basePower * (userEffect.TurnCount + 1));
if (userEffect.TurnCount < 5)
userEffect.TurnCount++;
basePower = basePower.MultiplyOrMax((byte)Math.Pow(2, userEffect.TurnCount));
}
}

View File

@@ -0,0 +1,25 @@
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "heal_bell")]
public class HealBell : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var party = move.User.BattleData?.Battle.Parties.FirstOrDefault(p => p.Party.Contains(target));
if (party == null)
return;
foreach (var pokemon in party.Party.WhereNotNull())
{
pokemon.ClearStatus();
var confusion = ScriptUtils.ResolveName<Confusion>();
if (pokemon.Volatile.Contains(confusion))
pokemon.Volatile.Remove(confusion);
}
}
}

View File

@@ -0,0 +1,13 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "heal_block")]
public class HealBlock : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
target.Volatile.Add(new HealBlockEffect());
}
}

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "heal_percent")]
public class HealPercent : Script
{
private float _healPercent = 0.5f;
/// <inheritdoc />
public override void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
{
if (parameters?.TryGetValue("healPercent", out var variable) == true && variable is float healPercent)
{
_healPercent = healPercent;
}
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
target.Heal((uint)(move.User.BoostedStats.Hp * _healPercent));
}
}

View File

@@ -0,0 +1,20 @@
using PkmnLib.Plugin.Gen7.Scripts.Side;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "healing_wish")]
public class HealingWish : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
var side = battleData.Battle.Sides[battleData.SideIndex];
side.VolatileScripts.Add(new HealingWishEffect(battleData.Position));
move.User.Faint(DamageSource.Misc);
}
}

View File

@@ -0,0 +1,26 @@
using System;
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "heart_swap")]
public class HeartSwap : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
var userStats = move.User.StatBoost;
var targetStats = target.StatBoost;
foreach (Statistic stat in Enum.GetValues(typeof(Statistic)))
{
var userStat = userStats.GetStatistic(stat);
var targetStat = targetStats.GetStatistic(stat);
if (userStat == targetStat)
continue;
move.User.ChangeStatBoost(stat, (sbyte)(userStat - targetStat), true, eventBatchId);
target.ChangeStatBoost(stat, (sbyte)(targetStat - userStat), false, eventBatchId);
}
}
}

View File

@@ -0,0 +1,19 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "heat_crash")]
public class HeatCrash : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
var weightMultiplier = move.User.WeightInKg / target.WeightInKg;
basePower = weightMultiplier switch
{
> 5 => 120,
> 4 => 100,
> 3 => 80,
> 2 => 60,
_ => 40,
};
}
}

View File

@@ -0,0 +1,11 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "helping_hand")]
public class HelpingHand : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit) =>
target.Volatile.Add(new HelpingHandEffect());
}

View File

@@ -0,0 +1,16 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "hex")]
public class Hex : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
if (!target.StatusScript.IsEmpty)
{
basePower = basePower.MultiplyOrMax(2);
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "hidden_power")]
public class HiddenPower : Script
{
/// <inheritdoc />
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
{
var ivs = move.User.IndividualValues;
var type = GetHiddenPowerValue(ivs, 0x00000001) * 15 / 63;
move.User.Library.StaticLibrary.Types.TryGetTypeIdentifierFromIndex((byte)(type + 2), out moveType);
}
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
var ivs = move.User.IndividualValues;
var power = GetHiddenPowerValue(ivs, 0x00000002) * 40 / 63 + 30;
// cast to byte with overflow check
basePower = (byte)Math.Min(power, byte.MaxValue);
}
/// <summary>
/// Helper method to calculate the hidden power value from the IVs.
/// This is used to determine the type and power of the move.
/// </summary>
private static int GetHiddenPowerValue(IndividualValueStatisticSet ivs, int significance) =>
((ivs.Hp & significance) >> (significance - 1)) + (((ivs.Attack & significance) >> (significance - 1)) << 1) +
(((ivs.Defense & significance) >> (significance - 1)) << 2) +
(((ivs.Speed & significance) >> (significance - 1)) << 3) +
(((ivs.SpecialAttack & significance) >> (significance - 1)) << 4) +
(((ivs.SpecialDefense & significance) >> (significance - 1)) << 5);
}

View File

@@ -0,0 +1,18 @@
using System;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "high_jump_kick")]
public class HighJumpKick : Script
{
/// <inheritdoc />
public override void OnMoveMiss(IExecutingMove move, IPokemon target)
{
var damage = move.GetHitData(target, 0).Damage;
var recoil = damage / 2;
// This recoil damage will not exceed half the user's max HP
var maxHp = move.User.BoostedStats.Hp;
recoil = Math.Min(recoil, maxHp / 2);
move.User.Damage(recoil, DamageSource.Misc);
}
}

View File

@@ -0,0 +1,18 @@
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "hyperspace_fury")]
public class HyperspaceFury : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var protectionScripts = target.Volatile.Select(x => x.Script).OfType<ProtectionEffectScript>();
foreach (var protectionScript in protectionScripts.ToList())
{
target.Volatile.Remove(protectionScript.Name);
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "ice_ball")]
public class IceBall : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
var userEffect = move.User.Volatile.Get<IceBallEffect>();
if (userEffect == null)
return;
basePower = basePower.MultiplyOrMax((byte)Math.Pow(2, userEffect.TurnCount));
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var userEffect = move.User.Volatile.Get<IceBallEffect>();
if (userEffect == null)
{
userEffect = new IceBallEffect(move.User, move.UseMove.Name);
move.User.Volatile.Add(userEffect);
}
else
{
userEffect.TurnCount++;
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "ice_burn")]
public class IceBurn : BaseChargeMove<RequireChargeEffect>
{
/// <inheritdoc />
public override RequireChargeEffect CreateVolatile(IPokemon user) => new(user, "ice_burn");
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
if (battleData.Battle.Random.EffectChance(30, move, target, hit))
{
target.SetStatus("burned");
}
}
}

View File

@@ -0,0 +1,24 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "ice_fang")]
public class IceFang : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
{
target.SetStatus("frozen");
}
if (battleData.Battle.Random.EffectChance(10, move, target, hit))
{
target.Volatile.Add(new FlinchEffect());
}
}
}

View File

@@ -0,0 +1,13 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "imprison")]
public class Imprison : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
target.Volatile.Add(new ImprisonEffect(move.User));
}
}

View File

@@ -0,0 +1,16 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "incinerate")]
public class Incinerate : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.HeldItem is { Category: ItemCategory.Berry })
{
target.RemoveHeldItemForBattle();
}
}
}

View File

@@ -0,0 +1,29 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "infestation")]
public class Infestation : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var infestationEffect = ScriptUtils.ResolveName<InfestationEffect>();
if (target.Volatile.Contains(infestationEffect))
{
move.GetHitData(target, hit).Fail();
return;
}
var battleData = move.User.BattleData;
if (battleData == null)
return;
var turns = 4;
if (battleData.Battle.Random.GetBool())
{
turns = 5;
}
target.Volatile.Add(new InfestationEffect(target, turns));
}
}