#ifndef POKEPLATINUM_BATTLE_BATTLE_LIB_H #define POKEPLATINUM_BATTLE_BATTLE_LIB_H #include "constants/battle.h" #include "constants/sound.h" #include "struct_decls/battle_system.h" #include "battle/battle_context.h" #include "battle/battle_message.h" #include "battle/battle_mon.h" #include "battle/btlcmd.h" #include "pokemon.h" enum CountAbilityMode { COUNT_ALL_BATTLERS_OUR_SIDE = 0, //< Count all the battlers on our side with the ability COUNT_ALIVE_BATTLERS_OUR_SIDE, //< Count all alive battlers on our side with the ability COUNT_ALL_BATTLERS_THEIR_SIDE, //< Count all the battlers on their side with the ability COUNT_ALIVE_BATTLERS_THEIR_SIDE, //< Count all alive battlers on their side with the ability COUNT_ALIVE_BATTLERS_THEIR_SIDE_FLAG, //< Return a mask of alive battlers on their side with the ability COUNT_ALL_BATTLERS, //< Count all battlers on the battlefield with the ability COUNT_ALL_BATTLERS_EXCEPT_ME, //< Count all battlers except for me which have the ability COUNT_ALL_BATTLERS_EXCEPT_ME_RETURN_BATTLER, //< Return the battler which has the ability COUNT_ALIVE_BATTLERS, //< Count all alive battlers on the battlefield with the ability COUNT_ALIVE_BATTLERS_EXCEPT_ME, //< Count all alive battlers except for me which have the ability }; /** * @brief Initialize a BattleMon from the Pokemon in the given battler's party, * from the given party slot. * * @param battleSys * @param battleCtx * @param battler The battler whose party will be read from * @param partySlot The slot in the party to retrieve */ void BattleSystem_InitBattleMon(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); /** * @brief Reload a BattleMon from the given battler's party, from the given * party slot. * * Specifically, this will only reload the following fields: * * - battle stats (attack, defense, etc.) * - level * - friendship * - move known in each slot * - total experience * * @param battleSys * @param battleCtx * @param battler The battler whose party will be read from * @param partySlot The slot in the party to retrieve */ void BattleSystem_ReloadPokemon(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); /** * @brief Load a script file from the specified NARC. * * @param battleCtx * @param narc Which NARC to open for the script * @param file Which file in the NARC to load */ void BattleSystem_LoadScript(BattleContext *battleCtx, int narc, int file); /** * @brief Load a script file from the specified NARC and invoke it as a call, * returning to the previous script once finished processing. * * @param battleCtx * @param narc Which NARC to open for the script * @param file Which file in the NARC to load */ void BattleSystem_CallScript(BattleContext *battleCtx, int narc, int file); /** * @brief Pop a script from the stack, if one is present, and load it for * execution. * * If a script is loaded, then this will also pop a value from the script cursor * stack and set the internal script cursor to that value. * * @param battleCtx * @return TRUE if there are no contents in the stack to be loaded; FALSE if * a stack was popped and should be executed. */ BOOL BattleSystem_PopScript(BattleContext *battleCtx); /** * @brief Enqueue a value onto the given IO queue for the battler. * * @param battleCtx * @param id ID of the queue to enqueue the value onto * @param battler Battler for which the value should be enqueued * @param val Value which will be enqueued */ void BattleIO_EnqueueVal(BattleContext *battleCtx, int id, int battler, int val); /** * @brief Dequeue a specific value from the given IO queue for the battler. * * @param battleCtx * @param id ID of the queue to dequeue the value from * @param battler Battler for which the value should be dequeued * @param val Value which will be dequeued */ void BattleIO_DequeueVal(BattleContext *battleCtx, int id, int battler, int val); /** * @brief Determine if the Battle IO queue is empty (i.e., there are no pending * actions to be executed for any players hooked into this particular battle). * * As a side effect, if the queue is empty, then this routine will also set the * link-battle timeout counter back to 0. * * @param battleCtx * @return TRUE if the queue has no remaining actions; FALSE otherwise. */ BOOL BattleIO_QueueIsEmpty(BattleContext *battleCtx); /** * @brief Increments the link-battle timeout counter. * * If the counter exceeds the maximum timeout value (1800, ~= 30 seconds), * then the link will be terminated with an error state. * * @param battleCtx */ void BattleIO_UpdateTimeout(BattleContext *battleCtx); /** * @brief Clear the battle IO queue of all data. * * @param battleCtx * @param battler */ void BattleIO_ClearBuffer(BattleContext *battleCtx, int battler); /** * @brief Get a data field value from a given battler. * * @param battleCtx * @param battler The requested battler * @param paramID ID of the field to retrieve from the battler * @param[out] outBuf Buffer output for non-integral values (i.e., strings) * @return The value of the data field, or 0 if not recognized or output is * presented via outBuf */ int BattleMon_Get(BattleContext *battleCtx, int battler, enum BattleMonParam paramID, void *buf); /** * @brief Set a data field value for a given battler. * * @param battleCtx * @param battler The requested battler * @param paramID ID of the field to retrieve from the battler * @param buf Buffer input for the value to be set */ void BattleMon_Set(BattleContext *battleCtx, int battler, enum BattleMonParam paramID, const void *buf); /** * @brief Add a value to a battler's data field. * * This is just a convenience wrapper around BattleMon_AddVal. * * @param battleCtx * @param battler The battler whose data should be modified * @param paramID ID of the field which should be modified * @param val Value to be added to the battler's data field */ void Battler_AddVal(BattleContext *battleCtx, int battler, enum BattleMonParam paramID, int val); /** * @brief Add a value to a Pokemon's data field. * * @param mon * @param paramID ID of the field which should be modified * @param val Value to be added to the Pokemon's data field */ void BattleMon_AddVal(BattleMon *mon, enum BattleMonParam paramID, int val); /** * @brief Compare the speed of two battlers and determine which of them should * move first. * * @param battleSys * @param battleCtx * @param battler1 * @param battler2 * @param ignoreQuickClaw If set to TRUE, the Quick Claw and Custap Berry * flags will NOT be set after determining if they * should activate. * @return A value representing the speed-ordering of the two battlers, * relative to the first of the two. See enum CompareSpeedResult. */ u8 BattleSystem_CompareBattlerSpeed(BattleSystem *battleSys, BattleContext *battleCtx, int battler1, int battler2, BOOL ignoreQuickClaw); /** * @brief Clear the flag denoting that a battler (or its partner) are due to * gain experience. * * @param battleCtx * @param battler The battler who should not gain experience. */ void BattleSystem_ClearSideExpGain(BattleContext *battleCtx, int battler); /** * @brief Flag a given battler as due to gain experience. * * If the battle involves an AI partner, then this routine will not touch the * flag for the opposing side of the battle. * * @param battleSys * @param battleCtx * @param battler The battler who should gain experience. */ void BattleSystem_FlagBattlerExpGain(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Trigger a primary effect on the current move. * * @param battleSys * @param battleCtx * @param[out] effect Output parameter for the effect to be loaded. * @return TRUE if an effect should be loaded, FALSE if the result should be * ignored. */ BOOL BattleSystem_TriggerPrimaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *effect); /** * @brief Trigger a secondary effect on the current move. * * @param battleSys * @param battleCtx * @param[out] effect Output parameter for the effect to be loaded. * @return TRUE if an effect should be loaded, FALSE if the result should be * ignored. */ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *effect); /** * @brief Find the defender for the move. * * The defender can be chosen at random in certain scenarios, but only while * the randomize parameter is TRUE: * * 1. The move's range is Me First * 2. The move's range is Acupressure * 3. The move is a standard single-target attack, e.g., Thunderbolt * * @param battleSys * @param battleCtx * @param attacker * @param move The move being used * @param randomize If TRUE, permit randomization of target-selection for certain moves * @param inRange An input range to prefer for the move over whatever range is set on the move data * @return The chosen defender for the move */ int BattleSystem_Defender(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, u16 move, BOOL randomize, int inRange); /** * @brief Check for redirection abilities given an attacker using a certain move. * * This routine will update the appropriate flags and the current target if the * used move is Electric- or Water-type, has single-target range, and at least * one other battler on the field has Lightning Rod or Storm Drain, respectively. * * @param battleSys * @param battleCtx * @param attacker * @param move */ void BattleSystem_CheckRedirectionAbilities(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, u16 move); /** * @brief Trigger a redirection ability's effect and load the appropriate * subscript for execution. * * @param battleSys * @param battleCtx * @return TRUE if a subscript was loaded and should be executed for the effect, * FALSE otherwise. */ BOOL BattleSystem_TriggerRedirectionAbilities(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Copy the given battler back to its backing Pokemon structure in the party. * * @param battleSys * @param battleCtx * @param battler */ void BattleMon_CopyToParty(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Locks the battler into their current move. * * @param battleSys * @param battleCtx * @param battler */ void Battler_LockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Unlocks the battler's future move choices. * * This will also, as a convenience, toggle off the flags for Bide and semi- * invulnerable moves and reset the counters for Rollout and Fury Cutter. * * @param battleSys * @param battleCtx * @param battler */ void Battler_UnlockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Calculate the status effect value for a battler's non-volatile * condition, if any. * * @param battleCtx * @param battler * @return A value representing the battler's status non-volatile status. */ enum BattleAnimation Battler_StatusCondition(BattleContext *battleCtx, int battler); /** * @brief Check if the given trainer has a trainer message to be shown. * * If a trainer message is to be shown, then the respective battler will be * updated with the appropriate flag, and battleCtx->msgTemp will be loaded * with the type of message to be shown. * * @param battleSys * @param battleCtx * @return TRUE if a message should be shown, else FALSE. */ BOOL BattleSystem_CheckTrainerMessage(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Initialize the BattleContext structure with start-of-turn state. * * @param battleCtx */ void BattleContext_Init(BattleContext *battleCtx); /** * @brief Initialize standard counters for the BattleContext structure. * * @param battleSys * @param battleCtx */ void BattleContext_InitCounters(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Update relevant buffers for a battler after a switch. * * This handles all of the logic for what effects are zero'd out due to a * switch, as well as what effects are transferred across a switch due to * Baton Pass. * * This routine will update the battler's chosen command to be MOVE_END, which * functionally ends their turn. * * @param battleSys * @param battleCtx * @param battler The switching battler */ void BattleSystem_UpdateAfterSwitch(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Cleanup lingering state according to the given battler. * * This routine will clean up any volatile status values dependent on the * fainted battler (Mean Look, Attract, Bind), all move effects and single-turn * flags, and extra data associated with the battler that is elsewhere in the * battle context struct (e.g., buffers for Conversion 2, Sketch, and Mirror * Move). * * @param battleSys * @param battleCtx * @param battler */ void BattleSystem_CleanupFaintedMon(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Clear single-turn flags and buffered values in setup for the next turn. * * @param battleSys * @param battleCtx */ void BattleSystem_SetupNextTurn(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Compute which moves are invalid for the battler to use, performing * checks according to the input opcode mask. * * The following op-codes are supported in the input mask: * - CHECK_INVALID_NO_MOVE -> flag empty move-slots * - CHECK_INVALID_NO_PP -> flag moves with no remaining PP * - CHECK_INVALID_DISABLED -> flag the battler's Disabled move * - CHECK_INVALID_TORMENTED -> flag the battler's last-used move * - CHECK_INVALID_TAUNTED -> flag any of the battler's moves with 0 power * - CHECK_INVALID_IMPRISONED -> flag any of the battler's Imprisoned moves * - CHECK_INVALID_GRAVITY -> flag any of the battler's moves which fail in high gravity * - CHECK_INVALID_HEAL_BLOCK -> flag any of the battler's healing moves * - CHECK_INVALID_CHOICE_ITEM -> flag any of the battler's moves other than their choice-locked move * * @param battleSys * @param battleCtx * @param battler The battler choosing their move * @param invalidMoves An initial mask of moves which should be deemed invalid * @param opMask An input opcode mask determining which checks should be * made for move validity * @return A bitmask denoting which of the battler's move slots are invalid for * selection */ int BattleSystem_CheckInvalidMoves(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int invalidMoves, int opMask); /** * @brief Determine if a battler can use the move in the given slot, populating * the input BattleMessage struct with a message to display if they cannot. * * @param battleSys * @param battleCtx * @param battler * @param moveSlot The slot of the move that the battler is trying to use * @param[out] msgOut An output message for display to the player * @return TRUE if the move can be used, FALSE if it cannot */ BOOL BattleSystem_CanUseMove(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int moveSlot, BattleMessage *msgOut); /** * @brief Determine which slot of the Pokemon's moveset contains a given move. * * @param mon * @param move * @return The slot of the Pokemon's moveset containing the input move */ int Battler_SlotForMove(BattleMon *mon, u16 move); /** * @brief Apply type-chart effectiveness for a given move against its target. * * This encapsulates the following multipliers: * - Same-Type Attack Bonus (and its modification by the ability Adaptability) * - Super/Not Very Effective multipliers for each of the defender's types * - Type-effectiveness overrides for effects like Iron Ball, Roost, and Miracle Eye * - Wonder Guard's override for moves that are not super-effective * - Expert Belt's multiplier for super-effective moves * - Filter and Solid Rock's multipliers for defenders taking super-effective damage * - Tinted Lens's multiplier for defenders taking not-very-effective damage * * The move status mask will also be updated with the correct flags. * * @param battleSys * @param battleCtx * @param move * @param inType If this is non-zero, then it will be regarded as the move's type * @param attacker * @param defender * @param damage Pre-calculated starting damage value * @param[out] moveStatusMask * @return Damage value after applying the type-chart and related multipliers */ int BattleSystem_ApplyTypeChart(BattleSystem *battleSys, BattleContext *battleCtx, int move, int inType, int attacker, int defender, int damage, u32 *moveStatusMask); /** * @brief Calculate the effectiveness mask of the given move. * * @param battleCtx * @param move * @param inType If this is non-zero, then it will be regarded as the move's type * @param attackerAbility * @param defenderAbility * @param defenderItemEffect * @param defenderType1 * @param defenderType2 * @param[out] moveStatusMask */ void BattleSystem_CalcEffectiveness(BattleContext *battleCtx, int move, int inType, int attackerAbility, int defenderAbility, int defenderItemEffect, int defenderType1, int defenderType2, u32 *moveStatusMask); /** * @brief Check if a battler's move failed to execute for the turn. * * @param battleCtx * @param battler * @return TRUE if the battler's move failed to execute for the turn, FALSE * otherwise. */ BOOL BattleContext_MoveFailed(BattleContext *battleCtx, int battler); /** * @brief Count the number of targets hit by a move. * * @param battleSys * @param battleCtx * @param sameSide If TRUE, only the battlers on the same side of the field as * the defender will be counted. If FALSE, all battlers will * be counted. * @param defender * @return The number of battlers hit by the move. */ u8 BattleSystem_CountAliveBattlers(BattleSystem *battleSys, BattleContext *battleCtx, BOOL sameSide, int defender); /** * @brief Apply a nickname tag to the given battler for message-formatting. * * @param battleSys * @param battler * @return The battler + a nickname tag value. */ int BattleSystem_NicknameTag(BattleContext *battleSys, int battler); /** * @brief Get a battler's selected move for the turn, if any. * * @param battleCtx * @param battler * @return The battler's selected move for the turn. */ u16 Battler_SelectedMove(BattleContext *battleCtx, int battler); /** * @brief Count the number of instances of the given ability on the battlefield. * * @param battleSys * @param battleCtx * @param mode The behavior mode. See enum CountAbilityMode. * @param battler * @param ability * @return The number of battlers with the given ability matching the input * criteria; if the mode is one of *_FLAG, then the return value will instead * be a mask of the battlers matching the criteria. */ int BattleSystem_CountAbility(BattleSystem *battleSys, BattleContext *battleCtx, enum CountAbilityMode mode, int battler, int ability); /** * @brief Determine if a given move is a multi-turn move. * * @param battleCtx * @param move * @return TRUE if the move is a multi-turn move (one which has a charging * turn); FALSE if not */ BOOL Move_IsMultiTurn(BattleContext *battleCtx, int move); /** * @brief Access a particular entry in the type-matchup table. * * If the requested entry falls outside the bounds of the table, then a * random entry's data will instead be accessed. * * @param battleSys * @param idx The index of table entry to access. * @param[out] atkType Attacking type of the table entry. * @param[out] defType Defending type of the table entry. * @param[out] multi Multiplier for the type matchup. * @return TRUE if the requested entry was accessed; FALSE if the requested * entry falls outside the bounds of the table. */ BOOL BattleSystem_TypeMatchup(BattleSystem *battleSys, int idx, u8 *moveType, u8 *vsType, u8 *multi); /** * @brief Determine the total multiplier classification to use for an attacking * type against a pair of defending types. * * This routine centers 1x damage as a return value of 40. From there, the * multiplier varies by powers of 2: * - 1/4x -> 10 * - 1/2x -> 20 * - 1x -> 40 * - 2x -> 80 * - 4x -> 160 * * @param attackingType * @param defendingType1 * @param defendingType2 * @return The total multiplier of the attacking type against a defender with * the pair of types. */ int BattleSystem_TypeMatchupMultiplier(u8 attackingType, u8 defendingType1, u8 defendingType2); /** * @brief Determines if a move is an invoker-class move. * * Invoker-class moves are those which call other moves and have no outward * effect of their own. * * @param move * @return TRUE if the move is invoker-class, FALSE if not. */ BOOL Move_IsInvoker(u16 move); /** * @brief Check if a given move is Curse being used by a Ghost-type Pokemon. * * @param battleCtx * @param move * @param battler * @return TRUE if the move is Curse and the battler has the Ghost typing; * FALSE otherwise */ BOOL Move_IsGhostCurse(BattleContext *battleCtx, u16 move, int battler); /** * @brief Determine if a battler's item can be stolen. * * @param battleSys * @param battleCtx * @param battler * @return FALSE */ BOOL BattleSystem_CanStealItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Check if a battler is *not* holding Mail. * * @param battleCtx * @param battler * @return TRUE if the battler is *not* holding Mail, FALSE if so. */ BOOL BattleSystem_NotHoldingMail(BattleContext *battleCtx, int battler); /** * @brief Determine if a target can be Whirlwinded away by an attacker. * * If the attacker is of a lesser level than the target, then this routine has * a random chance to return FALSE. Given a random integer R between 0 and 255, * Whirlwind will fail if the following condition holds: * * R * (attackerLevel + defenderLevel) defenderLevel * ----------------------------------- + 1 ≤ ------------- * 256 4 * * @param battleSys * @param battleCtx * @return TRUE if Whirlwind should succeed, FALSE if it should fail. */ BOOL BattleSystem_CanWhirlwind(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Get the battler's ability, accounting for disrupting effects on itself, * e.g. Gastro Acid, Gravity, and Ingrain. * * @param battleCtx * @param battler * @return The battler's ability */ u8 Battler_Ability(BattleContext *battleCtx, int battler); /** * @brief Check if the given defender has the specified ability, treating it as * ignorable. * * The ability will be ignored if the attacker has Mold Breaker. * * @param battleCtx * @param attacker * @param defender * @param ability * @return TRUE if the defender has the given ability and it is not ignored; * FALSE if the ability is ignored, or if the defender does not have it. */ BOOL Battler_IgnorableAbility(BattleContext *battleCtx, int attacker, int defender, int ability); /** * @brief Checks if there are any Pokemon which can act as a replacement for a * fainted one. * * Replacement-eligible Pokemon have HP > 0 and belong to the same party as a * fallen ally. * * @param battleSys * @param battleCtx * @param battler The battler which wishes to replace a fainted Pokemon. * @return TRUE if there are any Pokemon which can replace the fainted one; * otherwise FALSE. */ BOOL BattleSystem_AnyReplacementMons(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Check if a battler is trapped and cannot switch and, optionally, * populate a message for display. * * @param battleSys * @param battleCtx * @param battler * @param[out] msgOut If non-null, will be populated with a message for * display to the player * @return TRUE if the battler is trapped, FALSE if not. */ BOOL Battler_IsTrappedMsg(BattleSystem *battleSys, BattleContext *battleCtx, int battler, BattleMessage *msgOut); /** * @brief Try to escape a battle. * * @param battleSys * @param battleCtx * @param battler The battler trying to escape * @return TRUE if escape is successful, FALSE otherwise */ BOOL Battler_CanEscape(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Check if Truant is active for the turn for a given battler. * * @param battleCtx * @param battler * @return TRUE if the battler is loafing due to Truant, FALSE if not. */ BOOL Battler_CheckTruant(BattleContext *battleCtx, int battler); /** * @brief Checks if a given move has been Imprisoned by one of the battler's * opponents. * * @param battleSys * @param battleCtx * @param battler The battler trying to execute a move. * @param move The move to be executed. * @return TRUE if any of the battler's opponents has used Imprison and also * knows the requested move; FALSE otherwise. */ BOOL Move_Imprisoned(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int move); /** * @brief Check if any active battlers are flagged as having the given move * effect. * * @param battleSys * @param battleCtx * @param effectMask The requested move effect * @return TRUE if any active battler has the requested move effect; FALSE * othewise */ BOOL BattleSystem_AnyBattlersWithMoveEffect(BattleSystem *battleSys, BattleContext *battleCtx, int effectMask); /** * @brief Setup flags for a move loop, e.g. for multi-hit or spread moves. * * @param battleSys * @param battleCtx */ void BattleSystem_SetupLoop(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Sort all active battlers by their speed for the turn, ignoring Quick * Claw type effects. * * @param battleSys * @param battleCtx */ void BattleSystem_SortMonSpeedOrder(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Check if a given move should fail due to high gravity conditions. * * @param battleSys * @param battleCtx * @param battler * @param move The move to be executed * @return TRUE if the field is under high gravity conditions AND the move * should fail in such conditions; FALSE otherwise */ BOOL Move_FailsInHighGravity(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int move); /** * @brief Check if a given move should fail due to the battler being afflicted * by Heal Block. * * @param battleSys * @param battleCtx * @param battler The battler trying to execute a move * @param move The move to be executed * @return TRUE if the battler is afflicted with Heal Block AND the move should * fail due to such afflicition; FALSE otherwise */ BOOL Move_HealBlocked(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int move); /** * @brief Update buffers for the attacking Pokemon related to Last Resort. * * @param battleSys * @param battleCtx */ void BattleSystem_UpdateLastResort(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Count the number of moves known by a battler. * * @param battleSys * @param battleCtx * @param battler * @return The number of moves known. */ int Battler_CountMoves(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Trigger an immunity-granting ability of the defender based on the * attacker's current move. * * Despite its name, this routine does NOT check for Levitate, which is * handled inside the type-chart check routine. * * @param battleCtx * @param attacker * @param defender * @return A subscript to be loaded for any triggered effect. */ int BattleSystem_TriggerImmunityAbility(BattleContext *battleCtx, int attacker, int defender); /** * @brief Trigger an end-of-turn ability for the battler. * * If an end-of-turn ability is triggered, then the respective subscript will * be loaded into the script buffer, and the battle control command will be * updated to run that script. * * @param battleSys * @param battleCtx * @param battler * @return TRUE if a subscript has been loaded for a triggered effect, FALSE * otherwise. */ BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Perform a division, setting any zero-result to 1 or -1, matching the * sign of the dividend. * * @param dividend The division's dividend. If positive, quotients of 0 will * be set to 1; if negative, quotients of 0 will be set to -1. * @param divisor The dividend's divisor. * @return The result of the division, not permitted to be lesser in magnitude * than 1. */ int BattleSystem_Divide(int dividend, int divisor); /** * @brief Trigger effects which process on-switch-in, e.g. weather abilities, * Intimidate, status-restoring berries, and Amulet Coin. * * @param battleSys * @param battleCtx * @return A subscript which should be loaded as a triggered effect, if any. */ int BattleSystem_TriggerEffectOnSwitch(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Pick a random opponent for the given attacker. * * In a single-battle, this will always return the lone opponent. * * In a double-battle, if one of the two opponents has fainted, then the other * opponent will always be chosen. * * @param battleSys * @param battleCtx * @param attacker * @return A random opponent of the attacker's. */ int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCtx, int attacker); /** * @brief Trigger the defender's ability after a move deals damage to it. * * @param battleSys * @param battleCtx * @param[out] subscript Return-param for the subscript to be loaded for any * triggered effect. * @return TRUE if the returned subscript param should be loaded for a * triggered effect. */ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript); /** * @brief Triggers a battler's ability which prevents an illegal status * condition on the given battler, e.g. a paralyzed Pokemon with Limber. * * This also contains the check responsible for setting the canUnburden flag. * * @param battleSys * @param battleCtx * @param battler * @param skipLoad If TRUE, the routine will skip loading the subscript * responsible for curing an illegal status condition. * @return TRUE if a subscript for an ability effect was loaded, FALSE * otherwise. */ BOOL BattleSystem_RecoverStatusByAbility(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int skipLoad); /** * @brief Check if an ability forbids a value in the given status mask. * * @param battleSys * @param ability The ability to check * @param status A mask of status values * @return TRUE if the given ability forbids some status in the given mask; * FALSE if not */ BOOL Ability_ForbidsStatus(BattleContext *battleSys, int ability, int status); /** * @brief Synchronize a defender's newly-applied status with the Pokemon who * applied it. * * @param battleSys * @param battleCtx * @param controllerCommand The command to return to after sharing the status * @return TRUE if a subscript has been loaded for the status-sharing effect, * FALSE if not. */ BOOL BattleSystem_SynchronizeStatus(BattleSystem *battleSys, BattleContext *battleCtx, int controllerCommand); /** * @brief Check if a held item should trigger due to status, an HP threshold, or * a stat reduction, then load any such triggered effect's corresponding subscript. * * @param battleSys * @param battleCtx * @param battler * @return TRUE if a subscript has been loaded for a triggered effect, FALSE * otherwise. */ BOOL BattleSystem_TriggerHeldItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Check if a Leftovers-type item should trigger at the end of the turn. * * This also contains the split-effect for Black Sludge. * * @param battleSys * @param battleCtx * @param battler * @return TRUE if an effect has been loaded for a subscript to be run, FALSE * otherwise. */ BOOL BattleSystem_TriggerLeftovers(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Check if a held item should trigger due to status, an HP threshold, or * a stat reduction. * * Unlike its counterpart TriggerHeldItem, this routine will return the triggered * effect subscript to the caller rather than immediately loading it for * execution. * * @param battleSys * @param battleCtx * @param battler * @param[out] subscript Return param for the subscript to load for a * triggered effect. * @return TRUE if a subscript has been returned for a triggered effect, FALSE * otherwise. */ BOOL BattleSystem_TriggerHeldItemOnStatus(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int *subscript); /** * @brief Check if a detrimental held item should trigger at the end of the turn. * * This accounts for the effects of Toxic Orb, Flame Orb, and Sticky Barb. * * @param battleSys * @param battleCtx * @param battler * @return TRUE if an effect has been loaded for a subscript to be run, FALSE * otherwise. */ BOOL BattleSystem_TriggerDetrimentalHeldItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Get the battler's held item. * * @param battleCtx * @param battler * @return Integer ID of the battler's held item */ u16 Battler_HeldItem(BattleContext *battleCtx, int battler); /** * @brief Check if a battler moved this turn. * * @param battleCtx * @param battler * @return TRUE if the battler's turn is over, FALSE if they have yet to move. */ BOOL Battler_MovedThisTurn(BattleContext *battleCtx, int battler); /** * @brief Trigger a held item's effect when its holder takes damage. * * @param battleSys * @param battleCtx * @param[out] subscript Return param for the subscript to load for a * triggered effect. * @return TRUE if a subscript should be loaded for a triggered effect, * FALSE otherwise. */ BOOL BattleSystem_TriggerHeldItemOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript); /** * @brief Get the effect of the battler's held item. * * @param battleCtx * @param battler * @return Integer ID of the effect of the battler's held item */ s32 Battler_HeldItemEffect(BattleContext *battleCtx, int battler); enum HeldItemPowerOp { ITEM_POWER_CHECK_ALL = 0, //< Check all possible effects which would suppress a battler's held item. ITEM_POWER_CHECK_NONE, //< Perform no suppression checks; always return the item's power. ITEM_POWER_CHECK_EMBARGO, //< Check if Embargo is active; if so, return 0 power. }; /** * @brief Get the power of the battler's held item. * * This routine optionally can perform a series of checks for effects which * would suppress the held item. * * @param battleCtx * @param battler * @param opcode Opcode controlling the behavior of this subroutine. * @return The power of the battler's held item. */ s32 Battler_HeldItemPower(BattleContext *battleCtx, int battler, enum HeldItemPowerOp opcode); /** * @brief Get the Natural Gift base power for a battler's held item. * * @param battleCtx * @param battler * @return Base power for Natural Gift. */ s32 Battler_NaturalGiftPower(BattleContext *battleCtx, int battler); /** * @brief Get the Natural Gift type for a battler's held item. * * @param battleCtx * @param battler * @return Type for Natural Gift. */ s32 Battler_NaturalGiftType(BattleContext *battleCtx, int battler); /** * @brief Get the Pluck effect of the battler's held item. * * @param battleCtx * @param battler * @return Pluck effect of the battler's held item. */ s32 Battler_ItemPluckEffect(BattleContext *battleCtx, int battler); /** * @brief Get the Fling effect of the battler's held item. * * @param battleCtx * @param battler * @return Fling effect of the battler's held item. */ s32 Battler_ItemFlingEffect(BattleContext *battleCtx, int battler); /** * @brief Get the Fling power of the battler's held item. * * @param battleCtx * @param battler * @return Fling power of the battler's held item. */ s32 Battler_ItemFlingPower(BattleContext *battleCtx, int battler); /** * @brief Check if a battler is trapped and cannot switch. * * @param battleSys * @param battleCtx * @param battler * @return TRUE if the battler is trapped, FALSE if not. */ BOOL Battler_IsTrapped(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Try to Pluck the given battler's berry. * * This routine will determine what subsequence should be run as the stolen * effect (if any) and store it in battleCtx->scriptTemp. It will also update * the attacker's self-turn status flags to denote that the attacker has * Plucked a berry. * * @param battleSys * @param battleCtx * @param battler The battler whose berry is to be Plucked. * @return TRUE if a follow-up subsequence should be run to apply the berry's * Pluck effect; FALSE if no such follow-up is needed. */ BOOL BattleSystem_PluckBerry(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Try to Fling the attacker's item at the given battler. * * This routine will determine what subsequence should be run as the flung * effect (if any) and store it in battleCtx->flingScript. It will also * determine the base power of Fling, as specified in the item data, and * store it in battleCtx->movePower. * * @param battleSys * @param battleCtx * @param battler The target of the flung item. * @return TRUE if a follow-up subsequence should be run to apply the item's * Fling effect; FALSE if no such follow-up is needed. */ BOOL BattleSystem_FlingItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler); /** * @brief Update the count for the Metronome held item. * * @param battleSys * @param battleCtx */ void BattleSystem_UpdateMetronomeCount(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Verify the current count for the Metronome held item. * * @param battleSys * @param battleCtx */ void BattleSystem_VerifyMetronomeCount(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Determine what modulating effect to apply to a battler's cry * whenever they are sent into battle. * * @param battleCtx * @param battler * @param battlerType * @param encounter TRUE if this is a start-of-battle cry. * @return The type of modulating effect applied to the battler's cry. */ enum PokemonCryMod Battler_CryModulation(BattleContext *battleCtx, int battler, int battlerType, BOOL encounter); /** * @brief Check if a battler can choose their action for the turn. * * @param battleSys * @param battler * @return TRUE if the battler can choose their action for the turn, FALSE * if not. */ BOOL Battler_CanPickCommand(BattleContext *battleSys, int battler); /** * @brief Set the catch-data for a newly-caught Pokemon. * * This will set the met-location and Poke Ball for the newly-caught Pokemon. * * @param battleSys * @param battleCtx * @param mon */ void BattleSystem_SetPokemonCatchData(BattleSystem *battleSys, BattleContext *battleCtx, Pokemon *mon); /** * @brief Get the top byte of the IO buffer for the given battler. * * @param battleCtx * @param battler * @return Top byte of the IO buffer for the given battler. */ u8 BattleContext_IOBufferVal(BattleContext *battleCtx, int battler); /** * @brief Check if a battler's substitute was hit. * * @param battleCtx * @param battler * @return TRUE if the battler's substitute was hit, FALSE if not. */ BOOL Battler_SubstituteWasHit(BattleContext *battleCtx, int battler); /** * @brief Check if the player is the attacking Pokemon's OT. * * @param battleSys * @param battleCtx * @return TRUE if the player is the attacking Pokemon's OT, FALSE * otherwise. */ BOOL BattleSystem_TrainerIsOT(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Check if the player is a given Pokemon's OT. * * @param battleSys * @param mon * @return TRUE if the player is the given Pokemon's OT, FALSE otherwise. */ BOOL BattleSystem_PokemonIsOT(BattleSystem *battleSys, Pokemon *mon); /** * @brief Trigger a form change for the battler stored in battleCtx->msgBattlerTemp, * if applicable. * * @param battleSys * @param battleCtx * @param[out] subscript Return-param for the subscript to be loaded for any * triggered effect. * @return TRUE if a form change has triggered and the returned subscript should * be loaded for execution, FALSE otherwise. */ BOOL BattleSystem_TriggerFormChange(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript); /** * @brief Initialize the party order buffer. * * @param battleSys * @param battleCtx */ void BattleSystem_InitPartyOrder(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Switch the party order by swapping the battler in the given party slot * with an active slot. * * @param battleSys * @param battleCtx * @param battler The battler who is switching * @param partySlot The party slot which should be moved to an active slot */ void BattleSystem_SwitchSlots(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); /** * @brief Calculate the base damage for a move using the general damage formula. * * This computes the following value: * * ( ( 2 x Level ) ( Attack ) ) * ( ( --------- + 2 ) * Power * ( ------- ) ) * ( ( 5 ) ( Defense ) ) * ( --------------------------------------- ) * Burn * Screens * Targets * Weather * FlashFire + 2 * ( 50 ) * * @param battleSys * @param battleCtx * @param move The move being calculated * @param sideConditions State of the side conditions mask at the time of calculation * @param fieldConditions State of the field conditions mask at the time of calculation * @param inPower Input power for variable base-power moves * @param inType Input type for variable type moves (e.g. Hidden Power) * @param attacker * @param defender * @param criticalMul Critical multiplier; must always be >= 1, 1 == no crit, * 2+ signifies a crit * @return The computed base damage for the move */ int BattleSystem_CalcMoveDamage(BattleSystem *battleSys, BattleContext *battleCtx, int move, u32 sideConditions, u32 fieldConditions, u16 inPower, u8 inType, u8 attacker, u8 defender, u8 criticalMul); /** * @brief Incorporate random variance in the given damage value. * * A random factor in the range of [0.85, 1] will be used to vary the output * damage value, i.e., we compute the following: * * Damage = Damage * Random([0.85, 1]) * * @param battleSys * @param battleCtx * @param damage * @return The varied damage value. */ int BattleSystem_CalcDamageVariance(BattleSystem *battleSys, BattleContext *battleCtx, int damage); /** * @brief Calculate the critical multiplier to be applied to a move's damage. * * This also performs all of the calculations for if a critical hit should/can * occur. * * @param battleSys * @param battleCtx * @param attacker * @param defender * @param criticalStage The existing critical hit stage for the attacker * @param sideConditions State of the side conditions mask at the time of calculation * @return 1 if no critical occurs, 2 if a critical occurs, 3 if a critical * occurs and the attacker also has the ability Sniper */ int BattleSystem_CalcCriticalMulti(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, int defender, int criticalStage, u32 sideConditions); /** * @brief Check if a move can be copied by Mimic. * * @param move * @return TRUE if the move can be copied by Mimic, FALSE if not. */ BOOL Move_CanBeMimicked(u16 move); /** * @brief Check if a move can be invoked by Metronome. * * @param battleSys * @param battleCtx * @param battler The battler using Metronome. * @param move * @return TRUE if the move can be invoked by Metronome, FALSE if not. */ BOOL Move_CanBeMetronomed(BattleSystem *battleSys, BattleContext *battleCtx, int battler, u16 move); /** * @brief Check if a move can be Encored. * * @param battleCtx * @param move * @return TRUE if the move can be Encored, FALSE if not. */ BOOL Move_CanBeEncored(BattleContext *battleCtx, u16 move); /** * @brief Check if a move can be copied by Me First. * * @param battleCtx * @param move * @return TRUE if the move can be copied by Me First, FALSE if not. */ BOOL Move_MeFirstCanCopy(BattleContext *battleCtx, u16 move); /** * @brief Get a data element out of the given item's data structure. * * This consults the item table loaded at battle start-time. * * @param battleCtx * @param item ID of the item to be loaded * @param paramID ID of the item param to be retrieved * @return s32-representation of the data pulled from the item table */ s32 BattleSystem_GetItemData(BattleContext *battleCtx, u16 item, enum ItemDataParam paramID); /** * @brief Determine the first battler which matches the input side value. * * @param battleSys * @param battleCtx * @param side * @return The first battler which matches the input side value. */ int BattleSystem_SideToBattler(BattleSystem *battleSys, BattleContext *battleCtx, int side); /** * @brief Sort the action order for battlers based on their speed and actions. * * @param battleSys * @param battleCtx */ void BattleSystem_SortMonActionOrder(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Determine if a status effect should be shown for the given battler. * * This handles the determination of if a given status effect animation should * be played if the battler is behind a substitute or is in an invulnerable * state. * * @param battleCtx * @param battler The battler for whom the status effect should be shown. * @param status The status effect attempting to be shown. * @return TRUE if the status effect should be shown, FALSE otherwise. */ BOOL BattleSystem_ShouldShowStatusEffect(BattleContext *battleCtx, int battler, int status); /** * @brief Trigger a held item's effect after a pivoting move has been used. * * This is meant to support triggering effects such as Shell Bell, Life Orb, * and Sticky Barb transferral before the user of a pivoting move switches out. * * @param battleSys * @param battleCtx * @param[out] subscript Return param for the subscript to load for a * triggered effect. * @return TRUE if a subscript should be loaded for a triggered effect, * FALSE otherwise. */ BOOL BattleSystem_TriggerHeldItemOnPivotMove(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript); /** * @brief Decrement additional PP from the attacker's selected move if its * target has the Pressure ability. * * @param battleCtx * @param attacker * @param defender */ void BattleSystem_DecPPForPressure(BattleContext *battleCtx, int attacker, int defender); /** * @brief Check if the recording for a battle has finished playing. * * If the recording has finished, then the controller will be set to a * SCREEN_WIPE command. * * @param battleSys * @param battleCtx * @return TRUE if the recording has stopped, FALSE otherwise. */ BOOL Battle_RecordingStopped(BattleSystem *battleSys, BattleContext *battleCtx); /** * @brief Get an accessible field from the BattleContext struct. * * See: enum BattleContextParam * * @param battleSys * @param battleCtx * @param paramID ID of the field to retrieve * @param battler Battler for retrieving the correct field, if applicable * @return Value of the field, or 0 if unrecognized. */ int BattleContext_Get(BattleSystem *battleSys, BattleContext *battleCtx, enum BattleContextParam paramID, int battler); /** * @brief Set the value of an accessible field in the BattleContext struct. * * See: enum BattleContextParam * * The following values may be modified: * - The full side conditions mask for a particular side * - The number of turns of Mist for a particular side * - The selected party slot for a battler * - The total number of turns that have elapsed * - The AI's chosen target for the turn * - The AI's chosen target from a particular battler for the turn * * @param battleSys * @param battleCtx * @param paramID ID of the field to retrieve * @param battler Battler for accessing the correct field, if applicable * @param val Value to which the field should be set */ void BattleContext_Set(BattleSystem *battleSys, BattleContext *battleCtx, enum BattleContextParam paramID, int battler, int val); /** * @brief Determine what Pokemon the AI will switch-in from their party after * one of their active battlers has been KO'd. * * @param battleSys * @param battler * @return The party slot of the Pokemon to be switched in. */ int BattleAI_PostKOSwitchIn(BattleSystem *battleSys, int battler); /** * @brief Get the switched-to slot determined by the AI for a given battler. * * @param battleSys * @param battler * @return The AI's switched-to slot for the battler. */ int BattleAI_SwitchedSlot(BattleSystem *battleSys, int battler); /** * @brief Compute the variable-type of a move, given its use by a given Pokemon. * * This is used by moves such as Natural Gift, Hidden Power, and Weather Ball. * * @param battleSys * @param battleCtx * @param mon The Pokemon using the move. * @param move The move being used. * @return The variable-type of a move, considering parameters of its user and * the battlefield. */ int Move_CalcVariableType(BattleSystem *battleSys, BattleContext *battleCtx, Pokemon *mon, int move); #endif // POKEPLATINUM_BATTLE_BATTLE_LIB_H