More moves implemented

This commit is contained in:
2025-02-01 15:00:22 +01:00
parent 3a75493912
commit 00fe08dcd4
50 changed files with 1146 additions and 139 deletions

View File

@@ -55,6 +55,10 @@ public class Gen7BattleStatCalculator : IBattleStatCalculator
executingMove.RunScriptHook(x => x.ChangeAccuracyModifier(executingMove, target, hitIndex, ref accuracyModifier));
var modifiedAccuracy = (int)(moveAccuracy * accuracyModifier);
var targetEvasion = target.StatBoost.Evasion;
var ignoreEvasion = false;
executingMove.RunScriptHook(x => x.BypassEvasionStatBoosts(executingMove, target, hitIndex, ref ignoreEvasion));
if (ignoreEvasion)
targetEvasion = 0;
var userAccuracy = executingMove.User.StatBoost.Accuracy;
var difference = targetEvasion - userAccuracy;
var statModifier = difference switch

View File

@@ -0,0 +1,17 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.MoveVolatile;
[Script(ScriptCategory.MoveVolatile, "electrify")]
public class ElectrifyEffect : Script {
/// <inheritdoc />
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
{
var battleData = target.BattleData;
if (battleData == null)
return;
if (!battleData.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("electric", out var electricType))
return;
moveType = electricType;
}
}

View File

@@ -1,15 +0,0 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "bulk_up")]
public class BulkUp : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
move.User.ChangeStatBoost(Statistic.Attack, 1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.Defense, 1, true, eventBatchId);
}
}

View File

@@ -1,15 +0,0 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "calm_mind")]
public class CalmMind : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
move.User.ChangeStatBoost(Statistic.SpecialAttack, 1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.SpecialDefense, 1, true, eventBatchId);
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PkmnLib.Static;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "change_multiple_user_stat_boosts")]
public class ChangeMultipleUserStatBoosts : Script
{
private Dictionary<Statistic, sbyte> _statBoosts = new();
/// <inheritdoc />
public override void OnInitialize(IReadOnlyDictionary<StringKey, object?>? parameters)
{
if (parameters == null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var par in parameters)
{
if (!Enum.TryParse<Statistic>(par.Key, true, out var stat))
continue;
if (par.Value is sbyte value)
{
_statBoosts[stat] = value;
}
}
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId batchId = new();
foreach (var stat in _statBoosts!)
{
move.User.ChangeStatBoost(stat.Key, stat.Value, true, batchId);
}
}
}

View File

@@ -76,4 +76,20 @@ public class ChangeUserSpeed : ChangeUserStats
public ChangeUserSpeed() : base(Statistic.Speed)
{
}
}
[Script(ScriptCategory.Move, "change_user_accuracy")]
public class ChangeUserAccuracy : ChangeUserStats
{
public ChangeUserAccuracy() : base(Statistic.Accuracy)
{
}
}
[Script(ScriptCategory.Move, "change_user_evasion")]
public class ChangeUserEvasion : ChangeUserStats
{
public ChangeUserEvasion() : base(Statistic.Evasion)
{
}
}

View File

@@ -4,10 +4,10 @@ namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
public class ChipAway : Script
{
/// <inheritdoc />
public override void BypassDefensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass)
{
public override void BypassDefensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass) =>
bypass = true;
}
// TODO: bypass evasion stat.
/// <inheritdoc />
public override void BypassEvasionStatBoosts(IExecutingMove move, IPokemon target, byte hitIndex, ref bool bypass)
=> bypass = true;
}

View File

@@ -1,16 +0,0 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "coil")]
public class Coil : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
move.User.ChangeStatBoost(Statistic.Attack, 1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.Defense, 1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.Accuracy, 1, true, eventBatchId);
}
}

View File

@@ -1,15 +0,0 @@
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "cosmic_power")]
public class CosmicPower : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
move.User.ChangeStatBoost(Statistic.Defense, 1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.SpecialDefense, 1, true, eventBatchId);
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "counter")]
public class Counter : Script
{
/// <inheritdoc />
public override void OnBeforeTurnStart(ITurnChoice choice)
{
choice.User.Volatile.Add(new CounterHelperEffect());
}
/// <inheritdoc />
public override void ChangeTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
{
var counterHelper = moveChoice.User.Volatile.Get<CounterHelperEffect>();
var lastHitBy = counterHelper?.LastHitBy;
if (lastHitBy == null)
{
moveChoice.Fail();
return;
}
targets = [lastHitBy];
}
/// <inheritdoc />
public override void ChangeDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
var counterHelper = move.User.Volatile.Get<CounterHelperEffect>();
if (counterHelper == null || counterHelper.LastHitBy == null || counterHelper.LastHitBy != target)
{
move.GetHitData(target, hit).Fail();
return;
}
var lastDamage = counterHelper.LastDamage;
damage = lastDamage.MultiplyOrMax(2);
}
}

