diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_ai_script_commands.c | 13 | ||||
-rw-r--r-- | src/battle_util.c | 1147 | ||||
-rw-r--r-- | src/battle_util2.c | 5 | ||||
-rw-r--r-- | src/pokemon.c | 18 |
4 files changed, 1163 insertions, 20 deletions
diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 1c281e853..0d389aa7f 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -34,7 +34,6 @@ enum extern const u8 *gAIScriptPtr; extern u8 *BattleAIs[]; -extern u16 gLastUsedMove[]; static void BattleAICmd_if_random_less_than(void); static void BattleAICmd_if_random_greater_than(void); @@ -466,7 +465,7 @@ void sub_80C7164(void) { if (BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] == 0) { - BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] = gLastUsedMove[gBattlerTarget]; + BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] = gLastMoves[gBattlerTarget]; return; } } @@ -1035,9 +1034,9 @@ static void BattleAICmd_is_most_powerful_move(void) static void BattleAICmd_get_move(void) { if (gAIScriptPtr[1] == USER) - AI_THINKING_STRUCT->funcResult = gLastUsedMove[gBattlerAttacker]; + AI_THINKING_STRUCT->funcResult = gLastMoves[gBattlerAttacker]; else - AI_THINKING_STRUCT->funcResult = gLastUsedMove[gBattlerTarget]; + AI_THINKING_STRUCT->funcResult = gLastMoves[gBattlerTarget]; gAIScriptPtr += 2; } @@ -1373,7 +1372,7 @@ static void BattleAICmd_get_weather(void) AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_RAIN; if (gBattleWeather & WEATHER_SANDSTORM_ANY) AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SANDSTORM; - if (gBattleWeather & WEATHER_SUNNY_ANY) + if (gBattleWeather & WEATHER_SUN_ANY) AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SUNNY; if (gBattleWeather & WEATHER_HAIL) AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_HAIL; @@ -1931,7 +1930,7 @@ static void BattleAICmd_if_level_compare(void) static void BattleAICmd_if_taunted(void) { - if (gDisableStructs[gBattlerTarget].tauntTimer1 != 0) + if (gDisableStructs[gBattlerTarget].tauntTimer != 0) gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; @@ -1939,7 +1938,7 @@ static void BattleAICmd_if_taunted(void) static void BattleAICmd_if_not_taunted(void) { - if (gDisableStructs[gBattlerTarget].tauntTimer1 == 0) + if (gDisableStructs[gBattlerTarget].tauntTimer == 0) gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; diff --git a/src/battle_util.c b/src/battle_util.c new file mode 100644 index 000000000..8b0383929 --- /dev/null +++ b/src/battle_util.c @@ -0,0 +1,1147 @@ +#include "global.h" +#include "item.h" +#include "text.h" +#include "util.h" +#include "link.h" +#include "berry.h" +#include "random.h" +#include "pokemon.h" +#include "string_util.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_scripts.h" +#include "battle_message.h" +#include "battle_controllers.h" +#include "constants/battle.h" +#include "constants/moves.h" +#include "constants/items.h" +#include "constants/species.h" +#include "constants/abilities.h" +#include "constants/battle_anim.h" +#include "constants/hold_effects.h" +#include "constants/battle_move_effects.h" +#include "constants/battle_script_commands.h" + +const u16 sSoundMovesTable[] = +{ + MOVE_GROWL, MOVE_ROAR, MOVE_SING, MOVE_SUPERSONIC, MOVE_SCREECH, MOVE_SNORE, + MOVE_UPROAR, MOVE_METAL_SOUND, MOVE_GRASS_WHISTLE, MOVE_HYPER_VOICE, 0xFFFF +}; + +u8 GetBattlerForBattleScript(u8 caseId) +{ + u32 ret = 0; + + switch (caseId) + { + case BS_TARGET: + ret = gBattlerTarget; + break; + case BS_ATTACKER: + ret = gBattlerAttacker; + break; + case BS_EFFECT_BATTLER: + ret = gEffectBattler; + break; + case BS_BATTLER_0: + ret = 0; + break; + case BS_SCRIPTING: + ret = gBattleScripting.battler; + break; + case BS_FAINTED: + ret = gBattlerFainted; + break; + case 5: + ret = gBattlerFainted; + break; + case BS_PLAYER1: + ret = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + break; + case BS_OPPONENT1: + ret = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + break; + case 4: + case 6: + case 8: + case 9: + break; + } + return ret; +} + +void PressurePPLose(u8 target, u8 attacker, u16 move) +{ + s32 i; + + if (gBattleMons[target].ability == ABILITY_PRESSURE) + { + for (i = 0; i < MAX_MON_MOVES && gBattleMons[attacker].moves[i] != move; ++i); + if (i != MAX_MON_MOVES) + { + if (gBattleMons[attacker].pp[i]) + --gBattleMons[attacker].pp[i]; + if (!(gBattleMons[attacker].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[attacker].mimickedMoves & gBitTable[i])) + { + gActiveBattler = attacker; + BtlController_EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBattler].pp[i]); + MarkBattlerForControllerExec(gActiveBattler); + } + } + } +} + +void PressurePPLoseOnUsingImprison(u8 attacker) +{ + s32 i, j; + s32 imprisonPos = 4; + u8 atkSide = GetBattlerSide(attacker); + + for (i = 0; i < gBattlersCount; ++i) + { + if (atkSide != GetBattlerSide(i) && gBattleMons[i].ability == ABILITY_PRESSURE) + { + for (j = 0; j < MAX_MON_MOVES && gBattleMons[attacker].moves[j] != MOVE_IMPRISON; ++j); + if (j != MAX_MON_MOVES) + { + imprisonPos = j; + if (gBattleMons[attacker].pp[j]) + --gBattleMons[attacker].pp[j]; + } + } + } + if (imprisonPos != 4 + && !(gBattleMons[attacker].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[attacker].mimickedMoves & gBitTable[imprisonPos])) + { + gActiveBattler = attacker; + BtlController_EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + imprisonPos, 0, 1, &gBattleMons[gActiveBattler].pp[imprisonPos]); + MarkBattlerForControllerExec(gActiveBattler); + } +} + +void PressurePPLoseOnUsingPerishSong(u8 attacker) +{ + s32 i, j; + s32 perishSongPos = 4; + + for (i = 0; i < gBattlersCount; ++i) + { + if (gBattleMons[i].ability == ABILITY_PRESSURE && i != attacker) + { + for (j = 0; j < MAX_MON_MOVES && gBattleMons[attacker].moves[j] != MOVE_PERISH_SONG; ++j); + if (j != MAX_MON_MOVES) + { + perishSongPos = j; + if (gBattleMons[attacker].pp[j]) + --gBattleMons[attacker].pp[j]; + } + } + } + if (perishSongPos != MAX_MON_MOVES + && !(gBattleMons[attacker].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[attacker].mimickedMoves & gBitTable[perishSongPos])) + { + gActiveBattler = attacker; + BtlController_EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + perishSongPos, 0, 1, &gBattleMons[gActiveBattler].pp[perishSongPos]); + MarkBattlerForControllerExec(gActiveBattler); + } +} + +void MarkAllBattlersForControllerExec(void) +{ + s32 i; + + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + for (i = 0; i < gBattlersCount; ++i) + gBattleControllerExecFlags |= gBitTable[i] << 0x1C; + else + for (i = 0; i < gBattlersCount; ++i) + gBattleControllerExecFlags |= gBitTable[i]; +} + +void MarkBattlerForControllerExec(u8 battlerId) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + gBattleControllerExecFlags |= gBitTable[battlerId] << 0x1C; + else + gBattleControllerExecFlags |= gBitTable[battlerId]; +} + +void sub_8017298(u8 arg0) +{ + s32 i; + + for (i = 0; i < GetLinkPlayerCount(); ++i) + gBattleControllerExecFlags |= gBitTable[arg0] << (i << 2); + gBattleControllerExecFlags &= ~(0x10000000 << arg0); +} + +void CancelMultiTurnMoves(u8 battler) +{ + gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS); + gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE); + gBattleMons[battler].status2 &= ~(STATUS2_UPROAR); + gBattleMons[battler].status2 &= ~(STATUS2_BIDE); + gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE); + gDisableStructs[battler].rolloutTimer = 0; + gDisableStructs[battler].furyCutterCounter = 0; +} + +bool8 WasUnableToUseMove(u8 battler) +{ + if (gProtectStructs[battler].prlzImmobility + || gProtectStructs[battler].targetNotAffected + || gProtectStructs[battler].usedImprisonedMove + || gProtectStructs[battler].loveImmobility + || gProtectStructs[battler].usedDisabledMove + || gProtectStructs[battler].usedTauntedMove + || gProtectStructs[battler].flag2Unknown + || gProtectStructs[battler].flinchImmobility + || gProtectStructs[battler].confusionSelfDmg) + return TRUE; + else + return FALSE; +} + +void PrepareStringBattle(u16 stringId, u8 battler) +{ + gActiveBattler = battler; + BtlController_EmitPrintString(0, stringId); + MarkBattlerForControllerExec(gActiveBattler); +} + +void ResetSentPokesToOpponentValue(void) +{ + s32 i; + u32 bits = 0; + + gSentPokesToOpponent[0] = 0; + gSentPokesToOpponent[1] = 0; + for (i = 0; i < gBattlersCount; i += 2) + bits |= gBitTable[gBattlerPartyIndexes[i]]; + for (i = 1; i < gBattlersCount; i += 2) + gSentPokesToOpponent[(i & BIT_FLANK) >> 1] = bits; +} + +void sub_8017434(u8 battler) +{ + s32 i = 0; + u32 bits = 0; + + if (GetBattlerSide(battler) == B_SIDE_OPPONENT) + { + u8 flank = ((battler & BIT_FLANK) >> 1); + gSentPokesToOpponent[flank] = 0; + for (i = 0; i < gBattlersCount; i += 2) + if (!(gAbsentBattlerFlags & gBitTable[i])) + bits |= gBitTable[gBattlerPartyIndexes[i]]; + gSentPokesToOpponent[flank] = bits; + } +} + +void sub_80174B8(u8 battler) +{ + if (GetBattlerSide(battler) == B_SIDE_OPPONENT) + { + sub_8017434(battler); + } + else + { + s32 i; + + for (i = 1; i < gBattlersCount; ++i) + gSentPokesToOpponent[(i & BIT_FLANK) >> 1] |= gBitTable[gBattlerPartyIndexes[battler]]; + } +} + +void BattleScriptPush(const u8 *bsPtr) +{ + gBattleResources->battleScriptsStack->ptr[gBattleResources->battleScriptsStack->size++] = bsPtr; +} + +void BattleScriptPushCursor(void) +{ + gBattleResources->battleScriptsStack->ptr[gBattleResources->battleScriptsStack->size++] = gBattlescriptCurrInstr; +} + +void BattleScriptPop(void) +{ + gBattlescriptCurrInstr = gBattleResources->battleScriptsStack->ptr[--gBattleResources->battleScriptsStack->size]; +} + +u8 TrySetCantSelectMoveBattleScript(void) +{ + u8 holdEffect; + u8 limitations = 0; + u16 move = gBattleMons[gActiveBattler].moves[gBattleBufferB[gActiveBattler][2]]; + u16* choicedMove = &gBattleStruct->choicedMove[gActiveBattler]; + + if (gDisableStructs[gActiveBattler].disabledMove == move && move != MOVE_NONE) + { + gBattleScripting.battler = gActiveBattler; + gCurrentMove = move; + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingDisabledMove; + limitations = 1; + } + if (move == gLastMoves[gActiveBattler] && move != MOVE_STRUGGLE && (gBattleMons[gActiveBattler].status2 & STATUS2_TORMENT)) + { + CancelMultiTurnMoves(gActiveBattler); + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingTormentedMove; + ++limitations; + } + if (gDisableStructs[gActiveBattler].tauntTimer && !gBattleMoves[move].power) + { + gCurrentMove = move; + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingNotAllowedMoveTaunt; + ++limitations; + } + if (GetImprisonedMovesCount(gActiveBattler, move)) + { + gCurrentMove = move; + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingImprisonedMove; + ++limitations; + } + if (gBattleMons[gActiveBattler].item == ITEM_ENIGMA_BERRY) + holdEffect = gEnigmaBerries[gActiveBattler].holdEffect; + else + holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBattler].item); + gPotentialItemEffectBattler = gActiveBattler; + if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove && *choicedMove != 0xFFFF && *choicedMove != move) + { + gCurrentMove = *choicedMove; + gLastUsedItem = gBattleMons[gActiveBattler].item; + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingNotAllowedMoveChoiceItem; + ++limitations; + } + if (!gBattleMons[gActiveBattler].pp[gBattleBufferB[gActiveBattler][2]]) + { + gSelectionBattleScripts[gActiveBattler] = BattleScript_SelectingMoveWithNoPP; + ++limitations; + } + return limitations; +} + +u8 CheckMoveLimitations(u8 battlerId, u8 unusableMoves, u8 check) +{ + u8 holdEffect; + u16 *choicedMove = &gBattleStruct->choicedMove[battlerId]; + s32 i; + + if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY) + holdEffect = gEnigmaBerries[battlerId].holdEffect; + else + holdEffect = ItemId_GetHoldEffect(gBattleMons[battlerId].item); + gPotentialItemEffectBattler = battlerId; + + for (i = 0; i < MAX_MON_MOVES; ++i) + { + if (gBattleMons[battlerId].moves[i] == 0 && check & MOVE_LIMITATION_ZEROMOVE) + unusableMoves |= gBitTable[i]; + if (gBattleMons[battlerId].pp[i] == 0 && check & MOVE_LIMITATION_PP) + unusableMoves |= gBitTable[i]; + if (gBattleMons[battlerId].moves[i] == gDisableStructs[battlerId].disabledMove && check & MOVE_LIMITATION_DISABLED) + unusableMoves |= gBitTable[i]; + if (gBattleMons[battlerId].moves[i] == gLastMoves[battlerId] && check & MOVE_LIMITATION_TORMENTED && gBattleMons[battlerId].status2 & STATUS2_TORMENT) + unusableMoves |= gBitTable[i]; + if (gDisableStructs[battlerId].tauntTimer && check & MOVE_LIMITATION_TAUNT && gBattleMoves[gBattleMons[battlerId].moves[i]].power == 0) + unusableMoves |= gBitTable[i]; + if (GetImprisonedMovesCount(battlerId, gBattleMons[battlerId].moves[i]) && check & MOVE_LIMITATION_IMPRISON) + unusableMoves |= gBitTable[i]; + if (gDisableStructs[battlerId].encoreTimer && gDisableStructs[battlerId].encoredMove != gBattleMons[battlerId].moves[i]) + unusableMoves |= gBitTable[i]; + if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[battlerId].moves[i]) + unusableMoves |= gBitTable[i]; + } + return unusableMoves; +} + +bool8 AreAllMovesUnusable(void) +{ + u8 unusable = CheckMoveLimitations(gActiveBattler, 0, 0xFF); + + if (unusable == 0xF) // All moves are unusable. + { + gProtectStructs[gActiveBattler].noValidMoves = 1; + gSelectionBattleScripts[gActiveBattler] = BattleScript_NoMovesLeft; + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + gBattleBufferB[gActiveBattler][3] = GetBattlerAtPosition((BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler))) | (Random() & 2)); + else + gBattleBufferB[gActiveBattler][3] = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(gActiveBattler))); + } + else + { + gProtectStructs[gActiveBattler].noValidMoves = 0; + } + return (unusable == 0xF); +} + +u8 GetImprisonedMovesCount(u8 battlerId, u16 move) +{ + s32 i; + u8 imprisonedMoves = 0; + u8 battlerSide = GetBattlerSide(battlerId); + + for (i = 0; i < gBattlersCount; ++i) + { + if (battlerSide != GetBattlerSide(i) && gStatuses3[i] & STATUS3_IMPRISONED_OTHERS) + { + s32 j; + for (j = 0; j < MAX_MON_MOVES && move != gBattleMons[i].moves[j]; ++j); + if (j < MAX_MON_MOVES) + ++imprisonedMoves; + } + } + return imprisonedMoves; +} + +enum +{ + ENDTURN_ORDER, + ENDTURN_REFLECT, + ENDTURN_LIGHT_SCREEN, + ENDTURN_MIST, + ENDTURN_SAFEGUARD, + ENDTURN_WISH, + ENDTURN_RAIN, + ENDTURN_SANDSTORM, + ENDTURN_SUN, + ENDTURN_HAIL, + ENDTURN_FIELD_COUNT, +}; + +u8 DoFieldEndTurnEffects(void) +{ + u8 effect = 0; + s32 i; + + for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount && gAbsentBattlerFlags & gBitTable[gBattlerAttacker]; ++gBattlerAttacker); + for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount && gAbsentBattlerFlags & gBitTable[gBattlerTarget]; ++gBattlerTarget); + do + { + u8 side; + + switch (gBattleStruct->turnCountersTracker) + { + case ENDTURN_ORDER: + for (i = 0; i < gBattlersCount; ++i) + gBattlerByTurnOrder[i] = i; + for (i = 0; i < gBattlersCount - 1; ++i) + { + s32 j; + + for (j = i + 1; j < gBattlersCount; ++j) + if (GetWhoStrikesFirst(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], 0)) + SwapTurnOrder(i, j); + } + { + u8* var = &gBattleStruct->turnCountersTracker; + + ++*var; + gBattleStruct->turnSideTracker = 0; + } + // fall through + case ENDTURN_REFLECT: + while (gBattleStruct->turnSideTracker < 2) + { + side = gBattleStruct->turnSideTracker; + gActiveBattler = gBattlerAttacker = gSideTimers[side].reflectBattlerId; + if (gSideStatuses[side] & SIDE_STATUS_REFLECT) + { + if (--gSideTimers[side].reflectTimer == 0) + { + gSideStatuses[side] &= ~SIDE_STATUS_REFLECT; + BattleScriptExecute(BattleScript_SideStatusWoreOff); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_REFLECT); + ++effect; + } + } + ++gBattleStruct->turnSideTracker; + if (effect) + break; + } + if (!effect) + { + ++gBattleStruct->turnCountersTracker; + gBattleStruct->turnSideTracker = 0; + } + break; + case ENDTURN_LIGHT_SCREEN: + while (gBattleStruct->turnSideTracker < 2) + { + side = gBattleStruct->turnSideTracker; + gActiveBattler = gBattlerAttacker = gSideTimers[side].lightscreenBattlerId; + if (gSideStatuses[side] & SIDE_STATUS_LIGHTSCREEN) + { + if (--gSideTimers[side].lightscreenTimer == 0) + { + gSideStatuses[side] &= ~SIDE_STATUS_LIGHTSCREEN; + BattleScriptExecute(BattleScript_SideStatusWoreOff); + gBattleCommunication[MULTISTRING_CHOOSER] = side; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_LIGHT_SCREEN); + ++effect; + } + } + ++gBattleStruct->turnSideTracker; + if (effect) + break; + } + if (!effect) + { + ++gBattleStruct->turnCountersTracker; + gBattleStruct->turnSideTracker = 0; + } + break; + case ENDTURN_MIST: + while (gBattleStruct->turnSideTracker < 2) + { + side = gBattleStruct->turnSideTracker; + gActiveBattler = gBattlerAttacker = gSideTimers[side].mistBattlerId; + if (gSideTimers[side].mistTimer != 0 && --gSideTimers[side].mistTimer == 0) + { + gSideStatuses[side] &= ~SIDE_STATUS_MIST; + BattleScriptExecute(BattleScript_SideStatusWoreOff); + gBattleCommunication[MULTISTRING_CHOOSER] = side; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_MIST); + ++effect; + } + ++gBattleStruct->turnSideTracker; + if (effect) + break; + } + if (!effect) + { + ++gBattleStruct->turnCountersTracker; + gBattleStruct->turnSideTracker = 0; + } + break; + case ENDTURN_SAFEGUARD: + while (gBattleStruct->turnSideTracker < 2) + { + side = gBattleStruct->turnSideTracker; + gActiveBattler = gBattlerAttacker = gSideTimers[side].safeguardBattlerId; + if (gSideStatuses[side] & SIDE_STATUS_SAFEGUARD) + { + if (--gSideTimers[side].safeguardTimer == 0) + { + gSideStatuses[side] &= ~SIDE_STATUS_SAFEGUARD; + BattleScriptExecute(BattleScript_SafeguardEnds); + ++effect; + } + } + ++gBattleStruct->turnSideTracker; + if (effect) + break; + } + if (!effect) + { + ++gBattleStruct->turnCountersTracker; + gBattleStruct->turnSideTracker = 0; + } + break; + case ENDTURN_WISH: + while (gBattleStruct->turnSideTracker < gBattlersCount) + { + gActiveBattler = gBattlerByTurnOrder[gBattleStruct->turnSideTracker]; + if (gWishFutureKnock.wishCounter[gActiveBattler] != 0 + && --gWishFutureKnock.wishCounter[gActiveBattler] == 0 + && gBattleMons[gActiveBattler].hp != 0) + { + gBattlerTarget = gActiveBattler; + BattleScriptExecute(BattleScript_WishComesTrue); + ++effect; + } + ++gBattleStruct->turnSideTracker; + if (effect) + break; + } + if (!effect) + ++gBattleStruct->turnCountersTracker; + break; + case ENDTURN_RAIN: + 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; + } + BattleScriptExecute(BattleScript_RainContinuesOrEnds); + ++effect; + } + ++gBattleStruct->turnCountersTracker; + break; + case ENDTURN_SANDSTORM: + if (gBattleWeather & WEATHER_SANDSTORM_ANY) + { + if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_SANDSTORM_TEMPORARY; + gBattlescriptCurrInstr = BattleScript_SandStormHailEnds; + } + else + { + gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; + } + gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + BattleScriptExecute(gBattlescriptCurrInstr); + ++effect; + } + ++gBattleStruct->turnCountersTracker; + break; + case ENDTURN_SUN: + if (gBattleWeather & WEATHER_SUN_ANY) + { + if (!(gBattleWeather & WEATHER_SUN_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_SUN_TEMPORARY; + gBattlescriptCurrInstr = BattleScript_SunlightFaded; + } + else + { + gBattlescriptCurrInstr = BattleScript_SunlightContinues; + } + BattleScriptExecute(gBattlescriptCurrInstr); + ++effect; + } + ++gBattleStruct->turnCountersTracker; + break; + case ENDTURN_HAIL: + if (gBattleWeather & WEATHER_HAIL_ANY) + { + if (--gWishFutureKnock.weatherDuration == 0) + { + gBattleWeather &= ~WEATHER_HAIL; + gBattlescriptCurrInstr = BattleScript_SandStormHailEnds; + } + else + { + gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; + } + gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + BattleScriptExecute(gBattlescriptCurrInstr); + ++effect; + } + ++gBattleStruct->turnCountersTracker; + break; + case ENDTURN_FIELD_COUNT: + ++effect; + break; + } + } while (!effect); + return (gBattleMainFunc != BattleTurnPassed); +} + +enum +{ + ENDTURN_INGRAIN, + ENDTURN_ABILITIES, + ENDTURN_ITEMS1, + ENDTURN_LEECH_SEED, + ENDTURN_POISON, + ENDTURN_BAD_POISON, + ENDTURN_BURN, + ENDTURN_NIGHTMARES, + ENDTURN_CURSE, + ENDTURN_WRAP, + ENDTURN_UPROAR, + ENDTURN_THRASH, + ENDTURN_DISABLE, + ENDTURN_ENCORE, + ENDTURN_LOCK_ON, + ENDTURN_CHARGE, + ENDTURN_TAUNT, + ENDTURN_YAWN, + ENDTURN_ITEMS2, + ENDTURN_BATTLER_COUNT +}; + +u8 DoBattlerEndTurnEffects(void) +{ + u8 effect = 0; + + gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); + while (gBattleStruct->turnEffectsBattlerId < gBattlersCount && gBattleStruct->turnEffectsTracker <= ENDTURN_BATTLER_COUNT) + { + gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->turnEffectsBattlerId]; + if (gAbsentBattlerFlags & gBitTable[gActiveBattler]) + { + ++gBattleStruct->turnEffectsBattlerId; + } + else + { + switch (gBattleStruct->turnEffectsTracker) + { + case ENDTURN_INGRAIN: // ingrain + if ((gStatuses3[gActiveBattler] & STATUS3_ROOTED) + && gBattleMons[gActiveBattler].hp != gBattleMons[gActiveBattler].maxHP + && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + BattleScriptExecute(BattleScript_IngrainTurnHeal); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_ABILITIES: // end turn abilities + if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, gActiveBattler, 0, 0, 0)) + ++effect; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_ITEMS1: // item effects + if (ItemBattleEffects(1, gActiveBattler, FALSE)) + ++effect; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_ITEMS2: // item effects again + if (ItemBattleEffects(1, gActiveBattler, TRUE)) + ++effect; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_LEECH_SEED: // leech seed + if ((gStatuses3[gActiveBattler] & STATUS3_LEECHSEED) + && gBattleMons[gStatuses3[gActiveBattler] & STATUS3_LEECHSEED_BATTLER].hp != 0 + && gBattleMons[gActiveBattler].hp != 0) + { + gBattlerTarget = gStatuses3[gActiveBattler] & STATUS3_LEECHSEED_BATTLER; // Notice gBattlerTarget is actually the HP receiver. + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleScripting.animArg1 = gBattlerTarget; + gBattleScripting.animArg2 = gBattlerAttacker; + BattleScriptExecute(BattleScript_LeechSeedTurnDrain); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_POISON: // poison + if ((gBattleMons[gActiveBattler].status1 & STATUS1_POISON) && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_PoisonTurnDmg); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_BAD_POISON: // toxic poison + if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON) && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if ((gBattleMons[gActiveBattler].status1 & 0xF00) != 0xF00) // not 16 turns + gBattleMons[gActiveBattler].status1 += 0x100; + gBattleMoveDamage *= (gBattleMons[gActiveBattler].status1 & 0xF00) >> 8; + BattleScriptExecute(BattleScript_PoisonTurnDmg); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_BURN: // burn + if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN) && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_BurnTurnDmg); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_NIGHTMARES: // spooky nightmares + if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBattler].hp != 0) + { + // R/S does not perform this sleep check, which causes the nightmare effect to + // persist even after the affected Pokemon has been awakened by Shed Skin. + if (gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_NightmareTurnDmg); + ++effect; + } + else + { + gBattleMons[gActiveBattler].status2 &= ~STATUS2_NIGHTMARE; + } + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_CURSE: // curse + if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED) && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + BattleScriptExecute(BattleScript_CurseTurnDmg); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_WRAP: // wrap + if ((gBattleMons[gActiveBattler].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMons[gActiveBattler].status2 -= 0x2000; + if (gBattleMons[gActiveBattler].status2 & STATUS2_WRAPPED) // damaged by wrap + { + gBattleScripting.animArg1 = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 0); + gBattleScripting.animArg2 = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 1); + gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN; + gBattleTextBuff1[1] = B_BUFF_MOVE; + gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 0); + gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 1); + gBattleTextBuff1[4] = EOS; + gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + } + else // broke free + { + gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN; + gBattleTextBuff1[1] = B_BUFF_MOVE; + gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 0); + gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 1); + gBattleTextBuff1[4] = EOS; + gBattlescriptCurrInstr = BattleScript_WrapEnds; + } + BattleScriptExecute(gBattlescriptCurrInstr); + ++effect; + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_UPROAR: // uproar + if (gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR) + { + for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; ++gBattlerAttacker) + { + if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) + && gBattleMons[gBattlerAttacker].ability != ABILITY_SOUNDPROOF) + { + gBattleMons[gBattlerAttacker].status1 &= ~(STATUS1_SLEEP); + gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_NIGHTMARE); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + BattleScriptExecute(BattleScript_MonWokeUpInUproar); + gActiveBattler = gBattlerAttacker; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + break; + } + } + if (gBattlerAttacker != gBattlersCount) + { + effect = 2; // a pokemon was awaken + break; + } + else + { + gBattlerAttacker = gActiveBattler; + gBattleMons[gActiveBattler].status2 -= 0x10; // uproar timer goes down + if (WasUnableToUseMove(gActiveBattler)) + { + CancelMultiTurnMoves(gActiveBattler); + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + } + else if (gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + gBattleMons[gActiveBattler].status2 |= STATUS2_MULTIPLETURNS; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + CancelMultiTurnMoves(gActiveBattler); + } + BattleScriptExecute(BattleScript_PrintUproarOverTurns); + effect = 1; + } + } + if (effect != 2) + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_THRASH: // thrash + if (gBattleMons[gActiveBattler].status2 & STATUS2_LOCK_CONFUSE) + { + gBattleMons[gActiveBattler].status2 -= 0x400; + if (WasUnableToUseMove(gActiveBattler)) + CancelMultiTurnMoves(gActiveBattler); + else if (!(gBattleMons[gActiveBattler].status2 & STATUS2_LOCK_CONFUSE) + && (gBattleMons[gActiveBattler].status2 & STATUS2_MULTIPLETURNS)) + { + gBattleMons[gActiveBattler].status2 &= ~(STATUS2_MULTIPLETURNS); + if (!(gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION)) + { + gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER; + SetMoveEffect(1, 0); + if (gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION) + BattleScriptExecute(BattleScript_ThrashConfuses); + ++effect; + } + } + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_DISABLE: // disable + if (gDisableStructs[gActiveBattler].disableTimer != 0) + { + s32 i; + for (i = 0; i < MAX_MON_MOVES; ++i) + { + if (gDisableStructs[gActiveBattler].disabledMove == gBattleMons[gActiveBattler].moves[i]) + break; + } + if (i == MAX_MON_MOVES) // pokemon does not have the disabled move anymore + { + gDisableStructs[gActiveBattler].disabledMove = 0; + gDisableStructs[gActiveBattler].disableTimer = 0; + } + else if (--gDisableStructs[gActiveBattler].disableTimer == 0) // disable ends + { + gDisableStructs[gActiveBattler].disabledMove = 0; + BattleScriptExecute(BattleScript_DisabledNoMore); + ++effect; + } + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_ENCORE: // encore + if (gDisableStructs[gActiveBattler].encoreTimer != 0) + { + if (gBattleMons[gActiveBattler].moves[gDisableStructs[gActiveBattler].encoredMovePos] != gDisableStructs[gActiveBattler].encoredMove) // pokemon does not have the encored move anymore + { + gDisableStructs[gActiveBattler].encoredMove = 0; + gDisableStructs[gActiveBattler].encoreTimer = 0; + } + else if (--gDisableStructs[gActiveBattler].encoreTimer == 0 + || gBattleMons[gActiveBattler].pp[gDisableStructs[gActiveBattler].encoredMovePos] == 0) + { + gDisableStructs[gActiveBattler].encoredMove = 0; + gDisableStructs[gActiveBattler].encoreTimer = 0; + BattleScriptExecute(BattleScript_EncoredNoMore); + ++effect; + } + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_LOCK_ON: // lock-on decrement + if (gStatuses3[gActiveBattler] & STATUS3_ALWAYS_HITS) + gStatuses3[gActiveBattler] -= 0x8; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_CHARGE: // charge + if (gDisableStructs[gActiveBattler].chargeTimer && --gDisableStructs[gActiveBattler].chargeTimer == 0) + gStatuses3[gActiveBattler] &= ~STATUS3_CHARGED_UP; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_TAUNT: // taunt + if (gDisableStructs[gActiveBattler].tauntTimer) + --gDisableStructs[gActiveBattler].tauntTimer; + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_YAWN: // yawn + if (gStatuses3[gActiveBattler] & STATUS3_YAWN) + { + gStatuses3[gActiveBattler] -= 0x800; + if (!(gStatuses3[gActiveBattler] & STATUS3_YAWN) && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY) + && gBattleMons[gActiveBattler].ability != ABILITY_VITAL_SPIRIT + && gBattleMons[gActiveBattler].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler)) + { + CancelMultiTurnMoves(gActiveBattler); + gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2; + BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1); + MarkBattlerForControllerExec(gActiveBattler); + gEffectBattler = gActiveBattler; + BattleScriptExecute(BattleScript_YawnMakesAsleep); + ++effect; + } + } + ++gBattleStruct->turnEffectsTracker; + break; + case ENDTURN_BATTLER_COUNT: // done + gBattleStruct->turnEffectsTracker = 0; + ++gBattleStruct->turnEffectsBattlerId; + break; + } + if (effect) + return effect; + } + } + gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); + return 0; +} + +bool8 HandleWishPerishSongOnTurnEnd(void) +{ + gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); + switch (gBattleStruct->wishPerishSongState) + { + case 0: + while (gBattleStruct->wishPerishSongBattlerId < gBattlersCount) + { + gActiveBattler = gBattleStruct->wishPerishSongBattlerId; + if (gAbsentBattlerFlags & gBitTable[gActiveBattler]) + { + ++gBattleStruct->wishPerishSongBattlerId; + continue; + } + ++gBattleStruct->wishPerishSongBattlerId; + if (gWishFutureKnock.futureSightCounter[gActiveBattler] != 0 + && --gWishFutureKnock.futureSightCounter[gActiveBattler] == 0 + && gBattleMons[gActiveBattler].hp != 0) + { + if (gWishFutureKnock.futureSightMove[gActiveBattler] == MOVE_FUTURE_SIGHT) + gBattleCommunication[MULTISTRING_CHOOSER] = 0; + else + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gWishFutureKnock.futureSightMove[gActiveBattler]); + gBattlerTarget = gActiveBattler; + gBattlerAttacker = gWishFutureKnock.futureSightAttacker[gActiveBattler]; + gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gActiveBattler]; + gSpecialStatuses[gBattlerTarget].dmg = 0xFFFF; + BattleScriptExecute(BattleScript_MonTookFutureAttack); + return TRUE; + } + } + { + u8 *state = &gBattleStruct->wishPerishSongState; + + *state = 1; + gBattleStruct->wishPerishSongBattlerId = 0; + } + // fall through + case 1: + while (gBattleStruct->wishPerishSongBattlerId < gBattlersCount) + { + gActiveBattler = gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->wishPerishSongBattlerId]; + if (gAbsentBattlerFlags & gBitTable[gActiveBattler]) + { + ++gBattleStruct->wishPerishSongBattlerId; + continue; + } + ++gBattleStruct->wishPerishSongBattlerId; + if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG) + { + PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gActiveBattler].perishSongTimer); + if (gDisableStructs[gActiveBattler].perishSongTimer == 0) + { + gStatuses3[gActiveBattler] &= ~STATUS3_PERISH_SONG; + gBattleMoveDamage = gBattleMons[gActiveBattler].hp; + gBattlescriptCurrInstr = BattleScript_PerishSongTakesLife; + } + else + { + --gDisableStructs[gActiveBattler].perishSongTimer; + gBattlescriptCurrInstr = BattleScript_PerishSongCountGoesDown; + } + BattleScriptExecute(gBattlescriptCurrInstr); + return TRUE; + } + } + break; + } + gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); + return FALSE; +} + +#define FAINTED_ACTIONS_MAX_CASE 7 + +bool8 HandleFaintedMonActions(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_SAFARI) + return FALSE; + do + { + s32 i; + switch (gBattleStruct->faintedActionsState) + { + case 0: + gBattleStruct->faintedActionsBattlerId = 0; + ++gBattleStruct->faintedActionsState; + for (i = 0; i < gBattlersCount; ++i) + { + if (gAbsentBattlerFlags & gBitTable[i] && !HasNoMonsToSwitch(i, 6, 6)) + gAbsentBattlerFlags &= ~(gBitTable[i]); + } + // fall through + case 1: + do + { + gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; + if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 + && !(gBattleStruct->givenExpMons & gBitTable[gBattlerPartyIndexes[gBattleStruct->faintedActionsBattlerId]]) + && !(gAbsentBattlerFlags & gBitTable[gBattleStruct->faintedActionsBattlerId])) + { + BattleScriptExecute(BattleScript_GiveExp); + gBattleStruct->faintedActionsState = 2; + return TRUE; + } + } while (++gBattleStruct->faintedActionsBattlerId != gBattlersCount); + gBattleStruct->faintedActionsState = 3; + break; + case 2: + sub_8017434(gBattlerFainted); + if (++gBattleStruct->faintedActionsBattlerId == gBattlersCount) + gBattleStruct->faintedActionsState = 3; + else + gBattleStruct->faintedActionsState = 1; + break; + case 3: + gBattleStruct->faintedActionsBattlerId = 0; + ++gBattleStruct->faintedActionsState; + // fall through + case 4: + do + { + gBattlerFainted = gBattlerTarget = gBattleStruct->faintedActionsBattlerId; + if (gBattleMons[gBattleStruct->faintedActionsBattlerId].hp == 0 + && !(gAbsentBattlerFlags & gBitTable[gBattleStruct->faintedActionsBattlerId])) + { + BattleScriptExecute(BattleScript_HandleFaintedMon); + gBattleStruct->faintedActionsState = 5; + return TRUE; + } + } while (++gBattleStruct->faintedActionsBattlerId != gBattlersCount); + gBattleStruct->faintedActionsState = 6; + break; + case 5: + if (++gBattleStruct->faintedActionsBattlerId == gBattlersCount) + gBattleStruct->faintedActionsState = 6; + else + gBattleStruct->faintedActionsState = 4; + break; + case 6: + if (AbilityBattleEffects(ABILITYEFFECT_INTIMIDATE1, 0, 0, 0, 0) || AbilityBattleEffects(ABILITYEFFECT_TRACE, 0, 0, 0, 0) || ItemBattleEffects(1, 0, TRUE) || AbilityBattleEffects(ABILITYEFFECT_FORECAST, 0, 0, 0, 0)) + return TRUE; + ++gBattleStruct->faintedActionsState; + break; + case FAINTED_ACTIONS_MAX_CASE: + break; + } + } while (gBattleStruct->faintedActionsState != FAINTED_ACTIONS_MAX_CASE); + return FALSE; +} diff --git a/src/battle_util2.c b/src/battle_util2.c index 83014a83b..6a3f3525b 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -19,10 +19,7 @@ void AllocateBattleResources(void) *ptr++ = AllocZeroed(8); while (--i >= 0); } - // TODO: Figure out whether 0x200 is really the size of *gBattleStruct. - // The following works in pokeem: - // gBattleStruct = AllocZeroed(sizeof(*gBattleStruct)); - gBattleStruct = AllocZeroed(0x200); + gBattleStruct = AllocZeroed(sizeof(*gBattleStruct)); gBattleResources = AllocZeroed(sizeof(*gBattleResources)); gBattleResources->secretBase = AllocZeroed(sizeof(*gBattleResources->secretBase)); gBattleResources->flags = AllocZeroed(sizeof(*gBattleResources->flags)); diff --git a/src/pokemon.c b/src/pokemon.c index d75650d91..615bf55f1 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2552,7 +2552,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de damage /= 2; // sunny - if (gBattleWeather & WEATHER_SUNNY_ANY) + if (gBattleWeather & WEATHER_SUN_ANY) { switch (type) { @@ -4117,14 +4117,14 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo { gAbsentBattlerFlags &= ~gBitTable[sp34]; CopyPlayerPartyMonToBattleData(sp34, pokemon_order_func(gBattlerPartyIndexes[sp34])); - if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.unk4 < 255) - gBattleResults.unk4++; + if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255) + gBattleResults.numRevivesUsed++; } else { gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2]; - if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.unk4 < 255) - gBattleResults.unk4++; + if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255) + gBattleResults.numRevivesUsed++; } } } @@ -4164,8 +4164,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo gBattleMons[sp34].hp = data; if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == 0) { - if (gBattleResults.unk3 < 255) - gBattleResults.unk3++; + if (gBattleResults.numHealingItemsUsed < 255) + gBattleResults.numHealingItemsUsed++; // I have to re-use this variable to match. r5 = gActiveBattler; gActiveBattler = sp34; @@ -4204,7 +4204,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo SetMonData(pkmn, MON_DATA_PP1 + r5, &data); if (gMain.inBattle && sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000) - && !(gDisableStructs[sp34].unk18_b & gBitTable[r5])) + && !(gDisableStructs[sp34].mimickedMoves & gBitTable[r5])) gBattleMons[sp34].pp[r5] = data; retVal = FALSE; } @@ -4229,7 +4229,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *pkmn, u16 item, u8 partyIndex, u8 mo SetMonData(pkmn, MON_DATA_PP1 + moveIndex, &data); if (gMain.inBattle && sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000) - && !(gDisableStructs[sp34].unk18_b & gBitTable[moveIndex])) + && !(gDisableStructs[sp34].mimickedMoves & gBitTable[moveIndex])) gBattleMons[sp34].pp[moveIndex] = data; retVal = FALSE; } |