#include "global.h" #include "battle.h" #include "abilities.h" #include "moves.h" #include "hold_effects.h" #include "pokemon.h" #include "species.h" #include "item.h" #include "items.h" #include "util.h" #include "battle_move_effects.h" #include "rng.h" #include "text.h" #include "string_util.h" #include "battle_message.h" extern const u8* gBattlescriptCurrInstr; extern const u8* gUnknown_02024220[BATTLE_BANKS_COUNT]; extern const u8* gUnknown_02024230[BATTLE_BANKS_COUNT]; extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT]; extern u8 gActiveBank; extern u8 gStringBank; extern u16 gCurrentMove; extern u16 gLastUsedItem; extern u8 gNoOfAllBanks; extern u32 gStatuses3[BATTLE_BANKS_COUNT]; extern u8 gBankAttacker; extern u8 gBankTarget; extern u8 gAbsentBankFlags; extern u16 gBattleWeather; extern u8 gTurnOrder[BATTLE_BANKS_COUNT]; extern u16 gSideAffecting[]; extern u8 gBattleCommunication[]; extern void (*gBattleMainFunc)(void); extern s32 gBattleMoveDamage; extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT]; extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200]; extern u32 gBattleTypeFlags; extern u16 gLastUsedMovesByBanks[BATTLE_BANKS_COUNT]; extern u32 gHitMarker; extern u8 gEffectBank; extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; extern u8 gBank1; extern u16 gChosenMovesByBanks[]; extern u8 gBattleMoveFlags; extern s32 gTakenDmg[BATTLE_BANKS_COUNT]; extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT]; extern const struct BattleMove gBattleMoves[]; // scripts extern const u8 gUnknown_082DAE2A[]; extern const u8 gUnknown_082DAE1F[]; extern const u8 gUnknown_082DB089[]; extern const u8 gUnknown_082DB098[]; extern const u8 gUnknown_082DB0AF[]; extern const u8 gUnknown_082DB0A0[]; extern const u8 gUnknown_082DB185[]; extern const u8 gUnknown_082DB181[]; extern const u8 gUnknown_082DB812[]; extern const u8 gUnknown_082DB076[]; extern const u8 BattleScript_NoMovesLeft[]; extern const u8 gUnknown_082DACFA[]; extern const u8 gUnknown_082DAD0B[]; extern const u8 gUnknown_082DACC9[]; extern const u8 gUnknown_082DAC47[]; extern const u8 gUnknown_082DACE0[]; extern const u8 gUnknown_082DACD2[]; extern const u8 BattleScript_WishComesTrue[]; extern const u8 gUnknown_082DACC9[]; extern const u8 gUnknown_082DAC2C[]; extern const u8 BattleScript_IngrainTurnHeal[]; extern const u8 BattleScript_LeechSeedTurnDrain[]; extern const u8 BattleScript_PoisonTurnDmg[]; extern const u8 BattleScript_BurnTurnDmg[]; extern const u8 BattleScript_NightmareTurnDmg[]; extern const u8 BattleScript_CurseTurnDmg[]; extern const u8 BattleScript_WrapTurnDmg[]; extern const u8 BattleScript_WrapEnds[]; extern const u8 gUnknown_082DB234[]; extern const u8 gUnknown_082DB2A6[]; extern const u8 BattleScript_ThrashConfuses[]; extern const u8 BattleScript_DisabledNoMore[]; extern const u8 BattleScript_EncoredNoMore[]; extern const u8 BattleScript_YawnMakesAsleep[]; extern const u8 gUnknown_082DAFE4[]; extern const u8 gUnknown_082DB8F3[]; extern const u8 gUnknown_082DAF05[]; extern const u8 gUnknown_082DAF20[]; extern const u8 gUnknown_082DA7C4[]; extern const u8 gUnknown_082DA7CD[]; extern const u8 BattleScript_MoveUsedWokeUp[]; extern const u8 BattleScript_MoveUsedIsAsleep[]; extern const u8 BattleScript_MoveUsedIsFrozen[]; extern const u8 BattleScript_MoveUsedUnfroze[]; extern const u8 BattleScript_MoveUsedLoafingAround[]; extern const u8 BattleScript_MoveUsedMustRecharge[]; extern const u8 BattleScript_MoveUsedFlinched[]; extern const u8 BattleScript_MoveUsedIsDisabled[]; extern const u8 BattleScript_MoveUsedIsTaunted[]; extern const u8 BattleScript_MoveUsedIsImprisoned[]; extern const u8 BattleScript_MoveUsedIsConfused[]; extern const u8 BattleScript_MoveUsedIsConfusedNoMore[]; extern const u8 BattleScript_MoveUsedIsParalyzed[]; extern const u8 BattleScript_MoveUsedIsParalyzedCantAttack[]; extern const u8 BattleScript_MoveUsedIsInLove[]; extern const u8 BattleScript_BideStoringEnergy[]; extern const u8 BattleScript_BideAttack[]; extern const u8 BattleScript_BideNoEnergyToAttack[]; extern void CancelMultiTurnMoves(u8 bank); extern u8 b_first_side(u8, u8, u8); extern void sub_803CEDC(u8, u8); extern void b_call_bc_move_exec(const u8 *); extern void BattleTurnPassed(void); extern void EmitSetAttributes(u8 a, u8 request, u8 c, u8 bytes, void *data); extern void SetMoveEffect(bool8 primary, u8 certainArg); extern bool8 UproarWakeUpCheck(u8 bank); extern void MarkBufferBankForExecution(u8 bank); extern u8 sub_803F90C(u8 bank); extern u8 GetBankIdentity(u8); extern void sub_803F9EC(); extern bool8 sub_80423F4(u8 bank, u8, u8); extern s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideFlags, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef); u8 IsImprisoned(u8 bank, u16 move); u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn); u8 GetMoveTarget(u16 move, u8 useMoveTarget); void b_movescr_stack_push(const u8* bsPtr) { BATTLESCRIPTS_STACK->ptr[BATTLESCRIPTS_STACK->size++] = bsPtr; } void b_movescr_stack_push_cursor(void) { BATTLESCRIPTS_STACK->ptr[BATTLESCRIPTS_STACK->size++] = gBattlescriptCurrInstr; } void b_movescr_stack_pop_cursor(void) { gBattlescriptCurrInstr = BATTLESCRIPTS_STACK->ptr[--BATTLESCRIPTS_STACK->size]; } u8 sub_803FB4C(void) // msg, can't select a move { u8 limitations = 0; u16 move = gBattleMons[gActiveBank].moves[gBattleBufferB[gActiveBank][2]]; u8 holdEffect; u16* choicedMove = &gBattleStruct->choicedMove[gActiveBank]; if (gDisableStructs[gActiveBank].disabledMove == move && move != 0) { gBattleScripting.bank = gActiveBank; gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gUnknown_02024230[gActiveBank] = gUnknown_082DAE2A; gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DAE1F; limitations = 1; } } if (move == gLastUsedMovesByBanks[gActiveBank] && move != MOVE_STRUGGLE && (gBattleMons[gActiveBank].status2 & STATUS2_TORMENT)) { CancelMultiTurnMoves(gActiveBank); if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gUnknown_02024230[gActiveBank] = gUnknown_082DB098; gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DB089; limitations++; } } if (gDisableStructs[gActiveBank].tauntTimer1 != 0 && gBattleMoves[move].power == 0) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gUnknown_02024230[gActiveBank] = gUnknown_082DB0AF; gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DB0A0; limitations++; } } if (IsImprisoned(gActiveBank, move)) { gCurrentMove = move; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gUnknown_02024230[gActiveBank] = gUnknown_082DB185; gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DB181; limitations++; } } if (gBattleMons[gActiveBank].item == ITEM_ENIGMA_BERRY) holdEffect = gEnigmaBerries[gActiveBank].holdEffect; else holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBank].item); gStringBank = gActiveBank; if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != move) { gCurrentMove = *choicedMove; gLastUsedItem = gBattleMons[gActiveBank].item; if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DB812; limitations++; } } if (gBattleMons[gActiveBank].pp[gBattleBufferB[gActiveBank][2]] == 0) { if (gBattleTypeFlags & BATTLE_TYPE_PALACE) { gProtectStructs[gActiveBank].flag_x10 = 1; } else { gUnknown_02024220[gActiveBank] = gUnknown_082DB076; limitations++; } } return limitations; } #define MOVE_LIMITATION_ZEROMOVE (1 << 0) #define MOVE_LIMITATION_PP (1 << 1) #define MOVE_LIMITATION_DISABLED (1 << 2) #define MOVE_LIMITATION_TORMENTED (1 << 3) #define MOVE_LIMITATION_TAUNT (1 << 4) #define MOVE_LIMITATION_IMPRISION (1 << 5) u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check) { u8 holdEffect; u16* choicedMove = &gBattleStruct->choicedMove[bank]; s32 i; if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY) holdEffect = gEnigmaBerries[bank].holdEffect; else holdEffect = ItemId_GetHoldEffect(gBattleMons[bank].item); gStringBank = bank; for (i = 0; i < BATTLE_BANKS_COUNT; i++) { if (gBattleMons[bank].moves[i] == 0 && check & MOVE_LIMITATION_ZEROMOVE) unusableMoves |= gBitTable[i]; if (gBattleMons[bank].pp[i] == 0 && check & MOVE_LIMITATION_PP) unusableMoves |= gBitTable[i]; if (gBattleMons[bank].moves[i] == gDisableStructs[bank].disabledMove && check & MOVE_LIMITATION_DISABLED) unusableMoves |= gBitTable[i]; if (gBattleMons[bank].moves[i] == gLastUsedMovesByBanks[bank] && check & MOVE_LIMITATION_TORMENTED && gBattleMons[bank].status2 & STATUS2_TORMENT) unusableMoves |= gBitTable[i]; if (gDisableStructs[bank].tauntTimer1 && check & MOVE_LIMITATION_TAUNT && gBattleMoves[gBattleMons[bank].moves[i]].power == 0) unusableMoves |= gBitTable[i]; if (IsImprisoned(bank, gBattleMons[bank].moves[i]) && check & MOVE_LIMITATION_IMPRISION) unusableMoves |= gBitTable[i]; if (gDisableStructs[bank].encoreTimer1 && gDisableStructs[bank].encoredMove != gBattleMons[bank].moves[i]) unusableMoves |= gBitTable[i]; if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[bank].moves[i]) unusableMoves |= gBitTable[i]; } return unusableMoves; } bool8 AreAllMovesUnusable(void) { u8 unusable; unusable = CheckMoveLimitations(gActiveBank, 0, 0xFF); if (unusable == 0xF) // all moves are unusable { gProtectStructs[gActiveBank].onlyStruggle = 1; gUnknown_02024220[gActiveBank] = BattleScript_NoMovesLeft; } else { gProtectStructs[gActiveBank].onlyStruggle = 0; } return (unusable == 0xF); } u8 IsImprisoned(u8 bank, u16 move) { s32 i; u8 imprisionedMoves = 0; u8 bankSide = GetBankSide(bank); for (i = 0; i < gNoOfAllBanks; i++) { if (bankSide != GetBankSide(i) && gStatuses3[i] & STATUS3_IMPRISIONED) { s32 j; for (j = 0; j < 4; j++) { if (move == gBattleMons[i].moves[j]) break; } if (j < 4) imprisionedMoves++; } } return imprisionedMoves; } u8 UpdateTurnCounters(void) { u8 effect = 0; s32 i; for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankAttacker]; gBankAttacker++) { } for (gBankTarget = 0; gBankTarget < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankTarget]; gBankTarget++) { } do { u8 sideBank; switch (gBattleStruct->turncountersTracker) { case 0: for (i = 0; i < gNoOfAllBanks; i++) { gTurnOrder[i] = i; } for (i = 0; i < gNoOfAllBanks - 1; i++) { s32 j; for (j = i + 1; j < gNoOfAllBanks; j++) { if (b_first_side(gTurnOrder[i], gTurnOrder[j], 0)) sub_803CEDC(i, j); } } // It's stupid, but won't match without it { u8* var = &gBattleStruct->turncountersTracker; (*var)++; gBattleStruct->turnSideTracker = 0; } // fall through case 1: while (gBattleStruct->turnSideTracker < 2) { sideBank = gBattleStruct->turnSideTracker; gActiveBank = gBankAttacker = gSideTimers[sideBank].reflectBank; if (gSideAffecting[sideBank] & SIDE_STATUS_REFLECT) { if (--gSideTimers[sideBank].reflectTimer == 0) { gSideAffecting[sideBank] &= ~SIDE_STATUS_REFLECT; b_call_bc_move_exec(gUnknown_082DACFA); gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = MOVE_REFLECT; gBattleTextBuff1[3] = MOVE_REFLECT >> 8; gBattleTextBuff1[4] = EOS; effect++; } } gBattleStruct->turnSideTracker++; if (effect) break; } if (!effect) { gBattleStruct->turncountersTracker++; gBattleStruct->turnSideTracker = 0; } break; case 2: while (gBattleStruct->turnSideTracker < 2) { sideBank = gBattleStruct->turnSideTracker; gActiveBank = gBankAttacker = gSideTimers[sideBank].lightscreenBank; if (gSideAffecting[sideBank] & SIDE_STATUS_LIGHTSCREEN) { if (--gSideTimers[sideBank].lightscreenTimer == 0) { gSideAffecting[sideBank] &= ~SIDE_STATUS_LIGHTSCREEN; b_call_bc_move_exec(gUnknown_082DACFA); gBattleCommunication[MULTISTRING_CHOOSER] = sideBank; gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = MOVE_LIGHT_SCREEN; gBattleTextBuff1[3] = MOVE_LIGHT_SCREEN >> 8; gBattleTextBuff1[4] = EOS; effect++; } } gBattleStruct->turnSideTracker++; if (effect) break; } if (!effect) { gBattleStruct->turncountersTracker++; gBattleStruct->turnSideTracker = 0; } break; case 3: while (gBattleStruct->turnSideTracker < 2) { sideBank = gBattleStruct->turnSideTracker; gActiveBank = gBankAttacker = gSideTimers[sideBank].mistBank; if (gSideTimers[sideBank].mistTimer != 0 && --gSideTimers[sideBank].mistTimer == 0) { gSideAffecting[sideBank] &= ~SIDE_STATUS_MIST; b_call_bc_move_exec(gUnknown_082DACFA); gBattleCommunication[MULTISTRING_CHOOSER] = sideBank; gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = MOVE_MIST; gBattleTextBuff1[3] = MOVE_MIST >> 8; gBattleTextBuff1[4] = EOS; effect++; } gBattleStruct->turnSideTracker++; if (effect) break; } if (!effect) { gBattleStruct->turncountersTracker++; gBattleStruct->turnSideTracker = 0; } break; case 4: while (gBattleStruct->turnSideTracker < 2) { sideBank = gBattleStruct->turnSideTracker; gActiveBank = gBankAttacker = gSideTimers[sideBank].safeguardBank; if (gSideAffecting[sideBank] & SIDE_STATUS_SAFEGUARD) { if (--gSideTimers[sideBank].safeguardTimer == 0) { gSideAffecting[sideBank] &= ~SIDE_STATUS_SAFEGUARD; b_call_bc_move_exec(gUnknown_082DAD0B); effect++; } } gBattleStruct->turnSideTracker++; if (effect) break; } if (!effect) { gBattleStruct->turncountersTracker++; gBattleStruct->turnSideTracker = 0; } break; case 5: while (gBattleStruct->turnSideTracker < gNoOfAllBanks) { gActiveBank = gTurnOrder[gBattleStruct->turnSideTracker]; if (gWishFutureKnock.wishCounter[gActiveBank] != 0 && --gWishFutureKnock.wishCounter[gActiveBank] == 0 && gBattleMons[gActiveBank].hp != 0) { gBankTarget = gActiveBank; b_call_bc_move_exec(BattleScript_WishComesTrue); effect++; } gBattleStruct->turnSideTracker++; if (effect) break; } if (!effect) { gBattleStruct->turncountersTracker++; } break; case 6: if (gBattleWeather & WEATHER_RAIN_ANY) { if (!(gBattleWeather & WEATHER_RAIN_PERMANENT)) { if (--gWishFutureKnock.weatherDuration == 0) { gBattleWeather &= ~WEATHER_RAIN_TEMPORARY; gBattleWeather &= ~WEATHER_RAIN_DOWNPOUR; gBattleCommunication[MULTISTRING_CHOOSER] = 2; } else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR) gBattleCommunication[MULTISTRING_CHOOSER] = 1; else gBattleCommunication[MULTISTRING_CHOOSER] = 0; } else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR) gBattleCommunication[MULTISTRING_CHOOSER] = 1; else gBattleCommunication[MULTISTRING_CHOOSER] = 0; b_call_bc_move_exec(gUnknown_082DAC2C); effect++; } gBattleStruct->turncountersTracker++; break; case 7: if (gBattleWeather & WEATHER_SANDSTORM_ANY) { if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) { gBattleWeather &= ~WEATHER_SANDSTORM_TEMPORARY; gBattlescriptCurrInstr = gUnknown_082DACC9; } else gBattlescriptCurrInstr = gUnknown_082DAC47; gBattleScripting.animArg1 = 0xC; gBattleCommunication[MULTISTRING_CHOOSER] = 0; b_call_bc_move_exec(gBattlescriptCurrInstr); effect++; } gBattleStruct->turncountersTracker++; break; case 8: if (gBattleWeather & WEATHER_SUN_ANY) { if (!(gBattleWeather & WEATHER_SUN_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) { gBattleWeather &= ~WEATHER_SUN_TEMPORARY; gBattlescriptCurrInstr = gUnknown_082DACE0; } else gBattlescriptCurrInstr = gUnknown_082DACD2; b_call_bc_move_exec(gBattlescriptCurrInstr); effect++; } gBattleStruct->turncountersTracker++; break; case 9: if (gBattleWeather & WEATHER_HAIL) { if (--gWishFutureKnock.weatherDuration == 0) { gBattleWeather &= ~WEATHER_HAIL; gBattlescriptCurrInstr = gUnknown_082DACC9; } else gBattlescriptCurrInstr = gUnknown_082DAC47; gBattleScripting.animArg1 = 0xD; gBattleCommunication[MULTISTRING_CHOOSER] = 1; b_call_bc_move_exec(gBattlescriptCurrInstr); effect++; } gBattleStruct->turncountersTracker++; break; case 10: effect++; break; } } while (effect == 0); return (gBattleMainFunc != BattleTurnPassed); } #define TURNBASED_MAX_CASE 19 u8 TurnBasedEffects(void) { u8 effect = 0; gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); while (gBattleStruct->turnEffectsBank < gNoOfAllBanks && gBattleStruct->turnEffectsTracker <= TURNBASED_MAX_CASE) { gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->turnEffectsBank]; if (gAbsentBankFlags & gBitTable[gActiveBank]) { gBattleStruct->turnEffectsBank++; } else { switch (gBattleStruct->turnEffectsTracker) { case 0: // ingrain if ((gStatuses3[gActiveBank] & STATUS3_ROOTED) && gBattleMons[gActiveBank].hp != gBattleMons[gActiveBank].maxHP && gBattleMons[gActiveBank].hp != 0) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; gBattleMoveDamage *= -1; b_call_bc_move_exec(BattleScript_IngrainTurnHeal); effect++; } gBattleStruct->turnEffectsTracker++; break; case 1: // end turn abilities if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, gActiveBank, 0, 0, 0)) effect++; gBattleStruct->turnEffectsTracker++; break; case 2: // item effects if (ItemBattleEffects(1, gActiveBank, 0)) effect++; gBattleStruct->turnEffectsTracker++; break; case 18: // item effects again if (ItemBattleEffects(1, gActiveBank, 1)) effect++; gBattleStruct->turnEffectsTracker++; break; case 3: // leech seed if ((gStatuses3[gActiveBank] & STATUS3_LEECHSEED) && gBattleMons[gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK].hp != 0 && gBattleMons[gActiveBank].hp != 0) { gBankTarget = gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK; //funny how the 'target' is actually the bank that receives HP gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; gBattleScripting.animArg1 = gBankTarget; gBattleScripting.animArg2 = gBankAttacker; b_call_bc_move_exec(BattleScript_LeechSeedTurnDrain); effect++; } gBattleStruct->turnEffectsTracker++; break; case 4: // poison if ((gBattleMons[gActiveBank].status1 & STATUS_POISON) && gBattleMons[gActiveBank].hp != 0) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; b_call_bc_move_exec(BattleScript_PoisonTurnDmg); effect++; } gBattleStruct->turnEffectsTracker++; break; case 5: // toxic poison if ((gBattleMons[gActiveBank].status1 & STATUS_TOXIC_POISON) && gBattleMons[gActiveBank].hp != 0) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; if ((gBattleMons[gActiveBank].status1 & 0xF00) != 0xF00) //not 16 turns gBattleMons[gActiveBank].status1 += 0x100; gBattleMoveDamage *= (gBattleMons[gActiveBank].status1 & 0xF00) >> 8; b_call_bc_move_exec(BattleScript_PoisonTurnDmg); effect++; } gBattleStruct->turnEffectsTracker++; break; case 6: // burn if ((gBattleMons[gActiveBank].status1 & STATUS_BURN) && gBattleMons[gActiveBank].hp != 0) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; b_call_bc_move_exec(BattleScript_BurnTurnDmg); effect++; } gBattleStruct->turnEffectsTracker++; break; case 7: // spooky nightmares if ((gBattleMons[gActiveBank].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBank].hp != 0) { // R/S does not perform this sleep check, which causes the nighmare effect to // persist even after the affected Pokemon has been awakened by Shed Skin if (gBattleMons[gActiveBank].status1 & STATUS_SLEEP) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; b_call_bc_move_exec(BattleScript_NightmareTurnDmg); effect++; } else { gBattleMons[gActiveBank].status2 &= ~STATUS2_NIGHTMARE; } } gBattleStruct->turnEffectsTracker++; break; case 8: // curse if ((gBattleMons[gActiveBank].status2 & STATUS2_CURSED) && gBattleMons[gActiveBank].hp != 0) { gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; b_call_bc_move_exec(BattleScript_CurseTurnDmg); effect++; } gBattleStruct->turnEffectsTracker++; break; case 9: // wrap if ((gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBank].hp != 0) { gBattleMons[gActiveBank].status2 -= 0x2000; if (gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) // damaged by wrap { // This is the only way I could get this array access to match. gBattleScripting.animArg1 = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0); gBattleScripting.animArg2 = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1); gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0); gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1); gBattleTextBuff1[4] = EOS; gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; } else // broke free { gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0); gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1); gBattleTextBuff1[4] = EOS; gBattlescriptCurrInstr = BattleScript_WrapEnds; } b_call_bc_move_exec(gBattlescriptCurrInstr); effect++; } gBattleStruct->turnEffectsTracker++; break; case 10: // uproar if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR) { for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks; gBankAttacker++) { if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) && gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF) { gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); gBattleCommunication[MULTISTRING_CHOOSER] = 1; b_call_bc_move_exec(gUnknown_082DB234); gActiveBank = gBankAttacker; EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); MarkBufferBankForExecution(gActiveBank); break; } } if (gBankAttacker != gNoOfAllBanks) { effect = 2; // a pokemon was awaken break; } else { gBankAttacker = gActiveBank; gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down if (sub_803F90C(gActiveBank)) { CancelMultiTurnMoves(gActiveBank); gBattleCommunication[MULTISTRING_CHOOSER] = 1; } else if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR) { gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattleMons[gActiveBank].status2 |= STATUS2_MULTIPLETURNS; } else { gBattleCommunication[MULTISTRING_CHOOSER] = 1; CancelMultiTurnMoves(gActiveBank); } b_call_bc_move_exec(gUnknown_082DB2A6); effect = 1; } } if (effect != 2) gBattleStruct->turnEffectsTracker++; break; case 11: // thrash if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) { gBattleMons[gActiveBank].status2 -= 0x400; if (sub_803F90C(gActiveBank)) CancelMultiTurnMoves(gActiveBank); else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE) && (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS)) { gBattleMons[gActiveBank].status2 &= ~(STATUS2_MULTIPLETURNS); if (!(gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION)) { gBattleCommunication[MOVE_EFFECT_BYTE] = 0x47; SetMoveEffect(1, 0); if (gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION) b_call_bc_move_exec(BattleScript_ThrashConfuses); effect++; } } } gBattleStruct->turnEffectsTracker++; break; case 12: // disable if (gDisableStructs[gActiveBank].disableTimer1 != 0) { int i; for (i = 0; i < 4; i++) { if (gDisableStructs[gActiveBank].disabledMove == gBattleMons[gActiveBank].moves[i]) break; } if (i == 4) // pokemon does not have the disabled move anymore { gDisableStructs[gActiveBank].disabledMove = 0; gDisableStructs[gActiveBank].disableTimer1 = 0; } else if (--gDisableStructs[gActiveBank].disableTimer1 == 0) // disable ends { gDisableStructs[gActiveBank].disabledMove = 0; b_call_bc_move_exec(BattleScript_DisabledNoMore); effect++; } } gBattleStruct->turnEffectsTracker++; break; case 13: // encore if (gDisableStructs[gActiveBank].encoreTimer1 != 0) { if (gBattleMons[gActiveBank].moves[gDisableStructs[gActiveBank].encoredMovePos] != gDisableStructs[gActiveBank].encoredMove) // pokemon does not have the encored move anymore { gDisableStructs[gActiveBank].encoredMove = 0; gDisableStructs[gActiveBank].encoreTimer1 = 0; } else if (--gDisableStructs[gActiveBank].encoreTimer1 == 0 || gBattleMons[gActiveBank].pp[gDisableStructs[gActiveBank].encoredMovePos] == 0) { gDisableStructs[gActiveBank].encoredMove = 0; gDisableStructs[gActiveBank].encoreTimer1 = 0; b_call_bc_move_exec(BattleScript_EncoredNoMore); effect++; } } gBattleStruct->turnEffectsTracker++; break; case 14: // lock-on decrement if (gStatuses3[gActiveBank] & STATUS3_ALWAYS_HITS) gStatuses3[gActiveBank] -= 0x8; gBattleStruct->turnEffectsTracker++; break; case 15: // charge if (gDisableStructs[gActiveBank].chargeTimer1 && --gDisableStructs[gActiveBank].chargeTimer1 == 0) gStatuses3[gActiveBank] &= ~STATUS3_CHARGED_UP; gBattleStruct->turnEffectsTracker++; break; case 16: // taunt if (gDisableStructs[gActiveBank].tauntTimer1) gDisableStructs[gActiveBank].tauntTimer1--; gBattleStruct->turnEffectsTracker++; break; case 17: // yawn if (gStatuses3[gActiveBank] & STATUS3_YAWN) { gStatuses3[gActiveBank] -= 0x800; if (!(gStatuses3[gActiveBank] & STATUS3_YAWN) && !(gBattleMons[gActiveBank].status1 & STATUS_ANY) && gBattleMons[gActiveBank].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gActiveBank].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBank)) { CancelMultiTurnMoves(gActiveBank); gBattleMons[gActiveBank].status1 |= (Random() & 3) + 2; EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); MarkBufferBankForExecution(gActiveBank); gEffectBank = gActiveBank; b_call_bc_move_exec(BattleScript_YawnMakesAsleep); effect++; } } gBattleStruct->turnEffectsTracker++; break; case 19: // done gBattleStruct->turnEffectsTracker = 0; gBattleStruct->turnEffectsBank++; break; } if (effect != 0) return effect; } } gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); return 0; } bool8 sub_8041364(void) { gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); switch (gBattleStruct->unk1A0) { case 0: while (gBattleStruct->unk1A1 < gNoOfAllBanks) { gActiveBank = gBattleStruct->unk1A1; if (gAbsentBankFlags & gBitTable[gActiveBank]) { gBattleStruct->unk1A1++; continue; } gBattleStruct->unk1A1++; if (gWishFutureKnock.futureSightCounter[gActiveBank] != 0 && --gWishFutureKnock.futureSightCounter[gActiveBank] == 0 && gBattleMons[gActiveBank].hp != 0) { if (gWishFutureKnock.futureSightMove[gActiveBank] == MOVE_FUTURE_SIGHT) gBattleCommunication[MULTISTRING_CHOOSER] = 0; else gBattleCommunication[MULTISTRING_CHOOSER] = 1; gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 2; gBattleTextBuff1[2] = gWishFutureKnock.futureSightMove[gActiveBank]; gBattleTextBuff1[3] = gWishFutureKnock.futureSightMove[gActiveBank] >> 8; gBattleTextBuff1[4] = EOS; gBankTarget = gActiveBank; gBankAttacker = gWishFutureKnock.futureSightAttacker[gActiveBank]; gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gActiveBank]; gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF; b_call_bc_move_exec(gUnknown_082DAFE4); if (gWishFutureKnock.futureSightCounter[gActiveBank] == 0 && gWishFutureKnock.futureSightCounter[gActiveBank ^ 2] == 0) { gSideAffecting[GetBankIdentity(gBankTarget) & 1] &= ~SIDE_STATUS_FUTUREATTACK; } return 1; } } // Why do I have to keep doing this to match? { u8* var = &gBattleStruct->unk1A0; *var = 1; gBattleStruct->unk1A1 = 0; } // fall through case 1: while (gBattleStruct->unk1A1 < gNoOfAllBanks) { gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->unk1A1]; if (gAbsentBankFlags & gBitTable[gActiveBank]) { gBattleStruct->unk1A1++; continue; } gBattleStruct->unk1A1++; if (gStatuses3[gActiveBank] & STATUS3_PERISH_SONG) { gBattleTextBuff1[0] = 0xFD; gBattleTextBuff1[1] = 1; gBattleTextBuff1[2] = 1; gBattleTextBuff1[3] = 1; gBattleTextBuff1[4] = gDisableStructs[gActiveBank].perishSong1; gBattleTextBuff1[5] = EOS; if (gDisableStructs[gActiveBank].perishSong1 == 0) { gStatuses3[gActiveBank] &= ~STATUS3_PERISH_SONG; gBattleMoveDamage = gBattleMons[gActiveBank].hp; gBattlescriptCurrInstr = gUnknown_082DAF05; } else { gDisableStructs[gActiveBank].perishSong1--; gBattlescriptCurrInstr = gUnknown_082DAF20; } b_call_bc_move_exec(gBattlescriptCurrInstr); return 1; } } // Hm... { u8* var = &gBattleStruct->unk1A0; *var = 2; gBattleStruct->unk1A1 = 0; } // fall through case 2: if ((gBattleTypeFlags & BATTLE_TYPE_ARENA) && gBattleStruct->unkDA == 2 && gBattleMons[0].hp != 0 && gBattleMons[1].hp != 0) { s32 i; for (i = 0; i < 2; i++) CancelMultiTurnMoves(i); gBattlescriptCurrInstr = gUnknown_082DB8F3; b_call_bc_move_exec(gUnknown_082DB8F3); gBattleStruct->unk1A0++; return 1; } break; } gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); return 0; } #define sub_8041728_MAX_CASE 7 bool8 sub_8041728(void) { if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) return FALSE; do { int i; switch (gBattleStruct->field_4D) { case 0: gBattleStruct->field_4E = 0; gBattleStruct->field_4D++; for (i = 0; i < gNoOfAllBanks; i++) { if (gAbsentBankFlags & gBitTable[i] && !sub_80423F4(i, 6, 6)) gAbsentBankFlags &= ~(gBitTable[i]); } // fall through case 1: do { gBank1 = gBankTarget = gBattleStruct->field_4E; if (gBattleMons[gBattleStruct->field_4E].hp == 0 && !(gBattleStruct->unkDF & gBitTable[gBattlePartyID[gBattleStruct->field_4E]]) && !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E])) { b_call_bc_move_exec(gUnknown_082DA7C4); gBattleStruct->field_4D = 2; return TRUE; } } while (++gBattleStruct->field_4E != gNoOfAllBanks); gBattleStruct->field_4D = 3; break; case 2: sub_803F9EC(gBank1); if (++gBattleStruct->field_4E == gNoOfAllBanks) gBattleStruct->field_4D = 3; else gBattleStruct->field_4D = 1; break; case 3: gBattleStruct->field_4E = 0; gBattleStruct->field_4D++; // fall through case 4: do { gBank1 = gBankTarget = gBattleStruct->field_4E; //or should banks be switched? if (gBattleMons[gBattleStruct->field_4E].hp == 0 && !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E])) { b_call_bc_move_exec(gUnknown_082DA7CD); gBattleStruct->field_4D = 5; return TRUE; } } while (++gBattleStruct->field_4E != gNoOfAllBanks); gBattleStruct->field_4D = 6; break; case 5: if (++gBattleStruct->field_4E == gNoOfAllBanks) gBattleStruct->field_4D = 6; else gBattleStruct->field_4D = 4; break; case 6: if (AbilityBattleEffects(9, 0, 0, 0, 0) || AbilityBattleEffects(0xB, 0, 0, 0, 0) || ItemBattleEffects(1, 0, 1) || AbilityBattleEffects(6, 0, 0, 0, 0)) return TRUE; gBattleStruct->field_4D++; break; case 7: break; } } while (gBattleStruct->field_4D != sub_8041728_MAX_CASE); return FALSE; } void b_clear_atk_up_if_hit_flag_unless_enraged(void) { int i; for (i = 0; i < gNoOfAllBanks; i++) { if ((gBattleMons[i].status2 & STATUS2_RAGE) && gChosenMovesByBanks[i] != MOVE_RAGE) gBattleMons[i].status2 &= ~(STATUS2_RAGE); } } #define ATKCANCELLER_MAX_CASE 14 u8 AtkCanceller_UnableToUseMove(void) { u8 effect = 0; s32* bideDmg = &gBattleScripting.bideDmg; do { switch (gBattleStruct->atkCancellerTracker) { case 0: // flags clear gBattleMons[gBankAttacker].status2 &= ~(STATUS2_DESTINY_BOND); gStatuses3[gBankAttacker] &= ~(STATUS3_GRUDGE); gBattleStruct->atkCancellerTracker++; break; case 1: // check being asleep if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) { if (UproarWakeUpCheck(gBankAttacker)) { gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); b_movescr_stack_push_cursor(); gBattleCommunication[MULTISTRING_CHOOSER] = 1; gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; effect = 2; } else { u8 toSub; if (gBattleMons[gBankAttacker].ability == ABILITY_EARLY_BIRD) toSub = 2; else toSub = 1; if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) < toSub) gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP); else gBattleMons[gBankAttacker].status1 -= toSub; if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) { if (gCurrentMove != MOVE_SNORE && gCurrentMove != MOVE_SLEEP_TALK) { gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 2; } } else { gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE); b_movescr_stack_push_cursor(); gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp; effect = 2; } } } gBattleStruct->atkCancellerTracker++; break; case 2: // check being frozen if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE) { if (Random() % 5) { if (gBattleMoves[gCurrentMove].effect != EFFECT_THAW_HIT) // unfreezing via a move effect happens in case 13 { gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen; gHitMarker |= HITMARKER_NO_ATTACKSTRING; } else { gBattleStruct->atkCancellerTracker++; break; } } else // unfreeze { gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE); b_movescr_stack_push_cursor(); gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; gBattleCommunication[MULTISTRING_CHOOSER] = 0; } effect = 2; } gBattleStruct->atkCancellerTracker++; break; case 3: // truant if (gBattleMons[gBankAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBankAttacker].truantCounter) { CancelMultiTurnMoves(gBankAttacker); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround; gBattleMoveFlags |= MOVESTATUS_MISSED; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 4: // recharge if (gBattleMons[gBankAttacker].status2 & STATUS2_RECHARGE) { gBattleMons[gBankAttacker].status2 &= ~(STATUS2_RECHARGE); gDisableStructs[gBankAttacker].rechargeCounter = 0; CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 5: // flinch if (gBattleMons[gBankAttacker].status2 & STATUS2_FLINCHED) { gBattleMons[gBankAttacker].status2 &= ~(STATUS2_FLINCHED); gProtectStructs[gBankAttacker].flinchImmobility = 1; CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 6: // disabled move if (gDisableStructs[gBankAttacker].disabledMove == gCurrentMove && gDisableStructs[gBankAttacker].disabledMove != 0) { gProtectStructs[gBankAttacker].usedDisabledMove = 1; gBattleScripting.bank = gBankAttacker; CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 7: // taunt if (gDisableStructs[gBankAttacker].tauntTimer1 && gBattleMoves[gCurrentMove].power == 0) { gProtectStructs[gBankAttacker].usedTauntedMove = 1; CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 8: // imprisoned if (IsImprisoned(gBankAttacker, gCurrentMove)) { gProtectStructs[gBankAttacker].usedImprisionedMove = 1; CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 9: // confusion if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION) { gBattleMons[gBankAttacker].status2--; if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION) { if (Random() & 1) { gBattleCommunication[MULTISTRING_CHOOSER] = 0; b_movescr_stack_push_cursor(); } else // confusion dmg { gBattleCommunication[MULTISTRING_CHOOSER] = 1; gBankTarget = gBankAttacker; gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankAttacker], MOVE_POUND, 0, 40, 0, gBankAttacker, gBankAttacker); gProtectStructs[gBankAttacker].confusionSelfDmg = 1; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; } gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused; } else // snapped out of confusion { b_movescr_stack_push_cursor(); gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore; } effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 10: // paralysis if ((gBattleMons[gBankAttacker].status1 & STATUS_PARALYSIS) && (Random() % 4) == 0) { gProtectStructs[gBankAttacker].prlzImmobility = 1; // This is removed in Emerald for some reason //CancelMultiTurnMoves(gBankAttacker); gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed; gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 11: // infatuation if (gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) { gBattleScripting.bank = CountTrailingZeroBits((gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) >> 0x10); if (Random() & 1) b_movescr_stack_push_cursor(); else { b_movescr_stack_push(BattleScript_MoveUsedIsParalyzedCantAttack); gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE; gProtectStructs[gBankAttacker].loveImmobility = 1; CancelMultiTurnMoves(gBankAttacker); } gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove; effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 12: // bide if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE) { gBattleMons[gBankAttacker].status2 -= 0x100; if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE) gBattlescriptCurrInstr = BattleScript_BideStoringEnergy; else { // This is removed in Emerald for some reason //gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS); if (gTakenDmg[gBankAttacker]) { gCurrentMove = MOVE_BIDE; *bideDmg = gTakenDmg[gBankAttacker] * 2; gBankTarget = gTakenDmgBanks[gBankAttacker]; if (gAbsentBankFlags & gBitTable[gBankTarget]) gBankTarget = GetMoveTarget(MOVE_BIDE, 1); gBattlescriptCurrInstr = BattleScript_BideAttack; } else gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack; } effect = 1; } gBattleStruct->atkCancellerTracker++; break; case 13: // move thawing if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE) { if (gBattleMoves[gCurrentMove].effect == EFFECT_THAW_HIT) { gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE); b_movescr_stack_push_cursor(); gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze; gBattleCommunication[MULTISTRING_CHOOSER] = 1; } effect = 2; } gBattleStruct->atkCancellerTracker++; break; case 14: // last case break; } } while (gBattleStruct->atkCancellerTracker != ATKCANCELLER_MAX_CASE && effect == 0); if (effect == 2) { gActiveBank = gBankAttacker; EmitSetAttributes(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1); MarkBufferBankForExecution(gActiveBank); } return effect; }