Merge branch 'rh-hideout-master'
This commit is contained in:
commit
db9e97e2f0
@ -1050,7 +1050,7 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro trydobeatup endInstr, failInstr
|
||||
.macro trydobeatup endInstr:req, failInstr:req
|
||||
.byte 0xc4
|
||||
.4byte \endInstr
|
||||
.4byte \failInstr
|
||||
|
||||
@ -1585,7 +1585,7 @@ BattleScript_MoveEffectFlameBurst::
|
||||
healthbarupdate BS_SCRIPTING
|
||||
datahpupdate BS_SCRIPTING
|
||||
tryfaintmon BS_SCRIPTING
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectPowerTrick::
|
||||
attackcanceler
|
||||
@ -1673,7 +1673,7 @@ BattleScript_DefogDoAnim::
|
||||
BattleScript_DefogPrintString::
|
||||
printfromtable gStatDownStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_DefogTryHazards::
|
||||
BattleScript_DefogTryHazards:
|
||||
copybyte gEffectBattler, gBattlerAttacker
|
||||
trydefog TRUE, NULL
|
||||
copybyte gBattlerAttacker, gEffectBattler
|
||||
@ -1683,6 +1683,12 @@ BattleScript_DefogTryHazardsWithAnim:
|
||||
waitanimation
|
||||
goto BattleScript_DefogTryHazards
|
||||
|
||||
BattleScript_MoveEffectDefog::
|
||||
saveattacker
|
||||
trydefog TRUE, NULL
|
||||
restoreattacker
|
||||
return
|
||||
|
||||
BattleScript_EffectCopycat::
|
||||
attackcanceler
|
||||
attackstring
|
||||
@ -2217,6 +2223,10 @@ BattleScript_EffectEntrainment::
|
||||
setlastusedability
|
||||
printstring STRINGID_PKMNACQUIREDABILITY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
tryendneutralizinggas
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectSimpleBeam::
|
||||
@ -2292,6 +2302,9 @@ BattleScript_EffectHealingWishGen4:
|
||||
switchindataupdate BS_ATTACKER
|
||||
hpthresholds BS_ATTACKER
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
tryendneutralizinggas
|
||||
flushtextbox
|
||||
printstring STRINGID_SWITCHINMON
|
||||
switchinanim BS_ATTACKER, FALSE, TRUE
|
||||
@ -2604,8 +2617,11 @@ BattleScript_EffectMiracleEye::
|
||||
ppreduce
|
||||
setvolatile BS_TARGET, VOLATILE_MIRACLE_EYE
|
||||
goto BattleScript_IdentifiedFoe
|
||||
|
||||
BattleScript_EffectGravity::
|
||||
call BattleScript_EffectGravityInternal
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectGravityInternal:
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
@ -2631,7 +2647,7 @@ BattleScript_GravityLoopEnd:
|
||||
moveendcase MOVEEND_TARGET_VISIBLE
|
||||
jumpifnexttargetvalid BattleScript_GravityLoop
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectRoost::
|
||||
attackcanceler
|
||||
@ -2756,6 +2772,13 @@ BattleScript_TerrainPreventsEnd2::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end2
|
||||
|
||||
BattleScript_ImmunityProtectedEnd2::
|
||||
call BattleScript_AbilityPopUp
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printfromtable gStatusPreventionStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end2
|
||||
|
||||
BattleScript_ElectricTerrainPrevents::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_ELECTRICTERRAINPREVENTS
|
||||
@ -3303,6 +3326,9 @@ BattleScript_EffectTransform::
|
||||
attackstring
|
||||
ppreduce
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
tryendneutralizinggas
|
||||
flushtextbox
|
||||
transformdataexecution
|
||||
attackanimation
|
||||
@ -3347,11 +3373,15 @@ BattleScript_EffectReflect::
|
||||
BattleScript_PrintReflectLightScreenSafeguardString::
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_EffectAuroraVeilSuccess::
|
||||
printfromtable gReflectLightScreenSafeguardStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MoveEffectAuroraVeil::
|
||||
printfromtable gReflectLightScreenSafeguardStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_VoltAbsorbHeal:
|
||||
copybyte gBattlerAbility, gBattlerTarget
|
||||
tryhealquarterhealth BS_TARGET, BattleScript_MonMadeMoveUseless @ Check if max hp
|
||||
@ -3732,13 +3762,13 @@ BattleScript_EffectSpite::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
@ TODO: Simplfy script
|
||||
BattleScript_EffectHealBell::
|
||||
attackcanceler
|
||||
attackstring
|
||||
ppreduce
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_EffectHealBell_FromHeal::
|
||||
healpartystatus
|
||||
waitstate
|
||||
printfromtable gPartyStatusHealStringIds
|
||||
@ -3758,6 +3788,15 @@ BattleScript_PartyHealEnd::
|
||||
waitstate
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MoveEffectAromatherapy::
|
||||
healpartystatus
|
||||
waitstate
|
||||
printfromtable gPartyStatusHealStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_ATTACKER_WITH_PARTNER
|
||||
waitstate
|
||||
return
|
||||
|
||||
BattleScript_EffectMeanLook::
|
||||
attackcanceler
|
||||
attackstring
|
||||
@ -4247,15 +4286,6 @@ BattleScript_DoEffectTeleport::
|
||||
BattleScript_EffectBeatUp::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
.if B_BEAT_UP >= GEN_5
|
||||
attackstring
|
||||
ppreduce
|
||||
critcalc
|
||||
damagecalc
|
||||
adjustdamage
|
||||
trydobeatup
|
||||
goto BattleScript_HitFromAtkAnimation
|
||||
.else
|
||||
attackstring
|
||||
pause B_WAIT_TIME_SHORT
|
||||
ppreduce
|
||||
@ -4285,7 +4315,6 @@ BattleScript_BeatUpAttack::
|
||||
goto BattleScript_BeatUpLoop
|
||||
BattleScript_BeatUpEnd::
|
||||
end
|
||||
.endif
|
||||
|
||||
BattleScript_EffectDefenseCurl::
|
||||
attackcanceler
|
||||
@ -4522,6 +4551,7 @@ BattleScript_EffectNonVolatileStatus::
|
||||
attackanimation
|
||||
waitanimation
|
||||
setnonvolatilestatus TRIGGER_ON_MOVE
|
||||
clearmoveresultflags MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
@ -4763,8 +4793,8 @@ BattleScript_BrickBreakDoHit::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setadditionaleffects
|
||||
tryfaintmon BS_TARGET
|
||||
setadditionaleffects
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectYawn::
|
||||
@ -4776,11 +4806,15 @@ BattleScript_EffectYawn::
|
||||
setyawn BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
BattleScript_EffectYawnSuccess::
|
||||
printstring STRINGID_PKMNWASMADEDROWSY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_MoveEffectYawnSide::
|
||||
printstring STRINGID_PKMNWASMADEDROWSY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_PrintAbilityMadeIneffective::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
call BattleScript_AbilityPopUp
|
||||
@ -5042,6 +5076,9 @@ BattleScript_FaintAttacker::
|
||||
dofaintanimation BS_ATTACKER
|
||||
printstring STRINGID_ATTACKERFAINTED
|
||||
cleareffectsonfaint BS_ATTACKER
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
waitanimation
|
||||
tryactivatesoulheart
|
||||
tryactivatereceiver BS_ATTACKER
|
||||
@ -5057,6 +5094,9 @@ BattleScript_FaintTarget::
|
||||
dofaintanimation BS_TARGET
|
||||
printstring STRINGID_TARGETFAINTED
|
||||
cleareffectsonfaint BS_TARGET
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
waitanimation
|
||||
tryactivatesoulheart
|
||||
tryactivatereceiver BS_TARGET
|
||||
@ -6577,6 +6617,7 @@ BattleScript_CudChewActivates::
|
||||
|
||||
BattleScript_ApplyDisguiseFormChangeHPLoss::
|
||||
jumpifgenconfiglowerthan GEN_CONFIG_DISGUISE_HP_LOSS, GEN_8, BattleScript_ApplyDisguiseFormChangeHPLossReturn
|
||||
orword gHitMarker, HITMARKER_PASSIVE_HP_UPDATE
|
||||
healthbarupdate BS_SCRIPTING
|
||||
datahpupdate BS_SCRIPTING
|
||||
BattleScript_ApplyDisguiseFormChangeHPLossReturn:
|
||||
@ -6701,7 +6742,7 @@ BattleScript_MoveUsedWokeUp::
|
||||
BattleScript_MonWokeUpInUproar::
|
||||
printstring STRINGID_PKMNWOKEUPINUPROAR
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_ATTACKER
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
end2
|
||||
|
||||
BattleScript_PoisonTurnDmg::
|
||||
@ -6947,7 +6988,7 @@ BattleScript_UpdateEffectStatusIconRet::
|
||||
flushtextbox
|
||||
return
|
||||
|
||||
BattleScript_YawnMakesAsleep::
|
||||
BattleScript_YawnMakesAsleepEnd2::
|
||||
statusanimation BS_EFFECT_BATTLER
|
||||
printstring STRINGID_PKMNFELLASLEEP
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
@ -7823,7 +7864,7 @@ BattleScript_FlinchPrevention::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNSXPREVENTSFLINCHING
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_OwnTempoPrevents::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -7912,7 +7953,7 @@ BattleScript_TeraShellDistortingTypeMatchups::
|
||||
|
||||
BattleScript_CursedBodyActivates::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_CUSEDBODYDISABLED
|
||||
printstring STRINGID_CURSEDBODYDISABLED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
@ -7928,6 +7969,10 @@ BattleScript_MummyActivates::
|
||||
recordability BS_ATTACKER
|
||||
printstring STRINGID_ATTACKERACQUIREDABILITY
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
trytoclearprimalweather
|
||||
tryrevertweatherform
|
||||
flushtextbox
|
||||
tryendneutralizinggas
|
||||
return
|
||||
|
||||
BattleScript_WanderingSpiritActivates::
|
||||
@ -7997,11 +8042,12 @@ BattleScript_WeakArmorDefPrintString:
|
||||
printstring STRINGID_TARGETABILITYSTATLOWER
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_WeakArmorActivatesSpeed:
|
||||
.if B_WEAK_ARMOR_SPEED >= GEN_7
|
||||
jumpifgenconfiglowerthan GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7, BattleScript_WeakArmorSetSpeedGen6
|
||||
setstatchanger STAT_SPEED, 2, FALSE
|
||||
.else
|
||||
goto BattleScript_WeakArmorDoSpeed
|
||||
BattleScript_WeakArmorSetSpeedGen6:
|
||||
setstatchanger STAT_SPEED, 1, FALSE
|
||||
.endif
|
||||
BattleScript_WeakArmorDoSpeed:
|
||||
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, BattleScript_WeakArmorActivatesEnd
|
||||
jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_WeakArmorSpeedPrintString
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_ROSE_EMPTY, BattleScript_WeakArmorActivatesEnd
|
||||
@ -9252,26 +9298,7 @@ BattleScript_TargetAbilityStatRaiseRet_End:
|
||||
BattleScript_EffectMaxMove::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
|
||||
attackstring
|
||||
ppreduce
|
||||
critcalc
|
||||
damagecalc
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
tryfaintmon BS_TARGET
|
||||
setadditionaleffects
|
||||
moveendall
|
||||
end
|
||||
goto BattleScript_HitFromAtkString
|
||||
|
||||
BattleScript_EffectRaiseStatAllies::
|
||||
savetarget
|
||||
@ -9287,7 +9314,7 @@ BattleScript_RaiseSideStatsIncrement:
|
||||
setallytonexttarget BattleScript_RaiseSideStatsLoop
|
||||
BattleScript_RaiseSideStatsEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectLowerStatFoes::
|
||||
savetarget
|
||||
@ -9303,26 +9330,26 @@ BattleScript_LowerSideStatsIncrement:
|
||||
setallytonexttarget BattleScript_LowerSideStatsLoop
|
||||
BattleScript_LowerSideStatsEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectSetWeather::
|
||||
playanimation 0, B_ANIM_MAX_SET_WEATHER
|
||||
printfromtable gMoveWeatherChangeStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
call BattleScript_ActivateWeatherAbilities
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectSetTerrain::
|
||||
printfromtable gTerrainStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
|
||||
call BattleScript_ActivateTerrainEffects
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_DamageNonTypesStarts::
|
||||
printfromtable gDamageNonTypesStartStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_DamageNonTypesContinues::
|
||||
printfromtable gDamageNonTypesDmgStringIds
|
||||
@ -9335,7 +9362,7 @@ BattleScript_EffectTryReducePP::
|
||||
tryspiteppreduce BattleScript_MoveEnd
|
||||
printstring STRINGID_PKMNREDUCEDPP
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectParalyzeSide::
|
||||
savetarget
|
||||
@ -9343,18 +9370,12 @@ BattleScript_EffectParalyzeSide::
|
||||
BattleScript_ParalyzeSideLoop:
|
||||
jumpifabsent BS_TARGET, BattleScript_ParalyzeSideIncrement
|
||||
trysetparalysis BattleScript_ParalyzeSideIncrement
|
||||
statusanimation BS_TARGET
|
||||
updatestatusicon BS_TARGET
|
||||
printfromtable gStatusConditionsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
BattleScript_ParalyzeSideIncrement:
|
||||
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_ParalyzeSideEnd
|
||||
setallytonexttarget BattleScript_ParalyzeSideLoop
|
||||
BattleScript_ParalyzeSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectPoisonSide::
|
||||
savetarget
|
||||
@ -9362,18 +9383,12 @@ BattleScript_EffectPoisonSide::
|
||||
BattleScript_PoisonSideLoop:
|
||||
jumpifabsent BS_TARGET, BattleScript_PoisonSideIncrement
|
||||
trysetpoison BattleScript_PoisonSideIncrement
|
||||
statusanimation BS_TARGET
|
||||
updatestatusicon BS_TARGET
|
||||
printfromtable gStatusConditionsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
BattleScript_PoisonSideIncrement:
|
||||
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonSideEnd
|
||||
setallytonexttarget BattleScript_PoisonSideLoop
|
||||
BattleScript_PoisonSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectPoisonParalyzeSide::
|
||||
savetarget
|
||||
@ -9381,18 +9396,12 @@ BattleScript_EffectPoisonParalyzeSide::
|
||||
BattleScript_PoisonParalyzeSideLoop:
|
||||
jumpifabsent BS_TARGET, BattleScript_PoisonParalyzeSideIncrement
|
||||
trysetpoisonparalysis BattleScript_PoisonParalyzeSideIncrement
|
||||
statusanimation BS_TARGET
|
||||
updatestatusicon BS_TARGET
|
||||
printfromtable gStatusConditionsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
BattleScript_PoisonParalyzeSideIncrement:
|
||||
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_PoisonParalyzeSideEnd
|
||||
setallytonexttarget BattleScript_PoisonParalyzeSideLoop
|
||||
BattleScript_PoisonParalyzeSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectEffectSporeSide::
|
||||
savetarget
|
||||
@ -9400,18 +9409,12 @@ BattleScript_EffectEffectSporeSide::
|
||||
BattleScript_EffectSporeSideLoop:
|
||||
jumpifabsent BS_TARGET, BattleScript_EffectSporeSideIncrement
|
||||
tryseteffectspore BattleScript_EffectSporeSideIncrement
|
||||
statusanimation BS_TARGET
|
||||
updatestatusicon BS_TARGET
|
||||
printfromtable gStatusConditionsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
BattleScript_EffectSporeSideIncrement:
|
||||
jumpifbytenotequal gBattlerTarget, sBATTLER, BattleScript_EffectSporeSideEnd
|
||||
setallytonexttarget BattleScript_EffectSporeSideLoop
|
||||
BattleScript_EffectSporeSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectConfuseSide::
|
||||
savetarget
|
||||
@ -9429,11 +9432,11 @@ BattleScript_ConfuseSideIncrement:
|
||||
BattleScript_ConfuseSideEnd:
|
||||
restoretarget
|
||||
jumpifbyte CMP_EQUAL, gBattleCommunication + 1, 1, BattleScript_PrintCoinsScattered @ Gold Rush
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_PrintCoinsScattered:
|
||||
printstring STRINGID_COINSSCATTERED
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectInfatuateSide::
|
||||
savetarget
|
||||
@ -9450,7 +9453,7 @@ BattleScript_InfatuateSideIncrement:
|
||||
setallytonexttarget BattleScript_InfatuateSideLoop
|
||||
BattleScript_InfatuateSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectTormentSide::
|
||||
savetarget
|
||||
@ -9466,7 +9469,7 @@ BattleScript_TormentSideIncrement:
|
||||
setallytonexttarget BattleScript_TormentSideLoop
|
||||
BattleScript_TormentSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_TormentEnds::
|
||||
printstring STRINGID_TORMENTEDNOMORE
|
||||
@ -9487,7 +9490,7 @@ BattleScript_MeanLookSideIncrement:
|
||||
setallytonexttarget BattleScript_MeanLookSideLoop
|
||||
BattleScript_MeanLookSideEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectRaiseCritAlliesAnim::
|
||||
savetarget
|
||||
@ -9503,7 +9506,7 @@ BattleScript_RaiseCritAlliesIncrement:
|
||||
setallytonexttarget BattleScript_RaiseCritAlliesLoop
|
||||
BattleScript_RaiseCritAlliesEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectHealOneSixthAllies::
|
||||
jumpifteamhealthy BattleScript_MoveEnd
|
||||
@ -9522,7 +9525,7 @@ BattleScript_HealOneSixthAlliesIncrement:
|
||||
setallytonexttarget BattleScript_HealOneSixthAlliesLoop
|
||||
BattleScript_HealOneSixthAlliesEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectRecycleBerriesAllies::
|
||||
savetarget
|
||||
@ -9539,13 +9542,13 @@ BattleScript_RecycleBerriesAlliesIncrement:
|
||||
setallytonexttarget BattleScript_RecycleBerriesAlliesLoop
|
||||
BattleScript_RecycleBerriesAlliesEnd:
|
||||
restoretarget
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
BattleScript_EffectSteelsurge::
|
||||
setsteelsurge BattleScript_MoveEnd
|
||||
printfromtable gDmgHazardsStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
return
|
||||
|
||||
@@@ END MAX MOVES @@@
|
||||
|
||||
@ -9682,7 +9685,7 @@ BattleScript_SleepClauseBlocked::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_SleepClausePreventsEnd::
|
||||
BattleScript_SleepClausePreventsEnd2::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_BLOCKEDBYSLEEPCLAUSE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
|
||||
@ -130,16 +130,16 @@ struct DisableStruct
|
||||
u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case
|
||||
u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in
|
||||
u8 hazardsDone:1;
|
||||
u8 padding1:1;
|
||||
u8 endured:1;
|
||||
u8 octolockedBy:3;
|
||||
u8 padding2:5;
|
||||
u8 tryEjectPack:1;
|
||||
u8 padding:4;
|
||||
};
|
||||
|
||||
// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects
|
||||
struct ProtectStruct
|
||||
{
|
||||
u32 protected:7; // 126 protect options
|
||||
u32 endured:1;
|
||||
u32 noValidMoves:1;
|
||||
u32 helpingHand:1;
|
||||
u32 bounceMove:1;
|
||||
@ -155,26 +155,26 @@ struct ProtectStruct
|
||||
u32 statRaised:1;
|
||||
u32 usedCustapBerry:1; // also quick claw
|
||||
u32 touchedProtectLike:1;
|
||||
u32 unused:8;
|
||||
u32 disableEjectPack:1;
|
||||
u32 pranksterElevated:1;
|
||||
u32 quickDraw:1;
|
||||
u32 beakBlastCharge:1;
|
||||
u32 quash:1;
|
||||
u32 shellTrap:1;
|
||||
u32 eatMirrorHerb:1;
|
||||
u32 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
|
||||
// End of 32-bit bitfield
|
||||
u16 disableEjectPack:1;
|
||||
u16 tryEjectPack:1;
|
||||
u16 pranksterElevated:1;
|
||||
u16 quickDraw:1;
|
||||
u16 beakBlastCharge:1;
|
||||
u16 quash:1;
|
||||
u16 shellTrap:1;
|
||||
u16 eatMirrorHerb:1;
|
||||
u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
|
||||
u16 usedAllySwitch:1;
|
||||
u16 lashOutAffected:1;
|
||||
u16 assuranceDoubled:1;
|
||||
u16 padding:3;
|
||||
u16 myceliumMight:1;
|
||||
u16 laggingTail:1;
|
||||
u16 padding:11;
|
||||
// End of 16-bit bitfield
|
||||
u16 physicalDmg;
|
||||
u16 specialDmg;
|
||||
u8 physicalBattlerId;
|
||||
u8 specialBattlerId;
|
||||
u8 physicalBattlerId:4;
|
||||
u8 specialBattlerId:4;
|
||||
};
|
||||
|
||||
// Cleared at the start of HandleAction_ActionFinished
|
||||
@ -737,6 +737,7 @@ struct BattleStruct
|
||||
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
|
||||
u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle.
|
||||
// When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without.
|
||||
u16 beatUpSpecies[PARTY_SIZE];
|
||||
u8 attackerBeforeBounce:2;
|
||||
u8 beatUpSlot:3;
|
||||
u8 pledgeMove:1;
|
||||
|
||||
@ -150,7 +150,7 @@ extern const u8 BattleScript_TargetWokeUp[];
|
||||
extern const u8 BattleScript_TargetBurnHeal[];
|
||||
extern const u8 BattleScript_TargetPoisonHealed[];
|
||||
extern const u8 BattleScript_MoveEffectSleep[];
|
||||
extern const u8 BattleScript_YawnMakesAsleep[];
|
||||
extern const u8 BattleScript_YawnMakesAsleepEnd2[];
|
||||
extern const u8 BattleScript_MoveEffectPoison[];
|
||||
extern const u8 BattleScript_MoveEffectBurn[];
|
||||
extern const u8 BattleScript_MoveEffectFrostbite[];
|
||||
@ -424,6 +424,7 @@ extern const u8 BattleScript_EjectPackActivates[];
|
||||
extern const u8 BattleScript_MentalHerbCureRet[];
|
||||
extern const u8 BattleScript_MentalHerbCureEnd2[];
|
||||
extern const u8 BattleScript_TerrainPreventsEnd2[];
|
||||
extern const u8 BattleScript_ImmunityProtectedEnd2[];
|
||||
extern const u8 BattleScript_MistyTerrainPrevents[];
|
||||
extern const u8 BattleScript_ElectricTerrainPrevents[];
|
||||
extern const u8 BattleScript_DoesntAffectTargetAtkString[];
|
||||
@ -518,7 +519,7 @@ extern const u8 BattleScript_BoosterEnergyEnd2[];
|
||||
extern const u8 BattleScript_BoosterEnergyRet[];
|
||||
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
|
||||
extern const u8 BattleScript_TeraFormChange[];
|
||||
extern const u8 BattleScript_SleepClausePreventsEnd[];
|
||||
extern const u8 BattleScript_SleepClausePreventsEnd2[];
|
||||
extern const u8 BattleScript_PowerConstruct[];
|
||||
extern const u8 BattleScript_AbilityProtectsDoesntAffect[];
|
||||
extern const u8 BattleScript_ImmunityProtected[];
|
||||
@ -551,10 +552,10 @@ extern const u8 BattleScript_EffectStonesurge[];
|
||||
extern const u8 BattleScript_EffectSteelsurge[];
|
||||
extern const u8 BattleScript_DamageNonTypesStarts[];
|
||||
extern const u8 BattleScript_DamageNonTypesContinues[];
|
||||
extern const u8 BattleScript_DefogTryHazards[];
|
||||
extern const u8 BattleScript_EffectAuroraVeilSuccess[];
|
||||
extern const u8 BattleScript_MoveEffectDefog[];
|
||||
extern const u8 BattleScript_MoveEffectAuroraVeil[];
|
||||
extern const u8 BattleScript_EffectGravitySuccess[];
|
||||
extern const u8 BattleScript_EffectYawnSuccess[];
|
||||
extern const u8 BattleScript_MoveEffectYawnSide[];
|
||||
extern const u8 BattleScript_EffectTryReducePP[];
|
||||
extern const u8 BattleScript_EffectParalyzeSide[];
|
||||
extern const u8 BattleScript_EffectPoisonSide[];
|
||||
@ -649,7 +650,7 @@ extern const u8 BattleScript_EffectSleepTalk[];
|
||||
extern const u8 BattleScript_EffectDestinyBond[];
|
||||
extern const u8 BattleScript_EffectSpite[];
|
||||
extern const u8 BattleScript_EffectHealBell[];
|
||||
extern const u8 BattleScript_EffectHealBell_FromHeal[];
|
||||
extern const u8 BattleScript_MoveEffectAromatherapy[];
|
||||
extern const u8 BattleScript_EffectMeanLook[];
|
||||
extern const u8 BattleScript_EffectNightmare[];
|
||||
extern const u8 BattleScript_EffectMinimize[];
|
||||
|
||||
@ -363,7 +363,7 @@ enum BattleWeather
|
||||
#define B_WEATHER_LOW_LIGHT (B_WEATHER_FOG | B_WEATHER_ICY_ANY | B_WEATHER_RAIN | B_WEATHER_SANDSTORM)
|
||||
#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS)
|
||||
|
||||
// Explicit numbers until frostbite because those shouldn't be shifted
|
||||
// Explicit numbers until frostbite because those shouldn't be shifted
|
||||
enum __attribute__((packed)) MoveEffect
|
||||
{
|
||||
MOVE_EFFECT_NONE = 0,
|
||||
|
||||
@ -480,7 +480,7 @@ enum StringID
|
||||
STRINGID_HEALINGWISHCAMETRUE,
|
||||
STRINGID_HEALINGWISHHEALED,
|
||||
STRINGID_LUNARDANCECAMETRUE,
|
||||
STRINGID_CUSEDBODYDISABLED,
|
||||
STRINGID_CURSEDBODYDISABLED,
|
||||
STRINGID_ATTACKERACQUIREDABILITY,
|
||||
STRINGID_TARGETABILITYSTATLOWER,
|
||||
STRINGID_TARGETSTATWONTGOHIGHER,
|
||||
|
||||
@ -35,6 +35,12 @@ enum GenConfigTag
|
||||
GEN_CONFIG_DISGUISE_HP_LOSS,
|
||||
GEN_CONFIG_AFTER_YOU_TURN_ORDER,
|
||||
GEN_CONFIG_HEALING_WISH_SWITCH,
|
||||
GEN_CONFIG_MEGA_EVO_TURN_ORDER,
|
||||
GEN_CONFIG_SHEER_COLD_IMMUNITY,
|
||||
GEN_CONFIG_WEAK_ARMOR_SPEED,
|
||||
GEN_CONFIG_PRANKSTER_DARK_TYPES,
|
||||
GEN_CONFIG_DESTINY_BOND_FAIL,
|
||||
GEN_CONFIG_POWDER_RAIN,
|
||||
GEN_CONFIG_COUNT
|
||||
};
|
||||
|
||||
|
||||
@ -38,6 +38,12 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
|
||||
[GEN_CONFIG_DISGUISE_HP_LOSS] = B_DISGUISE_HP_LOSS,
|
||||
[GEN_CONFIG_AFTER_YOU_TURN_ORDER] = B_AFTER_YOU_TURN_ORDER,
|
||||
[GEN_CONFIG_HEALING_WISH_SWITCH] = B_HEALING_WISH_SWITCH,
|
||||
[GEN_CONFIG_MEGA_EVO_TURN_ORDER] = B_MEGA_EVO_TURN_ORDER,
|
||||
[GEN_CONFIG_SHEER_COLD_IMMUNITY] = B_SHEER_COLD_IMMUNITY,
|
||||
[GEN_CONFIG_WEAK_ARMOR_SPEED] = B_WEAK_ARMOR_SPEED,
|
||||
[GEN_CONFIG_PRANKSTER_DARK_TYPES] = B_PRANKSTER_DARK_TYPES,
|
||||
[GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL,
|
||||
[GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN,
|
||||
};
|
||||
|
||||
#if TESTING
|
||||
|
||||
@ -214,6 +214,7 @@ enum RandomTag
|
||||
RNG_AI_ASSUME_ALL_STATUS,
|
||||
RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN,
|
||||
RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM,
|
||||
RNG_WRAP,
|
||||
};
|
||||
|
||||
#define RandomWeighted(tag, ...) \
|
||||
|
||||
@ -19,6 +19,7 @@ SECTIONS {
|
||||
{
|
||||
__ewram_start = .;
|
||||
*(.ewram*)
|
||||
. = ALIGN(4);
|
||||
__ewram_end = .;
|
||||
} > EWRAM
|
||||
|
||||
|
||||
@ -1258,7 +1258,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
} // def partner ability checks
|
||||
|
||||
// gen7+ dark type mons immune to priority->elevated moves from prankster
|
||||
if (B_PRANKSTER_DARK_TYPES >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)
|
||||
if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK)
|
||||
&& aiData->abilities[battlerAtk] == ABILITY_PRANKSTER && IsBattleMoveStatus(move)
|
||||
&& !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER)))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
@ -1702,7 +1702,9 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_TOXIC_THREAD:
|
||||
if (!CanLowerStat(battlerAtk, battlerDef, aiData, STAT_SPEED))
|
||||
ADJUST_SCORE(-1); // may still want to just poison
|
||||
//fallthrough
|
||||
if (!AI_CanPoison(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_LIGHT_SCREEN:
|
||||
if (gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL)
|
||||
|| (HasPartner(battlerAtk) && AreMovesEquivalent(battlerAtk, BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)))
|
||||
@ -1720,7 +1722,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_SHEER_COLD:
|
||||
if (B_SHEER_COLD_IMMUNITY >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && IS_BATTLER_OF_TYPE(battlerDef, TYPE_ICE))
|
||||
RETURN_SCORE_MINUS(20);
|
||||
// fallthrough
|
||||
case EFFECT_OHKO:
|
||||
@ -2600,7 +2602,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
{
|
||||
// This only happens if the ally already rolled on double trick room on final turn.
|
||||
// Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out.
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter)
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1))
|
||||
ADJUST_SCORE(PERFECT_EFFECT);
|
||||
else
|
||||
ADJUST_SCORE(-10);
|
||||
@ -2611,7 +2613,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
ADJUST_SCORE(-10);
|
||||
// Don't unset a trick room that doesn't harm you unless it's about to expire.
|
||||
else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != gBattleTurnCounter && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
else if ((gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && !ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
ADJUST_SCORE(-10);
|
||||
}
|
||||
break;
|
||||
@ -2808,7 +2810,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_TAILWIND:
|
||||
if (gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_TAILWIND
|
||||
|| PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND)
|
||||
|| (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter))
|
||||
|| (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1)))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_LUCKY_CHANT:
|
||||
@ -3092,7 +3094,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
switch (effect)
|
||||
{
|
||||
case EFFECT_HELPING_HAND:
|
||||
if (!hasPartner
|
||||
if (!hasPartner
|
||||
|| !HasDamagingMove(battlerAtkPartner)
|
||||
|| (aiData->partnerMove != MOVE_NONE && IsBattleMoveStatus(aiData->partnerMove)))
|
||||
{
|
||||
@ -3108,7 +3110,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (hasTwoOpponents)
|
||||
{
|
||||
// Might be about to die
|
||||
if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) && CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk)
|
||||
if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtk), battlerAtk) && CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk)
|
||||
&& AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtk), move, predictedMove, DONT_CONSIDER_PRIORITY)
|
||||
&& AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
@ -3130,14 +3132,14 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
else if (IsBattlerAlive(BATTLE_OPPOSITE(battlerAtkPartner)))
|
||||
{
|
||||
// Might be about to die
|
||||
if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk)
|
||||
if (CanTargetFaintAi(BATTLE_OPPOSITE(battlerAtkPartner), battlerAtk)
|
||||
&& AI_IsSlower(battlerAtk, BATTLE_OPPOSITE(battlerAtkPartner), move, predictedMove, DONT_CONSIDER_PRIORITY))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
|
||||
if (ownHitsToKOFoe2 > partnerHitsToKOFoe2 && partnerHitsToKOFoe2 > 1)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EFFECT_PERISH_SONG:
|
||||
@ -3173,15 +3175,15 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
// Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out.
|
||||
// This unsets Trick Room and resets it with a full timer.
|
||||
case EFFECT_TRICK_ROOM:
|
||||
if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter
|
||||
if (hasPartner && gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1)
|
||||
&& ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM)
|
||||
&& HasMoveWithEffect(battlerAtkPartner, MOVE_TRICK_ROOM)
|
||||
&& HasMoveWithEffect(battlerAtkPartner, EFFECT_TRICK_ROOM)
|
||||
&& RandomPercentage(RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN, DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE))
|
||||
ADJUST_SCORE(PERFECT_EFFECT);
|
||||
break;
|
||||
case EFFECT_TAILWIND:
|
||||
// Anticipate both opponents protecting to stall out Trick Room, and apply Tailwind.
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == (gBattleTurnCounter + 1)
|
||||
&& RandomPercentage(RNG_AI_APPLY_TAILWIND_ON_LAST_TURN_OF_TRICK_ROOM, TAILWIND_IN_TRICK_ROOM_CHANCE))
|
||||
ADJUST_SCORE(BEST_EFFECT);
|
||||
break;
|
||||
@ -5182,9 +5184,9 @@ case EFFECT_GUARD_SPLIT:
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
// Set it for next pokemon in singles.
|
||||
else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
// Don't unset it on last turn.
|
||||
else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1) && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
break;
|
||||
@ -5292,7 +5294,7 @@ case EFFECT_GUARD_SPLIT:
|
||||
break;
|
||||
case EFFECT_TAILWIND:
|
||||
{
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter)
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != (gBattleTurnCounter + 1))
|
||||
break;
|
||||
|
||||
if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL))
|
||||
@ -5313,7 +5315,7 @@ case EFFECT_GUARD_SPLIT:
|
||||
u32 partnerSpeed = aiData->speedStats[BATTLE_PARTNER(battlerAtk)];
|
||||
u32 foe1Speed = aiData->speedStats[FOE(battlerAtk)];
|
||||
u32 foe2Speed = aiData->speedStats[BATTLE_PARTNER(FOE(battlerAtk))];
|
||||
|
||||
|
||||
if (speed <= foe1Speed && (speed * 2) > foe1Speed)
|
||||
tailwindScore += 1;
|
||||
if (speed <= foe2Speed && (speed * 2) > foe2Speed)
|
||||
|
||||
@ -28,6 +28,17 @@ static u32 GetAIEffectGroup(enum BattleMoveEffects effect);
|
||||
static u32 GetAIEffectGroupFromMove(u32 battler, u32 move);
|
||||
|
||||
// Functions
|
||||
static u32 AI_GetMoldBreakerSanitizedAbility(u32 battlerAtk, u32 abilityAtk, u32 abilityDef, u32 holdEffectDef, u32 move)
|
||||
{
|
||||
if (MoveIgnoresTargetAbility(move))
|
||||
return ABILITY_NONE;
|
||||
|
||||
if (holdEffectDef != HOLD_EFFECT_ABILITY_SHIELD && IsMoldBreakerTypeAbility(battlerAtk, abilityAtk))
|
||||
return ABILITY_NONE;
|
||||
|
||||
return abilityDef;
|
||||
}
|
||||
|
||||
static bool32 AI_IsDoubleSpreadMove(u32 battlerAtk, u32 move)
|
||||
{
|
||||
u32 numOfTargets = 0;
|
||||
@ -896,10 +907,10 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
|
||||
ctx.updateFlags = FALSE;
|
||||
ctx.weather = weather;
|
||||
ctx.fixedBasePower = SetFixedMoveBasePower(battlerAtk, move);
|
||||
ctx.abilityAtk = aiData->abilities[battlerAtk];
|
||||
ctx.abilityDef = aiData->abilities[battlerDef];
|
||||
ctx.holdEffectAtk = aiData->holdEffects[battlerAtk];
|
||||
ctx.holdEffectDef = aiData->holdEffects[battlerDef];
|
||||
ctx.abilityAtk = aiData->abilities[battlerAtk];
|
||||
ctx.abilityDef = AI_GetMoldBreakerSanitizedAbility(battlerAtk, ctx.abilityAtk, aiData->abilities[battlerDef], ctx.holdEffectDef, move);
|
||||
ctx.typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(&ctx);
|
||||
|
||||
u32 movePower = GetMovePower(move);
|
||||
|
||||
@ -763,8 +763,9 @@ static bool32 HandleEndTurnWrap(u32 battler)
|
||||
|
||||
if (gBattleMons[battler].volatiles.wrapped && IsBattlerAlive(battler))
|
||||
{
|
||||
if (--gDisableStructs[battler].wrapTurns != 0)
|
||||
if (gDisableStructs[battler].wrapTurns != 0)
|
||||
{
|
||||
gDisableStructs[battler].wrapTurns--;
|
||||
if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD))
|
||||
return effect;
|
||||
|
||||
@ -1024,7 +1025,6 @@ static bool32 HandleEndTurnYawn(u32 battler)
|
||||
&& !UproarWakeUpCheck(battler)
|
||||
&& !IsLeafGuardProtected(battler, ability))
|
||||
{
|
||||
CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN);
|
||||
gEffectBattler = gBattlerTarget = battler;
|
||||
if (IsBattlerTerrainAffected(battler, STATUS_FIELD_ELECTRIC_TERRAIN))
|
||||
{
|
||||
@ -1038,7 +1038,15 @@ static bool32 HandleEndTurnYawn(u32 battler)
|
||||
}
|
||||
else if (IsSleepClauseActiveForSide(GetBattlerSide(battler)))
|
||||
{
|
||||
BattleScriptExecute(BattleScript_SleepClausePreventsEnd);
|
||||
BattleScriptExecute(BattleScript_SleepClausePreventsEnd2);
|
||||
}
|
||||
else if ((gBattleScripting.battler = IsAbilityOnSide(battler, ABILITY_SWEET_VEIL)))
|
||||
{
|
||||
gBattleScripting.battler--;
|
||||
gLastUsedAbility = ABILITY_SWEET_VEIL;
|
||||
gBattlerAbility = gBattleScripting.battler;
|
||||
RecordAbilityBattle(gBattleScripting.battler, ABILITY_SWEET_VEIL);
|
||||
BattleScriptExecute(BattleScript_ImmunityProtectedEnd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1047,10 +1055,11 @@ static bool32 HandleEndTurnYawn(u32 battler)
|
||||
else
|
||||
gBattleMons[battler].status1 |= ((Random() % 4) + 3);
|
||||
|
||||
CancelMultiTurnMoves(battler, SKY_DROP_STATUS_YAWN);
|
||||
TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]);
|
||||
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
BattleScriptExecute(BattleScript_YawnMakesAsleep);
|
||||
BattleScriptExecute(BattleScript_YawnMakesAsleepEnd2);
|
||||
}
|
||||
effect = TRUE;
|
||||
}
|
||||
@ -1361,25 +1370,22 @@ static bool32 HandleEndTurnThirdEventBlock(u32 battler)
|
||||
case THIRD_EVENT_BLOCK_UPROAR:
|
||||
if (gBattleMons[battler].volatiles.uproarTurns)
|
||||
{
|
||||
for (gBattlerAttacker = 0; gBattlerAttacker < gBattlersCount; gBattlerAttacker++)
|
||||
for (gEffectBattler = 0; gEffectBattler < gBattlersCount; gEffectBattler++)
|
||||
{
|
||||
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
|
||||
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF)
|
||||
if ((gBattleMons[gEffectBattler].status1 & STATUS1_SLEEP)
|
||||
&& GetBattlerAbility(gEffectBattler) != ABILITY_SOUNDPROOF)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP;
|
||||
gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE;
|
||||
gBattleMons[gEffectBattler].status1 &= ~STATUS1_SLEEP;
|
||||
gBattleMons[gEffectBattler].volatiles.nightmare = FALSE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
|
||||
BattleScriptExecute(BattleScript_MonWokeUpInUproar);
|
||||
BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
BtlController_EmitSetMonData(gEffectBattler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1);
|
||||
MarkBattlerForControllerExec(gEffectBattler);
|
||||
effect = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gBattlerAttacker != gBattlersCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (effect == FALSE)
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
gBattleMons[battler].volatiles.uproarTurns--; // uproar timer goes down
|
||||
|
||||
@ -3197,6 +3197,9 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
|
||||
memset(&gDisableStructs[battler], 0, sizeof(struct DisableStruct));
|
||||
|
||||
if (GetProtectType(gProtectStructs[battler].protected) == PROTECT_TYPE_SINGLE) // Side type protects expire at the end of the turn
|
||||
gProtectStructs[battler].protected = PROTECT_NONE;
|
||||
|
||||
if (effect == EFFECT_BATON_PASS)
|
||||
{
|
||||
gDisableStructs[battler].substituteHP = disableStructCopy.substituteHP;
|
||||
@ -3294,9 +3297,7 @@ const u8* FaintClearSetData(u32 battler)
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[battler].statStages[i] = DEFAULT_STAT_STAGE;
|
||||
|
||||
bool32 keepGastroAcid = FALSE;
|
||||
if (gBattleMons[battler].volatiles.gastroAcid)
|
||||
keepGastroAcid = TRUE;
|
||||
bool32 keepGastroAcid = gBattleMons[battler].volatiles.gastroAcid;
|
||||
memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles));
|
||||
gBattleMons[battler].volatiles.gastroAcid = keepGastroAcid; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out.
|
||||
|
||||
@ -3323,7 +3324,6 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gProtectStructs[battler].protected = PROTECT_NONE;
|
||||
|
||||
gProtectStructs[battler].quash = FALSE;
|
||||
gProtectStructs[battler].endured = FALSE;
|
||||
gProtectStructs[battler].noValidMoves = FALSE;
|
||||
gProtectStructs[battler].helpingHand = FALSE;
|
||||
gProtectStructs[battler].bounceMove = FALSE;
|
||||
@ -3335,7 +3335,6 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gProtectStructs[battler].fleeType = 0;
|
||||
gProtectStructs[battler].notFirstStrike = FALSE;
|
||||
gProtectStructs[battler].statRaised = FALSE;
|
||||
gProtectStructs[battler].tryEjectPack = FALSE;
|
||||
gProtectStructs[battler].pranksterElevated = FALSE;
|
||||
|
||||
gDisableStructs[battler].isFirstTurn = 2;
|
||||
@ -4488,6 +4487,10 @@ static void HandleTurnActionSelectionState(void)
|
||||
gBattleStruct->chosenMovePositions[battler] = gBattleResources->bufferB[battler][2] & ~RET_GIMMICK;
|
||||
gChosenMoveByBattler[battler] = gBattleMons[battler].moves[gBattleStruct->chosenMovePositions[battler]];
|
||||
gBattleStruct->moveTarget[battler] = gBattleResources->bufferB[battler][3];
|
||||
if (IsBattleMoveStatus(gChosenMoveByBattler[battler]) && GetBattlerAbility(battler) == ABILITY_MYCELIUM_MIGHT)
|
||||
gProtectStructs[battler].myceliumMight = TRUE;
|
||||
if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_LAGGING_TAIL)
|
||||
gProtectStructs[battler].laggingTail = TRUE;
|
||||
|
||||
// Check to see if any gimmicks need to be prepared.
|
||||
if (gBattleResources->bufferB[battler][2] & RET_GIMMICK)
|
||||
@ -4821,9 +4824,13 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move)
|
||||
if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS)
|
||||
return GetMovePriority(MOVE_MAX_GUARD);
|
||||
|
||||
if (ability == ABILITY_GALE_WINGS
|
||||
&& (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler))
|
||||
&& GetMoveType(move) == TYPE_FLYING)
|
||||
if (gProtectStructs[battler].quash)
|
||||
{
|
||||
priority = -8;
|
||||
}
|
||||
else if (ability == ABILITY_GALE_WINGS
|
||||
&& (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || IsBattlerAtMaxHp(battler))
|
||||
&& GetMoveType(move) == TYPE_FLYING)
|
||||
{
|
||||
priority++;
|
||||
}
|
||||
@ -4837,10 +4844,9 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move)
|
||||
priority++;
|
||||
}
|
||||
else if (ability == ABILITY_TRIAGE && IsHealingMove(move))
|
||||
{
|
||||
priority += 3;
|
||||
|
||||
if (gProtectStructs[battler].quash)
|
||||
priority = -8;
|
||||
}
|
||||
|
||||
return priority;
|
||||
}
|
||||
@ -4857,16 +4863,16 @@ s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMov
|
||||
// Lagging Tail - always last
|
||||
bool32 battler1HasQuickEffect = gProtectStructs[battler1].quickDraw || gProtectStructs[battler1].usedCustapBerry;
|
||||
bool32 battler2HasQuickEffect = gProtectStructs[battler2].quickDraw || gProtectStructs[battler2].usedCustapBerry;
|
||||
bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || (ability1 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler1]));
|
||||
bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || (ability2 == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gChosenMoveByBattler[battler2]));
|
||||
bool32 battler1HasStallingAbility = ability1 == ABILITY_STALL || gProtectStructs[battler1].myceliumMight;
|
||||
bool32 battler2HasStallingAbility = ability2 == ABILITY_STALL || gProtectStructs[battler2].myceliumMight;
|
||||
|
||||
if (battler1HasQuickEffect && !battler2HasQuickEffect)
|
||||
strikesFirst = 1;
|
||||
else if (battler2HasQuickEffect && !battler1HasQuickEffect)
|
||||
strikesFirst = -1;
|
||||
else if (holdEffectBattler1 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler2 != HOLD_EFFECT_LAGGING_TAIL)
|
||||
else if (gProtectStructs[battler1].laggingTail && !gProtectStructs[battler2].laggingTail)
|
||||
strikesFirst = -1;
|
||||
else if (holdEffectBattler2 == HOLD_EFFECT_LAGGING_TAIL && holdEffectBattler1 != HOLD_EFFECT_LAGGING_TAIL)
|
||||
else if (gProtectStructs[battler2].laggingTail && !gProtectStructs[battler1].laggingTail)
|
||||
strikesFirst = 1;
|
||||
else if (battler1HasStallingAbility && !battler2HasStallingAbility)
|
||||
strikesFirst = -1;
|
||||
@ -5185,7 +5191,7 @@ static bool32 TryDoGimmicksBeforeMoves(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (B_MEGA_EVO_TURN_ORDER >= GEN_7)
|
||||
if (GetGenConfig(GEN_CONFIG_MEGA_EVO_TURN_ORDER) >= GEN_7)
|
||||
TryChangeTurnOrder(); // This will just do nothing if no mon has mega evolved.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_PKMNFASTASLEEP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n正在呼呼大睡。"),
|
||||
[STRINGID_PKMNWOKEUP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n醒过来了!"),
|
||||
[STRINGID_PKMNUPROARKEPTAWAKE] = COMPOUND_STRING("但是,{B_SCR_NAME_WITH_PREFIX2}\n被吵得无法入睡!"),
|
||||
[STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX2}\n被吵醒了!"),
|
||||
[STRINGID_PKMNWOKEUPINUPROAR] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX2}\n被吵醒了!"),
|
||||
[STRINGID_PKMNCAUSEDUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n吵闹了起来!"),
|
||||
[STRINGID_PKMNMAKINGUPROAR] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n吵闹个不停!"),
|
||||
[STRINGID_PKMNCALMEDDOWN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n平静了下来!"),
|
||||
@ -623,7 +623,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_SOLARPOWERHPDROP] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}因{B_ATK_ABILITY}\n削减了体力!"), //don't think this message is displayed anymore
|
||||
[STRINGID_AFTERMATHDMG] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n受伤了!"),
|
||||
[STRINGID_ANTICIPATIONACTIVATES] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}\n发抖了!"),
|
||||
[STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("因{B_SCR_ABILITY},{B_SCR_NAME_WITH_PREFIX2}察觉到了\n{B_DEF_NAME_WITH_PREFIX2}的{B_BUFF1}!"),
|
||||
[STRINGID_FOREWARNACTIVATES] = COMPOUND_STRING("因{B_SCR_ABILITY},{B_SCR_NAME_WITH_PREFIX2}察觉到了\n{B_EFF_NAME_WITH_PREFIX2}的{B_BUFF1}!"),
|
||||
[STRINGID_ICEBODYHPGAIN] = COMPOUND_STRING("因为{B_ATK_ABILITY},\n{B_ATK_NAME_WITH_PREFIX}回复了少许HP。"), //don't think this message is displayed anymore
|
||||
[STRINGID_SNOWWARNINGHAIL] = COMPOUND_STRING("开始下冰雹了!"),
|
||||
[STRINGID_FRISKACTIVATES] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}察觉到了\n{B_DEF_NAME_WITH_PREFIX2}的{B_LAST_ITEM}!"),
|
||||
@ -640,7 +640,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
||||
[STRINGID_HEALINGWISHCAMETRUE] = COMPOUND_STRING("治愈之愿\n在{B_ATK_NAME_WITH_PREFIX2}身上实现了!"),
|
||||
[STRINGID_HEALINGWISHHEALED] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的\n体力回复了!"),
|
||||
[STRINGID_LUNARDANCECAMETRUE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}\n被神秘的月光包围了!"),
|
||||
[STRINGID_CUSEDBODYDISABLED] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX2}的{B_DEF_ABILITY},\n封住了{B_ATK_NAME_WITH_PREFIX}的\l{B_BUFF1}!"),
|
||||
[STRINGID_CURSEDBODYDISABLED] = COMPOUND_STRING("因{B_DEF_NAME_WITH_PREFIX2}的{B_DEF_ABILITY},\n封住了{B_ATK_NAME_WITH_PREFIX}的\l{B_BUFF1}!"),
|
||||
[STRINGID_ATTACKERACQUIREDABILITY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}的特性\n变为{B_LAST_ABILITY}了!"),
|
||||
[STRINGID_TARGETABILITYSTATLOWER] = COMPOUND_STRING("因为{B_DEF_ABILITY},\n{B_DEF_NAME_WITH_PREFIX}的{B_BUFF1}降低了!"),
|
||||
[STRINGID_TARGETSTATWONTGOHIGHER] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}的\n{B_BUFF1}已经无法再提高了!"),
|
||||
|
||||
@ -1920,7 +1920,7 @@ static void Cmd_adjustdamage(void)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
}
|
||||
else if (gProtectStructs[battlerDef].endured)
|
||||
else if (gDisableStructs[battlerDef].endured)
|
||||
{
|
||||
enduredHit |= 1u << battlerDef;
|
||||
gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED;
|
||||
@ -2321,6 +2321,7 @@ static void Cmd_datahpupdate(void)
|
||||
{
|
||||
CMD_ARGS(u8 battler);
|
||||
bool32 isPassiveHpUpdate = gHitMarker & HITMARKER_PASSIVE_HP_UPDATE;
|
||||
bool32 disguiseActivates = FALSE;
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
@ -2362,7 +2363,7 @@ static void Cmd_datahpupdate(void)
|
||||
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8;
|
||||
BattleScriptPush(cmd->nextInstr);
|
||||
gBattlescriptCurrInstr = BattleScript_TargetFormChange;
|
||||
return;
|
||||
disguiseActivates = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2447,6 +2448,9 @@ static void Cmd_datahpupdate(void)
|
||||
&& CanBattlerGetOrLoseItem(gBattlerTarget, gBattleMons[gBattlerTarget].item)
|
||||
&& !NoAliveMonsForEitherParty())
|
||||
gBattleStruct->battlerState[gBattlerTarget].itemCanBeKnockedOff = TRUE;
|
||||
|
||||
if (disguiseActivates)
|
||||
return;
|
||||
}
|
||||
|
||||
TryRestoreDamageAfterCheekPouch(battler);
|
||||
@ -2893,7 +2897,7 @@ static inline bool32 TrySetLightScreen(u32 battler)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger)
|
||||
static void SetNonVolatileStatus(u32 effectBattler, enum MoveEffect effect, enum StatusTrigger trigger)
|
||||
{
|
||||
gEffectBattler = effectBattler;
|
||||
|
||||
@ -3037,7 +3041,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
battlerAbility,
|
||||
gBattleScripting.moveEffect,
|
||||
CHECK_TRIGGER))
|
||||
SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_MOVE);
|
||||
break;
|
||||
case MOVE_EFFECT_CONFUSION:
|
||||
if (!CanBeConfused(gEffectBattler)
|
||||
@ -3075,6 +3079,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
gLastUsedAbility = ABILITY_INNER_FOCUS;
|
||||
gBattlerAbility = gEffectBattler;
|
||||
RecordAbilityBattle(gEffectBattler, ABILITY_INNER_FOCUS);
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_FlinchPrevention;
|
||||
}
|
||||
else
|
||||
@ -3173,7 +3178,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW)
|
||||
gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5;
|
||||
else
|
||||
gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2;
|
||||
gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? RandomUniform(RNG_WRAP, 4, 5) : RandomUniform(RNG_WRAP, 2, 5);
|
||||
|
||||
gBattleStruct->wrappedMove[gEffectBattler] = gCurrentMove;
|
||||
gBattleStruct->wrappedBy[gEffectBattler] = gBattlerAttacker;
|
||||
@ -3386,6 +3391,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
gBattleStruct->moveDamage[i] = gBattleMons[i].maxHP / 16;
|
||||
if (gBattleStruct->moveDamage[i] == 0)
|
||||
gBattleStruct->moveDamage[i] = 1;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectFlameBurst;
|
||||
}
|
||||
break;
|
||||
@ -3892,7 +3898,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
|| gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)
|
||||
{
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_DefogTryHazards;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectDefog;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_AURORA_VEIL:
|
||||
@ -3905,7 +3911,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
gSideTimers[GetBattlerSide(gBattlerAttacker)].auroraVeilTimer = gBattleTurnCounter + 5;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SET_SAFEGUARD;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_EffectAuroraVeilSuccess;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectAuroraVeil;
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_GRAVITY:
|
||||
@ -3951,7 +3957,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
{
|
||||
gBattleMons[gBattlerTarget].volatiles.yawn = 2;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_EffectYawnSuccess;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectYawnSide;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4017,7 +4023,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
break;
|
||||
case MOVE_EFFECT_AROMATHERAPY:
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_EffectHealBell_FromHeal;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectAromatherapy;
|
||||
break;
|
||||
case MOVE_EFFECT_RECYCLE_BERRIES:
|
||||
if (RandomPercentage(RNG_G_MAX_REPLENISH, 50))
|
||||
@ -5539,7 +5545,7 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum
|
||||
|
||||
static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect)
|
||||
{
|
||||
if (gProtectStructs[battlerDef].tryEjectPack
|
||||
if (gDisableStructs[battlerDef].tryEjectPack
|
||||
&& GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& CountUsablePartyMons(battlerDef) > 0
|
||||
@ -6009,7 +6015,7 @@ static void Cmd_moveend(void)
|
||||
|
||||
// Not strictly a protect effect, but works the same way
|
||||
if (gProtectStructs[gBattlerTarget].beakBlastCharge
|
||||
&& CanBeBurned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker))
|
||||
&& CanBeBurned(gBattlerAttacker, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))
|
||||
&& !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT))
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE;
|
||||
@ -6559,7 +6565,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEjectButtonBattlers > 1)
|
||||
@ -6622,7 +6628,7 @@ static void Cmd_moveend(void)
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEmergencyExitBattlers > 1)
|
||||
@ -6677,7 +6683,7 @@ static void Cmd_moveend(void)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -6904,7 +6910,7 @@ static void Cmd_moveend(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE;
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
if (gBattleStruct->battlerState[i].commanderSpecies != SPECIES_NONE && !IsBattlerAlive(i))
|
||||
{
|
||||
@ -9527,7 +9533,7 @@ static void Cmd_setprotectlike(void)
|
||||
{
|
||||
if (GetMoveEffect(gCurrentMove) == EFFECT_ENDURE)
|
||||
{
|
||||
gProtectStructs[gBattlerAttacker].endured = TRUE;
|
||||
gDisableStructs[gBattlerAttacker].endured = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BRACED_ITSELF;
|
||||
}
|
||||
else if (GetProtectType(protectMethod) == PROTECT_TYPE_SIDE)
|
||||
@ -10323,7 +10329,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan
|
||||
}
|
||||
else if (!flags.onlyChecking)
|
||||
{
|
||||
gProtectStructs[battler].tryEjectPack = TRUE;
|
||||
gDisableStructs[battler].tryEjectPack = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
}
|
||||
}
|
||||
@ -10924,7 +10930,7 @@ static void Cmd_tryKO(void)
|
||||
|
||||
if (lands)
|
||||
{
|
||||
if (gProtectStructs[gBattlerTarget].endured)
|
||||
if (gDisableStructs[gBattlerTarget].endured)
|
||||
{
|
||||
gBattleStruct->moveDamage[gBattlerTarget] = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FOE_ENDURED;
|
||||
@ -12464,12 +12470,6 @@ static void Cmd_trysetfutureattack(void)
|
||||
|
||||
static void Cmd_trydobeatup(void)
|
||||
{
|
||||
#if B_BEAT_UP >= GEN_5
|
||||
CMD_ARGS();
|
||||
|
||||
gBattleStruct->beatUpSlot++;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
#else
|
||||
CMD_ARGS(const u8 *endInstr, const u8 *failInstr);
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
|
||||
@ -12514,7 +12514,6 @@ static void Cmd_trydobeatup(void)
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Cmd_setsemiinvulnerablebit(void)
|
||||
@ -14517,13 +14516,13 @@ static void Cmd_setnonvolatilestatus(void)
|
||||
if (gBattleScripting.moveEffect >= MOVE_EFFECT_CONFUSION)
|
||||
SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE);
|
||||
else
|
||||
SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY);
|
||||
SetNonVolatileStatus(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY);
|
||||
break;
|
||||
case TRIGGER_ON_MOVE:
|
||||
SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE);
|
||||
SetNonVolatileStatus(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE);
|
||||
break;
|
||||
case TRIGGER_ON_PROTECT:
|
||||
SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT);
|
||||
SetNonVolatileStatus(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -16330,12 +16329,8 @@ static void TrySetParalysis(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBeParalyzed(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_PARALYSIS;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
|
||||
gEffectBattler = gBattlerTarget;
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
gBattlescriptCurrInstr = nextInstr - 1;
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_PARALYSIS, TRIGGER_ON_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -16347,12 +16342,8 @@ static void TrySetPoison(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerAbility(gBattlerTarget)))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_POISON;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
gEffectBattler = gBattlerTarget;
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
gBattlescriptCurrInstr = nextInstr - 1;
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_POISON, TRIGGER_ON_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -16364,17 +16355,8 @@ static void TrySetSleep(const u8 *nextInstr, const u8 *failInstr)
|
||||
{
|
||||
if (CanBeSlept(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget), BLOCKED_BY_SLEEP_CLAUSE))
|
||||
{
|
||||
if (B_SLEEP_TURNS >= GEN_5)
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2);
|
||||
else
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3);
|
||||
|
||||
TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
|
||||
gEffectBattler = gBattlerTarget;
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
gBattlescriptCurrInstr = nextInstr - 1;
|
||||
SetNonVolatileStatus(gBattlerTarget, MOVE_EFFECT_SLEEP, TRIGGER_ON_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -17860,7 +17842,7 @@ void BS_GetTotemBoost(void)
|
||||
void BS_ActivateItemEffects(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
if (ItemBattleEffects(ITEMEFFECT_NORMAL, gBattlerTarget))
|
||||
if (ItemBattleEffects(ITEMEFFECT_TRY_HEALING, gBattlerTarget))
|
||||
return;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -267,15 +267,8 @@ bool32 EndOrContinueWeather(void)
|
||||
|
||||
static u32 CalcBeatUpPower(void)
|
||||
{
|
||||
u32 basePower;
|
||||
u32 species;
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
|
||||
// Party slot is incremented by the battle script for Beat Up after this damage calculation
|
||||
species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES);
|
||||
basePower = (GetSpeciesBaseAttack(species) / 10) + 5;
|
||||
|
||||
return basePower;
|
||||
u32 species = gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++];
|
||||
return (GetSpeciesBaseAttack(species) / 10) + 5;
|
||||
}
|
||||
|
||||
static bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef, u32 abilityDef)
|
||||
@ -1937,7 +1930,7 @@ static enum MoveCanceller CancellerRecharge(void)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.recharge)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.recharge = TRUE;
|
||||
gBattleMons[gBattlerAttacker].volatiles.recharge = FALSE;
|
||||
gDisableStructs[gBattlerAttacker].rechargeTimer = 0;
|
||||
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge;
|
||||
@ -1956,6 +1949,7 @@ static enum MoveCanceller CancellerAsleepOrFrozen(void)
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]);
|
||||
gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP;
|
||||
gBattleMons[gBattlerAttacker].volatiles.nightmare = FALSE;
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR;
|
||||
BattleScriptCall(BattleScript_MoveUsedWokeUp);
|
||||
return MOVE_STEP_REMOVES_STATUS;
|
||||
@ -2341,7 +2335,7 @@ static enum MoveCanceller CancellerWeatherPrimal(void)
|
||||
if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0)
|
||||
{
|
||||
u32 moveType = GetBattleMoveType(gCurrentMove);
|
||||
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (B_POWDER_RAIN >= GEN_7 || !TryActivatePowderStatus(gCurrentMove)))
|
||||
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (GetGenConfig(GEN_CONFIG_POWDER_RAIN) >= GEN_7 || !TryActivatePowderStatus(gCurrentMove)))
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN;
|
||||
effect = MOVE_STEP_BREAK;
|
||||
@ -2484,14 +2478,19 @@ static enum MoveCanceller CancellerMultihitMoves(void)
|
||||
{
|
||||
struct Pokemon* party = GetBattlerParty(gBattlerAttacker);
|
||||
int i;
|
||||
gBattleStruct->beatUpSlot = 0;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP)
|
||||
&& GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
|
||||
u32 species = GetMonData(&party[i], MON_DATA_SPECIES);
|
||||
if (species != SPECIES_NONE
|
||||
&& GetMonData(&party[i], MON_DATA_HP)
|
||||
&& !GetMonData(&party[i], MON_DATA_IS_EGG)
|
||||
&& !GetMonData(&party[i], MON_DATA_STATUS))
|
||||
{
|
||||
gBattleStruct->beatUpSpecies[gBattleStruct->beatUpSlot++] = species;
|
||||
gMultiHitCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->beatUpSlot = 0;
|
||||
@ -2905,9 +2904,9 @@ static void ForewarnChooseMove(u32 battler)
|
||||
bestId = i;
|
||||
}
|
||||
|
||||
gBattlerTarget = data[bestId].battler;
|
||||
gEffectBattler = data[bestId].battler;
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, data[bestId].moveId)
|
||||
RecordKnownMove(gBattlerTarget, data[bestId].moveId);
|
||||
RecordKnownMove(data[bestId].battler, data[bestId].moveId);
|
||||
|
||||
Free(data);
|
||||
}
|
||||
@ -3975,27 +3974,33 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
break;
|
||||
case ABILITY_INTREPID_SWORD:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& !GetBattlerPartyState(battler)->intrepidSwordBoost)
|
||||
{
|
||||
if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
effect++;
|
||||
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITY_DAUNTLESS_SHIELD:
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)
|
||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||
&& !GetBattlerPartyState(battler)->dauntlessShieldBoost)
|
||||
{
|
||||
if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9)
|
||||
GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE;
|
||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
effect++;
|
||||
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
||||
{
|
||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITY_WIND_RIDER:
|
||||
@ -5181,6 +5186,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
gBattlerTarget,
|
||||
gBattlerAttacker,
|
||||
@ -5189,9 +5197,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
gBattleStruct->synchronizeMoveEffect,
|
||||
CHECK_TRIGGER))
|
||||
{
|
||||
if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
gBattleScripting.moveEffect = gBattleStruct->synchronizeMoveEffect;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, ABILITY_SYNCHRONIZE);
|
||||
@ -5211,6 +5216,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
gBattleScripting.battler = gBattlerAbility = gBattlerAttacker;
|
||||
RecordAbilityBattle(gBattlerAttacker, ABILITY_SYNCHRONIZE);
|
||||
|
||||
if (B_SYNCHRONIZE_TOXIC < GEN_5 && gBattleStruct->synchronizeMoveEffect == MOVE_EFFECT_TOXIC)
|
||||
gBattleStruct->synchronizeMoveEffect = MOVE_EFFECT_POISON;
|
||||
|
||||
if (CanSetNonVolatileStatus(
|
||||
gBattlerAttacker,
|
||||
gBattlerTarget,
|
||||
@ -7724,7 +7732,7 @@ enum IronBallCheck
|
||||
};
|
||||
|
||||
// Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics
|
||||
static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall)
|
||||
static bool32 IsBattlerGroundedInverseCheck(u32 battler, u32 ability, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall)
|
||||
{
|
||||
enum ItemHoldEffect holdEffect = GetBattlerHoldEffect(battler, TRUE);
|
||||
|
||||
@ -7742,7 +7750,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck
|
||||
return FALSE;
|
||||
if (holdEffect == HOLD_EFFECT_AIR_BALLOON)
|
||||
return FALSE;
|
||||
if (gAiLogicData->aiCalcInProgress ? gAiLogicData->abilities[battler] == ABILITY_LEVITATE : IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_LEVITATE))
|
||||
if (ability == ABILITY_LEVITATE)
|
||||
return FALSE;
|
||||
if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE)))
|
||||
return FALSE;
|
||||
@ -7751,7 +7759,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck
|
||||
|
||||
bool32 IsBattlerGrounded(u32 battler)
|
||||
{
|
||||
return IsBattlerGroundedInverseCheck(battler, NOT_INVERSE_BATTLE, CHECK_IRON_BALL);
|
||||
return IsBattlerGroundedInverseCheck(battler, GetBattlerAbility(battler), NOT_INVERSE_BATTLE, CHECK_IRON_BALL);
|
||||
}
|
||||
|
||||
u32 GetMoveSlot(u16 *moves, u32 move)
|
||||
@ -9560,8 +9568,8 @@ s32 CalculateMoveDamage(struct DamageContext *ctx)
|
||||
ctx->weather = GetWeather();
|
||||
ctx->abilityAtk = GetBattlerAbility(ctx->battlerAtk);
|
||||
ctx->abilityDef = GetBattlerAbility(ctx->battlerDef);
|
||||
ctx->holdEffectAtk = GetItemHoldEffect(ctx->battlerAtk);
|
||||
ctx->holdEffectDef = GetItemHoldEffect(ctx->battlerDef);
|
||||
ctx->holdEffectAtk = GetBattlerHoldEffect(ctx->battlerAtk, TRUE);
|
||||
ctx->holdEffectDef = GetBattlerHoldEffect(ctx->battlerDef, TRUE);
|
||||
|
||||
ctx->typeEffectivenessModifier = CalcTypeEffectivenessMultiplier(ctx);
|
||||
|
||||
@ -9705,7 +9713,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
||||
if (B_GLARE_GHOST < GEN_4 && ctx->move == MOVE_GLARE && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_GHOST))
|
||||
modifier = UQ_4_12(0.0);
|
||||
}
|
||||
else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move)))
|
||||
else if (ctx->moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(ctx->move)))
|
||||
{
|
||||
modifier = UQ_4_12(0.0);
|
||||
if (ctx->updateFlags && ctx->abilityDef == ABILITY_LEVITATE)
|
||||
@ -9717,7 +9725,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
||||
RecordAbilityBattle(ctx->battlerDef, ABILITY_LEVITATE);
|
||||
}
|
||||
}
|
||||
else if (B_SHEER_COLD_IMMUNITY >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE))
|
||||
else if (GetGenConfig(GEN_CONFIG_SHEER_COLD_IMMUNITY) >= GEN_7 && GetMoveEffect(ctx->move) == EFFECT_SHEER_COLD && IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_ICE))
|
||||
{
|
||||
modifier = UQ_4_12(0.0);
|
||||
}
|
||||
@ -9735,7 +9743,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(struct DamageCont
|
||||
&& ctx->moveType == TYPE_GROUND
|
||||
&& IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING)
|
||||
&& GetBattlerHoldEffect(ctx->battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL
|
||||
&& !IsBattlerGroundedInverseCheck(ctx->battlerDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL)
|
||||
&& !IsBattlerGroundedInverseCheck(ctx->battlerDef, ctx->abilityDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL)
|
||||
&& !FlagGet(B_FLAG_INVERSE_BATTLE))
|
||||
{
|
||||
modifier = UQ_4_12(1.0);
|
||||
@ -10805,7 +10813,7 @@ bool32 TryRoomService(u32 battler)
|
||||
|
||||
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget)
|
||||
{
|
||||
if (B_PRANKSTER_DARK_TYPES < GEN_7)
|
||||
if (GetGenConfig(GEN_CONFIG_PRANKSTER_DARK_TYPES) < GEN_7)
|
||||
return FALSE;
|
||||
if (!gProtectStructs[battlerPrankster].pranksterElevated)
|
||||
return FALSE;
|
||||
@ -11331,7 +11339,7 @@ void ClearDamageCalcResults(void)
|
||||
|
||||
bool32 DoesDestinyBondFail(u32 battler)
|
||||
{
|
||||
if (B_DESTINY_BOND_FAIL >= GEN_7
|
||||
if (GetGenConfig(GEN_CONFIG_DESTINY_BOND_FAIL) >= GEN_7
|
||||
&& GetMoveEffect(gLastLandedMoves[battler]) == EFFECT_DESTINY_BOND
|
||||
&& GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND)
|
||||
return TRUE;
|
||||
@ -11454,7 +11462,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID)
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gProtectStructs[i].tryEjectPack
|
||||
if (gDisableStructs[i].tryEjectPack
|
||||
&& GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(i)
|
||||
&& CountUsablePartyMons(i) > 0)
|
||||
@ -11472,7 +11480,7 @@ bool32 TrySwitchInEjectPack(enum ItemCaseId caseID)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
gDisableStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
|
||||
@ -132,6 +132,7 @@ u32 BattlePalace_TryEscapeStatus(u8 battler)
|
||||
if (UproarWakeUpCheck(battler))
|
||||
{
|
||||
// Wake up from Uproar
|
||||
gEffectBattler = battler;
|
||||
gBattleMons[battler].status1 &= ~(STATUS1_SLEEP);
|
||||
gBattleMons[battler].volatiles.nightmare = FALSE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR;
|
||||
|
||||
@ -791,7 +791,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
|
||||
|
||||
[EFFECT_BEAT_UP] =
|
||||
{
|
||||
.battleScript = BattleScript_EffectBeatUp,
|
||||
.battleScript = (B_BEAT_UP >= GEN_5) ? BattleScript_EffectHit : BattleScript_EffectBeatUp,
|
||||
.battleTvScore = 2,
|
||||
},
|
||||
|
||||
|
||||
@ -32096,6 +32096,7 @@ static const u16 sDipplinTeachableLearnset[] = {
|
||||
static const u16 sHydrappleTeachableLearnset[] = {
|
||||
MOVE_BODY_SLAM,
|
||||
MOVE_BULLET_SEED,
|
||||
MOVE_DEFENSE_CURL,
|
||||
MOVE_DOUBLE_EDGE,
|
||||
MOVE_EARTHQUAKE,
|
||||
MOVE_ENDURE,
|
||||
@ -32106,6 +32107,7 @@ static const u16 sHydrappleTeachableLearnset[] = {
|
||||
MOVE_RAIN_DANCE,
|
||||
MOVE_REFLECT,
|
||||
MOVE_REST,
|
||||
MOVE_ROLLOUT,
|
||||
MOVE_SLEEP_TALK,
|
||||
MOVE_SOLAR_BEAM,
|
||||
MOVE_SUNNY_DAY,
|
||||
|
||||
@ -2055,19 +2055,7 @@ static u32 LoadDynamicFollowerPalette(u32 species, bool32 shiny, bool32 female)
|
||||
spritePalette.data = gSpeciesInfo[species].overworldPalette;
|
||||
}
|
||||
|
||||
// Check if pal data must be decompressed
|
||||
if (IsLZ77Data(spritePalette.data, PLTT_SIZE_4BPP, PLTT_SIZE_4BPP))
|
||||
{
|
||||
struct SpritePalette compSpritePalette;
|
||||
|
||||
compSpritePalette.data = (const void *) spritePalette.data;
|
||||
compSpritePalette.tag = spritePalette.tag;
|
||||
paletteNum = LoadSpritePalette(&compSpritePalette);
|
||||
}
|
||||
else
|
||||
{
|
||||
paletteNum = LoadSpritePalette(&spritePalette);
|
||||
}
|
||||
paletteNum = LoadSpritePalette(&spritePalette);
|
||||
}
|
||||
else
|
||||
#endif //OW_POKEMON_OBJECT_EVENTS == TRUE && OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE
|
||||
|
||||
@ -83,3 +83,18 @@ SINGLE_BATTLE_TEST("Desolate Land will not create a softlock when move in semi i
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Desolate Land is removed immediately if user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_GROUDON) { HP(1); Item(ITEM_RED_ORB); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_POUND); SEND_OUT(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent);
|
||||
NOT MESSAGE("The sunlight is strong.");
|
||||
MESSAGE("The extremely harsh sunlight faded!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,25 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Filter (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Filter reduces damage to Super Effective moves by 0.75", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_SOUNDPROOF; }
|
||||
PARAMETRIZE { ability = ABILITY_FILTER; }
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[0] == TYPE_PSYCHIC);
|
||||
ASSUME(gSpeciesInfo[SPECIES_MR_MIME].types[1] == TYPE_FAIRY);
|
||||
ASSUME(gMovesInfo[MOVE_POISON_JAB].type == TYPE_POISON);
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0));
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0));
|
||||
PLAYER(SPECIES_MR_MIME) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_POISON_JAB); }
|
||||
} SCENE {
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
MESSAGE("It's super effective!");
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ SINGLE_BATTLE_TEST("Flash Fire boosts fire type moves by 50% but no subsequent i
|
||||
PLAYER(SPECIES_HEATRAN) { Ability(ABILITY_FLASH_FIRE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); }
|
||||
TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); }
|
||||
TURN { MOVE(player, MOVE_EMBER); }
|
||||
TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); MOVE(opponent, MOVE_EMBER); }
|
||||
TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); MOVE(opponent, MOVE_EMBER); }
|
||||
TURN { MOVE(player, MOVE_EMBER, secondaryEffect: FALSE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
|
||||
@ -1,4 +1,115 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Levitate (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Levitate activates when targeted by ground type moves")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND);
|
||||
PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_MUD_SLAP); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_LEVITATE);
|
||||
MESSAGE("Lunatone makes Ground-type moves miss with Levitate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Levitate does not activate if protected")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND);
|
||||
PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_LEVITATE);
|
||||
MESSAGE("Lunatone makes Ground-type moves miss with Levitate!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Levitate does not activate on status moves")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_SAND_ATTACK) == TYPE_GROUND);
|
||||
ASSUME(GetMoveCategory(MOVE_SAND_ATTACK) == DAMAGE_CATEGORY_STATUS);
|
||||
PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SAND_ATTACK); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_LEVITATE);
|
||||
MESSAGE("Lunatone makes Ground-type moves miss with Levitate!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Levitate does not activate if attacked by an opponent with Mold Breaker")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND);
|
||||
PLAYER(SPECIES_LUNATONE) { Ability(ABILITY_LEVITATE); }
|
||||
OPPONENT(SPECIES_TINKATON) { Ability(ABILITY_MOLD_BREAKER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PROTECT); MOVE(opponent, MOVE_MUD_SLAP); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_LEVITATE);
|
||||
MESSAGE("Lunatone makes Ground-type moves miss with Levitate!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Levitate does not cause single remaining target to take higher damage")
|
||||
{
|
||||
s16 damage[3];
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_REGIROCK) { Speed(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
OPPONENT(SPECIES_LUNATONE) { Speed(3); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerRight, MOVE_CELEBRATE); MOVE(playerLeft, MOVE_EARTHQUAKE); }
|
||||
TURN { MOVE(playerRight, MOVE_MEMENTO, target:opponentLeft); MOVE(playerLeft, MOVE_EARTHQUAKE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft);
|
||||
HP_BAR(playerRight, captureDamage: &damage[0]);
|
||||
HP_BAR(opponentRight, captureDamage: &damage[1]);
|
||||
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, playerLeft);
|
||||
HP_BAR(opponentRight, captureDamage: &damage[2]);
|
||||
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
EXPECT_EQ(damage[1], damage[2]);
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Levitate is seen correctly by switch AI")
|
||||
{
|
||||
u32 ability = ABILITY_NONE, item = ITEM_NONE;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_OWN_TEMPO, item = ITEM_NONE ; }
|
||||
PARAMETRIZE { ability = ABILITY_MOLD_BREAKER, item = ITEM_NONE ; }
|
||||
PARAMETRIZE { ability = ABILITY_MOLD_BREAKER, item = ITEM_ABILITY_SHIELD ; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_MUD_SLAP) == TYPE_GROUND);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_TINKATON) { Ability(ability); Speed(3); }
|
||||
OPPONENT(SPECIES_PONYTA) { Level(1); Item(ITEM_EJECT_PACK); Moves(MOVE_OVERHEAT); Speed(4); } // Forces switchout
|
||||
OPPONENT(SPECIES_VIKAVOLT) { HP(1); Speed(1); Ability(ABILITY_LEVITATE); Moves(MOVE_FLAMETHROWER); Item(item); }
|
||||
OPPONENT(SPECIES_HYPNO) { Speed(1); Moves(MOVE_IRON_HEAD); }
|
||||
} WHEN {
|
||||
if ((ability == ABILITY_MOLD_BREAKER) && (item != ITEM_ABILITY_SHIELD))
|
||||
TURN { MOVE(player, MOVE_MUD_SLAP); EXPECT_SEND_OUT(opponent, 2); }
|
||||
else
|
||||
TURN { MOVE(player, MOVE_MUD_SLAP); EXPECT_SEND_OUT(opponent, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,3 +67,30 @@ SINGLE_BATTLE_TEST("Mycelium Might vs Stall action order depends on speed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Mycelium Might priority bracket will not change if the ability is changed mid-turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_TOEDSCOOL) { Speed(100); Ability(ABILITY_MYCELIUM_MIGHT); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(30); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(20); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_WORRY_SEED, target: playerLeft);
|
||||
MOVE(playerLeft, MOVE_SCREECH, target: opponentLeft);
|
||||
}
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WORRY_SEED, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCREECH, playerLeft);
|
||||
|
||||
// Turn 2
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,22 +7,31 @@ ASSUMPTIONS
|
||||
ASSUME(GetMoveCategory(MOVE_CONFUSE_RAY) == DAMAGE_CATEGORY_STATUS);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon")
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon (Gen7+)")
|
||||
{
|
||||
u32 gen;
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CONFUSE_RAY); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
MESSAGE("It doesn't affect Umbreon…");
|
||||
if (gen == GEN_6) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
MESSAGE("It doesn't affect Umbreon…");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves don't affect Dark-type Pokémon after they switch-in")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
@ -49,39 +58,62 @@ DOUBLE_BATTLE_TEST("Prankster-affected moves affect Ally Dark-type Pokémon")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark-type Pokémon")
|
||||
SINGLE_BATTLE_TEST("Prankster-affected moves called via Assist don't affect Dark-type Pokémon (Gen 7+)")
|
||||
{
|
||||
u32 gen;
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_UMBREON);
|
||||
OPPONENT(SPECIES_VOLBEAT) { Ability(ABILITY_PRANKSTER); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CONFUSE_RAY); };
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_ASSIST); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
MESSAGE("It doesn't affect Umbreon…");
|
||||
if (gen == GEN_6) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, opponent);
|
||||
MESSAGE("It doesn't affect Umbreon…");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tested on Showdown, even though Bulbapedia says otherwise.
|
||||
DOUBLE_BATTLE_TEST("Prankster-affected moves called via Instruct do not affect Dark-type Pokémon")
|
||||
{
|
||||
u32 gen;
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, gen);
|
||||
PLAYER(SPECIES_VOLBEAT) { Speed(20); Ability(ABILITY_PRANKSTER); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10);}
|
||||
OPPONENT(SPECIES_UMBREON) { Speed(1); }
|
||||
OPPONENT(SPECIES_UMBREON) { Speed(15); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(1); }
|
||||
OPPONENT(SPECIES_UMBREON) { Speed(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_CONFUSE_RAY, target: opponentLeft);
|
||||
MOVE(opponentLeft, MOVE_U_TURN, target: playerRight, WITH_RNG(RNG_CONFUSION, FALSE));
|
||||
SEND_OUT(opponentLeft, 2);
|
||||
MOVE(playerRight, MOVE_INSTRUCT, target: playerLeft);
|
||||
}
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
MESSAGE("It doesn't affect the opposing Umbreon…");
|
||||
if (gen == GEN_6) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
MESSAGE("It doesn't affect the opposing Umbreon…");
|
||||
}
|
||||
MESSAGE("Wobbuffet used Instruct!");
|
||||
MESSAGE("Volbeat used Confuse Ray!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
MESSAGE("It doesn't affect the opposing Umbreon…");
|
||||
if (gen == GEN_6) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, playerLeft);
|
||||
MESSAGE("It doesn't affect the opposing Umbreon…");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +203,7 @@ SINGLE_BATTLE_TEST("Prankster-affected moves which are reflected by Magic Coat c
|
||||
PARAMETRIZE { sableyeAbility = ABILITY_KEEN_EYE; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
PLAYER(SPECIES_SABLEYE) { Ability(sableyeAbility); }
|
||||
OPPONENT(SPECIES_MURKROW) { Ability(ABILITY_PRANKSTER); }
|
||||
} WHEN {
|
||||
|
||||
@ -1,4 +1,25 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Prism Armor (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Prism Armor reduces damage to Super Effective moves by 0.75", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; }
|
||||
PARAMETRIZE { ability = ABILITY_LEVITATE; }
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[0] == TYPE_PSYCHIC);
|
||||
ASSUME(gSpeciesInfo[SPECIES_NECROZMA].types[1] == TYPE_PSYCHIC);
|
||||
ASSUME(gMovesInfo[MOVE_DARK_PULSE].type == TYPE_DARK);
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_FAIRY] > UQ_4_12(1.0));
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_POISON][TYPE_PSYCHIC] == UQ_4_12(1.0));
|
||||
PLAYER(SPECIES_NECROZMA);
|
||||
OPPONENT(SPECIES_WEEZING) { Ability(ability); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_DARK_PULSE); }
|
||||
} SCENE {
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
MESSAGE("It's super effective!");
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage);
|
||||
}
|
||||
}
|
||||
|
||||
25
test/battle/ability/solid_rock.c
Normal file
25
test/battle/ability/solid_rock.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
SINGLE_BATTLE_TEST("Solid Rock reduces damage to Super Effective moves by 0.75", s16 damage)
|
||||
{
|
||||
u32 ability;
|
||||
PARAMETRIZE { ability = ABILITY_STURDY; }
|
||||
PARAMETRIZE { ability = ABILITY_SOLID_ROCK; }
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[0] == TYPE_WATER);
|
||||
ASSUME(gSpeciesInfo[SPECIES_CARRACOSTA].types[1] == TYPE_ROCK);
|
||||
ASSUME(gMovesInfo[MOVE_CLOSE_COMBAT].type == TYPE_FIGHTING);
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_ROCK] > UQ_4_12(1.0));
|
||||
ASSUME(gTypeEffectivenessTable[TYPE_FIGHTING][TYPE_WATER] == UQ_4_12(1.0));
|
||||
PLAYER(SPECIES_CARRACOSTA) { Ability(ability); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_CLOSE_COMBAT); }
|
||||
} SCENE {
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
MESSAGE("It's super effective!");
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage);
|
||||
}
|
||||
}
|
||||
@ -17,7 +17,7 @@ DOUBLE_BATTLE_TEST("Sweet Veil prevents Sleep on partner - right target")
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentRight); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Hypnosis!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, playerLeft);
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_SWEET_VEIL);
|
||||
NOT STATUS_ICON(opponentRight, sleep: TRUE);
|
||||
}
|
||||
@ -33,7 +33,27 @@ DOUBLE_BATTLE_TEST("Sweet Veil prevents Sleep on partner - left target")
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_HYPNOSIS, target: opponentLeft); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet used Hypnosis!");
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPNOSIS, playerLeft);
|
||||
ABILITY_POPUP(opponentRight, ABILITY_SWEET_VEIL);
|
||||
NOT STATUS_ICON(opponentLeft, sleep: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Sweet Veil prevents Yawn activation")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_BOUNSWEET) { Ability(ABILITY_SWEET_VEIL); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_YAWN, target: opponentLeft); }
|
||||
TURN { SWITCH(opponentRight, 2); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_YAWN, playerLeft);
|
||||
|
||||
// Turn 2
|
||||
ABILITY_POPUP(opponentRight, ABILITY_SWEET_VEIL);
|
||||
NOT STATUS_ICON(opponentLeft, sleep: TRUE);
|
||||
}
|
||||
|
||||
@ -7,17 +7,18 @@ ASSUMPTIONS
|
||||
ASSUME(!IsBattleMoveStatus(MOVE_GUST));
|
||||
ASSUME(GetMoveCategory(MOVE_GUST) == DAMAGE_CATEGORY_SPECIAL);
|
||||
ASSUME(GetMoveCategory(MOVE_SCRATCH) == DAMAGE_CATEGORY_PHYSICAL);
|
||||
ASSUME(B_WEAK_ARMOR_SPEED >= GEN_7);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 2 when hit by a physical attack")
|
||||
SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 1 (Gen5-6) or 2 (Gen7+) when hit by a physical attack")
|
||||
{
|
||||
u16 move;
|
||||
u16 move, gen;
|
||||
|
||||
PARAMETRIZE { move = MOVE_SCRATCH; }
|
||||
PARAMETRIZE { move = MOVE_GUST; }
|
||||
PARAMETRIZE { move = MOVE_SCRATCH; gen = GEN_6; }
|
||||
PARAMETRIZE { move = MOVE_SCRATCH; gen = GEN_7; }
|
||||
PARAMETRIZE { move = MOVE_GUST; gen = GEN_7; }
|
||||
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen);
|
||||
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -41,7 +42,10 @@ SINGLE_BATTLE_TEST("Weak Armor lowers Defense by 1 and boosts Speed by 2 when hi
|
||||
} THEN {
|
||||
if (move == MOVE_SCRATCH) {
|
||||
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1);
|
||||
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + (gen == GEN_7 ? 2 : 1));
|
||||
} else {
|
||||
EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE);
|
||||
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,7 +83,12 @@ SINGLE_BATTLE_TEST("Weak Armor does not trigger when brought in by Dragon Tail a
|
||||
|
||||
SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower")
|
||||
{
|
||||
u16 gen;
|
||||
|
||||
PARAMETRIZE { gen = GEN_6; }
|
||||
PARAMETRIZE { gen = GEN_7; }
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, gen);
|
||||
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
@ -100,7 +109,7 @@ SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower"
|
||||
MESSAGE("Slugma's Weak Armor raised its Speed!");
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_DEF], MIN_STAT_STAGE);
|
||||
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2);
|
||||
EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + (gen == GEN_7 ? 2 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,6 +144,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Defense can'
|
||||
{
|
||||
u32 j;
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7);
|
||||
PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); }
|
||||
OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); }
|
||||
} WHEN {
|
||||
@ -173,6 +183,7 @@ SINGLE_BATTLE_TEST("Weak Armor doesn't interrupt multi hit moves if Speed can't
|
||||
{
|
||||
u32 j;
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_WEAK_ARMOR_SPEED, GEN_7);
|
||||
PLAYER(SPECIES_MAGCARGO) { Ability(ABILITY_WEAK_ARMOR); Defense(999); }
|
||||
OPPONENT(SPECIES_CLOYSTER) { Ability(ABILITY_SKILL_LINK); }
|
||||
} WHEN {
|
||||
|
||||
@ -595,6 +595,25 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently")
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Trick Room with both battlers on the turn it expires in line with the double Trick Room config")
|
||||
{
|
||||
PASSES_RANDOMLY(DOUBLE_TRICK_ROOM_ON_LAST_TURN_CHANCE, 100, RNG_AI_REFRESH_TRICK_ROOM_ON_LAST_TURN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(4); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Moves(MOVE_TRICK_ROOM, MOVE_PSYCHIC); Speed(2); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_TRICK_ROOM, MOVE_PSYCHIC); Speed(1); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_TRICK_ROOM); EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Helping Hand if it's about to die")
|
||||
{
|
||||
u32 hp;
|
||||
|
||||
@ -64,13 +64,14 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: Mid-battle switches prioritize offensive o
|
||||
PARAMETRIZE { aiRiskyFlag = AI_FLAG_RISKY; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(P_UPDATED_STATS >= GEN_7); // Swellow's 50 Sp.Atk in Gen 6 instead of the current 75 causes the AI to switch to Electrode
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT | aiRiskyFlag);
|
||||
PLAYER(SPECIES_SWELLOW) { Level(30); Moves(MOVE_WING_ATTACK, MOVE_BOOMBURST); Speed(5); }
|
||||
OPPONENT(SPECIES_PONYTA) { Level(1); Moves(MOVE_NONE); Speed(4); } // Forces switchout
|
||||
OPPONENT(SPECIES_ARON) { Level(30); Moves(MOVE_HEADBUTT); Speed(4); SpDefense(41); } // Mid battle, AI sends out Aron
|
||||
OPPONENT(SPECIES_ELECTRODE) { Level(30); Moves(MOVE_CHARGE_BEAM); Speed(6); Ability(ABILITY_STATIC); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WING_ATTACK); EXPECT_SWITCH(opponent, aiRiskyFlag? 2 : 1); }
|
||||
TURN { MOVE(player, MOVE_WING_ATTACK); EXPECT_SWITCH(opponent, aiRiskyFlag? 2 : 1); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1033,7 +1033,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch into mon with good type matchup
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI correctly handles abilities when scoring moves")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_PRANKSTER_DARK_TYPES >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_PRANKSTER_DARK_TYPES, GEN_7);
|
||||
ASSUME(GetSpeciesType(SPECIES_GRENINJA, 1) == TYPE_DARK);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_MON_CHOICES);
|
||||
PLAYER(SPECIES_GRENINJA) { Moves(MOVE_WATER_GUN); }
|
||||
|
||||
@ -62,7 +62,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 1-100")
|
||||
{
|
||||
u32 moveStart = 0;
|
||||
u32 moveCap = 100;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -92,7 +92,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 1-100")
|
||||
case EFFECT_DISABLE:
|
||||
|
||||
// tests exist elsewhere
|
||||
|
||||
|
||||
// Skipped on purpose.
|
||||
case EFFECT_PROTECT:
|
||||
case EFFECT_NON_VOLATILE_STATUS:
|
||||
@ -124,7 +124,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 101-200")
|
||||
{
|
||||
u32 moveStart = 100;
|
||||
u32 moveCap = 200;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -200,7 +200,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 201-300")
|
||||
{
|
||||
u32 moveStart = 200;
|
||||
u32 moveCap = 300;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -285,7 +285,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400")
|
||||
{
|
||||
u32 moveStart = 300;
|
||||
u32 moveCap = 400;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -329,7 +329,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 301-400")
|
||||
// tests exist elsewhere
|
||||
case EFFECT_HEAL_BELL:
|
||||
case EFFECT_ATTACK_UP_USER_ALLY:
|
||||
|
||||
|
||||
// Skipped on purpose.
|
||||
case EFFECT_PROTECT:
|
||||
case EFFECT_NON_VOLATILE_STATUS:
|
||||
@ -361,7 +361,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500")
|
||||
{
|
||||
u32 moveStart = 400;
|
||||
u32 moveCap = 500;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -390,12 +390,13 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 401-500")
|
||||
//TODO: AI TESTS
|
||||
case EFFECT_RESTORE_HP:
|
||||
case EFFECT_CAPTIVATE:
|
||||
case EFFECT_DARK_VOID: // Gen 4-6's case is not being handled
|
||||
|
||||
// tests exist elsewhere
|
||||
case EFFECT_TRICK_ROOM:
|
||||
case EFFECT_GUARD_SPLIT:
|
||||
case EFFECT_POWER_SPLIT:
|
||||
|
||||
|
||||
// Skipped on purpose.
|
||||
case EFFECT_PROTECT:
|
||||
case EFFECT_NON_VOLATILE_STATUS:
|
||||
@ -427,7 +428,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 501-600")
|
||||
{
|
||||
u32 moveStart = 515;
|
||||
u32 moveCap = 600;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -502,7 +503,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700")
|
||||
{
|
||||
u32 moveStart = 600;
|
||||
u32 moveCap = 700;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -542,7 +543,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 601-700")
|
||||
case EFFECT_ELECTRIC_TERRAIN:
|
||||
case EFFECT_PSYCHIC_TERRAIN:
|
||||
case EFFECT_AURORA_VEIL:
|
||||
|
||||
|
||||
// Skipped on purpose.
|
||||
case EFFECT_PROTECT:
|
||||
case EFFECT_NON_VOLATILE_STATUS:
|
||||
@ -574,7 +575,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 701-800")
|
||||
{
|
||||
u32 moveStart = 700;
|
||||
u32 moveCap = 800;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
@ -643,7 +644,7 @@ AI_DOUBLE_BATTLE_TEST("AI can use all moves, 801-900")
|
||||
{
|
||||
u32 moveStart = 800;
|
||||
u32 moveCap = 900;
|
||||
|
||||
|
||||
if (moveCap > MOVES_COUNT)
|
||||
moveCap = MOVES_COUNT - 1;
|
||||
|
||||
|
||||
@ -71,10 +71,26 @@ SINGLE_BATTLE_TEST("Rayquaza can Mega Evolve knowing Dragon Ascent")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Mega Evolution affects turn order")
|
||||
SINGLE_BATTLE_TEST("Mega Evolution doesn't affect turn order (Gen6)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_6);
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); }
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wobbuffet used Celebrate!");
|
||||
MESSAGE("Gardevoir used Celebrate!");
|
||||
} THEN {
|
||||
ASSUME(player->speed == 205);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Mega Evolution affects turn order (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7);
|
||||
PLAYER(SPECIES_GARDEVOIR) { Item(ITEM_GARDEVOIRITE); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
} WHEN {
|
||||
@ -90,7 +106,7 @@ SINGLE_BATTLE_TEST("Mega Evolution affects turn order")
|
||||
SINGLE_BATTLE_TEST("Abilities replaced by Mega Evolution do not affect turn order")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7);
|
||||
ASSUME(GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 0) != ABILITY_STALL
|
||||
&& GetSpeciesAbility(SPECIES_SABLEYE_MEGA, 1) != ABILITY_STALL);
|
||||
PLAYER(SPECIES_SABLEYE) { Item(ITEM_SABLENITE); Ability(ABILITY_STALL); Speed(105); }
|
||||
|
||||
@ -58,7 +58,7 @@ DOUBLE_BATTLE_TEST("Ultra Burst's order is determined by Speed - player faster")
|
||||
SINGLE_BATTLE_TEST("Ultra Burst affects turn order")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_MEGA_EVO_TURN_ORDER >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7);
|
||||
PLAYER(SPECIES_NECROZMA_DUSK_MANE) { Item(ITEM_ULTRANECROZIUM_Z); Speed(105); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(106); }
|
||||
} WHEN {
|
||||
|
||||
@ -1018,11 +1018,11 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Volt Crash paralyzes both opponents")
|
||||
} SCENE {
|
||||
MESSAGE("Pikachu used G-Max Volt Crash!");
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentLeft);
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PRZ, opponentRight);
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wynaut is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,22 +1048,22 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Stun Shock paralyzes or poisons both opponent
|
||||
// opponent left
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft);
|
||||
if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
STATUS_ICON(opponentLeft, poison: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet was poisoned!");
|
||||
STATUS_ICON(opponentLeft, poison: TRUE);
|
||||
}
|
||||
else {
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
}
|
||||
// opponent right
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight);
|
||||
if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
STATUS_ICON(opponentRight, poison: TRUE);
|
||||
MESSAGE("The opposing Wynaut was poisoned!");
|
||||
STATUS_ICON(opponentRight, poison: TRUE);
|
||||
}
|
||||
else {
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wynaut is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1118,30 +1118,30 @@ DOUBLE_BATTLE_TEST("Dynamax: G-Max Befuddle paralyzes, poisons, or sleeps both o
|
||||
// opponent left
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentLeft);
|
||||
if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
STATUS_ICON(opponentLeft, poison: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet was poisoned!");
|
||||
STATUS_ICON(opponentLeft, poison: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentLeft, paralysis: TRUE);
|
||||
}
|
||||
else {
|
||||
STATUS_ICON(opponentLeft, sleep: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet fell asleep!");
|
||||
STATUS_ICON(opponentLeft, sleep: TRUE);
|
||||
}
|
||||
// opponent right
|
||||
ANIMATION(ANIM_TYPE_STATUS, statusAnim, opponentRight);
|
||||
if (statusAnim == B_ANIM_STATUS_PSN) {
|
||||
STATUS_ICON(opponentRight, poison: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet was poisoned!");
|
||||
STATUS_ICON(opponentRight, poison: TRUE);
|
||||
}
|
||||
else if (statusAnim == B_ANIM_STATUS_PRZ) {
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet is paralyzed, so it may be unable to move!");
|
||||
STATUS_ICON(opponentRight, paralysis: TRUE);
|
||||
}
|
||||
else {
|
||||
STATUS_ICON(opponentRight, sleep: TRUE);
|
||||
MESSAGE("The opposing Wobbuffet fell asleep!");
|
||||
STATUS_ICON(opponentRight, sleep: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,9 +6,10 @@
|
||||
SINGLE_BATTLE_TEST("(Z-MOVE) Z-Moves do not retain priority")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks
|
||||
ASSUME(GetMoveType(MOVE_QUICK_ATTACK) == TYPE_NORMAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(2); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SCRATCH);
|
||||
MOVE(player, MOVE_QUICK_ATTACK, gimmick: GIMMICK_Z_MOVE); }
|
||||
|
||||
@ -317,3 +317,24 @@ DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Eject Pack does not activate if mon is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); };
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_BULLDOZE);
|
||||
SEND_OUT(opponent, 1);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLDOZE, player);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
MESSAGE("The opposing Wobbuffet is switched out with the Eject Button!");
|
||||
MESSAGE("2 sent out Wobbuffet!");
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
31
test/battle/hold_effect/lagging_tail.c
Normal file
31
test/battle/hold_effect/lagging_tail.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(gItemsInfo[ITEM_LAGGING_TAIL].holdEffect == HOLD_EFFECT_LAGGING_TAIL);
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Lagging Tail priority bracket will not change if the item is removed is changed mid-turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(100); Item(ITEM_LAGGING_TAIL); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(10); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(30); Item(ITEM_BERRY_JUICE); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(20); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponentLeft, MOVE_TRICK, target: playerLeft); }
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft);
|
||||
|
||||
// Turn 2
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentLeft); // Now last because of Tricking Lagging Tail onto itself
|
||||
}
|
||||
}
|
||||
@ -131,3 +131,22 @@ SINGLE_BATTLE_TEST("Life Orb activates if move connected but no damage was dealt
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Life Orb does not activate on a charge turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FLY); }
|
||||
TURN { SKIP_TURN(player); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, player);
|
||||
NONE_OF {
|
||||
HP_BAR(player);
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
}
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player); // Lief Orb
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +112,21 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Beak Blast doesn't burn fire types")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_ARCANINE].types[0] == TYPE_FIRE || gSpeciesInfo[SPECIES_ARCANINE].types[1]);
|
||||
PLAYER(SPECIES_ARCANINE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_BEAK_BLAST); MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
NOT STATUS_ICON(player, burn: TRUE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAK_BLAST, opponent);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed");
|
||||
TO_DO_BATTLE_TEST("Beak Blast fails if it's forced by Encore after choosing a different move");
|
||||
TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes");
|
||||
|
||||
@ -2,7 +2,32 @@
|
||||
#include "test/battle.h"
|
||||
|
||||
// General
|
||||
TO_DO_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party");
|
||||
SINGLE_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_PICHU)
|
||||
PLAYER(SPECIES_PIKACHU) { Status1(STATUS1_POISON); }
|
||||
PLAYER(SPECIES_RAICHU)
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_BEAT_UP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_BEAT_UP, player);
|
||||
MESSAGE("The Pokémon was hit 4 time(s)!");
|
||||
} THEN {
|
||||
EXPECT_EQ(gBattleStruct->beatUpSpecies[0], SPECIES_WOBBUFFET);
|
||||
EXPECT_EQ(gBattleStruct->beatUpSpecies[1], SPECIES_WYNAUT);
|
||||
EXPECT_EQ(gBattleStruct->beatUpSpecies[2], SPECIES_PICHU);
|
||||
EXPECT_EQ(gBattleStruct->beatUpSpecies[3], SPECIES_RAICHU);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Beat Up doesn't consider Comatose as a status")
|
||||
TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit");
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@ TO_DO_BATTLE_TEST("Copycat copies moves called by other calling moves instead of
|
||||
DOUBLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon can have their base moves copied by Copycat")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_MEGA_EVO_TURN_ORDER, GEN_7); // TODO: Decouple this config from other gimmicks
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_DESTINY_BOND) == EFFECT_DESTINY_BOND);
|
||||
}
|
||||
@ -21,10 +21,28 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+")
|
||||
SINGLE_BATTLE_TEST("Destiny Bond doesn't fail if used sequentially (Gen2-6)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_6);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_DESTINY_BOND); }
|
||||
TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
|
||||
MESSAGE("2 sent out Zigzagoon!");
|
||||
NOT { MESSAGE("But it failed!"); }
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
@ -39,10 +57,10 @@ SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves in Gen 7+")
|
||||
SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
@ -58,10 +76,10 @@ SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by o
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing in Gen 7+")
|
||||
SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_DESTINY_BOND_FAIL >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_DESTINY_BOND_FAIL, GEN_7);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
@ -108,4 +126,3 @@ TO_DO_BATTLE_TEST("Destiny Bond's effect can trigger on the next turn if the use
|
||||
TO_DO_BATTLE_TEST("Destiny Bond can be used multiple times in a row (Gen 2-6)");
|
||||
TO_DO_BATTLE_TEST("Destiny Bond always fails if it was successfully used the previous turn (Gen 7+)");
|
||||
TO_DO_BATTLE_TEST("Destiny Bond cannot be used in Raids");
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ WILD_BATTLE_TEST("Embargo doesn't block held item effects that affect effort val
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_WEIGHT); }
|
||||
OPPONENT(SPECIES_CATERPIE) { HP(1); }
|
||||
ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffect == HOLD_EFFECT_POWER_ITEM);
|
||||
ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffectParam == 8);
|
||||
ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].holdEffectParam != 0);
|
||||
ASSUME(gItemsInfo[ITEM_POWER_WEIGHT].secondaryId == STAT_HP);
|
||||
ASSUME(gSpeciesInfo[SPECIES_CATERPIE].evYield_HP == 1);
|
||||
} WHEN {
|
||||
|
||||
@ -27,6 +27,33 @@ SINGLE_BATTLE_TEST("Endure does not prevent multiple hits and stat changes occur
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Endure is not transferred to a mon that is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { HP(1); Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_ENDURE);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENDURE, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
MESSAGE("The opposing Wynaut endured the hit!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
|
||||
NOT MESSAGE("The opposing Squirtle endured the hit!");
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Endure's success rate decreases for every consecutively used turn");
|
||||
TO_DO_BATTLE_TEST("Endure uses the same counter as Protect");
|
||||
TO_DO_BATTLE_TEST("Endure doesn't trigger effects that require damage to be done to the Pokémon (Gen 2-4)"); // Eg. Rough Skin
|
||||
|
||||
@ -58,4 +58,19 @@ SINGLE_BATTLE_TEST("Entrainment fails if the target's ability has cantBeOverwrit
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Entrainment causes primal weather to revert")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); }
|
||||
OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_ENTRAINMENT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_ENTRAINMENT, player);
|
||||
MESSAGE("The extremely harsh sunlight faded!");
|
||||
} THEN {
|
||||
EXPECT(opponent->ability == ABILITY_TELEPATHY);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Entrainment fails on Dynamaxed Pokémon");
|
||||
|
||||
@ -119,7 +119,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use status moves if the player's best attacking
|
||||
ASSUME(GetMoveEffect(MOVE_FOCUS_PUNCH) == EFFECT_FOCUS_PUNCH);
|
||||
ASSUME(GetMoveCategory(MOVE_SWORDS_DANCE) == DAMAGE_CATEGORY_STATUS);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_SNORLAX) { Moves(MOVE_FOCUS_PUNCH, MOVE_TACKLE); }
|
||||
PLAYER(SPECIES_SNORLAX) { Moves(MOVE_FOCUS_PUNCH, MOVE_POUND); }
|
||||
OPPONENT(SPECIES_CLEFABLE) { Moves(MOVE_PLAY_ROUGH, MOVE_SWORDS_DANCE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FOCUS_PUNCH); EXPECT_MOVE(opponent, MOVE_PLAY_ROUGH); }
|
||||
|
||||
@ -80,10 +80,27 @@ SINGLE_BATTLE_TEST("Powder doesn't damage target if it has Magic Guard")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain")
|
||||
SINGLE_BATTLE_TEST("Powder damages the target under heavy rain (Gen 6)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_POWDER_RAIN >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_6);
|
||||
PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); }
|
||||
OPPONENT(SPECIES_VIVILLON);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_POWDER); MOVE(player, MOVE_EMBER); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||
HP_BAR(player);
|
||||
} THEN {
|
||||
EXPECT_LT(player->hp, player->maxHP);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain (Gen 7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_POWDER_RAIN, GEN_7);
|
||||
PLAYER(SPECIES_KYOGRE_PRIMAL) { Ability(ABILITY_PRIMORDIAL_SEA); }
|
||||
OPPONENT(SPECIES_VIVILLON);
|
||||
} WHEN {
|
||||
@ -92,7 +109,7 @@ SINGLE_BATTLE_TEST("Powder doesn't damage target under heavy rain")
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POWDER, opponent);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player);
|
||||
}
|
||||
} THEN {
|
||||
EXPECT_EQ(player->maxHP, player->hp);
|
||||
|
||||
@ -675,3 +675,58 @@ SINGLE_BATTLE_TEST("Protect: Protective Pads protects from secondary effects")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Protect is not transferred to a mon that is switched in due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_URSHIFU) { Ability(ABILITY_UNSEEN_FIST); };
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_PROTECT);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerRight);
|
||||
HP_BAR(opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Wide Guard is still activate even if user is switched out due to Eject Button")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WYNAUT) { Item(ITEM_EJECT_BUTTON); }
|
||||
OPPONENT(SPECIES_SQUIRTLE);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_WIDE_GUARD);
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
MOVE(playerRight, MOVE_HYPER_VOICE, target: opponentRight);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WIDE_GUARD, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight);
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerRight);
|
||||
HP_BAR(opponentLeft);
|
||||
HP_BAR(opponentRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +251,6 @@ SINGLE_BATTLE_TEST("Rage Fist base power is not increased if move had no affect"
|
||||
|
||||
SINGLE_BATTLE_TEST("Rage Fist base power is increased if Disguise breaks (Gen7)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
s16 timesGotHit[2];
|
||||
u16 species = SPECIES_NONE;
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ SINGLE_BATTLE_TEST("Role Play copies target's ability")
|
||||
} THEN {
|
||||
EXPECT_EQ(player->ability, ABILITY_BLAZE);
|
||||
EXPECT_EQ(opponent->ability, ABILITY_BLAZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Role Play copies target's current ability even if it changed during that turn")
|
||||
@ -93,7 +93,8 @@ SINGLE_BATTLE_TEST("Role Play fails if user's ability can't be suppressed")
|
||||
u32 species, ability;
|
||||
|
||||
PARAMETRIZE { species = SPECIES_ARCEUS; ability = ABILITY_MULTITYPE; }
|
||||
PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; }
|
||||
if (B_UPDATED_ABILITY_DATA >= GEN_7)
|
||||
PARAMETRIZE { species = SPECIES_DARMANITAN; ability = ABILITY_ZEN_MODE; }
|
||||
PARAMETRIZE { species = SPECIES_AEGISLASH; ability = ABILITY_STANCE_CHANGE; }
|
||||
PARAMETRIZE { species = SPECIES_MINIOR; ability = ABILITY_SHIELDS_DOWN; }
|
||||
PARAMETRIZE { species = SPECIES_WISHIWASHI; ability = ABILITY_SCHOOLING; }
|
||||
|
||||
@ -6,10 +6,26 @@ ASSUMPTIONS
|
||||
ASSUME(GetMoveEffect(MOVE_SHEER_COLD) == EFFECT_SHEER_COLD);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon")
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen3-6)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_6);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SHEER_COLD); }
|
||||
} SCENE {
|
||||
NOT MESSAGE("It doesn't affect the opposing Glalie…");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player);
|
||||
HP_BAR(opponent, hp: 0);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon (Gen7+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
|
||||
@ -27,3 +27,17 @@ DOUBLE_BATTLE_TEST("Uproar status causes sleeping Pokémon to wake up during an
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Uproar wakes up other pokemon on field")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(B_UPROAR_TURNS >= GEN_5);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_UPROAR); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_UPROAR, opponent);
|
||||
MESSAGE("The uproar woke Wobbuffet!");
|
||||
}
|
||||
}
|
||||
|
||||
86
test/battle/move_effect_secondary/wrap.c
Normal file
86
test/battle/move_effect_secondary/wrap.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_WRAP, MOVE_EFFECT_WRAP));
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 5 turns 50% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(50, 100, RNG_WRAP);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WRAP); }
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player);
|
||||
HP_BAR(opponent); // Direct damage
|
||||
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
NOT HP_BAR(opponent); // Residual Damage
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon for 4 turns 50% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(50, 100, RNG_WRAP);
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WRAP); }
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player);
|
||||
HP_BAR(opponent); // Direct damage
|
||||
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
NOT HP_BAR(opponent); // Residual Damage
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Wrap can damage the wrapped mon 7 turns while holding a Grip Claw")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_GRIP_CLAW); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WRAP); }
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_WRAP, player);
|
||||
HP_BAR(opponent); // Direct damage
|
||||
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
HP_BAR(opponent); // Residual Damage
|
||||
NOT HP_BAR(opponent); // Residual Damage
|
||||
}
|
||||
}
|
||||
@ -690,7 +690,7 @@ DOUBLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo
|
||||
ASSUME(GetMoveEffect(MOVE_UPROAR) == EFFECT_UPROAR);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_ZIGZAGOON);
|
||||
} WHEN {
|
||||
|
||||
@ -77,3 +77,17 @@ SINGLE_BATTLE_TEST("Thunder Wave doesn't affect Electric types in Gen6+")
|
||||
MESSAGE("It doesn't affect the opposing Pikachu…");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Thunder Wave doesn't print an effectiveness message")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_PIDGEY].types[1] == TYPE_FLYING);
|
||||
PLAYER(SPECIES_PIDGEY);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_THUNDER_WAVE); }
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wobbuffet used Thunder Wave!");
|
||||
NOT MESSAGE("It's super effective!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,6 +169,7 @@ static const struct Trainer sTestTrainer2 =
|
||||
|
||||
TEST("Trainer Class Balls apply to the entire party")
|
||||
{
|
||||
ASSUME(B_TRAINER_CLASS_POKE_BALLS >= GEN_8);
|
||||
u32 j;
|
||||
struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon));
|
||||
CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainer2, TRUE, BATTLE_TYPE_TRAINER);
|
||||
|
||||
@ -109,7 +109,7 @@ SINGLE_BATTLE_TEST("Trainer Slide: Enemy Mon Unaffected")
|
||||
{
|
||||
gBattleTestRunnerState->data.recordedBattle.opponentA = TRAINER_SLIDE_ENEMY_MON_UNAFFECTED;
|
||||
GIVEN {
|
||||
ASSUME(B_SHEER_COLD_IMMUNITY >= GEN_7);
|
||||
WITH_CONFIG(GEN_CONFIG_SHEER_COLD_IMMUNITY, GEN_7);
|
||||
ASSUME(GetSpeciesType(SPECIES_GLALIE, 0) == TYPE_ICE);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_GLALIE);
|
||||
|
||||
@ -446,6 +446,11 @@ top:
|
||||
case STATE_EXIT:
|
||||
MgbaExit_(gTestRunnerState.exitCode);
|
||||
break;
|
||||
default:
|
||||
MgbaOpen_();
|
||||
Test_MgbaPrintf("\e[31mInvalid TestRunner state, exiting\e[0m");
|
||||
gTestRunnerState.exitCode = 1;
|
||||
gTestRunnerState.state = STATE_EXIT;
|
||||
}
|
||||
|
||||
if (gMain.callback2 == CB2_TestRunner)
|
||||
|
||||
@ -1564,9 +1564,14 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species)
|
||||
(*partySize)++;
|
||||
|
||||
CreateMon(DATA.currentMon, species, 100, 0, TRUE, 0, OT_ID_PRESET, 0);
|
||||
data = MOVE_NONE;
|
||||
// Reset move IDs, but force PP to be non-zero. This is a safeguard against test species that only learn 1 move having test moves with 0 PP
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
data = MOVE_NONE;
|
||||
SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data);
|
||||
data = 0x7F; // Max PP possible
|
||||
SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &data);
|
||||
}
|
||||
data = 0;
|
||||
if (B_FRIENDSHIP_BOOST)
|
||||
{
|
||||
@ -2112,6 +2117,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 *
|
||||
SetMonData(DATA.currentMon, MON_DATA_PP1 + i, &pp);
|
||||
*moveSlot = i;
|
||||
*moveId = ctx->move;
|
||||
INVALID_IF(GetMovePP(ctx->move) == 0, "%S has 0 PP!", GetMoveName(ctx->move));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2216,7 +2222,7 @@ void Move(u32 sourceLine, struct BattlePokemon *battler, struct MoveContext ctx)
|
||||
DATA.battleRecordTurns[DATA.turns][battlerId].secondaryEffect = 1 + ctx.secondaryEffect;
|
||||
if (ctx.explicitRNG)
|
||||
DATA.battleRecordTurns[DATA.turns][battlerId].rng = ctx.rng;
|
||||
|
||||
|
||||
u32 shellSideArmCount = 0;
|
||||
for (u32 i = 0; i < STATE->battlersCount; i++)
|
||||
{
|
||||
|
||||
@ -675,7 +675,7 @@ TEST("Battle strings fit on the battle message window")
|
||||
case STRINGID_PKMNSXWOREOFF:
|
||||
case STRINGID_BUFFERENDS:
|
||||
case STRINGID_FOREWARNACTIVATES:
|
||||
case STRINGID_CUSEDBODYDISABLED:
|
||||
case STRINGID_CURSEDBODYDISABLED:
|
||||
case STRINGID_CURRENTMOVECANTSELECT:
|
||||
case STRINGID_TARGETISHURTBYSALTCURE:
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, longMoveID);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user