This commit is contained in:
parent
e68491e72a
commit
4326794611
@ -57,8 +57,7 @@ public static class MoveTurnExecutor
|
||||
return;
|
||||
}
|
||||
|
||||
var targetSide = battle.Sides[moveChoice.TargetSide];
|
||||
targetSide.RunScriptHook(x => x.ChangeIncomingTargets(moveChoice, ref targets));
|
||||
targets.WhereNotNull().RunScriptHook(x => x.ChangeIncomingTargets(moveChoice, ref targets));
|
||||
|
||||
byte numberOfHits = 1;
|
||||
moveChoice.RunScriptHook(x => x.ChangeNumberOfHits(moveChoice, ref numberOfHits));
|
||||
@ -154,6 +153,11 @@ public static class MoveTurnExecutor
|
||||
break;
|
||||
|
||||
var useMove = executingMove.UseMove;
|
||||
|
||||
var isContact = useMove.HasFlag("contact");
|
||||
executingMove.RunScriptHook(x => x.ModifyIsContact(executingMove, target, hitIndex, ref isContact));
|
||||
hitData.IsContact = isContact;
|
||||
|
||||
var hitType = (TypeIdentifier?)useMove.MoveType;
|
||||
executingMove.RunScriptHook(x => x.ChangeMoveType(executingMove, target, hitIndex, ref hitType));
|
||||
|
||||
|
@ -37,6 +37,11 @@ public interface IHitData
|
||||
/// </summary>
|
||||
TypeIdentifier? Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hit is a contact hit. This is used to determine whether abilities that trigger on contact should be activated.
|
||||
/// </summary>
|
||||
bool IsContact { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hit has failed.
|
||||
/// </summary>
|
||||
@ -76,6 +81,9 @@ public record HitData : IHitData
|
||||
/// <inheritdoc />
|
||||
public TypeIdentifier? Type { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsContact { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool HasFailed { get; private set; }
|
||||
|
||||
|
@ -769,4 +769,12 @@ public abstract class Script : IDeepCloneable
|
||||
public virtual void ModifyWeight(ref float weight)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies whether a move is a contact move or not. This is used for abilities such as Long Reach.
|
||||
/// </summary>
|
||||
public virtual void ModifyIsContact(IExecutingMove executingMove, IPokemon target, byte hitIndex,
|
||||
ref bool isContact)
|
||||
{
|
||||
}
|
||||
}
|
@ -315,15 +315,33 @@
|
||||
"klutz": {
|
||||
"effect": "klutz"
|
||||
},
|
||||
"leaf_guard": {},
|
||||
"levitate": {},
|
||||
"light_metal": {},
|
||||
"lightning_rod": {},
|
||||
"limber": {},
|
||||
"liquid_ooze": {},
|
||||
"liquid_voice": {},
|
||||
"long_reach": {},
|
||||
"magic_bounce": {},
|
||||
"leaf_guard": {
|
||||
"effect": "leaf_guard"
|
||||
},
|
||||
"levitate": {
|
||||
"effect": "levitate"
|
||||
},
|
||||
"light_metal": {
|
||||
"effect": "light_metal"
|
||||
},
|
||||
"lightning_rod": {
|
||||
"effect": "lightning_rod"
|
||||
},
|
||||
"limber": {
|
||||
"effect": "limber"
|
||||
},
|
||||
"liquid_ooze": {
|
||||
"effect": "liquid_ooze"
|
||||
},
|
||||
"liquid_voice": {
|
||||
"effect": "liquid_voice"
|
||||
},
|
||||
"long_reach": {
|
||||
"effect": "long_reach"
|
||||
},
|
||||
"magic_bounce": {
|
||||
"effect": "magic_bounce"
|
||||
},
|
||||
"magic_guard": {},
|
||||
"magician": {},
|
||||
"magma_armor": {},
|
||||
|
@ -14,7 +14,7 @@ public class Aftermath : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
_lastAttack = move;
|
||||
_lastAttack = !move.GetHitData(target, hit).IsContact ? move : null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -22,7 +22,7 @@ public class Aftermath : Script
|
||||
{
|
||||
if (source != DamageSource.MoveDamage)
|
||||
return;
|
||||
if (_lastAttack is null || !_lastAttack.UseMove.HasFlag("contact"))
|
||||
if (_lastAttack is null)
|
||||
return;
|
||||
var user = _lastAttack.User;
|
||||
if (!user.IsUsable)
|
||||
|
@ -17,7 +17,7 @@ public class CuteCharm : Script
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
// Only trigger on contact moves
|
||||
if (!move.UseMove.HasFlag("contact"))
|
||||
if (!move.GetHitData(target, hit).IsContact)
|
||||
return;
|
||||
|
||||
// 30% chance to infatuate
|
||||
|
@ -19,7 +19,7 @@ public class EffectSpore : Script
|
||||
return;
|
||||
if (move.User.HasHeldItem("safety_goggles"))
|
||||
return;
|
||||
if (!move.UseMove.HasFlag("contact"))
|
||||
if (!move.GetHitData(target, hit).IsContact)
|
||||
return;
|
||||
|
||||
var rng = move.Battle.Random;
|
||||
|
@ -12,7 +12,7 @@ public class FlameBody : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (!move.UseMove.HasFlag("contact"))
|
||||
if (!move.GetHitData(target, hit).IsContact)
|
||||
return;
|
||||
|
||||
var rng = move.Battle.Random;
|
||||
|
@ -16,7 +16,7 @@ public class Fluffy : Script
|
||||
{
|
||||
modifier *= 2f;
|
||||
}
|
||||
if (move.UseMove.HasFlag("contact"))
|
||||
if (move.GetHitData(target, hit).IsContact)
|
||||
{
|
||||
modifier *= 0.5f;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public class Gooey : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (!move.UseMove.HasFlag("contact"))
|
||||
if (!move.GetHitData(target, hit).IsContact)
|
||||
return;
|
||||
move.User.ChangeStatBoost(Statistic.Speed, -1, false, false);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public class IronBarbs : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.UseMove.HasFlag("contact"))
|
||||
if (move.GetHitData(target, hit).IsContact)
|
||||
{
|
||||
move.User.Damage(move.User.MaxHealth / 8, DamageSource.Misc);
|
||||
}
|
||||
|
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LeafGuard.cs
Normal file
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LeafGuard.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Leaf Guard is an ability that prevents status conditions in harsh sunlight.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Leaf_Guard_(Ability)">Bulbapedia - Leaf Guard</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "leaf_guard")]
|
||||
public class LeafGuard : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void PreventStatusChange(IPokemon pokemon, StringKey status, bool selfInflicted,
|
||||
ref bool preventStatus)
|
||||
{
|
||||
if (pokemon.BattleData?.Battle.WeatherName != ScriptUtils.ResolveName<Weather.HarshSunlight>())
|
||||
return;
|
||||
if (selfInflicted)
|
||||
return;
|
||||
preventStatus = true;
|
||||
}
|
||||
}
|
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Levitate.cs
Normal file
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Levitate.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Levitate is an ability that gives full immunity to all Ground-type moves.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Levitate_(Ability)">Bulbapedia - Levitate</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "levitate")]
|
||||
public class Levitate : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void IsFloating(IPokemon pokemon, ref bool isFloating)
|
||||
{
|
||||
isFloating = true;
|
||||
}
|
||||
}
|
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LightMetal.cs
Normal file
16
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LightMetal.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Light Metal is an ability that halves the Pokémon's weight.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Light_Metal_(Ability)">Bulbapedia - Light Metal</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "light_metal")]
|
||||
public class LightMetal : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ModifyWeight(ref float weight)
|
||||
{
|
||||
weight *= 0.5f;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Lightning Rod is an ability that draws all Electric-type moves to the Pokémon, raising its Special Attack.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Lightning_Rod_(Ability)">Bulbapedia - Lightning Rod</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "lightning_rod")]
|
||||
public class LightningRod : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
|
||||
{
|
||||
if (moveChoice.ChosenMove.MoveData.MoveType.Name == "electric" && 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 != "electric")
|
||||
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);
|
||||
}
|
||||
}
|
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Limber.cs
Normal file
25
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/Limber.cs
Normal file
@ -0,0 +1,25 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Limber is an ability that prevents the Pokémon from being paralyzed.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Limber_(Ability)">Bulbapedia - Limber</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "limber")]
|
||||
public class Limber : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void PreventStatusChange(IPokemon pokemon, StringKey status, bool selfInflicted,
|
||||
ref bool preventStatus)
|
||||
{
|
||||
if (status != ScriptUtils.ResolveName<Status.Paralyzed>())
|
||||
return;
|
||||
|
||||
// If the status is being inflicted by a move, we can also prevent the move from inflicting it
|
||||
if (selfInflicted)
|
||||
return;
|
||||
|
||||
pokemon.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(pokemon));
|
||||
preventStatus = true;
|
||||
}
|
||||
}
|
19
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LiquidOoze.cs
Normal file
19
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LiquidOoze.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Liquid Ooze is an ability that damages attackers using draining moves instead of healing them.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(Ability)">Bulbapedia - Liquid Ooze</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "liquid_ooze")]
|
||||
public class LiquidOoze : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void CustomTrigger(StringKey eventName, IDictionary<StringKey, object?>? parameters)
|
||||
{
|
||||
if (eventName != CustomTriggers.ModifyDrain || parameters is null)
|
||||
return;
|
||||
|
||||
parameters["invert"] = true;
|
||||
}
|
||||
}
|
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LiquidVoice.cs
Normal file
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LiquidVoice.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Liquid Voice is an ability that makes all sound-based moves become Water-type.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Liquid_Voice_(Ability)">Bulbapedia - Liquid Voice</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "liquid_voice")]
|
||||
public class LiquidVoice : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit,
|
||||
ref TypeIdentifier? typeIdentifier)
|
||||
{
|
||||
if (move.UseMove.HasFlag("sound") &&
|
||||
move.Battle.Library.StaticLibrary.Types.TryGetTypeIdentifier("water", out var waterType))
|
||||
{
|
||||
typeIdentifier = waterType;
|
||||
}
|
||||
}
|
||||
}
|
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LongReach.cs
Normal file
17
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/LongReach.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Long Reach is an ability that allows the Pokémon to use contact moves without making contact.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Long_Reach_(Ability)">Bulbapedia - Long Reach</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "long_reach")]
|
||||
public class LongReach : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ModifyIsContact(IExecutingMove executingMove, IPokemon target, byte hitIndex,
|
||||
ref bool isContact)
|
||||
{
|
||||
isContact = false;
|
||||
}
|
||||
}
|
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/MagicBounce.cs
Normal file
21
Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/MagicBounce.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Abilities;
|
||||
|
||||
/// <summary>
|
||||
/// Magic Bounce is an ability that reflects status moves back to the user.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Magic_Bounce_(Ability)">Bulbapedia - Magic Bounce</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Ability, "magic_bounce")]
|
||||
public class MagicBounce : Script
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void ChangeIncomingTargets(IMoveChoice moveChoice, ref IReadOnlyList<IPokemon?> targets)
|
||||
{
|
||||
if (moveChoice.ChosenMove.MoveData.HasFlag("reflectable"))
|
||||
{
|
||||
var target = targets[0];
|
||||
target?.BattleData?.Battle.EventHook.Invoke(new AbilityTriggerEvent(target));
|
||||
targets = [moveChoice.User];
|
||||
}
|
||||
}
|
||||
}
|
@ -27,4 +27,6 @@ public static class CustomTriggers
|
||||
public static readonly StringKey BypassProtection = "bypass_protection";
|
||||
|
||||
public static readonly StringKey BypassSubstitute = "bypass_subsitute";
|
||||
|
||||
public static readonly StringKey ModifyDrain = "modify_drain";
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
[Script(ScriptCategory.Move, "drain")]
|
||||
@ -24,6 +22,26 @@ public class Drain : Script
|
||||
var healed = (uint)(damage * DrainModifier);
|
||||
if (move.User.HasHeldItem("big_root"))
|
||||
healed = (uint)(healed * 1.3f);
|
||||
var invert = false;
|
||||
var parameters = new Dictionary<StringKey, object?>
|
||||
{
|
||||
{ "user", user },
|
||||
{ "target", target },
|
||||
{ "damage", damage },
|
||||
{ "healed", healed },
|
||||
{ "invert", invert },
|
||||
};
|
||||
target.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifyDrain, parameters));
|
||||
if (parameters.TryGetValue("invert", out var invertObj) && invertObj is bool invertBool)
|
||||
invert = invertBool;
|
||||
|
||||
if (invert)
|
||||
{
|
||||
user.Damage(damage, DamageSource.Misc);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.Heal(healed);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,27 @@ public class DreamEater : Script
|
||||
var healed = (uint)(damage * 0.5f);
|
||||
if (move.User.HasHeldItem("big_root"))
|
||||
healed = (uint)(healed * 1.3f);
|
||||
|
||||
var invert = false;
|
||||
var parameters = new Dictionary<StringKey, object?>
|
||||
{
|
||||
{ "user", user },
|
||||
{ "target", target },
|
||||
{ "damage", damage },
|
||||
{ "healed", healed },
|
||||
{ "invert", invert },
|
||||
};
|
||||
target.RunScriptHook(x => x.CustomTrigger(CustomTriggers.ModifyDrain, parameters));
|
||||
if (parameters.TryGetValue("invert", out var invertObj) && invertObj is bool invertBool)
|
||||
invert = invertBool;
|
||||
|
||||
if (invert)
|
||||
{
|
||||
user.Damage(damage, DamageSource.Misc);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.Heal(healed);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,8 @@ public class BanefulBunkerEffect : ProtectionEffectScript
|
||||
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||
{
|
||||
base.BlockIncomingHit(executingMove, target, hitIndex, ref block);
|
||||
if (executingMove.UseMove.Category != MoveCategory.Status && executingMove.UseMove.HasFlag("contact"))
|
||||
if (executingMove.UseMove.Category != MoveCategory.Status &&
|
||||
executingMove.GetHitData(target, hitIndex).IsContact)
|
||||
{
|
||||
executingMove.User.SetStatus("poisoned", false);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ public class BeakBlastEffect : Script
|
||||
/// <inheritdoc />
|
||||
public override void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
if (move.UseMove.HasFlag("contact"))
|
||||
if (move.GetHitData(target, hit).IsContact)
|
||||
{
|
||||
move.User.SetStatus("burned", false);
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ public class KingsShield : ProtectionEffectScript
|
||||
public override void BlockIncomingHit(IExecutingMove executingMove, IPokemon target, byte hitIndex, ref bool block)
|
||||
{
|
||||
base.BlockIncomingHit(executingMove, target, hitIndex, ref block);
|
||||
if (executingMove.UseMove.Category != MoveCategory.Status && executingMove.UseMove.HasFlag("contact"))
|
||||
if (executingMove.UseMove.Category != MoveCategory.Status &&
|
||||
executingMove.GetHitData(target, hitIndex).IsContact)
|
||||
{
|
||||
executingMove.User.ChangeStatBoost(Statistic.Accuracy, -2, false, false);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user