diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index e386c389c9..425ba1cac9 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1331,7 +1331,7 @@ .byte \stat .endm - .macro jumpifoppositegenders jumpInstr:req + .macro jumpifcaptivateaffected jumpInstr:req .byte 0xfc .4byte \jumpInstr .endm @@ -1367,6 +1367,10 @@ callnative BS_RestoreAttacker .endm + .macro jumpifintimidateabilityprevented + callnative BS_JumpIfIntimidateAbilityPrevented + .endm + .macro metalburstdamagecalculator failInstr:req callnative BS_CalcMetalBurstDmg .4byte \failInstr @@ -1383,6 +1387,10 @@ .byte \battler .endm + .macro tryintimidatejectpack + callnative BS_TryIntimidatEjectpack + .endm + .macro allyswitchswapbattlers callnative BS_AllySwitchSwapBattler .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4f17840393..a4f13be0b9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2713,6 +2713,7 @@ BattleScript_EffectGravity:: attackstring ppreduce setgravity BattleScript_ButItFailed + savetarget attackanimation waitanimation BattleScript_EffectGravitySuccess:: @@ -2730,6 +2731,7 @@ BattleScript_GravityLoopDrop: BattleScript_GravityLoopEnd: moveendcase MOVEEND_TARGET_VISIBLE jumpifnexttargetvalid BattleScript_GravityLoop + restoretarget goto BattleScript_MoveEnd BattleScript_EffectRoost:: @@ -2743,11 +2745,13 @@ BattleScript_EffectRoost:: BattleScript_EffectCaptivate:: setstatchanger STAT_SPATK, 2, TRUE attackcanceler - jumpifsubstituteblocks BattleScript_FailedFromAtkString - jumpifoppositegenders BattleScript_CaptivateCheckAcc - goto BattleScript_FailedFromAtkString + attackstring + ppreduce + jumpifsubstituteblocks BattleScript_ButItFailed + jumpifcaptivateaffected BattleScript_CaptivateCheckAcc + goto BattleScript_ButItFailed BattleScript_CaptivateCheckAcc: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE goto BattleScript_StatDownFromAttackString BattleScript_EffectHealBlock:: @@ -4211,6 +4215,7 @@ BattleScript_EffectPerishSong:: attackstring ppreduce trysetperishsong BattleScript_ButItFailed + savetarget attackanimation waitanimation printstring STRINGID_FAINTINTHREE @@ -4222,6 +4227,7 @@ BattleScript_PerishSongLoop:: BattleScript_PerishSongLoopIncrement:: addbyte gBattlerTarget, 1 jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop + restoretarget goto BattleScript_MoveEnd BattleScript_PerishSongBlocked:: @@ -7102,7 +7108,6 @@ BattleScript_MoveUsedIsAsleep:: goto BattleScript_MoveEnd BattleScript_MoveUsedWokeUp:: - bicword gHitMarker, HITMARKER_WAKE_UP_CLEAR printfromtable gWokeUpStringIds waitmessage B_WAIT_TIME_LONG updatestatusicon BS_ATTACKER @@ -7730,13 +7735,7 @@ BattleScript_IntimidateLoop: jumpiftargetally BattleScript_IntimidateLoopIncrement jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement -.if B_UPDATED_INTIMIDATE >= GEN_8 @These abilties specifically prevent just intimidate, without blocking stat decreases - jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_SCRAPPY, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_OBLIVIOUS, BattleScript_IntimidatePrevented -.endif - jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse + jumpifintimidateabilityprevented BattleScript_IntimidateEffect: copybyte sBATTLER, gBattlerAttacker setstatchanger STAT_ATK, 1, TRUE @@ -7761,9 +7760,10 @@ BattleScript_IntimidateLoopIncrement: destroyabilitypopup restoretarget pause B_WAIT_TIME_MED + tryintimidatejectpack end3 -BattleScript_IntimidatePrevented: +BattleScript_IntimidatePrevented:: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUp printstring STRINGID_PKMNPREVENTSSTATLOSSWITH @@ -7783,7 +7783,7 @@ BattleScript_IntimidateContrary_WontIncrease: printstring STRINGID_TARGETSTATWONTGOHIGHER goto BattleScript_IntimidateEffect_WaitString -BattleScript_IntimidateInReverse: +BattleScript_IntimidateInReverse:: copybyte sBATTLER, gBattlerTarget call BattleScript_AbilityPopUpTarget pause B_WAIT_TIME_SHORT @@ -9528,7 +9528,7 @@ BattleScript_EjectButtonActivates:: printstring STRINGID_EJECTBUTTONACTIVATE waitmessage B_WAIT_TIME_LONG removeitem BS_SCRIPTING - undodynamax BS_SCRIPTING + undodynamax BS_SCRIPTING makeinvisible BS_SCRIPTING openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd copybyte sSAVED_BATTLER, sBATTLER diff --git a/include/battle.h b/include/battle.h index 823e4813e9..1189ada4ea 100644 --- a/include/battle.h +++ b/include/battle.h @@ -183,7 +183,8 @@ struct ProtectStruct u16 eatMirrorHerb:1; u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy u16 usedAllySwitch:1; - u16 padding:2; + u16 lashOutAffected:1; + u16 padding:1; // End of 16-bit bitfield u32 physicalDmg; u32 specialDmg; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index d11d2b814e..20ea1ccd49 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -170,6 +170,8 @@ extern const u8 BattleScript_RainDishActivates[]; extern const u8 BattleScript_SandstreamActivates[]; extern const u8 BattleScript_ShedSkinActivates[]; extern const u8 BattleScript_IntimidateActivates[]; +extern const u8 BattleScript_IntimidatePrevented[]; +extern const u8 BattleScript_IntimidateInReverse[]; extern const u8 BattleScript_DroughtActivates[]; extern const u8 BattleScript_TookAttack[]; extern const u8 BattleScript_SturdyPreventsOHKO[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index ce1cf0e948..de7bbdfe92 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -196,7 +196,7 @@ #define STATUS4_SYRUP_BOMB (1 << 5) #define STATUS4_GLAIVE_RUSH (1 << 6) -#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked. +#define HITMARKER_UNUSED_1 (1 << 4) #define HITMARKER_IGNORE_BIDE (1 << 5) #define HITMARKER_DESTINYBOND (1 << 6) #define HITMARKER_NO_ANIMATIONS (1 << 7) // set from battleSceneOff. Never changed during battle @@ -204,16 +204,16 @@ #define HITMARKER_NO_ATTACKSTRING (1 << 9) #define HITMARKER_ATTACKSTRING_PRINTED (1 << 10) #define HITMARKER_NO_PPDEDUCT (1 << 11) -#define HITMARKER_SWAP_ATTACKER_TARGET (1 << 12) +#define HITMARKER_UNUSED_2 (1 << 12) #define HITMARKER_STATUS_ABILITY_EFFECT (1 << 13) #define HITMARKER_SYNCHRONISE_EFFECT (1 << 14) #define HITMARKER_RUN (1 << 15) #define HITMARKER_IGNORE_DISGUISE (1 << 16) #define HITMARKER_DISABLE_ANIMATION (1 << 17) // disable animations during battle scripts, e.g. for Bug Bite -// 3 free spots because of change in handling of UNDERGROUND/UNDERWATER/ON AIR +#define HITMARKER_UNUSED_3 (1 << 18) #define HITMARKER_UNABLE_TO_USE_MOVE (1 << 19) #define HITMARKER_PASSIVE_DAMAGE (1 << 20) -#define HITMARKER_DISOBEDIENT_MOVE (1 << 21) +#define HITMARKER_UNUSED_4 (1 << 21) #define HITMARKER_PLAYER_FAINTED (1 << 22) #define HITMARKER_ALLOW_NO_PP (1 << 23) #define HITMARKER_GRUDGE (1 << 24) diff --git a/include/move.h b/include/move.h index 5537840703..743889850e 100644 --- a/include/move.h +++ b/include/move.h @@ -137,7 +137,7 @@ struct MoveInfo const u8 *battleAnimScript; }; -extern const struct MoveInfo gMovesInfo[]; +extern const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL]; extern const u8 gNotDoneYetDescription[]; extern const struct BattleMoveEffect gBattleMoveEffects[]; @@ -154,19 +154,19 @@ static inline const u8 *GetMoveName(u32 moveId) return gMovesInfo[SanitizeMoveId(moveId)].name; } -static inline const u8 *GetMoveDescription(u32 moveId) -{ - moveId = SanitizeMoveId(moveId); - if (gMovesInfo[moveId].effect == EFFECT_PLACEHOLDER) - return gNotDoneYetDescription; - return gMovesInfo[moveId].description; -} - static inline u32 GetMoveEffect(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].effect; } +static inline const u8 *GetMoveDescription(u32 moveId) +{ + moveId = SanitizeMoveId(moveId); + if (GetMoveEffect(moveId) == EFFECT_PLACEHOLDER) + return gNotDoneYetDescription; + return gMovesInfo[moveId].description; +} + static inline u32 GetMoveType(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].type; @@ -437,6 +437,11 @@ static inline bool32 IsMoveSketchBanned(u32 moveId) return gMovesInfo[SanitizeMoveId(moveId)].sketchBanned; } +static inline bool32 IsValidApprenticeMove(u32 moveId) +{ + return gMovesInfo[SanitizeMoveId(moveId)].validApprenticeMove; +} + static inline u32 GetMoveTwoTurnAttackStringId(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.stringId; @@ -529,12 +534,12 @@ static inline const u8 *GetMoveAnimationScript(u32 moveId) static inline const u8 *GetMoveBattleScript(u32 moveId) { moveId = SanitizeMoveId(moveId); - if (gBattleMoveEffects[gMovesInfo[moveId].effect].battleScript == NULL) + if (gBattleMoveEffects[GetMoveEffect(moveId)].battleScript == NULL) { DebugPrintfLevel(MGBA_LOG_WARN, "No effect for moveId=%u", moveId); return gBattleMoveEffects[EFFECT_PLACEHOLDER].battleScript; } - return gBattleMoveEffects[gMovesInfo[moveId].effect].battleScript; + return gBattleMoveEffects[GetMoveEffect(moveId)].battleScript; } #endif // GUARD_MOVES_H diff --git a/src/apprentice.c b/src/apprentice.c index 7769dde6e3..7dcca7b28b 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -411,7 +411,7 @@ static u16 GetRandomAlternateMove(u8 monId) if (TrySetMove(monId, moveId)) { - if (gMovesInfo[moveId].validApprenticeMove) + if (IsValidApprenticeMove(moveId)) break; i++; } diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ca94655476..6478950a85 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1465,7 +1465,7 @@ bool32 IsConfusionMoveEffect(u32 moveEffect) bool32 IsHazardMove(u32 move) { // Hazard setting moves like Stealth Rock, Spikes, etc. - u32 i, moveEffect = gMovesInfo[move].effect; + u32 i, moveEffect = GetMoveEffect(move); switch (moveEffect) { case EFFECT_SPIKES: @@ -1491,7 +1491,7 @@ bool32 IsHazardMove(u32 move) bool32 IsHazardClearingMove(u32 move) { // Hazard clearing effects like Rapid Spin, Tidy Up, etc. - u32 i, moveEffect = gMovesInfo[move].effect; + u32 i, moveEffect = GetMoveEffect(move); switch (moveEffect) { case EFFECT_RAPID_SPIN: diff --git a/src/battle_main.c b/src/battle_main.c index 20959ef394..00a12fdeff 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3751,6 +3751,7 @@ static void TryDoEventsBeforeFirstTurn(void) { for (i = 0; i < gBattlersCount; i++) { + gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; // Included here because switches can happen before during set ups (eg. eject pack) struct Pokemon *party = GetBattlerParty(i); struct Pokemon *mon = &party[gBattlerPartyIndexes[i]]; if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG)) @@ -4846,7 +4847,6 @@ s8 GetBattleMovePriority(u32 battler, u16 move) return priority; } -// Function for AI with variables provided as arguments to speed the computation time s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2, u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2) { @@ -5106,6 +5106,9 @@ static void TurnValuesCleanUp(bool8 var0) gProtectStructs[i].spikyShielded = FALSE; gProtectStructs[i].kingsShielded = FALSE; gProtectStructs[i].banefulBunkered = FALSE; + gProtectStructs[i].obstructed = FALSE; + gProtectStructs[i].silkTrapped = FALSE; + gProtectStructs[i].burningBulwarked = FALSE; gProtectStructs[i].quash = FALSE; gProtectStructs[i].usedCustapBerry = FALSE; gProtectStructs[i].quickDraw = FALSE; @@ -5135,6 +5138,7 @@ static void TurnValuesCleanUp(bool8 var0) gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF; gBattleStruct->battlerState[i].usedEjectItem = FALSE; + gProtectStructs[i].lashOutAffected = FALSE; } gSideStatuses[B_SIDE_PLAYER] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4e090e3257..225646ee29 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -599,7 +599,7 @@ static void Cmd_trainerslideout(void); static void Cmd_settelekinesis(void); static void Cmd_swapstatstages(void); static void Cmd_averagestats(void); -static void Cmd_jumpifoppositegenders(void); +static void Cmd_jumpifcaptivateaffected(void); static void Cmd_unused(void); static void Cmd_tryworryseed(void); static void Cmd_callnative(void); @@ -836,8 +836,8 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_jumpifhasnohp, //0xE3 Cmd_jumpifnotcurrentmoveargtype, //0xE4 Cmd_pickup, //0xE5 - Cmd_unused_0xE6, //0xE6 - Cmd_unused_0xE7, //0xE7 + Cmd_unused_0xE6, //0xE6 + Cmd_unused_0xE7, //0xE7 Cmd_settypebasedhalvers, //0xE8 Cmd_jumpifsubstituteblocks, //0xE9 Cmd_tryrecycleitem, //0xEA @@ -858,7 +858,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_settelekinesis, //0xF9 Cmd_swapstatstages, //0xFA Cmd_averagestats, //0xFB - Cmd_jumpifoppositegenders, //0xFC + Cmd_jumpifcaptivateaffected, //0xFC Cmd_unused, //0xFD Cmd_tryworryseed, //0xFE Cmd_callnative, //0xFF @@ -1198,7 +1198,7 @@ static void Cmd_attackcanceler(void) if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBattlerTarget, 0, 0, 0)) return; - if (gMovesInfo[gCurrentMove].effect == EFFECT_PARALYZE && AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, gCurrentMove)) + if (GetMoveEffect(gCurrentMove) == EFFECT_PARALYZE && AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, gCurrentMove)) return; if (IsMovePowderBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) return; @@ -2423,7 +2423,7 @@ static void Cmd_attackanimation(void) } // handle special move animations - if (gMovesInfo[gCurrentMove].effect == EFFECT_EXPANDING_FORCE && moveTarget & MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, BATTLE_OPPOSITE(gBattlerAttacker) > 1)) + if (GetMoveEffect(gCurrentMove) == EFFECT_EXPANDING_FORCE && moveTarget & MOVE_TARGET_BOTH && CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, BATTLE_OPPOSITE(gBattlerAttacker) > 1)) gBattleScripting.animTurn = 1; if (!(moveResultFlags & MOVE_RESULT_NO_EFFECT)) @@ -6475,7 +6475,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - else if (gMovesInfo[gCurrentMove].effect == EFFECT_RECOIL_IF_MISS + else if (GetMoveEffect(gCurrentMove) == EFFECT_RECOIL_IF_MISS && (!IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !gBattleStruct->noTargetPresent && IsBattlerAlive(gBattlerAttacker)) @@ -6708,6 +6708,7 @@ static void Cmd_moveend(void) && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) + && !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER) && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) { u32 targetAbility = GetBattlerAbility(gBattlerTarget); @@ -6841,12 +6842,13 @@ static void Cmd_moveend(void) } } - if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) + // After swapattackerwithtarget is used for snatch the correct battlers have to be restored so data is stored correctly + if (gBattleStruct->snatchedMoveIsUsed) { - u8 temp; + u32 temp; SWAP(gBattlerAttacker, gBattlerTarget, temp); - gHitMarker &= ~HITMARKER_SWAP_ATTACKER_TARGET; } + if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) { gDisableStructs[gBattlerAttacker].usedMoves |= 1u << gCurrMovePos; @@ -7147,6 +7149,9 @@ static void Cmd_moveend(void) if (numEjectPackBattlers > 1) SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + gProtectStructs[i].statFell = FALSE; // restore for every possible eject pack battler + for (i = 0; i < gBattlersCount; i++) { u32 battler = battlers[i]; @@ -7165,7 +7170,6 @@ static void Cmd_moveend(void) BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_EjectPackActivates; AI_DATA->ejectPackSwitch = TRUE; - gProtectStructs[battler].statFell = FALSE; break; // Only the fastest Eject item activates } } @@ -8175,6 +8179,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; gSpecialStatuses[battler].announceNeutralizingGas = TRUE; + gDisableStructs[battler].neutralizingGas = TRUE; gBattlerAbility = battler; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_SwitchInAbilityMsgRet; @@ -8826,14 +8831,8 @@ static void Cmd_swapattackerwithtarget(void) { CMD_ARGS(); - u8 temp; + u32 temp; SWAP(gBattlerAttacker, gBattlerTarget, temp); - - if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) - gHitMarker &= ~HITMARKER_SWAP_ATTACKER_TARGET; - else - gHitMarker |= HITMARKER_SWAP_ATTACKER_TARGET; - gBattlescriptCurrInstr = cmd->nextInstr; } @@ -12592,7 +12591,8 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr } else { - gProtectStructs[battler].statFell = TRUE; // Eject pack, lash out + gProtectStructs[battler].statFell = TRUE; + gProtectStructs[battler].lashOutAffected = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL } } @@ -16669,14 +16669,24 @@ static void Cmd_averagestats(void) gBattlescriptCurrInstr = cmd->nextInstr; } -static void Cmd_jumpifoppositegenders(void) +static void Cmd_jumpifcaptivateaffected(void) { CMD_ARGS(const u8 *jumpInstr); - if (AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + if (GetBattlerAbility(gBattlerTarget) == ABILITY_OBLIVIOUS) + { + gBattlescriptCurrInstr = BattleScript_NotAffectedAbilityPopUp; + gLastUsedAbility = ABILITY_OBLIVIOUS; + RecordAbilityBattle(gBattlerTarget, ABILITY_OBLIVIOUS); + } + else if (AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget)) + { gBattlescriptCurrInstr = cmd->jumpInstr; + } else + { gBattlescriptCurrInstr = cmd->nextInstr; + } } static void Cmd_unused(void) @@ -18805,3 +18815,87 @@ void BS_SetSteelsurge(void) gBattlescriptCurrInstr = cmd->nextInstr; } } + +void BS_JumpIfIntimidateAbilityPrevented(void) +{ + NATIVE_ARGS(); + + u32 hasAbility = FALSE; + u32 ability = GetBattlerAbility(gBattlerTarget); + + switch (ability) + { + case ABILITY_INNER_FOCUS: + case ABILITY_SCRAPPY: + case ABILITY_OWN_TEMPO: + case ABILITY_OBLIVIOUS: + if (B_UPDATED_INTIMIDATE >= GEN_8) + { + hasAbility = TRUE; + gBattlescriptCurrInstr = BattleScript_IntimidatePrevented; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr; + } + break; + case ABILITY_GUARD_DOG: + hasAbility = TRUE; + gBattlescriptCurrInstr = BattleScript_IntimidateInReverse; + break; + default: + gBattlescriptCurrInstr = cmd->nextInstr; + break; + } + + if (hasAbility) + { + gLastUsedAbility = ability; + gBattlerAbility = gBattlerTarget; + RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); + } +} + +void BS_TryIntimidatEjectpack(void) +{ + NATIVE_ARGS(); + + u32 affectedBattler = 0xFF; + u32 battler = BATTLE_OPPOSITE(gBattlerAttacker); + u32 partnerBattler = BATTLE_PARTNER(battler); + + bool32 ejectPackBattler = CanEjectPackTrigger(gBattlerAttacker, battler, MOVE_NONE); + bool32 ejectPackPartnerBattler = CanEjectPackTrigger(gBattlerAttacker, partnerBattler, MOVE_NONE); + + if (ejectPackBattler && ejectPackPartnerBattler) + { + u32 battlerSpeed = GetBattlerTotalSpeedStat(battler); + u32 partnerbattlerSpeed = GetBattlerTotalSpeedStat(partnerBattler); + + if (battlerSpeed >= partnerbattlerSpeed) + affectedBattler = battler; + else + affectedBattler = partnerBattler; + } + else if (ejectPackBattler) + { + affectedBattler = battler; + } + else if (ejectPackPartnerBattler) + { + affectedBattler = partnerBattler; + } + + gBattlescriptCurrInstr = cmd->nextInstr; + if (affectedBattler != 0xFF) + { + gProtectStructs[battler].statFell = FALSE; + gProtectStructs[partnerBattler].statFell = FALSE; + AI_DATA->ejectPackSwitch = TRUE; + gBattleScripting.battler = affectedBattler; + gLastUsedItem = gBattleMons[affectedBattler].item; + RecordItemEffectBattle(affectedBattler, HOLD_EFFECT_EJECT_PACK); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret; + } +} diff --git a/src/battle_util.c b/src/battle_util.c index d38135dbb2..d9e64c969c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -787,7 +787,7 @@ void HandleAction_NothingIsFainted(void) gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber]; gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE - | HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT + | HITMARKER_OBEYS | HITMARKER_SYNCHRONISE_EFFECT | HITMARKER_CHARGING | HITMARKER_NEVER_SET); } @@ -801,7 +801,7 @@ void HandleAction_ActionFinished(void) SpecialStatusesClear(); gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_STATUS_ABILITY_EFFECT | HITMARKER_PASSIVE_DAMAGE - | HITMARKER_OBEYS | HITMARKER_WAKE_UP_CLEAR | HITMARKER_SYNCHRONISE_EFFECT + | HITMARKER_OBEYS | HITMARKER_SYNCHRONISE_EFFECT | HITMARKER_CHARGING | HITMARKER_NEVER_SET | HITMARKER_IGNORE_DISGUISE); // check if Stellar type boost should be used up @@ -3309,7 +3309,6 @@ static void CancellerObedience(u32 *effect) SetAtkCancellerForCalledMove(); gBattlescriptCurrInstr = BattleScript_IgnoresAndUsesRandomMove; gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE); - gHitMarker |= HITMARKER_DISOBEDIENT_MOVE; gHitMarker |= HITMARKER_OBEYS; break; } @@ -5363,6 +5362,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_COMMANDER: partner = BATTLE_PARTNER(battler); if (!gSpecialStatuses[battler].switchInAbilityDone + && IsBattlerAlive(partner) + && IsBattlerAlive(battler) && gBattleStruct->commanderActive[partner] == SPECIES_NONE && gBattleMons[partner].species == SPECIES_DONDOZO && GET_BASE_SPECIES_ID(GetMonData(GetPartyBattlerData(battler), MON_DATA_SPECIES)) == SPECIES_TATSUGIRI) @@ -7233,6 +7234,9 @@ static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemCaseId caseID, bool32 pe static bool32 UnnerveOn(u32 battler, u32 itemId) { + if (gBattleScripting.overrideBerryRequirements > 0) // Berries that aren't eaten naturally ignore unnerve + return FALSE; + if (ItemId_GetPocket(itemId) == POCKET_BERRIES && IsUnnerveAbilityOnOpposingSide(battler)) return TRUE; return FALSE; @@ -8448,9 +8452,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; } break; - case HOLD_EFFECT_EJECT_PACK: - effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN); - break; } break; } @@ -9228,7 +9229,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower *= 2; break; case EFFECT_LASH_OUT: - if (gProtectStructs[battlerAtk].statFell) + if (gProtectStructs[battlerAtk].lashOutAffected) basePower *= 2; break; case EFFECT_EXPLOSION: diff --git a/test/battle/ability/color_change.c b/test/battle/ability/color_change.c index cc0a3e2472..42932a7d58 100644 --- a/test/battle/ability/color_change.c +++ b/test/battle/ability/color_change.c @@ -5,7 +5,7 @@ SINGLE_BATTLE_TEST("Color Change changes the type of a Pokemon being hit by a mo { GIVEN { ASSUME(gSpeciesInfo[SPECIES_KECLEON].types[0] != TYPE_PSYCHIC && gSpeciesInfo[SPECIES_KECLEON].types[1] != TYPE_PSYCHIC); - ASSUME(gMovesInfo[MOVE_PSYWAVE].type == TYPE_PSYCHIC); + ASSUME(GetMoveType(MOVE_PSYWAVE) == TYPE_PSYCHIC); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_COLOR_CHANGE); } } WHEN { @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Color Change does not change the type when hit by a move tha { GIVEN { ASSUME(gSpeciesInfo[SPECIES_KECLEON].types[0] == TYPE_NORMAL || gSpeciesInfo[SPECIES_KECLEON].types[1] == TYPE_NORMAL); - ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(GetMoveType(MOVE_TACKLE) == TYPE_NORMAL); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_KECLEON) { Ability(ABILITY_COLOR_CHANGE); } } WHEN { diff --git a/test/battle/ability/commander.c b/test/battle/ability/commander.c index d4b31f23b8..a50eba7b8c 100644 --- a/test/battle/ability/commander.c +++ b/test/battle/ability/commander.c @@ -421,3 +421,37 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri does not get hit by Dragon Darts when co NOT HP_BAR(playerLeft); } } + +DOUBLE_BATTLE_TEST("Commander will not activate if Dondozo fainted right before Tatsugiri came in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_DONDOZO) { HP(1); } + PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_TACKLE, target: playerRight); MOVE(playerLeft, MOVE_SHED_TAIL); SEND_OUT(playerLeft, 2); SEND_OUT(playerRight, 3); } + } SCENE { + NOT ABILITY_POPUP(playerLeft, ABILITY_COMMANDER); + } +} + +DOUBLE_BATTLE_TEST("Commander prevent Dondozo from switch out by Dragon Tail") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_DRAGON_TAIL) == EFFECT_HIT_SWITCH_TARGET); + PLAYER(SPECIES_DONDOZO); + PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_DRAGON_TAIL, target: playerLeft); } + } SCENE { + ABILITY_POPUP(playerRight, ABILITY_COMMANDER); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, opponentLeft); + NOT MESSAGE("Wobbuffet was dragged out!"); + } +} diff --git a/test/battle/ability/intimidate.c b/test/battle/ability/intimidate.c index 61b53f42e1..e5571b23fc 100644 --- a/test/battle/ability/intimidate.c +++ b/test/battle/ability/intimidate.c @@ -104,7 +104,7 @@ DOUBLE_BATTLE_TEST("Intimidate doesn't activate on an empty field in a double ba } } -SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack") +SINGLE_BATTLE_TEST("Intimidate and Eject Button don't force the opponent to Attack") { GIVEN { ASSUME(gItemsInfo[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON); @@ -365,6 +365,7 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second } SCENE { ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS); @@ -372,14 +373,13 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); } - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); } } SINGLE_BATTLE_TEST("Intimdate does not lose timing after mega evolution and switch out by a hit escape move") { GIVEN { - ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); + ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_MANECTRIC) { Item(ITEM_MANECTITE); } OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); } @@ -390,3 +390,48 @@ SINGLE_BATTLE_TEST("Intimdate does not lose timing after mega evolution and swit ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); } } + +DOUBLE_BATTLE_TEST("Intimidate drop down both opposing atk before eject pack has the chance to activate") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Intimidate will not miss timing for competitive") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_MILOTIC) { Ability(ABILITY_COMPETITIVE); } + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } +} diff --git a/test/battle/ability/neutralizing_gas.c b/test/battle/ability/neutralizing_gas.c index ef83483d32..ae11c458f7 100644 --- a/test/battle/ability/neutralizing_gas.c +++ b/test/battle/ability/neutralizing_gas.c @@ -51,7 +51,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas prevents ally's switch-in ability from acti DOUBLE_BATTLE_TEST("Neutralizing Gas ignores all battlers' ability effects") { GIVEN { - ASSUME(gMovesInfo[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY); PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_WATER_ABSORB); } @@ -87,7 +87,7 @@ SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from attacker's ability PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WEEZING) { Ability(ability); } OPPONENT(SPECIES_AZUMARILL) { Ability(ABILITY_HUGE_POWER); } } WHEN { @@ -106,8 +106,8 @@ SINGLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from target's ability", PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].makesContact == TRUE); - ASSUME(gMovesInfo[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(MoveMakesContact(MOVE_TACKLE) == TRUE); + ASSUME(GetMoveType(MOVE_TACKLE) == TYPE_NORMAL); PLAYER(SPECIES_WEEZING) { Ability(ability); } OPPONENT(SPECIES_BEWEAR) { Ability(ABILITY_FLUFFY); } } WHEN { @@ -146,7 +146,7 @@ DOUBLE_BATTLE_TEST("Neutralizing Gas ignores multipliers from ally's ability", s PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } PARAMETRIZE { ability = ABILITY_LEVITATE; } GIVEN { - ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WEEZING) { Ability(ability); } PLAYER(SPECIES_WO_CHIEN) { Ability(ABILITY_TABLETS_OF_RUIN); } OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } diff --git a/test/battle/ability/oblivious.c b/test/battle/ability/oblivious.c index 3ac979a271..a787ec6578 100644 --- a/test/battle/ability/oblivious.c +++ b/test/battle/ability/oblivious.c @@ -23,7 +23,7 @@ SINGLE_BATTLE_TEST("Oblivious prevents Captivate") PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OBLIVIOUS); Gender(MON_MALE); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); } } WHEN { - TURN { MOVE(opponent, MOVE_ATTRACT); } + TURN { MOVE(opponent, MOVE_CAPTIVATE); } } SCENE { ABILITY_POPUP(player, ABILITY_OBLIVIOUS); NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } diff --git a/test/battle/ability/teraform_zero.c b/test/battle/ability/teraform_zero.c index 09ce921931..96186f2047 100644 --- a/test/battle/ability/teraform_zero.c +++ b/test/battle/ability/teraform_zero.c @@ -84,7 +84,6 @@ SINGLE_BATTLE_TEST("Teraform Zero cannot be copied") DOUBLE_BATTLE_TEST("Teraform Zero shouldn't cause Neutralizing Gas to show it's popup when trying to activate") { - KNOWN_FAILING; // #5010 GIVEN { PLAYER(SPECIES_TERAPAGOS_TERASTAL); PLAYER(SPECIES_ABSOL) {Ability(ABILITY_PRESSURE); } @@ -95,8 +94,8 @@ DOUBLE_BATTLE_TEST("Teraform Zero shouldn't cause Neutralizing Gas to show it's TURN { SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_TERA); } } SCENE { MESSAGE("Terapagos is storing energy!"); - MESSAGE("Terapagos terastalized into the Stellar type!"); + MESSAGE("Terapagos terastallized into the Stellar type!"); NOT ABILITY_POPUP(playerRight, ABILITY_NEUTRALIZING_GAS); - MESSAGE("Terapagos used Celebreate!"); + MESSAGE("Terapagos used Celebrate!"); } } diff --git a/test/battle/ability/thermal_exchange.c b/test/battle/ability/thermal_exchange.c index 57f4256d7a..7484fa207c 100644 --- a/test/battle/ability/thermal_exchange.c +++ b/test/battle/ability/thermal_exchange.c @@ -4,7 +4,7 @@ SINGLE_BATTLE_TEST("Thermal Exchange makes Will-O-Wisp fail") { GIVEN { - ASSUME(gMovesInfo[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); + ASSUME(GetMoveEffect(MOVE_WILL_O_WISP) == EFFECT_WILL_O_WISP); PLAYER(SPECIES_BAXCALIBUR) { Ability(ABILITY_THERMAL_EXCHANGE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -37,8 +37,8 @@ SINGLE_BATTLE_TEST("Thermal Exchange prevents the user from getting burned when SINGLE_BATTLE_TEST("Thermal Exchange cures burns when acquired") { GIVEN { - ASSUME(gMovesInfo[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); - ASSUME(gMovesInfo[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP); + ASSUME(GetMoveEffect(MOVE_WILL_O_WISP) == EFFECT_WILL_O_WISP); + ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP); PLAYER(SPECIES_BAXCALIBUR) { Ability(ABILITY_THERMAL_EXCHANGE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Thermal Exchange cures burns when acquired") SINGLE_BATTLE_TEST("Thermal Exchange burn prevention can be bypassed with Mold Breaker but is cured after") { GIVEN { - ASSUME(gMovesInfo[MOVE_WILL_O_WISP].effect == EFFECT_WILL_O_WISP); + ASSUME(GetMoveEffect(MOVE_WILL_O_WISP) == EFFECT_WILL_O_WISP); PLAYER(SPECIES_BAXCALIBUR) { Ability(ABILITY_THERMAL_EXCHANGE); } OPPONENT(SPECIES_RAMPARDOS) { Ability(ABILITY_MOLD_BREAKER); } } WHEN { @@ -73,7 +73,7 @@ SINGLE_BATTLE_TEST("Thermal Exchange burn prevention can be bypassed with Mold B SINGLE_BATTLE_TEST("Thermal Exchange boosts attack if hit by a damaging fire type move") { GIVEN { - ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE); + ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE); PLAYER(SPECIES_BAXCALIBUR) { Ability(ABILITY_THERMAL_EXCHANGE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index d11f146fc1..6f56e608b3 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -835,8 +835,8 @@ AI_SINGLE_BATTLE_TEST("AI stays choice locked into moves in spite of the player' AI_SINGLE_BATTLE_TEST("AI won't use Sucker Punch if it expects a move of the same priority bracket and the opponent is faster") { GIVEN { - ASSUME(gMovesInfo[MOVE_QUICK_ATTACK].priority == 1); - ASSUME(gMovesInfo[MOVE_SUCKER_PUNCH].priority == 1); + ASSUME(GetMovePriority(MOVE_QUICK_ATTACK) == 1); + ASSUME(GetMovePriority(MOVE_SUCKER_PUNCH) == 1); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_WOBBUFFET) { Speed(300); Moves(MOVE_QUICK_ATTACK); } OPPONENT(SPECIES_WOBBUFFET) { Speed(100); Moves(MOVE_SUCKER_PUNCH, MOVE_TACKLE); } diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index da053ec5e6..0a21362a99 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -160,3 +160,74 @@ SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Eject Butt EXPECT(opponent->species == SPECIES_WYNAUT); } } + +DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after intimidate") +{ + u32 speed; + + PARAMETRIZE { speed = 1; } + PARAMETRIZE { speed = 11; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WYNAUT) { Speed(4); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_EKANS) { Speed(6); Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { + SWITCH(opponentLeft, 2); + if (speed == 11) + SEND_OUT(playerRight, 2); + else + SEND_OUT(playerLeft, 2); + } + } SCENE { + ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + if (speed == 11) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + } else { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + } + } +} + +DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after a move stat drop") +{ + u32 speed; + + PARAMETRIZE { speed = 1; } + PARAMETRIZE { speed = 11; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WYNAUT) { Speed(4); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_BUBBLE); + if (speed == 11) + SEND_OUT(playerRight, 2); + else + SEND_OUT(playerLeft, 2); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BUBBLE, opponentLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + if (speed == 11) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + } else { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + } + } +} diff --git a/test/battle/hold_effect/shell_bell.c b/test/battle/hold_effect/shell_bell.c index f669c55081..8e91011865 100644 --- a/test/battle/hold_effect/shell_bell.c +++ b/test/battle/hold_effect/shell_bell.c @@ -208,7 +208,7 @@ DOUBLE_BATTLE_TEST("Shell Bell heals accumulated damage for spread moves") const u16 maxHp = 200; const u16 initHp = 1; GIVEN { - ASSUME(gMovesInfo[MOVE_DISCHARGE].target == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY); PLAYER(SPECIES_ARIADOS) { MaxHP(maxHp); HP(initHp); Item(ITEM_SHELL_BELL); } PLAYER(SPECIES_WOBBUFFET) {} OPPONENT(SPECIES_GYARADOS) {} diff --git a/test/battle/move_effect/dream_eater.c b/test/battle/move_effect/dream_eater.c index 67b2ed5af5..caa365a17a 100644 --- a/test/battle/move_effect/dream_eater.c +++ b/test/battle/move_effect/dream_eater.c @@ -77,9 +77,9 @@ SINGLE_BATTLE_TEST("Dream Eater works on targets with Comatose") SINGLE_BATTLE_TEST("Dream Eater fails if the target is behind a Substitute (Gen 1-4)") { GIVEN { - ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); - ASSUME(gMovesInfo[MOVE_SUBSTITUTE].effect == EFFECT_SUBSTITUTE); - ASSUME(!gMovesInfo[MOVE_DREAM_EATER].ignoresSubstitute); + ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN); + ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE); + ASSUME(!MoveIgnoresSubstitute(MOVE_DREAM_EATER)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -97,8 +97,8 @@ SINGLE_BATTLE_TEST("Dream Eater works if the target is behind a Substitute (Gen s16 damage; s16 healed; GIVEN { - ASSUME(gMovesInfo[MOVE_YAWN].effect == EFFECT_YAWN); - ASSUME(gMovesInfo[MOVE_SUBSTITUTE].effect == EFFECT_SUBSTITUTE); + ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN); + ASSUME(GetMoveEffect(MOVE_SUBSTITUTE) == EFFECT_SUBSTITUTE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { HP(1); } } WHEN { diff --git a/test/battle/move_effect/follow_me.c b/test/battle/move_effect/follow_me.c index fe7b96207d..f24629f141 100644 --- a/test/battle/move_effect/follow_me.c +++ b/test/battle/move_effect/follow_me.c @@ -3,8 +3,8 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_FOLLOW_ME].effect == EFFECT_FOLLOW_ME); - ASSUME(gMovesInfo[MOVE_SPOTLIGHT].effect == EFFECT_FOLLOW_ME); + ASSUME(GetMoveEffect(MOVE_FOLLOW_ME) == EFFECT_FOLLOW_ME); + ASSUME(GetMoveEffect(MOVE_SPOTLIGHT) == EFFECT_FOLLOW_ME); } DOUBLE_BATTLE_TEST("Follow Me redirects single target moves used by opponents to user") diff --git a/test/battle/move_effect/instruct.c b/test/battle/move_effect/instruct.c index 85f56d4c4b..e61540b9c5 100644 --- a/test/battle/move_effect/instruct.c +++ b/test/battle/move_effect/instruct.c @@ -249,8 +249,8 @@ DOUBLE_BATTLE_TEST("Instructed move will be redirected by Follow Me after instru PARAMETRIZE { moveTarget = opponentLeft; } PARAMETRIZE { moveTarget = opponentRight; } GIVEN { - ASSUME(gMovesInfo[MOVE_FOLLOW_ME].effect == EFFECT_FOLLOW_ME); - ASSUME(gMovesInfo[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP); + ASSUME(GetMoveEffect(MOVE_FOLLOW_ME) == EFFECT_FOLLOW_ME); + ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP); PLAYER(SPECIES_DURALUDON) { Ability(ABILITY_STALWART); } PLAYER(SPECIES_DURALUDON) { Ability(ABILITY_STALWART); } OPPONENT(SPECIES_WOBBUFFET); @@ -279,9 +279,9 @@ DOUBLE_BATTLE_TEST("Instructed move will be redirected by Rage Powder after inst PARAMETRIZE { moveTarget = opponentLeft; } PARAMETRIZE { moveTarget = opponentRight; } GIVEN { - ASSUME(gMovesInfo[MOVE_RAGE_POWDER].effect == EFFECT_FOLLOW_ME); - ASSUME(gMovesInfo[MOVE_RAGE_POWDER].powderMove == TRUE); - ASSUME(gMovesInfo[MOVE_SOAK].effect == EFFECT_SOAK); + ASSUME(GetMoveEffect(MOVE_RAGE_POWDER) == EFFECT_FOLLOW_ME); + ASSUME(IsPowderMove(MOVE_RAGE_POWDER) == TRUE); + ASSUME(GetMoveEffect(MOVE_SOAK) == EFFECT_SOAK); PLAYER(SPECIES_TREECKO); PLAYER(SPECIES_SCEPTILE); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/laser_focus.c b/test/battle/move_effect/laser_focus.c index c486a3cbee..17922d3231 100644 --- a/test/battle/move_effect/laser_focus.c +++ b/test/battle/move_effect/laser_focus.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_LASER_FOCUS].effect == EFFECT_LASER_FOCUS); + ASSUME(GetMoveEffect(MOVE_LASER_FOCUS) == EFFECT_LASER_FOCUS); } SINGLE_BATTLE_TEST("Laser Focus causes the user's move used on the next turn to result in a Critical Hit") diff --git a/test/battle/move_effect/recoil_if_miss.c b/test/battle/move_effect/recoil_if_miss.c index 0b65eb8541..a5dbfef178 100644 --- a/test/battle/move_effect/recoil_if_miss.c +++ b/test/battle/move_effect/recoil_if_miss.c @@ -102,7 +102,7 @@ SINGLE_BATTLE_TEST("Recoil if miss: Jump Kick's recoil happens after Spiky Shiel SINGLE_BATTLE_TEST("Recoil if miss: Jump Kick recoil happens after Spiky Shield damage") { GIVEN { - ASSUME(!gMovesInfo[MOVE_JUMP_KICK].ignoresProtect); + ASSUME(!MoveIgnoresProtect(MOVE_JUMP_KICK)); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/rototiller.c b/test/battle/move_effect/rototiller.c index 32ae7da75f..34b62a2666 100644 --- a/test/battle/move_effect/rototiller.c +++ b/test/battle/move_effect/rototiller.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_ROTOTILLER].effect == EFFECT_ROTOTILLER); + ASSUME(GetMoveEffect(MOVE_ROTOTILLER) == EFFECT_ROTOTILLER); } DOUBLE_BATTLE_TEST("Rototiller boosts Attack and Special Attack of all Grass types on the field") @@ -55,7 +55,7 @@ SINGLE_BATTLE_TEST("Rototiller doesn't affect pokemon that are semi-invulnerable { GIVEN { ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); - ASSUME(gMovesInfo[MOVE_DIG].effect == EFFECT_SEMI_INVULNERABLE); + ASSUME(GetMoveEffect(MOVE_DIG) == EFFECT_SEMI_INVULNERABLE); PLAYER(SPECIES_TANGELA); OPPONENT(SPECIES_TANGELA); } WHEN { @@ -79,7 +79,7 @@ SINGLE_BATTLE_TEST("Rototiller fails if the only valid target is semi-invulnerab ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_GRASS); ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_GRASS); - ASSUME(gMovesInfo[MOVE_DIG].effect == EFFECT_SEMI_INVULNERABLE); + ASSUME(GetMoveEffect(MOVE_DIG) == EFFECT_SEMI_INVULNERABLE); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_TANGELA); } WHEN { diff --git a/test/battle/move_effect/sleep_talk.c b/test/battle/move_effect/sleep_talk.c index b00f89e582..fd246f47aa 100644 --- a/test/battle/move_effect/sleep_talk.c +++ b/test/battle/move_effect/sleep_talk.c @@ -94,8 +94,8 @@ SINGLE_BATTLE_TEST("Sleep Talk can use moves while choiced into Sleep Talk") SINGLE_BATTLE_TEST("Sleep Talk fails if user is taunted") { GIVEN { - ASSUME(gMovesInfo[MOVE_TAUNT].effect == EFFECT_TAUNT); - ASSUME(gMovesInfo[MOVE_SLEEP_TALK].category == DAMAGE_CATEGORY_STATUS); + ASSUME(GetMoveEffect(MOVE_TAUNT) == EFFECT_TAUNT); + ASSUME(GetMoveCategory(MOVE_SLEEP_TALK) == DAMAGE_CATEGORY_STATUS); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_TACKLE, MOVE_FLY, MOVE_DIG); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -113,7 +113,7 @@ DOUBLE_BATTLE_TEST("Sleep Talk calls move and that move may be redirected by Lig { PASSES_RANDOMLY(1, 2, RNG_RANDOM_TARGET); GIVEN { - ASSUME(gMovesInfo[MOVE_SPARK].type == TYPE_ELECTRIC); + ASSUME(GetMoveType(MOVE_SPARK) == TYPE_ELECTRIC); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_SPARK, MOVE_FLY, MOVE_DIG); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -132,7 +132,7 @@ DOUBLE_BATTLE_TEST("Sleep Talk calls move and that move may be redirected by Sto { PASSES_RANDOMLY(1, 2, RNG_RANDOM_TARGET); GIVEN { - ASSUME(gMovesInfo[MOVE_WATER_GUN].type == TYPE_WATER); + ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); Moves(MOVE_SLEEP_TALK, MOVE_WATER_GUN, MOVE_FLY, MOVE_DIG); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/snore.c b/test/battle/move_effect/snore.c index d83e35b16c..410406a65b 100644 --- a/test/battle/move_effect/snore.c +++ b/test/battle/move_effect/snore.c @@ -3,7 +3,7 @@ ASSUMPTIONS { - ASSUME(gMovesInfo[MOVE_SNORE].effect == EFFECT_SNORE); + ASSUME(GetMoveEffect(MOVE_SNORE) == EFFECT_SNORE); } SINGLE_BATTLE_TEST("Snore fails if not asleep") @@ -47,7 +47,7 @@ SINGLE_BATTLE_TEST("Snore fails if user is throat chopped") { GIVEN { ASSUME(MoveHasAdditionalEffect(MOVE_THROAT_CHOP, MOVE_EFFECT_THROAT_CHOP)); - ASSUME(gMovesInfo[MOVE_SNORE].soundMove == TRUE); + ASSUME(IsSoundMove(MOVE_SNORE) == TRUE); PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect/spectral_thief.c b/test/battle/move_effect/spectral_thief.c index 7bb5d5a536..885df9f5e3 100644 --- a/test/battle/move_effect/spectral_thief.c +++ b/test/battle/move_effect/spectral_thief.c @@ -8,8 +8,8 @@ SINGLE_BATTLE_TEST("Spectral Thief steals opponents boost before attacking", s16 PARAMETRIZE { move = MOVE_SWORDS_DANCE; } GIVEN { - ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); - ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + ASSUME(GetMoveEffect(MOVE_SPECTRAL_THIEF) == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_REGIROCK); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -32,8 +32,8 @@ SINGLE_BATTLE_TEST("Spectral Thief steals opponents boost before attacking", s16 SINGLE_BATTLE_TEST("Spectral Thief can't steal opponent's boost if target is immune") { GIVEN { - ASSUME(gMovesInfo[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); - ASSUME(gMovesInfo[MOVE_SPECTRAL_THIEF].effect == EFFECT_SPECTRAL_THIEF); + ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2); + ASSUME(GetMoveEffect(MOVE_SPECTRAL_THIEF) == EFFECT_SPECTRAL_THIEF); PLAYER(SPECIES_MEOWTH); OPPONENT(SPECIES_WOBBUFFET); } WHEN { diff --git a/test/battle/move_effect_secondary/bug_bite.c b/test/battle/move_effect_secondary/bug_bite.c index e086941a5e..70e0966caa 100644 --- a/test/battle/move_effect_secondary/bug_bite.c +++ b/test/battle/move_effect_secondary/bug_bite.c @@ -133,3 +133,18 @@ SINGLE_BATTLE_TEST("Tanga Berry activates before Bug Bite") EXPECT_EQ(player->item, ITEM_NONE); } } + +SINGLE_BATTLE_TEST("Bug Bite ignores Unnerve") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_TYRANITAR) { Ability(ABILITY_UNNERVE); Item(ITEM_ORAN_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_BUG_BITE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BUG_BITE, player); + HP_BAR(player); + } THEN { + EXPECT_EQ(opponent->item, ITEM_NONE); + } +} diff --git a/test/battle/move_effect_secondary/haze.c b/test/battle/move_effect_secondary/haze.c index c3831f0768..c6a0f2cab1 100644 --- a/test/battle/move_effect_secondary/haze.c +++ b/test/battle/move_effect_secondary/haze.c @@ -16,7 +16,10 @@ SINGLE_BATTLE_TEST("Freeze Frost restores stat changes when it was succesful") PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_FREEZY_FROST, hit: moveSuccess); } + TURN { + MOVE(opponent, MOVE_SAND_ATTACK); + MOVE(player, MOVE_FREEZY_FROST, hit: moveSuccess); + } } SCENE { if (moveSuccess == TRUE) { diff --git a/test/battle/move_effect_secondary/leech_seed.c b/test/battle/move_effect_secondary/leech_seed.c index c5a8db57cc..b7eef45ed4 100644 --- a/test/battle/move_effect_secondary/leech_seed.c +++ b/test/battle/move_effect_secondary/leech_seed.c @@ -26,7 +26,10 @@ SINGLE_BATTLE_TEST("Sappy Seed is not going to seed the target if it fails") PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_SAPPY_SEED, hit: FALSE); } + TURN { + MOVE(opponent, MOVE_SAND_ATTACK); + MOVE(player, MOVE_SAPPY_SEED, hit: FALSE); + } } SCENE { NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_SAPPY_SEED, player); diff --git a/test/battle/move_effect_secondary/light_screen.c b/test/battle/move_effect_secondary/light_screen.c index 244e469893..e834e6055f 100644 --- a/test/battle/move_effect_secondary/light_screen.c +++ b/test/battle/move_effect_secondary/light_screen.c @@ -16,7 +16,10 @@ SINGLE_BATTLE_TEST("Glitzy Glow sets up Light Screen when it was succesful") PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_GLITZY_GLOW, hit: moveSuccess); } + TURN { + MOVE(opponent, MOVE_SAND_ATTACK); + MOVE(player, MOVE_GLITZY_GLOW, hit: moveSuccess); + } } SCENE { if (moveSuccess == TRUE) { diff --git a/test/battle/move_effect_secondary/reflect.c b/test/battle/move_effect_secondary/reflect.c index 6a0dda06d8..0b1dbf7fd3 100644 --- a/test/battle/move_effect_secondary/reflect.c +++ b/test/battle/move_effect_secondary/reflect.c @@ -16,7 +16,10 @@ SINGLE_BATTLE_TEST("Baddy Bad sets up Reflect when it was succesful") PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_BADDY_BAD, hit: moveSuccess); } + TURN { + MOVE(opponent, MOVE_SAND_ATTACK); + MOVE(player, MOVE_BADDY_BAD, hit: moveSuccess); + } } SCENE { if (moveSuccess == TRUE) { diff --git a/test/battle/move_flags/recoil.c b/test/battle/move_flags/recoil.c index 5a8f3be576..0293a07a80 100644 --- a/test/battle/move_flags/recoil.c +++ b/test/battle/move_flags/recoil.c @@ -87,7 +87,7 @@ SINGLE_BATTLE_TEST("Flare Blitz deals 33% of recoil damage to the user and can b SINGLE_BATTLE_TEST("Flare Blitz is absorbed by Flash Fire and no recoil damage is dealt") { GIVEN { - ASSUME(gMovesInfo[MOVE_FLARE_BLITZ].recoil > 0); + ASSUME(GetMoveRecoil(MOVE_FLARE_BLITZ) > 0); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_VULPIX) { Ability(ABILITY_FLASH_FIRE); }; } WHEN { diff --git a/test/battle/status1/freeze.c b/test/battle/status1/freeze.c index f363ab9e35..12104438ac 100644 --- a/test/battle/status1/freeze.c +++ b/test/battle/status1/freeze.c @@ -61,3 +61,20 @@ SINGLE_BATTLE_TEST("Freeze isn't thawed if opponent is asleep during thawing att } } } + +SINGLE_BATTLE_TEST("Freeze isn't thawed if opponent is asleep during thawing attack when using Scald") +{ + PASSES_RANDOMLY(80, 100, RNG_FROZEN); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCALD); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent); + MESSAGE("Wobbuffet thawed out!"); + STATUS_ICON(player, none: TRUE); + } + } +} diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 399cb8a852..806dcf1956 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -2034,16 +2034,16 @@ s32 MoveGetTarget(s32 battlerId, u32 moveId, struct MoveContext *ctx, u32 source } else { - const struct MoveInfo *move = &gMovesInfo[moveId]; - if (move->target == MOVE_TARGET_RANDOM - || move->target == MOVE_TARGET_BOTH - || move->target == MOVE_TARGET_DEPENDS - || move->target == MOVE_TARGET_FOES_AND_ALLY - || move->target == MOVE_TARGET_OPPONENTS_FIELD) + u32 moveTarget = GetMoveTarget(moveId); + if (moveTarget == MOVE_TARGET_RANDOM + || moveTarget == MOVE_TARGET_BOTH + || moveTarget == MOVE_TARGET_DEPENDS + || moveTarget == MOVE_TARGET_FOES_AND_ALLY + || moveTarget == MOVE_TARGET_OPPONENTS_FIELD) { target = BATTLE_OPPOSITE(battlerId); } - else if (move->target == MOVE_TARGET_SELECTED || move->target == MOVE_TARGET_OPPONENT) + else if (moveTarget == MOVE_TARGET_SELECTED || moveTarget == MOVE_TARGET_OPPONENT) { // In AI Doubles not specified target allows any target for EXPECT_MOVE. if (GetBattleTest()->type != BATTLE_TEST_AI_DOUBLES) @@ -2053,11 +2053,11 @@ s32 MoveGetTarget(s32 battlerId, u32 moveId, struct MoveContext *ctx, u32 source target = BATTLE_OPPOSITE(battlerId); } - else if (move->target == MOVE_TARGET_USER || move->target == MOVE_TARGET_ALL_BATTLERS) + else if (moveTarget == MOVE_TARGET_USER || moveTarget == MOVE_TARGET_ALL_BATTLERS) { target = battlerId; } - else if (move->target == MOVE_TARGET_ALLY) + else if (moveTarget == MOVE_TARGET_ALLY) { target = BATTLE_PARTNER(battlerId); }