Switch-in Events Refactor (#8128)

This commit is contained in:
Alex 2025-11-30 17:25:20 +01:00 committed by GitHub
parent f6c94867f6
commit f222bcaff5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 1272 additions and 1437 deletions

View File

@ -425,8 +425,9 @@
.4byte \jumpInstr .4byte \jumpInstr
.endm .endm
.macro unused_0x48 .macro trainerslidein position:req
.byte 0x48 .byte 0x48
.byte \position
.endm .endm
.macro moveend endMode:req, endState:req .macro moveend endMode:req, endState:req
@ -516,9 +517,8 @@
.byte \battler .byte \battler
.endm .endm
.macro trainerslidein position:req .macro switchinevents
.byte 0x53 .byte 0x53
.byte \position
.endm .endm
.macro playse song:req .macro playse song:req
@ -1297,7 +1297,7 @@
.byte 0xf3 .byte 0xf3
.endm .endm
.macro unused_0xf4 .macro sortbattlers
.byte 0xf4 .byte 0xf4
.endm .endm
@ -1873,10 +1873,6 @@
manipulatedamage DMG_1_8_TARGET_HP manipulatedamage DMG_1_8_TARGET_HP
.endm .endm
.macro dmgtomaxattackerhp
manipulatedamage DMG_FULL_ATTACKER_HP
.endm
.macro jumpifflowerveil jumpInstr:req .macro jumpifflowerveil jumpInstr:req
jumpifnottype BS_TARGET, TYPE_GRASS, 1f jumpifnottype BS_TARGET, TYPE_GRASS, 1f
jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpInstr
@ -2119,8 +2115,9 @@
callnative BS_InstantHpDrop callnative BS_InstantHpDrop
.endm .endm
.macro clearstatus .macro clearstatus battler:req
callnative BS_ClearStatus callnative BS_ClearStatus
.byte \battler
.endm .endm
.macro restoremovepp .macro restoremovepp

View File

@ -143,6 +143,7 @@ BattleScript_EffectShedTail::
switchinanim BS_ATTACKER, FALSE, TRUE switchinanim BS_ATTACKER, FALSE, TRUE
waitstate waitstate
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
end end
BattleScript_EffectPsychicNoise:: BattleScript_EffectPsychicNoise::
@ -246,15 +247,15 @@ BattleScript_EffectChillyReceptionPlayAnimation:
return return
BattleScript_EffectChillyReceptionBlockedByPrimalSun: BattleScript_EffectChillyReceptionBlockedByPrimalSun:
call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed
call BattleScript_ExtremelyHarshSunlightWasNotLessenedRet call BattleScript_ExtremelyHarshSunlightWasNotLessened
goto BattleScript_MoveSwitch goto BattleScript_MoveSwitch
BattleScript_EffectChillyReceptionBlockedByPrimalRain: BattleScript_EffectChillyReceptionBlockedByPrimalRain:
call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed
call BattleScript_NoReliefFromHeavyRainRet call BattleScript_NoReliefFromHeavyRain
goto BattleScript_MoveSwitch goto BattleScript_MoveSwitch
BattleScript_EffectChillyReceptionBlockedByStrongWinds: BattleScript_EffectChillyReceptionBlockedByStrongWinds:
call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed call BattleScript_EffectChillyReceptionTrySwitchWeatherFailed
call BattleScript_MysteriousAirCurrentBlowsOnRet call BattleScript_MysteriousAirCurrentBlowsOn
goto BattleScript_MoveSwitch goto BattleScript_MoveSwitch
BattleScript_EffectChillyReceptionTrySwitchWeatherFailed: BattleScript_EffectChillyReceptionTrySwitchWeatherFailed:
jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_ButItFailed
@ -290,6 +291,7 @@ BattleScript_MoveSwitchOpenPartyScreen::
switchinanim BS_ATTACKER, FALSE, FALSE switchinanim BS_ATTACKER, FALSE, FALSE
waitstate waitstate
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
BattleScript_MoveSwitchEnd: BattleScript_MoveSwitchEnd:
end end
@ -440,6 +442,7 @@ BattleScript_EffectRevivalBlessingSendOut:
switchinanim BS_SCRIPTING, FALSE, FALSE switchinanim BS_SCRIPTING, FALSE, FALSE
waitstate waitstate
switchineffects BS_SCRIPTING switchineffects BS_SCRIPTING
switchinevents
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_StealthRockActivates:: BattleScript_StealthRockActivates::
@ -589,7 +592,7 @@ BattleScript_AffectionBasedStatus_HealFrostbiteString:
printstring STRINGID_ATTACKERHEALEDITSFROSTBITE printstring STRINGID_ATTACKERHEALEDITSFROSTBITE
BattleScript_AffectionBasedStatusHeal_Continue: BattleScript_AffectionBasedStatusHeal_Continue:
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
clearstatus clearstatus BS_ATTACKER
waitstate waitstate
updatestatusicon BS_ATTACKER updatestatusicon BS_ATTACKER
waitstate waitstate
@ -2041,6 +2044,7 @@ BattleScript_EffectHealingWishGen4:
switchinanim BS_ATTACKER, FALSE, TRUE switchinanim BS_ATTACKER, FALSE, TRUE
waitstate waitstate
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
goto BattleScript_EffectHealingWishEnd goto BattleScript_EffectHealingWishEnd
BattleScript_HealingWishActivates:: BattleScript_HealingWishActivates::
@ -2052,15 +2056,13 @@ BattleScript_LunarDanceActivates::
BattleScript_EffectHealingWishRestore: BattleScript_EffectHealingWishRestore:
printfromtable gHealingWishStringIds printfromtable gHealingWishStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_WISH_HEAL playanimation BS_SCRIPTING, B_ANIM_WISH_HEAL
waitanimation waitanimation
dmgtomaxattackerhp healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
manipulatedamage DMG_CHANGE_SIGN datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE clearstatus BS_SCRIPTING,
datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE
clearstatus
waitstate waitstate
updatestatusicon BS_ATTACKER updatestatusicon BS_SCRIPTING
waitstate waitstate
printstring STRINGID_HEALINGWISHHEALED printstring STRINGID_HEALINGWISHHEALED
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -3584,6 +3586,7 @@ BattleScript_EffectBatonPass::
switchinanim BS_ATTACKER, FALSE, TRUE switchinanim BS_ATTACKER, FALSE, TRUE
waitstate waitstate
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
BattleScript_EffectMorningSun:: BattleScript_EffectMorningSun::
@ -3617,71 +3620,28 @@ BattleScript_EffectSunnyDay::
goto BattleScript_MoveWeatherChange goto BattleScript_MoveWeatherChange
BattleScript_ExtremelyHarshSunlightWasNotLessened: BattleScript_ExtremelyHarshSunlightWasNotLessened:
pause B_WAIT_TIME_SHORT
printstring STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_ExtremelyHarshSunlightWasNotLessenedEnd3:
pause B_WAIT_TIME_SHORT
printstring STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_ExtremelyHarshSunlightWasNotLessenedRet:
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
printstring STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED printstring STRINGID_EXTREMELYHARSHSUNLIGHTWASNOTLESSENED
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_NoReliefFromHeavyRain: BattleScript_NoReliefFromHeavyRain:
pause B_WAIT_TIME_SHORT
printstring STRINGID_NORELIEFROMHEAVYRAIN
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_NoReliefFromHeavyRainEnd3:
pause B_WAIT_TIME_SHORT
printstring STRINGID_NORELIEFROMHEAVYRAIN
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_NoReliefFromHeavyRainRet:
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
printstring STRINGID_NORELIEFROMHEAVYRAIN printstring STRINGID_NORELIEFROMHEAVYRAIN
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_MysteriousAirCurrentBlowsOn: BattleScript_MysteriousAirCurrentBlowsOn:
pause B_WAIT_TIME_SHORT
printstring STRINGID_MYSTERIOUSAIRCURRENTBLOWSON
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_MysteriousAirCurrentBlowsOnEnd3:
pause B_WAIT_TIME_SHORT
printstring STRINGID_MYSTERIOUSAIRCURRENTBLOWSON
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_MysteriousAirCurrentBlowsOnRet:
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
printstring STRINGID_MYSTERIOUSAIRCURRENTBLOWSON printstring STRINGID_MYSTERIOUSAIRCURRENTBLOWSON
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_BlockedByPrimalWeatherEnd3:: BattleScript_BlockedByPrimalWeather::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_SUN_PRIMAL, BattleScript_ExtremelyHarshSunlightWasNotLessenedEnd3 jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_SUN_PRIMAL, BattleScript_ExtremelyHarshSunlightWasNotLessened
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_NoReliefFromHeavyRainEnd3 jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_NoReliefFromHeavyRain
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_MysteriousAirCurrentBlowsOnEnd3 jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_MysteriousAirCurrentBlowsOn
end3
BattleScript_BlockedByPrimalWeatherRet::
call BattleScript_AbilityPopUp
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_SUN_PRIMAL, BattleScript_ExtremelyHarshSunlightWasNotLessenedRet
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_NoReliefFromHeavyRainRet
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_MysteriousAirCurrentBlowsOnRet
return return
BattleScript_EffectBellyDrum:: BattleScript_EffectBellyDrum::
@ -4474,6 +4434,7 @@ BattleScript_FaintedMonSendOutNew:
jumpifbytenotequal sSHIFT_SWITCHED, sZero, BattleScript_FaintedMonShiftSwitched jumpifbytenotequal sSHIFT_SWITCHED, sZero, BattleScript_FaintedMonShiftSwitched
BattleScript_FaintedMonSendOutNewEnd: BattleScript_FaintedMonSendOutNewEnd:
switchineffects BS_FAINTED switchineffects BS_FAINTED
switchinevents
jumpifbattletype BATTLE_TYPE_DOUBLE, BattleScript_FaintedMonEnd jumpifbattletype BATTLE_TYPE_DOUBLE, BattleScript_FaintedMonEnd
cancelallactions cancelallactions
BattleScript_FaintedMonEnd:: BattleScript_FaintedMonEnd::
@ -4481,6 +4442,7 @@ BattleScript_FaintedMonEnd::
BattleScript_FaintedMonShiftSwitched: BattleScript_FaintedMonShiftSwitched:
copybyte sSAVED_BATTLER, gBattlerTarget copybyte sSAVED_BATTLER, gBattlerTarget
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
resetsentmonsvalue resetsentmonsvalue
copybyte gBattlerTarget, sSAVED_BATTLER copybyte gBattlerTarget, sSAVED_BATTLER
goto BattleScript_FaintedMonSendOutNewEnd goto BattleScript_FaintedMonSendOutNewEnd
@ -4506,9 +4468,13 @@ BattleScript_HandleFaintedMonLoop::
switchineffects BS_FAINTED_MULTIPLE_1 switchineffects BS_FAINTED_MULTIPLE_1
jumpifbytenotequal gBattlerFainted, gBattlersCount, BattleScript_HandleFaintedMonLoop jumpifbytenotequal gBattlerFainted, gBattlersCount, BattleScript_HandleFaintedMonLoop
BattleScript_HandleFaintedMonMultipleEnd:: BattleScript_HandleFaintedMonMultipleEnd::
switchineffects BS_FAINTED_MULTIPLE_2 switchinevents
end2 end2
BattleScript_FirstTurnSwitchInEvents::
switchinevents
end3
BattleScript_LocalTrainerBattleWon:: BattleScript_LocalTrainerBattleWon::
jumpifbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTwoTrainersDefeated jumpifbattletype BATTLE_TYPE_TWO_OPPONENTS, BattleScript_LocalTwoTrainersDefeated
printstring STRINGID_PLAYERDEFEATEDTRAINER1 printstring STRINGID_PLAYERDEFEATEDTRAINER1
@ -4720,6 +4686,7 @@ BattleScript_DoSwitchOut::
switchinanim BS_ATTACKER, FALSE, FALSE switchinanim BS_ATTACKER, FALSE, FALSE
waitstate waitstate
switchineffects BS_ATTACKER switchineffects BS_ATTACKER
switchinevents
moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES
moveendcase MOVEEND_MIRROR_MOVE moveendcase MOVEEND_MIRROR_MOVE
end2 end2
@ -4863,8 +4830,9 @@ BattleScript_MagicRoomEnds::
printstring STRINGID_MAGICROOMENDS printstring STRINGID_MAGICROOMENDS
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
setbyte gBattlerTarget, 0 setbyte gBattlerTarget, 0
sortbattlers
BattleScript_MagicRoomHealingItemsLoop: BattleScript_MagicRoomHealingItemsLoop:
copyarraywithindex gBattlerAttacker, gBattlerByTurnOrder, gBattlerTarget, 1 copyarraywithindex gBattlerAttacker, gBattlersBySpeed, gBattlerTarget, 1
tryactivateitem BS_ATTACKER, ACTIVATION_ON_USABLE_AGAIN tryactivateitem BS_ATTACKER, ACTIVATION_ON_USABLE_AGAIN
addbyte gBattlerTarget, 1 addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MagicRoomHealingItemsLoop jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_MagicRoomHealingItemsLoop
@ -4986,6 +4954,7 @@ BattleScript_RoarSuccessSwitch::
waitstate waitstate
printstring STRINGID_PKMNWASDRAGGEDOUT printstring STRINGID_PKMNWASDRAGGEDOUT
switchineffects BS_TARGET switchineffects BS_TARGET
switchinevents
jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessSwitch_Ret jumpifbyte CMP_EQUAL, sSWITCH_CASE, B_SWITCH_RED_CARD, BattleScript_RoarSuccessSwitch_Ret
setbyte sSWITCH_CASE, B_SWITCH_NORMAL setbyte sSWITCH_CASE, B_SWITCH_NORMAL
goto BattleScript_MoveEnd goto BattleScript_MoveEnd
@ -5116,62 +5085,18 @@ BattleScript_DestinyBondTakesLife::
tryfaintmon BS_ATTACKER tryfaintmon BS_ATTACKER
return return
BattleScript_DmgHazardsOnAttacker:: BattleScript_DmgHazardsOnBattler::
healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE
datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_ATTACKER
tryfaintmon_spikes BS_ATTACKER, BattleScript_DmgHazardsOnAttackerFainted
return
BattleScript_DmgHazardsOnAttackerFainted::
setbyte sGIVEEXP_STATE, 0
getexp BS_ATTACKER
moveendall
goto BattleScript_HandleFaintedMon
BattleScript_DmgHazardsOnTarget::
healthbarupdate BS_TARGET, PASSIVE_HP_UPDATE
datahpupdate BS_TARGET, PASSIVE_HP_UPDATE
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_TARGET
tryfaintmon_spikes BS_TARGET, BattleScript_DmgHazardsOnTargetFainted
return
BattleScript_DmgHazardsOnTargetFainted::
setbyte sGIVEEXP_STATE, 0
getexp BS_TARGET
moveendall
goto BattleScript_HandleFaintedMon
BattleScript_DmgHazardsOnBattlerScripting::
healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
call BattleScript_PrintHurtByDmgHazards call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_SCRIPTING tryfaintmon BS_SCRIPTING
tryfaintmon_spikes BS_SCRIPTING, BattleScript_DmgHazardsOnBattlerScriptingFainted
return return
BattleScript_DmgHazardsOnBattlerScriptingFainted:: BattleScript_DmgHazardsOnBattlerScriptingFainted::
setbyte sGIVEEXP_STATE, 0 setbyte sGIVEEXP_STATE, 0
getexp BS_SCRIPTING getexp BS_SCRIPTING
moveendall
goto BattleScript_HandleFaintedMon
BattleScript_DmgHazardsOnFaintedBattler::
healthbarupdate BS_FAINTED, PASSIVE_HP_UPDATE
datahpupdate BS_FAINTED, PASSIVE_HP_UPDATE
call BattleScript_PrintHurtByDmgHazards
tryfaintmon BS_FAINTED
tryfaintmon_spikes BS_FAINTED, BattleScript_DmgHazardsOnFaintedBattlerFainted
return return
BattleScript_DmgHazardsOnFaintedBattlerFainted::
setbyte sGIVEEXP_STATE, 0
getexp BS_FAINTED
moveendall
goto BattleScript_HandleFaintedMon
BattleScript_PrintHurtByDmgHazards:: BattleScript_PrintHurtByDmgHazards::
printfromtable gDmgHazardsStringIds printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -5802,7 +5727,7 @@ BattleScript_PrimalReversion::
printstring STRINGID_PKMNREVERTEDTOPRIMAL printstring STRINGID_PKMNREVERTEDTOPRIMAL
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
switchinabilities BS_SCRIPTING switchinabilities BS_SCRIPTING
end3 return
BattleScript_PowerConstruct:: BattleScript_PowerConstruct::
flushtextbox flushtextbox
@ -5848,10 +5773,6 @@ BattleScript_BattlerFormChangeNoPopup:
handleformchange BS_SCRIPTING, 2 handleformchange BS_SCRIPTING, 2
return return
BattleScript_BattlerFormChangeEnd3::
call BattleScript_BattlerFormChange
end3
BattleScript_BattlerFormChangeEnd3NoPopup:: BattleScript_BattlerFormChangeEnd3NoPopup::
call BattleScript_BattlerFormChangeNoPopup call BattleScript_BattlerFormChangeNoPopup
end2 end2
@ -5860,7 +5781,7 @@ BattleScript_BattlerFormChangeEnd2::
call BattleScript_BattlerFormChange call BattleScript_BattlerFormChange
end2 end2
BattleScript_BattlerFormChangeWithStringEnd3:: BattleScript_BattlerFormChangeWithString::
pause 5 pause 5
call BattleScript_AbilityPopUpScripting call BattleScript_AbilityPopUpScripting
flushtextbox flushtextbox
@ -5871,7 +5792,7 @@ BattleScript_BattlerFormChangeWithStringEnd3::
handleformchange BS_SCRIPTING, 2 handleformchange BS_SCRIPTING, 2
printstring STRINGID_PKMNTRANSFORMED printstring STRINGID_PKMNTRANSFORMED
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_AttackerFormChangeMoveEffect:: BattleScript_AttackerFormChangeMoveEffect::
waitmessage 1 waitmessage 1
@ -5940,10 +5861,6 @@ BattleScript_IllusionOffAndTerastallization::
call BattleScript_IllusionOff call BattleScript_IllusionOff
goto BattleScript_Terastallization goto BattleScript_Terastallization
BattleScript_IllusionOffEnd3::
call BattleScript_IllusionOff
end3
BattleScript_IllusionOff:: BattleScript_IllusionOff::
setspriteignore0hp TRUE setspriteignore0hp TRUE
playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF
@ -6381,7 +6298,7 @@ BattleScript_DrizzleActivates::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_AbilityRaisesDefenderStat:: BattleScript_AbilityRaisesDefenderStat::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6463,6 +6380,11 @@ BattleScript_EmergencyExit::
pause B_WAIT_TIME_LONG pause B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN
waitanimation waitanimation
jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EmergencyExitTrainer
setteleportoutcome BS_SCRIPTING
finishaction
return
BattleScript_EmergencyExitTrainer:
openpartyscreen BS_SCRIPTING, BattleScript_EmergencyExitRet openpartyscreen BS_SCRIPTING, BattleScript_EmergencyExitRet
waitstate waitstate
returntoball BS_SCRIPTING, FALSE returntoball BS_SCRIPTING, FALSE
@ -6475,48 +6397,12 @@ BattleScript_EmergencyExit::
switchinanim BS_SCRIPTING, FALSE, TRUE switchinanim BS_SCRIPTING, FALSE, TRUE
waitstate waitstate
switchineffects BS_SCRIPTING switchineffects BS_SCRIPTING
switchinevents
BattleScript_EmergencyExitRet: BattleScript_EmergencyExitRet:
return return
BattleScript_EmergencyExitWild::
pause 5
call BattleScript_AbilityPopUpScripting
pause B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_SLIDE_OFFSCREEN
waitanimation
setteleportoutcome BS_SCRIPTING
finishaction
return
BattleScript_EmergencyExitEnd2:: BattleScript_EmergencyExitEnd2::
pause 5 call BattleScript_EmergencyExit
call BattleScript_AbilityPopUp
pause B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_SLIDE_OFFSCREEN
waitanimation
openpartyscreen BS_ATTACKER, BattleScript_EmergencyExitRetEnd2
waitstate
returntoball BS_ATTACKER, FALSE
switchoutabilities BS_ATTACKER
switchhandleorder BS_ATTACKER, 2
getswitchedmondata BS_ATTACKER
switchindataupdate BS_ATTACKER
hpthresholds BS_ATTACKER
printstring STRINGID_SWITCHINMON
switchinanim BS_ATTACKER, FALSE, TRUE
waitstate
switchineffects BS_ATTACKER
BattleScript_EmergencyExitRetEnd2:
end2
BattleScript_EmergencyExitWildEnd2::
pause 5
call BattleScript_AbilityPopUp
pause B_WAIT_TIME_LONG
playanimation BS_ATTACKER, B_ANIM_SLIDE_OFFSCREEN
waitanimation
setteleportoutcome BS_ATTACKER
finishaction
end2 end2
BattleScript_TraceActivates:: BattleScript_TraceActivates::
@ -6526,7 +6412,7 @@ BattleScript_TraceActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
settracedability BS_SCRIPTING settracedability BS_SCRIPTING
switchinabilities BS_SCRIPTING switchinabilities BS_SCRIPTING
end3 return
BattleScript_ReceiverActivates:: BattleScript_ReceiverActivates::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
@ -6599,7 +6485,7 @@ BattleScript_SandstreamActivates::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES playanimation BS_BATTLER_0, B_ANIM_SANDSTORM_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_SandSpitActivates:: BattleScript_SandSpitActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6622,8 +6508,9 @@ BattleScript_ActivateWeatherAbilities:
savetarget savetarget
tryboosterenergy ON_WEATHER tryboosterenergy ON_WEATHER
setbyte gBattlerAttacker, 0 setbyte gBattlerAttacker, 0
sortbattlers
BattleScript_ActivateWeatherAbilities_Loop: BattleScript_ActivateWeatherAbilities_Loop:
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 copyarraywithindex gBattlerTarget, gBattlersBySpeed, gBattlerAttacker, 1
activateweatherchangeabilities BS_TARGET activateweatherchangeabilities BS_TARGET
addbyte gBattlerAttacker, 1 addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateWeatherAbilities_Loop
@ -6676,7 +6563,7 @@ BattleScript_IntimidateLoopIncrement:
restoretarget restoretarget
restoreattacker restoreattacker
pause B_WAIT_TIME_MED pause B_WAIT_TIME_MED
end3 return
BattleScript_IntimidatePrevented:: BattleScript_IntimidatePrevented::
copybyte sBATTLER, gBattlerTarget copybyte sBATTLER, gBattlerTarget
@ -6728,7 +6615,7 @@ BattleScript_SupersweetSyrupLoopIncrement:
restoretarget restoretarget
restoreattacker restoreattacker
pause B_WAIT_TIME_MED pause B_WAIT_TIME_MED
end3 return
BattleScript_SupersweetSyrupWontDecrease: BattleScript_SupersweetSyrupWontDecrease:
printstring STRINGID_STATSWONTDECREASE printstring STRINGID_STATSWONTDECREASE
@ -6741,7 +6628,7 @@ BattleScript_DroughtActivates::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_DesolateLandActivates:: BattleScript_DesolateLandActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6750,7 +6637,7 @@ BattleScript_DesolateLandActivates::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES playanimation BS_BATTLER_0, B_ANIM_SUN_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_PrimalWeatherBlocksMove:: BattleScript_PrimalWeatherBlocksMove::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6765,7 +6652,7 @@ BattleScript_PrimordialSeaActivates::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES playanimation BS_BATTLER_0, B_ANIM_RAIN_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_DeltaStreamActivates:: BattleScript_DeltaStreamActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6773,7 +6660,7 @@ BattleScript_DeltaStreamActivates::
printstring STRINGID_MYSTERIOUSAIRCURRENT printstring STRINGID_MYSTERIOUSAIRCURRENT
waitstate waitstate
playanimation BS_ATTACKER, B_ANIM_STRONG_WINDS playanimation BS_ATTACKER, B_ANIM_STRONG_WINDS
end3 return
BattleScript_ProtosynthesisActivates:: BattleScript_ProtosynthesisActivates::
call BattleScript_AbilityPopUpScripting call BattleScript_AbilityPopUpScripting
@ -6781,7 +6668,7 @@ BattleScript_ProtosynthesisActivates::
waitmessage B_WAIT_TIME_MED waitmessage B_WAIT_TIME_MED
printstring STRINGID_STATWASHEIGHTENED printstring STRINGID_STATWASHEIGHTENED
waitmessage B_WAIT_TIME_MED waitmessage B_WAIT_TIME_MED
end3 return
BattleScript_QuarkDriveActivates:: BattleScript_QuarkDriveActivates::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
@ -6789,34 +6676,34 @@ BattleScript_QuarkDriveActivates::
waitmessage B_WAIT_TIME_MED waitmessage B_WAIT_TIME_MED
printstring STRINGID_STATWASHEIGHTENED printstring STRINGID_STATWASHEIGHTENED
waitmessage B_WAIT_TIME_MED waitmessage B_WAIT_TIME_MED
end3 return
BattleScript_RuinAbilityActivates:: BattleScript_RuinAbilityActivates::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printstring STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT printstring STRINGID_ABILITYWEAKENEDSURROUNDINGMONSSTAT
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_SupremeOverlordActivates:: BattleScript_SupremeOverlordActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printstring STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN printstring STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_CostarActivates:: BattleScript_CostarActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printstring STRINGID_PKMNCOPIEDSTATCHANGES printstring STRINGID_PKMNCOPIEDSTATCHANGES
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_ZeroToHeroActivates:: BattleScript_ZeroToHeroActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUpScripting call BattleScript_AbilityPopUpScripting
printstring STRINGID_ZEROTOHEROTRANSFORMATION printstring STRINGID_ZEROTOHEROTRANSFORMATION
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_CommanderActivates:: BattleScript_CommanderActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6855,7 +6742,7 @@ BattleScript_CommanderSpeedIncrease:
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
BattleScript_CommanderEnd: BattleScript_CommanderEnd:
restoreattacker restoreattacker
end3 return
BattleScript_HospitalityActivates:: BattleScript_HospitalityActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6865,7 +6752,7 @@ BattleScript_HospitalityActivates::
playanimation BS_EFFECT_BATTLER, B_ANIM_SIMPLE_HEAL playanimation BS_EFFECT_BATTLER, B_ANIM_SIMPLE_HEAL
healthbarupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE healthbarupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE
datahpupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE datahpupdate BS_EFFECT_BATTLER, PASSIVE_HP_UPDATE
end3 return
BattleScript_AttackWeakenedByStrongWinds:: BattleScript_AttackWeakenedByStrongWinds::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6878,7 +6765,7 @@ BattleScript_MimicryActivates::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printstring STRINGID_BATTLERTYPECHANGEDTO printstring STRINGID_BATTLERTYPECHANGEDTO
waitmessage B_WAIT_TIME_SHORT waitmessage B_WAIT_TIME_SHORT
end3 return
BattleScript_SnowWarningActivatesHail:: BattleScript_SnowWarningActivatesHail::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6887,7 +6774,7 @@ BattleScript_SnowWarningActivatesHail::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES playanimation BS_BATTLER_0, B_ANIM_HAIL_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_SnowWarningActivatesSnow:: BattleScript_SnowWarningActivatesSnow::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6896,7 +6783,7 @@ BattleScript_SnowWarningActivatesSnow::
waitstate waitstate
playanimation BS_BATTLER_0, B_ANIM_SNOW_CONTINUES playanimation BS_BATTLER_0, B_ANIM_SNOW_CONTINUES
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_ActivateTerrainEffects: BattleScript_ActivateTerrainEffects:
saveattacker saveattacker
@ -6904,8 +6791,9 @@ BattleScript_ActivateTerrainEffects:
tryboosterenergy ON_TERRAIN tryboosterenergy ON_TERRAIN
resetterrainabilityflags resetterrainabilityflags
setbyte gBattlerAttacker, 0 setbyte gBattlerAttacker, 0
sortbattlers
BattleScript_ActivateTerrainSeed: BattleScript_ActivateTerrainSeed:
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 copyarraywithindex gBattlerTarget, gBattlersBySpeed, gBattlerAttacker, 1
tryterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility tryterrainseed BS_TARGET, BattleScript_ActivateTerrainAbility
removeitem BS_TARGET removeitem BS_TARGET
BattleScript_ActivateTerrainAbility: BattleScript_ActivateTerrainAbility:
@ -6923,7 +6811,7 @@ BattleScript_ElectricSurgeActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects call BattleScript_ActivateTerrainEffects
end3 return
BattleScript_MistySurgeActivates:: BattleScript_MistySurgeActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6932,7 +6820,7 @@ BattleScript_MistySurgeActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects call BattleScript_ActivateTerrainEffects
end3 return
BattleScript_GrassySurgeActivates:: BattleScript_GrassySurgeActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6941,7 +6829,7 @@ BattleScript_GrassySurgeActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects call BattleScript_ActivateTerrainEffects
end3 return
BattleScript_PsychicSurgeActivates:: BattleScript_PsychicSurgeActivates::
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
@ -6950,7 +6838,7 @@ BattleScript_PsychicSurgeActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG playanimation BS_SCRIPTING, B_ANIM_RESTORE_BG
call BattleScript_ActivateTerrainEffects call BattleScript_ActivateTerrainEffects
end3 return
BattleScript_BadDreamsActivates:: BattleScript_BadDreamsActivates::
setbyte gBattlerTarget, 0 setbyte gBattlerTarget, 0
@ -7231,7 +7119,7 @@ BattleScript_BattlerAbilityStatRaiseOnSwitchIn::
printstring STRINGID_SCRIPTINGABILITYSTATRAISE printstring STRINGID_SCRIPTINGABILITYSTATRAISE
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
BattleScript_BattlerAbilityStatRaiseOnSwitchInRet: BattleScript_BattlerAbilityStatRaiseOnSwitchInRet:
end3 return
BattleScript_ScriptingAbilityStatRaise:: BattleScript_ScriptingAbilityStatRaise::
copybyte gBattlerAbility, sBATTLER copybyte gBattlerAbility, sBATTLER
@ -7310,7 +7198,7 @@ BattleScript_FellStingerRaisesAtkEnd:
BattleScript_AttackerAbilityStatRaiseEnd3:: BattleScript_AttackerAbilityStatRaiseEnd3::
call BattleScript_AttackerAbilityStatRaise call BattleScript_AttackerAbilityStatRaise
restoreattacker restoreattacker
end3 return
BattleScript_AttackerAbilityStatRaiseEnd2:: BattleScript_AttackerAbilityStatRaiseEnd2::
call BattleScript_AttackerAbilityStatRaise call BattleScript_AttackerAbilityStatRaise
@ -7318,12 +7206,6 @@ BattleScript_AttackerAbilityStatRaiseEnd2::
end2 end2
BattleScript_SwitchInAbilityMsg:: BattleScript_SwitchInAbilityMsg::
call BattleScript_AbilityPopUp
printfromtable gSwitchInAbilityStringIds
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_SwitchInAbilityMsgRet::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printfromtable gSwitchInAbilityStringIds printfromtable gSwitchInAbilityStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -7339,7 +7221,7 @@ BattleScript_ActivateAsOne::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printfromtable gSwitchInAbilityStringIds printfromtable gSwitchInAbilityStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
end3 return
BattleScript_FriskMsgWithPopup:: BattleScript_FriskMsgWithPopup::
copybyte gBattlerAbility, gBattlerAttacker copybyte gBattlerAbility, gBattlerAttacker
@ -7356,7 +7238,7 @@ BattleScript_FriskActivates::
tryfriskmessage tryfriskmessage
restoreattacker restoreattacker
restoretarget restoretarget
end3 return
BattleScript_ImposterActivates:: BattleScript_ImposterActivates::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
@ -7367,7 +7249,7 @@ BattleScript_ImposterActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
restoreattacker restoreattacker
restoretarget restoretarget
end3 return
BattleScript_HurtAttacker: BattleScript_HurtAttacker:
healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE
@ -7501,13 +7383,6 @@ BattleScript_AbilityCuredStatus::
updatestatusicon BS_SCRIPTING updatestatusicon BS_SCRIPTING
return return
BattleScript_AbilityCuredStatusEnd3::
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNSXCUREDITSYPROBLEM
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_SCRIPTING
end3
BattleScript_BattlerShookOffTaunt:: BattleScript_BattlerShookOffTaunt::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
printstring STRINGID_PKMNSHOOKOFFTHETAUNT printstring STRINGID_PKMNSHOOKOFFTHETAUNT
@ -7565,10 +7440,6 @@ BattleScript_SubstituteFade::
printstring STRINGID_PKMNSUBSTITUTEFADED printstring STRINGID_PKMNSUBSTITUTEFADED
return return
BattleScript_BerryCureStatusEnd2::
call BattleScript_BerryCureStatusRet
end2
BattleScript_BerryCureStatusRet:: BattleScript_BerryCureStatusRet::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printfromtable CureStatusBerryEffectStringID printfromtable CureStatusBerryEffectStringID
@ -7595,10 +7466,6 @@ BattleScript_BerryReduceDmg::
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_BerryCureConfusionEnd2::
call BattleScript_BerryCureConfusionRet
end2
BattleScript_BerryCureConfusionRet:: BattleScript_BerryCureConfusionRet::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_PKMNSITEMSNAPPEDOUT printstring STRINGID_PKMNSITEMSNAPPEDOUT
@ -7629,7 +7496,7 @@ BattleScript_WhiteHerbRet::
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_ItemHealHP_RemoveItemRet:: BattleScript_ItemHealHP_RemoveItem::
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp
goto BattleScript_ItemHealHP_RemoveItemRet_Anim goto BattleScript_ItemHealHP_RemoveItemRet_Anim
BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp: BattleScript_ItemHealHP_RemoveItemRet_AbilityPopUp:
@ -7643,21 +7510,7 @@ BattleScript_ItemHealHP_RemoveItemRet_Anim:
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_ItemHealHP_RemoveItemEnd2:: BattleScript_BerryPPHeal::
jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp
goto BattleScript_ItemHealHP_RemoveItemEnd2_Anim
BattleScript_ItemHealHP_RemoveItemEnd2_AbilityPopUp:
call BattleScript_AbilityPopUpScripting
BattleScript_ItemHealHP_RemoveItemEnd2_Anim:
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_PKMNSITEMRESTOREDHEALTH
waitmessage B_WAIT_TIME_LONG
healthbarupdate BS_ATTACKER, PASSIVE_HP_UPDATE
datahpupdate BS_ATTACKER, PASSIVE_HP_UPDATE
removeitem BS_ATTACKER
end2
BattleScript_BerryPPHealRet::
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryPPHeal_AbilityPopup jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryPPHeal_AbilityPopup
goto BattleScript_BerryPPHeal_Anim goto BattleScript_BerryPPHeal_Anim
BattleScript_BerryPPHeal_AbilityPopup: BattleScript_BerryPPHeal_AbilityPopup:
@ -7669,19 +7522,10 @@ BattleScript_BerryPPHeal_Anim:
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_BerryPPHealEnd2::
call BattleScript_BerryPPHealRet
end2
BattleScript_ItemHealHP_End2:: BattleScript_ItemHealHP_End2::
call BattleScript_ItemHealHP_Ret call BattleScript_ItemHealHP_Ret
end2 end2
BattleScript_AirBalloonMsgIn::
printstring STRINGID_AIRBALLOONFLOAT
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_AirBalloonMsgInRet:: BattleScript_AirBalloonMsgInRet::
printstring STRINGID_AIRBALLOONFLOAT printstring STRINGID_AIRBALLOONFLOAT
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
@ -7756,22 +7600,7 @@ BattleScript_HangedOnMsg::
BattleScript_HangedOnMsgRet: BattleScript_HangedOnMsgRet:
return return
BattleScript_BerryConfuseHealEnd2:: BattleScript_BerryConfuseHeal::
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealEnd2_AbilityPopup
goto BattleScript_BerryConfuseHealEnd2_Anim
BattleScript_BerryConfuseHealEnd2_AbilityPopup:
call BattleScript_AbilityPopUp
BattleScript_BerryConfuseHealEnd2_Anim:
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_PKMNSITEMRESTOREDHEALTH
waitmessage B_WAIT_TIME_LONG
healthbarupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
datahpupdate BS_SCRIPTING, PASSIVE_HP_UPDATE
seteffectprimary BS_SCRIPTING, BS_SCRIPTING, MOVE_EFFECT_CONFUSION
removeitem BS_SCRIPTING
end2
BattleScript_BerryConfuseHealRet::
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_BerryConfuseHealRet_AbilityPopup
goto BattleScript_BerryConfuseHealRet_Anim goto BattleScript_BerryConfuseHealRet_Anim
BattleScript_BerryConfuseHealRet_AbilityPopup: BattleScript_BerryConfuseHealRet_AbilityPopup:
@ -7786,10 +7615,6 @@ BattleScript_BerryConfuseHealRet_Anim:
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_ConsumableStatRaiseEnd2::
call BattleScript_ConsumableStatRaiseRet
end2
BattleScript_ConsumableStatRaiseRet:: BattleScript_ConsumableStatRaiseRet::
jumpifnotberry BS_SCRIPTING, BattleScript_ConsumableStatRaiseRet_Anim jumpifnotberry BS_SCRIPTING, BattleScript_ConsumableStatRaiseRet_Anim
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ConsumableStatRaiseRet_AbilityPopup jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_ConsumableStatRaiseRet_AbilityPopup
@ -7809,17 +7634,13 @@ BattleScript_ConsumableStatRaiseRet_Anim:
BattleScript_ConsumableStatRaiseRet_End: BattleScript_ConsumableStatRaiseRet_End:
return return
BattleScript_BerryFocusEnergyRet:: BattleScript_BerryFocusEnergy::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_PKMNUSEDXTOGETPUMPED printstring STRINGID_PKMNUSEDXTOGETPUMPED
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_BerryFocusEnergyEnd2::
call BattleScript_BerryFocusEnergyRet
end2
BattleScript_ActionSelectionItemsCantBeUsed:: BattleScript_ActionSelectionItemsCantBeUsed::
printselectionstring STRINGID_ITEMSCANTBEUSEDNOW printselectionstring STRINGID_ITEMSCANTBEUSEDNOW
endselectionscript endselectionscript
@ -7990,10 +7811,6 @@ BattleScript_OpportunistCopyStatChangeEnd:
setbyte sSTAT_ANIM_PLAYED, FALSE setbyte sSTAT_ANIM_PLAYED, FALSE
return return
BattleScript_OpportunistCopyStatChangeEnd3::
call BattleScript_OpportunistCopyStatChange
end3
BattleScript_TotemVar:: BattleScript_TotemVar::
call BattleScript_TotemVar_Ret call BattleScript_TotemVar_Ret
end2 end2
@ -8014,14 +7831,14 @@ BattleScript_AnnounceAirLockCloudNine::
printstring STRINGID_AIRLOCKACTIVATES printstring STRINGID_AIRLOCKACTIVATES
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
call BattleScript_ActivateWeatherAbilities call BattleScript_ActivateWeatherAbilities
end3 return
BattleScript_ActivateTeraformZero:: BattleScript_ActivateTeraformZero::
call BattleScript_AbilityPopUp call BattleScript_AbilityPopUp
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_ANY, BattleScript_ActivateTeraformZero_RemoveWeather jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_ANY, BattleScript_ActivateTeraformZero_RemoveWeather
jumpifhalfword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ActivateTeraformZero_RemoveTerrain jumpifhalfword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ActivateTeraformZero_RemoveTerrain
goto BattleScript_ActivateTeraformZero_End goto BattleScript_ActivateTeraformZero_Ret
BattleScript_ActivateTeraformZero_RemoveWeather: BattleScript_ActivateTeraformZero_RemoveWeather:
removeweather removeweather
printfromtable gWeatherEndsStringIds printfromtable gWeatherEndsStringIds
@ -8039,16 +7856,17 @@ BattleScript_ActivateTeraformZeroEffects:
tryboosterenergy ON_ANY tryboosterenergy ON_ANY
resetterrainabilityflags resetterrainabilityflags
setbyte gBattlerAttacker, 0 setbyte gBattlerAttacker, 0
sortbattlers
BattleScript_ActivateTeraformZeroLoop: BattleScript_ActivateTeraformZeroLoop:
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 copyarraywithindex gBattlerTarget, gBattlersBySpeed, gBattlerAttacker, 1
activateterrainchangeabilities BS_TARGET activateterrainchangeabilities BS_TARGET
activateweatherchangeabilities BS_TARGET activateweatherchangeabilities BS_TARGET
addbyte gBattlerAttacker, 1 addbyte gBattlerAttacker, 1
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateTeraformZeroLoop jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_ActivateTeraformZeroLoop
restoreattacker restoreattacker
restoretarget restoretarget
BattleScript_ActivateTeraformZero_End: BattleScript_ActivateTeraformZero_Ret:
end3 return
BattleScript_QuickClawActivation:: BattleScript_QuickClawActivation::
flushtextbox flushtextbox
@ -8074,19 +7892,7 @@ BattleScript_CustapBerryActivation::
removeitem BS_ATTACKER removeitem BS_ATTACKER
end2 end2
BattleScript_MicleBerryActivateEnd2:: BattleScript_MicleBerryActivate::
jumpifability BS_ATTACKER, ABILITY_RIPEN, BattleScript_MicleBerryActivateEnd2_Ripen
goto BattleScript_MicleBerryActivateEnd2_Anim
BattleScript_MicleBerryActivateEnd2_Ripen:
call BattleScript_AbilityPopUp
BattleScript_MicleBerryActivateEnd2_Anim:
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_MICLEBERRYACTIVATES
waitmessage B_WAIT_TIME_LONG
removeitem BS_ATTACKER
end2
BattleScript_MicleBerryActivateRet::
jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_MicleBerryActivateRet_Ripen jumpifability BS_SCRIPTING, ABILITY_RIPEN, BattleScript_MicleBerryActivateRet_Ripen
goto BattleScript_MicleBerryActivateRet_Anim goto BattleScript_MicleBerryActivateRet_Anim
BattleScript_MicleBerryActivateRet_Ripen: BattleScript_MicleBerryActivateRet_Ripen:
@ -8295,6 +8101,7 @@ BattleScript_EjectButtonActivates::
switchinanim BS_SCRIPTING, FALSE, TRUE switchinanim BS_SCRIPTING, FALSE, TRUE
waitstate waitstate
switchineffects BS_SCRIPTING switchineffects BS_SCRIPTING
switchinevents
BattleScript_EjectButtonEnd: BattleScript_EjectButtonEnd:
return return
@ -8305,10 +8112,6 @@ BattleScript_EjectPackActivate_End2::
call BattleScript_EjectPackActivate_Ret call BattleScript_EjectPackActivate_Ret
end2 end2
BattleScript_EjectPackActivate_End3::
call BattleScript_EjectPackActivate_Ret
end3
BattleScript_EjectPackActivates:: BattleScript_EjectPackActivates::
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
goto BattleScript_EjectPackActivate_Ret goto BattleScript_EjectPackActivate_Ret
@ -8366,7 +8169,7 @@ BattleScript_PastelVeilLoopIncrement:
goto BattleScript_PastelVeilEnd goto BattleScript_PastelVeilEnd
BattleScript_PastelVeilEnd: BattleScript_PastelVeilEnd:
restoretarget restoretarget
end3 return
BattleScript_NeutralizingGasExits:: BattleScript_NeutralizingGasExits::
saveattacker saveattacker
@ -8375,8 +8178,9 @@ BattleScript_NeutralizingGasExits::
printstring STRINGID_NEUTRALIZINGGASOVER printstring STRINGID_NEUTRALIZINGGASOVER
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
setbyte gBattlerAttacker, 0 setbyte gBattlerAttacker, 0
sortbattlers
BattleScript_NeutralizingGasExitsLoop: BattleScript_NeutralizingGasExitsLoop:
copyarraywithindex gBattlerTarget, gBattlerByTurnOrder, gBattlerAttacker, 1 copyarraywithindex gBattlerTarget, gBattlersBySpeed, gBattlerAttacker, 1
jumpifabilitycantbereactivated BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement jumpifabilitycantbereactivated BS_TARGET, BattleScript_NeutralizingGasExitsLoopIncrement
saveattacker saveattacker
switchinabilities BS_TARGET switchinabilities BS_TARGET
@ -8759,14 +8563,6 @@ BattleScript_BerserkGeneRet_End:
removeitem BS_SCRIPTING removeitem BS_SCRIPTING
return return
BattleScript_BerserkGeneRetEnd2::
call BattleScript_BerserkGeneRet
end2
BattleScript_BoosterEnergyEnd2::
call BattleScript_BoosterEnergyRet
end2
BattleScript_BoosterEnergyRet:: BattleScript_BoosterEnergyRet::
playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1 playanimation BS_SCRIPTING, B_ANIM_HELD_ITEM_EFFECT, sB_ANIM_ARG1
call BattleScript_AbilityPopUpScripting call BattleScript_AbilityPopUpScripting

View File

@ -81,6 +81,7 @@ BattleScript_ItemRestoreHP_SendOutRevivedBattler:
switchinanim BS_SCRIPTING, FALSE, FALSE switchinanim BS_SCRIPTING, FALSE, FALSE
waitstate waitstate
switchineffects BS_SCRIPTING switchineffects BS_SCRIPTING
switchinevents
end end
BattleScript_ItemCureStatus:: BattleScript_ItemCureStatus::

View File

@ -3,6 +3,7 @@
// should they be included here or included individually by every file? // should they be included here or included individually by every file?
#include "constants/battle_end_turn.h" #include "constants/battle_end_turn.h"
#include "constants/battle_switch_in.h"
#include "constants/abilities.h" #include "constants/abilities.h"
#include "constants/battle.h" #include "constants/battle.h"
#include "constants/form_change_types.h" #include "constants/form_change_types.h"
@ -133,12 +134,11 @@ struct DisableStruct
u8 neutralizingGas:1; u8 neutralizingGas:1;
u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case 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 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in
u8 hazardsDone:1;
u8 endured:1; u8 endured:1;
u8 tryEjectPack:1; u8 tryEjectPack:1;
u8 octolockedBy:3; u8 octolockedBy:3;
u8 paradoxBoostedStat:4; u8 paradoxBoostedStat:4;
u8 padding2:1; u8 padding2:2;
}; };
// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects // Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects
@ -171,7 +171,8 @@ struct ProtectStruct
u16 helpingHand:3; u16 helpingHand:3;
u16 assuranceDoubled:1; u16 assuranceDoubled:1;
u16 myceliumMight:1; u16 myceliumMight:1;
u16 padding:11; u16 forcedSwitch:1;
u16 padding:10;
// End of 16-bit bitfield // End of 16-bit bitfield
u16 physicalDmg; u16 physicalDmg;
u16 specialDmg; u16 specialDmg;
@ -192,27 +193,23 @@ struct SpecialStatus
u8 afterYou:1; u8 afterYou:1;
u8 enduredDamage:1; u8 enduredDamage:1;
u8 dancerUsedMove:1; u8 dancerUsedMove:1;
u8 padding1:1; u8 rototillerAffected:1; // to be affected by rototiller
// End of byte // End of byte
u8 switchInAbilityDone:1; u8 criticalHit:1;
u8 switchInItemDone:1; u8 switchInItemDone:1;
u8 instructedChosenTarget:3; u8 instructedChosenTarget:3;
u8 berryReduced:1; u8 berryReduced:1;
u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS
u8 padding2:1; u8 padding2:1;
// End of byte // End of byte
u8 gemParam; u8 gemParam:7;
// End of byte
u8 gemBoost:1; u8 gemBoost:1;
u8 rototillerAffected:1; // to be affected by rototiller // End of byte
u8 parentalBondState:2; u8 parentalBondState:2;
u8 multiHitOn:1; u8 multiHitOn:1;
u8 distortedTypeMatchups:1; u8 distortedTypeMatchups:1;
u8 teraShellAbilityDone:1; u8 teraShellAbilityDone:1;
u8 criticalHit:1;
// End of byte
u8 dancerOriginalTarget:3; u8 dancerOriginalTarget:3;
u8 padding3:5;
// End of byte // End of byte
}; };
@ -588,8 +585,10 @@ struct BattlerState
u32 wasAboveHalfHp:1; // For Berserk, Emergency Exit, Wimp Out and Anger Shell. u32 wasAboveHalfHp:1; // For Berserk, Emergency Exit, Wimp Out and Anger Shell.
u32 commanderSpecies:11; u32 commanderSpecies:11;
u32 selectionScriptFinished:1; u32 selectionScriptFinished:1;
u32 switchIn:1;
u32 padding:3; u32 padding:3;
// End of Word // End of Word
u16 hpOnSwitchout;
}; };
struct PartyState struct PartyState
@ -620,7 +619,9 @@ struct EventStates
enum BattlerId faintedActionBattler:4; enum BattlerId faintedActionBattler:4;
enum MoveSuccessOrder atkCanceler:8; enum MoveSuccessOrder atkCanceler:8;
enum BattleIntroStates battleIntro:8; enum BattleIntroStates battleIntro:8;
u32 padding:24; enum SwitchInEvents switchIn:8;
u32 battlerSwitchIn:8; // SwitchInFirstEventBlock, SwitchInSecondEventBlock
u32 padding:8;
}; };
// Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise.
@ -669,17 +670,15 @@ struct BattleStruct
u8 wallyWaitFrames; u8 wallyWaitFrames;
u8 wallyMoveFrames; u8 wallyMoveFrames;
u16 lastTakenMove[MAX_BATTLERS_COUNT]; // Last move that a battler was hit with. u16 lastTakenMove[MAX_BATTLERS_COUNT]; // Last move that a battler was hit with.
u16 hpOnSwitchout[NUM_BATTLE_SIDES];
u32 savedBattleTypeFlags; u32 savedBattleTypeFlags;
u16 abilityPreventingSwitchout; u16 abilityPreventingSwitchout;
u8 hpScale; u8 hpScale;
u16 synchronizeMoveEffect; u16 synchronizeMoveEffect;
u8 anyMonHasTransformed:1; // Only used in battle_tv.c u8 anyMonHasTransformed:1; // Only used in battle_tv.c
u8 multipleSwitchInState:2;
u8 multipleSwitchInCursor:3;
u8 sleepClauseNotBlocked:1; u8 sleepClauseNotBlocked:1;
u8 isSkyBattle:1; u8 isSkyBattle:1;
u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; u8 unused:5;
u8 sortedBattlers[MAX_BATTLERS_COUNT];
void (*savedCallback)(void); void (*savedCallback)(void);
u16 chosenItem[MAX_BATTLERS_COUNT]; u16 chosenItem[MAX_BATTLERS_COUNT];
u16 choicedMove[MAX_BATTLERS_COUNT]; u16 choicedMove[MAX_BATTLERS_COUNT];
@ -696,7 +695,7 @@ struct BattleStruct
u8 fickleBeamBoosted:1; u8 fickleBeamBoosted:1;
u8 poisonPuppeteerConfusion:1; u8 poisonPuppeteerConfusion:1;
u8 toxicChainPriority:1; // If Toxic Chain will trigger on target, all other non volatiles will be blocked u8 toxicChainPriority:1; // If Toxic Chain will trigger on target, all other non volatiles will be blocked
u8 moldBreakerActive:1; u8 battlersSorted:1; // To avoid unnessasery computation
u16 startingStatusTimer; u16 startingStatusTimer;
struct BattleTvMovePoints tvMovePoints; struct BattleTvMovePoints tvMovePoints;
struct BattleTv tv; struct BattleTv tv;
@ -775,7 +774,7 @@ struct BattleStruct
u8 printedStrongWindsWeakenedAttack:1; u8 printedStrongWindsWeakenedAttack:1;
u8 numSpreadTargets:2; u8 numSpreadTargets:2;
u8 noTargetPresent:1; u8 noTargetPresent:1;
u8 padding2:1; u8 moldBreakerActive:1;
struct MessageStatus slideMessageStatus; struct MessageStatus slideMessageStatus;
u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT]; u8 trainerSlideSpriteIds[MAX_BATTLERS_COUNT];
u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT]; u8 hazardsQueue[NUM_BATTLE_SIDES][HAZARDS_MAX_COUNT];
@ -787,7 +786,7 @@ struct BattleStruct
u16 flingItem; u16 flingItem;
u8 incrementEchoedVoice:1; u8 incrementEchoedVoice:1;
u8 echoedVoiceCounter:3; u8 echoedVoiceCounter:3;
u8 padding3:4; u8 padding4:4;
}; };
struct AiBattleData struct AiBattleData
@ -1045,6 +1044,7 @@ extern u16 gBattlerPartyIndexes[MAX_BATTLERS_COUNT];
extern u8 gBattlerPositions[MAX_BATTLERS_COUNT]; extern u8 gBattlerPositions[MAX_BATTLERS_COUNT];
extern u8 gActionsByTurnOrder[MAX_BATTLERS_COUNT]; extern u8 gActionsByTurnOrder[MAX_BATTLERS_COUNT];
extern u8 gBattlerByTurnOrder[MAX_BATTLERS_COUNT]; extern u8 gBattlerByTurnOrder[MAX_BATTLERS_COUNT];
extern u8 gBattlersBySpeed[MAX_BATTLERS_COUNT];
extern u8 gCurrentTurnActionNumber; extern u8 gCurrentTurnActionNumber;
extern u8 gCurrentActionFuncId; extern u8 gCurrentActionFuncId;
extern struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT]; extern struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT];

