More abilities, refactor stealing held items
All checks were successful
Build / Build (push) Successful in 50s
All checks were successful
Build / Build (push) Successful in 50s
This commit is contained in:
parent
1b9d137bb0
commit
f5d18d7186
@ -1,3 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using JetBrains.Annotations;
|
||||
using PkmnLib.Dynamic.Events;
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
@ -251,6 +252,12 @@ public interface IPokemon : IScriptSource, IDeepCloneable
|
||||
/// </remarks>
|
||||
IItem? RemoveHeldItemForBattle();
|
||||
|
||||
/// <summary>
|
||||
/// Tries to steal the held item of the Pokémon. If successful, the item is removed from the Pokémon and returned.
|
||||
/// If the Pokémon does not have a held item, or the item is a form changer, this will return false.
|
||||
/// </summary>
|
||||
bool TryStealHeldItem([NotNullWhen(true)] out IItem? item);
|
||||
|
||||
/// <summary>
|
||||
/// Restores the held item of a Pokémon if it was temporarily removed.
|
||||
/// </summary>
|
||||
@ -812,6 +819,25 @@ public class PokemonImpl : ScriptSource, IPokemon
|
||||
return _stolenHeldItem = RemoveHeldItem();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryStealHeldItem([NotNullWhen(true)] out IItem? item)
|
||||
{
|
||||
if (HeldItem is null || HeldItem.Category == ItemCategory.FormChanger)
|
||||
{
|
||||
item = null;
|
||||
return false;
|
||||
}
|
||||
var prevent = false;
|
||||
this.RunScriptHook(script => script.PreventHeldItemSteal(this, HeldItem, ref prevent));
|
||||
if (prevent)
|
||||
{
|
||||
item = null;
|
||||
return false;
|
||||
}
|
||||
item = RemoveHeldItemForBattle();
|
||||
return item is not null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RestoreStolenHeldItem()
|
||||
{
|
||||
|
@ -812,6 +812,13 @@ public abstract class Script : IDeepCloneable
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to prevent a held item from being stolen by an effect such as Thief or Covet.
|
||||
/// </summary>
|
||||
public virtual void PreventHeldItemSteal(IPokemon pokemon, IItem heldItem, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to run after a held item has changed.
|
||||
/// </summary>
|
||||
|
@ -594,18 +594,37 @@
|
||||
"speed_boost": {
|
||||
"effect": "speed_boost"
|
||||
},
|
||||
"stakeout": {},
|
||||
"stall": {},
|
||||
"stamina": {},
|
||||
"stakeout": {
|
||||
"effect": "stakeout"
|
||||
},
|
||||
"stall": {
|
||||
"effect": "stall"
|
||||
},
|
||||
"stamina": {
|
||||
"effect": "stamina"
|
||||
},
|
||||
"stance_change": {
|
||||
"effect": "stance_change",
|
||||
"canBeChanged": false
|
||||
},
|
||||
"static": {},
|
||||
"steadfast": {},
|
||||
"steelworker": {},
|
||||
"stench": {},
|
||||
"sticky_hold": {},
|
||||
"storm_drain": {},
|
||||
"static": {
|
||||
"effect": "static"
|
||||
},
|
||||
"steadfast": {
|
||||
"effect": "steadfast"
|
||||
},
|
||||
"steelworker": {
|
||||
"effect": "steelworker"
|
||||
},
|
||||
"stench": {
|
||||
"effect": "stench"
|
||||
},
|
||||
"sticky_hold": {
|
||||
"effect": "sticky_hold"
|
||||
},
|
||||
"storm_drain": {
|
||||
"effect": "storm_drain"
|
||||
},
|
||||
"strong_jaw": {},
|
||||
"sturdy": {},
|
||||
"suction_cups": {},
|
||||
|
@ -946,6 +946,7 @@
|
||||
"flags": [],
|
||||
"formes": {
|
||||
"blade": {
|
||||
"isBattleOnly": true,
|
||||
"abilities": [
|
||||
"stance_change"
|
||||
],
|
||||
|
@ -19,7 +19,10 @@ public class Magician : Script
|
||||
if (move.User.HeldItem is not null || target.HeldItem is null)
|
||||
return;
|
||||
|
||||
if (!move.User.TryStealHeldItem(out var item))
|
||||
return;
|
||||
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
|
||||
_ = move.User.SetHeldItem(target.RemoveHeldItemForBattle());
|
||||
_ = move.User.SetHeldItem(item);
|
||||
}
|
||||
}
|
@ -11,10 +11,10 @@ public class Pickpocket : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.GetHitData(target, hit).IsContact && target.HeldItem is null && move.User.HeldItem is not null)
|
||||
{
|
||||
if (!move.GetHitData(target, hit).IsContact || target.HeldItem is not null ||
|
||||
!move.User.TryStealHeldItem(out var item))
|
||||
return;
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
|
||||
_ = target.SetHeldItem(move.User.RemoveHeldItemForBattle());
|
||||
}
|
||||
_ = target.SetHeldItem(item);
|
||||
}
|
||||
}
|
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stakeout.cs
Normal file
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stakeout.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Stakeout is an ability that doubles the damage dealt to Pokémon that have switched in this turn.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Stakeout_(Ability)">Bulbapedia - Stakeout</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "stakeout")]
|
||||
public class Stakeout : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
|
||||
{
|
||||
if (target.BattleData?.SwitchInTurn == move.Battle.CurrentTurnNumber)
|
||||
basePower = basePower.MultiplyOrMax(2);
|
||||
}
|
||||
}
|
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stall.cs
Normal file
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stall.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Stall is an ability that makes the Pokémon move last in its priority bracket.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Stall_(Ability)">Bulbapedia - Stall</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "stall")]
|
||||
public class Stall : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeSpeed(ITurnChoice choice, ref uint speed)
|
||||
{
|
||||
speed = 0;
|
||||
}
|
||||
}
|
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stamina.cs
Normal file
23
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stamina.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Stamina is an ability that raises the user's Defense by one stage when hit by an attack.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Stamina_(Ability)">Bulbapedia - Stamina</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "stamina")]
|
||||
public class Stamina : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
EventBatchId batchId = new();
|
||||
if (target.ChangeStatBoost(Statistic.Defense, 1, true, false, batchId))
|
||||
{
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target)
|
||||
{
|
||||
BatchId = batchId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
using PkmnLib.Static.Moves;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Stance Change is an ability that changes Aegislash's form depending on the move used.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Stance_Change_(Ability)">Bulbapedia - Stance Change</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "stance_change")]
|
||||
public class StanceChange : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnBeforeMove(IExecutingMove move)
|
||||
{
|
||||
if (move.User.Species.Name != "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))
|
||||
return;
|
||||
EventBatchId batchId = new();
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User)
|
||||
{
|
||||
BatchId = batchId,
|
||||
});
|
||||
move.User.ChangeForm(bladeForm, batchId);
|
||||
// Kings shield is handled in the move script.
|
||||
}
|
||||
}
|
31
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Static.cs
Normal file
31
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Static.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Static is an ability that may paralyze attackers using contact moves.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Static_(Ability)">Bulbapedia - Static</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "static")]
|
||||
public class Static : Script
|
||||
{
|
||||
private const int ChanceToParalyze = 30;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (!move.GetHitData(target, hit).IsContact)
|
||||
return;
|
||||
|
||||
if (move.Battle.Random.GetInt(0, 100) < ChanceToParalyze)
|
||||
{
|
||||
EventBatchId batchId = new();
|
||||
if (target.SetStatus(ScriptUtils.ResolveName<Status.Paralyzed>(), false, batchId))
|
||||
{
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(target)
|
||||
{
|
||||
BatchId = batchId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Steadfast.cs
Normal file
26
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Steadfast.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Steadfast is an ability that raises the user's Speed each time it flinches.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Steadfast_(Ability)">Bulbapedia - Steadfast</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "steadfast")]
|
||||
public class Steadfast : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void CustomTrigger(StringKey eventName, ICustomTriggerArgs args)
|
||||
{
|
||||
if (eventName != CustomTriggers.OnFlinch)
|
||||
return;
|
||||
if (args is not CustomTriggers.OnFlinchArgs flinchArgs)
|
||||
return;
|
||||
|
||||
EventBatchId batchId = new();
|
||||
flinchArgs.Move.Battle.EventHook.Invoke(new AbilityTriggerEvent(flinchArgs.Move.User)
|
||||
{
|
||||
BatchId = batchId,
|
||||
});
|
||||
flinchArgs.Move.User.ChangeStatBoost(Statistic.Speed, 1, true, false, batchId);
|
||||
}
|
||||
}
|
20
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Steelworker.cs
Normal file
20
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Steelworker.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Steelworker is an ability that boosts the power of Steel-type moves.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Steelworker_(Ability)">Bulbapedia - Steelworker</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "steelworker")]
|
||||
public class Steelworker : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override 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")
|
||||
{
|
||||
value = value.MultiplyOrMax(1.5f);
|
||||
}
|
||||
}
|
||||
}
|
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stench.cs
Normal file
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Stench.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Stench is an ability that may cause the target to flinch when hit by a damaging move.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Stench_(Ability)">Bulbapedia - Stench</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "stench")]
|
||||
public class Stench : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.Battle.Random.GetInt(100) >= 10)
|
||||
return;
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User));
|
||||
target.Volatile.Add(new FlinchEffect());
|
||||
}
|
||||
}
|
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/StickyHold.cs
Normal file
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/StickyHold.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Sticky Hold is an ability that prevents the Pokémon's held item from being taken.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Sticky_Hold_(Ability)">Bulbapedia - Sticky Hold</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "sticky_hold")]
|
||||
public class StickyHold : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void PreventHeldItemSteal(IPokemon pokemon, IItem heldItem, ref bool prevent)
|
||||
{
|
||||
prevent = true;
|
||||
}
|
||||
}
|
34
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/StormDrain.cs
Normal file
34
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/StormDrain.cs
Normal file
@ -0,0 +1,34 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Storm Drain is an ability that draws in all Water-type moves to up its Special Attack.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Storm_Drain_(Ability)">Bulbapedia - Storm Drain</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "storm_drain")]
|
||||
public class StormDrain : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
|
||||
{
|
||||
if (moveChoice.ChosenMove.MoveData.MoveType.Name == "water" && targets.Count == 1)
|
||||
{
|
||||
targets = [moveChoice.User];
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
|
||||
{
|
||||
if (move.GetHitData(target, hit).Type?.Name != "water")
|
||||
return;
|
||||
|
||||
effectiveness = 0f;
|
||||
EventBatchId batchId = new();
|
||||
move.Battle.EventHook.Invoke(new AbilityTriggerEvent(move.User)
|
||||
{
|
||||
BatchId = batchId,
|
||||
});
|
||||
move.User.ChangeStatBoost(Statistic.SpecialAttack, 1, true, true, batchId);
|
||||
}
|
||||
}
|
@ -132,4 +132,11 @@ public static class CustomTriggers
|
||||
{
|
||||
public byte NumberOfHits { get; set; } = NumberOfHits;
|
||||
}
|
||||
|
||||
public static readonly StringKey OnFlinch = "on_flinch";
|
||||
|
||||
public record OnFlinchArgs(IExecutingMove Move) : ICustomTriggerArgs
|
||||
{
|
||||
public bool Prevent { get; set; } = false;
|
||||
}
|
||||
}
|
@ -13,11 +13,12 @@ public class BugBite : Script
|
||||
|
||||
var targetHeldItem = target.HeldItem;
|
||||
|
||||
if (targetHeldItem is not { Category: ItemCategory.Berry })
|
||||
if (targetHeldItem is not { Category: ItemCategory.Berry } || !target.TryStealHeldItem(out targetHeldItem))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
|
||||
_ = target.SetHeldItem(null);
|
||||
targetHeldItem.RunItemScript(battleData.Battle.Library.ScriptResolver, user);
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ public class Covet : Script
|
||||
{
|
||||
if (target.HeldItem == null)
|
||||
return;
|
||||
if (move.User.HeldItem != null)
|
||||
if (!move.User.TryStealHeldItem(out var item))
|
||||
return;
|
||||
_ = move.User.SetHeldItem(target.RemoveHeldItemForBattle());
|
||||
_ = move.User.SetHeldItem(item);
|
||||
}
|
||||
}
|
@ -6,9 +6,11 @@ public class Incinerate : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (target.HeldItem is { Category: ItemCategory.Berry })
|
||||
if (target.HeldItem is not { Category: ItemCategory.Berry } || !target.TryStealHeldItem(out _))
|
||||
{
|
||||
target.RemoveHeldItemForBattle();
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
// TODO: Add message for item incineration
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ public class KnockOff : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (target.RemoveHeldItemForBattle() is null)
|
||||
if (!target.TryStealHeldItem(out var item))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
}
|
||||
|
@ -7,6 +7,11 @@ public class FlinchEffect : Script
|
||||
public override void PreventMove(IExecutingMove move, ref bool prevent)
|
||||
{
|
||||
prevent = true;
|
||||
var args = new CustomTriggers.OnFlinchArgs(move);
|
||||
move.RunScriptHook(x => x.CustomTrigger(CustomTriggers.OnFlinch, args));
|
||||
if (args.Prevent)
|
||||
return;
|
||||
|
||||
RemoveSelf();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user