diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index afbd257d21..798c8d1bd4 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1046,7 +1046,7 @@ .byte 0xc3 .endm - .macro trydobeatup endInstr, failInstr + .macro trydobeatup endInstr:req, failInstr:req .byte 0xc4 .4byte \endInstr .4byte \failInstr diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 645481bedd..c9ccb48d0c 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1475,7 +1475,7 @@ BattleScript_MoveEffectFlameBurst:: healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING tryfaintmon BS_SCRIPTING - goto BattleScript_MoveEnd + return BattleScript_EffectPowerTrick:: attackcanceler @@ -1555,7 +1555,7 @@ BattleScript_DefogDoAnim:: BattleScript_DefogPrintString:: printfromtable gStatDownStringIds waitmessage B_WAIT_TIME_LONG -BattleScript_DefogTryHazards:: +BattleScript_DefogTryHazards: copybyte gEffectBattler, gBattlerAttacker trydefog TRUE, NULL copybyte gBattlerAttacker, gEffectBattler @@ -1565,6 +1565,12 @@ BattleScript_DefogTryHazardsWithAnim: waitanimation goto BattleScript_DefogTryHazards +BattleScript_MoveEffectDefog:: + saveattacker + trydefog TRUE, NULL + restoreattacker + return + BattleScript_EffectInstruct:: attackcanceler pause B_WAIT_TIME_SHORT @@ -2027,6 +2033,10 @@ BattleScript_EffectEntrainment:: switchinabilities BS_TARGET printstring STRINGID_PKMNACQUIREDABILITY waitmessage B_WAIT_TIME_LONG + trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas goto BattleScript_MoveEnd BattleScript_EffectSimpleBeam:: @@ -2086,6 +2096,9 @@ BattleScript_EffectHealingWishGen4: switchindataupdate BS_ATTACKER hpthresholds BS_ATTACKER trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas flushtextbox printstring STRINGID_SWITCHINMON switchinanim BS_ATTACKER, FALSE, TRUE @@ -2358,8 +2371,11 @@ BattleScript_EffectMiracleEye:: accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE goto BattleScript_IdentifiedFoe - BattleScript_EffectGravity:: + call BattleScript_EffectGravityInternal + goto BattleScript_MoveEnd + +BattleScript_EffectGravityInternal: attackcanceler setgravity BattleScript_ButItFailed attackanimation @@ -2383,7 +2399,7 @@ BattleScript_GravityLoopEnd: moveendcase MOVEEND_TARGET_VISIBLE jumpifnexttargetvalid BattleScript_GravityLoop restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRoost:: attackcanceler @@ -2491,6 +2507,13 @@ BattleScript_TerrainPreventsEnd2:: waitmessage B_WAIT_TIME_LONG end2 +BattleScript_ImmunityProtectedEnd2:: + call BattleScript_AbilityPopUp + pause B_WAIT_TIME_SHORT + printstring STRINGID_ITDOESNTAFFECT + waitmessage B_WAIT_TIME_LONG + end2 + BattleScript_ElectricTerrainPrevents:: pause B_WAIT_TIME_SHORT printstring STRINGID_ELECTRICTERRAINPREVENTS @@ -2977,6 +3000,9 @@ BattleScript_EffectEvasionUp2:: BattleScript_EffectTransform:: attackcanceler trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas flushtextbox transformdataexecution attackanimation @@ -3019,11 +3045,15 @@ BattleScript_EffectReflect:: BattleScript_PrintReflectLightScreenSafeguardString:: attackanimation waitanimation -BattleScript_EffectAuroraVeilSuccess:: printfromtable gReflectLightScreenSafeguardStringIds waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_MoveEffectAuroraVeil:: + printfromtable gReflectLightScreenSafeguardStringIds + waitmessage B_WAIT_TIME_LONG + return + BattleScript_VoltAbsorbHeal: copybyte gBattlerAbility, gBattlerTarget tryhealquarterhealth BS_TARGET, BattleScript_MonMadeMoveUseless @ Check if max hp @@ -3319,11 +3349,11 @@ BattleScript_EffectSpite:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +@ TODO: Simplfy script BattleScript_EffectHealBell:: attackcanceler attackanimation waitanimation -BattleScript_EffectHealBell_FromHeal:: healpartystatus waitstate printfromtable gPartyStatusHealStringIds @@ -3343,6 +3373,15 @@ BattleScript_PartyHealEnd:: waitstate goto BattleScript_MoveEnd +BattleScript_MoveEffectAromatherapy:: + healpartystatus + waitstate + printfromtable gPartyStatusHealStringIds + waitmessage B_WAIT_TIME_LONG + updatestatusicon BS_ATTACKER_WITH_PARTNER + waitstate + return + BattleScript_EffectMeanLook:: attackcanceler accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON @@ -3774,13 +3813,6 @@ BattleScript_DoEffectTeleport:: BattleScript_EffectBeatUp:: attackcanceler accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE -.if B_BEAT_UP >= GEN_5 - critcalc - damagecalc - adjustdamage - trydobeatup - goto BattleScript_HitFromAtkAnimation -.else pause B_WAIT_TIME_SHORT setbyte gBattleCommunication, 0 BattleScript_BeatUpLoop:: @@ -3808,7 +3840,6 @@ BattleScript_BeatUpAttack:: goto BattleScript_BeatUpLoop BattleScript_BeatUpEnd:: end -.endif BattleScript_EffectDefenseCurl:: attackcanceler @@ -3993,6 +4024,7 @@ BattleScript_EffectNonVolatileStatus:: attackanimation waitanimation setnonvolatilestatus TRIGGER_ON_MOVE + clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE resultmessage waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd @@ -4185,8 +4217,8 @@ BattleScript_BrickBreakDoHit:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - setadditionaleffects tryfaintmon BS_TARGET + setadditionaleffects goto BattleScript_MoveEnd BattleScript_EffectYawn:: @@ -4196,11 +4228,15 @@ BattleScript_EffectYawn:: setyawn BattleScript_ButItFailed attackanimation waitanimation -BattleScript_EffectYawnSuccess:: printstring STRINGID_PKMNWASMADEDROWSY waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_MoveEffectYawnSide:: + printstring STRINGID_PKMNWASMADEDROWSY + waitmessage B_WAIT_TIME_LONG + return + BattleScript_PrintAbilityMadeIneffective:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp @@ -4435,6 +4471,9 @@ BattleScript_FaintAttacker:: dofaintanimation BS_ATTACKER printstring STRINGID_ATTACKERFAINTED cleareffectsonfaint BS_ATTACKER + trytoclearprimalweather + tryrevertweatherform + flushtextbox waitanimation tryactivatesoulheart tryactivatereceiver BS_ATTACKER @@ -4450,6 +4489,9 @@ BattleScript_FaintTarget:: dofaintanimation BS_TARGET printstring STRINGID_TARGETFAINTED cleareffectsonfaint BS_TARGET + trytoclearprimalweather + tryrevertweatherform + flushtextbox waitanimation tryactivatesoulheart tryactivatereceiver BS_TARGET @@ -5957,6 +5999,7 @@ BattleScript_CudChewActivates:: BattleScript_ApplyDisguiseFormChangeHPLoss:: jumpifgenconfiglowerthan GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn + orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING datahpupdate BS_SCRIPTING BattleScript_ApplyDisguiseFormChangeHPLossReturn: @@ -6081,7 +6124,7 @@ BattleScript_MoveUsedWokeUp:: BattleScript_MonWokeUpInUproar:: printstring STRINGID_PKMNWOKEUPINUPROAR waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER + updatestatusicon BS_EFFECT_BATTLER end2 BattleScript_PoisonTurnDmg:: @@ -6322,7 +6365,7 @@ BattleScript_UpdateEffectStatusIconRet:: flushtextbox return -BattleScript_YawnMakesAsleep:: +BattleScript_YawnMakesAsleepEnd2:: statusanimation BS_EFFECT_BATTLER printstring STRINGID_PKMNFELLASLEEP waitmessage B_WAIT_TIME_LONG @@ -7156,7 +7199,7 @@ BattleScript_FlinchPrevention:: call BattleScript_AbilityPopUp printstring STRINGID_PKMNSXPREVENTSFLINCHING waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_OwnTempoPrevents:: pause B_WAIT_TIME_SHORT @@ -7243,7 +7286,7 @@ BattleScript_TeraShellDistortingTypeMatchups:: BattleScript_CursedBodyActivates:: call BattleScript_AbilityPopUp - printstring STRINGID_CUSEDBODYDISABLED + printstring STRINGID_CURSEDBODYDISABLED waitmessage B_WAIT_TIME_LONG return @@ -7257,6 +7300,10 @@ BattleScript_MummyActivates:: recordability BS_ATTACKER printstring STRINGID_ATTACKERACQUIREDABILITY waitmessage B_WAIT_TIME_LONG + trytoclearprimalweather + tryrevertweatherform + flushtextbox + tryendneutralizinggas return BattleScript_WanderingSpiritActivates:: @@ -7324,11 +7371,12 @@ BattleScript_WeakArmorDefPrintString: printstring STRINGID_TARGETABILITYSTATLOWER waitmessage B_WAIT_TIME_LONG BattleScript_WeakArmorActivatesSpeed: -.if B_WEAK_ARMOR_SPEED >= GEN_7 + jumpifgenconfiglowerthan GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6 setstatchanger STAT_SPEED, 2, FALSE -.else + goto BattleScript_WeakArmorDoSpeed +BattleScript_WeakArmorSetSpeedGen6: setstatchanger STAT_SPEED, 1, FALSE -.endif +BattleScript_WeakArmorDoSpeed: statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesEnd jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_CHANGE, BattleScript_WeakArmorSpeedPrintString jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_CHANGE_EMPTY, BattleScript_WeakArmorActivatesEnd @@ -8550,24 +8598,7 @@ BattleScript_TargetAbilityStatRaiseRet_End: BattleScript_EffectMaxMove:: attackcanceler accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - setadditionaleffects - moveendall - end + goto BattleScript_HitFromAtkString BattleScript_EffectRaiseStatAllies:: savetarget @@ -8583,7 +8614,7 @@ BattleScript_RaiseSideStatsIncrement: setallytonexttarget BattleScript_RaiseSideStatsLoop BattleScript_RaiseSideStatsEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectLowerStatFoes:: savetarget @@ -8599,26 +8630,26 @@ BattleScript_LowerSideStatsIncrement: setallytonexttarget BattleScript_LowerSideStatsLoop BattleScript_LowerSideStatsEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectSetWeather:: playanimation 0, B_ANIM_MAX_SET_WEATHER printfromtable gMoveWeatherChangeStringIds waitmessage B_WAIT_TIME_LONG call BattleScript_ActivateWeatherAbilities - goto BattleScript_MoveEnd + return BattleScript_EffectSetTerrain:: printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG playanimation BS_ATTACKER, B_ANIM_RESTORE_BG call BattleScript_ActivateTerrainEffects - goto BattleScript_MoveEnd + return BattleScript_DamageNonTypesStarts:: printfromtable gDamageNonTypesStartStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_DamageNonTypesContinues:: printfromtable gDamageNonTypesDmgStringIds @@ -8631,7 +8662,7 @@ BattleScript_EffectTryReducePP:: tryspiteppreduce BattleScript_MoveEnd printstring STRINGID_PKMNREDUCEDPP waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return BattleScript_EffectParalyzeSide:: savetarget @@ -8639,18 +8670,12 @@ BattleScript_EffectParalyzeSide:: BattleScript_ParalyzeSideLoop: jumpifabsent BS_TARGET, BattleScript_ParalyzeSideIncrement trysetparalysis BattleScript_ParalyzeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_ParalyzeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ParalyzeSideEnd setallytonexttarget BattleScript_ParalyzeSideLoop BattleScript_ParalyzeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectPoisonSide:: savetarget @@ -8658,18 +8683,12 @@ BattleScript_EffectPoisonSide:: BattleScript_PoisonSideLoop: jumpifabsent BS_TARGET, BattleScript_PoisonSideIncrement trysetpoison BattleScript_PoisonSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_PoisonSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonSideEnd setallytonexttarget BattleScript_PoisonSideLoop BattleScript_PoisonSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectPoisonParalyzeSide:: savetarget @@ -8677,18 +8696,12 @@ BattleScript_EffectPoisonParalyzeSide:: BattleScript_PoisonParalyzeSideLoop: jumpifabsent BS_TARGET, BattleScript_PoisonParalyzeSideIncrement trysetpoisonparalysis BattleScript_PoisonParalyzeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_PoisonParalyzeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonParalyzeSideEnd setallytonexttarget BattleScript_PoisonParalyzeSideLoop BattleScript_PoisonParalyzeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectEffectSporeSide:: savetarget @@ -8696,18 +8709,12 @@ BattleScript_EffectEffectSporeSide:: BattleScript_EffectSporeSideLoop: jumpifabsent BS_TARGET, BattleScript_EffectSporeSideIncrement tryseteffectspore BattleScript_EffectSporeSideIncrement - statusanimation BS_TARGET - updatestatusicon BS_TARGET - printfromtable gStatusConditionsStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_EFFECT_BATTLER - waitstate BattleScript_EffectSporeSideIncrement: jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_EffectSporeSideEnd setallytonexttarget BattleScript_EffectSporeSideLoop BattleScript_EffectSporeSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectConfuseSide:: savetarget @@ -8725,11 +8732,11 @@ BattleScript_ConfuseSideIncrement: BattleScript_ConfuseSideEnd: restoretarget jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush - goto BattleScript_MoveEnd + return BattleScript_PrintCoinsScattered: printstring STRINGID_COINSSCATTERED - goto BattleScript_MoveEnd + return BattleScript_EffectInfatuateSide:: savetarget @@ -8746,7 +8753,7 @@ BattleScript_InfatuateSideIncrement: setallytonexttarget BattleScript_InfatuateSideLoop BattleScript_InfatuateSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectTormentSide:: savetarget @@ -8762,7 +8769,7 @@ BattleScript_TormentSideIncrement: setallytonexttarget BattleScript_TormentSideLoop BattleScript_TormentSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_TormentEnds:: printstring STRINGID_TORMENTEDNOMORE @@ -8783,7 +8790,7 @@ BattleScript_MeanLookSideIncrement: setallytonexttarget BattleScript_MeanLookSideLoop BattleScript_MeanLookSideEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRaiseCritAlliesAnim:: savetarget @@ -8799,7 +8806,7 @@ BattleScript_RaiseCritAlliesIncrement: setallytonexttarget BattleScript_RaiseCritAlliesLoop BattleScript_RaiseCritAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectHealOneSixthAllies:: jumpifteamhealthy BattleScript_MoveEnd @@ -8818,7 +8825,7 @@ BattleScript_HealOneSixthAlliesIncrement: setallytonexttarget BattleScript_HealOneSixthAlliesLoop BattleScript_HealOneSixthAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectRecycleBerriesAllies:: savetarget @@ -8835,13 +8842,13 @@ BattleScript_RecycleBerriesAlliesIncrement: setallytonexttarget BattleScript_RecycleBerriesAlliesLoop BattleScript_RecycleBerriesAlliesEnd: restoretarget - goto BattleScript_MoveEnd + return BattleScript_EffectSteelsurge:: setsteelsurge BattleScript_MoveEnd printfromtable gDmgHazardsStringIds waitmessage B_WAIT_TIME_LONG - goto BattleScript_MoveEnd + return @@@ END MAX MOVES @@@ @@ -8972,7 +8979,7 @@ BattleScript_SleepClauseBlocked:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd -BattleScript_SleepClausePreventsEnd:: +BattleScript_SleepClausePreventsEnd2:: pause B_WAIT_TIME_SHORT printstring STRINGID_BLOCKEDBYSLEEPCLAUSE waitmessage B_WAIT_TIME_LONG diff --git a/include/battle.h b/include/battle.h index 3af2efc504..16e8e83316 100644 --- a/include/battle.h +++ b/include/battle.h @@ -130,16 +130,16 @@ struct DisableStruct u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in u8 hazardsDone:1; - u8 padding2:1; + u8 endured:1; + u8 tryEjectPack:1; u8 octolockedBy:3; - u8 padding3:5; + u8 padding:5; }; // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects struct ProtectStruct { u32 protected:7; // 126 protect options - u32 endured:1; u32 noValidMoves:1; u32 helpingHand:1; u32 bounceMove:1; @@ -154,26 +154,26 @@ struct ProtectStruct u32 statRaised:1; u32 usedCustapBerry:1; // also quick claw u32 touchedProtectLike:1; - u32 unused:9; + u32 disableEjectPack:1; + u32 pranksterElevated:1; + u32 quickDraw:1; + u32 beakBlastCharge:1; + u32 quash:1; + u32 shellTrap:1; + u32 eatMirrorHerb:1; + u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy + u32 usedAllySwitch:1; // End of 32-bit bitfield - u16 disableEjectPack:1; - u16 tryEjectPack:1; - u16 pranksterElevated:1; - u16 quickDraw:1; - u16 beakBlastCharge:1; - u16 quash:1; - u16 shellTrap:1; - 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 lashOutAffected:1; u16 assuranceDoubled:1; - u16 padding:3; + u16 myceliumMight:1; + u16 laggingTail:1; + u16 padding:12; // End of 16-bit bitfield u16 physicalDmg; u16 specialDmg; - u8 physicalBattlerId; - u8 specialBattlerId; + u8 physicalBattlerId:4; + u8 specialBattlerId:4; }; // Cleared at the start of HandleAction_ActionFinished @@ -736,6 +736,7 @@ struct BattleStruct u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. + u16 beatUpSpecies[PARTY_SIZE]; u8 attackerBeforeBounce:2; u8 beatUpSlot:3; u8 pledgeMove:1; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 18c30b6cc8..3ba335db44 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -149,7 +149,7 @@ extern const u8 BattleScript_TargetWokeUp[]; extern const u8 BattleScript_TargetBurnHeal[]; extern const u8 BattleScript_TargetPoisonHealed[]; extern const u8 BattleScript_MoveEffectSleep[]; -extern const u8 BattleScript_YawnMakesAsleep[]; +extern const u8 BattleScript_YawnMakesAsleepEnd2[]; extern const u8 BattleScript_MoveEffectPoison[]; extern const u8 BattleScript_MoveEffectBurn[]; extern const u8 BattleScript_MoveEffectFrostbite[]; @@ -416,6 +416,7 @@ extern const u8 BattleScript_EjectPackActivates[]; extern const u8 BattleScript_MentalHerbCureRet[]; extern const u8 BattleScript_MentalHerbCureEnd2[]; extern const u8 BattleScript_TerrainPreventsEnd2[]; +extern const u8 BattleScript_ImmunityProtectedEnd2[]; extern const u8 BattleScript_MistyTerrainPrevents[]; extern const u8 BattleScript_ElectricTerrainPrevents[]; extern const u8 BattleScript_DoesntAffectTargetAtkString[]; @@ -510,7 +511,7 @@ extern const u8 BattleScript_BoosterEnergyEnd2[]; extern const u8 BattleScript_BoosterEnergyRet[]; extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraFormChange[]; -extern const u8 BattleScript_SleepClausePreventsEnd[]; +extern const u8 BattleScript_SleepClausePreventsEnd2[]; extern const u8 BattleScript_PowerConstruct[]; extern const u8 BattleScript_AbilityProtectsDoesntAffect[]; extern const u8 BattleScript_ImmunityProtected[]; @@ -543,10 +544,10 @@ extern const u8 BattleScript_EffectStonesurge[]; extern const u8 BattleScript_EffectSteelsurge[]; extern const u8 BattleScript_DamageNonTypesStarts[]; extern const u8 BattleScript_DamageNonTypesContinues[]; -extern const u8 BattleScript_DefogTryHazards[]; -extern const u8 BattleScript_EffectAuroraVeilSuccess[]; +extern const u8 BattleScript_MoveEffectDefog[]; +extern const u8 BattleScript_MoveEffectAuroraVeil[]; extern const u8 BattleScript_EffectGravitySuccess[]; -extern const u8 BattleScript_EffectYawnSuccess[]; +extern const u8 BattleScript_MoveEffectYawnSide[]; extern const u8 BattleScript_EffectTryReducePP[]; extern const u8 BattleScript_EffectParalyzeSide[]; extern const u8 BattleScript_EffectPoisonSide[]; @@ -640,7 +641,7 @@ extern const u8 BattleScript_EffectSketch[]; extern const u8 BattleScript_EffectDestinyBond[]; extern const u8 BattleScript_EffectSpite[]; extern const u8 BattleScript_EffectHealBell[]; -extern const u8 BattleScript_EffectHealBell_FromHeal[]; +extern const u8 BattleScript_MoveEffectAromatherapy[]; extern const u8 BattleScript_EffectMeanLook[]; extern const u8 BattleScript_EffectNightmare[]; extern const u8 BattleScript_EffectMinimize[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index e37da539f9..35bf757580 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -459,7 +459,7 @@ enum StringID STRINGID_HEALINGWISHCAMETRUE, STRINGID_HEALINGWISHHEALED, STRINGID_LUNARDANCECAMETRUE, - STRINGID_CUSEDBODYDISABLED, + STRINGID_CURSEDBODYDISABLED, STRINGID_ATTACKERACQUIREDABILITY, STRINGID_TARGETABILITYSTATLOWER, STRINGID_TARGETSTATWONTGOHIGHER, diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 0478240320..b365a6ea8f 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -35,6 +35,12 @@ enum GenConfigTag GEN_CONFIG_DISGUISE_HP_LOSS, GEN_CONFIG_AFTER_YOU_TURN_ORDER, GEN_CONFIG_HEALING_WISH_SWITCH, + GEN_CONFIG_MEGA_EVO_TURN_ORDER, + GEN_CONFIG_SHEER_COLD_IMMUNITY, + GEN_CONFIG_WEAK_ARMOR_SPEED, + GEN_CONFIG_PRANKSTER_DARK_TYPES, + GEN_CONFIG_DESTINY_BOND_FAIL, + GEN_CONFIG_POWDER_RAIN, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index c3667d1af5..a45325caab 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -38,6 +38,12 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_DISGUISE_HP_LOSS] = B_DISGUISE_HP_LOSS, [GEN_CONFIG_AFTER_YOU_TURN_ORDER] = B_AFTER_YOU_TURN_ORDER, [GEN_CONFIG_HEALING_WISH_SWITCH] = B_HEALING_WISH_SWITCH, + [GEN_CONFIG_MEGA_EVO_TURN_ORDER] = B_MEGA_EVO_TURN_ORDER, + [GEN_CONFIG_SHEER_COLD_IMMUNITY] = B_SHEER_COLD_IMMUNITY, + [GEN_CONFIG_WEAK_ARMOR_SPEED] = B_WEAK_ARMOR_SPEED, + [GEN_CONFIG_PRANKSTER_DARK_TYPES] = B_PRANKSTER_DARK_TYPES, + [GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL, + [GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN, }; #if TESTING diff --git a/include/random.h b/include/random.h index 283813b1b1..de0f406fe5 100644 --- a/include/random.h +++ b/include/random.h @@ -214,6 +214,7 @@ enum RandomTag RNG_AI_ASSUME_ALL_STATUS, RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, + RNG_WRAP, }; #define RandomWeighted(tag, ...) \ diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6cc42f482c..8399f7f977 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1259,7 +1259,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // def partner ability checks // gen7+ dark type mons immune to priority->elevated moves from prankster - if (B_PRANKSTER_DARK_TYPES >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) + if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move) && !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) RETURN_SCORE_MINUS(10); @@ -1721,7 +1721,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_SHEER_COLD: - if (B_SHEER_COLD_IMMUNITY >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) + if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE)) RETURN_SCORE_MINUS(20); // fallthrough case EFFECT_OHKO: @@ -2615,7 +2615,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // This only happens if the ally already rolled on double trick room on final turn. // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1)) ADJUST_SCORE(PERFECT_EFFECT); else ADJUST_SCORE(-10); @@ -2626,7 +2626,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(-10); // Don't unset a trick room that doesn't harm you unless it's about to expire. - else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != gBattleTurnCounter && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(-10); } break; @@ -2825,7 +2825,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_TAILWIND: if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND) - || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter)) + || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1))) ADJUST_SCORE(-10); break; case EFFECT_LUCKY_CHANT: @@ -3204,15 +3204,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. // This unsets Trick Room and resets it with a full timer. case EFFECT_TRICK_ROOM: - if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM) - && HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM) + && HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM) && RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE)) ADJUST_SCORE(PERFECT_EFFECT); break; case EFFECT_TAILWIND: // Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind. - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1) && RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE)) ADJUST_SCORE(BEST_EFFECT); break; @@ -5276,7 +5276,7 @@ case EFFECT_GUARD_SPLIT: else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0)) ADJUST_SCORE(DECENT_EFFECT); // Don't unset it on last turn. - else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) + else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)) ADJUST_SCORE(GOOD_EFFECT); } break; @@ -5388,7 +5388,7 @@ case EFFECT_GUARD_SPLIT: break; case EFFECT_TAILWIND: { - if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1)) break; if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL)) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index fc62eb907a..dfc305ec5b 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -28,6 +28,17 @@ static u32 GetAIEffectGroup(enum BattleMoveEffects effect); static u32 GetAIEffectGroupFromMove(u32 battler, u32 move); // Functions +static u32 AI_GetMoldBreakerSanitizedAbility(u32 battlerAtk, u32 abilityAtk, u32 abilityDef, u32 holdEffectDef, u32 move) +{ + if (MoveIgnoresTargetAbility(move)) + return ABILITY_NONE; + + if (holdEffectDef != HOLD_EFFECT_ABILITY_SHIELD && IsMoldBreakerTypeAbility(battlerAtk, abilityAtk)) + return ABILITY_NONE; + + return abilityDef; +} + static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move) { u32 numOfTargets = 0; @@ -919,10 +930,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u ctx.updateFlags = FALSE; ctx.weather = weather; ctx.fixedBasePower = SetFixedMoveBasePower(battlerAtk, move); - ctx.abilityAtk = aiData->abilities[battlerAtk]; - ctx.abilityDef = aiData->abilities[battlerDef]; ctx.holdEffectAtk = aiData->holdEffects[battlerAtk]; ctx.holdEffectDef = aiData->holdEffects[battlerDef]; + ctx.abilityAtk = aiData->abilities[battlerAtk]; + ctx.abilityDef = AI_GetMoldBreakerSanitizedAbility(battlerAtk, ctx.abilityAtk, aiData->abilities[battlerDef], ctx.holdEffectDef, move); ctx.typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(&ctx); u32 movePower = GetMovePower(move); diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 224cea1030..85a77399c0 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -763,8 +763,9 @@ static bool32 HandleEndTurnWrap(u32 battler) if (gBattleMons[battler].volatiles.wrapped && IsBattlerAlive(battler)) { - if (--gDisableStructs[battler].wrapTurns != 0) + if (gDisableStructs[battler].wrapTurns != 0) { + gDisableStructs[battler].wrapTurns--; if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) return effect; @@ -1024,7 +1025,6 @@ static bool32 HandleEndTurnYawn(u32 battler) && !UproarWakeUpCheck(battler) && !IsLeafGuardProtected(battler, ability)) { - CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN); gEffectBattler = gBattlerTarget = battler; if (IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN)) { @@ -1038,7 +1038,15 @@ static bool32 HandleEndTurnYawn(u32 battler) } else if (IsSleepClauseActiveForSide(GetBattlerSide(battler))) { - BattleScriptExecute(BattleScript_SleepClausePreventsEnd); + BattleScriptExecute(BattleScript_SleepClausePreventsEnd2); + } + else if ((gBattleScripting.battler = IsAbilityOnSide(battler, ABILITY_SWEET_VEIL))) + { + gBattleScripting.battler--; + gLastUsedAbility = ABILITY_SWEET_VEIL; + gBattlerAbility = gBattleScripting.battler; + RecordAbilityBattle(gBattleScripting.battler, ABILITY_SWEET_VEIL); + BattleScriptExecute(BattleScript_ImmunityProtectedEnd2); } else { @@ -1047,10 +1055,11 @@ static bool32 HandleEndTurnYawn(u32 battler) else gBattleMons[battler].status1 |= ((Random() % 4) + 3); + CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN); TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1); MarkBattlerForControllerExec(battler); - BattleScriptExecute(BattleScript_YawnMakesAsleep); + BattleScriptExecute(BattleScript_YawnMakesAsleepEnd2); } effect = TRUE; } @@ -1361,25 +1370,22 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler) case THIRD_EVENT_BLOCK_UPROAR: if (gBattleMons[battler].volatiles.uproarTurns) { - for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++) + for (gEffectBattler = 0; gEffectBattler < gBattlersCount; gEffectBattler++) { - if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF) + if ((gBattleMons[gEffectBattler].status1 & STATUS1_SLEEP) + && GetBattlerAbility(gEffectBattler) != ABILITY_SOUNDPROOF) { - gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP; - gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE; + gBattleMons[gEffectBattler].status1 &= ~STATUS1_SLEEP; + gBattleMons[gEffectBattler].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = 1; BattleScriptExecute(BattleScript_MonWokeUpInUproar); - BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); - MarkBattlerForControllerExec(gBattlerAttacker); + BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1); + MarkBattlerForControllerExec(gEffectBattler); + effect = TRUE; break; } } - if (gBattlerAttacker != gBattlersCount) - { - break; - } - else + if (effect == FALSE) { gBattlerAttacker = battler; gBattleMons[battler].volatiles.uproarTurns--; // uproar timer goes down diff --git a/src/battle_main.c b/src/battle_main.c index e7150694f1..5eb147a517 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3197,6 +3197,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy) memset(&gDisableStructs[battler], 0, sizeof(struct DisableStruct)); + if (GetProtectType(gProtectStructs[battler].protected) == PROTECT_TYPE_SINGLE) // Side type protects expire at the end of the turn + gProtectStructs[battler].protected = PROTECT_NONE; + if (effect == EFFECT_BATON_PASS) { gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP; @@ -3294,9 +3297,7 @@ const u8* FaintClearSetData(u32 battler) for (i = 0; i < NUM_BATTLE_STATS; i++) gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; - bool32 keepGastroAcid = FALSE; - if (gBattleMons[battler].volatiles.gastroAcid) - keepGastroAcid = TRUE; + bool32 keepGastroAcid = gBattleMons[battler].volatiles.gastroAcid; memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out. @@ -3323,7 +3324,6 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].protected = PROTECT_NONE; gProtectStructs[battler].quash = FALSE; - gProtectStructs[battler].endured = FALSE; gProtectStructs[battler].noValidMoves = FALSE; gProtectStructs[battler].helpingHand = FALSE; gProtectStructs[battler].bounceMove = FALSE; @@ -3335,7 +3335,6 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].fleeType = 0; gProtectStructs[battler].notFirstStrike = FALSE; gProtectStructs[battler].statRaised = FALSE; - gProtectStructs[battler].tryEjectPack = FALSE; gProtectStructs[battler].pranksterElevated = FALSE; gDisableStructs[battler].isFirstTurn = 2; @@ -4488,6 +4487,10 @@ static void HandleTurnActionSelectionState(void) gBattleStruct->chosenMovePositions[battler] = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK; gChosenMoveByBattler[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]]; gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3]; + if (IsBattleMoveStatus(gChosenMoveByBattler[battler]) && GetBattlerAbility(battler) == ABILITY_MYCELIUM_MIGHT) + gProtectStructs[battler].myceliumMight = TRUE; + if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LAGGING_TAIL) + gProtectStructs[battler].laggingTail = TRUE; // Check to see if any gimmicks need to be prepared. if (gBattleResources->bufferB[battler][2] & RET_GIMMICK) @@ -4824,9 +4827,13 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS) return GetMovePriority(MOVE_MAX_GUARD); - if (ability == ABILITY_GALE_WINGS - && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) - && GetMoveType(move) == TYPE_FLYING) + if (gProtectStructs[battler].quash) + { + priority = -8; + } + else if (ability == ABILITY_GALE_WINGS + && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler)) + && GetMoveType(move) == TYPE_FLYING) { priority++; } @@ -4844,9 +4851,6 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) priority += 3; } - if (gProtectStructs[battler].quash) - priority = -8; - return priority; } @@ -4862,16 +4866,16 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov // Lagging Tail - always last bool32 battler1HasQuickEffect = gProtectStructs[battler1].quickDraw || gProtectStructs[battler1].usedCustapBerry; bool32 battler2HasQuickEffect = gProtectStructs[battler2].quickDraw || gProtectStructs[battler2].usedCustapBerry; - bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || (ability1 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler1])); - bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || (ability2 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler2])); + bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || gProtectStructs[battler1].myceliumMight; + bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || gProtectStructs[battler2].myceliumMight; if (battler1HasQuickEffect && !battler2HasQuickEffect) strikesFirst = 1; else if (battler2HasQuickEffect && !battler1HasQuickEffect) strikesFirst = -1; - else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL) + else if (gProtectStructs[battler1].laggingTail && !gProtectStructs[battler2].laggingTail) strikesFirst = -1; - else if (holdEffectBattler2 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler1 != HOLD_EFFECT_LAGGING_TAIL) + else if (gProtectStructs[battler2].laggingTail && !gProtectStructs[battler1].laggingTail) strikesFirst = 1; else if (battler1HasStallingAbility && !battler2HasStallingAbility) strikesFirst = -1; @@ -5190,7 +5194,7 @@ static bool32 TryDoGimmicksBeforeMoves(void) } } - if (B_MEGA_EVO_TURN_ORDER >= GEN_7) + if (GetGenConfig(GEN_CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7) TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved. return FALSE; } diff --git a/src/battle_message.c b/src/battle_message.c index 04414d602d..d79e7bf573 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -266,7 +266,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_PKMNFASTASLEEP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is fast asleep."), [STRINGID_PKMNWOKEUP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} woke up!"), [STRINGID_PKMNUPROARKEPTAWAKE] = COMPOUND_STRING("But the uproar kept {B_SCR_NAME_WITH_PREFIX2} awake!"), - [STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("The uproar woke {B_ATK_NAME_WITH_PREFIX2}!"), + [STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("The uproar woke {B_EFF_NAME_WITH_PREFIX2}!"), [STRINGID_PKMNCAUSEDUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} caused an uproar!"), [STRINGID_PKMNMAKINGUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is making an uproar!"), [STRINGID_PKMNCALMEDDOWN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} calmed down."), @@ -602,7 +602,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_SOLARPOWERHPDROP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} takes its toll!"), //don't think this message is displayed anymore [STRINGID_AFTERMATHDMG] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} was hurt!"), [STRINGID_ANTICIPATIONACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} shuddered!"), - [STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("{B_SCR_ABILITY} alerted {B_SCR_NAME_WITH_PREFIX2} to {B_DEF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), + [STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("{B_SCR_ABILITY} alerted {B_SCR_NAME_WITH_PREFIX2} to {B_EFF_NAME_WITH_PREFIX2}'s {B_BUFF1}!"), [STRINGID_ICEBODYHPGAIN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY} healed it a little bit!"), //don't think this message is displayed anymore [STRINGID_SNOWWARNINGHAIL] = COMPOUND_STRING("It started to hail!"), [STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} frisked {B_DEF_NAME_WITH_PREFIX2} and found its {B_LAST_ITEM}!"), @@ -619,7 +619,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] = [STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_ATK_NAME_WITH_PREFIX2}!"), [STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} regained health!"), [STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in mystical moonlight!"), - [STRINGID_CUSEDBODYDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"), + [STRINGID_CURSEDBODYDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"), [STRINGID_ATTACKERACQUIREDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} acquired {B_ATK_ABILITY}!"), [STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} {B_BUFF2}lowered its {B_BUFF1}!"), [STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any higher!"), diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 41976e1149..ef38192cf6 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1857,7 +1857,7 @@ static void Cmd_adjustdamage(void) { enduredHit |= 1u << battlerDef; } - else if (gProtectStructs[battlerDef].endured) + else if (gDisableStructs[battlerDef].endured) { enduredHit |= 1u << battlerDef; gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED; @@ -2258,6 +2258,7 @@ static void Cmd_datahpupdate(void) { CMD_ARGS(u8 battler); bool32 isPassiveHpUpdate = gHitMarker & HITMARKER_PASSIVE_HP_UPDATE; + bool32 disguiseActivates = FALSE; if (gBattleControllerExecFlags) return; @@ -2299,7 +2300,7 @@ static void Cmd_datahpupdate(void) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; BattleScriptPush(cmd->nextInstr); gBattlescriptCurrInstr = BattleScript_TargetFormChange; - return; + disguiseActivates = TRUE; } else { @@ -2384,6 +2385,9 @@ static void Cmd_datahpupdate(void) && CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item) && !NoAliveMonsForEitherParty()) gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE; + + if (disguiseActivates) + return; } TryRestoreDamageAfterCheekPouch(battler); @@ -2830,7 +2834,7 @@ static inline bool32 TrySetLightScreen(u32 battler) return FALSE; } -static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger) +static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger) { gEffectBattler = effectBattler; @@ -2974,7 +2978,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai battlerAbility, gBattleScripting.moveEffect, CHECK_TRIGGER)) - SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); + SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE); break; case MOVE_EFFECT_CONFUSION: if (!CanBeConfused(gEffectBattler) @@ -3012,6 +3016,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gLastUsedAbility = ABILITY_INNER_FOCUS; gBattlerAbility = gEffectBattler; RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS); + BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_FlinchPrevention; } else @@ -3110,7 +3115,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW) gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5; else - gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2; + gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5); gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove; gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker; @@ -3323,6 +3328,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gBattleStruct->moveDamage[i] = gBattleMons[i].maxHP / 16; if (gBattleStruct->moveDamage[i] == 0) gBattleStruct->moveDamage[i] = 1; + BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst; } break; @@ -3829,7 +3835,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai || gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) { BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_DefogTryHazards; + gBattlescriptCurrInstr = BattleScript_MoveEffectDefog; } break; case MOVE_EFFECT_AURORA_VEIL: @@ -3842,7 +3848,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectAuroraVeilSuccess; + gBattlescriptCurrInstr = BattleScript_MoveEffectAuroraVeil; } break; case MOVE_EFFECT_GRAVITY: @@ -3888,7 +3894,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai { gBattleMons[gBattlerTarget].volatiles.yawn = 2; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectYawnSuccess; + gBattlescriptCurrInstr = BattleScript_MoveEffectYawnSide; } break; } @@ -3954,7 +3960,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai break; case MOVE_EFFECT_AROMATHERAPY: BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_EffectHealBell_FromHeal; + gBattlescriptCurrInstr = BattleScript_MoveEffectAromatherapy; break; case MOVE_EFFECT_RECYCLE_BERRIES: if (RandomPercentage(RNG_G_MAX_REPLENISH, 50)) @@ -5476,7 +5482,7 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect) { - if (gProtectStructs[battlerDef].tryEjectPack + if (gDisableStructs[battlerDef].tryEjectPack && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(battlerDef) && CountUsablePartyMons(battlerDef) > 0 @@ -5946,7 +5952,7 @@ static void Cmd_moveend(void) // Not strictly a protect effect, but works the same way if (gProtectStructs[gBattlerTarget].beakBlastCharge - && CanBeBurned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker)) + && CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; @@ -6493,7 +6499,7 @@ static void Cmd_moveend(void) } for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; u8 battlers[4] = {0, 1, 2, 3}; if (numEjectButtonBattlers > 1) @@ -6556,7 +6562,7 @@ static void Cmd_moveend(void) } for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; u8 battlers[4] = {0, 1, 2, 3}; if (numEmergencyExitBattlers > 1) @@ -6611,7 +6617,7 @@ static void Cmd_moveend(void) SortBattlersBySpeed(battlers, FALSE); for (i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; for (i = 0; i < gBattlersCount; i++) { @@ -6840,7 +6846,7 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE; - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; if (gBattleStruct->battlerState[i].commanderSpecies != SPECIES_NONE && !IsBattlerAlive(i)) { @@ -9463,7 +9469,7 @@ static void Cmd_setprotectlike(void) { if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE) { - gProtectStructs[gBattlerAttacker].endured = TRUE; + gDisableStructs[gBattlerAttacker].endured = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF; } else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE) @@ -10163,7 +10169,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan } else if (!flags.onlyChecking) { - gProtectStructs[battler].tryEjectPack = TRUE; + gDisableStructs[battler].tryEjectPack = TRUE; gProtectStructs[battler].lashOutAffected = TRUE; gBattleScripting.statChanger |= STAT_BUFF_NEGATIVE; } @@ -10760,7 +10766,7 @@ static void Cmd_tryKO(void) if (lands) { - if (gProtectStructs[gBattlerTarget].endured) + if (gDisableStructs[gBattlerTarget].endured) { gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED; @@ -12207,12 +12213,6 @@ static void Cmd_setfutureattack(void) static void Cmd_trydobeatup(void) { -#if B_BEAT_UP >= GEN_5 - CMD_ARGS(); - - gBattleStruct->beatUpSlot++; - gBattlescriptCurrInstr = cmd->nextInstr; -#else CMD_ARGS(const u8 *endInstr, const u8 *failInstr); struct Pokemon *party = GetBattlerParty(gBattlerAttacker); @@ -12257,7 +12257,6 @@ static void Cmd_trydobeatup(void) gBattlescriptCurrInstr = cmd->failInstr; } } -#endif } static void Cmd_setsemiinvulnerablebit(void) @@ -14181,13 +14180,13 @@ static void Cmd_setnonvolatilestatus(void) if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION) SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE); else - SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); + SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY); break; case TRIGGER_ON_MOVE: - SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); + SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE); break; case TRIGGER_ON_PROTECT: - SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); + SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT); break; } } @@ -15944,12 +15943,8 @@ static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr) { if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget))) { - gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS; - gBattleCommunication[MULTISTRING_CHOOSER] = 3; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, TRIGGER_ON_MOVE); } else { @@ -15961,12 +15956,8 @@ static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr) { if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget))) { - gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON; - gBattleCommunication[MULTISTRING_CHOOSER] = 0; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, TRIGGER_ON_MOVE); } else { @@ -15978,17 +15969,8 @@ static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr) { if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)) { - if (B_SLEEP_TURNS >= GEN_5) - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2); - else - gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3); - - TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]); - gBattleCommunication[MULTISTRING_CHOOSER] = 4; - gEffectBattler = gBattlerTarget; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - gBattlescriptCurrInstr = nextInstr; + gBattlescriptCurrInstr = nextInstr - 1; + SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, TRIGGER_ON_MOVE); } else { @@ -17426,7 +17408,7 @@ void BS_GetTotemBoost(void) void BS_ActivateItemEffects(void) { NATIVE_ARGS(); - if (ItemBattleEffects(ITEMEFFECT_NORMAL, gBattlerTarget)) + if (ItemBattleEffects(ITEMEFFECT_TRY_HEALING, gBattlerTarget)) return; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/battle_util.c b/src/battle_util.c index cc5543618e..f838cc5fce 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -276,15 +276,8 @@ bool32 EndOrContinueWeather(void) static u32 CalcBeatUpPower(void) { - u32 basePower; - u32 species; - struct Pokemon *party = GetBattlerParty(gBattlerAttacker); - - // Party slot is incremented by the battle script for Beat Up after this damage calculation - species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); - basePower = (GetSpeciesBaseAttack(species) / 10) + 5; - - return basePower; + u32 species = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++]; + return (GetSpeciesBaseAttack(species) / 10) + 5; } static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef) @@ -1977,6 +1970,7 @@ static enum MoveCanceller CancellerAsleepOrFrozen(struct BattleContext *ctx) TryDeactivateSleepClause(GetBattlerSide(ctx->battlerAtk), gBattlerPartyIndexes[ctx->battlerAtk]); gBattleMons[ctx->battlerAtk].status1 &= ~STATUS1_SLEEP; gBattleMons[ctx->battlerAtk].volatiles.nightmare = FALSE; + gEffectBattler = ctx->battlerAtk; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; BattleScriptCall(BattleScript_MoveUsedWokeUp); return MOVE_STEP_REMOVES_STATUS; @@ -2547,7 +2541,7 @@ static enum MoveCanceller CancellerWeatherPrimal(struct BattleContext *ctx) if (HasWeatherEffect() && GetMovePower(ctx->currentMove) > 0) { u32 moveType = GetBattleMoveType(ctx->currentMove); - if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (B_POWDER_RAIN >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove))) + if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetGenConfig(GEN_CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(ctx->currentMove))) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; effect = MOVE_STEP_FAILURE; @@ -2842,14 +2836,19 @@ static enum MoveCanceller CancellerMultihitMoves(struct BattleContext *ctx) { struct Pokemon* party = GetBattlerParty(ctx->battlerAtk); int i; + gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) - && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + u32 species = GetMonData(&party[i], MON_DATA_SPECIES); + if (species != SPECIES_NONE + && GetMonData(&party[i], MON_DATA_HP) && !GetMonData(&party[i], MON_DATA_IS_EGG) && !GetMonData(&party[i], MON_DATA_STATUS)) + { + gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++] = species; gMultiHitCounter++; + } } gBattleStruct->beatUpSlot = 0; @@ -3241,9 +3240,9 @@ static void ForewarnChooseMove(u32 battler) bestId = i; } - gBattlerTarget = data[bestId].battler; + gEffectBattler = data[bestId].battler; PREPARE_MOVE_BUFFER(gBattleTextBuff1, data[bestId].moveId) - RecordKnownMove(gBattlerTarget, data[bestId].moveId); + RecordKnownMove(data[bestId].battler, data[bestId].moveId); Free(data); } @@ -4263,27 +4262,33 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_INTREPID_SWORD: - if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) + if (!gSpecialStatuses[battler].switchInAbilityDone && !GetBattlerPartyState(battler)->intrepidSwordBoost) { if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9) GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - SET_STATCHANGER(STAT_ATK, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); - effect++; + if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_ATK, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } } break; case ABILITY_DAUNTLESS_SHIELD: - if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN) + if (!gSpecialStatuses[battler].switchInAbilityDone && !GetBattlerPartyState(battler)->dauntlessShieldBoost) { if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9) GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE; - SET_STATCHANGER(STAT_DEF, 1, FALSE); - BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); - effect++; + if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) + { + SET_STATCHANGER(STAT_DEF, 1, FALSE); + BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn); + effect++; + } } break; case ABILITY_WIND_RIDER: @@ -5472,6 +5477,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleScripting.battler = gBattlerAbility = gBattlerTarget; RecordAbilityBattle(gBattlerTarget, ABILITY_SYNCHRONIZE); + if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + if (CanSetNonVolatileStatus( gBattlerTarget, gBattlerAttacker, @@ -5480,9 +5488,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleStruct->synchronizeMoveEffect, CHECK_TRIGGER)) { - if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) - gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; - gEffectBattler = gBattlerAttacker; gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE); @@ -5502,6 +5507,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattleScripting.battler = gBattlerAbility = gBattlerAttacker; RecordAbilityBattle(gBattlerAttacker, ABILITY_SYNCHRONIZE); + if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC) + gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON; + if (CanSetNonVolatileStatus( gBattlerAttacker, gBattlerTarget, @@ -7999,7 +8007,7 @@ enum IronBallCheck }; // Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics -static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall) +static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall) { enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE); @@ -8017,7 +8025,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck return FALSE; if (holdEffect == HOLD_EFFECT_AIR_BALLOON) return FALSE; - if (gAiLogicData->aiCalcInProgress ? gAiLogicData->abilities[battler] == ABILITY_LEVITATE : IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_LEVITATE)) + if (ability == ABILITY_LEVITATE) return FALSE; if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE))) return FALSE; @@ -8026,7 +8034,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck bool32 IsBattlerGrounded(u32 battler) { - return IsBattlerGroundedInverseCheck(battler, NOT_INVERSE_BATTLE, CHECK_IRON_BALL); + return IsBattlerGroundedInverseCheck(battler, GetBattlerAbility(battler), NOT_INVERSE_BATTLE, CHECK_IRON_BALL); } u32 GetMoveSlot(u16 *moves, u32 move) @@ -9994,7 +10002,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST)) modifier = UQ_4_12(0.0); } - else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) + else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move))) { modifier = UQ_4_12(0.0); if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE) @@ -10006,7 +10014,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont RecordAbilityBattle(ctx->battlerDef, ABILITY_LEVITATE); } } - else if (B_SHEER_COLD_IMMUNITY >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) + else if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE)) { modifier = UQ_4_12(0.0); } @@ -10024,7 +10032,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont && ctx->moveType == TYPE_GROUND && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING) && GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL - && !IsBattlerGroundedInverseCheck(ctx->battlerDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL) + && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityAtk, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL) && !FlagGet(B_FLAG_INVERSE_BATTLE)) { modifier = UQ_4_12(1.0); @@ -11068,7 +11076,7 @@ bool32 TryRoomService(u32 battler) bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget) { - if (B_PRANKSTER_DARK_TYPES < GEN_7) + if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) < GEN_7) return FALSE; if (!gProtectStructs[battlerPrankster].pranksterElevated) return FALSE; @@ -11594,7 +11602,7 @@ void ClearDamageCalcResults(void) bool32 DoesDestinyBondFail(u32 battler) { - return B_DESTINY_BOND_FAIL >= GEN_7 && gBattleMons[battler].volatiles.destinyBond; + return GetGenConfig(GEN_CONFIG_DESTINY_BOND_FAIL) >= GEN_7 && gBattleMons[battler].volatiles.destinyBond; } // This check has always to be the last in a condtion statement because of the recording of AI data. @@ -11713,7 +11721,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) for (u32 i = 0; i < gBattlersCount; i++) { - if (gProtectStructs[i].tryEjectPack + if (gDisableStructs[i].tryEjectPack && GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK && IsBattlerAlive(i) && CountUsablePartyMons(i) > 0) @@ -11731,7 +11739,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID) SortBattlersBySpeed(battlers, FALSE); for (u32 i = 0; i < gBattlersCount; i++) - gProtectStructs[i].tryEjectPack = FALSE; + gDisableStructs[i].tryEjectPack = FALSE; for (u32 i = 0; i < gBattlersCount; i++) { diff --git a/src/battle_util2.c b/src/battle_util2.c index 3a05e5ac13..3f25271300 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -132,6 +132,7 @@ u32 BattlePalace_TryEscapeStatus(u8 battler) if (UproarWakeUpCheck(battler)) { // Wake up from Uproar + gEffectBattler = battler; gBattleMons[battler].status1 &= ~(STATUS1_SLEEP); gBattleMons[battler].volatiles.nightmare = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR; diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 03e55ba9f7..094f2c7dfe 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -791,7 +791,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_BEAT_UP] = { - .battleScript = BattleScript_EffectBeatUp, + .battleScript = (B_BEAT_UP >= GEN_5) ? BattleScript_EffectHit : BattleScript_EffectBeatUp, .battleTvScore = 2, }, diff --git a/src/data/pokemon/teachable_learnsets.h b/src/data/pokemon/teachable_learnsets.h index ae04d18e68..8b400f5675 100644 --- a/src/data/pokemon/teachable_learnsets.h +++ b/src/data/pokemon/teachable_learnsets.h @@ -32096,6 +32096,7 @@ static const u16 sDipplinTeachableLearnset[] = { static const u16 sHydrappleTeachableLearnset[] = { MOVE_BODY_SLAM, MOVE_BULLET_SEED, + MOVE_DEFENSE_CURL, MOVE_DOUBLE_EDGE, MOVE_EARTHQUAKE, MOVE_ENDURE, @@ -32106,6 +32107,7 @@ static const u16 sHydrappleTeachableLearnset[] = { MOVE_RAIN_DANCE, MOVE_REFLECT, MOVE_REST, + MOVE_ROLLOUT, MOVE_SLEEP_TALK, MOVE_SOLAR_BEAM, MOVE_SUNNY_DAY, diff --git a/src/event_object_movement.c b/src/event_object_movement.c index a91bb04b25..84f810e95a 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2055,19 +2055,7 @@ static u32 LoadDynamicFollowerPalette(u32 species, bool32 shiny, bool32 female) spritePalette.data = gSpeciesInfo[species].overworldPalette; } - // Check if pal data must be decompressed - if (IsLZ77Data(spritePalette.data, PLTT_SIZE_4BPP, PLTT_SIZE_4BPP)) - { - struct SpritePalette compSpritePalette; - - compSpritePalette.data = (const void *) spritePalette.data; - compSpritePalette.tag = spritePalette.tag; - paletteNum = LoadSpritePalette(&compSpritePalette); - } - else - { - paletteNum = LoadSpritePalette(&spritePalette); - } + paletteNum = LoadSpritePalette(&spritePalette); } else #endif //OW_POKEMON_OBJECT_EVENTS == TRUE && OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE diff --git a/test/battle/ability/desolate_land.c b/test/battle/ability/desolate_land.c index 0b99040189..b7cc02d47e 100644 --- a/test/battle/ability/desolate_land.c +++ b/test/battle/ability/desolate_land.c @@ -83,3 +83,18 @@ SINGLE_BATTLE_TEST("Desolate Land will not create a softlock when move in semi i ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); } } + +SINGLE_BATTLE_TEST("Desolate Land is removed immediately if user faints") +{ + GIVEN { + PLAYER(SPECIES_GROUDON) { HP(1); Item(ITEM_RED_ORB); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_POUND); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent); + NOT MESSAGE("The sunlight is strong."); + MESSAGE("The extremely harsh sunlight faded!"); + } +} diff --git a/test/battle/ability/filter.c b/test/battle/ability/filter.c index ca323b1be2..c9a742c48d 100644 --- a/test/battle/ability/filter.c +++ b/test/battle/ability/filter.c @@ -1,4 +1,25 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Filter (Ability) test titles") +SINGLE_BATTLE_TEST("Filter reduces damage to Super Effective moves by 0.75", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_SOUNDPROOF; } + PARAMETRIZE { ability = ABILITY_FILTER; } + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[0] == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[1] == TYPE_FAIRY); + ASSUME(gMovesInfo[MOVE_POISON_JAB].type == TYPE_POISON); + ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0)); + ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0)); + PLAYER(SPECIES_MR_MIME) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_POISON_JAB); } + } SCENE { + HP_BAR(player, captureDamage: &results[i].damage); + MESSAGE("It's super effective!"); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + } +} diff --git a/test/battle/ability/flash_fire.c b/test/battle/ability/flash_fire.c index c81967d1af..4cdcec9973 100644 --- a/test/battle/ability/flash_fire.c +++ b/test/battle/ability/flash_fire.c @@ -9,9 +9,9 @@ SINGLE_BATTLE_TEST("Flash Fire boosts fire type moves by 50% but no subsequent i PLAYER(SPECIES_HEATRAN) { Ability(ABILITY_FLASH_FIRE); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); } - TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); } - TURN { MOVE(player, MOVE_EMBER); } + TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); HP_BAR(opponent, captureDamage: &damage[0]); diff --git a/test/battle/ability/levitate.c b/test/battle/ability/levitate.c index a1c1dc927d..348d347f3b 100644 --- a/test/battle/ability/levitate.c +++ b/test/battle/ability/levitate.c @@ -1,4 +1,115 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Levitate (Ability) test titles") +SINGLE_BATTLE_TEST("Levitate activates when targeted by ground type moves") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND); + PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MUD_SLAP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_LEVITATE); + MESSAGE("Lunatone makes Ground-type moves miss with Levitate!"); + } +} + +SINGLE_BATTLE_TEST("Levitate does not activate if protected") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND); + PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); } + } SCENE { + NONE_OF { + ABILITY_POPUP(player, ABILITY_LEVITATE); + MESSAGE("Lunatone makes Ground-type moves miss with Levitate!"); + } + } +} + +SINGLE_BATTLE_TEST("Levitate does not activate on status moves") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_SAND_ATTACK) == TYPE_GROUND); + ASSUME(GetMoveCategory(MOVE_SAND_ATTACK) == DAMAGE_CATEGORY_STATUS); + PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SAND_ATTACK); } + } SCENE { + NONE_OF { + ABILITY_POPUP(player, ABILITY_LEVITATE); + MESSAGE("Lunatone makes Ground-type moves miss with Levitate!"); + } + } +} + +SINGLE_BATTLE_TEST("Levitate does not activate if attacked by an opponent with Mold Breaker") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND); + PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); } + OPPONENT(SPECIES_TINKATON) { Ability(ABILITY_MOLD_BREAKER); } + } WHEN { + TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); } + } SCENE { + NONE_OF { + ABILITY_POPUP(player, ABILITY_LEVITATE); + MESSAGE("Lunatone makes Ground-type moves miss with Levitate!"); + } + } +} + +DOUBLE_BATTLE_TEST("Levitate does not cause single remaining target to take higher damage") +{ + s16 damage[3]; + GIVEN { + PLAYER(SPECIES_REGIROCK) { Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + OPPONENT(SPECIES_LUNATONE) { Speed(3); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(playerRight, MOVE_CELEBRATE); MOVE(playerLeft, MOVE_EARTHQUAKE); } + TURN { MOVE(playerRight, MOVE_MEMENTO, target:opponentLeft); MOVE(playerLeft, MOVE_EARTHQUAKE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft); + HP_BAR(playerRight, captureDamage: &damage[0]); + HP_BAR(opponentRight, captureDamage: &damage[1]); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft); + HP_BAR(opponentRight, captureDamage: &damage[2]); + + } THEN { + EXPECT_EQ(damage[0], damage[1]); + EXPECT_EQ(damage[1], damage[2]); + } +} + +AI_SINGLE_BATTLE_TEST("Levitate is seen correctly by switch AI") +{ + u32 ability = ABILITY_NONE, item = ITEM_NONE; + + PARAMETRIZE { ability = ABILITY_OWN_TEMPO, item = ITEM_NONE ; } + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER, item = ITEM_NONE ; } + PARAMETRIZE { ability = ABILITY_MOLD_BREAKER, item = ITEM_ABILITY_SHIELD ; } + + GIVEN { + ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_TINKATON) { Ability(ability); Speed(3); } + OPPONENT(SPECIES_PONYTA) { Level(1); Item(ITEM_EJECT_PACK); Moves(MOVE_OVERHEAT); Speed(4); } // Forces switchout + OPPONENT(SPECIES_VIKAVOLT) { HP(1); Speed(1); Ability(ABILITY_LEVITATE); Moves(MOVE_FLAMETHROWER); Item(item); } + OPPONENT(SPECIES_HYPNO) { Speed(1); Moves(MOVE_IRON_HEAD); } + } WHEN { + if ((ability == ABILITY_MOLD_BREAKER) && (item != ITEM_ABILITY_SHIELD)) + TURN { MOVE(player, MOVE_MUD_SLAP); EXPECT_SEND_OUT(opponent, 2); } + else + TURN { MOVE(player, MOVE_MUD_SLAP); EXPECT_SEND_OUT(opponent, 1); } + } +} + diff --git a/test/battle/ability/mycelium_might.c b/test/battle/ability/mycelium_might.c index 8491aede51..7ffac1c641 100644 --- a/test/battle/ability/mycelium_might.c +++ b/test/battle/ability/mycelium_might.c @@ -67,3 +67,30 @@ SINGLE_BATTLE_TEST("Mycelium Might vs Stall action order depends on speed") } } } + +DOUBLE_BATTLE_TEST("Mycelium Might priority bracket will not change if the ability is changed mid-turn") +{ + GIVEN { + PLAYER(SPECIES_TOEDSCOOL) { Speed(100); Ability(ABILITY_MYCELIUM_MIGHT); } + PLAYER(SPECIES_WOBBUFFET) { Speed(10); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(30); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(20); } + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_WORRY_SEED, target: playerLeft); + MOVE(playerLeft, MOVE_SCREECH, target: opponentLeft); + } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, playerLeft); + + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + } +} diff --git a/test/battle/ability/prankster.c b/test/battle/ability/prankster.c index fd45b94b09..e927c2d94f 100644 --- a/test/battle/ability/prankster.c +++ b/test/battle/ability/prankster.c @@ -7,22 +7,31 @@ ASSUMPTIONS ASSUME(GetMoveCategory(MOVE_CONFUSE_RAY) == DAMAGE_CATEGORY_STATUS); } -SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon") +SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Gen7+)") { + u32 gen; + PARAMETRIZE { gen = GEN_6; } + PARAMETRIZE { gen = GEN_7; } GIVEN { + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } } WHEN { TURN { MOVE(opponent, MOVE_CONFUSE_RAY); } } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); - MESSAGE("It doesn't affect Umbreon…"); + if (gen == GEN_6) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); + } else { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); + MESSAGE("It doesn't affect Umbreon…"); + } } } SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon after they switch-in") { GIVEN { + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } @@ -49,39 +58,62 @@ DOUBLE_BATTLE_TEST("Prankster-affected moves affect Ally Dark-type Pokémon") } } -SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark-type Pokémon") +SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark-type Pokémon (Gen 7+)") { + u32 gen; + PARAMETRIZE { gen = GEN_6; } + PARAMETRIZE { gen = GEN_7; } GIVEN { + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_UMBREON); OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CONFUSE_RAY); }; } WHEN { TURN { MOVE(opponent, MOVE_ASSIST); } } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); - MESSAGE("It doesn't affect Umbreon…"); + if (gen == GEN_6) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); + } else { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent); + MESSAGE("It doesn't affect Umbreon…"); + } } } // Tested on Showdown, even though Bulbapedia says otherwise. DOUBLE_BATTLE_TEST("Prankster-affected moves called via Instruct do not affect Dark-type Pokémon") { + u32 gen; + PARAMETRIZE { gen = GEN_6; } + PARAMETRIZE { gen = GEN_7; } GIVEN { + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen); PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); } PLAYER(SPECIES_WOBBUFFET) { Speed(10);} - OPPONENT(SPECIES_UMBREON) { Speed(1); } + OPPONENT(SPECIES_UMBREON) { Speed(15); } OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } + OPPONENT(SPECIES_UMBREON) { Speed(1); } } WHEN { TURN { MOVE(playerLeft, MOVE_CONFUSE_RAY, target: opponentLeft); + MOVE(opponentLeft, MOVE_U_TURN, target: playerRight, WITH_RNG(RNG_CONFUSION, FALSE)); + SEND_OUT(opponentLeft, 2); MOVE(playerRight, MOVE_INSTRUCT, target: playerLeft); } } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); - MESSAGE("It doesn't affect the opposing Umbreon…"); + if (gen == GEN_6) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); + } else { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); + MESSAGE("It doesn't affect the opposing Umbreon…"); + } MESSAGE("Wobbuffet used Instruct!"); MESSAGE("Volbeat used Confuse Ray!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); - MESSAGE("It doesn't affect the opposing Umbreon…"); + if (gen == GEN_6) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); + } else { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft); + MESSAGE("It doesn't affect the opposing Umbreon…"); + } } } @@ -171,6 +203,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves which are reflected by Magic Coat c PARAMETRIZE { sableyeAbility = ABILITY_KEEN_EYE; } GIVEN { + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); PLAYER(SPECIES_SABLEYE) { Ability(sableyeAbility); } OPPONENT(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); } } WHEN { diff --git a/test/battle/ability/prism_armor.c b/test/battle/ability/prism_armor.c index 532642d3a2..60c8e238cf 100644 --- a/test/battle/ability/prism_armor.c +++ b/test/battle/ability/prism_armor.c @@ -1,4 +1,25 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Prism Armor (Ability) test titles") +SINGLE_BATTLE_TEST("Prism Armor reduces damage to Super Effective moves by 0.75", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } + PARAMETRIZE { ability = ABILITY_LEVITATE; } + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[0] == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[1] == TYPE_PSYCHIC); + ASSUME(gMovesInfo[MOVE_DARK_PULSE].type == TYPE_DARK); + ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0)); + ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0)); + PLAYER(SPECIES_NECROZMA); + OPPONENT(SPECIES_WEEZING) { Ability(ability); } + } WHEN { + TURN { MOVE(opponent, MOVE_DARK_PULSE); } + } SCENE { + HP_BAR(player, captureDamage: &results[i].damage); + MESSAGE("It's super effective!"); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + } +} diff --git a/test/battle/ability/solid_rock.c b/test/battle/ability/solid_rock.c new file mode 100644 index 0000000000..b3dea4ae5e --- /dev/null +++ b/test/battle/ability/solid_rock.c @@ -0,0 +1,25 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Solid Rock reduces damage to Super Effective moves by 0.75", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_STURDY; } + PARAMETRIZE { ability = ABILITY_SOLID_ROCK; } + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[1] == TYPE_ROCK); + ASSUME(gMovesInfo[MOVE_CLOSE_COMBAT].type == TYPE_FIGHTING); + ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_ROCK] > UQ_4_12(1.0)); + ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_WATER] == UQ_4_12(1.0)); + PLAYER(SPECIES_CARRACOSTA) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_CLOSE_COMBAT); } + } SCENE { + HP_BAR(player, captureDamage: &results[i].damage); + MESSAGE("It's super effective!"); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + } +} diff --git a/test/battle/ability/sweet_veil.c b/test/battle/ability/sweet_veil.c index 56431055c6..9560586203 100644 --- a/test/battle/ability/sweet_veil.c +++ b/test/battle/ability/sweet_veil.c @@ -17,7 +17,7 @@ DOUBLE_BATTLE_TEST("Sweet Veil prevents Sleep on partner - right target") } WHEN { TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); } } SCENE { - MESSAGE("Wobbuffet used Hypnosis!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, playerLeft); ABILITY_POPUP(opponentLeft, ABILITY_SWEET_VEIL); NOT STATUS_ICON(opponentRight, sleep: TRUE); } @@ -33,7 +33,27 @@ DOUBLE_BATTLE_TEST("Sweet Veil prevents Sleep on partner - left target") } WHEN { TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentLeft); } } SCENE { - MESSAGE("Wobbuffet used Hypnosis!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, playerLeft); + ABILITY_POPUP(opponentRight, ABILITY_SWEET_VEIL); + NOT STATUS_ICON(opponentLeft, sleep: TRUE); + } +} + +DOUBLE_BATTLE_TEST("Sweet Veil prevents Yawn activation") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_BOUNSWEET) { Ability(ABILITY_SWEET_VEIL); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_YAWN, target: opponentLeft); } + TURN { SWITCH(opponentRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft); + + // Turn 2 ABILITY_POPUP(opponentRight, ABILITY_SWEET_VEIL); NOT STATUS_ICON(opponentLeft, sleep: TRUE); } diff --git a/test/battle/ability/weak_armor.c b/test/battle/ability/weak_armor.c index f4d7e64afa..c443d39c20 100644 --- a/test/battle/ability/weak_armor.c +++ b/test/battle/ability/weak_armor.c @@ -7,17 +7,18 @@ ASSUMPTIONS ASSUME(!IsBattleMoveStatus(MOVE_GUST)); ASSUME(GetMoveCategory(MOVE_GUST) == DAMAGE_CATEGORY_SPECIAL); ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL); - ASSUME(B_WEAK_ARMOR_SPEED >= GEN_7); } -SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 2 when hit by a physical attack") +SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 1 (Gen5-6) or 2 (Gen7+) when hit by a physical attack") { - u16 move; + u16 move, gen; - PARAMETRIZE { move = MOVE_SCRATCH; } - PARAMETRIZE { move = MOVE_GUST; } + PARAMETRIZE { move = MOVE_SCRATCH; gen = GEN_6; } + PARAMETRIZE { move = MOVE_SCRATCH; gen = GEN_7; } + PARAMETRIZE { move = MOVE_GUST; gen = GEN_7; } GIVEN { + WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen); PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -28,20 +29,19 @@ SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 2 when hi if (move == MOVE_SCRATCH) { ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); } else { NONE_OF { ABILITY_POPUP(player, ABILITY_WEAK_ARMOR); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor lowered its Defense!"); - MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); } } } THEN { if (move == MOVE_SCRATCH) { EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1); - EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + (gen == GEN_7 ? 2 : 1)); + } else { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); } } } @@ -79,7 +79,12 @@ SINGLE_BATTLE_TEST("Weak Armor does not trigger when brought in by Dragon Tail a SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower") { + u16 gen; + + PARAMETRIZE { gen = GEN_6; } + PARAMETRIZE { gen = GEN_7; } GIVEN { + WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen); PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -97,10 +102,14 @@ SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower" } MESSAGE("Slugma's Defense won't go any lower!"); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); - MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); + if (gen == GEN_6) + MESSAGE("Slugma's Weak Armor raised its Speed!"); + else + MESSAGE("Slugma's Weak Armor sharply raised its Speed!"); + } THEN { EXPECT_EQ(player->statStages[STAT_DEF], MIN_STAT_STAGE); - EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + (gen == GEN_7 ? 2 : 1)); } } @@ -135,6 +144,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Defense can' { u32 j; GIVEN { + WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7); PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); } OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); } } WHEN { @@ -173,6 +183,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Speed can't { u32 j; GIVEN { + WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7); PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); } OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); } } WHEN { diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index b867eca087..e5c88a2ff3 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -596,6 +596,25 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently") } } +AI_DOUBLE_BATTLE_TEST("AI uses Trick Room with both battlers on the turn it expires in line with the double Trick Room config") +{ + PASSES_RANDOMLY(DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE, 100, RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN); + GIVEN { + ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE); + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_WOBBUFFET) { Speed(3); } + OPPONENT(SPECIES_WYNAUT) { Moves(MOVE_TRICK_ROOM, MOVE_PSYCHIC); Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TRICK_ROOM, MOVE_PSYCHIC); Speed(1); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + TURN { EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); } + } +} + AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if it's about to die") { u32 hp; diff --git a/test/battle/ai/ai_flag_risky.c b/test/battle/ai/ai_flag_risky.c index 5af51b9e8c..befefb814b 100644 --- a/test/battle/ai/ai_flag_risky.c +++ b/test/battle/ai/ai_flag_risky.c @@ -64,13 +64,14 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: Mid-battle switches prioritize offensive o PARAMETRIZE { aiRiskyFlag = AI_FLAG_RISKY; } GIVEN { + ASSUME(P_UPDATED_STATS >= GEN_7); // Swellow's 50 Sp.Atk in Gen 6 instead of the current 75 causes the AI to switch to Electrode AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT | aiRiskyFlag); PLAYER(SPECIES_SWELLOW) { Level(30); Moves(MOVE_WING_ATTACK, MOVE_BOOMBURST); Speed(5); } OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(4); } // Forces switchout OPPONENT(SPECIES_ARON) { Level(30); Moves(MOVE_HEADBUTT); Speed(4); SpDefense(41); } // Mid battle, AI sends out Aron OPPONENT(SPECIES_ELECTRODE) { Level(30); Moves(MOVE_CHARGE_BEAM); Speed(6); Ability(ABILITY_STATIC); } } WHEN { - TURN { MOVE(player, MOVE_WING_ATTACK); EXPECT_SWITCH(opponent, aiRiskyFlag? 2 : 1); } + TURN { MOVE(player, MOVE_WING_ATTACK); EXPECT_SWITCH(opponent, aiRiskyFlag? 2 : 1); } } } diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index a0532a5df3..b1aad9afb2 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1033,7 +1033,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch into mon with good type matchup AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI correctly handles abilities when scoring moves") { GIVEN { - ASSUME(B_PRANKSTER_DARK_TYPES >= GEN_7); + WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7); ASSUME(GetSpeciesType(SPECIES_GRENINJA, 1) == TYPE_DARK); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES); PLAYER(SPECIES_GRENINJA) { Moves(MOVE_WATER_GUN); } diff --git a/test/battle/ai/can_use_all_moves.c b/test/battle/ai/can_use_all_moves.c index 8b6e985a93..78f7e3bda8 100644 --- a/test/battle/ai/can_use_all_moves.c +++ b/test/battle/ai/can_use_all_moves.c @@ -62,7 +62,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 1-100") { u32 moveStart = 0; u32 moveCap = 100; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -92,7 +92,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 1-100") case EFFECT_DISABLE: // tests exist elsewhere - + // Skipped on purpose. case EFFECT_PROTECT: case EFFECT_NON_VOLATILE_STATUS: @@ -124,7 +124,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 101-200") { u32 moveStart = 100; u32 moveCap = 200; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -200,7 +200,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 201-300") { u32 moveStart = 200; u32 moveCap = 300; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -285,7 +285,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400") { u32 moveStart = 300; u32 moveCap = 400; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -329,7 +329,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400") case EFFECT_GRAVITY: case EFFECT_HEAL_BELL: case EFFECT_ATTACK_UP_USER_ALLY: - + // Skipped on purpose. case EFFECT_PROTECT: case EFFECT_NON_VOLATILE_STATUS: @@ -361,7 +361,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500") { u32 moveStart = 400; u32 moveCap = 500; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -390,12 +390,13 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500") //TODO: AI TESTS case EFFECT_RESTORE_HP: case EFFECT_CAPTIVATE: + case EFFECT_DARK_VOID: // Gen 4-6's case is not being handled // tests exist elsewhere case EFFECT_TRICK_ROOM: case EFFECT_GUARD_SPLIT: case EFFECT_POWER_SPLIT: - + // Skipped on purpose. case EFFECT_PROTECT: case EFFECT_NON_VOLATILE_STATUS: @@ -427,7 +428,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 501-600") { u32 moveStart = 515; u32 moveCap = 600; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -502,7 +503,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700") { u32 moveStart = 600; u32 moveCap = 700; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -574,7 +575,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 701-800") { u32 moveStart = 700; u32 moveCap = 800; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; @@ -643,7 +644,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 801-900") { u32 moveStart = 800; u32 moveCap = 900; - + if (moveCap > MOVES_COUNT) moveCap = MOVES_COUNT - 1; diff --git a/test/battle/form_change/mega_evolution.c b/test/battle/form_change/mega_evolution.c index eea438229a..8cce1a084d 100644 --- a/test/battle/form_change/mega_evolution.c +++ b/test/battle/form_change/mega_evolution.c @@ -71,10 +71,26 @@ SINGLE_BATTLE_TEST("Rayquaza can Mega Evolve knowing Dragon Ascent") } } -SINGLE_BATTLE_TEST("Mega Evolution affects turn order") +SINGLE_BATTLE_TEST("Mega Evolution doesn't affect turn order (Gen6)") { GIVEN { - ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_6); + PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(106); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Celebrate!"); + MESSAGE("Gardevoir used Celebrate!"); + } THEN { + ASSUME(player->speed == 205); + } +} + +SINGLE_BATTLE_TEST("Mega Evolution affects turn order (Gen7+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); } OPPONENT(SPECIES_WOBBUFFET) { Speed(106); } } WHEN { @@ -90,7 +106,7 @@ SINGLE_BATTLE_TEST("Mega Evolution affects turn order") SINGLE_BATTLE_TEST("Abilities replaced by Mega Evolution do not affect turn order") { GIVEN { - ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); ASSUME(GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 0) != ABILITY_STALL && GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 1) != ABILITY_STALL); PLAYER(SPECIES_SABLEYE) { Item(ITEM_SABLENITE); Ability(ABILITY_STALL); Speed(105); } diff --git a/test/battle/form_change/ultra_burst.c b/test/battle/form_change/ultra_burst.c index 640db3f881..9d7ec1c396 100644 --- a/test/battle/form_change/ultra_burst.c +++ b/test/battle/form_change/ultra_burst.c @@ -58,7 +58,7 @@ DOUBLE_BATTLE_TEST("Ultra Burst's order is determined by Speed - player faster") SINGLE_BATTLE_TEST("Ultra Burst affects turn order") { GIVEN { - ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7); + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z); Speed(105); } OPPONENT(SPECIES_WOBBUFFET) { Speed(106); } } WHEN { diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index e0a13971be..3e2f0c93e4 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -1018,11 +1018,11 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Volt Crash paralyzes both opponents") } SCENE { MESSAGE("Pikachu used G-Max Volt Crash!"); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft); - STATUS_ICON(opponentLeft, paralysis: TRUE); MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentLeft, paralysis: TRUE); ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentRight); - STATUS_ICON(opponentRight, paralysis: TRUE); MESSAGE("The opposing Wynaut is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentRight, paralysis: TRUE); } } @@ -1048,22 +1048,22 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Stun Shock paralyzes or poisons both opponent // opponent left ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft); if (statusAnim == B_ANIM_STATUS_PSN) { - STATUS_ICON(opponentLeft, poison: TRUE); MESSAGE("The opposing Wobbuffet was poisoned!"); + STATUS_ICON(opponentLeft, poison: TRUE); } else { - STATUS_ICON(opponentLeft, paralysis: TRUE); MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentLeft, paralysis: TRUE); } // opponent right ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight); if (statusAnim == B_ANIM_STATUS_PSN) { - STATUS_ICON(opponentRight, poison: TRUE); MESSAGE("The opposing Wynaut was poisoned!"); + STATUS_ICON(opponentRight, poison: TRUE); } else { - STATUS_ICON(opponentRight, paralysis: TRUE); MESSAGE("The opposing Wynaut is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentRight, paralysis: TRUE); } } } @@ -1118,30 +1118,30 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Befuddle paralyzes, poisons, or sleeps both o // opponent left ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft); if (statusAnim == B_ANIM_STATUS_PSN) { - STATUS_ICON(opponentLeft, poison: TRUE); MESSAGE("The opposing Wobbuffet was poisoned!"); + STATUS_ICON(opponentLeft, poison: TRUE); } else if (statusAnim == B_ANIM_STATUS_PRZ) { - STATUS_ICON(opponentLeft, paralysis: TRUE); MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentLeft, paralysis: TRUE); } else { - STATUS_ICON(opponentLeft, sleep: TRUE); MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentLeft, sleep: TRUE); } // opponent right ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight); if (statusAnim == B_ANIM_STATUS_PSN) { - STATUS_ICON(opponentRight, poison: TRUE); MESSAGE("The opposing Wobbuffet was poisoned!"); + STATUS_ICON(opponentRight, poison: TRUE); } else if (statusAnim == B_ANIM_STATUS_PRZ) { - STATUS_ICON(opponentRight, paralysis: TRUE); MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!"); + STATUS_ICON(opponentRight, paralysis: TRUE); } else { - STATUS_ICON(opponentRight, sleep: TRUE); MESSAGE("The opposing Wobbuffet fell asleep!"); + STATUS_ICON(opponentRight, sleep: TRUE); } } } diff --git a/test/battle/gimmick/zmove.c b/test/battle/gimmick/zmove.c index e1acb4e406..2495ec0b60 100644 --- a/test/battle/gimmick/zmove.c +++ b/test/battle/gimmick/zmove.c @@ -6,9 +6,10 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Z-Moves do not retain priority") { GIVEN { + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL); - PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); } - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Speed(1); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } } WHEN { TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); } diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index a4696eb8ff..600af04515 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -317,3 +317,24 @@ DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after } } } + +SINGLE_BATTLE_TEST("Eject Pack does not activate if mon is switched in due to Eject Button") +{ + GIVEN { + PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_BULLDOZE); + SEND_OUT(opponent, 1); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("The opposing Wobbuffet is switched out with the Eject Button!"); + MESSAGE("2 sent out Wobbuffet!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} diff --git a/test/battle/hold_effect/lagging_tail.c b/test/battle/hold_effect/lagging_tail.c new file mode 100644 index 0000000000..13312034e1 --- /dev/null +++ b/test/battle/hold_effect/lagging_tail.c @@ -0,0 +1,31 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL); +} + +DOUBLE_BATTLE_TEST("Lagging Tail priority bracket will not change if the item is removed is changed mid-turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); Item(ITEM_LAGGING_TAIL); } + PLAYER(SPECIES_WYNAUT) { Speed(10); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(30); Item(ITEM_BERRY_JUICE); } + OPPONENT(SPECIES_WYNAUT) { Speed(20); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_TRICK, target: playerLeft); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); // Now last because of Tricking Lagging Tail onto itself + } +} diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c index 2f1514538c..81ddd614db 100644 --- a/test/battle/hold_effect/life_orb.c +++ b/test/battle/hold_effect/life_orb.c @@ -131,3 +131,22 @@ SINGLE_BATTLE_TEST("Life Orb activates if move connected but no damage was dealt MESSAGE("Wobbuffet was hurt by the Life Orb!"); } } + +SINGLE_BATTLE_TEST("Life Orb does not activate on a charge turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLY); } + TURN { SKIP_TURN(player); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, player); + NONE_OF { + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + } + HP_BAR(opponent); + HP_BAR(player); // Lief Orb + } +} diff --git a/test/battle/move_effect/beak_blast.c b/test/battle/move_effect/beak_blast.c index 8c28e7f8ea..b879a198c8 100644 --- a/test/battle/move_effect/beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -112,6 +112,21 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used") } } +SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1]); + PLAYER(SPECIES_ARCANINE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + NOT STATUS_ICON(player, burn: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAK_BLAST, opponent); + } +} + TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed"); TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move"); TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes"); diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c index dd0d19925f..e584ccc0f9 100644 --- a/test/battle/move_effect/beat_up.c +++ b/test/battle/move_effect/beat_up.c @@ -2,7 +2,32 @@ #include "test/battle.h" // General -TO_DO_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party"); +SINGLE_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_PICHU) + PLAYER(SPECIES_PIKACHU) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_RAICHU) + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BEAT_UP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player); + MESSAGE("The Pokémon was hit 4 time(s)!"); + } THEN { + EXPECT_EQ(gBattleStruct->beatUpSpecies[0], SPECIES_WOBBUFFET); + EXPECT_EQ(gBattleStruct->beatUpSpecies[1], SPECIES_WYNAUT); + EXPECT_EQ(gBattleStruct->beatUpSpecies[2], SPECIES_PICHU); + EXPECT_EQ(gBattleStruct->beatUpSpecies[3], SPECIES_RAICHU); + } +} + TO_DO_BATTLE_TEST("Beat Up doesn't consider Comatose as a status") TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit"); diff --git a/test/battle/move_effect/copycat.c b/test/battle/move_effect/copycat.c index 6b14df8615..34f3551676 100644 --- a/test/battle/move_effect/copycat.c +++ b/test/battle/move_effect/copycat.c @@ -45,6 +45,7 @@ SINGLE_BATTLE_TEST("Copycat deducts power points from itself, not the copied mov DOUBLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can have their base moves copied by Copycat") { GIVEN { + WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/destiny_bond.c b/test/battle/move_effect/destiny_bond.c index 0713a4858a..ddebc6bb1f 100644 --- a/test/battle/move_effect/destiny_bond.c +++ b/test/battle/move_effect/destiny_bond.c @@ -1,7 +1,7 @@ #include "global.h" #include "test/battle.h" -ASSUMPTIONS +ASSUMPTIONS { ASSUME(GetMoveEffect(MOVE_DESTINY_BOND) == EFFECT_DESTINY_BOND); } @@ -21,10 +21,28 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the } } -SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+") +SINGLE_BATTLE_TEST("Destiny Bond doesn't fail if used sequentially (Gen2-6)") { GIVEN { - ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_6); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); } + TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + MESSAGE("2 sent out Zigzagoon!"); + NOT { MESSAGE("But it failed!"); } + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + } +} + +SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially (Gen7+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -39,10 +57,10 @@ SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+") } } -SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves in Gen 7+") +SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves (Gen7+)") { GIVEN { - ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -58,10 +76,10 @@ SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by o } } -SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing in Gen 7+") +SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing (Gen7+)") { GIVEN { - ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7); PLAYER(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); @@ -108,4 +126,3 @@ TO_DO_BATTLE_TEST("Destiny Bond's effect can trigger on the next turn if the use TO_DO_BATTLE_TEST("Destiny Bond can be used multiple times in a row (Gen 2-6)"); TO_DO_BATTLE_TEST("Destiny Bond always fails if it was successfully used the previous turn (Gen 7+)"); TO_DO_BATTLE_TEST("Destiny Bond cannot be used in Raids"); - diff --git a/test/battle/move_effect/embargo.c b/test/battle/move_effect/embargo.c index 4b06b92fc1..41c456d9ac 100644 --- a/test/battle/move_effect/embargo.c +++ b/test/battle/move_effect/embargo.c @@ -77,7 +77,7 @@ WILD_BATTLE_TEST("Embargo doesn't block held item effects that affect effort val PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_WEIGHT); } OPPONENT(SPECIES_CATERPIE) { HP(1); } ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffect == HOLD_EFFECT_POWER_ITEM); - ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffectParam == 8); + ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffectParam != 0); ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].secondaryId == STAT_HP); ASSUME(gSpeciesInfo[SPECIES_CATERPIE].evYield_HP == 1); } WHEN { diff --git a/test/battle/move_effect/endure.c b/test/battle/move_effect/endure.c index 5401321162..f332fc28de 100644 --- a/test/battle/move_effect/endure.c +++ b/test/battle/move_effect/endure.c @@ -27,6 +27,33 @@ SINGLE_BATTLE_TEST("Endure does not prevent multiple hits and stat changes occur } } +DOUBLE_BATTLE_TEST("Endure is not transferred to a mon that is switched in due to Eject Button") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { HP(1); Item(ITEM_EJECT_BUTTON); } + OPPONENT(SPECIES_SQUIRTLE) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentRight, MOVE_ENDURE); + MOVE(playerLeft, MOVE_POUND, target: opponentRight); + SEND_OUT(opponentRight, 2); + MOVE(playerRight, MOVE_POUND, target: opponentRight); + SEND_OUT(opponentRight, 3); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); + MESSAGE("The opposing Wynaut endured the hit!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + NOT MESSAGE("The opposing Squirtle endured the hit!"); + } +} + TO_DO_BATTLE_TEST("Endure's success rate decreases for every consecutively used turn"); TO_DO_BATTLE_TEST("Endure uses the same counter as Protect"); TO_DO_BATTLE_TEST("Endure doesn't trigger effects that require damage to be done to the Pokémon (Gen 2-4)"); // Eg. Rough Skin diff --git a/test/battle/move_effect/entrainment.c b/test/battle/move_effect/entrainment.c index fd47937f04..ac6050bbe0 100644 --- a/test/battle/move_effect/entrainment.c +++ b/test/battle/move_effect/entrainment.c @@ -58,4 +58,19 @@ SINGLE_BATTLE_TEST("Entrainment fails if the target's ability has cantBeOverwrit } } +SINGLE_BATTLE_TEST("Entrainment causes primal weather to revert") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + } WHEN { + TURN { MOVE(player, MOVE_ENTRAINMENT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ENTRAINMENT, player); + MESSAGE("The extremely harsh sunlight faded!"); + } THEN { + EXPECT(opponent->ability == ABILITY_TELEPATHY); + } +} + TO_DO_BATTLE_TEST("Entrainment fails on Dynamaxed Pokémon"); diff --git a/test/battle/move_effect/focus_punch.c b/test/battle/move_effect/focus_punch.c index e186c094a8..3f8f96d4c4 100644 --- a/test/battle/move_effect/focus_punch.c +++ b/test/battle/move_effect/focus_punch.c @@ -119,7 +119,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use status moves if the player's best attacking ASSUME(GetMoveEffect(MOVE_FOCUS_PUNCH) == EFFECT_FOCUS_PUNCH); ASSUME(GetMoveCategory(MOVE_SWORDS_DANCE) == DAMAGE_CATEGORY_STATUS); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT); - PLAYER(SPECIES_SNORLAX) { Moves(MOVE_FOCUS_PUNCH, MOVE_TACKLE); } + PLAYER(SPECIES_SNORLAX) { Moves(MOVE_FOCUS_PUNCH, MOVE_POUND); } OPPONENT(SPECIES_CLEFABLE) { Moves(MOVE_PLAY_ROUGH, MOVE_SWORDS_DANCE); } } WHEN { TURN { MOVE(player, MOVE_FOCUS_PUNCH); EXPECT_MOVE(opponent, MOVE_PLAY_ROUGH); } diff --git a/test/battle/move_effect/powder.c b/test/battle/move_effect/powder.c index 0cbe273ef2..c4e053db87 100644 --- a/test/battle/move_effect/powder.c +++ b/test/battle/move_effect/powder.c @@ -80,10 +80,27 @@ SINGLE_BATTLE_TEST("Powder doesn't damage target if it has Magic Guard") } } -SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain") +SINGLE_BATTLE_TEST("Powder damages the target under heavy rain (Gen 6)") { GIVEN { - ASSUME(B_POWDER_RAIN >= GEN_7); + WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_6); + PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); } + OPPONENT(SPECIES_VIVILLON); + } WHEN { + TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(player); + } THEN { + EXPECT_LT(player->hp, player->maxHP); + } +} + +SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain (Gen 7+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_7); PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); } OPPONENT(SPECIES_VIVILLON); } WHEN { @@ -92,7 +109,7 @@ SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain") ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent); NONE_OF { ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); - HP_BAR(opponent); + HP_BAR(player); } } THEN { EXPECT_EQ(player->maxHP, player->hp); diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 2f7cfeba5e..97a09bd922 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -675,3 +675,58 @@ SINGLE_BATTLE_TEST("Protect: Protective Pads protects from secondary effects") } } } + +DOUBLE_BATTLE_TEST("Protect is not transferred to a mon that is switched in due to Eject Button") +{ + GIVEN { + PLAYER(SPECIES_URSHIFU) { Ability(ABILITY_UNSEEN_FIST); }; + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); } + OPPONENT(SPECIES_SQUIRTLE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentRight, MOVE_PROTECT); + MOVE(playerLeft, MOVE_POUND, target: opponentRight); + SEND_OUT(opponentRight, 2); + MOVE(playerRight, MOVE_POUND, target: opponentRight); + SEND_OUT(opponentRight, 3); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight); + HP_BAR(opponentRight); + } +} + +DOUBLE_BATTLE_TEST("Wide Guard is still activate even if user is switched out due to Eject Button") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); } + OPPONENT(SPECIES_SQUIRTLE); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentRight, MOVE_WIDE_GUARD); + MOVE(playerLeft, MOVE_POUND, target: opponentRight); + SEND_OUT(opponentRight, 2); + MOVE(playerRight, MOVE_HYPER_VOICE, target: opponentRight); + SEND_OUT(opponentRight, 3); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WIDE_GUARD, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerRight); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + } + } +} diff --git a/test/battle/move_effect/rage_fist.c b/test/battle/move_effect/rage_fist.c index 5d92544e53..a750893d11 100644 --- a/test/battle/move_effect/rage_fist.c +++ b/test/battle/move_effect/rage_fist.c @@ -251,7 +251,6 @@ SINGLE_BATTLE_TEST("Rage Fist base power is not increased if move had no affect" SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen7)") { - KNOWN_FAILING; s16 timesGotHit[2]; u16 species = SPECIES_NONE; diff --git a/test/battle/move_effect/role_play.c b/test/battle/move_effect/role_play.c index d2d937f7d1..1a05f02d4a 100644 --- a/test/battle/move_effect/role_play.c +++ b/test/battle/move_effect/role_play.c @@ -19,7 +19,7 @@ SINGLE_BATTLE_TEST("Role Play copies target's ability") } THEN { EXPECT_EQ(player->ability, ABILITY_BLAZE); EXPECT_EQ(opponent->ability, ABILITY_BLAZE); - } + } } DOUBLE_BATTLE_TEST("Role Play copies target's current ability even if it changed during that turn") @@ -93,7 +93,8 @@ SINGLE_BATTLE_TEST("Role Play fails if user's ability can't be suppressed") u32 species, ability; PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; } - PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } + if (B_UPDATED_ABILITY_DATA >= GEN_7) + PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; } PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; } PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; } PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; } diff --git a/test/battle/move_effect/sheer_cold.c b/test/battle/move_effect/sheer_cold.c index 2cb469e92d..77ecb55bf7 100644 --- a/test/battle/move_effect/sheer_cold.c +++ b/test/battle/move_effect/sheer_cold.c @@ -6,10 +6,26 @@ ASSUMPTIONS ASSUME(GetMoveEffect(MOVE_SHEER_COLD) == EFFECT_SHEER_COLD); } -SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon") +SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen3-6)") { GIVEN { - ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7); + WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_6); + ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_GLALIE); + } WHEN { + TURN { MOVE(player, MOVE_SHEER_COLD); } + } SCENE { + NOT MESSAGE("It doesn't affect the opposing Glalie…"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player); + HP_BAR(opponent, hp: 0); + } +} + +SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen7+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_GLALIE); diff --git a/test/battle/move_effect/uproar.c b/test/battle/move_effect/uproar.c index 23bcdce458..93f8be9c5b 100644 --- a/test/battle/move_effect/uproar.c +++ b/test/battle/move_effect/uproar.c @@ -27,3 +27,17 @@ DOUBLE_BATTLE_TEST("Uproar status causes sleeping Pokémon to wake up during an ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); } } + +SINGLE_BATTLE_TEST("Uproar wakes up other pokemon on field") +{ + GIVEN { + ASSUME(B_UPROAR_TURNS >= GEN_5); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_UPROAR); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_UPROAR, opponent); + MESSAGE("The uproar woke Wobbuffet!"); + } +} diff --git a/test/battle/move_effect_secondary/wrap.c b/test/battle/move_effect_secondary/wrap.c new file mode 100644 index 0000000000..dc05bbe288 --- /dev/null +++ b/test/battle/move_effect_secondary/wrap.c @@ -0,0 +1,86 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(MoveHasAdditionalEffect(MOVE_WRAP, MOVE_EFFECT_WRAP)); +} + +SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 5 turns 50% of the time") +{ + PASSES_RANDOMLY(50, 100, RNG_WRAP); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WRAP); } + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player); + HP_BAR(opponent); // Direct damage + + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + NOT HP_BAR(opponent); // Residual Damage + } +} + +SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 4 turns 50% of the time") +{ + PASSES_RANDOMLY(50, 100, RNG_WRAP); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WRAP); } + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player); + HP_BAR(opponent); // Direct damage + + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + NOT HP_BAR(opponent); // Residual Damage + } +} + +SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon 7 turns while holding a Grip Claw") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRIP_CLAW); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WRAP); } + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player); + HP_BAR(opponent); // Direct damage + + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + HP_BAR(opponent); // Residual Damage + NOT HP_BAR(opponent); // Residual Damage + } +} diff --git a/test/battle/sleep_clause.c b/test/battle/sleep_clause.c index ca416d230e..73f419289c 100644 --- a/test/battle/sleep_clause.c +++ b/test/battle/sleep_clause.c @@ -690,7 +690,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo ASSUME(GetMoveEffect(MOVE_UPROAR) == EFFECT_UPROAR); PLAYER(SPECIES_ZIGZAGOON); PLAYER(SPECIES_ZIGZAGOON); - PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); } OPPONENT(SPECIES_ZIGZAGOON); OPPONENT(SPECIES_ZIGZAGOON); } WHEN { diff --git a/test/battle/status1/paralysis.c b/test/battle/status1/paralysis.c index 0635e83d1d..c81daa9179 100644 --- a/test/battle/status1/paralysis.c +++ b/test/battle/status1/paralysis.c @@ -77,3 +77,17 @@ SINGLE_BATTLE_TEST("Thunder Wave doesn't affect Electric types in Gen6+") MESSAGE("It doesn't affect the opposing Pikachu…"); } } + +SINGLE_BATTLE_TEST("Thunder Wave doesn't print an effectiveness message") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_PIDGEY].types[1] == TYPE_FLYING); + PLAYER(SPECIES_PIDGEY); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_THUNDER_WAVE); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Thunder Wave!"); + NOT MESSAGE("It's super effective!"); + } +} diff --git a/test/battle/trainer_control.c b/test/battle/trainer_control.c index b42c89196c..663a720d3d 100644 --- a/test/battle/trainer_control.c +++ b/test/battle/trainer_control.c @@ -169,6 +169,7 @@ static const struct Trainer sTestTrainer2 = TEST("Trainer Class Balls apply to the entire party") { + ASSUME(B_TRAINER_CLASS_POKE_BALLS >= GEN_8); u32 j; struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainer2, TRUE, BATTLE_TYPE_TRAINER); diff --git a/test/battle/trainer_slides.c b/test/battle/trainer_slides.c index 273885fe75..012ae6e7e9 100644 --- a/test/battle/trainer_slides.c +++ b/test/battle/trainer_slides.c @@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Enemy Mon Unaffected") { gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_MON_UNAFFECTED; GIVEN { - ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7); + WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7); ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_GLALIE); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index ba1c0ba109..f2bb69fa91 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1577,9 +1577,14 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species) (*partySize)++; CreateMon(DATA.currentMon, species, 100, 0, TRUE, 0, OT_ID_PRESET, 0); - data = MOVE_NONE; + // Reset move IDs, but force PP to be non-zero. This is a safeguard against test species that only learn 1 move having test moves with 0 PP for (i = 0; i < MAX_MON_MOVES; i++) + { + data = MOVE_NONE; SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data); + data = 0x7F; // Max PP possible + SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &data); + } data = 0; if (B_FRIENDSHIP_BOOST) { @@ -2148,6 +2153,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &pp); *moveSlot = i; *moveId = ctx->move; + INVALID_IF(GetMovePP(ctx->move) == 0, "%S has 0 PP!", GetMoveName(ctx->move)); break; } } @@ -2248,7 +2254,7 @@ void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx) DATA.battleRecordTurns[DATA.turns][battlerId].secondaryEffect = 1 + ctx.secondaryEffect; if (ctx.explicitRNG) DATA.battleRecordTurns[DATA.turns][battlerId].rng = ctx.rng; - + u32 shellSideArmCount = 0; for (u32 i = 0; i < STATE->battlersCount; i++) { diff --git a/test/text.c b/test/text.c index d635df2072..4f3c4722e1 100644 --- a/test/text.c +++ b/test/text.c @@ -673,7 +673,7 @@ TEST("Battle strings fit on the battle message window") case STRINGID_PKMNSXWOREOFF: case STRINGID_BUFFERENDS: case STRINGID_FOREWARNACTIVATES: - case STRINGID_CUSEDBODYDISABLED: + case STRINGID_CURSEDBODYDISABLED: case STRINGID_CURRENTMOVECANTSELECT: case STRINGID_TARGETISHURTBYSALTCURE: PREPARE_MOVE_BUFFER(gBattleTextBuff1, longMoveID); diff --git a/tools/learnset_helpers/porymoves_files/sv.json b/tools/learnset_helpers/porymoves_files/sv.json index b6f43b8d07..f4fd675c34 100644 --- a/tools/learnset_helpers/porymoves_files/sv.json +++ b/tools/learnset_helpers/porymoves_files/sv.json @@ -208,7 +208,12 @@ "MOVE_DOUBLE_EDGE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_CURSE", + "MOVE_INGRAIN", + "MOVE_PETAL_DANCE", + "MOVE_TOXIC" + ], "TutorMoves": [] }, "VENUSAUR": { @@ -331,7 +336,12 @@ "MOVE_PETAL_BLIZZARD", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_CURSE", + "MOVE_INGRAIN", + "MOVE_PETAL_DANCE", + "MOVE_TOXIC" + ], "TutorMoves": [] }, "CHARMANDER": { @@ -901,7 +911,17 @@ "MOVE_WHIRLPOOL", "MOVE_MUDDY_WATER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AQUA_JET", + "MOVE_AQUA_RING", + "MOVE_FAKE_OUT", + "MOVE_FLAIL", + "MOVE_LIFE_DEW", + "MOVE_MIRROR_COAT", + "MOVE_MIST", + "MOVE_WATER_SPOUT", + "MOVE_YAWN" + ], "TutorMoves": [] }, "BLASTOISE": { @@ -1023,7 +1043,17 @@ "MOVE_WHIRLPOOL", "MOVE_MUDDY_WATER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AQUA_JET", + "MOVE_AQUA_RING", + "MOVE_FAKE_OUT", + "MOVE_FLAIL", + "MOVE_LIFE_DEW", + "MOVE_MIRROR_COAT", + "MOVE_MIST", + "MOVE_WATER_SPOUT", + "MOVE_YAWN" + ], "TutorMoves": [] }, "CATERPIE": { @@ -3203,7 +3233,17 @@ "MOVE_GRASSY_GLIDE", "MOVE_PETAL_BLIZZARD" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AFTER_YOU", + "MOVE_FLAIL", + "MOVE_INGRAIN", + "MOVE_LEECH_SEED", + "MOVE_RAZOR_LEAF", + "MOVE_STRENGTH_SAP", + "MOVE_SYNTHESIS", + "MOVE_TEETER_DANCE", + "MOVE_TICKLE" + ], "TutorMoves": [] }, "VILEPLUME": { @@ -3308,7 +3348,17 @@ "MOVE_PETAL_BLIZZARD", "MOVE_SLUDGE_WAVE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AFTER_YOU", + "MOVE_FLAIL", + "MOVE_INGRAIN", + "MOVE_LEECH_SEED", + "MOVE_RAZOR_LEAF", + "MOVE_STRENGTH_SAP", + "MOVE_SYNTHESIS", + "MOVE_TEETER_DANCE", + "MOVE_TICKLE" + ], "TutorMoves": [] }, "PARAS": { @@ -3880,7 +3930,6 @@ "MOVE_NASTY_PLOT", "MOVE_THUNDER", "MOVE_TERA_BLAST", - "MOVE_SAND_TOMB", "MOVE_SPITE", "MOVE_KNOCK_OFF", "MOVE_LASH_OUT", @@ -5761,7 +5810,17 @@ "MOVE_SKITTER_SMACK", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ACUPRESSURE", + "MOVE_AQUA_RING", + "MOVE_AURORA_BEAM", + "MOVE_CONFUSE_RAY", + "MOVE_HAZE", + "MOVE_KNOCK_OFF", + "MOVE_MIRROR_COAT", + "MOVE_RAPID_SPIN", + "MOVE_TICKLE" + ], "TutorMoves": [] }, "GEODUDE": { @@ -6846,7 +6905,12 @@ "MOVE_FEATHER_DANCE", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ASSURANCE", + "MOVE_FLAIL", + "MOVE_SKY_ATTACK", + "MOVE_WHIRLWIND" + ], "TutorMoves": [] }, "SEEL": { @@ -7094,7 +7158,18 @@ "MOVE_CURSE", "MOVE_ALLURING_VOICE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BELCH", + "MOVE_DISABLE", + "MOVE_ENTRAINMENT", + "MOVE_FAKE_OUT", + "MOVE_HORN_DRILL", + "MOVE_LICK", + "MOVE_PERISH_SONG", + "MOVE_SPIT_UP", + "MOVE_STOCKPILE", + "MOVE_SWALLOW" + ], "TutorMoves": [] }, "GRIMER": { @@ -8764,7 +8839,16 @@ "MOVE_CURSE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_BLOCK", + "MOVE_CURSE", + "MOVE_INGRAIN", + "MOVE_MOONLIGHT", + "MOVE_POISON_POWDER", + "MOVE_SLEEP_POWDER", + "MOVE_STUN_SPORE" + ], "TutorMoves": [] }, "CUBONE": { @@ -8905,7 +8989,15 @@ "MOVE_THROAT_CHOP", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BULLET_PUNCH", + "MOVE_COUNTER", + "MOVE_FEINT", + "MOVE_HIGH_JUMP_KICK", + "MOVE_MACH_PUNCH", + "MOVE_RAPID_SPIN", + "MOVE_VACUUM_WAVE" + ], "TutorMoves": [] }, "HITMONCHAN": { @@ -9043,7 +9135,15 @@ "MOVE_THROAT_CHOP", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BULLET_PUNCH", + "MOVE_COUNTER", + "MOVE_FEINT", + "MOVE_HIGH_JUMP_KICK", + "MOVE_MACH_PUNCH", + "MOVE_RAPID_SPIN", + "MOVE_VACUUM_WAVE" + ], "TutorMoves": [] }, "LICKITUNG": { @@ -9549,7 +9649,14 @@ "MOVE_BREAKING_SWIPE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_CURSE", + "MOVE_DRAGON_RUSH", + "MOVE_GUARD_SPLIT", + "MOVE_METAL_BURST", + "MOVE_ROCK_POLISH" + ], "TutorMoves": [] }, "CHANSEY": { @@ -9906,7 +10013,13 @@ "MOVE_WHIRLPOOL", "MOVE_MUDDY_WATER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AURORA_BEAM", + "MOVE_CLEAR_SMOG", + "MOVE_DISABLE", + "MOVE_FLAIL", + "MOVE_SPLASH" + ], "TutorMoves": [] }, "GOLDEEN": { @@ -10170,7 +10283,14 @@ "MOVE_ELECTROWEB", "MOVE_METAL_SOUND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_CROSS_CHOP", + "MOVE_DYNAMIC_PUNCH", + "MOVE_FEINT", + "MOVE_FOCUS_PUNCH", + "MOVE_FOLLOW_ME", + "MOVE_HAMMER_ARM" + ], "TutorMoves": [] }, "MAGMAR": { @@ -10285,7 +10405,15 @@ "MOVE_SCORCHING_SANDS", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BELCH", + "MOVE_BELLY_DRUM", + "MOVE_CROSS_CHOP", + "MOVE_DYNAMIC_PUNCH", + "MOVE_FOCUS_PUNCH", + "MOVE_FOLLOW_ME", + "MOVE_MACH_PUNCH" + ], "TutorMoves": [] }, "PINSIR": { @@ -13002,7 +13130,14 @@ "MOVE_DOUBLE_EDGE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_COUNTER", + "MOVE_FLAIL", + "MOVE_HEAL_PULSE", + "MOVE_INGRAIN", + "MOVE_VINE_WHIP" + ], "TutorMoves": [] }, "MEGANIUM": { @@ -13122,7 +13257,14 @@ "MOVE_PETAL_BLIZZARD", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_COUNTER", + "MOVE_FLAIL", + "MOVE_HEAL_PULSE", + "MOVE_INGRAIN", + "MOVE_VINE_WHIP" + ], "TutorMoves": [] }, "CYNDAQUIL": { @@ -13726,7 +13868,13 @@ "MOVE_BREAKING_SWIPE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_AQUA_JET", + "MOVE_BLOCK", + "MOVE_COUNTER", + "MOVE_FLATTER" + ], "TutorMoves": [] }, "FERALIGATR": { @@ -13862,7 +14010,13 @@ "MOVE_BREAKING_SWIPE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_AQUA_JET", + "MOVE_BLOCK", + "MOVE_COUNTER", + "MOVE_FLATTER" + ], "TutorMoves": [] }, "SENTRET": { @@ -14857,7 +15011,13 @@ "MOVE_ELECTROWEB", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_MIST", + "MOVE_PSYBEAM", + "MOVE_SOAK", + "MOVE_SUCKER_PUNCH", + "MOVE_WATER_PULSE" + ], "TutorMoves": [] }, "PICHU": { @@ -15641,7 +15801,17 @@ "MOVE_PETAL_BLIZZARD", "MOVE_TRIPLE_AXEL" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AFTER_YOU", + "MOVE_FLAIL", + "MOVE_INGRAIN", + "MOVE_LEECH_SEED", + "MOVE_RAZOR_LEAF", + "MOVE_STRENGTH_SAP", + "MOVE_SYNTHESIS", + "MOVE_TEETER_DANCE", + "MOVE_TICKLE" + ], "TutorMoves": [] }, "MARILL": { @@ -19016,7 +19186,13 @@ "MOVE_TEMPER_FLARE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_MIMIC", + "MOVE_PRESENT", + "MOVE_RETALIATE", + "MOVE_SNORE" + ], "TutorMoves": [] }, "QWILFISH": { @@ -20901,7 +21077,13 @@ "MOVE_MUDDY_WATER", "MOVE_BREAKING_SWIPE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AURORA_BEAM", + "MOVE_CLEAR_SMOG", + "MOVE_DISABLE", + "MOVE_FLAIL", + "MOVE_SPLASH" + ], "TutorMoves": [] }, "PHANPY": { @@ -21573,7 +21755,15 @@ "MOVE_COACHING", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BULLET_PUNCH", + "MOVE_COUNTER", + "MOVE_FEINT", + "MOVE_HIGH_JUMP_KICK", + "MOVE_MACH_PUNCH", + "MOVE_RAPID_SPIN", + "MOVE_VACUUM_WAVE" + ], "TutorMoves": [] }, "SMOOCHUM": { @@ -23304,7 +23494,16 @@ "MOVE_BREAKING_SWIPE", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ABSORB", + "MOVE_DOUBLE_KICK", + "MOVE_DRAGON_BREATH", + "MOVE_LEECH_SEED", + "MOVE_NIGHT_SLASH", + "MOVE_SLASH", + "MOVE_SYNTHESIS", + "MOVE_WORRY_SEED" + ], "TutorMoves": [] }, "SCEPTILE": { @@ -23456,7 +23655,16 @@ "MOVE_DRAGON_CHEER", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ABSORB", + "MOVE_DOUBLE_KICK", + "MOVE_DRAGON_BREATH", + "MOVE_LEECH_SEED", + "MOVE_NIGHT_SLASH", + "MOVE_SLASH", + "MOVE_SYNTHESIS", + "MOVE_WORRY_SEED" + ], "TutorMoves": [] }, "TORCHIC": { @@ -23698,7 +23906,14 @@ "MOVE_FEATHER_DANCE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_CRUSH_CLAW", + "MOVE_FEINT", + "MOVE_LAST_RESORT", + "MOVE_NIGHT_SLASH", + "MOVE_PECK" + ], "TutorMoves": [] }, "BLAZIKEN": { @@ -23853,7 +24068,14 @@ "MOVE_CURSE", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_CRUSH_CLAW", + "MOVE_FEINT", + "MOVE_LAST_RESORT", + "MOVE_NIGHT_SLASH", + "MOVE_PECK" + ], "TutorMoves": [] }, "MUDKIP": { @@ -24090,7 +24312,19 @@ "MOVE_SLUDGE_WAVE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_BITE", + "MOVE_COUNTER", + "MOVE_CURSE", + "MOVE_DOUBLE_EDGE", + "MOVE_MIRROR_COAT", + "MOVE_MUD_SLAP", + "MOVE_SLUDGE", + "MOVE_STOMP", + "MOVE_WIDE_GUARD", + "MOVE_YAWN" + ], "TutorMoves": [] }, "SWAMPERT": { @@ -24238,7 +24472,19 @@ "MOVE_CURSE", "MOVE_HARD_PRESS" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ANCIENT_POWER", + "MOVE_BITE", + "MOVE_COUNTER", + "MOVE_CURSE", + "MOVE_DOUBLE_EDGE", + "MOVE_MIRROR_COAT", + "MOVE_MUD_SLAP", + "MOVE_SLUDGE", + "MOVE_STOMP", + "MOVE_WIDE_GUARD", + "MOVE_YAWN" + ], "TutorMoves": [] }, "POOCHYENA": { @@ -27938,6 +28184,10 @@ }, "PLUSLE": { "LevelMoves": [ + { + "Level": 1, + "Move": "MOVE_NUZZLE" + }, { "Level": 1, "Move": "MOVE_QUICK_ATTACK" @@ -28067,6 +28317,10 @@ }, "MINUN": { "LevelMoves": [ + { + "Level": 1, + "Move": "MOVE_NUZZLE" + }, { "Level": 1, "Move": "MOVE_QUICK_ATTACK" @@ -29650,7 +29904,15 @@ "MOVE_SCORCHING_SANDS", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BUG_BITE", + "MOVE_FEINT", + "MOVE_FIRST_IMPRESSION", + "MOVE_FLAIL", + "MOVE_FURY_CUTTER", + "MOVE_GUST", + "MOVE_QUICK_ATTACK" + ], "TutorMoves": [] }, "FLYGON": { @@ -29817,7 +30079,15 @@ "MOVE_ALLURING_VOICE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BUG_BITE", + "MOVE_FEINT", + "MOVE_FIRST_IMPRESSION", + "MOVE_FLAIL", + "MOVE_FURY_CUTTER", + "MOVE_GUST", + "MOVE_QUICK_ATTACK" + ], "TutorMoves": [] }, "CACNEA": { @@ -30092,7 +30362,16 @@ "MOVE_THROAT_CHOP", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ACID", + "MOVE_BELCH", + "MOVE_BLOCK", + "MOVE_COUNTER", + "MOVE_DISABLE", + "MOVE_FELL_STINGER", + "MOVE_SWITCHEROO", + "MOVE_TEETER_DANCE" + ], "TutorMoves": [] }, "SWABLU": { @@ -36598,7 +36877,12 @@ "MOVE_CURSE", "MOVE_DRAGON_CHEER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_HAMMER_ARM", + "MOVE_STOMP", + "MOVE_THRASH", + "MOVE_WHIRLWIND" + ], "TutorMoves": [] }, "SHIELDON": { @@ -36828,7 +37112,14 @@ "MOVE_CURSE", "MOVE_HARD_PRESS" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_FISSURE", + "MOVE_FOCUS_ENERGY", + "MOVE_GUARD_SPLIT", + "MOVE_HEADBUTT", + "MOVE_SCREECH" + ], "TutorMoves": [] }, "BURMY": { @@ -39739,8 +40030,7 @@ "MOVE_CROSS_CHOP", "MOVE_DETECT", "MOVE_HI_JUMP_KICK", - "MOVE_HOWL", - "MOVE_HIGH_JUMP_KICK" + "MOVE_HOWL" ], "TutorMoves": [] }, @@ -41332,7 +41622,14 @@ "MOVE_BREAKING_SWIPE", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_CURSE", + "MOVE_DRAGON_RUSH", + "MOVE_GUARD_SPLIT", + "MOVE_METAL_BURST", + "MOVE_ROCK_POLISH" + ], "TutorMoves": [] }, "TANGROWTH": { @@ -41463,7 +41760,14 @@ "MOVE_ELECTROWEB", "MOVE_METAL_SOUND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_CROSS_CHOP", + "MOVE_DYNAMIC_PUNCH", + "MOVE_FEINT", + "MOVE_FOCUS_PUNCH", + "MOVE_FOLLOW_ME", + "MOVE_HAMMER_ARM" + ], "TutorMoves": [] }, "MAGMORTAR": { @@ -41587,7 +41891,15 @@ "MOVE_SCORCHING_SANDS", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BELCH", + "MOVE_BELLY_DRUM", + "MOVE_CROSS_CHOP", + "MOVE_DYNAMIC_PUNCH", + "MOVE_FOCUS_PUNCH", + "MOVE_FOLLOW_ME", + "MOVE_MACH_PUNCH" + ], "TutorMoves": [] }, "TOGEKISS": { @@ -45225,7 +45537,15 @@ "MOVE_DOUBLE_EDGE", "MOVE_PETAL_BLIZZARD" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_GLARE", + "MOVE_IRON_TAIL", + "MOVE_MEAN_LOOK", + "MOVE_MIRROR_COAT", + "MOVE_SWEET_SCENT", + "MOVE_SYNTHESIS", + "MOVE_TWISTER" + ], "TutorMoves": [] }, "SERPERIOR": { @@ -45332,7 +45652,15 @@ "MOVE_PETAL_BLIZZARD", "MOVE_BREAKING_SWIPE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_GLARE", + "MOVE_IRON_TAIL", + "MOVE_MEAN_LOOK", + "MOVE_MIRROR_COAT", + "MOVE_SWEET_SCENT", + "MOVE_SYNTHESIS", + "MOVE_TWISTER" + ], "TutorMoves": [] }, "TEPIG": { @@ -45576,7 +45904,12 @@ "MOVE_COACHING", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_SUCKER_PUNCH", + "MOVE_SUPERPOWER", + "MOVE_THRASH", + "MOVE_YAWN" + ], "TutorMoves": [] }, "EMBOAR": { @@ -45720,7 +46053,12 @@ "MOVE_CURSE", "MOVE_HARD_PRESS" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_SUCKER_PUNCH", + "MOVE_SUPERPOWER", + "MOVE_THRASH", + "MOVE_YAWN" + ], "TutorMoves": [] }, "OSHAWOTT": { @@ -46408,7 +46746,12 @@ "MOVE_SUPERCELL_SLAM", "MOVE_ELECTROWEB" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_DOUBLE_KICK", + "MOVE_FEINT", + "MOVE_SAND_ATTACK", + "MOVE_SCREECH" + ], "TutorMoves": [] }, "ROGGENROLA": { @@ -46664,7 +47007,10 @@ "MOVE_METAL_SOUND", "MOVE_CURSE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_METAL_SOUND", + "MOVE_SLASH" + ], "TutorMoves": [] }, "AUDINO": { @@ -47592,7 +47938,13 @@ "MOVE_GRASSY_GLIDE", "MOVE_ENDEAVOR" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BEAT_UP", + "MOVE_MEMENTO", + "MOVE_SWITCHEROO", + "MOVE_TICKLE", + "MOVE_WORRY_SEED" + ], "TutorMoves": [] }, "PETILIL": { @@ -48628,7 +48980,12 @@ "MOVE_CURSE", "MOVE_UPPER_HAND" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_COUNTER", + "MOVE_DETECT", + "MOVE_FAKE_OUT", + "MOVE_QUICK_GUARD" + ], "TutorMoves": [] }, "SIGILYPH": { @@ -49172,7 +49529,13 @@ "MOVE_TRIPLE_AXEL", "MOVE_ALLURING_VOICE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AQUA_TAIL", + "MOVE_FLAIL", + "MOVE_KNOCK_OFF", + "MOVE_TAIL_WHIP", + "MOVE_TIDY_UP" + ], "TutorMoves": [] }, "GOTHITA": { @@ -49746,7 +50109,11 @@ "MOVE_FUTURE_SIGHT", "MOVE_EXPANDING_FORCE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ACID_ARMOR", + "MOVE_ASTONISH", + "MOVE_CONFUSE_RAY" + ], "TutorMoves": [] }, "REUNICLUS": { @@ -49875,7 +50242,11 @@ "MOVE_EXPANDING_FORCE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ACID_ARMOR", + "MOVE_ASTONISH", + "MOVE_CONFUSE_RAY" + ], "TutorMoves": [] }, "DUCKLETT": { @@ -50878,7 +51249,13 @@ "MOVE_SKITTER_SMACK", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_DOUBLE_TEAM", + "MOVE_INFESTATION", + "MOVE_LUNGE", + "MOVE_POISON_STING", + "MOVE_STRUGGLE_BUG" + ], "TutorMoves": [] }, "FERROSEED": { @@ -58260,7 +58637,10 @@ "MOVE_ALLURING_VOICE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_TICKLE", + "MOVE_YAWN" + ], "TutorMoves": [] }, "HONEDGE": { @@ -58546,7 +58926,11 @@ "MOVE_THROAT_CHOP", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ACUPRESSURE", + "MOVE_DESTINY_BOND", + "MOVE_DISABLE" + ], "TutorMoves": [] }, "BINACLE": { @@ -60731,7 +61115,8 @@ ], "EggMoves": [ "MOVE_DEFOG", - "MOVE_DRAGON_RUSH" + "MOVE_DRAGON_RUSH", + "MOVE_SWITCHEROO" ], "TutorMoves": [] }, @@ -61732,7 +62117,11 @@ "MOVE_ENDEAVOR", "MOVE_TEMPER_FLARE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_FAKE_OUT", + "MOVE_PARTING_SHOT", + "MOVE_POWER_TRIP" + ], "TutorMoves": [] }, "INCINEROAR": { @@ -61879,7 +62268,11 @@ "MOVE_SCORCHING_SANDS", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_FAKE_OUT", + "MOVE_PARTING_SHOT", + "MOVE_POWER_TRIP" + ], "TutorMoves": [] }, "POPPLIO": { @@ -62080,7 +62473,11 @@ "MOVE_WHIRLPOOL", "MOVE_TRIPLE_AXEL" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AQUA_RING", + "MOVE_LIFE_DEW", + "MOVE_PERISH_SONG" + ], "TutorMoves": [] }, "PRIMARINA": { @@ -62202,7 +62599,11 @@ "MOVE_ALLURING_VOICE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_AQUA_RING", + "MOVE_LIFE_DEW", + "MOVE_PERISH_SONG" + ], "TutorMoves": [] }, "PIKIPEK": { @@ -62398,7 +62799,11 @@ "MOVE_ENDEAVOR", "MOVE_FEATHER_DANCE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BOOMBURST", + "MOVE_GUNK_SHOT", + "MOVE_SKY_ATTACK" + ], "TutorMoves": [] }, "TOUCANNON": { @@ -62512,7 +62917,11 @@ "MOVE_FEATHER_DANCE", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BOOMBURST", + "MOVE_GUNK_SHOT", + "MOVE_SKY_ATTACK" + ], "TutorMoves": [] }, "YUNGOOS": { @@ -63845,6 +64254,7 @@ "EggMoves": [ "MOVE_ENDEAVOR", "MOVE_LAST_RESORT", + "MOVE_SUCKER_PUNCH", "MOVE_THRASH" ], "TutorMoves": [] @@ -64464,7 +64874,12 @@ "MOVE_ENDEAVOR", "MOVE_SKITTER_SMACK" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_POWER_SPLIT", + "MOVE_SPIT_UP", + "MOVE_STICKY_WEB", + "MOVE_STOCKPILE" + ], "TutorMoves": [] }, "FOMANTIS": { @@ -64664,6 +65079,7 @@ ], "EggMoves": [ "MOVE_DEFOG", + "MOVE_SUPERPOWER", "MOVE_WORRY_SEED" ], "TutorMoves": [] @@ -67859,8 +68275,7 @@ "MOVE_HI_JUMP_KICK", "MOVE_SAND_ATTACK", "MOVE_SUCKER_PUNCH", - "MOVE_SUPER_FANG", - "MOVE_HIGH_JUMP_KICK" + "MOVE_SUPER_FANG" ], "TutorMoves": [] }, @@ -69922,6 +70337,10 @@ }, "CRAMORANT": { "LevelMoves": [ + { + "Level": 1, + "Move": "MOVE_BELCH" + }, { "Level": 1, "Move": "MOVE_PECK" @@ -71591,7 +72010,10 @@ "MOVE_ENDEAVOR", "MOVE_ALLURING_VOICE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_BABY_DOLL_EYES", + "MOVE_LAST_RESORT" + ], "TutorMoves": [] }, "FALINKS": { @@ -88260,7 +88682,11 @@ "MOVE_HARD_PRESS", "MOVE_DRAGON_CHEER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_MIRROR_COAT", + "MOVE_NIGHT_SLASH", + "MOVE_SLASH" + ], "TutorMoves": [] }, "HYDRAPPLE": { @@ -88388,7 +88814,12 @@ "MOVE_CURSE", "MOVE_DRAGON_CHEER" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_DEFENSE_CURL", + "MOVE_RECYCLE", + "MOVE_ROLLOUT", + "MOVE_SUCKER_PUNCH" + ], "TutorMoves": [] }, "GOUGING_FIRE": { @@ -96509,7 +96940,10 @@ "MOVE_ALLURING_VOICE", "MOVE_PSYCHIC_NOISE" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_TICKLE", + "MOVE_YAWN" + ], "TutorMoves": [] }, "HOOPA_UNBOUND": { @@ -96779,6 +97213,7 @@ "EggMoves": [ "MOVE_ENDEAVOR", "MOVE_LAST_RESORT", + "MOVE_SUCKER_PUNCH", "MOVE_THRASH" ], "TutorMoves": [] @@ -96928,7 +97363,12 @@ "MOVE_ENDEAVOR", "MOVE_THROAT_CHOP" ], - "EggMoves": [], + "EggMoves": [ + "MOVE_ENDEAVOR", + "MOVE_LAST_RESORT", + "MOVE_SUCKER_PUNCH", + "MOVE_THRASH" + ], "TutorMoves": [] }, "TOXTRICITY_LOW_KEY": { @@ -98005,8 +98445,54 @@ } ], "PreEvoMoves": [], - "TMMoves": [], - "EggMoves": [], + "TMMoves": [ + "MOVE_BODY_PRESS", + "MOVE_BODY_SLAM", + "MOVE_BULLDOZE", + "MOVE_BULLET_SEED", + "MOVE_CHILLING_WATER", + "MOVE_CURSE", + "MOVE_DIG", + "MOVE_DISARMING_VOICE", + "MOVE_DOUBLE_EDGE", + "MOVE_EARTH_POWER", + "MOVE_ENDEAVOR", + "MOVE_ENDURE", + "MOVE_ENERGY_BALL", + "MOVE_FACADE", + "MOVE_GIGA_IMPACT", + "MOVE_HELPING_HAND", + "MOVE_HIGH_HORSEPOWER", + "MOVE_HYPER_BEAM", + "MOVE_HYPER_VOICE", + "MOVE_IRON_HEAD", + "MOVE_LASH_OUT", + "MOVE_MUD_SHOT", + "MOVE_MUD_SLAP", + "MOVE_PLAY_ROUGH", + "MOVE_PROTECT", + "MOVE_RAIN_DANCE", + "MOVE_REST", + "MOVE_SEED_BOMB", + "MOVE_SLEEP_TALK", + "MOVE_STOMPING_TANTRUM", + "MOVE_SUBSTITUTE", + "MOVE_SUNNY_DAY", + "MOVE_SUPER_FANG", + "MOVE_TAKE_DOWN", + "MOVE_TERA_BLAST", + "MOVE_THIEF", + "MOVE_TRAILBLAZE", + "MOVE_UPROAR", + "MOVE_ZEN_HEADBUTT" + ], + "EggMoves": [ + "MOVE_ENDEAVOR", + "MOVE_SPIT_UP", + "MOVE_STOCKPILE", + "MOVE_STUFF_CHEEKS", + "MOVE_SWALLOW" + ], "TutorMoves": [] } } \ No newline at end of file