rhh merge/upcoming

This commit is contained in:
AlexOn1ine 2025-02-09 14:04:21 +01:00
commit 4babfd003e
84 changed files with 2667 additions and 1788 deletions

View File

@ -1276,8 +1276,9 @@
.byte 0xef
.endm
.macro givecaughtmon
.macro givecaughtmon passInstr:req
.byte 0xf0
.4byte \passInstr
.endm
.macro trysetcaughtmondexflags failInstr:req
@ -1289,9 +1290,8 @@
.byte 0xf2
.endm
.macro trygivecaughtmonnick successInstr:req
.macro trygivecaughtmonnick
.byte 0xf3
.4byte \successInstr
.endm
.macro subattackerhpbydmg
@ -1554,13 +1554,43 @@
.4byte \failInstr
.endm
.macro trysetstatus1, ptr:req
callnative BS_TrySetStatus1
.macro trysetparalysis, ptr:req
callnative BS_TrySetParalysis
.4byte \ptr
.endm
.macro trysetstatus2, ptr:req
callnative BS_TrySetStatus2
.macro trysetpoison, ptr:req
callnative BS_TrySetPoison
.4byte \ptr
.endm
.macro trysetpoisonparalysis, ptr:req
callnative BS_TrySetPoisonParalyzis
.4byte \ptr
.endm
.macro tryseteffectspore, ptr:req
callnative BS_TrySetEffectSpore
.4byte \ptr
.endm
.macro trysetconfusion, ptr:req
callnative BS_TrySetConfusion
.4byte \ptr
.endm
.macro trysetinfatuation, ptr:req
callnative BS_TrySetInfatuation
.4byte \ptr
.endm
.macro trysetescapeprevention, ptr:req
callnative BS_TrySetEscapePrevention
.4byte \ptr
.endm
.macro trysettorment, ptr:req
callnative BS_TrySetTorment
.4byte \ptr
.endm

View File

@ -18215,10 +18215,50 @@ TeraStarstormCreateBeam::
createsprite gTeraStarstormBeamSpriteTemplate, ANIM_BATTLER, 1, 2, 0, 0, 0, 20
return
gBattleAnimMove_TachyonCutter::
loadspritegfx ANIM_TAG_CUT
loadspritegfx ANIM_TAG_BUBBLE
createsprite gTachyonCutterSpriteTemplate, ANIM_ATTACKER, 2, 40, -32, 0
createsprite gTachyonCutterSpriteTemplate, ANIM_ATTACKER, 2, 40, -32, 1
playsewithpan SE_M_RAZOR_WIND2, SOUND_PAN_ATTACKER
waitforvisualfinish
end
gBattleAnimMove_SaltCure::
loadspritegfx ANIM_TAG_SALT_PARTICLE
loadspritegfx ANIM_TAG_WATER_ORB
call SaltCureEffect
call SaltCureEffect
call SaltCureEffect
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
waitforvisualfinish
call gBattleAnimGeneral_SaltCureDamage
end
SaltCureEffect:
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 28, 384, 50, 8, 50, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 32, 240, 40, 11, -46, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 33, 416, 40, 4, 42, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 31, 288, 45, 6, -42, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 28, 448, 45, 11, 46, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
createsprite gSaltCureSwirlSpriteTemplate, ANIM_TARGET, 2, 0, 33, 464, 50, 10, -50, ANIM_TARGET
delay 2
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
return
gBattleAnimMove_TeraBlast::
gBattleAnimMove_OrderUp::
gBattleAnimMove_GlaiveRush::
gBattleAnimMove_SaltCure::
gBattleAnimMove_TripleDive::
gBattleAnimMove_Doodle::
gBattleAnimMove_Ruination::
@ -18233,7 +18273,6 @@ gBattleAnimMove_MagicalTorque::
gBattleAnimMove_Psyblade::
gBattleAnimMove_MatchaGotcha::
gBattleAnimMove_MightyCleave::
gBattleAnimMove_TachyonCutter::
gBattleAnimMove_SupercellSlam::
end @to do
@ -28927,7 +28966,41 @@ General_AffectionHangedOn_3Hearts:
end
gBattleAnimGeneral_SaltCureDamage::
goto gBattleAnimStatus_Freeze
loadspritegfx ANIM_TAG_SALT_PARTICLE
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, -10, -10, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 10, 20, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, -29, 0, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 29, -20, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, -5, 10, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 17, -12, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, -20, 0, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, -15, 15, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 26, -5, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 0, 0, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
delay 4
createsprite gSaltCureCrystalSpriteTemplate, ANIM_TARGET, 2, 20, 2, 1
playsewithpan SE_M_ICY_WIND, SOUND_PAN_TARGET
waitforvisualfinish
end
gBattleAnimGeneral_Rainbow::
call RainDrops

View File

@ -5952,10 +5952,14 @@ BattleScript_SafeguardEnds::
waitmessage B_WAIT_TIME_LONG
end2
@ Leech Seed end turn effect
@ attacker is the victim
@ target is the leech seeder (recieving HP)
BattleScript_LeechSeedTurnDrainLiquidOoze::
call BattleScript_LeechSeedTurnDrain
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
copybyte gBattlerAttacker, gBattlerTarget @ needed to get liquid ooze message correct
goto BattleScript_LeechSeedTurnDrainGainHp
BattleScript_LeechSeedTurnDrainHealBlock::
@ -8231,15 +8235,12 @@ BattleScript_FlashFireBoost::
goto BattleScript_MoveEnd
BattleScript_AbilityPreventsPhasingOut::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNANCHORSITSELFWITH
waitmessage B_WAIT_TIME_LONG
call BattleScript_AbilityPreventsPhasingOutRet
goto BattleScript_MoveEnd
BattleScript_AbilityPreventsPhasingOutRet::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
call BattleScript_AbilityPopUpTarget
printstring STRINGID_PKMNANCHORSITSELFWITH
waitmessage B_WAIT_TIME_LONG
return
@ -9735,7 +9736,7 @@ BattleScript_EffectMaxMove::
resultmessage
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
setmaxmoveeffect
setadditionaleffects
moveendall
end
@ -9809,61 +9810,158 @@ BattleScript_EffectTryReducePP::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectStatus1Foes::
BattleScript_EffectParalyzeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_Status1FoesLoop:
jumpifabsent BS_TARGET, BattleScript_Status1FoesIncrement
trysetstatus1 BattleScript_Status1FoesIncrement
BattleScript_ParalyzeSideLoop:
jumpifabsent BS_TARGET, BattleScript_ParalyzeSideIncrement
trysetparalysis BattleScript_ParalyzeSideIncrement
statusanimation BS_TARGET
updatestatusicon BS_TARGET
printfromtable gStatusConditionsStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_EFFECT_BATTLER
waitstate
BattleScript_Status1FoesIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_Status1FoesEnd
setallytonexttarget BattleScript_Status1FoesLoop
BattleScript_Status1FoesEnd:
BattleScript_ParalyzeSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ParalyzeSideEnd
setallytonexttarget BattleScript_ParalyzeSideLoop
BattleScript_ParalyzeSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectStatus2Foes::
BattleScript_EffectPoisonSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_Status2FoesLoop:
jumpifabsent BS_TARGET, BattleScript_Status2FoesIncrement
trysetstatus2 BattleScript_Status2FoesIncrement
jumpifbyte CMP_EQUAL, gBattleCommunication, 1, BattleScript_DoConfuseAnim
jumpifbyte CMP_EQUAL, gBattleCommunication, 2, BattleScript_DoInfatuationAnim
BattleScript_Status2FoesPrintMessage:
BattleScript_PoisonSideLoop:
jumpifabsent BS_TARGET, BattleScript_PoisonSideIncrement
trysetpoison BattleScript_PoisonSideIncrement
statusanimation BS_TARGET
updatestatusicon BS_TARGET
printfromtable gStatusConditionsStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_EFFECT_BATTLER
waitstate
BattleScript_PoisonSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonSideEnd
setallytonexttarget BattleScript_PoisonSideLoop
BattleScript_PoisonSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectPoisonParalyzeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_PoisonParalyzeSideLoop:
jumpifabsent BS_TARGET, BattleScript_PoisonParalyzeSideIncrement
trysetpoisonparalysis BattleScript_PoisonParalyzeSideIncrement
statusanimation BS_TARGET
updatestatusicon BS_TARGET
printfromtable gStatusConditionsStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_EFFECT_BATTLER
waitstate
BattleScript_PoisonParalyzeSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonParalyzeSideEnd
setallytonexttarget BattleScript_PoisonParalyzeSideLoop
BattleScript_PoisonParalyzeSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectEffectSporeSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_EffectSporeSideLoop:
jumpifabsent BS_TARGET, BattleScript_EffectSporeSideIncrement
tryseteffectspore BattleScript_EffectSporeSideIncrement
statusanimation BS_TARGET
updatestatusicon BS_TARGET
printfromtable gStatusConditionsStringIds
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_EFFECT_BATTLER
waitstate
BattleScript_EffectSporeSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_EffectSporeSideEnd
setallytonexttarget BattleScript_EffectSporeSideLoop
BattleScript_EffectSporeSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectConfuseSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_ConfuseSideLoop:
jumpifabsent BS_TARGET, BattleScript_ConfuseSideIncrement
trysetconfusion BattleScript_ConfuseSideIncrement
status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION
BattleScript_ConfuseSidePrintMessage:
printfromtable gStatus2StringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_Status2FoesIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_Status2FoesEnd
setallytonexttarget BattleScript_Status2FoesLoop
BattleScript_Status2FoesEnd:
BattleScript_ConfuseSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ConfuseSideEnd
setallytonexttarget BattleScript_ConfuseSideLoop
BattleScript_ConfuseSideEnd:
restoretarget
jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush
goto BattleScript_MoveEnd
BattleScript_DoConfuseAnim:
status2animation BS_EFFECT_BATTLER, STATUS2_CONFUSION
goto BattleScript_Status2FoesPrintMessage
BattleScript_DoInfatuationAnim:
status2animation BS_EFFECT_BATTLER, STATUS2_INFATUATION
goto BattleScript_Status2FoesPrintMessage
BattleScript_PrintCoinsScattered:
printstring STRINGID_COINSSCATTERED
goto BattleScript_MoveEnd
BattleScript_EffectInfatuateSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_InfatuateSideLoop:
jumpifabsent BS_TARGET, BattleScript_InfatuateSideIncrement
trysetinfatuation BattleScript_InfatuateSideIncrement
status2animation BS_EFFECT_BATTLER, STATUS2_INFATUATION
BattleScript_InfatuateSidePrintMessage:
printfromtable gStatus2StringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_InfatuateSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_InfatuateSideEnd
setallytonexttarget BattleScript_InfatuateSideLoop
BattleScript_InfatuateSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectTormentSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_TormentSideLoop:
jumpifabsent BS_TARGET, BattleScript_TormentSideIncrement
trysettorment BattleScript_TormentSideIncrement
BattleScript_TormentSidePrintMessage:
printfromtable gStatus2StringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_TormentSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_TormentSideEnd
setallytonexttarget BattleScript_TormentSideLoop
BattleScript_TormentSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_TormentEnds::
printstring STRINGID_TORMENTEDNOMORE
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_EffectMeanLookSide::
savetarget
copybyte sBATTLER, gBattlerTarget
BattleScript_MeanLookSideLoop:
jumpifabsent BS_TARGET, BattleScript_MeanLookSideIncrement
trysetescapeprevention BattleScript_MeanLookSideIncrement
BattleScript_MeanLookSidePrintMessage:
printfromtable gStatus2StringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_MeanLookSideIncrement:
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_MeanLookSideEnd
setallytonexttarget BattleScript_MeanLookSideLoop
BattleScript_MeanLookSideEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectRaiseCritAlliesAnim::
savetarget
copybyte gBattlerTarget, gBattlerAttacker
@ -9941,12 +10039,6 @@ BattleScript_RecycleBerriesAlliesEnd:
restoretarget
goto BattleScript_MoveEnd
BattleScript_EffectStonesurge::
setstealthrock BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_EffectSteelsurge::
setsteelsurge BattleScript_MoveEnd
printfromtable gDmgHazardsStringIds

View File

@ -195,13 +195,13 @@ BattleScript_TryNicknameCaughtMon::
printstring STRINGID_GIVENICKNAMECAPTURED
waitstate
setbyte gBattleCommunication, 0
trygivecaughtmonnick BattleScript_GiveCaughtMonEnd
givecaughtmon
trygivecaughtmonnick
givecaughtmon BattleScript_SuccessBallThrowEnd
printfromtable gCaughtMonStringIds
waitmessage B_WAIT_TIME_LONG
goto BattleScript_SuccessBallThrowEnd
BattleScript_GiveCaughtMonEnd::
givecaughtmon
givecaughtmon BattleScript_SuccessBallThrowEnd
BattleScript_SuccessBallThrowEnd::
setbyte gBattleOutcome, B_OUTCOME_CAUGHT
finishturn

View File

@ -51,138 +51,60 @@ BattleFrontier_Lounge5_Text_NatureGirlNoneShown::
.string "Boo!\n"
.string "Cheapie!$"
BattleFrontier_Lounge5_Text_NatureGirlHardy::
BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "It will battle even if it has a lot\l"
.string "of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlLonely::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "But if it gets enough ouchies,\l"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlBrave::
BattleFrontier_Lounge5_Text_NatureGirlAttackHighDefenseLow::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "But if it gets enough ouchies,\l"
.string "it will worry about itself!$"
BattleFrontier_Lounge5_Text_NatureGirlAdamant::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "It will battle even if it has a lot\l"
.string "of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlNaughty::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "But if it gets enough ouchies,\l"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlBold::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "But if it gets enough ouchies,\l"
.string "it will worry about itself!$"
BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "It will battle even if it has a lot\l"
.string "of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlRelaxed::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "But if it gets enough ouchies,\l"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlImpish::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "But if it gets enough ouchies,\l"
.string "it will worry about itself!$"
BattleFrontier_Lounge5_Text_NatureGirlLax::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "It says it likes to be sneaky even\l"
.string "if it has a lot of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlTimid::
BattleFrontier_Lounge5_Text_NatureGirlAttackHighSupportLow::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "But if it gets enough ouchies,\l"
.string "it will turn sneaky!$"
BattleFrontier_Lounge5_Text_NatureGirlHasty::
BattleFrontier_Lounge5_Text_NatureGirlDefenseHighAttackLow::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "It will battle even if it has a lot\l"
.string "of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlSerious::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "It says it likes to be sneaky even\l"
.string "if it has a lot of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlJolly::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "This one says it looks after itself!\n"
.string "But if it gets enough ouchies,\l"
.string "it will worry about itself!$"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlModest::
BattleFrontier_Lounge5_Text_NatureGirlDefenseHighDefenseLow::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "It says it worries about itself whether\l"
.string "or not it has a lot of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlMild::
BattleFrontier_Lounge5_Text_NatureGirlDefenseHighSupportLow::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "But if it gets enough ouchies,\l"
.string "it will turn sneaky!$"
BattleFrontier_Lounge5_Text_NatureGirlBashful::
BattleFrontier_Lounge5_Text_NatureGirlSupportHighAttackLow::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "It says it worries about itself even\l"
.string "if it has a lot of ouchies!$"
.string "This one says it likes to be sneaky!\n"
.string "But if it gets enough ouchies,\l"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlRash::
BattleFrontier_Lounge5_Text_NatureGirlSupportHighDefenseLow::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "But if it gets enough ouchies,\l"
.string "it will worry about itself!$"
BattleFrontier_Lounge5_Text_NatureGirlSupportHighSupportLow::
.string "Hmhm…\p"
.string "This one says it likes to be sneaky!\n"
.string "It says it likes to be sneaky even\l"
.string "if it has a lot of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlCalm::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "It says it worries about itself even\l"
.string "if it has a lot of ouchies!$"
BattleFrontier_Lounge5_Text_NatureGirlGentle::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "But if it gets enough ouchies,\l"
.string "it will hit back!$"
BattleFrontier_Lounge5_Text_NatureGirlSassy::
.string "Hmhm…\p"
.string "This one says it likes to battle!\n"
.string "But if it gets enough ouchies,\l"
.string "it will turn sneaky!$"
BattleFrontier_Lounge5_Text_NatureGirlCareful::
.string "Hmhm…\p"
.string "This one says it looks after itself!\n"
.string "But if it gets enough ouchies,\l"
.string "it will turn sneaky!$"
BattleFrontier_Lounge5_Text_NatureGirlEgg::
.string "That's silly! An EGG is asleep!\n"
.string "I can't talk to it!$"

View File

@ -22,6 +22,12 @@ gText_PkmnTransferredLanettesPCBoxFull::
.string "{STR_VAR_2} was transferred to\n"
.string "BOX “{STR_VAR_1}.”$"
gText_PkmnSentToPCAfterCatch::
.string "{STR_VAR_2} was sent to\n"
.string "{B_PC_CREATOR_NAME} PC.\p"
.string "It was placed in \n"
.string "BOX “{STR_VAR_1}”.$"
gText_NoMoreRoomForPokemon::
.string "There's no more room for POKéMON!\p"
.string "The POKéMON BOXES are full and\n"

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@ -1,9 +1,15 @@
#ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H
#define GUARD_BATTLE_AI_SWITCH_ITEMS_H
enum SwitchType
{
SWITCH_AFTER_KO,
SWITCH_MID_BATTLE,
};
void GetAIPartyIndexes(u32 battlerId, s32 *firstId, s32 *lastId);
void AI_TrySwitchOrUseItem(u32 battler);
u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd);
u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType);
bool32 ShouldSwitch(u32 battler);
bool32 IsMonGrounded(u16 heldItemEffect, u32 ability, u8 type1, u8 type2);

View File

@ -3,59 +3,6 @@
#define DYNAMAX_TURNS_COUNT 3
enum MaxMoveEffect
{
MAX_EFFECT_NONE,
MAX_EFFECT_RAISE_TEAM_ATTACK,
MAX_EFFECT_RAISE_TEAM_DEFENSE,
MAX_EFFECT_RAISE_TEAM_SPEED,
MAX_EFFECT_RAISE_TEAM_SP_ATK,
MAX_EFFECT_RAISE_TEAM_SP_DEF,
MAX_EFFECT_LOWER_ATTACK,
MAX_EFFECT_LOWER_DEFENSE,
MAX_EFFECT_LOWER_SPEED,
MAX_EFFECT_LOWER_SP_ATK,
MAX_EFFECT_LOWER_SP_DEF,
MAX_EFFECT_SUN,
MAX_EFFECT_RAIN,
MAX_EFFECT_SANDSTORM,
MAX_EFFECT_HAIL,
MAX_EFFECT_MISTY_TERRAIN,
MAX_EFFECT_GRASSY_TERRAIN,
MAX_EFFECT_ELECTRIC_TERRAIN,
MAX_EFFECT_PSYCHIC_TERRAIN,
MAX_EFFECT_VINE_LASH,
MAX_EFFECT_WILDFIRE,
MAX_EFFECT_CANNONADE,
MAX_EFFECT_EFFECT_SPORE_FOES,
MAX_EFFECT_PARALYZE_FOES,
MAX_EFFECT_CONFUSE_FOES_PAY_DAY,
MAX_EFFECT_CRIT_PLUS,
MAX_EFFECT_MEAN_LOOK,
MAX_EFFECT_AURORA_VEIL,
MAX_EFFECT_INFATUATE_FOES,
MAX_EFFECT_RECYCLE_BERRIES,
MAX_EFFECT_POISON_FOES,
MAX_EFFECT_STEALTH_ROCK,
MAX_EFFECT_DEFOG,
MAX_EFFECT_POISON_PARALYZE_FOES,
MAX_EFFECT_HEAL_TEAM,
MAX_EFFECT_SPITE,
MAX_EFFECT_GRAVITY,
MAX_EFFECT_VOLCALITH,
MAX_EFFECT_SANDBLAST_FOES,
MAX_EFFECT_YAWN_FOE,
MAX_EFFECT_LOWER_EVASIVENESS_FOES,
MAX_EFFECT_AROMATHERAPY,
MAX_EFFECT_CONFUSE_FOES,
MAX_EFFECT_STEELSURGE,
MAX_EFFECT_TORMENT_FOES,
MAX_EFFECT_LOWER_SPEED_2_FOES,
MAX_EFFECT_FIRE_SPIN_FOES,
MAX_EFFECT_FIXED_POWER,
MAX_EFFECT_BYPASS_PROTECT,
};
bool32 CanDynamax(u32 battler);
bool32 IsGigantamaxed(u32 battler);
void ApplyDynamaxHPMultiplier(struct Pokemon* mon);
@ -67,12 +14,11 @@ bool32 IsMoveBlockedByMaxGuard(u32 move);
bool32 IsMoveBlockedByDynamax(u32 move);
u16 GetMaxMove(u32 battler, u32 baseMove);
u8 GetMaxMovePower(u32 move);
u32 GetMaxMovePower(u32 move);
bool32 IsMaxMove(u32 move);
void ChooseDamageNonTypesString(u8 type);
void BS_UpdateDynamax(void);
void BS_SetMaxMoveEffect(void);
void BS_SetSteelsurge(void);
void BS_TrySetStatus1(void);
void BS_TrySetStatus2(void);

View File

@ -43,8 +43,8 @@ bool32 CanParalyzeType(u8 battlerAttacker, u8 battlerTarget);
bool32 CanUseLastResort(u8 battlerId);
u32 IsFlowerVeilProtected(u32 battler);
u32 IsLeafGuardProtected(u32 battler, u32 ability);
bool32 IsShieldsDownProtected(u32 battler);
u32 IsAbilityStatusProtected(u32 battler);
bool32 IsShieldsDownProtected(u32 battler, u32 ability);
u32 IsAbilityStatusProtected(u32 battler, u32 ability);
bool32 TryResetBattlerStatChanges(u8 battler);
bool32 CanCamouflage(u8 battlerId);
u32 GetNaturePowerMove(u32 battler);

View File

@ -546,8 +546,14 @@ extern const u8 BattleScript_EffectAuroraVeilSuccess[];
extern const u8 BattleScript_EffectGravitySuccess[];
extern const u8 BattleScript_EffectYawnSuccess[];
extern const u8 BattleScript_EffectTryReducePP[];
extern const u8 BattleScript_EffectStatus1Foes[];
extern const u8 BattleScript_EffectStatus2Foes[];
extern const u8 BattleScript_EffectParalyzeSide[];
extern const u8 BattleScript_EffectPoisonSide[];
extern const u8 BattleScript_EffectPoisonParalyzeSide[];
extern const u8 BattleScript_EffectEffectSporeSide[];
extern const u8 BattleScript_EffectConfuseSide[];
extern const u8 BattleScript_EffectInfatuateSide[];
extern const u8 BattleScript_EffectTormentSide[];
extern const u8 BattleScript_EffectMeanLookSide[];
extern const u8 BattleScript_TormentEnds[];
extern const u8 BattleScript_EffectRaiseCritAlliesAnim[];
extern const u8 BattleScript_EffectHealOneSixthAllies[];

View File

@ -22,13 +22,10 @@
#define MOVE_LIMITATION_PLACEHOLDER (1 << 15)
#define MOVE_LIMITATIONS_ALL 0xFFFF
enum MoveBlocked
enum AbilityEffectOptions
{
MOVE_BLOCKED_BY_NO_ABILITY,
MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF,
MOVE_BLOCKED_BY_DAZZLING,
MOVE_BLOCKED_BY_PARTNER_DAZZLING,
MOVE_BLOCKED_BY_GOOD_AS_GOLD,
ABILITY_CHECK_TRIGGER,
ABILITY_RUN_SCRIPT,
};
enum MoveAbsorbed
@ -217,9 +214,8 @@ u32 AtkCanceller_MoveSuccessOrder(void);
void SetAtkCancellerForCalledMove(void);
bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2);
bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility);
u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef);
u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef);
u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType);
bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef, enum AbilityEffectOptions option);
bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option);
u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg);
bool32 TryPrimalReversion(u32 battler);
bool32 IsNeutralizingGasOnField(void);

View File

@ -250,6 +250,8 @@
#define B_LAST_USED_BALL TRUE // If TRUE, the "last used ball" feature from Gen 7 will be implemented
#define B_LAST_USED_BALL_BUTTON R_BUTTON // If last used ball is implemented, this button (or button combo) will trigger throwing the last used ball.
#define B_LAST_USED_BALL_CYCLE TRUE // If TRUE, then holding B_LAST_USED_BALL_BUTTON while pressing the D-Pad cycles through the balls
#define B_CATCH_SWAP_INTO_PARTY GEN_LATEST // In Gen 7+, the option to swap the caught wild mon to the party will appear, allowing you to send a different mon to the box.
#define B_CATCH_SWAP_CHECK_HMS TRUE // If TRUE, the catch swap feature above will prevent returning mons to the box if they know HMs.
// Other settings
#define B_DOUBLE_WILD_CHANCE 0 // % chance of encountering two Pokémon in a Wild Encounter.

View File

