More moves

This commit is contained in:
2025-04-17 13:07:45 +02:00
parent 1b54c78b07
commit d02c05874b
31 changed files with 682 additions and 65 deletions

View File

@@ -6,7 +6,8 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
public class FoulPlay : Script
{
/// <inheritdoc />
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
public override void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, uint _,
ref uint value)
{
value = move.UseMove.Category == MoveCategory.Physical
? target.BoostedStats.Attack

View File

@@ -22,6 +22,9 @@ public class GuardSplit : Script
userStats.SetStatistic(Statistic.Defense, newDefense);
userStats.SetStatistic(Statistic.SpecialDefense, newSpecialDefense);
targetStats.SetStatistic(Statistic.Defense, newDefense);
targetStats.SetStatistic(Statistic.SpecialDefense, newSpecialDefense);
user.RecalculateFlatStats();
target.RecalculateFlatStats();
}
}

View File

@@ -0,0 +1,28 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Parting Shot, which lowers the target's Attack and Special Attack by one stage each,
/// then forces the user to switch out if at least one stat change was successful.
/// </summary>
[Script(ScriptCategory.Move, "parting_shot")]
public class PartingShot : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
var evtBatch = new EventBatchId();
var attackChanged = target.ChangeStatBoost(Statistic.Attack, -1, false, evtBatch);
var specialAttackChanged = target.ChangeStatBoost(Statistic.SpecialAttack, -1, false, evtBatch);
if (attackChanged || specialAttackChanged)
{
battleData.BattleSide.SwapPokemon(battleData.Position, null);
}
}
}

View File

@@ -0,0 +1,7 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "pay_day")]
public class PayDay : Script
{
// TODO: Implement the Pay Day move effect
}

View File

@@ -0,0 +1,23 @@
using PkmnLib.Static;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Payback, which doubles the move's power if the user moves after the target.
/// </summary>
[Script(ScriptCategory.Move, "payback")]
public class Payback : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
var battleData = move.User.BattleData;
// Check if the target has already moved this turn
if (battleData?.Battle.ChoiceQueue?.FirstOrDefault(x => x.User == target) != null)
{
basePower = basePower.MultiplyOrMax(2);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.Linq;
using PkmnLib.Static;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Perish Song, which causes all Pokemon on the field to faint in 3 turns.
/// </summary>
[Script(ScriptCategory.Move, "perish_song")]
public class PerishSong : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Volatile.Contains<PerishSongEffect>())
return;
var battleData = move.User.BattleData;
if (battleData == null)
return;
// Add Perish Song volatile to all Pokémon on the field
foreach (var pokemon in battleData.Battle.Sides.SelectMany(x => x.Pokemon).WhereNotNull())
{
pokemon.Volatile.Add(new PerishSongEffect(pokemon));
}
}
}

View File

@@ -0,0 +1,26 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Petal Dance, which forces the user to continue using the move for 2-3 turns,
/// then confuses the user.
/// </summary>
[Script(ScriptCategory.Move, "petal_dance")]
public class PetalDance : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Volatile.Contains<PetalDanceEffect>())
return;
var battleData = move.User.BattleData;
if (battleData == null)
return;
var turns = battleData.Battle.Random.GetBool() ? 2 : 3;
move.User.Volatile.Add(new PetalDanceEffect(move.User, turns, move.MoveChoice.TargetSide,
move.MoveChoice.TargetPosition));
}
}

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Phantom Force, which makes the user semi-invulnerable on the first turn
/// and attacks on the second turn.
/// </summary>
[Script(ScriptCategory.Move, "phantom_force")]
public class PhantomForce : Script
{
/// <inheritdoc />
public override void PreventMove(IExecutingMove move, ref bool prevent)
{
if (move.User.Volatile.Contains<PhantomForceCharge>())
return;
move.User.Volatile.Add(new PhantomForceCharge(move.User));
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("phantom_force_charge",
new Dictionary<string, object>
{
{ "user", move.User },
}));
prevent = true;
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Volatile.Contains<PhantomForceCharge>())
return;
move.User.Volatile.Add(new PhantomForceCharge(move.User));
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using PkmnLib.Plugin.Gen7.Scripts.Status;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "poison_tail")]
public class PoisonTail : Script
{
/// <inheritdoc />
public override void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
{
if (stage == 255)
return;
stage += 1;
}
/// <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(ScriptUtils.ResolveName<BadlyPoisoned>());
}
}
}

