From 143cb7ad3512fba621ce50fe287700f2a9c3f555 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 22 Aug 2019 15:57:33 +0200 Subject: [PATCH] Updated switch mechanics --- include/battle_script_commands.h | 1 + include/battle_scripts.h | 1 + src/battle_main.c | 12 +- src/battle_script_commands.c | 77 ++- src/battle_util.c | 826 ++++++++++++++++--------------- 5 files changed, 480 insertions(+), 437 deletions(-) diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index e84500b78..72f04323a 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -6,6 +6,7 @@ s32 CalcCritChanceStage(u8 battlerAtk, u8 battlerDef, u32 move, bool32 recordAbility); u8 GetBattlerTurnOrderNum(u8 battlerId); +bool32 NoAliveMonsForEitherParty(void); void SetMoveEffect(bool32 primary, u32 certain); void BattleDestroyYesNoCursorAt(u8 cursorPosition); void BattleCreateYesNoCursorAt(u8 cursorPosition); diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 4288bb141..7750536d5 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -7,6 +7,7 @@ extern const u8 BattleScript_MakeMoveMissed[]; extern const u8 BattleScript_PrintMoveMissed[]; extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissed[]; +extern const u8 BattleScript_ButItFailedAtkStringPpReduce[]; extern const u8 BattleScript_ButItFailed[]; extern const u8 BattleScript_StatUp[]; extern const u8 BattleScript_StatDown[]; diff --git a/src/battle_main.c b/src/battle_main.c index 0eaf6a174..8c4883e0e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5220,7 +5220,7 @@ static void HandleAction_UseMove(void) { if (gBattlerTarget == gBattlerAttacker) continue; - if (!(gAbsentBattlerFlags & gBitTable[gBattlerTarget])) + if (IsBattlerAlive(gBattlerTarget)) break; } } @@ -5229,7 +5229,7 @@ static void HandleAction_UseMove(void) gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker); } - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (!IsBattlerAlive(gBattlerTarget)) { if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) { @@ -5238,7 +5238,7 @@ static void HandleAction_UseMove(void) else { gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerAttacker) ^ BIT_SIDE); - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (!IsBattlerAlive(gBattlerTarget)) gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK); } } @@ -5292,14 +5292,14 @@ static void HandleAction_UseMove(void) { if (gBattlerTarget == gBattlerAttacker) continue; - if (!(gAbsentBattlerFlags & gBitTable[gBattlerTarget])) + if (IsBattlerAlive(gBattlerTarget)) break; } } else { gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker); - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (!IsBattlerAlive(gBattlerTarget)) { if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) { @@ -5308,7 +5308,7 @@ static void HandleAction_UseMove(void) else { gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerAttacker) ^ BIT_SIDE); - if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) + if (!IsBattlerAlive(gBattlerTarget)) gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK); } } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e6a2303b1..1f207084f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -943,10 +943,35 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) return FALSE; } +static bool32 NoTargetPresent(u32 move) +{ + if (!IsBattlerAlive(gBattlerTarget)) + gBattlerTarget = GetMoveTarget(move, 0); + + switch (gBattleMoves[move].target) + { + case MOVE_TARGET_SELECTED: + case MOVE_TARGET_DEPENDS: + case MOVE_TARGET_RANDOM: + if (!IsBattlerAlive(gBattlerTarget)) + return TRUE; + break; + case MOVE_TARGET_BOTH: + if (!IsBattlerAlive(gBattlerTarget) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget))) + return TRUE; + break; + case MOVE_TARGET_FOES_AND_ALLY: + if (!IsBattlerAlive(gBattlerTarget) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget)) && !IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker))) + return TRUE; + break; + } + + return FALSE; +} + static void atk00_attackcanceler(void) { - s32 i; - u32 moveType; + s32 i, moveType; if (gBattleOutcome != 0) { @@ -990,11 +1015,9 @@ static void atk00_attackcanceler(void) } gHitMarker &= ~(HITMARKER_x800000); - if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)) { - i = IsMonDisobedient(); // why use the 'i' variable...? - switch (i) + switch (IsMonDisobedient()) { case 0: break; @@ -1009,6 +1032,12 @@ static void atk00_attackcanceler(void) gHitMarker |= HITMARKER_OBEYS; + if (NoTargetPresent(gCurrentMove)) + { + gBattlescriptCurrInstr = BattleScript_ButItFailedAtkStringPpReduce; + return; + } + if (gProtectStructs[gBattlerTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED && !gProtectStructs[gBattlerAttacker].usesBouncedMove) @@ -3553,7 +3582,7 @@ static void atk23_getexp(void) } } -static bool32 IsBattleLostForPlayer(void) +static bool32 NoAliveMonsForPlayer(void) { u32 i; u32 HP_count = 0; @@ -3581,7 +3610,7 @@ static bool32 IsBattleLostForPlayer(void) return (HP_count == 0); } -static bool32 IsBattleWonForPlayer(void) +static bool32 NoAliveMonsForOpponent(void) { u32 i; u32 HP_count = 0; @@ -3598,14 +3627,19 @@ static bool32 IsBattleWonForPlayer(void) return (HP_count == 0); } +bool32 NoAliveMonsForEitherParty(void) +{ + return (NoAliveMonsForPlayer() || NoAliveMonsForOpponent()); +} + static void atk24(void) { if (gBattleControllerExecFlags) return; - if (IsBattleLostForPlayer()) + if (NoAliveMonsForPlayer()) gBattleOutcome |= B_OUTCOME_LOST; - if (IsBattleWonForPlayer()) + if (NoAliveMonsForOpponent()) gBattleOutcome |= B_OUTCOME_WON; if (gBattleOutcome == 0 && (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) @@ -6910,8 +6944,7 @@ static void atk76_various(void) case VARIOUS_TRY_ACTIVATE_MOXIE: if (GetBattlerAbility(gActiveBattler) == ABILITY_MOXIE && HasAttackerFaintedTarget() - && !IsBattleLostForPlayer() - && !IsBattleWonForPlayer() + && !NoAliveMonsForEitherParty() && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) { gBattleMons[gBattlerAttacker].statStages[STAT_ATK]++; @@ -6925,8 +6958,7 @@ static void atk76_various(void) case VARIOUS_TRY_ACTIVATE_FELL_STINGER: if (gBattleMoves[gCurrentMove].effect == EFFECT_FELL_STINGER && HasAttackerFaintedTarget() - && !IsBattleLostForPlayer() - && !IsBattleWonForPlayer() + && !NoAliveMonsForEitherParty() && gBattleMons[gBattlerAttacker].statStages[STAT_ATK] != 12) { if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] >= 11) @@ -7112,7 +7144,7 @@ static void atk76_various(void) } return; case VARIOUS_JUMP_IF_BATTLE_END: - if (IsBattleLostForPlayer() || IsBattleWonForPlayer()) + if (NoAliveMonsForEitherParty()) gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; @@ -7739,7 +7771,7 @@ static void atk7A_jumpifnexttargetvalid(void) { if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER)) continue; - if (!(gAbsentBattlerFlags & gBitTable[gBattlerTarget])) + if (IsBattlerAlive(gBattlerTarget)) break; } @@ -8791,7 +8823,11 @@ static void atk95_setsandstorm(void) static void atk96_weatherdamage(void) { - if (WEATHER_HAS_EFFECT) + if (!IsBattlerAlive(gBattlerAttacker) || !WEATHER_HAS_EFFECT) + { + gBattleMoveDamage = 0; + } + else { u32 ability = GetBattlerAbility(gBattlerAttacker); if (gBattleWeather & WEATHER_SANDSTORM_ANY) @@ -8847,13 +8883,6 @@ static void atk96_weatherdamage(void) } } } - else - { - gBattleMoveDamage = 0; - } - - if (gAbsentBattlerFlags & gBitTable[gBattlerAttacker]) - gBattleMoveDamage = 0; gBattlescriptCurrInstr++; } @@ -10089,7 +10118,7 @@ static void atkC2_selectfirstvalidtarget(void) { if (gBattlerTarget == gBattlerAttacker && !(gBattleMoves[gCurrentMove].target & MOVE_TARGET_USER)) continue; - if (!(gAbsentBattlerFlags & gBitTable[gBattlerTarget])) + if (IsBattlerAlive(gBattlerTarget)) break; } gBattlescriptCurrInstr++; diff --git a/src/battle_util.c b/src/battle_util.c index 4e2f95fc0..c016a4ace 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1372,7 +1372,7 @@ enum u8 DoBattlerEndTurnEffects(void) { - u8 effect = FALSE; + u32 ability, effect = 0; gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20); while (gBattleStruct->turnEffectsBattlerId < gBattlersCount && gBattleStruct->turnEffectsTracker <= ENDTURN_BATTLER_COUNT) @@ -1381,453 +1381,454 @@ u8 DoBattlerEndTurnEffects(void) if (gAbsentBattlerFlags & gBitTable[gActiveBattler]) { gBattleStruct->turnEffectsBattlerId++; + continue; } - else + + ability = GetBattlerAbility(gActiveBattler); + switch (gBattleStruct->turnEffectsTracker) { - u8 ability = GetBattlerAbility(gActiveBattler); - switch (gBattleStruct->turnEffectsTracker) + case ENDTURN_INGRAIN: // ingrain + if ((gStatuses3[gActiveBattler] & STATUS3_ROOTED) + && !BATTLER_MAX_HP(gActiveBattler) + && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) + && gBattleMons[gActiveBattler].hp != 0) { - case ENDTURN_INGRAIN: // ingrain - if ((gStatuses3[gActiveBattler] & STATUS3_ROOTED) - && !BATTLER_MAX_HP(gActiveBattler) - && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) - && 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_AQUA_RING: // aqua ring + if ((gStatuses3[gActiveBattler] & STATUS3_AQUA_RING) + && !BATTLER_MAX_HP(gActiveBattler) + && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) + && gBattleMons[gActiveBattler].hp != 0) + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + gBattleMoveDamage *= -1; + BattleScriptExecute(BattleScript_AquaRingHeal); + 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_ORBS: + if (ItemBattleEffects(ITEMEFFECT_ORBS, gActiveBattler, FALSE)) + 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 + && ability != ABILITY_MAGIC_GUARD) + { + if (ability == ABILITY_POISON_HEAL) { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - BattleScriptExecute(BattleScript_IngrainTurnHeal); - effect++; - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_AQUA_RING: // aqua ring - if ((gStatuses3[gActiveBattler] & STATUS3_AQUA_RING) - && !BATTLER_MAX_HP(gActiveBattler) - && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) - && gBattleMons[gActiveBattler].hp != 0) - { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - BattleScriptExecute(BattleScript_AquaRingHeal); - 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_ORBS: - if (ItemBattleEffects(ITEMEFFECT_ORBS, gActiveBattler, FALSE)) - 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 - && ability != ABILITY_MAGIC_GUARD) - { - if (ability == ABILITY_POISON_HEAL) - { - if (!BATTLER_MAX_HP(gActiveBattler) && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK)) - { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - BattleScriptExecute(BattleScript_PoisonHealActivates); - effect++; - } - } - else + if (!BATTLER_MAX_HP(gActiveBattler) && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK)) { gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; - BattleScriptExecute(BattleScript_PoisonTurnDmg); + gBattleMoveDamage *= -1; + BattleScriptExecute(BattleScript_PoisonHealActivates); effect++; } } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_BAD_POISON: // toxic poison - if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON) - && gBattleMons[gActiveBattler].hp != 0 - && ability != ABILITY_MAGIC_GUARD) - { - if (ability == ABILITY_POISON_HEAL) - { - if (!BATTLER_MAX_HP(gActiveBattler) && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK)) - { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - gBattleMoveDamage *= -1; - BattleScriptExecute(BattleScript_PoisonHealActivates); - effect++; - } - } - else - { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_COUNTER) // not 16 turns - gBattleMons[gActiveBattler].status1 += 0x100; - gBattleMoveDamage *= (gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) >> 8; - BattleScriptExecute(BattleScript_PoisonTurnDmg); - effect++; - } - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_BURN: // burn - if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN) - && gBattleMons[gActiveBattler].hp != 0 - && ability != ABILITY_MAGIC_GUARD) + else { gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; - BattleScriptExecute(BattleScript_BurnTurnDmg); + BattleScriptExecute(BattleScript_PoisonTurnDmg); effect++; } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_NIGHTMARES: // spooky nightmares - if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) - && gBattleMons[gActiveBattler].hp != 0 - && ability != ABILITY_MAGIC_GUARD) + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_BAD_POISON: // toxic poison + if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON) + && gBattleMons[gActiveBattler].hp != 0 + && ability != ABILITY_MAGIC_GUARD) + { + if (ability == ABILITY_POISON_HEAL) { - // 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) + if (!BATTLER_MAX_HP(gActiveBattler) && !(gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK)) { - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4; + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; - BattleScriptExecute(BattleScript_NightmareTurnDmg); + gBattleMoveDamage *= -1; + BattleScriptExecute(BattleScript_PoisonHealActivates); effect++; } - else - { - gBattleMons[gActiveBattler].status2 &= ~STATUS2_NIGHTMARE; - } } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_CURSE: // curse - if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED) - && gBattleMons[gActiveBattler].hp != 0 - && ability != ABILITY_MAGIC_GUARD) + else + { + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; + if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_COUNTER) // not 16 turns + gBattleMons[gActiveBattler].status1 += 0x100; + gBattleMoveDamage *= (gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) >> 8; + BattleScriptExecute(BattleScript_PoisonTurnDmg); + effect++; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_BURN: // burn + if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN) + && gBattleMons[gActiveBattler].hp != 0 + && ability != ABILITY_MAGIC_GUARD) + { + 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 + && ability != ABILITY_MAGIC_GUARD) + { + // 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_CurseTurnDmg); + BattleScriptExecute(BattleScript_NightmareTurnDmg); effect++; } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_WRAP: // wrap - if ((gBattleMons[gActiveBattler].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBattler].hp != 0) + else { - if (--gDisableStructs[gActiveBattler].wrapTurns != 0) // damaged by wrap - { - gBattleScripting.animArg1 = gBattleStruct->wrappedMove[gActiveBattler]; - gBattleScripting.animArg2 = gBattleStruct->wrappedMove[gActiveBattler] >> 8; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gActiveBattler]); - gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; - if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[gActiveBattler], TRUE) == HOLD_EFFECT_BINDING_BAND) - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; - else - gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; + gBattleMons[gActiveBattler].status2 &= ~STATUS2_NIGHTMARE; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_CURSE: // curse + if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED) + && gBattleMons[gActiveBattler].hp != 0 + && ability != ABILITY_MAGIC_GUARD) + { + 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) + { + if (--gDisableStructs[gActiveBattler].wrapTurns != 0) // damaged by wrap + { + gBattleScripting.animArg1 = gBattleStruct->wrappedMove[gActiveBattler]; + gBattleScripting.animArg2 = gBattleStruct->wrappedMove[gActiveBattler] >> 8; + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gActiveBattler]); + gBattlescriptCurrInstr = BattleScript_WrapTurnDmg; + if (GetBattlerHoldEffect(gBattleStruct->wrappedBy[gActiveBattler], TRUE) == HOLD_EFFECT_BINDING_BAND) + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8; + else + gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16; - if (gBattleMoveDamage == 0) - gBattleMoveDamage = 1; - } - else // broke free - { - gBattleMons[gActiveBattler].status2 &= ~(STATUS2_WRAPPED); - PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gActiveBattler]); - gBattlescriptCurrInstr = BattleScript_WrapEnds; - } - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; + if (gBattleMoveDamage == 0) + gBattleMoveDamage = 1; } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_UPROAR: // uproar - if (gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR) + else // broke free { - for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) + gBattleMons[gActiveBattler].status2 &= ~(STATUS2_WRAPPED); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleStruct->wrappedMove[gActiveBattler]); + 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) { - 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 + 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 { - 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)) + gBattleCommunication[MULTISTRING_CHOOSER] = 1; 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)) - { - gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER; - SetMoveEffect(1, 0); - if (gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION) - BattleScriptExecute(BattleScript_ThrashConfuses); - effect++; - } } + BattleScriptExecute(BattleScript_PrintUproarOverTurns); + effect = 1; } - 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 == 0) - { - BattleScriptExecute(BattleScript_BufferEndTurn); - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - effect++; - } - 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_LASER_FOCUS: - if (gStatuses3[gActiveBattler] & STATUS3_LASER_FOCUS) - { - if (gDisableStructs[gActiveBattler].laserFocusTimer == 0 || --gDisableStructs[gActiveBattler].laserFocusTimer == 0) - gStatuses3[gActiveBattler] &= ~(STATUS3_LASER_FOCUS); - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_EMBARGO: - if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO) - { - if (gDisableStructs[gActiveBattler].embargoTimer == 0 || --gDisableStructs[gActiveBattler].embargoTimer == 0) - { - gStatuses3[gActiveBattler] &= ~(STATUS3_EMBARGO); - BattleScriptExecute(BattleScript_EmbargoEndTurn); - effect++; - } - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_MAGNET_RISE: - if (gStatuses3[gActiveBattler] & STATUS3_MAGNET_RISE) - { - if (gDisableStructs[gActiveBattler].magnetRiseTimer == 0 || --gDisableStructs[gActiveBattler].magnetRiseTimer == 0) - { - gStatuses3[gActiveBattler] &= ~(STATUS3_MAGNET_RISE); - BattleScriptExecute(BattleScript_BufferEndTurn); - PREPARE_STRING_BUFFER(gBattleTextBuff1, STRINGID_ELECTROMAGNETISM); - effect++; - } - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_TELEKINESIS: - if (gStatuses3[gActiveBattler] & STATUS3_TELEKINESIS) - { - if (gDisableStructs[gActiveBattler].telekinesisTimer == 0 || --gDisableStructs[gActiveBattler].telekinesisTimer == 0) - { - gStatuses3[gActiveBattler] &= ~(STATUS3_TELEKINESIS); - BattleScriptExecute(BattleScript_TelekinesisEndTurn); - effect++; - } - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_HEALBLOCK: - if (gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) - { - if (gDisableStructs[gActiveBattler].healBlockTimer == 0 || --gDisableStructs[gActiveBattler].healBlockTimer == 0) - { - gStatuses3[gActiveBattler] &= ~(STATUS3_HEAL_BLOCK); - BattleScriptExecute(BattleScript_BufferEndTurn); - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_HEAL_BLOCK); - effect++; - } - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_ROOST: // Return flying type. - if (gBattleResources->flags->flags[gActiveBattler] & RESOURCE_FLAG_ROOST) - { - gBattleResources->flags->flags[gActiveBattler] &= ~(RESOURCE_FLAG_ROOST); - gBattleMons[gActiveBattler].type1 = gBattleStruct->roostTypes[gActiveBattler][0]; - gBattleMons[gActiveBattler].type2 = gBattleStruct->roostTypes[gActiveBattler][1]; - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_ELECTRIFY: - gStatuses3[gActiveBattler] &= ~(STATUS3_ELECTRIFIED); - gBattleStruct->turnEffectsTracker++; - case ENDTURN_POWDER: - gBattleMons[gActiveBattler].status2 &= ~(STATUS2_POWDER); - gBattleStruct->turnEffectsTracker++; - case ENDTURN_THROAT_CHOP: - if (gDisableStructs[gActiveBattler].throatChopTimer && --gDisableStructs[gActiveBattler].throatChopTimer == 0) - { - BattleScriptExecute(BattleScript_ThroatChopEndTurn); - effect++; - } - gBattleStruct->turnEffectsTracker++; - break; - case ENDTURN_BATTLER_COUNT: // done - gBattleStruct->turnEffectsTracker = 0; - gBattleStruct->turnEffectsBattlerId++; - break; } - if (effect != 0) - return effect; + 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)) + { + gBattleScripting.moveEffect = 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 == 0) + { + BattleScriptExecute(BattleScript_BufferEndTurn); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); + effect++; + } + 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_LASER_FOCUS: + if (gStatuses3[gActiveBattler] & STATUS3_LASER_FOCUS) + { + if (gDisableStructs[gActiveBattler].laserFocusTimer == 0 || --gDisableStructs[gActiveBattler].laserFocusTimer == 0) + gStatuses3[gActiveBattler] &= ~(STATUS3_LASER_FOCUS); + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_EMBARGO: + if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO) + { + if (gDisableStructs[gActiveBattler].embargoTimer == 0 || --gDisableStructs[gActiveBattler].embargoTimer == 0) + { + gStatuses3[gActiveBattler] &= ~(STATUS3_EMBARGO); + BattleScriptExecute(BattleScript_EmbargoEndTurn); + effect++; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_MAGNET_RISE: + if (gStatuses3[gActiveBattler] & STATUS3_MAGNET_RISE) + { + if (gDisableStructs[gActiveBattler].magnetRiseTimer == 0 || --gDisableStructs[gActiveBattler].magnetRiseTimer == 0) + { + gStatuses3[gActiveBattler] &= ~(STATUS3_MAGNET_RISE); + BattleScriptExecute(BattleScript_BufferEndTurn); + PREPARE_STRING_BUFFER(gBattleTextBuff1, STRINGID_ELECTROMAGNETISM); + effect++; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_TELEKINESIS: + if (gStatuses3[gActiveBattler] & STATUS3_TELEKINESIS) + { + if (gDisableStructs[gActiveBattler].telekinesisTimer == 0 || --gDisableStructs[gActiveBattler].telekinesisTimer == 0) + { + gStatuses3[gActiveBattler] &= ~(STATUS3_TELEKINESIS); + BattleScriptExecute(BattleScript_TelekinesisEndTurn); + effect++; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_HEALBLOCK: + if (gStatuses3[gActiveBattler] & STATUS3_HEAL_BLOCK) + { + if (gDisableStructs[gActiveBattler].healBlockTimer == 0 || --gDisableStructs[gActiveBattler].healBlockTimer == 0) + { + gStatuses3[gActiveBattler] &= ~(STATUS3_HEAL_BLOCK); + BattleScriptExecute(BattleScript_BufferEndTurn); + PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_HEAL_BLOCK); + effect++; + } + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_ROOST: // Return flying type. + if (gBattleResources->flags->flags[gActiveBattler] & RESOURCE_FLAG_ROOST) + { + gBattleResources->flags->flags[gActiveBattler] &= ~(RESOURCE_FLAG_ROOST); + gBattleMons[gActiveBattler].type1 = gBattleStruct->roostTypes[gActiveBattler][0]; + gBattleMons[gActiveBattler].type2 = gBattleStruct->roostTypes[gActiveBattler][1]; + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_ELECTRIFY: + gStatuses3[gActiveBattler] &= ~(STATUS3_ELECTRIFIED); + gBattleStruct->turnEffectsTracker++; + case ENDTURN_POWDER: + gBattleMons[gActiveBattler].status2 &= ~(STATUS2_POWDER); + gBattleStruct->turnEffectsTracker++; + case ENDTURN_THROAT_CHOP: + if (gDisableStructs[gActiveBattler].throatChopTimer && --gDisableStructs[gActiveBattler].throatChopTimer == 0) + { + BattleScriptExecute(BattleScript_ThroatChopEndTurn); + effect++; + } + gBattleStruct->turnEffectsTracker++; + break; + case ENDTURN_BATTLER_COUNT: // done + gBattleStruct->turnEffectsTracker = 0; + gBattleStruct->turnEffectsBattlerId++; + break; } + + if (effect != 0) + return effect; + } gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20); return 0; @@ -1978,6 +1979,15 @@ bool8 HandleFaintedMonActions(void) gBattleStruct->faintedActionsState = 3; else gBattleStruct->faintedActionsState = 1; + + // Don't switch mons until all pokemon performed their actions or the battle's over. + if (gBattleOutcome == 0 + && !NoAliveMonsForEitherParty() + && gCurrentTurnActionNumber != gBattlersCount) + { + gAbsentBattlerFlags |= gBitTable[gBattlerFainted]; + return FALSE; + } break; case 3: gBattleStruct->faintedActionsBattlerId = 0; @@ -4591,14 +4601,16 @@ u8 GetMoveTarget(u16 move, u8 setTarget) case MOVE_TARGET_SELECTED: side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE; if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp) + { targetBattler = gSideTimers[side].followmeTarget; + } else { side = GetBattlerSide(gBattlerAttacker); do { targetBattler = Random() % gBattlersCount; - } while (targetBattler == gBattlerAttacker || side == GetBattlerSide(targetBattler) || gAbsentBattlerFlags & gBitTable[targetBattler]); + } while (targetBattler == gBattlerAttacker || side == GetBattlerSide(targetBattler) || !IsBattlerAlive(targetBattler)); if (gBattleMoves[move].type == TYPE_ELECTRIC && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD) && gBattleMons[targetBattler].ability != ABILITY_LIGHTNING_ROD) @@ -4622,7 +4634,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget) case MOVE_TARGET_FOES_AND_ALLY: case MOVE_TARGET_OPPONENTS_FIELD: targetBattler = GetBattlerAtPosition((GetBattlerPosition(gBattlerAttacker) & BIT_SIDE) ^ BIT_SIDE); - if (gAbsentBattlerFlags & gBitTable[targetBattler]) + if (!IsBattlerAlive(targetBattler)) targetBattler ^= BIT_FLANK; break; case MOVE_TARGET_RANDOM: @@ -4645,7 +4657,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget) else targetBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); } - if (gAbsentBattlerFlags & gBitTable[targetBattler]) + if (!IsBattlerAlive(targetBattler)) targetBattler ^= BIT_FLANK; } else