View File

@ -4,4 +4,3 @@
u32 DoEndTurnEffects(void); u32 DoEndTurnEffects(void);
#endif // GUARD_BATTLE_END_TURN #endif // GUARD_BATTLE_END_TURN

View File

@ -4,11 +4,8 @@
struct HoldEffectInfo struct HoldEffectInfo
{ {
u32 onSwitchIn:1; u32 onSwitchIn:1;
u32 onSwitchInFirstTurn:1;
u32 mirrorHerb:1; u32 mirrorHerb:1;
u32 mirrorHerbFirstTurn:1;
u32 whiteHerb:1; u32 whiteHerb:1;
u32 whiteHerbFirstTurn:1;
u32 whiteHerbEndTurn:1; u32 whiteHerbEndTurn:1;
u32 onStatusChange:1; u32 onStatusChange:1;
u32 onHpThreshold:1; u32 onHpThreshold:1;
@ -21,7 +18,8 @@ struct HoldEffectInfo
u32 orbs:1; u32 orbs:1;
u32 onEffect:1; u32 onEffect:1;
u32 onFling:1; u32 onFling:1;
u32 padding:14; u32 boosterEnergy:1;
u32 padding:16;
}; };
extern const struct HoldEffectInfo gHoldEffectsInfo[]; extern const struct HoldEffectInfo gHoldEffectsInfo[];
@ -30,11 +28,8 @@ typedef bool32 (*ActivationTiming)(enum HoldEffect holdEffect);
enum ItemEffect ItemBattleEffects(u32 primaryBattler, u32 secondaryBattler, enum HoldEffect holdEffect, ActivationTiming timing); enum ItemEffect ItemBattleEffects(u32 primaryBattler, u32 secondaryBattler, enum HoldEffect holdEffect, ActivationTiming timing);
bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect); bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect);
bool32 IsOnSwitchInFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect); bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect);
bool32 IsMirrorHerbFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect); bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect); bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect);
bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect); bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect);
bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect); bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect);
@ -48,5 +43,6 @@ bool32 IsOnEffectActivation(enum HoldEffect holdEffect);
bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect); bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect);
bool32 IsOnBerryActivation(enum HoldEffect holdEffect); bool32 IsOnBerryActivation(enum HoldEffect holdEffect);
bool32 IsOnFlingActivation(enum HoldEffect holdEffect); bool32 IsOnFlingActivation(enum HoldEffect holdEffect);
bool32 IsBoosterEnergyActivation(enum HoldEffect holdEffect);
#endif // GUARD_BATTLE_HOLD_EFFECTS #endif // GUARD_BATTLE_HOLD_EFFECTS