@ -322,102 +322,150 @@ enum BattleWeather
#define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG)
#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS)
// Move Effects
#define MOVE_EFFECT_SLEEP 1
#define MOVE_EFFECT_POISON 2
#define MOVE_EFFECT_BURN 3
#define MOVE_EFFECT_FREEZE 4
#define MOVE_EFFECT_PARALYSIS 5
#define MOVE_EFFECT_TOXIC 6
#define MOVE_EFFECT_FROSTBITE 7
enum MoveEffects
{
MOVE_EFFECT_NONE,
MOVE_EFFECT_SLEEP,
MOVE_EFFECT_POISON,
MOVE_EFFECT_BURN,
MOVE_EFFECT_FREEZE,
MOVE_EFFECT_PARALYSIS,
MOVE_EFFECT_TOXIC,
MOVE_EFFECT_FROSTBITE,
MOVE_EFFECT_CONFUSION,
MOVE_EFFECT_FLINCH,
MOVE_EFFECT_TRI_ATTACK,
MOVE_EFFECT_UPROAR,
MOVE_EFFECT_PAYDAY,
MOVE_EFFECT_CHARGING,
MOVE_EFFECT_WRAP,
MOVE_EFFECT_ATK_PLUS_1,
MOVE_EFFECT_DEF_PLUS_1,
MOVE_EFFECT_SPD_PLUS_1,
MOVE_EFFECT_SP_ATK_PLUS_1,
MOVE_EFFECT_SP_DEF_PLUS_1,
MOVE_EFFECT_ACC_PLUS_1,
MOVE_EFFECT_EVS_PLUS_1,
MOVE_EFFECT_ATK_MINUS_1,
MOVE_EFFECT_DEF_MINUS_1,
MOVE_EFFECT_SPD_MINUS_1,
MOVE_EFFECT_SP_ATK_MINUS_1,
MOVE_EFFECT_SP_DEF_MINUS_1,
MOVE_EFFECT_ACC_MINUS_1,
MOVE_EFFECT_EVS_MINUS_1,
MOVE_EFFECT_REMOVE_ARG_TYPE,
MOVE_EFFECT_RECHARGE,
MOVE_EFFECT_RAGE,
MOVE_EFFECT_STEAL_ITEM,
MOVE_EFFECT_PREVENT_ESCAPE,
MOVE_EFFECT_NIGHTMARE,
MOVE_EFFECT_ALL_STATS_UP,
MOVE_EFFECT_REMOVE_STATUS,
MOVE_EFFECT_ATK_DEF_DOWN,
MOVE_EFFECT_ATK_PLUS_2,
MOVE_EFFECT_DEF_PLUS_2,
MOVE_EFFECT_SPD_PLUS_2,
MOVE_EFFECT_SP_ATK_PLUS_2,
MOVE_EFFECT_SP_DEF_PLUS_2,
MOVE_EFFECT_ACC_PLUS_2,
MOVE_EFFECT_EVS_PLUS_2,
MOVE_EFFECT_ATK_MINUS_2,
MOVE_EFFECT_DEF_MINUS_2,
MOVE_EFFECT_SPD_MINUS_2,
MOVE_EFFECT_SP_ATK_MINUS_2,
MOVE_EFFECT_SP_DEF_MINUS_2,
MOVE_EFFECT_ACC_MINUS_2,
MOVE_EFFECT_EVS_MINUS_2,
MOVE_EFFECT_SCALE_SHOT,
MOVE_EFFECT_THRASH,
MOVE_EFFECT_KNOCK_OFF,
MOVE_EFFECT_DEF_SPDEF_DOWN,
MOVE_EFFECT_CLEAR_SMOG,
MOVE_EFFECT_SMACK_DOWN,
MOVE_EFFECT_FLAME_BURST,
MOVE_EFFECT_FEINT,
MOVE_EFFECT_SPECTRAL_THIEF,
MOVE_EFFECT_V_CREATE,
MOVE_EFFECT_HAPPY_HOUR,
MOVE_EFFECT_CORE_ENFORCER,
MOVE_EFFECT_THROAT_CHOP,
MOVE_EFFECT_INCINERATE,
MOVE_EFFECT_BUG_BITE,
MOVE_EFFECT_RECOIL_HP_25,
MOVE_EFFECT_TRAP_BOTH,
MOVE_EFFECT_ROUND,
MOVE_EFFECT_STOCKPILE_WORE_OFF,
MOVE_EFFECT_DIRE_CLAW,
MOVE_EFFECT_STEALTH_ROCK,
MOVE_EFFECT_SPIKES,
MOVE_EFFECT_SYRUP_BOMB,
MOVE_EFFECT_FLORAL_HEALING,
MOVE_EFFECT_SECRET_POWER,
MOVE_EFFECT_PSYCHIC_NOISE,
MOVE_EFFECT_TERA_BLAST,
MOVE_EFFECT_ORDER_UP,
MOVE_EFFECT_ION_DELUGE,
MOVE_EFFECT_HAZE,
MOVE_EFFECT_LEECH_SEED,
MOVE_EFFECT_REFLECT,
MOVE_EFFECT_LIGHT_SCREEN,
MOVE_EFFECT_SALT_CURE,
MOVE_EFFECT_EERIE_SPELL,
MOVE_EFFECT_RAISE_TEAM_ATTACK,
MOVE_EFFECT_RAISE_TEAM_DEFENSE,
MOVE_EFFECT_RAISE_TEAM_SPEED,
MOVE_EFFECT_RAISE_TEAM_SP_ATK,
MOVE_EFFECT_RAISE_TEAM_SP_DEF,
MOVE_EFFECT_LOWER_ATTACK_SIDE,
MOVE_EFFECT_LOWER_DEFENSE_SIDE,
MOVE_EFFECT_LOWER_SPEED_SIDE,
MOVE_EFFECT_LOWER_SP_ATK_SIDE,
MOVE_EFFECT_LOWER_SP_DEF_SIDE,
MOVE_EFFECT_SUN,
MOVE_EFFECT_RAIN,
MOVE_EFFECT_SANDSTORM,
MOVE_EFFECT_HAIL,
MOVE_EFFECT_MISTY_TERRAIN,
MOVE_EFFECT_GRASSY_TERRAIN,
MOVE_EFFECT_ELECTRIC_TERRAIN,
MOVE_EFFECT_PSYCHIC_TERRAIN,
MOVE_EFFECT_VINE_LASH,
MOVE_EFFECT_WILDFIRE,
MOVE_EFFECT_CANNONADE,
MOVE_EFFECT_EFFECT_SPORE_SIDE,
MOVE_EFFECT_PARALYZE_SIDE,
MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE,
MOVE_EFFECT_CRIT_PLUS_SIDE,
MOVE_EFFECT_PREVENT_ESCAPE_SIDE,
MOVE_EFFECT_AURORA_VEIL,
MOVE_EFFECT_INFATUATE_SIDE,
MOVE_EFFECT_RECYCLE_BERRIES,
MOVE_EFFECT_POISON_SIDE,
MOVE_EFFECT_DEFOG,
MOVE_EFFECT_POISON_PARALYZE_SIDE,
MOVE_EFFECT_HEAL_TEAM,
MOVE_EFFECT_SPITE,
MOVE_EFFECT_GRAVITY,
MOVE_EFFECT_VOLCALITH,
MOVE_EFFECT_SANDBLAST_SIDE,
MOVE_EFFECT_YAWN_FOE,
MOVE_EFFECT_LOWER_EVASIVENESS_SIDE,
MOVE_EFFECT_AROMATHERAPY,
MOVE_EFFECT_CONFUSE_SIDE,
MOVE_EFFECT_STEELSURGE,
MOVE_EFFECT_TORMENT_SIDE,
MOVE_EFFECT_LOWER_SPEED_2_SIDE,
MOVE_EFFECT_FIRE_SPIN_SIDE,
MOVE_EFFECT_FIXED_POWER,
NUM_MOVE_EFFECTS
};
#define PRIMARY_STATUS_MOVE_EFFECT MOVE_EFFECT_FROSTBITE // All above move effects apply primary status
#if B_USE_FROSTBITE == TRUE
#define MOVE_EFFECT_FREEZE_OR_FROSTBITE MOVE_EFFECT_FROSTBITE
#else
#define MOVE_EFFECT_FREEZE_OR_FROSTBITE MOVE_EFFECT_FREEZE
#endif
#define MOVE_EFFECT_CONFUSION 8
#define MOVE_EFFECT_FLINCH 9
#define MOVE_EFFECT_TRI_ATTACK 10
#define MOVE_EFFECT_UPROAR 11
#define MOVE_EFFECT_PAYDAY 12
#define MOVE_EFFECT_CHARGING 13
#define MOVE_EFFECT_WRAP 14
#define MOVE_EFFECT_ATK_PLUS_1 15
#define MOVE_EFFECT_DEF_PLUS_1 16
#define MOVE_EFFECT_SPD_PLUS_1 17
#define MOVE_EFFECT_SP_ATK_PLUS_1 18
#define MOVE_EFFECT_SP_DEF_PLUS_1 19
#define MOVE_EFFECT_ACC_PLUS_1 20
#define MOVE_EFFECT_EVS_PLUS_1 21
#define MOVE_EFFECT_ATK_MINUS_1 22
#define MOVE_EFFECT_DEF_MINUS_1 23
#define MOVE_EFFECT_SPD_MINUS_1 24
#define MOVE_EFFECT_SP_ATK_MINUS_1 25
#define MOVE_EFFECT_SP_DEF_MINUS_1 26
#define MOVE_EFFECT_ACC_MINUS_1 27
#define MOVE_EFFECT_EVS_MINUS_1 28
#define MOVE_EFFECT_REMOVE_ARG_TYPE 29
#define MOVE_EFFECT_RECHARGE 30
#define MOVE_EFFECT_RAGE 31
#define MOVE_EFFECT_STEAL_ITEM 32
#define MOVE_EFFECT_PREVENT_ESCAPE 33
#define MOVE_EFFECT_NIGHTMARE 34
#define MOVE_EFFECT_ALL_STATS_UP 35
#define MOVE_EFFECT_REMOVE_STATUS 36
#define MOVE_EFFECT_ATK_DEF_DOWN 37
#define MOVE_EFFECT_ATK_PLUS_2 38
#define MOVE_EFFECT_DEF_PLUS_2 39
#define MOVE_EFFECT_SPD_PLUS_2 40
#define MOVE_EFFECT_SP_ATK_PLUS_2 41
#define MOVE_EFFECT_SP_DEF_PLUS_2 42
#define MOVE_EFFECT_ACC_PLUS_2 43
#define MOVE_EFFECT_EVS_PLUS_2 44
#define MOVE_EFFECT_ATK_MINUS_2 45
#define MOVE_EFFECT_DEF_MINUS_2 46
#define MOVE_EFFECT_SPD_MINUS_2 47
#define MOVE_EFFECT_SP_ATK_MINUS_2 48
#define MOVE_EFFECT_SP_DEF_MINUS_2 49
#define MOVE_EFFECT_ACC_MINUS_2 50
#define MOVE_EFFECT_EVS_MINUS_2 51
#define MOVE_EFFECT_SCALE_SHOT 52
#define MOVE_EFFECT_THRASH 53
#define MOVE_EFFECT_KNOCK_OFF 54
#define MOVE_EFFECT_DEF_SPDEF_DOWN 55
#define MOVE_EFFECT_CLEAR_SMOG 56
#define MOVE_EFFECT_SMACK_DOWN 57
#define MOVE_EFFECT_FLAME_BURST 58
#define MOVE_EFFECT_FEINT 59
#define MOVE_EFFECT_SPECTRAL_THIEF 60
#define MOVE_EFFECT_V_CREATE 61
#define MOVE_EFFECT_HAPPY_HOUR 62
#define MOVE_EFFECT_CORE_ENFORCER 63
#define MOVE_EFFECT_THROAT_CHOP 64
#define MOVE_EFFECT_INCINERATE 65
#define MOVE_EFFECT_BUG_BITE 66
#define MOVE_EFFECT_RECOIL_HP_25 67
#define MOVE_EFFECT_TRAP_BOTH 68
#define MOVE_EFFECT_ROUND 69
#define MOVE_EFFECT_STOCKPILE_WORE_OFF 70
#define MOVE_EFFECT_DIRE_CLAW 71
#define MOVE_EFFECT_STEALTH_ROCK 72
#define MOVE_EFFECT_SPIKES 73
#define MOVE_EFFECT_SYRUP_BOMB 74
#define MOVE_EFFECT_FLORAL_HEALING 75
#define MOVE_EFFECT_SECRET_POWER 76
#define MOVE_EFFECT_PSYCHIC_NOISE 77
#define MOVE_EFFECT_TERA_BLAST 78
#define MOVE_EFFECT_ORDER_UP 79
#define MOVE_EFFECT_ION_DELUGE 80
#define MOVE_EFFECT_AROMATHERAPY 81 // No functionality yet
#define MOVE_EFFECT_HAZE 82
#define MOVE_EFFECT_LEECH_SEED 83
#define MOVE_EFFECT_REFLECT 84
#define MOVE_EFFECT_LIGHT_SCREEN 85
#define MOVE_EFFECT_SALT_CURE 86
#define MOVE_EFFECT_EERIE_SPELL 87
#define NUM_MOVE_EFFECTS 88
#define MOVE_EFFECT_AFFECTS_USER 0x2000
#define MOVE_EFFECT_CERTAIN 0x4000

View File

@ -418,6 +418,7 @@
#define ANIM_TAG_PURPLE_CHAIN (ANIM_SPRITES_START + 404)
#define ANIM_TAG_PINKVIO_ORB (ANIM_SPRITES_START + 405)
#define ANIM_TAG_STARSTORM (ANIM_SPRITES_START + 406)
#define ANIM_TAG_SALT_PARTICLE (ANIM_SPRITES_START + 407)
// battlers
#define ANIM_ATTACKER 0

View File

@ -727,8 +727,10 @@
#define STRINGID_SUPEREFFECTIVETWOFOES 725
#define STRINGID_NOTVERYEFFECTIVETWOFOES 726
#define STRINGID_ITDOESNTAFFECTTWOFOES 727
#define STRINGID_SENDCAUGHTMONPARTYORBOX 728
#define STRINGID_PKMNSENTTOPCAFTERCATCH 729
#define BATTLESTRINGS_COUNT 728
#define BATTLESTRINGS_COUNT 730
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -892,10 +894,12 @@
#define B_MSG_WEAKEN_FIRE 1
// gCaughtMonStringIds
#define B_MSG_SENT_SOMEONES_PC 0
#define B_MSG_SENT_LANETTES_PC 1
#define B_MSG_SOMEONES_BOX_FULL 2
#define B_MSG_LANETTES_BOX_FULL 3
#define B_MSG_NO_MESSSAGE_SKIP 0
#define B_MSG_SENT_SOMEONES_PC 1
#define B_MSG_SENT_LANETTES_PC 2
#define B_MSG_SOMEONES_BOX_FULL 3
#define B_MSG_LANETTES_BOX_FULL 4
#define B_MSG_SWAPPED_INTO_PARTY 5
// gPrimalWeatherBlocksStringIds
#define B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN 0

View File

@ -270,19 +270,23 @@
#define OBJ_EVENT_GFX_VAR_E (OBJ_EVENT_GFX_VARS + 0xE)
#define OBJ_EVENT_GFX_VAR_F (OBJ_EVENT_GFX_VARS + 0xF)
#define OBJ_EVENT_GFX_MON_BASE 0x200 // 512
#define OBJ_EVENT_GFX_SPECIES_BITS 12 // This will need to be updated when NUM_SPECIES is > ~3.5k
#define OBJ_EVENT_GFX_SPECIES_MASK ((1 << OBJ_EVENT_GFX_SPECIES_BITS) - 1)
#define OBJ_EVENT_MON (1 << 13)
#define OBJ_EVENT_MON_SHINY (1 << 14)
#define OBJ_EVENT_MON_FEMALE (1 << 15)
#define OBJ_EVENT_MON_SPECIES_MASK (OBJ_EVENT_MON - 1)
// Used to call a specific species' follower graphics. Useful for static encounters.
#define OBJ_EVENT_GFX_SPECIES(name) (SPECIES_##name + OBJ_EVENT_GFX_MON_BASE)
#define OBJ_EVENT_GFX_SPECIES_SHINY(name) (SPECIES_##name + OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG)
#define OBJ_EVENT_GFX_SPECIES(name) (SPECIES_##name + OBJ_EVENT_MON)
#define OBJ_EVENT_GFX_SPECIES_SHINY(name) (SPECIES_##name + OBJ_EVENT_MON + OBJ_EVENT_MON_SHINY)
#define OBJ_EVENT_GFX_SPECIES_FEMALE(name) (SPECIES_##name + OBJ_EVENT_MON + OBJ_EVENT_MON_FEMALE)
#define OBJ_EVENT_GFX_SPECIES_SHINY_FEMALE(name) (SPECIES_##name + OBJ_EVENT_MON + OBJ_EVENT_MON_SHINY + OBJ_EVENT_MON_FEMALE)
#define OW_SPECIES(x) (((x)->graphicsId & OBJ_EVENT_GFX_SPECIES_MASK) - OBJ_EVENT_GFX_MON_BASE)
#define OW_FORM(x) ((x)->graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS)
#define OW_SPECIES(x) ((x)->graphicsId & OBJ_EVENT_MON_SPECIES_MASK)
#define OW_SHINY(x) ((x)->graphicsId & OBJ_EVENT_MON_SHINY)
#define OW_FEMALE(x) ((x)->graphicsId & OBJ_EVENT_MON_FEMALE)
// Whether Object Event is an OW pokemon
#define IS_OW_MON_OBJ(obj) ((obj)->graphicsId >= OBJ_EVENT_GFX_MON_BASE)
#define IS_OW_MON_OBJ(obj) ((obj)->graphicsId & OBJ_EVENT_MON)
#define SHADOW_SIZE_S 0
#define SHADOW_SIZE_M 1

View File

@ -48,7 +48,7 @@
#define PARTY_ACTION_CHOOSE_AND_CLOSE 11
#define PARTY_ACTION_MOVE_TUTOR 12
#define PARTY_ACTION_MINIGAME 13
#define PARTY_ACTION_REUSABLE_ITEM 14 // Unused. The only reusable items are handled separately
#define PARTY_ACTION_SEND_MON_TO_BOX 14
#define PARTY_ACTION_CHOOSE_FAINTED_MON 15
// IDs for DisplayPartyMenuStdMessage, to display the message at the bottom of the party menu
@ -82,6 +82,8 @@
#define PARTY_MSG_WHICH_APPLIANCE 27
#define PARTY_MSG_CHOOSE_SECOND_FUSION 28
#define PARTY_MSG_NO_POKEMON 29
#define PARTY_MSG_CHOOSE_MON_FOR_BOX 30
#define PARTY_MSG_NONE 127
// IDs for DisplayPartyPokemonDescriptionText, to display a message in the party pokemon's box

View File

@ -0,0 +1,21 @@
#ifndef GUARD_CONSTANTS_REGIONS_H
#define GUARD_CONSTANTS_REGIONS_H
// Core-series regions
enum Region
{
REGION_NONE,
REGION_KANTO,
REGION_JOHTO,
REGION_HOENN,
REGION_SINNOH,
REGION_UNOVA,
REGION_KALOS,
REGION_ALOLA,
REGION_GALAR,
REGION_HISUI,
REGION_PALDEA,
REGIONS_COUNT,
};
#endif // GUARD_CONSTANTS_REGIONS_H

View File

@ -13,6 +13,7 @@ enum ComparisonOperators
enum TrainerSlideType
{
TRAINER_SLIDE_NONE,
TRAINER_SLIDE_BEFORE_FIRST_TURN,
TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT,
TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT,

View File

@ -34,6 +34,7 @@ void ShowDaycareLevelMenu(void);
void ChooseSendDaycareMon(void);
u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves);
bool8 SpeciesCanLearnEggMove(u16 species, u16 move);
void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon);
u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves);
#endif // GUARD_DAYCARE_H

View File

@ -107,13 +107,6 @@ struct LockedAnimObjectEvents
u8 count;
};
struct FollowerSpriteVisualizerData
{
u16 currentmonId;
bool8 isShiny;
bool8 isFemale;
};
extern const struct OamData gObjectEventBaseOam_32x8;
extern const struct OamData gObjectEventBaseOam_32x32;
extern const struct OamData gObjectEventBaseOam_64x64;
@ -154,7 +147,6 @@ void RemoveFollowingPokemon(void);
struct ObjectEvent *GetFollowerObject(void);
void TrySpawnObjectEvents(s16 cameraX, s16 cameraY);
u8 CreateObjectGraphicsSprite(u16, void (*)(struct Sprite *), s16 x, s16 y, u8 subpriority);
u8 CreateObjectGraphicsFollowerSpriteForVisualizer(u16, void (*)(struct Sprite *), s16 x, s16 y, u8 subpriority, struct FollowerSpriteVisualizerData *data);
u8 TrySpawnObjectEvent(u8 localId, u8 mapNum, u8 mapGroup);
u8 SpawnSpecialObjectEventParameterized(u16 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 elevation);
u8 SpawnSpecialObjectEvent(struct ObjectEventTemplate *);

View File

@ -2895,6 +2895,8 @@ extern const u32 gBattleAnimSpriteGfx_PinkVioletOrb[];
extern const u32 gBattleAnimSpritePal_PinkVioletOrb[];
extern const u32 gBattleAnimSpriteGfx_TeraStarstormBeam[];
extern const u32 gBattleAnimSpritePal_TeraStarstormBeam[];
extern const u32 gBattleAnimSpriteGfx_SaltParticle[];
extern const u32 gBattleAnimSpritePal_SaltParticle[];
extern const u32 gBattleAnimBgImage_Dark[];
extern const u32 gBattleAnimBgImage_Ghost[];

View File

@ -122,7 +122,6 @@ struct MoveInfo
u16 type;
u16 fixedDamage;
u16 absorbPercentage;
u16 maxEffect;
} argument;
// primary/secondary effects
@ -489,11 +488,6 @@ static inline u32 GetMoveAbsorbPercentage(u32 moveId)
return gMovesInfo[moveId].argument.absorbPercentage;
}
static inline u32 GetMoveMaxEffect(u32 moveId)
{
return gMovesInfo[SanitizeMoveId(moveId)].argument.maxEffect;
}
static inline const struct AdditionalEffect *GetMoveAdditionalEffectById(u32 moveId, u32 effect)
{
return &gMovesInfo[SanitizeMoveId(moveId)].additionalEffects[effect];

View File

@ -12,6 +12,8 @@ enum {
NAMING_SCREEN_CODE,
};
extern void BattleMainCB2(void);
void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGender, u32 monPersonality, MainCallback returnCallback);
#endif // GUARD_NAMING_SCREEN_H

View File

@ -3,6 +3,7 @@
#include "sprite.h"
#include "constants/items.h"
#include "constants/regions.h"
#include "constants/region_map_sections.h"
#include "constants/map_groups.h"
#include "contest_effect.h"
@ -806,5 +807,7 @@ void UpdateDaysPassedSinceFormChange(u16 days);
void TrySetDayLimitToFormChange(struct Pokemon *mon);
u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler);
uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier);
u32 GetRegionalFormByRegion(u32 species, u32 region);
bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion);
#endif // GUARD_POKEMON_H

View File

@ -30,7 +30,7 @@ struct Sfc32State {
typedef struct Sfc32State rng_value_t;
#define RNG_VALUE_EMPTY {}
#define RNG_VALUE_EMPTY {0}
// Calling this function directly is discouraged.
// Use LocalRandom() instead.
@ -43,9 +43,14 @@ static inline u32 _SFC32_Next(struct Sfc32State *state)
return result;
}
static inline u32 LocalRandom32(rng_value_t *val)
{
return _SFC32_Next(val);
}
static inline u16 LocalRandom(rng_value_t *val)
{
return _SFC32_Next(val) >> 16;
return LocalRandom32(val) >> 16;
}
u32 Random32(void);

12
include/regions.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef GUARD_REGIONS_H
#define GUARD_REGIONS_H
#include "constants/regions.h"
static inline u32 GetCurrentRegion(void)
{
// TODO: Since there's no current multi-region support, we have this constant for the purposes of regional form comparisons.
return REGION_HOENN;
}
#endif // GUARD_REGIONS_H

View File

@ -553,28 +553,15 @@ extern const u8 BattleFrontier_Lounge2_Text_PyramidKingSilverMons[];
extern const u8 BattleFrontier_Lounge2_Text_PyramidKingGoldMons[];
// Battle Frontier Nature Girl
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlHardy[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlLonely[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlBrave[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlAdamant[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlNaughty[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlBold[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlRelaxed[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlImpish[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlLax[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlTimid[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlHasty[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlSerious[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlJolly[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlModest[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlMild[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlBashful[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlRash[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlCalm[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlGentle[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlSassy[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlCareful[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlAttackHighDefenseLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlAttackHighSupportLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlDefenseHighAttackLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlDefenseHighDefenseLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlDefenseHighSupportLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlSupportHighAttackLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlSupportHighDefenseLow[];
extern const u8 BattleFrontier_Lounge5_Text_NatureGirlSupportHighSupportLow[];
// Battle Frontier Gambler
extern const u8 BattleFrontier_Lounge3_Text_ChallengeBattleTowerSingle[];
@ -1551,6 +1538,7 @@ extern const u8 gText_PkmnTransferredSomeonesPCBoxFull[];
extern const u8 gText_PkmnTransferredLanettesPCBoxFull[];
extern const u8 gText_PkmnTransferredSomeonesPC[];
extern const u8 gText_PkmnTransferredLanettesPC[];
extern const u8 gText_PkmnSentToPCAfterCatch[];
// hall of fame
extern const u8 gText_LeagueChamp[];
@ -1584,6 +1572,7 @@ extern const u8 gDaycareText_PlayOther[];
extern const u8 gText_ChoosePokemon[];
extern const u8 gText_ChoosePokemonCancel[];
extern const u8 gText_ChoosePokemonConfirm[];
extern const u8 gText_SendWhichMonToPC[];
extern const u8 gText_MoveToWhere[];
extern const u8 gText_TeachWhichPokemon[];
extern const u8 gText_UseOnWhichPokemon[];
@ -2429,4 +2418,7 @@ extern const u8 gText_PlayerScurriedBackHome[];
extern const u8 gText_Relearn[]; // move relearner from summary screen
extern const u8 gText_Rename[]; // change nickname from summary screen
// Switch Caught Mon into Party
extern const u8 gText_CannotSendMonToBoxHM[];
#endif // GUARD_STRINGS_H

View File

@ -893,10 +893,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
// target ability checks
if (!DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
{
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef]))
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef], FALSE))
RETURN_SCORE_MINUS(20);
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType))
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType, FALSE))
RETURN_SCORE_MINUS(20);
switch (aiData->abilities[battlerDef])
@ -983,7 +983,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
RETURN_SCORE_MINUS(10);
break;
case ABILITY_SHIELDS_DOWN:
if (IsShieldsDownProtected(battlerAtk) && IsNonVolatileStatusMoveEffect(moveEffect))
if (IsShieldsDownProtected(battlerAtk, aiData->abilities[battlerAtk]) && IsNonVolatileStatusMoveEffect(moveEffect))
RETURN_SCORE_MINUS(10);
break;
case ABILITY_LEAF_GUARD:
@ -997,9 +997,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
// target partner ability checks & not attacking partner
if (isDoubleBattle)
{
if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)]))
RETURN_SCORE_MINUS(20);
switch (aiData->abilities[BATTLE_PARTNER(battlerDef)])
{
case ABILITY_LIGHTNING_ROD:

View File

@ -875,7 +875,7 @@ static bool32 ShouldSwitchIfBadChoiceLock(u32 battler)
if (HOLD_EFFECT_CHOICE(holdEffect) && gBattleMons[battler].ability != ABILITY_KLUTZ)
{
if (GetMoveCategory(gLastUsedMove) == DAMAGE_CATEGORY_STATUS)
if (GetMoveCategory(AI_DATA->lastUsedMove[battler]) == DAMAGE_CATEGORY_STATUS)
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
}
@ -1312,9 +1312,9 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon
&& ability != ABILITY_IMMUNITY && ability != ABILITY_POISON_HEAL && ability != ABILITY_COMATOSE
&& status == 0
&& !(hazardFlags & SIDE_STATUS_SAFEGUARD)
&& !(IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL))
&& !(IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN))
&& !(IsAbilityStatusProtected(battler))
&& !IsAbilityOnSide(battler, ABILITY_PASTEL_VEIL)
&& !IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)
&& !IsAbilityStatusProtected(battler, ability)
&& heldItemEffect != HOLD_EFFECT_CURE_PSN && heldItemEffect != HOLD_EFFECT_CURE_STATUS
&& IsMonGrounded(heldItemEffect, ability, defType1, defType2)))
{
@ -1732,7 +1732,7 @@ static bool32 CanAbilityTrapOpponent(u16 ability, u32 opponent)
return FALSE;
}
static inline bool32 IsFreeSwitch(bool32 isSwitchAfterKO, u32 battlerSwitchingOut, u32 opposingBattler)
static inline bool32 IsFreeSwitch(enum SwitchType switchType, u32 battlerSwitchingOut, u32 opposingBattler)
{
bool32 movedSecond = GetBattlerTurnOrderNum(battlerSwitchingOut) > GetBattlerTurnOrderNum(opposingBattler) ? TRUE : FALSE;
@ -1755,7 +1755,7 @@ static inline bool32 IsFreeSwitch(bool32 isSwitchAfterKO, u32 battlerSwitchingOu
}
// Post KO check has to be last because the GetMostSuitableMonToSwitchInto call in OpponentHandleChoosePokemon assumes a KO rather than a forced switch choice
if (isSwitchAfterKO)
if (switchType == SWITCH_AFTER_KO)
return TRUE;
else
return FALSE;
@ -1777,7 +1777,7 @@ static inline bool32 CanSwitchinWin1v1(u32 hitsToKOAI, u32 hitsToKOPlayer, bool3
// This function splits switching behaviour depending on whether the switch is free.
// Everything runs in the same loop to minimize computation time. This makes it harder to read, but hopefully the comments can guide you!
static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, bool32 isSwitchAfterKO)
static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, u32 battler, u32 opposingBattler, u32 battlerIn1, u32 battlerIn2, enum SwitchType switchType)
{
int revengeKillerId = PARTY_SIZE, slowRevengeKillerId = PARTY_SIZE, fastThreatenId = PARTY_SIZE, slowThreatenId = PARTY_SIZE, damageMonId = PARTY_SIZE;
int batonPassId = PARTY_SIZE, typeMatchupId = PARTY_SIZE, typeMatchupEffectiveId = PARTY_SIZE, defensiveMonId = PARTY_SIZE, aceMonId = PARTY_SIZE, trapperId = PARTY_SIZE;
@ -1786,7 +1786,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
s32 playerMonHP = gBattleMons[opposingBattler].hp, maxDamageDealt = 0, damageDealt = 0;
u32 aiMove, hitsToKOAI, maxHitsToKO = 0;
u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup;
bool32 isFreeSwitch = IsFreeSwitch(isSwitchAfterKO, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1;
bool32 isFreeSwitch = IsFreeSwitch(switchType, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1;
// Iterate through mons
for (i = firstId; i < lastId; i++)
@ -1979,7 +1979,7 @@ static u32 GetNextMonInParty(struct Pokemon *party, int firstId, int lastId, u32
return PARTY_SIZE;
}
u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType)
{
u32 opposingBattler = 0;
u32 bestMonId = PARTY_SIZE;
@ -2024,7 +2024,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd)
// Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer.
if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic
{
bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchAfterMonKOd);
bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchType);
return bestMonId;
}

View File

@ -424,18 +424,11 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
{
struct AiLogicData *aiData = AI_DATA;
u32 battlerDefAbility;
u32 partnerBattlerDefAbility;
if (DoesBattlerIgnoreAbilityChecks(battlerAtk, aiData->abilities[battlerAtk], move))
{
battlerDefAbility = ABILITY_NONE;
partnerBattlerDefAbility = ABILITY_NONE;
}
else
{
battlerDefAbility = aiData->abilities[battlerDef];
partnerBattlerDefAbility = aiData->abilities[BATTLE_PARTNER(battlerDef)];
}
if (battlerDef == BATTLE_PARTNER(battlerAtk))
battlerDefAbility = aiData->abilities[battlerDef];
@ -443,13 +436,10 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy
if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
return TRUE;
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef]))
if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef], FALSE))
return TRUE;
if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, partnerBattlerDefAbility))
return TRUE;
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType))
if (CanAbilityAbsorbMove(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, moveType, FALSE))
return TRUE;
switch (GetMoveEffect(move))
@ -2403,8 +2393,8 @@ static inline bool32 IsMoveSleepClauseTrigger(u32 move)
switch (additionalEffect->moveEffect)
{
// Skip MOVE_EFFECT_SLEEP as moves with a secondary chance of applying sleep are allowed by Smogon's rules (ie. Relic Song)
case MAX_EFFECT_EFFECT_SPORE_FOES:
case MAX_EFFECT_YAWN_FOE:
case MOVE_EFFECT_EFFECT_SPORE_SIDE:
case MOVE_EFFECT_YAWN_FOE:
return TRUE;
}
}
@ -2699,19 +2689,9 @@ static bool32 AnyUsefulStatIsRaised(u32 battler)
return FALSE;
}
struct Pokemon *GetPartyBattlerPartyData(u32 battlerId, u32 switchBattler)
{
struct Pokemon *mon;
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
mon = &gPlayerParty[switchBattler];
else
mon = &gEnemyParty[switchBattler];
return mon;
}
static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler)
{
struct Pokemon *mon = GetPartyBattlerPartyData(currBattler, switchBattler);
struct Pokemon *mon = &GetBattlerParty(currBattler)[switchBattler];
u32 ability = GetMonAbility(mon); // we know our own party data
u32 holdEffect;
u32 species = GetMonData(mon, MON_DATA_SPECIES);
@ -3041,7 +3021,7 @@ bool32 AI_CanGetFrostbite(u32 battler, u32 ability)
|| ability == ABILITY_COMATOSE
|| IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD)
return FALSE;
return TRUE;

