diff --git a/include/battle/battle_context.h b/include/battle/battle_context.h index 9678f28008..d18fab228e 100644 --- a/include/battle/battle_context.h +++ b/include/battle/battle_context.h @@ -164,7 +164,7 @@ struct BattleContext { int gainedExp; int sharedExp; - u32 monsGainingExp[2]; + u32 sideGetExpMask[2]; int scriptNarc; int scriptFile; diff --git a/include/battle/battle_controller.h b/include/battle/battle_controller.h index 7419493031..a4ee5956ab 100644 --- a/include/battle/battle_controller.h +++ b/include/battle/battle_controller.h @@ -55,6 +55,41 @@ enum BattleControlSequence { BATTLE_CONTROL_END_WAIT, }; +enum { + PLAYER_INPUT_FIGHT = 1, + PLAYER_INPUT_ITEM, + PLAYER_INPUT_PARTY, + PLAYER_INPUT_RUN, + + PLAYER_INPUT_SAFARI_BALL = PLAYER_INPUT_FIGHT, + PLAYER_INPUT_SAFARI_BAIT = PLAYER_INPUT_ITEM, + PLAYER_INPUT_SAFARI_ROCK = PLAYER_INPUT_PARTY, + PLAYER_INPUT_SAFARI_RUN = PLAYER_INPUT_RUN, + PLAYER_INPUT_SAFARI_WAIT, + + PLAYER_INPUT_PAL_PARK_BALL = PLAYER_INPUT_FIGHT, + PLAYER_INPUT_PAL_PARK_RUN = PLAYER_INPUT_RUN, + + PLAYER_INPUT_MOVE_1 = 1, + PLAYER_INPUT_MOVE_2, + PLAYER_INPUT_MOVE_3, + PLAYER_INPUT_MOVE_4, + + PLAYER_INPUT_PARTY_SLOT_1 = 1, + PLAYER_INPUT_PARTY_SLOT_2, + PLAYER_INPUT_PARTY_SLOT_3, + PLAYER_INPUT_PARTY_SLOT_4, + PLAYER_INPUT_PARTY_SLOT_5, + PLAYER_INPUT_PARTY_SLOT_6, + + PLAYER_INPUT_TARGET_BATTLER_1 = 1, + PLAYER_INPUT_TARGET_BATTLER_2, + PLAYER_INPUT_TARGET_BATTLER_3, + PLAYER_INPUT_TARGET_BATTLER_4, + + PLAYER_INPUT_CANCEL = 0xFF, +}; + /** * @brief Create a new BattleContext struct from the given BattleSystem. * diff --git a/include/battle/common.h b/include/battle/common.h index 75c011cf0b..cd8a46d427 100644 --- a/include/battle/common.h +++ b/include/battle/common.h @@ -78,7 +78,7 @@ enum { BATTLE_STAT_DEFENSE, BATTLE_STAT_SPEED, BATTLE_STAT_SP_ATTACK, - BATTEL_STAT_SP_DEFENSE, + BATTLE_STAT_SP_DEFENSE, BATTLE_STAT_ACCURACY, BATTLE_STAT_EVASION, diff --git a/include/constants/battle.h b/include/constants/battle.h index 88dd67bf36..a476683f40 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -43,7 +43,6 @@ #define BATTLE_TYPE_2vs2_TAG (BATTLE_TYPE_2vs2 | BATTLE_TYPE_TAG) #define BATTLE_TYPE_ALWAYS_CATCH (BATTLE_TYPE_PAL_PARK | BATTLE_TYPE_CATCH_TUTORIAL) #define BATTLE_TYPE_RESTORE_ITEMS_AFTER (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER) -#define BATTLE_TYPE_2vs2_AI_DOUBLES (BATTLE_TYPE_DOUBLES | BATTLE_TYPE_2vs2 | BATTLE_TYPE_AI) #define MAX_LINK_BATTLERS 4 #define MAX_BATTLERS 4 diff --git a/include/constants/battle/condition.h b/include/constants/battle/condition.h index 7a7e5ef925..40a6ade6ea 100644 --- a/include/constants/battle/condition.h +++ b/include/constants/battle/condition.h @@ -95,9 +95,34 @@ | FIELD_CONDITION_SANDSTORM \ | FIELD_CONDITION_HAILING \ | FIELD_CONDITION_DEEP_FOG) +#define FIELD_CONDITION_CASTFORM (FIELD_CONDITION_RAINING | FIELD_CONDITION_SUNNY | FIELD_CONDITION_HAILING) #define FIELD_CONDITION_UPROAR_SHIFT 8 #define FIELD_CONDITION_GRAVITY_SHIFT 12 #define FIELD_CONDITION_TRICK_ROOM_SHIFT 16 +enum { + OVERWORLD_WEATHER_CLEAR = 0, + OVERWORLD_WEATHER_CLOUDY, + OVERWORLD_WEATHER_RAINING, + OVERWORLD_WEATHER_HEAVY_RAIN, + OVERWORLD_WEATHER_THUNDERSTORM, + OVERWORLD_WEATHER_SNOWING, + OVERWORLD_WEATHER_HEAVY_SNOW, + OVERWORLD_WEATHER_BLIZZARD, + OVERWORLD_WEATHER_CLEAR_8, + OVERWORLD_WEATHER_SLOW_ASHFALL, + OVERWORLD_WEATHER_SANDSTORM, + OVERWORLD_WEATHER_HAILING, + OVERWORLD_WEATHER_SPIRITS, + OVERWORLD_WEATHER_CLEAR_13, + OVERWORLD_WEATHER_FOG, + OVERWORLD_WEATHER_DEEP_FOG, + OVERWORLD_WEATHER_DARK_FLASH, + + // these are only for the Battle Frontier + OVERWORLD_WEATHER_HARSH_SUN = 1001, + OVERWORLD_WEATHER_TRICK_ROOM, +}; + #endif // POKEPLATINUM_CONSTANTS_BATTLE_CONDITION_H \ No newline at end of file diff --git a/include/constants/battle/side_effects.h b/include/constants/battle/side_effects.h index 22c7a41b80..982e1e3845 100644 --- a/include/constants/battle/side_effects.h +++ b/include/constants/battle/side_effects.h @@ -1,40 +1,6 @@ #ifndef POKEPLATINUM_CONSTANTS_BATTLE_SIDE_EFFECTS_H #define POKEPLATINUM_CONSTANTS_BATTLE_SIDE_EFFECTS_H -#define MOVE_SIDE_EFFECT_SLEEP 0x00000001 -#define MOVE_SIDE_EFFECT_FREEZE 0x00000004 -#define MOVE_SIDE_EFFECT_PARALYZE 0x00000005 -#define MOVE_SIDE_EFFECT_FLINCH 0x00000008 -#define MOVE_SIDE_EFFECT_ATTACK_UP_1_STAGE 0x0000000F -#define MOVE_SIDE_EFFECT_DEFENSE_UP_1_STAGE 0x00000010 -#define MOVE_SIDE_EFFECT_SPEED_UP_1_STAGE 0x00000011 -#define MOVE_SIDE_EFFECT_SP_ATTACK_UP_1_STAGE 0x00000012 -#define MOVE_SIDE_EFFECT_SP_DEFENSE_UP_1_STAGE 0x00000013 -#define MOVE_SIDE_EFFECT_ACCURACY_UP_1_STAGE 0x00000014 -#define MOVE_SIDE_EFFECT_EVASION_UP_1_STAGE 0x00000015 -#define MOVE_SIDE_EFFECT_ATTACK_DOWN_1_STAGE 0x00000016 -#define MOVE_SIDE_EFFECT_DEFENSE_DOWN_1_STAGE 0x00000017 -#define MOVE_SIDE_EFFECT_SPEED_DOWN_1_STAGE 0x00000018 -#define MOVE_SIDE_EFFECT_SP_ATTACK_DOWN_1_STAGE 0x00000019 -#define MOVE_SIDE_EFFECT_SP_DEFENSE_DOWN_1_STAGE 0x0000001A -#define MOVE_SIDE_EFFECT_ACCURACY_DOWN_1_STAGE 0x0000001B -#define MOVE_SIDE_EFFECT_EVASION_DOWN_1_STAGE 0x0000001C - -#define MOVE_SIDE_EFFECT_ATTACK_UP_2_STAGES 0x00000027 -#define MOVE_SIDE_EFFECT_DEFENSE_UP_2_STAGES 0x00000028 -#define MOVE_SIDE_EFFECT_SPEED_UP_2_STAGES 0x00000029 -#define MOVE_SIDE_EFFECT_SP_ATTACK_UP_2_STAGES 0x0000002A -#define MOVE_SIDE_EFFECT_SP_DEFENSE_UP_2_STAGES 0x0000002B -#define MOVE_SIDE_EFFECT_ACCURACY_UP_2_STAGES 0x0000002C -#define MOVE_SIDE_EFFECT_EVASION_UP_2_STAGES 0x0000002D -#define MOVE_SIDE_EFFECT_ATTACK_DOWN_2_STAGES 0x0000002E -#define MOVE_SIDE_EFFECT_DEFENSE_DOWN_2_STAGES 0x0000002F -#define MOVE_SIDE_EFFECT_SPEED_DOWN_2_STAGES 0x00000030 -#define MOVE_SIDE_EFFECT_SP_ATTACK_DOWN_2_STAGES 0x00000031 -#define MOVE_SIDE_EFFECT_SP_DEFENSE_DOWN_2_STAGES 0x00000032 -#define MOVE_SIDE_EFFECT_ACCURACY_DOWN_2_STAGES 0x00000033 -#define MOVE_SIDE_EFFECT_EVASION_DOWN_2_STAGES 0x00000034 - #define MOVE_SIDE_EFFECT_BREAK_SCREENS (1 << 23) #define MOVE_SIDE_EFFECT_CHECK_SUBSTITUTE (1 << 24) #define MOVE_SIDE_EFFECT_CHECK_HP_AND_SUBSTITUTE (1 << 25) @@ -45,15 +11,176 @@ #define MOVE_SIDE_EFFECT_TO_ATTACKER (1 << 30) #define MOVE_SIDE_EFFECT_TO_DEFENDER (1 << 31) +#define MOVE_SIDE_EFFECT_FLAGS (MOVE_SIDE_EFFECT_BREAK_SCREENS \ + | MOVE_SIDE_EFFECT_CHECK_SUBSTITUTE \ + | MOVE_SIDE_EFFECT_CHECK_HP_AND_SUBSTITUTE \ + | MOVE_SIDE_EFFECT_PROBABILISTIC \ + | MOVE_SIDE_EFFECT_CANNOT_PREVENT \ + | MOVE_SIDE_EFFECT_CHECK_HP \ + | MOVE_SIDE_EFFECT_ON_HIT \ + | MOVE_SIDE_EFFECT_TO_ATTACKER \ + | MOVE_SIDE_EFFECT_TO_DEFENDER) +#define MOVE_SIDE_EFFECT_SUBSCRIPT_POINTER (~MOVE_SIDE_EFFECT_FLAGS) + enum { - SIDE_EFFECT_SOURCE_NONE = 0, - SIDE_EFFECT_SOURCE_DIRECT, - SIDE_EFFECT_SOURCE_INDIRECT, - SIDE_EFFECT_SOURCE_ABILITY, - SIDE_EFFECT_SOURCE_MOVE_EFFECT, - SIDE_EFFECT_SOURCE_HELD_ITEM, - SIDE_EFFECT_SOURCE_TOXIC_SPIKES, - SIDE_EFFECT_SOURCE_DISOBEDIENCE, + MOVE_SUBSCRIPT_PTR_NONE = 0, + MOVE_SUBSCRIPT_PTR_SLEEP, + MOVE_SUBSCRIPT_PTR_POISON, + MOVE_SUBSCRIPT_PTR_BURN, + MOVE_SUBSCRIPT_PTR_FREEZE, + MOVE_SUBSCRIPT_PTR_PARALYZE, + MOVE_SUBSCRIPT_PTR_BADLY_POISON, + MOVE_SUBSCRIPT_PTR_CONFUSE, + MOVE_SUBSCRIPT_PTR_FLINCH, + MOVE_SUBSCRIPT_PTR_REST, + MOVE_SUBSCRIPT_PTR_UPROAR, + MOVE_SUBSCRIPT_PTR_PAY_DAY, + MOVE_SUBSCRIPT_PTR_VANISH_CHARGE_TURN, + MOVE_SUBSCRIPT_PTR_BIND_TARGET, + MOVE_SUBSCRIPT_PTR_QUARTER_RECOIL, + MOVE_SUBSCRIPT_PTR_ATTACK_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_DEFENSE_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_SPEED_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_SP_ATTACK_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_SP_DEFENSE_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_ACCURACY_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_EVASION_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_DEFENSE_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_SPEED_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_SP_ATTACK_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_SP_DEFENSE_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_EVASION_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_RECHARGE_TURN, + MOVE_SUBSCRIPT_PTR_SET_RAGE_FLAG, + MOVE_SUBSCRIPT_PTR_STEAL_ITEM, + MOVE_SUBSCRIPT_PTR_MEAN_LOOK, + MOVE_SUBSCRIPT_PTR_NIGHTMARE_START, + MOVE_SUBSCRIPT_PTR_BOOST_ALL_STATS, + MOVE_SUBSCRIPT_PTR_RAPID_SPIN, + MOVE_SUBSCRIPT_PTR_HEAL_TARGET_PARALYSIS, + MOVE_SUBSCRIPT_PTR_USER_ATK_AND_DEF_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_RECOIL_1_3, + MOVE_SUBSCRIPT_PTR_ATTACK_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_DEFENSE_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_SPEED_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_SP_ATTACK_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_SP_DEFENSE_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_ACCURACY_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_EVASION_UP_2_STAGES, + MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_DEFENSE_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_SPEED_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_SP_ATTACK_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_SP_DEFENSE_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_EVASION_DOWN_2_STAGES, + MOVE_SUBSCRIPT_PTR_THRASH, + MOVE_SUBSCRIPT_PTR_KNOCK_OFF, + MOVE_SUBSCRIPT_PTR_USER_DEF_AND_SPDEF_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_USER_ATK_AND_DEF_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_TARGET_ATK_AND_DEF_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_USER_SPATK_AND_SPDEF_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_USER_ATK_AND_SPEED_UP_1_STAGE, + MOVE_SUBSCRIPT_PTR_DRAIN_HALF_DAMAGE_DEALT, + MOVE_SUBSCRIPT_PTR_DREAM_EATER, + MOVE_SUBSCRIPT_PTR_RESET_ALL_STAT_STAGES, + MOVE_SUBSCRIPT_PTR_BIDE_START, + MOVE_SUBSCRIPT_PTR_STRUGGLE, + MOVE_SUBSCRIPT_PTR_CONVERSION, + MOVE_SUBSCRIPT_PTR_RECOVER_HALF_MAX_HP, + MOVE_SUBSCRIPT_PTR_LIGHT_SCREEN, + MOVE_SUBSCRIPT_PTR_REFLECT, + MOVE_SUBSCRIPT_PTR_MIST, + MOVE_SUBSCRIPT_PTR_FOCUS_ENERGY, + MOVE_SUBSCRIPT_PTR_MIMIC, + MOVE_SUBSCRIPT_PTR_LEECH_SEED_START, + MOVE_SUBSCRIPT_PTR_DISABLE_START, + MOVE_SUBSCRIPT_PTR_ENCORE_START, + MOVE_SUBSCRIPT_PTR_PAIN_SPLIT, + MOVE_SUBSCRIPT_PTR_CONVERSION_2, + MOVE_SUBSCRIPT_PTR_LOCK_ON, + MOVE_SUBSCRIPT_PTR_SKETCH, + MOVE_SUBSCRIPT_PTR_FEINT, + MOVE_SUBSCRIPT_PTR_DESTINY_BOND, + MOVE_SUBSCRIPT_PTR_REDUCE_TARGET_PP, + MOVE_SUBSCRIPT_PTR_PROTECT, + MOVE_SUBSCRIPT_PTR_HEAL_BELL, + MOVE_SUBSCRIPT_PTR_TRY_SUBSTITUTE, + MOVE_SUBSCRIPT_PTR_FORCE_TARGET_TO_SWITCH_OR_FLEE, + MOVE_SUBSCRIPT_PTR_TRANSFORM_INTO_TARGET, + MOVE_SUBSCRIPT_PTR_MINIMIZE, + MOVE_SUBSCRIPT_PTR_CURSE_NORMAL, + MOVE_SUBSCRIPT_PTR_CURSE_GHOST, + MOVE_SUBSCRIPT_PTR_PRINT_MESSAGE_AND_PLAY_ANIMATION, + MOVE_SUBSCRIPT_PTR_FORESIGHT, + MOVE_SUBSCRIPT_PTR_PERISH_SONG_START, + MOVE_SUBSCRIPT_PTR_WEATHER_START, + MOVE_SUBSCRIPT_PTR_SWAGGER, + MOVE_SUBSCRIPT_PTR_INFATUATE, + MOVE_SUBSCRIPT_PTR_SAFEGUARD_START, + MOVE_SUBSCRIPT_PTR_PRESENT_HEAL, + MOVE_SUBSCRIPT_PTR_MAGNITUDE, + MOVE_SUBSCRIPT_PTR_BATON_PASS, + MOVE_SUBSCRIPT_PTR_BELLY_DRUM, + MOVE_SUBSCRIPT_PTR_TELEPORT, + MOVE_SUBSCRIPT_PTR_FUTURE_SIGHT_START, + MOVE_SUBSCRIPT_PTR_STOCKPILE, + MOVE_SUBSCRIPT_PTR_SWALLOW, + MOVE_SUBSCRIPT_PTR_TORMENT_START, + MOVE_SUBSCRIPT_PTR_FLATTER, + MOVE_SUBSCRIPT_PTR_MEMENTO, + MOVE_SUBSCRIPT_PTR_CHARGE, + MOVE_SUBSCRIPT_PTR_TAUNT_START, + MOVE_SUBSCRIPT_PTR_EXCHANGE_ITEMS, + MOVE_SUBSCRIPT_PTR_COPY_ABILITY, + MOVE_SUBSCRIPT_PTR_BREAK_SCREENS, + MOVE_SUBSCRIPT_PTR_YAWN, + MOVE_SUBSCRIPT_PTR_EXCHANGE_ABILITIES, + MOVE_SUBSCRIPT_PTR_RECOVER_PSN_PRZ_BRN, + MOVE_SUBSCRIPT_PTR_ROOST, + MOVE_SUBSCRIPT_PTR_HEAL_TARGET_SLEEP, + MOVE_SUBSCRIPT_PTR_GRAVITY_START, + MOVE_SUBSCRIPT_PTR_MIRACLE_EYE, + MOVE_SUBSCRIPT_PTR_HEALING_WISH, + MOVE_SUBSCRIPT_PTR_TAILWIND_START, + MOVE_SUBSCRIPT_PTR_USER_DEF_AND_SPDEF_DOWN_1_STAGE, + MOVE_SUBSCRIPT_PTR_USER_SWAP_ATK_AND_DEF, + MOVE_SUBSCRIPT_PTR_SUPPRESS_TARGET_ABILITY, + MOVE_SUBSCRIPT_PTR_LUCKY_CHANT_START, + MOVE_SUBSCRIPT_PTR_EXCHANGE_ATK_AND_SPATK_STAGES, + MOVE_SUBSCRIPT_PTR_EXCHANGE_DEF_AND_SPDEF_STAGES, + MOVE_SUBSCRIPT_PTR_GIVE_TARGET_INSOMNIA, + MOVE_SUBSCRIPT_PTR_EXCHANGE_ALL_STAT_STAGES, + MOVE_SUBSCRIPT_PTR_RECOIL_1_3_CHANCE_TO_BURN, + MOVE_SUBSCRIPT_PTR_DEFOG, + MOVE_SUBSCRIPT_PTR_HEAL_BLOCK_START, + MOVE_SUBSCRIPT_PTR_ATTACK_THEN_SWITCH_OUT, + MOVE_SUBSCRIPT_PTR_EMBARGO_START, + MOVE_SUBSCRIPT_PTR_PLUCK, + MOVE_SUBSCRIPT_PTR_FLING, + MOVE_SUBSCRIPT_PTR_RECOIL_1_3_CHANCE_TO_PARALYZE, + MOVE_SUBSCRIPT_PTR_RECOIL_1_2, + MOVE_SUBSCRIPT_PTR_BURN_OR_FLINCH, + MOVE_SUBSCRIPT_PTR_FREEZE_OR_FLINCH, + MOVE_SUBSCRIPT_PTR_PARALYZE_OR_FLINCH, + MOVE_SUBSCRIPT_PTR_CHATTER, + MOVE_SUBSCRIPT_PTR_LUNAR_DANCE, + MOVE_SUBSCRIPT_PTR_GIVE_TARGET_OWN_STATUS, + + MOVE_SUBSCRIPT_PTR_MAX = MOVE_SIDE_EFFECT_SUBSCRIPT_POINTER, +}; + +enum SideEffectType { + SIDE_EFFECT_TYPE_NONE = 0, //< No side effect to apply + SIDE_EFFECT_TYPE_DIRECT, //< A direct side effect; used for, e.g., status moves whose only purpose is the effect + SIDE_EFFECT_TYPE_INDIRECT, //< An indirect side effect; used for moves which deal damage and have some secondary effect + SIDE_EFFECT_TYPE_ABILITY, //< An effect applied from an ability, e.g. Effect Spore or Static + SIDE_EFFECT_TYPE_MOVE_EFFECT, //< An effect which comes from another move's effect, e.g. Yawn, where the sleep is delayed + SIDE_EFFECT_TYPE_HELD_ITEM, //< An effect which comes from a held item, e.g. Flame Orb + SIDE_EFFECT_TYPE_TOXIC_SPIKES, //< An effect which comes from specifically Toxic Spikes + SIDE_EFFECT_TYPE_DISOBEDIENCE, //< An effect which comes from a Pokemon disobeying its trainer }; #endif // POKEPLATINUM_CONSTANTS_BATTLE_SIDE_EFFECTS_H diff --git a/include/constants/battle/system_control.h b/include/constants/battle/system_control.h index 6dbae8ec37..6776c5d91c 100644 --- a/include/constants/battle/system_control.h +++ b/include/constants/battle/system_control.h @@ -30,7 +30,9 @@ #define SYSCTL_MAGIC_COAT_REFLECTED (1 << 3) #define SYSCTL_UTURN_ACTIVE (1 << 4) #define SYSCTL_MOVE_SUCCEEDED (1 << 6) // this only reflects that the move is executed, not whether it hit or missed -#define SYSCTL_LINK_WAITING ((1 << 24) | (1 << 25) | (1 << 26) | (1 << 27)) +#define SYSCTL_FORM_CHANGE (1 << 26) + +#define SYSCTL_LINK_WAITING ((1 << 24) | (1 << 25) | SYSCTL_FORM_CHANGE | (1 << 27)) #define SYSCTL_PAYOUT_EXP ((1 << 28) | (1 << 29) | (1 << 30) | (1 << 31)) #define SYSCTL_LINK_WAITING_SHIFT 24 diff --git a/include/constants/items.h b/include/constants/items.h index e2b9012a8a..567f1868d4 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -149,7 +149,7 @@ enum { #define HOLD_EFFECT_ACCURACY_UP_SLOWER 104 #define HOLD_EFFECT_BOOST_REPEATED 105 #define HOLD_EFFECT_SPEED_DOWN_GROUNDED 106 -#define HOLD_EFFECT_SPEED_DOWN 107 +#define HOLD_EFFECT_PRIORITY_DOWN 107 #define HOLD_EFFECT_RECIPROCATE_INFAT 108 #define HOLD_EFFECT_HP_RESTORE_PSN_TYPE 109 #define HOLD_EFFECT_EXTEND_HAIL 110 diff --git a/include/constants/narc_files/battle_skill_subseq.h b/include/constants/narc_files/battle_skill_subseq.h index 3d65cd9357..e91008cf2a 100644 --- a/include/constants/narc_files/battle_skill_subseq.h +++ b/include/constants/narc_files/battle_skill_subseq.h @@ -14,8 +14,9 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_SWITCH_POKEMON, BATTLE_SUBSEQ_SHOW_PARTY_LIST, BATTLE_SUBSEQ_THROW_POKEBALL, - - BATTLE_SUBSEQ_FLINCH_MON = 14, + BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + BATTLE_SUBSEQ_VANISH_ON_CHARGE_TURN, + BATTLE_SUBSEQ_FLINCH_MON, BATTLE_SUBSEQ_FLINCHED, BATTLE_SUBSEQ_CRITICAL_HIT, BATTLE_SUBSEQ_HIT_X_TIMES, @@ -25,92 +26,181 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_MOVE_FOLLOWUP_MESSAGE, BATTLE_SUBSEQ_POISON, BATTLE_SUBSEQ_POISON_DAMAGE, - - BATTLE_SUBSEQ_BURN = 25, + BATTLE_SUBSEQ_DRAIN_HALF_DAMAGE_DEALT, + BATTLE_SUBSEQ_BURN, BATTLE_SUBSEQ_BURN_DAMAGE, - - BATTLE_SUBSEQ_FROZEN = 28, + BATTLE_SUBSEQ_FREEZE, + BATTLE_SUBSEQ_FROZEN, BATTLE_SUBSEQ_THAW_OUT, BATTLE_SUBSEQ_DEFROSTED_BY_MOVE, BATTLE_SUBSEQ_PARALYZE, BATTLE_SUBSEQ_FULLY_PARALYZED, - - BATTLE_SUBSEQ_BIDE_END = 36, - - BATTLE_SUBSEQ_CONFUSED = 38, + BATTLE_SUBSEQ_DREAM_EATER, + BATTLE_SUBSEQ_RESET_ALL_STAT_STAGES, + BATTLE_SUBSEQ_BIDE_START, + BATTLE_SUBSEQ_BIDE_END, + BATTLE_SUBSEQ_CONFUSE, + BATTLE_SUBSEQ_CONFUSED, BATTLE_SUBSEQ_HURT_SELF_IN_CONFUSION, BATTLE_SUBSEQ_SNAP_OUT_OF_CONFUSION, BATTLE_SUBSEQ_TRAINER_MESSAGE, BATTLE_SUBSEQ_NO_PP, - - BATTLE_SUBSEQ_BADLY_POISON = 47, - - BATTLE_SUBSEQ_MOVE_EFFECT_END = 50, + BATTLE_SUBSEQ_STRUGGLE, + BATTLE_SUBSEQ_THRASH, + BATTLE_SUBSEQ_CONVERSION, + BATTLE_SUBSEQ_RECOVER_HALF_MAX_HP, + BATTLE_SUBSEQ_BADLY_POISON, + BATTLE_SUBSEQ_PAY_DAY, + BATTLE_SUBSEQ_LIGHT_SCREEN, + BATTLE_SUBSEQ_MOVE_EFFECT_END, BATTLE_SUBSEQ_THRASH_END, + BATTLE_SUBSEQ_REFLECT, - BATTLE_SUBSEQ_BIND_EFFECT = 59, - BATTLE_SUBSEQ_BIND_END, + BATTLE_SUBSEQ_MIST = 54, + BATTLE_SUBSEQ_REST, + BATTLE_SUBSEQ_UPROAR, - BATTLE_SUBSEQ_RECHARGING = 65, - - BATTLE_SUBSEQ_LEECH_SEED_EFFECT = 69, + BATTLE_SUBSEQ_BIND_START = 58, + BATTLE_SUBSEQ_BIND_EFFECT, + BATTLE_SUBSEQ_BIND_END, - BATTLE_SUBSEQ_MOVE_IS_DISABLED = 71, + BATTLE_SUBSEQ_FOCUS_ENERGY = 62, + BATTLE_SUBSEQ_RECOIL_1_4, + BATTLE_SUBSEQ_RECHARGE_TURN, + BATTLE_SUBSEQ_RECHARGING, + BATTLE_SUBSEQ_SET_RAGE_FLAG, + BATTLE_SUSBEQ_MIMIC, + BATTLE_SUBSEQ_LEECH_SEED_START, + BATTLE_SUBSEQ_LEECH_SEED_EFFECT, + BATTLE_SUBSEQ_DISABLE_START, + BATTLE_SUBSEQ_MOVE_IS_DISABLED, BATTLE_SUBSEQ_DISABLE_END, - - BATTLE_SUBSEQ_ENCORE_END = 74, - - BATTLE_SUBSEQ_FAINT_CHECK_DESTINY_BOND = 83, - - BATTLE_SUBSEQ_HIT_SUBSTITUTE = 90, - - BATTLE_SUBSEQ_NIGHTMARE_EFFECT = 94, - - BATTLE_SUBSEQ_CURSE_DAMAGE = 98, - - BATTLE_SUBSEQ_CONTINUE_PERISH_SONG = 102, - - BATTLE_SUBSEQ_WEATHER_CONTINUES = 104, - - BATTLE_SUBSEQ_INFATUATE = 106, + BATTLE_SUBSEQ_ENCORE_START, + BATTLE_SUBSEQ_ENCORE_END, + + BATTLE_SUBSEQ_PAIN_SPLIT = 77, + BATTLE_SUBSEQ_CONVERSION_2, + BATTLE_SUBSEQ_LOCK_ON, + BATTLE_SUBSEQ_SKETCH, + BATTLE_SUBSEQ_FEINT, + BATTLE_SUBSEQ_DESTINY_BOND, + BATTLE_SUBSEQ_FAINT_CHECK_DESTINY_BOND, + BATTLE_SUBSEQ_REDUCE_TARGET_PP, + BATTLE_SUBSEQ_STEAL_ITEM, + BATTLE_SUBSEQ_MEAN_LOOK, + BATTLE_SUBSEQ_PROTECT, + BATTLE_SUBSEQ_HEAL_BELL, + BATTLE_SUBSEQ_TRY_SUBSTITUTE, + BATTLE_SUBSEQ_HIT_SUBSTITUTE, + BATTLE_SUBSEQ_FORCE_TARGET_TO_SWITCH_OR_FLEE, + BATTLE_SUSBEQ_TRANSFORM_INTO_TARGET, + BATTLE_SUBSEQ_NIGHTMARE_START, + BATTLE_SUBSEQ_NIGHTMARE_EFFECT, + BATTLE_SUBSEQ_MINIMIZE, + BATTLE_SUBSEQ_CURSE_NORMAL, + BATTLE_SUBSEQ_CURSE_GHOST, + BATTLE_SUBSEQ_CURSE_DAMAGE, + BATTLE_SUBSEQ_HAZARDS_CHECK, + BATTLE_SUBSEQ_FORESIGHT, + BATTLE_SUBSEQ_PERISH_SONG_START, + BATTLE_SUBSEQ_CONTINUE_PERISH_SONG, + BATTLE_SUBSEQ_WEATHER_START, + BATTLE_SUBSEQ_WEATHER_CONTINUES, + BATTLE_SUBSEQ_SWAGGER, + BATTLE_SUBSEQ_INFATUATE, BATTLE_SUBSEQ_INFATUATED, BATTLE_SUBSEQ_IMMOBILIZED_BY_LOVE, - - BATTLE_SUBSEQ_SAFEGUARD_END = 110, - - BATTLE_SUBSEQ_BREAK_BIND_EFFECT = 116, + BATTLE_SUBSEQ_SAFEGUARD_START, + BATTLE_SUBSEQ_SAFEGUARD_END, + + BATTLE_SUBSEQ_PRESENT_HEAL = 112, + BATTLE_SUBSEQ_MAGNITUDE, + BATTLE_SUBSEQ_BATON_PASS, + BATTLE_SUBSEQ_RAPID_SPIN, + BATTLE_SUBSEQ_BREAK_BIND_EFFECT, BATTLE_SUBSEQ_BLOW_AWAY_HAZARDS, - - BATTLE_SUBSEQ_FUTURE_SIGHT_DAMAGE = 121, - - BATTLE_SUBSEQ_MOVE_FAIL_TAUNTED = 133, - - BATTLE_SUBSEQ_WISH_HEAL = 136, + BATTLE_SUBSEQ_GIVE_TARGET_OWN_STATUS, + BATTLE_SUBSEQ_BOOST_ALL_STATS, + BATTLE_SUBSEQ_BELLY_DRUM, + BATTLE_SUBSEQ_FUTURE_SIGHT_DAMAGE, + BATTLE_SUBSEQ_TELEPORT, + BATTLE_SUBSEQ_FUTURE_SIGHT_START, + BATTLE_SUBSEQ_STOCKPILE, + BATTLE_SUBSEQ_SWALLOW, + BATTLE_SUBSEQ_PRINT_MESSAGE_AND_PLAY_ANIMATION, + BATTLE_SUBSEQ_TORMENT_START, + BATTLE_SUBSEQ_FLATTER, + BATTLE_SUBSEQ_MEMENTO, + BATTLE_SUBSEQ_HEAL_TARGET_PARALYSIS, + BATTLE_SUBSEQ_CHARGE, + BATTLE_SUBSEQ_TAUNT_START, + BATTLE_SUBSEQ_MOVE_FAIL_TAUNTED, + BATTLE_SUBSEQ_EXCHANGE_ITEMS, + BATTLE_SUBSEQ_COPY_ABILITY, + BATTLE_SUBSEQ_WISH_HEAL, BATTLE_SUBSEQ_INGRAIN_HEAL, - - BATTLE_SUBSEQ_MAGIC_COAT = 139, - - BATTLE_SUBSEQ_MOVE_IS_IMPRISONED = 144, - - BATTLE_SUBSEQ_SNATCH = 146, - - BATTLE_SUBSEQ_MOVE_FAIL_GRAVITY = 157, - - BATTLE_SUBSEQ_AQUA_RING_HEAL = 169, - - BATTLE_SUBSEQ_MOVE_IS_HEAL_BLOCKED = 174, - - BATTLE_SUBSEQ_LIGHTNING_ROD_REDIRECTED = 180, + BATTLE_SUBSEQ_USER_ATK_AND_DEF_DOWN_1_STAGE, + BATTLE_SUBSEQ_MAGIC_COAT, + BATTLE_SUBSEQ_BREAK_SCREENS, + BATTLE_SUBSEQ_YAWN, + BATTLE_SUBSEQ_KNOCK_OFF, + BATTLE_SUBSEQ_EXCHANGE_ABILITIES, + BATTLE_SUBSEQ_MOVE_IS_IMPRISONED, + BATTLE_SUBSEQ_RECOVER_PSN_PRZ_BRN, + BATTLE_SUBSEQ_SNATCH, + BATTLE_SUBSEQ_RECOIL_1_3, + BATTLE_SUBSEQ_TARGET_ATK_AND_DEF_DOWN_1_STAGE, + + BATTLE_SUBSEQ_USER_DEF_AND_SPDEF_UP_1_STAGE = 149, + BATTLE_SUBSEQ_USER_ATK_AND_DEF_UP_1_STAGE, + BATTLE_SUBSEQ_USER_SPATK_AND_SPDEF_UP_1_STAGE, + BATTLE_SUBSEQ_USER_ATK_AND_SPEED_UP_1_STAGE, + BATTLE_SUBSEQ_PURSUIT, + BATTLE_SUBSEQ_ROOST, + BATTLE_SUBSEQ_HEAL_TARGET_SLEEP, + BATTLE_SUBSEQ_GRAVITY_START, + BATTLE_SUBSEQ_MOVE_FAIL_GRAVITY, + BATTLE_SUBSEQ_MIRACLE_EYE, + BATTLE_SUBSEQ_HEALING_WISH, + BATTLE_SUBSEQ_TAILWIND_START, + BATTLE_SUBSEQ_USER_DEF_AND_SPDEF_DOWN_1_STAGE, + BATTLE_SUBSEQ_USER_SWAP_ATK_AND_DEF, + BATTLE_SUBSEQ_SUPPRESS_TARGET_ABILITY, + BATTLE_SUBSEQ_LUCKY_CHANT_START, + BATTLE_SUBSEQ_EXCHANGE_ATK_AND_SPATK_STAGES, + BATTLE_SUBSEQ_EXCHANGE_DEF_AND_SPDEF_STAGES, + BATTLE_SUBSEQ_GIVE_TARGET_INSOMNIA, + BATTLE_SUBSEQ_EXCHANGE_ALL_STAT_STAGES, + BATTLE_SUBSEQ_AQUA_RING_HEAL, + BATTLE_SUBSEQ_RECOIL_1_3_CHANCE_TO_BURN, + BATTLE_SUBSEQ_DEFOG, + + BATTLE_SUBSEQ_HEAL_BLOCK_START = 173, + BATTLE_SUBSEQ_MOVE_IS_HEAL_BLOCKED, + BATTLE_SUBSEQ_ATTACK_THEN_SWITCH_OUT, + + BATTLE_SUBSEQ_MOLD_BREAKER = 177, + BATTLE_SUBSEQ_ABILITY_RESTORES_HP, + BATTLE_SUBSEQ_ABSORB_AND_BOOST_FIRE_TYPE_MOVES, + BATTLE_SUBSEQ_LIGHTNING_ROD_REDIRECTED, BATTLE_SUBSEQ_BLOCKED_BY_SOUNDPROOF, - - BATTLE_SUBSEQ_COLOR_CHANGE = 188, + BATTLE_SUBSEQ_ABSORB_AND_SPEED_UP_1_STAGE, + BATTLE_SUBSEQ_DRIZZLE, + BATTLE_SUBSEQ_SAND_STREAM, + BATTLE_SUBSEQ_DROUGHT, + BATTLE_SUBSEQ_INTIMIDATE, + BATTLE_SUBSEQ_TRACE, + BATTLE_SUBSEQ_COLOR_CHANGE, BATTLE_SUBSEQ_ROUGH_SKIN, - - BATTLE_SUBSEQ_LOAFING_AROUND = 191, + BATTLE_SUBSEQ_ABILITY_RESTORE_STATUS, + BATTLE_SUBSEQ_LOAFING_AROUND, BATTLE_SUBSEQ_AFTERMATH = 193, - - BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE = 198, + BATTLE_SUBSEQ_ANTICIPATION, + BATTLE_SUBSEQ_FOREWARN, + BATTLE_SUBSEQ_SLOW_START, + BATTLE_SUBSEQ_SLOW_START_END, + BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE, BATTLE_SUBSEQ_HELD_ITEM_PRZ_RESTORE, BATTLE_SUBSEQ_HELD_ITEM_SLP_RESTORE, BATTLE_SUBSEQ_HELD_ITEM_PSN_RESTORE, @@ -127,13 +217,18 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_HELD_ITEM_HEAL_INFATUATION, BATTLE_SUBSEQ_RESTORE_A_LITTLE_HP, BATTLE_SUBSEQ_LOSE_HP_FROM_ITEM, - + BATTLE_SUBSEQ_LOSE_HP_FROM_ITEM_WITH_MESSAGE, BATTLE_SUBSEQ_TRANSFER_STICKY_BARB = 216, - - BATTLE_SUBSEQ_ESCAPE_ITEM = 222, + + BATTLE_SUBSEQ_EMBARGO_START = 218, + BATTLE_SUBSEQ_PLUCK, + BATTLE_SUBSEQ_FLING, + BATTLE_SUBSEQ_ABILITY_FORBIDS_STATUS, + BATTLE_SUBSEQ_ESCAPE_ITEM, BATTLE_SUBSEQ_BATTLE_ITEM, - BATTLE_SUBSEQ_SAFARI_THROW_BAIT = 227, + BATTLE_SUBSEQ_RECOIL_1_3_CHANCE_TO_PARALYZE = 226, + BATTLE_SUBSEQ_SAFARI_THROW_BAIT, BATTLE_SUBSEQ_SAFARI_THROW_ROCK, BATTLE_SUBSEQ_SAFARI_ESCAPE, BATTLE_SUBSEQ_ENEMY_ESCAPE, @@ -152,17 +247,25 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_HEAL_BLOCK_END, BATTLE_SUBSEQ_EMBARGO_END, BATTLE_SUBSEQ_RAGE_IS_BUILDING, + BATTLE_SUBSEQ_RECOIL_1_2, + BATTLE_SUBSEQ_BURN_OR_FLINCH, + BATTLE_SUBSEQ_FREEZE_OR_FLINCH, + BATTLE_SUBSEQ_PARALYZE_OR_FLINCH, BATTLE_SUBSEQ_LUCKY_CHANT_END = 250, BATTLE_SUBSEQ_TRICK_ROOM_END, - - BATTLE_SUBSEQ_DISOBEY_WHILE_ASLEEP = 254, + BATTLE_SUBSEQ_SNOW_WARNING, + BATTLE_SUBSEQ_FRISK, + BATTLE_SUBSEQ_DISOBEY_WHILE_ASLEEP, BATTLE_SUBSEQ_DISOBEY_DO_NOTHING, BATTLE_SUBSEQ_DISOBEY_ORDERS, BATTLE_SUBSEQ_DISOBEY_SLEEP, BATTLE_SUBSEQ_DISOBEY_HIT_SELF, - BATTLE_SUBSEQ_BAD_DREAMS = 263, + BATTLE_SUBSEQ_CHATTER = 260, + BATTLE_SUBSEQ_LUNAR_DANCE, + BATTLE_SUBSEQ_FORM_CHANGE, + BATTLE_SUBSEQ_BAD_DREAMS, BATTLE_SUBSEQ_HELD_ITEM_TEMP_ACC_UP = 265, BATTLE_SUBSEQ_HELD_ITEM_RECOIL_WHEN_HIT, @@ -170,8 +273,11 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_USE_STATUS_RECOVERY, BATTLE_SUBSEQ_USE_STAT_BOOSTER, BATTLE_SUBSEQ_USE_GUARD_SPEC, - - BATTLE_SUBSEQ_THROW_SAFARI_BALL = 275, + BATTLE_SUBSEQ_OVERWORLD_RAIN, + BATTLE_SUBSEQ_OVERWORLD_HAIL, + BATTLE_SUBSEQ_OVERWORLD_SAND, + BATTLE_SUBSEQ_OVERWORLD_FOG, + BATTLE_SUBSEQ_THROW_SAFARI_BALL, BATTLE_SUBSEQ_GRANT_EXP, BATTLE_SUBSEQ_AFTER_SELFDESTRUCT, BATTLE_SUBSEQ_CHECK_QUICK_CLAW, @@ -179,7 +285,8 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_NO_TARGET = 281, BATTLE_SUBSEQ_BIDE_NO_TARGET, - BATTLE_SUBSEQ_ENEMY_ESCAPE_FAILED = 286, + BATTLE_SUBSEQ_PRESSURE = 285, + BATTLE_SUBSEQ_ENEMY_ESCAPE_FAILED, BATTLE_SUBSEQ_VANISH_OFF, BATTLE_SUBSEQ_TAUNT_END = 288, @@ -188,6 +295,9 @@ enum NARCFilesBattleSubSeq { BATTLE_SUBSEQ_WAIT_MOVE_ANIMATION = 291, BATTLE_SUBSEQ_CHECK_SHAYMIN_FORM = 293, + BATTLE_SUBSEQ_OVERWORLD_SUN, + BATTLE_SUBSEQ_OVERWORLD_TRICK_ROOM, + BATTLE_SUBSEQ_GIRATINA_FORM_CHANGE, }; #endif // POKEPLATINUM_NARC_FILES_BATTLE_SKILL_SUBSEQ_H diff --git a/include/data/move_side_effect_subscripts.h b/include/data/move_side_effect_subscripts.h new file mode 100644 index 0000000000..f1731c77e4 --- /dev/null +++ b/include/data/move_side_effect_subscripts.h @@ -0,0 +1,150 @@ +#include "constants/battle/side_effects.h" +#include "constants/narc_files/battle_skill_subseq.h" + +static const int sSideEffectSubscripts[] = { + [MOVE_SUBSCRIPT_PTR_NONE] = NULL, + [MOVE_SUBSCRIPT_PTR_SLEEP] = BATTLE_SUBSEQ_FALL_ASLEEP, + [MOVE_SUBSCRIPT_PTR_POISON] = BATTLE_SUBSEQ_POISON, + [MOVE_SUBSCRIPT_PTR_BURN] = BATTLE_SUBSEQ_BURN, + [MOVE_SUBSCRIPT_PTR_FREEZE] = BATTLE_SUBSEQ_FREEZE, + [MOVE_SUBSCRIPT_PTR_PARALYZE] = BATTLE_SUBSEQ_PARALYZE, + [MOVE_SUBSCRIPT_PTR_BADLY_POISON] = BATTLE_SUBSEQ_BADLY_POISON, + [MOVE_SUBSCRIPT_PTR_CONFUSE] = BATTLE_SUBSEQ_CONFUSE, + [MOVE_SUBSCRIPT_PTR_FLINCH] = BATTLE_SUBSEQ_FLINCH_MON, + [MOVE_SUBSCRIPT_PTR_REST] = BATTLE_SUBSEQ_REST, + [MOVE_SUBSCRIPT_PTR_UPROAR] = BATTLE_SUBSEQ_UPROAR, + [MOVE_SUBSCRIPT_PTR_PAY_DAY] = BATTLE_SUBSEQ_PAY_DAY, + [MOVE_SUBSCRIPT_PTR_VANISH_CHARGE_TURN] = BATTLE_SUBSEQ_VANISH_ON_CHARGE_TURN, + [MOVE_SUBSCRIPT_PTR_BIND_TARGET] = BATTLE_SUBSEQ_BIND_START, + [MOVE_SUBSCRIPT_PTR_QUARTER_RECOIL] = BATTLE_SUBSEQ_RECOIL_1_4, + [MOVE_SUBSCRIPT_PTR_ATTACK_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_DEFENSE_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SPEED_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_ATTACK_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_DEFENSE_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ACCURACY_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_EVASION_UP_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_DEFENSE_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SPEED_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_ATTACK_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_DEFENSE_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_EVASION_DOWN_1_STAGE] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_RECHARGE_TURN] = BATTLE_SUBSEQ_RECHARGE_TURN, + [MOVE_SUBSCRIPT_PTR_SET_RAGE_FLAG] = BATTLE_SUBSEQ_SET_RAGE_FLAG, + [MOVE_SUBSCRIPT_PTR_STEAL_ITEM] = BATTLE_SUBSEQ_STEAL_ITEM, + [MOVE_SUBSCRIPT_PTR_MEAN_LOOK] = BATTLE_SUBSEQ_MEAN_LOOK, + [MOVE_SUBSCRIPT_PTR_NIGHTMARE_START] = BATTLE_SUBSEQ_NIGHTMARE_START, + [MOVE_SUBSCRIPT_PTR_BOOST_ALL_STATS] = BATTLE_SUBSEQ_BOOST_ALL_STATS, + [MOVE_SUBSCRIPT_PTR_RAPID_SPIN] = BATTLE_SUBSEQ_RAPID_SPIN, + [MOVE_SUBSCRIPT_PTR_HEAL_TARGET_PARALYSIS] = BATTLE_SUBSEQ_HEAL_TARGET_PARALYSIS, + [MOVE_SUBSCRIPT_PTR_USER_ATK_AND_DEF_DOWN_1_STAGE] = BATTLE_SUBSEQ_USER_ATK_AND_DEF_DOWN_1_STAGE, + [MOVE_SUBSCRIPT_PTR_RECOIL_1_3] = BATTLE_SUBSEQ_RECOIL_1_3, + [MOVE_SUBSCRIPT_PTR_ATTACK_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_DEFENSE_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SPEED_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_ATTACK_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_DEFENSE_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ACCURACY_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_EVASION_UP_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_DEFENSE_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SPEED_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_ATTACK_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_SP_DEFENSE_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_EVASION_DOWN_2_STAGES] = BATTLE_SUBSEQ_UPDATE_STAT_STAGE, + [MOVE_SUBSCRIPT_PTR_THRASH] = BATTLE_SUBSEQ_THRASH, + [MOVE_SUBSCRIPT_PTR_KNOCK_OFF] = BATTLE_SUBSEQ_KNOCK_OFF, + [MOVE_SUBSCRIPT_PTR_USER_DEF_AND_SPDEF_UP_1_STAGE] = BATTLE_SUBSEQ_USER_DEF_AND_SPDEF_UP_1_STAGE, + [MOVE_SUBSCRIPT_PTR_USER_ATK_AND_DEF_UP_1_STAGE] = BATTLE_SUBSEQ_USER_ATK_AND_DEF_UP_1_STAGE, + [MOVE_SUBSCRIPT_PTR_TARGET_ATK_AND_DEF_DOWN_1_STAGE] = BATTLE_SUBSEQ_TARGET_ATK_AND_DEF_DOWN_1_STAGE, + [MOVE_SUBSCRIPT_PTR_USER_SPATK_AND_SPDEF_UP_1_STAGE] = BATTLE_SUBSEQ_USER_SPATK_AND_SPDEF_UP_1_STAGE, + [MOVE_SUBSCRIPT_PTR_USER_ATK_AND_SPEED_UP_1_STAGE] = BATTLE_SUBSEQ_USER_ATK_AND_SPEED_UP_1_STAGE, + [MOVE_SUBSCRIPT_PTR_DRAIN_HALF_DAMAGE_DEALT] = BATTLE_SUBSEQ_DRAIN_HALF_DAMAGE_DEALT, + [MOVE_SUBSCRIPT_PTR_DREAM_EATER] = BATTLE_SUBSEQ_DREAM_EATER, + [MOVE_SUBSCRIPT_PTR_RESET_ALL_STAT_STAGES] = BATTLE_SUBSEQ_RESET_ALL_STAT_STAGES, + [MOVE_SUBSCRIPT_PTR_BIDE_START] = BATTLE_SUBSEQ_BIDE_START, + [MOVE_SUBSCRIPT_PTR_STRUGGLE] = BATTLE_SUBSEQ_STRUGGLE, + [MOVE_SUBSCRIPT_PTR_CONVERSION] = BATTLE_SUBSEQ_CONVERSION, + [MOVE_SUBSCRIPT_PTR_RECOVER_HALF_MAX_HP] = BATTLE_SUBSEQ_RECOVER_HALF_MAX_HP, + [MOVE_SUBSCRIPT_PTR_LIGHT_SCREEN] = BATTLE_SUBSEQ_LIGHT_SCREEN, + [MOVE_SUBSCRIPT_PTR_REFLECT] = BATTLE_SUBSEQ_REFLECT, + [MOVE_SUBSCRIPT_PTR_MIST] = BATTLE_SUBSEQ_MIST, + [MOVE_SUBSCRIPT_PTR_FOCUS_ENERGY] = BATTLE_SUBSEQ_FOCUS_ENERGY, + [MOVE_SUBSCRIPT_PTR_MIMIC] = BATTLE_SUSBEQ_MIMIC, + [MOVE_SUBSCRIPT_PTR_LEECH_SEED_START] = BATTLE_SUBSEQ_LEECH_SEED_START, + [MOVE_SUBSCRIPT_PTR_DISABLE_START] = BATTLE_SUBSEQ_DISABLE_START, + [MOVE_SUBSCRIPT_PTR_ENCORE_START] = BATTLE_SUBSEQ_ENCORE_START, + [MOVE_SUBSCRIPT_PTR_PAIN_SPLIT] = BATTLE_SUBSEQ_PAIN_SPLIT, + [MOVE_SUBSCRIPT_PTR_CONVERSION_2] = BATTLE_SUBSEQ_CONVERSION_2, + [MOVE_SUBSCRIPT_PTR_LOCK_ON] = BATTLE_SUBSEQ_LOCK_ON, + [MOVE_SUBSCRIPT_PTR_SKETCH] = BATTLE_SUBSEQ_SKETCH, + [MOVE_SUBSCRIPT_PTR_FEINT] = BATTLE_SUBSEQ_FEINT, + [MOVE_SUBSCRIPT_PTR_DESTINY_BOND] = BATTLE_SUBSEQ_DESTINY_BOND, + [MOVE_SUBSCRIPT_PTR_REDUCE_TARGET_PP] = BATTLE_SUBSEQ_REDUCE_TARGET_PP, + [MOVE_SUBSCRIPT_PTR_PROTECT] = BATTLE_SUBSEQ_PROTECT, + [MOVE_SUBSCRIPT_PTR_HEAL_BELL] = BATTLE_SUBSEQ_HEAL_BELL, + [MOVE_SUBSCRIPT_PTR_TRY_SUBSTITUTE] = BATTLE_SUBSEQ_TRY_SUBSTITUTE, + [MOVE_SUBSCRIPT_PTR_FORCE_TARGET_TO_SWITCH_OR_FLEE] = BATTLE_SUBSEQ_FORCE_TARGET_TO_SWITCH_OR_FLEE, + [MOVE_SUBSCRIPT_PTR_TRANSFORM_INTO_TARGET] = BATTLE_SUSBEQ_TRANSFORM_INTO_TARGET, + [MOVE_SUBSCRIPT_PTR_MINIMIZE] = BATTLE_SUBSEQ_MINIMIZE, + [MOVE_SUBSCRIPT_PTR_CURSE_NORMAL] = BATTLE_SUBSEQ_CURSE_NORMAL, + [MOVE_SUBSCRIPT_PTR_CURSE_GHOST] = BATTLE_SUBSEQ_CURSE_GHOST, + [MOVE_SUBSCRIPT_PTR_PRINT_MESSAGE_AND_PLAY_ANIMATION] = BATTLE_SUBSEQ_PRINT_MESSAGE_AND_PLAY_ANIMATION, + [MOVE_SUBSCRIPT_PTR_FORESIGHT] = BATTLE_SUBSEQ_FORESIGHT, + [MOVE_SUBSCRIPT_PTR_PERISH_SONG_START] = BATTLE_SUBSEQ_PERISH_SONG_START, + [MOVE_SUBSCRIPT_PTR_WEATHER_START] = BATTLE_SUBSEQ_WEATHER_START, + [MOVE_SUBSCRIPT_PTR_SWAGGER] = BATTLE_SUBSEQ_SWAGGER, + [MOVE_SUBSCRIPT_PTR_INFATUATE] = BATTLE_SUBSEQ_INFATUATE, + [MOVE_SUBSCRIPT_PTR_SAFEGUARD_START] = BATTLE_SUBSEQ_SAFEGUARD_START, + [MOVE_SUBSCRIPT_PTR_PRESENT_HEAL] = BATTLE_SUBSEQ_PRESENT_HEAL, + [MOVE_SUBSCRIPT_PTR_MAGNITUDE] = BATTLE_SUBSEQ_MAGNITUDE, + [MOVE_SUBSCRIPT_PTR_BATON_PASS] = BATTLE_SUBSEQ_BATON_PASS, + [MOVE_SUBSCRIPT_PTR_BELLY_DRUM] = BATTLE_SUBSEQ_BELLY_DRUM, + [MOVE_SUBSCRIPT_PTR_TELEPORT] = BATTLE_SUBSEQ_TELEPORT, + [MOVE_SUBSCRIPT_PTR_FUTURE_SIGHT_START] = BATTLE_SUBSEQ_FUTURE_SIGHT_START, + [MOVE_SUBSCRIPT_PTR_STOCKPILE] = BATTLE_SUBSEQ_STOCKPILE, + [MOVE_SUBSCRIPT_PTR_SWALLOW] = BATTLE_SUBSEQ_SWALLOW, + [MOVE_SUBSCRIPT_PTR_TORMENT_START] = BATTLE_SUBSEQ_TORMENT_START, + [MOVE_SUBSCRIPT_PTR_FLATTER] = BATTLE_SUBSEQ_FLATTER, + [MOVE_SUBSCRIPT_PTR_MEMENTO] = BATTLE_SUBSEQ_MEMENTO, + [MOVE_SUBSCRIPT_PTR_CHARGE] = BATTLE_SUBSEQ_CHARGE, + [MOVE_SUBSCRIPT_PTR_TAUNT_START] = BATTLE_SUBSEQ_TAUNT_START, + [MOVE_SUBSCRIPT_PTR_EXCHANGE_ITEMS] = BATTLE_SUBSEQ_EXCHANGE_ITEMS, + [MOVE_SUBSCRIPT_PTR_COPY_ABILITY] = BATTLE_SUBSEQ_COPY_ABILITY, + [MOVE_SUBSCRIPT_PTR_BREAK_SCREENS] = BATTLE_SUBSEQ_BREAK_SCREENS, + [MOVE_SUBSCRIPT_PTR_YAWN] = BATTLE_SUBSEQ_YAWN, + [MOVE_SUBSCRIPT_PTR_EXCHANGE_ABILITIES] = BATTLE_SUBSEQ_EXCHANGE_ABILITIES, + [MOVE_SUBSCRIPT_PTR_RECOVER_PSN_PRZ_BRN] = BATTLE_SUBSEQ_RECOVER_PSN_PRZ_BRN, + [MOVE_SUBSCRIPT_PTR_ROOST] = BATTLE_SUBSEQ_ROOST, + [MOVE_SUBSCRIPT_PTR_HEAL_TARGET_SLEEP] = BATTLE_SUBSEQ_HEAL_TARGET_SLEEP, + [MOVE_SUBSCRIPT_PTR_GRAVITY_START] = BATTLE_SUBSEQ_GRAVITY_START, + [MOVE_SUBSCRIPT_PTR_MIRACLE_EYE] = BATTLE_SUBSEQ_MIRACLE_EYE, + [MOVE_SUBSCRIPT_PTR_HEALING_WISH] = BATTLE_SUBSEQ_HEALING_WISH, + [MOVE_SUBSCRIPT_PTR_TAILWIND_START] = BATTLE_SUBSEQ_TAILWIND_START, + [MOVE_SUBSCRIPT_PTR_USER_DEF_AND_SPDEF_DOWN_1_STAGE] = BATTLE_SUBSEQ_USER_DEF_AND_SPDEF_DOWN_1_STAGE, + [MOVE_SUBSCRIPT_PTR_USER_SWAP_ATK_AND_DEF] = BATTLE_SUBSEQ_USER_SWAP_ATK_AND_DEF, + [MOVE_SUBSCRIPT_PTR_SUPPRESS_TARGET_ABILITY] = BATTLE_SUBSEQ_SUPPRESS_TARGET_ABILITY, + [MOVE_SUBSCRIPT_PTR_LUCKY_CHANT_START] = BATTLE_SUBSEQ_LUCKY_CHANT_START, + [MOVE_SUBSCRIPT_PTR_EXCHANGE_ATK_AND_SPATK_STAGES] = BATTLE_SUBSEQ_EXCHANGE_ATK_AND_SPATK_STAGES, + [MOVE_SUBSCRIPT_PTR_EXCHANGE_DEF_AND_SPDEF_STAGES] = BATTLE_SUBSEQ_EXCHANGE_DEF_AND_SPDEF_STAGES, + [MOVE_SUBSCRIPT_PTR_GIVE_TARGET_INSOMNIA] = BATTLE_SUBSEQ_GIVE_TARGET_INSOMNIA, + [MOVE_SUBSCRIPT_PTR_EXCHANGE_ALL_STAT_STAGES] = BATTLE_SUBSEQ_EXCHANGE_ALL_STAT_STAGES, + [MOVE_SUBSCRIPT_PTR_RECOIL_1_3_CHANCE_TO_BURN] = BATTLE_SUBSEQ_RECOIL_1_3_CHANCE_TO_BURN, + [MOVE_SUBSCRIPT_PTR_DEFOG] = BATTLE_SUBSEQ_DEFOG, + [MOVE_SUBSCRIPT_PTR_HEAL_BLOCK_START] = BATTLE_SUBSEQ_HEAL_BLOCK_START, + [MOVE_SUBSCRIPT_PTR_ATTACK_THEN_SWITCH_OUT] = BATTLE_SUBSEQ_ATTACK_THEN_SWITCH_OUT, + [MOVE_SUBSCRIPT_PTR_EMBARGO_START] = BATTLE_SUBSEQ_EMBARGO_START, + [MOVE_SUBSCRIPT_PTR_PLUCK] = BATTLE_SUBSEQ_PLUCK, + [MOVE_SUBSCRIPT_PTR_FLING] = BATTLE_SUBSEQ_FLING, + [MOVE_SUBSCRIPT_PTR_RECOIL_1_3_CHANCE_TO_PARALYZE] = BATTLE_SUBSEQ_RECOIL_1_3_CHANCE_TO_PARALYZE, + [MOVE_SUBSCRIPT_PTR_RECOIL_1_2] = BATTLE_SUBSEQ_RECOIL_1_2, + [MOVE_SUBSCRIPT_PTR_BURN_OR_FLINCH] = BATTLE_SUBSEQ_BURN_OR_FLINCH, + [MOVE_SUBSCRIPT_PTR_FREEZE_OR_FLINCH] = BATTLE_SUBSEQ_FREEZE_OR_FLINCH, + [MOVE_SUBSCRIPT_PTR_PARALYZE_OR_FLINCH] = BATTLE_SUBSEQ_PARALYZE_OR_FLINCH, + [MOVE_SUBSCRIPT_PTR_CHATTER] = BATTLE_SUBSEQ_CHATTER, + [MOVE_SUBSCRIPT_PTR_LUNAR_DANCE] = BATTLE_SUBSEQ_LUNAR_DANCE, + [MOVE_SUBSCRIPT_PTR_GIVE_TARGET_OWN_STATUS] = BATTLE_SUBSEQ_GIVE_TARGET_OWN_STATUS, +}; diff --git a/include/data/terrain/to_secondary_effect.h b/include/data/terrain/to_secondary_effect.h index c3759905b4..e16f2e87bd 100644 --- a/include/data/terrain/to_secondary_effect.h +++ b/include/data/terrain/to_secondary_effect.h @@ -2,17 +2,17 @@ #include "constants/battle/terrain.h" static const u32 sTerrainSideEffect[] = { - [TERRAIN_PLAIN] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_ACCURACY_DOWN_1_STAGE, - [TERRAIN_SAND] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_ACCURACY_DOWN_1_STAGE, - [TERRAIN_GRASS] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_SLEEP, - [TERRAIN_PUDDLE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_SLEEP, - [TERRAIN_MOUNTAIN] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_FLINCH, - [TERRAIN_CAVE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_FLINCH, - [TERRAIN_SNOW] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_FREEZE, - [TERRAIN_WATER] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_ATTACK_DOWN_1_STAGE, - [TERRAIN_ICE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_FREEZE, - [TERRAIN_BUILDING] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_PARALYZE, - [TERRAIN_GREAT_MARSH] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_SPEED_DOWN_1_STAGE, - [TERRAIN_BRIDGE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_EVASION_DOWN_1_STAGE, - [TERRAIN_SPECIAL] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SIDE_EFFECT_PARALYZE, + [TERRAIN_PLAIN] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_1_STAGE, + [TERRAIN_SAND] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_ACCURACY_DOWN_1_STAGE, + [TERRAIN_GRASS] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_SLEEP, + [TERRAIN_PUDDLE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_SLEEP, + [TERRAIN_MOUNTAIN] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_FLINCH, + [TERRAIN_CAVE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_FLINCH, + [TERRAIN_SNOW] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_FREEZE, + [TERRAIN_WATER] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_1_STAGE, + [TERRAIN_ICE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_FREEZE, + [TERRAIN_BUILDING] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_PARALYZE, + [TERRAIN_GREAT_MARSH] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_SPEED_DOWN_1_STAGE, + [TERRAIN_BRIDGE] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_EVASION_DOWN_1_STAGE, + [TERRAIN_SPECIAL] = MOVE_SIDE_EFFECT_TO_DEFENDER | MOVE_SUBSCRIPT_PTR_PARALYZE, }; diff --git a/include/overlay016/ov16_0223DF00.h b/include/overlay016/ov16_0223DF00.h index 69cfc9c7bf..567a5007a0 100644 --- a/include/overlay016/ov16_0223DF00.h +++ b/include/overlay016/ov16_0223DF00.h @@ -207,7 +207,7 @@ u16 * ov16_0223F1F0(BattleSystem * param0); int ov16_0223F1F8(BattleSystem * param0); u16 * ov16_0223F204(BattleSystem * param0); u16 * ov16_0223F210(BattleSystem * param0); -int ov16_0223F21C(BattleSystem * param0); +int BattleSystem_FieldWeather(BattleSystem * param0); u8 ov16_0223F228(BattleSystem * param0); void ov16_0223F234(BattleSystem * param0, u8 param1); int ov16_0223F240(BattleSystem * param0); diff --git a/include/overlay016/ov16_0225177C.h b/include/overlay016/ov16_0225177C.h index 21b6c7898f..ff0ea96a36 100644 --- a/include/overlay016/ov16_0225177C.h +++ b/include/overlay016/ov16_0225177C.h @@ -226,6 +226,13 @@ BOOL BattleIO_QueueIsEmpty(BattleContext *battleCtx); * @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); /** @@ -270,11 +277,65 @@ void Battler_AddVal(BattleContext *battleCtx, int battler, enum BattleMonParam p * @param val Value to be added to the Pokemon's data field */ void BattleMon_AddVal(BattleMon *mon, enum BattleMonParam paramID, int val); -u8 BattleSystem_CompareBattlerSpeed(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4); -void BattleSystem_NoExpGain(BattleContext * param0, int param1); -void BattleSystem_FlagExpGain(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_CheckPrimaryEffect(BattleSystem * param0, BattleContext * param1, int * param2); -BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq); + +/** + * @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 0 if battler 1 should move first, 1 if battler 2 should move first, + * 2 if battler 2 should move first and won a speed tie. + */ +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. @@ -529,8 +590,35 @@ void BattleSystem_UpdateLastResort(BattleSystem * param0, BattleContext * param1 * @return The number of moves known. */ int Battler_CountMoves(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -int BattleSystem_CheckImmunityAbilities(BattleContext * param0, int param1, int param2); -BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem * param0, BattleContext * param1, int param2); + +/** + * @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 @@ -543,7 +631,16 @@ BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem * param0, BattleContext * p * than 1. */ int BattleSystem_Divide(int dividend, int divisor); -int BattleSystem_ShowMonChecks(BattleSystem * param0, BattleContext * param1); + +/** + * @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. @@ -559,8 +656,34 @@ int BattleSystem_ShowMonChecks(BattleSystem * param0, BattleContext * param1); * @return A random opponent of the attacker's. */ int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCtx, int attacker); -BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq); -BOOL BattleSystem_RecoverStatusByAbility(BattleSystem * param0, BattleContext * param1, int param2, int param3); + +/** + * @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. @@ -573,10 +696,62 @@ BOOL BattleSystem_RecoverStatusByAbility(BattleSystem * param0, BattleContext * */ BOOL Ability_ForbidsStatus(BattleContext *battleSys, int ability, int status); BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * battleCtx, int controllerCommand); -BOOL BattleSystem_TriggerHeldItem(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_TriggerLeftovers(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_TriggerHeldItemOnStatus(BattleSystem * param0, BattleContext * param1, int param2, int * param3); -BOOL BattleSystem_TriggerDetrimentalHeldItem(BattleSystem * param0, BattleContext * param1, int param2); + +/** + * @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. @@ -586,9 +761,36 @@ BOOL BattleSystem_TriggerDetrimentalHeldItem(BattleSystem * param0, BattleContex * @return Integer ID of the battler's held item */ u16 Battler_HeldItem(BattleContext *battleCtx, int battler); -BOOL Battler_MovedThisTurn(BattleContext * param0, int param1); -BOOL BattleSystem_TriggerHeldItemOnHit(BattleSystem * param0, BattleContext * param1, int * param2); -s32 Battler_HeldItemEffect(BattleContext * param0, int param1); + +/** + * @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. @@ -703,7 +905,19 @@ u8 BattleContext_IOBufferVal(BattleContext *battleCtx, int battler); BOOL Battler_SubstituteWasHit(BattleContext *battleCtx, int battler); BOOL BattleSystem_TrainerIsOT(BattleSystem * param0, BattleContext * param1); BOOL BattleSystem_PokemonIsOT(BattleSystem * param0, Pokemon * param1); -BOOL BattleSystem_UpdateWeatherForms(BattleSystem * param0, BattleContext * param1, int * param2); + +/** + * @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); void ov16_0225A1B0(BattleSystem * param0, BattleContext * param1); /** diff --git a/include/struct_defs/battle_system.h b/include/struct_defs/battle_system.h index 86fa90fb57..9476c55313 100644 --- a/include/struct_defs/battle_system.h +++ b/include/struct_defs/battle_system.h @@ -126,7 +126,7 @@ struct BattleSystem { u16 unk_241E; int unk_2420; int unk_2424; - int unk_2428; + int fieldWeather; int unk_242C; u32 unk_2430; int unk_2434; diff --git a/res/items/pl_item_data.csv b/res/items/pl_item_data.csv index 358ea89afd..f21e8bf798 100644 --- a/res/items/pl_item_data.csv +++ b/res/items/pl_item_data.csv @@ -256,7 +256,7 @@ ITEM_FOCUS_SASH,200,HOLD_EFFECT_ENDURE,0,0,0,10,0,31,false,false,POCKET_ITEMS,0, ITEM_ZOOM_LENS,200,HOLD_EFFECT_ACCURACY_UP_SLOWER,20,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_METRONOME,200,HOLD_EFFECT_BOOST_REPEATED,10,0,0,30,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_IRON_BALL,200,HOLD_EFFECT_SPEED_DOWN_GROUNDED,0,0,0,130,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 -ITEM_LAGGING_TAIL,200,HOLD_EFFECT_SPEED_DOWN,0,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 +ITEM_LAGGING_TAIL,200,HOLD_EFFECT_PRIORITY_DOWN,0,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_DESTINY_KNOT,200,HOLD_EFFECT_RECIPROCATE_INFAT,0,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_BLACK_SLUDGE,200,HOLD_EFFECT_HP_RESTORE_PSN_TYPE,16,0,0,30,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_ICY_ROCK,200,HOLD_EFFECT_EXTEND_HAIL,3,0,0,40,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 @@ -293,7 +293,7 @@ ITEM_DREAD_PLATE,1000,HOLD_EFFECT_ARCEUS_DARK,20,0,0,90,0,31,false,false,POCKET_ ITEM_IRON_PLATE,1000,HOLD_EFFECT_ARCEUS_STEEL,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_ODD_INCENSE,9600,HOLD_EFFECT_STRENGTHEN_PSYCHIC,20,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_ROCK_INCENSE,9600,HOLD_EFFECT_STRENGTHEN_ROCK,20,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 -ITEM_FULL_INCENSE,9600,HOLD_EFFECT_SPEED_DOWN,0,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 +ITEM_FULL_INCENSE,9600,HOLD_EFFECT_PRIORITY_DOWN,0,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_WAVE_INCENSE,9600,HOLD_EFFECT_STRENGTHEN_WATER,20,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_ROSE_INCENSE,9600,HOLD_EFFECT_STRENGTHEN_GRASS,20,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 ITEM_LUCK_INCENSE,9600,HOLD_EFFECT_MONEY_UP,10,0,0,10,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0 diff --git a/src/overlay016/battle_controller.c b/src/overlay016/battle_controller.c index 6b916cec71..7b457691c4 100644 --- a/src/overlay016/battle_controller.c +++ b/src/overlay016/battle_controller.c @@ -253,7 +253,7 @@ static void BattleController_TrainerMessage(BattleSystem *battleSys, BattleConte static void BattleController_ShowBattleMon(BattleSystem *battleSys, BattleContext *battleCtx) { - int nextSeq = BattleSystem_ShowMonChecks(battleSys, battleCtx); + int nextSeq = BattleSystem_TriggerEffectOnSwitch(battleSys, battleCtx); if (nextSeq) { LOAD_SUBSEQ(nextSeq); @@ -304,41 +304,6 @@ enum { COMMAND_SELECTION_CLEAR_TOUCH_SCREEN, }; -enum { - PLAYER_INPUT_FIGHT = 1, - PLAYER_INPUT_ITEM, - PLAYER_INPUT_PARTY, - PLAYER_INPUT_RUN, - - PLAYER_INPUT_SAFARI_BALL = PLAYER_INPUT_FIGHT, - PLAYER_INPUT_SAFARI_BAIT = PLAYER_INPUT_ITEM, - PLAYER_INPUT_SAFARI_ROCK = PLAYER_INPUT_PARTY, - PLAYER_INPUT_SAFARI_RUN = PLAYER_INPUT_RUN, - PLAYER_INPUT_SAFARI_WAIT, - - PLAYER_INPUT_PAL_PARK_BALL = PLAYER_INPUT_FIGHT, - PLAYER_INPUT_PAL_PARK_RUN = PLAYER_INPUT_RUN, - - PLAYER_INPUT_MOVE_1 = 1, - PLAYER_INPUT_MOVE_2, - PLAYER_INPUT_MOVE_3, - PLAYER_INPUT_MOVE_4, - - PLAYER_INPUT_PARTY_SLOT_1 = 1, - PLAYER_INPUT_PARTY_SLOT_2, - PLAYER_INPUT_PARTY_SLOT_3, - PLAYER_INPUT_PARTY_SLOT_4, - PLAYER_INPUT_PARTY_SLOT_5, - PLAYER_INPUT_PARTY_SLOT_6, - - PLAYER_INPUT_TARGET_BATTLER_1 = 1, - PLAYER_INPUT_TARGET_BATTLER_2, - PLAYER_INPUT_TARGET_BATTLER_3, - PLAYER_INPUT_TARGET_BATTLER_4, - - PLAYER_INPUT_CANCEL = 0xFF, -}; - static inline BOOL SingleControllerForSide(BattleContext *battleCtx, int battler, int side) { return (battler == side + 2 && battleCtx->curCommandState[side] != COMMAND_SELECTION_END); @@ -1720,7 +1685,7 @@ static void BattleController_CheckMonConditions(BattleSystem *battleSys, BattleC if ((battleCtx->battleMons[battler].moveEffectsMask & MOVE_EFFECT_YAWN) == FALSE) { battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = 4; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_MOVE_EFFECT; PrepareSubroutineSequence(battleCtx, BATTLE_SUBSEQ_FALL_ASLEEP); state = STATE_BREAK_OUT; @@ -2822,7 +2787,7 @@ static BOOL BattleController_TriggerImmunityAbilities(BattleSystem *battleSys, B do { switch (battleCtx->abilityCheckState) { case IMMUNITY_ABILITY_STATE_CHECK: - int nextSeq = BattleSystem_CheckImmunityAbilities(battleCtx, battleCtx->attacker, battleCtx->defender); + int nextSeq = BattleSystem_TriggerImmunityAbility(battleCtx, battleCtx->attacker, battleCtx->defender); if ((nextSeq && (battleCtx->moveStatusFlags & MOVE_STATUS_DID_NOT_HIT) == FALSE) || nextSeq == BATTLE_SUBSEQ_BLOCKED_BY_SOUNDPROOF) { @@ -3334,7 +3299,7 @@ static void BattleController_TryMove(BattleSystem *battleSys, BattleContext *bat static void BattleController_PrimaryEffect(BattleSystem *battleSys, BattleContext *battleCtx) { int nextSeq; - if (BattleSystem_CheckPrimaryEffect(battleSys, battleCtx, &nextSeq) == TRUE) { + if (BattleSystem_TriggerPrimaryEffect(battleSys, battleCtx, &nextSeq) == TRUE) { LOAD_SUBSEQ(nextSeq); battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; battleCtx->commandNext = BATTLE_CONTROL_MOVE_FAILED; @@ -3711,7 +3676,7 @@ static void BattleController_AfterMoveEffects(BattleSystem *battleSys, BattleCon } case AFTER_MOVE_EFFECT_TRIGGER_SWITCH_IN_EFFECTS: - int switchinSeq = BattleSystem_ShowMonChecks(battleSys, battleCtx); + int switchinSeq = BattleSystem_TriggerEffectOnSwitch(battleSys, battleCtx); if (switchinSeq) { LOAD_SUBSEQ(switchinSeq); battleCtx->commandNext = battleCtx->command; @@ -4011,7 +3976,7 @@ static void BattleController_MoveEnd(BattleSystem *battleSys, BattleContext *bat return; } - int nextSeq = BattleSystem_ShowMonChecks(battleSys, battleCtx); + int nextSeq = BattleSystem_TriggerEffectOnSwitch(battleSys, battleCtx); if (nextSeq) { LOAD_SUBSEQ(nextSeq); battleCtx->commandNext = battleCtx->command; @@ -4682,7 +4647,7 @@ static BOOL BattleController_CheckExtraFlinch(BattleSystem *battleSys, BattleCon && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_TRIGGERS_KINGS_ROCK) && DEFENDING_MON.curHP) { battleCtx->sideEffectMon = battleCtx->defender; - battleCtx->sideEffectType = 2; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; LOAD_SUBSEQ(BATTLE_SUBSEQ_FLINCH_MON); battleCtx->commandNext = battleCtx->command; diff --git a/src/overlay016/battle_script.c b/src/overlay016/battle_script.c index e85fe48e26..3b18f62ec0 100644 --- a/src/overlay016/battle_script.c +++ b/src/overlay016/battle_script.c @@ -699,8 +699,8 @@ static BOOL BtlCmd_ShowEncounter(BattleSystem *battleSys, BattleContext *battleC } } - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); break; case BTLSCR_ENEMY: @@ -708,8 +708,8 @@ static BOOL BtlCmd_ShowEncounter(BattleSystem *battleSys, BattleContext *battleC battlerData = BattleSystem_BattlerData(battleSys, i); if (battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) { - BattleSystem_NoExpGain(battleCtx, i); - BattleSystem_FlagExpGain(battleSys, battleCtx, i); + BattleSystem_ClearSideExpGain(battleCtx, i); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, i); BattleIO_ShowEncounter(battleSys, i); BattleSystem_DexFlagSeen(battleSys, i); } @@ -720,11 +720,11 @@ static BOOL BtlCmd_ShowEncounter(BattleSystem *battleSys, BattleContext *battleC battlerData = BattleSystem_BattlerData(battleSys, battleCtx->attacker); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->attacker); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->attacker); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->attacker); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->attacker); } BattleSystem_DexFlagSeen(battleSys, battleCtx->attacker); @@ -735,11 +735,11 @@ static BOOL BtlCmd_ShowEncounter(BattleSystem *battleSys, BattleContext *battleC battlerData = BattleSystem_BattlerData(battleSys, battleCtx->defender); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->defender); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->defender); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->defender); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->defender); } BattleSystem_DexFlagSeen(battleSys, battleCtx->defender); @@ -750,11 +750,11 @@ static BOOL BtlCmd_ShowEncounter(BattleSystem *battleSys, BattleContext *battleC battlerData = BattleSystem_BattlerData(battleSys, battleCtx->switchedMon); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->switchedMon); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->switchedMon); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->switchedMon); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->switchedMon); } BattleSystem_DexFlagSeen(battleSys, battleCtx->switchedMon); @@ -805,8 +805,8 @@ static BOOL BtlCmd_ShowPokemon(BattleSystem *battleSys, BattleContext *battleCtx } } - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); break; case BTLSCR_ENEMY: @@ -814,8 +814,8 @@ static BOOL BtlCmd_ShowPokemon(BattleSystem *battleSys, BattleContext *battleCtx battlerData = BattleSystem_BattlerData(battleSys, i); if (battlerData->battlerType & 0x1) { - BattleSystem_NoExpGain(battleCtx, i); - BattleSystem_FlagExpGain(battleSys, battleCtx, i); + BattleSystem_ClearSideExpGain(battleCtx, i); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, i); BattleIO_ShowPokemon(battleSys, i, NULL, 0); BattleSystem_DexFlagSeen(battleSys, i); } @@ -826,11 +826,11 @@ static BOOL BtlCmd_ShowPokemon(BattleSystem *battleSys, BattleContext *battleCtx battlerData = BattleSystem_BattlerData(battleSys, battleCtx->attacker); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->attacker); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->attacker); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->attacker); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->attacker); } BattleSystem_DexFlagSeen(battleSys, battleCtx->attacker); @@ -841,11 +841,11 @@ static BOOL BtlCmd_ShowPokemon(BattleSystem *battleSys, BattleContext *battleCtx battlerData = BattleSystem_BattlerData(battleSys, battleCtx->defender); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->defender); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->defender); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->defender); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->defender); } BattleSystem_DexFlagSeen(battleSys, battleCtx->defender); @@ -856,11 +856,11 @@ static BOOL BtlCmd_ShowPokemon(BattleSystem *battleSys, BattleContext *battleCtx battlerData = BattleSystem_BattlerData(battleSys, battleCtx->switchedMon); if ((battlerData->battlerType & BATTLER_TYPE_SOLO_ENEMY) == FALSE) { - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); - BattleSystem_FlagExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_1); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, BATTLER_ENEMY_SLOT_2); } else { - BattleSystem_NoExpGain(battleCtx, battleCtx->switchedMon); - BattleSystem_FlagExpGain(battleSys, battleCtx, battleCtx->switchedMon); + BattleSystem_ClearSideExpGain(battleCtx, battleCtx->switchedMon); + BattleSystem_FlagBattlerExpGain(battleSys, battleCtx, battleCtx->switchedMon); } BattleSystem_DexFlagSeen(battleSys, battleCtx->switchedMon); @@ -2440,7 +2440,7 @@ static BOOL BtlCmd_CalcExpGain(BattleSystem *battleSys, BattleContext *battleCtx Pokemon *mon = BattleSystem_PartyPokemon(battleSys, BATTLER_US, i); if (Pokemon_GetValue(mon, MON_DATA_SPECIES, NULL) && Pokemon_GetValue(mon, MON_DATA_CURRENT_HP, NULL)) { - if (battleCtx->monsGainingExp[(battleCtx->faintedMon >> 1) & 1] & FlagIndex(i)) { + if (battleCtx->sideGetExpMask[(battleCtx->faintedMon >> 1) & 1] & FlagIndex(i)) { totalMonsGainingExp++; } @@ -3058,20 +3058,20 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl battleCtx->battleStatusMask &= ~SYSCTL_FAIL_STAT_STAGE_CHANGE; - if (battleCtx->sideEffectParam >= MOVE_SIDE_EFFECT_ATTACK_DOWN_2_STAGES) { - statOffset = battleCtx->sideEffectParam - MOVE_SIDE_EFFECT_ATTACK_DOWN_2_STAGES; + if (battleCtx->sideEffectParam >= MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_2_STAGES) { + statOffset = battleCtx->sideEffectParam - MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_2_STAGES; stageChange = -2; battleCtx->scriptTemp = STATUS_EFFECT_STAGE_DOWN; - } else if (battleCtx->sideEffectParam >= MOVE_SIDE_EFFECT_ATTACK_UP_2_STAGES) { - statOffset = battleCtx->sideEffectParam - MOVE_SIDE_EFFECT_ATTACK_UP_2_STAGES; + } else if (battleCtx->sideEffectParam >= MOVE_SUBSCRIPT_PTR_ATTACK_UP_2_STAGES) { + statOffset = battleCtx->sideEffectParam - MOVE_SUBSCRIPT_PTR_ATTACK_UP_2_STAGES; stageChange = 2; battleCtx->scriptTemp = STATUS_EFFECT_STAGE_UP; - } else if (battleCtx->sideEffectParam >= MOVE_SIDE_EFFECT_ATTACK_DOWN_1_STAGE) { - statOffset = battleCtx->sideEffectParam - MOVE_SIDE_EFFECT_ATTACK_DOWN_1_STAGE; + } else if (battleCtx->sideEffectParam >= MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_1_STAGE) { + statOffset = battleCtx->sideEffectParam - MOVE_SUBSCRIPT_PTR_ATTACK_DOWN_1_STAGE; stageChange = -1; battleCtx->scriptTemp = STATUS_EFFECT_STAGE_DOWN; } else { - statOffset = battleCtx->sideEffectParam - MOVE_SIDE_EFFECT_ATTACK_UP_1_STAGE; + statOffset = battleCtx->sideEffectParam - MOVE_SUBSCRIPT_PTR_ATTACK_UP_1_STAGE; stageChange = 1; battleCtx->scriptTemp = STATUS_EFFECT_STAGE_UP; } @@ -3080,17 +3080,17 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl if (mon->statBoosts[BATTLE_STAT_ATTACK + statOffset] == 12) { battleCtx->battleStatusMask |= SYSCTL_FAIL_STAT_STAGE_CHANGE; - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_INDIRECT - || battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_INDIRECT + || battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { BattleScript_Iter(battleCtx, jumpBlocked); } else { SetupNicknameStatMsg(battleCtx, 142, statOffset); // "{0}'s {1} won't go higher!" BattleScript_Iter(battleCtx, jumpNoChange); } } else { - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { SetupNicknameAbilityStatMsg(battleCtx, 622, statOffset); // "{0}'s {1} raised its {2}!" - } else if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_HELD_ITEM) { + } else if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_HELD_ITEM) { battleCtx->msgBuffer.id = 756; // "The {0} raised {1}'s {2}!" battleCtx->msgBuffer.tags = TAG_NICKNAME_ITEM_STAT; battleCtx->msgBuffer.params[0] = BattleSystem_NicknameTag(battleCtx, battleCtx->sideEffectMon); @@ -3118,7 +3118,7 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl result = 1; } else if (Battler_IgnorableAbility(battleCtx, battleCtx->attacker, battleCtx->sideEffectMon, ABILITY_CLEAR_BODY) == TRUE || Battler_IgnorableAbility(battleCtx, battleCtx->attacker, battleCtx->sideEffectMon, ABILITY_WHITE_SMOKE) == TRUE) { - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { SetupNicknameAbilityNicknameAbilityMsg(battleCtx, 727); // "{0}'s {1} suppressed {2}'s {3}!" } else { battleCtx->msgBuffer.id = 669; // "{0}'s {1} prevents stat loss!" @@ -3130,7 +3130,7 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl result = 1; } else if (AbilityBlocksSpecificStatReduction(battleCtx, statOffset, ABILITY_KEEN_EYE, BATTLE_STAT_ACCURACY) || AbilityBlocksSpecificStatReduction(battleCtx, statOffset, ABILITY_HYPER_CUTTER, BATTLE_STAT_ATTACK)) { - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { SetupNicknameAbilityNicknameAbilityMsg(battleCtx, 727); // "{0}'s {1} suppressed {2}'s {3}!" } else { SetupNicknameAbilityStatMsg(battleCtx, 704, statOffset); // "{0}'s {1} prevents {2} loss!" @@ -3140,8 +3140,8 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl } else if (mon->statBoosts[BATTLE_STAT_ATTACK + statOffset] == 0) { battleCtx->battleStatusMask |= SYSCTL_FAIL_STAT_STAGE_CHANGE; - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_INDIRECT - || battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_INDIRECT + || battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { BattleScript_Iter(battleCtx, jumpBlocked); return FALSE; @@ -3152,7 +3152,7 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl return FALSE; } } else if (Battler_IgnorableAbility(battleCtx, battleCtx->attacker, battleCtx->sideEffectMon, ABILITY_SHIELD_DUST) == TRUE - && battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_INDIRECT) { + && battleCtx->sideEffectType == SIDE_EFFECT_TYPE_INDIRECT) { result = 1; } else if (battleCtx->battleMons[battleCtx->sideEffectMon].statusVolatile & VOLATILE_CONDITION_SUBSTITUTE) { result = 2; @@ -3160,8 +3160,8 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl } else if (mon->statBoosts[BATTLE_STAT_ATTACK + statOffset] == 0) { battleCtx->battleStatusMask |= SYSCTL_FAIL_STAT_STAGE_CHANGE; - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_INDIRECT - || battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_INDIRECT + || battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { BattleScript_Iter(battleCtx, jumpBlocked); return FALSE; @@ -3173,11 +3173,11 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl } } - if (result == 2 && battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_DIRECT) { + if (result == 2 && battleCtx->sideEffectType == SIDE_EFFECT_TYPE_DIRECT) { BattleScript_Iter(battleCtx, jumpBlockedBySubstitute); return FALSE; - } else if (result && battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_INDIRECT) { + } else if (result && battleCtx->sideEffectType == SIDE_EFFECT_TYPE_INDIRECT) { BattleScript_Iter(battleCtx, jumpBlocked); return FALSE; @@ -3188,7 +3188,7 @@ static BOOL BtlCmd_ChangeStatStage(BattleSystem *battleSys, BattleContext *battl } } - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_ABILITY) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_ABILITY) { battleCtx->msgBuffer.id = 662; // "{0}'s {1} cuts {2}'s {3}!" battleCtx->msgBuffer.tags = TAG_NICKNAME_ABILITY_NICKNAME_STAT; battleCtx->msgBuffer.params[0] = BattleSystem_NicknameTag(battleCtx, battleCtx->attacker); @@ -7863,7 +7863,7 @@ static BOOL BtlCmd_TryToxicSpikes(BattleSystem * battleSys, BattleContext * batt * - battleCtx->calcTemp will be set to the number of layers of Toxic Spikes on * the switched-in battler's side of the field. If the switched-in battler has * the Poison type, then this will instead be set to 0. - * - battleCtx->sideEffectType will be set to SIDE_EFFECT_SOURCE_TOXIC_SPIKES. + * - battleCtx->sideEffectType will be set to SIDE_EFFECT_TYPE_TOXIC_SPIKES. * - battleCtx->sideEffectMon will be set to the switched-in battler. * - If the switched-in battler has the Poison type, then Toxic Spikes will be * cleared from its side of the field. @@ -7883,7 +7883,7 @@ static BOOL BtlCmd_CheckToxicSpikes(BattleSystem * battleSys, BattleContext * ba if (battleCtx->sideConditions[side].toxicSpikesLayers) { battleCtx->calcTemp = battleCtx->sideConditions[side].toxicSpikesLayers; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_TOXIC_SPIKES; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_TOXIC_SPIKES; battleCtx->sideEffectMon = battler; if (MON_HAS_TYPE(battleCtx->switchedMon, TYPE_POISON)) { @@ -9121,7 +9121,7 @@ static BOOL BtlCmd_CheckWhiteOut(BattleSystem *battleSys, BattleContext *battleC // Don't consider the second slot if we have a partner // first condition here does not match as an AND of NEQs, must be a NOT of an OR of EQs - if (!(battleType == BATTLE_TYPE_TRAINER_WITH_AI_PARTNER || battleType == BATTLE_TYPE_2vs2_AI_DOUBLES) + if (!(battleType == BATTLE_TYPE_TRAINER_WITH_AI_PARTNER || battleType == BATTLE_TYPE_AI_PARTNER) || Battler_Side(battleSys, battler) != BATTLER_US || BattleSystem_BattlerSlot(battleSys, battler) != BATTLER_PLAYER_SLOT_2) { for (i = 0; i < Party_GetCurrentCount(party2); i++) { @@ -9190,7 +9190,7 @@ static BOOL BtlCmd_BoostRandomStatBy2(BattleSystem *battleSys, BattleContext *ba } if (validStats) { - battleCtx->sideEffectDirectFlags = MOVE_SIDE_EFFECT_ATTACK_UP_2_STAGES + stats[BattleSystem_RandNext(battleSys) % validStats]; + battleCtx->sideEffectDirectFlags = MOVE_SUBSCRIPT_PTR_ATTACK_UP_2_STAGES + stats[BattleSystem_RandNext(battleSys) % validStats]; battleCtx->sideEffectDirectFlags |= MOVE_SIDE_EFFECT_TO_DEFENDER; } else { BattleScript_Iter(battleCtx, jumpNoValidBoosts); @@ -9951,8 +9951,7 @@ static void BattleScript_GetExpTask(SysTask *task, void *inData) item = Pokemon_GetValue(mon, MON_DATA_HELD_ITEM, NULL); itemEffect = Item_LoadParam(item, ITEM_PARAM_HOLD_EFFECT, HEAP_ID_BATTLE); - // TODO: rename monsGainingExp (sideGetExpMask?) - if (itemEffect == HOLD_EFFECT_EXP_SHARE || (data->battleCtx->monsGainingExp[battler] & FlagIndex(slot))) { + if (itemEffect == HOLD_EFFECT_EXP_SHARE || (data->battleCtx->sideGetExpMask[battler] & FlagIndex(slot))) { break; } } @@ -9985,7 +9984,7 @@ static void BattleScript_GetExpTask(SysTask *task, void *inData) msg.id = 1; // "{0} gained {1} Exp. Points!" if (Pokemon_GetValue(mon, MON_DATA_CURRENT_HP, NULL) && Pokemon_GetValue(mon, MON_DATA_LEVEL, NULL) != 100) { - if (data->battleCtx->monsGainingExp[battler] & FlagIndex(slot)) { + if (data->battleCtx->sideGetExpMask[battler] & FlagIndex(slot)) { totalExp = data->battleCtx->gainedExp; } @@ -10437,7 +10436,7 @@ static void BattleScript_GetExpTask(SysTask *task, void *inData) break; case SEQ_GET_EXP_CHECK_DONE: - data->battleCtx->monsGainingExp[battler] &= (FlagIndex(slot) ^ 0xFFFFFFFF); // this mon is done + data->battleCtx->sideGetExpMask[battler] &= (FlagIndex(slot) ^ 0xFFFFFFFF); // this mon is done data->tmpData[GET_EXP_PARTY_SLOT] = slot + 1; data->seqNum = SEQ_GET_EXP_START; // go back to the top and get the next mon break; diff --git a/src/overlay016/ov16_0223B140.c b/src/overlay016/ov16_0223B140.c index 52aad067e1..30430c8842 100644 --- a/src/overlay016/ov16_0223B140.c +++ b/src/overlay016/ov16_0223B140.c @@ -1113,7 +1113,7 @@ static void ov16_0223C2C0 (BattleSystem * param0, BattleParams * param1) param0->unk_2418 = param1->unk_16C; param0->unk_2424 = param1->unk_140; param0->unk_242C = param1->unk_144; - param0->unk_2428 = param1->unk_14C; + param0->fieldWeather = param1->unk_14C; param0->unk_218 = param1->unk_11C; GF_ASSERT(param1->unk_11C != NULL); diff --git a/src/overlay016/ov16_0223DF00.c b/src/overlay016/ov16_0223DF00.c index 35653ca815..b83d46b102 100644 --- a/src/overlay016/ov16_0223DF00.c +++ b/src/overlay016/ov16_0223DF00.c @@ -154,7 +154,7 @@ u16 * ov16_0223F1F0(BattleSystem * param0); int ov16_0223F1F8(BattleSystem * param0); u16 * ov16_0223F204(BattleSystem * param0); u16 * ov16_0223F210(BattleSystem * param0); -int ov16_0223F21C(BattleSystem * param0); +int BattleSystem_FieldWeather(BattleSystem * param0); u8 ov16_0223F228(BattleSystem * param0); void ov16_0223F234(BattleSystem * param0, u8 param1); int ov16_0223F240(BattleSystem * param0); @@ -1239,9 +1239,9 @@ u16 * ov16_0223F210 (BattleSystem * param0) return ¶m0->unk_2304[0]; } -int ov16_0223F21C (BattleSystem * param0) +int BattleSystem_FieldWeather(BattleSystem *battleSys) { - return param0->unk_2428; + return battleSys->fieldWeather; } u8 ov16_0223F228 (BattleSystem * param0) diff --git a/src/overlay016/ov16_0225177C.c b/src/overlay016/ov16_0225177C.c index 4bdb306cba..28cdd58bfe 100644 --- a/src/overlay016/ov16_0225177C.c +++ b/src/overlay016/ov16_0225177C.c @@ -44,126 +44,8 @@ #include "overlay016/ov16_0225CBB8.h" #include "overlay016/ov16_0226485C.h" -void BattleSystem_InitBattleMon(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); -void BattleSystem_ReloadPokemon(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); -void BattleSystem_LoadScript(BattleContext *battleCtx, int narc, int file); -void BattleSystem_CallScript(BattleContext *battleCtx, int narc, int file); -BOOL BattleSystem_PopScript(BattleContext *battleCtx); -void ov16_02251F44(BattleContext * param0, int param1, int param2, int param3); -void ov16_02251F80(BattleContext * param0, int param1, int param2, int param3); -BOOL BattleIO_QueueIsEmpty(BattleContext *battleCtx); -void BattleIO_UpdateTimeout(BattleContext *battleCtx); -void BattleIO_ClearBuffer(BattleContext *battleCtx, int battler); -int BattleMon_Get(BattleContext *battleCtx, int battler, enum BattleMonParam paramID, void *buf); -void BattleMon_Set(BattleContext *battleCtx, int battler, enum BattleMonParam param, const void *buf); -void Battler_AddVal(BattleContext *battleCtx, int battler, enum BattleMonParam paramID, int val); -void BattleMon_AddVal(BattleMon *mon, enum BattleMonParam paramID, int val); -u8 BattleSystem_CompareBattlerSpeed(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4); -void BattleSystem_NoExpGain(BattleContext * param0, int param1); -void BattleSystem_FlagExpGain(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_CheckPrimaryEffect(BattleSystem * param0, BattleContext * param1, int * param2); -BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq); -int BattleSystem_Defender(BattleSystem * param0, BattleContext * param1, int param2, u16 param3, int param4, int param5); -void BattleSystem_RedirectTarget(BattleSystem * param0, BattleContext * param1, int param2, u16 param3); -BOOL BattleMove_TriggerRedirectionAbilities(BattleSystem * param0, BattleContext * param1); -void BattleMon_CopyToParty(BattleSystem * param0, BattleContext * param1, int param2); -void Battler_LockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -void Battler_UnlockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -int ov16_02253F7C(BattleContext * param0, int param1); -BOOL BattleSystem_CheckTrainerMessage(BattleSystem * param0, BattleContext * param1); -void BattleContext_Init(BattleContext * param0); -void BattleContext_InitCounters(BattleSystem * param0, BattleContext * param1); -void BattleSystem_UpdateAfterSwitch(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -void BattleSystem_CleanupFaintedMon(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -void BattleSystem_SetupNextTurn(BattleSystem * param0, BattleContext * param1); -int BattleSystem_CheckStruggling(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4); -BOOL BattleSystem_CanUseMove(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int moveSlot, BattleMessage *msgOut); -int Battler_SlotForMove(BattleMon * param0, u16 param1); -int BattleSystem_CheckTypeChart(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4, int param5, int param6, u32 * param7); -void ov16_022552D4(BattleContext * param0, int param1, int param2, int param3, int param4, int param5, int param6, int param7, u32 * param8); -BOOL BattleContext_MoveFailed(BattleContext * param0, int param1); -u8 BattleSystem_CountAliveBattlers(BattleSystem *battleSys, BattleContext *battleCtx, BOOL sameSide, int defender); -int BattleSystem_NicknameTag(BattleContext *battleSys, int battler); -u16 Battler_SelectedMove(BattleContext * param0, int param1); -int BattleSystem_CountAbility(BattleSystem *battleSys, BattleContext *battleCtx, enum CountAbilityMode mode, int battler, int ability); -BOOL BattleMove_IsMultiTurn(BattleContext * param0, int param1); -BOOL BattleSystem_TypeMatchup(BattleSystem *battleSys, int idx, u8 *moveType, u8 *vsType, u8 *multi); -int BattleSystem_TypeMatchupMultiplier(u8 attackingType, u8 defendingType1, u8 defendingType2); -BOOL Move_IsInvoker(u16 move); -BOOL BattleSystem_IsGhostCurse(BattleContext * param0, u16 param1, int param2); -BOOL BattleSystem_CanStealItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -BOOL BattleSystem_NotHoldingMail(BattleContext * param0, int param1); -BOOL BattleSystem_CanWhirlwind(BattleSystem *battleSys, BattleContext *battleCtx); -u8 Battler_Ability(BattleContext * param0, int param1); -BOOL Battler_IgnorableAbility(BattleContext *battleCtx, int attacker, int defender, int ability); -BOOL BattleSystem_AnyReplacementMons(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -BOOL BattleSystem_Trapped(BattleSystem * param0, BattleContext * param1, int param2, BattleMessage * param3); -BOOL BattleSystem_TryEscape(BattleSystem * param0, BattleContext * param1, int param2); -BOOL Battler_CheckTruant(BattleContext * param0, int param1); -BOOL BattleSystem_Imprisoned(BattleSystem * param0, BattleContext * param1, int param2, int param3); -BOOL BattleSystem_AnyBattlersWithMoveEffect(BattleSystem *battleSys, BattleContext *battleCtx, int effectMask); -void BattleSystem_SetupLoop(BattleSystem *battleSys, BattleContext *battleCtx); -void BattleSystem_SortMonsBySpeed(BattleSystem * param0, BattleContext * param1); -BOOL BattleSystem_FailsInHighGravity(BattleSystem * param0, BattleContext * param1, int param2, int param3); -BOOL BattleSystem_HealBlocked(BattleSystem * param0, BattleContext * param1, int param2, int param3); -void BattleSystem_UpdateLastResort(BattleSystem * param0, BattleContext * param1); -int Battler_CountMoves(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -int BattleSystem_CheckImmunityAbilities(BattleContext * param0, int param1, int param2); -BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem * param0, BattleContext * param1, int param2); -int BattleSystem_Divide(int dividend, int divisor); -int BattleSystem_ShowMonChecks(BattleSystem * param0, BattleContext * param1); -int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCtx, int attacker); -BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq); -BOOL BattleSystem_RecoverStatusByAbility(BattleSystem * param0, BattleContext * param1, int param2, int param3); -BOOL Ability_ForbidsStatus(BattleContext *battleSys, int ability, int status); -BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * battleCtx, int controllerCommand); -BOOL BattleSystem_TriggerHeldItem(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_TriggerLeftovers(BattleSystem * param0, BattleContext * param1, int param2); -BOOL BattleSystem_TriggerHeldItemOnStatus(BattleSystem * param0, BattleContext * param1, int param2, int * param3); -BOOL BattleSystem_TriggerDetrimentalHeldItem(BattleSystem * param0, BattleContext * param1, int param2); -u16 Battler_HeldItem(BattleContext *battleCtx, int battler); -BOOL Battler_MovedThisTurn(BattleContext * param0, int param1); -BOOL BattleSystem_TriggerHeldItemOnHit(BattleSystem * param0, BattleContext * param1, int * param2); -s32 Battler_HeldItemEffect(BattleContext * param0, int param1); -s32 Battler_HeldItemPower(BattleContext *battleCtx, int battler, enum HeldItemPowerOp opcode); -s32 Battler_NaturalGiftPower(BattleContext *battleCtx, int battler); -s32 Battler_NaturalGiftType(BattleContext *battleCtx, int battler); -s32 Battler_ItemPluckEffect(BattleContext *battleCtx, int battler); -s32 Battler_ItemFlingEffect(BattleContext *battleCtx, int battler); -s32 Battler_ItemFlingPower(BattleContext *battleCtx, int battler); -int BattleSystem_CanSwitch(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -BOOL BattleSystem_PluckBerry(BattleSystem *battleSys, BattleContext *battleCtx, int battler); -BOOL BattleSystem_FlingItem(BattleSystem * param0, BattleContext * param1, int param2); -void BattleSystem_UpdateMetronomeCount(BattleSystem * param0, BattleContext * param1); -void BattleSystem_VerifyMetronomeCount(BattleSystem * param0, BattleContext * param1); -int ov16_022599D0(BattleContext * param0, int param1, int param2, int param3); -BOOL BattleSystem_CanPickCommand(BattleContext *battleSys, int battler); -void ov16_02259A5C(BattleSystem * param0, BattleContext * param1, Pokemon * param2); -u8 BattleContext_IOBufferVal(BattleContext *battleCtx, int battler); -BOOL Battler_SubstituteWasHit(BattleContext *battleCtx, int battler); -BOOL BattleSystem_TrainerIsOT(BattleSystem * param0, BattleContext * param1); -BOOL BattleSystem_PokemonWasTraded(BattleSystem * param0, Pokemon * param1); -BOOL BattleSystem_UpdateWeatherForms(BattleSystem * param0, BattleContext * param1, int * param2); -void ov16_0225A1B0(BattleSystem * param0, BattleContext * param1); -void BattleSystem_SwitchSlots(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int partySlot); -int BattleSystem_CalcMoveDamage(BattleSystem *battleSys, BattleContext *battleCtx, int move, u32 sideConditions, u32 fieldConditions, u16 inPower, u8 inType, u8 attacker, u8 defender, u8 criticalMul); -int BattleSystem_CalcDamageVariance(BattleSystem *battleSys, BattleContext *battleCtx, int damage); -int BattleSystem_CalcCriticalMulti(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, int defender, int criticalStage, u32 sideConditions); -BOOL Move_CanBeMimicked(u16 move); -BOOL Move_CanBeMetronomed(BattleSystem *battleSys, BattleContext *battleCtx, int battler, u16 move); -BOOL Move_CanBeEncored(BattleContext *battleCtx, u16 move); -BOOL Move_MeFirstCanCopy(BattleContext *battleCtx, u16 move); -s32 BattleSystem_GetItemData(BattleContext *battleCtx, u16 item, enum ItemDataParam paramID); -int BattleSystem_SideToBattler(BattleSystem * param0, BattleContext * param1, int param2); -void BattleSystem_SortMonsInTrickRoom(BattleSystem * param0, BattleContext * param1); -BOOL BattleSystem_ShouldShowStatusEffect(BattleContext *battleCtx, int battler, int status); -BOOL BattleSystem_TriggerHeldItemOnPivotMove(BattleSystem * param0, BattleContext * param1, int * param2); -void BattleSystem_DecPPForPressure(BattleContext * param0, int param1, int param2); -BOOL BattleSystem_RecordingStopped(BattleSystem * param0, BattleContext * param1); -int BattleContext_Get(BattleSystem *battleSys, BattleContext *battleCtx, enum BattleContextParam paramID, int battler); -void BattleContext_Set(BattleSystem *battleSys, BattleContext *battleCtx, enum BattleContextParam paramID, int battler, int val); static BOOL ov16_02254EF4(BattleContext * param0, int param1, int param2, int param3); -static int BattleContext_SideEffect(BattleContext * param0, int param1, u32 param2); +static int MapSideEffectToSubscript(BattleContext *battleCtx, enum SideEffectType type, u32 effect); static int ov16_0225B63C(BattleContext * param0, int param1, int param2, int param3, int param4, u32 * param5); static BOOL ov16_022553F8(BattleContext * param0, int param1, int param2); static void ov16_02255448(int param0, u32 * param1); @@ -172,12 +54,9 @@ static u8 Battler_MonType(BattleContext *battleCtx, int battler, enum BattleMonP static void BattleAI_ClearKnownMoves(BattleContext *battleCtx, u8 battler); static void BattleAI_ClearKnownAbility(BattleContext *battleCtx, u8 battler); static void BattleAI_ClearKnownItem(BattleContext *battleCtx, u8 battler); -static int ov16_0225B840(BattleSystem * param0, BattleContext * param1, int param2, int param3); -static BOOL ov16_0225B8E4(BattleContext * param0, int param1); +static int ChooseTraceTarget(BattleSystem *battleSys, BattleContext *battleCtx, int defender1, int defender2); +static BOOL MoveCannotTriggerAnticipation(BattleContext * param0, int param1); static int BattleMove_Type(BattleSystem * param0, BattleContext * param1, int param2, int param3); -int ov16_0225BA88(BattleSystem * param0, int param1); -int ov16_0225BE28(BattleSystem * param0, int param1); -int ov16_0225BE3C(BattleSystem * param0, BattleContext * param1, Pokemon * param2, int param3); static const Fraction sStatStageBoosts[]; @@ -405,7 +284,7 @@ void BattleIO_UpdateTimeout(BattleContext *battleCtx) } } -void BattleIO_ClearBuffer (BattleContext *battleCtx, int battler) +void BattleIO_ClearBuffer(BattleContext *battleCtx, int battler) { for (int i = 0; i < BATTLE_IO_BUFFER_SIZE; i++) { battleCtx->ioBuffer[battler][i] = 0; @@ -1275,343 +1154,346 @@ void BattleMon_AddVal(BattleMon *mon, enum BattleMonParam paramID, int val) } } -static const u8 Unk_ov16_0226EBA8[] = { - 0x32, - 0x6A, - 0x7A, - 0x75, - 0x76, - 0x79, - 0x77, - 0x78 +static const u8 sSpeedHalvingItemEffects[] = { + HOLD_EFFECT_EVS_UP_SPEED_DOWN, + HOLD_EFFECT_SPEED_DOWN_GROUNDED, + HOLD_EFFECT_LVLUP_HP_EV_UP, + HOLD_EFFECT_LVLUP_ATK_EV_UP, + HOLD_EFFECT_LVLUP_DEF_EV_UP, + HOLD_EFFECT_LVLUP_SPEED_EV_UP, + HOLD_EFFECT_LVLUP_SPATK_EV_UP, + HOLD_EFFECT_LVLUP_SPDEF_EV_UP }; -u8 BattleSystem_CompareBattlerSpeed (BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4) +static inline int CompareSpeed_ApplySimple(BattleContext *battleCtx, int battler, int stage) { - u8 v0 = 0; - u32 v1, v2; - u16 v3 = 0, v4 = 0; - u8 v5; - u8 v6; - u8 v7; - u8 v8; - s8 v9 = 0; - s8 v10 = 0; - u8 v11 = 0, v12 = 0; - u8 v13 = 0, v14 = 0; - int v15; - int v16; - int v17; - int v18; - int v19; - int v20; - int v21; - int v22; - int v23; - - if ((param1->battleMons[param2].curHP == 0) && (param1->battleMons[param3].curHP)) { - return 1; - } + if (Battler_Ability(battleCtx, battler) == ABILITY_SIMPLE) { + stage = 6 + ((stage - 6) * 2); - if ((param1->battleMons[param2].curHP) && (param1->battleMons[param3].curHP == 0)) { - return 0; + if (stage > 12) { + stage = 12; + } + + if (stage < 0) { + stage = 0; + } } - v19 = Battler_Ability(param1, param2); - v20 = Battler_Ability(param1, param3); - v5 = Battler_HeldItemEffect(param1, param2); - v6 = Battler_HeldItemPower(param1, param2, 0); - v7 = Battler_HeldItemEffect(param1, param3); - v8 = Battler_HeldItemPower(param1, param3, 0); - v21 = param1->battleMons[param2].statBoosts[0x3]; - v22 = param1->battleMons[param3].statBoosts[0x3]; + return stage; +} - if (Battler_Ability(param1, param2) == 86) { - v21 = 6 + ((v21 - 6) * 2); +enum { + BATTLER_1_GOES_FIRST = 0, + BATTLER_2_GOES_FIRST, + BATTLER_2_WINS_SPEED_TIE, +}; - if (v21 > 12) { - v21 = 12; - } +u8 BattleSystem_CompareBattlerSpeed(BattleSystem *battleSys, BattleContext *battleCtx, int battler1, int battler2, BOOL ignoreQuickClaw) +{ + u8 result = BATTLER_1_GOES_FIRST; + u32 battler1Speed, battler2Speed; + u16 battler1Move = 0, battler2Move = 0; + u8 battler1ItemEffect, battler1ItemParam; + u8 battler2ItemEffect, battler2ItemParam; + s8 battler1Priority = 0, battler2Priority = 0; + u8 battler1QuickClaw = 0, battler2QuickClaw = 0; + u8 battler1LaggingTail = 0, battler2LaggingTail = 0; + int battler1Action, battler2Action; + int battler1MoveSlot, battler2MoveSlot; + int battler1Ability, battler2Ability; + int battler1SpeedStage, battler2SpeedStage; + int i; - if (v21 < 0) { - v21 = 0; - } + // If either battler is dead, short-circuit to preferring the other + if (battleCtx->battleMons[battler1].curHP == 0 && battleCtx->battleMons[battler2].curHP) { + return 1; } - if (Battler_Ability(param1, param3) == 86) { - v22 = 6 + ((v22 - 6) * 2); + if (battleCtx->battleMons[battler1].curHP && battleCtx->battleMons[battler2].curHP == 0) { + return 0; + } - if (v22 > 12) { - v22 = 12; - } + battler1Ability = Battler_Ability(battleCtx, battler1); + battler2Ability = Battler_Ability(battleCtx, battler2); + battler1ItemEffect = Battler_HeldItemEffect(battleCtx, battler1); + battler1ItemParam = Battler_HeldItemPower(battleCtx, battler1, ITEM_POWER_CHECK_ALL); + battler2ItemEffect = Battler_HeldItemEffect(battleCtx, battler2); + battler2ItemParam = Battler_HeldItemPower(battleCtx, battler2, ITEM_POWER_CHECK_ALL); + battler1SpeedStage = battleCtx->battleMons[battler1].statBoosts[BATTLE_STAT_SPEED]; + battler2SpeedStage = battleCtx->battleMons[battler2].statBoosts[BATTLE_STAT_SPEED]; - if (v22 < 0) { - v22 = 0; - } - } + battler1SpeedStage = CompareSpeed_ApplySimple(battleCtx, battler1, battler1SpeedStage); + battler2SpeedStage = CompareSpeed_ApplySimple(battleCtx, battler2, battler2SpeedStage); - v1 = param1->battleMons[param2].speed * sStatStageBoosts[v21].numerator / sStatStageBoosts[v21].denominator; - v2 = param1->battleMons[param3].speed * sStatStageBoosts[v22].numerator / sStatStageBoosts[v22].denominator; + battler1Speed = battleCtx->battleMons[battler1].speed * sStatStageBoosts[battler1SpeedStage].numerator / sStatStageBoosts[battler1SpeedStage].denominator; + battler2Speed = battleCtx->battleMons[battler2].speed * sStatStageBoosts[battler2SpeedStage].numerator / sStatStageBoosts[battler2SpeedStage].denominator; - if ((BattleSystem_CountAbility(param0, param1, 8, 0, 13) == 0) && (BattleSystem_CountAbility(param0, param1, 8, 0, 76) == 0)) { - if (((v19 == 33) && (param1->fieldConditionsMask & 0x3)) || ((v19 == 34) && (param1->fieldConditionsMask & 0x30))) { - v1 *= 2; + if (NO_CLOUD_NINE) { + if ((battler1Ability == ABILITY_SWIFT_SWIM && WEATHER_IS_RAIN) + || (battler1Ability == ABILITY_CHLOROPHYLL && WEATHER_IS_SUN)) { + battler1Speed *= 2; } - if (((v20 == 33) && (param1->fieldConditionsMask & 0x3)) || ((v20 == 34) && (param1->fieldConditionsMask & 0x30))) { - v2 *= 2; + if ((battler2Ability == ABILITY_SWIFT_SWIM && WEATHER_IS_RAIN) + || (battler2Ability == ABILITY_CHLOROPHYLL && WEATHER_IS_SUN)) { + battler2Speed *= 2; } } - for (v23 = 0; v23 < NELEMS(Unk_ov16_0226EBA8); v23++) { - if (BattleSystem_GetItemData(param1, param1->battleMons[param2].heldItem, 1) == Unk_ov16_0226EBA8[v23]) { - v1 /= 2; + for (i = 0; i < NELEMS(sSpeedHalvingItemEffects); i++) { + // The speed-halving effect of these items are not ignored by any negation effect + if (BattleSystem_GetItemData(battleCtx, battleCtx->battleMons[battler1].heldItem, ITEM_PARAM_HOLD_EFFECT) == sSpeedHalvingItemEffects[i]) { + battler1Speed /= 2; break; } } - if (v5 == 115) { - v1 = v1 * 15 / 10; + if (battler1ItemEffect == HOLD_EFFECT_CHOICE_SPEED) { + battler1Speed = battler1Speed * 15 / 10; } - if ((v5 == 102) && (param1->battleMons[param2].species == 132)) { - v1 *= 2; + if (battler1ItemEffect == HOLD_EFFECT_DITTO_SPEED_UP + && battleCtx->battleMons[battler1].species == SPECIES_DITTO) { + battler1Speed *= 2; } - if ((v19 == 95) && (param1->battleMons[param2].status & 0xff)) { - v1 = v1 * 15 / 10; - } else { - if (param1->battleMons[param2].status & 0x40) { - v1 /= 4; - } + if (battler1Ability == ABILITY_QUICK_FEET && (battleCtx->battleMons[battler1].status & MON_CONDITION_ANY)) { + battler1Speed = battler1Speed * 15 / 10; + } else if (battleCtx->battleMons[battler1].status & MON_CONDITION_PARALYSIS) { + battler1Speed /= 4; } - if ((v19 == 112) && ((param1->totalTurns - param1->battleMons[param2].moveEffectsData.slowStartTurnNumber) < 5)) { - v1 /= 2; + if (battler1Ability == ABILITY_SLOW_START + && battleCtx->totalTurns - battleCtx->battleMons[battler1].moveEffectsData.slowStartTurnNumber < 5) { + battler1Speed /= 2; } - if ((v19 == 84) && (param1->battleMons[param2].moveEffectsData.canUnburden) && (param1->battleMons[param2].heldItem == 0)) { - v1 *= 2; + if (battler1Ability == ABILITY_UNBURDEN + && battleCtx->battleMons[battler1].moveEffectsData.canUnburden + && battleCtx->battleMons[battler1].heldItem == ITEM_NONE) { + battler1Speed *= 2; } - if (param1->sideConditionsMask[Battler_Side(param0, param2)] & 0x300) { - v1 *= 2; + if (battleCtx->sideConditionsMask[Battler_Side(battleSys, battler1)] & SIDE_CONDITION_TAILWIND) { + battler1Speed *= 2; } - if (v5 == 52) { - if ((param1->speedRand[param2] % (100 / v6)) == 0) { - v11 = 1; + if (battler1ItemEffect == HOLD_EFFECT_SOMETIMES_PRIORITY) { + if (battleCtx->speedRand[battler1] % (100 / battler1ItemParam) == 0) { + battler1QuickClaw = 1; - if (param4 == 0) { - param1->battleMons[param2].moveEffectsData.quickClaw = 1; + if (ignoreQuickClaw == FALSE) { + battleCtx->battleMons[battler1].moveEffectsData.quickClaw = 1; } } } - if (v5 == 45) { - if (Battler_Ability(param1, param2) == 82) { - v6 /= 2; + if (battler1ItemEffect == HOLD_EFFECT_PINCH_PRIORITY) { + if (Battler_Ability(battleCtx, battler1) == ABILITY_GLUTTONY) { + battler1ItemParam /= 2; } - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v6)) { - v11 = 1; + if (battleCtx->battleMons[battler1].curHP <= (battleCtx->battleMons[battler1].maxHP / battler1ItemParam)) { + battler1QuickClaw = 1; - if (param4 == 0) { - param1->battleMons[param2].moveEffectsData.custapBerry = 1; + if (ignoreQuickClaw == FALSE) { + battleCtx->battleMons[battler1].moveEffectsData.custapBerry = 1; } } } - if (v5 == 107) { - v13 = 1; + if (battler1ItemEffect == HOLD_EFFECT_PRIORITY_DOWN) { + battler1LaggingTail = 1; } - for (v23 = 0; v23 < NELEMS(Unk_ov16_0226EBA8); v23++) { - if (BattleSystem_GetItemData(param1, param1->battleMons[param3].heldItem, 1) == Unk_ov16_0226EBA8[v23]) { - v2 /= 2; + for (i = 0; i < NELEMS(sSpeedHalvingItemEffects); i++) { + // The speed-halving effect of these items are not ignored by any negation effect + if (BattleSystem_GetItemData(battleCtx, battleCtx->battleMons[battler2].heldItem, ITEM_PARAM_HOLD_EFFECT) == sSpeedHalvingItemEffects[i]) { + battler2Speed /= 2; break; } } - if (v7 == 115) { - v2 = v2 * 15 / 10; + if (battler2ItemEffect == HOLD_EFFECT_CHOICE_SPEED) { + battler2Speed = battler2Speed * 15 / 10; } - if ((v7 == 102) && (param1->battleMons[param3].species == 132)) { - v2 *= 2; + if (battler2ItemEffect == HOLD_EFFECT_DITTO_SPEED_UP + && battleCtx->battleMons[battler2].species == SPECIES_DITTO) { + battler2Speed *= 2; } - if ((v20 == 95) && (param1->battleMons[param3].status & 0xff)) { - v2 = v2 * 15 / 10; - } else { - if (param1->battleMons[param3].status & 0x40) { - v2 /= 4; - } + if (battler2Ability == ABILITY_QUICK_FEET && (battleCtx->battleMons[battler2].status & MON_CONDITION_ANY)) { + battler2Speed = battler2Speed * 15 / 10; + } else if (battleCtx->battleMons[battler2].status & MON_CONDITION_PARALYSIS) { + battler2Speed /= 4; } - if ((v20 == 112) && ((param1->totalTurns - param1->battleMons[param3].moveEffectsData.slowStartTurnNumber) < 5)) { - v2 /= 2; + if (battler2Ability == ABILITY_SLOW_START + && battleCtx->totalTurns - battleCtx->battleMons[battler2].moveEffectsData.slowStartTurnNumber < 5) { + battler2Speed /= 2; } - if ((v20 == 84) && (param1->battleMons[param3].moveEffectsData.canUnburden) && (param1->battleMons[param3].heldItem == 0)) { - v2 *= 2; + if (battler2Ability == ABILITY_UNBURDEN + && battleCtx->battleMons[battler2].moveEffectsData.canUnburden + && battleCtx->battleMons[battler2].heldItem == ITEM_NONE) { + battler2Speed *= 2; } - if (param1->sideConditionsMask[Battler_Side(param0, param3)] & 0x300) { - v2 *= 2; + if (battleCtx->sideConditionsMask[Battler_Side(battleSys, battler2)] & SIDE_CONDITION_TAILWIND) { + battler2Speed *= 2; } - if (v7 == 52) { - if ((param1->speedRand[param3] % (100 / v8)) == 0) { - v12 = 1; + if (battler2ItemEffect == HOLD_EFFECT_SOMETIMES_PRIORITY) { + if (battleCtx->speedRand[battler2] % (100 / battler2ItemParam) == 0) { + battler2QuickClaw = 1; - if (param4 == 0) { - param1->battleMons[param3].moveEffectsData.quickClaw = 1; + if (ignoreQuickClaw == FALSE) { + battleCtx->battleMons[battler2].moveEffectsData.quickClaw = 1; } } } - if (v7 == 45) { - if (Battler_Ability(param1, param3) == 82) { - v8 /= 2; + if (battler2ItemEffect == HOLD_EFFECT_PINCH_PRIORITY) { + if (Battler_Ability(battleCtx, battler2) == ABILITY_GLUTTONY) { + battler2ItemParam /= 2; } - if (param1->battleMons[param3].curHP <= (param1->battleMons[param3].maxHP / v8)) { - v12 = 1; + if (battleCtx->battleMons[battler2].curHP <= (battleCtx->battleMons[battler2].maxHP / battler2ItemParam)) { + battler2QuickClaw = 1; - if (param4 == 0) { - param1->battleMons[param3].moveEffectsData.custapBerry = 1; + if (ignoreQuickClaw == FALSE) { + battleCtx->battleMons[battler2].moveEffectsData.custapBerry = 1; } } } - if (v7 == 107) { - v14 = 1; + if (battler2ItemEffect == HOLD_EFFECT_PRIORITY_DOWN) { + battler2LaggingTail = 1; } - param1->monSpeedValues[param2] = v1; - param1->monSpeedValues[param3] = v2; + battleCtx->monSpeedValues[battler1] = battler1Speed; + battleCtx->monSpeedValues[battler2] = battler2Speed; - if (param4 == 0) { - v15 = param1->battlerActions[param2][3]; - v16 = param1->battlerActions[param3][3]; - v17 = param1->moveSlot[param2]; - v18 = param1->moveSlot[param3]; + if (ignoreQuickClaw == FALSE) { + battler1Action = battleCtx->battlerActions[battler1][BATTLE_ACTION_SELECTED_COMMAND]; + battler2Action = battleCtx->battlerActions[battler2][BATTLE_ACTION_SELECTED_COMMAND]; + battler1MoveSlot = battleCtx->moveSlot[battler1]; + battler2MoveSlot = battleCtx->moveSlot[battler2]; - if (v15 == 1) { - if (param1->turnFlags[param2].struggling) { - v3 = 165; + if (battler1Action == PLAYER_INPUT_FIGHT) { + if (battleCtx->turnFlags[battler1].struggling) { + battler1Move = MOVE_STRUGGLE; } else { - v3 = BattleMon_Get(param1, param2, 6 + v17, NULL); + battler1Move = BattleMon_Get(battleCtx, battler1, BATTLEMON_MOVE_1 + battler1MoveSlot, NULL); } } - if (v16 == 1) { - if (param1->turnFlags[param3].struggling) { - v4 = 165; + if (battler2Action == PLAYER_INPUT_FIGHT) { + if (battleCtx->turnFlags[battler2].struggling) { + battler2Move = MOVE_STRUGGLE; } else { - v4 = BattleMon_Get(param1, param3, 6 + v18, NULL); + battler2Move = BattleMon_Get(battleCtx, battler2, BATTLEMON_MOVE_1 + battler2MoveSlot, NULL); } } - v9 = param1->aiContext.moveTable[v3].priority; - v10 = param1->aiContext.moveTable[v4].priority; + battler1Priority = MOVE_DATA(battler1Move).priority; + battler2Priority = MOVE_DATA(battler2Move).priority; } - if (v9 == v10) { - if ((v11) && (v12)) { - if (v1 < v2) { - v0 = 1; - } else if ((v1 == v2) && (BattleSystem_RandNext(param0) & 1)) { - v0 = 2; + if (battler1Priority == battler2Priority) { + if (battler1QuickClaw && battler2QuickClaw) { + if (battler1Speed < battler2Speed) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1Speed == battler2Speed && (BattleSystem_RandNext(battleSys) & 1)) { + result = BATTLER_2_WINS_SPEED_TIE; } - } else if ((v11 == 0) && (v12)) { - v0 = 1; - } else if ((v11) && (v12 == 0)) { - v0 = 0; - } else if ((v13) && (v14)) { - if (v1 > v2) { - v0 = 1; - } else if ((v1 == v2) && (BattleSystem_RandNext(param0) & 1)) { - v0 = 2; + } else if (battler1QuickClaw == FALSE && battler2QuickClaw) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1QuickClaw && battler2QuickClaw == FALSE) { + result = BATTLER_1_GOES_FIRST; + } else if (battler1LaggingTail && battler2LaggingTail) { + if (battler1Speed > battler2Speed) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1Speed == battler2Speed && (BattleSystem_RandNext(battleSys) & 1)) { + result = BATTLER_2_WINS_SPEED_TIE; } - } else if ((v13) && (v14 == 0)) { - v0 = 1; - } else if ((v13 == 0) && (v14)) { - v0 = 0; - } else if ((v19 == 100) && (v20 == 100)) { - if (v1 > v2) { - v0 = 1; - } else if ((v1 == v2) && (BattleSystem_RandNext(param0) & 1)) { - v0 = 2; + } else if (battler1LaggingTail && battler2LaggingTail == FALSE) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1LaggingTail == FALSE && battler2LaggingTail) { + result = BATTLER_1_GOES_FIRST; + } else if (battler1Ability == ABILITY_STALL && battler2Ability == ABILITY_STALL) { + if (battler1Speed > battler2Speed) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1Speed == battler2Speed && (BattleSystem_RandNext(battleSys) & 1)) { + result = BATTLER_2_WINS_SPEED_TIE; } - } else if ((v19 == 100) && (v20 != 100)) { - v0 = 1; - } else if ((v19 != 100) && (v20 == 100)) { - v0 = 0; - } else if (param1->fieldConditionsMask & 0x70000) { - if (v1 > v2) { - v0 = 1; + } else if (battler1Ability == ABILITY_STALL && battler2Ability != ABILITY_STALL) { + result = BATTLER_2_GOES_FIRST; + } else if (battler1Ability != ABILITY_STALL && battler2Ability == ABILITY_STALL) { + result = BATTLER_1_GOES_FIRST; + } else if (battleCtx->fieldConditionsMask & FIELD_CONDITION_TRICK_ROOM) { + if (battler1Speed > battler2Speed) { + result = BATTLER_2_GOES_FIRST; } - if ((v1 == v2) && (BattleSystem_RandNext(param0) & 1)) { - v0 = 2; + if (battler1Speed == battler2Speed && (BattleSystem_RandNext(battleSys) & 1)) { + result = BATTLER_2_WINS_SPEED_TIE; } } else { - if (v1 < v2) { - v0 = 1; + if (battler1Speed < battler2Speed) { + result = BATTLER_2_GOES_FIRST; } - if ((v1 == v2) && (BattleSystem_RandNext(param0) & 1)) { - v0 = 2; + if (battler1Speed == battler2Speed && (BattleSystem_RandNext(battleSys) & 1)) { + result = BATTLER_2_WINS_SPEED_TIE; } } - } else if (v9 < v10) { - v0 = 1; + } else if (battler1Priority < battler2Priority) { + result = BATTLER_2_GOES_FIRST; } - return v0; + return result; } -void BattleSystem_NoExpGain (BattleContext * param0, int param1) +void BattleSystem_ClearSideExpGain(BattleContext *battleCtx, int battler) { - param0->monsGainingExp[(param1 >> 1) & 1] = 0; + battleCtx->sideGetExpMask[(battler >> 1) & 1] = 0; } -void BattleSystem_FlagExpGain (BattleSystem * param0, BattleContext * param1, int param2) +void BattleSystem_FlagBattlerExpGain(BattleSystem *battleSys, BattleContext *battleCtx, int battler) { - int v0; - u32 v1; - - v0 = 0; - v1 = BattleSystem_BattleType(param0); + int side = 0; + u32 battleType = BattleSystem_BattleType(battleSys); - while (v0 <= 2) { - if (((param1->battlersSwitchingMask & FlagIndex(v0)) == 0) && ((param1->battlersSwitchingMask & FlagIndex(param2)) == 0) && (param1->battleMons[param2].curHP)) { - param1->monsGainingExp[(param2 >> 1) & 1] |= FlagIndex(param1->selectedPartySlot[v0]); + while (side <= 2) { + if ((battleCtx->battlersSwitchingMask & FlagIndex(side)) == FALSE + && (battleCtx->battlersSwitchingMask & FlagIndex(battler)) == FALSE + && battleCtx->battleMons[battler].curHP) { + battleCtx->sideGetExpMask[(battler >> 1) & 1] |= FlagIndex(battleCtx->selectedPartySlot[side]); } - v0 += 2; + side += 2; - if ((v1 == (0x2 | 0x8 | 0x40)) || (v1 == ((0x2 | 0x1) | 0x8 | 0x40))) { + if (battleType == BATTLE_TYPE_AI_PARTNER || battleType == BATTLE_TYPE_TRAINER_WITH_AI_PARTNER) { break; } } } -BOOL BattleSystem_CheckPrimaryEffect (BattleSystem *battleSys, BattleContext * battleCtx, int * nextSeq) +BOOL BattleSystem_TriggerPrimaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *effect) { BOOL result = FALSE; if (battleCtx->sideEffectDirectFlags & MOVE_SIDE_EFFECT_ON_HIT) { - *nextSeq = BattleContext_SideEffect(battleCtx, 1, battleCtx->sideEffectDirectFlags); + *effect = MapSideEffectToSubscript(battleCtx, 1, battleCtx->sideEffectDirectFlags); battleCtx->sideEffectDirectFlags = 0; if ((battleCtx->moveStatusFlags & MOVE_STATUS_NO_EFFECTS) == FALSE) { result = TRUE; } } else if (battleCtx->sideEffectDirectFlags) { - *nextSeq = BattleContext_SideEffect(battleCtx, 1, battleCtx->sideEffectDirectFlags); + *effect = MapSideEffectToSubscript(battleCtx, 1, battleCtx->sideEffectDirectFlags); if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP && ((battleCtx->moveStatusFlags & MOVE_STATUS_NO_EFFECTS) == FALSE @@ -1631,32 +1513,32 @@ BOOL BattleSystem_CheckPrimaryEffect (BattleSystem *battleSys, BattleContext * b return result; } -static inline void SetupSideEffect(BattleContext *battleCtx, int *nextSeq, int source) +static inline void SetupSideEffect(BattleContext *battleCtx, int *effect, int source) { - *nextSeq = BattleContext_SideEffect(battleCtx, source, battleCtx->sideEffectIndirectFlags); + *effect = MapSideEffectToSubscript(battleCtx, source, battleCtx->sideEffectIndirectFlags); battleCtx->sideEffectIndirectFlags = 0; } -BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq) +BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *effect) { BOOL result = FALSE; u16 effectChance; if (battleCtx->sideEffectIndirectFlags & MOVE_SIDE_EFFECT_ON_HIT) { - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if ((battleCtx->moveStatusFlags & MOVE_STATUS_NO_EFFECTS) == FALSE) { result = TRUE; } } else if (battleCtx->sideEffectIndirectFlags & MOVE_SIDE_EFFECT_CHECK_SUBSTITUTE) { - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if (Battler_SubstituteWasHit(battleCtx, battleCtx->sideEffectMon) == FALSE && (battleCtx->moveStatusFlags & MOVE_STATUS_NO_EFFECTS) == FALSE) { result = TRUE; } } else if (battleCtx->sideEffectIndirectFlags & MOVE_SIDE_EFFECT_CHECK_HP_AND_SUBSTITUTE) { - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP && Battler_SubstituteWasHit(battleCtx, battleCtx->sideEffectMon) == FALSE @@ -1664,7 +1546,7 @@ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext result = TRUE; } } else if (battleCtx->sideEffectIndirectFlags & MOVE_SIDE_EFFECT_CHECK_HP) { - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP) { result = TRUE; @@ -1682,7 +1564,7 @@ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext battleCtx->battleStatusMask |= SYSCTL_APPLY_SECONDARY_EFFECT; } - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP == 0) { battleCtx->battleStatusMask &= ~SYSCTL_APPLY_SECONDARY_EFFECT; } @@ -1698,7 +1580,7 @@ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext GF_ASSERT(effectChance != 0); if (BattleSystem_RandNext(battleSys) % 100 < effectChance) { - SetupSideEffect(battleCtx, nextSeq, SIDE_EFFECT_SOURCE_INDIRECT); + SetupSideEffect(battleCtx, effect, SIDE_EFFECT_TYPE_INDIRECT); if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP && Battler_SubstituteWasHit(battleCtx, battleCtx->sideEffectMon) == FALSE @@ -1707,7 +1589,7 @@ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext } } } else if (battleCtx->sideEffectAbilityFlags) { - *nextSeq = BattleContext_SideEffect(battleCtx, SIDE_EFFECT_SOURCE_ABILITY, battleCtx->sideEffectAbilityFlags); + *effect = MapSideEffectToSubscript(battleCtx, SIDE_EFFECT_TYPE_ABILITY, battleCtx->sideEffectAbilityFlags); battleCtx->sideEffectAbilityFlags = 0; if (battleCtx->battleMons[battleCtx->sideEffectMon].curHP) { @@ -3562,133 +3444,130 @@ int Battler_CountMoves(BattleSystem *battleSys, BattleContext *battleCtx, int ba return i; } -static u16 Unk_ov16_02270B8C[] = { - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x67, - 0xAD, - 0xFD, - 0x13F, - 0x140, - 0x130, - 0x195, - 0x1C0 +static u16 sSoundMoves[] = { + MOVE_GROWL, + MOVE_ROAR, + MOVE_SING, + MOVE_SUPERSONIC, + MOVE_SCREECH, + MOVE_SNORE, + MOVE_UPROAR, + MOVE_METAL_SOUND, + MOVE_GRASS_WHISTLE, + MOVE_HYPER_VOICE, + MOVE_BUG_BUZZ, + MOVE_CHATTER, }; -int BattleSystem_CheckImmunityAbilities (BattleContext * param0, int param1, int param2) +int BattleSystem_TriggerImmunityAbility(BattleContext *battleCtx, int attacker, int defender) { - int v0; - int v1; + int subscript = NULL, moveType; - v0 = 0; - - if (Battler_Ability(param0, param1) == 96) { - v1 = 0; - } else if (param0->moveType) { - v1 = param0->moveType; + if (Battler_Ability(battleCtx, attacker) == ABILITY_NORMALIZE) { + moveType = TYPE_NORMAL; + } else if (battleCtx->moveType) { + moveType = battleCtx->moveType; } else { - v1 = param0->aiContext.moveTable[param0->moveCur].type; + moveType = CURRENT_MOVE_DATA.type; } - if (Battler_IgnorableAbility(param0, param1, param2, 10) == 1) { - if ((v1 == 13) && (param1 != param2)) { - param0->hpCalcTemp = BattleSystem_Divide(param0->battleMons[param2].maxHP, 4); - v0 = (0 + 178); - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_VOLT_ABSORB) == TRUE + && moveType == TYPE_ELECTRIC + && attacker != defender) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[defender].maxHP, 4); + subscript = BATTLE_SUBSEQ_ABILITY_RESTORES_HP; } - if (Battler_IgnorableAbility(param0, param1, param2, 11) == 1) { - if ((v1 == 11) && ((param0->battleStatusMask & 0x20) == 0) && (param0->aiContext.moveTable[param0->moveCur].power)) { - param0->hpCalcTemp = BattleSystem_Divide(param0->battleMons[param2].maxHP, 4); - v0 = (0 + 178); - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_WATER_ABSORB) == TRUE + && moveType == TYPE_WATER + && (battleCtx->battleStatusMask & SYSCTL_FIRST_OF_MULTI_TURN) == FALSE // do not proc on first turn of Dive + && CURRENT_MOVE_DATA.power) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[defender].maxHP, 4); + subscript = BATTLE_SUBSEQ_ABILITY_RESTORES_HP; } - if (Battler_IgnorableAbility(param0, param1, param2, 18) == 1) { - if ((v1 == 10) && ((param0->battleMons[param2].status & 0x20) == 0) && ((param0->battleStatusMask & 0x20) == 0) && ((param0->aiContext.moveTable[param0->moveCur].power) || (param0->moveCur == 261))) { - v0 = (0 + 179); - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_FLASH_FIRE) == TRUE + && moveType == TYPE_FIRE + && (battleCtx->battleMons[defender].status & MON_CONDITION_FREEZE) == FALSE + && (battleCtx->battleStatusMask & SYSCTL_FIRST_OF_MULTI_TURN) == FALSE + && (CURRENT_MOVE_DATA.power || battleCtx->moveCur == MOVE_WILL_O_WISP)) { + subscript = BATTLE_SUBSEQ_ABSORB_AND_BOOST_FIRE_TYPE_MOVES; } - if (Battler_IgnorableAbility(param0, param1, param2, 43) == 1) { - { - int v2; - - for (v2 = 0; v2 < NELEMS(Unk_ov16_02270B8C); v2++) { - if (Unk_ov16_02270B8C[v2] == param0->moveCur) { - v0 = (0 + 181); - break; - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_SOUNDPROOF) == TRUE) { + for (int i = 0; i < NELEMS(sSoundMoves); i++) { + if (sSoundMoves[i] == battleCtx->moveCur) { + subscript = BATTLE_SUBSEQ_BLOCKED_BY_SOUNDPROOF; + break; } } } - if (Battler_IgnorableAbility(param0, param1, param2, 78) == 1) { - if ((v1 == 13) && (param1 != param2)) { - v0 = (0 + 182); - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_MOTOR_DRIVE) == TRUE + && moveType == TYPE_ELECTRIC + && attacker != defender) { + subscript = BATTLE_SUBSEQ_ABSORB_AND_SPEED_UP_1_STAGE; } - if (Battler_IgnorableAbility(param0, param1, param2, 87) == 1) { - if ((v1 == 11) && ((param0->battleStatusMask & 0x20) == 0) && (param0->aiContext.moveTable[param0->moveCur].power)) { - param0->hpCalcTemp = BattleSystem_Divide(param0->battleMons[param2].maxHP, 4); - v0 = (0 + 178); - } + if (Battler_IgnorableAbility(battleCtx, attacker, defender, ABILITY_DRY_SKIN) == TRUE + && moveType == TYPE_WATER + && (battleCtx->battleStatusMask & SYSCTL_FIRST_OF_MULTI_TURN) == FALSE + && CURRENT_MOVE_DATA.power) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[defender].maxHP, 4); + subscript = BATTLE_SUBSEQ_ABILITY_RESTORES_HP; } - return v0; + return subscript; } -BOOL BattleSystem_TriggerTurnEndAbility (BattleSystem * param0, BattleContext * param1, int param2) +BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem *battleSys, BattleContext *battleCtx, int battler) { - BOOL v0; - int v1; - - v0 = 0; - - switch (Battler_Ability(param1, param2)) { - case 3: - if ((param1->battleMons[param2].curHP) && (param1->battleMons[param2].statBoosts[0x3] < 12) && (param1->battleMons[param2].moveEffectsData.fakeOutTurnNumber != param1->totalTurns + 1)) { - param1->sideEffectParam = 0x11; - param1->sideEffectType = 3; - param1->sideEffectMon = param2; - v1 = (0 + 12); - v0 = 1; + BOOL result = FALSE; + int subscript; + + switch (Battler_Ability(battleCtx, battler)) { + case ABILITY_SPEED_BOOST: + if (battleCtx->battleMons[battler].curHP + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SPEED] < 12 + && battleCtx->battleMons[battler].moveEffectsData.fakeOutTurnNumber != battleCtx->totalTurns + 1) { + battleCtx->sideEffectParam = MOVE_SUBSCRIPT_PTR_SPEED_UP_1_STAGE; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; + battleCtx->sideEffectMon = battler; + subscript = BATTLE_SUBSEQ_UPDATE_STAT_STAGE; + result = TRUE; } break; - case 61: - if ((param1->battleMons[param2].status & 0xff) && (param1->battleMons[param2].curHP) && (BattleSystem_RandNext(param0) % 10 < 3)) { - if (param1->battleMons[param2].status & 0x7) { - param1->msgTemp = 0; - } else if (param1->battleMons[param2].status & 0xf88) { - param1->msgTemp = 1; - } else if (param1->battleMons[param2].status & 0x10) { - param1->msgTemp = 2; - } else if (param1->battleMons[param2].status & 0x40) { - param1->msgTemp = 3; + + case ABILITY_SHED_SKIN: + if ((battleCtx->battleMons[battler].status & MON_CONDITION_ANY) + && battleCtx->battleMons[battler].curHP + && BattleSystem_RandNext(battleSys) % 10 < 3) { + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + battleCtx->msgTemp = MSGCOND_SLEEP; + } else if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + battleCtx->msgTemp = MSGCOND_POISON; + } else if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + battleCtx->msgTemp = MSGCOND_BURN; + } else if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + battleCtx->msgTemp = MSGCOND_PARALYSIS; } else { - param1->msgTemp = 4; + battleCtx->msgTemp = MSGCOND_FREEZE; } - param1->msgBattlerTemp = param2; - - v1 = (0 + 190); - v0 = 1; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_ABILITY_RESTORE_STATUS; + result = TRUE; } break; - default: - break; } - if (v0 == 1) { - BattleSystem_LoadScript(param1, 1, v1); - param1->commandNext = param1->command; - param1->command = 21; + if (result == TRUE) { + LOAD_SUBSEQ(subscript); + battleCtx->commandNext = battleCtx->command; + battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; } - return v0; + return result; } int BattleSystem_Divide(int dividend, int divisor) @@ -3713,487 +3592,559 @@ int BattleSystem_Divide(int dividend, int divisor) return dividend; } -int BattleSystem_ShowMonChecks (BattleSystem * param0, BattleContext * param1) +enum { + SWITCH_IN_CHECK_STATE_START = 0, + + SWITCH_IN_CHECK_STATE_FIELD_WEATHER = SWITCH_IN_CHECK_STATE_START, + SWITCH_IN_CHECK_STATE_TRACE, + SWITCH_IN_CHECK_STATE_WEATHER_ABILITIES, + SWITCH_IN_CHECK_STATE_INTIMIDATE, + SWITCH_IN_CHECK_STATE_DOWNLOAD, + SWITCH_IN_CHECK_STATE_ANTICIPATION, + SWITCH_IN_CHECK_STATE_FOREWARN, + SWITCH_IN_CHECK_STATE_FRISK, + SWITCH_IN_CHECK_STATE_SLOW_START, + SWITCH_IN_CHECK_STATE_MOLD_BREAKER, + SWITCH_IN_CHECK_STATE_PRESSURE, + SWITCH_IN_CHECK_STATE_FORM_CHANGE, + SWITCH_IN_CHECK_STATE_AMULET_COIN, + SWITCH_IN_CHECK_STATE_FORBIDDEN_STATUS, + SWITCH_IN_CHECK_STATE_HELD_ITEM_STATUS, + + SWITCH_IN_CHECK_STATE_DONE, +}; + +enum { + SWITCH_IN_CHECK_RESULT_CONTINUE = 0, + SWITCH_IN_CHECK_RESULT_BREAK, + SWITCH_IN_CHECK_RESULT_DONE, +}; + +int BattleSystem_TriggerEffectOnSwitch(BattleSystem *battleSys, BattleContext *battleCtx) { - int v0, v1; - int v2; - int v3; - int v4; - int v5; + // must declare C89-style to match + int i; + int subscript; + int result; + int battler; + int maxBattlers; - v5 = BattleSystem_MaxBattlers(param0); - v2 = 0; - v3 = 0; + maxBattlers = BattleSystem_MaxBattlers(battleSys); + subscript = NULL; + result = SWITCH_IN_CHECK_RESULT_CONTINUE; do { - switch (param1->switchInCheckState) { - case 0: - if (param1->fieldWeatherChecked == 0) { - switch (ov16_0223F21C(param0)) { - case 2: - case 3: - case 4: - v2 = (0 + 271); - v3 = 1; + switch (battleCtx->switchInCheckState) { + case SWITCH_IN_CHECK_STATE_FIELD_WEATHER: + if (battleCtx->fieldWeatherChecked == FALSE) { + switch (BattleSystem_FieldWeather(battleSys)) { + case OVERWORLD_WEATHER_RAINING: + case OVERWORLD_WEATHER_HEAVY_RAIN: + case OVERWORLD_WEATHER_THUNDERSTORM: + subscript = BATTLE_SUBSEQ_OVERWORLD_RAIN; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; - case 5: - case 6: - case 7: - v2 = (0 + 272); - v3 = 1; + + case OVERWORLD_WEATHER_SNOWING: + case OVERWORLD_WEATHER_HEAVY_SNOW: + case OVERWORLD_WEATHER_BLIZZARD: + subscript = BATTLE_SUBSEQ_OVERWORLD_HAIL; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; - case 10: - v2 = (0 + 273); - v3 = 1; + + case OVERWORLD_WEATHER_SANDSTORM: + subscript = BATTLE_SUBSEQ_OVERWORLD_SAND; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; - case 14: - case 15: - v2 = (0 + 274); - v3 = 1; + + case OVERWORLD_WEATHER_FOG: + case OVERWORLD_WEATHER_DEEP_FOG: + subscript = BATTLE_SUBSEQ_OVERWORLD_FOG; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; - case 1001: - v2 = (0 + 294); - v3 = 1; + + case OVERWORLD_WEATHER_HARSH_SUN: + subscript = BATTLE_SUBSEQ_OVERWORLD_SUN; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; - case 1002: - v2 = (0 + 295); - v3 = 1; + + case OVERWORLD_WEATHER_TRICK_ROOM: + subscript = BATTLE_SUBSEQ_OVERWORLD_TRICK_ROOM; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; + default: break; } - if (v3 == 1) { - param1->fieldWeatherChecked = 1; + if (result == SWITCH_IN_CHECK_RESULT_BREAK) { + battleCtx->fieldWeatherChecked = TRUE; } } - param1->switchInCheckState++; + battleCtx->switchInCheckState++; break; - case 1: - { - int v6, v7; - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - v6 = BattleSystem_EnemyInSlot(param0, v4, 0); - v7 = BattleSystem_EnemyInSlot(param0, v4, 2); + case SWITCH_IN_CHECK_STATE_TRACE: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + int defender1 = BattleSystem_EnemyInSlot(battleSys, battler, ENEMY_IN_SLOT_RIGHT); + int defender2 = BattleSystem_EnemyInSlot(battleSys, battler, ENEMY_IN_SLOT_LEFT); - param1->msgDefender = ov16_0225B840(param0, param1, v6, v7); + battleCtx->msgDefender = ChooseTraceTarget(battleSys, battleCtx, defender1, defender2); - if ((param1->battleMons[v4].traceAnnounced == 0) && (param1->msgDefender != 0xff) && (param1->battleMons[v4].curHP) && (param1->battleMons[v4].heldItem != 112) && (param1->battleMons[param1->msgDefender].curHP) && (Battler_Ability(param1, v4) == 36)) { - param1->battleMons[v4].traceAnnounced = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 187); - v3 = 1; + if (battleCtx->battleMons[battler].traceAnnounced == FALSE + && battleCtx->msgDefender != BATTLER_NONE + && battleCtx->battleMons[battler].curHP + && battleCtx->battleMons[battler].heldItem != ITEM_GRISEOUS_ORB + && battleCtx->battleMons[battleCtx->msgDefender].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_TRACE) { + battleCtx->battleMons[battler].traceAnnounced = TRUE; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_TRACE; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 2: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if ((param1->battleMons[v4].weatherAbilityAnnounced == 0) && (param1->battleMons[v4].curHP)) { - switch (Battler_Ability(param1, v4)) { - case 2: - param1->battleMons[v4].weatherAbilityAnnounced = 1; + case SWITCH_IN_CHECK_STATE_WEATHER_ABILITIES: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].weatherAbilityAnnounced == FALSE + && battleCtx->battleMons[battler].curHP) { + switch (Battler_Ability(battleCtx, battler)) { + case ABILITY_DRIZZLE: + battleCtx->battleMons[battler].weatherAbilityAnnounced = TRUE; - if ((param1->fieldConditionsMask & 0x2) == 0) { - v2 = (0 + 183); - v3 = 1; + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_RAINING_PERM) == FALSE) { + subscript = BATTLE_SUBSEQ_DRIZZLE; + result = SWITCH_IN_CHECK_RESULT_BREAK; } break; - case 45: - param1->battleMons[v4].weatherAbilityAnnounced = 1; - if ((param1->fieldConditionsMask & 0x8) == 0) { - v2 = (0 + 184); - v3 = 1; + case ABILITY_SAND_STREAM: + battleCtx->battleMons[battler].weatherAbilityAnnounced = TRUE; + + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_SANDSTORM_PERM) == FALSE) { + subscript = BATTLE_SUBSEQ_SAND_STREAM; + result = SWITCH_IN_CHECK_RESULT_BREAK; } break; - case 70: - param1->battleMons[v4].weatherAbilityAnnounced = 1; - if ((param1->fieldConditionsMask & 0x20) == 0) { - v2 = (0 + 185); - v3 = 1; + case ABILITY_DROUGHT: + battleCtx->battleMons[battler].weatherAbilityAnnounced = TRUE; + + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_SUNNY_PERM) == FALSE) { + subscript = BATTLE_SUBSEQ_DROUGHT; + result = SWITCH_IN_CHECK_RESULT_BREAK; } break; - case 117: - param1->battleMons[v4].weatherAbilityAnnounced = 1; - if ((param1->fieldConditionsMask & 0x80) == 0) { - v2 = (0 + 252); - v3 = 1; + case ABILITY_SNOW_WARNING: + battleCtx->battleMons[battler].weatherAbilityAnnounced = TRUE; + + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_HAILING_PERM) == FALSE) { + subscript = BATTLE_SUBSEQ_SNOW_WARNING; + result = SWITCH_IN_CHECK_RESULT_BREAK; } break; } } - if (v3 == 1) { - param1->msgBattlerTemp = v4; + if (result == SWITCH_IN_CHECK_RESULT_BREAK) { + battleCtx->msgBattlerTemp = battler; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 3: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - - if ((param1->battleMons[v4].intimidateAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 22)) { - param1->battleMons[v4].intimidateAnnounced = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 186); - v3 = 1; + + case SWITCH_IN_CHECK_STATE_INTIMIDATE: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].intimidateAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_INTIMIDATE) { + battleCtx->battleMons[battler].intimidateAnnounced = TRUE; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_INTIMIDATE; + result = TRUE; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 4: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if ((param1->battleMons[v4].downloadAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 88)) { - { - int v8; - int v9, v10; + case SWITCH_IN_CHECK_STATE_DOWNLOAD: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; - v9 = 0; - v10 = 0; + if (battleCtx->battleMons[battler].downloadAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_DOWNLOAD) { + int j; // must declare here to match + int sumDef = 0, sumSpDef = 0; - for (v8 = 0; v8 < v5; v8++) { - if ((Battler_Side(param0, v4) != Battler_Side(param0, v8)) && ((param1->battleMons[v8].statusVolatile & 0x1000000) == 0) && (param1->battleMons[v8].curHP)) { - v9 += param1->battleMons[v8].defense * sStatStageBoosts[param1->battleMons[v8].statBoosts[0x2]].numerator / sStatStageBoosts[param1->battleMons[v8].statBoosts[0x2]].denominator; - v10 += param1->battleMons[v8].spDefense * sStatStageBoosts[param1->battleMons[v8].statBoosts[0x5]].numerator / sStatStageBoosts[param1->battleMons[v8].statBoosts[0x5]].denominator; - } + for (j = 0; j < maxBattlers; j++) { + if (Battler_Side(battleSys, battler) != Battler_Side(battleSys, j) + && (battleCtx->battleMons[j].statusVolatile & VOLATILE_CONDITION_SUBSTITUTE) == FALSE + && battleCtx->battleMons[j].curHP) { + sumDef += battleCtx->battleMons[j].defense + * sStatStageBoosts[battleCtx->battleMons[j].statBoosts[BATTLE_STAT_DEFENSE]].numerator + / sStatStageBoosts[battleCtx->battleMons[j].statBoosts[BATTLE_STAT_DEFENSE]].denominator; + sumSpDef += battleCtx->battleMons[j].spDefense + * sStatStageBoosts[battleCtx->battleMons[j].statBoosts[BATTLE_STAT_SP_DEFENSE]].numerator + / sStatStageBoosts[battleCtx->battleMons[j].statBoosts[BATTLE_STAT_SP_DEFENSE]].denominator; } + } - param1->battleMons[v4].downloadAnnounced = 1; - - if ((v9 + v10) != 0) { - if (v9 >= v10) { - param1->sideEffectParam = 0x12; - } else { - param1->sideEffectParam = 0xf; - } + battleCtx->battleMons[battler].downloadAnnounced = TRUE; - param1->sideEffectType = 3; - param1->sideEffectMon = v4; - v2 = (0 + 12); - v3 = 1; - break; + if (sumDef + sumSpDef != 0) { + if (sumDef >= sumSpDef) { + battleCtx->sideEffectParam = MOVE_SUBSCRIPT_PTR_SP_ATTACK_UP_1_STAGE; + } else { + battleCtx->sideEffectParam = MOVE_SUBSCRIPT_PTR_ATTACK_UP_1_STAGE; } + + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; + battleCtx->sideEffectMon = battler; + subscript = BATTLE_SUBSEQ_UPDATE_STAT_STAGE; + result = SWITCH_IN_CHECK_RESULT_BREAK; + break; } } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 5: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if ((param1->battleMons[v4].anticipationAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 107)) { - param1->battleMons[v4].anticipationAnnounced = 1; - { - int v11, v12; - u16 v13; - u32 v14; + case SWITCH_IN_CHECK_STATE_ANTICIPATION: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; - for (v11 = 0; v11 < v5; v11++) { - if ((Battler_Side(param0, v4) != Battler_Side(param0, v11)) && (param1->battleMons[v11].curHP)) { - for (v12 = 0; v12 < 4; v12++) { - v13 = param1->battleMons[v11].moves[v12]; + if (battleCtx->battleMons[battler].anticipationAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_ANTICIPATION) { + int j, k; + u16 move; + u32 effectiveness; - if (v13) { - v14 = 0; - param1->damage = BattleSystem_CheckTypeChart(param0, param1, v13, NULL, v11, v4, param1->damage, &v14); + battleCtx->battleMons[battler].anticipationAnnounced = TRUE; - if (((v14 & 0x8) == 0) && (ov16_0225B8E4(param1, v13) == 0) && ((v14 & 0x2) || ((param1->aiContext.moveTable[v13].effect == 38) && (param1->battleMons[v4].level <= param1->battleMons[v11].level)))) { - v3 = 1; - break; - } + for (j = 0; j < maxBattlers; j++) { + if (Battler_Side(battleSys, battler) != Battler_Side(battleSys, j) && battleCtx->battleMons[j].curHP) { + for (k = 0; k < 4; k++) { + move = battleCtx->battleMons[j].moves[k]; + + if (move) { + effectiveness = 0; + battleCtx->damage = BattleSystem_CheckTypeChart(battleSys, battleCtx, move, NULL, j, battler, battleCtx->damage, &effectiveness); + + if ((effectiveness & MOVE_STATUS_INEFFECTIVE) == FALSE + && MoveCannotTriggerAnticipation(battleCtx, move) == FALSE + && ((effectiveness & MOVE_STATUS_SUPER_EFFECTIVE) + || (MOVE_DATA(move).effect == BATTLE_EFFECT_ONE_HIT_KO + && battleCtx->battleMons[battler].level <= battleCtx->battleMons[j].level))) { + result = SWITCH_IN_CHECK_RESULT_BREAK; + break; } } + } - if (v3 == 1) { - break; - } + if (result == SWITCH_IN_CHECK_RESULT_BREAK) { + break; } } + } - if (v3 == 1) { - param1->msgBattlerTemp = v4; - v2 = (0 + 194); - } - break; + if (result == SWITCH_IN_CHECK_RESULT_BREAK) { + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_ANTICIPATION; } + break; } } - if (v0 == v5) { - param1->switchInCheckState++; - } - break; - case 6: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - - if ((param1->battleMons[v4].forewarnAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 108)) { - param1->battleMons[v4].forewarnAnnounced = 1; - { - int v15, v16; - u16 v17; - u32 v18, v19; - int v20; - - v19 = 0; - v20 = 0; - - for (v15 = 0; v15 < v5; v15++) { - if ((Battler_Side(param0, v4) != Battler_Side(param0, v15)) && (param1->battleMons[v15].curHP)) { - v20 += param1->battleMons[v15].curHP; - - for (v16 = 0; v16 < 4; v16++) { - v17 = param1->battleMons[v15].moves[v16]; - - v18 = param1->aiContext.moveTable[v17].power; - - switch (v18) { - case 1: - switch (param1->aiContext.moveTable[v17].effect) { - case 38: - if ((v19 < 150) || ((v19 == 150) && (BattleSystem_RandNext(param0) & 1))) { - v19 = 150; - param1->msgMoveTemp = v17; - } - break; - case 89: - case 144: - case 227: - if ((v19 < 120) || ((v19 == 120) && (BattleSystem_RandNext(param0) & 1))) { - v19 = 120; - param1->msgMoveTemp = v17; - } - break; - default: - if ((v19 < 80) || ((v19 == 80) && (BattleSystem_RandNext(param0) & 1))) { - v19 = 80; - param1->msgMoveTemp = v17; - } - break; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; + } + break; + + case SWITCH_IN_CHECK_STATE_FOREWARN: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].forewarnAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_FOREWARN) { + int j, k; + u16 move; + u32 movePower, maxPower; + int sumEnemyHP; + + battleCtx->battleMons[battler].forewarnAnnounced = TRUE; + maxPower = 0; + sumEnemyHP = 0; + + for (j = 0; j < maxBattlers; j++) { + if (Battler_Side(battleSys, battler) != Battler_Side(battleSys, j) + && battleCtx->battleMons[j].curHP) { + sumEnemyHP += battleCtx->battleMons[j].curHP; + + for (k = 0; k < 4; k++) { + move = battleCtx->battleMons[j].moves[k]; + movePower = MOVE_DATA(move).power; + + if (movePower == 1) { + switch (MOVE_DATA(move).effect) { + case BATTLE_EFFECT_ONE_HIT_KO: + if (maxPower < 150 || (maxPower == 150 && (BattleSystem_RandNext(battleSys) & 1))) { + maxPower = 150; + battleCtx->msgMoveTemp = move; } break; + + case BATTLE_EFFECT_COUNTER: + case BATTLE_EFFECT_MIRROR_COAT: + case BATTLE_EFFECT_METAL_BURST: + if (maxPower < 120 || (maxPower == 120 && (BattleSystem_RandNext(battleSys) & 1))) { + maxPower = 120; + battleCtx->msgMoveTemp = move; + } + break; + default: - if ((v19 < v18) || ((v19 == v18) && (BattleSystem_RandNext(param0) & 1))) { - v19 = v18; - param1->msgMoveTemp = v17; + if (maxPower < 80 || (maxPower == 80 && (BattleSystem_RandNext(battleSys) & 1))) { + maxPower = 80; + battleCtx->msgMoveTemp = move; } break; } + } else if (maxPower < movePower || (maxPower == movePower && (BattleSystem_RandNext(battleSys) & 1))) { + maxPower = movePower; + battleCtx->msgMoveTemp = move; } } } + } - if (v19) { - param1->msgBattlerTemp = v4; + if (maxPower) { + battleCtx->msgBattlerTemp = battler; - v2 = (0 + 195); - v3 = 1; - } else if (v20) { - v15 = BattleSystem_RandomOpponent(param0, param1, v4); - v16 = Battler_CountMoves(param0, param1, v15); + subscript = BATTLE_SUBSEQ_FOREWARN; + result = SWITCH_IN_CHECK_RESULT_BREAK; + } else if (sumEnemyHP) { + j = BattleSystem_RandomOpponent(battleSys, battleCtx, battler); + k = Battler_CountMoves(battleSys, battleCtx, j); - param1->msgMoveTemp = param1->battleMons[v15].moves[BattleSystem_RandNext(param0) % v16]; - param1->msgBattlerTemp = v4; + battleCtx->msgMoveTemp = battleCtx->battleMons[j].moves[BattleSystem_RandNext(battleSys) % k]; + battleCtx->msgBattlerTemp = battler; - v2 = (0 + 195); - v3 = 1; - } - break; + subscript = BATTLE_SUBSEQ_FOREWARN; + result = SWITCH_IN_CHECK_RESULT_BREAK; } + break; } } - if (v0 == v5) { - param1->switchInCheckState++; - } - break; - case 7: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - - if ((param1->battleMons[v4].friskAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 119)) { - param1->battleMons[v4].friskAnnounced = 1; - - if (BattleSystem_BattleType(param0) & 0x2) { - { - int v21[2]; - - v21[0] = BattleSystem_EnemyInSlot(param0, v4, 0); - v21[1] = BattleSystem_EnemyInSlot(param0, v4, 2); - - if ((param1->battleMons[v21[0]].curHP) && (param1->battleMons[v21[0]].heldItem) && (param1->battleMons[v21[1]].curHP) && (param1->battleMons[v21[1]].heldItem)) { - param1->msgItemTemp = param1->battleMons[v21[BattleSystem_RandNext(param0) & 1]].heldItem; - v3 = 1; - } else if ((param1->battleMons[v21[0]].curHP) && (param1->battleMons[v21[0]].heldItem)) { - param1->msgItemTemp = param1->battleMons[v21[0]].heldItem; - v3 = 1; - } else if ((param1->battleMons[v21[1]].curHP) && (param1->battleMons[v21[1]].heldItem)) { - param1->msgItemTemp = param1->battleMons[v21[1]].heldItem; - v3 = 1; - } - } - } else { - if ((param1->battleMons[v4 ^ 1].curHP) && (param1->battleMons[v4 ^ 1].heldItem)) { - param1->msgItemTemp = param1->battleMons[v4 ^ 1].heldItem; - v3 = 1; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; + } + break; + + case SWITCH_IN_CHECK_STATE_FRISK: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].friskAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_FRISK) { + battleCtx->battleMons[battler].friskAnnounced = TRUE; + + if (BattleSystem_BattleType(battleSys) & BATTLE_TYPE_DOUBLES) { + int enemies[] = { + BattleSystem_EnemyInSlot(battleSys, battler, ENEMY_IN_SLOT_RIGHT), + BattleSystem_EnemyInSlot(battleSys, battler, ENEMY_IN_SLOT_LEFT), + }; + + if (battleCtx->battleMons[enemies[0]].curHP + && battleCtx->battleMons[enemies[0]].heldItem + && battleCtx->battleMons[enemies[1]].curHP + && battleCtx->battleMons[enemies[1]].heldItem) { + battleCtx->msgItemTemp = battleCtx->battleMons[enemies[BattleSystem_RandNext(battleSys) & 1]].heldItem; + result = SWITCH_IN_CHECK_RESULT_BREAK; + } else if (battleCtx->battleMons[enemies[0]].curHP + && battleCtx->battleMons[enemies[0]].heldItem) { + battleCtx->msgItemTemp = battleCtx->battleMons[enemies[0]].heldItem; + result = SWITCH_IN_CHECK_RESULT_BREAK; + } else if (battleCtx->battleMons[enemies[1]].curHP + && battleCtx->battleMons[enemies[1]].heldItem) { + battleCtx->msgItemTemp = battleCtx->battleMons[enemies[1]].heldItem; + result = SWITCH_IN_CHECK_RESULT_BREAK; } + } else if (battleCtx->battleMons[battler ^ 1].curHP && battleCtx->battleMons[battler ^ 1].heldItem) { + battleCtx->msgItemTemp = battleCtx->battleMons[battler ^ 1].heldItem; + result = SWITCH_IN_CHECK_RESULT_BREAK; } } - if (v3 == 1) { - param1->msgBattlerTemp = v4; - v2 = (0 + 253); + if (result == SWITCH_IN_CHECK_RESULT_BREAK) { + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_FRISK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 8: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if ((param1->battleMons[v4].slowStartAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 112) && (param1->totalTurns <= param1->battleMons[v4].moveEffectsData.slowStartTurnNumber)) { - param1->battleMons[v4].slowStartAnnounced = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 196); - v3 = 1; + case SWITCH_IN_CHECK_STATE_SLOW_START: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].slowStartAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_SLOW_START + && battleCtx->totalTurns <= battleCtx->battleMons[battler].moveEffectsData.slowStartTurnNumber) { + battleCtx->battleMons[battler].slowStartAnnounced = TRUE; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_SLOW_START; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } - if ((param1->battleMons[v4].slowStartFinished == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 112) && ((param1->totalTurns - param1->battleMons[v4].moveEffectsData.slowStartTurnNumber) == 5)) { - param1->battleMons[v4].slowStartFinished = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 197); - v3 = 1; + if ((battleCtx->battleMons[battler].slowStartFinished == 0) && (battleCtx->battleMons[battler].curHP) && (Battler_Ability(battleCtx, battler) == 112) && ((battleCtx->totalTurns - battleCtx->battleMons[battler].moveEffectsData.slowStartTurnNumber) == 5)) { + battleCtx->battleMons[battler].slowStartFinished = 1; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_SLOW_START_END; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 9: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - - if ((param1->battleMons[v4].moldBreakerAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 104)) { - param1->battleMons[v4].moldBreakerAnnounced = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 177); - v3 = 1; + + case SWITCH_IN_CHECK_STATE_MOLD_BREAKER: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].moldBreakerAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_MOLD_BREAKER) { + battleCtx->battleMons[battler].moldBreakerAnnounced = TRUE; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_MOLD_BREAKER; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 10: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if ((param1->battleMons[v4].pressureAnnounced == 0) && (param1->battleMons[v4].curHP) && (Battler_Ability(param1, v4) == 46)) { - param1->battleMons[v4].pressureAnnounced = 1; - param1->msgBattlerTemp = v4; - v2 = (0 + 285); - v3 = 1; + case SWITCH_IN_CHECK_STATE_PRESSURE: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battler].pressureAnnounced == FALSE + && battleCtx->battleMons[battler].curHP + && Battler_Ability(battleCtx, battler) == ABILITY_PRESSURE) { + battleCtx->battleMons[battler].pressureAnnounced = TRUE; + battleCtx->msgBattlerTemp = battler; + subscript = BATTLE_SUBSEQ_PRESSURE; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 11: - if (BattleSystem_UpdateWeatherForms(param0, param1, &v2) == 1) { - v3 = 1; + + case SWITCH_IN_CHECK_STATE_FORM_CHANGE: + if (BattleSystem_TriggerFormChange(battleSys, battleCtx, &subscript) == TRUE) { + result = SWITCH_IN_CHECK_RESULT_BREAK; } else { - param1->switchInCheckState++; + battleCtx->switchInCheckState++; } break; - case 12: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if (BattleSystem_GetItemData(param1, param1->battleMons[v4].heldItem, 1) == 58) { - param1->prizeMoneyMul = 2; + case SWITCH_IN_CHECK_STATE_AMULET_COIN: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (BattleSystem_GetItemData(battleCtx, battleCtx->battleMons[battler].heldItem, ITEM_PARAM_HOLD_EFFECT) == HOLD_EFFECT_MONEY_UP) { + battleCtx->prizeMoneyMul = 2; } } - param1->switchInCheckState++; + battleCtx->switchInCheckState++; break; - case 13: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if (BattleSystem_RecoverStatusByAbility(param0, param1, v4, 1) == 1) { - v2 = (0 + 221); - v3 = 1; + case SWITCH_IN_CHECK_STATE_FORBIDDEN_STATUS: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (BattleSystem_RecoverStatusByAbility(battleSys, battleCtx, battler, TRUE) == TRUE) { + subscript = BATTLE_SUBSEQ_ABILITY_FORBIDS_STATUS; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 14: - for (v0 = 0; v0 < v5; v0++) { - v4 = param1->monSpeedOrder[v0]; - if (BattleSystem_TriggerHeldItemOnStatus(param0, param1, v4, &v2) == 1) { - param1->msgBattlerTemp = v4; - v3 = 1; + case SWITCH_IN_CHECK_STATE_HELD_ITEM_STATUS: + for (i = 0; i < maxBattlers; i++) { + battler = battleCtx->monSpeedOrder[i]; + + if (BattleSystem_TriggerHeldItemOnStatus(battleSys, battleCtx, battler, &subscript) == TRUE) { // document + battleCtx->msgBattlerTemp = battler; + result = SWITCH_IN_CHECK_RESULT_BREAK; break; } } - if (v0 == v5) { - param1->switchInCheckState++; + if (i == maxBattlers) { + battleCtx->switchInCheckState++; } break; - case 15: - param1->switchInCheckState = 0; - v3 = 2; + + case SWITCH_IN_CHECK_STATE_DONE: + battleCtx->switchInCheckState = 0; + result = SWITCH_IN_CHECK_RESULT_DONE; break; } - } while (v3 == 0); + } while (result == SWITCH_IN_CHECK_RESULT_CONTINUE); - return v2; + return subscript; } int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCtx, int attacker) @@ -4219,7 +4170,7 @@ int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCt return chosen; } -BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq) +BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript) { BOOL result = FALSE; @@ -4242,11 +4193,11 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba && (DEFENDER_SELF_TURN_FLAGS.physicalDamageTaken || DEFENDER_SELF_TURN_FLAGS.specialDamageTaken) && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_MAKES_CONTACT) && BattleSystem_RandNext(battleSys) % 10 < 3) { - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; battleCtx->sideEffectMon = battleCtx->attacker; battleCtx->msgBattlerTemp = battleCtx->defender; - *nextSeq = BATTLE_SUBSEQ_PARALYZE; + *subscript = BATTLE_SUBSEQ_PARALYZE; result = TRUE; } break; @@ -4270,7 +4221,7 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba && CURRENT_MOVE_DATA.power && BattleMon_Get(battleCtx, battleCtx->defender, 27, NULL) != moveType && BattleMon_Get(battleCtx, battleCtx->defender, 28, NULL) != moveType) { - *nextSeq = BATTLE_SUBSEQ_COLOR_CHANGE; + *subscript = BATTLE_SUBSEQ_COLOR_CHANGE; battleCtx->msgTemp = moveType; result = TRUE; } @@ -4287,7 +4238,7 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba battleCtx->hpCalcTemp = BattleSystem_Divide(ATTACKING_MON.maxHP * -1, 8); battleCtx->msgBattlerTemp = battleCtx->attacker; - *nextSeq = BATTLE_SUBSEQ_ROUGH_SKIN; + *subscript = BATTLE_SUBSEQ_ROUGH_SKIN; result = TRUE; } break; @@ -4304,17 +4255,17 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba switch (BattleSystem_RandNext(battleSys) % 3) { case 0: default: - *nextSeq = BATTLE_SUBSEQ_POISON; + *subscript = BATTLE_SUBSEQ_POISON; break; case 1: - *nextSeq = BATTLE_SUBSEQ_PARALYZE; + *subscript = BATTLE_SUBSEQ_PARALYZE; break; case 2: - *nextSeq = BATTLE_SUBSEQ_FALL_ASLEEP; + *subscript = BATTLE_SUBSEQ_FALL_ASLEEP; break; } - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; battleCtx->sideEffectMon = battleCtx->attacker; battleCtx->msgBattlerTemp = battleCtx->defender; @@ -4331,11 +4282,11 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba && (DEFENDER_SELF_TURN_FLAGS.physicalDamageTaken || DEFENDER_SELF_TURN_FLAGS.specialDamageTaken) && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_MAKES_CONTACT) && BattleSystem_RandNext(battleSys) % 10 < 3) { - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; battleCtx->sideEffectMon = battleCtx->attacker; battleCtx->msgBattlerTemp = battleCtx->defender; - *nextSeq = BATTLE_SUBSEQ_POISON; + *subscript = BATTLE_SUBSEQ_POISON; result = TRUE; } break; @@ -4349,11 +4300,11 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba && (DEFENDER_SELF_TURN_FLAGS.physicalDamageTaken || DEFENDER_SELF_TURN_FLAGS.specialDamageTaken) && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_MAKES_CONTACT) && BattleSystem_RandNext(battleSys) % 10 < 3) { - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; battleCtx->sideEffectMon = battleCtx->attacker; battleCtx->msgBattlerTemp = battleCtx->defender; - *nextSeq = BATTLE_SUBSEQ_BURN; + *subscript = BATTLE_SUBSEQ_BURN; result = TRUE; } break; @@ -4368,11 +4319,11 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_MAKES_CONTACT) && DEFENDING_MON.curHP && BattleSystem_RandNext(battleSys) % 10 < 3) { - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; battleCtx->sideEffectMon = battleCtx->attacker; battleCtx->msgBattlerTemp = battleCtx->defender; - *nextSeq = BATTLE_SUBSEQ_INFATUATE; + *subscript = BATTLE_SUBSEQ_INFATUATE; result = TRUE; } break; @@ -4388,87 +4339,89 @@ BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *ba battleCtx->hpCalcTemp = BattleSystem_Divide(ATTACKING_MON.maxHP * -1, 4); battleCtx->msgBattlerTemp = battleCtx->attacker; - *nextSeq = BATTLE_SUBSEQ_AFTERMATH; + *subscript = BATTLE_SUBSEQ_AFTERMATH; result = TRUE; } break; - - default: - break; } return result; } -BOOL BattleSystem_RecoverStatusByAbility (BattleSystem * param0, BattleContext * param1, int param2, int param3) +BOOL BattleSystem_RecoverStatusByAbility(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int skipLoad) { - BOOL v0; - - v0 = 0; + BOOL result = FALSE; - switch (Battler_Ability(param1, param2)) { - case 17: - if (param1->battleMons[param2].status & 0xf88) { - param1->msgTemp = 1; - v0 = 1; + switch (Battler_Ability(battleCtx, battler)) { + case ABILITY_IMMUNITY: + if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + battleCtx->msgTemp = MSGCOND_POISON; + result = TRUE; } break; - case 20: - if (param1->battleMons[param2].statusVolatile & 0x7) { - param1->msgTemp = 5; - v0 = 1; + + case ABILITY_OWN_TEMPO: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION) { + battleCtx->msgTemp = MSGCOND_CONFUSION; + result = TRUE; } break; - case 7: - if (param1->battleMons[param2].status & 0x40) { - param1->msgTemp = 3; - v0 = 1; + + case ABILITY_LIMBER: + if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + battleCtx->msgTemp = MSGCOND_PARALYSIS; + result = TRUE; } break; - case 15: - case 72: - if (param1->battleMons[param2].status & 0x7) { - param1->msgTemp = 0; - v0 = 1; + + case ABILITY_INSOMNIA: + case ABILITY_VITAL_SPIRIT: + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + battleCtx->msgTemp = MSGCOND_SLEEP; + result = TRUE; } break; - case 41: - if (param1->battleMons[param2].status & 0x10) { - param1->msgTemp = 2; - v0 = 1; + + case ABILITY_WATER_VEIL: + if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + battleCtx->msgTemp = MSGCOND_BURN; + result = TRUE; } break; - case 40: - if (param1->battleMons[param2].status & 0x20) { - param1->msgTemp = 4; - v0 = 1; + + case ABILITY_MAGMA_ARMOR: + if (battleCtx->battleMons[battler].status & MON_CONDITION_FREEZE) { + battleCtx->msgTemp = MSGCOND_FREEZE; + result = TRUE; } break; - case 12: - if (param1->battleMons[param2].statusVolatile & 0xf0000) { - param1->msgTemp = 6; - v0 = 1; + + case ABILITY_OBLIVIOUS: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_ATTRACT) { + battleCtx->msgTemp = MSGCOND_INFATUATION; + result = TRUE; } break; - case 84: - if (param1->battleMons[param2].heldItem) { - param1->battleMons[param2].moveEffectsData.canUnburden = 1; + + case ABILITY_UNBURDEN: + if (battleCtx->battleMons[battler].heldItem) { + battleCtx->battleMons[battler].moveEffectsData.canUnburden = TRUE; } break; } - if (v0 == 1) { - param1->msgBattlerTemp = param2; - param1->msgAbilityTemp = Battler_Ability(param1, param2); + if (result == TRUE) { + battleCtx->msgBattlerTemp = battler; + battleCtx->msgAbilityTemp = Battler_Ability(battleCtx, battler); - if (param3 == 0) { - BattleSystem_LoadScript(param1, 1, (0 + 221)); - param1->commandNext = param1->command; - param1->command = 21; + if (skipLoad == FALSE) { + LOAD_SUBSEQ(BATTLE_SUBSEQ_ABILITY_FORBIDS_STATUS); + battleCtx->commandNext = battleCtx->command; + battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; } } - return v0; + return result; } BOOL Ability_ForbidsStatus(BattleContext *battleSys, int ability, int status) @@ -4543,7 +4496,7 @@ BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * ba } if (nextSeq) { - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_ABILITY; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_ABILITY; LOAD_SUBSEQ(nextSeq); battleCtx->commandNext = controllerCommand; @@ -4553,7 +4506,7 @@ BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * ba } } - result = BattleSystem_UpdateWeatherForms(battleSys, battleCtx, &nextSeq); + result = BattleSystem_TriggerFormChange(battleSys, battleCtx, &nextSeq); if (result == TRUE) { LOAD_SUBSEQ(nextSeq); battleCtx->commandNext = controllerCommand; @@ -4580,7 +4533,7 @@ BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * ba if (result == TRUE) { nextSeq = BATTLE_SUBSEQ_INFATUATE; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_HELD_ITEM; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_HELD_ITEM; LOAD_SUBSEQ(nextSeq); battleCtx->commandNext = controllerCommand; @@ -4592,751 +4545,778 @@ BOOL BattleSystem_SynchronizeStatus(BattleSystem * battleSys, BattleContext * ba return FALSE; } -BOOL BattleSystem_TriggerHeldItem (BattleSystem * param0, BattleContext * param1, int param2) +BOOL BattleSystem_TriggerHeldItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler) { - BOOL v0; - int v1; - int v2; - int v3; - - v0 = 0; - v2 = Battler_HeldItemEffect(param1, param2); - v3 = Battler_HeldItemPower(param1, param2, 0); - - if (param1->battleMons[param2].curHP) { - switch (v2) { - case 1: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = v3; - v1 = (0 + 198); - v0 = 1; + BOOL result = FALSE; + int subscript; + int itemEffect = Battler_HeldItemEffect(battleCtx, battler); + int itemPower = Battler_HeldItemPower(battleCtx, battler, ITEM_POWER_CHECK_ALL); + + if (battleCtx->battleMons[battler].curHP) { + switch (itemEffect) { + case HOLD_EFFECT_HP_RESTORE: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = itemPower; + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; + result = TRUE; } break; - case 13: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP * v3, 100); - v1 = (0 + 198); - v0 = 1; + + case HOLD_EFFECT_HP_PCT_RESTORE: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP * itemPower, 100); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; + result = TRUE; } break; - case 5: - if (param1->battleMons[param2].status & 0x40) { - v1 = (0 + 199); - v0 = 1; + + case HOLD_EFFECT_PRZ_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_PRZ_RESTORE; + result = TRUE; } break; - case 6: - if (param1->battleMons[param2].status & 0x7) { - v1 = (0 + 200); - v0 = 1; + + case HOLD_EFFECT_SLP_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_SLP_RESTORE; + result = TRUE; } break; - case 7: - if (param1->battleMons[param2].status & 0xf88) { - v1 = (0 + 201); - v0 = 1; + + case HOLD_EFFECT_PSN_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_PSN_RESTORE; + result = TRUE; } break; - case 8: - if (param1->battleMons[param2].status & 0x10) { - v1 = (0 + 202); - v0 = 1; + + case HOLD_EFFECT_BRN_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_BRN_RESTORE; + result = TRUE; } break; - case 9: - if (param1->battleMons[param2].status & 0x20) { - v1 = (0 + 203); - v0 = 1; + + case HOLD_EFFECT_FRZ_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_FREEZE) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_FRZ_RESTORE; + result = TRUE; } break; - case 10: - { - int v4; - for (v4 = 0; v4 < 4; v4++) { - if ((param1->battleMons[param2].moves[v4]) && (param1->battleMons[param2].ppCur[v4] == 0)) { + case HOLD_EFFECT_PP_RESTORE: { + int i; + for (i = 0; i < LEARNED_MOVES_MAX; i++) { + if (battleCtx->battleMons[battler].moves[i] && battleCtx->battleMons[battler].ppCur[i] == 0) { break; } } - if (v4 != 4) { - BattleMon_AddVal(¶m1->battleMons[param2], 31 + v4, v3); - BattleMon_CopyToParty(param0, param1, param2); - param1->msgMoveTemp = param1->battleMons[param2].moves[v4]; - v1 = (0 + 204); - v0 = 1; + if (i != LEARNED_MOVES_MAX) { + BattleMon_AddVal(&battleCtx->battleMons[battler], BATTLEMON_CUR_PP_1 + i, itemPower); + BattleMon_CopyToParty(battleSys, battleCtx, battler); + battleCtx->msgMoveTemp = battleCtx->battleMons[battler].moves[i]; + subscript = BATTLE_SUBSEQ_HELD_ITEM_PP_RESTORE; + result = TRUE; } + + break; } - break; - case 11: - if (param1->battleMons[param2].statusVolatile & 0x7) { - v1 = (0 + 205); - v0 = 1; + + case HOLD_EFFECT_CONFUSE_RESTORE: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_CNF_RESTORE; + result = TRUE; } break; - case 12: - if ((param1->battleMons[param2].status & 0xff) || (param1->battleMons[param2].statusVolatile & 0x7)) { - if (param1->battleMons[param2].status & 0x40) { - v1 = (0 + 199); + + case HOLD_EFFECT_STATUS_RESTORE: + if ((battleCtx->battleMons[battler].status & MON_CONDITION_ANY) + || (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION)) { + if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_PRZ_RESTORE; } - if (param1->battleMons[param2].status & 0x7) { - v1 = (0 + 200); + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_SLP_RESTORE; } - if (param1->battleMons[param2].status & 0xf88) { - v1 = (0 + 201); + if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_PSN_RESTORE; } - if (param1->battleMons[param2].status & 0x10) { - v1 = (0 + 202); + if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_BRN_RESTORE; } - if (param1->battleMons[param2].status & 0x20) { - v1 = (0 + 203); + if (battleCtx->battleMons[battler].status & MON_CONDITION_FREEZE) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_FRZ_RESTORE; } - if (param1->battleMons[param2].statusVolatile & 0x7) { - v1 = (0 + 205); + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_CNF_RESTORE; } - if ((param1->battleMons[param2].status & 0xff) && (param1->battleMons[param2].statusVolatile & 0x7)) { - v1 = (0 + 206); + if ((battleCtx->battleMons[battler].status & MON_CONDITION_ANY) + && (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION)) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_MULTI_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 14: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 0; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 0) == -1) { - v1 = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SPICY: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SPICY; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SPICY) == -1) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - v1 = (0 + 198); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 15: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 1; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 1) == -1) { - v1 = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_DRY: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_DRY; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_DRY) == -1) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - v1 = (0 + 198); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 16: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 2; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 2) == -1) { - v1 = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SWEET: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SWEET; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SWEET) == -1) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - v1 = (0 + 198); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 17: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 3; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 3) == -1) { - v1 = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_BITTER: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_BITTER; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_BITTER) == -1) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - v1 = (0 + 198); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 18: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 4; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 4) == -1) { - v1 = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SOUR: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SOUR; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SOUR) == -1) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - v1 = (0 + 198); + subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } - break; - case 36: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + break;case HOLD_EFFECT_PINCH_ATK_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x1] < 12)) { - param1->msgTemp = 0x1; - v1 = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK] < 12) { + battleCtx->msgTemp = BATTLE_STAT_ATTACK; + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 37: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_DEF_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x2] < 12)) { - param1->msgTemp = 0x2; - v1 = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_DEFENSE; + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 38: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPEED_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x3] < 12)) { - param1->msgTemp = 0x3; - v1 = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SPEED] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SPEED; + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 39: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPATK_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x4] < 12)) { - param1->msgTemp = 0x4; - v1 = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SP_ATTACK] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_ATTACK; + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 40: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPDEF_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x5] < 12)) { - param1->msgTemp = 0x5; - v1 = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SP_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_DEFENSE; + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 41: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_CRITRATE_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && ((param1->battleMons[param2].statusVolatile & 0x100000) == 0)) { - v1 = (0 + 209); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_FOCUS_ENERGY) == FALSE) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_CRIT; + result = TRUE; } break; - case 42: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; - } - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) { - { - int v5; + case HOLD_EFFECT_PINCH_RANDOM_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; + } - for (v5 = 0; v5 < 5; v5++) { - if (param1->battleMons[param2].statBoosts[0x1 + v5] < 12) { - break; - } + if (battleCtx->battleMons[battler].curHP <= (battleCtx->battleMons[battler].maxHP / itemPower)) { + int i; + for (i = 0; i < 5; i++) { + if (battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK + i] < 12) { + break; } + } - if (v5 != 5) { - do { - v5 = BattleSystem_RandNext(param0) % 5; - } while (param1->battleMons[param2].statBoosts[0x1 + v5] == 12); - - param1->msgTemp = 0x1 + v5; + if (i != 5) { + do { + i = BattleSystem_RandNext(battleSys) % 5; + } while (battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK + i] == 12); - v1 = (0 + 210); - v0 = 1; - } + battleCtx->msgTemp = BATTLE_STAT_ATTACK + i; + subscript = BATTLE_SUBSEQ_HELD_ITEM_SHARPLY_RAISE_STAT; + result = TRUE; } } break; - case 49: - { - int v6; - for (v6 = 0; v6 < 0x8; v6++) { - if (param1->battleMons[param2].statBoosts[v6] < 6) { - param1->battleMons[param2].statBoosts[v6] = 6; - v0 = 1; + case HOLD_EFFECT_STATDOWN_RESTORE: { + for (int i = BATTLE_STAT_HP; i < BATTLE_STAT_MAX; i++) { + if (battleCtx->battleMons[battler].statBoosts[i] < 6) { + battleCtx->battleMons[battler].statBoosts[i] = 6; + result = TRUE; } } - if (v0 == 1) { - v1 = (0 + 211); + if (result == TRUE) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_STATDOWN_RESTORE; } + break; } - break; - case 54: - if (param1->battleMons[param2].statusVolatile & 0xf0000) { - param1->msgTemp = 6; - v1 = (0 + 212); - v0 = 1; + + case HOLD_EFFECT_HEAL_INFATUATION: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_ATTRACT) { + battleCtx->msgTemp = MSGCOND_INFATUATION; + subscript = BATTLE_SUBSEQ_HELD_ITEM_HEAL_INFATUATION; + result = TRUE; } break; - case 44: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_ACC_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) { - v1 = (0 + 265); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower) { + subscript = BATTLE_SUBSEQ_HELD_ITEM_TEMP_ACC_UP; + result = TRUE; } break; - default: - break; } - if (v0 == 1) { - param1->msgBattlerTemp = param2; - param1->msgItemTemp = Battler_HeldItem(param1, param2); - BattleSystem_LoadScript(param1, 1, v1); - param1->commandNext = param1->command; - param1->command = 21; + if (result == TRUE) { + battleCtx->msgBattlerTemp = battler; + battleCtx->msgItemTemp = Battler_HeldItem(battleCtx, battler); + + LOAD_SUBSEQ(subscript); + battleCtx->commandNext = battleCtx->command; + battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; } } - return v0; + return result; } -BOOL BattleSystem_TriggerLeftovers (BattleSystem * param0, BattleContext * param1, int param2) +BOOL BattleSystem_TriggerLeftovers(BattleSystem *battleSys, BattleContext *battleCtx, int battler) { - BOOL v0; - int v1; - int v2; - int v3; + BOOL result = 0; + int subscript; + int itemEffect = Battler_HeldItemEffect(battleCtx, battler); + int itemPower = Battler_HeldItemPower(battleCtx, battler, ITEM_POWER_CHECK_ALL); - v0 = 0; - v2 = Battler_HeldItemEffect(param1, param2); - v3 = Battler_HeldItemPower(param1, param2, 0); - - if (param1->battleMons[param2].curHP) { - switch (v2) { - case 69: - if (param1->battleMons[param2].curHP < (param1->battleMons[param2].maxHP)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, 16); - v1 = (0 + 213); - v0 = 1; + if (battleCtx->battleMons[battler].curHP) { + switch (itemEffect) { + case HOLD_EFFECT_HP_RESTORE_GRADUAL: + if (battleCtx->battleMons[battler].curHP < (battleCtx->battleMons[battler].maxHP)) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, 16); + subscript = BATTLE_SUBSEQ_RESTORE_A_LITTLE_HP; + result = TRUE; } break; - case 109: - if ((BattleMon_Get(param1, param2, 27, NULL) == 3) || (BattleMon_Get(param1, param2, 28, NULL) == 3)) { - if (param1->battleMons[param2].curHP < (param1->battleMons[param2].maxHP)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, 16); - v1 = (0 + 213); - v0 = 1; + + case HOLD_EFFECT_HP_RESTORE_PSN_TYPE: + if (MON_HAS_TYPE(battler, TYPE_POISON)) { + if (battleCtx->battleMons[battler].curHP < (battleCtx->battleMons[battler].maxHP)) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, 16); + subscript = BATTLE_SUBSEQ_RESTORE_A_LITTLE_HP; + result = TRUE; } - } else if (Battler_Ability(param1, param2) != 98) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP * -1, 8); - v1 = (0 + 215); - v0 = 1; + } else if (Battler_Ability(battleCtx, battler) != ABILITY_MAGIC_GUARD) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP * -1, 8); + subscript = BATTLE_SUBSEQ_LOSE_HP_FROM_ITEM_WITH_MESSAGE; + result = TRUE; } break; - default: - break; } - if (v0 == 1) { - param1->msgBattlerTemp = param2; - param1->msgItemTemp = Battler_HeldItem(param1, param2); - BattleSystem_LoadScript(param1, 1, v1); - param1->commandNext = param1->command; - param1->command = 21; + if (result == TRUE) { + battleCtx->msgBattlerTemp = battler; + battleCtx->msgItemTemp = Battler_HeldItem(battleCtx, battler); + + LOAD_SUBSEQ(subscript); + battleCtx->commandNext = battleCtx->command; + battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; } } - return v0; + return result; } -BOOL BattleSystem_TriggerHeldItemOnStatus (BattleSystem * param0, BattleContext * param1, int param2, int * param3) +BOOL BattleSystem_TriggerHeldItemOnStatus(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int *subscript) { - BOOL v0; - u16 v1; - int v2; - int v3; - - v0 = 0; - v2 = Battler_HeldItemEffect(param1, param2); - v3 = Battler_HeldItemPower(param1, param2, 0); - - if (param1->battleMons[param2].curHP) { - switch (v2) { - case 1: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = v3; - param3[0] = (0 + 198); - v0 = 1; + BOOL result = FALSE; + int itemEffect = Battler_HeldItemEffect(battleCtx, battler); + int itemPower = Battler_HeldItemPower(battleCtx, battler, ITEM_POWER_CHECK_ALL); + + if (battleCtx->battleMons[battler].curHP) { + switch (itemEffect) { + case HOLD_EFFECT_HP_RESTORE: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = itemPower; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; + result = TRUE; } break; - case 13: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP * v3, 100); - param3[0] = (0 + 198); - v0 = 1; + + case HOLD_EFFECT_HP_PCT_RESTORE: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP * itemPower, 100); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; + result = TRUE; } break; - case 5: - if (param1->battleMons[param2].status & 0x40) { - param3[0] = (0 + 199); - v0 = 1; + + case HOLD_EFFECT_PRZ_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_PRZ_RESTORE; + result = TRUE; } break; - case 6: - if (param1->battleMons[param2].status & 0x7) { - param3[0] = (0 + 200); - v0 = 1; + + case HOLD_EFFECT_SLP_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_SLP_RESTORE; + result = TRUE; } break; - case 7: - if (param1->battleMons[param2].status & 0xf88) { - param3[0] = (0 + 201); - v0 = 1; + + case HOLD_EFFECT_PSN_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_PSN_RESTORE; + result = TRUE; } break; - case 8: - if (param1->battleMons[param2].status & 0x10) { - param3[0] = (0 + 202); - v0 = 1; + + case HOLD_EFFECT_BRN_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_BRN_RESTORE; + result = TRUE; } break; - case 9: - if (param1->battleMons[param2].status & 0x20) { - param3[0] = (0 + 203); - v0 = 1; + + case HOLD_EFFECT_FRZ_RESTORE: + if (battleCtx->battleMons[battler].status & MON_CONDITION_FREEZE) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_FRZ_RESTORE; + result = TRUE; } break; - case 10: - { - int v4; - for (v4 = 0; v4 < 4; v4++) { - if ((param1->battleMons[param2].moves[v4]) && (param1->battleMons[param2].ppCur[v4] == 0)) { + case HOLD_EFFECT_PP_RESTORE: { + int i; + for (i = 0; i < LEARNED_MOVES_MAX; i++) { + if (battleCtx->battleMons[battler].moves[i] && battleCtx->battleMons[battler].ppCur[i] == 0) { break; } } - if (v4 != 4) { - BattleMon_AddVal(¶m1->battleMons[param2], 31 + v4, v3); - BattleMon_CopyToParty(param0, param1, param2); - param1->msgMoveTemp = param1->battleMons[param2].moves[v4]; - param3[0] = (0 + 204); - v0 = 1; + if (i != LEARNED_MOVES_MAX) { + BattleMon_AddVal(&battleCtx->battleMons[battler], BATTLEMON_CUR_PP_1 + i, itemPower); + BattleMon_CopyToParty(battleSys, battleCtx, battler); + battleCtx->msgMoveTemp = battleCtx->battleMons[battler].moves[i]; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_PP_RESTORE; + result = TRUE; } + + break; } - break; - case 11: - if (param1->battleMons[param2].statusVolatile & 0x7) { - param3[0] = (0 + 205); - v0 = 1; + + case HOLD_EFFECT_CONFUSE_RESTORE: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_CNF_RESTORE; + result = TRUE; } break; - case 12: - if ((param1->battleMons[param2].status & 0xff) || (param1->battleMons[param2].statusVolatile & 0x7)) { - if (param1->battleMons[param2].status & 0x40) { - param3[0] = (0 + 199); + + case HOLD_EFFECT_STATUS_RESTORE: + if ((battleCtx->battleMons[battler].status & MON_CONDITION_ANY) + || (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION)) { + if (battleCtx->battleMons[battler].status & MON_CONDITION_PARALYSIS) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_PRZ_RESTORE; } - if (param1->battleMons[param2].status & 0x7) { - param3[0] = (0 + 200); + if (battleCtx->battleMons[battler].status & MON_CONDITION_SLEEP) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_SLP_RESTORE; } - if (param1->battleMons[param2].status & 0xf88) { - param3[0] = (0 + 201); + if (battleCtx->battleMons[battler].status & MON_CONDITION_ANY_POISON) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_PSN_RESTORE; } - if (param1->battleMons[param2].status & 0x10) { - param3[0] = (0 + 202); + if (battleCtx->battleMons[battler].status & MON_CONDITION_BURN) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_BRN_RESTORE; } - if (param1->battleMons[param2].status & 0x20) { - param3[0] = (0 + 203); + if (battleCtx->battleMons[battler].status & MON_CONDITION_FREEZE) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_FRZ_RESTORE; } - if (param1->battleMons[param2].statusVolatile & 0x7) { - param3[0] = (0 + 205); + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_CNF_RESTORE; } - if ((param1->battleMons[param2].status & 0xff) && (param1->battleMons[param2].statusVolatile & 0x7)) { - param3[0] = (0 + 206); + if ((battleCtx->battleMons[battler].status & MON_CONDITION_ANY) + && (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_CONFUSION)) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_MULTI_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 49: - { - int v5; - for (v5 = 0; v5 < 0x8; v5++) { - if (param1->battleMons[param2].statBoosts[v5] < 6) { - param1->battleMons[param2].statBoosts[v5] = 6; - v0 = 1; + case HOLD_EFFECT_STATDOWN_RESTORE: { + for (int i = BATTLE_STAT_HP; i < BATTLE_STAT_MAX; i++) { + if (battleCtx->battleMons[battler].statBoosts[i] < 6) { + battleCtx->battleMons[battler].statBoosts[i] = 6; + result = TRUE; } } - if (v0 == 1) { - param3[0] = (0 + 211); + if (result == TRUE) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_STATDOWN_RESTORE; } + break; } - break; - case 54: - if (param1->battleMons[param2].statusVolatile & 0xf0000) { - param1->msgTemp = 6; - param3[0] = (0 + 212); - v0 = 1; + + case HOLD_EFFECT_HEAL_INFATUATION: + if (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_ATTRACT) { + battleCtx->msgTemp = MSGCOND_INFATUATION; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HEAL_INFATUATION; + result = TRUE; } break; - case 44: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_ACC_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) { - param3[0] = (0 + 265); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_TEMP_ACC_UP; + result = TRUE; } break; - case 14: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 0; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 0) == -1) { - param3[0] = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SPICY: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SPICY; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SPICY) == -1) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - param3[0] = (0 + 198); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 15: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 1; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 1) == -1) { - param3[0] = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_DRY: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_DRY; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_DRY) == -1) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - param3[0] = (0 + 198); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 16: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 2; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 2) == -1) { - param3[0] = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SWEET: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SWEET; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SWEET) == -1) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - param3[0] = (0 + 198); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 17: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 3; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 3) == -1) { - param3[0] = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_BITTER: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_BITTER; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_BITTER) == -1) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - param3[0] = (0 + 198); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 18: - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / 2)) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP, v3); - param1->msgTemp = 4; - if (Pokemon_GetFlavorAffinityOf(param1->battleMons[param2].personality, 4) == -1) { - param3[0] = (0 + 207); + case HOLD_EFFECT_HP_RESTORE_SOUR: + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / 2) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP, itemPower); + battleCtx->msgTemp = FLAVOR_SOUR; + + if (Pokemon_GetFlavorAffinityOf(battleCtx->battleMons[battler].personality, FLAVOR_SOUR) == -1) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_DISLIKE_FLAVOR; } else { - param3[0] = (0 + 198); + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; } - v0 = 1; + result = TRUE; } break; - case 36: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_ATK_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x1] < 12)) { - param1->msgTemp = 0x1; - param3[0] = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK] < 12) { + battleCtx->msgTemp = BATTLE_STAT_ATTACK; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 37: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_DEF_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x2] < 12)) { - param1->msgTemp = 0x2; - param3[0] = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_DEFENSE; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 38: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPEED_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x3] < 12)) { - param1->msgTemp = 0x3; - param3[0] = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SPEED] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SPEED; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 39: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPATK_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x4] < 12)) { - param1->msgTemp = 0x4; - param3[0] = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SP_ATTACK] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_ATTACK; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 40: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_SPDEF_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && (param1->battleMons[param2].statBoosts[0x5] < 12)) { - param1->msgTemp = 0x5; - param3[0] = (0 + 208); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_SP_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_DEFENSE; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; + result = TRUE; } break; - case 41: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; + + case HOLD_EFFECT_PINCH_CRITRATE_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; } - if ((param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) && ((param1->battleMons[param2].statusVolatile & 0x100000) == 0)) { - param3[0] = (0 + 209); - v0 = 1; + if (battleCtx->battleMons[battler].curHP <= battleCtx->battleMons[battler].maxHP / itemPower + && (battleCtx->battleMons[battler].statusVolatile & VOLATILE_CONDITION_FOCUS_ENERGY) == FALSE) { + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_CRIT; + result = TRUE; } break; - case 42: - if (Battler_Ability(param1, param2) == 82) { - v3 /= 2; - } - if (param1->battleMons[param2].curHP <= (param1->battleMons[param2].maxHP / v3)) { - { - int v6; + case HOLD_EFFECT_PINCH_RANDOM_UP: + if (Battler_Ability(battleCtx, battler) == ABILITY_GLUTTONY) { + itemPower /= 2; + } - for (v6 = 0; v6 < 5; v6++) { - if (param1->battleMons[param2].statBoosts[0x1 + v6] < 12) { - break; - } + if (battleCtx->battleMons[battler].curHP <= (battleCtx->battleMons[battler].maxHP / itemPower)) { + int i; + for (i = 0; i < 5; i++) { + if (battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK + i] < 12) { + break; } + } - if (v6 != 5) { - do { - v6 = BattleSystem_RandNext(param0) % 5; - } while (param1->battleMons[param2].statBoosts[0x1 + v6] == 12); + if (i != 5) { + do { + i = BattleSystem_RandNext(battleSys) % 5; + } while (battleCtx->battleMons[battler].statBoosts[BATTLE_STAT_ATTACK + i] == 12); - param1->msgTemp = 0x1 + v6; - param3[0] = (0 + 210); - v0 = 1; - } + battleCtx->msgTemp = BATTLE_STAT_ATTACK + i; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_SHARPLY_RAISE_STAT; + result = TRUE; } } break; - default: - break; } - if (v0 == 1) { - param1->msgItemTemp = Battler_HeldItem(param1, param2); + if (result == TRUE) { + battleCtx->msgItemTemp = Battler_HeldItem(battleCtx, battler); } } - return v0; + return result; } -BOOL BattleSystem_TriggerDetrimentalHeldItem (BattleSystem * param0, BattleContext * param1, int param2) +BOOL BattleSystem_TriggerDetrimentalHeldItem(BattleSystem *battleSys, BattleContext *battleCtx, int battler) { - BOOL v0; - int v1; - u16 v2; - int v3; - int v4; - - v0 = 0; - v3 = Battler_HeldItemEffect(param1, param2); - v4 = Battler_HeldItemPower(param1, param2, 0); - - if (param1->battleMons[param2].curHP) { - switch (v3) { - case 100: - param1->sideEffectMon = param2; - param1->sideEffectType = 5; - v1 = (0 + 47); - v0 = 1; + BOOL result = FALSE; + int subscript; + int itemEffect = Battler_HeldItemEffect(battleCtx, battler); + int itemPower = Battler_HeldItemPower(battleCtx, battler, 0); + + if (battleCtx->battleMons[battler].curHP) { + switch (itemEffect) { + case HOLD_EFFECT_PSN_USER: + battleCtx->sideEffectMon = battler; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_HELD_ITEM; + subscript = BATTLE_SUBSEQ_BADLY_POISON; + result = TRUE; break; - case 101: - param1->sideEffectMon = param2; - param1->sideEffectType = 5; - v1 = (0 + 25); - v0 = 1; + + case HOLD_EFFECT_BRN_USER: + battleCtx->sideEffectMon = battler; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_HELD_ITEM; + subscript = BATTLE_SUBSEQ_BURN; + result = TRUE; break; - case 116: - if (Battler_Ability(param1, param2) != 98) { - param1->hpCalcTemp = BattleSystem_Divide(param1->battleMons[param2].maxHP * -1, v4); - v1 = (0 + 215); - v0 = 1; + + case HOLD_EFFECT_DMG_USER_CONTACT_XFR: + if (Battler_Ability(battleCtx, battler) != ABILITY_MAGIC_GUARD) { + battleCtx->hpCalcTemp = BattleSystem_Divide(battleCtx->battleMons[battler].maxHP * -1, itemPower); + subscript = BATTLE_SUBSEQ_LOSE_HP_FROM_ITEM_WITH_MESSAGE; + result = TRUE; } break; - default: - break; } - if (v0 == 1) { - param1->msgBattlerTemp = param2; - param1->msgItemTemp = Battler_HeldItem(param1, param2); - BattleSystem_LoadScript(param1, 1, v1); - param1->commandNext = param1->command; - param1->command = 21; + if (result == TRUE) { + battleCtx->msgBattlerTemp = battler; + battleCtx->msgItemTemp = Battler_HeldItem(battleCtx, battler); + + LOAD_SUBSEQ(subscript); + battleCtx->commandNext = battleCtx->command; + battleCtx->command = BATTLE_CONTROL_EXEC_SCRIPT; } } - return v0; + return result; } u16 Battler_HeldItem(BattleContext *battleCtx, int battler) @@ -5352,12 +5332,12 @@ u16 Battler_HeldItem(BattleContext *battleCtx, int battler) return battleCtx->battleMons[battler].heldItem; } -BOOL Battler_MovedThisTurn (BattleContext * param0, int param1) +BOOL Battler_MovedThisTurn(BattleContext *battleCtx, int battler) { - return param0->battlerActions[param1][0] == 39; + return battleCtx->battlerActions[battler][BATTLE_ACTION_PICK_COMMAND] == BATTLE_CONTROL_MOVE_END; } -BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext * battleCtx, int * nextSeq) +BOOL BattleSystem_TriggerHeldItemOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript) { BOOL result = FALSE; @@ -5382,7 +5362,7 @@ BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext && (DEFENDER_SELF_TURN_FLAGS.physicalDamageTaken || DEFENDER_SELF_TURN_FLAGS.specialDamageTaken) && (battleCtx->battleStatusMask2 & SYSCTL_UTURN_ACTIVE) == FALSE && (CURRENT_MOVE_DATA.flags & MOVE_FLAG_MAKES_CONTACT)) { - *nextSeq = BATTLE_SUBSEQ_TRANSFER_STICKY_BARB; + *subscript = BATTLE_SUBSEQ_TRANSFER_STICKY_BARB; result = TRUE; } break; @@ -5393,7 +5373,7 @@ BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext && (battleCtx->battleStatusMask2 & SYSCTL_UTURN_ACTIVE) == FALSE && DEFENDER_SELF_TURN_FLAGS.physicalDamageTaken) { battleCtx->hpCalcTemp = BattleSystem_Divide(ATTACKING_MON.maxHP * -1, itemPower); - *nextSeq = BATTLE_SUBSEQ_HELD_ITEM_RECOIL_WHEN_HIT; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RECOIL_WHEN_HIT; result = TRUE; } break; @@ -5403,7 +5383,7 @@ BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext && Battler_Ability(battleCtx, battleCtx->attacker) != ABILITY_MAGIC_GUARD && DEFENDER_SELF_TURN_FLAGS.specialDamageTaken) { battleCtx->hpCalcTemp = BattleSystem_Divide(ATTACKING_MON.maxHP * -1, itemPower); - *nextSeq = BATTLE_SUBSEQ_HELD_ITEM_RECOIL_WHEN_HIT; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_RECOIL_WHEN_HIT; result = TRUE; } break; @@ -5411,7 +5391,7 @@ BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext case HOLD_EFFECT_HP_RESTORE_SE: if (DEFENDING_MON.curHP && (battleCtx->moveStatusFlags & MOVE_STATUS_SUPER_EFFECTIVE)) { battleCtx->hpCalcTemp = BattleSystem_Divide(DEFENDING_MON.maxHP, itemPower); - *nextSeq = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; + *subscript = BATTLE_SUBSEQ_HELD_ITEM_HP_RESTORE; battleCtx->msgBattlerTemp = battleCtx->defender; battleCtx->msgItemTemp = battleCtx->battleMons[battleCtx->defender].heldItem; result = TRUE; @@ -5425,12 +5405,10 @@ BOOL BattleSystem_TriggerHeldItemOnHit (BattleSystem * battleSys, BattleContext return result; } -s32 Battler_HeldItemEffect (BattleContext * param0, int param1) +s32 Battler_HeldItemEffect(BattleContext *battleCtx, int battler) { - u16 v0; - - v0 = Battler_HeldItem(param0, param1); - return BattleSystem_GetItemData(param0, v0, 1); + u16 item = Battler_HeldItem(battleCtx, battler); + return BattleSystem_GetItemData(battleCtx, item, ITEM_PARAM_HOLD_EFFECT); } s32 Battler_HeldItemPower(BattleContext *battleCtx, int battler, enum HeldItemPowerOp opcode) @@ -5765,8 +5743,8 @@ BOOL BattleSystem_PluckBerry(BattleSystem *battleSys, BattleContext *battleCtx, break; case PLUCK_EFFECT_SPDEF_UP: - if (ATTACKING_MON.statBoosts[BATTEL_STAT_SP_DEFENSE] < 12) { - battleCtx->msgTemp = BATTEL_STAT_SP_DEFENSE; + if (ATTACKING_MON.statBoosts[BATTLE_STAT_SP_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_DEFENSE; nextSeq = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; } @@ -5836,7 +5814,7 @@ BOOL BattleSystem_FlingItem(BattleSystem *battleSys, BattleContext *battleCtx, i battleCtx->movePower = Battler_ItemFlingPower(battleCtx, battler); battleCtx->flingScript = 0; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_NONE; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_NONE; if (battleCtx->movePower == 0) { return FALSE; @@ -6022,31 +6000,31 @@ BOOL BattleSystem_FlingItem(BattleSystem *battleSys, BattleContext *battleCtx, i case FLING_EFFECT_FLINCH: battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_INDIRECT; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; battleCtx->flingScript = BATTLE_SUBSEQ_FLINCH_MON; break; case FLING_EFFECT_PARALYZE: battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_INDIRECT; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; battleCtx->flingScript = BATTLE_SUBSEQ_PARALYZE; break; case FLING_EFFECT_POISON: battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_INDIRECT; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; battleCtx->flingScript = BATTLE_SUBSEQ_POISON; break; case FLING_EFFECT_BADLY_POISON: battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_INDIRECT; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; battleCtx->flingScript = BATTLE_SUBSEQ_BADLY_POISON; break; case FLING_EFFECT_BURN: battleCtx->sideEffectMon = battler; - battleCtx->sideEffectType = SIDE_EFFECT_SOURCE_INDIRECT; + battleCtx->sideEffectType = SIDE_EFFECT_TYPE_INDIRECT; battleCtx->flingScript = BATTLE_SUBSEQ_BURN; break; @@ -6079,8 +6057,8 @@ BOOL BattleSystem_FlingItem(BattleSystem *battleSys, BattleContext *battleCtx, i break; case FLING_EFFECT_SPDEF_UP: - if (DEFENDING_MON.statBoosts[BATTEL_STAT_SP_DEFENSE] < 12) { - battleCtx->msgTemp = BATTEL_STAT_SP_DEFENSE; + if (DEFENDING_MON.statBoosts[BATTLE_STAT_SP_DEFENSE] < 12) { + battleCtx->msgTemp = BATTLE_STAT_SP_DEFENSE; battleCtx->flingScript = BATTLE_SUBSEQ_HELD_ITEM_RAISE_STAT; } break; @@ -6125,7 +6103,7 @@ BOOL BattleSystem_FlingItem(BattleSystem *battleSys, BattleContext *battleCtx, i } else { battleCtx->msgItemTemp = battleCtx->battleMons[battler].heldItem; - if (battleCtx->sideEffectType == SIDE_EFFECT_SOURCE_NONE && battleCtx->flingScript) { + if (battleCtx->sideEffectType == SIDE_EFFECT_TYPE_NONE && battleCtx->flingScript) { ATTACKER_SELF_TURN_FLAGS.statusFlags |= SELF_TURN_FLAG_PLUCK_BERRY; } @@ -6286,151 +6264,164 @@ BOOL BattleSystem_PokemonIsOT (BattleSystem * param0, Pokemon * param1) return 0; } -BOOL BattleSystem_UpdateWeatherForms (BattleSystem * param0, BattleContext * param1, int * param2) +BOOL BattleSystem_TriggerFormChange(BattleSystem *battleSys, BattleContext *battleCtx, int *subscript) { - int v0; - int v1; - BOOL v2 = 0; + int i; + int arceusForm; + BOOL result = FALSE; - for (v0 = 0; v0 < BattleSystem_MaxBattlers(param0); v0++) { - param1->msgBattlerTemp = param1->monSpeedOrder[v0]; - - if ((param1->battleMons[param1->msgBattlerTemp].species == 351) && (param1->battleMons[param1->msgBattlerTemp].curHP) && (Battler_Ability(param1, param1->msgBattlerTemp) == 59)) { - if ((BattleSystem_CountAbility(param0, param1, 8, 0, 13) == 0) && (BattleSystem_CountAbility(param0, param1, 8, 0, 76) == 0)) { - if (((param1->fieldConditionsMask & (0x3 | 0x30 | 0xc0)) == 0) && (param1->battleMons[param1->msgBattlerTemp].type1 != 0) && (param1->battleMons[param1->msgBattlerTemp].type2 != 0)) { - param1->battleMons[param1->msgBattlerTemp].type1 = 0; - param1->battleMons[param1->msgBattlerTemp].type2 = 0; - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; + for (i = 0; i < BattleSystem_MaxBattlers(battleSys); i++) { + battleCtx->msgBattlerTemp = battleCtx->monSpeedOrder[i]; + + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].species == SPECIES_CASTFORM + && battleCtx->battleMons[battleCtx->msgBattlerTemp].curHP + && Battler_Ability(battleCtx, battleCtx->msgBattlerTemp) == ABILITY_FORECAST) { + if (NO_CLOUD_NINE) { + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_CASTFORM) == FALSE + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 != TYPE_NORMAL + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 != TYPE_NORMAL) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 = TYPE_NORMAL; + battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 = TYPE_NORMAL; + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } else if ((param1->fieldConditionsMask & 0x30) && (param1->battleMons[param1->msgBattlerTemp].type1 != 10) && (param1->battleMons[param1->msgBattlerTemp].type2 != 10)) { - param1->battleMons[param1->msgBattlerTemp].type1 = 10; - param1->battleMons[param1->msgBattlerTemp].type2 = 10; - param1->battleMons[param1->msgBattlerTemp].formNum = 1; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_SUN + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 != TYPE_FIRE + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 != TYPE_FIRE) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 = TYPE_FIRE; + battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 = TYPE_FIRE; + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 1; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } else if ((param1->fieldConditionsMask & 0x3) && (param1->battleMons[param1->msgBattlerTemp].type1 != 11) && (param1->battleMons[param1->msgBattlerTemp].type2 != 11)) { - param1->battleMons[param1->msgBattlerTemp].type1 = 11; - param1->battleMons[param1->msgBattlerTemp].type2 = 11; - param1->battleMons[param1->msgBattlerTemp].formNum = 2; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_RAIN + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 != TYPE_WATER + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 != TYPE_WATER) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 = TYPE_WATER; + battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 = TYPE_WATER; + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 2; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } else if ((param1->fieldConditionsMask & 0xc0) && (param1->battleMons[param1->msgBattlerTemp].type1 != 15) && (param1->battleMons[param1->msgBattlerTemp].type2 != 15)) { - param1->battleMons[param1->msgBattlerTemp].type1 = 15; - param1->battleMons[param1->msgBattlerTemp].type2 = 15; - param1->battleMons[param1->msgBattlerTemp].formNum = 3; - *param2 = (0 + 262); - v2 = 1; - break; - } - } else { - if ((param1->battleMons[param1->msgBattlerTemp].type1 != 0) && (param1->battleMons[param1->msgBattlerTemp].type2 != 0)) { - param1->battleMons[param1->msgBattlerTemp].type1 = 0; - param1->battleMons[param1->msgBattlerTemp].type2 = 0; - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_HAIL + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 != TYPE_ICE + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 != TYPE_ICE) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 = TYPE_ICE; + battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 = TYPE_ICE; + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 3; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; } + } else if (battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 != TYPE_NORMAL + && battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 != TYPE_NORMAL) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].type1 = TYPE_NORMAL; + battleCtx->battleMons[battleCtx->msgBattlerTemp].type2 = TYPE_NORMAL; + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; + break; } } - if ((param1->battleMons[param1->msgBattlerTemp].species == 421) && (param1->battleMons[param1->msgBattlerTemp].curHP)) { - if ((BattleSystem_CountAbility(param0, param1, 8, 0, 13) == 0) && (BattleSystem_CountAbility(param0, param1, 8, 0, 76) == 0)) { - if (((param1->fieldConditionsMask & (0x3 | 0x30 | 0xc0)) == 0) && (param1->battleMons[param1->msgBattlerTemp].formNum == 1)) { - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; - break; - } else if ((param1->fieldConditionsMask & 0x30) && (param1->battleMons[param1->msgBattlerTemp].formNum == 0)) { - param1->battleMons[param1->msgBattlerTemp].formNum = 1; - *param2 = (0 + 262); - v2 = 1; + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].species == SPECIES_CHERRIM + && battleCtx->battleMons[battleCtx->msgBattlerTemp].curHP) { + if (NO_CLOUD_NINE) { + if ((battleCtx->fieldConditionsMask & FIELD_CONDITION_CASTFORM) == FALSE + && battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 1) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } else if ((param1->fieldConditionsMask & 0x3) && (param1->battleMons[param1->msgBattlerTemp].formNum == 1)) { - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_SUN && battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 0) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 1; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } else if ((param1->fieldConditionsMask & 0xc0) && (param1->battleMons[param1->msgBattlerTemp].formNum == 1)) { - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_RAIN && battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 1) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; - } - } else { - if (param1->battleMons[param1->msgBattlerTemp].formNum == 1) { - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - *param2 = (0 + 262); - v2 = 1; + } else if (WEATHER_IS_HAIL && battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 1) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; } + } else if (battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 1) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; + break; } } - if ((param1->battleMons[param1->msgBattlerTemp].species == 493) && (param1->battleMons[param1->msgBattlerTemp].curHP) && (Battler_Ability(param1, param1->msgBattlerTemp) == 121)) { - v1 = Pokemon_GetArceusTypeOf(Item_LoadParam(param1->battleMons[param1->msgBattlerTemp].heldItem, 1, 5)); + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].species == SPECIES_ARCEUS + && battleCtx->battleMons[battleCtx->msgBattlerTemp].curHP + && Battler_Ability(battleCtx, battleCtx->msgBattlerTemp) == ABILITY_MULTITYPE) { + arceusForm = Pokemon_GetArceusTypeOf(Item_LoadParam(battleCtx->battleMons[battleCtx->msgBattlerTemp].heldItem, ITEM_PARAM_HOLD_EFFECT, HEAP_ID_BATTLE)); - if (param1->battleMons[param1->msgBattlerTemp].formNum != v1) { - param1->battleMons[param1->msgBattlerTemp].formNum = v1; - *param2 = (0 + 262); - v2 = 1; + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum != arceusForm) { + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = arceusForm; + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; break; } } - if ((param1->battleMons[param1->msgBattlerTemp].species == 487) && (param1->battleMons[param1->msgBattlerTemp].curHP) && (param1->battleMons[param1->msgBattlerTemp].formNum == 1)) { - if ((param1->battleMons[param1->msgBattlerTemp].statusVolatile & 0x200000) || (((BattleSystem_BattleStatus(param0) & 0x80) == 0) && (param1->battleMons[param1->msgBattlerTemp].heldItem != 112))) { - if (param1->battleMons[param1->msgBattlerTemp].statusVolatile & 0x200000) { - Pokemon * v3; - int v4; - int v5; + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].species == SPECIES_GIRATINA + && battleCtx->battleMons[battleCtx->msgBattlerTemp].curHP + && battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum == 1 + && ((battleCtx->battleMons[battleCtx->msgBattlerTemp].statusVolatile & VOLATILE_CONDITION_TRANSFORM) + || ((BattleSystem_BattleStatus(battleSys) & BATTLE_STATUS_DISTORTION) == FALSE + && battleCtx->battleMons[battleCtx->msgBattlerTemp].heldItem != ITEM_GRISEOUS_ORB))) { + if (battleCtx->battleMons[battleCtx->msgBattlerTemp].statusVolatile & VOLATILE_CONDITION_TRANSFORM) { + Pokemon *mon = Pokemon_New(HEAP_ID_BATTLE); - v3 = Pokemon_New(5); - - if (BattleSystem_BattleType(param0) & 0x2) { - v4 = param1->battlerActions[param1->msgBattlerTemp][1]; - } else { - v4 = param1->msgBattlerTemp ^ 1; - } - - Pokemon_Copy(BattleSystem_PartyPokemon(param0, v4, param1->selectedPartySlot[v4]), v3); - v5 = 0; - - Pokemon_SetValue(v3, 6, &v5); - v5 = 0; - - Pokemon_SetValue(v3, 112, &v5); - Pokemon_SetGiratinaForm(v3); - - param1->battleMons[param1->msgBattlerTemp].attack = Pokemon_GetValue(v3, MON_DATA_ATK, 0); - param1->battleMons[param1->msgBattlerTemp].defense = Pokemon_GetValue(v3, MON_DATA_DEF, 0); - param1->battleMons[param1->msgBattlerTemp].speed = Pokemon_GetValue(v3, MON_DATA_SPEED, 0); - param1->battleMons[param1->msgBattlerTemp].spAttack = Pokemon_GetValue(v3, MON_DATA_SP_ATK, 0); - param1->battleMons[param1->msgBattlerTemp].spDefense = Pokemon_GetValue(v3, MON_DATA_SP_DEF, 0); - param1->battleMons[param1->msgBattlerTemp].ability = Pokemon_GetValue(v3, MON_DATA_ABILITY, 0); - param1->battleMons[param1->msgBattlerTemp].formNum = 0; - param1->battleStatusMask2 |= 0x4000000; - - BattleIO_UpdatePartyMon(param0, param1, param1->msgBattlerTemp); - Heap_FreeToHeap(v3); - - *param2 = (0 + 262); - v2 = 1; - break; + int target; + if (BattleSystem_BattleType(battleSys) & BATTLE_TYPE_DOUBLES) { + target = battleCtx->battlerActions[battleCtx->msgBattlerTemp][BATTLE_ACTION_CHOOSE_TARGET]; } else { - *param2 = (0 + 296); - v2 = 1; - break; + target = battleCtx->msgBattlerTemp ^ 1; } + + Pokemon_Copy(BattleSystem_PartyPokemon(battleSys, target, battleCtx->selectedPartySlot[target]), mon); + + // Don't copy the Griseous Orb + int tmp = ITEM_NONE; + Pokemon_SetValue(mon, MON_DATA_HELD_ITEM, &tmp); + + // Force Giratina-Altered form + tmp = 0; + Pokemon_SetValue(mon, MON_DATA_FORM, &tmp); + Pokemon_SetGiratinaForm(mon); + + battleCtx->battleMons[battleCtx->msgBattlerTemp].attack = Pokemon_GetValue(mon, MON_DATA_ATK, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].defense = Pokemon_GetValue(mon, MON_DATA_DEF, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].speed = Pokemon_GetValue(mon, MON_DATA_SPEED, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].spAttack = Pokemon_GetValue(mon, MON_DATA_SP_ATK, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].spDefense = Pokemon_GetValue(mon, MON_DATA_SP_DEF, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].ability = Pokemon_GetValue(mon, MON_DATA_ABILITY, 0); + battleCtx->battleMons[battleCtx->msgBattlerTemp].formNum = 0; + battleCtx->battleStatusMask2 |= SYSCTL_FORM_CHANGE; + + BattleIO_UpdatePartyMon(battleSys, battleCtx, battleCtx->msgBattlerTemp); + Heap_FreeToHeap(mon); + + *subscript = BATTLE_SUBSEQ_FORM_CHANGE; + result = TRUE; + break; + } else { + *subscript = BATTLE_SUBSEQ_GIRATINA_FORM_CHANGE; + result = TRUE; + break; } } } - return v2; + return result; } void ov16_0225A1B0 (BattleSystem * param0, BattleContext * param1) @@ -7466,173 +7457,33 @@ void BattleContext_Set(BattleSystem *battleSys, BattleContext *battleCtx, enum B } } -static const int Unk_ov16_0226EE24[] = { - NULL, - 0x12, - 0x16, - 0x19, - 0x1B, - 0x1F, - 0x2F, - 0x25, - 0xE, - 0x37, - 0x38, - 0x30, - 0xD, - 0x3A, - 0x3F, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0x40, - 0x42, - 0x55, - 0x56, - 0x5D, - 0x77, - 0x73, - 0x82, - 0x8A, - 0x93, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0xC, - 0x2C, - 0x8E, - 0x95, - 0x96, - 0x94, - 0x97, - 0x98, - 0x18, - 0x21, - 0x22, - 0x23, - 0x2B, - 0x2D, - 0x2E, - 0x31, - 0x34, - 0x36, - 0x3E, - 0x43, - 0x44, - 0x46, - 0x49, - 0x4D, - 0x4E, - 0x4F, - 0x50, - 0x51, - 0x52, - 0x54, - 0x57, - 0x58, - 0x59, - 0x5B, - 0x5C, - 0x5F, - 0x60, - 0x61, - 0x7E, - 0x64, - 0x65, - 0x67, - 0x69, - 0x6A, - 0x6D, - 0x70, - 0x71, - 0x72, - 0x78, - 0x7A, - 0x7B, - 0x7C, - 0x7D, - 0x7F, - 0x80, - 0x81, - 0x83, - 0x84, - 0x86, - 0x87, - 0x8C, - 0x8D, - 0x8F, - 0x91, - 0x9A, - 0x9B, - 0x9C, - 0x9E, - 0x9F, - 0xA0, - 0xA1, - 0xA2, - 0xA3, - 0xA4, - 0xA5, - 0xA6, - 0xA7, - 0xA8, - 0xAA, - 0xAB, - 0xAD, - 0xAF, - 0xDA, - 0xDB, - 0xDC, - 0xE2, - 0xF6, - 0xF7, - 0xF8, - 0xF9, - 0x104, - 0x105, - 0x76 -}; +#include "data/move_side_effect_subscripts.h" -static int BattleContext_SideEffect (BattleContext * param0, int param1, u32 param2) +/** + * @brief Map the given side effect to an appropriate subscript. + * + * @param battleCtx + * @param type Type of side effect; see enum SideEffectType + * @param effect Effect which should be mapped to a corresponding subscript + * @return int + */ +static int MapSideEffectToSubscript(BattleContext *battleCtx, enum SideEffectType type, u32 effect) { - param0->sideEffectType = param1; - param0->sideEffectParam = param2 & 0x7fffff; - param0->sideEffectFlags = param2 & (0x7fffff ^ 0xffffffff); + battleCtx->sideEffectType = type; + battleCtx->sideEffectParam = effect & MOVE_SIDE_EFFECT_SUBSCRIPT_POINTER; + battleCtx->sideEffectFlags = effect & MOVE_SIDE_EFFECT_FLAGS; - if (param2 & 0x40000000) { - param0->sideEffectMon = param0->attacker; - } else if (param2 & 0x80000000) { - param0->sideEffectMon = param0->defender; - } else if ((param2 & 0x20000000) || (param2 & 0x10000000)) { - param0->sideEffectMon = 0; - } else { - (void)0; + if (effect & MOVE_SIDE_EFFECT_TO_ATTACKER) { + battleCtx->sideEffectMon = battleCtx->attacker; + } else if (effect & MOVE_SIDE_EFFECT_TO_DEFENDER) { + battleCtx->sideEffectMon = battleCtx->defender; + } else if ((effect & MOVE_SIDE_EFFECT_ON_HIT) || (effect & MOVE_SIDE_EFFECT_CHECK_HP)) { + battleCtx->sideEffectMon = 0; } - GF_ASSERT(NELEMS(Unk_ov16_0226EE24) > (param2 & 0x7fffff)); + GF_ASSERT(NELEMS(sSideEffectSubscripts) > (effect & MOVE_SIDE_EFFECT_SUBSCRIPT_POINTER)); - return Unk_ov16_0226EE24[param2 & 0x7fffff]; + return sSideEffectSubscripts[effect & MOVE_SIDE_EFFECT_SUBSCRIPT_POINTER]; } static int ov16_0225B63C (BattleContext * param0, int param1, int param2, int param3, int param4, u32 * param5) @@ -7822,45 +7673,67 @@ static void BattleAI_ClearKnownItem(BattleContext *battleCtx, u8 battler) battleCtx->aiContext.battlerHeldItems[battler] = ITEM_NONE; } -static int ov16_0225B840 (BattleSystem * param0, BattleContext * param1, int param2, int param3) -{ - int v0 = 0xff; - - if ((param1->battleMons[param2].ability != 59) && (param1->battleMons[param2].ability != 36) && (param1->battleMons[param2].ability != 121) && (param1->battleMons[param2].curHP) && (param1->battleMons[param3].curHP) && (param1->battleMons[param3].ability != 59) && (param1->battleMons[param3].ability != 36) && (param1->battleMons[param3].ability != 121)) { - if (BattleSystem_RandNext(param0) & 1) { - v0 = param3; +/** + * @brief Choose the target for Trace. + * + * @param battleSys + * @param battleCtx + * @param defender1 + * @param defender2 + * @return Either of defender1 or defender2, if at least one has a Traceable + * ability, or BATTLER_NONE, if there is no valid Trace target. + */ +static int ChooseTraceTarget(BattleSystem *battleSys, BattleContext *battleCtx, int defender1, int defender2) +{ + int trace = BATTLER_NONE; + + if (battleCtx->battleMons[defender1].ability != ABILITY_FORECAST + && battleCtx->battleMons[defender1].ability != ABILITY_TRACE + && battleCtx->battleMons[defender1].ability != ABILITY_MULTITYPE + && battleCtx->battleMons[defender1].curHP + && battleCtx->battleMons[defender2].curHP + && battleCtx->battleMons[defender2].ability != ABILITY_FORECAST + && battleCtx->battleMons[defender2].ability != ABILITY_TRACE + && battleCtx->battleMons[defender2].ability != ABILITY_MULTITYPE) { + // Both targets are eligible; choose randomly + if (BattleSystem_RandNext(battleSys) & 1) { + trace = defender2; } else { - v0 = param2; - } - } else if ((param1->battleMons[param2].ability != 59) && (param1->battleMons[param2].ability != 36) && (param1->battleMons[param2].curHP) && (param1->battleMons[param2].ability != 121)) { - v0 = param2; - } else if ((param1->battleMons[param3].ability != 59) && (param1->battleMons[param3].ability != 36) && (param1->battleMons[param3].curHP) && (param1->battleMons[param3].ability != 121)) { - v0 = param3; - } - - return v0; -} - -static const u16 Unk_ov16_0226EBBC[] = { - 0x29, - 0x57, - 0x58, - 0x59, - 0x90, - 0xE3 + trace = defender1; + } + } else if (battleCtx->battleMons[defender1].ability != ABILITY_FORECAST + && battleCtx->battleMons[defender1].ability != ABILITY_TRACE + && battleCtx->battleMons[defender1].curHP + && battleCtx->battleMons[defender1].ability != ABILITY_MULTITYPE) { + trace = defender1; + } else if (battleCtx->battleMons[defender2].ability != ABILITY_FORECAST + && battleCtx->battleMons[defender2].ability != ABILITY_TRACE + && battleCtx->battleMons[defender2].curHP + && battleCtx->battleMons[defender2].ability != ABILITY_MULTITYPE) { + trace = defender2; + } + + return trace; +} + +static const u16 sMovesCannotTriggerAnticipation[] = { + BATTLE_EFFECT_40_DAMAGE_FLAT, + BATTLE_EFFECT_LEVEL_DAMAGE_FLAT, + BATTLE_EFFECT_RANDOM_DAMAGE_1_TO_150_LEVEL, + BATTLE_EFFECT_COUNTER, + BATTLE_EFFECT_MIRROR_COAT, + BATTLE_EFFECT_METAL_BURST, }; -static BOOL ov16_0225B8E4 (BattleContext * param0, int param1) +static BOOL MoveCannotTriggerAnticipation(BattleContext *battleCtx, int move) { - int v0; - - for (v0 = 0; v0 < NELEMS(Unk_ov16_0226EBBC); v0++) { - if (Unk_ov16_0226EBBC[v0] == param0->aiContext.moveTable[param1].effect) { - return 1; + for (int i = 0; i < NELEMS(sMovesCannotTriggerAnticipation); i++) { + if (sMovesCannotTriggerAnticipation[i] == MOVE_DATA(move).effect) { + return TRUE; } } - return 0; + return FALSE; } static int BattleMove_Type (BattleSystem * param0, BattleContext * param1, int param2, int param3)