View File

@@ -0,0 +1,39 @@
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "pollen_puff")]
public class PollenPuff : Script
{
/// <inheritdoc />
/// <inheritdoc />
public override void ChangeCategory(IExecutingMove move, IPokemon target, byte hitIndex, ref MoveCategory category)
{
var battleData = move.User.BattleData;
var targetBattleData = target.BattleData;
if (battleData == null || targetBattleData == null)
return;
if (battleData.SideIndex == targetBattleData.SideIndex)
{
category = MoveCategory.Status;
}
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
var targetBattleData = target.BattleData;
if (battleData == null || targetBattleData == null)
return;
if (battleData.SideIndex == targetBattleData.SideIndex)
{
var maxHealth = target.MaxHealth;
target.Heal(maxHealth / 2);
}
}
}

View File

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

View File

@@ -0,0 +1,30 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "power_split")]
public class PowerSplit : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var user = move.User;
var userStats = user.FlatStats;
var targetStats = target.FlatStats;
var userAttack = userStats.GetStatistic(Statistic.Attack);
var targetAttack = targetStats.GetStatistic(Statistic.Attack);
var userSpecialAttack = userStats.GetStatistic(Statistic.SpecialAttack);
var targetSpecialAttack = targetStats.GetStatistic(Statistic.SpecialAttack);
var newAttack = (userAttack + targetAttack) / 2;
var newSpecialAttack = (userSpecialAttack + targetSpecialAttack) / 2;
userStats.SetStatistic(Statistic.Attack, newAttack);
userStats.SetStatistic(Statistic.SpecialAttack, newSpecialAttack);
targetStats.SetStatistic(Statistic.Attack, newAttack);
targetStats.SetStatistic(Statistic.SpecialAttack, newSpecialAttack);
user.RecalculateFlatStats();
target.RecalculateFlatStats();
}
}

View File

@@ -0,0 +1,26 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "power_swap")]
public class PowerSwap : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var user = move.User;
var eventBatchId = new EventBatchId();
var userAttack = user.StatBoost.Attack;
var targetAttack = target.StatBoost.Attack;
var userSpecialAttack = user.StatBoost.SpecialAttack;
var targetSpecialAttack = target.StatBoost.SpecialAttack;
user.ChangeStatBoost(Statistic.Attack, (sbyte)(targetAttack - userAttack), true, eventBatchId);
user.ChangeStatBoost(Statistic.SpecialAttack, (sbyte)(targetSpecialAttack - userSpecialAttack), true,
eventBatchId);
target.ChangeStatBoost(Statistic.Attack, (sbyte)(userAttack - targetAttack), true, eventBatchId);
target.ChangeStatBoost(Statistic.SpecialAttack, (sbyte)(userSpecialAttack - targetSpecialAttack), true,
eventBatchId);
}
}

View File

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

View File

@@ -0,0 +1,26 @@
using System;
using System.Linq;
using PkmnLib.Static;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "power_trip")]
public class PowerTrip : Script
{
/// <inheritdoc />
public override void ChangeMoveDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
var modifier = 1;
foreach (Statistic stat in Enum.GetValues(typeof(Statistic)))
{
if (stat is Statistic.Accuracy or Statistic.Evasion)
continue;
var statChange = move.User.StatBoost.GetStatistic(stat);
if (statChange > 0)
modifier += statChange;
}
damage = damage.MultiplyOrMax(modifier);
}
}

View File

@@ -0,0 +1,26 @@
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
/// <summary>
/// Implements the secondary effect of Thrash, which forces the user to continue using the move for 2-3 turns,
/// then confuses the user.
/// </summary>
[Script(ScriptCategory.Move, "thrash")]
public class Thrash : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (move.User.Volatile.Contains<ThrashEffect>())
return;
var battleData = move.User.BattleData;
if (battleData == null)
return;
var turns = battleData.Battle.Random.GetBool() ? 2 : 3;
move.User.Volatile.Add(new ThrashEffect(move.User, turns, move.MoveChoice.TargetSide,
move.MoveChoice.TargetPosition));
}
}