View File

@@ -0,0 +1,15 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "covet")]
public class Covet : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.HeldItem == null)
return;
if (move.User.HeldItem != null)
return;
_ = move.User.SetHeldItem(target.RemoveHeldItem());
}
}

View File

@@ -0,0 +1,17 @@
using PkmnLib.Plugin.Gen7.Scripts.Side;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "crafty_shield")]
public class CraftyShield : 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 CraftyShieldEffect());
}
}

View File

@@ -0,0 +1,13 @@
using System;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "crush_grip")]
public class CrushGrip : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
basePower = Math.Max((byte)(120 * target.CurrentHealth / target.BoostedStats.Hp), (byte)1);
}
}

View File

@@ -0,0 +1,34 @@
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "curse")]
public class Curse : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
var typeLibrary = battleData.Battle.Library.StaticLibrary.Types;
if (!typeLibrary.TryGetTypeIdentifier("ghost", out var ghostType))
return;
if (move.User.Types.Contains(ghostType))
{
move.User.Damage(move.User.CurrentHealth / 2, DamageSource.Misc);
if (move.User.CurrentHealth == 0)
return;
target.Volatile.Add(new GhostCurseEffect(target));
}
else
{
EventBatchId batchId = new();
move.User.ChangeStatBoost(Statistic.Speed, -1, true, batchId);
move.User.ChangeStatBoost(Statistic.Defense, 1, true, batchId);
move.User.ChangeStatBoost(Statistic.Attack, 1, true, batchId);
}
}
}

View File

@@ -0,0 +1,13 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "darkest_lariat")]
public class DarkestLariat : Script
{
/// <inheritdoc />
public override void BypassDefensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass) =>
bypass = true;
/// <inheritdoc />
public override void
BypassEvasionStatBoosts(IExecutingMove move, IPokemon target, byte hitIndex, ref bool bypass) => bypass = true;
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "defog")]
public class Defog : Script
{
public static HashSet<StringKey> DefoggedEffects = new()
{
"mist",
"light_screen",
"reflect",
"safe_guard",
"spikes",
"toxic_spikes",
"stealth_rock",
};
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
if (target.BattleData == null)
return;
var targetSide = target.BattleData.Battle.Sides[target.BattleData.SideIndex];
foreach (var effect in DefoggedEffects)
{
targetSide.VolatileScripts.Remove(effect);
}
}
}

View File

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

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "dig")]
public class Dig : Script
{
/// <inheritdoc />
public override void PreventMove(IExecutingMove move, ref bool prevent)
{
if (move.User.Volatile.Contains<DigEffect>())
return;
move.User.Volatile.Add(new DigEffect(move.User));
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("dig_charge", new Dictionary<string, object>()
{
{ "user", move.User }
}));
prevent = true;
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
move.User.Volatile.Remove(ScriptUtils.ResolveName<DigEffect>());
}
}

View File

@@ -0,0 +1,28 @@
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "disable")]
public class Disable : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
var choiceQueue = battleData.Battle.PreviousTurnChoices;
var lastMove = choiceQueue
.SelectMany(x => x)
.OfType<IMoveChoice>()
.LastOrDefault(x => x.User == target);
if (lastMove == null)
{
move.GetHitData(target, hit).Fail();
return;
}
var lastMoveName = lastMove.ChosenMove.MoveData.Name;
target.Volatile.Add(new DisableEffect(lastMoveName));
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "dive")]
public class Dive : Script
{
/// <inheritdoc />
public override void PreventMove(IExecutingMove move, ref bool prevent)
{
if (move.User.Volatile.Contains<DiveEffect>())
return;
move.User.Volatile.Add(new DigEffect(move.User));
move.User.BattleData?.Battle.EventHook.Invoke(new DialogEvent("dive_charge", new Dictionary<string, object>()
{
{ "user", move.User }
}));
prevent = true;
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
move.User.Volatile.Remove(ScriptUtils.ResolveName<DiveEffect>());
}
}

View File

@@ -0,0 +1,31 @@
using System.Linq;
using PkmnLib.Plugin.Gen7.Scripts.Side;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "doom_desire")]
public class DoomDesire : Script
{
/// <inheritdoc />
public override void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
var battleData = target.BattleData;
if (battleData == null)
return;
var side = battleData.Battle.Sides[battleData.SideIndex];
var effect = side.VolatileScripts.Get<DoomDesireEffect>();
if (effect != null && effect.HasTarget(battleData.Position))
{
executingMove.GetHitData(target, hitIndex).Fail();
return;
}
if (effect == null)
{
effect = new DoomDesireEffect(side);
side.VolatileScripts.Add(effect);
}
effect.AddTarget(battleData.Position, executingMove.GetHitData(target, hitIndex).Damage);
block = true;
}
}

