using PkmnLib.Dynamic.Libraries; using PkmnLib.Dynamic.Models; using PkmnLib.Dynamic.Models.Choices; using PkmnLib.Dynamic.ScriptHandling.Registry; using PkmnLib.Static; using PkmnLib.Static.Utils; namespace PkmnLib.Dynamic.ScriptHandling; /// /// 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. /// public abstract class Script { private bool _markedForDeletion; private int _suppressCount; /// /// The name of a script is its unique identifier. /// If not overridden, this will resolve the name from the of the /// script. /// public virtual StringKey Name => this.ResolveName(); public bool MarkForDeletion() => _markedForDeletion = true; public bool IsMarkedForDeletion() => _markedForDeletion; /// /// 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. /// public int SuppressCount => _suppressCount; /// /// Helper function to check if there is at least one suppression on the script /// public bool IsSuppressed => _suppressCount > 0; /// /// 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 and remove it in the /// function. /// public void Suppress() => _suppressCount++; /// /// 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 was called earlier /// public void Unsuppress() => _suppressCount--; /// /// 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. /// public virtual void Stack() { } /// /// This function is ran when this script stops being in effect, and is removed from its owner. /// public virtual void OnRemove() { } /// /// This function is ran when this script starts being in effect. /// public virtual void OnInitialize(IDynamicLibrary library, IReadOnlyDictionary? parameters) { } /// /// 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. /// public virtual void OnBeforeTurnStart(ITurnChoice choice) { } /// /// 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. /// public virtual void ChangeSpeed(ITurnChoice choice, ref uint speed) { } /// /// 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. /// public virtual void ChangePriority(IMoveChoice choice, ref sbyte priority) { } /// /// 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. /// public virtual void ChangeMove(IMoveChoice choice, ref StringKey moveName) { } /// /// 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. /// public virtual void ChangeNumberOfHits(IMoveChoice choice, ref byte numberOfHits) { } /// /// 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. /// public virtual void PreventMove(IExecutingMove move, ref bool prevent) { } /// /// This function makes the move fail. If the fail field gets set to true, the move ends execution, /// and fail events get triggered. /// public virtual void FailMove(IExecutingMove move, ref bool fail) { } /// /// Similar to . This function will also stop execution of the move, but /// PP will still be decreased. /// public virtual void StopBeforeMove(IExecutingMove move, ref bool stop) { } /// /// This function runs just before the move starts its execution. /// public virtual void OnBeforeMove(IExecutingMove move) { } /// /// 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. /// public virtual void FailIncomingMove(IExecutingMove move, IPokemon target, ref bool fail) { } /// /// This function allows a script to make its owner invulnerable to an incoming move. /// public virtual void IsInvulnerableToMove(IExecutingMove move, IPokemon target, ref bool invulnerable) { } /// /// 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. /// public virtual void OnMoveMiss(IExecutingMove move, IPokemon target) { } /// /// This function allows the script to change the actual type that is used for the move on a target. /// public virtual void ChangeMoveType(IExecutingMove move, IPokemon target, byte hit, ref TypeIdentifier moveType) { } /// /// This function allows the script to change how effective a move is on a target. /// public virtual void ChangeEffectiveness(IExecutingMove move, IPokemon target, byte hit, ref float effectiveness) { } /// /// This function allows a script to block an outgoing move from being critical. /// public virtual void BlockCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block) { } /// /// This function allows a script to block an incoming move from being critical. /// public virtual void BlockIncomingCriticalHit(IExecutingMove move, IPokemon target, byte hit, ref bool block) { } /// /// 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. /// public virtual void ChangeAccuracy(IExecutingMove move, IPokemon target, byte hit, ref byte accuracy) { } /// /// This function allows a script to change the critical stage of the move used. /// public virtual void ChangeCriticalStage(IExecutingMove move, IPokemon target, byte hit, ref byte stage) { } /// /// This function allows a script to change the damage modifier of a critical hit. This will only /// run when a hit is critical. /// public virtual void ChangeCriticalModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier) { } /// /// 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. /// public virtual void ChangeStabModifier(IExecutingMove executingMove, IPokemon target, byte hitNumber, ref float modifier) { } /// /// This function allows a script to change the effective base power of a move hit. /// public virtual void ChangeBasePower(IExecutingMove move, IPokemon target, byte hit, ref byte basePower) { } /// /// 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. /// public virtual void BypassDefensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass) { } /// /// 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. /// public virtual void BypassOffensiveStatBoosts(IExecutingMove move, IPokemon target, byte hit, ref bool bypass) { } /// /// This function allows a script to change the actual offensive stat values used when calculating damage /// public virtual void ChangeOffensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value) { } /// /// This function allows a script to change the actual defensive stat values used when calculating damage. /// public virtual void ChangeDefensiveStatValue(IExecutingMove move, IPokemon target, byte hit, ref uint value) { } /// /// 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. /// public virtual void ChangeDamageStatModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier) { } /// /// This function allows a script to apply a raw multiplier to the damage done by a move. /// public virtual void ChangeDamageModifier(IExecutingMove move, IPokemon target, byte hit, ref float modifier) { } /// /// This function allows a script to modify the outgoing damage done by a move. /// public virtual void ChangeDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) { } /// /// This function allows a script to modify the incoming damage done by a move. /// public virtual void ChangeIncomingDamage(IExecutingMove move, IPokemon target, byte hit, ref uint damage) { } /// /// This function triggers when an incoming hit happens. This triggers after the damage is done, /// but before the secondary effect of the move happens. /// public virtual void OnIncomingHit(IExecutingMove move, IPokemon target, byte hit) { } /// /// This function triggers when an opponent on the field faints. /// public virtual void OnOpponentFaints(IExecutingMove move, IPokemon target, byte hit) { } /// /// This function allows a script attached to a Pokemon or its parents to prevent stat boost /// changes on that Pokemon. /// public virtual void PreventStatBoostChange(IPokemon target, Statistic stat, sbyte amount, bool selfInflicted, ref bool prevent) { } /// /// 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. /// public virtual void ChangeStatBoostChange(IPokemon target, Statistic stat, bool selfInflicted, ref sbyte amount) { } /// /// 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. /// public virtual void PreventSecondaryEffect(IExecutingMove move, IPokemon target, byte hit, ref bool prevent) { } /// /// 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. /// public virtual void ChangeEffectChance(IExecutingMove move, IPokemon target, byte hit, ref float chance) { } /// /// 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. /// public virtual void ChangeIncomingEffectChance(IExecutingMove move, IPokemon target, byte hit, ref float chance) { } /// /// 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. /// public virtual void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit) { } /// /// This function triggers on a move or its parents when all hits on a target are finished. /// public virtual void OnAfterHits(IExecutingMove move, IPokemon target) { } /// /// This function prevents the Pokemon it is attached to from being able to switch out. /// public virtual void PreventSelfSwitch(ISwitchChoice choice, ref bool prevent) { } /// /// This function allows the prevention of switching for any opponent. /// public virtual void PreventOpponentSwitch(ISwitchChoice choice, ref bool prevent) { } /// /// This function is called on a move and its parents when the move fails. /// public virtual void OnFail(IPokemon pokemon) { } /// /// This function is called on a script when an opponent fails. /// /// public virtual void OnOpponentFail(IPokemon pokemon) { } /// /// This function allows preventing the running away of the Pokemon its attached to /// public virtual void PreventSelfRunAway(IFleeChoice choice, ref bool prevent) { } /// /// This function prevents a Pokemon on another side than where its attached to from running away. /// public virtual void PreventOpponentRunAway(IFleeChoice choice, ref bool prevent) { } /// /// 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. /// public virtual void OnEndTurn() { } /// /// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage. /// public virtual void OnDamage(IPokemon pokemon, DamageSource source, uint oldHealth, uint newHealth) { } /// /// This function is triggered on a Pokemon and its parents when the given Pokemon faints. /// public virtual void OnFaint(IPokemon pokemon, DamageSource source) { } /// /// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into /// the battlefield. /// public virtual void OnSwitchIn(IPokemon pokemon) { } /// /// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the /// held item it had. /// public virtual void OnAfterHeldItemConsume(IPokemon pokemon, IItem item) { } /// /// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience, /// and allows for changing this amount of experience. /// public virtual void ChangeExperienceGained(IPokemon faintedPokemon, IPokemon winningPokemon, ref uint amount) { } /// /// 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. /// public virtual void ShareExperience(IPokemon faintedPokemon, IPokemon winningPokemon, ref bool share, ref float amount) { } /// /// This function is triggered on a battle and its parents when something attempts to change the /// weather, and allows for blocking the weather change. /// public virtual void BlockWeatherChange(IBattle battle, ref bool block) { } /// /// 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. /// public virtual void ChangeCaptureRateBonus(IPokemon pokemon, IItem pokeball, ref byte modifier) { } }