View File

@ -370,12 +370,7 @@ void LaunchBattleAnimation(u32 animType, u32 animId)
InitPrioritiesForVisibleBattlers();
UpdateOamPriorityInAllHealthboxes(0, sAnimHideHpBoxes);
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (GetBattlerSide(i) != B_SIDE_PLAYER)
gAnimBattlerSpecies[i] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
else
gAnimBattlerSpecies[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
}
gAnimBattlerSpecies[i] = GetMonData(GetPartyBattlerData(i), MON_DATA_SPECIES);
}
else
{

View File

@ -932,16 +932,9 @@ void AnimTask_MetallicShine(u8 taskId)
}
if (IsContest())
{
species = gContestResources->moveAnim->species;
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
}
species = GetMonData(GetPartyBattlerData(gBattleAnimAttacker), MON_DATA_SPECIES);
spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
newSpriteId = CreateInvisibleSpriteCopy(gBattleAnimAttacker, spriteId, species);

View File

@ -3417,51 +3417,24 @@ void AnimTask_RolePlaySilhouette(u8 taskId)
isShiny = gContestResources->moveAnim->targetIsShiny;
species = gContestResources->moveAnim->targetSpecies;
xOffset = 20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
else
{
struct Pokemon *mon = GetPartyBattlerData(gBattleAnimTarget);
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
isBackPic = FALSE;
personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY);
isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
else
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
}
else
{
species = gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies;
}
xOffset = 20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
else
{
isBackPic = TRUE;
personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY);
isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE)
{
if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
else
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_SPECIES);
}
else
{
species = gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies;
}
personality = GetMonData(mon, MON_DATA_PERSONALITY);
isShiny = GetMonData(mon, MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE)
species = GetMonData(mon, MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies;
xOffset = -20;
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
}
xOffset = -20;
}
priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker);
coord1 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X);
coord2 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y);
@ -5331,28 +5304,22 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId)
}
else
{
struct Pokemon *mon = GetPartyBattlerData(gBattleAnimAttacker);
personality = GetMonData(mon, MON_DATA_PERSONALITY);
isShiny = GetMonData(mon, MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE)
species = GetMonData(mon, MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies;
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY);
isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies;
subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1;
isBackPic = FALSE;
x = DISPLAY_WIDTH + 32;
}
else
{
personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY);
isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_IS_SHINY);
if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies;
subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority - 1;
isBackPic = TRUE;
x = -32;

View File

@ -143,28 +143,16 @@ u8 GetBattlerYDelta(u8 battlerId, u16 species)
u8 ret;
species = SanitizeSpeciesId(species);
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER || IsContest())
if (IsContest())
{
if (species == SPECIES_UNOWN)
{
if (IsContest())
{
if (gContestResources->moveAnim->hasTargetAnim)
personality = gContestResources->moveAnim->targetPersonality;
else
personality = gContestResources->moveAnim->personality;
}
if (gContestResources->moveAnim->hasTargetAnim)
personality = gContestResources->moveAnim->targetPersonality;
else
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY);
else
personality = gTransformedPersonalities[battlerId];
}
personality = gContestResources->moveAnim->personality;
species = GetUnownSpeciesId(personality);
}
ret = gSpeciesInfo[species].backPicYOffset;
}
else
{
@ -172,14 +160,17 @@ u8 GetBattlerYDelta(u8 battlerId, u16 species)
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY);
personality = GetMonData(GetPartyBattlerData(battlerId), MON_DATA_PERSONALITY);
else
personality = gTransformedPersonalities[battlerId];
species = GetUnownSpeciesId(personality);
}
ret = gSpeciesInfo[species].frontPicYOffset;
}
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER || IsContest())
ret = gSpeciesInfo[species].backPicYOffset;
else
ret = gSpeciesInfo[species].frontPicYOffset;
return ret;
}
@ -279,22 +270,13 @@ u8 GetBattlerYCoordWithElevation(u8 battlerId)
y = GetBattlerSpriteCoord(battlerId, BATTLER_COORD_Y);
if (!IsContest())
{
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
else
species = spriteInfo[battlerId].transformSpecies;
}
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(GetPartyBattlerData(battlerId), MON_DATA_SPECIES);
else
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
else
species = spriteInfo[battlerId].transformSpecies;
}
species = spriteInfo[battlerId].transformSpecies;
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
y -= GetBattlerElevation(battlerId, species);
}
@ -845,19 +827,8 @@ bool8 IsBattlerSpritePresent(u8 battlerId)
if (GetBattlerPosition(battlerId) == 0xff)
return FALSE;
if (!gBattleStruct->spriteIgnore0Hp)
{
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
{
if (GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) == 0)
return FALSE;
}
else
{
if (GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_HP) == 0)
return FALSE;
}
}
if (!gBattleStruct->spriteIgnore0Hp && GetMonData(GetPartyBattlerData(battlerId), MON_DATA_HP) == 0)
return FALSE;
return TRUE;
}
}
@ -1531,6 +1502,12 @@ void TranslateAnimSpriteToTargetMonLocation(struct Sprite *sprite)
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
// arg0: start x offset
// arg1: start y offset
// arg2: end x offset
// arg3: end y offset
// arg4: duration
// arg5: arc amplitude
void AnimThrowProjectile(struct Sprite *sprite)
{
InitSpritePosToAnimAttacker(sprite, TRUE);
@ -1874,26 +1851,16 @@ static u16 GetBattlerYDeltaFromSpriteId(u8 spriteId)
}
else
{
if (GetBattlerSide(i) == B_SIDE_PLAYER)
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
else
species = spriteInfo[battlerId].transformSpecies;
return gSpeciesInfo[species].backPicYOffset;
}
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(GetPartyBattlerData(i), MON_DATA_SPECIES);
else
{
spriteInfo = gBattleSpritesDataPtr->battlerData;
if (!spriteInfo[battlerId].transformSpecies)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES);
else
species = spriteInfo[battlerId].transformSpecies;
species = spriteInfo[battlerId].transformSpecies;
if (GetBattlerSide(i) == B_SIDE_PLAYER)
return gSpeciesInfo[species].backPicYOffset;
else
return gSpeciesInfo[species].frontPicYOffset;
}
}
}
}

View File

@ -9267,21 +9267,15 @@ void AnimTask_DynamaxGrowth(u8 taskId) // from CFRU
void AnimTask_GetWeatherToSet(u8 taskId)
{
switch (GetMoveMaxEffect(gCurrentMove))
{
case MAX_EFFECT_SUN:
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SUN;
break;
case MAX_EFFECT_RAIN:
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_RAIN;
break;
case MAX_EFFECT_SANDSTORM:
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SANDSTORM;
break;
case MAX_EFFECT_HAIL:
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_HAIL;
break;
}
if (MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_SUN))
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SUN;
else if (MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_RAIN))
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_RAIN;
else if (MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_SANDSTORM))
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_SANDSTORM;
else if (MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_HAIL))
gBattleAnimArgs[ARG_RET_ID] = ANIM_WEATHER_HAIL;
DestroyAnimVisualTask(taskId);
}

View File

@ -1379,3 +1379,14 @@ void AnimPsychoBoost(struct Sprite *sprite)
break;
}
}
const struct SpriteTemplate gTachyonCutterSpriteTemplate =
{
.tileTag = ANIM_TAG_CUT,
.paletteTag = ANIM_TAG_BUBBLE,
.oam = &gOamData_AffineOff_ObjBlend_32x32,
.anims = gCuttingSliceAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = AnimCuttingSlice,
};

View File

@ -1026,3 +1026,25 @@ void AnimTask_SeismicTossBgAccelerateDownAtEnd(u8 taskId)
DestroyAnimVisualTask(taskId);
}
}
const struct SpriteTemplate gSaltCureCrystalSpriteTemplate =
{
.tileTag = ANIM_TAG_SALT_PARTICLE,
.paletteTag = ANIM_TAG_SALT_PARTICLE,
.oam = &gOamData_AffineNormal_ObjBlend_16x16,
.anims = gAnims_IceCrystalLarge,
.images = NULL,
.affineAnims = gAffineAnims_IceCrystalHit,
.callback = AnimIceEffectParticle,
};
const struct SpriteTemplate gSaltCureSwirlSpriteTemplate =
{
.tileTag = ANIM_TAG_SALT_PARTICLE,
.paletteTag = ANIM_TAG_SALT_PARTICLE,
.oam = &gOamData_AffineNormal_ObjBlend_16x16,
.anims = gAnims_WaterMudOrb,
.images = NULL,
.affineAnims = gAffineAnims_Whirlpool,
.callback = AnimParticleInVortex,
};

View File

@ -908,10 +908,7 @@ void AnimTask_SwitchOutBallEffect(u8 taskId)
u32 selectedPalettes;
spriteId = gBattlerSpriteIds[gBattleAnimAttacker];
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
ballId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_POKEBALL);
else
ballId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_POKEBALL);
ballId = GetMonData(GetPartyBattlerData(gBattleAnimAttacker), MON_DATA_POKEBALL);
switch (gTasks[taskId].data[0])
{

View File

@ -316,16 +316,9 @@ void AnimTask_DrawFallingWhiteLinesOnAttacker(u8 taskId)
}
if (IsContest())
{
species = gContestResources->moveAnim->species;
}
else
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
else
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES);
}
species = GetMonData(GetPartyBattlerData(gBattleAnimAttacker), MON_DATA_SPECIES);
spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER);
newSpriteId = CreateInvisibleSpriteCopy(gBattleAnimAttacker, spriteId, species);
@ -458,16 +451,9 @@ static void StatsChangeAnimation_Step1(u8 taskId)
}
if (IsContest())
{
sAnimStatsChangeData->species = gContestResources->moveAnim->species;
}
else
{
if (GetBattlerSide(sAnimStatsChangeData->battler1) != B_SIDE_PLAYER)
sAnimStatsChangeData->species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[sAnimStatsChangeData->battler1]], MON_DATA_SPECIES);
else
sAnimStatsChangeData->species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[sAnimStatsChangeData->battler1]], MON_DATA_SPECIES);
}
sAnimStatsChangeData->species = GetMonData(GetPartyBattlerData(sAnimStatsChangeData->battler1), MON_DATA_SPECIES);
gTasks[taskId].func = StatsChangeAnimation_Step2;
}
@ -840,16 +826,9 @@ void StartMonScrollingBgMask(u8 taskId, int UNUSED unused, u16 scrollSpeed, u8 b
SetGpuReg(REG_OFFSET_BG1CNT, bg1Cnt);
if (IsContest())
{
species = gContestResources->moveAnim->species;
}
else
{
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
else
species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
}
species = GetMonData(GetPartyBattlerData(battler), MON_DATA_SPECIES);
spriteId = CreateInvisibleSpriteCopy(battler, gBattlerSpriteIds[battler], species);
if (includePartner)

View File

@ -1349,25 +1349,11 @@ static u8 GetWaterSpoutPowerForAnim(void)
u8 i;
u16 hp;
u16 maxhp;
u16 partyIndex;
struct Pokemon *slot;
struct Pokemon *slot = GetPartyBattlerData(gBattleAnimAttacker);
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER)
{
partyIndex = gBattlerPartyIndexes[gBattleAnimAttacker];
slot = &gPlayerParty[partyIndex];
maxhp = GetMonData(slot, MON_DATA_MAX_HP);
hp = GetMonData(slot, MON_DATA_HP);
maxhp /= 4;
}
else
{
partyIndex = gBattlerPartyIndexes[gBattleAnimAttacker];
slot = &gEnemyParty[partyIndex];
maxhp = GetMonData(slot, MON_DATA_MAX_HP);
hp = GetMonData(slot, MON_DATA_HP);
maxhp /= 4;
}
maxhp = GetMonData(slot, MON_DATA_MAX_HP);
hp = GetMonData(slot, MON_DATA_HP);
maxhp /= 4;
for (i = 0; i < 3; i++)
{
if (hp < maxhp * (i + 1))

View File

@ -680,7 +680,7 @@ static void OpponentHandleChoosePokemon(u32 battler)
// Switching out
else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE)
{
chosenMonId = GetMostSuitableMonToSwitchInto(battler, TRUE);
chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO);
if (chosenMonId == PARTY_SIZE)
{
s32 battler1, battler2, firstId, lastId;

View File

@ -2174,7 +2174,8 @@ static void PlayerHandleChoosePokemon(u32 battler)
gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[battler][4 + i];
if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH
&& (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON)
&& (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON
&& (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_SEND_MON_TO_BOX)
{
BtlController_EmitChosenMonReturnValue(battler, BUFFER_B, gBattlerPartyIndexes[battler] + 1, gBattlePartyCurrentOrder);
PlayerBufferExecCompleted(battler);

View File

@ -387,7 +387,7 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler)
// Switching out
else if (gBattleStruct->monToSwitchIntoId[battler] >= PARTY_SIZE || !IsValidForBattle(&gPlayerParty[gBattleStruct->monToSwitchIntoId[battler]]))
{
chosenMonId = GetMostSuitableMonToSwitchInto(battler, TRUE);
chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO);
if (chosenMonId == PARTY_SIZE || !IsValidForBattle(&gPlayerParty[chosenMonId])) // just switch to the next mon
{

View File

@ -23,7 +23,7 @@
#include "constants/items.h"
#include "constants/moves.h"
static u8 GetMaxPowerTier(u32 move);
static u32 GetMaxPowerTier(u32 move);
struct GMaxMove
{
@ -197,13 +197,10 @@ void ActivateDynamax(u32 battler)
// Unsets the flags used for Dynamaxing and reverts max HP if needed.
void UndoDynamax(u32 battler)
{
u8 side = GetBattlerSide(battler);
u8 monId = gBattlerPartyIndexes[battler];
// Revert HP if battler is still Dynamaxed.
if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX)
{
struct Pokemon *mon = (side == B_SIDE_PLAYER) ? &gPlayerParty[monId] : &gEnemyParty[monId];
struct Pokemon *mon = GetPartyBattlerData(battler);
uq4_12_t mult = GetDynamaxLevelHPMultiplier(GetMonData(mon, MON_DATA_DYNAMAX_LEVEL), TRUE);
gBattleMons[battler].hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult + 1) + UQ_4_12_ROUND); // round up
SetMonData(mon, MON_DATA_HP, &gBattleMons[battler].hp);
@ -317,11 +314,11 @@ enum
};
// Gets the base power of a Max Move.
u8 GetMaxMovePower(u32 move)
u32 GetMaxMovePower(u32 move)
{
u8 tier;
u32 tier;
// G-Max Drum Solo, G-Max Hydrosnipe, and G-Max Fireball always have 160 base power.
if (GetMoveMaxEffect(GetMaxMove(gBattlerAttacker, move)) == MAX_EFFECT_FIXED_POWER)
if (MoveHasAdditionalEffect(move, MOVE_EFFECT_FIXED_POWER))
return 160;
// Exceptions to all other rules below:
@ -369,7 +366,7 @@ u8 GetMaxMovePower(u32 move)
}
}
static u8 GetMaxPowerTier(u32 move)
static u32 GetMaxPowerTier(u32 move)
{
u32 strikeCount = GetMoveStrikeCount(move);
if (strikeCount >= 2 && strikeCount <= 5)
@ -470,42 +467,6 @@ void ChooseDamageNonTypesString(u8 type)
}
}
// Returns the status effect that should be applied by a G-Max Move.
static u32 GetMaxMoveStatusEffect(u32 move)
{
u8 maxEffect = GetMoveMaxEffect(move);
switch (maxEffect)
{
// Status 1
case MAX_EFFECT_PARALYZE_FOES:
return STATUS1_PARALYSIS;
case MAX_EFFECT_POISON_FOES:
return STATUS1_POISON;
case MAX_EFFECT_POISON_PARALYZE_FOES:
{
static const u8 sStunShockEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON};
return RandomElement(RNG_G_MAX_STUN_SHOCK, sStunShockEffects);
}
case MAX_EFFECT_EFFECT_SPORE_FOES:
{
static const u8 sBefuddleEffects[] = {STATUS1_PARALYSIS, STATUS1_POISON, STATUS1_SLEEP};
return RandomElement(RNG_G_MAX_BEFUDDLE, sBefuddleEffects);
}
// Status 2
case MAX_EFFECT_CONFUSE_FOES:
case MAX_EFFECT_CONFUSE_FOES_PAY_DAY:
return STATUS2_CONFUSION;
case MAX_EFFECT_INFATUATE_FOES:
return STATUS2_INFATUATION;
case MAX_EFFECT_MEAN_LOOK:
return STATUS2_ESCAPE_PREVENTION;
case MAX_EFFECT_TORMENT_FOES:
return STATUS2_TORMENT;
default:
return STATUS1_NONE;
}
}
// Updates Dynamax HP multipliers and healthboxes.
void BS_UpdateDynamax(void)
{
@ -519,502 +480,6 @@ void BS_UpdateDynamax(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
// Activates the secondary effect of a Max Move.
void BS_SetMaxMoveEffect(void)
{
NATIVE_ARGS();
u16 effect = 0;
u8 maxEffect = GetMoveMaxEffect(gCurrentMove);
// Don't continue if the move didn't land.
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)
{
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
switch (maxEffect)
{
case MAX_EFFECT_RAISE_TEAM_ATTACK:
case MAX_EFFECT_RAISE_TEAM_DEFENSE:
case MAX_EFFECT_RAISE_TEAM_SPEED:
case MAX_EFFECT_RAISE_TEAM_SP_ATK:
case MAX_EFFECT_RAISE_TEAM_SP_DEF:
if (!NoAliveMonsForEitherParty())
{
// Max Effects are ordered by stat ID.
SET_STATCHANGER(maxEffect, 1, FALSE);
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRaiseStatAllies;
effect++;
}
break;
case MAX_EFFECT_LOWER_ATTACK:
case MAX_EFFECT_LOWER_DEFENSE:
case MAX_EFFECT_LOWER_SPEED:
case MAX_EFFECT_LOWER_SP_ATK:
case MAX_EFFECT_LOWER_SP_DEF:
case MAX_EFFECT_LOWER_SPEED_2_FOES:
case MAX_EFFECT_LOWER_EVASIVENESS_FOES:
if (!NoAliveMonsForEitherParty())
{
u8 statId = 0;
u8 stage = 1;
switch (maxEffect)
{
case MAX_EFFECT_LOWER_SPEED_2_FOES:
statId = STAT_SPEED;
stage = 2;
break;
case MAX_EFFECT_LOWER_EVASIVENESS_FOES:
statId = STAT_EVASION;
break;
default:
// Max Effects are ordered by stat ID.
statId = maxEffect - MAX_EFFECT_LOWER_ATTACK + 1;
break;
}
SET_STATCHANGER(statId, stage, TRUE);
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectLowerStatFoes;
effect++;
}
break;
case MAX_EFFECT_SUN:
case MAX_EFFECT_RAIN:
case MAX_EFFECT_SANDSTORM:
case MAX_EFFECT_HAIL:
{
u8 weather = 0, msg = 0;
switch (maxEffect)
{
case MAX_EFFECT_SUN:
weather = BATTLE_WEATHER_SUN;
msg = B_MSG_STARTED_SUNLIGHT;
break;
case MAX_EFFECT_RAIN:
weather = BATTLE_WEATHER_RAIN;
msg = B_MSG_STARTED_RAIN;
break;
case MAX_EFFECT_SANDSTORM:
weather = BATTLE_WEATHER_SANDSTORM;
msg = B_MSG_STARTED_SANDSTORM;
break;
case MAX_EFFECT_HAIL:
weather = BATTLE_WEATHER_HAIL;
msg = B_MSG_STARTED_HAIL;
break;
}
if (TryChangeBattleWeather(gBattlerAttacker, weather, FALSE))
{
gBattleCommunication[MULTISTRING_CHOOSER] = msg;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectSetWeather;
effect++;
}
break;
}
case MAX_EFFECT_MISTY_TERRAIN:
case MAX_EFFECT_GRASSY_TERRAIN:
case MAX_EFFECT_ELECTRIC_TERRAIN:
case MAX_EFFECT_PSYCHIC_TERRAIN:
{
u32 statusFlag = 0;
switch (GetMoveEffectArg_MoveProperty(gCurrentMove))
{
case MAX_EFFECT_MISTY_TERRAIN:
statusFlag = STATUS_FIELD_MISTY_TERRAIN;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_MISTY;
break;
case MAX_EFFECT_GRASSY_TERRAIN:
statusFlag = STATUS_FIELD_GRASSY_TERRAIN;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_GRASSY;
break;
case MAX_EFFECT_ELECTRIC_TERRAIN:
statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_ELECTRIC;
break;
case MAX_EFFECT_PSYCHIC_TERRAIN:
statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC;
break;
}
if (!(gFieldStatuses & statusFlag) && statusFlag != 0)
{
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY;
gFieldStatuses |= statusFlag;
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER)
gFieldTimers.terrainTimer = gBattleTurnCounter + 8;
else
gFieldTimers.terrainTimer = gBattleTurnCounter + 5;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectSetTerrain;
effect++;
}
break;
}
case MAX_EFFECT_VINE_LASH:
case MAX_EFFECT_CANNONADE:
case MAX_EFFECT_WILDFIRE:
case MAX_EFFECT_VOLCALITH:
{
u8 side = GetBattlerSide(gBattlerTarget);
if (!(gSideStatuses[side] & SIDE_STATUS_DAMAGE_NON_TYPES))
{
u32 moveType = GetMoveType(gCurrentMove);
gSideStatuses[side] |= SIDE_STATUS_DAMAGE_NON_TYPES;
gSideTimers[side].damageNonTypesTimer = gBattleTurnCounter + 5; // damage is dealt for 4 turns, ends on 5th
gSideTimers[side].damageNonTypesType = moveType;
BattleScriptPush(gBattlescriptCurrInstr + 1);
ChooseDamageNonTypesString(moveType);
gBattlescriptCurrInstr = BattleScript_DamageNonTypesStarts;
effect++;
}
break;
}
case MAX_EFFECT_STEALTH_ROCK:
if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEALTH_ROCK))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_POINTEDSTONESFLOAT;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectStonesurge;
effect++;
}
break;
case MAX_EFFECT_STEELSURGE:
if (!(gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_STEELSURGE))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SHARPSTEELFLOATS;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectSteelsurge;
effect++;
}
break;
case MAX_EFFECT_DEFOG:
if (gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_SCREEN_ANY
|| gSideStatuses[GetBattlerSide(gBattlerTarget)] & SIDE_STATUS_HAZARDS_ANY
|| gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_HAZARDS_ANY
|| gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_DefogTryHazards;
effect++;
}
break;
case MAX_EFFECT_AURORA_VEIL:
if (!(gSideStatuses[GetBattlerSide(gBattlerAttacker)] & SIDE_STATUS_AURORA_VEIL))
{
gSideStatuses[GetBattlerSide(gBattlerAttacker)] |= SIDE_STATUS_AURORA_VEIL;
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LIGHT_CLAY)
gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 8;
else
gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5;
gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilBattlerId = gBattlerAttacker;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectAuroraVeilSuccess;
effect++;
}
break;
case MAX_EFFECT_GRAVITY:
if (!(gFieldStatuses & STATUS_FIELD_GRAVITY))
{
gFieldStatuses |= STATUS_FIELD_GRAVITY;
gFieldTimers.gravityTimer = gBattleTurnCounter + 5;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectGravitySuccess;
effect++;
}
break;
case MAX_EFFECT_SANDBLAST_FOES:
case MAX_EFFECT_FIRE_SPIN_FOES:
{
// Affects both opponents, but doesn't print strings so we can handle it here.
u8 battler;
for (battler = 0; battler < MAX_BATTLERS_COUNT; ++battler)
{
if (GetBattlerSide(battler) != GetBattlerSide(gBattlerTarget))
continue;
if (!(gBattleMons[battler].status2 & STATUS2_WRAPPED))
{
gBattleMons[battler].status2 |= STATUS2_WRAPPED;
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW)
#if B_BINDING_TURNS >= GEN_5
gDisableStructs[battler].wrapTurns = 7;
else
gDisableStructs[battler].wrapTurns = (Random() % 2) + 4;
#else
gDisableStructs[battler].wrapTurns = 5;
else
gDisableStructs[battler].wrapTurns = (Random() % 4) + 2;
#endif
// The Wrap effect does not expire when the user switches, so here's some cheese.
gBattleStruct->wrappedBy[battler] = gBattlerTarget;
if (maxEffect == MAX_EFFECT_SANDBLAST_FOES)
gBattleStruct->wrappedMove[battler] = MOVE_SAND_TOMB;
else
gBattleStruct->wrappedMove[battler] = MOVE_FIRE_SPIN;
}
}
break;
}
case MAX_EFFECT_YAWN_FOE:
{
static const u8 sSnoozeEffects[] = {TRUE, FALSE};
if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN)
&& CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE)
&& RandomElement(RNG_G_MAX_SNOOZE, sSnoozeEffects)) // 50% chance of success
{
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectYawnSuccess;
effect++;
}
break;
}
case MAX_EFFECT_SPITE:
if (gLastMoves[gBattlerTarget] != MOVE_NONE
&& gLastMoves[gBattlerTarget] != MOVE_UNAVAILABLE)
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectTryReducePP;
effect++;
}
break;
case MAX_EFFECT_PARALYZE_FOES:
case MAX_EFFECT_POISON_FOES:
case MAX_EFFECT_POISON_PARALYZE_FOES:
case MAX_EFFECT_EFFECT_SPORE_FOES:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectStatus1Foes;
effect++;
break;
case MAX_EFFECT_CONFUSE_FOES_PAY_DAY:
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
u16 payday = gPaydayMoney;
gPaydayMoney += (gBattleMons[gBattlerAttacker].level * 100);
if (payday > gPaydayMoney)
gPaydayMoney = 0xFFFF;
gBattleCommunication[CURSOR_POSITION] = 1; // add "Coins scattered." message
}
// fall through
case MAX_EFFECT_CONFUSE_FOES:
case MAX_EFFECT_INFATUATE_FOES:
case MAX_EFFECT_TORMENT_FOES:
case MAX_EFFECT_MEAN_LOOK:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectStatus2Foes;
effect++;
break;
case MAX_EFFECT_CRIT_PLUS:
gBattleStruct->bonusCritStages[gBattlerAttacker]++;
gBattleStruct->bonusCritStages[BATTLE_PARTNER(gBattlerAttacker)]++;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRaiseCritAlliesAnim;
effect++;
break;
case MAX_EFFECT_HEAL_TEAM:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectHealOneSixthAllies;
effect++;
break;
case MAX_EFFECT_AROMATHERAPY:
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectCureStatusAllies;
effect++;
break;
case MAX_EFFECT_RECYCLE_BERRIES:
{
static const u8 sReplenishEffects[] = {TRUE, FALSE};
if (RandomElement(RNG_G_MAX_REPLENISH, sReplenishEffects)) // 50% chance of success
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_EffectRecycleBerriesAllies;
effect++;
}
break;
}
}
if (!effect)
gBattlescriptCurrInstr = cmd->nextInstr;
}
// Sets up sharp steel on the target's side.
void BS_SetSteelsurge(void)
{
NATIVE_ARGS(const u8 *failInstr);
u8 targetSide = GetBattlerSide(gBattlerTarget);
if (gSideStatuses[targetSide] & SIDE_STATUS_STEELSURGE)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
gSideStatuses[targetSide] |= SIDE_STATUS_STEELSURGE;
gSideTimers[targetSide].steelsurgeAmount = 1;
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
// Applies the status1 effect associated with a given G-Max Move.
// Could be expanded to function for any move.
void BS_TrySetStatus1(void)
{
NATIVE_ARGS(const u8 *failInstr);
u8 effect = 0;
u32 status1 = GetMaxMoveStatusEffect(gCurrentMove);
switch (status1)
{
case STATUS1_POISON:
if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
{
gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
effect++;
}
break;
case STATUS1_PARALYSIS:
if (CanBeParalyzed(gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
{
gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS;
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
effect++;
}
break;
case STATUS1_SLEEP:
if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE))
{
if (B_SLEEP_TURNS >= GEN_5)
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2);
else
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3);
TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]);
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
effect++;
}
break;
}
if (effect)
{
gEffectBattler = gBattlerTarget;
BtlController_EmitSetMonData(gBattlerTarget, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
MarkBattlerForControllerExec(gBattlerTarget);
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
gBattlescriptCurrInstr = cmd->failInstr;
}
}
// Applies the status2 effect associated with a given G-Max Move.
void BS_TrySetStatus2(void)
{
NATIVE_ARGS(const u8 *failInstr);
u8 effect = 0;
u32 status2 = GetMaxMoveStatusEffect(gCurrentMove);
switch (status2)
{
case STATUS2_CONFUSION:
if (CanBeConfused(gBattlerTarget))
{
gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gBattleCommunication[MULTIUSE_STATE] = 1;
effect++;
}
break;
case STATUS2_INFATUATION:
{
u8 atkGender = GetGenderFromSpeciesAndPersonality(gBattleMons[gBattlerAttacker].species, gBattleMons[gBattlerAttacker].personality);
u8 defGender = GetGenderFromSpeciesAndPersonality(gBattleMons[gBattlerTarget].species, gBattleMons[gBattlerTarget].personality);
if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_INFATUATION)
&& gBattleMons[gBattlerTarget].ability != ABILITY_OBLIVIOUS
&& !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL)
&& atkGender != defGender
&& atkGender != MON_GENDERLESS
&& defGender != MON_GENDERLESS)
{
gBattleMons[gBattlerTarget].status2 |= STATUS2_INFATUATED_WITH(gBattlerAttacker);
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gBattleCommunication[MULTIUSE_STATE] = 2;
effect++;
}
break;
}
case STATUS2_ESCAPE_PREVENTION:
if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_ESCAPE_PREVENTION))
{
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
effect++;
}
break;
case STATUS2_TORMENT:
if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT)
&& !IsAbilityOnSide(gBattlerTarget, ABILITY_AROMA_VEIL))
{
gBattleMons[gBattlerTarget].status2 |= STATUS2_TORMENT;
gDisableStructs[gBattlerTarget].tormentTimer = 3; // 3 turns excluding current turn
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
effect++;
}
break;
}
if (effect)
{
gEffectBattler = gBattlerTarget;
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
gBattlescriptCurrInstr = cmd->failInstr;
}
}
// Heals one-sixth of the target's HP, including for Dynamaxed targets.
void BS_HealOneSixth(void)
{
NATIVE_ARGS(const u8* failInstr);
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].maxHP / 6;
if (gBattleStruct->moveDamage[gBattlerTarget] == 0)
gBattleStruct->moveDamage[gBattlerTarget] = 1;
gBattleStruct->moveDamage[gBattlerTarget] *= -1;
if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP)
gBattlescriptCurrInstr = cmd->failInstr; // fail
else
gBattlescriptCurrInstr = cmd->nextInstr; // can heal
}
// Recycles the target's item if it is specifically holding a berry.
void BS_TryRecycleBerry(void)
{
NATIVE_ARGS(const u8 *failInstr);
u16* usedHeldItem = &gBattleStruct->usedHeldItems[gBattlerPartyIndexes[gBattlerTarget]][GetBattlerSide(gBattlerTarget)];
if (gBattleMons[gBattlerTarget].item == ITEM_NONE
&& gBattleStruct->changedItems[gBattlerTarget] == ITEM_NONE // Will not inherit an item
&& ItemId_GetPocket(*usedHeldItem) == POCKET_BERRIES)
{
gLastUsedItem = *usedHeldItem;
*usedHeldItem = ITEM_NONE;
gBattleMons[gBattlerTarget].item = gLastUsedItem;
BtlController_EmitSetMonData(gBattlerTarget, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].item), &gBattleMons[gBattlerTarget].item);
MarkBattlerForControllerExec(gBattlerTarget);
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
gBattlescriptCurrInstr = cmd->failInstr;
}
}
// Goes to the jump instruction if the target is Dynamaxed.
void BS_JumpIfDynamaxed(void)
{

View File

@ -4142,7 +4142,7 @@ enum
STATE_SELECTION_SCRIPT_MAY_RUN
};
void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
void SetupAISwitchingData(u32 battler, enum SwitchType switchType)
{
s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler)));
@ -4151,7 +4151,7 @@ void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
{
AI_DATA->aiSwitchPredictionInProgress = TRUE;
AI_DATA->battlerDoingPrediction = battler;
AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, isAiRisky);
AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, switchType);
if (ShouldSwitch(opposingBattler))
AI_DATA->shouldSwitch |= (1u << opposingBattler);
AI_DATA->aiSwitchPredictionInProgress = FALSE;
@ -4161,7 +4161,7 @@ void SetupAISwitchingData(u32 battler, bool32 isAiRisky)
}
// AI's data
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky);
AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, switchType);
if (ShouldSwitch(battler))
AI_DATA->shouldSwitch |= (1u << battler);
}
@ -4179,7 +4179,7 @@ static void HandleTurnActionSelectionState(void)
case STATE_TURN_START_RECORD: // Recorded battle related action on start of every turn.
RecordedBattle_CopyBattlerMoves(battler);
gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN;
u32 isAiRisky = AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_RISKY; // Risky AI switches aggressively even mid battle
enum SwitchType switchType = (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_RISKY) ? SWITCH_AFTER_KO : SWITCH_MID_BATTLE; // Risky AI switches aggressively even mid battle
// Do AI score computations here so we can use them in AI_TrySwitchOrUseItem
if ((gBattleTypeFlags & BATTLE_TYPE_HAS_AI || IsWildMonSmart())
@ -4189,7 +4189,7 @@ static void HandleTurnActionSelectionState(void)
// Setup battler data
BattleAI_SetupAIData(0xF, battler);
SetupAISwitchingData(battler, isAiRisky);
SetupAISwitchingData(battler, switchType);
// Do scoring
gBattleStruct->aiMoveOrAction[battler] = BattleAI_ChooseMoveOrAction(battler);

View File

@ -891,6 +891,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_SUPEREFFECTIVETWOFOES] = COMPOUND_STRING("It's super effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"),
[STRINGID_NOTVERYEFFECTIVETWOFOES] = COMPOUND_STRING("It's not very effective on {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}!"),
[STRINGID_ITDOESNTAFFECTTWOFOES] = COMPOUND_STRING("It doesn't affect {B_DEF_NAME_WITH_PREFIX2} and {B_DEF_PARTNER_NAME}…"),
[STRINGID_SENDCAUGHTMONPARTYORBOX] = COMPOUND_STRING("Add {B_DEF_NAME} to your party?"),
[STRINGID_PKMNSENTTOPCAFTERCATCH] = gText_PkmnSentToPCAfterCatch,
};
const u16 gTrainerUsedItemStringIds[] =
@ -1362,10 +1364,11 @@ const u16 gFlashFireStringIds[] =
const u16 gCaughtMonStringIds[] =
{
[B_MSG_SENT_SOMEONES_PC] = STRINGID_PKMNTRANSFERREDSOMEONESPC,
[B_MSG_SENT_LANETTES_PC] = STRINGID_PKMNTRANSFERREDLANETTESPC,
[B_MSG_SOMEONES_BOX_FULL] = STRINGID_PKMNBOXSOMEONESPCFULL,
[B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL,
[B_MSG_SENT_SOMEONES_PC] = STRINGID_PKMNTRANSFERREDSOMEONESPC,
[B_MSG_SENT_LANETTES_PC] = STRINGID_PKMNTRANSFERREDLANETTESPC,
[B_MSG_SOMEONES_BOX_FULL] = STRINGID_PKMNBOXSOMEONESPCFULL,
[B_MSG_LANETTES_BOX_FULL] = STRINGID_PKMNBOXLANETTESPCFULL,
[B_MSG_SWAPPED_INTO_PARTY] = STRINGID_PKMNSENTTOPCAFTERCATCH,
};
const u16 gRoomsStringIds[] =

View File

@ -983,8 +983,10 @@ static void SetPickupItem(void)
{
int i;
int itemIndex;
int rand;
int randVal;
u32 randSeedIndex, randSeed;
u8 id;
rng_value_t rand;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 floor = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
u32 round = (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] / FRONTIER_STAGES_PER_CHALLENGE) % TOTAL_PYRAMID_ROUNDS;
@ -994,15 +996,19 @@ static void SetPickupItem(void)
id = GetPyramidFloorTemplateId();
itemIndex = (gSpecialVar_LastTalked - sPyramidFloorTemplates[id].numTrainers) - 1;
rand = gSaveBlock2Ptr->frontier.pyramidRandoms[itemIndex / 2];
SeedRng2(rand);
randSeedIndex = (itemIndex & 1) * 2;
randSeed = (u32)gSaveBlock2Ptr->frontier.pyramidRandoms[randSeedIndex + 1] << 16;
randSeed |= gSaveBlock2Ptr->frontier.pyramidRandoms[randSeedIndex];
rand = LocalRandomSeed(randSeed);
for (i = 0; i < itemIndex + 1; i++)
rand = Random2() % 100;
for (i = 0; i < itemIndex / 2; i++)
LocalRandom(&rand);
randVal = LocalRandom(&rand) % 100;
for (i = sPickupItemOffsets[floor]; i < ARRAY_COUNT(sPickupItemSlots); i++)
{
if (rand < sPickupItemSlots[i][0])
if (randVal < sPickupItemSlots[i][0])
break;
}

File diff suppressed because it is too large Load Diff

View File

@ -1271,7 +1271,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move)
}
// Dynamax bypasses all selection prevention except Taunt and Assault Vest.
#define DYNAMAX_BYPASS_CHECK (!IsGimmickSelected(gBattlerAttacker, GIMMICK_DYNAMAX) && GetActiveGimmick(gBattlerAttacker) != GIMMICK_DYNAMAX)
#define DYNAMAX_BYPASS_CHECK (!IsGimmickSelected(battler, GIMMICK_DYNAMAX) && GetActiveGimmick(battler) != GIMMICK_DYNAMAX)
u32 TrySetCantSelectMoveBattleScript(u32 battler)
{
@ -1282,7 +1282,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
u16 *choicedMove = &gBattleStruct->choicedMove[battler];
u32 moveEffect = GetMoveEffect(move);
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].disabledMove == move && move != MOVE_NONE)
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].disabledMove == move && move != MOVE_NONE)
{
gBattleScripting.battler = battler;
gCurrentMove = move;
@ -1298,7 +1298,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && move == gLastMoves[battler] && move != MOVE_STRUGGLE && (gBattleMons[battler].status2 & STATUS2_TORMENT))
{
CancelMultiTurnMoves(battler);
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1313,9 +1313,9 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].tauntTimer != 0 && IsBattleMoveStatus(move))
if (GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].tauntTimer != 0 && IsBattleMoveStatus(move))
{
if ((GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX))
if ((GetActiveGimmick(battler) == GIMMICK_DYNAMAX))
gCurrentMove = MOVE_MAX_GUARD;
else
gCurrentMove = move;
@ -1331,7 +1331,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer > gBattleTurnCounter && IsSoundMove(move))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && gDisableStructs[battler].throatChopTimer > gBattleTurnCounter && IsSoundMove(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1346,7 +1346,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(battler, move))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(battler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1361,7 +1361,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsGravityPreventingMove(move))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsGravityPreventingMove(move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1376,7 +1376,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsHealBlockPreventingMove(battler, move))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsHealBlockPreventingMove(battler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1391,7 +1391,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
}
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && IsBelchPreventingMove(battler, move))
if (DYNAMAX_BYPASS_CHECK && GetActiveGimmick(battler) != GIMMICK_Z_MOVE && IsBelchPreventingMove(battler, move))
{
gCurrentMove = move;
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
@ -1455,7 +1455,7 @@ u32 TrySetCantSelectMoveBattleScript(u32 battler)
}
else if (holdEffect == HOLD_EFFECT_ASSAULT_VEST && IsBattleMoveStatus(move) && moveEffect != EFFECT_ME_FIRST)
{
if ((GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX))
if ((GetActiveGimmick(battler) == GIMMICK_DYNAMAX))
gCurrentMove = MOVE_MAX_GUARD;
else
gCurrentMove = move;
@ -2905,67 +2905,87 @@ static void ChooseStatBoostAnimation(u32 battler)
#undef ANIM_STAT_ACC
#undef ANIM_STAT_EVASION
u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef)
bool32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef, enum AbilityEffectOptions option)
{
enum MoveBlocked effect = MOVE_BLOCKED_BY_NO_ABILITY;
const u8 *battleScriptBlocksMove = NULL;
u32 atkPriority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
u32 battlerAbility = battlerDef;
switch (abilityDef)
{
case ABILITY_SOUNDPROOF:
if (IsSoundMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF;
if (IsSoundMove(move) && !(moveTarget & MOVE_TARGET_USER))
{
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battleScriptBlocksMove = BattleScript_SoundproofProtected;
}
break;
case ABILITY_BULLETPROOF:
if (IsBallisticMove(move))
effect = MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF;
{
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battleScriptBlocksMove = BattleScript_SoundproofProtected;
}
break;
case ABILITY_DAZZLING:
case ABILITY_QUEENLY_MAJESTY:
case ABILITY_ARMOR_TAIL:
if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef))
if (atkPriority > 0 && !IsAlly(battlerAtk, battlerDef))
{
u32 priority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
if (priority > 0)
effect = MOVE_BLOCKED_BY_DAZZLING;
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battleScriptBlocksMove = BattleScript_DazzlingProtected;
}
break;
case ABILITY_GOOD_AS_GOLD:
if (IsBattleMoveStatus(move))
{
u32 moveTarget = GetBattlerMoveTargetType(battlerAtk, move);
if (!(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) && !(moveTarget & MOVE_TARGET_ALL_BATTLERS))
effect = MOVE_BLOCKED_BY_GOOD_AS_GOLD;
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
}
break;
}
if (!effect)
effect = CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, GetBattlerAbility(BATTLE_PARTNER(battlerDef)));
return effect;
}
u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef)
{
switch (abilityDef)
// Check def partner ability
if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battlerDef)))
{
case ABILITY_DAZZLING:
case ABILITY_QUEENLY_MAJESTY:
case ABILITY_ARMOR_TAIL:
if (GetBattlerSide(battlerAtk) != GetBattlerSide(battlerDef))
switch (GetBattlerAbility(BATTLE_PARTNER(battlerDef)))
{
s32 priority = AI_DATA->aiCalcInProgress ? GetBattleMovePriority(battlerAtk, move) : GetChosenMovePriority(battlerAtk);
if (priority > 0)
return MOVE_BLOCKED_BY_PARTNER_DAZZLING;
case ABILITY_DAZZLING:
case ABILITY_QUEENLY_MAJESTY:
case ABILITY_ARMOR_TAIL:
if (atkPriority > 0 && !IsAlly(battlerAtk, BATTLE_PARTNER(battlerDef)))
{
if (gBattleMons[battlerAtk].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battlerAbility = BATTLE_PARTNER(battlerDef);
battleScriptBlocksMove = BattleScript_DazzlingProtected;
}
break;
}
break;
}
return MOVE_BLOCKED_BY_NO_ABILITY;
if (battleScriptBlocksMove == NULL)
return FALSE;
if (option == ABILITY_RUN_SCRIPT)
{
gBattleScripting.battler = gBattlerAbility = battlerAbility;
gBattlescriptCurrInstr = battleScriptBlocksMove;
}
return TRUE;
}
u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType)
bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType, enum AbilityEffectOptions option)
{
enum MoveAbsorbed effect = MOVE_ABSORBED_BY_NO_ABILITY;
const u8 *battleScript = NULL;
u32 statId = 0;
u32 statAmount = 1;
switch (abilityDef)
{
@ -2987,27 +3007,46 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov
break;
case ABILITY_MOTOR_DRIVE:
if (moveType == TYPE_ELECTRIC && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction)
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statId = STAT_SPEED;
}
break;
case ABILITY_LIGHTNING_ROD:
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_ELECTRIC && GetMoveTarget(move) != MOVE_TARGET_ALL_BATTLERS) // Potential bug in singles (might be solved with simu hp reudction)
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statId = STAT_SPATK;
}
break;
case ABILITY_STORM_DRAIN:
if (B_REDIRECT_ABILITY_IMMUNITY >= GEN_5 && moveType == TYPE_WATER)
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statId = STAT_SPATK;
}
break;
case ABILITY_SAP_SIPPER:
if (moveType == TYPE_GRASS)
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statId = STAT_ATK;
}
break;
case ABILITY_WELL_BAKED_BODY:
if (moveType == TYPE_FIRE)
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statAmount = 2;
statId = STAT_DEF;
}
break;
case ABILITY_WIND_RIDER:
if (IsWindMove(move) && !(GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_USER))
{
effect = MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY;
statId = STAT_ATK;
}
break;
case ABILITY_FLASH_FIRE:
if (moveType == TYPE_FIRE && (B_FLASH_FIRE_FROZEN >= GEN_5 || !(gBattleMons[battlerDef].status1 & STATUS1_FREEZE)))
@ -3015,6 +3054,84 @@ u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 mov
break;
}
if (effect == MOVE_ABSORBED_BY_NO_ABILITY || option == ABILITY_CHECK_TRIGGER)
return effect;
switch (effect)
{
default:
return FALSE;
case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY:
gBattleStruct->pledgeMove = FALSE;
if (IsBattlerAtMaxHp(battlerDef) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK))
{
if ((gProtectStructs[battlerAtk].notFirstStrike))
battleScript = BattleScript_MonMadeMoveUseless;
else
battleScript = BattleScript_MonMadeMoveUseless_PPLoss;
}
else
{
if (gProtectStructs[battlerAtk].notFirstStrike)
battleScript = BattleScript_MoveHPDrain;
else
battleScript = BattleScript_MoveHPDrain_PPLoss;
gBattleStruct->moveDamage[battlerDef] = GetNonDynamaxMaxHP(battlerDef) / 4;
if (gBattleStruct->moveDamage[battlerDef] == 0)
gBattleStruct->moveDamage[battlerDef] = 1;
gBattleStruct->moveDamage[battlerDef] *= -1;
}
break;
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
gBattleStruct->pledgeMove = FALSE;
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
{
if ((gProtectStructs[battlerAtk].notFirstStrike))
battleScript = BattleScript_MonMadeMoveUseless;
else
battleScript = BattleScript_MonMadeMoveUseless_PPLoss;
}
else
{
if (gProtectStructs[battlerAtk].notFirstStrike)
battleScript = BattleScript_MoveStatDrain;
else
battleScript = BattleScript_MoveStatDrain_PPLoss;
SET_STATCHANGER(statId, statAmount, FALSE);
if (B_ABSORBING_ABILITY_STRING < GEN_5)
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
}
break;
case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE:
gBattleStruct->pledgeMove = FALSE;
if (!gDisableStructs[battlerDef].flashFireBoosted)
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
if (gProtectStructs[battlerAtk].notFirstStrike)
battleScript = BattleScript_FlashFireBoost;
else
battleScript = BattleScript_FlashFireBoost_PPLoss;
gDisableStructs[battlerDef].flashFireBoosted = TRUE;
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
if (gProtectStructs[battlerAtk].notFirstStrike)
battleScript = BattleScript_FlashFireBoost;
else
battleScript = BattleScript_FlashFireBoost_PPLoss;
}
break;
}
if (battleScript != NULL)
{
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
gBattlescriptCurrInstr = battleScript;
}
return effect;
}
@ -3389,6 +3506,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_UNNERVE:
if (!gSpecialStatuses[battler].switchInAbilityDone)
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler)));
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_UNNERVE;
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg);
@ -3399,6 +3517,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_AS_ONE_SHADOW_RIDER:
if (!gSpecialStatuses[battler].switchInAbilityDone)
{
gBattlerTarget = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerAtPosition(battler)));
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_ASONE;
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_ActivateAsOne);
@ -4172,153 +4291,35 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
}
break;
case ABILITYEFFECT_WOULD_BLOCK:
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility);
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility, ABILITY_CHECK_TRIGGER);
if (effect && gLastUsedAbility != 0xFFFF)
RecordAbilityBattle(battler, gLastUsedAbility);
break;
return effect;
case ABILITYEFFECT_MOVES_BLOCK:
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility, ABILITY_RUN_SCRIPT);
// prankster check
if (effect == 0
&& GetChosenMovePriority(gBattlerAttacker) > 0
&& BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
&& !(IsBattleMoveStatus(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove)))
{
effect = CanAbilityBlockMove(gBattlerAttacker, battler, move, gLastUsedAbility);
const u8 * battleScriptBlocksMove = NULL;
switch (effect)
{
case MOVE_BLOCKED_BY_SOUNDPROOF_OR_BULLETPROOF:
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battleScriptBlocksMove = BattleScript_SoundproofProtected;
break;
case MOVE_BLOCKED_BY_DAZZLING:
case MOVE_BLOCKED_BY_PARTNER_DAZZLING:
if (effect == MOVE_BLOCKED_BY_PARTNER_DAZZLING)
gBattleScripting.battler = BATTLE_PARTNER(battler);
else
gBattleScripting.battler = battler;
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
gHitMarker |= HITMARKER_NO_PPDEDUCT;
battleScriptBlocksMove = BattleScript_DazzlingProtected;
break;
case MOVE_BLOCKED_BY_GOOD_AS_GOLD:
battleScriptBlocksMove = BattleScript_GoodAsGoldActivates;
break;
default:
if (GetChosenMovePriority(gBattlerAttacker) > 0
&& BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE)
&& !(IsBattleMoveStatus(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove)))
{
if (!IsDoubleBattle()
|| !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
battleScriptBlocksMove = BattleScript_DarkTypePreventsPrankster;
effect = 1;
}
}
if (effect)
gBattlescriptCurrInstr = battleScriptBlocksMove;
if (!IsDoubleBattle()
|| !(GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
effect = 1;
}
break;
case ABILITYEFFECT_WOULD_ABSORB:
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType);
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, ABILITY_CHECK_TRIGGER);
gBattleStruct->pledgeMove = FALSE;
if (effect && gLastUsedAbility != 0xFFFF)
RecordAbilityBattle(battler, gLastUsedAbility);
return effect;
case ABILITYEFFECT_ABSORBING:
{
u32 statId = 0;
u32 statAmount = 1;
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType);
if (effect)
{
switch(gLastUsedAbility)
{
case ABILITY_MOTOR_DRIVE:
statId = STAT_SPEED;
break;
case ABILITY_LIGHTNING_ROD:
case ABILITY_STORM_DRAIN:
statId = STAT_SPATK;
break;
case ABILITY_SAP_SIPPER:
case ABILITY_WIND_RIDER:
statId = STAT_ATK;
break;
case ABILITY_WELL_BAKED_BODY:
statAmount = 2;
statId = STAT_DEF;
break;
}
}
switch (effect)
{
case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY:
gBattleStruct->pledgeMove = FALSE;
if (IsBattlerAtMaxHp(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK))
{
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
else
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss;
}
else
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4;
if (gBattleStruct->moveDamage[battler] == 0)
gBattleStruct->moveDamage[battler] = 1;
gBattleStruct->moveDamage[battler] *= -1;
}
break;
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
gBattleStruct->pledgeMove = FALSE;
if (!CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
{
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
else
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss;
}
else
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveStatDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss;
SET_STATCHANGER(statId, statAmount, FALSE);
if (B_ABSORBING_ABILITY_STRING < GEN_5)
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
}
break;
case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE:
gBattleStruct->pledgeMove = FALSE;
if (!gDisableStructs[battler].flashFireBoosted)
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST;
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
gDisableStructs[battler].flashFireBoosted = TRUE;
}
else
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_NO_BOOST;
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
else
gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
}
break;
}
if (effect)
gMultiHitCounter = 0; // Prevent multi-hit moves from hitting more than once after move has been absorbed.
}
effect = CanAbilityAbsorbMove(gBattlerAttacker, battler, gLastUsedAbility, move, moveType, ABILITY_RUN_SCRIPT);
break;
case ABILITYEFFECT_MOVE_END: // Think contact abilities.
switch (gLastUsedAbility)
@ -5512,7 +5513,7 @@ bool32 CanBeSlept(u32 battler, u32 ability, enum SleepClauseBlock isBlockedBySle
|| gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityOnSide(battler, ABILITY_SWEET_VEIL)
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -5527,7 +5528,7 @@ bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|| defAbility == ABILITY_COMATOSE
|| defAbility == ABILITY_PURIFYING_SALT
|| IsAbilityOnSide(battlerDef, ABILITY_PASTEL_VEIL)
|| IsAbilityStatusProtected(battlerDef)
|| IsAbilityStatusProtected(battlerDef, defAbility)
|| IsBattlerTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -5543,7 +5544,7 @@ bool32 CanBeBurned(u32 battler, u32 ability)
|| ability == ABILITY_COMATOSE
|| ability == ABILITY_THERMAL_EXCHANGE
|| ability == ABILITY_PURIFYING_SALT
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -5557,7 +5558,7 @@ bool32 CanBeParalyzed(u32 battler, u32 ability)
|| ability == ABILITY_COMATOSE
|| ability == ABILITY_PURIFYING_SALT
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -5573,7 +5574,7 @@ bool32 CanBeFrozen(u32 battler)
|| ability == ABILITY_COMATOSE
|| ability == ABILITY_PURIFYING_SALT
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -5588,7 +5589,7 @@ bool32 CanGetFrostbite(u32 battler)
|| ability == ABILITY_COMATOSE
|| ability == ABILITY_PURIFYING_SALT
|| gBattleMons[battler].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battler)
|| IsAbilityStatusProtected(battler, ability)
|| IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
@ -7480,13 +7481,13 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
bool32 isProtected = FALSE;
if ((IsZMove(move) || IsMaxMove(move))
&& (!gProtectStructs[battlerDef].maxGuarded || GetMoveMaxEffect(move) == MAX_EFFECT_BYPASS_PROTECT))
&& (!gProtectStructs[battlerDef].maxGuarded || MoveIgnoresProtect(move)))
isProtected = FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard).
else if (gProtectStructs[battlerDef].maxGuarded && IsMoveBlockedByMaxGuard(move))
isProtected = TRUE;
else if (!gProtectStructs[battlerDef].maxGuarded // Max Guard cannot be bypassed by Unseen Fist
&& IsMoveMakingContact(move, gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST)
&& IsMoveMakingContact(move, battlerAtk)
&& GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST)
isProtected = FALSE;
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD && IsBattleMoveStatus(move) && GetMoveEffect(move) != EFFECT_COACHING)
isProtected = TRUE;
@ -7495,7 +7496,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
else if (gProtectStructs[battlerDef].protected)
isProtected = TRUE;
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_WIDE_GUARD
&& GetBattlerMoveTargetType(gBattlerAttacker, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
&& GetBattlerMoveTargetType(battlerAtk, move) & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))
isProtected = TRUE;
else if (gProtectStructs[battlerDef].banefulBunkered)
isProtected = TRUE;
@ -7510,7 +7511,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move)
else if (gProtectStructs[battlerDef].maxGuarded)
isProtected = TRUE;
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_QUICK_GUARD
&& GetChosenMovePriority(gBattlerAttacker) > 0)
&& GetChosenMovePriority(battlerAtk) > 0)
isProtected = TRUE;
else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_MAT_BLOCK
&& !IsBattleMoveStatus(move))
@ -9268,7 +9269,7 @@ static inline bool32 IsFutureSightAttackerInParty(struct DamageCalculationData *
if (GetMoveEffect(damageCalcData->move) != EFFECT_FUTURE_SIGHT)
return FALSE;
struct Pokemon *party = GetSideParty(GetBattlerSide(gBattlerAttacker));
struct Pokemon *party = GetSideParty(GetBattlerSide(damageCalcData->battlerAtk));
return &party[gWishFutureKnock.futureSightPartyIndex[damageCalcData->battlerDef]]
!= &party[gBattlerPartyIndexes[damageCalcData->battlerAtk]];
}
@ -9962,7 +9963,7 @@ bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId)
else if (holdEffect == HOLD_EFFECT_Z_CRYSTAL)
return FALSE;
else if (holdEffect == HOLD_EFFECT_BOOSTER_ENERGY
&& (gSpeciesInfo[gBattleMons[gBattlerAttacker].species].isParadox || gSpeciesInfo[gBattleMons[gBattlerTarget].species].isParadox))
&& (gSpeciesInfo[gBattleMons[battler].species].isParadox || gSpeciesInfo[gBattleMons[gBattlerTarget].species].isParadox))
return FALSE;
else
return TRUE;

View File

@ -212,7 +212,6 @@ static void ShowContestPainting(void)
gMain.state++;
break;
case 2:
SeedRng(gMain.vblankCounter1);
InitKeys();
InitContestPaintingWindow();
gMain.state++;
@ -595,4 +594,3 @@ static void CreateContestPaintingPicture(u8 contestWinnerId, bool8 isForArtist)
InitPaintingMonOamData(contestWinnerId);
LoadContestPaintingFrame(contestWinnerId, isForArtist);
}

View File

@ -1467,6 +1467,7 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] =
{gBattleAnimSpriteGfx_PurpleChain, 0x1000, ANIM_TAG_PURPLE_CHAIN},
{gBattleAnimSpriteGfx_PinkVioletOrb, 0x0080, ANIM_TAG_PINKVIO_ORB},
{gBattleAnimSpriteGfx_TeraStarstormBeam, 0x200, ANIM_TAG_STARSTORM},
{gBattleAnimSpriteGfx_SaltParticle, 0x400, ANIM_TAG_SALT_PARTICLE},
};
const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
@ -1935,6 +1936,7 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] =
{gBattleAnimSpritePal_PurpleChain, ANIM_TAG_PURPLE_CHAIN},
{gBattleAnimSpritePal_PinkVioletOrb, ANIM_TAG_PINKVIO_ORB},
{gBattleAnimSpritePal_TeraStarstormBeam, ANIM_TAG_STARSTORM},
{gBattleAnimSpritePal_SaltParticle, ANIM_TAG_SALT_PARTICLE},
};
const struct BattleAnimBackground gBattleAnimBackgroundTable[] =

View File

@ -15152,7 +15152,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
{
.name = COMPOUND_STRING("Nuzzle"),
.description = COMPOUND_STRING(
"Rubs its cheecks against\n"
"Rubs its cheeks against\n"
"the foe, paralyzing it."),
.effect = EFFECT_HIT,
.power = 20,
@ -21249,8 +21249,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_SUN },
.battleAnimScript = gBattleAnimMove_MaxFlare,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SUN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_FLUTTERBY] =
@ -21265,8 +21269,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_SP_ATK },
.battleAnimScript = gBattleAnimMove_MaxFlutterby,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_SP_ATK_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_LIGHTNING] =
@ -21281,8 +21289,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_ELECTRIC_TERRAIN },
.battleAnimScript = gBattleAnimMove_MaxLightning,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_ELECTRIC_TERRAIN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_STRIKE] =
@ -21297,8 +21309,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_SPEED },
.battleAnimScript = gBattleAnimMove_MaxStrike,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_SPEED_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_KNUCKLE] =
@ -21313,8 +21329,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_ATTACK },
.battleAnimScript = gBattleAnimMove_MaxKnuckle,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAISE_TEAM_ATTACK,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_PHANTASM] =
@ -21329,8 +21349,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_DEFENSE },
.battleAnimScript = gBattleAnimMove_MaxPhantasm,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_DEFENSE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_HAILSTORM] =
@ -21345,8 +21369,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_HAIL },
.battleAnimScript = gBattleAnimMove_MaxHailstorm,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_HAIL,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_OOZE] =
@ -21361,8 +21389,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SP_ATK },
.battleAnimScript = gBattleAnimMove_MaxOoze,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_ATK,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_GEYSER] =
@ -21377,8 +21409,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAIN },
.battleAnimScript = gBattleAnimMove_MaxGeyser,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAIN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_AIRSTREAM] =
@ -21393,8 +21429,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SPEED },
.battleAnimScript = gBattleAnimMove_MaxAirstream,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAISE_TEAM_SPEED,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_STARFALL] =
@ -21409,8 +21449,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_MISTY_TERRAIN },
.battleAnimScript = gBattleAnimMove_MaxStarfall,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_MISTY_TERRAIN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_WYRMWIND] =
@ -21425,8 +21469,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_ATTACK },
.battleAnimScript = gBattleAnimMove_MaxWyrmwind,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_ATTACK_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_MINDSTORM] =
@ -21441,8 +21489,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_PSYCHIC_TERRAIN },
.battleAnimScript = gBattleAnimMove_MaxMindstorm,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PSYCHIC_TERRAIN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_ROCKFALL] =
@ -21457,8 +21509,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_SANDSTORM },
.battleAnimScript = gBattleAnimMove_MaxRockfall,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SANDSTORM,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_QUAKE] =
@ -21473,9 +21529,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_SP_DEF },
.skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS,
.battleAnimScript = gBattleAnimMove_MaxQuake,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAISE_TEAM_SP_DEF,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_DARKNESS] =
@ -21490,8 +21550,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_SP_DEF },
.battleAnimScript = gBattleAnimMove_MaxDarkness,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_SP_DEF_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_OVERGROWTH] =
@ -21506,8 +21570,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_GRASSY_TERRAIN },
.battleAnimScript = gBattleAnimMove_MaxOvergrowth,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_GRASSY_TERRAIN,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_MAX_STEELSPIKE] =
@ -21522,8 +21590,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RAISE_TEAM_DEFENSE },
.battleAnimScript = gBattleAnimMove_MaxSteelspike,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RAISE_TEAM_DEFENSE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_VINE_LASH] =
@ -21538,8 +21610,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_VINE_LASH },
.battleAnimScript = gBattleAnimMove_GMaxVineLash,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_VINE_LASH,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_WILDFIRE] =
@ -21554,8 +21630,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_WILDFIRE },
.battleAnimScript = gBattleAnimMove_GMaxWildfire,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_WILDFIRE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_CANNONADE] =
@ -21570,8 +21650,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_CANNONADE },
.battleAnimScript = gBattleAnimMove_GMaxCannonade,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_CANNONADE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_BEFUDDLE] =
@ -21586,8 +21670,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_EFFECT_SPORE_FOES },
.battleAnimScript = gBattleAnimMove_GMaxBefuddle,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_EFFECT_SPORE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_VOLT_CRASH] =
@ -21602,8 +21690,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_PARALYZE_FOES },
.battleAnimScript = gBattleAnimMove_GMaxVoltCrash,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PARALYZE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_GOLD_RUSH] =
@ -21618,8 +21710,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_CONFUSE_FOES_PAY_DAY },
.battleAnimScript = gBattleAnimMove_GMaxGoldRush,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_CHI_STRIKE] =
@ -21634,8 +21730,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_CRIT_PLUS },
.battleAnimScript = gBattleAnimMove_GMaxChiStrike,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_CRIT_PLUS_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_TERROR] =
@ -21650,8 +21750,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_MEAN_LOOK },
.battleAnimScript = gBattleAnimMove_GMaxTerror,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_PREVENT_ESCAPE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_FOAM_BURST] =
@ -21666,8 +21770,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_SPEED_2_FOES },
.battleAnimScript = gBattleAnimMove_GMaxFoamBurst,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_SPEED_2_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_RESONANCE] =
@ -21682,8 +21790,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_AURORA_VEIL },
.battleAnimScript = gBattleAnimMove_GMaxResonance,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_AURORA_VEIL,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_CUDDLE] =
@ -21698,8 +21810,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_INFATUATE_FOES },
.battleAnimScript = gBattleAnimMove_GMaxCuddle,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_INFATUATE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_REPLENISH] =
@ -21714,8 +21830,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_RECYCLE_BERRIES },
.battleAnimScript = gBattleAnimMove_GMaxReplenish,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_RECYCLE_BERRIES,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_MALODOR] =
@ -21730,8 +21850,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_POISON_FOES },
.battleAnimScript = gBattleAnimMove_GMaxMalodor,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_POISON_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_MELTDOWN] =
@ -21746,8 +21870,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_TORMENT_FOES },
.battleAnimScript = gBattleAnimMove_GMaxMeltdown,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_TORMENT_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_DRUM_SOLO] =
@ -21762,9 +21890,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_FIXED_POWER },
.ignoresTargetAbility = TRUE,
.battleAnimScript = gBattleAnimMove_GMaxDrumSolo,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FIXED_POWER,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_FIREBALL] =
@ -21779,9 +21911,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_FIXED_POWER },
.ignoresTargetAbility = TRUE,
.battleAnimScript = gBattleAnimMove_GMaxFireball,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FIXED_POWER,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_HYDROSNIPE] =
@ -21796,9 +21932,13 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_FIXED_POWER },
.ignoresTargetAbility = TRUE,
.battleAnimScript = gBattleAnimMove_GMaxHydrosnipe,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FIXED_POWER,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_WIND_RAGE] =
@ -21813,8 +21953,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_DEFOG },
.battleAnimScript = gBattleAnimMove_GMaxWindRage,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_DEFOG,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_GRAVITAS] =
@ -21829,8 +21973,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_GRAVITY },
.battleAnimScript = gBattleAnimMove_GMaxGravitas,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_GRAVITY,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_STONESURGE] =
@ -21845,8 +21993,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_STEALTH_ROCK },
.battleAnimScript = gBattleAnimMove_GMaxStonesurge,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_STEALTH_ROCK,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_VOLCALITH] =
@ -21861,8 +22013,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_VOLCALITH },
.battleAnimScript = gBattleAnimMove_GMaxVolcalith,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_VOLCALITH,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_TARTNESS] =
@ -21877,8 +22033,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_LOWER_EVASIVENESS_FOES },
.battleAnimScript = gBattleAnimMove_GMaxTartness,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_LOWER_EVASIVENESS_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_SWEETNESS] =
@ -21893,8 +22053,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_AROMATHERAPY },
.battleAnimScript = gBattleAnimMove_GMaxSweetness,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_AROMATHERAPY,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_SANDBLAST] =
@ -21909,8 +22073,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_SANDBLAST_FOES },
.battleAnimScript = gBattleAnimMove_GMaxSandblast,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SANDBLAST_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_STUN_SHOCK] =
@ -21925,8 +22093,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_POISON_PARALYZE_FOES },
.battleAnimScript = gBattleAnimMove_GMaxStunShock,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_POISON_PARALYZE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_CENTIFERNO] =
@ -21941,8 +22113,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_FIRE_SPIN_FOES },
.battleAnimScript = gBattleAnimMove_GMaxCentiferno,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_FIRE_SPIN_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_SMITE] =
@ -21957,8 +22133,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_CONFUSE_FOES },
.battleAnimScript = gBattleAnimMove_GMaxSmite,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_CONFUSE_SIDE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
@ -21974,8 +22154,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_YAWN_FOE },
.battleAnimScript = gBattleAnimMove_GMaxSnooze,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_YAWN_FOE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_FINALE] =
@ -21990,8 +22174,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_HEAL_TEAM },
.battleAnimScript = gBattleAnimMove_GMaxFinale,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_HEAL_TEAM,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_STEELSURGE] =
@ -22006,8 +22194,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_STEELSURGE },
.battleAnimScript = gBattleAnimMove_GMaxSteelsurge,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_STEELSURGE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_DEPLETION] =
@ -22022,8 +22214,12 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_SPITE },
.battleAnimScript = gBattleAnimMove_GMaxDepletion,
.additionalEffects = ADDITIONAL_EFFECTS({
.moveEffect = MOVE_EFFECT_SPITE,
.chance = 100,
.sheerForceBoost = SHEER_FORCE_NO_BOOST,
}),
},
[MOVE_G_MAX_ONE_BLOW] =
@ -22038,14 +22234,14 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_BYPASS_PROTECT },
.ignoresProtect = TRUE,
.battleAnimScript = gBattleAnimMove_GMaxOneBlow,
},
[MOVE_G_MAX_RAPID_FLOW] =
{
.name = COMPOUND_STRING("G-Max Rapid Flow"),
.description = sNullDescription, //ANIM TODO
.description = sNullDescription,
.effect = EFFECT_MAX_MOVE,
.power = 10,
.type = TYPE_WATER,
@ -22054,8 +22250,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.argument = { .maxEffect = MAX_EFFECT_BYPASS_PROTECT },
.ignoresProtect = TRUE,
.battleAnimScript = gBattleAnimMove_GMaxRapidFlow,
},
};

View File

@ -660,6 +660,7 @@ static const u8 *const sActionStringTable[] =
[PARTY_MSG_WHICH_APPLIANCE] = gText_WhichAppliance,
[PARTY_MSG_CHOOSE_SECOND_FUSION] = gText_NextFusionMon,
[PARTY_MSG_NO_POKEMON] = COMPOUND_STRING("You have no POKéMON."),
[PARTY_MSG_CHOOSE_MON_FOR_BOX] = gText_SendWhichMonToPC,
};
static const u8 *const sDescriptionStringTable[] =

View File

@ -21,6 +21,7 @@
#include "list_menu.h"
#include "overworld.h"
#include "item.h"
#include "regions.h"
#include "constants/form_change_types.h"
#include "constants/items.h"
#include "constants/hold_effects.h"
@ -243,7 +244,7 @@ static void TransferEggMoves(void)
}
}
static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
{
if (MonHasMail(mon))
{
@ -549,14 +550,15 @@ static void _TriggerPendingDaycareEgg(struct DayCare *daycare)
{
s32 parent;
s32 natureTries = 0;
rng_value_t personalityRand;
SeedRng2(gMain.vblankCounter2);
personalityRand = LocalRandomSeed(gMain.vblankCounter2);
parent = GetParentToInheritNature(daycare);
// don't inherit nature
if (parent < 0)
{
daycare->offspringPersonality = (Random2() << 16) | ((Random() % 0xfffe) + 1);
daycare->offspringPersonality = (LocalRandom(&personalityRand) << 16) | ((Random() % 0xfffe) + 1);
}
// inherit nature
else
@ -566,7 +568,7 @@ static void _TriggerPendingDaycareEgg(struct DayCare *daycare)
do
{
personality = (Random2() << 16) | (Random());
personality = (LocalRandom(&personalityRand) << 16) | (Random());
if (wantedNature == GetNatureFromPersonality(personality) && personality != 0)
break; // found a personality with the same nature
@ -985,9 +987,12 @@ STATIC_ASSERT(P_SCATTERBUG_LINE_FORM_BREED == SPECIES_SCATTERBUG_ICY_SNOW || (P_
static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parentSlots)
{
u16 i;
u16 species[DAYCARE_MON_COUNT];
u16 eggSpecies;
u32 i;
u32 species[DAYCARE_MON_COUNT];
u32 eggSpecies, parentSpecies;
bool32 hasMotherEverstone, hasFatherEverstone, motherIsForeign, fatherIsForeign;
bool32 motherEggSpecies, fatherEggSpecies;
u32 currentRegion = GetCurrentRegion();
for (i = 0; i < DAYCARE_MON_COUNT; i++)
{
@ -1004,7 +1009,24 @@ static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parent
}
}
eggSpecies = GetEggSpecies(species[parentSlots[0]]);
motherEggSpecies = GetEggSpecies(species[parentSlots[0]]);
fatherEggSpecies = GetEggSpecies(species[parentSlots[1]]);
hasMotherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[0]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE;
hasFatherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[1]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE;
motherIsForeign = IsSpeciesForeignRegionalForm(motherEggSpecies, currentRegion);
fatherIsForeign = IsSpeciesForeignRegionalForm(fatherEggSpecies, currentRegion);
if (hasMotherEverstone)
parentSpecies = motherEggSpecies;
else if (fatherIsForeign && hasFatherEverstone)
parentSpecies = fatherEggSpecies;
else if (motherIsForeign)
parentSpecies = GetRegionalFormByRegion(motherEggSpecies, currentRegion);
else
parentSpecies = motherEggSpecies;
eggSpecies = GetEggSpecies(parentSpecies);
if (eggSpecies == SPECIES_NIDORAN_F && daycare->offspringPersonality & EGG_GENDER_MALE)
eggSpecies = SPECIES_NIDORAN_M;
else if (eggSpecies == SPECIES_ILLUMISE && daycare->offspringPersonality & EGG_GENDER_MALE)
@ -1049,6 +1071,9 @@ static void _GiveEggFromDaycare(struct DayCare *daycare)
u8 parentSlots[DAYCARE_MON_COUNT] = {0};
bool8 isEgg;
if (GetDaycareCompatibilityScore(daycare) == PARENTS_INCOMPATIBLE)
return;
species = DetermineEggSpeciesAndParentSlots(daycare, parentSlots);
if (P_INCENSE_BREEDING < GEN_9)
AlterEggSpeciesWithIncenseItem(&species, daycare);
@ -1566,4 +1591,3 @@ static u8 ModifyBreedingScoreForOvalCharm(u8 score)
return score;
}

View File

@ -186,7 +186,7 @@ static void SetSpriteDataForNormalStep(struct Sprite *, u8, u8);
static void InitSpriteForFigure8Anim(struct Sprite *);
static bool8 AnimateSpriteInFigure8(struct Sprite *);
u8 GetDirectionToFace(s16 x1, s16 y1, s16 x2, s16 y2);
static void FollowerSetGraphics(struct ObjectEvent *, u16, u8, bool8);
static void FollowerSetGraphics(struct ObjectEvent * objectEvent, u32 species, bool32 shiny, bool32 female);
static void ObjectEventSetGraphics(struct ObjectEvent *, const struct ObjectEventGraphicsInfo *);
static void SpriteCB_VirtualObject(struct Sprite *);
static void DoShadowFieldEffect(struct ObjectEvent *);
@ -197,13 +197,16 @@ static u8 DoJumpSpriteMovement(struct Sprite *);
static u8 DoJumpSpecialSpriteMovement(struct Sprite *);
static void CreateLevitateMovementTask(struct ObjectEvent *);
static void DestroyLevitateMovementTask(u8);
static bool8 GetFollowerInfo(u16 *species, u8 *form, u8 *shiny);
static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool32 shiny);
static const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u16 species, u8 form);
static bool8 GetFollowerInfo(u32 *species, bool32 *shiny, bool32 *female);
static u32 LoadDynamicFollowerPalette(u32 species, bool32 shiny, bool32 female);
static const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u32 species, bool32 shiny, bool32 female);
static bool8 NpcTakeStep(struct Sprite *);
static bool8 AreElevationsCompatible(u8, u8);
static void CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(u16 graphicsId, u16 movementType, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables);
static u16 GetGraphicsIdForMon(u32 species, bool32 shiny, bool32 female);
static u16 GetUnownSpecies(struct Pokemon *mon);
static const struct SpriteFrameImage sPicTable_PechaBerryTree[];
static void StartSlowRunningAnim(struct ObjectEvent *objectEvent, struct Sprite *sprite, u8 direction);
@ -1678,17 +1681,8 @@ static u8 TrySetupObjectEventSprite(const struct ObjectEventTemplate *objectEven
if (OW_GFX_COMPRESS)
spriteTemplate->tileTag = LoadSheetGraphicsInfo(graphicsInfo, objectEvent->graphicsId, NULL);
if (objectEvent->graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG)
{
if (objectEvent->graphicsId & OBJ_EVENT_MON && objectEvent->graphicsId & OBJ_EVENT_MON_SHINY)
objectEvent->shiny = TRUE;
objectEvent->graphicsId -= SPECIES_SHINY_TAG;
}
if (objectEvent->graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG)
{
objectEvent->shiny = TRUE;
objectEvent->graphicsId -= SPECIES_SHINY_TAG;
}
spriteId = CreateSprite(spriteTemplate, 0, 0, 0);
if (spriteId == MAX_SPRITES)
@ -1700,7 +1694,7 @@ static u8 TrySetupObjectEventSprite(const struct ObjectEventTemplate *objectEven
sprite = &gSprites[spriteId];
// Use palette from species palette table
if (spriteTemplate->paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
sprite->oam.paletteNum = LoadDynamicFollowerPalette(OW_SPECIES(objectEvent), OW_FORM(objectEvent), objectEvent->shiny);
sprite->oam.paletteNum = LoadDynamicFollowerPalette(OW_SPECIES(objectEvent), OW_SHINY(objectEvent), OW_FEMALE(objectEvent));
if (OW_GFX_COMPRESS && sprite->usingSheet)
sprite->sheetSpan = GetSpanPerImage(sprite->oam.shape, sprite->oam.size);
GetMapCoordsFromSpritePos(objectEvent->currentCoords.x + cameraX, objectEvent->currentCoords.y + cameraY, &sprite->x, &sprite->y);
@ -1812,13 +1806,20 @@ static void UNUSED MakeSpriteTemplateFromObjectEventTemplate(const struct Object
// Loads information from graphicsId, with shininess separate
// also can write palette tag to the template
static u8 LoadDynamicFollowerPaletteFromGraphicsId(u16 graphicsId, bool8 shiny, struct SpriteTemplate *template)
static u32 LoadDynamicFollowerPaletteFromGraphicsId(u16 graphicsId, struct SpriteTemplate *template)
{
u16 species = ((graphicsId & OBJ_EVENT_GFX_SPECIES_MASK) - OBJ_EVENT_GFX_MON_BASE);
u8 form = (graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS);
u8 paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
u16 species = graphicsId & OBJ_EVENT_MON_SPECIES_MASK;
bool32 shiny = graphicsId & OBJ_EVENT_MON_SHINY;
bool32 female = graphicsId & OBJ_EVENT_MON_FEMALE;
u8 paletteNum = LoadDynamicFollowerPalette(species, shiny, female);
if (template)
template->paletteTag = species;
{
template->paletteTag = species + OBJ_EVENT_MON;
if (shiny)
template->paletteTag += OBJ_EVENT_MON_SHINY;
if (female)
template->paletteTag += OBJ_EVENT_MON_FEMALE;
}
return paletteNum;
}
@ -1830,7 +1831,7 @@ u8 CreateObjectGraphicsSprite(u16 graphicsId, void (*callback)(struct Sprite *),
const struct ObjectEventGraphicsInfo *graphicsInfo = GetObjectEventGraphicsInfo(graphicsId);
struct Sprite *sprite;
u8 spriteId;
bool32 isShiny = graphicsId >= SPECIES_SHINY_TAG + OBJ_EVENT_GFX_MON_BASE;
bool32 isShiny = graphicsId & OBJ_EVENT_MON_SHINY;
spriteTemplate = Alloc(sizeof(struct SpriteTemplate));
CopyObjectGraphicsInfoToSpriteTemplate(graphicsId, callback, spriteTemplate, &subspriteTables);
@ -1847,52 +1848,7 @@ u8 CreateObjectGraphicsSprite(u16 graphicsId, void (*callback)(struct Sprite *),
if (spriteTemplate->paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
{
u32 paletteNum = LoadDynamicFollowerPaletteFromGraphicsId(graphicsId, isShiny, spriteTemplate);
spriteTemplate->paletteTag = GetSpritePaletteTagByPaletteNum(paletteNum);
}
else if (spriteTemplate->paletteTag != TAG_NONE)
{
LoadObjectEventPalette(spriteTemplate->paletteTag);
}
spriteId = CreateSprite(spriteTemplate, x, y, subpriority);
Free(spriteTemplate);
if (spriteId != MAX_SPRITES && subspriteTables != NULL)
{
sprite = &gSprites[spriteId];
if (OW_GFX_COMPRESS && graphicsInfo->compressed)
sprite->sheetSpan = GetSpanPerImage(sprite->oam.shape, sprite->oam.size);
SetSubspriteTables(sprite, subspriteTables);
sprite->subspriteMode = SUBSPRITES_IGNORE_PRIORITY;
}
return spriteId;
}
// Horrible workaround for sprite the visualizer, this should probably be reworked later
u8 CreateObjectGraphicsFollowerSpriteForVisualizer(u16 graphicsId, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, struct FollowerSpriteVisualizerData *data)
{
struct SpriteTemplate *spriteTemplate;
const struct SubspriteTable *subspriteTables;
const struct ObjectEventGraphicsInfo *graphicsInfo = GetObjectEventGraphicsInfo(graphicsId);
struct Sprite *sprite;
u8 spriteId;
bool32 isShiny = data->isShiny;
spriteTemplate = Alloc(sizeof(struct SpriteTemplate));
CopyObjectGraphicsInfoToSpriteTemplate(graphicsId, callback, spriteTemplate, &subspriteTables);
if (OW_GFX_COMPRESS)
{
// Checking only for compressed here so as not to mess with decorations
if (graphicsInfo->compressed)
spriteTemplate->tileTag = LoadSheetGraphicsInfo(graphicsInfo, graphicsId, NULL);
}
if (spriteTemplate->paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
{
u32 paletteNum = LoadDynamicFollowerPaletteFromGraphicsId(graphicsId, isShiny, spriteTemplate);
u32 paletteNum = LoadDynamicFollowerPaletteFromGraphicsId(graphicsId, spriteTemplate);
spriteTemplate->paletteTag = GetSpritePaletteTagByPaletteNum(paletteNum);
}
else if (spriteTemplate->paletteTag != TAG_NONE)
@ -1988,19 +1944,18 @@ struct ObjectEvent *GetFollowerObject(void)
}
// Return graphicsInfo for a pokemon species & form
static const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u16 species, u8 form)
static const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u32 species, bool32 shiny, bool32 female)
{
const struct ObjectEventGraphicsInfo *graphicsInfo = NULL;
#if OW_POKEMON_OBJECT_EVENTS
switch (species)
{
case SPECIES_UNOWN: // Letters >A are defined as species >= NUM_SPECIES, so are not contiguous with A
form %= NUM_UNOWN_FORMS;
graphicsInfo = &gSpeciesInfo[form ? SPECIES_UNOWN_B + form - 1 : species].overworldData;
case SPECIES_UNOWN: // Deal with Unown forms later
graphicsInfo = &gSpeciesInfo[species].overworldData;
break;
default:
#if P_GENDER_DIFFERENCES
if (form == 1 && gSpeciesInfo[species].overworldDataFemale.paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
if (female && gSpeciesInfo[species].overworldDataFemale.paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
{
graphicsInfo = &gSpeciesInfo[species].overworldDataFemale;
}
@ -2024,17 +1979,18 @@ static const struct ObjectEventGraphicsInfo *SpeciesToGraphicsInfo(u16 species,
}
// Find, or load, the palette for the specified pokemon info
static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool32 shiny)
static u32 LoadDynamicFollowerPalette(u32 species, bool32 shiny, bool32 female)
{
u32 paletteNum;
bool32 female = (form == 1);
// Use standalone palette, unless entry is OOB or NULL (fallback to front-sprite-based)
#if OW_POKEMON_OBJECT_EVENTS == TRUE && OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE
if ((shiny && gSpeciesInfo[species].overworldPalette)
|| (!shiny && gSpeciesInfo[species].overworldShinyPalette))
{
struct SpritePalette spritePalette;
u16 palTag = shiny ? (species + SPECIES_SHINY_TAG + OBJ_EVENT_PAL_TAG_DYNAMIC) : (species + OBJ_EVENT_PAL_TAG_DYNAMIC);
u16 palTag = species + OBJ_EVENT_MON + (shiny ? OBJ_EVENT_MON_SHINY : 0);
if (female && gSpeciesInfo[species].overworldShinyPaletteFemale != NULL)
palTag += OBJ_EVENT_MON_FEMALE;
// palette already loaded
if ((paletteNum = IndexOfSpritePaletteTag(palTag)) < 16)
return paletteNum;
@ -2091,13 +2047,11 @@ static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool32 shiny)
}
// Set graphics & sprite for a follower object event by species & shininess.
static void FollowerSetGraphics(struct ObjectEvent *objEvent, u16 species, u8 form, bool8 shiny)
static void FollowerSetGraphics(struct ObjectEvent *objEvent, u32 species, bool32 shiny, bool32 female)
{
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, form);
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, shiny, female);
ObjectEventSetGraphics(objEvent, graphicsInfo);
objEvent->graphicsId = (OBJ_EVENT_GFX_MON_BASE + species) & OBJ_EVENT_GFX_SPECIES_MASK;
objEvent->graphicsId |= form << OBJ_EVENT_GFX_SPECIES_BITS;
objEvent->shiny = shiny;
objEvent->graphicsId = GetGraphicsIdForMon(species, shiny, female);
if (graphicsInfo->paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC) // Use palette from species palette table
{
struct Sprite *sprite = &gSprites[objEvent->spriteId];
@ -2105,7 +2059,7 @@ static void FollowerSetGraphics(struct ObjectEvent *objEvent, u16 species, u8 fo
sprite->inUse = FALSE;
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
sprite->inUse = TRUE;
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, shiny, female);
}
else if (gWeatherPtr->currWeather != WEATHER_FOG_HORIZONTAL) // don't want to weather blend in fog
{
@ -2118,9 +2072,9 @@ static void FollowerSetGraphics(struct ObjectEvent *objEvent, u16 species, u8 fo
static void RefreshFollowerGraphics(struct ObjectEvent *objEvent)
{
u32 species = OW_SPECIES(objEvent);
u32 form = OW_FORM(objEvent);
u32 shiny = objEvent->shiny;
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, form);
bool32 shiny = OW_SHINY(objEvent);
bool32 female = OW_FEMALE(objEvent);
const struct ObjectEventGraphicsInfo *graphicsInfo = SpeciesToGraphicsInfo(species, shiny, female);
struct Sprite *sprite = &gSprites[objEvent->spriteId];
u32 i = FindObjectEventPaletteIndexByTag(graphicsInfo->paletteTag);
@ -2149,7 +2103,7 @@ static void RefreshFollowerGraphics(struct ObjectEvent *objEvent)
sprite->inUse = FALSE;
FieldEffectFreePaletteIfUnused(sprite->oam.paletteNum);
sprite->inUse = TRUE;
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, form, shiny);
sprite->oam.paletteNum = LoadDynamicFollowerPalette(species, shiny, female);
}
else if (i != 0xFF)
{
@ -2179,23 +2133,22 @@ u16 GetOverworldWeatherSpecies(u16 species)
return species;
}
static bool8 GetMonInfo(struct Pokemon *mon, u16 *species, u8 *form, u8 *shiny)
static bool8 GetMonInfo(struct Pokemon *mon, u32 *species, bool32 *shiny, bool32 *female)
{
*form = 0; // default
if (!mon)
{
*species = SPECIES_NONE;
*form = 0;
*shiny = 0;
*shiny = FALSE;
*female = FALSE;
return FALSE;
}
*species = GetMonData(mon, MON_DATA_SPECIES);
*form = GetMonGender(mon) == MON_FEMALE;
*shiny = IsMonShiny(mon);
*shiny = IsMonShiny(mon) ? OBJ_EVENT_MON_SHINY : 0;
*female = GetMonGender(mon) == MON_FEMALE ? OBJ_EVENT_MON_FEMALE : 0;
switch (*species)
{
case SPECIES_UNOWN:
*form = GET_UNOWN_LETTER(mon->box.personality);
*species = GetUnownSpecies(mon);
break;
default:
*species = GetOverworldWeatherSpecies(*species);
@ -2205,9 +2158,9 @@ static bool8 GetMonInfo(struct Pokemon *mon, u16 *species, u8 *form, u8 *shiny)
}
// Retrieve graphic information about the following pokemon, if any
static bool8 GetFollowerInfo(u16 *species, u8 *form, u8 *shiny)
static bool8 GetFollowerInfo(u32 *species, bool32 *shiny, bool32 *female)
{
return GetMonInfo(GetFirstLiveMon(), species, form, shiny);
return GetMonInfo(GetFirstLiveMon(), species, shiny, female);
}
// Update following pokemon if any
@ -2215,18 +2168,18 @@ void UpdateFollowingPokemon(void)
{
struct ObjectEvent *objEvent = GetFollowerObject();
struct Sprite *sprite;
u16 species;
bool8 shiny;
u8 form;
u32 species;
bool32 shiny;
bool32 female;
// Don't spawn follower if:
// 1. GetFollowerInfo returns FALSE
// 2. Map is indoors and gfx is larger than 32x32
// 3. flag is set
if (OW_POKEMON_OBJECT_EVENTS == FALSE
|| OW_FOLLOWERS_ENABLED == FALSE
|| !GetFollowerInfo(&species, &form, &shiny)
|| SpeciesToGraphicsInfo(species, form) == NULL
|| (gMapHeader.mapType == MAP_TYPE_INDOOR && SpeciesToGraphicsInfo(species, form)->oam->size > ST_OAM_SIZE_2)
|| !GetFollowerInfo(&species, &shiny, &female)
|| SpeciesToGraphicsInfo(species, shiny, female) == NULL
|| (gMapHeader.mapType == MAP_TYPE_INDOOR && SpeciesToGraphicsInfo(species, shiny, female)->oam->size > ST_OAM_SIZE_2)
|| FlagGet(FLAG_TEMP_HIDE_FOLLOWER))
{
RemoveFollowingPokemon();
@ -2240,7 +2193,7 @@ void UpdateFollowingPokemon(void)
struct ObjectEventTemplate template =
{
.localId = OBJ_EVENT_ID_FOLLOWER,
.graphicsId = OBJ_EVENT_GFX_MON_BASE + species,
.graphicsId = GetGraphicsIdForMon(species, shiny, female),
.flagId = 0,
.x = gSaveBlock1Ptr->pos.x,
.y = gSaveBlock1Ptr->pos.y,
@ -2248,7 +2201,7 @@ void UpdateFollowingPokemon(void)
.elevation = gObjectEvents[objId].active ? gObjectEvents[objId].currentElevation : 3,
.movementType = MOVEMENT_TYPE_FOLLOW_PLAYER,
// store form info in template
.trainerRange_berryTreeId = (form & 0x1F) | (shiny << 5),
//.trainerRange_berryTreeId = (form & 0x1F) | (shiny << 5), // ???? what?
};
if ((objId = SpawnSpecialObjectEvent(&template)) >= OBJECT_EVENTS_COUNT)
return;
@ -2257,12 +2210,12 @@ void UpdateFollowingPokemon(void)
}
sprite = &gSprites[objEvent->spriteId];
// Follower appearance changed; move to player and set invisible
if (species != OW_SPECIES(objEvent) || shiny != objEvent->shiny || form != OW_FORM(objEvent))
if (species != OW_SPECIES(objEvent) || shiny != OW_SHINY(objEvent) || female != OW_FEMALE(objEvent))
{
MoveObjectEventToMapCoords(objEvent,
gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x,
gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y);
FollowerSetGraphics(objEvent, species, form, shiny);
FollowerSetGraphics(objEvent, species, shiny, female);
objEvent->invisible = TRUE;
}
sprite->data[6] = 0; // set animation data
@ -2703,7 +2656,7 @@ static void SpawnObjectEventOnReturnToField(u8 objectEventId, s16 x, s16 y)
if (spriteTemplate.paletteTag == OBJ_EVENT_PAL_TAG_DYNAMIC)
{
u32 paletteNum = LoadDynamicFollowerPalette(OW_SPECIES(objectEvent), OW_FORM(objectEvent), objectEvent->shiny);
u32 paletteNum = LoadDynamicFollowerPalette(OW_SPECIES(objectEvent), OW_SHINY(objectEvent), OW_FEMALE(objectEvent));
spriteTemplate.paletteTag = GetSpritePaletteTagByPaletteNum(paletteNum);
}
else if (spriteTemplate.paletteTag != TAG_NONE)
@ -2898,24 +2851,14 @@ static void SetBerryTreeGraphics(struct ObjectEvent *objectEvent, struct Sprite
const struct ObjectEventGraphicsInfo *GetObjectEventGraphicsInfo(u16 graphicsId)
{
u32 form = 0;
if (graphicsId >= OBJ_EVENT_GFX_VARS && graphicsId <= OBJ_EVENT_GFX_VAR_F)
graphicsId = VarGetObjectEventGraphicsId(graphicsId - OBJ_EVENT_GFX_VARS);
if (graphicsId > OBJ_EVENT_GFX_SPECIES_MASK)
{
form = graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS;
graphicsId = graphicsId & OBJ_EVENT_GFX_SPECIES_MASK;
}
if (graphicsId == OBJ_EVENT_GFX_BARD)
{
return gMauvilleOldManGraphicsInfoPointers[GetCurrentMauvilleOldMan()];
}
if (graphicsId >= OBJ_EVENT_GFX_MON_BASE)
return SpeciesToGraphicsInfo(graphicsId - OBJ_EVENT_GFX_MON_BASE, form);
if (graphicsId & OBJ_EVENT_MON)
return SpeciesToGraphicsInfo(graphicsId & OBJ_EVENT_MON_SPECIES_MASK, graphicsId & OBJ_EVENT_MON_SHINY, graphicsId & OBJ_EVENT_MON_FEMALE);
if (graphicsId >= NUM_OBJ_EVENT_GFX)
graphicsId = OBJ_EVENT_GFX_NINJA_BOY;
@ -5398,7 +5341,7 @@ static bool8 UpdateFollowerTransformEffect(struct ObjectEvent *objectEvent, stru
objectEvent->graphicsId = multi;
break;
}
objectEvent->graphicsId += OBJ_EVENT_GFX_MON_BASE;
objectEvent->graphicsId += OBJ_EVENT_MON;
RefreshFollowerGraphics(objectEvent);
break;
case TRANSFORM_TYPE_RANDOM_WILD:
@ -5409,7 +5352,7 @@ static bool8 UpdateFollowerTransformEffect(struct ObjectEvent *objectEvent, stru
objectEvent->graphicsId = multi;
break;
}
objectEvent->graphicsId += OBJ_EVENT_GFX_MON_BASE;
objectEvent->graphicsId += OBJ_EVENT_MON;
RefreshFollowerGraphics(objectEvent);
objectEvent->graphicsId = multi;
break;
@ -7481,7 +7424,7 @@ bool8 MovementAction_ExitPokeball_Step1(struct ObjectEvent *objectEvent, struct
// Set graphics, palette, and affine animation
else if (sprite->sDuration == animStepFrame)
{
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_FORM(objectEvent), objectEvent->shiny);
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_SHINY(objectEvent), OW_FEMALE(objectEvent));
LoadFillColorPalette(RGB_WHITE, OBJ_EVENT_PAL_TAG_WHITE, sprite);
// Initialize affine animation
sprite->affineAnims = sAffineAnims_PokeballFollower;
@ -7498,7 +7441,7 @@ bool8 MovementAction_ExitPokeball_Step1(struct ObjectEvent *objectEvent, struct
sprite->affineAnimEnded = TRUE;
FreeSpriteOamMatrix(sprite);
sprite->oam.affineMode = ST_OAM_AFFINE_OFF;
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_FORM(objectEvent), objectEvent->shiny);
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_SHINY(objectEvent), OW_FEMALE(objectEvent));
}
return FALSE;
}
@ -7554,7 +7497,7 @@ bool8 MovementAction_EnterPokeball_Step1(struct ObjectEvent *objectEvent, struct
bool8 MovementAction_EnterPokeball_Step2(struct ObjectEvent *objectEvent, struct Sprite *sprite)
{
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_FORM(objectEvent), objectEvent->shiny);
FollowerSetGraphics(objectEvent, OW_SPECIES(objectEvent), OW_SHINY(objectEvent), OW_FEMALE(objectEvent));
objectEvent->invisible = TRUE;
sprite->sTypeFuncId = 0;
sprite->sSpeedFlip = 0;
@ -11016,9 +10959,9 @@ void GetDaycareGraphics(struct ScriptContext *ctx)
{
u16 varGfx[] = {ScriptReadHalfword(ctx), ScriptReadHalfword(ctx)};
u16 varForm[] = {ScriptReadHalfword(ctx), ScriptReadHalfword(ctx)};
u16 specGfx;
u8 form;
u8 shiny;
u32 specGfx;
bool32 shiny;
bool32 female;
s32 i;
Script_RequestEffects(SCREFF_V1);
@ -11029,14 +10972,17 @@ void GetDaycareGraphics(struct ScriptContext *ctx)
for (i = 0; i < 2; i++)
{
GetMonInfo((struct Pokemon *) &gSaveBlock1Ptr->daycare.mons[i].mon, &specGfx, &form, &shiny);
GetMonInfo((struct Pokemon *) &gSaveBlock1Ptr->daycare.mons[i].mon, &specGfx, &shiny, &female);
if (specGfx == SPECIES_NONE)
break;
// Assemble gfx ID like FollowerSetGraphics
specGfx = (OBJ_EVENT_GFX_MON_BASE + specGfx) & OBJ_EVENT_GFX_SPECIES_MASK;
specGfx |= form << OBJ_EVENT_GFX_SPECIES_BITS;
VarSet(varGfx[i], specGfx);
VarSet(varForm[i], form | (shiny << 5));
specGfx = specGfx + OBJ_EVENT_MON;
if (shiny)
specGfx += OBJ_EVENT_MON_SHINY;
if (female)
specGfx += OBJ_EVENT_MON_FEMALE;
VarSet(varGfx[i], (u16)specGfx);
VarSet(varForm[i], 0); // This shouldn't be needed anymore, track down
}
gSpecialVar_Result = i;
}
@ -11087,3 +11033,21 @@ bool8 MovementActionFunc_RunSlow_Step1(struct ObjectEvent *objectEvent, struct S
}
return FALSE;
}
static u16 GetGraphicsIdForMon(u32 species, bool32 shiny, bool32 female)
{
u16 graphicsId = species + OBJ_EVENT_MON;
if (shiny)
graphicsId += OBJ_EVENT_MON_SHINY;
if (female)
graphicsId += OBJ_EVENT_MON_FEMALE;
return graphicsId;
}
static u16 GetUnownSpecies(struct Pokemon *mon)
{
u32 form = GET_UNOWN_LETTER(mon->box.personality);
if (form == 0)
return SPECIES_UNOWN;
return SPECIES_UNOWN_B + form - 1;
}

View File

@ -1290,6 +1290,9 @@ const u32 gBattleAnimSpritePal_FlatRock[] = INCBIN_U32("graphics/battle_anims/sp
const u32 gBattleAnimSpriteGfx_TeraStarstormBeam[] = INCBIN_U32("graphics/battle_anims/sprites/starstorm_beam.4bpp.lz");
const u32 gBattleAnimSpritePal_TeraStarstormBeam[] = INCBIN_U32("graphics/battle_anims/sprites/starstorm_beam.gbapal.lz");
const u32 gBattleAnimSpriteGfx_SaltParticle[] = INCBIN_U32("graphics/battle_anims/sprites/salt_particle.4bpp.lz");
const u32 gBattleAnimSpritePal_SaltParticle[] = INCBIN_U32("graphics/battle_anims/sprites/salt_particle.gbapal.lz");
const u32 gBattleAnimUnusedPal_Unknown2[] = INCBIN_U32("graphics/battle_anims/unused/unknown_2.gbapal.lz");
#include "data/graphics/trainers.h"

View File

@ -235,7 +235,7 @@ void LoadObjectEvents(void)
// Try to restore saved inactive follower
if (gObjectEvents[i].localId == OBJ_EVENT_ID_FOLLOWER &&
!gObjectEvents[i].active &&
gObjectEvents[i].graphicsId >= OBJ_EVENT_GFX_MON_BASE)
gObjectEvents[i].graphicsId & OBJ_EVENT_MON)
gObjectEvents[i].active = TRUE;
}
}

View File

@ -672,18 +672,8 @@ static bool8 MainState_PressedOKButton(void)
SetInputState(INPUT_STATE_DISABLED);
SetCursorFlashing(FALSE);
TryStartButtonFlash(BUTTON_COUNT, FALSE, TRUE);
if (sNamingScreen->templateNum == NAMING_SCREEN_CAUGHT_MON
&& CalculatePlayerPartyCount() >= PARTY_SIZE)
{
DisplaySentToPCMessage();
sNamingScreen->state = STATE_WAIT_SENT_TO_PC_MESSAGE;
return FALSE;
}
else
{
sNamingScreen->state = STATE_FADE_OUT;
return TRUE;
}
sNamingScreen->state = STATE_FADE_OUT;
return TRUE;
}
static bool8 MainState_FadeOut(void)
@ -699,7 +689,11 @@ static bool8 MainState_Exit(void)
{
if (sNamingScreen->templateNum == NAMING_SCREEN_PLAYER)
SeedRngAndSetTrainerId();
SetMainCallback2(sNamingScreen->returnCallback);
if (sNamingScreen->templateNum == NAMING_SCREEN_CAUGHT_MON
&& CalculatePlayerPartyCount() < PARTY_SIZE)
SetMainCallback2(BattleMainCB2);
else
SetMainCallback2(sNamingScreen->returnCallback);
DestroyTask(FindTaskIdByFunc(Task_NamingScreen));
FreeAllWindowBuffers();
FREE_AND_SET_NULL(sNamingScreen);
@ -707,7 +701,7 @@ static bool8 MainState_Exit(void)
return FALSE;
}
static void DisplaySentToPCMessage(void)
static UNUSED void DisplaySentToPCMessage(void)
{
u8 stringToDisplay = 0;

View File

@ -174,6 +174,14 @@ enum {
#define MENU_DIR_RIGHT 2
#define MENU_DIR_LEFT -2
#define HM_MOVES_END 0xFFFF
static const u16 sHMMoves[] =
{
MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH,
MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END
};
enum {
CAN_LEARN_MOVE,
CANNOT_LEARN_MOVE,
@ -320,6 +328,7 @@ static void HandleChooseMonSelection(u8, s8 *);
static u16 PartyMenuButtonHandler(s8 *);
static s8 *GetCurrentPartySlotPtr(void);
static bool8 IsSelectedMonNotEgg(u8 *);
static bool8 DoesSelectedMonKnowHM(u8 *);
static void PartyMenuRemoveWindow(u8 *);
static void CB2_SetUpExitToBattleScreen(void);
static void Task_ClosePartyMenuAfterText(u8);
@ -1524,6 +1533,30 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr)
}
break;
}
case PARTY_ACTION_SEND_MON_TO_BOX:
{
u8 partyId = GetPartyIdFromBattleSlot((u8)*slotPtr);
if (partyId == 0 || ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && partyId == 2)
|| ((gBattleTypeFlags & BATTLE_TYPE_MULTI) && partyId >= (PARTY_SIZE / 2)))
{
// Can't select if mon is currently on the field, or doesn't belong to you
PlaySE(SE_FAILURE);
}
else if (DoesSelectedMonKnowHM((u8 *)slotPtr))
{
PlaySE(SE_FAILURE);
DisplayPartyMenuMessage(gText_CannotSendMonToBoxHM, FALSE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
}
else
{
PlaySE(SE_SELECT);
gSelectedMonPartyId = partyId;
Task_ClosePartyMenu(taskId);
}
break;
}
default:
case PARTY_ACTION_ABILITY_PREVENTS:
case PARTY_ACTION_SWITCHING:
@ -1544,6 +1577,25 @@ static bool8 IsSelectedMonNotEgg(u8 *slotPtr)
return TRUE;
}
static bool8 DoesSelectedMonKnowHM(u8 *slotPtr)
{
if (B_CATCH_SWAP_CHECK_HMS == FALSE)
return FALSE;
for (u32 i = 0; i < MAX_MON_MOVES; i++)
{
u32 j = 0;
u16 move = GetMonData(&gPlayerParty[*slotPtr], MON_DATA_MOVE1 + i);
while (sHMMoves[j] != HM_MOVES_END)
{
if (sHMMoves[j++] == move)
return TRUE;
}
}
return FALSE;
}
static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr)
{
switch (gPartyMenu.action)
@ -1561,6 +1613,11 @@ static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr)
PlaySE(SE_SELECT);
CancelParticipationPrompt(taskId);
break;
case PARTY_ACTION_SEND_MON_TO_BOX:
PlaySE(SE_SELECT);
gSelectedMonPartyId = PARTY_SIZE + 1;
Task_ClosePartyMenu(taskId);
break;
default:
PlaySE(SE_SELECT);
if (DisplayCancelChooseMonYesNo(taskId) != TRUE)
@ -1924,7 +1981,10 @@ static void Task_ReturnToChooseMonAfterText(u8 taskId)
}
else
{
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
if (gPartyMenu.action == PARTY_ACTION_SEND_MON_TO_BOX)
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON_FOR_BOX);
else
DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
gTasks[taskId].func = Task_HandleChooseMonInput;
}
}
@ -4665,8 +4725,7 @@ void ItemUseCB_Medicine(u8 taskId, TaskFunc task)
if (!IsItemFlute(item))
{
PlaySE(SE_USE_ITEM);
if (gPartyMenu.action != PARTY_ACTION_REUSABLE_ITEM)
RemoveBagItem(item, 1);
RemoveBagItem(item, 1);
}
else
{
@ -7124,7 +7183,14 @@ static u8 GetPartyLayoutFromBattleType(void)
void OpenPartyMenuInBattle(u8 partyAction)
{
InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), partyAction, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_SetUpReshowBattleScreenAfterMenu);
u8 partyMessage;
if (partyAction == PARTY_ACTION_SEND_MON_TO_BOX)
partyMessage = PARTY_MSG_CHOOSE_MON_FOR_BOX;
else
partyMessage = PARTY_MSG_CHOOSE_MON;
InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), partyAction, FALSE, partyMessage, Task_HandleChooseMonInput, CB2_SetUpReshowBattleScreenAfterMenu);
ReshowBattleScreenDummy();
UpdatePartyToBattleOrder();
}

View File

@ -993,16 +993,11 @@ static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite)
u16 wantedCryCase;
u8 taskId;
mon = GetPartyBattlerData(battlerId);
if (GetBattlerSide(battlerId) != B_SIDE_PLAYER)
{
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
pan = 25;
}
else
{
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
pan = -25;
}
if ((battlerId == GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) || battlerId == GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))
&& IsDoubleBattle() && gBattleSpritesDataPtr->animationData->introAnimActive)

View File

@ -59,6 +59,7 @@
#include "constants/items.h"
#include "constants/layouts.h"
#include "constants/moves.h"
#include "constants/regions.h"
#include "constants/songs.h"
#include "constants/trainers.h"
#include "constants/union_room.h"
@ -381,7 +382,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_ATK,
.backAnim = 0,
.pokeBlockAnim = {ANIM_HARDY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlHardy,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(61, 7, 61, 7), //32% support >= 50% HP, 32% support < 50% HP
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -393,7 +394,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_DEF,
.backAnim = 2,
.pokeBlockAnim = {ANIM_LONELY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlLonely,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighAttackLow,
.battlePalacePercents = PALACE_STYLE(20, 25, 84, 8), //55%, 8%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -405,7 +406,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPEED,
.backAnim = 0,
.pokeBlockAnim = {ANIM_BRAVE, AFFINE_TURN_UP},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlBrave,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(70, 15, 32, 60), //15%, 8%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -417,7 +418,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPATK,
.backAnim = 0,
.pokeBlockAnim = {ANIM_ADAMANT, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAdamant,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(38, 31, 70, 15), //31%, 15%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -429,7 +430,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPDEF,
.backAnim = 0,
.pokeBlockAnim = {ANIM_NAUGHTY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlNaughty,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighAttackLow,
.battlePalacePercents = PALACE_STYLE(20, 70, 70, 22), //10%, 8%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -441,7 +442,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_ATK,
.backAnim = 1,
.pokeBlockAnim = {ANIM_BOLD, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlBold,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(30, 20, 32, 58), //50%, 10%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -453,7 +454,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_DEF,
.backAnim = 1,
.pokeBlockAnim = {ANIM_DOCILE, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(56, 22, 56, 22), //22%, 22%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_RANDOM,
@ -465,7 +466,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPEED,
.backAnim = 1,
.pokeBlockAnim = {ANIM_RELAXED, AFFINE_TURN_UP_AND_DOWN},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlRelaxed,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighAttackLow,
.battlePalacePercents = PALACE_STYLE(25, 15, 75, 15), //60%, 10%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -477,7 +478,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPATK,
.backAnim = 0,
.pokeBlockAnim = {ANIM_IMPISH, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlImpish,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(69, 6, 28, 55), //25%, 17%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -489,7 +490,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPDEF,
.backAnim = 1,
.pokeBlockAnim = {ANIM_LAX, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlLax,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighSupportLow,
.battlePalacePercents = PALACE_STYLE(35, 10, 29, 6), //55%, 65%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -501,7 +502,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_ATK,
.backAnim = 2,
.pokeBlockAnim = {ANIM_TIMID, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlTimid,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighSupportLow,
.battlePalacePercents = PALACE_STYLE(62, 10, 30, 20), //28%, 50%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -513,7 +514,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_DEF,
.backAnim = 0,
.pokeBlockAnim = {ANIM_HASTY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlHasty,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(58, 37, 88, 6), //5%, 6%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -525,7 +526,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPEED,
.backAnim = 1,
.pokeBlockAnim = {ANIM_SERIOUS, AFFINE_TURN_DOWN},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSerious,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighSupportLow,
.battlePalacePercents = PALACE_STYLE(34, 11, 29, 11), //55%, 60%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -537,7 +538,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPATK,
.backAnim = 0,
.pokeBlockAnim = {ANIM_JOLLY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlJolly,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(35, 5, 35, 60), //60%, 5%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -549,7 +550,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPDEF,
.backAnim = 0,
.pokeBlockAnim = {ANIM_NAIVE, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(56, 22, 56, 22), //22%, 22%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_RANDOM,
@ -561,7 +562,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_ATK,
.backAnim = 2,
.pokeBlockAnim = {ANIM_MODEST, AFFINE_TURN_DOWN_SLOW},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlModest,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(35, 45, 34, 60), //20%, 6%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -573,7 +574,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_DEF,
.backAnim = 2,
.pokeBlockAnim = {ANIM_MILD, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlMild,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighSupportLow,
.battlePalacePercents = PALACE_STYLE(44, 50, 34, 6), //6%, 60%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -585,7 +586,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPEED,
.backAnim = 2,
.pokeBlockAnim = {ANIM_QUIET, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(56, 22, 56, 22), //22%, 22%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -597,7 +598,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPATK,
.backAnim = 2,
.pokeBlockAnim = {ANIM_BASHFUL, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlBashful,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(30, 58, 30, 58), //12%, 12%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -609,7 +610,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPDEF,
.backAnim = 1,
.pokeBlockAnim = {ANIM_RASH, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlRash,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSupportHighSupportLow,
.battlePalacePercents = PALACE_STYLE(30, 13, 27, 6), //57%, 67%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -621,7 +622,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_ATK,
.backAnim = 1,
.pokeBlockAnim = {ANIM_CALM, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlCalm,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighDefenseLow,
.battlePalacePercents = PALACE_STYLE(40, 50, 25, 62), //10%, 13%
.battlePalaceFlavorText = B_MSG_GETTING_IN_POS,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -633,7 +634,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_DEF,
.backAnim = 2,
.pokeBlockAnim = {ANIM_GENTLE, AFFINE_TURN_DOWN_SLIGHT},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlGentle,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighAttackLow,
.battlePalacePercents = PALACE_STYLE(18, 70, 90, 5), //12%, 5%
.battlePalaceFlavorText = B_MSG_GLINT_IN_EYE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -645,7 +646,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPEED,
.backAnim = 1,
.pokeBlockAnim = {ANIM_SASSY, AFFINE_TURN_UP_HIGH},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlSassy,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighSupportLow,
.battlePalacePercents = PALACE_STYLE(88, 6, 22, 20), //6%, 58%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -657,7 +658,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPATK,
.backAnim = 2,
.pokeBlockAnim = {ANIM_CAREFUL, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlCareful,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDefenseHighSupportLow,
.battlePalacePercents = PALACE_STYLE(42, 50, 42, 5), //8%, 53%
.battlePalaceFlavorText = B_MSG_GROWL_DEEPLY,
.battlePalaceSmokescreen = PALACE_TARGET_WEAKER,
@ -669,7 +670,7 @@ const struct NatureInfo gNaturesInfo[NUM_NATURES] =
.statDown = STAT_SPDEF,
.backAnim = 1,
.pokeBlockAnim = {ANIM_QUIRKY, AFFINE_NONE},
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlDocileNaiveQuietQuirky,
.natureGirlMessage = BattleFrontier_Lounge5_Text_NatureGirlAttackHighAttackLow,
.battlePalacePercents = PALACE_STYLE(56, 22, 56, 22), //22%, 22%
.battlePalaceFlavorText = B_MSG_EAGER_FOR_MORE,
.battlePalaceSmokescreen = PALACE_TARGET_STRONGER,
@ -6987,3 +6988,70 @@ uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier)
return UQ_4_12(1.0/(1.5 + 0.05 * dynamaxLevel));
return UQ_4_12(1.5 + 0.05 * dynamaxLevel);
}
bool32 IsSpeciesRegionalForm(u32 species)
{
return gSpeciesInfo[species].isAlolanForm
|| gSpeciesInfo[species].isGalarianForm
|| gSpeciesInfo[species].isHisuianForm
|| gSpeciesInfo[species].isPaldeanForm;
}
bool32 IsSpeciesRegionalFormFromRegion(u32 species, u32 region)
{
switch (region)
{
case REGION_ALOLA: return gSpeciesInfo[species].isAlolanForm;
case REGION_GALAR: return gSpeciesInfo[species].isGalarianForm;
case REGION_HISUI: return gSpeciesInfo[species].isHisuianForm;
case REGION_PALDEA: return gSpeciesInfo[species].isPaldeanForm;
default: return FALSE;
}
}
bool32 SpeciesHasRegionalForm(u32 species)
{
u32 formId;
const u16 *formTable = GetSpeciesFormTable(species);
for (formId = 0; formTable != NULL && formTable[formId] != FORM_SPECIES_END; formId++)
{
if (IsSpeciesRegionalForm(formTable[formId]))
return TRUE;
}
return FALSE;
}
u32 GetRegionalFormByRegion(u32 species, u32 region)
{
u32 formId = 0;
u32 firstFoundSpecies = 0;
const u16 *formTable = GetSpeciesFormTable(species);
if (formTable != NULL)
{
for (formId = 0; formTable[formId] != FORM_SPECIES_END; formId++)
{
if (firstFoundSpecies == 0)
firstFoundSpecies = formTable[formId];
if (IsSpeciesRegionalFormFromRegion(formTable[formId], region))
return formTable[formId];
}
if (firstFoundSpecies != 0)
return firstFoundSpecies;
}
return species;
}
bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion)
{
u32 i;
for (i = 0; i < REGIONS_COUNT; i++)
{
if (currentRegion != i && IsSpeciesRegionalFormFromRegion(species, i))
return TRUE;
else if (currentRegion == i && SpeciesHasRegionalForm(species) && !IsSpeciesRegionalFormFromRegion(species, i))
return TRUE;
}
return FALSE;
}

View File

@ -1311,7 +1311,7 @@ void CB2_Pokemon_Sprite_Visualizer(void)
gSprites[data->iconspriteId].oam.priority = 0;
//Follower Sprite
data->followerspriteId = CreateObjectGraphicsSprite(OBJ_EVENT_GFX_MON_BASE + species, SpriteCB_Follower, VISUALIZER_FOLLOWER_X, VISUALIZER_FOLLOWER_Y, 0);
data->followerspriteId = CreateObjectGraphicsSprite(OBJ_EVENT_MON + species, SpriteCB_Follower, VISUALIZER_FOLLOWER_X, VISUALIZER_FOLLOWER_Y, 0);
gSprites[data->followerspriteId].oam.priority = 0;
gSprites[data->followerspriteId].anims = sAnims_Follower;
@ -2002,18 +2002,16 @@ static void ReloadPokemonSprites(struct PokemonSpriteVisualizer *data)
gSprites[data->iconspriteId].oam.priority = 0;
//Follower Sprite
u16 graphicsId = (OBJ_EVENT_GFX_MON_BASE + species) & OBJ_EVENT_GFX_SPECIES_MASK;
struct FollowerSpriteVisualizerData followerData;
followerData.currentmonId = graphicsId;
followerData.isFemale = data->isFemale;
followerData.isShiny = data->isShiny;
graphicsId |= data->isFemale << OBJ_EVENT_GFX_SPECIES_BITS;
data->followerspriteId = CreateObjectGraphicsFollowerSpriteForVisualizer(graphicsId,
u16 graphicsId = species + OBJ_EVENT_MON;
if (data->isShiny)
graphicsId += OBJ_EVENT_MON_SHINY;
if (data->isFemale)
graphicsId += OBJ_EVENT_MON_FEMALE;
data->followerspriteId = CreateObjectGraphicsSprite(graphicsId,
SpriteCB_Follower,
VISUALIZER_FOLLOWER_X,
VISUALIZER_FOLLOWER_Y,
0,
&followerData);
0);
gSprites[data->followerspriteId].oam.priority = 0;
gSprites[data->followerspriteId].anims = sAnims_Follower;

View File

@ -770,14 +770,12 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size
bool8 canHoldItem[MAX_LINK_PLAYERS][DAYCARE_MON_COUNT];
u8 idxs[MAX_LINK_PLAYERS][2];
u8 numDaycareCanHold;
u16 oldSeed;
bool32 anyRS;
rng_value_t localRngState = LocalRandomSeed(gLinkPlayers[0].trainerId);
// Seed RNG to the first player's trainer id so that
// every player has the same random swap occur
// (see the other use of Random2 in this function)
oldSeed = Random2();
SeedRng2(gLinkPlayers[0].trainerId);
linkPlayerCount = GetLinkPlayerCount();
for (i = 0; i < MAX_LINK_PLAYERS; i++)
{
@ -907,7 +905,7 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size
itemId2 = GetDaycareMailItemId(&mixMail->mail[1]);
if ((!itemId1 && !itemId2) || (itemId1 && itemId2))
idxs[j][DAYCARE_SLOT] = Random2() % 2;
idxs[j][DAYCARE_SLOT] = LocalRandom32(&localRngState) % 2;
else if (itemId1 && !itemId2)
idxs[j][DAYCARE_SLOT] = 0;
else if (!itemId1 && itemId2)
@ -958,7 +956,6 @@ static void ReceiveDaycareMailData(struct RecordMixingDaycareMail *records, size
mixMail = (void *)records + multiplayerId * recordSize;
memcpy(&gSaveBlock1Ptr->daycare.mons[0].mail, &mixMail->mail[0], sizeof(struct DaycareMail));
memcpy(&gSaveBlock1Ptr->daycare.mons[1].mail, &mixMail->mail[1], sizeof(struct DaycareMail));
SeedRng(oldSeed);
}

View File

@ -2046,7 +2046,7 @@ bool8 ScrCmd_vmessage(struct ScriptContext *ctx)
bool8 ScrCmd_bufferspeciesname(struct ScriptContext *ctx)
{
u8 stringVarIndex = ScriptReadByte(ctx);
u16 species = VarGet(ScriptReadHalfword(ctx)) & OBJ_EVENT_GFX_SPECIES_MASK; // ignore possible shiny / form bits
u16 species = VarGet(ScriptReadHalfword(ctx)) & OBJ_EVENT_MON_SPECIES_MASK; // ignore possible shiny / form bits
Script_RequestEffects(SCREFF_V1);

View File

@ -872,7 +872,7 @@ static void BuyMenuCollectObjectEventData(void)
u8 objEventId = GetObjectEventIdByXY(facingX - 4 + x, facingY - 2 + y);
// skip if invalid or an overworld pokemon that is not following the player
if (objEventId != OBJECT_EVENTS_COUNT && !(gObjectEvents[objEventId].active && gObjectEvents[objEventId].graphicsId >= OBJ_EVENT_GFX_MON_BASE && gObjectEvents[objEventId].localId != OBJ_EVENT_ID_FOLLOWER))
if (objEventId != OBJECT_EVENTS_COUNT && !(gObjectEvents[objEventId].active && gObjectEvents[objEventId].graphicsId & OBJ_EVENT_MON && gObjectEvents[objEventId].localId != OBJ_EVENT_ID_FOLLOWER))
{
sShopData->viewportObjects[numObjects][OBJ_EVENT_ID] = objEventId;
sShopData->viewportObjects[numObjects][X_COORD] = x;

View File

@ -8,6 +8,7 @@
#include "constants/cries.h"
#include "constants/songs.h"
#include "task.h"
#include "test_runner.h"
struct Fanfare
{
@ -237,6 +238,13 @@ bool8 IsFanfareTaskInactive(void)
static void Task_Fanfare(u8 taskId)
{
if (gTestRunnerHeadless)
{
DestroyTask(taskId);
sFanfareCounter = 0;
return;
}
if (sFanfareCounter)
{
sFanfareCounter--;

View File

@ -319,6 +319,7 @@ const u8 gText_CurrentIsTooFast[] = _("The current is much too fast!");
const u8 gText_DoWhatWithMail[] = _("Do what with the MAIL?");
const u8 gText_ChoosePokemonCancel[] = _("Choose POKéMON or CANCEL.");
const u8 gText_ChoosePokemonConfirm[] = _("Choose POKéMON and confirm.");
const u8 gText_SendWhichMonToPC[] = _("Send which POKéMON to the PC?");
const u8 gText_EnjoyCycling[] = _("Let's enjoy cycling!");
const u8 gText_InUseAlready_PM[] = _("This is in use already.");
const u8 gText_AlreadyHoldingOne[] = _("{STR_VAR_1} is already holding\none {STR_VAR_2}.");
@ -1293,3 +1294,4 @@ const u8 gText_AM[] = _("AM");
const u8 gText_PM[] = _("PM");
const u8 gText_Relearn[] = _("{START_BUTTON} RELEARN"); // future note: don't decap this, because it mimics the summary screen BG graphics which will not get decapped
const u8 gText_Rename[] = _("RENAME");
const u8 gText_CannotSendMonToBoxHM[] = _("Cannot send that mon to the box,\nbecause it knows a HM move.{PAUSE_UNTIL_PRESS}");

View File

@ -257,7 +257,7 @@ static void RandomizePoolIndices(const struct Trainer *trainer, u8 *poolIndexArr
u32 seed = GetPoolSeed(trainer);
localRngState = LocalRandomSeed(seed);
// Replace the LocalRandom with LocalRandom32 when implemented
rnd = LocalRandom(&localRngState) + (LocalRandom(&localRngState) << 16);
rnd = LocalRandom32(&localRngState);
}
else
{
@ -284,7 +284,7 @@ static void RandomizePoolIndices(const struct Trainer *trainer, u8 *poolIndexArr
if (usedBits + numBits > 32)
{
if (B_POOL_SETTING_CONSISTENT_RNG)
rnd = LocalRandom(&localRngState) + (LocalRandom(&localRngState) << 16);
rnd = LocalRandom32(&localRngState);
else
rnd = Random32();
usedBits = 0;

View File

@ -108,9 +108,11 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of
}
}
SINGLE_BATTLE_TEST("Liquid Ooze causes leech seedee to faint before seeder")
/* * https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(Ability)#In_battle:
* If the recipient of Leech Seed's effect were to faint due to Liquid Ooze on the same turn as the victim of Leech Seed, then the victim faints before the recipient. This means that the victim's team loses the battle if both teams had their final Pokémon sent out.
*/
SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder")
{
KNOWN_FAILING; // Message fails
u16 ability;
PARAMETRIZE { ability = ABILITY_CLEAR_BODY; }
PARAMETRIZE { ability = ABILITY_LIQUID_OOZE; }
@ -120,16 +122,17 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seedee to faint before seeder")
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
// Player seeds opponent
MESSAGE("Bulbasaur used Leech Seed!");
// Drain at end of turn
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_LEECH_SEED_DRAIN, opponent);
if (ability != ABILITY_LIQUID_OOZE) {
MESSAGE("The opposing Tentacool's health is sapped by Leech Seed!");
MESSAGE("The opposing Tentacool fainted!");
MESSAGE("The opposing Tentacool's health is sapped by Leech Seed!");
} else {
MESSAGE("The opposing Tentacool fainted!");
ABILITY_POPUP(opponent, ABILITY_LIQUID_OOZE);
MESSAGE("Bulbasaur sucked up the liquid ooze!");
MESSAGE("The opposing Tentacool fainted!");
MESSAGE("Bulbasaur fainted!");
}
}

View File

@ -33,7 +33,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Eruption", s16 damage)
PLAYER(SPECIES_TAUROS) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_PRESENT); }
TURN { MOVE(player, MOVE_ERUPTION); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
@ -50,7 +50,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Water Spout", s16 damage)
PLAYER(SPECIES_TAUROS) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_PRESENT); }
TURN { MOVE(player, MOVE_WATER_SPOUT); }
} SCENE {
HP_BAR(opponent, captureDamage: &results[i].damage);
} FINALLY {
@ -347,7 +347,7 @@ SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage)
EXPECT_NE(results[0].damage, 0);
}
}
SINGLE_BATTLE_TEST("Sheer Force doesn't boost Comeuppance", s16 damage)
SINGLE_BATTLE_TEST("Sheer Force doesn't boost Payback", s16 damage)
{
u16 ability = 0;
PARAMETRIZE { ability = ABILITY_SHEER_FORCE; }

View File

@ -2,5 +2,73 @@
#include "test/battle.h"
// Remember to add a PARAMETRIZE for As One in the following tests:
TO_DO_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries");
TO_DO_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift");
SINGLE_BATTLE_TEST("Unnerve prevents opposing Pokémon from eating their own berries")
{
u16 mon;
u16 ability;
PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; }
PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; }
GIVEN {
ASSUME(gItemsInfo[ITEM_RAWST_BERRY].holdEffect == HOLD_EFFECT_CURE_BRN);
PLAYER(mon) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_RAWST_BERRY); Status1(STATUS1_BURN); }
} WHEN {
TURN { }
} SCENE {
ABILITY_POPUP(player, ability);
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
HP_BAR(opponent);
}
}
SINGLE_BATTLE_TEST("Unnerve doesn't prevent opposing Pokémon from using Natural Gift")
{
u16 mon;
u16 ability;
PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; }
PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; }
GIVEN {
ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT);
PLAYER(mon) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_ORAN_BERRY); }
} WHEN {
TURN { MOVE(opponent, MOVE_NATURAL_GIFT); }
} SCENE {
ABILITY_POPUP(player, ability);
HP_BAR(player);
}
}
SINGLE_BATTLE_TEST("Unnerve prints the correct string (player)")
{
u16 mon;
u16 ability;
PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; }
PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; }
GIVEN {
PLAYER(mon) { Ability(ability); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(player, ability);
MESSAGE("The opposing team is too nervous to eat Berries!");
}
}
SINGLE_BATTLE_TEST("Unnerve prints the correct string (opponent)")
{
u16 mon;
u16 ability;
PARAMETRIZE { mon = SPECIES_JOLTIK, ability = ABILITY_UNNERVE; }
PARAMETRIZE { mon = SPECIES_CALYREX_ICE, ability = ABILITY_AS_ONE_ICE_RIDER; }
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(mon) { Ability(ability); }
} WHEN {
TURN {}
} SCENE {
ABILITY_POPUP(opponent, ability);
MESSAGE("Your team is too nervous to eat Berries!");
}
}

View File

@ -42,6 +42,20 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon switch out after using a status move onc
}
}
AI_SINGLE_BATTLE_TEST("Choiced Pokémon only consider their own status moves when determining if they should switch")
{
GIVEN
{
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_RISKY | AI_FLAG_SMART_SWITCHING | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES);
PLAYER(SPECIES_ZIGZAGOON) { Speed(4); Moves(MOVE_TAIL_WHIP, MOVE_TACKLE); }
OPPONENT(SPECIES_ZIGZAGOON) { Speed(5); Moves(MOVE_TACKLE); Item(ITEM_CHOICE_BAND); }
OPPONENT(SPECIES_ZIGZAGOON) { Speed(5); Moves(MOVE_TACKLE); }
} WHEN {
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_TAIL_WHIP); }
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_TAIL_WHIP); }
}
}
AI_SINGLE_BATTLE_TEST("Choiced Pokémon won't use stat boosting moves")
{
// Moves defined by MOVE_TARGET_USER (with exceptions?)

View File

@ -683,7 +683,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed")
{
GIVEN {
// Fails?: ASSUME(GetMaxMove(B_POSITION_PLAYER_LEFT, MOVE_TACKLE) == MOVE_MAX_STRIKE);
ASSUME(GetMoveMaxEffect(MOVE_MAX_STRIKE) == MAX_EFFECT_LOWER_SPEED);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_STRIKE, MOVE_EFFECT_LOWER_SPEED_SIDE));
OPPONENT(SPECIES_WOBBUFFET) { Speed(100); }
PLAYER(SPECIES_WOBBUFFET) { Speed(80); }
} WHEN {
@ -707,7 +707,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers single opponent's speed")
DOUBLE_BATTLE_TEST("(DYNAMAX) Max Strike lowers both opponents' speed")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_STRIKE) == MAX_EFFECT_LOWER_SPEED);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_STRIKE, MOVE_EFFECT_LOWER_SPEED_SIDE));
PLAYER(SPECIES_WOBBUFFET) { Speed(80); }
PLAYER(SPECIES_WOBBUFFET) { Speed(79); }
OPPONENT(SPECIES_WOBBUFFET) {Speed(100); }
@ -744,7 +744,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack")
{
s16 damage[4];
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_KNUCKLE) == MAX_EFFECT_RAISE_TEAM_ATTACK);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_KNUCKLE, MOVE_EFFECT_RAISE_TEAM_ATTACK));
ASSUME(GetMoveCategory(MOVE_CLOSE_COMBAT) == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
@ -786,7 +786,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Max Knuckle raises both allies' attack")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Flare sets up sunlight")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_FLARE) == MAX_EFFECT_SUN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_FLARE, MOVE_EFFECT_SUN));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -802,7 +802,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Flare sets up sunlight")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Geyser sets up heavy rain")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_GEYSER) == MAX_EFFECT_RAIN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_GEYSER, MOVE_EFFECT_RAIN));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -818,7 +818,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Geyser sets up heavy rain")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Hailstorm sets up hail")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_HAILSTORM) == MAX_EFFECT_HAIL);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_HAILSTORM, MOVE_EFFECT_HAIL));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -834,7 +834,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Hailstorm sets up hail")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Rockfall sets up a sandstorm")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_ROCKFALL) == MAX_EFFECT_SANDSTORM);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_ROCKFALL, MOVE_EFFECT_SANDSTORM));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -851,7 +851,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Overgrowth sets up Grassy Terrain")
{
s32 maxHP = 490; // Because of recalculated stats upon Dynamaxing
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_OVERGROWTH) == MAX_EFFECT_GRASSY_TERRAIN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_OVERGROWTH, MOVE_EFFECT_GRASSY_TERRAIN));
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseHP == 190);
OPPONENT(SPECIES_WOBBUFFET) { MaxHP(maxHP); HP(maxHP / 2); };
PLAYER(SPECIES_WOBBUFFET) { MaxHP(maxHP); HP(maxHP / 2); };
@ -871,7 +871,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Overgrowth sets up Grassy Terrain")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Mindstorm sets up Psychic Terrain")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_MINDSTORM) == MAX_EFFECT_PSYCHIC_TERRAIN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_MINDSTORM, MOVE_EFFECT_PSYCHIC_TERRAIN));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -888,7 +888,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Mindstorm sets up Psychic Terrain")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Lightning sets up Electric Terrain")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_LIGHTNING) == MAX_EFFECT_ELECTRIC_TERRAIN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_LIGHTNING, MOVE_EFFECT_ELECTRIC_TERRAIN));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -903,7 +903,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Lightning sets up Electric Terrain")
SINGLE_BATTLE_TEST("(DYNAMAX) Max Starfall sets up Misty Terrain")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_MAX_STARFALL) == MAX_EFFECT_MISTY_TERRAIN);
ASSUME(MoveHasAdditionalEffect(MOVE_MAX_STARFALL, MOVE_EFFECT_MISTY_TERRAIN));
OPPONENT(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
} WHEN {
@ -918,7 +918,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Starfall sets up Misty Terrain")
SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_STONESURGE) == MAX_EFFECT_STEALTH_ROCK);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STONESURGE, MOVE_EFFECT_STEALTH_ROCK));
PLAYER(SPECIES_DREDNAW) { GigantamaxFactor(TRUE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -938,7 +938,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks")
SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_STEELSURGE) == MAX_EFFECT_STEELSURGE);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STEELSURGE, MOVE_EFFECT_STEELSURGE));
PLAYER(SPECIES_COPPERAJAH) { GigantamaxFactor(TRUE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_HATTERENE);
@ -969,7 +969,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Hydrosnipe has fixed power and ignores abili
PARAMETRIZE { move = MOVE_WATER_GUN; }
PARAMETRIZE { move = MOVE_HYDRO_CANNON; }
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_HYDROSNIPE) == MAX_EFFECT_FIXED_POWER);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_HYDROSNIPE, MOVE_EFFECT_FIXED_POWER));
PLAYER(SPECIES_INTELEON) { GigantamaxFactor(TRUE); }
OPPONENT(SPECIES_ARCTOVISH) { Ability(ABILITY_WATER_ABSORB); }
} WHEN {
@ -985,7 +985,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Hydrosnipe has fixed power and ignores abili
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Volt Crash paralyzes both opponents")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_VOLT_CRASH) == MAX_EFFECT_PARALYZE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_VOLT_CRASH, MOVE_EFFECT_PARALYZE_SIDE));
PLAYER(SPECIES_PIKACHU) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_PICHU);
OPPONENT(SPECIES_WOBBUFFET);
@ -1012,7 +1012,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PRZ; rng = STATUS1_PARALYSIS; }
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; }
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_STUN_SHOCK) == MAX_EFFECT_POISON_PARALYZE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STUN_SHOCK, MOVE_EFFECT_POISON_PARALYZE_SIDE));
PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_TOXEL);
OPPONENT(SPECIES_WOBBUFFET);
@ -1049,7 +1049,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before considering immunities")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_STUN_SHOCK) == MAX_EFFECT_POISON_PARALYZE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_STUN_SHOCK, MOVE_EFFECT_POISON_PARALYZE_SIDE));
PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_TOXEL);
OPPONENT(SPECIES_GARBODOR);
@ -1082,7 +1082,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both
PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; }
PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = STATUS1_SLEEP; }
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_BEFUDDLE) == MAX_EFFECT_EFFECT_SPORE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_BEFUDDLE, MOVE_EFFECT_EFFECT_SPORE_SIDE));
PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_CATERPIE);
OPPONENT(SPECIES_WOBBUFFET);
@ -1126,7 +1126,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Gold Rush confuses both opponents and generates money")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_GOLD_RUSH) == MAX_EFFECT_CONFUSE_FOES_PAY_DAY);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_GOLD_RUSH, MOVE_EFFECT_CONFUSE_PAY_DAY_SIDE));
PLAYER(SPECIES_MEOWTH) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_PERSIAN);
OPPONENT(SPECIES_WOBBUFFET);
@ -1146,7 +1146,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Gold Rush confuses both opponents and genera
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Smite confuses both opponents")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_SMITE) == MAX_EFFECT_CONFUSE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SMITE, MOVE_EFFECT_CONFUSE_SIDE));
PLAYER(SPECIES_HATTERENE) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_HATENNA);
OPPONENT(SPECIES_WOBBUFFET);
@ -1165,7 +1165,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Smite confuses both opponents")
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possible")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_CUDDLE) == MAX_EFFECT_INFATUATE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_CUDDLE, MOVE_EFFECT_INFATUATE_SIDE));
PLAYER(SPECIES_EEVEE) { Gender(MON_MALE); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_EEVEE);
OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); }
@ -1186,7 +1186,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possibl
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_TERROR) == MAX_EFFECT_MEAN_LOOK);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_TERROR, MOVE_EFFECT_PREVENT_ESCAPE_SIDE));
PLAYER(SPECIES_GENGAR) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_GASTLY);
OPPONENT(SPECIES_WOBBUFFET);
@ -1205,7 +1205,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents")
SINGLE_BATTLE_TEST("(DYNAMAX) Baton Pass passes G-Max Terror's escape prevention effect")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_TERROR) == MAX_EFFECT_MEAN_LOOK);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_TERROR, MOVE_EFFECT_PREVENT_ESCAPE_SIDE));
PLAYER(SPECIES_GENGAR) { GigantamaxFactor(TRUE); }
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
@ -1222,7 +1222,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Baton Pass passes G-Max Terror's escape prevention
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Meltdown torments both opponents for 3 turns")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_MELTDOWN) == MAX_EFFECT_TORMENT_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_MELTDOWN, MOVE_EFFECT_TORMENT_SIDE));
PLAYER(SPECIES_MELMETAL) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MELTAN);
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_CELEBRATE); }
@ -1259,7 +1259,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Wildfire sets a field effect that damages no
{
s16 damage;
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_WILDFIRE) == MAX_EFFECT_WILDFIRE);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_WILDFIRE, MOVE_EFFECT_WILDFIRE));
PLAYER(SPECIES_CHARIZARD) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_CHARMANDER);
OPPONENT(SPECIES_WOBBUFFET) { HP(600); MaxHP(600); }
@ -1305,7 +1305,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries 50\% of t
{
PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH);
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_REPLENISH) == MAX_EFFECT_RECYCLE_BERRIES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_REPLENISH, MOVE_EFFECT_RECYCLE_BERRIES));
PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); Ability(ABILITY_THICK_FAT); }
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); }
@ -1333,7 +1333,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy")
{
PASSES_RANDOMLY(1, 2, RNG_G_MAX_SNOOZE);
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_SNOOZE) == MAX_EFFECT_YAWN_FOE);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SNOOZE, MOVE_EFFECT_YAWN_FOE));
ASSUME(GetMoveCategory(MOVE_DARK_PULSE) == DAMAGE_CATEGORY_SPECIAL); // Otherwise, Blissey faints.
PLAYER(SPECIES_GRIMMSNARL) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_IMPIDIMP);
@ -1357,7 +1357,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health")
{
s16 damage1, damage2;
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_FINALE) == MAX_EFFECT_HEAL_TEAM);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_FINALE, MOVE_EFFECT_HEAL_TEAM));
PLAYER(SPECIES_ALCREMIE) { HP(1); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MILCERY) { HP(1); }
OPPONENT(SPECIES_WOBBUFFET);
@ -1377,7 +1377,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health")
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_SWEETNESS) == MAX_EFFECT_AROMATHERAPY);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SWEETNESS, MOVE_EFFECT_AROMATHERAPY));
PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); GigantamaxFactor(TRUE); }
PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); }
OPPONENT(SPECIES_WOBBUFFET);
@ -1397,7 +1397,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions")
DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin")
{
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_CENTIFERNO) == MAX_EFFECT_FIRE_SPIN_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_CENTIFERNO, MOVE_EFFECT_FIRE_SPIN_SIDE));
PLAYER(SPECIES_CENTISKORCH) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_SIZZLIPEDE);
PLAYER(SPECIES_SIZZLIPEDE);
@ -1426,7 +1426,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance")
u32 j;
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_6);
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_CHI_STRIKE) == MAX_EFFECT_CRIT_PLUS);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_CHI_STRIKE, MOVE_EFFECT_CRIT_PLUS_SIDE));
PLAYER(SPECIES_MACHAMP) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_MACHOP);
OPPONENT(SPECIES_WOBBUFFET);
@ -1458,11 +1458,12 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's
{
GIVEN {
ASSUME(GetMoveCategory(MOVE_DRAGON_CLAW) == DAMAGE_CATEGORY_PHYSICAL); // Otherwise Sableye faints.
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_DEPLETION) == MAX_EFFECT_SPITE);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_DEPLETION, MOVE_EFFECT_SPITE));
ASSUME(GetMovePP(MOVE_CELEBRATE) >= 3);
PLAYER(SPECIES_DURALUDON) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_WYNAUT);
// Dynamax behaves weird with test turn order because stats are recalculated.
OPPONENT(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); }
OPPONENT(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); Moves(MOVE_CELEBRATE); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CLAW, target: opponentLeft, gimmick: GIMMICK_DYNAMAX); }
@ -1470,6 +1471,8 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's
MESSAGE("The opposing Sableye used Celebrate!");
MESSAGE("Duraludon used G-Max Depletion!");
MESSAGE("The opposing Sableye's PP was reduced!");
} THEN {
EXPECT_EQ(opponentLeft->pp[0], GetMovePP(MOVE_CELEBRATE) - 3); // 1 from regular use + 2 from G-Max Depletion
}
}
@ -1480,7 +1483,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage"
PARAMETRIZE { protect = TRUE; }
PARAMETRIZE { protect = FALSE; }
GIVEN {
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_ONE_BLOW) == MAX_EFFECT_BYPASS_PROTECT);
ASSUME(MoveIgnoresProtect(MOVE_G_MAX_RAPID_FLOW));
PLAYER(SPECIES_URSHIFU) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_KUBFU);
OPPONENT(SPECIES_WOBBUFFET);