View File

@ -56,13 +56,7 @@ enum FirstTurnEventsStates
FIRST_TURN_EVENTS_TERRAIN, FIRST_TURN_EVENTS_TERRAIN,
FIRST_TURN_EVENTS_STARTING_STATUS, FIRST_TURN_EVENTS_STARTING_STATUS,
FIRST_TURN_EVENTS_TOTEM_BOOST, FIRST_TURN_EVENTS_TOTEM_BOOST,
FIRST_TURN_EVENTS_NEUTRALIZING_GAS, FIRST_TURN_SWITCH_IN_EVENTS,
FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES,
FIRST_TURN_EVENTS_ITEM_EFFECTS,
FIRST_TURN_EVENTS_WHITE_HERB,
FIRST_TURN_EVENTS_OPPORTUNIST,
FIRST_TURN_EVENTS_MIRROR_HERB,
FIRST_TURN_EVENTS_EJECT_PACK,
FIRST_TURN_EVENTS_END, FIRST_TURN_EVENTS_END,
}; };
@ -116,6 +110,7 @@ void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon
bool32 CanPlayerForfeitNormalTrainerBattle(void); bool32 CanPlayerForfeitNormalTrainerBattle(void);
bool32 DidPlayerForfeitNormalTrainerBattle(void); bool32 DidPlayerForfeitNormalTrainerBattle(void);
void BattleDebug_WonBattle(void); void BattleDebug_WonBattle(void);
s32 Factorial(s32 n);
extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE];

View File

@ -68,13 +68,11 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem);
u8 GetCatchingBattler(void); u8 GetCatchingBattler(void);
bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, enum Type moveType); bool32 ProteanTryChangeType(u32 battler, enum Ability ability, u32 move, enum Type moveType);
bool32 IsMoveNotAllowedInSkyBattles(u32 move); bool32 IsMoveNotAllowedInSkyBattles(u32 move);
bool32 DoSwitchInAbilities(u32 battlerId);
u8 GetFirstFaintedPartyIndex(u8 battlerId); u8 GetFirstFaintedPartyIndex(u8 battlerId);
bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler); bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler);
void SaveBattlerTarget(u32 battler); void SaveBattlerTarget(u32 battler);
void SaveBattlerAttacker(u32 battler); void SaveBattlerAttacker(u32 battler);
bool32 CanBurnHitThaw(u16 move); bool32 CanBurnHitThaw(u16 move);
bool32 EmergencyExitCanBeTriggered(u32 battler);
extern void (*const gBattleScriptingCommandsTable[])(void); extern void (*const gBattleScriptingCommandsTable[])(void);
extern const struct StatFractions gAccuracyStageRatios[]; extern const struct StatFractions gAccuracyStageRatios[];

View File

@ -3,7 +3,6 @@
extern const u8 BattleScript_SupersweetSyrupActivates[]; extern const u8 BattleScript_SupersweetSyrupActivates[];
extern const u8 BattleScript_OpportunistCopyStatChange[]; extern const u8 BattleScript_OpportunistCopyStatChange[];
extern const u8 BattleScript_OpportunistCopyStatChangeEnd3[];
extern const u8 BattleScript_MirrorHerbCopyStatChange[]; extern const u8 BattleScript_MirrorHerbCopyStatChange[];
extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[]; extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[];
extern const u8 BattleScript_NotAffected[]; extern const u8 BattleScript_NotAffected[];
@ -81,10 +80,7 @@ extern const u8 BattleScript_SelectingDisabledMoveInPalace[];
extern const u8 BattleScript_SelectingUnusableMoveInPalace[]; extern const u8 BattleScript_SelectingUnusableMoveInPalace[];
extern const u8 BattleScript_EncoredNoMore[]; extern const u8 BattleScript_EncoredNoMore[];
extern const u8 BattleScript_DestinyBondTakesLife[]; extern const u8 BattleScript_DestinyBondTakesLife[];
extern const u8 BattleScript_DmgHazardsOnAttacker[]; extern const u8 BattleScript_DmgHazardsOnBattler[];
extern const u8 BattleScript_DmgHazardsOnTarget[];
extern const u8 BattleScript_DmgHazardsOnBattlerScripting[];
extern const u8 BattleScript_DmgHazardsOnFaintedBattler[];
extern const u8 BattleScript_PerishSongTakesLife[]; extern const u8 BattleScript_PerishSongTakesLife[];
extern const u8 BattleScript_PerishSongCountGoesDown[]; extern const u8 BattleScript_PerishSongCountGoesDown[];
extern const u8 BattleScript_AllStatsUpZMove[]; extern const u8 BattleScript_AllStatsUpZMove[];
@ -199,7 +195,6 @@ extern const u8 BattleScript_AbilityStatusEffect[];
extern const u8 BattleScript_SynchronizeActivates[]; extern const u8 BattleScript_SynchronizeActivates[];
extern const u8 BattleScript_NoItemSteal[]; extern const u8 BattleScript_NoItemSteal[];
extern const u8 BattleScript_AbilityCuredStatus[]; extern const u8 BattleScript_AbilityCuredStatus[];
extern const u8 BattleScript_AbilityCuredStatusEnd3[];
extern const u8 BattleScript_IgnoresWhileAsleep[]; extern const u8 BattleScript_IgnoresWhileAsleep[];
extern const u8 BattleScript_IgnoresAndUsesRandomMove[]; extern const u8 BattleScript_IgnoresAndUsesRandomMove[];
extern const u8 BattleScript_MoveUsedLoafingAround[]; extern const u8 BattleScript_MoveUsedLoafingAround[];
@ -207,27 +202,20 @@ extern const u8 BattleScript_TruantLoafingAround[];
extern const u8 BattleScript_IgnoresAndFallsAsleep[]; extern const u8 BattleScript_IgnoresAndFallsAsleep[];
extern const u8 BattleScript_IgnoresAndHitsItself[]; extern const u8 BattleScript_IgnoresAndHitsItself[];
extern const u8 BattleScript_SubstituteFade[]; extern const u8 BattleScript_SubstituteFade[];
extern const u8 BattleScript_BerryCureStatusEnd2[];
extern const u8 BattleScript_BerryCureStatusRet[]; extern const u8 BattleScript_BerryCureStatusRet[];
extern const u8 BattleScript_BerryCureConfusionEnd2[];
extern const u8 BattleScript_BerryCureConfusionRet[]; extern const u8 BattleScript_BerryCureConfusionRet[];
extern const u8 BattleScript_WhiteHerbEnd2[]; extern const u8 BattleScript_WhiteHerbEnd2[];
extern const u8 BattleScript_WhiteHerbRet[]; extern const u8 BattleScript_WhiteHerbRet[];
extern const u8 BattleScript_ItemHealHP_RemoveItemRet[]; extern const u8 BattleScript_ItemHealHP_RemoveItem[];
extern const u8 BattleScript_ItemHealHP_RemoveItemEnd2[]; extern const u8 BattleScript_BerryPPHeal[];
extern const u8 BattleScript_BerryPPHealEnd2[];
extern const u8 BattleScript_BerryPPHealRet[];
extern const u8 BattleScript_ItemHealHP_End2[]; extern const u8 BattleScript_ItemHealHP_End2[];
extern const u8 BattleScript_ItemHealHP_Ret[]; extern const u8 BattleScript_ItemHealHP_Ret[];
extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItem[]; extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItem[];
extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItemInPalace[]; extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItemInPalace[];
extern const u8 BattleScript_HangedOnMsg[]; extern const u8 BattleScript_HangedOnMsg[];
extern const u8 BattleScript_BerryConfuseHealEnd2[]; extern const u8 BattleScript_BerryConfuseHeal[];
extern const u8 BattleScript_BerryConfuseHealRet[];
extern const u8 BattleScript_ConsumableStatRaiseEnd2[];
extern const u8 BattleScript_ConsumableStatRaiseRet[]; extern const u8 BattleScript_ConsumableStatRaiseRet[];
extern const u8 BattleScript_BerryFocusEnergyRet[]; extern const u8 BattleScript_BerryFocusEnergy[];
extern const u8 BattleScript_BerryFocusEnergyEnd2[];
extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[]; extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[];
extern const u8 BattleScript_AbilityAvoidsDamage[]; extern const u8 BattleScript_AbilityAvoidsDamage[];
extern const u8 BattleScript_AbilityShieldProtects[]; extern const u8 BattleScript_AbilityShieldProtects[];
@ -272,7 +260,6 @@ extern const u8 BattleScript_AttackerAbilityStatRaiseEnd2[];
extern const u8 BattleScript_PoisonHealActivates[]; extern const u8 BattleScript_PoisonHealActivates[];
extern const u8 BattleScript_BadDreamsActivates[]; extern const u8 BattleScript_BadDreamsActivates[];
extern const u8 BattleScript_SwitchInAbilityMsg[]; extern const u8 BattleScript_SwitchInAbilityMsg[];
extern const u8 BattleScript_SwitchInAbilityMsgRet[];
extern const u8 BattleScript_ToxicSpikesPoisoned[]; extern const u8 BattleScript_ToxicSpikesPoisoned[];
extern const u8 BattleScript_ToxicSpikesBadlyPoisoned[]; extern const u8 BattleScript_ToxicSpikesBadlyPoisoned[];
extern const u8 BattleScript_ToxicSpikesAbsorbed[]; extern const u8 BattleScript_ToxicSpikesAbsorbed[];
@ -344,7 +331,6 @@ extern const u8 BattleScript_WeaknessPolicy[];
extern const u8 BattleScript_TargetItemStatRaise[]; extern const u8 BattleScript_TargetItemStatRaise[];
extern const u8 BattleScript_RockyHelmetActivates[]; extern const u8 BattleScript_RockyHelmetActivates[];
extern const u8 BattleScript_ItemHurtEnd2[]; extern const u8 BattleScript_ItemHurtEnd2[];
extern const u8 BattleScript_AirBalloonMsgIn[];
extern const u8 BattleScript_AirBalloonMsgInRet[]; extern const u8 BattleScript_AirBalloonMsgInRet[];
extern const u8 BattleScript_AirBalloonMsgPop[]; extern const u8 BattleScript_AirBalloonMsgPop[];
extern const u8 BattleScript_ItemHurtRet[]; extern const u8 BattleScript_ItemHurtRet[];
@ -353,15 +339,12 @@ extern const u8 BattleScript_FlameOrb[];
extern const u8 BattleScript_MoveEffectIncinerate[]; extern const u8 BattleScript_MoveEffectIncinerate[];
extern const u8 BattleScript_MoveEffectBugBite[]; extern const u8 BattleScript_MoveEffectBugBite[];
extern const u8 BattleScript_IllusionOff[]; extern const u8 BattleScript_IllusionOff[];
extern const u8 BattleScript_IllusionOffEnd3[];
extern const u8 BattleScript_IllusionOffAndTerastallization[]; extern const u8 BattleScript_IllusionOffAndTerastallization[];
extern const u8 BattleScript_DancerActivates[]; extern const u8 BattleScript_DancerActivates[];
extern const u8 BattleScript_AftermathDmg[]; extern const u8 BattleScript_AftermathDmg[];
extern const u8 BattleScript_BattlerFormChange[]; extern const u8 BattleScript_BattlerFormChange[];
extern const u8 BattleScript_BattlerFormChangeEnd2[]; extern const u8 BattleScript_BattlerFormChangeEnd2[];
extern const u8 BattleScript_BattlerFormChangeEnd3[];
extern const u8 BattleScript_AttackerFormChangeWithString[]; extern const u8 BattleScript_AttackerFormChangeWithString[];
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[];
extern const u8 BattleScript_TargetFormChange[]; extern const u8 BattleScript_TargetFormChange[];
extern const u8 BattleScript_AnticipationActivates[]; extern const u8 BattleScript_AnticipationActivates[];
extern const u8 BattleScript_SlowStartEnds[]; extern const u8 BattleScript_SlowStartEnds[];
@ -373,9 +356,7 @@ extern const u8 BattleScript_FriskMsg[];
extern const u8 BattleScript_FriskMsgWithPopup[]; extern const u8 BattleScript_FriskMsgWithPopup[];
extern const u8 BattleScript_MoodyActivates[]; extern const u8 BattleScript_MoodyActivates[];
extern const u8 BattleScript_EmergencyExit[]; extern const u8 BattleScript_EmergencyExit[];
extern const u8 BattleScript_EmergencyExitWild[];
extern const u8 BattleScript_EmergencyExitEnd2[]; extern const u8 BattleScript_EmergencyExitEnd2[];
extern const u8 BattleScript_EmergencyExitWildEnd2[];
extern const u8 BattleScript_CheekPouchActivates[]; extern const u8 BattleScript_CheekPouchActivates[];
extern const u8 BattleScript_TotemVar[]; extern const u8 BattleScript_TotemVar[];
extern const u8 BattleScript_TotemFlaredToLife[]; extern const u8 BattleScript_TotemFlaredToLife[];
@ -392,7 +373,7 @@ extern const u8 BattleScript_QuickClawActivation[];
extern const u8 BattleScript_QuickDrawActivation[]; extern const u8 BattleScript_QuickDrawActivation[];
extern const u8 BattleScript_CustapBerryActivation[]; extern const u8 BattleScript_CustapBerryActivation[];
extern const u8 BattleScript_MicleBerryActivateEnd2[]; extern const u8 BattleScript_MicleBerryActivateEnd2[];
extern const u8 BattleScript_MicleBerryActivateRet[]; extern const u8 BattleScript_MicleBerryActivate[];
extern const u8 BattleScript_JabocaRowapBerryActivates[]; extern const u8 BattleScript_JabocaRowapBerryActivates[];
extern const u8 BattleScript_NotAffectedAbilityPopUp[]; extern const u8 BattleScript_NotAffectedAbilityPopUp[];
extern const u8 BattleScript_BattlerShookOffTaunt[]; extern const u8 BattleScript_BattlerShookOffTaunt[];
@ -405,7 +386,6 @@ extern const u8 BattleScript_RedCardActivates[];
extern const u8 BattleScript_EjectButtonActivates[]; extern const u8 BattleScript_EjectButtonActivates[];
extern const u8 BattleScript_EjectPackActivate_Ret[]; extern const u8 BattleScript_EjectPackActivate_Ret[];
extern const u8 BattleScript_EjectPackActivate_End2[]; extern const u8 BattleScript_EjectPackActivate_End2[];
extern const u8 BattleScript_EjectPackActivate_End3[];
extern const u8 BattleScript_EjectPackActivates[]; extern const u8 BattleScript_EjectPackActivates[];
extern const u8 BattleScript_MentalHerbCureRet[]; extern const u8 BattleScript_MentalHerbCureRet[];
extern const u8 BattleScript_MentalHerbCureEnd2[]; extern const u8 BattleScript_MentalHerbCureEnd2[];
@ -425,8 +405,7 @@ extern const u8 BattleScript_PrimalWeatherBlocksMove[];
extern const u8 BattleScript_DeltaStreamActivates[]; extern const u8 BattleScript_DeltaStreamActivates[];
extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[]; extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
extern const u8 BattleScript_AttackWeakenedByStrongWinds[]; extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[]; extern const u8 BattleScript_BlockedByPrimalWeather[];
extern const u8 BattleScript_BlockedByPrimalWeatherRet[];
extern const u8 BattleScript_PrimalReversion[]; extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[]; extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
@ -472,7 +451,7 @@ extern const u8 BattleScript_ToxicDebrisActivates[];
extern const u8 BattleScript_EarthEaterActivates[]; extern const u8 BattleScript_EarthEaterActivates[];
extern const u8 BattleScript_MimicryActivates[]; extern const u8 BattleScript_MimicryActivates[];
extern const u8 BattleScript_IceFaceNullsDamage[]; extern const u8 BattleScript_IceFaceNullsDamage[];
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[]; extern const u8 BattleScript_BattlerFormChangeWithString[];
extern const u8 BattleScript_DampPreventsAftermath[]; extern const u8 BattleScript_DampPreventsAftermath[];
extern const u8 BattleScript_HealingWishActivates[]; extern const u8 BattleScript_HealingWishActivates[];
extern const u8 BattleScript_LunarDanceActivates[]; extern const u8 BattleScript_LunarDanceActivates[];
@ -482,7 +461,6 @@ extern const u8 BattleScript_CouldntFullyProtect[];
extern const u8 BattleScript_MoveEffectStockpileWoreOff[]; extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_SpikesActivates[]; extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_BerserkGeneRet[]; extern const u8 BattleScript_BerserkGeneRet[];
extern const u8 BattleScript_BerserkGeneRetEnd2[];
extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[]; extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[];
extern const u8 BattleScript_DefDown[]; extern const u8 BattleScript_DefDown[];
extern const u8 BattleScript_UltraBurst[]; extern const u8 BattleScript_UltraBurst[];
@ -502,7 +480,6 @@ extern const u8 BattleScript_EffectPsychicNoise[];
extern const u8 BattleScript_AromaVeilProtectsRet[]; extern const u8 BattleScript_AromaVeilProtectsRet[];
extern const u8 BattleScript_LowerAtkSpAtk[]; extern const u8 BattleScript_LowerAtkSpAtk[];
extern const u8 BattleScript_Terastallization[]; extern const u8 BattleScript_Terastallization[];
extern const u8 BattleScript_BoosterEnergyEnd2[];
extern const u8 BattleScript_BoosterEnergyRet[]; extern const u8 BattleScript_BoosterEnergyRet[];
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[]; extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
extern const u8 BattleScript_TeraFormChange[]; extern const u8 BattleScript_TeraFormChange[];
@ -520,6 +497,7 @@ extern const u8 BattleScript_AlreadyParalyzed[];
extern const u8 BattleScript_AlreadyBurned[]; extern const u8 BattleScript_AlreadyBurned[];
extern const u8 BattleScript_PrintAbilityMadeIneffective[]; extern const u8 BattleScript_PrintAbilityMadeIneffective[];
extern const u8 BattleScript_ItDoesntAffectFoe[]; extern const u8 BattleScript_ItDoesntAffectFoe[];
extern const u8 BattleScript_FirstTurnSwitchInEvents[];
// zmoves // zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[]; extern const u8 BattleScript_ZMoveActivateDamaging[];

View File

@ -0,0 +1,8 @@
#ifndef GUARD_BATTLE_SWITCH_IN
#define GUARD_BATTLE_SWITCH_IN
#include "constants/battle_switch_in.h"
bool32 DoSwitchInEvents(void);
#endif // GUARD_BATTLE_SWITCH_IN

View File

@ -52,19 +52,21 @@ enum AbilityEffect
ABILITYEFFECT_ON_SWITCHIN, ABILITYEFFECT_ON_SWITCHIN,
ABILITYEFFECT_ENDTURN, ABILITYEFFECT_ENDTURN,
ABILITYEFFECT_MOVE_END_ATTACKER, ABILITYEFFECT_MOVE_END_ATTACKER,
ABILITYEFFECT_COLOR_CHANGE, // Color Change, Berserk, Anger Shell ABILITYEFFECT_COLOR_CHANGE, // Color Change / Berserk / Anger Shell
ABILITYEFFECT_MOVE_END, ABILITYEFFECT_MOVE_END,
ABILITYEFFECT_IMMUNITY, ABILITYEFFECT_IMMUNITY,
ABILITYEFFECT_SYNCHRONIZE, ABILITYEFFECT_SYNCHRONIZE,
ABILITYEFFECT_ATK_SYNCHRONIZE, ABILITYEFFECT_ATK_SYNCHRONIZE,
ABILITYEFFECT_MOVE_END_OTHER, ABILITYEFFECT_MOVE_END_OTHER,
// On Switch in
ABILITYEFFECT_TERA_SHIFT,
ABILITYEFFECT_NEUTRALIZINGGAS, ABILITYEFFECT_NEUTRALIZINGGAS,
ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, ABILITYEFFECT_UNNERVE,
ABILITYEFFECT_COMMANDER, // Commander / Hospitality / Costar
ABILITYEFFECT_ON_WEATHER, ABILITYEFFECT_ON_WEATHER,
ABILITYEFFECT_ON_TERRAIN, ABILITYEFFECT_ON_TERRAIN,
ABILITYEFFECT_OPPORTUNIST, ABILITYEFFECT_OPPORTUNIST,
ABILITYEFFECT_OPPORTUNIST_FIRST_TURN,
ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES,
}; };
enum ItemEffect enum ItemEffect
@ -207,7 +209,7 @@ enum SkyDropState
enum EjectPackTiming enum EjectPackTiming
{ {
FIRST_TURN, START_OF_TURN,
END_TURN, END_TURN,
OTHER, OTHER,
}; };
@ -263,7 +265,7 @@ bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag);
bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option); bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityAtk, enum Ability abilityDef, u32 move, enum FunctionCallOption option);
bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, enum Type moveType, enum FunctionCallOption option); bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, enum Type moveType, enum FunctionCallOption option);
bool32 TryFieldEffects(enum FieldEffectCases caseId); bool32 TryFieldEffects(enum FieldEffectCases caseId);
u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ability, u32 special, u32 moveArg); u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ability, u32 move, bool32 shouldAbilityTrigger);
bool32 TryPrimalReversion(u32 battler); bool32 TryPrimalReversion(u32 battler);
bool32 IsNeutralizingGasOnField(void); bool32 IsNeutralizingGasOnField(void);
bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability); bool32 IsMoldBreakerTypeAbility(u32 battler, enum Ability ability);
@ -322,13 +324,13 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method);
bool32 DoBattlersShareType(u32 battler1, u32 battler2); bool32 DoBattlersShareType(u32 battler1, u32 battler2);
bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId); bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId);
u32 GetBattlerVisualSpecies(u32 battler); u32 GetBattlerVisualSpecies(u32 battler);
bool32 TryClearIllusion(u32 battler, enum AbilityEffect caseID); bool32 TryClearIllusion(u32 battler, enum Ability ability);
u32 GetIllusionMonSpecies(u32 battler); u32 GetIllusionMonSpecies(u32 battler);
struct Pokemon *GetIllusionMonPtr(u32 battler); struct Pokemon *GetIllusionMonPtr(u32 battler);
void ClearIllusionMon(u32 battler); void ClearIllusionMon(u32 battler);
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler); u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler);
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler); bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
u32 TryImmunityAbilityHealStatus(u32 battler, enum AbilityEffect caseID); u32 TryImmunityAbilityHealStatus(u32 battler);
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler); bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
uq4_12_t GetBadgeBoostModifier(void); uq4_12_t GetBadgeBoostModifier(void);
enum DamageCategory GetBattleMoveCategory(u32 move); enum DamageCategory GetBattleMoveCategory(u32 move);
@ -347,7 +349,7 @@ void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item); bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem); void TrySaveExchangedItem(u32 battler, u16 stolenItem);
bool32 IsPartnerMonFromSameTrainer(u32 battler); bool32 IsPartnerMonFromSameTrainer(u32 battler);
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes); bool32 IsBattlerAffectedByHazards(u32 battler, enum HoldEffect holdEffect, bool32 toxicSpikes);
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast); void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability); bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability);
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget); bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
@ -415,6 +417,8 @@ bool32 HadMoreThanHalfHpNowDoesnt(u32 battler);
void ChooseStatBoostAnimation(u32 battler); void ChooseStatBoostAnimation(u32 battler);
void UpdateStallMons(void); void UpdateStallMons(void);
bool32 TrySwitchInEjectPack(enum EjectPackTiming timing); bool32 TrySwitchInEjectPack(enum EjectPackTiming timing);
bool32 TryEmergencyExit(void);
bool32 EmergencyExitCanBeTriggered(u32 battler);
u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile); u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile);
void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue); void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue);
bool32 ItemHealMonVolatile(u32 battler, u16 itemId); bool32 ItemHealMonVolatile(u32 battler, u16 itemId);

View File

@ -218,7 +218,7 @@ enum VolatileFlags
F(VOLATILE_VESSEL_OF_RUIN, vesselOfRuin, (u32, 1)) \ F(VOLATILE_VESSEL_OF_RUIN, vesselOfRuin, (u32, 1)) \
F(VOLATILE_SWORD_OF_RUIN, swordOfRuin, (u32, 1)) \ F(VOLATILE_SWORD_OF_RUIN, swordOfRuin, (u32, 1)) \
F(VOLATILE_TABLETS_OF_RUIN, tabletsOfRuin, (u32, 1)) \ F(VOLATILE_TABLETS_OF_RUIN, tabletsOfRuin, (u32, 1)) \
F(VOLATILE_BEADS_OF_RUIN, beadsOfRuin, (u32, 1)) F(VOLATILE_BEADS_OF_RUIN, beadsOfRuin, (u32, 1))
/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */ /* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */

View File

@ -88,17 +88,10 @@
#define CMP_COMMON_BITS 4 #define CMP_COMMON_BITS 4
#define CMP_NO_COMMON_BITS 5 #define CMP_NO_COMMON_BITS 5
// Veriouses have been deprecated but the enum and function will be supported for one more release cycle
enum CmdVarious
{
VARIOUS_NONE,
};
// Cmd_manipulatedamage // Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 1 #define DMG_CHANGE_SIGN 1
#define DMG_1_8_TARGET_HP 2 #define DMG_1_8_TARGET_HP 2
#define DMG_FULL_ATTACKER_HP 3 #define DMG_BIG_ROOT 3
#define DMG_BIG_ROOT 4
// Cmd_jumpifcantswitch // Cmd_jumpifcantswitch
#define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7) #define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7)
@ -189,10 +182,12 @@ enum MoveEndEffects
MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE = (MOVEEND_HIT_ESCAPE + 1), MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE = (MOVEEND_HIT_ESCAPE + 1),
}; };
// switch cases enum SwitchInCases
#define B_SWITCH_NORMAL 0 {
#define B_SWITCH_HIT 1 // dragon tail, circle throw B_SWITCH_NORMAL,
#define B_SWITCH_RED_CARD 2 B_SWITCH_HIT, // dragon tail, circle throw
B_SWITCH_RED_CARD,
};
enum StatusTrigger enum StatusTrigger
{ {

View File

@ -0,0 +1,37 @@
#ifndef GUARD_CONSTANTS_BATTLE_SWITCH_IN_H
#define GUARD_CONSTANTS_BATTLE_SWITCH_IN_H
enum SwitchInEvents
{
SWITCH_IN_EVENTS_ORDER_BY_SPEED,
SWITCH_IN_EVENTS_TERA_SHIFT,
SWITCH_IN_EVENTS_NEUTRALIZING_GAS,
SWITCH_IN_EVENTS_UNNERVE,
SWITCH_IN_EVENTS_FIRST_BLOCK,
SWITCH_IN_EVENTS_SECOND_BLOCK,
SWITCH_IN_EVENTS_WHITE_HERB,
SWITCH_IN_EVENTS_OPPORTUNIST,
SWITCH_IN_EVENTS_MIRROR_HERB,
SWITCH_IN_EVENTS_CLEAR_SET_VALUES,
SWITCH_IN_EVENTS_EJECT_PACK,
SWITCH_IN_EVENTS_COUNT,
};
enum SwitchInFirstEventBlock
{
FIRST_EVENT_BLOCK_HEALING_WISH,
FIRST_EVENT_BLOCK_HAZARDS,
FIRST_EVENT_BLOCK_GENERAL_ABILITIES,
FIRST_EVENT_BLOCK_IMMUNITY_ABILITIES,
FIRST_EVENT_BLOCK_ITEMS,
FIRST_EVENT_BLOCK_COUNT,
};
enum SwitchInSecondEventBlock
{
SECOND_EVENT_ABILITIES,
SECOND_EVENT_BOOSTER_ENERGY,
SECOND_EVENT_BLOCK_COUNT,
};
#endif // GUARD_CONSTANTS_BATTLE_SWITCH_IN_H

View File

@ -111,12 +111,12 @@ u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario)
static bool32 IsAceMon(u32 battler, u32 monPartyId) static bool32 IsAceMon(u32 battler, u32 monPartyId)
{ {
if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON
&& !gBattleStruct->battlerState[battler].forcedSwitch && !gProtectStructs[battler].forcedSwitch
&& monPartyId == CalculateEnemyPartyCountInSide(battler)-1) && monPartyId == CalculateEnemyPartyCountInSide(battler)-1)
return TRUE; return TRUE;
if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON
&& !gBattleStruct->battlerState[battler].forcedSwitch && !gProtectStructs[battler].forcedSwitch
&& (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2)) && (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2))
return TRUE; return TRUE;
return FALSE; return FALSE;
} }

View File

@ -190,7 +190,7 @@ void ActivateDynamax(u32 battler)
if (!gBattleMons[battler].volatiles.transformed) // Ditto cannot Gigantamax. if (!gBattleMons[battler].volatiles.transformed) // Ditto cannot Gigantamax.
TryBattleFormChange(battler, FORM_CHANGE_BATTLE_GIGANTAMAX); TryBattleFormChange(battler, FORM_CHANGE_BATTLE_GIGANTAMAX);
BattleScriptExecute(BattleScript_DynamaxBegins); BattleScriptPushCursorAndCallback(BattleScript_DynamaxBegins);
} }
// Unsets the flags used for Dynamaxing and reverts max HP if needed. // Unsets the flags used for Dynamaxing and reverts max HP if needed.

View File

@ -123,7 +123,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler)
case BATTLE_WEATHER_RAIN_DOWNPOUR: case BATTLE_WEATHER_RAIN_DOWNPOUR:
if (ability == ABILITY_DRY_SKIN || ability == ABILITY_RAIN_DISH) if (ability == ABILITY_DRY_SKIN || ability == ABILITY_RAIN_DISH)
{ {
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
} }
break; break;
@ -131,7 +131,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler)
case BATTLE_WEATHER_SUN_PRIMAL: case BATTLE_WEATHER_SUN_PRIMAL:
if (ability == ABILITY_DRY_SKIN || ability == ABILITY_SOLAR_POWER) if (ability == ABILITY_DRY_SKIN || ability == ABILITY_SOLAR_POWER)
{ {
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
} }
break; break;
@ -156,7 +156,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler)
case BATTLE_WEATHER_SNOW: case BATTLE_WEATHER_SNOW:
if (ability == ABILITY_ICE_BODY) if (ability == ABILITY_ICE_BODY)
{ {
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
} }
else if (currBattleWeather == BATTLE_WEATHER_HAIL) else if (currBattleWeather == BATTLE_WEATHER_HAIL)
@ -192,12 +192,8 @@ static bool32 HandleEndTurnEmergencyExit(u32 battler)
{ {
gBattlerAbility = battler; gBattlerAbility = battler;
gLastUsedAbility = ability; gLastUsedAbility = ability;
gBattleScripting.battler = battler;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) BattleScriptExecute(BattleScript_EmergencyExitEnd2);
BattleScriptExecute(BattleScript_EmergencyExitEnd2);
else
BattleScriptExecute(BattleScript_EmergencyExitWildEnd2);
effect = TRUE; effect = TRUE;
} }
@ -380,7 +376,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
case ABILITY_HEALER: case ABILITY_HEALER:
case ABILITY_HYDRATION: case ABILITY_HYDRATION:
case ABILITY_SHED_SKIN: case ABILITY_SHED_SKIN:
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
break; break;
default: default:
@ -1281,7 +1277,7 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler)
case ABILITY_MOODY: case ABILITY_MOODY:
case ABILITY_PICKUP: case ABILITY_PICKUP:
case ABILITY_SPEED_BOOST: case ABILITY_SPEED_BOOST:
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
break; break;
default: default:
@ -1333,7 +1329,7 @@ static bool32 HandleEndTurnFormChangeAbilities(u32 battler)
case ABILITY_SHIELDS_DOWN: case ABILITY_SHIELDS_DOWN:
case ABILITY_ZEN_MODE: case ABILITY_ZEN_MODE:
case ABILITY_HUNGER_SWITCH: case ABILITY_HUNGER_SWITCH:
if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, 0, MOVE_NONE)) if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, battler, ability, MOVE_NONE, TRUE))
effect = TRUE; effect = TRUE;
default: default:
break; break;

View File

@ -12,11 +12,8 @@
#include "constants/berry.h" #include "constants/berry.h"
bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onSwitchIn; } bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onSwitchIn; }
bool32 IsOnSwitchInFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onSwitchInFirstTurn; }
bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].mirrorHerb; } bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].mirrorHerb; }
bool32 IsMirrorHerbFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].mirrorHerbFirstTurn; }
bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerb; } bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerb; }
bool32 IsWhiteHerbFirstTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerbFirstTurn; }
bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerbEndTurn; } bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].whiteHerbEndTurn; }
bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onStatusChange; } bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onStatusChange; }
bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onHpThreshold; } bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onHpThreshold; }
@ -29,6 +26,7 @@ bool32 IsOrbsActivation(enum HoldEffect holdEffect) { return gHol
bool32 IsOnEffectActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onEffect; } bool32 IsOnEffectActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onEffect; }
bool32 IsOnBerryActivation(enum HoldEffect holdEffect) { return GetItemPocket(gLastUsedItem) == POCKET_BERRIES; } bool32 IsOnBerryActivation(enum HoldEffect holdEffect) { return GetItemPocket(gLastUsedItem) == POCKET_BERRIES; }
bool32 IsOnFlingActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onFling; } bool32 IsOnFlingActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onFling; }
bool32 IsBoosterEnergyActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].boosterEnergy; }
bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect) bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect)
{ {
@ -51,7 +49,7 @@ static enum ItemEffect TryDoublePrize(u32 battler)
return effect; return effect;
} }
enum ItemEffect TryBoosterEnergy(u32 battler, enum Ability ability, ActivationTiming timing) enum ItemEffect TryBoosterEnergy(u32 battler, enum Ability ability)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -66,17 +64,14 @@ enum ItemEffect TryBoosterEnergy(u32 battler, enum Ability ability, ActivationTi
gBattlerAbility = gBattleScripting.battler = battler; gBattlerAbility = gBattleScripting.battler = battler;
gDisableStructs[battler].boosterEnergyActivated = TRUE; gDisableStructs[battler].boosterEnergyActivated = TRUE;
RecordAbilityBattle(battler, ability); RecordAbilityBattle(battler, ability);
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BoosterEnergyRet);
BattleScriptExecute(BattleScript_BoosterEnergyEnd2);
else
BattleScriptCall(BattleScript_BoosterEnergyRet);
effect = ITEM_EFFECT_OTHER; effect = ITEM_EFFECT_OTHER;
} }
return effect; return effect;
} }
static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing) static enum ItemEffect TryRoomService(u32 battler)
{ {
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler))) if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler)))
{ {
@ -84,19 +79,15 @@ static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing)
SET_STATCHANGER(STAT_SPEED, 1, TRUE); SET_STATCHANGER(STAT_SPEED, 1, TRUE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED; gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_SPEED;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
gLastUsedItem = gBattleMons[battler].item;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2);
else
BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
return ITEM_STATS_CHANGE; return ITEM_STATS_CHANGE;
} }
return ITEM_NO_EFFECT; return ITEM_NO_EFFECT;
} }
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId, ActivationTiming timing) enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId)
{ {
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler))) if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler)))
{ {
@ -104,32 +95,29 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId, Ac
SET_STATCHANGER(statId, 1, FALSE); SET_STATCHANGER(statId, 1, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2);
else
BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
return ITEM_STATS_CHANGE; return ITEM_STATS_CHANGE;
} }
return ITEM_NO_EFFECT; return ITEM_NO_EFFECT;
} }
static enum ItemEffect TryTerrainSeeds(u32 battler, u32 item, ActivationTiming timing) static enum ItemEffect TryTerrainSeeds(u32 battler, u32 item)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
switch (GetItemHoldEffectParam(item)) switch (GetItemHoldEffectParam(item))
{ {
case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN: case HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF, timing); effect = TryHandleSeed(battler, STATUS_FIELD_ELECTRIC_TERRAIN, STAT_DEF);
break; break;
case HOLD_EFFECT_PARAM_GRASSY_TERRAIN: case HOLD_EFFECT_PARAM_GRASSY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF, timing); effect = TryHandleSeed(battler, STATUS_FIELD_GRASSY_TERRAIN, STAT_DEF);
break; break;
case HOLD_EFFECT_PARAM_MISTY_TERRAIN: case HOLD_EFFECT_PARAM_MISTY_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF, timing); effect = TryHandleSeed(battler, STATUS_FIELD_MISTY_TERRAIN, STAT_SPDEF);
break; break;
case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN: case HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN:
effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF, timing); effect = TryHandleSeed(battler, STATUS_FIELD_PSYCHIC_TERRAIN, STAT_SPDEF);
break; break;
} }
@ -146,7 +134,7 @@ static bool32 CanBeInfinitelyConfused(u32 battler)
return TRUE; return TRUE;
} }
static enum ItemEffect TryBerserkGene(u32 battler, ActivationTiming timing) static enum ItemEffect TryBerserkGene(u32 battler)
{ {
if (CanBeInfinitelyConfused(battler)) if (CanBeInfinitelyConfused(battler))
gBattleMons[battler].volatiles.infiniteConfusion = TRUE; gBattleMons[battler].volatiles.infiniteConfusion = TRUE;
@ -154,11 +142,7 @@ static enum ItemEffect TryBerserkGene(u32 battler, ActivationTiming timing)
SET_STATCHANGER(STAT_ATK, 2, FALSE); SET_STATCHANGER(STAT_ATK, 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK; gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + STAT_ATK;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerserkGeneRet);
BattleScriptExecute(BattleScript_BerserkGeneRetEnd2);
else
BattleScriptCall(BattleScript_BerserkGeneRet);
return ITEM_STATS_CHANGE; return ITEM_STATS_CHANGE;
} }
@ -185,7 +169,7 @@ static enum ItemEffect RestoreWhiteHerbStats(u32 battler, ActivationTiming timin
return effect; return effect;
} }
static enum ItemEffect TryConsumeMirrorHerb(u32 battler, ActivationTiming timing) static enum ItemEffect TryConsumeMirrorHerb(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -193,10 +177,7 @@ static enum ItemEffect TryConsumeMirrorHerb(u32 battler, ActivationTiming timing
{ {
gProtectStructs[battler].eatMirrorHerb = 0; gProtectStructs[battler].eatMirrorHerb = 0;
ChooseStatBoostAnimation(battler); ChooseStatBoostAnimation(battler);
if (timing == IsMirrorHerbFirstTurnActivation) BattleScriptCall(BattleScript_MirrorHerbCopyStatChange);
BattleScriptExecute(BattleScript_MirrorHerbCopyStatChangeEnd2);
else
BattleScriptCall(BattleScript_MirrorHerbCopyStatChange);
effect = ITEM_STATS_CHANGE; effect = ITEM_STATS_CHANGE;
} }
@ -244,10 +225,7 @@ static enum ItemEffect TryAirBalloon(u32 battler, ActivationTiming timing)
else if (!gSpecialStatuses[battler].switchInItemDone) else if (!gSpecialStatuses[battler].switchInItemDone)
{ {
gSpecialStatuses[battler].switchInItemDone = TRUE; gSpecialStatuses[battler].switchInItemDone = TRUE;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_AirBalloonMsgInRet);
BattleScriptPushCursorAndCallback(BattleScript_AirBalloonMsgIn);
else
BattleScriptCall(BattleScript_AirBalloonMsgInRet);
RecordItemEffectBattle(battler, HOLD_EFFECT_AIR_BALLOON); RecordItemEffectBattle(battler, HOLD_EFFECT_AIR_BALLOON);
effect = ITEM_EFFECT_OTHER; effect = ITEM_EFFECT_OTHER;
} }
@ -411,7 +389,7 @@ static enum ItemEffect TrySetEnigmaBerry(u32 battlerDef, u32 battlerAtk)
if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN) if (GetBattlerAbility(battlerDef) == ABILITY_RIPEN)
healAmount *= 2; healAmount *= 2;
SetHealAmount(battlerDef, healAmount); SetHealAmount(battlerDef, healAmount);
BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet); BattleScriptCall(BattleScript_ItemHealHP_RemoveItem);
effect = ITEM_HP_CHANGE; effect = ITEM_HP_CHANGE;
} }
@ -677,7 +655,7 @@ static enum ItemEffect TryBlackSludgeDamage(u32 battler, enum HoldEffect holdEff
return effect; return effect;
} }
static enum ItemEffect TryCureParalysis(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureParalysis(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -685,17 +663,14 @@ static enum ItemEffect TryCureParalysis(u32 battler, ActivationTiming timing)
{ {
gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS; gBattleMons[battler].status1 &= ~STATUS1_PARALYSIS;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PARALYSIS; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_PARALYSIS;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureStatusRet);
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
effect = ITEM_STATUS_CHANGE; effect = ITEM_STATUS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect TryCurePoison(u32 battler, ActivationTiming timing) static enum ItemEffect TryCurePoison(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -703,17 +678,14 @@ static enum ItemEffect TryCurePoison(u32 battler, ActivationTiming timing)
{ {
gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER); gBattleMons[battler].status1 &= ~(STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_POISON; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_POISON;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureStatusRet);
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
effect = ITEM_STATUS_CHANGE; effect = ITEM_STATUS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect TryCureBurn(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureBurn(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -721,17 +693,14 @@ static enum ItemEffect TryCureBurn(u32 battler, ActivationTiming timing)
{ {
gBattleMons[battler].status1 &= ~STATUS1_BURN; gBattleMons[battler].status1 &= ~STATUS1_BURN;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_BURN; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_BURN;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureStatusRet);
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
effect = ITEM_STATUS_CHANGE; effect = ITEM_STATUS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect TryCureFreezeOrFrostbite(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureFreezeOrFrostbite(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -749,17 +718,12 @@ static enum ItemEffect TryCureFreezeOrFrostbite(u32 battler, ActivationTiming ti
} }
if (effect == ITEM_STATUS_CHANGE) if (effect == ITEM_STATUS_CHANGE)
{ BattleScriptCall(BattleScript_BerryCureStatusRet);
if (timing == IsOnSwitchInFirstTurnActivation)
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
}
return effect; return effect;
} }
static enum ItemEffect TryCureSleep(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureSleep(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -769,34 +733,28 @@ static enum ItemEffect TryCureSleep(u32 battler, ActivationTiming timing)
gBattleMons[battler].volatiles.nightmare = FALSE; gBattleMons[battler].volatiles.nightmare = FALSE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_SLEEP; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_CURED_SLEEP;
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]); TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureStatusRet);
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
effect = ITEM_STATUS_CHANGE; effect = ITEM_STATUS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect TryCureConfusion(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureConfusion(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
if (gBattleMons[battler].volatiles.confusionTurns > 0) if (gBattleMons[battler].volatiles.confusionTurns > 0)
{ {
RemoveConfusionStatus(battler); RemoveConfusionStatus(battler);
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureConfusionRet);
BattleScriptExecute(BattleScript_BerryCureConfusionEnd2);
else
BattleScriptCall(BattleScript_BerryCureConfusionRet);
effect = ITEM_EFFECT_OTHER; effect = ITEM_EFFECT_OTHER;
} }
return effect; return effect;
} }
static enum ItemEffect TryCureAnyStatus(u32 battler, ActivationTiming timing) static enum ItemEffect TryCureAnyStatus(u32 battler)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
u32 string = 0; u32 string = 0;
@ -841,10 +799,7 @@ static enum ItemEffect TryCureAnyStatus(u32 battler, ActivationTiming timing)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_NORMALIZED_STATUS;
gBattleMons[battler].status1 = 0; gBattleMons[battler].status1 = 0;
RemoveConfusionStatus(battler); RemoveConfusionStatus(battler);
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryCureStatusRet);
BattleScriptExecute(BattleScript_BerryCureStatusEnd2);
else
BattleScriptCall(BattleScript_BerryCureStatusRet);
effect = ITEM_STATUS_CHANGE; effect = ITEM_STATUS_CHANGE;
} }
@ -857,7 +812,7 @@ enum HealAmount
PERCENT_HEAL_AMOUNT, PERCENT_HEAL_AMOUNT,
}; };
static u32 ItemHealHp(u32 battler, u32 itemId, enum HealAmount percentHeal, ActivationTiming timing) static u32 ItemHealHp(u32 battler, u32 itemId, enum HealAmount percentHeal)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
enum Ability ability = GetBattlerAbility(battler); enum Ability ability = GetBattlerAbility(battler);
@ -876,18 +831,14 @@ static u32 ItemHealHp(u32 battler, u32 itemId, enum HealAmount percentHeal, Acti
healAmount *= 2; healAmount *= 2;
SetHealAmount(battler, healAmount); SetHealAmount(battler, healAmount);
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_ItemHealHP_RemoveItem);
BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2);
else
BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet);
effect = ITEM_HP_CHANGE; effect = ITEM_HP_CHANGE;
} }
return effect; return effect;
} }
static u32 ItemRestorePp(u32 battler, u32 itemId, ActivationTiming timing) static u32 ItemRestorePp(u32 battler, u32 itemId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
struct Pokemon *mon = GetBattlerMon(battler); struct Pokemon *mon = GetBattlerMon(battler);
@ -915,12 +866,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, ActivationTiming timing)
changedPP = currentPP + ppRestored; changedPP = currentPP + ppRestored;
PREPARE_MOVE_BUFFER(gBattleTextBuff1, move); PREPARE_MOVE_BUFFER(gBattleTextBuff1, move);
BattleScriptCall(BattleScript_BerryPPHeal);
if (timing == IsOnSwitchInFirstTurnActivation)
BattleScriptExecute(BattleScript_BerryPPHealEnd2);
else
BattleScriptCall(BattleScript_BerryPPHealRet);
gBattleScripting.battler = battler; gBattleScripting.battler = battler;
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP); BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP);
MarkBattlerForControllerExec(battler); MarkBattlerForControllerExec(battler);
@ -932,7 +878,7 @@ static u32 ItemRestorePp(u32 battler, u32 itemId, ActivationTiming timing)
return effect; return effect;
} }
static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, ActivationTiming timing) static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
u32 hpFraction = B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2; u32 hpFraction = B_CONFUSE_BERRIES_HEAL >= GEN_7 ? 4 : 2;
@ -945,28 +891,17 @@ static enum ItemEffect HealConfuseBerry(u32 battler, u32 itemId, u32 flavorId, A
if (ability == ABILITY_RIPEN) if (ability == ABILITY_RIPEN)
healAmount *= 2; healAmount *= 2;
SetHealAmount(battler, healAmount); SetHealAmount(battler, healAmount);
if (timing == IsOnSwitchInFirstTurnActivation) if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0)
{ BattleScriptCall(BattleScript_BerryConfuseHeal);
if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0)
BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
else
BattleScriptExecute(BattleScript_ItemHealHP_RemoveItemEnd2);
}
else else
{ BattleScriptCall(BattleScript_ItemHealHP_RemoveItem);
if (GetFlavorRelationByPersonality(gBattleMons[battler].personality, flavorId) < 0)
BattleScriptCall(BattleScript_BerryConfuseHealRet);
else
BattleScriptCall(BattleScript_ItemHealHP_RemoveItemRet);
}
PREPARE_FLAVOR_BUFFER(gBattleTextBuff1, flavorId);
effect = ITEM_HP_CHANGE; effect = ITEM_HP_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, enum Stat statId, ActivationTiming timing) static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, enum Stat statId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
enum Ability ability = GetBattlerAbility(battler); enum Ability ability = GetBattlerAbility(battler);
@ -978,18 +913,14 @@ static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, enum Stat statId,
SET_STATCHANGER(statId, ability == ABILITY_RIPEN ? 2 : 1, FALSE); SET_STATCHANGER(statId, ability == ABILITY_RIPEN ? 2 : 1, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId; gBattleScripting.animArg1 = STAT_ANIM_PLUS1 + statId;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
if (timing == IsOnSwitchInFirstTurnActivation)
BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2);
else
BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
effect = ITEM_STATS_CHANGE; effect = ITEM_STATS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect CriticalHitRatioUp(u32 battler, u32 itemId, ActivationTiming timing) static enum ItemEffect CriticalHitRatioUp(u32 battler, u32 itemId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
@ -998,17 +929,14 @@ static enum ItemEffect CriticalHitRatioUp(u32 battler, u32 itemId, ActivationTim
&& HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), GetItemHoldEffectParam(itemId), itemId)) && HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), GetItemHoldEffectParam(itemId), itemId))
{ {
gBattleMons[battler].volatiles.focusEnergy = TRUE; gBattleMons[battler].volatiles.focusEnergy = TRUE;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_BerryFocusEnergy);
BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2);
else
BattleScriptCall(BattleScript_BerryFocusEnergyRet);
effect = ITEM_EFFECT_OTHER; effect = ITEM_EFFECT_OTHER;
} }
return effect; return effect;
} }
static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, ActivationTiming timing) static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
enum Stat stat; enum Stat stat;
@ -1039,27 +967,21 @@ static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, ActivationT
SET_STATCHANGER(stat, ability == ABILITY_RIPEN ? 4 : 2, FALSE); SET_STATCHANGER(stat, ability == ABILITY_RIPEN ? 4 : 2, FALSE);
gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + stat; gBattleScripting.animArg1 = STAT_ANIM_PLUS2 + stat;
gBattleScripting.animArg2 = 0; gBattleScripting.animArg2 = 0;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
BattleScriptExecute(BattleScript_ConsumableStatRaiseEnd2);
else
BattleScriptCall(BattleScript_ConsumableStatRaiseRet);
effect = ITEM_STATS_CHANGE; effect = ITEM_STATS_CHANGE;
} }
return effect; return effect;
} }
static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId, ActivationTiming timing) static enum ItemEffect TrySetMicleBerry(u32 battler, u32 itemId)
{ {
enum ItemEffect effect = ITEM_NO_EFFECT; enum ItemEffect effect = ITEM_NO_EFFECT;
if (HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), 4, itemId)) if (HasEnoughHpToEatBerry(battler, GetBattlerAbility(battler), 4, itemId))
{ {
gBattleStruct->battlerState[battler].usedMicleBerry = TRUE; gBattleStruct->battlerState[battler].usedMicleBerry = TRUE;
if (timing == IsOnSwitchInFirstTurnActivation) BattleScriptCall(BattleScript_MicleBerryActivate);
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
else
BattleScriptCall(BattleScript_MicleBerryActivateRet);
effect = ITEM_EFFECT_OTHER; effect = ITEM_EFFECT_OTHER;
} }
return effect; return effect;
@ -1092,22 +1014,22 @@ enum ItemEffect ItemBattleEffects(u32 itemBattler, u32 battler, enum HoldEffect
effect = TryDoublePrize(itemBattler); effect = TryDoublePrize(itemBattler);
break; break;
case HOLD_EFFECT_ROOM_SERVICE: case HOLD_EFFECT_ROOM_SERVICE:
effect = TryRoomService(itemBattler, timing); effect = TryRoomService(itemBattler);
break; break;
case HOLD_EFFECT_TERRAIN_SEED: case HOLD_EFFECT_TERRAIN_SEED:
effect = TryTerrainSeeds(itemBattler, item, timing); effect = TryTerrainSeeds(itemBattler, item);
break; break;
case HOLD_EFFECT_BERSERK_GENE: case HOLD_EFFECT_BERSERK_GENE:
effect = TryBerserkGene(itemBattler, timing); effect = TryBerserkGene(itemBattler);
break; break;
case HOLD_EFFECT_BOOSTER_ENERGY: case HOLD_EFFECT_BOOSTER_ENERGY:
effect = TryBoosterEnergy(itemBattler, GetBattlerAbility(itemBattler), timing); effect = TryBoosterEnergy(itemBattler, GetBattlerAbility(itemBattler));
break; break;
case HOLD_EFFECT_WHITE_HERB: case HOLD_EFFECT_WHITE_HERB:
effect = RestoreWhiteHerbStats(itemBattler, timing); effect = RestoreWhiteHerbStats(itemBattler, timing);
break; break;
case HOLD_EFFECT_MIRROR_HERB: case HOLD_EFFECT_MIRROR_HERB:
effect = TryConsumeMirrorHerb(itemBattler, timing); effect = TryConsumeMirrorHerb(itemBattler);
break; break;
case HOLD_EFFECT_FLINCH: // Kings Rock case HOLD_EFFECT_FLINCH: // Kings Rock
effect = TryKingsRock(itemBattler, battler, item); effect = TryKingsRock(itemBattler, battler, item);
@ -1185,73 +1107,73 @@ enum ItemEffect ItemBattleEffects(u32 itemBattler, u32 battler, enum HoldEffect
effect = TryBlackSludgeDamage(itemBattler, holdEffect); effect = TryBlackSludgeDamage(itemBattler, holdEffect);
break; break;
case HOLD_EFFECT_CURE_PAR: // Cheri Berry case HOLD_EFFECT_CURE_PAR: // Cheri Berry
effect = TryCureParalysis(itemBattler, timing); effect = TryCureParalysis(itemBattler);
break; break;
case HOLD_EFFECT_CURE_PSN: // Pecha Berry case HOLD_EFFECT_CURE_PSN: // Pecha Berry
effect = TryCurePoison(itemBattler, timing); effect = TryCurePoison(itemBattler);
break; break;
case HOLD_EFFECT_CURE_BRN: // Rawst Berry case HOLD_EFFECT_CURE_BRN: // Rawst Berry
effect = TryCureBurn(itemBattler, timing); effect = TryCureBurn(itemBattler);
break; break;
case HOLD_EFFECT_CURE_FRZ: // Aspear Berry case HOLD_EFFECT_CURE_FRZ: // Aspear Berry
effect = TryCureFreezeOrFrostbite(itemBattler, timing); effect = TryCureFreezeOrFrostbite(itemBattler);
break; break;
case HOLD_EFFECT_CURE_SLP: // Chesto Berry case HOLD_EFFECT_CURE_SLP: // Chesto Berry
effect = TryCureSleep(itemBattler, timing); effect = TryCureSleep(itemBattler);
break; break;
case HOLD_EFFECT_CURE_CONFUSION: // Persim Berry case HOLD_EFFECT_CURE_CONFUSION: // Persim Berry
effect = TryCureConfusion(itemBattler, timing); effect = TryCureConfusion(itemBattler);
break; break;
case HOLD_EFFECT_CURE_STATUS: // Lum Berry case HOLD_EFFECT_CURE_STATUS: // Lum Berry
effect = TryCureAnyStatus(itemBattler, timing); effect = TryCureAnyStatus(itemBattler);
break; break;
case HOLD_EFFECT_RESTORE_HP: // Oran / Sitrus Berry / Berry Juice case HOLD_EFFECT_RESTORE_HP: // Oran / Sitrus Berry / Berry Juice
effect = ItemHealHp(itemBattler, item, FIXED_HEAL_AMOUNT, timing); effect = ItemHealHp(itemBattler, item, FIXED_HEAL_AMOUNT);
break; break;
case HOLD_EFFECT_RESTORE_PCT_HP: // Sitrus Berry case HOLD_EFFECT_RESTORE_PCT_HP: // Sitrus Berry
effect = ItemHealHp(itemBattler, item, PERCENT_HEAL_AMOUNT, timing); effect = ItemHealHp(itemBattler, item, PERCENT_HEAL_AMOUNT);
break; break;
case HOLD_EFFECT_RESTORE_PP: // Leppa Berry case HOLD_EFFECT_RESTORE_PP: // Leppa Berry
effect = ItemRestorePp(itemBattler, item, timing); effect = ItemRestorePp(itemBattler, item);
break; break;
case HOLD_EFFECT_CONFUSE_SPICY: // Figy Berry case HOLD_EFFECT_CONFUSE_SPICY: // Figy Berry
effect = HealConfuseBerry(itemBattler, item, FLAVOR_SPICY, timing); effect = HealConfuseBerry(itemBattler, item, FLAVOR_SPICY);
break; break;
case HOLD_EFFECT_CONFUSE_DRY: // Wiki Berry case HOLD_EFFECT_CONFUSE_DRY: // Wiki Berry
effect = HealConfuseBerry(itemBattler, item, FLAVOR_DRY, timing); effect = HealConfuseBerry(itemBattler, item, FLAVOR_DRY);
break; break;
case HOLD_EFFECT_CONFUSE_SWEET: // Mago Berry case HOLD_EFFECT_CONFUSE_SWEET: // Mago Berry
effect = HealConfuseBerry(itemBattler, item, FLAVOR_SWEET, timing); effect = HealConfuseBerry(itemBattler, item, FLAVOR_SWEET);
break; break;
case HOLD_EFFECT_CONFUSE_BITTER: // Aguav Berry case HOLD_EFFECT_CONFUSE_BITTER: // Aguav Berry
effect = HealConfuseBerry(itemBattler, item, FLAVOR_BITTER, timing); effect = HealConfuseBerry(itemBattler, item, FLAVOR_BITTER);
break; break;
case HOLD_EFFECT_CONFUSE_SOUR: // Iapapa Berry case HOLD_EFFECT_CONFUSE_SOUR: // Iapapa Berry
effect = HealConfuseBerry(itemBattler, item, FLAVOR_SOUR, timing); effect = HealConfuseBerry(itemBattler, item, FLAVOR_SOUR);
break; break;
case HOLD_EFFECT_ATTACK_UP: // Liechi Berry case HOLD_EFFECT_ATTACK_UP: // Liechi Berry
effect = StatRaiseBerry(itemBattler, item, STAT_ATK, timing); effect = StatRaiseBerry(itemBattler, item, STAT_ATK);
break; break;
case HOLD_EFFECT_DEFENSE_UP: // Ganlon Berry case HOLD_EFFECT_DEFENSE_UP: // Ganlon Berry
effect = StatRaiseBerry(itemBattler, item, STAT_DEF, timing); effect = StatRaiseBerry(itemBattler, item, STAT_DEF);
break; break;
case HOLD_EFFECT_SPEED_UP: // Salac Berry case HOLD_EFFECT_SPEED_UP: // Salac Berry
effect = StatRaiseBerry(itemBattler, item, STAT_SPEED, timing); effect = StatRaiseBerry(itemBattler, item, STAT_SPEED);
break; break;
case HOLD_EFFECT_SP_ATTACK_UP: // Petaya Berry case HOLD_EFFECT_SP_ATTACK_UP: // Petaya Berry
effect = StatRaiseBerry(itemBattler, item, STAT_SPATK, timing); effect = StatRaiseBerry(itemBattler, item, STAT_SPATK);
break; break;
case HOLD_EFFECT_SP_DEFENSE_UP: // Apicot Berry case HOLD_EFFECT_SP_DEFENSE_UP: // Apicot Berry
effect = StatRaiseBerry(itemBattler, item, STAT_SPDEF, timing); effect = StatRaiseBerry(itemBattler, item, STAT_SPDEF);
break; break;
case HOLD_EFFECT_CRITICAL_UP: // Lansat Berry case HOLD_EFFECT_CRITICAL_UP: // Lansat Berry
effect = CriticalHitRatioUp(itemBattler, item, timing); effect = CriticalHitRatioUp(itemBattler, item);
break; break;
case HOLD_EFFECT_RANDOM_STAT_UP: // Starf Berry case HOLD_EFFECT_RANDOM_STAT_UP: // Starf Berry
effect = RandomStatRaiseBerry(itemBattler, item, timing); effect = RandomStatRaiseBerry(itemBattler, item);
break; break;
case HOLD_EFFECT_MICLE_BERRY: case HOLD_EFFECT_MICLE_BERRY:
effect = TrySetMicleBerry(itemBattler, item, timing); effect = TrySetMicleBerry(itemBattler, item);
break; break;
default: default:
break; break;

View File

@ -127,7 +127,6 @@ static void HandleEndTurn_MonFled(void);
static void HandleEndTurn_FinishBattle(void); static void HandleEndTurn_FinishBattle(void);
static u32 Crc32B (const u8 *data, u32 size); static u32 Crc32B (const u8 *data, u32 size);
static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i);
static s32 Factorial(s32);
EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_X = 0;
EWRAM_DATA u16 gBattle_BG0_Y = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0;
@ -157,6 +156,7 @@ EWRAM_DATA u16 gBattlerPartyIndexes[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gBattlerPositions[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gBattlerPositions[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gActionsByTurnOrder[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gActionsByTurnOrder[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gBattlerByTurnOrder[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gBattlerByTurnOrder[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gBattlersBySpeed[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u8 gCurrentTurnActionNumber = 0; EWRAM_DATA u8 gCurrentTurnActionNumber = 0;
EWRAM_DATA u8 gCurrentActionFuncId = 0; EWRAM_DATA u8 gCurrentActionFuncId = 0;
EWRAM_DATA struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT] = {0};
@ -208,12 +208,10 @@ EWRAM_DATA u8 gSentPokesToOpponent[2] = {0};
EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA struct BattleScripting gBattleScripting = {0}; EWRAM_DATA struct BattleScripting gBattleScripting = {0};
EWRAM_DATA struct BattleStruct *gBattleStruct = NULL; EWRAM_DATA struct BattleStruct *gBattleStruct = NULL;
EWRAM_DATA struct AiThinkingStruct *gAiThinkingStruct = NULL; EWRAM_DATA struct AiThinkingStruct *gAiThinkingStruct = NULL;
EWRAM_DATA struct AiLogicData *gAiLogicData = NULL; EWRAM_DATA struct AiLogicData *gAiLogicData = NULL;
EWRAM_DATA struct AiPartyData *gAiPartyData = NULL; EWRAM_DATA struct AiPartyData *gAiPartyData = NULL;
EWRAM_DATA struct BattleHistory *gBattleHistory = NULL; EWRAM_DATA struct BattleHistory *gBattleHistory = NULL;
EWRAM_DATA struct AiBattleData *gAiBattleData = NULL; EWRAM_DATA struct AiBattleData *gAiBattleData = NULL;
EWRAM_DATA u8 *gLinkBattleSendBuffer = NULL; EWRAM_DATA u8 *gLinkBattleSendBuffer = NULL;
@ -3242,7 +3240,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
gBattleStruct->battlerState[battler].canPickupItem = FALSE; gBattleStruct->battlerState[battler].canPickupItem = FALSE;
gBattleStruct->battlerState[battler].wasAboveHalfHp = gBattleMons[battler].hp > gBattleMons[battler].maxHP / 2; gBattleStruct->battlerState[battler].wasAboveHalfHp = gBattleMons[battler].hp > gBattleMons[battler].maxHP / 2;
gBattleStruct->hazardsCounter = 0; gBattleStruct->hazardsCounter = 0;
gDisableStructs[battler].hazardsDone = FALSE;
gSpecialStatuses[battler].switchInItemDone = FALSE; gSpecialStatuses[battler].switchInItemDone = FALSE;
ClearPursuitValuesIfSet(battler); ClearPursuitValuesIfSet(battler);
@ -3265,9 +3262,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
gBattleStruct->choicedMove[battler] = MOVE_NONE; gBattleStruct->choicedMove[battler] = MOVE_NONE;
gBattleStruct->eventState.arenaTurn = 0xFF; gBattleStruct->eventState.arenaTurn = 0xFF;
// Restore struct member so replacement does not miss timing
gSpecialStatuses[battler].switchInAbilityDone = FALSE;
// Reset damage to prevent things like red card activating if the switched-in mon is holding it // Reset damage to prevent things like red card activating if the switched-in mon is holding it
gSpecialStatuses[battler].physicalDmg = 0; gSpecialStatuses[battler].physicalDmg = 0;
gSpecialStatuses[battler].specialDmg = 0; gSpecialStatuses[battler].specialDmg = 0;
@ -3491,7 +3485,7 @@ static void DoBattleIntro(void)
gBattleMons[battler].types[1] = GetSpeciesType(gBattleMons[battler].species, 1); gBattleMons[battler].types[1] = GetSpeciesType(gBattleMons[battler].species, 1);
gBattleMons[battler].types[2] = TYPE_MYSTERY; gBattleMons[battler].types[2] = TYPE_MYSTERY;
gBattleMons[battler].ability = GetAbilityBySpecies(gBattleMons[battler].species, gBattleMons[battler].abilityNum); gBattleMons[battler].ability = GetAbilityBySpecies(gBattleMons[battler].species, gBattleMons[battler].abilityNum);
gBattleStruct->hpOnSwitchout[GetBattlerSide(battler)] = gBattleMons[battler].hp; gBattleStruct->battlerState[battler].hpOnSwitchout = gBattleMons[battler].hp;
memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles)); memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles));
for (i = 0; i < NUM_BATTLE_STATS; i++) for (i = 0; i < NUM_BATTLE_STATS; i++)
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE; gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
@ -3771,7 +3765,7 @@ static void DoBattleIntro(void)
static void TryDoEventsBeforeFirstTurn(void) static void TryDoEventsBeforeFirstTurn(void)
{ {
s32 i, j; s32 i;
if (gBattleControllerExecFlags) if (gBattleControllerExecFlags)
return; return;
@ -3807,25 +3801,6 @@ static void TryDoEventsBeforeFirstTurn(void)
gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1); gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1);
gBattleTurnCounter = 0; gBattleTurnCounter = 0;
struct BattleContext ctx = {0};
for (i = 0; i < gBattlersCount; i++)
{
gBattlerByTurnOrder[i] = i;
ctx.abilities[i] = GetBattlerAbility(i);
ctx.holdEffects[i] = GetBattlerHoldEffect(i);
}
for (i = 0; i < gBattlersCount - 1; i++)
{
for (j = i + 1; j < gBattlersCount; j++)
{
ctx.battlerAtk = gBattlerByTurnOrder[i];
ctx.battlerDef = gBattlerByTurnOrder[j];
if (GetWhichBattlerFaster(&ctx, TRUE) == -1)
SwapTurnOrder(i, j);
}
}
gBattleStruct->eventState.beforeFristTurn++; gBattleStruct->eventState.beforeFristTurn++;
break; break;
case FIRST_TURN_EVENTS_OVERWORLD_WEATHER: case FIRST_TURN_EVENTS_OVERWORLD_WEATHER:
@ -3856,78 +3831,13 @@ static void TryDoEventsBeforeFirstTurn(void)
memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts for Mirror Herb and Opportunist memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts for Mirror Herb and Opportunist
gBattleStruct->eventState.beforeFristTurn++; gBattleStruct->eventState.beforeFristTurn++;
break; break;
case FIRST_TURN_EVENTS_NEUTRALIZING_GAS: case FIRST_TURN_SWITCH_IN_EVENTS:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest gBattleStruct->eventState.switchIn = 0;
{ for (u32 battler = 0; battler < gBattlersCount; battler++)
i = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++]; gBattleStruct->battlerState[battler].switchIn = TRUE;
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, i, 0, 0, 0) != 0) BattleScriptPushCursorAndCallback(BattleScript_FirstTurnSwitchInEvents);
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++; gBattleStruct->eventState.beforeFristTurn++;
break; break;
case FIRST_TURN_EVENTS_SWITCH_IN_ABILITIES:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (TryPrimalReversion(battler))
return;
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0))
return;
if (TryClearIllusion(battler, ABILITYEFFECT_ON_SWITCHIN))
return;
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, battler, 0, 0, 0) != 0)
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_ITEM_EFFECTS:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnSwitchInFirstTurnActivation))
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_WHITE_HERB:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsWhiteHerbFirstTurnActivation))
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_OPPORTUNIST:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST_FIRST_TURN, battler, GetBattlerAbility(battler), 0, 0))
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_MIRROR_HERB:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
u32 battler = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsMirrorHerbFirstTurnActivation))
return;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_EJECT_PACK:
gBattleStruct->eventState.beforeFristTurn++;
if (TrySwitchInEjectPack(FIRST_TURN))
return;
break;
case FIRST_TURN_EVENTS_END: case FIRST_TURN_EVENTS_END:
for (i = 0; i < MAX_BATTLERS_COUNT; i++) for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{ {
@ -5403,7 +5313,7 @@ static void RunTurnActionsFunctions(void)
} }
} }
*(&gBattleStruct->savedTurnActionNumber) = gCurrentTurnActionNumber; gBattleStruct->savedTurnActionNumber = gCurrentTurnActionNumber;
sTurnActionsFuncsTable[gCurrentActionFuncId](); sTurnActionsFuncsTable[gCurrentActionFuncId]();
if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished
@ -6168,7 +6078,7 @@ bool32 IsWildMonSmart(void)
#endif #endif
} }
static s32 Factorial(s32 n) s32 Factorial(s32 n)
{ {
s32 f = 1, i; s32 f = 1, i;
for (i = 2; i <= n; i++) for (i = 2; i <= n; i++)

View File

@ -616,10 +616,10 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was poisoned!"), [STRINGID_TOXICSPIKESPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was poisoned!"),
[STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was badly poisoned!"), [STRINGID_TOXICSPIKESBADLYPOISONED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was badly poisoned!"),
[STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was caught in a sticky web!"), [STRINGID_STICKYWEBSWITCHIN] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} was caught in a sticky web!"),
[STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_ATK_NAME_WITH_PREFIX2}!"), [STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_SCR_NAME_WITH_PREFIX2}!"),
[STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} regained health!"), [STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} regained health!"),
[STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in mystical moonlight!"), [STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} became cloaked in mystical moonlight!"),
[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_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_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_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!"), [STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any higher!"),

View File

@ -6,6 +6,7 @@
#include "battle_ai_main.h" #include "battle_ai_main.h"
#include "battle_ai_util.h" #include "battle_ai_util.h"
#include "battle_scripts.h" #include "battle_scripts.h"
#include "battle_switch_in.h"
#include "battle_environment.h" #include "battle_environment.h"
#include "battle_z_move.h" #include "battle_z_move.h"
#include "item.h" #include "item.h"
@ -411,7 +412,7 @@ static void Cmd_endselectionscript(void);
static void Cmd_playanimation(void); static void Cmd_playanimation(void);
static void Cmd_playanimation_var(void); static void Cmd_playanimation_var(void);
static void Cmd_jumpfifsemiinvulnerable(void); static void Cmd_jumpfifsemiinvulnerable(void);
static void Cmd_unused_0x48(void); static void Cmd_trainerslidein(void);
static void Cmd_moveend(void); static void Cmd_moveend(void);
static void Cmd_sethealblock(void); static void Cmd_sethealblock(void);
static void Cmd_returnatktoball(void); static void Cmd_returnatktoball(void);
@ -422,7 +423,7 @@ static void Cmd_jumpifcantswitch(void);
static void Cmd_openpartyscreen(void); static void Cmd_openpartyscreen(void);
static void Cmd_switchhandleorder(void); static void Cmd_switchhandleorder(void);
static void Cmd_switchineffects(void); static void Cmd_switchineffects(void);
static void Cmd_trainerslidein(void); static void Cmd_switchinevents(void);
static void Cmd_playse(void); static void Cmd_playse(void);
static void Cmd_fanfare(void); static void Cmd_fanfare(void);
static void Cmd_playfaintcry(void); static void Cmd_playfaintcry(void);
@ -583,7 +584,7 @@ static void Cmd_givecaughtmon(void);
static void Cmd_trysetcaughtmondexflags(void); static void Cmd_trysetcaughtmondexflags(void);
static void Cmd_displaydexinfo(void); static void Cmd_displaydexinfo(void);
static void Cmd_trygivecaughtmonnick(void); static void Cmd_trygivecaughtmonnick(void);
static void Cmd_unused_0xf4(void); static void Cmd_sortbattlers(void);
static void Cmd_removeattackerstatus1(void); static void Cmd_removeattackerstatus1(void);
static void Cmd_finishaction(void); static void Cmd_finishaction(void);
static void Cmd_finishturn(void); static void Cmd_finishturn(void);
@ -670,7 +671,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_playanimation, //0x45 Cmd_playanimation, //0x45
Cmd_playanimation_var, //0x46 Cmd_playanimation_var, //0x46
Cmd_jumpfifsemiinvulnerable, //0x47 Cmd_jumpfifsemiinvulnerable, //0x47
Cmd_unused_0x48, //0x48 Cmd_trainerslidein, //0x48
Cmd_moveend, //0x49 Cmd_moveend, //0x49
Cmd_sethealblock, //0x4A Cmd_sethealblock, //0x4A
Cmd_returnatktoball, //0x4B Cmd_returnatktoball, //0x4B
@ -681,7 +682,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_openpartyscreen, //0x50 Cmd_openpartyscreen, //0x50
Cmd_switchhandleorder, //0x51 Cmd_switchhandleorder, //0x51
Cmd_switchineffects, //0x52 Cmd_switchineffects, //0x52
Cmd_trainerslidein, //0x53 Cmd_switchinevents, //0x53
Cmd_playse, //0x54 Cmd_playse, //0x54
Cmd_fanfare, //0x55 Cmd_fanfare, //0x55
Cmd_playfaintcry, //0x56 Cmd_playfaintcry, //0x56
@ -842,7 +843,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_trysetcaughtmondexflags, //0xF1 Cmd_trysetcaughtmondexflags, //0xF1
Cmd_displaydexinfo, //0xF2 Cmd_displaydexinfo, //0xF2
Cmd_trygivecaughtmonnick, //0xF3 Cmd_trygivecaughtmonnick, //0xF3
Cmd_unused_0xf4, //0xF4 Cmd_sortbattlers, //0xF4
Cmd_removeattackerstatus1, //0xF5 Cmd_removeattackerstatus1, //0xF5
Cmd_finishaction, //0xF6 Cmd_finishaction, //0xF6
Cmd_finishturn, //0xF7 Cmd_finishturn, //0xF7
@ -960,7 +961,9 @@ static void ValidateSavedBattlerCounts(void)
if (gBattleStruct->savedAttackerCount > 0) if (gBattleStruct->savedAttackerCount > 0)
{ {
if (TESTING) if (TESTING)
{
Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!", __FILE__, __LINE__); Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!", __FILE__, __LINE__);
}
else else
DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!"); DebugPrintfLevel(MGBA_LOG_WARN, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!");
} }
@ -1089,23 +1092,6 @@ bool32 IsPowderMoveBlocked(struct BattleContext *ctx)
return TRUE; return TRUE;
} }
bool32 EmergencyExitCanBeTriggered(u32 battler)
{
enum Ability ability = GetBattlerAbility(battler);
if (ability != ABILITY_EMERGENCY_EXIT && ability != ABILITY_WIMP_OUT)
return FALSE;
if (IsBattlerAlive(battler)
&& HadMoreThanHalfHpNowDoesnt(battler)
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
return TRUE;
return FALSE;
}
static inline bool32 IsBattlerUsingBeakBlast(u32 battler) static inline bool32 IsBattlerUsingBeakBlast(u32 battler)
{ {
if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE) if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE)
@ -2464,6 +2450,7 @@ static void Cmd_datahpupdate(void)
if (gBattleControllerExecFlags) if (gBattleControllerExecFlags)
return; return;
switch (cmd->updateState) switch (cmd->updateState)
{ {
case PASSIVE_HP_UPDATE: case PASSIVE_HP_UPDATE:
@ -4285,6 +4272,7 @@ static void Cmd_tryfaintmon(void)
&& !IsBattlerAlive(battler)) && !IsBattlerAlive(battler))
{ {
gHitMarker |= HITMARKER_FAINTED(battler); gHitMarker |= HITMARKER_FAINTED(battler);
gBattleStruct->eventState.faintedAction = 0;
BattleScriptPush(cmd->nextInstr); BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = faintScript; gBattlescriptCurrInstr = faintScript;
if (IsOnPlayerSide(battler)) if (IsOnPlayerSide(battler))
@ -5001,8 +4989,10 @@ static void Cmd_checkteamslost(void)
u32 occupiedOpponentSpots = (gBattlersCount / 2) - emptyOpponentSpots; u32 occupiedOpponentSpots = (gBattlersCount / 2) - emptyOpponentSpots;
u32 alivePlayerPartyMons = CountAliveMonsForBattlerSide(B_POSITION_PLAYER_LEFT) - occupiedPlayerSpots; u32 alivePlayerPartyMons = CountAliveMonsForBattlerSide(B_POSITION_PLAYER_LEFT) - occupiedPlayerSpots;
u32 aliveOpponentPartyMons = CountAliveMonsForBattlerSide(B_POSITION_OPPONENT_LEFT) - occupiedOpponentSpots; u32 aliveOpponentPartyMons = CountAliveMonsForBattlerSide(B_POSITION_OPPONENT_LEFT) - occupiedOpponentSpots;
u32 emptySlotsTotal = emptyPlayerSpots + emptyOpponentSpots;
u32 alivePartyMonsTotal = alivePlayerPartyMons + aliveOpponentPartyMons;
if (emptyPlayerSpots > 0 && alivePlayerPartyMons > 0 && emptyOpponentSpots > 0 && aliveOpponentPartyMons > 0) if (emptySlotsTotal >= 2 && alivePartyMonsTotal >= 2)
gBattlescriptCurrInstr = cmd->jumpInstr; gBattlescriptCurrInstr = cmd->jumpInstr;
else else
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
@ -5547,8 +5537,15 @@ static void Cmd_jumpfifsemiinvulnerable(void)
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
static void Cmd_unused_0x48(void) static void Cmd_trainerslidein(void)
{ {
CMD_ARGS(u8 position);
u32 battler = GetBattlerForBattleScript(cmd->position);
BtlController_EmitTrainerSlide(battler, B_COMM_TO_CONTROLLER);
MarkBattlerForControllerExec(battler);
gBattlescriptCurrInstr = cmd->nextInstr;
} }
static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally) static inline bool32 TryTriggerSymbiosis(u32 battler, u32 ally)
@ -6235,33 +6232,34 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_SYNCHRONIZE_TARGET: // target synchronize case MOVEEND_SYNCHRONIZE_TARGET: // target synchronize
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, TRUE))
effect = TRUE; effect = TRUE;
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_ABILITIES: // Such as abilities activating on contact(Poison Spore, Rough Skin, etc.). case MOVEEND_ABILITIES: // Such as abilities activating on contact(Poison Spore, Rough Skin, etc.).
if (AbilityBattleEffects(ABILITYEFFECT_MOVE_END, gBattlerTarget, 0, 0, 0)) i = GetBattlerAbility(gBattlerTarget);
if (AbilityBattleEffects(ABILITYEFFECT_MOVE_END, gBattlerTarget, i, 0, TRUE))
effect = TRUE; effect = TRUE;
else if (TryClearIllusion(gBattlerTarget, ABILITYEFFECT_MOVE_END)) else if (TryClearIllusion(gBattlerTarget, i))
effect = TRUE; effect = TRUE;
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_ABILITIES_ATTACKER: // Poison Touch, possibly other in the future case MOVEEND_ABILITIES_ATTACKER: // Poison Touch, possibly other in the future
if (AbilityBattleEffects(ABILITYEFFECT_MOVE_END_ATTACKER, gBattlerAttacker, 0, 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_MOVE_END_ATTACKER, gBattlerAttacker, 0, 0, TRUE))
effect = TRUE; effect = TRUE;
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities
for (u16 battler = 0; battler < gBattlersCount; battler++) for (u16 battler = 0; battler < gBattlersCount; battler++)
{ {
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, TRUE))
effect = TRUE; effect = TRUE;
} }
if (!effect) if (!effect)
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize
if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBattlerAttacker, 0, 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBattlerAttacker, 0, 0, TRUE))
effect = TRUE; effect = TRUE;
gBattleScripting.moveendState++; gBattleScripting.moveendState++;
break; break;
@ -6661,7 +6659,7 @@ static void Cmd_moveend(void)
u32 battler = gBattleStruct->eventState.moveEndBattler++; u32 battler = gBattleStruct->eventState.moveEndBattler++;
if (battler == gBattlerAttacker) if (battler == gBattlerAttacker)
continue; continue;
if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, TRUE))
return; return;
} }
gBattleStruct->eventState.moveEndBattler = 0; gBattleStruct->eventState.moveEndBattler = 0;
@ -6831,12 +6829,7 @@ static void Cmd_moveend(void)
effect = TRUE; effect = TRUE;
gBattleScripting.battler = battler; gBattleScripting.battler = battler;
BattleScriptCall(BattleScript_EmergencyExit);
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
BattleScriptCall(BattleScript_EmergencyExit);
else
BattleScriptCall(BattleScript_EmergencyExitWild);
break; // Only the fastest Emergency Exit / Wimp Out activates break; // Only the fastest Emergency Exit / Wimp Out activates
} }
} }
@ -6935,7 +6928,7 @@ static void Cmd_moveend(void)
u32 battler = gBattleStruct->eventState.moveEndBattler++; u32 battler = gBattleStruct->eventState.moveEndBattler++;
if (!IsBattlerAlive(battler)) if (!IsBattlerAlive(battler))
continue; continue;
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, 0)) if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, TRUE))
return; return;
} }
gBattleStruct->eventState.moveEndBattler = 0; gBattleStruct->eventState.moveEndBattler = 0;
@ -7151,7 +7144,7 @@ static void Cmd_moveend(void)
nextDancer = battler | 0x4; nextDancer = battler | 0x4;
} }
} }
if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, 0, gCurrentMove)) if (nextDancer && AbilityBattleEffects(ABILITYEFFECT_MOVE_END_OTHER, nextDancer & 0x3, 0, gCurrentMove, TRUE))
effect = TRUE; effect = TRUE;
} }
} }
@ -7814,264 +7807,39 @@ static void Cmd_switchhandleorder(void)
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
bool32 DoSwitchInAbilities(u32 battler)
{
return (TryPrimalReversion(battler)
|| AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0)
|| (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect() && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0))
|| (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0)));
}
static void UpdateSentMonFlags(u32 battler) static void UpdateSentMonFlags(u32 battler)
{ {
UpdateSentPokesToOpponentValue(battler); UpdateSentPokesToOpponentValue(battler);
gHitMarker &= ~HITMARKER_FAINTED(battler); gHitMarker &= ~HITMARKER_FAINTED(battler);
gSpecialStatuses[battler].faintedHasReplacement = FALSE; gSpecialStatuses[battler].faintedHasReplacement = FALSE;
} gBattleStruct->battlerState[battler].switchIn = TRUE;
gProtectStructs[battler].forcedSwitch = FALSE;
static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) // There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts.
{ // The truant counter is not updated in the case where a mon switches in after a lost judgment in the battle arena.
gBattleScripting.battler = battler; if (GetBattlerAbility(battler) == ABILITY_TRUANT
gBattleCommunication[MULTISTRING_CHOOSER] = multistringId; && gCurrentActionFuncId != B_ACTION_USE_MOVE
&& !gDisableStructs[battler].truantSwitchInHack)
gDisableStructs[battler].truantCounter = 1;
gDisableStructs[battler].truantSwitchInHack = 0;
if (gBattlescriptCurrInstr[1] == BS_TARGET) for (u32 i = 0; i < gBattlersCount; i++)
BattleScriptCall(BattleScript_DmgHazardsOnTarget);
else if (gBattlescriptCurrInstr[1] == BS_ATTACKER)
BattleScriptCall(BattleScript_DmgHazardsOnAttacker);
else if (gBattlescriptCurrInstr[1] == BS_SCRIPTING)
BattleScriptCall(BattleScript_DmgHazardsOnBattlerScripting);
else
BattleScriptCall(BattleScript_DmgHazardsOnFaintedBattler);
}
void TryHazardsOnSwitchIn(u32 battler, u32 side, enum Hazards hazardType)
{
switch (hazardType)
{ {
case HAZARDS_NONE: if (gBattlerByTurnOrder[i] == battler)
break; gActionsByTurnOrder[i] = B_ACTION_CANCEL_PARTNER;
case HAZARDS_SPIKES:
{
enum Ability ability = GetBattlerAbility(battler);
if (ability != ABILITY_MAGIC_GUARD
&& IsBattlerAffectedByHazards(battler, FALSE)
&& IsBattlerGrounded(battler, ability, GetBattlerHoldEffect(battler)))
{
s32 spikesDmg = GetNonDynamaxMaxHP(battler) / ((5 - gSideTimers[side].spikesAmount) * 2);
SetPassiveDamageAmount(battler, spikesDmg);
SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES);
}
break;
} }
case HAZARDS_STICKY_WEB:
if (IsBattlerAffectedByHazards(battler, FALSE) && IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)))
{
gBattleScripting.battler = battler;
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
BattleScriptCall(BattleScript_StickyWebOnSwitchIn);
}
break;
case HAZARDS_TOXIC_SPIKES:
if (!IsBattlerGrounded(battler, GetBattlerAbility(battler), GetBattlerHoldEffect(battler)))
break;
if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes.
{
gBattleStruct->hazardsCounter--; // reduce counter so the next hazard can be applied
gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount = 0;
RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES);
gEffectBattler = battler;
BattleScriptCall(BattleScript_ToxicSpikesAbsorbed);
}
else if (IsBattlerAffectedByHazards(battler, TRUE)
&& CanBePoisoned(battler, battler, GetBattlerAbility(battler), GetBattlerAbility(battler)))
{
gBattleScripting.battler = battler;
BattleScriptPushCursor();
if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2)
{
gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned;
gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON;
}
else
{
gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
gBattleMons[battler].status1 |= STATUS1_POISON;
}
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
}
break;
case HAZARDS_STEALTH_ROCK:
if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD)
{
gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler);
if (gBattleStruct->passiveHpUpdate[battler] != 0)
SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG);
}
break;
case HAZARDS_STEELSURGE:
if (IsBattlerAffectedByHazards(battler, FALSE) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD)
{
gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler);
if (gBattleStruct->passiveHpUpdate[battler] != 0)
SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG);
}
break;
case HAZARDS_MAX_COUNT:
break;
}
}
static bool32 DoSwitchInEffectsForBattler(u32 battler)
{
u32 i = 0;
u32 side = GetBattlerSide(battler);
// Neutralizing Gas announces itself before hazards
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0))
{
return TRUE;
}
// Healing Wish activates before hazards.
// Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways.
else if ((gBattleStruct->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance)
&& (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || GetGenConfig(GEN_CONFIG_HEALING_WISH_SWITCH) < GEN_8))
{
gBattlerAttacker = battler;
if (gBattleStruct->battlerState[battler].storedHealingWish)
{
BattleScriptCall(BattleScript_HealingWishActivates);
gBattleStruct->battlerState[battler].storedHealingWish = FALSE;
}
else // Lunar Dance
{
BattleScriptCall(BattleScript_LunarDanceActivates);
gBattleStruct->battlerState[battler].storedLunarDance = FALSE;
}
}
else if (EmergencyExitCanBeTriggered(battler))
{
gBattleScripting.battler = gBattlerAbility = battler;
gSpecialStatuses[battler].switchInItemDone = FALSE;
gBattleStruct->battlerState[battler].forcedSwitch = FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
BattleScriptCall(BattleScript_EmergencyExit);
else
BattleScriptCall(BattleScript_EmergencyExitWild);
}
else if (!gDisableStructs[battler].hazardsDone)
{
TryHazardsOnSwitchIn(battler, side, gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter]);
gBattleStruct->hazardsCounter++;
// Done once we reach the first element without any hazard type or the array is full
if (gBattleStruct->hazardsQueue[side][gBattleStruct->hazardsCounter] == HAZARDS_NONE
|| gBattleStruct->hazardsCounter == HAZARDS_MAX_COUNT)
{
gDisableStructs[battler].hazardsDone = TRUE;
gBattleStruct->hazardsCounter = 0;
}
}
else if (gBattleMons[battler].hp != gBattleMons[battler].maxHP && gBattleStruct->zmove.healReplacement)
{
gBattleStruct->zmove.healReplacement = FALSE;
SetHealAmount(battler, gBattleMons[battler].maxHP);
gBattleScripting.battler = battler;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
BattleScriptCall(BattleScript_HealReplacementZMove);
}
else
{
enum Ability battlerAbility = GetBattlerAbility(battler);
// There is a hack here to ensure the truant counter will be 0 when the battler's next turn starts.
// The truant counter is not updated in the case where a mon switches in after a lost judgment in the battle arena.
if (battlerAbility == ABILITY_TRUANT
&& gCurrentActionFuncId != B_ACTION_USE_MOVE
&& !gDisableStructs[battler].truantSwitchInHack)
gDisableStructs[battler].truantCounter = 1;
gDisableStructs[battler].truantSwitchInHack = 0;
if (DoSwitchInAbilities(battler))
return TRUE;
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsOnSwitchInActivation))
return TRUE;
for (i = 0; i < gBattlersCount; i++)
{
if (i == battler)
continue;
enum Ability ability = GetBattlerAbility(i);
switch (ability)
{
case ABILITY_TRACE:
case ABILITY_COMMANDER:
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, i, ability, 0, 0))
return TRUE;
break;
case ABILITY_FORECAST:
case ABILITY_FLOWER_GIFT:
case ABILITY_PROTOSYNTHESIS:
if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, i, ability, 0, 0))
return TRUE;
break;
default:
break;
}
if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN))
return TRUE;
}
for (i = 0; i < gBattlersCount; i++)
{
if (ItemBattleEffects(i, 0, GetBattlerHoldEffect(i), IsWhiteHerbActivation))
return TRUE;
}
for (i = 0; i < gBattlersCount; i++)
{
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, i, GetBattlerAbility(i), 0, 0))
return TRUE;
}
for (i = 0; i < gBattlersCount; i++)
{
if (ItemBattleEffects(i, 0, GetBattlerHoldEffect(i), IsMirrorHerbActivation))
return TRUE;
}
for (i = 0; i < gBattlersCount; i++)
{
if (gBattlerByTurnOrder[i] == battler)
gActionsByTurnOrder[i] = B_ACTION_CANCEL_PARTNER;
gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp;
}
gSpecialStatuses[battler].switchInItemDone = FALSE;
gBattleStruct->battlerState[battler].forcedSwitch = FALSE;
gBattleStruct->battlerState[battler].wasAboveHalfHp = FALSE;
return FALSE;
}
return TRUE; // Effect's script plays.
} }
static void Cmd_switchineffects(void) static void Cmd_switchineffects(void)
{ {
CMD_ARGS(u8 battler); CMD_ARGS(u8 battler);
u32 i, battler = GetBattlerForBattleScript(cmd->battler); u32 battler = GetBattlerForBattleScript(cmd->battler);
switch (cmd->battler) UpdateSentMonFlags(battler);
if (cmd->battler == BS_FAINTED_MULTIPLE_1)
{ {
// Multiple mons fainted and are being switched-in. Their abilities/hazards will play according to speed ties. do // Increment fainted battler
case BS_FAINTED_MULTIPLE_1: // Saves the battlers.
gBattleStruct->battlerState[battler].multipleSwitchInBattlers = TRUE;
UpdateSentMonFlags(battler);
// Increment fainted battler.
do
{ {
gBattlerFainted++; gBattlerFainted++;
if (gBattlerFainted >= gBattlersCount) if (gBattlerFainted >= gBattlersCount)
@ -8079,55 +7847,20 @@ static void Cmd_switchineffects(void)
if (gHitMarker & HITMARKER_FAINTED(gBattlerFainted) && !(gAbsentBattlerFlags & (1u << gBattlerFainted))) if (gHitMarker & HITMARKER_FAINTED(gBattlerFainted) && !(gAbsentBattlerFlags & (1u << gBattlerFainted)))
break; break;
} while (1); } while (1);
gBattlescriptCurrInstr = cmd->nextInstr;
return;
case BS_FAINTED_MULTIPLE_2: // Plays hazards/abilities.
switch (gBattleStruct->multipleSwitchInState)
{
case 0: // Sort battlers by speed
for (i = 0; i < gBattlersCount; i++)
gBattleStruct->multipleSwitchInSortedBattlers[i] = i;
SortBattlersBySpeed(gBattleStruct->multipleSwitchInSortedBattlers, FALSE);
gBattleStruct->multipleSwitchInState++;
gBattleStruct->multipleSwitchInCursor = 0;
// Loop through all available battlers
case 1:
for (; gBattleStruct->multipleSwitchInCursor < gBattlersCount; gBattleStruct->multipleSwitchInCursor++)
{
gBattlerFainted = gBattleStruct->multipleSwitchInSortedBattlers[gBattleStruct->multipleSwitchInCursor];
if (gBattleStruct->battlerState[gBattlerFainted].multipleSwitchInBattlers)
{
if (DoSwitchInEffectsForBattler(gBattlerFainted))
return;
}
}
if (TrySwitchInEjectPack(OTHER))
return;
// All battlers done, end
for (i = 0; i < gBattlersCount; i++)
gBattleStruct->battlerState[i].multipleSwitchInBattlers = FALSE;
gBattleStruct->multipleSwitchInState = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
}
break;
default:
UpdateSentMonFlags(battler);
if (!DoSwitchInEffectsForBattler(battler) && !TrySwitchInEjectPack(OTHER))
gBattlescriptCurrInstr = cmd->nextInstr;
break;
} }
gBattleStruct->eventState.switchIn = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
} }
static void Cmd_trainerslidein(void) static void Cmd_switchinevents(void)
{ {
CMD_ARGS(u8 position); CMD_ARGS();
while (gBattleStruct->eventState.switchIn < SWITCH_IN_EVENTS_COUNT)
u32 battler = GetBattlerForBattleScript(cmd->position); {
BtlController_EmitTrainerSlide(battler, B_COMM_TO_CONTROLLER); if (DoSwitchInEvents())
MarkBattlerForControllerExec(battler); return;
}
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
@ -9235,7 +8968,7 @@ static void Cmd_hpthresholds2(void)
{ {
u32 battler = GetBattlerForBattleScript(cmd->battler); u32 battler = GetBattlerForBattleScript(cmd->battler);
u32 opposingBattler = BATTLE_OPPOSITE(battler); u32 opposingBattler = BATTLE_OPPOSITE(battler);
u8 hpSwitchout = gBattleStruct->hpOnSwitchout[GetBattlerSide(opposingBattler)]; u32 hpSwitchout = gBattleStruct->battlerState[opposingBattler].hpOnSwitchout;
s32 result = (hpSwitchout - gBattleMons[opposingBattler].hp) * 100 / hpSwitchout; s32 result = (hpSwitchout - gBattleMons[opposingBattler].hp) * 100 / hpSwitchout;
if (gBattleMons[opposingBattler].hp >= hpSwitchout) if (gBattleMons[opposingBattler].hp >= hpSwitchout)
@ -9884,9 +9617,6 @@ static void Cmd_manipulatedamage(void)
case DMG_1_8_TARGET_HP: case DMG_1_8_TARGET_HP:
SetPassiveDamageAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 8); SetPassiveDamageAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 8);
break; break;
case DMG_FULL_ATTACKER_HP:
gBattleStruct->passiveHpUpdate[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker);
break;
case DMG_BIG_ROOT: case DMG_BIG_ROOT:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = -1 * GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->passiveHpUpdate[gBattlerAttacker]); gBattleStruct->passiveHpUpdate[gBattlerAttacker] = -1 * GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->passiveHpUpdate[gBattlerAttacker]);
break; break;
@ -10746,9 +10476,8 @@ static void Cmd_forcerandomswitch(void)
{ {
gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget]; gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget];
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE; gProtectStructs[gBattlerTarget].forcedSwitch = TRUE;
gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)]; gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
if (!IsMultiBattle()) if (!IsMultiBattle())
SwitchPartyOrder(gBattlerTarget); SwitchPartyOrder(gBattlerTarget);
@ -14233,8 +13962,17 @@ static void Cmd_trygivecaughtmonnick(void)
} }
} }
static void Cmd_unused_0xf4(void) static void Cmd_sortbattlers(void)
{ {
CMD_ARGS();
if (!gBattleStruct->battlersSorted)
{
for (u32 i = 0; i < gBattlersCount; i++)
gBattlersBySpeed[i] = i;
SortBattlersBySpeed(gBattlersBySpeed, FALSE);
}
gBattlescriptCurrInstr = cmd->nextInstr;
} }
static void Cmd_removeattackerstatus1(void) static void Cmd_removeattackerstatus1(void)
@ -15826,7 +15564,7 @@ void BS_ActivateWeatherChangeAbilities(void)
u32 battler = GetBattlerForBattleScript(cmd->battler); u32 battler = GetBattlerForBattleScript(cmd->battler);
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, GetBattlerAbility(battler), MOVE_NONE, TRUE);
} }
void BS_ActivateTerrainChangeAbilities(void) void BS_ActivateTerrainChangeAbilities(void)
@ -15835,7 +15573,7 @@ void BS_ActivateTerrainChangeAbilities(void)
u32 battler = GetBattlerForBattleScript(cmd->battler); u32 battler = GetBattlerForBattleScript(cmd->battler);
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, GetBattlerAbility(battler), MOVE_NONE, TRUE);
} }
void BS_ResetTerrainAbilityFlags(void) void BS_ResetTerrainAbilityFlags(void)
@ -16673,7 +16411,8 @@ void BS_SetTracedAbility(void)
void BS_TryIllusionOff(void) void BS_TryIllusionOff(void)
{ {
NATIVE_ARGS(u8 battler); NATIVE_ARGS(u8 battler);
if (TryClearIllusion(GetBattlerForBattleScript(cmd->battler), ABILITYEFFECT_MOVE_END)) u32 battler = GetBattlerForBattleScript(cmd->battler);
if (TryClearIllusion(battler, GetBattlerAbility(battler)))
return; return;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
@ -16775,10 +16514,10 @@ void BS_GetBattlerFainted(void)
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
// TODO: What is this fixing???
void BS_ResetSwitchInAbilityBits(void) void BS_ResetSwitchInAbilityBits(void)
{ {
NATIVE_ARGS(); NATIVE_ARGS();
gSpecialStatuses[gBattlerAttacker].switchInAbilityDone = FALSE;
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
@ -17038,17 +16777,17 @@ void BS_SwitchinAbilities(void)
{ {
NATIVE_ARGS(u8 battler); NATIVE_ARGS(u8 battler);
u32 battler = GetBattlerForBattleScript(cmd->battler); u32 battler = GetBattlerForBattleScript(cmd->battler);
u32 ability = GetBattlerAbility(battler);
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_TERA_SHIFT, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_UNNERVE, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, ability, MOVE_NONE, TRUE);
if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect()) AbilityBattleEffects(ABILITYEFFECT_COMMANDER, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0); AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, ability, MOVE_NONE, TRUE);
if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0);
} }
void BS_InstantHpDrop(void) void BS_InstantHpDrop(void)
@ -17061,16 +16800,17 @@ void BS_InstantHpDrop(void)
void BS_ClearStatus(void) void BS_ClearStatus(void)
{ {
NATIVE_ARGS(); NATIVE_ARGS(u8 battler);
gBattleMons[gBattlerAttacker].status1 = 0; u32 battler = GetBattlerForBattleScript(cmd->battler);
gBattleMons[battler].status1 = 0;
BtlController_EmitSetMonData( BtlController_EmitSetMonData(
gBattlerAttacker, battler,
B_COMM_TO_CONTROLLER, B_COMM_TO_CONTROLLER,
REQUEST_STATUS_BATTLE, REQUEST_STATUS_BATTLE,
0, 0,
sizeof(gBattleMons[gBattlerAttacker].status1), sizeof(gBattleMons[battler].status1),
&gBattleMons[gBattlerAttacker].status1); &gBattleMons[battler].status1);
MarkBattlerForControllerExec(gBattlerAttacker); MarkBattlerForControllerExec(battler);
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }

406
src/battle_switch_in.c Normal file
View File

@ -0,0 +1,406 @@
#include "global.h"
#include "battle.h"
#include "battle_hold_effects.h"
#include "battle_util.h"
#include "battle_scripts.h"
#include "battle_switch_in.h"
#include "battle_controllers.h"
#include "generational_changes.h"
#include "constants/battle.h"
#include "constants/moves.h"
static bool32 FirstEventBlockEvents(struct BattleContext *ctx);
static bool32 TryHazardsOnSwitchIn(u32 battler, enum Ability ability, enum HoldEffect holdEffect, enum Hazards hazardType);
static bool32 SecondEventBlockEvents(struct BattleContext *ctx);
bool32 DoSwitchInEvents(void)
{
u32 battler;
struct BattleContext ctx = {0};
for (battler = 0; battler < gBattlersCount; battler++)
{
if (!IsBattlerAlive(battler))
continue;
ctx.abilities[battler] = GetBattlerAbility(battler);
ctx.holdEffects[battler] = GetBattlerHoldEffect(battler);
}
switch (gBattleStruct->eventState.switchIn)
{
case SWITCH_IN_EVENTS_ORDER_BY_SPEED:
for (u32 i = 0; i < gBattlersCount; i++)
gBattlersBySpeed[i] = i;
SortBattlersBySpeed(gBattlersBySpeed, FALSE);
gBattleStruct->battlersSorted = TRUE;
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.battlerSwitchIn = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_TERA_SHIFT:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_TERA_SHIFT, battler, ctx.abilities[battler], 0, gBattleStruct->battlerState[battler].switchIn))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_NEUTRALIZING_GAS:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, ctx.abilities[battler], 0, gBattleStruct->battlerState[battler].switchIn))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_UNNERVE:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_UNNERVE, battler, ctx.abilities[battler], 0, gBattleStruct->battlerState[battler].switchIn))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_FIRST_BLOCK:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter];
if (!IsBattlerAlive(battler) && gBattleStruct->eventState.battlerSwitchIn != FIRST_EVENT_BLOCK_HAZARDS)
{
gBattleStruct->switchInBattlerCounter++;
gBattleStruct->eventState.battlerSwitchIn = 0;
continue;
}
ctx.battlerAtk = battler;
while (gBattleStruct->eventState.battlerSwitchIn < FIRST_EVENT_BLOCK_COUNT)
{
if (FirstEventBlockEvents(&ctx))
return TRUE;
}
gBattleStruct->switchInBattlerCounter++;
gBattleStruct->eventState.battlerSwitchIn = 0;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_SECOND_BLOCK:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter];
if (!IsBattlerAlive(battler))
{
gBattleStruct->switchInBattlerCounter++;
gBattleStruct->eventState.battlerSwitchIn = 0;
continue;
}
ctx.battlerAtk = battler;
while (gBattleStruct->eventState.battlerSwitchIn < SECOND_EVENT_BLOCK_COUNT)
{
if (SecondEventBlockEvents(&ctx))
return TRUE;
}
gBattleStruct->switchInBattlerCounter++;
gBattleStruct->eventState.battlerSwitchIn = 0;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_WHITE_HERB:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
u32 battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (ItemBattleEffects(battler, 0, ctx.holdEffects[battler], IsWhiteHerbActivation))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_OPPORTUNIST:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
u32 battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, ctx.abilities[battler], 0, TRUE))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_MIRROR_HERB:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount)
{
u32 battler = gBattlersBySpeed[gBattleStruct->switchInBattlerCounter++];
if (ItemBattleEffects(battler, 0, GetBattlerHoldEffect(battler), IsMirrorHerbActivation))
return TRUE;
}
gBattleStruct->switchInBattlerCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_CLEAR_SET_VALUES:
for (battler = 0; battler < gBattlersCount; battler++)
{
if (gBattleStruct->battlerState[battler].switchIn)
{
gBattleStruct->battlerState[battler].hpOnSwitchout = gBattleMons[battler].hp;
gBattleStruct->battlerState[battler].switchIn = FALSE;
}
}
gBattleStruct->battlersSorted = FALSE;
gBattleStruct->hazardsCounter = 0;
gBattleStruct->eventState.switchIn++;
break;
case SWITCH_IN_EVENTS_EJECT_PACK:
gBattleStruct->eventState.switchIn++;
if (TrySwitchInEjectPack(START_OF_TURN))
return TRUE;
break;
case SWITCH_IN_EVENTS_COUNT:
break;
}
return FALSE;
}
static bool32 CanBattlerBeHealed(u32 battler)
{
if (GetGenConfig(GEN_CONFIG_HEALING_WISH_SWITCH) < GEN_8)
return TRUE;
if (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1)
return TRUE;
return FALSE;
}
static bool32 FirstEventBlockEvents(struct BattleContext *ctx)
{
bool32 effect = FALSE;
u32 battler = ctx->battlerAtk;
switch (gBattleStruct->eventState.battlerSwitchIn)
{
case FIRST_EVENT_BLOCK_HEALING_WISH:
if (!gBattleStruct->battlerState[battler].switchIn || !CanBattlerBeHealed(battler))
{
effect = FALSE;
}
else if (gBattleStruct->battlerState[battler].storedHealingWish)
{
gBattleStruct->battlerState[battler].storedHealingWish = FALSE;
SetHealAmount(battler, GetNonDynamaxMaxHP(battler));
gBattleScripting.battler = battler;
BattleScriptCall(BattleScript_HealingWishActivates);
effect = TRUE;
}
else if (gBattleStruct->battlerState[battler].storedLunarDance)
{
gBattleStruct->battlerState[battler].storedLunarDance = FALSE;
SetHealAmount(battler, GetNonDynamaxMaxHP(battler));
gBattleScripting.battler = battler;
BattleScriptCall(BattleScript_LunarDanceActivates);
effect = TRUE;
}
else if (gBattleStruct->zmove.healReplacement & 1u << battler)
{
gBattleStruct->zmove.healReplacement &= ~(1u << battler);
SetHealAmount(battler, GetNonDynamaxMaxHP(battler));
gBattleScripting.battler = battler;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
BattleScriptCall(BattleScript_HealReplacementZMove);
effect = TRUE;
}
gBattleStruct->eventState.battlerSwitchIn++;
break;
case FIRST_EVENT_BLOCK_HAZARDS:
if (!gBattleStruct->battlerState[battler].switchIn)
{
gBattleStruct->eventState.battlerSwitchIn++;
}
else if (EmergencyExitCanBeTriggered(battler))
{
gBattleScripting.battler = gBattlerAbility = battler;
gSpecialStatuses[battler].switchInItemDone = FALSE;
gBattleStruct->battlerState[battler].forcedSwitch = FALSE;
gBattleStruct->eventState.switchIn = 0;
BattleScriptCall(BattleScript_EmergencyExit);
effect = TRUE;
}
else
{
enum Hazards hazard = gBattleStruct->hazardsQueue[GetBattlerSide(battler)][gBattleStruct->hazardsCounter];
if (hazard == HAZARDS_NONE || gBattleStruct->hazardsCounter >= HAZARDS_MAX_COUNT)
{
gBattleStruct->hazardsCounter = 0;
gBattleStruct->eventState.battlerSwitchIn++;
}
else
{
effect = TryHazardsOnSwitchIn(battler, ctx->abilities[battler], ctx->holdEffects[battler], hazard);
}
}
break;
case FIRST_EVENT_BLOCK_GENERAL_ABILITIES:
if (TryPrimalReversion(battler)
|| AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, ctx->abilities[battler], MOVE_NONE, gBattleStruct->battlerState[battler].switchIn)
|| TryClearIllusion(battler, ctx->abilities[battler]))
effect = TRUE;
gBattleStruct->eventState.battlerSwitchIn++;
break;
case FIRST_EVENT_BLOCK_IMMUNITY_ABILITIES:
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, ctx->abilities[battler], MOVE_NONE, TRUE))
effect = TRUE;
gBattleStruct->eventState.battlerSwitchIn++;
break;
case FIRST_EVENT_BLOCK_ITEMS:
if (ItemBattleEffects(battler, 0, ctx->holdEffects[battler], IsOnSwitchInActivation))
effect = TRUE;
gBattleStruct->eventState.battlerSwitchIn++;
break;
case FIRST_EVENT_BLOCK_COUNT:
gBattleStruct->eventState.battlerSwitchIn++;
break;
}
return effect;
}
static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId)
{
gBattleScripting.battler = battler;
gBattleCommunication[MULTISTRING_CHOOSER] = multistringId;
BattleScriptCall(BattleScript_DmgHazardsOnBattler);
}
static bool32 TryHazardsOnSwitchIn(u32 battler, enum Ability ability, enum HoldEffect holdEffect, enum Hazards hazardType)
{
bool32 effect = FALSE;
u32 side = GetBattlerSide(battler);
bool32 clearedToxicSpikes = FALSE;
switch (hazardType)
{
case HAZARDS_NONE:
break;
case HAZARDS_SPIKES:
if (!IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)
&& IsBattlerAffectedByHazards(battler, holdEffect, FALSE)
&& IsBattlerGrounded(battler, ability, holdEffect))
{
s32 spikesDmg = GetNonDynamaxMaxHP(battler) / ((5 - gSideTimers[side].spikesAmount) * 2);
SetPassiveDamageAmount(battler, spikesDmg);
SetDmgHazardsBattlescript(battler, B_MSG_PKMNHURTBYSPIKES);
effect = TRUE;
}
break;
case HAZARDS_STICKY_WEB:
if (IsBattlerAffectedByHazards(battler, holdEffect, FALSE) && IsBattlerGrounded(battler, ability, holdEffect))
{
gBattleScripting.battler = battler;
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
BattleScriptCall(BattleScript_StickyWebOnSwitchIn);
effect = TRUE;
}
break;
case HAZARDS_TOXIC_SPIKES:
if (!IsBattlerGrounded(battler, ability, holdEffect))
{
effect = FALSE;
}
else if (IS_BATTLER_OF_TYPE(battler, TYPE_POISON)) // Absorb the toxic spikes.
{
gSideTimers[side].toxicSpikesAmount = 0;
RemoveHazardFromField(side, HAZARDS_TOXIC_SPIKES);
gEffectBattler = battler;
BattleScriptCall(BattleScript_ToxicSpikesAbsorbed);
clearedToxicSpikes = TRUE;
effect = TRUE;
}
else if (IsBattlerAffectedByHazards(battler, holdEffect, TRUE)
&& CanBePoisoned(battler, battler, ability, ability))
{
gBattleScripting.battler = battler;
BattleScriptPushCursor();
if (gSideTimers[GetBattlerSide(battler)].toxicSpikesAmount >= 2)
{
gBattlescriptCurrInstr = BattleScript_ToxicSpikesBadlyPoisoned;
gBattleMons[battler].status1 |= STATUS1_TOXIC_POISON;
}
else
{
gBattlescriptCurrInstr = BattleScript_ToxicSpikesPoisoned;
gBattleMons[battler].status1 |= STATUS1_POISON;
}
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
effect = TRUE;
}
break;
case HAZARDS_STEALTH_ROCK:
if (IsBattlerAffectedByHazards(battler, holdEffect, FALSE) && ability != ABILITY_MAGIC_GUARD)
{
gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler);
if (gBattleStruct->passiveHpUpdate[battler] != 0)
{
SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG);
effect = TRUE;
}
}
break;
case HAZARDS_STEELSURGE:
if (IsBattlerAffectedByHazards(battler, holdEffect, FALSE) && ability != ABILITY_MAGIC_GUARD)
{
gBattleStruct->passiveHpUpdate[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler);
if (gBattleStruct->passiveHpUpdate[battler] != 0)
{
SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG);
effect = TRUE;
}
}
break;
case HAZARDS_MAX_COUNT:
break;
}
if (!clearedToxicSpikes)
gBattleStruct->hazardsCounter++;
return effect;
}
static bool32 SecondEventBlockEvents(struct BattleContext *ctx)
{
bool32 effect = FALSE;
u32 battler = ctx->battlerAtk;
switch (gBattleStruct->eventState.battlerSwitchIn)
{
case SECOND_EVENT_ABILITIES:
if (AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, ctx->abilities[battler], MOVE_NONE, TRUE)
|| AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, ctx->abilities[battler], MOVE_NONE, TRUE)
|| AbilityBattleEffects(ABILITYEFFECT_COMMANDER, battler, ctx->abilities[battler], MOVE_NONE, gBattleStruct->battlerState[battler].switchIn))
effect = TRUE;
gBattleStruct->eventState.battlerSwitchIn++;
break;
case SECOND_EVENT_BOOSTER_ENERGY:
if (ItemBattleEffects(battler, 0, ctx->holdEffects[battler], IsBoosterEnergyActivation))
effect = TRUE;
gBattleStruct->eventState.battlerSwitchIn++;
break;
case SECOND_EVENT_BLOCK_COUNT:
gBattleStruct->eventState.battlerSwitchIn++;
break;
}
return effect;
}

View File

@ -35,12 +35,12 @@ void ActivateTera(u32 battler)
// Execute battle script. // Execute battle script.
PREPARE_TYPE_BUFFER(gBattleTextBuff1, GetBattlerTeraType(battler)); PREPARE_TYPE_BUFFER(gBattleTextBuff1, GetBattlerTeraType(battler));
if (TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_TERASTALLIZATION)) if (TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_TERASTALLIZATION))
BattleScriptExecute(BattleScript_TeraFormChange); BattleScriptPushCursorAndCallback(BattleScript_TeraFormChange);
else if (gBattleStruct->illusion[gBattlerAttacker].state == ILLUSION_ON else if (gBattleStruct->illusion[gBattlerAttacker].state == ILLUSION_ON
&& DoesSpeciesHaveFormChangeMethod(GetIllusionMonSpecies(gBattlerAttacker), FORM_CHANGE_BATTLE_TERASTALLIZATION)) && DoesSpeciesHaveFormChangeMethod(GetIllusionMonSpecies(gBattlerAttacker), FORM_CHANGE_BATTLE_TERASTALLIZATION))
BattleScriptExecute(BattleScript_IllusionOffAndTerastallization); BattleScriptPushCursorAndCallback(BattleScript_IllusionOffAndTerastallization);
else else
BattleScriptExecute(BattleScript_Terastallization); BattleScriptPushCursorAndCallback(BattleScript_Terastallization);
} }
// Applies palette blend and enables UI indicator after animation has played // Applies palette blend and enables UI indicator after animation has played

File diff suppressed because it is too large Load Diff

View File

@ -517,7 +517,7 @@ void SetZEffect(void)
} }
break; break;
case Z_EFFECT_RESTORE_REPLACEMENT_HP: case Z_EFFECT_RESTORE_REPLACEMENT_HP:
gBattleStruct->zmove.healReplacement = TRUE; gBattleStruct->zmove.healReplacement |= 1u << gBattlerAttacker;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH); BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString; gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;

View File

@ -7,161 +7,138 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_RESTORE_HP] = [HOLD_EFFECT_RESTORE_HP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CURE_PAR] = [HOLD_EFFECT_CURE_PAR] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CURE_SLP] = [HOLD_EFFECT_CURE_SLP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CURE_PSN] = [HOLD_EFFECT_CURE_PSN] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CURE_BRN] = [HOLD_EFFECT_CURE_BRN] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CURE_FRZ] = [HOLD_EFFECT_CURE_FRZ] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_RESTORE_PP] = [HOLD_EFFECT_RESTORE_PP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onAttackerAfterHit = TRUE, .onAttackerAfterHit = TRUE,
}, },
[HOLD_EFFECT_CURE_CONFUSION] = [HOLD_EFFECT_CURE_CONFUSION] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CURE_STATUS] = [HOLD_EFFECT_CURE_STATUS] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onStatusChange = TRUE, .onStatusChange = TRUE,
}, },
[HOLD_EFFECT_CONFUSE_SPICY] = [HOLD_EFFECT_CONFUSE_SPICY] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CONFUSE_DRY] = [HOLD_EFFECT_CONFUSE_DRY] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CONFUSE_SWEET] = [HOLD_EFFECT_CONFUSE_SWEET] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CONFUSE_BITTER] = [HOLD_EFFECT_CONFUSE_BITTER] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CONFUSE_SOUR] = [HOLD_EFFECT_CONFUSE_SOUR] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_ATTACK_UP] = [HOLD_EFFECT_ATTACK_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_DEFENSE_UP] = [HOLD_EFFECT_DEFENSE_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_SPEED_UP] = [HOLD_EFFECT_SPEED_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_SP_ATTACK_UP] = [HOLD_EFFECT_SP_ATTACK_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_SP_DEFENSE_UP] = [HOLD_EFFECT_SP_DEFENSE_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_CRITICAL_UP] = [HOLD_EFFECT_CRITICAL_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_RANDOM_STAT_UP] = [HOLD_EFFECT_RANDOM_STAT_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_EVASION_UP] = [HOLD_EFFECT_EVASION_UP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_WHITE_HERB] = [HOLD_EFFECT_WHITE_HERB] =
{ {
.whiteHerb = TRUE, .whiteHerb = TRUE,
.whiteHerbFirstTurn = TRUE,
.whiteHerbEndTurn = TRUE, .whiteHerbEndTurn = TRUE,
.onFling = TRUE, .onFling = TRUE,
}, },
@ -201,7 +178,6 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_DOUBLE_PRIZE] = [HOLD_EFFECT_DOUBLE_PRIZE] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
}, },
[HOLD_EFFECT_REPEL] = [HOLD_EFFECT_REPEL] =
@ -424,14 +400,12 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_RESTORE_PCT_HP] = [HOLD_EFFECT_RESTORE_PCT_HP] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
[HOLD_EFFECT_MICLE_BERRY] = [HOLD_EFFECT_MICLE_BERRY] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onHpThreshold = TRUE, .onHpThreshold = TRUE,
}, },
@ -492,7 +466,6 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
{ {
.onTargetAfterHit = TRUE, .onTargetAfterHit = TRUE,
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
}, },
[HOLD_EFFECT_RED_CARD] = [HOLD_EFFECT_RED_CARD] =
@ -559,7 +532,6 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_TERRAIN_SEED] = [HOLD_EFFECT_TERRAIN_SEED] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onEffect = TRUE, .onEffect = TRUE,
}, },
@ -586,7 +558,6 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_ROOM_SERVICE] = [HOLD_EFFECT_ROOM_SERVICE] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onEffect = TRUE, .onEffect = TRUE,
}, },
@ -615,7 +586,6 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_MIRROR_HERB] = [HOLD_EFFECT_MIRROR_HERB] =
{ {
.mirrorHerb = TRUE, .mirrorHerb = TRUE,
.mirrorHerbFirstTurn = TRUE,
}, },
[HOLD_EFFECT_PUNCHING_GLOVE] = [HOLD_EFFECT_PUNCHING_GLOVE] =
@ -632,9 +602,8 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_BOOSTER_ENERGY] = [HOLD_EFFECT_BOOSTER_ENERGY] =
{ {
.onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
.onEffect = TRUE, .onEffect = TRUE,
.boosterEnergy = TRUE,
}, },
[HOLD_EFFECT_OGERPON_MASK] = [HOLD_EFFECT_OGERPON_MASK] =
@ -644,6 +613,5 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] =
[HOLD_EFFECT_BERSERK_GENE] = [HOLD_EFFECT_BERSERK_GENE] =
{ {
.onSwitchIn = TRUE, .onSwitchIn = TRUE,
.onSwitchInFirstTurn = TRUE,
}, },
}; };

View File

@ -3728,7 +3728,7 @@ void CopyPartyMonToBattleData(u32 battler, u32 partyIndex)
u32 side = GetBattlerSide(battler); u32 side = GetBattlerSide(battler);
struct Pokemon *party = GetSideParty(side); struct Pokemon *party = GetSideParty(side);
PokemonToBattleMon(&party[partyIndex], &gBattleMons[battler]); PokemonToBattleMon(&party[partyIndex], &gBattleMons[battler]);
gBattleStruct->hpOnSwitchout[side] = gBattleMons[battler].hp; gBattleStruct->battlerState[battler].hpOnSwitchout = gBattleMons[battler].hp;
UpdateSentPokesToOpponentValue(battler); UpdateSentPokesToOpponentValue(battler);
ClearTemporarySpeciesSpriteData(battler, FALSE, FALSE); ClearTemporarySpeciesSpriteData(battler, FALSE, FALSE);
} }

View File

@ -66,9 +66,9 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri will still take residual damage from a f
} WHEN { } WHEN {
TURN { } TURN { }
} SCENE { } SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_SAND_STREAM);
ABILITY_POPUP(playerLeft, ABILITY_COMMANDER); ABILITY_POPUP(playerLeft, ABILITY_COMMANDER);
MESSAGE("Tatsugiri was swallowed by Dondozo and became Dondozo's commander!"); MESSAGE("Tatsugiri was swallowed by Dondozo and became Dondozo's commander!");
ABILITY_POPUP(opponentLeft, ABILITY_SAND_STREAM);
MESSAGE("Dondozo is buffeted by the sandstorm!"); MESSAGE("Dondozo is buffeted by the sandstorm!");
MESSAGE("Tatsugiri is buffeted by the sandstorm!"); MESSAGE("Tatsugiri is buffeted by the sandstorm!");
MESSAGE("The opposing Wobbuffet is buffeted by the sandstorm!"); MESSAGE("The opposing Wobbuffet is buffeted by the sandstorm!");

View File

@ -25,6 +25,35 @@ DOUBLE_BATTLE_TEST("Costar copies an ally's stat stages upon entering battle")
} }
} }
DOUBLE_BATTLE_TEST("Costar copies an ally's stat stages after their ability activates upon entering battle")
{
u32 speedLeft, speedRight = 0;
PARAMETRIZE { speedLeft = 200; speedRight = 150; }
PARAMETRIZE { speedLeft = 150; speedRight = 200; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(100); }
PLAYER(SPECIES_WOBBUFFET) { Speed(110); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); HP(1); };
OPPONENT(SPECIES_WYNAUT) { Speed(10); HP(1); };
OPPONENT(SPECIES_FLAMIGO) { Speed(speedLeft); Ability(ABILITY_COSTAR); }
OPPONENT(SPECIES_ZACIAN) { Speed(speedRight); Ability(ABILITY_INTREPID_SWORD); }
} WHEN {
TURN {
MOVE(playerLeft, MOVE_HYPER_VOICE);
SEND_OUT(opponentLeft, 2);
SEND_OUT(opponentRight, 3);
}
} SCENE {
ABILITY_POPUP(opponentRight, ABILITY_INTREPID_SWORD);
ABILITY_POPUP(opponentLeft, ABILITY_COSTAR);
} THEN {
EXPECT_EQ(opponentRight->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
EXPECT_EQ(opponentLeft->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1);
}
}
// Copy from Ruin ability tests // Copy from Ruin ability tests
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player"); TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Player");
TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent"); TO_DO_BATTLE_TEST("Costar's message displays correctly after all battlers fainted - Opponent");

View File

@ -111,3 +111,39 @@ DOUBLE_BATTLE_TEST("Hospitality is blocked by Heal Block")
} }
} }
} }
DOUBLE_BATTLE_TEST("Hospitality user restores 25% of ally's max HP after taking hazard damage")
{
u32 speedLeft, speedRight = 0;
PARAMETRIZE { speedLeft = 200; speedRight = 150; }
PARAMETRIZE { speedLeft = 150; speedRight = 200; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(1); HP(1); }
PLAYER(SPECIES_WOBBUFFET) { Speed(1); HP(1); }
PLAYER(SPECIES_WOBBUFFET) { Speed(speedLeft); };
PLAYER(SPECIES_POLTCHAGEIST) { Speed(speedRight); Ability(ABILITY_HOSPITALITY); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(110); };
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); };
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_SPIKES);
MOVE(opponentRight, MOVE_HYPER_VOICE);
SEND_OUT(playerLeft, 2);
SEND_OUT(playerRight, 3);
}
} SCENE {
HP_BAR(playerLeft);
HP_BAR(playerRight);
if (speedLeft == 200) {
HP_BAR(playerLeft); // Spikes dmg
HP_BAR(playerRight); // Spikes dmg
} else {
HP_BAR(playerRight); // Spikes dmg
HP_BAR(playerLeft); // Spikes dmg
}
ABILITY_POPUP(playerRight, ABILITY_HOSPITALITY);
HP_BAR(playerLeft); // Hospitality Heal
}
}

View File