View File

@@ -2,14 +2,14 @@ using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "close_combat")]
public class CloseCombat : Script
[Script(ScriptCategory.Move, "dragon_ascent")]
public class DragonAscent : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
EventBatchId eventBatchId = new();
move.User.ChangeStatBoost(Statistic.Defense, -1, true, eventBatchId);
move.User.ChangeStatBoost(Statistic.SpecialDefense, -1, true, eventBatchId);
EventBatchId batchId = new();
move.User.ChangeStatBoost(Statistic.Defense, -1, true, batchId);
move.User.ChangeStatBoost(Statistic.SpecialDefense, -1, true, batchId);
}
}

View File

@@ -0,0 +1,11 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "dragon_rage")]
public class DragonRage : Script
{
/// <inheritdoc />
public override void ChangeDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
damage = 40;
}
}

View File

@@ -0,0 +1,23 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "dream_eater")]
public class DreamEater : Script
{
/// <inheritdoc />
public override void BlockOutgoingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
if (!target.HasStatus("asleep"))
block = true;
}
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var user = move.User;
var damage = move.GetHitData(target, hit).Damage;
var healed = (uint)(damage * 0.5f);
if (move.User.HasHeldItem("big_root"))
healed = (uint)(healed * 1.3f);
user.Heal(healed, false);
}
}

View File

@@ -0,0 +1,31 @@
using PkmnLib.Plugin.Gen7.Scripts.Side;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "echoed_voice")]
public class EchoedVoice : Script
{
/// <inheritdoc />
public override void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
var battleData = move.User.BattleData;
if (battleData == null)
return;
var side = battleData.Battle.Sides[battleData.SideIndex];
var echoedVoiceData = side.VolatileScripts.Get<EchoedVoiceData>();
if (echoedVoiceData == null)
return;
modifier *= 2;
}
/// <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 EchoedVoiceData());
}
}

View File

@@ -0,0 +1,12 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "electric_terrain")]
public class ElectricTerrain : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var battleData = move.User.BattleData;
battleData?.Battle.SetTerrain(ScriptUtils.ResolveName<ElectricTerrain>());
}
}

View File

@@ -0,0 +1,23 @@
using PkmnLib.Plugin.Gen7.Scripts.MoveVolatile;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "electrify")]
public class Electrify : Script
{
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
var choiceQueue = target.BattleData?.Battle.ChoiceQueue;
if (choiceQueue == null)
return;
if (choiceQueue.Where(x => x is IMoveChoice moveChoice && moveChoice.User == target) is not IMoveChoice choice)
{
move.GetHitData(target, hit).Fail();
return;
}
choice.Volatile.Add(new ElectrifyEffect());
}
}

View File

@@ -0,0 +1,23 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "electro_ball")]
public class ElectroBall : Script
{
/// <inheritdoc />
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower)
{
var user = move.User;
var targetSpeed = target.BoostedStats.Speed;
var userSpeed = user.BoostedStats.Speed;
var ratio = (float) userSpeed / targetSpeed;
basePower = ratio switch
{
> 4 => 150,
> 3 => 120,
> 2 => 80,
> 1 => 60,
_ => 40
};
}
}

View File

@@ -3,10 +3,11 @@ using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
public abstract class ProtectionScript : Script
[Script(ScriptCategory.Move, "protect")]
public class ProtectionScript : Script
{
protected abstract ProtectionEffectScript GetEffectScript();
protected virtual ProtectionEffectScript GetEffectScript() => new();
/// <inheritdoc />
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{

View File

@@ -0,0 +1,20 @@
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "counterhelper")]
public class CounterHelperEffect : Script
{
public IPokemon? LastHitBy { get; private set; }
public uint LastDamage { get; private set; }
/// <inheritdoc />
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
if (move.UseMove.Category == MoveCategory.Physical)
{
LastHitBy = move.User;
LastDamage = move.GetHitData(target, hit).Damage;
}
}
}

View File

@@ -0,0 +1,22 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "destiny_bond")]
public class DestinyBondEffect : Script
{
/// <inheritdoc />
public override void OnFaint(IPokemon pokemon, DamageSource source)
{
if (source == DamageSource.MoveDamage)
{
if (pokemon.BattleData?.Battle.ChoiceQueue?.LastRanChoice is not IMoveChoice lastChoice)
return;
lastChoice.User.Damage(lastChoice.User.BoostedStats.Hp * 10, DamageSource.Misc);
}
}
/// <inheritdoc />
public override void OnBeforeMove(IExecutingMove move)
{
RemoveSelf();
}
}

View File

