Adds script hooks, bug fix for empty ScriptIterator
This commit is contained in:
parent
74996d96b0
commit
cb2b566388
|
@ -1,36 +1,495 @@
|
|||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.Models.Choices;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||
|
||||
/// <summary>
|
||||
/// The script class is used to make changes to how a battle executes, without requiring hardcoded
|
||||
/// changes. This allows for easily defining generational differences, and add effects that the
|
||||
/// developer might require.
|
||||
/// </summary>
|
||||
public abstract class Script
|
||||
{
|
||||
private bool _markedForDeletion;
|
||||
private int _suppressCount;
|
||||
|
||||
/// <summary>
|
||||
/// The name of a script is its unique identifier. This should generally be set on load, and be
|
||||
/// the same as the key that was used to load it.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
public bool MarkForDeletion() => _markedForDeletion = true;
|
||||
public bool IsMarkedForDeletion() => _markedForDeletion;
|
||||
public int SuppressCount() => _suppressCount;
|
||||
public bool IsSuppressed() => _suppressCount > 0;
|
||||
|
||||
/// <summary>
|
||||
/// A script can be suppressed by other scripts. If a script is suppressed by at least one script
|
||||
/// we will not execute its methods. This should return the number of suppressions on the script.
|
||||
/// </summary>
|
||||
public int SuppressCount => _suppressCount;
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to check if there is at least one suppression on the script
|
||||
/// </summary>
|
||||
public bool IsSuppressed => _suppressCount > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a suppression. This makes the script not run anymore. Note that adding this should also
|
||||
/// remove the suppression later.
|
||||
///
|
||||
/// A common pattern for this is to run this in the <see cref="OnInitialize"/> and remove it in the
|
||||
/// <see cref="OnRemove"/> function.
|
||||
/// </summary>
|
||||
public void Suppress() => _suppressCount++;
|
||||
|
||||
/// <summary>
|
||||
/// Removes a suppression. This allows the script to run again (provided other scripts are not
|
||||
/// suppressing it). Note that running this should only occur if <see cref="Suppress"/> was called earlier
|
||||
/// </summary>
|
||||
public void Unsuppress() => _suppressCount--;
|
||||
|
||||
/// <summary>
|
||||
/// This function is ran when a volatile effect is added while that volatile effect already is
|
||||
/// in place. Instead of adding the volatile effect twice, it will execute this function instead.
|
||||
/// </summary>
|
||||
public virtual void Stack()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||
/// </summary>
|
||||
public virtual void OnRemove()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is ran when this script starts being in effect.
|
||||
/// </summary>
|
||||
public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary<StringKey, object> parameters)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
||||
/// something has happened during a turn.
|
||||
/// </summary>
|
||||
public virtual void OnBeforeTurnStart(ITurnChoice choice)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows you to modify the effective speed of the Pokemon. This is run before
|
||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
|
||||
/// </summary>
|
||||
public virtual void ChangeSpeed(ITurnChoice choice, ref uint speed)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows you to modify the effective priority of the Pokemon. This is run before
|
||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
|
||||
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
|
||||
/// </summary>
|
||||
public virtual void ChangePriority(IMoveChoice choice, ref sbyte priority)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows you to change the move that is used during execution. This is useful for
|
||||
/// moves such as metronome, where the move chosen actually differs from the move used.
|
||||
/// </summary>
|
||||
public virtual void ChangeMove(IMoveChoice choice, ref string moveName)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows you to change a move into a multi-hit move. The number of hits set here
|
||||
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
|
||||
/// first hit.
|
||||
/// </summary>
|
||||
public virtual void ChangeNumberOfHits(IMoveChoice choice, ref byte numberOfHits)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows you to prevent a move from running. If this gets set to true, the move
|
||||
/// ends execution here. No PP will be decreased in this case.
|
||||
/// </summary>
|
||||
public virtual void PreventMove(IExecutingMove move, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
|
||||
/// and fail events get triggered.
|
||||
/// </summary>
|
||||
public virtual void FailMove(IExecutingMove move, ref bool fail)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Similar to <see cref="PreventMove"/>. This function will also stop execution of the move, but
|
||||
/// PP will still be decreased.
|
||||
/// </summary>
|
||||
public virtual void StopBeforeMove(IExecutingMove move, ref bool stop)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function runs just before the move starts its execution.
|
||||
/// </summary>
|
||||
public virtual void OnBeforeMove(IExecutingMove move)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
public virtual void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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 a script to block an outgoing move from being critical.
|
||||
/// </summary>
|
||||
public virtual void BlockCriticalHit(IExecutingMove move, IPokemon target, 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, 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 ChangeAccuracy(IExecutingMove move, IPokemon target, byte hit, ref byte accuracy)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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,
|
||||
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 byte 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
|
||||
/// stat boosts will still be applied.
|
||||
/// </summary>
|
||||
public virtual void BypassDefensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to bypass offensive stat boosts for a move hit.
|
||||
/// If this is true, the damage will be calculated as if the user has no negative offensive stat boosts. Positive
|
||||
/// stat boosts will still be applied.
|
||||
/// </summary>
|
||||
public virtual void BypassOffensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
||||
/// </summary>
|
||||
public virtual void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
||||
/// </summary>
|
||||
public virtual void ChangeDefensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to change the raw modifier we retrieved from the stats of the
|
||||
/// defender and attacker. The default value is the offensive stat divided by the defensive stat.
|
||||
/// </summary>
|
||||
public virtual void ChangeDamageStatModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to apply a raw multiplier to the damage done by a move.
|
||||
/// </summary>
|
||||
public virtual void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to modify the outgoing damage done by a move.
|
||||
/// </summary>
|
||||
public virtual void ChangeDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script to modify the incoming damage done by a move.
|
||||
/// </summary>
|
||||
public virtual void ChangeIncomingDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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.
|
||||
/// </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.
|
||||
/// </summary>
|
||||
public virtual void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted,
|
||||
ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script attached to a Pokemon or its parents to modify the amount by
|
||||
/// which the stat boost will change. If the stat boost is done by the user itself, self
|
||||
/// inflicted will be true, otherwise it will be false.
|
||||
/// </summary>
|
||||
public virtual void ChangeStatBoostChange(IPokemon target, Statistic stat, bool selfInflicted, ref sbyte amount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
|
||||
/// secondary effect. This means the move will still hit and do damage, but not trigger its
|
||||
/// secondary effect. Note that this function is not called for status moves.
|
||||
/// </summary>
|
||||
public virtual void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script attached to a move or its parents to change the chance the
|
||||
/// secondary effect of a move will trigger. The chance is depicted in percentage here, so
|
||||
/// changing this to above or equal to 100 will make it always hit, while setting it to equal or
|
||||
/// below 0 will make it never hit.
|
||||
/// </summary>
|
||||
public virtual void ChangeEffectChance(IExecutingMove move, IPokemon target, byte hit, ref float chance)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows a script attached to a Pokemon or its parents to change the chance the
|
||||
/// secondary effect of an incoming move will trigger. The chance is depicted in percentage here,
|
||||
/// so changing this to above or equal to 100 will make it always hit, while setting it to equal
|
||||
/// or below 0 will make it never hit.
|
||||
/// </summary>
|
||||
public virtual void ChangeIncomingEffectChance(IExecutingMove move, IPokemon target, ref float chance)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public virtual void OnAfterHits(IExecutingMove move, IPokemon target)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function prevents the Pokemon it is attached to from being able to switch out.
|
||||
/// </summary>
|
||||
public virtual void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows the prevention of switching for any opponent.
|
||||
/// </summary>
|
||||
public virtual void PreventOpponentSwitch(ISwitchChoice choice, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called on a move and its parents when the move fails.
|
||||
/// </summary>
|
||||
public virtual void OnFail(IPokemon pokemon)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called on a script when an opponent fails.
|
||||
/// </summary>
|
||||
/// <param name="pokemon"></param>
|
||||
public virtual void OnOpponentFail(IPokemon pokemon)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function allows preventing the running away of the Pokemon its attached to
|
||||
/// </summary>
|
||||
public virtual void PreventSelfRunAway(IFleeChoice choice, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function prevents a Pokemon on another side than where its attached to from running away.
|
||||
/// </summary>
|
||||
public virtual void PreventOpponentRunAway(IFleeChoice choice, ref bool prevent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function id triggered on all scripts active in the battle after all choices have finished
|
||||
/// running. Note that choices are not active anymore here, so their scripts do not call this
|
||||
/// function.
|
||||
/// </summary>
|
||||
public virtual void OnEndTurn()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
|
||||
/// </summary>
|
||||
public virtual void OnDamage(IPokemon pokemon, DamageSource source, uint oldHealth, uint newHealth)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
|
||||
/// </summary>
|
||||
public virtual void OnFaint(IPokemon pokemon, DamageSource source)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
|
||||
/// the battlefield.
|
||||
/// </summary>
|
||||
public virtual void OnSwitchIn(IPokemon pokemon)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
|
||||
/// held item it had.
|
||||
/// </summary>
|
||||
public virtual void OnAfterHeldItemConsume(IPokemon pokemon, IItem item)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||
/// and allows for changing this amount of experience.
|
||||
/// </summary>
|
||||
public virtual void ChangeExperienceGained(IPokemon faintedPokemon, IPokemon winningPokemon, ref uint amount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||
/// and allows for making the experience be shared across multiple Pokemon.
|
||||
/// Amount is the modifier for how much experience is shared, with 1 being the default amount.
|
||||
/// </summary>
|
||||
public virtual void ShareExperience(IPokemon faintedPokemon, IPokemon winningPokemon, ref bool share,
|
||||
ref float amount)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is triggered on a battle and its parents when something attempts to change the
|
||||
/// weather, and allows for blocking the weather change.
|
||||
/// </summary>
|
||||
public virtual void BlockWeatherChange(IBattle battle, ref bool block)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
|
||||
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
||||
/// example status effects that change capture rates.
|
||||
/// </summary>
|
||||
public virtual void ChangeCaptureRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PkmnLib.Dynamic.ScriptHandling;
|
||||
|
||||
public static class ScriptExecution
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void RunScriptHook(this IScriptSource source, Action<Script> hook)
|
||||
{
|
||||
var iterator = source.GetScripts();
|
||||
|
@ -10,6 +13,8 @@ public static class ScriptExecution
|
|||
if (container.IsEmpty)
|
||||
continue;
|
||||
var script = container.Script;
|
||||
if (script.IsSuppressed)
|
||||
continue;
|
||||
hook(script);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class ScriptIterator : IEnumerable<ScriptContainer>
|
|||
_scripts = scripts;
|
||||
}
|
||||
|
||||
bool IncrementToNext()
|
||||
private bool IncrementToNext()
|
||||
{
|
||||
if (_index != -1)
|
||||
{
|
||||
|
@ -51,6 +51,8 @@ public class ScriptIterator : IEnumerable<ScriptContainer>
|
|||
/// <inheritdoc />
|
||||
public IEnumerator<ScriptContainer> GetEnumerator()
|
||||
{
|
||||
if (_scripts.Count == 0)
|
||||
yield break;
|
||||
while (IncrementToNext())
|
||||
{
|
||||
var current = _scripts[_index];
|
||||
|
|
|
@ -36,6 +36,7 @@ public class DamageCalculatorTests
|
|||
// a Garchomp with an effective Defense stat of 163
|
||||
defender.Setup(x => x.BoostedStats).Returns(new StatisticSet<uint>(
|
||||
1, 1, 163, 1, 1, 1));
|
||||
defender.Setup(x => x.GetScripts()).Returns(new ScriptIterator([]));
|
||||
|
||||
var useMove = new Mock<IMoveData>();
|
||||
// Ice Fang (an Ice-type physical move with a power of 65)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
|
@ -23,7 +22,7 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
var levelModifier = (2.0f * executingMove.User.Level) / 5.0f + 2.0f;
|
||||
var basePower = (float)hitData.BasePower;
|
||||
var statModifier = GetStatModifier(executingMove, target, hitNumber, hitData);
|
||||
var damageModifier = GetDamageModifier(executingMove, target, hitNumber, hitData);
|
||||
var damageModifier = GetDamageModifier(executingMove, target, hitNumber);
|
||||
|
||||
var floatDamage = MathF.Floor(levelModifier * basePower);
|
||||
floatDamage = MathF.Floor(floatDamage * statModifier);
|
||||
|
@ -35,7 +34,8 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
if (hitData.IsCritical)
|
||||
{
|
||||
var critModifier = 1.5f;
|
||||
// TODO: script hook to change the critical modifier
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeCriticalModifier(executingMove, target, hitNumber, ref critModifier));
|
||||
floatDamage = MathF.Floor(floatDamage * critModifier);
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,10 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
< 1 => 1,
|
||||
_ => (uint)floatDamage
|
||||
};
|
||||
// TODO: script hook to modify the damage
|
||||
// TODO: script hook to modify incoming damage
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeDamage(executingMove, target, hitNumber, ref damage));
|
||||
target.RunScriptHook(script =>
|
||||
script.ChangeIncomingDamage(executingMove, target, hitNumber, ref damage));
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
@ -76,18 +78,19 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
if (executingMove.UseMove.Category == MoveCategory.Status)
|
||||
return 0;
|
||||
var basePower = hitData.BasePower;
|
||||
// TODO: script hook to modify the base power
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeBasePower(executingMove, target, hitNumber, ref basePower));
|
||||
return basePower;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[SuppressMessage("ReSharper", "UnreachableSwitchArmDueToIntegerAnalysis")] // disabled because of the TODO
|
||||
public bool IsCritical(IBattle battle, IExecutingMove executingMove, IPokemon target, byte hitNumber)
|
||||
{
|
||||
if (executingMove.UseMove.Category == MoveCategory.Status)
|
||||
return false;
|
||||
byte critStage = 0;
|
||||
// TODO: script hook to modify the crit stage
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeCriticalStage(executingMove, target, hitNumber, ref critStage));
|
||||
|
||||
var random = battle.Random;
|
||||
return critStage switch
|
||||
|
@ -115,13 +118,15 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
// move is critical, and the target has a defensive stat boost of > 0, but a script is
|
||||
// allowed to change this.
|
||||
var bypassDefense = hitData.IsCritical && target.StatBoost.GetStatistic(defensive) > 0;
|
||||
// TODO: script hook
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.BypassDefensiveStatBoosts(executingMove, target, hitNumber, ref bypassDefense));
|
||||
|
||||
// Check if we can bypass the offensive stat boost on the user. We default to this if the
|
||||
// move is critical, and the user has an offensive stat boost of < 0, but a script is
|
||||
// allowed to change this.
|
||||
var bypassOffense = hitData.IsCritical && executingMove.User.StatBoost.GetStatistic(offensive) < 0;
|
||||
// TODO: script hook
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.BypassOffensiveStatBoosts(executingMove, target, hitNumber, ref bypassOffense));
|
||||
|
||||
var userStats = executingMove.User.BoostedStats;
|
||||
if (bypassOffense)
|
||||
|
@ -132,11 +137,15 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
if (bypassDefense)
|
||||
targetStats = target.FlatStats;
|
||||
var defensiveStat = targetStats.GetStatistic(defensive);
|
||||
|
||||
// TODO: script hook to modify the stats above
|
||||
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeOffensiveStatValue(executingMove, target, hitNumber, ref offensiveStat));
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeDefensiveStatValue(executingMove, target, hitNumber, ref defensiveStat));
|
||||
|
||||
var modifier = (float)offensiveStat / defensiveStat;
|
||||
// TODO: script hook to modify the modifier
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeDamageStatModifier(executingMove, target, hitNumber, ref modifier));
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
@ -145,12 +154,12 @@ public class Gen7DamageCalculator(bool hasRandomness) : IDamageCalculator
|
|||
/// Gets the damage modifier. This is a value that defaults to 1.0, but can be modified by scripts
|
||||
/// to apply a raw modifier to the damage.
|
||||
/// </summary>
|
||||
private static float GetDamageModifier(IExecutingMove executingMove, IPokemon target, byte hitNumber,
|
||||
IHitData hitData)
|
||||
private static float GetDamageModifier(IExecutingMove executingMove, IPokemon target, byte hitNumber)
|
||||
{
|
||||
var modifier = 1.0f;
|
||||
|
||||
// TODO: script hook to modify the modifier
|
||||
executingMove.RunScriptHook(script =>
|
||||
script.ChangeDamageModifier(executingMove, target, hitNumber, ref modifier));
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue