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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,11 +4,8 @@
struct HoldEffectInfo
{
u32 onSwitchIn:1;
u32 onSwitchInFirstTurn:1;
u32 mirrorHerb:1;
u32 mirrorHerbFirstTurn:1;
u32 whiteHerb:1;
u32 whiteHerbFirstTurn:1;
u32 whiteHerbEndTurn:1;
u32 onStatusChange:1;
u32 onHpThreshold:1;
@ -21,7 +18,8 @@ struct HoldEffectInfo
u32 orbs:1;
u32 onEffect:1;
u32 onFling:1;
u32 padding:14;
u32 boosterEnergy:1;
u32 padding:16;
};
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);
bool32 IsOnSwitchInActivation(enum HoldEffect holdEffect);
bool32 IsOnSwitchInFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsMirrorHerbActivation(enum HoldEffect holdEffect);
bool32 IsMirrorHerbFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbFirstTurnActivation(enum HoldEffect holdEffect);
bool32 IsWhiteHerbEndTurnActivation(enum HoldEffect holdEffect);
bool32 IsOnStatusChangeActivation(enum HoldEffect holdEffect);
bool32 IsOnHpThresholdActivation(enum HoldEffect holdEffect);
@ -48,5 +43,6 @@ bool32 IsOnEffectActivation(enum HoldEffect holdEffect);
bool32 IsForceTriggerItemActivation(enum HoldEffect holdEffect);
bool32 IsOnBerryActivation(enum HoldEffect holdEffect);
bool32 IsOnFlingActivation(enum HoldEffect holdEffect);
bool32 IsBoosterEnergyActivation(enum HoldEffect holdEffect);
#endif // GUARD_BATTLE_HOLD_EFFECTS

View File

@ -56,13 +56,7 @@ enum FirstTurnEventsStates
FIRST_TURN_EVENTS_TERRAIN,
FIRST_TURN_EVENTS_STARTING_STATUS,
FIRST_TURN_EVENTS_TOTEM_BOOST,
FIRST_TURN_EVENTS_NEUTRALIZING_GAS,
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_SWITCH_IN_EVENTS,
FIRST_TURN_EVENTS_END,
};
@ -116,6 +110,7 @@ void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMon
bool32 CanPlayerForfeitNormalTrainerBattle(void);
bool32 DidPlayerForfeitNormalTrainerBattle(void);
void BattleDebug_WonBattle(void);
s32 Factorial(s32 n);
extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE];

View File

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

View File

@ -3,7 +3,6 @@
extern const u8 BattleScript_SupersweetSyrupActivates[];
extern const u8 BattleScript_OpportunistCopyStatChange[];
extern const u8 BattleScript_OpportunistCopyStatChangeEnd3[];
extern const u8 BattleScript_MirrorHerbCopyStatChange[];
extern const u8 BattleScript_MirrorHerbCopyStatChangeEnd2[];
extern const u8 BattleScript_NotAffected[];
@ -81,10 +80,7 @@ extern const u8 BattleScript_SelectingDisabledMoveInPalace[];
extern const u8 BattleScript_SelectingUnusableMoveInPalace[];
extern const u8 BattleScript_EncoredNoMore[];
extern const u8 BattleScript_DestinyBondTakesLife[];
extern const u8 BattleScript_DmgHazardsOnAttacker[];
extern const u8 BattleScript_DmgHazardsOnTarget[];
extern const u8 BattleScript_DmgHazardsOnBattlerScripting[];
extern const u8 BattleScript_DmgHazardsOnFaintedBattler[];
extern const u8 BattleScript_DmgHazardsOnBattler[];
extern const u8 BattleScript_PerishSongTakesLife[];
extern const u8 BattleScript_PerishSongCountGoesDown[];
extern const u8 BattleScript_AllStatsUpZMove[];
@ -199,7 +195,6 @@ extern const u8 BattleScript_AbilityStatusEffect[];
extern const u8 BattleScript_SynchronizeActivates[];
extern const u8 BattleScript_NoItemSteal[];
extern const u8 BattleScript_AbilityCuredStatus[];
extern const u8 BattleScript_AbilityCuredStatusEnd3[];
extern const u8 BattleScript_IgnoresWhileAsleep[];
extern const u8 BattleScript_IgnoresAndUsesRandomMove[];
extern const u8 BattleScript_MoveUsedLoafingAround[];
@ -207,27 +202,20 @@ extern const u8 BattleScript_TruantLoafingAround[];
extern const u8 BattleScript_IgnoresAndFallsAsleep[];
extern const u8 BattleScript_IgnoresAndHitsItself[];
extern const u8 BattleScript_SubstituteFade[];
extern const u8 BattleScript_BerryCureStatusEnd2[];
extern const u8 BattleScript_BerryCureStatusRet[];
extern const u8 BattleScript_BerryCureConfusionEnd2[];
extern const u8 BattleScript_BerryCureConfusionRet[];
extern const u8 BattleScript_WhiteHerbEnd2[];
extern const u8 BattleScript_WhiteHerbRet[];
extern const u8 BattleScript_ItemHealHP_RemoveItemRet[];
extern const u8 BattleScript_ItemHealHP_RemoveItemEnd2[];
extern const u8 BattleScript_BerryPPHealEnd2[];
extern const u8 BattleScript_BerryPPHealRet[];
extern const u8 BattleScript_ItemHealHP_RemoveItem[];
extern const u8 BattleScript_BerryPPHeal[];
extern const u8 BattleScript_ItemHealHP_End2[];
extern const u8 BattleScript_ItemHealHP_Ret[];
extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItem[];
extern const u8 BattleScript_SelectingNotAllowedMoveChoiceItemInPalace[];
extern const u8 BattleScript_HangedOnMsg[];
extern const u8 BattleScript_BerryConfuseHealEnd2[];
extern const u8 BattleScript_BerryConfuseHealRet[];
extern const u8 BattleScript_ConsumableStatRaiseEnd2[];
extern const u8 BattleScript_BerryConfuseHeal[];
extern const u8 BattleScript_ConsumableStatRaiseRet[];
extern const u8 BattleScript_BerryFocusEnergyRet[];
extern const u8 BattleScript_BerryFocusEnergyEnd2[];
extern const u8 BattleScript_BerryFocusEnergy[];
extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[];
extern const u8 BattleScript_AbilityAvoidsDamage[];
extern const u8 BattleScript_AbilityShieldProtects[];
@ -272,7 +260,6 @@ extern const u8 BattleScript_AttackerAbilityStatRaiseEnd2[];
extern const u8 BattleScript_PoisonHealActivates[];
extern const u8 BattleScript_BadDreamsActivates[];
extern const u8 BattleScript_SwitchInAbilityMsg[];
extern const u8 BattleScript_SwitchInAbilityMsgRet[];
extern const u8 BattleScript_ToxicSpikesPoisoned[];
extern const u8 BattleScript_ToxicSpikesBadlyPoisoned[];
extern const u8 BattleScript_ToxicSpikesAbsorbed[];
@ -344,7 +331,6 @@ extern const u8 BattleScript_WeaknessPolicy[];
extern const u8 BattleScript_TargetItemStatRaise[];
extern const u8 BattleScript_RockyHelmetActivates[];
extern const u8 BattleScript_ItemHurtEnd2[];
extern const u8 BattleScript_AirBalloonMsgIn[];
extern const u8 BattleScript_AirBalloonMsgInRet[];
extern const u8 BattleScript_AirBalloonMsgPop[];
extern const u8 BattleScript_ItemHurtRet[];
@ -353,15 +339,12 @@ extern const u8 BattleScript_FlameOrb[];
extern const u8 BattleScript_MoveEffectIncinerate[];
extern const u8 BattleScript_MoveEffectBugBite[];
extern const u8 BattleScript_IllusionOff[];
extern const u8 BattleScript_IllusionOffEnd3[];
extern const u8 BattleScript_IllusionOffAndTerastallization[];
extern const u8 BattleScript_DancerActivates[];
extern const u8 BattleScript_AftermathDmg[];
extern const u8 BattleScript_BattlerFormChange[];
extern const u8 BattleScript_BattlerFormChangeEnd2[];
extern const u8 BattleScript_BattlerFormChangeEnd3[];
extern const u8 BattleScript_AttackerFormChangeWithString[];
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[];
extern const u8 BattleScript_TargetFormChange[];
extern const u8 BattleScript_AnticipationActivates[];
extern const u8 BattleScript_SlowStartEnds[];
@ -373,9 +356,7 @@ extern const u8 BattleScript_FriskMsg[];
extern const u8 BattleScript_FriskMsgWithPopup[];
extern const u8 BattleScript_MoodyActivates[];
extern const u8 BattleScript_EmergencyExit[];
extern const u8 BattleScript_EmergencyExitWild[];
extern const u8 BattleScript_EmergencyExitEnd2[];
extern const u8 BattleScript_EmergencyExitWildEnd2[];
extern const u8 BattleScript_CheekPouchActivates[];
extern const u8 BattleScript_TotemVar[];
extern const u8 BattleScript_TotemFlaredToLife[];
@ -392,7 +373,7 @@ extern const u8 BattleScript_QuickClawActivation[];
extern const u8 BattleScript_QuickDrawActivation[];
extern const u8 BattleScript_CustapBerryActivation[];
extern const u8 BattleScript_MicleBerryActivateEnd2[];
extern const u8 BattleScript_MicleBerryActivateRet[];
extern const u8 BattleScript_MicleBerryActivate[];
extern const u8 BattleScript_JabocaRowapBerryActivates[];
extern const u8 BattleScript_NotAffectedAbilityPopUp[];
extern const u8 BattleScript_BattlerShookOffTaunt[];
@ -405,7 +386,6 @@ extern const u8 BattleScript_RedCardActivates[];
extern const u8 BattleScript_EjectButtonActivates[];
extern const u8 BattleScript_EjectPackActivate_Ret[];
extern const u8 BattleScript_EjectPackActivate_End2[];
extern const u8 BattleScript_EjectPackActivate_End3[];
extern const u8 BattleScript_EjectPackActivates[];
extern const u8 BattleScript_MentalHerbCureRet[];
extern const u8 BattleScript_MentalHerbCureEnd2[];
@ -425,8 +405,7 @@ extern const u8 BattleScript_PrimalWeatherBlocksMove[];
extern const u8 BattleScript_DeltaStreamActivates[];
extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[];
extern const u8 BattleScript_AttackWeakenedByStrongWinds[];
extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[];
extern const u8 BattleScript_BlockedByPrimalWeatherRet[];
extern const u8 BattleScript_BlockedByPrimalWeather[];
extern const u8 BattleScript_PrimalReversion[];
extern const u8 BattleScript_HyperspaceFuryRemoveProtect[];
extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[];
@ -472,7 +451,7 @@ extern const u8 BattleScript_ToxicDebrisActivates[];
extern const u8 BattleScript_EarthEaterActivates[];
extern const u8 BattleScript_MimicryActivates[];
extern const u8 BattleScript_IceFaceNullsDamage[];
extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[];
extern const u8 BattleScript_BattlerFormChangeWithString[];
extern const u8 BattleScript_DampPreventsAftermath[];
extern const u8 BattleScript_HealingWishActivates[];
extern const u8 BattleScript_LunarDanceActivates[];
@ -482,7 +461,6 @@ extern const u8 BattleScript_CouldntFullyProtect[];
extern const u8 BattleScript_MoveEffectStockpileWoreOff[];
extern const u8 BattleScript_SpikesActivates[];
extern const u8 BattleScript_BerserkGeneRet[];
extern const u8 BattleScript_BerserkGeneRetEnd2[];
extern const u8 BattleScript_TargetFormChangeWithStringNoPopup[];
extern const u8 BattleScript_DefDown[];
extern const u8 BattleScript_UltraBurst[];
@ -502,7 +480,6 @@ extern const u8 BattleScript_EffectPsychicNoise[];
extern const u8 BattleScript_AromaVeilProtectsRet[];
extern const u8 BattleScript_LowerAtkSpAtk[];
extern const u8 BattleScript_Terastallization[];
extern const u8 BattleScript_BoosterEnergyEnd2[];
extern const u8 BattleScript_BoosterEnergyRet[];
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
extern const u8 BattleScript_TeraFormChange[];
@ -520,6 +497,7 @@ extern const u8 BattleScript_AlreadyParalyzed[];
extern const u8 BattleScript_AlreadyBurned[];
extern const u8 BattleScript_PrintAbilityMadeIneffective[];
extern const u8 BattleScript_ItDoesntAffectFoe[];
extern const u8 BattleScript_FirstTurnSwitchInEvents[];
// zmoves
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_ENDTURN,
ABILITYEFFECT_MOVE_END_ATTACKER,
ABILITYEFFECT_COLOR_CHANGE, // Color Change, Berserk, Anger Shell
ABILITYEFFECT_COLOR_CHANGE, // Color Change / Berserk / Anger Shell
ABILITYEFFECT_MOVE_END,
ABILITYEFFECT_IMMUNITY,
ABILITYEFFECT_SYNCHRONIZE,
ABILITYEFFECT_ATK_SYNCHRONIZE,
ABILITYEFFECT_MOVE_END_OTHER,
// On Switch in
ABILITYEFFECT_TERA_SHIFT,
ABILITYEFFECT_NEUTRALIZINGGAS,
ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN,
ABILITYEFFECT_UNNERVE,
ABILITYEFFECT_COMMANDER, // Commander / Hospitality / Costar
ABILITYEFFECT_ON_WEATHER,
ABILITYEFFECT_ON_TERRAIN,
ABILITYEFFECT_OPPORTUNIST,
ABILITYEFFECT_OPPORTUNIST_FIRST_TURN,
ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES,
};
enum ItemEffect
@ -207,7 +209,7 @@ enum SkyDropState
enum EjectPackTiming
{
FIRST_TURN,
START_OF_TURN,
END_TURN,
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 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability abilityDef, u32 move, enum Type moveType, enum FunctionCallOption option);
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 IsNeutralizingGasOnField(void);
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 CanBattlerGetOrLoseItem(u32 battler, u16 itemId);
u32 GetBattlerVisualSpecies(u32 battler);
bool32 TryClearIllusion(u32 battler, enum AbilityEffect caseID);
bool32 TryClearIllusion(u32 battler, enum Ability ability);
u32 GetIllusionMonSpecies(u32 battler);
struct Pokemon *GetIllusionMonPtr(u32 battler);
void ClearIllusionMon(u32 battler);
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, 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);
uq4_12_t GetBadgeBoostModifier(void);
enum DamageCategory GetBattleMoveCategory(u32 move);
@ -347,7 +349,7 @@ void TryRestoreHeldItems(void);
bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, u16 item);
void TrySaveExchangedItem(u32 battler, u16 stolenItem);
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);
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability);
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
@ -415,6 +417,8 @@ bool32 HadMoreThanHalfHpNowDoesnt(u32 battler);
void ChooseStatBoostAnimation(u32 battler);
void UpdateStallMons(void);
bool32 TrySwitchInEjectPack(enum EjectPackTiming timing);
bool32 TryEmergencyExit(void);
bool32 EmergencyExitCanBeTriggered(u32 battler);
u32 GetBattlerVolatile(u32 battler, enum Volatile _volatile);
void SetMonVolatile(u32 battler, enum Volatile _volatile, u32 newValue);
bool32 ItemHealMonVolatile(u32 battler, u16 itemId);

View File

@ -218,7 +218,7 @@ enum VolatileFlags
F(VOLATILE_VESSEL_OF_RUIN, vesselOfRuin, (u32, 1)) \
F(VOLATILE_SWORD_OF_RUIN, swordOfRuin, (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. */

View File

@ -88,17 +88,10 @@
#define CMP_COMMON_BITS 4
#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
#define DMG_CHANGE_SIGN 1
#define DMG_1_8_TARGET_HP 2
#define DMG_FULL_ATTACKER_HP 3
#define DMG_BIG_ROOT 4
#define DMG_BIG_ROOT 3
// Cmd_jumpifcantswitch
#define SWITCH_IGNORE_ESCAPE_PREVENTION (1 << 7)
@ -189,10 +182,12 @@ enum MoveEndEffects
MOVEEND_JUMP_TO_HIT_ESCAPE_PLUS_ONE = (MOVEEND_HIT_ESCAPE + 1),
};
// switch cases
#define B_SWITCH_NORMAL 0
#define B_SWITCH_HIT 1 // dragon tail, circle throw
#define B_SWITCH_RED_CARD 2
enum SwitchInCases
{
B_SWITCH_NORMAL,
B_SWITCH_HIT, // dragon tail, circle throw
B_SWITCH_RED_CARD,
};
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)
{
if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_ACE_POKEMON
&& !gBattleStruct->battlerState[battler].forcedSwitch
&& monPartyId == CalculateEnemyPartyCountInSide(battler)-1)
&& !gProtectStructs[battler].forcedSwitch
&& monPartyId == CalculateEnemyPartyCountInSide(battler)-1)
return TRUE;
if (gAiThinkingStruct->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON
&& !gBattleStruct->battlerState[battler].forcedSwitch
&& (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2))
&& !gProtectStructs[battler].forcedSwitch
&& (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2))
return TRUE;
return FALSE;
}

View File

@ -190,7 +190,7 @@ void ActivateDynamax(u32 battler)
if (!gBattleMons[battler].volatiles.transformed) // Ditto cannot 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.

View File

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

View File

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

View File

@ -127,7 +127,6 @@ static void HandleEndTurn_MonFled(void);
static void HandleEndTurn_FinishBattle(void);
static u32 Crc32B (const u8 *data, u32 size);
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_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 gActionsByTurnOrder[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 gCurrentActionFuncId = 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 BattleScripting gBattleScripting = {0};
EWRAM_DATA struct BattleStruct *gBattleStruct = NULL;
EWRAM_DATA struct AiThinkingStruct *gAiThinkingStruct = NULL;
EWRAM_DATA struct AiLogicData *gAiLogicData = NULL;
EWRAM_DATA struct AiPartyData *gAiPartyData = NULL;
EWRAM_DATA struct BattleHistory *gBattleHistory = NULL;
EWRAM_DATA struct AiBattleData *gAiBattleData = 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].wasAboveHalfHp = gBattleMons[battler].hp > gBattleMons[battler].maxHP / 2;
gBattleStruct->hazardsCounter = 0;
gDisableStructs[battler].hazardsDone = FALSE;
gSpecialStatuses[battler].switchInItemDone = FALSE;
ClearPursuitValuesIfSet(battler);
@ -3265,9 +3262,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
gBattleStruct->choicedMove[battler] = MOVE_NONE;
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
gSpecialStatuses[battler].physicalDmg = 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[2] = TYPE_MYSTERY;
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));
for (i = 0; i < NUM_BATTLE_STATS; i++)
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
@ -3771,7 +3765,7 @@ static void DoBattleIntro(void)
static void TryDoEventsBeforeFirstTurn(void)
{
s32 i, j;
s32 i;
if (gBattleControllerExecFlags)
return;
@ -3807,25 +3801,6 @@ static void TryDoEventsBeforeFirstTurn(void)
gBattleStruct->speedTieBreaks = RandomUniform(RNG_SPEED_TIE, 0, Factorial(MAX_BATTLERS_COUNT) - 1);
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++;
break;
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
gBattleStruct->eventState.beforeFristTurn++;
break;
case FIRST_TURN_EVENTS_NEUTRALIZING_GAS:
while (gBattleStruct->switchInBattlerCounter < gBattlersCount) // From fastest to slowest
{
i = gBattlerByTurnOrder[gBattleStruct->switchInBattlerCounter++];
if (AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS_FIRST_TURN, i, 0, 0, 0) != 0)
return;
}
gBattleStruct->switchInBattlerCounter = 0;
case FIRST_TURN_SWITCH_IN_EVENTS:
gBattleStruct->eventState.switchIn = 0;
for (u32 battler = 0; battler < gBattlersCount; battler++)
gBattleStruct->battlerState[battler].switchIn = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_FirstTurnSwitchInEvents);
gBattleStruct->eventState.beforeFristTurn++;
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:
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
@ -5403,7 +5313,7 @@ static void RunTurnActionsFunctions(void)
}
}
*(&gBattleStruct->savedTurnActionNumber) = gCurrentTurnActionNumber;
gBattleStruct->savedTurnActionNumber = gCurrentTurnActionNumber;
sTurnActionsFuncsTable[gCurrentActionFuncId]();
if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished
@ -6168,7 +6078,7 @@ bool32 IsWildMonSmart(void)
#endif
}
static s32 Factorial(s32 n)
s32 Factorial(s32 n)
{
s32 f = 1, 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_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_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_ATK_NAME_WITH_PREFIX2}!"),
[STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} regained health!"),
[STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} became cloaked in mystical moonlight!"),
[STRINGID_CURSEDBODYDISABLED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_BUFF1} was disabled by {B_DEF_NAME_WITH_PREFIX2}'s {B_DEF_ABILITY}!"),
[STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("The healing wish came true for {B_SCR_NAME_WITH_PREFIX2}!"),
[STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} regained health!"),
[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_ATTACKERACQUIREDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} acquired {B_ATK_ABILITY}!"),
[STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_DEF_ABILITY} {B_BUFF2}lowered its {B_BUFF1}!"),
[STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s {B_BUFF1} won't go any higher!"),

View File

@ -6,6 +6,7 @@
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "battle_scripts.h"
#include "battle_switch_in.h"
#include "battle_environment.h"
#include "battle_z_move.h"
#include "item.h"
@ -411,7 +412,7 @@ static void Cmd_endselectionscript(void);
static void Cmd_playanimation(void);
static void Cmd_playanimation_var(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_sethealblock(void);
static void Cmd_returnatktoball(void);
@ -422,7 +423,7 @@ static void Cmd_jumpifcantswitch(void);
static void Cmd_openpartyscreen(void);
static void Cmd_switchhandleorder(void);
static void Cmd_switchineffects(void);
static void Cmd_trainerslidein(void);
static void Cmd_switchinevents(void);
static void Cmd_playse(void);
static void Cmd_fanfare(void);
static void Cmd_playfaintcry(void);
@ -583,7 +584,7 @@ static void Cmd_givecaughtmon(void);
static void Cmd_trysetcaughtmondexflags(void);
static void Cmd_displaydexinfo(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_finishaction(void);
static void Cmd_finishturn(void);
@ -670,7 +671,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_playanimation, //0x45
Cmd_playanimation_var, //0x46
Cmd_jumpfifsemiinvulnerable, //0x47
Cmd_unused_0x48, //0x48
Cmd_trainerslidein, //0x48
Cmd_moveend, //0x49
Cmd_sethealblock, //0x4A
Cmd_returnatktoball, //0x4B
@ -681,7 +682,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_openpartyscreen, //0x50
Cmd_switchhandleorder, //0x51
Cmd_switchineffects, //0x52
Cmd_trainerslidein, //0x53
Cmd_switchinevents, //0x53
Cmd_playse, //0x54
Cmd_fanfare, //0x55
Cmd_playfaintcry, //0x56
@ -842,7 +843,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_trysetcaughtmondexflags, //0xF1
Cmd_displaydexinfo, //0xF2
Cmd_trygivecaughtmonnick, //0xF3
Cmd_unused_0xf4, //0xF4
Cmd_sortbattlers, //0xF4
Cmd_removeattackerstatus1, //0xF5
Cmd_finishaction, //0xF6
Cmd_finishturn, //0xF7
@ -960,7 +961,9 @@ static void ValidateSavedBattlerCounts(void)
if (gBattleStruct->savedAttackerCount > 0)
{
if (TESTING)
{
Test_ExitWithResult(TEST_RESULT_ERROR, 0, "savedAttackerCount is greater than 0! More calls to SaveBattlerAttacker than RestoreBattlerAttacker!", __FILE__, __LINE__);
}
else
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;
}
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)
{
if (gChosenActionByBattler[battler] != B_ACTION_USE_MOVE)
@ -2464,6 +2450,7 @@ static void Cmd_datahpupdate(void)
if (gBattleControllerExecFlags)
return;
switch (cmd->updateState)
{
case PASSIVE_HP_UPDATE:
@ -4285,6 +4272,7 @@ static void Cmd_tryfaintmon(void)
&& !IsBattlerAlive(battler))
{
gHitMarker |= HITMARKER_FAINTED(battler);
gBattleStruct->eventState.faintedAction = 0;
BattleScriptPush(cmd->nextInstr);
gBattlescriptCurrInstr = faintScript;
if (IsOnPlayerSide(battler))
@ -5001,8 +4989,10 @@ static void Cmd_checkteamslost(void)
u32 occupiedOpponentSpots = (gBattlersCount / 2) - emptyOpponentSpots;
u32 alivePlayerPartyMons = CountAliveMonsForBattlerSide(B_POSITION_PLAYER_LEFT) - occupiedPlayerSpots;
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;
else
gBattlescriptCurrInstr = cmd->nextInstr;
@ -5547,8 +5537,15 @@ static void Cmd_jumpfifsemiinvulnerable(void)
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)
@ -6235,33 +6232,34 @@ static void Cmd_moveend(void)
gBattleScripting.moveendState++;
break;
case MOVEEND_SYNCHRONIZE_TARGET: // target synchronize
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, 0))
if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBattlerTarget, 0, 0, TRUE))
effect = TRUE;
gBattleScripting.moveendState++;
break;
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;
else if (TryClearIllusion(gBattlerTarget, ABILITYEFFECT_MOVE_END))
else if (TryClearIllusion(gBattlerTarget, i))
effect = TRUE;
gBattleScripting.moveendState++;
break;
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;
gBattleScripting.moveendState++;
break;
case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities
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;
}
if (!effect)
gBattleScripting.moveendState++;
break;
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;
gBattleScripting.moveendState++;
break;
@ -6661,7 +6659,7 @@ static void Cmd_moveend(void)
u32 battler = gBattleStruct->eventState.moveEndBattler++;
if (battler == gBattlerAttacker)
continue;
if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, 0))
if (AbilityBattleEffects(ABILITYEFFECT_COLOR_CHANGE, battler, GetBattlerAbility(battler), 0, TRUE))
return;
}
gBattleStruct->eventState.moveEndBattler = 0;
@ -6831,12 +6829,7 @@ static void Cmd_moveend(void)
effect = TRUE;
gBattleScripting.battler = battler;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
BattleScriptCall(BattleScript_EmergencyExit);
else
BattleScriptCall(BattleScript_EmergencyExitWild);
BattleScriptCall(BattleScript_EmergencyExit);
break; // Only the fastest Emergency Exit / Wimp Out activates
}
}
@ -6935,7 +6928,7 @@ static void Cmd_moveend(void)
u32 battler = gBattleStruct->eventState.moveEndBattler++;
if (!IsBattlerAlive(battler))
continue;
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, 0))
if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, GetBattlerAbility(battler), 0, TRUE))
return;
}
gBattleStruct->eventState.moveEndBattler = 0;
@ -7151,7 +7144,7 @@ static void Cmd_moveend(void)
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;
}
}
@ -7814,264 +7807,39 @@ static void Cmd_switchhandleorder(void)
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)
{
UpdateSentPokesToOpponentValue(battler);
gHitMarker &= ~HITMARKER_FAINTED(battler);
gSpecialStatuses[battler].faintedHasReplacement = FALSE;
}
gBattleStruct->battlerState[battler].switchIn = TRUE;
gProtectStructs[battler].forcedSwitch = FALSE;
static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId)
{
gBattleScripting.battler = battler;
gBattleCommunication[MULTISTRING_CHOOSER] = 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.
if (GetBattlerAbility(battler) == ABILITY_TRUANT
&& gCurrentActionFuncId != B_ACTION_USE_MOVE
&& !gDisableStructs[battler].truantSwitchInHack)
gDisableStructs[battler].truantCounter = 1;
gDisableStructs[battler].truantSwitchInHack = 0;
if (gBattlescriptCurrInstr[1] == BS_TARGET)
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)
for (u32 i = 0; i < gBattlersCount; i++)
{
case HAZARDS_NONE:
break;
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;
if (gBattlerByTurnOrder[i] == battler)
gActionsByTurnOrder[i] = B_ACTION_CANCEL_PARTNER;
}
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)
{
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.
case BS_FAINTED_MULTIPLE_1: // Saves the battlers.
gBattleStruct->battlerState[battler].multipleSwitchInBattlers = TRUE;
UpdateSentMonFlags(battler);
// Increment fainted battler.
do
do // Increment fainted battler
{
gBattlerFainted++;
if (gBattlerFainted >= gBattlersCount)
@ -8079,55 +7847,20 @@ static void Cmd_switchineffects(void)
if (gHitMarker & HITMARKER_FAINTED(gBattlerFainted) && !(gAbsentBattlerFlags & (1u << gBattlerFainted)))
break;
} 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);
u32 battler = GetBattlerForBattleScript(cmd->position);
BtlController_EmitTrainerSlide(battler, B_COMM_TO_CONTROLLER);
MarkBattlerForControllerExec(battler);
CMD_ARGS();
while (gBattleStruct->eventState.switchIn < SWITCH_IN_EVENTS_COUNT)
{
if (DoSwitchInEvents())
return;
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
@ -9235,7 +8968,7 @@ static void Cmd_hpthresholds2(void)
{
u32 battler = GetBattlerForBattleScript(cmd->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;
if (gBattleMons[opposingBattler].hp >= hpSwitchout)
@ -9884,9 +9617,6 @@ static void Cmd_manipulatedamage(void)
case DMG_1_8_TARGET_HP:
SetPassiveDamageAmount(gBattlerTarget, GetNonDynamaxMaxHP(gBattlerTarget) / 8);
break;
case DMG_FULL_ATTACKER_HP:
gBattleStruct->passiveHpUpdate[gBattlerTarget] = GetNonDynamaxMaxHP(gBattlerAttacker);
break;
case DMG_BIG_ROOT:
gBattleStruct->passiveHpUpdate[gBattlerAttacker] = -1 * GetDrainedBigRootHp(gBattlerAttacker, gBattleStruct->passiveHpUpdate[gBattlerAttacker]);
break;
@ -10746,9 +10476,8 @@ static void Cmd_forcerandomswitch(void)
{
gBattleStruct->battlerPartyIndexes[gBattlerTarget] = gBattlerPartyIndexes[gBattlerTarget];
gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch;
gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE;
gProtectStructs[gBattlerTarget].forcedSwitch = TRUE;
gBattleStruct->monToSwitchIntoId[gBattlerTarget] = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)];
if (!IsMultiBattle())
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)
@ -15826,7 +15564,7 @@ void BS_ActivateWeatherChangeAbilities(void)
u32 battler = GetBattlerForBattleScript(cmd->battler);
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)
@ -15835,7 +15573,7 @@ void BS_ActivateTerrainChangeAbilities(void)
u32 battler = GetBattlerForBattleScript(cmd->battler);
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)
@ -16673,7 +16411,8 @@ void BS_SetTracedAbility(void)
void BS_TryIllusionOff(void)
{
NATIVE_ARGS(u8 battler);
if (TryClearIllusion(GetBattlerForBattleScript(cmd->battler), ABILITYEFFECT_MOVE_END))
u32 battler = GetBattlerForBattleScript(cmd->battler);
if (TryClearIllusion(battler, GetBattlerAbility(battler)))
return;
gBattlescriptCurrInstr = cmd->nextInstr;
}
@ -16775,10 +16514,10 @@ void BS_GetBattlerFainted(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
// TODO: What is this fixing???
void BS_ResetSwitchInAbilityBits(void)
{
NATIVE_ARGS();
gSpecialStatuses[gBattlerAttacker].switchInAbilityDone = FALSE;
gBattlescriptCurrInstr = cmd->nextInstr;
}
@ -17038,17 +16777,17 @@ void BS_SwitchinAbilities(void)
{
NATIVE_ARGS(u8 battler);
u32 battler = GetBattlerForBattleScript(cmd->battler);
u32 ability = GetBattlerAbility(battler);
gBattlescriptCurrInstr = cmd->nextInstr;
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0);
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0);
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0);
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0);
if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect())
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
if (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, 0, 0, 0);
AbilityBattleEffects(ABILITYEFFECT_TERA_SHIFT, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_UNNERVE, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_COMMANDER, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battler, ability, MOVE_NONE, TRUE);
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, ability, MOVE_NONE, TRUE);
}
void BS_InstantHpDrop(void)
@ -17061,16 +16800,17 @@ void BS_InstantHpDrop(void)
void BS_ClearStatus(void)
{
NATIVE_ARGS();
gBattleMons[gBattlerAttacker].status1 = 0;
NATIVE_ARGS(u8 battler);
u32 battler = GetBattlerForBattleScript(cmd->battler);
gBattleMons[battler].status1 = 0;
BtlController_EmitSetMonData(
gBattlerAttacker,
battler,
B_COMM_TO_CONTROLLER,
REQUEST_STATUS_BATTLE,
0,
sizeof(gBattleMons[gBattlerAttacker].status1),
&gBattleMons[gBattlerAttacker].status1);
MarkBattlerForControllerExec(gBattlerAttacker);
sizeof(gBattleMons[battler].status1),
&gBattleMons[battler].status1);
MarkBattlerForControllerExec(battler);
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.
PREPARE_TYPE_BUFFER(gBattleTextBuff1, GetBattlerTeraType(battler));
if (TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_TERASTALLIZATION))
BattleScriptExecute(BattleScript_TeraFormChange);
BattleScriptPushCursorAndCallback(BattleScript_TeraFormChange);
else if (gBattleStruct->illusion[gBattlerAttacker].state == ILLUSION_ON
&& DoesSpeciesHaveFormChangeMethod(GetIllusionMonSpecies(gBattlerAttacker), FORM_CHANGE_BATTLE_TERASTALLIZATION))
BattleScriptExecute(BattleScript_IllusionOffAndTerastallization);
BattleScriptPushCursorAndCallback(BattleScript_IllusionOffAndTerastallization);
else
BattleScriptExecute(BattleScript_Terastallization);
BattleScriptPushCursorAndCallback(BattleScript_Terastallization);
}
// 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;
case Z_EFFECT_RESTORE_REPLACEMENT_HP:
gBattleStruct->zmove.healReplacement = TRUE;
gBattleStruct->zmove.healReplacement |= 1u << gBattlerAttacker;
BattleScriptPush(gBattlescriptCurrInstr + Z_EFFECT_BS_LENGTH);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_Z_HP_TRAP;
gBattlescriptCurrInstr = BattleScript_ZEffectPrintString;

View File

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

View File

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

View File

@ -66,9 +66,9 @@ DOUBLE_BATTLE_TEST("Commander Tatsugiri will still take residual damage from a f
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_SAND_STREAM);
ABILITY_POPUP(playerLeft, ABILITY_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("Tatsugiri 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
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");

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 {
TURN { ; }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
ABILITY_POPUP(player, ABILITY_TERA_SHIFT);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
MESSAGE("Terapagos transformed!");
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
} THEN {
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;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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);
// 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;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_RATTATA);
// 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_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { EXPECT_SWITCH(playerRight, 5); };
} SCENE {
@ -128,12 +128,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch mid-turn into a player Pok
{
u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_RATTATA);
// 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_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { EXPECT_SWITCH(playerRight, 5); };
} SCENE {
@ -160,12 +160,12 @@ AI_MULTI_BATTLE_TEST("AI partner will not switch into a player Pokémon after fa
{
u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_RATTATA);
// 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_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); };
} SCENE {
@ -190,12 +190,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon aft
{
u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_RATTATA);
// 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_OPPONENT_A(SPECIES_TRAPINCH) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_VIBRAVA) { Moves(MOVE_CELEBRATE); }
} WHEN {
TURN { EXPECT_MOVE(playerRight, MOVE_CELEBRATE); EXPECT_SEND_OUT(playerRight, 5); };
} 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_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_B(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN {
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); };
@ -250,12 +250,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI partner will not switch into a player Pokémon (2v
{
u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_RATTATA);
// 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_OPPONENT_A(SPECIES_RATTATA) { Moves(MOVE_CELEBRATE); }
MULTI_OPPONENT_A(SPECIES_KANGASKHAN) { Moves(MOVE_CELEBRATE); }
} WHEN {
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); };
@ -279,12 +279,12 @@ AI_TWO_VS_ONE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2
{
u32 flags;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE {flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_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;
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
PARAMETRIZE {flags = 0; }
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING; }
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);
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_KANGASKHAN);
// 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_GASTLY) { Moves(MOVE_LICK); }
MULTI_OPPONENT_B(SPECIES_RATICATE) { Moves(MOVE_HEADBUTT); }
} WHEN {
TURN { EXPECT_SWITCH(opponentRight, 5); };
} 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")
{
u32 aiSmartMonChoicesFlag;
PARAMETRIZE { aiSmartMonChoicesFlag = 0; }
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; }
u32 flags;
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON; }
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 {
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); }
OPPONENT(SPECIES_ZIGZAGOON) { Item(ITEM_EJECT_BUTTON); };
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")
{
u32 aiSmartMonChoicesFlag;
PARAMETRIZE { aiSmartMonChoicesFlag = 0; }
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; }
u32 flags;
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON; }
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 {
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_ARCANINE) { Ability(ABILITY_INTIMIDATE); 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")
{
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 = 1; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } // AI_FLAG_SMART_MON_CHOICES avoids being KO'd as a result of hazards damage
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; 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 {
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
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
@ -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")
{
u32 aiSmartSwitchFlags = 0;
u32 flags = 0;
u32 move1;
u32 move2;
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 = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = 0; }
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 = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; }
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; 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; 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; flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES; }
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); }
OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(6); } // Forces switchout
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
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch in trapping mon mid battle")
{
u32 aiSmartSwitchingFlag = 0;
PARAMETRIZE { aiSmartSwitchingFlag = 0; }
PARAMETRIZE { aiSmartSwitchingFlag = AI_FLAG_SMART_SWITCHING; }
u32 flags = 0;
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; }
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);
GIVEN {
ASSUME(GetSpeciesType(SPECIES_GOLURK, 0) == TYPE_GROUND);
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_WOBBUFFET) { Speed(1); };
OPPONENT(SPECIES_SNORLAX) { Speed(1); Moves(MOVE_HEADBUTT); }
OPPONENT(SPECIES_DUGTRIO) { Speed(3); Ability(ABILITY_ARENA_TRAP); Moves(MOVE_EARTHQUAKE); }
OPPONENT(SPECIES_GOLURK) { Speed(5); Moves(MOVE_EARTHQUAKE); }
} WHEN {
if (aiSmartSwitchingFlag == AI_FLAG_SMART_SWITCHING)
if (flags & AI_FLAG_SMART_SWITCHING)
TURN { MOVE(player, MOVE_AURA_SPHERE) ; EXPECT_SWITCH(opponent, 1); }
else
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")
{
u32 aiSmartMonChoicesFlag = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } // No trapping behaviour
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches
u32 flags = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // No trapping behaviour
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 {
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_WOBBUFFET) { Speed(1); }
OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); }
OPPONENT(SPECIES_MAGNEZONE) { Speed(1); Ability(ABILITY_MAGNET_PULL); Moves(MOVE_SHOCK_WAVE); }
OPPONENT(SPECIES_MEGANIUM) { Speed(3); Moves(MOVE_EARTH_POWER); }
} 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); }
else
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")
{
u32 aiSmartMonChoicesFlag = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { aiSmartMonChoicesFlag = 0; } // No trapping behaviour
PARAMETRIZE { aiSmartMonChoicesFlag = AI_FLAG_SMART_MON_CHOICES; } // Traps with mid battle switches
u32 flags = 0; // Enables trapping behaviour after KOs
PARAMETRIZE { flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; } // No trapping behaviour
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 {
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); }
OPPONENT(SPECIES_SNORLAX) { Speed(3); Moves(MOVE_SELF_DESTRUCT); }
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")
{
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); }
}
}
#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")
{
@ -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")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
u32 flags;
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 { 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 {
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); }
OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_SLAKOTH) { Moves(MOVE_HEADBUTT); }
} WHEN {
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); }
else
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")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
u32 flags;
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 { 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 {
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); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} 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); }
else
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")
{
u32 aceFlag;
PARAMETRIZE{ aceFlag = 0; }
PARAMETRIZE{ aceFlag = AI_FLAG_ACE_POKEMON; }
u32 flag;
PARAMETRIZE{ flag = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT; }
PARAMETRIZE{ flag = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_ACE_POKEMON | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT; }
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); }
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_U_TURN); }
OPPONENT(SPECIES_NUMEL) { Level(5); Moves(MOVE_SPLASH); }
OPPONENT(SPECIES_SCIZOR) { Moves(MOVE_BUG_BITE); }
} 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); }
else
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);
}
}
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_SPIKES) == EFFECT_SPIKES);
ASSUME(GetMoveEffect(MOVE_TOXIC_SPIKES) == EFFECT_TOXIC_SPIKES);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_CATERPIE) { HP(1); }
PLAYER(SPECIES_SCRAFTY) { Ability(ABILITY_INTIMIDATE); }
PLAYER(SPECIES_RESHIRAM);
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_CATERPIE) { HP(1); }
OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
PLAYER(SPECIES_CATERPIE) { Speed(8); HP(1); }
PLAYER(SPECIES_SCRAFTY) { Speed(100); Ability(ABILITY_INTIMIDATE); }
PLAYER(SPECIES_RESHIRAM) { Speed(90); }
OPPONENT(SPECIES_CATERPIE) { Speed(9); HP(1); }
OPPONENT(SPECIES_CATERPIE) { Speed(7); HP(1); }
OPPONENT(SPECIES_KYOGRE) { Speed(80); Item(ITEM_BLUE_ORB); }
OPPONENT(SPECIES_GROUDON) { Speed(70); Item(ITEM_RED_ORB); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_STICKY_WEB);
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")
{
KNOWN_FAILING; // tryfaintmon changes something that doesn't allow other switch-in effects on the battler
GIVEN {
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_GRIMER) { HP(1); }
@ -134,13 +132,13 @@ DOUBLE_BATTLE_TEST("Hazards can trigger Emergency Exit and hazards still activat
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_FINAL_GAMBIT) == EFFECT_FINAL_GAMBIT);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_GOLISOPOD) { HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); }
PLAYER(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
PLAYER(SPECIES_WOBBUFFET) { Speed(1); HP(1); }
PLAYER(SPECIES_WOBBUFFET) { Speed(2); HP(1); }
PLAYER(SPECIES_GOLISOPOD) { Speed(10); HP(105); MaxHP(200); Ability(ABILITY_EMERGENCY_EXIT); }
PLAYER(SPECIES_WYNAUT) { Speed(5); }
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WOBBUFFET) { Speed(10); }
OPPONENT(SPECIES_WYNAUT) { Speed(5); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_TOXIC_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!");
SEND_IN_MESSAGE("Wobbuffet");
MESSAGE("The sharp steel bit into Wobbuffet!");
NONE_OF {
MESSAGE("The sharp steel bit into the opposing Wynaut!");
}
NOT MESSAGE("The sharp steel bit into the opposing Wynaut!");
}
}