@ -25,11 +25,29 @@ SINGLE_BATTLE_TEST("Tera Shift can't be suppressed by Neutralizing Gas")
} WHEN { } WHEN {
TURN { ; } TURN { ; }
} SCENE { } SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
ABILITY_POPUP(player, ABILITY_TERA_SHIFT); ABILITY_POPUP(player, ABILITY_TERA_SHIFT);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
MESSAGE("Terapagos transformed!"); MESSAGE("Terapagos transformed!");
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
} THEN { } THEN {
EXPECT_EQ(player->species, SPECIES_TERAPAGOS_TERASTAL); EXPECT_EQ(player->species, SPECIES_TERAPAGOS_TERASTAL);
} }
} }
SINGLE_BATTLE_TEST("Tera Shift activates before Neutralizing Gas regardless of Speed")
{
u32 speed = 0;
PARAMETRIZE { speed = 50; }
PARAMETRIZE { speed = 150; }
GIVEN {
PLAYER(SPECIES_TERAPAGOS_NORMAL) { Speed(speed); Ability(ABILITY_TERA_SHIFT); }
OPPONENT(SPECIES_KOFFING) { Speed(100); Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(player, ABILITY_TERA_SHIFT);
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
}
}

View File

@ -124,3 +124,21 @@ DOUBLE_BATTLE_TEST("Unnerve stops applying on death but applies on revive")
} }
} }
SINGLE_BATTLE_TEST("Unnerve activates before other switch in abilities regardless of Speed")
{
u32 speed = 0;
PARAMETRIZE { speed = 50; }
PARAMETRIZE { speed = 150; }
GIVEN {
PLAYER(SPECIES_PINSIR) { Speed(100); Ability(ABILITY_MOLD_BREAKER); }
OPPONENT(SPECIES_JOLTIK) { Speed(speed); Ability(ABILITY_UNNERVE); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(opponent, ABILITY_UNNERVE);
ABILITY_POPUP(player, ABILITY_MOLD_BREAKER);
}
}

View File

@ -66,12 +66,12 @@ AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same Pokémon for 2 spo
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
PLAYER(SPECIES_RATTATA); PLAYER(SPECIES_RATTATA);
PLAYER(SPECIES_RATTATA); PLAYER(SPECIES_RATTATA);
// No moves to damage player. // No moves to damage player.
@ -96,12 +96,12 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch mid-turn into a player Pokémon
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_HAUNTER); MULTI_PLAYER(SPECIES_HAUNTER);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
// No moves to damage opponents. // No moves to damage opponents.
@ -110,7 +110,7 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch mid-turn into a player Pokémon
MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); }
MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { EXPECT_SWITCH(playerRight, 5); }; TURN { EXPECT_SWITCH(playerRight, 5); };
} SCENE { } SCENE {
@ -128,12 +128,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch mid-turn into a player Pok
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_HAUNTER); MULTI_PLAYER(SPECIES_HAUNTER);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
// No moves to damage opponents. // No moves to damage opponents.
@ -142,7 +142,7 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch mid-turn into a player Pok
MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); }
MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { EXPECT_SWITCH(playerRight, 5); }; TURN { EXPECT_SWITCH(playerRight, 5); };
} SCENE { } SCENE {
@ -160,12 +160,12 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon after fa
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_GENGAR); MULTI_PLAYER(SPECIES_GENGAR);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
// No moves to damage opponents. // No moves to damage opponents.
@ -174,7 +174,7 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon after fa
MULTI_PARTNER(SPECIES_HAUNTER); MULTI_PARTNER(SPECIES_HAUNTER);
MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_B(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); }; TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); };
} SCENE { } SCENE {
@ -190,12 +190,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon aft
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_GENGAR); MULTI_PLAYER(SPECIES_GENGAR);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
// No moves to damage opponents. // No moves to damage opponents.
@ -204,7 +204,7 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon aft
MULTI_PARTNER(SPECIES_HAUNTER); MULTI_PARTNER(SPECIES_HAUNTER);
MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); }; TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); };
} SCENE { } SCENE {
@ -233,7 +233,7 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon (multi)"
MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); } MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); }
MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); }; TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); };
TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); }; TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); };
@ -250,12 +250,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon (2v
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_HAUNTER); MULTI_PLAYER(SPECIES_HAUNTER);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
// No moves to damage opponents. // No moves to damage opponents.
@ -263,7 +263,7 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon (2v
MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); } MULTI_PARTNER(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); HP(1); }
MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); } MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); }; TURN { MOVE(playerLeft, MOVE_AURA_SPHERE, target:playerRight); EXPECT_SWITCH(playerRight, 4); EXPECT_SEND_OUT(playerRight, 3); };
TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); }; TURN { EXPECT_MOVE(playerRight, MOVE_SHADOW_BALL, target:opponentLeft); };
@ -279,12 +279,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
MULTI_PARTNER(SPECIES_KANGASKHAN); MULTI_PARTNER(SPECIES_KANGASKHAN);
@ -309,12 +309,12 @@ AI_ONE_VS_TWO_BATTLE_TEST("AI will not switch into a partner Pokémon in a 1v2 b
{ {
u32 flags; u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD); PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags); AI_FLAGS(flags);
MULTI_PLAYER(SPECIES_RATTATA); MULTI_PLAYER(SPECIES_RATTATA);
MULTI_PLAYER(SPECIES_KANGASKHAN); MULTI_PLAYER(SPECIES_KANGASKHAN);
// No moves to damage player. // No moves to damage player.
@ -322,7 +322,7 @@ AI_ONE_VS_TWO_BATTLE_TEST("AI will not switch into a partner Pokémon in a 1v2 b
MULTI_OPPONENT_B(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); } MULTI_OPPONENT_B(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); }
MULTI_OPPONENT_B(SPECIES_GASTLY) { Moves(MOVE_LICK); } MULTI_OPPONENT_B(SPECIES_GASTLY) { Moves(MOVE_LICK); }
MULTI_OPPONENT_B(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); } MULTI_OPPONENT_B(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); }
} WHEN { } WHEN {
TURN { EXPECT_SWITCH(opponentRight, 5); }; TURN { EXPECT_SWITCH(opponentRight, 5); };
} SCENE { } SCENE {
@ -417,11 +417,11 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Switch effect moves will send
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Button will send out Ace Mon if it's the only one remaining") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Button will send out Ace Mon if it's the only one remaining")
{ {
u32 aiSmartMonChoicesFlag; u32 flags;
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON; }
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_ACE_POKEMON; }
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag | AI_FLAG_ACE_POKEMON); AI_FLAGS(flags);
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_BUTTON); }; OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_BUTTON); };
OPPONENT(SPECIES_LINOONE); OPPONENT(SPECIES_LINOONE);
@ -432,11 +432,11 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Button will send out Ace
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Pack will send out Ace Mon if it's the only one remaining") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Eject Pack will send out Ace Mon if it's the only one remaining")
{ {
u32 aiSmartMonChoicesFlag; u32 flags;
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON; }
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_ACE_POKEMON; }
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag | AI_FLAG_ACE_POKEMON); AI_FLAGS(flags);
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); } PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); }
PLAYER(SPECIES_ARCANINE) { Ability(ABILITY_INTIMIDATE); Moves(MOVE_SCRATCH); } PLAYER(SPECIES_ARCANINE) { Ability(ABILITY_INTIMIDATE); Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_PACK); Moves(MOVE_SCRATCH); } OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_PACK); Moves(MOVE_SCRATCH); }
@ -536,13 +536,13 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will not switch in a Pokemo
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI considers hazard damage when choosing which Pokemon to switch in") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI considers hazard damage when choosing which Pokemon to switch in")
{ {
u32 aiIsSmart = 0; u32 aiIsSmart = 0;
u32 aiSmartSwitchFlags = 0; u32 flags = 0;
PARAMETRIZE { aiIsSmart = 0; aiSmartSwitchFlags = 0; } // AI doesn't care about hazard damage resulting in Pokemon being KO'd PARAMETRIZE { aiIsSmart = 0; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // AI doesn't care about hazard damage resulting in Pokemon being KO'd
PARAMETRIZE { aiIsSmart = 1; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } // AI_FLAG_SMART_MON_CHOICES avoids being KO'd as a result of hazards damage PARAMETRIZE { aiIsSmart = 1; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; } // AI_FLAG_SMART_MON_CHOICES avoids being KO'd as a result of hazards damage
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartSwitchFlags); AI_FLAGS(flags);
PLAYER(SPECIES_MEGANIUM) { Speed(100); SpDefense(328); SpAttack(265); Moves(MOVE_STEALTH_ROCK, MOVE_SURF); } // Meganium does ~56% minimum ~66% maximum, enough to KO Charizard after rocks and never KO Typhlosion after rocks PLAYER(SPECIES_MEGANIUM) { Speed(100); SpDefense(328); SpAttack(265); Moves(MOVE_STEALTH_ROCK, MOVE_SURF); } // Meganium does ~56% minimum ~66% maximum, enough to KO Charizard after rocks and never KO Typhlosion after rocks
OPPONENT(SPECIES_PONYTA) { Level(5); Speed(5); Moves(MOVE_SCRATCH); } OPPONENT(SPECIES_PONYTA) { Level(5); Speed(5); Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_CHARIZARD) { Speed(200); Moves(MOVE_FLAMETHROWER); SpAttack(317); SpDefense(207); MaxHP(297); } // Outspeends and 2HKOs Meganium OPPONENT(SPECIES_CHARIZARD) { Speed(200); Moves(MOVE_FLAMETHROWER); SpAttack(317); SpDefense(207); MaxHP(297); } // Outspeends and 2HKOs Meganium
@ -555,18 +555,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI considers hazard damage whe
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize type matchup + SE move, then type matchup") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize type matchup + SE move, then type matchup")
{ {
u32 aiSmartSwitchFlags = 0; u32 flags = 0;
u32 move1; u32 move1;
u32 move2; u32 move2;
u32 expectedIndex; u32 expectedIndex;
PARAMETRIZE { expectedIndex = 3; move1 = MOVE_SCRATCH; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = 0; } // When not smart, AI will only switch in a defensive mon if it has a SE move, otherwise will just default to damage PARAMETRIZE { expectedIndex = 3; move1 = MOVE_SCRATCH; move2 = MOVE_SCRATCH; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // When not smart, AI will only switch in a defensive mon if it has a SE move, otherwise will just default to damage
PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = 0; } PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PARAMETRIZE { expectedIndex = 2; move1 = MOVE_SCRATCH; move2 = MOVE_WATER_PULSE; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } // When smart, AI will prioritize SE move, but still switch in good type matchup without SE move PARAMETRIZE { expectedIndex = 2; move1 = MOVE_SCRATCH; move2 = MOVE_WATER_PULSE; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; } // When smart, AI will prioritize SE move, but still switch in good type matchup without SE move
PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; }
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartSwitchFlags); AI_FLAGS(flags);
PLAYER(SPECIES_MARSHTOMP) { Level(30); Moves(MOVE_MUD_BOMB, MOVE_WATER_GUN, MOVE_GROWL, MOVE_MUD_SHOT); Speed(5); } PLAYER(SPECIES_MARSHTOMP) { Level(30); Moves(MOVE_MUD_BOMB, MOVE_WATER_GUN, MOVE_GROWL, MOVE_MUD_SHOT); Speed(5); }
OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(6); } // Forces switchout OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(6); } // Forces switchout
OPPONENT(SPECIES_TANGELA) { Level(30); Moves(move1); Speed(4); } OPPONENT(SPECIES_TANGELA) { Level(30); Moves(move1); Speed(4); }
@ -739,21 +739,21 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will not switch out if Pokemo
// Trapping behaviour // Trapping behaviour
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch in trapping mon mid battle") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch in trapping mon mid battle")
{ {
u32 aiSmartSwitchingFlag = 0; u32 flags = 0;
PARAMETRIZE { aiSmartSwitchingFlag = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
PARAMETRIZE { aiSmartSwitchingFlag = AI_FLAG_SMART_SWITCHING; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
PASSES_RANDOMLY(SHOULD_SWITCH_TRAPPER_PERCENTAGE, 100, RNG_AI_SWITCH_TRAPPER); PASSES_RANDOMLY(SHOULD_SWITCH_TRAPPER_PERCENTAGE, 100, RNG_AI_SWITCH_TRAPPER);
GIVEN { GIVEN {
ASSUME(GetSpeciesType(SPECIES_GOLURK, 0) == TYPE_GROUND); ASSUME(GetSpeciesType(SPECIES_GOLURK, 0) == TYPE_GROUND);
ASSUME(GetSpeciesType(SPECIES_GOLURK, 1) == TYPE_GHOST); ASSUME(GetSpeciesType(SPECIES_GOLURK, 1) == TYPE_GHOST);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartSwitchingFlag); AI_FLAGS(flags);
PLAYER(SPECIES_ELECTRODE) { Speed(4); Moves(MOVE_THUNDERBOLT, MOVE_AURA_SPHERE, MOVE_PROTECT); } PLAYER(SPECIES_ELECTRODE) { Speed(4); Moves(MOVE_THUNDERBOLT, MOVE_AURA_SPHERE, MOVE_PROTECT); }
PLAYER(SPECIES_WOBBUFFET) { Speed(1); }; PLAYER(SPECIES_WOBBUFFET) { Speed(1); };
OPPONENT(SPECIES_SNORLAX) { Speed(1); Moves(MOVE_HEADBUTT); } OPPONENT(SPECIES_SNORLAX) { Speed(1); Moves(MOVE_HEADBUTT); }
OPPONENT(SPECIES_DUGTRIO) { Speed(3); Ability(ABILITY_ARENA_TRAP); Moves(MOVE_EARTHQUAKE); } OPPONENT(SPECIES_DUGTRIO) { Speed(3); Ability(ABILITY_ARENA_TRAP); Moves(MOVE_EARTHQUAKE); }
OPPONENT(SPECIES_GOLURK) { Speed(5); Moves(MOVE_EARTHQUAKE); } OPPONENT(SPECIES_GOLURK) { Speed(5); Moves(MOVE_EARTHQUAKE); }
} WHEN { } WHEN {
if (aiSmartSwitchingFlag == AI_FLAG_SMART_SWITCHING) if (flags & AI_FLAG_SMART_SWITCHING)
TURN { MOVE(player, MOVE_AURA_SPHERE) ; EXPECT_SWITCH(opponent, 1); } TURN { MOVE(player, MOVE_AURA_SPHERE) ; EXPECT_SWITCH(opponent, 1); }
else else
TURN { MOVE(player, MOVE_AURA_SPHERE) ; EXPECT_MOVE(opponent, MOVE_HEADBUTT); } TURN { MOVE(player, MOVE_AURA_SPHERE) ; EXPECT_MOVE(opponent, MOVE_HEADBUTT); }
@ -762,19 +762,19 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch in trapping mon m
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will switch in trapping mon after KO") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will switch in trapping mon after KO")
{ {
u32 aiSmartMonChoicesFlag = 0; // Enables trapping behaviour after KOs u32 flags = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } // No trapping behaviour PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // No trapping behaviour
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches
GIVEN { GIVEN {
ASSUME(GetSpeciesType(SPECIES_MAWILE, 0) == TYPE_STEEL); ASSUME(GetSpeciesType(SPECIES_MAWILE, 0) == TYPE_STEEL);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag); AI_FLAGS(flags);
PLAYER(SPECIES_MAWILE) { Speed(2); Moves(MOVE_PROTECT, MOVE_SCRATCH); } PLAYER(SPECIES_MAWILE) { Speed(2); Moves(MOVE_PROTECT, MOVE_SCRATCH); }
PLAYER(SPECIES_WOBBUFFET) { Speed(1); } PLAYER(SPECIES_WOBBUFFET) { Speed(1); }
OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); } OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); }
OPPONENT(SPECIES_MAGNEZONE) { Speed(1); Ability(ABILITY_MAGNET_PULL); Moves(MOVE_SHOCK_WAVE); } OPPONENT(SPECIES_MAGNEZONE) { Speed(1); Ability(ABILITY_MAGNET_PULL); Moves(MOVE_SHOCK_WAVE); }
OPPONENT(SPECIES_MEGANIUM) { Speed(3); Moves(MOVE_EARTH_POWER); } OPPONENT(SPECIES_MEGANIUM) { Speed(3); Moves(MOVE_EARTH_POWER); }
} WHEN { } WHEN {
if (aiSmartMonChoicesFlag == AI_FLAG_SMART_MON_CHOICES) if (flags & AI_FLAG_SMART_MON_CHOICES)
TURN{ MOVE(player, MOVE_PROTECT); EXPECT_MOVE(opponent, MOVE_SELF_DESTRUCT); EXPECT_SEND_OUT(opponent, 1); } TURN{ MOVE(player, MOVE_PROTECT); EXPECT_MOVE(opponent, MOVE_SELF_DESTRUCT); EXPECT_SEND_OUT(opponent, 1); }
else else
TURN{ MOVE(player, MOVE_PROTECT); EXPECT_MOVE(opponent, MOVE_SELF_DESTRUCT); EXPECT_SEND_OUT(opponent, 2); } TURN{ MOVE(player, MOVE_PROTECT); EXPECT_MOVE(opponent, MOVE_SELF_DESTRUCT); EXPECT_SEND_OUT(opponent, 2); }
@ -783,12 +783,12 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will switch in trapping mon
AI_SINGLE_BATTLE_TEST("AI won't use trapping behaviour if player only has 1 mon left") AI_SINGLE_BATTLE_TEST("AI won't use trapping behaviour if player only has 1 mon left")
{ {
u32 aiSmartMonChoicesFlag = 0; // Enables trapping behaviour after KOs u32 flags = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } // No trapping behaviour PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // No trapping behaviour
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches
GIVEN { GIVEN {
ASSUME(GetSpeciesType(SPECIES_MAWILE, 0) == TYPE_STEEL); ASSUME(GetSpeciesType(SPECIES_MAWILE, 0) == TYPE_STEEL);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiSmartMonChoicesFlag); AI_FLAGS(flags);
PLAYER(SPECIES_MAWILE) { Speed(2); Moves(MOVE_PROTECT, MOVE_SCRATCH); } PLAYER(SPECIES_MAWILE) { Speed(2); Moves(MOVE_PROTECT, MOVE_SCRATCH); }
OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); } OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); }
OPPONENT(SPECIES_MAGNEZONE) { Speed(1); Ability(ABILITY_MAGNET_PULL); Moves(MOVE_SHOCK_WAVE); } OPPONENT(SPECIES_MAGNEZONE) { Speed(1); Ability(ABILITY_MAGNET_PULL); Moves(MOVE_SHOCK_WAVE); }
@ -1242,6 +1242,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and oppon
} }
} }
#if 0
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and opponent has invulnerability move and is faster") AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and opponent has invulnerability move and is faster")
{ {
PASSES_RANDOMLY(SHOULD_SWITCH_TRUANT_PERCENTAGE, 100, RNG_AI_SWITCH_TRUANT); PASSES_RANDOMLY(SHOULD_SWITCH_TRUANT_PERCENTAGE, 100, RNG_AI_SWITCH_TRUANT);
@ -1255,6 +1256,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and oppon
TURN { SKIP_TURN(player); EXPECT_SWITCH(opponent, 1); } TURN { SKIP_TURN(player); EXPECT_SWITCH(opponent, 1); }
} }
} }
#endif
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if main attacking stat lowered by 2 stages with good switchin candidate 50% of the time") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if main attacking stat lowered by 2 stages with good switchin candidate 50% of the time")
{ {
@ -1332,18 +1334,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI correctly handles abilities
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out if Yawn'd with only Ace mon remaining") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out if Yawn'd with only Ace mon remaining")
{ {
u32 aceFlag; u32 flags;
PARAMETRIZE{ aceFlag = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING | AI_FLAG_ACE_POKEMON; }
GIVEN { GIVEN {
ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN); ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING); AI_FLAGS(flags);
PLAYER(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH, MOVE_YAWN); } PLAYER(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH, MOVE_YAWN); }
OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH); } OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_HEADBUTT); } OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_HEADBUTT); }
} WHEN { } WHEN {
TURN { MOVE(player, MOVE_YAWN); EXPECT_MOVE(opponent, MOVE_SCRATCH); } TURN { MOVE(player, MOVE_YAWN); EXPECT_MOVE(opponent, MOVE_SCRATCH); }
if (aceFlag) if (flags & AI_FLAG_ACE_POKEMON)
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); } TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_SCRATCH); }
else else
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_SWITCH(opponent, 1); } TURN { MOVE(player, MOVE_SCRATCH); EXPECT_SWITCH(opponent, 1); }
@ -1352,17 +1354,17 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch out if Yawn'd wi
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch in ace mon after U-Turn if other options available") AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch in ace mon after U-Turn if other options available")
{ {
u32 aceFlag; u32 flags;
PARAMETRIZE{ aceFlag = 0; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; } PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING; }
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_SMART_SWITCHING); AI_FLAGS(flags);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); } PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); } OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); } OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} WHEN { } WHEN {
if (aceFlag) if (flags & AI_FLAG_ACE_POKEMON)
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); } TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); }
else else
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); } TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); }
@ -1371,17 +1373,17 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't switch in ace mon after
AI_SINGLE_BATTLE_TEST("Switch AI: AI won't switch in ace mon after U-Turn if other options available") AI_SINGLE_BATTLE_TEST("Switch AI: AI won't switch in ace mon after U-Turn if other options available")
{ {
u32 aceFlag; u32 flag;
PARAMETRIZE{ aceFlag = 0; } PARAMETRIZE{ flag = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; } PARAMETRIZE{ flag = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT; }
GIVEN { GIVEN {
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | aceFlag | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT); AI_FLAGS(flag);
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); } PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); } OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); } OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); } OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} WHEN { } WHEN {
if (aceFlag) if (flag & AI_FLAG_ACE_POKEMON)
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); } TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 1); MOVE(player, MOVE_SURF); }
else else
TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); } TURN { EXPECT_MOVE(opponent, MOVE_U_TURN); EXPECT_SEND_OUT(opponent, 2); MOVE(player, MOVE_SURF); }

View File

@ -139,3 +139,34 @@ ONE_VS_TWO_BATTLE_TEST("End Turn Effects: First Event Block is executed correctl
EXPECT_GT(damage, 0); EXPECT_GT(damage, 0);
} }
} }
DOUBLE_BATTLE_TEST("End Turn Effects: New mons will switch in after if previous mons died due to hazards")
{
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT) { HP(1); };
OPPONENT(SPECIES_WOBBUFFET) { HP(1); };
OPPONENT(SPECIES_WYNAUT) { HP(1); };
OPPONENT(SPECIES_WOBBUFFET) { HP(1); };
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {
MOVE(playerLeft, MOVE_SPIKES);
MOVE(playerRight, MOVE_HYPER_VOICE);
SEND_OUT(opponentLeft, 2);
SEND_OUT(opponentRight, 3);
SEND_OUT(opponentLeft, 4);
SEND_OUT(opponentRight, 5);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerRight);
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
HP_BAR(opponentLeft);
HP_BAR(opponentRight);
}
}

View File

@ -295,14 +295,14 @@ DOUBLE_BATTLE_TEST("Primal reversion and other switch-in effects trigger for all
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB); ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
ASSUME(GetMoveEffect(MOVE_SPIKES) == EFFECT_SPIKES); ASSUME(GetMoveEffect(MOVE_SPIKES) == EFFECT_SPIKES);
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES); ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_CATERPIE) { HP(1); } PLAYER(SPECIES_CATERPIE) { Speed(8); HP(1); }
PLAYER(SPECIES_SCRAFTY) { Ability(ABILITY_INTIMIDATE); } PLAYER(SPECIES_SCRAFTY) { Speed(100); Ability(ABILITY_INTIMIDATE); }
PLAYER(SPECIES_RESHIRAM); PLAYER(SPECIES_RESHIRAM) { Speed(90); }
OPPONENT(SPECIES_CATERPIE) { HP(1); } OPPONENT(SPECIES_CATERPIE) { Speed(9); HP(1); }
OPPONENT(SPECIES_CATERPIE) { HP(1); } OPPONENT(SPECIES_CATERPIE) { Speed(7); HP(1); }
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); } OPPONENT(SPECIES_KYOGRE) { Speed(80); Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } OPPONENT(SPECIES_GROUDON) { Speed(70); Item(ITEM_RED_ORB); }
} WHEN { } WHEN {
TURN { MOVE(playerLeft, MOVE_STICKY_WEB); TURN { MOVE(playerLeft, MOVE_STICKY_WEB);
MOVE(opponentLeft, MOVE_SPIKES); MOVE(opponentLeft, MOVE_SPIKES);

View File

@ -64,8 +64,6 @@ SINGLE_BATTLE_TEST("Hazards are applied correctly after a battler faints")
SINGLE_BATTLE_TEST("Toxic Spikes can be removed after fainting to other hazards") SINGLE_BATTLE_TEST("Toxic Spikes can be removed after fainting to other hazards")
{ {
KNOWN_FAILING; // tryfaintmon changes something that doesn't allow other switch-in effects on the battler
GIVEN { GIVEN {
PLAYER(SPECIES_WYNAUT); PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_GRIMER) { HP(1); } PLAYER(SPECIES_GRIMER) { HP(1); }
@ -134,13 +132,13 @@ DOUBLE_BATTLE_TEST("Hazards can trigger Emergency Exit and hazards still activat
{ {
GIVEN { GIVEN {
ASSUME(GetMoveEffect(MOVE_FINAL_GAMBIT) == EFFECT_FINAL_GAMBIT); ASSUME(GetMoveEffect(MOVE_FINAL_GAMBIT) == EFFECT_FINAL_GAMBIT);
PLAYER(SPECIES_WOBBUFFET) { HP(1); } PLAYER(SPECIES_WOBBUFFET) { Speed(1); HP(1); }
PLAYER(SPECIES_WOBBUFFET) { HP(1); } PLAYER(SPECIES_WOBBUFFET) { Speed(2); HP(1); }
PLAYER(SPECIES_GOLISOPOD) { HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); } PLAYER(SPECIES_GOLISOPOD) { Speed(10); HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); }
PLAYER(SPECIES_WYNAUT); PLAYER(SPECIES_WYNAUT) { Speed(5); }
PLAYER(SPECIES_WOBBUFFET); PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WYNAUT) { Speed(5); }
} WHEN { } WHEN {
TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_TOXIC_SPIKES); } TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_TOXIC_SPIKES); }
TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(opponentRight, MOVE_SPIKES); } TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(opponentRight, MOVE_SPIKES); }

View File

@ -171,9 +171,7 @@ DOUBLE_BATTLE_TEST("Court Change used by the player swaps G-Max Steelsurge")
MESSAGE("Copperajah used G-Max Steelsurge!"); MESSAGE("Copperajah used G-Max Steelsurge!");
SEND_IN_MESSAGE("Wobbuffet"); SEND_IN_MESSAGE("Wobbuffet");
MESSAGE("The sharp steel bit into Wobbuffet!"); MESSAGE("The sharp steel bit into Wobbuffet!");
NONE_OF { NOT MESSAGE("The sharp steel bit into the opposing Wynaut!");
MESSAGE("The sharp steel bit into the opposing Wynaut!");
}
} }
} }