Further work on refactor to interface based scripts

This commit is contained in:
2025-06-28 18:40:33 +02:00
parent b7bdf2b744
commit 436d1899e0
352 changed files with 940 additions and 867 deletions

View File

@@ -126,7 +126,8 @@ public static class MoveTurnExecutor
private static void ExecuteMoveChoiceForTarget(IBattle battle, IExecutingMove executingMove, IPokemon target)
{
var failed = false;
target.RunScriptHook(x => x.FailIncomingMove(executingMove, target, ref failed));
target.RunScriptHookInterface<IScriptFailIncomingMove>(x =>
x.FailIncomingMove(executingMove, target, ref failed));
if (failed)
{
// TODO: fail handling
@@ -134,7 +135,8 @@ public static class MoveTurnExecutor
}
var isInvulnerable = false;
target.RunScriptHook(x => x.IsInvulnerableToMove(executingMove, target, ref isInvulnerable));
target.RunScriptHookInterface<IScriptIsInvulnerableToMove>(x =>
x.IsInvulnerableToMove(executingMove, target, ref isInvulnerable));
if (isInvulnerable)
{
battle.EventHook.Invoke(new MoveInvulnerableEvent(executingMove, target));
@@ -166,7 +168,8 @@ public static class MoveTurnExecutor
hitData.IsContact = isContact;
var hitType = (TypeIdentifier?)useMove.MoveType;
executingMove.RunScriptHook(x => x.ChangeMoveType(executingMove, target, hitIndex, ref hitType));
executingMove.RunScriptHookInterface<IScriptChangeMoveType>(x =>
x.ChangeMoveType(executingMove, target, hitIndex, ref hitType));
hitData.Type = hitType;
@@ -177,14 +180,17 @@ public static class MoveTurnExecutor
var effectiveness = hitType == null
? 1
: battle.Library.StaticLibrary.Types.GetEffectiveness(hitType.Value, types);
executingMove.RunScriptHook(x => x.ChangeEffectiveness(executingMove, target, hitIndex, ref effectiveness));
target.RunScriptHook(x =>
executingMove.RunScriptHookInterface<IScriptChangeEffectiveness>(x =>
x.ChangeEffectiveness(executingMove, target, hitIndex, ref effectiveness));
target.RunScriptHookInterface<IScriptChangeIncomingEffectiveness>(x =>
x.ChangeIncomingEffectiveness(executingMove, target, hitIndex, ref effectiveness));
hitData.Effectiveness = effectiveness;
var blockCritical = false;
executingMove.RunScriptHook(x => x.BlockCriticalHit(executingMove, target, hitIndex, ref blockCritical));
target.RunScriptHook(x => x.BlockIncomingCriticalHit(executingMove, target, hitIndex, ref blockCritical));
executingMove.RunScriptHookInterface<IScriptBlockCriticalHit>(x =>
x.BlockCriticalHit(executingMove, target, hitIndex, ref blockCritical));
target.RunScriptHookInterface<IScriptBlockIncomingCriticalHit>(x =>
x.BlockIncomingCriticalHit(executingMove, target, hitIndex, ref blockCritical));
if (!blockCritical)
{
var critical = battle.Library.DamageCalculator.IsCritical(battle, executingMove, target, hitIndex);
@@ -208,7 +214,7 @@ public static class MoveTurnExecutor
if (accuracy < 100 && battle.Random.GetInt(100) >= accuracy)
{
executingMove.RunScriptHook(x => x.OnMoveMiss(executingMove, target));
executingMove.RunScriptHookInterface<IScriptOnMoveMiss>(x => x.OnMoveMiss(executingMove, target));
battle.EventHook.Invoke(new MoveMissEvent(executingMove));
break;
}
@@ -230,7 +236,8 @@ public static class MoveTurnExecutor
var chance = secondaryEffect.Chance;
if (chance < 0 || battle.Random.EffectChance(chance, executingMove, target, hitIndex))
{
executingMove.RunScriptHook(x => x.OnSecondaryEffect(executingMove, target, hitIndex));
executingMove.RunScriptHookInterface<IScriptOnSecondaryEffect>(x =>
x.OnSecondaryEffect(executingMove, target, hitIndex));
}
}
}
@@ -252,9 +259,11 @@ public static class MoveTurnExecutor
});
target.Damage(damage, DamageSource.MoveDamage, hitEventBatch);
if (!target.IsFainted)
target.RunScriptHook(x => x.OnIncomingHit(executingMove, target, hitIndex));
target.RunScriptHookInterface<IScriptOnIncomingHit>(x =>
x.OnIncomingHit(executingMove, target, hitIndex));
else
executingMove.RunScriptHook(x => x.OnOpponentFaints(executingMove, target, hitIndex));
executingMove.RunScriptHookInterface<IScriptOnOpponentFaints>(x =>
x.OnOpponentFaints(executingMove, target, hitIndex));
if (!target.IsFainted)
{
@@ -273,13 +282,14 @@ public static class MoveTurnExecutor
var chance = secondaryEffect.Chance;
if (chance < 0 || battle.Random.EffectChance(chance, executingMove, target, hitIndex))
{
executingMove.RunScriptHook(x =>
executingMove.RunScriptHookInterface<IScriptOnSecondaryEffect>(x =>
x.OnSecondaryEffect(executingMove, target, hitIndex));
}
}
}
if (target.IsFainted)
executingMove.RunScriptHook(x => x.OnOpponentFaints(executingMove, target, hitIndex));
executingMove.RunScriptHookInterface<IScriptOnOpponentFaints>(x =>
x.OnOpponentFaints(executingMove, target, hitIndex));
}
}
}
@@ -287,7 +297,7 @@ public static class MoveTurnExecutor
if (numberOfHits == 0)
{
target.RunScriptHook(x => x.OnMoveMiss(executingMove, target));
target.RunScriptHookInterface<IScriptOnMoveMiss>(x => x.OnMoveMiss(executingMove, target));
battle.EventHook.Invoke(new MoveMissEvent(executingMove));
}