@@ -0,0 +1,34 @@
using PkmnLib.Plugin.Gen7.Scripts.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "dig")]
public class DigEffect : Script
{
private readonly IPokemon _owner;
public DigEffect(IPokemon owner)
{
_owner = owner;
}
/// <inheritdoc />
public override void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
{
var opposingSideIndex = (byte)(_owner.BattleData?.SideIndex == 0 ? 1 : 0);
choice = TurnChoiceHelper.CreateMoveChoice(_owner, "dig", opposingSideIndex, position);
}
/// <inheritdoc />
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
if (!executingMove.UseMove.HasFlag("hit_underground"))
block = true;
}
/// <inheritdoc />
public override void ChangeIncomingDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (!move.UseMove.HasFlag("effective_against_underground"))
damage *= 2;
}
}

View File

@@ -0,0 +1,21 @@
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "disable")]
public class DisableEffect : Script
{
private readonly StringKey _move;
public DisableEffect(StringKey move)
{
_move = move;
}
/// <inheritdoc />
public override void PreventMoveSelection(IMoveChoice choice, ref bool prevent)
{
if (choice.ChosenMove.MoveData.Name == _move)
prevent = true;
}
}

View File

@@ -0,0 +1,34 @@
using PkmnLib.Plugin.Gen7.Scripts.Utils;
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "dive")]
public class DiveEffect : Script
{
private readonly IPokemon _owner;
public DiveEffect(IPokemon owner)
{
_owner = owner;
}
/// <inheritdoc />
public override void ForceTurnSelection(byte sideIndex, byte position, ref ITurnChoice? choice)
{
var opposingSideIndex = (byte)(_owner.BattleData?.SideIndex == 0 ? 1 : 0);
choice = TurnChoiceHelper.CreateMoveChoice(_owner, "dive", opposingSideIndex, position);
}
/// <inheritdoc />
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
{
if (!executingMove.UseMove.HasFlag("hit_underwater"))
block = true;
}
/// <inheritdoc />
public override void ChangeIncomingDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
{
if (!move.UseMove.HasFlag("effective_against_underwater"))
damage *= 2;
}
}

View File

@@ -0,0 +1,18 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
[Script(ScriptCategory.Pokemon, "ghostcurse")]
public class GhostCurseEffect : Script
{
private IPokemon _pokemon;
public GhostCurseEffect(IPokemon pokemon)
{
_pokemon = pokemon;
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
_pokemon.Damage(_pokemon.CurrentHealth / 4, DamageSource.Misc);
}
}

View File

@@ -1,6 +1,6 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Pokemon;
public abstract class ProtectionEffectScript : Script
public class ProtectionEffectScript : Script
{
/// <inheritdoc />
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)

View File

@@ -0,0 +1,14 @@
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "crafty_shield")]
public class CraftyShieldEffect : Script
{
/// <inheritdoc />
public override void StopBeforeMove(IExecutingMove move, ref bool stop)
{
if (move.UseMove.Category == MoveCategory.Status)
stop = true;
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
[Script(ScriptCategory.Side, "doom_desire_effect")]
public class DoomDesireEffect : Script
{
private class Target
{
public byte Position { get; }
public uint Damage { get; }
public int Turns { get; set; }
public Target(byte position, uint damage)
{
Position = position;
Damage = damage;
Turns = 3;
}
}
private readonly IBattleSide _side;
private List<Target> _targets = new();
public DoomDesireEffect(IBattleSide side)
{
_side = side;
}
public void AddTarget(byte position, uint damage)
{
_targets.Add(new Target(position, damage));
}
public bool HasTarget(byte position)
{
return _targets.Exists(x => x.Position == position);
}
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
var toRemove = new List<Target>();
foreach (var v in _targets)
{
v.Turns--;
if (v.Turns == 0)
{
var pokemon = _side.Pokemon[v.Position];
pokemon?.Damage(v.Damage, DamageSource.Misc);
toRemove.Add(v);
}
}
foreach (var v in toRemove)
{
_targets.Remove(v);
}
if (_targets.Count == 0)
{
RemoveSelf();
}
}
}

View File

@@ -0,0 +1,14 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Side;
/// <summary>
/// Just here to indicate that a Pokemon on this side has used Echoed Voice.
/// </summary>
[Script(ScriptCategory.Side, "echoed_voice_data")]
public class EchoedVoiceData : Script
{
/// <inheritdoc />
public override void OnEndTurn(IBattle battle)
{
RemoveSelf();
}
}

View File

@@ -0,0 +1,7 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Status;
[Script(ScriptCategory.Status, "sleep")]
public class Sleep : Script
{
}

View File

@@ -0,0 +1,7 @@
namespace PkmnLib.Plugin.Gen7.Scripts.Terrain;
[Script(ScriptCategory.Terrain, "electric_terrain")]
public class ElectricTerrain : Script
{
// TODO: Implement Electric Terrain
}