View File

@ -273,12 +273,13 @@ DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker is rooted")
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Wobbuffet!");
MESSAGE("The opposing Wobbuffet anchored itself with its roots!");
NOT MESSAGE("The opposing Unown was dragged out!");
// Red Card already consumed so cannot activate.
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight);
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
MESSAGE("Wynaut held up its Red Card against the opposing Wynaut!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!");
}
}
}
@ -301,12 +302,41 @@ DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker has Suction Cup
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Octillery!");
MESSAGE("The opposing Octillery anchors itself with Suction Cups!");
NOT MESSAGE("The opposing Unown was dragged out!");
// Red Card already consumed so cannot activate.
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight);
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
MESSAGE("Wynaut held up its Red Card against the opposing Wynaut!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!");
}
}
}
DOUBLE_BATTLE_TEST("Red Card activates but fails if the attacker has Guard Dog")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); }
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_OKIDOGI) { Ability(ABILITY_GUARD_DOG); }
OPPONENT(SPECIES_WYNAUT);
OPPONENT(SPECIES_UNOWN);
} WHEN {
TURN {
MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft);
MOVE(opponentRight, MOVE_TACKLE, target: playerLeft);
}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Okidogi!");
NOT MESSAGE("The opposing Unown was dragged out!");
// Red Card already consumed so cannot activate.
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight);
NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
MESSAGE("Wobbuffet held up its Red Card against the opposing Wynaut!");
}
}
}

View File

@ -40,6 +40,8 @@ SINGLE_BATTLE_TEST("Electric Seed raises the holder's Defense on Electric Terrai
SEND_IN_MESSAGE("Wobbuffet");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Electric Seed, the Defense of Wobbuffet rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
@ -69,6 +71,8 @@ SINGLE_BATTLE_TEST("Grassy Seed raises the holder's Defense on Grassy Terrain")
SEND_IN_MESSAGE("Wobbuffet");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Grassy Seed, the Defense of Wobbuffet rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
@ -98,6 +102,8 @@ SINGLE_BATTLE_TEST("Misty Seed raises the holder's Sp. Defense on Misty Terrain"
SEND_IN_MESSAGE("Wobbuffet");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Misty Seed, the Sp. Def of Wobbuffet rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1);
}
}
@ -127,5 +133,7 @@ SINGLE_BATTLE_TEST("Psychic Seed raises the holder's Sp. Defense on Psychic Terr
SEND_IN_MESSAGE("Wobbuffet");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
MESSAGE("Using Psychic Seed, the Sp. Def of Wobbuffet rose!");
} THEN {
EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1);
}
}

View File

@ -1,5 +1,74 @@
#include "global.h"
#include "test/battle.h"
TO_DO_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn");
TO_DO_BATTLE_TEST("Electrify can change status moves to Electric-type"); // Test type immunity
SINGLE_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn (single move)")
{
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND);
ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SANDSLASH);
} WHEN {
TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_TACKLE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player);
}
}
DOUBLE_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn (double move)")
{
KNOWN_FAILING;
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND);
ASSUME(gMovesInfo[MOVE_TACKLE].type != TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_SANDSLASH);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_TACKLE, target:opponentLeft); MOVE(playerRight, MOVE_INSTRUCT, target: playerLeft); MOVE(opponentRight, MOVE_CELEBRATE); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponentLeft);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_INSTRUCT, playerRight);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft);
}
}
SINGLE_BATTLE_TEST("Electrify can change status moves to Electric-type")
{
KNOWN_FAILING;
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND);
ASSUME(gMovesInfo[MOVE_LEER].category == DAMAGE_CATEGORY_STATUS);
ASSUME(gMovesInfo[MOVE_LEER].type != TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SANDSLASH);
} WHEN {
TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_LEER); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, player);
}
}
SINGLE_BATTLE_TEST("Electrify changes the type of foreseen moves")
{
KNOWN_FAILING;
GIVEN {
ASSUME(gSpeciesInfo[SPECIES_SANDSLASH].types[0] == TYPE_GROUND || gSpeciesInfo[SPECIES_SANDSLASH].types[1] == TYPE_GROUND);
ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT);
ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].type != TYPE_ELECTRIC);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SANDSLASH);
} WHEN {
TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_FUTURE_SIGHT); }
TURN {}
TURN {}
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponent);
ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player);
NOT HP_BAR(opponent);
}
}

View File

@ -90,7 +90,7 @@ SINGLE_BATTLE_TEST("Dragon Tail switches the target after Rocky Helmet and Iron
}
}
SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Guard Dog ability")
SINGLE_BATTLE_TEST("Dragon Tail effect fails against target with Guard Dog")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -104,7 +104,7 @@ SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Guard Dog ability")
}
}
SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Suction Cups ability")
SINGLE_BATTLE_TEST("Dragon Tail effect fails against target with Suction Cups")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -114,6 +114,7 @@ SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Suction Cups ability")
TURN { MOVE(player, MOVE_DRAGON_TAIL); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player);
ABILITY_POPUP(opponent, ABILITY_SUCTION_CUPS);
MESSAGE("The opposing Octillery anchors itself with Suction Cups!");
NOT MESSAGE("The opposing Charmander was dragged out!");
}

View File

@ -68,3 +68,38 @@ SINGLE_BATTLE_TEST("Roar fails if replacements fainted")
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Roar fails against target with Guard Dog")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_OKIDOGI) { Ability(ABILITY_GUARD_DOG); }
OPPONENT(SPECIES_CHARMANDER);
} WHEN {
TURN { MOVE(player, MOVE_ROAR); }
} SCENE {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player);
MESSAGE("The opposing Charmander was dragged out!");
}
MESSAGE("Wobbuffet used Roar!");
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Roar fails to switch out target with Suction Cups")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_OCTILLERY) { Ability(ABILITY_SUCTION_CUPS); }
OPPONENT(SPECIES_CHARMANDER);
} WHEN {
TURN { MOVE(player, MOVE_ROAR); }
} SCENE {
MESSAGE("Wobbuffet used Roar!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player);
ABILITY_POPUP(opponent, ABILITY_SUCTION_CUPS);
MESSAGE("The opposing Octillery anchors itself with Suction Cups!");
NOT MESSAGE("The opposing Charmander was dragged out!");
}
}

View File

@ -507,7 +507,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: G-Max Befuddle can only sleep one opposing mon
{
GIVEN {
FLAG_SET(B_FLAG_SLEEP_CLAUSE);
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_BEFUDDLE) == MAX_EFFECT_EFFECT_SPORE_FOES);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_BEFUDDLE, MOVE_EFFECT_EFFECT_SPORE_SIDE));
PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_CATERPIE);
OPPONENT(SPECIES_WOBBUFFET);
@ -1131,7 +1131,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo
{
GIVEN {
FLAG_SET(B_FLAG_SLEEP_CLAUSE);
ASSUME(GetMoveMaxEffect(MOVE_G_MAX_SWEETNESS) == MAX_EFFECT_AROMATHERAPY);
ASSUME(MoveHasAdditionalEffect(MOVE_G_MAX_SWEETNESS, MOVE_EFFECT_AROMATHERAPY));
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_SLEEP);
PLAYER(SPECIES_APPLETUN) { GigantamaxFactor(TRUE); }
PLAYER(SPECIES_WOBBUFFET);

View File

@ -4,7 +4,7 @@
SINGLE_BATTLE_TEST("Trainer Slide: Before First Turn")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_BEFORE_FIRST_TURN;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_BEFORE_FIRST_TURN;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -18,7 +18,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Before First Turn")
SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Critical Hit")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT;
GIVEN {
ASSUME(GetMoveEffect(MOVE_LASER_FOCUS) == EFFECT_LASER_FOCUS);
@ -37,7 +37,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Critical Hit")
SINGLE_BATTLE_TEST("Trainer Slide: Enemy Lands First Critical Hit")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT;
GIVEN {
ASSUME(GetMoveEffect(MOVE_LASER_FOCUS) == EFFECT_LASER_FOCUS);
@ -56,7 +56,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Enemy Lands First Critical Hit")
SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First STAB Hit")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE;
GIVEN {
ASSUME((GetMoveType(MOVE_VINE_WHIP)) == gSpeciesInfo[SPECIES_BULBASAUR].types[0]);
@ -73,7 +73,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First STAB Hit")
SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Super Effective Hit")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT;
GIVEN {
ASSUME(GetMoveType(MOVE_BITE) == TYPE_DARK);
@ -91,7 +91,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Super Effective Hit")
SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Down")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -107,7 +107,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Player Lands First Down")
SINGLE_BATTLE_TEST("Trainer Slide: Enemy Mon Unaffected")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_ENEMY_MON_UNAFFECTED;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_MON_UNAFFECTED;
GIVEN {
ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7);
ASSUME(gSpeciesInfo[SPECIES_GLALIE].types[0] == TYPE_ICE);
@ -124,7 +124,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Enemy Mon Unaffected")
SINGLE_BATTLE_TEST("Trainer Slide: Last Switchin")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_LAST_SWITCHIN;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_LAST_SWITCHIN;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
@ -139,7 +139,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Last Switchin")
SINGLE_BATTLE_TEST("Trainer Slide: Last Half Hp")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_LAST_HALF_HP;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_LAST_HALF_HP;
GIVEN {
ASSUME(gMovesInfo[MOVE_SUPER_FANG].effect == EFFECT_SUPER_FANG);
ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].baseHP == 190);
@ -154,7 +154,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Last Half Hp")
SINGLE_BATTLE_TEST("Trainer Slide: Last Low Hp")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_LAST_LOW_HP;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_LAST_LOW_HP;
GIVEN {
ASSUME(GetMoveEffect(MOVE_FALSE_SWIPE) == EFFECT_FALSE_SWIPE);
PLAYER(SPECIES_WOBBUFFET) { Attack(999);}
@ -168,7 +168,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Last Low Hp")
SINGLE_BATTLE_TEST("Trainer Slide: Mega Evolution")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_MEGA_EVOLUTION;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_MEGA_EVOLUTION;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
@ -184,7 +184,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Mega Evolution")
SINGLE_BATTLE_TEST("Trainer Slide: Z Move")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_Z_MOVE;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_Z_MOVE;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
@ -200,7 +200,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Z Move")
SINGLE_BATTLE_TEST("Trainer Slide: Dynamax")
{
gBattleTestRunnerState->data.recordedBattle.opponentA = 1 + TRAINER_SLIDE_DYNAMAX;
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_DYNAMAX;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);

View File

@ -1,54 +1,54 @@
[DIFFICULTY_NORMAL] =
{
[1 + TRAINER_SLIDE_BEFORE_FIRST_TURN] =
[TRAINER_SLIDE_BEFORE_FIRST_TURN] =
{
[TRAINER_SLIDE_BEFORE_FIRST_TURN] = COMPOUND_STRING("This message plays before the first turn.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT] =
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT] =
{
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_CRITICAL_HIT] = COMPOUND_STRING("This message plays after the player lands their first critical hit.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT] =
[TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT] =
{
[TRAINER_SLIDE_ENEMY_LANDS_FIRST_CRITICAL_HIT] = COMPOUND_STRING("This message plays after the enemy lands their first critical hit.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT] =
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT] =
{
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_SUPER_EFFECTIVE_HIT] = COMPOUND_STRING("This message plays after the player lands their first super effective hit.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN] =
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN] =
{
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_DOWN] = COMPOUND_STRING("This message plays after the player KOs one enemy mon.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_ENEMY_MON_UNAFFECTED] =
[TRAINER_SLIDE_ENEMY_MON_UNAFFECTED] =
{
[TRAINER_SLIDE_ENEMY_MON_UNAFFECTED] = COMPOUND_STRING("Player attacked enemy with ineffective move.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE] =
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE] =
{
[TRAINER_SLIDE_PLAYER_LANDS_FIRST_STAB_MOVE] = COMPOUND_STRING("Player lands their first STAB move.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_LAST_SWITCHIN] =
[TRAINER_SLIDE_LAST_SWITCHIN] =
{
[TRAINER_SLIDE_LAST_SWITCHIN] = COMPOUND_STRING("This message plays after the enemy switches in their last Pokemon.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_LAST_HALF_HP] =
[TRAINER_SLIDE_LAST_HALF_HP] =
{
[TRAINER_SLIDE_LAST_HALF_HP] = COMPOUND_STRING("Enemy last Mon has < 51% HP.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_LAST_LOW_HP] =
[TRAINER_SLIDE_LAST_LOW_HP] =
{
[TRAINER_SLIDE_LAST_LOW_HP] = COMPOUND_STRING("Enemy last Mon has < 26% HP.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_MEGA_EVOLUTION] =
[TRAINER_SLIDE_MEGA_EVOLUTION] =
{
[TRAINER_SLIDE_MEGA_EVOLUTION] = COMPOUND_STRING("This message plays before the enemy activates the Mega Evolution gimmick.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_Z_MOVE] =
[TRAINER_SLIDE_Z_MOVE] =
{
[TRAINER_SLIDE_Z_MOVE] = COMPOUND_STRING("This message plays before the enemy activates the Z-Move gimmick.{PAUSE_UNTIL_PRESS}"),
},
[1 + TRAINER_SLIDE_DYNAMAX] =
[TRAINER_SLIDE_DYNAMAX] =
{
[TRAINER_SLIDE_DYNAMAX] = COMPOUND_STRING("This message plays before the enemy activates the Dynamax gimmick.{PAUSE_UNTIL_PRESS}"),
},

164
test/daycare.c Normal file
View File

@ -0,0 +1,164 @@
#include "global.h"
#include "daycare.h"
#include "event_data.h"
#include "malloc.h"
#include "party_menu.h"
#include "regions.h"
#include "test/overworld_script.h"
#include "test/test.h"
// We don't run the StoreSelectedPokemonInDaycare special because it relies on calling the
// party select screen and the GetCursorSelectionMonId function, so we store directly to the struct.
#define STORE_IN_DAYCARE_AND_GET_EGG() \
StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[0]); \
StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[1]); \
RUN_OVERWORLD_SCRIPT( special GiveEggFromDaycare; );
TEST("(Daycare) Pokémon generate Eggs of the lowest member of the evolutionary family")
{
ASSUME(P_FAMILY_PIKACHU == TRUE);
ASSUME(P_GEN_2_CROSS_EVOS == TRUE);
ZeroPlayerPartyMons();
RUN_OVERWORLD_SCRIPT(
givemon SPECIES_PIKACHU, 100, gender=MON_MALE;
givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE;
);
STORE_IN_DAYCARE_AND_GET_EGG();
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_PICHU);
}
TEST("(Daycare) Pokémon offspring species is based off the mother's species")
{
u32 offspring = 0;
ASSUME(P_FAMILY_PIKACHU == TRUE);
ASSUME(P_GEN_2_CROSS_EVOS == TRUE);
ASSUME(P_FAMILY_RIOLU == TRUE);
ZeroPlayerPartyMons();
PARAMETRIZE { offspring = SPECIES_RIOLU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_MALE; givemon SPECIES_LUCARIO, 100, gender=MON_FEMALE, item=ITEM_NONE; ); }
PARAMETRIZE { offspring = SPECIES_PICHU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE; givemon SPECIES_LUCARIO, 100, gender=MON_MALE;); }
STORE_IN_DAYCARE_AND_GET_EGG();
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}
TEST("(Daycare) Pokémon can breed with Ditto if they don't belong to the Ditto or No Eggs Discovered group")
{
u32 j = 0;
u32 parentSpecies = 0;
ZeroPlayerPartyMons();
for (j = 1; j < NUM_SPECIES; j++)
PARAMETRIZE { parentSpecies = j; }
VarSet(VAR_TEMP_C, parentSpecies);
RUN_OVERWORLD_SCRIPT(
givemon SPECIES_DITTO, 100; givemon VAR_TEMP_C, 100;
);
STORE_IN_DAYCARE_AND_GET_EGG();
if (gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_NO_EGGS_DISCOVERED
&& gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_DITTO)
EXPECT_NE(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE);
else
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE);
}
TEST("(Daycare) Shellos' form is always based on the mother's form")
{
u32 offspring = 0;
ASSUME(P_FAMILY_MEOWTH == TRUE);
ASSUME(P_ALOLAN_FORMS == TRUE);
ASSUME(P_GALARIAN_FORMS == TRUE);
ZeroPlayerPartyMons();
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_NONE; ); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
STORE_IN_DAYCARE_AND_GET_EGG();
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}
TEST("(Daycare) Pokémon with regional forms give the correct offspring")
{
u32 region = 0, offspring = 0, species1 = 0, item1 = 0, species2 = 0, item2 = 0;
ZeroPlayerPartyMons();
region = GetCurrentRegion();
if (region == REGION_ALOLA) {
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; }
} else if (region == REGION_GALAR) {
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN; item2=ITEM_EVERSTONE; }
} else {
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_ALOLA; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_ALOLA, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_MEOWTH; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_DIGLETT; item1=ITEM_NONE; species2=SPECIES_MEOWTH_GALAR, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH_GALAR; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERRSERKER; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_MEOWTH; species1=SPECIES_PERSIAN_ALOLA; item1=ITEM_EVERSTONE; species2=SPECIES_PERSIAN, item2=ITEM_EVERSTONE; }
}
if (region == REGION_HISUI) {
PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_EVERSTONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASLER; item1=ITEM_EVERSTONE; species2=SPECIES_WEAVILE, item2=ITEM_EVERSTONE; }
} else {
PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASEL; item1=ITEM_EVERSTONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL_HISUI; species1=SPECIES_SNEASEL; item1=ITEM_NONE; species2=SPECIES_SNEASEL_HISUI, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_SNEASEL; species1=SPECIES_SNEASLER; item1=ITEM_EVERSTONE; species2=SPECIES_WEAVILE, item2=ITEM_EVERSTONE; }
}
if (region == REGION_PALDEA) {
PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_EVERSTONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_CLODSIRE; item1=ITEM_EVERSTONE; species2=SPECIES_QUAGSIRE, item2=ITEM_EVERSTONE; }
} else {
PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_WOOPER; item1=ITEM_EVERSTONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_NONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER_PALDEA; species1=SPECIES_WOOPER; item1=ITEM_NONE; species2=SPECIES_WOOPER_PALDEA, item2=ITEM_EVERSTONE; }
PARAMETRIZE { offspring=SPECIES_WOOPER; species1=SPECIES_CLODSIRE; item1=ITEM_EVERSTONE; species2=SPECIES_QUAGSIRE, item2=ITEM_EVERSTONE; }
}
ASSUME(IsSpeciesEnabled(species1) == TRUE);
ASSUME(IsSpeciesEnabled(species2) == TRUE);
ASSUME(IsSpeciesEnabled(offspring) == TRUE);
VarSet(VAR_0x8000, species1);
VarSet(VAR_0x8001, item1);
VarSet(VAR_0x8002, species2);
VarSet(VAR_0x8003, item2);
RUN_OVERWORLD_SCRIPT(givemon VAR_0x8000, 1, gender=MON_MALE, item=VAR_0x8001;);
RUN_OVERWORLD_SCRIPT(givemon VAR_0x8002, 1, gender=MON_FEMALE, item=VAR_0x8003;);
STORE_IN_DAYCARE_AND_GET_EGG();
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}