View File

@@ -61,106 +61,6 @@ public abstract class Script : IDeepCloneable
{
}
/// <summary>
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
/// the move fails, and fail events get triggered.
/// </summary>
public virtual void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail)
{
}
/// <summary>
/// This function allows a script to make its owner invulnerable to an incoming move.
/// </summary>
public virtual void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable)
{
}
/// <summary>
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
/// move, which include the scripts that are attached to the owner of the script.
/// </summary>
public virtual void OnMoveMiss(IExecutingMove move, IPokemon target)
{
}
/// <summary>
/// This function allows the script to change the actual type that is used for the move on a target.
/// If this is set to null, the move will be treated as a typeless move.
/// </summary>
public virtual void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit,
ref TypeIdentifier? typeIdentifier)
{
}
/// <summary>
/// This function allows the script to change how effective a move is on a target.
/// </summary>
public virtual void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness)
{
}
/// <summary>
/// This function allows the script to override how effective a move is on a target.
/// </summary>
public virtual void ChangeIncomingEffectiveness(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref float effectiveness)
{
}
/// <summary>
/// This function allows a script to block an outgoing move from being critical.
/// </summary>
public virtual void BlockCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block)
{
}
/// <summary>
/// This function allows a script to block an incoming move from being critical.
/// </summary>
public virtual void BlockIncomingCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block)
{
}
/// <summary>
/// This function allows a script to modify the accuracy of a move used. This value represents
/// the percentage accuracy, so anything above 100% will make it always hit.
/// </summary>
public virtual void ChangeAccuracyModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
}
/// <summary>
/// This function allows a script to change the critical stage of the move used.
/// </summary>
public virtual void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage)
{
}
/// <summary>
/// This function allows a script to change the damage modifier of a critical hit. This will only
/// run when a hit is critical.
/// </summary>
public virtual void ChangeCriticalModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
{
}
/// <summary>
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
/// occurs when the user has the move type as one of its own types.
/// </summary>
public virtual void ChangeStabModifier(IExecutingMove executingMove, IPokemon target, byte hitNumber, bool isStab,
ref float modifier)
{
}
/// <summary>
/// This function allows a script to change the effective base power of a move hit.
/// </summary>
public virtual void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower)
{
}
/// <summary>
/// This function allows a script to bypass defensive stat boosts for a move hit.
/// If this is true, the damage will be calculated as if the target has no positive stat boosts. Negative
@@ -257,21 +157,6 @@ public abstract class Script : IDeepCloneable
{
}
/// <summary>
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
/// but before the secondary effect of the move happens.
/// </summary>
public virtual void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit)
{
}
/// <summary>
/// This function triggers when an opponent on the field faints due to the move that is being executed.
/// </summary>
public virtual void OnOpponentFaints(IExecutingMove move, IPokemon target, byte hit)
{
}
/// <summary>
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
/// changes on that Pokemon.
@@ -335,15 +220,6 @@ public abstract class Script : IDeepCloneable
{
}
/// <summary>
/// This function triggers when the move uses its secondary effect. Moves should implement their
/// secondary effects here. Status moves should implement their actual functionality in this
/// function as well, as status moves effects are defined as secondary effects for simplicity.
/// </summary>
public virtual void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
{
}
/// <summary>
/// This function triggers on a move or its parents when all hits on a target are finished.
/// </summary>
@@ -910,4 +786,191 @@ public interface IScriptOnAfterMove
/// This function runs immediately after all targets have had their hits executed.
/// </summary>
void OnAfterMove(IExecutingMove move);
}
/// <summary>
/// This interface allows scripts to change the type of a move that is used on a target.
/// </summary>
public interface IScriptChangeMoveType
{
/// <summary>
/// This function allows the script to change the actual type that is used for the move on a target.
/// If this is set to null, the move will be treated as a typeless move.
/// </summary>
void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier? typeIdentifier);
}
/// <summary>
/// This interface allows scripts to change the effectiveness of a move on a target.
/// </summary>
public interface IScriptChangeEffectiveness
{
/// <summary>
/// This function allows the script to change how effective a move is on a target.
/// </summary>
void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness);
}
/// <summary>
/// This interface allows scripts to change the effectiveness of a move on a target.
/// </summary>
public interface IScriptChangeIncomingEffectiveness
{
/// <summary>
/// This function allows the script to override how effective a move is on a target.
/// </summary>
void ChangeIncomingEffectiveness(IExecutingMove executingMove, IPokemon target, byte hitIndex,
ref float effectiveness);
}
/// <summary>
/// This interface allows scripts to block a critical hit from being applied to a move.
/// </summary>
public interface IScriptBlockCriticalHit
{
/// <summary>
/// This function allows a script to block an outgoing move from being critical.
/// </summary>
void BlockCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block);
}
/// <summary>
/// This interface allows scripts to block an incoming critical hit from being applied to a move.
/// </summary>
public interface IScriptBlockIncomingCriticalHit
{
/// <summary>
/// This function allows a script to block an incoming move from being critical.
/// </summary>
void BlockIncomingCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block);
}
/// <summary>
/// This interface allows scripts to run when an incoming hit happens.
/// </summary>
public interface IScriptOnIncomingHit
{
/// <summary>
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
/// but before the secondary effect of the move happens.
/// </summary>
void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit);
}
/// <summary>
/// This interface allows scripts to run when an opponent faints due to the move that is being executed.
/// </summary>
public interface IScriptOnOpponentFaints
{
/// <summary>
/// This function triggers when an opponent on the f ield faints due to the move that is being executed.
/// </summary>
void OnOpponentFaints(IExecutingMove move, IPokemon target, byte hit);
}
/// <summary>
/// This interface allows scripts to run when the move uses its secondary effect.
/// </summary>
public interface IScriptOnSecondaryEffect
{
/// <summary>
/// This function triggers when the move uses its secondary effect. Moves should implement their
/// secondary effects here. Status moves should implement their actual functionality in this
/// function as well, as status moves effects are defined as secondary effects for simplicity.
/// </summary>
void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit);
}
/// <summary>
/// This interface allows scripts to run when a move fails to hit its target.
/// </summary>
public interface IScriptFailIncomingMove
{
/// <summary>
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
/// the move fails, and fail events get triggered.
/// </summary>
void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail);
}
/// <summary>
/// This interface allows scripts to run making the owner invulnerable to an incoming move.
/// </summary>
public interface IScriptIsInvulnerableToMove
{
/// <summary>
/// This function allows a script to make its owner invulnerable to an incoming move.
/// </summary>
void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable);
}
/// <summary>
/// This interface allows scripts to run when a move misses its target.
/// </summary>
public interface IScriptOnMoveMiss
{
/// <summary>
/// This function allows a script to run when a move misses its target. This is used for moves
/// that have a secondary effect that should run even if the move misses, such as Spore.
/// </summary>
void OnMoveMiss(IExecutingMove move, IPokemon target);
}
/// <summary>
/// This interface allows scripts to modify the accuracy modifier of a move.
/// </summary>
public interface IScriptChangeAccuracyModifier
{
/// <summary>
/// This function allows a script to modify the accuracy of a move used. This value represents
/// the percentage accuracy, so anything above 100% will make it always hit.
/// </summary>
void ChangeAccuracyModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier);
}
/// <summary>
/// This interface allows scripts to change the critical stage of a move.
/// </summary>
public interface IScriptChangeCriticalStage
{
/// <summary>
/// This function allows a script to change the critical stage of the move used.
/// </summary>
void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage);
}
/// <summary>
/// This interface allows scripts to change the damage modifier of a critical hit.
/// </summary>
public interface IScriptChangeCriticalModifier
{
/// <summary>
/// This function allows a script to change the damage modifier of a critical hit. This will only
/// run when a hit is critical.
/// </summary>
void ChangeCriticalModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier);
}
/// <summary>
/// This interface allows scripts to change the STAB (Same Type Attack Bonus) modifier.
/// </summary>
public interface IScriptChangeStabModifier
{
/// <summary>
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
/// occurs when the user has the move type as one of its own types.
/// </summary>
void ChangeStabModifier(IExecutingMove executingMove, IPokemon target, byte hitNumber, bool isStab,
ref float modifier);
}
/// <summary>
/// This interface allows scripts to change the effective base power of a move.
/// </summary>
public interface IScriptChangeBasePower
{
/// <summary>
/// This function allows a script to change the effective base power of a move hit.
/// </summary>
void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref ushort basePower);
}