ref: ee4ec65fc17a802425b606eeef59e92a9a6c9b81
dir: /engine/battle/effect_commands.asm/
DoPlayerTurn: ; 34000 call SetPlayerTurn ld a, [wPlayerAction] and a ret nz jr DoTurn ; 3400a DoEnemyTurn: ; 3400a call SetEnemyTurn ld a, [wLinkMode] and a jr z, DoTurn ld a, [wBattleAction] cp BATTLEACTION_E jr z, DoTurn cp BATTLEACTION_SWITCH1 ret nc ; fallthrough ; 3401d DoTurn: ; 3401d ; Read in and execute the user's move effects for this turn. xor a ld [wTurnEnded], a ; Effect command checkturn is called for every move. call CheckTurn ld a, [wTurnEnded] and a ret nz call UpdateMoveData ; 3402c DoMove: ; 3402c ; Get the user's move effect. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar ld c, a ld b, 0 ld hl, MoveEffectsPointers add hl, bc add hl, bc ld a, BANK(MoveEffectsPointers) call GetFarHalfword ld de, BattleScriptBuffer .GetMoveEffect: ld a, BANK(MoveEffects) call GetFarByte inc hl ld [de], a inc de cp $ff jr nz, .GetMoveEffect ; Start at the first command. ld hl, BattleScriptBuffer ld a, l ld [BattleScriptBufferAddress], a ld a, h ld [BattleScriptBufferAddress + 1], a .ReadMoveEffectCommand: ; ld a, [BattleScriptBufferAddress++] ld a, [BattleScriptBufferAddress] ld l, a ld a, [BattleScriptBufferAddress + 1] ld h, a ld a, [hli] push af ld a, l ld [BattleScriptBufferAddress], a ld a, h ld [BattleScriptBufferAddress + 1], a pop af ; endturn_command (-2) is used to terminate branches without ending the read cycle. cp endturn_command ret nc ; The rest of the commands (01-af) are read from BattleCommandPointers. push bc dec a ld c, a ld b, 0 ld hl, BattleCommandPointers add hl, bc add hl, bc pop bc ld a, BANK(BattleCommandPointers) call GetFarHalfword call .DoMoveEffectCommand jr .ReadMoveEffectCommand .DoMoveEffectCommand: jp hl ; 34084 CheckTurn: BattleCommand_CheckTurn: ; 34084 ; checkturn ; Repurposed as hardcoded turn handling. Useless as a command. ; Move $ff immediately ends the turn. ld a, BATTLE_VARS_MOVE call GetBattleVar inc a jp z, EndTurn xor a ld [AttackMissed], a ld [EffectFailed], a ld [wKickCounter], a ld [AlreadyDisobeyed], a ld [AlreadyFailed], a ld [wSomeoneIsRampaging], a ld a, 10 ; 1.0 ld [TypeModifier], a ld a, [hBattleTurn] and a jp nz, CheckEnemyTurn CheckPlayerTurn: ld hl, PlayerSubStatus4 bit SUBSTATUS_RECHARGE, [hl] jr z, .no_recharge res SUBSTATUS_RECHARGE, [hl] ld hl, MustRechargeText call StdBattleTextBox call CantMove jp EndTurn .no_recharge ld hl, BattleMonStatus ld a, [hl] and SLP jr z, .not_asleep dec a ld [BattleMonStatus], a and SLP jr z, .woke_up xor a ld [wNumHits], a ld de, ANIM_SLP call FarPlayBattleAnimation jr .fast_asleep .woke_up ld hl, WokeUpText call StdBattleTextBox call CantMove call UpdateBattleMonInParty ld hl, UpdatePlayerHUD call CallBattleCore ld a, $1 ld [hBGMapMode], a ld hl, PlayerSubStatus1 res SUBSTATUS_NIGHTMARE, [hl] jr .not_asleep .fast_asleep ld hl, FastAsleepText call StdBattleTextBox ; Snore and Sleep Talk bypass sleep. ld a, [CurPlayerMove] cp SNORE jr z, .not_asleep cp SLEEP_TALK jr z, .not_asleep call CantMove jp EndTurn .not_asleep ld hl, BattleMonStatus bit FRZ, [hl] jr z, .not_frozen ; Flame Wheel and Sacred Fire thaw the user. ld a, [CurPlayerMove] cp FLAME_WHEEL jr z, .not_frozen cp SACRED_FIRE jr z, .not_frozen ld hl, FrozenSolidText call StdBattleTextBox call CantMove jp EndTurn .not_frozen ld hl, PlayerSubStatus3 bit SUBSTATUS_FLINCHED, [hl] jr z, .not_flinched res SUBSTATUS_FLINCHED, [hl] ld hl, FlinchedText call StdBattleTextBox call CantMove jp EndTurn .not_flinched ld hl, PlayerDisableCount ld a, [hl] and a jr z, .not_disabled dec a ld [hl], a and $f jr nz, .not_disabled ld [hl], a ld [DisabledMove], a ld hl, DisabledNoMoreText call StdBattleTextBox .not_disabled ld a, [PlayerSubStatus3] add a jr nc, .not_confused ld hl, PlayerConfuseCount dec [hl] jr nz, .confused ld hl, PlayerSubStatus3 res SUBSTATUS_CONFUSED, [hl] ld hl, ConfusedNoMoreText call StdBattleTextBox jr .not_confused .confused ld hl, IsConfusedText call StdBattleTextBox xor a ld [wNumHits], a ld de, ANIM_CONFUSED call FarPlayBattleAnimation ; 50% chance of hitting itself call BattleRandom cp $80 jr nc, .not_confused ; clear confusion-dependent substatus ld hl, PlayerSubStatus3 ld a, [hl] and 1 << SUBSTATUS_CONFUSED ld [hl], a call HitConfusion call CantMove jp EndTurn .not_confused ld a, [PlayerSubStatus1] add a ; bit SUBSTATUS_ATTRACT jr nc, .not_infatuated ld hl, InLoveWithText call StdBattleTextBox xor a ld [wNumHits], a ld de, ANIM_IN_LOVE call FarPlayBattleAnimation ; 50% chance of infatuation call BattleRandom cp $80 jr c, .not_infatuated ld hl, InfatuationText call StdBattleTextBox call CantMove jp EndTurn .not_infatuated ; We can't disable a move that doesn't exist. ld a, [DisabledMove] and a jr z, .no_disabled_move ; Are we using the disabled move? ld hl, CurPlayerMove cp [hl] jr nz, .no_disabled_move call MoveDisabled call CantMove jp EndTurn .no_disabled_move ld hl, BattleMonStatus bit PAR, [hl] ret z ; 25% chance to be fully paralyzed call BattleRandom cp $3f ret nc ld hl, FullyParalyzedText call StdBattleTextBox call CantMove jp EndTurn ; 341f0 CantMove: ; 341f0 ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr res SUBSTATUS_ROLLOUT, [hl] ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr ld a, [hl] and $ff ^ (1<<SUBSTATUS_BIDE + 1<<SUBSTATUS_RAMPAGE + 1<<SUBSTATUS_CHARGED) ld [hl], a call ResetFuryCutterCount ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp FLY jr z, .fly_dig cp DIG ret nz .fly_dig res SUBSTATUS_UNDERGROUND, [hl] res SUBSTATUS_FLYING, [hl] jp AppearUserRaiseSub ; 34216 OpponentCantMove: ; 34216 call BattleCommand_SwitchTurn call CantMove jp BattleCommand_SwitchTurn ; 3421f CheckEnemyTurn: ; 3421f ld hl, EnemySubStatus4 bit SUBSTATUS_RECHARGE, [hl] jr z, .no_recharge res SUBSTATUS_RECHARGE, [hl] ld hl, MustRechargeText call StdBattleTextBox call CantMove jp EndTurn .no_recharge ld hl, EnemyMonStatus ld a, [hl] and SLP jr z, .not_asleep dec a ld [EnemyMonStatus], a and a jr z, .woke_up ld hl, FastAsleepText call StdBattleTextBox xor a ld [wNumHits], a ld de, ANIM_SLP call FarPlayBattleAnimation jr .fast_asleep .woke_up ld hl, WokeUpText call StdBattleTextBox call CantMove call UpdateEnemyMonInParty ld hl, UpdateEnemyHUD call CallBattleCore ld a, $1 ld [hBGMapMode], a ld hl, EnemySubStatus1 res SUBSTATUS_NIGHTMARE, [hl] jr .not_asleep .fast_asleep ; Snore and Sleep Talk bypass sleep. ld a, [CurEnemyMove] cp SNORE jr z, .not_asleep cp SLEEP_TALK jr z, .not_asleep call CantMove jp EndTurn .not_asleep ld hl, EnemyMonStatus bit FRZ, [hl] jr z, .not_frozen ld a, [CurEnemyMove] cp FLAME_WHEEL jr z, .not_frozen cp SACRED_FIRE jr z, .not_frozen ld hl, FrozenSolidText call StdBattleTextBox call CantMove jp EndTurn .not_frozen ld hl, EnemySubStatus3 bit SUBSTATUS_FLINCHED, [hl] jr z, .not_flinched res SUBSTATUS_FLINCHED, [hl] ld hl, FlinchedText call StdBattleTextBox call CantMove jp EndTurn .not_flinched ld hl, EnemyDisableCount ld a, [hl] and a jr z, .not_disabled dec a ld [hl], a and $f jr nz, .not_disabled ld [hl], a ld [EnemyDisabledMove], a ld hl, DisabledNoMoreText call StdBattleTextBox .not_disabled ld a, [EnemySubStatus3] add a ; bit SUBSTATUS_CONFUSED jr nc, .not_confused ld hl, EnemyConfuseCount dec [hl] jr nz, .confused ld hl, EnemySubStatus3 res SUBSTATUS_CONFUSED, [hl] ld hl, ConfusedNoMoreText call StdBattleTextBox jr .not_confused .confused ld hl, IsConfusedText call StdBattleTextBox xor a ld [wNumHits], a ld de, ANIM_CONFUSED call FarPlayBattleAnimation ; 50% chance of hitting itself call BattleRandom cp 1 + 50 percent jr nc, .not_confused ; clear confusion-dependent substatus ld hl, EnemySubStatus3 ld a, [hl] and 1 << SUBSTATUS_CONFUSED ld [hl], a ld hl, HurtItselfText call StdBattleTextBox call HitSelfInConfusion call BattleCommand_DamageCalc call BattleCommand_LowerSub xor a ld [wNumHits], a ; Flicker the monster pic unless flying or underground. ld de, ANIM_HIT_CONFUSION ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND call z, PlayFXAnimID ld c, $1 call EnemyHurtItself call BattleCommand_RaiseSub call CantMove jp EndTurn .not_confused ld a, [EnemySubStatus1] add a ; bit SUBSTATUS_ATTRACT jr nc, .not_infatuated ld hl, InLoveWithText call StdBattleTextBox xor a ld [wNumHits], a ld de, ANIM_IN_LOVE call FarPlayBattleAnimation ; 50% chance of infatuation call BattleRandom cp 1 + 50 percent jr c, .not_infatuated ld hl, InfatuationText call StdBattleTextBox call CantMove jp EndTurn .not_infatuated ; We can't disable a move that doesn't exist. ld a, [EnemyDisabledMove] and a jr z, .no_disabled_move ; Are we using the disabled move? ld hl, CurEnemyMove cp [hl] jr nz, .no_disabled_move call MoveDisabled call CantMove jp EndTurn .no_disabled_move ld hl, EnemyMonStatus bit PAR, [hl] ret z ; 25% chance to be fully paralyzed call BattleRandom cp $3f ret nc ld hl, FullyParalyzedText call StdBattleTextBox call CantMove ; fallthrough ; 34385 EndTurn: ; 34385 ld a, $1 ld [wTurnEnded], a jp ResetDamage ; 3438d MoveDisabled: ; 3438d ; Make sure any charged moves fail ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr res SUBSTATUS_CHARGED, [hl] ld a, BATTLE_VARS_MOVE call GetBattleVar ld [wNamedObjectIndexBuffer], a call GetMoveName ld hl, DisabledMoveText jp StdBattleTextBox ; 343a5 HitConfusion: ; 343a5 ld hl, HurtItselfText call StdBattleTextBox xor a ld [CriticalHit], a call HitSelfInConfusion call BattleCommand_DamageCalc call BattleCommand_LowerSub xor a ld [wNumHits], a ; Flicker the monster pic unless flying or underground. ld de, ANIM_HIT_CONFUSION ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND call z, PlayFXAnimID ld hl, UpdatePlayerHUD call CallBattleCore ld a, $1 ld [hBGMapMode], a ld c, $1 call PlayerHurtItself jp BattleCommand_RaiseSub ; 343db BattleCommand_CheckObedience: ; 343db ; checkobedience ; Enemy can't disobey ld a, [hBattleTurn] and a ret nz call CheckUserIsCharging ret nz ; If we've already checked this turn ld a, [AlreadyDisobeyed] and a ret nz xor a ld [AlreadyDisobeyed], a ; No obedience in link battles ; (since no handling exists for enemy) ld a, [wLinkMode] and a ret nz ld a, [InBattleTowerBattle] and a ret nz ; If the monster's id doesn't match the player's, ; some conditions need to be met. ld a, MON_ID call BattlePartyAttr ld a, [PlayerID] cp [hl] jr nz, .obeylevel inc hl ld a, [PlayerID + 1] cp [hl] ret z .obeylevel ; The maximum obedience level is constrained by owned badges: ld hl, wJohtoBadges ; risingbadge bit RISINGBADGE, [hl] ld a, MAX_LEVEL + 1 jr nz, .getlevel ; stormbadge bit STORMBADGE, [hl] ld a, 70 jr nz, .getlevel ; fogbadge bit FOGBADGE, [hl] ld a, 50 jr nz, .getlevel ; hivebadge bit HIVEBADGE, [hl] ld a, 30 jr nz, .getlevel ; no badges ld a, 10 .getlevel ; c = obedience level ; d = monster level ; b = c + d ld b, a ld c, a ld a, [BattleMonLevel] ld d, a add b ld b, a ; No overflow (this should never happen) jr nc, .checklevel ld b, $ff .checklevel ; If the monster's level is lower than the obedience level, it will obey. ld a, c cp d ret nc ; Random number from 0 to obedience level + monster level .rand1 call BattleRandom swap a cp b jr nc, .rand1 ; The higher above the obedience level the monster is, ; the more likely it is to disobey. cp c ret c ; Sleep-only moves have separate handling, and a higher chance of ; being ignored. Lazy monsters like their sleep. call IgnoreSleepOnly ret c ; Another random number from 0 to obedience level + monster level .rand2 call BattleRandom cp b jr nc, .rand2 ; A second chance. cp c jr c, .UseInstead ; No hope of using a move now. ; b = number of levels the monster is above the obedience level ld a, d sub c ld b, a ; The chance of napping is the difference out of 256. call BattleRandom swap a sub b jr c, .Nap ; The chance of not hitting itself is the same. cp b jr nc, .DoNothing ld hl, WontObeyText call StdBattleTextBox call HitConfusion jp .EndDisobedience .Nap: call BattleRandom add a swap a and SLP jr z, .Nap ld [BattleMonStatus], a ld hl, BeganToNapText jr .Print .DoNothing: call BattleRandom and 3 ld hl, LoafingAroundText and a jr z, .Print ld hl, WontObeyText dec a jr z, .Print ld hl, TurnedAwayText dec a jr z, .Print ld hl, IgnoredOrdersText .Print: call StdBattleTextBox jp .EndDisobedience .UseInstead: ; Can't use another move if the monster only has one! ld a, [BattleMonMoves + 1] and a jr z, .DoNothing ; Don't bother trying to handle Disable. ld a, [DisabledMove] and a jr nz, .DoNothing ld hl, BattleMonPP ld de, BattleMonMoves ld b, 0 ld c, NUM_MOVES .GetTotalPP: ld a, [hli] and $3f ; exclude pp up add b ld b, a dec c jr z, .CheckMovePP ; Stop at undefined moves. inc de ld a, [de] and a jr nz, .GetTotalPP .CheckMovePP: ld hl, BattleMonPP ld a, [CurMoveNum] ld e, a ld d, 0 add hl, de ; Can't use another move if only one move has PP. ld a, [hl] and $3f cp b jr z, .DoNothing ; Make sure we can actually use the move once we get there. ld a, 1 ld [AlreadyDisobeyed], a ld a, [w2DMenuNumRows] ld b, a ; Save the move we originally picked for afterward. ld a, [CurMoveNum] ld c, a push af .RandomMove: call BattleRandom and 3 ; TODO NUM_MOVES cp b jr nc, .RandomMove ; Not the move we were trying to use. cp c jr z, .RandomMove ; Make sure it has PP. ld [CurMoveNum], a ld hl, BattleMonPP ld e, a ld d, 0 add hl, de ld a, [hl] and $3f jr z, .RandomMove ; Use it. ld a, [CurMoveNum] ld c, a ld b, 0 ld hl, BattleMonMoves add hl, bc ld a, [hl] ld [CurPlayerMove], a call SetPlayerTurn call UpdateMoveData call DoMove ; Restore original move choice. pop af ld [CurMoveNum], a .EndDisobedience: xor a ld [LastPlayerMove], a ld [LastPlayerCounterMove], a ; Break Encore too. ld hl, PlayerSubStatus5 res SUBSTATUS_ENCORED, [hl] xor a ld [PlayerEncoreCount], a jp EndMoveEffect ; 3451f IgnoreSleepOnly: ; 3451f ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp SNORE jr z, .CheckSleep cp SLEEP_TALK jr z, .CheckSleep and a ret .CheckSleep: ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP ret z ; 'ignored orders…sleeping!' ld hl, IgnoredSleepingText call StdBattleTextBox call EndMoveEffect scf ret ; 34541 BattleCommand_UsedMoveText: ; 34541 ; usedmovetext farcall DisplayUsedMoveText ret ; 34548 CheckUserIsCharging: ; 34548 ld a, [hBattleTurn] and a ld a, [wPlayerCharging] ; player jr z, .end ld a, [wEnemyCharging] ; enemy .end and a ret ; 34555 BattleCommand_DoTurn: ; 34555 call CheckUserIsCharging ret nz ld hl, BattleMonPP ld de, PlayerSubStatus3 ld bc, PlayerTurnsTaken ld a, [hBattleTurn] and a jr z, .proceed ld hl, EnemyMonPP ld de, EnemySubStatus3 ld bc, EnemyTurnsTaken .proceed ; If we've gotten this far, this counts as a turn. ld a, [bc] inc a ld [bc], a ld a, BATTLE_VARS_MOVE call GetBattleVar cp STRUGGLE ret z ld a, [de] and 1 << SUBSTATUS_IN_LOOP | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE ret nz call .consume_pp ld a, b and a jp nz, EndMoveEffect ; SubStatus5 inc de inc de ld a, [de] bit SUBSTATUS_TRANSFORMED, a ret nz ld a, [hBattleTurn] and a ld hl, PartyMon1PP ld a, [CurBattleMon] jr z, .player ; mimic this part entirely if wildbattle ld a, [wBattleMode] dec a jr z, .wild ld hl, OTPartyMon1PP ld a, [CurOTMon] .player call GetPartyLocation push hl call CheckMimicUsed pop hl ret c .consume_pp ld a, [hBattleTurn] and a ld a, [CurMoveNum] jr z, .okay ld a, [CurEnemyMoveNum] .okay ld c, a ld b, 0 add hl, bc ld a, [hl] and $3f jr z, .out_of_pp dec [hl] ld b, 0 ret .wild ld hl, EnemyMonMoves ld a, [CurEnemyMoveNum] ld c, a ld b, 0 add hl, bc ld a, [hl] cp MIMIC jr z, .mimic ld hl, wWildMonMoves add hl, bc ld a, [hl] cp MIMIC ret z .mimic ld hl, wWildMonPP call .consume_pp ret .out_of_pp call BattleCommand_MoveDelay ; get move effect ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar ; continuous? ld hl, .continuousmoves ld de, 1 call IsInArray ; 'has no pp left for [move]' ld hl, HasNoPPLeftText jr c, .print ; 'but no pp is left for the move' ld hl, NoPPLeftText .print call StdBattleTextBox ld b, 1 ret ; 34602 .continuousmoves ; 34602 db EFFECT_RAZOR_WIND db EFFECT_SKY_ATTACK db EFFECT_SKULL_BASH db EFFECT_SOLARBEAM db EFFECT_FLY db EFFECT_ROLLOUT db EFFECT_BIDE db EFFECT_RAMPAGE db $ff ; 3460b CheckMimicUsed: ; 3460b ld a, [hBattleTurn] and a ld a, [CurMoveNum] jr z, .player ld a, [CurEnemyMoveNum] .player ld c, a ld a, MON_MOVES call UserPartyAttr ld a, BATTLE_VARS_MOVE call GetBattleVar cp MIMIC jr z, .mimic ; ld b, 0 add hl, bc ld a, [hl] cp MIMIC jr nz, .mimic scf ret .mimic and a ret ; 34631 BattleCommand_Critical: ; 34631 ; critical ; Determine whether this attack's hit will be critical. xor a ld [CriticalHit], a ld a, BATTLE_VARS_MOVE_POWER call GetBattleVar and a ret z ld a, [hBattleTurn] and a ld hl, EnemyMonItem ld a, [EnemyMonSpecies] jr nz, .Item ld hl, BattleMonItem ld a, [BattleMonSpecies] .Item: ld c, 0 cp CHANSEY jr nz, .Farfetchd ld a, [hl] cp LUCKY_PUNCH jr nz, .FocusEnergy ; +2 critical level ld c, 2 jr .Tally .Farfetchd: cp FARFETCH_D jr nz, .FocusEnergy ld a, [hl] cp STICK jr nz, .FocusEnergy ; +2 critical level ld c, 2 jr .Tally .FocusEnergy: ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_FOCUS_ENERGY, a jr z, .CheckCritical ; +1 critical level inc c .CheckCritical: ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld de, 1 ld hl, .Criticals push bc call IsInArray pop bc jr nc, .ScopeLens ; +2 critical level inc c inc c .ScopeLens: push bc call GetUserItem ld a, b cp HELD_CRITICAL_UP ; Increased critical chance. Only Scope Lens has this. pop bc jr nz, .Tally ; +1 critical level inc c .Tally: ld hl, .Chances ld b, 0 add hl, bc call BattleRandom cp [hl] ret nc ld a, 1 ld [CriticalHit], a ret .Criticals: db KARATE_CHOP, RAZOR_WIND, RAZOR_LEAF, CRABHAMMER, SLASH, AEROBLAST, CROSS_CHOP, $ff .Chances: ; 6.25% 12.1% 24.6% 33.2% 49.6% 49.6% 49.6% db $11, $20, $40, $55, $80, $80, $80 ; 0 1 2 3 4 5 6 ; 346b2 BattleCommand_TripleKick: ; 346b2 ; triplekick ld a, [wKickCounter] ld b, a inc b ld hl, CurDamage + 1 ld a, [hld] ld e, a ld a, [hli] ld d, a .next_kick dec b ret z ld a, [hl] add e ld [hld], a ld a, [hl] adc d ld [hli], a ; No overflow. jr nc, .next_kick ld a, $ff ld [hld], a ld [hl], a ret ; 346cd BattleCommand_KickCounter: ; 346cd ; kickcounter ld hl, wKickCounter inc [hl] ret ; 346d2 BattleCommand_Stab: ; 346d2 ; STAB = Same Type Attack Bonus ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp STRUGGLE ret z ld hl, BattleMonType1 ld a, [hli] ld b, a ld c, [hl] ld hl, EnemyMonType1 ld a, [hli] ld d, a ld e, [hl] ld a, [hBattleTurn] and a jr z, .go ; Who Attacks and who Defends ld hl, EnemyMonType1 ld a, [hli] ld b, a ld c, [hl] ld hl, BattleMonType1 ld a, [hli] ld d, a ld e, [hl] .go ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVarAddr ld [wTypeMatchup], a push hl push de push bc farcall DoWeatherModifiers pop bc pop de pop hl push de push bc farcall DoBadgeTypeBoosts pop bc pop de ld a, [wTypeMatchup] cp b jr z, .stab cp c jr z, .stab jr .SkipStab .stab ld hl, CurDamage + 1 ld a, [hld] ld h, [hl] ld l, a ld b, h ld c, l srl b rr c add hl, bc ld a, h ld [CurDamage], a ld a, l ld [CurDamage + 1], a ld hl, TypeModifier set 7, [hl] .SkipStab: ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVar ld b, a ld hl, TypeMatchups .TypesLoop: ld a, [hli] cp $ff jr z, .end ; foresight cp $fe jr nz, .SkipForesightCheck ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_IDENTIFIED, a jr nz, .end jr .TypesLoop .SkipForesightCheck: cp b jr nz, .SkipType ld a, [hl] cp d jr z, .GotMatchup cp e jr z, .GotMatchup jr .SkipType .GotMatchup: push hl push bc inc hl ld a, [TypeModifier] and %10000000 ld b, a ; If the target is immune to the move, treat it as a miss and calculate the damage as 0 ld a, [hl] and a jr nz, .NotImmune inc a ld [AttackMissed], a xor a .NotImmune: ld [hMultiplier], a add b ld [TypeModifier], a xor a ld [hMultiplicand + 0], a ld hl, CurDamage ld a, [hli] ld [hMultiplicand + 1], a ld a, [hld] ld [hMultiplicand + 2], a call Multiply ld a, [hProduct + 1] ld b, a ld a, [hProduct + 2] or b ld b, a ld a, [hProduct + 3] or b jr z, .ok ; This is a very convoluted way to get back that we've essentially dealt no damage. ; Take the product and divide it by 10. ld a, 10 ld [hDivisor], a ld b, 4 call Divide ld a, [hQuotient + 1] ld b, a ld a, [hQuotient + 2] or b jr nz, .ok ld a, 1 ld [hMultiplicand + 2], a .ok ld a, [hMultiplicand + 1] ld [hli], a ld a, [hMultiplicand + 2] ld [hl], a pop bc pop hl .SkipType: inc hl inc hl jr .TypesLoop .end call BattleCheckTypeMatchup ld a, [wTypeMatchup] ld b, a ld a, [TypeModifier] and %10000000 or b ld [TypeModifier], a ret ; 347c8 BattleCheckTypeMatchup: ; 347c8 ld hl, EnemyMonType1 ld a, [hBattleTurn] and a jr z, CheckTypeMatchup ld hl, BattleMonType1 CheckTypeMatchup: ; 347d3 ; There is an incorrect assumption about this function made in the AI related code: when ; the AI calls CheckTypeMatchup (not BattleCheckTypeMatchup), it assumes that placing the ; offensive type in a will make this function do the right thing. Since a is overwritten, ; this assumption is incorrect. A simple fix would be to load the move type for the ; current move into a in BattleCheckTypeMatchup, before falling through, which is ; consistent with how the rest of the code assumes this code works like. push hl push de push bc ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVar ld d, a ld b, [hl] inc hl ld c, [hl] ld a, 10 ; 1.0 ld [wTypeMatchup], a ld hl, TypeMatchups .TypesLoop: ld a, [hli] cp $ff jr z, .End cp $fe jr nz, .Next ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_IDENTIFIED, a jr nz, .End jr .TypesLoop .Next: cp d jr nz, .Nope ld a, [hli] cp b jr z, .Yup cp c jr z, .Yup jr .Nope2 .Nope: inc hl .Nope2: inc hl jr .TypesLoop .Yup: xor a ld [hDividend + 0], a ld [hMultiplicand + 0], a ld [hMultiplicand + 1], a ld a, [hli] ld [hMultiplicand + 2], a ld a, [wTypeMatchup] ld [hMultiplier], a call Multiply ld a, 10 ld [hDivisor], a push bc ld b, 4 call Divide pop bc ld a, [hQuotient + 2] ld [wTypeMatchup], a jr .TypesLoop .End: pop bc pop de pop hl ret ; 34833 BattleCommand_ResetTypeMatchup: ; 34833 ; Reset the type matchup multiplier to 1.0, if the type matchup is not 0. ; If there is immunity in play, the move automatically misses. call BattleCheckTypeMatchup ld a, [wTypeMatchup] and a ld a, 10 ; 1.0 jr nz, .reset call ResetDamage xor a ld [TypeModifier], a inc a ld [AttackMissed], a ret .reset ld [wTypeMatchup], a ret ; 3484e INCLUDE "engine/battle/ai/switch.asm" INCLUDE "data/type_matchups.asm" BattleCommand_DamageVariation: ; 34cfd ; damagevariation ; Modify the damage spread between 85% and 100%. ; Because of the method of division the probability distribution ; is not consistent. This makes the highest damage multipliers ; rarer than normal. ; No point in reducing 1 or 0 damage. ld hl, CurDamage ld a, [hli] and a jr nz, .go ld a, [hl] cp 2 ret c .go ; Start with the maximum damage. xor a ld [hMultiplicand + 0], a dec hl ld a, [hli] ld [hMultiplicand + 1], a ld a, [hl] ld [hMultiplicand + 2], a ; Multiply by 85-100%... .loop call BattleRandom rrca cp $d9 ; 85% jr c, .loop ld [hMultiplier], a call Multiply ; ...divide by 100%... ld a, $ff ; 100% ld [hDivisor], a ld b, $4 call Divide ; ...to get .85-1.00x damage. ld a, [hQuotient + 1] ld hl, CurDamage ld [hli], a ld a, [hQuotient + 2] ld [hl], a ret ; 34d32 BattleCommand_CheckHit: ; 34d32 ; checkhit call .DreamEater jp z, .Miss call .Protect jp nz, .Miss call .DrainSub jp z, .Miss call .LockOn ret nz call .FlyDigMoves jp nz, .Miss call .ThunderRain ret z call .XAccuracy ret nz ; Perfect-accuracy moves ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_ALWAYS_HIT ret z call .StatModifiers ld a, [wPlayerMoveStruct + MOVE_ACC] ld b, a ld a, [hBattleTurn] and a jr z, .BrightPowder ld a, [wEnemyMoveStruct + MOVE_ACC] ld b, a .BrightPowder: push bc call GetOpponentItem ld a, b cp HELD_BRIGHTPOWDER ld a, c ; % miss pop bc jr nz, .skip_brightpowder ld c, a ld a, b sub c ld b, a jr nc, .skip_brightpowder ld b, 0 .skip_brightpowder ld a, b cp $ff jr z, .Hit call BattleRandom cp b jr nc, .Miss .Hit: ret .Miss: ; Keep the damage value intact if we're using (Hi) Jump Kick. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_JUMP_KICK jr z, .Missed call ResetDamage .Missed: ld a, 1 ld [AttackMissed], a ret .DreamEater: ; Return z if we're trying to eat the dream of ; a monster that isn't sleeping. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_DREAM_EATER ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar and SLP ret .Protect: ; Return nz if the opponent is protected. ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_PROTECT, a ret z ld c, 40 call DelayFrames ; 'protecting itself!' ld hl, ProtectingItselfText call StdBattleTextBox ld c, 40 call DelayFrames ld a, 1 and a ret .LockOn: ; Return nz if we are locked-on and aren't trying to use Earthquake, ; Fissure or Magnitude on a monster that is flying. ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr bit SUBSTATUS_LOCK_ON, [hl] res SUBSTATUS_LOCK_ON, [hl] ret z ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar bit SUBSTATUS_FLYING, a jr z, .LockedOn ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp EARTHQUAKE ret z cp FISSURE ret z cp MAGNITUDE ret z .LockedOn: ld a, 1 and a ret .DrainSub: ; Return z if using an HP drain move on a substitute. call CheckSubstituteOpp jr z, .not_draining_sub ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_LEECH_HIT ret z cp EFFECT_DREAM_EATER ret z .not_draining_sub ld a, 1 and a ret .FlyDigMoves: ; Check for moves that can hit underground/flying opponents. ; Return z if the current move can hit the opponent. ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND ret z bit SUBSTATUS_FLYING, a jr z, .DigMoves ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp GUST ret z cp WHIRLWIND ret z cp THUNDER ret z cp TWISTER ret .DigMoves: ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp EARTHQUAKE ret z cp FISSURE ret z cp MAGNITUDE ret .ThunderRain: ; Return z if the current move always hits in rain, and it is raining. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_THUNDER ret nz ld a, [Weather] cp WEATHER_RAIN ret .XAccuracy: ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_X_ACCURACY, a ret .StatModifiers: ld a, [hBattleTurn] and a ; load the user's accuracy into b and the opponent's evasion into c. ld hl, wPlayerMoveStruct + MOVE_ACC ld a, [PlayerAccLevel] ld b, a ld a, [EnemyEvaLevel] ld c, a jr z, .got_acc_eva ld hl, wEnemyMoveStruct + MOVE_ACC ld a, [EnemyAccLevel] ld b, a ld a, [PlayerEvaLevel] ld c, a .got_acc_eva cp b jr c, .skip_foresight_check ; if the target's evasion is greater than the user's accuracy, ; check the target's foresight status ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_IDENTIFIED, a ret nz .skip_foresight_check ; subtract evasion from 14 ld a, 14 sub c ld c, a ; store the base move accuracy for math ops xor a ld [hMultiplicand + 0], a ld [hMultiplicand + 1], a ld a, [hl] ld [hMultiplicand + 2], a push hl ld d, 2 ; do this twice, once for the user's accuracy and once for the target's evasion .accuracy_loop ; look up the multiplier from the table push bc ld hl, .AccProb dec b sla b ld c, b ld b, 0 add hl, bc pop bc ; multiply by the first byte in that row... ld a, [hli] ld [hMultiplier], a call Multiply ; ... and divide by the second byte ld a, [hl] ld [hDivisor], a ld b, 4 call Divide ; minimum accuracy is $0001 ld a, [hQuotient + 2] ld b, a ld a, [hQuotient + 1] or b jr nz, .min_accuracy ld [hQuotient + 1], a ld a, 1 ld [hQuotient + 2], a .min_accuracy ; do the same thing to the target's evasion ld b, c dec d jr nz, .accuracy_loop ; if the result is more than 2 bytes, max out at 100% ld a, [hQuotient + 1] and a ld a, [hQuotient + 2] jr z, .finish_accuracy ld a, $ff .finish_accuracy pop hl ld [hl], a ret .AccProb: db 33, 100 ; 33% -6 db 36, 100 ; 36% -5 db 43, 100 ; 43% -4 db 50, 100 ; 50% -3 db 60, 100 ; 60% -2 db 75, 100 ; 75% -1 db 1, 1 ; 100% 0 db 133, 100 ; 133% +1 db 166, 100 ; 166% +2 db 2, 1 ; 200% +3 db 233, 100 ; 233% +4 db 133, 50 ; 266% +5 db 3, 1 ; 300% +6 ; 34ecc BattleCommand_EffectChance: ; 34ecc ; effectchance xor a ld [EffectFailed], a call CheckSubstituteOpp jr nz, .failed push hl ld hl, wPlayerMoveStruct + MOVE_CHANCE ld a, [hBattleTurn] and a jr z, .got_move_chance ld hl, wEnemyMoveStruct + MOVE_CHANCE .got_move_chance call BattleRandom cp [hl] pop hl ret c .failed ld a, 1 ld [EffectFailed], a and a ret ; 34eee BattleCommand_LowerSub: ; 34eee ; lowersub ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret z ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar bit SUBSTATUS_CHARGED, a jr nz, .already_charged ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_RAZOR_WIND jr z, .charge_turn cp EFFECT_SKY_ATTACK jr z, .charge_turn cp EFFECT_SKULL_BASH jr z, .charge_turn cp EFFECT_SOLARBEAM jr z, .charge_turn cp EFFECT_FLY jr z, .charge_turn .already_charged call .Rampage jr z, .charge_turn call CheckUserIsCharging ret nz .charge_turn call _CheckBattleScene jr c, .mimic_anims xor a ld [wNumHits], a ld [FXAnimID + 1], a inc a ld [wKickCounter], a ld a, SUBSTITUTE jp LoadAnim .mimic_anims call BattleCommand_LowerSubNoAnim jp BattleCommand_MoveDelay .Rampage: ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_ROLLOUT jr z, .rollout_rampage cp EFFECT_RAMPAGE jr z, .rollout_rampage ld a, 1 and a ret .rollout_rampage ld a, [wSomeoneIsRampaging] and a ld a, 0 ld [wSomeoneIsRampaging], a ret ; 34f57 BattleCommand_HitTarget: ; 34f57 ; hittarget call BattleCommand_LowerSub call BattleCommand_HitTargetNoSub jp BattleCommand_RaiseSub ; 34f60 BattleCommand_HitTargetNoSub: ; 34f60 ld a, [AttackMissed] and a jp nz, BattleCommand_MoveDelay ld a, [hBattleTurn] and a ld de, PlayerRolloutCount ld a, BATTLEANIM_ENEMY_DAMAGE jr z, .got_rollout_count ld de, EnemyRolloutCount ld a, BATTLEANIM_PLAYER_DAMAGE .got_rollout_count ld [wNumHits], a ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_MULTI_HIT jr z, .multihit cp EFFECT_CONVERSION jr z, .conversion cp EFFECT_DOUBLE_HIT jr z, .doublehit cp EFFECT_POISON_MULTI_HIT jr z, .twineedle cp EFFECT_TRIPLE_KICK jr z, .triplekick xor a ld [wKickCounter], a .triplekick ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld e, a ld d, 0 call PlayFXAnimID ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp FLY jr z, .fly_dig cp DIG ret nz .fly_dig ; clear sprite jp AppearUserLowerSub .multihit .conversion .doublehit .twineedle ld a, [wKickCounter] and 1 xor 1 ld [wKickCounter], a ld a, [de] cp $1 push af ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld e, a ld d, 0 pop af jp z, PlayFXAnimID xor a ld [wNumHits], a jp PlayFXAnimID ; 34fd1 BattleCommand_StatUpAnim: ; 34fd1 ld a, [AttackMissed] and a jp nz, BattleCommand_MoveDelay xor a jr BattleCommand_StatUpDownAnim ; 34fdb BattleCommand_StatDownAnim: ; 34fdb ld a, [AttackMissed] and a jp nz, BattleCommand_MoveDelay ld a, [hBattleTurn] and a ld a, BATTLEANIM_ENEMY_STAT_DOWN jr z, BattleCommand_StatUpDownAnim ld a, BATTLEANIM_WOBBLE ; fallthrough ; 34feb BattleCommand_StatUpDownAnim: ; 34feb ld [wNumHits], a xor a ld [wKickCounter], a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld e, a ld d, 0 jp PlayFXAnimID ; 34ffd BattleCommand_SwitchTurn: ; 34ffd ; switchturn ld a, [hBattleTurn] xor 1 ld [hBattleTurn], a ret ; 35004 BattleCommand_RaiseSub: ; 35004 ; raisesub ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret z call _CheckBattleScene jp c, BattleCommand_RaiseSubNoAnim xor a ld [wNumHits], a ld [FXAnimID + 1], a ld a, $2 ld [wKickCounter], a ld a, SUBSTITUTE jp LoadAnim ; 35023 BattleCommand_FailureText: ; 35023 ; failuretext ; If the move missed or failed, load the appropriate ; text, and end the effects of multi-turn or multi- ; hit moves. ld a, [AttackMissed] and a ret z call GetFailureResultText ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVarAddr cp FLY jr z, .fly_dig cp DIG jr z, .fly_dig ; Move effect: inc hl ld a, [hl] cp EFFECT_MULTI_HIT jr z, .multihit cp EFFECT_DOUBLE_HIT jr z, .multihit cp EFFECT_POISON_MULTI_HIT jr z, .multihit jp EndMoveEffect .multihit call BattleCommand_RaiseSub jp EndMoveEffect .fly_dig ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr res SUBSTATUS_UNDERGROUND, [hl] res SUBSTATUS_FLYING, [hl] call AppearUserRaiseSub jp EndMoveEffect ; 3505e BattleCommand_CheckFaint: ; 3505e ; checkfaint ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_ENDURE, a jr z, .not_enduring call BattleCommand_FalseSwipe ld b, $0 jr nc, .okay ld b, $1 jr .okay .not_enduring call GetOpponentItem ld a, b cp HELD_FOCUS_BAND ld b, $0 jr nz, .okay call BattleRandom cp c jr nc, .okay call BattleCommand_FalseSwipe ld b, $0 jr nc, .okay ld b, $2 .okay push bc call .check_sub ld c, $0 ld a, [hBattleTurn] and a jr nz, .damage_player call EnemyHurtItself jr .done_damage .damage_player call PlayerHurtItself .done_damage pop bc ld a, b and a ret z dec a jr nz, .not_enduring2 ld hl, EnduredText jp StdBattleTextBox .not_enduring2 call GetOpponentItem ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName ld hl, HungOnText jp StdBattleTextBox .check_sub ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret nz ld de, PlayerDamageTaken + 1 ld a, [hBattleTurn] and a jr nz, .damage_taken ld de, EnemyDamageTaken + 1 .damage_taken ld a, [CurDamage + 1] ld b, a ld a, [de] add b ld [de], a dec de ld a, [CurDamage] ld b, a ld a, [de] adc b ld [de], a ret nc ld a, $ff ld [de], a inc de ld [de], a ret ; 350e4 GetFailureResultText: ; 350e4 ld hl, DoesntAffectText ld de, DoesntAffectText ld a, [TypeModifier] and $7f jr z, .got_text ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_FUTURE_SIGHT ld hl, ButItFailedText ld de, ItFailedText jr z, .got_text ld hl, AttackMissedText ld de, AttackMissed2Text ld a, [CriticalHit] cp $ff jr nz, .got_text ld hl, UnaffectedText .got_text call FailText_CheckOpponentProtect xor a ld [CriticalHit], a ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_JUMP_KICK ret nz ld a, [TypeModifier] and $7f ret z ld hl, CurDamage ld a, [hli] ld b, [hl] rept 3 srl a rr b endr ld [hl], b dec hl ld [hli], a or b jr nz, .do_at_least_1_damage inc a ld [hl], a .do_at_least_1_damage ld hl, CrashedText call StdBattleTextBox ld a, $1 ld [wKickCounter], a call LoadMoveAnim ld c, $1 ld a, [hBattleTurn] and a jp nz, EnemyHurtItself jp PlayerHurtItself FailText_CheckOpponentProtect: ; 35157 ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVar bit SUBSTATUS_PROTECT, a jr z, .not_protected ld h, d ld l, e .not_protected jp StdBattleTextBox ; 35165 BattleCommanda5: ; 35165 ld a, [AttackMissed] and a ret z ld a, [TypeModifier] and $7f jp z, PrintDoesntAffect jp PrintButItFailed ; 35175 BattleCommand_CriticalText: ; 35175 ; criticaltext ; Prints the message for critical hits or one-hit KOs. ; If there is no message to be printed, wait 20 frames. ld a, [CriticalHit] and a jr z, .wait dec a add a ld hl, .texts ld b, 0 ld c, a add hl, bc ld a, [hli] ld h, [hl] ld l, a call StdBattleTextBox xor a ld [CriticalHit], a .wait ld c, 20 jp DelayFrames .texts dw CriticalHitText dw OneHitKOText ; 35197 BattleCommand_StartLoop: ; 35197 ; startloop ld hl, PlayerRolloutCount ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyRolloutCount .ok xor a ld [hl], a ret ; 351a5 BattleCommand_SuperEffectiveLoopText: ; 351a5 ; supereffectivelooptext ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr bit SUBSTATUS_IN_LOOP, a ret nz ; fallthrough ; 351ad BattleCommand_SuperEffectiveText: ; 351ad ; supereffectivetext ld a, [TypeModifier] and $7f cp 10 ; 1.0 ret z ld hl, SuperEffectiveText jr nc, .print ld hl, NotVeryEffectiveText .print jp StdBattleTextBox ; 351c0 BattleCommand_CheckDestinyBond: ; 351c0 ; checkdestinybond ; Faint the user if it fainted an opponent using Destiny Bond. ld hl, EnemyMonHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, BattleMonHP .got_hp ld a, [hli] or [hl] ret nz ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVar bit SUBSTATUS_DESTINY_BOND, a jr z, .no_dbond ld hl, TookDownWithItText call StdBattleTextBox ld a, [hBattleTurn] and a ld hl, EnemyMonMaxHP + 1 bccoord 2, 2 ; hp bar ld a, 0 jr nz, .got_max_hp ld hl, BattleMonMaxHP + 1 bccoord 10, 9 ; hp bar ld a, 1 .got_max_hp ld [wWhichHPBar], a ld a, [hld] ld [Buffer1], a ld a, [hld] ld [Buffer2], a ld a, [hl] ld [Buffer3], a xor a ld [hld], a ld a, [hl] ld [Buffer4], a xor a ld [hl], a ld [Buffer5], a ld [Buffer6], a ld h, b ld l, c predef AnimateHPBar call RefreshBattleHuds call BattleCommand_SwitchTurn xor a ld [wNumHits], a ld [FXAnimID + 1], a inc a ld [wKickCounter], a ld a, DESTINY_BOND call LoadAnim call BattleCommand_SwitchTurn jr .finish .no_dbond ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_MULTI_HIT jr z, .multiple_hit_raise_sub cp EFFECT_DOUBLE_HIT jr z, .multiple_hit_raise_sub cp EFFECT_POISON_MULTI_HIT jr z, .multiple_hit_raise_sub cp EFFECT_TRIPLE_KICK jr z, .multiple_hit_raise_sub cp EFFECT_BEAT_UP jr nz, .finish .multiple_hit_raise_sub call BattleCommand_RaiseSub .finish jp EndMoveEffect ; 35250 BattleCommand_BuildOpponentRage: ; 35250 ; buildopponentrage jp .start .start ld a, [AttackMissed] and a ret nz ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVar bit SUBSTATUS_RAGE, a ret z ld de, wEnemyRageCounter ld a, [hBattleTurn] and a jr z, .player ld de, wPlayerRageCounter .player ld a, [de] inc a ret z ld [de], a call BattleCommand_SwitchTurn ld hl, RageBuildingText call StdBattleTextBox jp BattleCommand_SwitchTurn ; 3527b BattleCommand_RageDamage: ; 3527b ; ragedamage ld a, [CurDamage] ld h, a ld b, a ld a, [CurDamage + 1] ld l, a ld c, a ld a, [hBattleTurn] and a ld a, [wPlayerRageCounter] jr z, .rage_loop ld a, [wEnemyRageCounter] .rage_loop and a jr z, .done dec a add hl, bc jr nc, .rage_loop ld hl, -1 .done ld a, h ld [CurDamage], a ld a, l ld [CurDamage + 1], a ret ; 352a3 EndMoveEffect: ; 352a3 ld a, [BattleScriptBufferAddress] ld l, a ld a, [BattleScriptBufferAddress + 1] ld h, a ld a, $ff ld [hli], a ld [hli], a ld [hl], a ret ; 352b1 DittoMetalPowder: ; 352b1 ld a, MON_SPECIES call BattlePartyAttr ld a, [hBattleTurn] and a ld a, [hl] jr nz, .Ditto ld a, [TempEnemyMonSpecies] .Ditto: cp DITTO ret nz push bc call GetOpponentItem ld a, [hl] cp METAL_POWDER pop bc ret nz ld a, c srl a add c ld c, a ret nc srl b ld a, b and a jr nz, .done inc b .done scf rr c ret ; 352dc BattleCommand_DamageStats: ; 352dc ; damagestats ld a, [hBattleTurn] and a jp nz, EnemyAttackDamage ; fallthrough ; 352e2 PlayerAttackDamage: ; 352e2 ; Return move power d, player level e, enemy defense c and player attack b. call ResetDamage ld hl, wPlayerMoveStructPower ld a, [hli] and a ld d, a ret z ld a, [hl] cp SPECIAL jr nc, .special .physical ld hl, EnemyMonDefense ld a, [hli] ld b, a ld c, [hl] ld a, [EnemyScreens] bit SCREENS_REFLECT, a jr z, .physicalcrit sla c rl b .physicalcrit ld hl, BattleMonAttack call GetDamageStatsCritical jr c, .thickclub ld hl, EnemyDefense ld a, [hli] ld b, a ld c, [hl] ld hl, PlayerAttack jr .thickclub .special ld hl, EnemyMonSpclDef ld a, [hli] ld b, a ld c, [hl] ld a, [EnemyScreens] bit SCREENS_LIGHT_SCREEN, a jr z, .specialcrit sla c rl b .specialcrit ld hl, BattleMonSpclAtk call GetDamageStatsCritical jr c, .lightball ld hl, EnemySpDef ld a, [hli] ld b, a ld c, [hl] ld hl, PlayerSpAtk .lightball ; Note: Returns player special attack at hl in hl. call LightBallBoost jr .done .thickclub ; Note: Returns player attack at hl in hl. call ThickClubBoost .done call TruncateHL_BC ld a, [BattleMonLevel] ld e, a call DittoMetalPowder ld a, 1 and a ret ; 3534d TruncateHL_BC: ; 3534d .loop ; Truncate 16-bit values hl and bc to 8-bit values b and c respectively. ; b = hl, c = bc ld a, h or b jr z, .finish srl b rr c srl b rr c ld a, c or b jr nz, .done_bc inc c .done_bc srl h rr l srl h rr l ld a, l or h jr nz, .finish inc l .finish ld a, [wLinkMode] cp 3 jr z, .done ; If we go back to the loop point, ; it's the same as doing this exact ; same check twice. ld a, h or b jr nz, .loop .done ld b, l ret ; 35378 GetDamageStatsCritical: ; 35378 ; Return carry if non-critical. ld a, [CriticalHit] and a scf ret z ; fallthrough ; 3537e GetDamageStats: ; 3537e ; Return the attacker's offensive stat and the defender's defensive ; stat based on whether the attacking type is physical or special. push hl push bc ld a, [hBattleTurn] and a jr nz, .enemy ld a, [wPlayerMoveStructType] cp SPECIAL ; special ld a, [PlayerSAtkLevel] ld b, a ld a, [EnemySDefLevel] jr nc, .end ; physical ld a, [PlayerAtkLevel] ld b, a ld a, [EnemyDefLevel] jr .end .enemy ld a, [wEnemyMoveStructType] cp SPECIAL ; special ld a, [EnemySAtkLevel] ld b, a ld a, [PlayerSDefLevel] jr nc, .end ; physical ld a, [EnemyAtkLevel] ld b, a ld a, [PlayerDefLevel] .end cp b pop bc pop hl ret ; 353b5 ThickClubBoost: ; 353b5 ; Return in hl the stat value at hl. ; If the attacking monster is Cubone or Marowak and ; it's holding a Thick Club, double it. push bc push de ld b, CUBONE ld c, MAROWAK ld d, THICK_CLUB call SpeciesItemBoost pop de pop bc ret ; 353c3 LightBallBoost: ; 353c3 ; Return in hl the stat value at hl. ; If the attacking monster is Pikachu and it's ; holding a Light Ball, double it. push bc push de ld b, PIKACHU ld c, PIKACHU ld d, LIGHT_BALL call SpeciesItemBoost pop de pop bc ret ; 353d1 SpeciesItemBoost: ; 353d1 ; Return in hl the stat value at hl. ; If the attacking monster is species b or c and ; it's holding item d, double it. ld a, [hli] ld l, [hl] ld h, a push hl ld a, MON_SPECIES call BattlePartyAttr ld a, [hBattleTurn] and a ld a, [hl] jr z, .CompareSpecies ld a, [TempEnemyMonSpecies] .CompareSpecies: pop hl cp b jr z, .GetItemHeldEffect cp c ret nz .GetItemHeldEffect: push hl call GetUserItem ld a, [hl] pop hl cp d ret nz ; Double the stat sla l rl h ret ; 353f6 EnemyAttackDamage: ; 353f6 call ResetDamage ; No damage dealt with 0 power. ld hl, wEnemyMoveStructPower ld a, [hli] ; hl = wEnemyMoveStructType ld d, a and a ret z ld a, [hl] cp SPECIAL jr nc, .Special .physical ld hl, BattleMonDefense ld a, [hli] ld b, a ld c, [hl] ld a, [PlayerScreens] bit SCREENS_REFLECT, a jr z, .physicalcrit sla c rl b .physicalcrit ld hl, EnemyMonAttack call GetDamageStatsCritical jr c, .thickclub ld hl, PlayerDefense ld a, [hli] ld b, a ld c, [hl] ld hl, EnemyAttack jr .thickclub .Special: ld hl, BattleMonSpclDef ld a, [hli] ld b, a ld c, [hl] ld a, [PlayerScreens] bit SCREENS_LIGHT_SCREEN, a jr z, .specialcrit sla c rl b .specialcrit ld hl, EnemyMonSpclAtk call GetDamageStatsCritical jr c, .lightball ld hl, PlayerSpDef ld a, [hli] ld b, a ld c, [hl] ld hl, EnemySpAtk .lightball call LightBallBoost jr .done .thickclub call ThickClubBoost .done call TruncateHL_BC ld a, [EnemyMonLevel] ld e, a call DittoMetalPowder ld a, 1 and a ret ; 35461 BattleCommand_BeatUp: ; 35461 ; beatup call ResetDamage ld a, [hBattleTurn] and a jp nz, .enemy_beats_up ld a, [PlayerSubStatus3] bit SUBSTATUS_IN_LOOP, a jr nz, .next_mon ld c, 20 call DelayFrames xor a ld [PlayerRolloutCount], a ld [wd002], a ld [wBeatUpHitAtLeastOnce], a jr .got_mon .next_mon ld a, [PlayerRolloutCount] ld b, a ld a, [PartyCount] sub b ld [wd002], a .got_mon ld a, [wd002] ld hl, PartyMonNicknames call GetNick ld a, MON_HP call GetBeatupMonLocation ld a, [hli] or [hl] jp z, .beatup_fail ; fainted ld a, [wd002] ld c, a ld a, [CurBattleMon] ; BUG: this can desynchronize link battles ; Change "cp [hl]" to "cp c" to fix cp [hl] ld hl, BattleMonStatus jr z, .active_mon ld a, MON_STATUS call GetBeatupMonLocation .active_mon ld a, [hl] and a jp nz, .beatup_fail ld a, $1 ld [wBeatUpHitAtLeastOnce], a ld hl, BeatUpAttackText call StdBattleTextBox ld a, [EnemyMonSpecies] ld [CurSpecies], a call GetBaseData ld a, [BaseDefense] ld c, a push bc ld a, MON_SPECIES call GetBeatupMonLocation ld a, [hl] ld [CurSpecies], a call GetBaseData ld a, [BaseAttack] pop bc ld b, a push bc ld a, MON_LEVEL call GetBeatupMonLocation ld a, [hl] ld e, a pop bc ld a, [wPlayerMoveStructPower] ld d, a ret .enemy_beats_up ld a, [EnemySubStatus3] bit SUBSTATUS_IN_LOOP, a jr nz, .not_first_enemy_beatup xor a ld [EnemyRolloutCount], a ld [wd002], a ld [wBeatUpHitAtLeastOnce], a jr .enemy_continue .not_first_enemy_beatup ld a, [EnemyRolloutCount] ld b, a ld a, [OTPartyCount] sub b ld [wd002], a .enemy_continue ld a, [wBattleMode] dec a jr z, .wild ld a, [wLinkMode] and a jr nz, .link_or_tower ld a, [InBattleTowerBattle] and a jr nz, .link_or_tower ld a, [wd002] ld c, a ld b, 0 ld hl, OTPartySpecies add hl, bc ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetPokemonName jr .got_enemy_nick .link_or_tower ld a, [wd002] ld hl, OTPartyMonNicknames ld bc, NAME_LENGTH call AddNTimes ld de, StringBuffer1 call CopyBytes .got_enemy_nick ld a, MON_HP call GetBeatupMonLocation ld a, [hli] or [hl] jp z, .beatup_fail ld a, [wd002] ld b, a ld a, [CurOTMon] cp b ld hl, EnemyMonStatus jr z, .active_enemy ld a, MON_STATUS call GetBeatupMonLocation .active_enemy ld a, [hl] and a jr nz, .beatup_fail ld a, $1 ld [wBeatUpHitAtLeastOnce], a jr .finish_beatup .wild ld a, [EnemyMonSpecies] ld [wNamedObjectIndexBuffer], a call GetPokemonName ld hl, BeatUpAttackText call StdBattleTextBox jp EnemyAttackDamage .finish_beatup ld hl, BeatUpAttackText call StdBattleTextBox ld a, [BattleMonSpecies] ld [CurSpecies], a call GetBaseData ld a, [BaseDefense] ld c, a push bc ld a, MON_SPECIES call GetBeatupMonLocation ld a, [hl] ld [CurSpecies], a call GetBaseData ld a, [BaseAttack] pop bc ld b, a push bc ld a, MON_LEVEL call GetBeatupMonLocation ld a, [hl] ld e, a pop bc ld a, [wEnemyMoveStructPower] ld d, a ret ; 355b0 .beatup_fail ; 355b0 ld b, buildopponentrage_command jp SkipToBattleCommand ; 355b5 BattleCommanda8: ; 355b5 ld a, [wBeatUpHitAtLeastOnce] and a ret nz jp PrintButItFailed ; 355bd GetBeatupMonLocation: ; 355bd push bc ld c, a ld b, 0 ld a, [hBattleTurn] and a ld hl, PartyMon1Species jr z, .got_species ld hl, OTPartyMon1Species .got_species ld a, [wd002] add hl, bc call GetPartyLocation pop bc ret BattleCommand_ClearMissDamage: ; 355d5 ; clearmissdamage ld a, [AttackMissed] and a ret z jp ResetDamage ; 355dd HitSelfInConfusion: ; 355dd call ResetDamage ld a, [hBattleTurn] and a ld hl, BattleMonDefense ld de, PlayerScreens ld a, [BattleMonLevel] jr z, .got_it ld hl, EnemyMonDefense ld de, EnemyScreens ld a, [EnemyMonLevel] .got_it push af ld a, [hli] ld b, a ld c, [hl] ld a, [de] bit SCREENS_REFLECT, a jr z, .mimic_screen sla c rl b .mimic_screen dec hl dec hl dec hl ld a, [hli] ld l, [hl] ld h, a call TruncateHL_BC ld d, 40 pop af ld e, a ret ; 35612 BattleCommand_DamageCalc: ; 35612 ; damagecalc ; Return a damage value for move power d, player level e, enemy defense c and player attack b. ; Return 1 if successful, else 0. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar ; Selfdestruct and Explosion halve defense. cp EFFECT_SELFDESTRUCT jr nz, .dont_selfdestruct srl c jr nz, .dont_selfdestruct inc c .dont_selfdestruct ; Variable-hit moves and Conversion can have a power of 0. cp EFFECT_MULTI_HIT jr z, .skip_zero_damage_check cp EFFECT_CONVERSION jr z, .skip_zero_damage_check ; No damage if move power is 0. ld a, d and a ret z .skip_zero_damage_check ; Minimum defense value is 1. ld a, c and a jr nz, .not_dividing_by_zero ld c, 1 .not_dividing_by_zero xor a ld hl, hDividend ld [hli], a ld [hli], a ld [hl], a ; Level * 2 ld a, e add a jr nc, .level_not_overflowing ld [hl], $1 .level_not_overflowing inc hl ld [hli], a ; / 5 ld a, 5 ld [hld], a push bc ld b, $4 call Divide pop bc ; + 2 inc [hl] inc [hl] ; * bp inc hl ld [hl], d call Multiply ; * Attack ld [hl], b call Multiply ; / Defense ld [hl], c ld b, $4 call Divide ; / 50 ld [hl], 50 ld b, $4 call Divide ; Item boosts call GetUserItem ld a, b and a jr z, .DoneItem ld hl, TypeBoostItems .NextItem: ld a, [hli] cp $ff jr z, .DoneItem ; Item effect cp b ld a, [hli] jr nz, .NextItem ; Type ld b, a ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVar cp b jr nz, .DoneItem ; * 100 + item effect amount ld a, c add 100 ld [hMultiplier], a call Multiply ; / 100 ld a, 100 ld [hDivisor], a ld b, 4 call Divide .DoneItem: ; Critical hits call .CriticalMultiplier ; Update CurDamage (capped at 997). ld hl, CurDamage ld b, [hl] ld a, [hProduct + 3] add b ld [hProduct + 3], a jr nc, .dont_cap_1 ld a, [hProduct + 2] inc a ld [hProduct + 2], a and a jr z, .Cap .dont_cap_1 ld a, [hProduct] ld b, a ld a, [hProduct + 1] or a jr nz, .Cap ld a, [hProduct + 2] cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) jr c, .dont_cap_2 cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + 1 jr nc, .Cap ld a, [hProduct + 3] cp LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) jr nc, .Cap .dont_cap_2 inc hl ld a, [hProduct + 3] ld b, [hl] add b ld [hld], a ld a, [hProduct + 2] ld b, [hl] adc b ld [hl], a jr c, .Cap ld a, [hl] cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) jr c, .dont_cap_3 cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + 1 jr nc, .Cap inc hl ld a, [hld] cp LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) jr c, .dont_cap_3 .Cap: ld a, HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE) ld [hli], a ld a, LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE) ld [hld], a .dont_cap_3 ; Minimum neutral damage is 2 (bringing the cap to 999). inc hl ld a, [hl] add MIN_NEUTRAL_DAMAGE ld [hld], a jr nc, .dont_floor inc [hl] .dont_floor ld a, 1 and a ret .CriticalMultiplier: ld a, [CriticalHit] and a ret z ; x2 ld a, [hQuotient + 2] add a ld [hProduct + 3], a ld a, [hQuotient + 1] rl a ld [hProduct + 2], a ; Cap at $ffff. ret nc ld a, $ff ld [hProduct + 2], a ld [hProduct + 3], a ret ; 35703 TypeBoostItems: ; 35703 db HELD_NORMAL_BOOST, NORMAL ; Pink/Polkadot Bow db HELD_FIGHTING_BOOST, FIGHTING ; Blackbelt db HELD_FLYING_BOOST, FLYING ; Sharp Beak db HELD_POISON_BOOST, POISON ; Poison Barb db HELD_GROUND_BOOST, GROUND ; Soft Sand db HELD_ROCK_BOOST, ROCK ; Hard Stone db HELD_BUG_BOOST, BUG ; Silverpowder db HELD_GHOST_BOOST, GHOST ; Spell Tag db HELD_FIRE_BOOST, FIRE ; Charcoal db HELD_WATER_BOOST, WATER ; Mystic Water db HELD_GRASS_BOOST, GRASS ; Miracle Seed db HELD_ELECTRIC_BOOST, ELECTRIC ; Magnet db HELD_PSYCHIC_BOOST, PSYCHIC ; Twistedspoon db HELD_ICE_BOOST, ICE ; Nevermeltice db HELD_DRAGON_BOOST, DRAGON ; Dragon Scale db HELD_DARK_BOOST, DARK ; Blackglasses db HELD_STEEL_BOOST, STEEL ; Metal Coat db $ff ; 35726 BattleCommand_ConstantDamage: ; 35726 ; constantdamage ld hl, BattleMonLevel ld a, [hBattleTurn] and a jr z, .got_turn ld hl, EnemyMonLevel .got_turn ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_LEVEL_DAMAGE ld b, [hl] ld a, 0 jr z, .got_power ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_PSYWAVE jr z, .psywave cp EFFECT_SUPER_FANG jr z, .super_fang cp EFFECT_REVERSAL jr z, .reversal ld a, BATTLE_VARS_MOVE_POWER call GetBattleVar ld b, a ld a, $0 jr .got_power .psywave ld a, b srl a add b ld b, a .psywave_loop call BattleRandom and a jr z, .psywave_loop cp b jr nc, .psywave_loop ld b, a ld a, $0 jr .got_power .super_fang ld hl, EnemyMonHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, BattleMonHP .got_hp ld a, [hli] srl a ld b, a ld a, [hl] rr a push af ld a, b pop bc and a jr nz, .got_power or b ld a, $0 jr nz, .got_power ld b, $1 jr .got_power .got_power ld hl, CurDamage ld [hli], a ld [hl], b ret .reversal ld hl, BattleMonHP ld a, [hBattleTurn] and a jr z, .reversal_got_hp ld hl, EnemyMonHP .reversal_got_hp xor a ld [hDividend], a ld [hMultiplicand + 0], a ld a, [hli] ld [hMultiplicand + 1], a ld a, [hli] ld [hMultiplicand + 2], a ld a, $30 ld [hMultiplier], a call Multiply ld a, [hli] ld b, a ld a, [hl] ld [hDivisor], a ld a, b and a jr z, .skip_to_divide ld a, [hProduct + 4] srl b rr a srl b rr a ld [hDivisor], a ld a, [hProduct + 2] ld b, a srl b ld a, [hProduct + 3] rr a srl b rr a ld [hDividend + 3], a ld a, b ld [hDividend + 2], a .skip_to_divide ld b, $4 call Divide ld a, [hQuotient + 2] ld b, a ld hl, .FlailPower .reversal_loop ld a, [hli] cp b jr nc, .break_loop inc hl jr .reversal_loop .break_loop ld a, [hBattleTurn] and a ld a, [hl] jr nz, .notPlayersTurn ld hl, wPlayerMoveStructPower ld [hl], a push hl call PlayerAttackDamage jr .notEnemysTurn .notPlayersTurn ld hl, wEnemyMoveStructPower ld [hl], a push hl call EnemyAttackDamage .notEnemysTurn call BattleCommand_DamageCalc pop hl ld [hl], 1 ret .FlailPower: ; px, bp db 1, 200 db 4, 150 db 9, 100 db 16, 80 db 32, 40 db 48, 20 ; 35813 BattleCommand_Counter: ; 35813 ; counter ld a, 1 ld [AttackMissed], a ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a ret z ld b, a callfar GetMoveEffect ld a, b cp EFFECT_COUNTER ret z call BattleCommand_ResetTypeMatchup ld a, [wTypeMatchup] and a ret z call CheckOpponentWentFirst ret z ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar dec a ld de, StringBuffer1 call GetMoveData ld a, [StringBuffer1 + MOVE_POWER] and a ret z ld a, [StringBuffer1 + MOVE_TYPE] cp SPECIAL ret nc ld hl, CurDamage ld a, [hli] or [hl] ret z ld a, [hl] add a ld [hld], a ld a, [hl] adc a ld [hl], a jr nc, .capped ld a, $ff ld [hli], a ld [hl], a .capped xor a ld [AttackMissed], a ret ; 35864 BattleCommand_Encore: ; 35864 ; encore ld hl, EnemyMonMoves ld de, EnemyEncoreCount ld a, [hBattleTurn] and a jr z, .ok ld hl, BattleMonMoves ld de, PlayerEncoreCount .ok ld a, BATTLE_VARS_LAST_MOVE_OPP call GetBattleVar and a jp z, .failed cp STRUGGLE jp z, .failed cp ENCORE jp z, .failed cp MIRROR_MOVE jp z, .failed ld b, a .got_move ld a, [hli] cp b jr nz, .got_move ld bc, BattleMonPP - BattleMonMoves - 1 add hl, bc ld a, [hl] and $3f jp z, .failed ld a, [AttackMissed] and a jp nz, .failed ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr bit SUBSTATUS_ENCORED, [hl] jp nz, .failed set SUBSTATUS_ENCORED, [hl] call BattleRandom and $3 inc a inc a inc a ld [de], a call CheckOpponentWentFirst jr nz, .finish_move ld a, [hBattleTurn] and a jr z, .force_last_enemy_move push hl ld a, [LastPlayerMove] ld b, a ld c, 0 ld hl, BattleMonMoves .find_player_move ld a, [hli] cp b jr z, .got_player_move inc c ld a, c cp NUM_MOVES jr c, .find_player_move pop hl res SUBSTATUS_ENCORED, [hl] xor a ld [de], a jr .failed .got_player_move pop hl ld a, c ld [CurMoveNum], a ld a, b ld [CurPlayerMove], a dec a ld de, wPlayerMoveStruct call GetMoveData jr .finish_move .force_last_enemy_move push hl ld a, [LastEnemyMove] ld b, a ld c, 0 ld hl, EnemyMonMoves .find_enemy_move ld a, [hli] cp b jr z, .got_enemy_move inc c ld a, c cp NUM_MOVES jr c, .find_enemy_move pop hl res SUBSTATUS_ENCORED, [hl] xor a ld [de], a jr .failed .got_enemy_move pop hl ld a, c ld [CurEnemyMoveNum], a ld a, b ld [CurEnemyMove], a dec a ld de, wEnemyMoveStruct call GetMoveData .finish_move call AnimateCurrentMove ld hl, GotAnEncoreText jp StdBattleTextBox .failed jp PrintDidntAffect2 ; 35926 BattleCommand_PainSplit: ; 35926 ; painsplit ld a, [AttackMissed] and a jp nz, .ButItFailed call CheckSubstituteOpp jp nz, .ButItFailed call AnimateCurrentMove ld hl, BattleMonMaxHP + 1 ld de, EnemyMonMaxHP + 1 call .PlayerShareHP ld a, $1 ld [wWhichHPBar], a hlcoord 10, 9 predef AnimateHPBar ld hl, EnemyMonHP ld a, [hli] ld [Buffer4], a ld a, [hli] ld [Buffer3], a ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a call .EnemyShareHP xor a ld [wWhichHPBar], a call ResetDamage hlcoord 2, 2 predef AnimateHPBar farcall _UpdateBattleHUDs ld hl, SharedPainText jp StdBattleTextBox .PlayerShareHP: ld a, [hld] ld [Buffer1], a ld a, [hld] ld [Buffer2], a ld a, [hld] ld b, a ld [Buffer3], a ld a, [hl] ld [Buffer4], a dec de dec de ld a, [de] dec de add b ld [CurDamage + 1], a ld b, [hl] ld a, [de] adc b srl a ld [CurDamage], a ld a, [CurDamage + 1] rr a ld [CurDamage + 1], a inc hl inc hl inc hl inc de inc de inc de .EnemyShareHP: ; 359ac ld c, [hl] dec hl ld a, [CurDamage + 1] sub c ld b, [hl] dec hl ld a, [CurDamage] sbc b jr nc, .skip ld a, [CurDamage] ld b, a ld a, [CurDamage + 1] ld c, a .skip ld a, c ld [hld], a ld [Buffer5], a ld a, b ld [hli], a ld [Buffer6], a ret ; 359cd .ButItFailed: jp PrintDidntAffect2 ; 359d0 BattleCommand_Snore: ; 359d0 ; snore ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP ret nz call ResetDamage ld a, $1 ld [AttackMissed], a call FailSnore jp EndMoveEffect ; 359e6 BattleCommand_Conversion2: ; 359e6 ; conversion2 ld a, [AttackMissed] and a jr nz, .failed ld hl, BattleMonType1 ld a, [hBattleTurn] and a jr z, .got_type ld hl, EnemyMonType1 .got_type ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a jr z, .failed push hl dec a ld hl, Moves + MOVE_TYPE call GetMoveAttr ld d, a pop hl cp CURSE_T jr z, .failed call AnimateCurrentMove call BattleCommand_SwitchTurn .loop call BattleRandom and $1f cp UNUSED_TYPES jr c, .okay cp UNUSED_TYPES_END jr c, .loop cp TYPES_END jr nc, .loop .okay ld [hli], a ld [hld], a push hl ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVarAddr push af push hl ld a, d ld [hl], a call BattleCheckTypeMatchup pop hl pop af ld [hl], a pop hl ld a, [wTypeMatchup] cp 10 jr nc, .loop call BattleCommand_SwitchTurn ld a, [hl] ld [wNamedObjectIndexBuffer], a predef GetTypeName ld hl, TransformedTypeText jp StdBattleTextBox .failed jp FailConversion2 ; 35a53 BattleCommand_LockOn: ; 35a53 ; lockon call CheckSubstituteOpp jr nz, .fail ld a, [AttackMissed] and a jr nz, .fail ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr set SUBSTATUS_LOCK_ON, [hl] call AnimateCurrentMove ld hl, TookAimText jp StdBattleTextBox .fail call AnimateFailedMove jp PrintDidntAffect ; 35a74 BattleCommand_Sketch: ; 35a74 ; sketch call ClearLastMove ; Don't sketch during a link battle ld a, [wLinkMode] and a jr z, .not_linked call AnimateFailedMove jp PrintNothingHappened .not_linked ; If the opponent has a substitute up, fail. call CheckSubstituteOpp jp nz, .fail ; If the opponent is transformed, fail. ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr bit SUBSTATUS_TRANSFORMED, [hl] jp nz, .fail ; Get the user's moveset in its party struct. ; This move replacement shall be permanent. ; Pointer will be in de. ld a, MON_MOVES call UserPartyAttr ld d, h ld e, l ; Get the battle move structs. ld hl, BattleMonMoves ld a, [hBattleTurn] and a jr z, .get_last_move ld hl, EnemyMonMoves .get_last_move ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar ld [wTypeMatchup], a ld b, a ; Fail if move is invalid or is Struggle. and a jr z, .fail cp STRUGGLE jr z, .fail ; Fail if user already knows that move ld c, NUM_MOVES .does_user_already_know_move ld a, [hli] cp b jr z, .fail dec c jr nz, .does_user_already_know_move ; Find Sketch in the user's moveset. ; Pointer in hl, and index in c. dec hl ld c, NUM_MOVES .find_sketch dec c ld a, [hld] cp SKETCH jr nz, .find_sketch inc hl ; The Sketched move is loaded to that slot. ld a, b ld [hl], a ; Copy the base PP from that move. push bc push hl dec a ld hl, Moves + MOVE_PP call GetMoveAttr pop hl ld bc, BattleMonPP - BattleMonMoves add hl, bc ld [hl], a pop bc ld a, [hBattleTurn] and a jr z, .user_trainer ld a, [wBattleMode] dec a jr nz, .user_trainer ; wildmon ld a, [hl] push bc ld hl, wWildMonPP ld b, 0 add hl, bc ld [hl], a ld hl, wWildMonMoves add hl, bc pop bc ld [hl], b jr .done_copy .user_trainer ld a, [hl] push af ld l, c ld h, 0 add hl, de ld a, b ld [hl], a pop af ld de, MON_PP - MON_MOVES add hl, de ld [hl], a .done_copy call GetMoveName call AnimateCurrentMove ld hl, SketchedText jp StdBattleTextBox .fail call AnimateFailedMove jp PrintDidntAffect ; 35b16 BattleCommand_DefrostOpponent: ; 35b16 ; defrostopponent ; Thaw the opponent if frozen, and ; raise the user's Attack one stage. call AnimateCurrentMove ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr call Defrost ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVarAddr ld a, [hl] push hl push af ld a, EFFECT_ATTACK_UP ld [hl], a call BattleCommand_StatUp pop af pop hl ld [hl], a ret ; 35b33 BattleCommand_SleepTalk: ; 35b33 ; sleeptalk call ClearLastMove ld a, [AttackMissed] and a jr nz, .fail ld a, [hBattleTurn] and a ld hl, BattleMonMoves + 1 ld a, [DisabledMove] ld d, a jr z, .got_moves ld hl, EnemyMonMoves + 1 ld a, [EnemyDisabledMove] ld d, a .got_moves ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP jr z, .fail ld a, [hl] and a jr z, .fail call .safely_check_has_usable_move jr c, .fail dec hl .sample_move push hl call BattleRandom and 3 ; TODO factor in NUM_MOVES ld c, a ld b, 0 add hl, bc ld a, [hl] pop hl and a jr z, .sample_move ld e, a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp e jr z, .sample_move ld a, e cp d jr z, .sample_move call .check_two_turn_move jr z, .sample_move ld a, BATTLE_VARS_MOVE call GetBattleVarAddr ld a, e ld [hl], a call CheckUserIsCharging jr nz, .charging ld a, [wKickCounter] push af call BattleCommand_LowerSub pop af ld [wKickCounter], a .charging call LoadMoveAnim call UpdateMoveData jp ResetTurn .fail call AnimateFailedMove jp TryPrintButItFailed .safely_check_has_usable_move push hl push de push bc call .check_has_usable_move pop bc pop de pop hl ret .check_has_usable_move ld a, [hBattleTurn] and a ld a, [DisabledMove] jr z, .got_move_2 ld a, [EnemyDisabledMove] .got_move_2 ld b, a ld a, BATTLE_VARS_MOVE call GetBattleVar ld c, a dec hl ld d, NUM_MOVES .loop2 ld a, [hl] and a jr z, .carry cp c jr z, .nope cp b jr z, .nope call .check_two_turn_move jr nz, .no_carry .nope inc hl dec d jr nz, .loop2 .carry scf ret .no_carry and a ret .check_two_turn_move push hl push de push bc ld b, a callfar GetMoveEffect ld a, b pop bc pop de pop hl cp EFFECT_SKULL_BASH ret z cp EFFECT_RAZOR_WIND ret z cp EFFECT_SKY_ATTACK ret z cp EFFECT_SOLARBEAM ret z cp EFFECT_FLY ret z cp EFFECT_BIDE ret ; 35bff BattleCommand_DestinyBond: ; 35bff ; destinybond ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVarAddr set SUBSTATUS_DESTINY_BOND, [hl] call AnimateCurrentMove ld hl, DestinyBondEffectText jp StdBattleTextBox ; 35c0f BattleCommand_Spite: ; 35c0f ; spite ld a, [AttackMissed] and a jp nz, .failed ld bc, PARTYMON_STRUCT_LENGTH ; ???? ld hl, EnemyMonMoves ld a, [hBattleTurn] and a jr z, .got_moves ld hl, BattleMonMoves .got_moves ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a jr z, .failed cp STRUGGLE jr z, .failed ld b, a ld c, -1 .loop inc c ld a, [hli] cp b jr nz, .loop ld [wTypeMatchup], a dec hl ld b, 0 push bc ld c, BattleMonPP - BattleMonMoves add hl, bc pop bc ld a, [hl] and $3f jr z, .failed push bc call GetMoveName call BattleRandom and 3 inc a inc a ld b, a ld a, [hl] and $3f cp b jr nc, .deplete_pp ld b, a .deplete_pp ld a, [hl] sub b ld [hl], a push af ld a, MON_PP call OpponentPartyAttr ld d, b pop af pop bc add hl, bc ld e, a ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVar bit SUBSTATUS_TRANSFORMED, a jr nz, .transformed ld a, [hBattleTurn] and a jr nz, .not_wildmon ld a, [wBattleMode] dec a jr nz, .not_wildmon ld hl, wWildMonPP add hl, bc .not_wildmon ld [hl], e .transformed push de call AnimateCurrentMove pop de ld a, d ld [wTypeMatchup], a ld hl, SpiteEffectText jp StdBattleTextBox .failed jp PrintDidntAffect2 ; 35c94 BattleCommand_FalseSwipe: ; 35c94 ; falseswipe ld hl, EnemyMonHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, BattleMonHP .got_hp ld de, CurDamage ld c, 2 push hl push de call StringCmp pop de pop hl jr c, .done ld a, [hli] ld [de], a inc de ld a, [hl] dec a ld [de], a inc a jr nz, .okay dec de ld a, [de] dec a ld [de], a .okay ld a, [CriticalHit] cp $2 jr nz, .carry xor a ld [CriticalHit], a .carry scf ret .done and a ret ; 35cc9 BattleCommand_HealBell: ; 35cc9 ; healbell ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr res SUBSTATUS_NIGHTMARE, [hl] ld de, PartyMon1Status ld a, [hBattleTurn] and a jr z, .got_status ld de, OTPartyMon1Status .got_status ld a, BATTLE_VARS_STATUS call GetBattleVarAddr xor a ld [hl], a ld h, d ld l, e ld bc, PARTYMON_STRUCT_LENGTH ld d, PARTY_LENGTH .loop ld [hl], a add hl, bc dec d jr nz, .loop call AnimateCurrentMove ld hl, BellChimedText call StdBattleTextBox ld a, [hBattleTurn] and a jp z, CalcPlayerStats jp CalcEnemyStats ; 35d00 FarPlayBattleAnimation: ; 35d00 ; play animation de ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND ret nz ; fallthrough ; 35d08 PlayFXAnimID: ; 35d08 ld a, e ld [FXAnimID], a ld a, d ld [FXAnimID + 1], a ld c, 3 call DelayFrames callfar PlayBattleAnim ret ; 35d1c EnemyHurtItself: ; 35d1c ld hl, CurDamage ld a, [hli] ld b, a ld a, [hl] or b jr z, .did_no_damage ld a, c and a jr nz, .mimic_sub_check ld a, [EnemySubStatus4] bit SUBSTATUS_SUBSTITUTE, a jp nz, SelfInflictDamageToSubstitute .mimic_sub_check ld a, [hld] ld b, a ld a, [EnemyMonHP + 1] ld [Buffer3], a sub b ld [EnemyMonHP + 1], a ld a, [hl] ld b, a ld a, [EnemyMonHP] ld [Buffer4], a sbc b ld [EnemyMonHP], a jr nc, .mimic_faint ld a, [Buffer4] ld [hli], a ld a, [Buffer3] ld [hl], a xor a ld hl, EnemyMonHP ld [hli], a ld [hl], a .mimic_faint ld hl, EnemyMonMaxHP ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a ld hl, EnemyMonHP ld a, [hli] ld [Buffer6], a ld a, [hl] ld [Buffer5], a hlcoord 2, 2 xor a ld [wWhichHPBar], a predef AnimateHPBar .did_no_damage jp RefreshBattleHuds ; 35d7e PlayerHurtItself: ; 35d7e ld hl, CurDamage ld a, [hli] ld b, a ld a, [hl] or b jr z, .did_no_damage ld a, c and a jr nz, .mimic_sub_check ld a, [PlayerSubStatus4] bit SUBSTATUS_SUBSTITUTE, a jp nz, SelfInflictDamageToSubstitute .mimic_sub_check ld a, [hld] ld b, a ld a, [BattleMonHP + 1] ld [Buffer3], a sub b ld [BattleMonHP + 1], a ld [Buffer5], a ld b, [hl] ld a, [BattleMonHP] ld [Buffer4], a sbc b ld [BattleMonHP], a ld [Buffer6], a jr nc, .mimic_faint ld a, [Buffer4] ld [hli], a ld a, [Buffer3] ld [hl], a xor a ld hl, BattleMonHP ld [hli], a ld [hl], a ld hl, Buffer5 ld [hli], a ld [hl], a .mimic_faint ld hl, BattleMonMaxHP ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a hlcoord 10, 9 ld a, $1 ld [wWhichHPBar], a predef AnimateHPBar .did_no_damage jp RefreshBattleHuds ; 35de0 SelfInflictDamageToSubstitute: ; 35de0 ld hl, SubTookDamageText call StdBattleTextBox ld de, EnemySubstituteHP ld a, [hBattleTurn] and a jr z, .got_hp ld de, PlayerSubstituteHP .got_hp ld hl, CurDamage ld a, [hli] and a jr nz, .broke ld a, [de] sub [hl] ld [de], a jr z, .broke jr nc, .done .broke ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVarAddr res SUBSTATUS_SUBSTITUTE, [hl] ld hl, SubFadedText call StdBattleTextBox call BattleCommand_SwitchTurn call BattleCommand_LowerSubNoAnim ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND call z, AppearUserLowerSub call BattleCommand_SwitchTurn ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVarAddr cp EFFECT_MULTI_HIT jr z, .ok cp EFFECT_DOUBLE_HIT jr z, .ok cp EFFECT_POISON_MULTI_HIT jr z, .ok cp EFFECT_TRIPLE_KICK jr z, .ok cp EFFECT_BEAT_UP jr z, .ok xor a ld [hl], a .ok call RefreshBattleHuds .done jp ResetDamage ; 35e40 UpdateMoveData: ; 35e40 ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVarAddr ld d, h ld e, l ld a, BATTLE_VARS_MOVE call GetBattleVar ld [CurMove], a ld [wNamedObjectIndexBuffer], a dec a call GetMoveData call GetMoveName jp CopyName1 ; 35e5c BattleCommand_SleepTarget: ; 35e5c ; sleeptarget call GetOpponentItem ld a, b cp HELD_PREVENT_SLEEP jr nz, .not_protected_by_item ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName ld hl, ProtectedByText jr .fail .not_protected_by_item ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr ld d, h ld e, l ld a, [de] and SLP ld hl, AlreadyAsleepText jr nz, .fail ld a, [AttackMissed] and a jp nz, PrintDidntAffect2 ld hl, DidntAffect1Text call .CheckAIRandomFail jr c, .fail ld a, [de] and a jr nz, .fail call CheckSubstituteOpp jr nz, .fail call AnimateCurrentMove ld b, $7 ld a, [InBattleTowerBattle] and a jr z, .random_loop ld b, $3 .random_loop call BattleRandom and b jr z, .random_loop cp 7 jr z, .random_loop inc a ld [de], a call UpdateOpponentInParty call RefreshBattleHuds ld hl, FellAsleepText call StdBattleTextBox farcall UseHeldStatusHealingItem jp z, OpponentCantMove ret .fail push hl call AnimateFailedMove pop hl jp StdBattleTextBox ; 35ece .CheckAIRandomFail: ; 35ece ; Enemy turn ld a, [hBattleTurn] and a jr z, .dont_fail ; Not in link battle ld a, [wLinkMode] and a jr nz, .dont_fail ld a, [InBattleTowerBattle] and a jr nz, .dont_fail ; Not locked-on by the enemy ld a, [PlayerSubStatus5] bit SUBSTATUS_LOCK_ON, a jr nz, .dont_fail call BattleRandom cp $40 ; 25% ret c .dont_fail xor a ret ; 35eee BattleCommand_PoisonTarget: ; 35eee ; poisontarget call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and a ret nz ld a, [TypeModifier] and $7f ret z call CheckIfTargetIsPoisonType ret z call GetOpponentItem ld a, b cp HELD_PREVENT_POISON ret z ld a, [EffectFailed] and a ret nz call SafeCheckSafeguard ret nz call PoisonOpponent ld de, ANIM_PSN call PlayOpponentBattleAnim call RefreshBattleHuds ld hl, WasPoisonedText call StdBattleTextBox farcall UseHeldStatusHealingItem ret ; 35f2c BattleCommand_Poison: ; 35f2c ; poison ld hl, DoesntAffectText ld a, [TypeModifier] and $7f jp z, .failed call CheckIfTargetIsPoisonType jp z, .failed ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar ld b, a ld hl, AlreadyPoisonedText and 1 << PSN jp nz, .failed call GetOpponentItem ld a, b cp HELD_PREVENT_POISON jr nz, .do_poison ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName ld hl, ProtectedByText jr .failed .do_poison ld hl, DidntAffect1Text ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar and a jr nz, .failed ld a, [hBattleTurn] and a jr z, .mimic_random ld a, [wLinkMode] and a jr nz, .mimic_random ld a, [InBattleTowerBattle] and a jr nz, .mimic_random ld a, [PlayerSubStatus5] bit SUBSTATUS_LOCK_ON, a jr nz, .mimic_random call BattleRandom cp $40 ; 25% chance AI fails jr c, .failed .mimic_random call CheckSubstituteOpp jr nz, .failed ld a, [AttackMissed] and a jr nz, .failed call .check_toxic jr z, .toxic call .apply_poison ld hl, WasPoisonedText call StdBattleTextBox jr .finished .toxic set SUBSTATUS_TOXIC, [hl] xor a ld [de], a call .apply_poison ld hl, BadlyPoisonedText call StdBattleTextBox .finished farcall UseHeldStatusHealingItem ret .failed push hl call AnimateFailedMove pop hl jp StdBattleTextBox ; 35fc0 .apply_poison ; 35fc0 call AnimateCurrentMove call PoisonOpponent jp RefreshBattleHuds ; 35fc9 .check_toxic ; 35fc9 ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr ld a, [hBattleTurn] and a ld de, EnemyToxicCount jr z, .ok ld de, PlayerToxicCount .ok ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_TOXIC ret ; 35fe1 CheckIfTargetIsPoisonType: ; 35fe1 ld de, EnemyMonType1 ld a, [hBattleTurn] and a jr z, .ok ld de, BattleMonType1 .ok ld a, [de] inc de cp POISON ret z ld a, [de] cp POISON ret ; 35ff5 PoisonOpponent: ; 35ff5 ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr set PSN, [hl] jp UpdateOpponentInParty ; 35fff BattleCommand_DrainTarget: ; 35fff ; draintarget call SapHealth ld hl, SuckedHealthText jp StdBattleTextBox ; 36008 BattleCommand_EatDream: ; 36008 ; eatdream call SapHealth ld hl, DreamEatenText jp StdBattleTextBox ; 36011 SapHealth: ; 36011 ld hl, CurDamage ld a, [hli] srl a ld [hDividend], a ld b, a ld a, [hl] rr a ld [hDividend + 1], a or b jr nz, .ok1 ld a, $1 ld [hDividend + 1], a .ok1 ld hl, BattleMonHP ld de, BattleMonMaxHP ld a, [hBattleTurn] and a jr z, .battlemonhp ld hl, EnemyMonHP ld de, EnemyMonMaxHP .battlemonhp ld bc, Buffer4 ld a, [hli] ld [bc], a ld a, [hl] dec bc ld [bc], a ld a, [de] dec bc ld [bc], a inc de ld a, [de] dec bc ld [bc], a ld a, [hDividend + 1] ld b, [hl] add b ld [hld], a ld [Buffer5], a ld a, [hDividend] ld b, [hl] adc b ld [hli], a ld [Buffer6], a jr c, .okay2 ld a, [hld] ld b, a ld a, [de] dec de sub b ld a, [hli] ld b, a ld a, [de] inc de sbc b jr nc, .okay3 .okay2 ld a, [de] ld [hld], a ld [Buffer5], a dec de ld a, [de] ld [hli], a ld [Buffer6], a inc de .okay3 ld a, [hBattleTurn] and a hlcoord 10, 9 ld a, $1 jr z, .hp_bar hlcoord 2, 2 xor a .hp_bar ld [wWhichHPBar], a predef AnimateHPBar call RefreshBattleHuds jp UpdateBattleMonInParty ; 3608c BattleCommand_BurnTarget: ; 3608c ; burntarget xor a ld [wNumHits], a call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and a jp nz, Defrost ld a, [TypeModifier] and $7f ret z call CheckMoveTypeMatchesTarget ; Don't burn a Fire-type ret z call GetOpponentItem ld a, b cp HELD_PREVENT_BURN ret z ld a, [EffectFailed] and a ret nz call SafeCheckSafeguard ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr set BRN, [hl] call UpdateOpponentInParty ld hl, ApplyBrnEffectOnAttack call CallBattleCore ld de, ANIM_BRN call PlayOpponentBattleAnim call RefreshBattleHuds ld hl, WasBurnedText call StdBattleTextBox farcall UseHeldStatusHealingItem ret ; 360dd Defrost: ; 360dd ld a, [hl] and 1 << FRZ ret z xor a ld [hl], a ld a, [hBattleTurn] and a ld a, [CurOTMon] ld hl, OTPartyMon1Status jr z, .ok ld hl, PartyMon1Status ld a, [CurBattleMon] .ok call GetPartyLocation xor a ld [hl], a call UpdateOpponentInParty ld hl, DefrostedOpponentText jp StdBattleTextBox ; 36102 BattleCommand_FreezeTarget: ; 36102 ; freezetarget xor a ld [wNumHits], a call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and a ret nz ld a, [TypeModifier] and $7f ret z ld a, [Weather] cp WEATHER_SUN ret z call CheckMoveTypeMatchesTarget ; Don't freeze an Ice-type ret z call GetOpponentItem ld a, b cp HELD_PREVENT_FREEZE ret z ld a, [EffectFailed] and a ret nz call SafeCheckSafeguard ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr set FRZ, [hl] call UpdateOpponentInParty ld de, ANIM_FRZ call PlayOpponentBattleAnim call RefreshBattleHuds ld hl, WasFrozenText call StdBattleTextBox farcall UseHeldStatusHealingItem ret nz call OpponentCantMove call EndRechargeOpp ld hl, wEnemyJustGotFrozen ld a, [hBattleTurn] and a jr z, .finish ld hl, wPlayerJustGotFrozen .finish ld [hl], $1 ret ; 36165 BattleCommand_ParalyzeTarget: ; 36165 ; paralyzetarget xor a ld [wNumHits], a call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and a ret nz ld a, [TypeModifier] and $7f ret z call GetOpponentItem ld a, b cp HELD_PREVENT_PARALYZE ret z ld a, [EffectFailed] and a ret nz call SafeCheckSafeguard ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr set PAR, [hl] call UpdateOpponentInParty ld hl, ApplyPrzEffectOnSpeed call CallBattleCore ld de, ANIM_PAR call PlayOpponentBattleAnim call RefreshBattleHuds call PrintParalyze ld hl, UseHeldStatusHealingItem jp CallBattleCore ; 361ac BattleCommand_AttackUp: ; 361ac ; attackup ld b, ATTACK jr BattleCommand_StatUp BattleCommand_DefenseUp: ; 361b0 ; defenseup ld b, DEFENSE jr BattleCommand_StatUp BattleCommand_SpeedUp: ; 361b4 ; speedup ld b, SPEED jr BattleCommand_StatUp BattleCommand_SpecialAttackUp: ; 361b8 ; specialattackup ld b, SP_ATTACK jr BattleCommand_StatUp BattleCommand_SpecialDefenseUp: ; 361bc ; specialdefenseup ld b, SP_DEFENSE jr BattleCommand_StatUp BattleCommand_AccuracyUp: ; 361c0 ; accuracyup ld b, ACCURACY jr BattleCommand_StatUp BattleCommand_EvasionUp: ; 361c4 ; evasionup ld b, EVASION jr BattleCommand_StatUp BattleCommand_AttackUp2: ; 361c8 ; attackup2 ld b, $10 | ATTACK jr BattleCommand_StatUp BattleCommand_DefenseUp2: ; 361cc ; defenseup2 ld b, $10 | DEFENSE jr BattleCommand_StatUp BattleCommand_SpeedUp2: ; 361d0 ; speedup2 ld b, $10 | SPEED jr BattleCommand_StatUp BattleCommand_SpecialAttackUp2: ; 361d4 ; specialattackup2 ld b, $10 | SP_ATTACK jr BattleCommand_StatUp BattleCommand_SpecialDefenseUp2: ; 361d8 ; specialdefenseup2 ld b, $10 | SP_DEFENSE jr BattleCommand_StatUp BattleCommand_AccuracyUp2: ; 361dc ; accuracyup2 ld b, $10 | ACCURACY jr BattleCommand_StatUp BattleCommand_EvasionUp2: ; 361e0 ; evasionup2 ld b, $10 | EVASION jr BattleCommand_StatUp BattleCommand_StatUp: ; 361e4 ; statup call CheckIfStatCanBeRaised ld a, [FailedMessage] and a ret nz jp StatUpAnimation ; 361ef CheckIfStatCanBeRaised: ; 361ef ld a, b ld [LoweredStat], a ld hl, PlayerStatLevels ld a, [hBattleTurn] and a jr z, .got_stat_levels ld hl, EnemyStatLevels .got_stat_levels ld a, [AttackMissed] and a jp nz, .stat_raise_failed ld a, [EffectFailed] and a jp nz, .stat_raise_failed ld a, [LoweredStat] and $f ld c, a ld b, 0 add hl, bc ld b, [hl] inc b ld a, $d cp b jp c, .cant_raise_stat ld a, [LoweredStat] and $f0 jr z, .got_num_stages inc b ld a, $d cp b jr nc, .got_num_stages ld b, a .got_num_stages ld [hl], b push hl ld a, c cp $5 jr nc, .done_calcing_stats ld hl, BattleMonStats + 1 ld de, PlayerStats ld a, [hBattleTurn] and a jr z, .got_stats_pointer ld hl, EnemyMonStats + 1 ld de, EnemyStats .got_stats_pointer push bc sla c ld b, 0 add hl, bc ld a, c add e ld e, a jr nc, .no_carry inc d .no_carry pop bc ld a, [hld] sub LOW(MAX_STAT_VALUE) jr nz, .not_already_max ld a, [hl] sbc HIGH(MAX_STAT_VALUE) jp z, .stats_already_max .not_already_max ld a, [hBattleTurn] and a jr z, .calc_player_stats call CalcEnemyStats jr .done_calcing_stats .calc_player_stats call CalcPlayerStats .done_calcing_stats pop hl xor a ld [FailedMessage], a ret ; 3626e .stats_already_max ; 3626e pop hl dec [hl] ; fallthrough ; 36270 .cant_raise_stat ; 36270 ld a, $2 ld [FailedMessage], a ld a, $1 ld [AttackMissed], a ret ; 3627b .stat_raise_failed ; 3627b ld a, $1 ld [FailedMessage], a ret ; 36281 StatUpAnimation: ; 36281 ld bc, wPlayerMinimized ld hl, DropPlayerSub ld a, [hBattleTurn] and a jr z, .do_player ld bc, wEnemyMinimized ld hl, DropEnemySub .do_player ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp MINIMIZE ret nz ld a, $1 ld [bc], a call _CheckBattleScene ret nc xor a ld [hBGMapMode], a call CallBattleCore call WaitBGMap jp BattleCommand_MoveDelay ; 362ad BattleCommand_AttackDown: ; 362ad ; attackdown ld a, ATTACK jr BattleCommand_StatDown BattleCommand_DefenseDown: ; 362b1 ; defensedown ld a, DEFENSE jr BattleCommand_StatDown BattleCommand_SpeedDown: ; 362b5 ; speeddown ld a, SPEED jr BattleCommand_StatDown BattleCommand_SpecialAttackDown: ; 362b9 ; specialattackdown ld a, SP_ATTACK jr BattleCommand_StatDown BattleCommand_SpecialDefenseDown: ; 362bd ; specialdefensedown ld a, SP_DEFENSE jr BattleCommand_StatDown BattleCommand_AccuracyDown: ; 362c1 ; accuracydown ld a, ACCURACY jr BattleCommand_StatDown BattleCommand_EvasionDown: ; 362c5 ; evasiondown ld a, EVASION jr BattleCommand_StatDown BattleCommand_AttackDown2: ; 362c9 ; attackdown2 ld a, $10 | ATTACK jr BattleCommand_StatDown BattleCommand_DefenseDown2: ; 362cd ; defensedown2 ld a, $10 | DEFENSE jr BattleCommand_StatDown BattleCommand_SpeedDown2: ; 362d1 ; speeddown2 ld a, $10 | SPEED jr BattleCommand_StatDown BattleCommand_SpecialAttackDown2: ; 362d5 ; specialattackdown2 ld a, $10 | SP_ATTACK jr BattleCommand_StatDown BattleCommand_SpecialDefenseDown2: ; 362d9 ; specialdefensedown2 ld a, $10 | SP_DEFENSE jr BattleCommand_StatDown BattleCommand_AccuracyDown2: ; 362dd ; accuracydown2 ld a, $10 | ACCURACY jr BattleCommand_StatDown BattleCommand_EvasionDown2: ; 362e1 ; evasiondown2 ld a, $10 | EVASION BattleCommand_StatDown: ; 362e3 ; statdown ld [LoweredStat], a call CheckMist jp nz, .Mist ld hl, EnemyStatLevels ld a, [hBattleTurn] and a jr z, .GetStatLevel ld hl, PlayerStatLevels .GetStatLevel: ; Attempt to lower the stat. ld a, [LoweredStat] and $f ld c, a ld b, 0 add hl, bc ld b, [hl] dec b jp z, .CantLower ; Sharply lower the stat if applicable. ld a, [LoweredStat] and $f0 jr z, .ComputerMiss dec b jr nz, .ComputerMiss inc b .ComputerMiss: ; Computer opponents have a 1/4 chance of failing. ld a, [hBattleTurn] and a jr z, .DidntMiss ld a, [wLinkMode] and a jr nz, .DidntMiss ld a, [InBattleTowerBattle] and a jr nz, .DidntMiss ; Lock-On still always works. ld a, [PlayerSubStatus5] bit SUBSTATUS_LOCK_ON, a jr nz, .DidntMiss ; Attacking moves that also lower accuracy are unaffected. ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_ACCURACY_DOWN_HIT jr z, .DidntMiss call BattleRandom cp $40 jr c, .Failed .DidntMiss: call CheckSubstituteOpp jr nz, .Failed ld a, [AttackMissed] and a jr nz, .Failed ld a, [EffectFailed] and a jr nz, .Failed call CheckHiddenOpponent jr nz, .Failed ; Accuracy/Evasion reduction don't involve stats. ld [hl], b ld a, c cp ACCURACY jr nc, .Hit push hl ld hl, EnemyMonAttack + 1 ld de, EnemyStats ld a, [hBattleTurn] and a jr z, .do_enemy ld hl, BattleMonAttack + 1 ld de, PlayerStats .do_enemy call TryLowerStat pop hl jr z, .CouldntLower .Hit: xor a ld [FailedMessage], a ret .CouldntLower: inc [hl] .CantLower: ld a, 3 ld [FailedMessage], a ld a, 1 ld [AttackMissed], a ret .Failed: ld a, 1 ld [FailedMessage], a ld [AttackMissed], a ret .Mist: ld a, 2 ld [FailedMessage], a ld a, 1 ld [AttackMissed], a ret ; 36391 CheckMist: ; 36391 ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_ATTACK_DOWN jr c, .dont_check_mist cp EFFECT_EVASION_DOWN + 1 jr c, .check_mist cp EFFECT_ATTACK_DOWN_2 jr c, .dont_check_mist cp EFFECT_EVASION_DOWN_2 + 1 jr c, .check_mist cp EFFECT_ATTACK_DOWN_HIT jr c, .dont_check_mist cp EFFECT_EVASION_DOWN_HIT + 1 jr c, .check_mist .dont_check_mist xor a ret .check_mist ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVar bit SUBSTATUS_MIST, a ret ; 363b8 BattleCommand_StatUpMessage: ; 363b8 ld a, [FailedMessage] and a ret nz ld a, [LoweredStat] and $f ld b, a inc b call GetStatName ld hl, .stat jp BattleTextBox .stat text_jump UnknownText_0x1c0cc6 start_asm ld hl, .up ld a, [LoweredStat] and $f0 ret z ld hl, .wayup ret .wayup text_jump UnknownText_0x1c0cd0 db "@" .up text_jump UnknownText_0x1c0ce0 db "@" ; 363e9 BattleCommand_StatDownMessage: ; 363e9 ld a, [FailedMessage] and a ret nz ld a, [LoweredStat] and $f ld b, a inc b call GetStatName ld hl, .stat jp BattleTextBox .stat text_jump UnknownText_0x1c0ceb start_asm ld hl, .fell ld a, [LoweredStat] and $f0 ret z ld hl, .sharplyfell ret .sharplyfell text_jump UnknownText_0x1c0cf5 db "@" .fell text_jump UnknownText_0x1c0d06 db "@" ; 3641a TryLowerStat: ; 3641a ; Lower stat c from stat struct hl (buffer de). push bc sla c ld b, 0 add hl, bc ; add de, c ld a, c add e ld e, a jr nc, .no_carry inc d .no_carry pop bc ; The lowest possible stat is 1. ld a, [hld] sub 1 jr nz, .not_min ld a, [hl] and a ret z .not_min ld a, [hBattleTurn] and a jr z, .Player call BattleCommand_SwitchTurn call CalcPlayerStats call BattleCommand_SwitchTurn jr .end .Player: call BattleCommand_SwitchTurn call CalcEnemyStats call BattleCommand_SwitchTurn .end ld a, 1 and a ret ; 3644c BattleCommand_StatUpFailText: ; 3644c ; statupfailtext ld a, [FailedMessage] and a ret z push af call BattleCommand_MoveDelay pop af dec a jp z, TryPrintButItFailed ld a, [LoweredStat] and $f ld b, a inc b call GetStatName ld hl, WontRiseAnymoreText jp StdBattleTextBox ; 3646a BattleCommand_StatDownFailText: ; 3646a ; statdownfailtext ld a, [FailedMessage] and a ret z push af call BattleCommand_MoveDelay pop af dec a jp z, TryPrintButItFailed dec a ld hl, ProtectedByMistText jp z, StdBattleTextBox ld a, [LoweredStat] and $f ld b, a inc b call GetStatName ld hl, WontDropAnymoreText jp StdBattleTextBox ; 3648f GetStatName: ; 3648f ld hl, .names ld c, "@" .CheckName: dec b jr z, .Copy .GetName: ld a, [hli] cp c jr z, .CheckName jr .GetName .Copy: ld de, StringBuffer2 ld bc, StringBuffer3 - StringBuffer2 jp CopyBytes .names db "ATTACK@" db "DEFENSE@" db "SPEED@" db "SPCL.ATK@" db "SPCL.DEF@" db "ACCURACY@" db "EVASION@" db "ABILITY@" ; 364e6 StatLevelMultipliers: ; 364e6 db 25, 100 ; 0.25x db 28, 100 ; 0.28x db 33, 100 ; 0.33x db 40, 100 ; 0.40x db 50, 100 ; 0.50x db 66, 100 ; 0.66x db 1, 1 ; 1.00x db 15, 10 ; 1.50x db 2, 1 ; 2.00x db 25, 10 ; 2.50x db 3, 1 ; 3.00x db 35, 10 ; 3.50x db 4, 1 ; 4.00x ; 36500 BattleCommand_AllStatsUp: ; 36500 ; allstatsup ; Attack call ResetMiss call BattleCommand_AttackUp call BattleCommand_StatUpMessage ; Defense call ResetMiss call BattleCommand_DefenseUp call BattleCommand_StatUpMessage ; Speed call ResetMiss call BattleCommand_SpeedUp call BattleCommand_StatUpMessage ; Special Attack call ResetMiss call BattleCommand_SpecialAttackUp call BattleCommand_StatUpMessage ; Special Defense call ResetMiss call BattleCommand_SpecialDefenseUp jp BattleCommand_StatUpMessage ; 3652d ResetMiss: ; 3652d xor a ld [AttackMissed], a ret ; 36532 LowerStat: ; 36532 ld [LoweredStat], a ld hl, PlayerStatLevels ld a, [hBattleTurn] and a jr z, .got_target ld hl, EnemyStatLevels .got_target ld a, [LoweredStat] and $f ld c, a ld b, 0 add hl, bc ld b, [hl] dec b jr z, .cant_lower_anymore ld a, [LoweredStat] and $f0 jr z, .got_num_stages dec b jr nz, .got_num_stages inc b .got_num_stages ld [hl], b ld a, c cp 5 jr nc, .accuracy_evasion push hl ld hl, BattleMonStats + 1 ld de, PlayerStats ld a, [hBattleTurn] and a jr z, .got_target_2 ld hl, EnemyMonStats + 1 ld de, EnemyStats .got_target_2 call TryLowerStat pop hl jr z, .failed .accuracy_evasion ld a, [hBattleTurn] and a jr z, .player call CalcEnemyStats jr .finish .player call CalcPlayerStats .finish xor a ld [FailedMessage], a ret .failed inc [hl] .cant_lower_anymore ld a, 2 ld [FailedMessage], a ret ; 3658f BattleCommand_TriStatusChance: ; 3658f ; tristatuschance call BattleCommand_EffectChance ; 1/3 chance of each status .loop call BattleRandom swap a and 3 jr z, .loop ; jump dec a ld hl, .ptrs rst JumpTable ret .ptrs dw BattleCommand_ParalyzeTarget ; paralyze dw BattleCommand_FreezeTarget ; freeze dw BattleCommand_BurnTarget ; burn ; 365a7 BattleCommand_Curl: ; 365a7 ; curl ld a, BATTLE_VARS_SUBSTATUS2 call GetBattleVarAddr set SUBSTATUS_CURLED, [hl] ret ; 365af BattleCommand_RaiseSubNoAnim: ; 365af ld hl, GetBattleMonBackpic ld a, [hBattleTurn] and a jr z, .PlayerTurn ld hl, GetEnemyMonFrontpic .PlayerTurn: xor a ld [hBGMapMode], a call CallBattleCore jp WaitBGMap ; 365c3 BattleCommand_LowerSubNoAnim: ; 365c3 ld hl, DropPlayerSub ld a, [hBattleTurn] and a jr z, .PlayerTurn ld hl, DropEnemySub .PlayerTurn: xor a ld [hBGMapMode], a call CallBattleCore jp WaitBGMap ; 365d7 CalcPlayerStats: ; 365d7 ld hl, PlayerAtkLevel ld de, PlayerStats ld bc, BattleMonAttack ld a, 5 call CalcStats ld hl, BadgeStatBoosts call CallBattleCore call BattleCommand_SwitchTurn ld hl, ApplyPrzEffectOnSpeed call CallBattleCore ld hl, ApplyBrnEffectOnAttack call CallBattleCore jp BattleCommand_SwitchTurn ; 365fd CalcEnemyStats: ; 365fd ld hl, EnemyAtkLevel ld de, EnemyStats ld bc, EnemyMonAttack ld a, 5 call CalcStats call BattleCommand_SwitchTurn ld hl, ApplyPrzEffectOnSpeed call CallBattleCore ld hl, ApplyBrnEffectOnAttack call CallBattleCore jp BattleCommand_SwitchTurn ; 3661d CalcStats: ; 3661d .loop push af ld a, [hli] push hl push bc ld c, a dec c ld b, 0 ld hl, StatLevelMultipliers add hl, bc add hl, bc xor a ld [hMultiplicand + 0], a ld a, [de] ld [hMultiplicand + 1], a inc de ld a, [de] ld [hMultiplicand + 2], a inc de ld a, [hli] ld [hMultiplier], a call Multiply ld a, [hl] ld [hDivisor], a ld b, 4 call Divide ld a, [hQuotient + 1] ld b, a ld a, [hQuotient + 2] or b jr nz, .check_maxed_out ld a, 1 ld [hQuotient + 2], a jr .not_maxed_out .check_maxed_out ld a, [hQuotient + 2] cp LOW(MAX_STAT_VALUE) ld a, b sbc HIGH(MAX_STAT_VALUE) jr c, .not_maxed_out ld a, LOW(MAX_STAT_VALUE) ld [hQuotient + 2], a ld a, HIGH(MAX_STAT_VALUE) ld [hQuotient + 1], a .not_maxed_out pop bc ld a, [hQuotient + 1] ld [bc], a inc bc ld a, [hQuotient + 2] ld [bc], a inc bc pop hl pop af dec a jr nz, .loop ret ; 36671 BattleCommand_StoreEnergy: ; 36671 ; storeenergy ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar bit SUBSTATUS_BIDE, a ret z ld hl, PlayerRolloutCount ld a, [hBattleTurn] and a jr z, .check_still_storing_energy ld hl, EnemyRolloutCount .check_still_storing_energy dec [hl] jr nz, .still_storing ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr res SUBSTATUS_BIDE, [hl] ld hl, UnleashedEnergyText call StdBattleTextBox ld a, BATTLE_VARS_MOVE_POWER call GetBattleVarAddr ld a, 1 ld [hl], a ld hl, PlayerDamageTaken + 1 ld de, wPlayerCharging ; player ld a, [hBattleTurn] and a jr z, .player ld hl, EnemyDamageTaken + 1 ld de, wEnemyCharging ; enemy .player ld a, [hld] add a ld b, a ld [CurDamage + 1], a ld a, [hl] rl a ld [CurDamage], a jr nc, .not_maxed ld a, $ff ld [CurDamage], a ld [CurDamage + 1], a .not_maxed or b jr nz, .built_up_something ld a, 1 ld [AttackMissed], a .built_up_something xor a ld [hli], a ld [hl], a ld [de], a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVarAddr ld a, BIDE ld [hl], a ld b, unleashenergy_command jp SkipToBattleCommand .still_storing ld hl, StoringEnergyText call StdBattleTextBox jp EndMoveEffect ; 366e5 BattleCommand_UnleashEnergy: ; 366e5 ; unleashenergy ld de, PlayerDamageTaken ld bc, PlayerRolloutCount ld a, [hBattleTurn] and a jr z, .got_damage ld de, EnemyDamageTaken ld bc, EnemyRolloutCount .got_damage ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr set SUBSTATUS_BIDE, [hl] xor a ld [de], a inc de ld [de], a ld [wPlayerMoveStructEffect], a ld [wEnemyMoveStructEffect], a call BattleRandom and 1 inc a inc a ld [bc], a ld a, 1 ld [wKickCounter], a call AnimateCurrentMove jp EndMoveEffect ; 3671a BattleCommand_CheckRampage: ; 3671a ; checkrampage ld de, PlayerRolloutCount ld a, [hBattleTurn] and a jr z, .player ld de, EnemyRolloutCount .player ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr bit SUBSTATUS_RAMPAGE, [hl] ret z ld a, [de] dec a ld [de], a jr nz, .continue_rampage res SUBSTATUS_RAMPAGE, [hl] call BattleCommand_SwitchTurn call SafeCheckSafeguard push af call BattleCommand_SwitchTurn pop af jr nz, .continue_rampage set SUBSTATUS_CONFUSED, [hl] call BattleRandom and %00000001 inc a inc a inc de ; ConfuseCount ld [de], a .continue_rampage ld b, rampage_command jp SkipToBattleCommand ; 36751 BattleCommand_Rampage: ; 36751 ; rampage ; No rampage during Sleep Talk. ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP ret nz ld de, PlayerRolloutCount ld a, [hBattleTurn] and a jr z, .ok ld de, EnemyRolloutCount .ok ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr set SUBSTATUS_RAMPAGE, [hl] ; Rampage for 1 or 2 more turns call BattleRandom and %00000001 inc a ld [de], a ld a, 1 ld [wSomeoneIsRampaging], a ret ; 36778 BattleCommand_Teleport: ; 36778 ; teleport ld a, [BattleType] cp BATTLETYPE_SHINY jr z, .failed cp BATTLETYPE_TRAP jr z, .failed cp BATTLETYPE_CELEBI jr z, .failed cp BATTLETYPE_SUICUNE jr z, .failed ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVar bit SUBSTATUS_CANT_RUN, a jr nz, .failed ; Only need to check these next things if it's your turn ld a, [hBattleTurn] and a jr nz, .enemy_turn ; Can't teleport from a trainer battle ld a, [wBattleMode] dec a jr nz, .failed ; If your level is greater than the opponent's, you run without fail. ld a, [CurPartyLevel] ld b, a ld a, [BattleMonLevel] cp b jr nc, .run_away ; Generate a number between 0 and (YourLevel + TheirLevel). add b ld c, a inc c .loop_player call BattleRandom cp c jr nc, .loop_player ; If that number is greater than 4 times your level, run away. srl b srl b cp b jr nc, .run_away .failed call AnimateFailedMove jp PrintButItFailed .enemy_turn ld a, [wBattleMode] dec a jr nz, .failed ld a, [BattleMonLevel] ld b, a ld a, [CurPartyLevel] cp b jr nc, .run_away add b ld c, a inc c .loop_enemy call BattleRandom cp c jr nc, .loop_enemy srl b srl b cp b ; This does the wrong thing. What was ; probably intended was jr c, .failed ; The way this is made makes enemy use ; of Teleport always succeed if able jr nc, .run_away .run_away call UpdateBattleMonInParty xor a ld [wNumHits], a inc a ld [wForcedSwitch], a ld [wKickCounter], a call SetBattleDraw call BattleCommand_LowerSub call LoadMoveAnim ld c, 20 call DelayFrames call SetBattleDraw ld hl, FledFromBattleText jp StdBattleTextBox ; 36804 SetBattleDraw: ; 36804 ld a, [wBattleResult] and $c0 or $2 ld [wBattleResult], a ret ; 3680f BattleCommand_ForceSwitch: ; 3680f ; forceswitch ld a, [BattleType] cp BATTLETYPE_SHINY jp z, .fail cp BATTLETYPE_TRAP jp z, .fail cp BATTLETYPE_CELEBI jp z, .fail cp BATTLETYPE_SUICUNE jp z, .fail ld a, [hBattleTurn] and a jp nz, .force_player_switch ld a, [AttackMissed] and a jr nz, .missed ld a, [wBattleMode] dec a jr nz, .trainer ld a, [CurPartyLevel] ld b, a ld a, [BattleMonLevel] cp b jr nc, .wild_force_flee add b ld c, a inc c .random_loop_wild call BattleRandom cp c jr nc, .random_loop_wild srl b srl b cp b jr nc, .wild_force_flee .missed jp .fail .wild_force_flee call UpdateBattleMonInParty xor a ld [wNumHits], a inc a ld [wForcedSwitch], a call SetBattleDraw ld a, [wPlayerMoveStructAnimation] jp .succeed .trainer call FindAliveEnemyMons jr c, .switch_fail ld a, [wEnemyGoesFirst] and a jr z, .switch_fail call UpdateEnemyMonInParty ld a, $1 ld [wKickCounter], a call AnimateCurrentMove ld c, $14 call DelayFrames hlcoord 1, 0 lb bc, 4, 10 call ClearBox ld c, 20 call DelayFrames ld a, [OTPartyCount] ld b, a ld a, [CurOTMon] ld c, a ; select a random enemy mon to switch to .random_loop_trainer call BattleRandom and $7 cp b jr nc, .random_loop_trainer cp c jr z, .random_loop_trainer push af push bc ld hl, OTPartyMon1HP call GetPartyLocation ld a, [hli] or [hl] pop bc pop de jr z, .random_loop_trainer ld a, d inc a ld [wEnemySwitchMonIndex], a callfar ForceEnemySwitch ld hl, DraggedOutText call StdBattleTextBox ld hl, SpikesDamage jp CallBattleCore .switch_fail jp .fail .force_player_switch ld a, [AttackMissed] and a jr nz, .player_miss ld a, [wBattleMode] dec a jr nz, .vs_trainer ld a, [BattleMonLevel] ld b, a ld a, [CurPartyLevel] cp b jr nc, .wild_succeed_playeristarget add b ld c, a inc c .wild_random_loop_playeristarget call BattleRandom cp c jr nc, .wild_random_loop_playeristarget srl b srl b cp b jr nc, .wild_succeed_playeristarget .player_miss jr .fail .wild_succeed_playeristarget call UpdateBattleMonInParty xor a ld [wNumHits], a inc a ld [wForcedSwitch], a call SetBattleDraw ld a, [wEnemyMoveStructAnimation] jr .succeed .vs_trainer call CheckPlayerHasMonToSwitchTo jr c, .fail ld a, [wEnemyGoesFirst] cp $1 jr z, .switch_fail call UpdateBattleMonInParty ld a, $1 ld [wKickCounter], a call AnimateCurrentMove ld c, 20 call DelayFrames hlcoord 9, 7 lb bc, 5, 11 call ClearBox ld c, 20 call DelayFrames ld a, [PartyCount] ld b, a ld a, [CurBattleMon] ld c, a .random_loop_trainer_playeristarget call BattleRandom and $7 cp b jr nc, .random_loop_trainer_playeristarget cp c jr z, .random_loop_trainer_playeristarget push af push bc ld hl, PartyMon1HP call GetPartyLocation ld a, [hli] or [hl] pop bc pop de jr z, .random_loop_trainer_playeristarget ld a, d ld [CurPartyMon], a ld hl, SwitchPlayerMon call CallBattleCore ld hl, DraggedOutText call StdBattleTextBox ld hl, SpikesDamage jp CallBattleCore .fail call BattleCommand_LowerSub call BattleCommand_MoveDelay call BattleCommand_RaiseSub jp PrintButItFailed .succeed push af call SetBattleDraw ld a, $1 ld [wKickCounter], a call AnimateCurrentMove ld c, 20 call DelayFrames pop af ld hl, FledInFearText cp ROAR jr z, .do_text ld hl, BlownAwayText .do_text jp StdBattleTextBox ; 36994 CheckPlayerHasMonToSwitchTo: ; 36994 ld a, [PartyCount] ld d, a ld e, 0 ld bc, PARTYMON_STRUCT_LENGTH .loop ld a, [CurBattleMon] cp e jr z, .next ld a, e ld hl, PartyMon1HP call AddNTimes ld a, [hli] or [hl] jr nz, .not_fainted .next inc e dec d jr nz, .loop scf ret .not_fainted and a ret ; 369b6 BattleCommand_EndLoop: ; 369b6 ; endloop ; Loop back to the command before 'critical'. ld de, PlayerRolloutCount ld bc, PlayerDamageTaken ld a, [hBattleTurn] and a jr z, .got_addrs ld de, EnemyRolloutCount ld bc, EnemyDamageTaken .got_addrs ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr bit SUBSTATUS_IN_LOOP, [hl] jp nz, .in_loop set SUBSTATUS_IN_LOOP, [hl] ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVarAddr ld a, [hl] cp EFFECT_POISON_MULTI_HIT jr z, .twineedle cp EFFECT_DOUBLE_HIT ld a, 1 jr z, .double_hit ld a, [hl] cp EFFECT_BEAT_UP jr z, .beat_up cp EFFECT_TRIPLE_KICK jr nz, .not_triple_kick .reject_triple_kick_sample call BattleRandom and $3 jr z, .reject_triple_kick_sample dec a jr nz, .double_hit ld a, 1 ld [bc], a jr .done_loop .beat_up ld a, [hBattleTurn] and a jr nz, .check_ot_beat_up ld a, [PartyCount] cp 1 jp z, .only_one_beatup dec a jr .double_hit .check_ot_beat_up ld a, [wBattleMode] cp WILD_BATTLE jp z, .only_one_beatup ld a, [OTPartyCount] cp 1 jp z, .only_one_beatup dec a jr .double_hit .only_one_beatup ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr res SUBSTATUS_IN_LOOP, [hl] call BattleCommanda8 jp EndMoveEffect .not_triple_kick call BattleRandom and $3 cp 2 jr c, .got_number_hits call BattleRandom and $3 .got_number_hits inc a .double_hit ld [de], a inc a ld [bc], a jr .loop_back_to_critical .twineedle ld a, 1 jr .double_hit .in_loop ld a, [de] dec a ld [de], a jr nz, .loop_back_to_critical .done_loop ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr res SUBSTATUS_IN_LOOP, [hl] ld hl, PlayerHitTimesText ld a, [hBattleTurn] and a jr z, .got_hit_n_times_text ld hl, EnemyHitTimesText .got_hit_n_times_text push bc ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_BEAT_UP jr z, .beat_up_2 call StdBattleTextBox .beat_up_2 pop bc xor a ld [bc], a ret ; Loop back to the command before 'critical'. .loop_back_to_critical ld a, [BattleScriptBufferAddress + 1] ld h, a ld a, [BattleScriptBufferAddress] ld l, a .not_critical ld a, [hld] cp critical_command jr nz, .not_critical inc hl ld a, h ld [BattleScriptBufferAddress + 1], a ld a, l ld [BattleScriptBufferAddress], a ret ; 36a82 BattleCommand_FakeOut: ; 36a82 ld a, [AttackMissed] and a ret nz call CheckSubstituteOpp jr nz, .fail ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar and 1 << FRZ | SLP jr nz, .fail call CheckOpponentWentFirst jr z, FlinchTarget .fail ld a, 1 ld [AttackMissed], a ret ; 36aa0 BattleCommand_FlinchTarget: ; 36aa0 call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar and 1 << FRZ | SLP ret nz call CheckOpponentWentFirst ret nz ld a, [EffectFailed] and a ret nz ; fallthrough ; 36ab5 FlinchTarget: ; 36ab5 ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr set SUBSTATUS_FLINCHED, [hl] jp EndRechargeOpp ; 36abf CheckOpponentWentFirst: ; 36abf ; Returns a=0, z if user went first ; Returns a=1, nz if opponent went first push bc ld a, [wEnemyGoesFirst] ; 0 if player went first ld b, a ld a, [hBattleTurn] ; 0 if it's the player's turn xor b ; 1 if opponent went first pop bc ret ; 36ac9 BattleCommand_HeldFlinch: ; 36ac9 ; kingsrock ld a, [AttackMissed] and a ret nz call GetUserItem ld a, b cp HELD_FLINCH ret nz call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVarAddr ld d, h ld e, l call GetUserItem call BattleRandom cp c ret nc call EndRechargeOpp ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr set SUBSTATUS_FLINCHED, [hl] ret ; 36af3 BattleCommand_OHKO: ; 36af3 ; ohko call ResetDamage ld a, [TypeModifier] and $7f jr z, .no_effect ld hl, EnemyMonLevel ld de, BattleMonLevel ld bc, wPlayerMoveStruct + MOVE_ACC ld a, [hBattleTurn] and a jr z, .got_move_accuracy push hl ld h, d ld l, e pop de ld bc, wEnemyMoveStruct + MOVE_ACC .got_move_accuracy ld a, [de] sub [hl] jr c, .no_effect add a ld e, a ld a, [bc] add e jr nc, .finish_ohko ld a, $ff .finish_ohko ld [bc], a call BattleCommand_CheckHit ld hl, CurDamage ld a, $ff ld [hli], a ld [hl], a ld a, $2 ld [CriticalHit], a ret .no_effect ld a, $ff ld [CriticalHit], a ld a, $1 ld [AttackMissed], a ret ; 36b3a BattleCommand_CheckCharge: ; 36b3a ; checkcharge ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr bit SUBSTATUS_CHARGED, [hl] ret z res SUBSTATUS_CHARGED, [hl] res SUBSTATUS_UNDERGROUND, [hl] res SUBSTATUS_FLYING, [hl] ld b, charge_command jp SkipToBattleCommand ; 36b4d BattleCommand_Charge: ; 36b4d ; charge call BattleCommand_ClearText ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP jr z, .awake call BattleCommand_MoveDelay call BattleCommand_RaiseSub call PrintButItFailed jp EndMoveEffect .awake ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr set SUBSTATUS_CHARGED, [hl] ld hl, IgnoredOrders2Text ld a, [AlreadyDisobeyed] and a call nz, StdBattleTextBox call BattleCommand_LowerSub xor a ld [wNumHits], a inc a ld [wKickCounter], a call LoadMoveAnim ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp FLY jr z, .flying cp DIG jr z, .flying call BattleCommand_RaiseSub jr .not_flying .flying call DisappearUser .not_flying ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld b, a cp FLY jr z, .set_flying cp DIG jr nz, .dont_set_digging set SUBSTATUS_UNDERGROUND, [hl] jr .dont_set_digging .set_flying set SUBSTATUS_FLYING, [hl] .dont_set_digging call CheckUserIsCharging jr nz, .mimic ld a, BATTLE_VARS_LAST_COUNTER_MOVE call GetBattleVarAddr ld [hl], b ld a, BATTLE_VARS_LAST_MOVE call GetBattleVarAddr ld [hl], b .mimic call ResetDamage ld hl, .UsedText call BattleTextBox ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_SKULL_BASH ld b, endturn_command jp z, SkipToBattleCommand jp EndMoveEffect .UsedText: text_jump UnknownText_0x1c0d0e ; "[USER]" start_asm ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar cp RAZOR_WIND ld hl, .RazorWind jr z, .done cp SOLARBEAM ld hl, .Solarbeam jr z, .done cp SKULL_BASH ld hl, .SkullBash jr z, .done cp SKY_ATTACK ld hl, .SkyAttack jr z, .done cp FLY ld hl, .Fly jr z, .done cp DIG ld hl, .Dig .done ret .RazorWind: ; 'made a whirlwind!' text_jump UnknownText_0x1c0d12 db "@" .Solarbeam: ; 'took in sunlight!' text_jump UnknownText_0x1c0d26 db "@" .SkullBash: ; 'lowered its head!' text_jump UnknownText_0x1c0d3a db "@" .SkyAttack: ; 'is glowing!' text_jump UnknownText_0x1c0d4e db "@" .Fly: ; 'flew up high!' text_jump UnknownText_0x1c0d5c db "@" .Dig: ; 'dug a hole!' text_jump UnknownText_0x1c0d6c db "@" ; 36c2c BattleCommand3c: ; 36c2c ; unused ret ; 36c2d BattleCommand_TrapTarget: ; 36c2d ; traptarget ld a, [AttackMissed] and a ret nz ld hl, wEnemyWrapCount ld de, wEnemyTrappingMove ld a, [hBattleTurn] and a jr z, .got_trap ld hl, wPlayerWrapCount ld de, wPlayerTrappingMove .got_trap ld a, [hl] and a ret nz ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret nz call BattleRandom and 3 inc a inc a inc a ld [hl], a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld [de], a ld b, a ld hl, .Traps .find_trap_text ld a, [hli] cp b jr z, .found_trap_text inc hl inc hl jr .find_trap_text .found_trap_text ld a, [hli] ld h, [hl] ld l, a jp StdBattleTextBox .Traps: dbw BIND, UsedBindText ; 'used BIND on' dbw WRAP, WrappedByText ; 'was WRAPPED by' dbw FIRE_SPIN, FireSpinTrapText ; 'was trapped!' dbw CLAMP, ClampedByText ; 'was CLAMPED by' dbw WHIRLPOOL, WhirlpoolTrapText ; 'was trapped!' ; 36c7e BattleCommand_Mist: ; 36c7e ; mist ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr bit SUBSTATUS_MIST, [hl] jr nz, .already_mist set SUBSTATUS_MIST, [hl] call AnimateCurrentMove ld hl, MistText jp StdBattleTextBox .already_mist call AnimateFailedMove jp PrintButItFailed ; 36c98 BattleCommand_FocusEnergy: ; 36c98 ; focusenergy ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr bit SUBSTATUS_FOCUS_ENERGY, [hl] jr nz, .already_pumped set SUBSTATUS_FOCUS_ENERGY, [hl] call AnimateCurrentMove ld hl, GettingPumpedText jp StdBattleTextBox .already_pumped call AnimateFailedMove jp PrintButItFailed ; 36cb2 BattleCommand_Recoil: ; 36cb2 ; recoil ld hl, BattleMonMaxHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, EnemyMonMaxHP .got_hp ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld d, a ; get 1/4 damage or 1 HP, whichever is higher ld a, [CurDamage] ld b, a ld a, [CurDamage + 1] ld c, a srl b rr c srl b rr c ld a, b or c jr nz, .min_damage inc c .min_damage ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a dec hl dec hl ld a, [hl] ld [Buffer3], a sub c ld [hld], a ld [Buffer5], a ld a, [hl] ld [Buffer4], a sbc b ld [hl], a ld [Buffer6], a jr nc, .dont_ko xor a ld [hli], a ld [hl], a ld hl, Buffer5 ld [hli], a ld [hl], a .dont_ko hlcoord 10, 9 ld a, [hBattleTurn] and a ld a, 1 jr z, .animate_hp_bar hlcoord 2, 2 xor a .animate_hp_bar ld [wWhichHPBar], a predef AnimateHPBar call RefreshBattleHuds ld hl, RecoilText jp StdBattleTextBox ; 36d1d BattleCommand_ConfuseTarget: ; 36d1d ; confusetarget call GetOpponentItem ld a, b cp HELD_PREVENT_CONFUSE ret z ld a, [EffectFailed] and a ret nz call SafeCheckSafeguard ret nz call CheckSubstituteOpp ret nz ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr bit SUBSTATUS_CONFUSED, [hl] ret nz jr BattleCommand_FinishConfusingTarget BattleCommand_Confuse: ; 36d3b ; confuse call GetOpponentItem ld a, b cp HELD_PREVENT_CONFUSE jr nz, .no_item_protection ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName call AnimateFailedMove ld hl, ProtectedByText jp StdBattleTextBox .no_item_protection ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr bit SUBSTATUS_CONFUSED, [hl] jr z, .not_already_confused call AnimateFailedMove ld hl, AlreadyConfusedText jp StdBattleTextBox .not_already_confused call CheckSubstituteOpp jr nz, BattleCommand_Confuse_CheckSnore_Swagger_ConfuseHit ld a, [AttackMissed] and a jr nz, BattleCommand_Confuse_CheckSnore_Swagger_ConfuseHit BattleCommand_FinishConfusingTarget: ; 36d70 ld bc, EnemyConfuseCount ld a, [hBattleTurn] and a jr z, .got_confuse_count ld bc, PlayerConfuseCount .got_confuse_count set SUBSTATUS_CONFUSED, [hl] call BattleRandom and 3 inc a inc a ld [bc], a ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_CONFUSE_HIT jr z, .got_effect cp EFFECT_SNORE jr z, .got_effect cp EFFECT_SWAGGER jr z, .got_effect call AnimateCurrentMove .got_effect ld de, ANIM_CONFUSED call PlayOpponentBattleAnim ld hl, BecameConfusedText call StdBattleTextBox call GetOpponentItem ld a, b cp HELD_HEAL_STATUS jr z, .heal_confusion cp HELD_HEAL_CONFUSION ret nz .heal_confusion ld hl, UseConfusionHealingItem jp CallBattleCore ; 36db6 BattleCommand_Confuse_CheckSnore_Swagger_ConfuseHit: ; 36db6 ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_CONFUSE_HIT ret z cp EFFECT_SNORE ret z cp EFFECT_SWAGGER ret z jp PrintDidntAffect2 ; 36dc7 BattleCommand_Paralyze: ; 36dc7 ; paralyze ld a, BATTLE_VARS_STATUS_OPP call GetBattleVar bit PAR, a jr nz, .paralyzed ld a, [TypeModifier] and $7f jr z, .didnt_affect call GetOpponentItem ld a, b cp HELD_PREVENT_PARALYZE jr nz, .no_item_protection ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName call AnimateFailedMove ld hl, ProtectedByText jp StdBattleTextBox .no_item_protection ld a, [hBattleTurn] and a jr z, .dont_sample_failure ld a, [wLinkMode] and a jr nz, .dont_sample_failure ld a, [InBattleTowerBattle] and a jr nz, .dont_sample_failure ld a, [PlayerSubStatus5] bit SUBSTATUS_LOCK_ON, a jr nz, .dont_sample_failure call BattleRandom cp 1 + 25 percent jr c, .failed .dont_sample_failure ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and a jr nz, .failed ld a, [AttackMissed] and a jr nz, .failed call CheckSubstituteOpp jr nz, .failed ld c, 30 call DelayFrames call AnimateCurrentMove ld a, $1 ld [hBGMapMode], a ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr set PAR, [hl] call UpdateOpponentInParty ld hl, ApplyPrzEffectOnSpeed call CallBattleCore call UpdateBattleHuds call PrintParalyze ld hl, UseHeldStatusHealingItem jp CallBattleCore .paralyzed call AnimateFailedMove ld hl, AlreadyParalyzedText jp StdBattleTextBox .failed jp PrintDidntAffect2 .didnt_affect call AnimateFailedMove jp PrintDoesntAffect ; 36e5b CheckMoveTypeMatchesTarget: ; 36e5b ; Compare move type to opponent type. ; Return z if matching the opponent type, ; unless the move is Normal (Tri Attack). push hl ld hl, EnemyMonType1 ld a, [hBattleTurn] and a jr z, .ok ld hl, BattleMonType1 .ok ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVar cp NORMAL jr z, .normal cp [hl] jr z, .return inc hl cp [hl] .return pop hl ret .normal ld a, 1 and a pop hl ret ; 36e7c BattleCommand_Substitute: ; 36e7c ; substitute call BattleCommand_MoveDelay ld hl, BattleMonMaxHP ld de, PlayerSubstituteHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, EnemyMonMaxHP ld de, EnemySubstituteHP .got_hp ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a jr nz, .already_has_sub ld a, [hli] ld b, [hl] srl a rr b srl a rr b dec hl dec hl ld a, b ld [de], a ld a, [hld] sub b ld e, a ld a, [hl] sbc 0 ld d, a jr c, .too_weak_to_sub ld a, d or e jr z, .too_weak_to_sub ld [hl], d inc hl ld [hl], e ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr set SUBSTATUS_SUBSTITUTE, [hl] ld hl, wPlayerWrapCount ld de, wPlayerTrappingMove ld a, [hBattleTurn] and a jr z, .player ld hl, wEnemyWrapCount ld de, wEnemyTrappingMove .player xor a ld [hl], a ld [de], a call _CheckBattleScene jr c, .no_anim xor a ld [wNumHits], a ld [FXAnimID + 1], a ld [wKickCounter], a ld a, SUBSTITUTE call LoadAnim jr .finish .no_anim call BattleCommand_RaiseSubNoAnim .finish ld hl, MadeSubstituteText call StdBattleTextBox jp RefreshBattleHuds .already_has_sub call CheckUserIsCharging call nz, BattleCommand_RaiseSub ld hl, HasSubstituteText jr .jp_stdbattletextbox .too_weak_to_sub call CheckUserIsCharging call nz, BattleCommand_RaiseSub ld hl, TooWeakSubText .jp_stdbattletextbox jp StdBattleTextBox ; 36f0b BattleCommand_RechargeNextTurn: ; 36f0b ; rechargenextturn ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr set SUBSTATUS_RECHARGE, [hl] ret ; 36f13 EndRechargeOpp: ; 36f13 push hl ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVarAddr res SUBSTATUS_RECHARGE, [hl] pop hl ret ; 36f1d BattleCommand_Rage: ; 36f1d ; rage ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr set SUBSTATUS_RAGE, [hl] ret ; 36f25 BattleCommand_DoubleFlyingDamage: ; 36f25 ; doubleflyingdamage ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar bit SUBSTATUS_FLYING, a ret z jr DoubleDamage ; 36f2f BattleCommand_DoubleUndergroundDamage: ; 36f2f ; doubleundergrounddamage ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar bit SUBSTATUS_UNDERGROUND, a ret z ; fallthrough ; 36f37 DoubleDamage: ; 36f37 ld hl, CurDamage + 1 sla [hl] dec hl rl [hl] jr nc, .quit ld a, $ff ld [hli], a ld [hl], a .quit ret ; 36f46 BattleCommand_Mimic: ; 36f46 ; mimic call ClearLastMove call BattleCommand_MoveDelay ld a, [AttackMissed] and a jr nz, .fail ld hl, BattleMonMoves ld a, [hBattleTurn] and a jr z, .player_turn ld hl, EnemyMonMoves .player_turn call CheckHiddenOpponent jr nz, .fail ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a jr z, .fail cp STRUGGLE jr z, .fail ld b, a ld c, NUM_MOVES .check_already_knows_move ld a, [hli] cp b jr z, .fail dec c jr nz, .check_already_knows_move dec hl .find_mimic ld a, [hld] cp MIMIC jr nz, .find_mimic inc hl ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar ld [hl], a ld [wNamedObjectIndexBuffer], a ld bc, BattleMonPP - BattleMonMoves add hl, bc ld [hl], 5 call GetMoveName call AnimateCurrentMove ld hl, LearnedMoveText jp StdBattleTextBox .fail jp FailMimic ; 36f9d BattleCommand_LeechSeed: ; 36f9d ; leechseed ld a, [AttackMissed] and a jr nz, .evaded call CheckSubstituteOpp jr nz, .evaded ld de, EnemyMonType1 ld a, [hBattleTurn] and a jr z, .ok ld de, BattleMonType1 .ok ld a, [de] cp GRASS jr z, .grass inc de ld a, [de] cp GRASS jr z, .grass ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVarAddr bit SUBSTATUS_LEECH_SEED, [hl] jr nz, .evaded set SUBSTATUS_LEECH_SEED, [hl] call AnimateCurrentMove ld hl, WasSeededText jp StdBattleTextBox .grass call AnimateFailedMove jp PrintDoesntAffect .evaded call AnimateFailedMove ld hl, EvadedText jp StdBattleTextBox ; 36fe1 BattleCommand_Splash: ; 36fe1 call AnimateCurrentMove farcall TrainerRankings_Splash jp PrintNothingHappened ; 36fed BattleCommand_Disable: ; 36fed ; disable ld a, [AttackMissed] and a jr nz, .failed ld de, EnemyDisableCount ld hl, EnemyMonMoves ld a, [hBattleTurn] and a jr z, .got_moves ld de, PlayerDisableCount ld hl, BattleMonMoves .got_moves ld a, [de] and a jr nz, .failed ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a jr z, .failed cp STRUGGLE jr z, .failed ld b, a ld c, $ff .loop inc c ld a, [hli] cp b jr nz, .loop ld a, [hBattleTurn] and a ld hl, EnemyMonPP jr z, .got_pp ld hl, BattleMonPP .got_pp ld b, 0 add hl, bc ld a, [hl] and a jr z, .failed .loop2 call BattleRandom and 7 jr z, .loop2 inc a inc c swap c add c ld [de], a call AnimateCurrentMove ld hl, DisabledMove ld a, [hBattleTurn] and a jr nz, .got_disabled_move_pointer inc hl .got_disabled_move_pointer ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar ld [hl], a ld [wNamedObjectIndexBuffer], a call GetMoveName ld hl, WasDisabledText jp StdBattleTextBox .failed jp FailDisable ; 3705c BattleCommand_PayDay: ; 3705c ; payday xor a ld hl, StringBuffer1 ld [hli], a ld a, [hBattleTurn] and a ld a, [BattleMonLevel] jr z, .ok ld a, [EnemyMonLevel] .ok add a ld hl, wPayDayMoney + 2 add [hl] ld [hld], a jr nc, .done inc [hl] dec hl jr nz, .done inc [hl] .done ld hl, CoinsScatteredText jp StdBattleTextBox ; 3707f BattleCommand_Conversion: ; 3707f ; conversion ld hl, BattleMonMoves ld de, BattleMonType1 ld a, [hBattleTurn] and a jr z, .got_moves ld hl, EnemyMonMoves ld de, EnemyMonType1 .got_moves push de ld c, 0 ld de, StringBuffer1 .loop push hl ld b, 0 add hl, bc ld a, [hl] pop hl and a jr z, .okay push hl push bc dec a ld hl, Moves + MOVE_TYPE call GetMoveAttr ld [de], a inc de pop bc pop hl inc c ld a, c cp NUM_MOVES jr c, .loop .okay ld a, $ff ld [de], a inc de ld [de], a inc de ld [de], a pop de ld hl, StringBuffer1 .loop2 ld a, [hl] cp -1 jr z, .fail cp CURSE_T jr z, .next ld a, [de] cp [hl] jr z, .next inc de ld a, [de] dec de cp [hl] jr nz, .done .next inc hl jr .loop2 .fail call AnimateFailedMove jp PrintButItFailed .done .loop3 call BattleRandom and 3 ; TODO factor in NUM_MOVES ld c, a ld b, 0 ld hl, StringBuffer1 add hl, bc ld a, [hl] cp -1 jr z, .loop3 cp CURSE_T jr z, .loop3 ld a, [de] cp [hl] jr z, .loop3 inc de ld a, [de] dec de cp [hl] jr z, .loop3 ld a, [hl] ld [de], a inc de ld [de], a ld [wNamedObjectIndexBuffer], a farcall GetTypeName call AnimateCurrentMove ld hl, TransformedTypeText jp StdBattleTextBox ; 3710e BattleCommand_ResetStats: ; 3710e ; resetstats ld a, 7 ; neutral ld hl, PlayerStatLevels call .Fill ld hl, EnemyStatLevels call .Fill ld a, [hBattleTurn] push af call SetPlayerTurn call CalcPlayerStats call SetEnemyTurn call CalcEnemyStats pop af ld [hBattleTurn], a call AnimateCurrentMove ld hl, EliminatedStatsText jp StdBattleTextBox .Fill: ld b, PlayerStatLevelsEnd - PlayerStatLevels .next ld [hli], a dec b jr nz, .next ret ; 3713e BattleCommand_Heal: ; 3713e ; heal ld de, BattleMonHP ld hl, BattleMonMaxHP ld a, [hBattleTurn] and a jr z, .got_hp ld de, EnemyMonHP ld hl, EnemyMonMaxHP .got_hp ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld b, a push hl push de push bc ld c, 2 call StringCmp pop bc pop de pop hl jp z, .hp_full ld a, b cp REST jr nz, .not_rest push hl push de push af call BattleCommand_MoveDelay ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVarAddr res SUBSTATUS_TOXIC, [hl] ld a, BATTLE_VARS_STATUS call GetBattleVarAddr ld a, [hl] and a ld [hl], REST_SLEEP_TURNS + 1 ld hl, WentToSleepText jr z, .no_status_to_heal ld hl, RestedText .no_status_to_heal call StdBattleTextBox ld a, [hBattleTurn] and a jr nz, .calc_enemy_stats call CalcPlayerStats jr .got_stats .calc_enemy_stats call CalcEnemyStats .got_stats pop af pop de pop hl .not_rest jr z, .restore_full_hp ld hl, GetHalfMaxHP call CallBattleCore jr .finish .restore_full_hp ld hl, GetMaxHP call CallBattleCore .finish call AnimateCurrentMove call BattleCommand_SwitchTurn ld hl, RestoreHP call CallBattleCore call BattleCommand_SwitchTurn call UpdateUserInParty call RefreshBattleHuds ld hl, RegainedHealthText jp StdBattleTextBox .hp_full call AnimateFailedMove ld hl, HPIsFullText jp StdBattleTextBox ; 371cd INCLUDE "engine/battle/effect_commands/transform.asm" BattleSideCopy: ; 372c6 ; Copy bc bytes from hl to de if it's the player's turn. ; Copy bc bytes from de to hl if it's the enemy's turn. ld a, [hBattleTurn] and a jr z, .copy ; Swap hl and de push hl ld h, d ld l, e pop de .copy jp CopyBytes ; 372d2 BattleEffect_ButItFailed: ; 372d2 call AnimateFailedMove jp PrintButItFailed ; 372d8 ClearLastMove: ; 372d8 ld a, BATTLE_VARS_LAST_COUNTER_MOVE call GetBattleVarAddr xor a ld [hl], a ld a, BATTLE_VARS_LAST_MOVE call GetBattleVarAddr xor a ld [hl], a ret ; 372e7 ResetActorDisable: ; 372e7 ld a, [hBattleTurn] and a jr z, .player xor a ld [EnemyDisableCount], a ld [EnemyDisabledMove], a ret .player xor a ld [PlayerDisableCount], a ld [DisabledMove], a ret ; 372fc BattleCommand_Screen: ; 372fc ; screen ld hl, PlayerScreens ld bc, PlayerLightScreenCount ld a, [hBattleTurn] and a jr z, .got_screens_pointer ld hl, EnemyScreens ld bc, EnemyLightScreenCount .got_screens_pointer ld a, BATTLE_VARS_MOVE_EFFECT call GetBattleVar cp EFFECT_LIGHT_SCREEN jr nz, .Reflect bit SCREENS_LIGHT_SCREEN, [hl] jr nz, .failed set SCREENS_LIGHT_SCREEN, [hl] ld a, 5 ld [bc], a ld hl, LightScreenEffectText jr .good .Reflect: bit SCREENS_REFLECT, [hl] jr nz, .failed set SCREENS_REFLECT, [hl] ; LightScreenCount -> ReflectCount inc bc ld a, 5 ld [bc], a ld hl, ReflectEffectText .good call AnimateCurrentMove jp StdBattleTextBox .failed call AnimateFailedMove jp PrintButItFailed ; 3733d PrintDoesntAffect: ; 3733d ; 'it doesn't affect' ld hl, DoesntAffectText jp StdBattleTextBox ; 37343 PrintNothingHappened: ; 37343 ; 'but nothing happened!' ld hl, NothingHappenedText jp StdBattleTextBox ; 37349 TryPrintButItFailed: ; 37349 ld a, [AlreadyFailed] and a ret nz ; fallthrough ; 3734e PrintButItFailed: ; 3734e ; 'but it failed!' ld hl, ButItFailedText jp StdBattleTextBox ; 37354 FailSnore: FailDisable: FailConversion2: FailAttract: FailForesight: FailSpikes: call AnimateFailedMove ; fallthrough ; 37357 FailMimic: ; 37357 ld hl, ButItFailedText ; 'but it failed!' ld de, ItFailedText ; 'it failed!' jp FailText_CheckOpponentProtect ; 37360 PrintDidntAffect: ; 37360 ; 'it didn't affect' ld hl, DidntAffect1Text jp StdBattleTextBox ; 37366 PrintDidntAffect2: ; 37366 call AnimateFailedMove ld hl, DidntAffect1Text ; 'it didn't affect' ld de, DidntAffect2Text ; 'it didn't affect' jp FailText_CheckOpponentProtect ; 37372 PrintParalyze: ; 37372 ; 'paralyzed! maybe it can't attack!' ld hl, ParalyzedText jp StdBattleTextBox ; 37378 CheckSubstituteOpp: ; 37378 ld a, BATTLE_VARS_SUBSTATUS4_OPP call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret ; 37380 BattleCommand_Selfdestruct: ; 37380 farcall TrainerRankings_Selfdestruct ld a, BATTLEANIM_PLAYER_DAMAGE ld [wNumHits], a ld c, 3 call DelayFrames ld a, BATTLE_VARS_STATUS call GetBattleVarAddr xor a ld [hli], a inc hl ld [hli], a ld [hl], a ld a, $1 ld [wKickCounter], a call BattleCommand_LowerSub call LoadMoveAnim ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr res SUBSTATUS_LEECH_SEED, [hl] ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr res SUBSTATUS_DESTINY_BOND, [hl] call _CheckBattleScene ret nc farcall DrawPlayerHUD farcall DrawEnemyHUD call WaitBGMap jp RefreshBattleHuds ; 373c9 INCLUDE "engine/battle/effect_commands/mirror_move.asm" INCLUDE "engine/battle/effect_commands/metronome.asm" CheckUserMove: ; 37462 ; Return z if the user has move a. ld b, a ld de, BattleMonMoves ld a, [hBattleTurn] and a jr z, .ok ld de, EnemyMonMoves .ok ld c, NUM_MOVES .loop ld a, [de] inc de cp b ret z dec c jr nz, .loop ld a, 1 and a ret ; 3747b ResetTurn: ; 3747b ld hl, wPlayerCharging ld a, [hBattleTurn] and a jr z, .player ld hl, wEnemyCharging .player ld [hl], 1 xor a ld [AlreadyDisobeyed], a call DoMove jp EndMoveEffect ; 37492 INCLUDE "engine/battle/effect_commands/thief.asm" BattleCommand_ArenaTrap: ; 37517 ; arenatrap ; Doesn't work on an absent opponent. call CheckHiddenOpponent jr nz, .failed ; Don't trap if the opponent is already trapped. ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVarAddr bit SUBSTATUS_CANT_RUN, [hl] jr nz, .failed ; Otherwise trap the opponent. set SUBSTATUS_CANT_RUN, [hl] call AnimateCurrentMove ld hl, CantEscapeNowText jp StdBattleTextBox .failed call AnimateFailedMove jp PrintButItFailed ; 37536 INCLUDE "engine/battle/effect_commands/nightmare.asm" BattleCommand_Defrost: ; 37563 ; defrost ; Thaw the user. ld a, BATTLE_VARS_STATUS call GetBattleVarAddr bit FRZ, [hl] ret z res FRZ, [hl] ; Don't update the enemy's party struct in a wild battle. ld a, [hBattleTurn] and a jr z, .party ld a, [wBattleMode] dec a jr z, .done .party ld a, MON_STATUS call UserPartyAttr res FRZ, [hl] .done call RefreshBattleHuds ld hl, WasDefrostedText jp StdBattleTextBox ; 37588 INCLUDE "engine/battle/effect_commands/curse.asm" INCLUDE "engine/battle/effect_commands/protect.asm" INCLUDE "engine/battle/effect_commands/endure.asm" INCLUDE "engine/battle/effect_commands/spikes.asm" INCLUDE "engine/battle/effect_commands/foresight.asm" INCLUDE "engine/battle/effect_commands/perish_song.asm" INCLUDE "engine/battle/effect_commands/sandstorm.asm" INCLUDE "engine/battle/effect_commands/rollout.asm" BattleCommand5d: ; 37791 ; unused ret ; 37792 BattleCommand_FuryCutter: ; 37792 ; furycutter ld hl, PlayerFuryCutterCount ld a, [hBattleTurn] and a jr z, .go ld hl, EnemyFuryCutterCount .go ld a, [AttackMissed] and a jp nz, ResetFuryCutterCount inc [hl] ; Damage capped at 5 turns' worth (16x). ld a, [hl] ld b, a cp 6 jr c, .checkdouble ld b, 5 .checkdouble dec b ret z ; Double the damage ld hl, CurDamage + 1 sla [hl] dec hl rl [hl] jr nc, .checkdouble ; No overflow ld a, $ff ld [hli], a ld [hl], a ret ; 377be ResetFuryCutterCount: ; 377be push hl ld hl, PlayerFuryCutterCount ld a, [hBattleTurn] and a jr z, .reset ld hl, EnemyFuryCutterCount .reset xor a ld [hl], a pop hl ret ; 377ce INCLUDE "engine/battle/effect_commands/attract.asm" BattleCommand_HappinessPower: ; 3784b ; happinesspower push bc ld hl, BattleMonHappiness ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonHappiness .ok xor a ld [hMultiplicand + 0], a ld [hMultiplicand + 1], a ld a, [hl] ld [hMultiplicand + 2], a ld a, 10 ld [hMultiplier], a call Multiply ld a, 25 ld [hDivisor], a ld b, 4 call Divide ld a, [hQuotient + 2] ld d, a pop bc ret ; 37874 INCLUDE "engine/battle/effect_commands/present.asm" BattleCommand_FrustrationPower: ; 3790e ; frustrationpower push bc ld hl, BattleMonHappiness ld a, [hBattleTurn] and a jr z, .got_happiness ld hl, EnemyMonHappiness .got_happiness ld a, $ff sub [hl] ld [hMultiplicand + 2], a xor a ld [hMultiplicand + 0], a ld [hMultiplicand + 1], a ld a, 10 ld [hMultiplier], a call Multiply ld a, 25 ld [hDivisor], a ld b, 4 call Divide ld a, [hQuotient + 2] ld d, a pop bc ret ; 37939 BattleCommand_Safeguard: ; 37939 ; safeguard ld hl, PlayerScreens ld de, PlayerSafeguardCount ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyScreens ld de, EnemySafeguardCount .ok bit SCREENS_SAFEGUARD, [hl] jr nz, .failed set SCREENS_SAFEGUARD, [hl] ld a, 5 ld [de], a call AnimateCurrentMove ld hl, CoveredByVeilText jp StdBattleTextBox .failed call AnimateFailedMove jp PrintButItFailed ; 37962 SafeCheckSafeguard: ; 37962 push hl ld hl, EnemyScreens ld a, [hBattleTurn] and a jr z, .got_turn ld hl, PlayerScreens .got_turn bit SCREENS_SAFEGUARD, [hl] pop hl ret ; 37972 BattleCommand_CheckSafeguard: ; 37972 ; checksafeguard ld hl, EnemyScreens ld a, [hBattleTurn] and a jr z, .got_turn ld hl, PlayerScreens .got_turn bit SCREENS_SAFEGUARD, [hl] ret z ld a, 1 ld [AttackMissed], a call BattleCommand_MoveDelay ld hl, SafeguardProtectText call StdBattleTextBox jp EndMoveEffect ; 37991 BattleCommand_GetMagnitude: ; 37991 ; getmagnitude push bc call BattleRandom ld b, a ld hl, .Magnitudes .loop ld a, [hli] cp b jr nc, .ok inc hl inc hl jr .loop .ok ld d, [hl] push de inc hl ld a, [hl] ld [wTypeMatchup], a call BattleCommand_MoveDelay ld hl, MagnitudeText call StdBattleTextBox pop de pop bc ret .Magnitudes: ; /255, BP, magnitude db 13, 10, 4 db 38, 30, 5 db 89, 50, 6 db 166, 70, 7 db 217, 90, 8 db 242, 110, 9 db 255, 150, 10 ; 379c9 BattleCommand_BatonPass: ; 379c9 ; batonpass ld a, [hBattleTurn] and a jp nz, .Enemy ; Need something to switch to call CheckAnyOtherAlivePartyMons jp z, FailedBatonPass call UpdateBattleMonInParty call AnimateCurrentMove ld c, 50 call DelayFrames ; Transition into switchmon menu call LoadStandardMenuDataHeader farcall SetUpBattlePartyMenu_NoLoop farcall ForcePickSwitchMonInBattle ; Return to battle scene call ClearPalettes farcall _LoadBattleFontsHPBar call CloseWindow call ClearSprites hlcoord 1, 0 lb bc, 4, 10 call ClearBox ld b, SCGB_BATTLE_COLORS call GetSGBLayout call SetPalettes call BatonPass_LinkPlayerSwitch ; Mobile link battles handle entrances differently farcall CheckMobileBattleError jp c, EndMoveEffect ld hl, PassedBattleMonEntrance call CallBattleCore call ResetBatonPassStatus ret .Enemy: ; Wildmons don't have anything to switch to ld a, [wBattleMode] dec a ; WILDMON jp z, FailedBatonPass call CheckAnyOtherAliveEnemyMons jp z, FailedBatonPass call UpdateEnemyMonInParty call AnimateCurrentMove call BatonPass_LinkEnemySwitch ; Mobile link battles handle entrances differently farcall CheckMobileBattleError jp c, EndMoveEffect ; Passed enemy PartyMon entrance xor a ld [wEnemySwitchMonIndex], a ld hl, EnemySwitch_SetMode call CallBattleCore ld hl, ResetBattleParticipants call CallBattleCore ld a, 1 ld [wTypeMatchup], a ld hl, ApplyStatLevelMultiplierOnAllStats call CallBattleCore ld hl, SpikesDamage call CallBattleCore jr ResetBatonPassStatus ; 37a67 BatonPass_LinkPlayerSwitch: ; 37a67 ld a, [wLinkMode] and a ret z ld a, 1 ld [wPlayerAction], a call LoadStandardMenuDataHeader ld hl, LinkBattleSendReceiveAction call CallBattleCore call CloseWindow xor a ld [wPlayerAction], a ret ; 37a82 BatonPass_LinkEnemySwitch: ; 37a82 ld a, [wLinkMode] and a ret z call LoadStandardMenuDataHeader ld hl, LinkBattleSendReceiveAction call CallBattleCore ld a, [OTPartyCount] add BATTLEACTION_SWITCH1 ld b, a ld a, [wBattleAction] cp BATTLEACTION_SWITCH1 jr c, .baton_pass cp b jr c, .switch .baton_pass ld a, [CurOTMon] add BATTLEACTION_SWITCH1 ld [wBattleAction], a .switch jp CloseWindow ; 37aab FailedBatonPass: ; 37aab call AnimateFailedMove jp PrintButItFailed ; 37ab1 ResetBatonPassStatus: ; 37ab1 ; Reset status changes that aren't passed by Baton Pass. ; Nightmare isn't passed. ld a, BATTLE_VARS_STATUS call GetBattleVar and SLP jr nz, .ok ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr res SUBSTATUS_NIGHTMARE, [hl] .ok ; Disable isn't passed. call ResetActorDisable ; Attraction isn't passed. ld hl, PlayerSubStatus1 res SUBSTATUS_IN_LOVE, [hl] ld hl, EnemySubStatus1 res SUBSTATUS_IN_LOVE, [hl] ld hl, PlayerSubStatus5 ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVarAddr res SUBSTATUS_TRANSFORMED, [hl] res SUBSTATUS_ENCORED, [hl] ; New mon hasn't used a move yet. ld a, BATTLE_VARS_LAST_MOVE call GetBattleVarAddr ld [hl], 0 xor a ld [wPlayerWrapCount], a ld [wEnemyWrapCount], a ret ; 37ae9 CheckAnyOtherAlivePartyMons: ; 37ae9 ld hl, PartyMon1HP ld a, [PartyCount] ld d, a ld a, [CurBattleMon] ld e, a jr CheckAnyOtherAliveMons ; 37af6 CheckAnyOtherAliveEnemyMons: ; 37af6 ld hl, OTPartyMon1HP ld a, [OTPartyCount] ld d, a ld a, [CurOTMon] ld e, a ; fallthrough ; 37b01 CheckAnyOtherAliveMons: ; 37b01 ; Check for nonzero HP starting from partymon ; HP at hl for d partymons, besides current mon e. ; Return nz if any are alive. xor a ld b, a ld c, a .loop ld a, c cp d jr z, .done cp e jr z, .next ld a, [hli] or b ld b, a ld a, [hld] or b ld b, a .next push bc ld bc, PARTYMON_STRUCT_LENGTH add hl, bc pop bc inc c jr .loop .done ld a, b and a ret ; 37b1d BattleCommand_Pursuit: ; 37b1d ; pursuit ; Double damage if the opponent is switching. ld hl, wEnemyIsSwitching ld a, [hBattleTurn] and a jr z, .ok ld hl, wPlayerIsSwitching .ok ld a, [hl] and a ret z ld hl, CurDamage + 1 sla [hl] dec hl rl [hl] ret nc ld a, $ff ld [hli], a ld [hl], a ret ; 37b39 BattleCommand_ClearHazards: ; 37b39 ; clearhazards ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr bit SUBSTATUS_LEECH_SEED, [hl] jr z, .not_leeched res SUBSTATUS_LEECH_SEED, [hl] ld hl, ShedLeechSeedText call StdBattleTextBox .not_leeched ld hl, PlayerScreens ld de, wPlayerWrapCount ld a, [hBattleTurn] and a jr z, .got_screens_wrap ld hl, EnemyScreens ld de, wEnemyWrapCount .got_screens_wrap bit SCREENS_SPIKES, [hl] jr z, .no_spikes res SCREENS_SPIKES, [hl] ld hl, BlewSpikesText push de call StdBattleTextBox pop de .no_spikes ld a, [de] and a ret z xor a ld [de], a ld hl, ReleasedByText jp StdBattleTextBox ; 37b74 BattleCommand_HealMorn: ; 37b74 ; healmorn ld b, MORN_F jr BattleCommand_TimeBasedHealContinue ; 37b78 BattleCommand_HealDay: ; 37b78 ; healday ld b, DAY_F jr BattleCommand_TimeBasedHealContinue ; 37b7c BattleCommand_HealNite: ; 37b7c ; healnite ld b, NITE_F ; fallthrough ; 37b7e BattleCommand_TimeBasedHealContinue: ; 37b7e ; Time- and weather-sensitive heal. ld hl, BattleMonMaxHP ld de, BattleMonHP ld a, [hBattleTurn] and a jr z, .start ld hl, EnemyMonMaxHP ld de, EnemyMonHP .start ; Index for .Multipliers ; Default restores half max HP. ld c, 2 ; Don't bother healing if HP is already full. push bc call StringCmp pop bc jr z, .Full ; Don't factor in time of day in link battles. ld a, [wLinkMode] and a jr nz, .Weather ld a, [TimeOfDay] cp b jr z, .Weather dec c ; double .Weather: ld a, [Weather] and a jr z, .Heal ; x2 in sun ; /2 in rain/sandstorm inc c cp WEATHER_SUN jr z, .Heal dec c dec c .Heal: ld b, 0 ld hl, .Multipliers add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a ld a, BANK(GetMaxHP) rst FarCall call AnimateCurrentMove call BattleCommand_SwitchTurn callfar RestoreHP call BattleCommand_SwitchTurn call UpdateUserInParty ; 'regained health!' ld hl, RegainedHealthText jp StdBattleTextBox .Full: call AnimateFailedMove ; 'hp is full!' ld hl, HPIsFullText jp StdBattleTextBox .Multipliers: dw GetEighthMaxHP dw GetQuarterMaxHP dw GetHalfMaxHP dw GetMaxHP ; 37be8 BattleCommand_HiddenPower: ; 37be8 ; hiddenpower ld a, [AttackMissed] and a ret nz farcall HiddenPowerDamage ret ; 37bf4 BattleCommand_StartRain: ; 37bf4 ; startrain ld a, WEATHER_RAIN ld [Weather], a ld a, 5 ld [WeatherCount], a call AnimateCurrentMove ld hl, DownpourText jp StdBattleTextBox ; 37c07 BattleCommand_StartSun: ; 37c07 ; startsun ld a, WEATHER_SUN ld [Weather], a ld a, 5 ld [WeatherCount], a call AnimateCurrentMove ld hl, SunGotBrightText jp StdBattleTextBox ; 37c1a BattleCommand_BellyDrum: ; 37c1a ; bellydrum ; This command is buggy because it raises the user's attack ; before checking that it has enough HP to use the move. ; Swap the order of these two blocks to fix. call BattleCommand_AttackUp2 ld a, [AttackMissed] and a jr nz, .failed callfar GetHalfMaxHP callfar CheckUserHasEnoughHP jr nc, .failed push bc call AnimateCurrentMove pop bc callfar SubtractHPFromUser call UpdateUserInParty ld a, 5 .max_attack_loop push af call BattleCommand_AttackUp2 pop af dec a jr nz, .max_attack_loop ld hl, BellyDrumText jp StdBattleTextBox .failed call AnimateFailedMove jp PrintButItFailed ; 37c55 BattleCommand_PsychUp: ; 37c55 ; psychup ld hl, EnemyStatLevels ld de, PlayerStatLevels ld a, [hBattleTurn] and a jr z, .pointers_correct ; It's the enemy's turn, so swap the pointers. push hl ld h, d ld l, e pop de .pointers_correct push hl ld b, NUM_LEVEL_STATS ; If any of the enemy's stats is modified from its base level, ; the move succeeds. Otherwise, it fails. .loop ld a, [hli] cp BASE_STAT_LEVEL jr nz, .break dec b jr nz, .loop pop hl call AnimateFailedMove jp PrintButItFailed .break pop hl ld b, NUM_LEVEL_STATS .loop2 ld a, [hli] ld [de], a inc de dec b jr nz, .loop2 ld a, [hBattleTurn] and a jr nz, .calc_enemy_stats call CalcPlayerStats jr .merge .calc_enemy_stats call CalcEnemyStats .merge call AnimateCurrentMove ld hl, CopiedStatsText jp StdBattleTextBox ; 37c95 BattleCommand_MirrorCoat: ; 37c95 ; mirrorcoat ld a, 1 ld [AttackMissed], a ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar and a ret z ld b, a callfar GetMoveEffect ld a, b cp EFFECT_MIRROR_COAT ret z call BattleCommand_ResetTypeMatchup ld a, [wTypeMatchup] and a ret z call CheckOpponentWentFirst ret z ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP call GetBattleVar dec a ld de, StringBuffer1 call GetMoveData ld a, [StringBuffer1 + 2] and a ret z ld a, [StringBuffer1 + 3] cp SPECIAL ret c ld hl, CurDamage ld a, [hli] or [hl] ret z ld a, [hl] add a ld [hld], a ld a, [hl] adc a ld [hl], a jr nc, .capped ld a, $ff ld [hli], a ld [hl], a .capped xor a ld [AttackMissed], a ret ; 37ce6 BattleCommand_DoubleMinimizeDamage: ; 37ce6 ; doubleminimizedamage ld hl, wEnemyMinimized ld a, [hBattleTurn] and a jr z, .ok ld hl, wPlayerMinimized .ok ld a, [hl] and a ret z ld hl, CurDamage + 1 sla [hl] dec hl rl [hl] ret nc ld a, $ff ld [hli], a ld [hl], a ret ; 37d02 BattleCommand_SkipSunCharge: ; 37d02 ; mimicsuncharge ld a, [Weather] cp WEATHER_SUN ret nz ld b, charge_command jp SkipToBattleCommand ; 37d0d BattleCommand_CheckFutureSight: ; 37d0d ; checkfuturesight ld hl, wPlayerFutureSightCount ld de, wPlayerFutureSightDamage ld a, [hBattleTurn] and a jr z, .ok ld hl, wEnemyFutureSightCount ld de, wEnemyFutureSightDamage .ok ld a, [hl] and a ret z cp 1 ret nz ld [hl], 0 ld a, [de] inc de ld [CurDamage], a ld a, [de] ld [CurDamage + 1], a ld b, futuresight_command jp SkipToBattleCommand ; 37d34 BattleCommand_FutureSight: ; 37d34 ; futuresight call CheckUserIsCharging jr nz, .AlreadyChargingFutureSight ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar ld b, a ld a, BATTLE_VARS_LAST_COUNTER_MOVE call GetBattleVarAddr ld [hl], b ld a, BATTLE_VARS_LAST_MOVE call GetBattleVarAddr ld [hl], b .AlreadyChargingFutureSight: ld hl, wPlayerFutureSightCount ld a, [hBattleTurn] and a jr z, .GotFutureSightCount ld hl, wEnemyFutureSightCount .GotFutureSightCount: ld a, [hl] and a jr nz, .failed ld a, 4 ld [hl], a call BattleCommand_LowerSub call BattleCommand_MoveDelay ld hl, ForesawAttackText call StdBattleTextBox call BattleCommand_RaiseSub ld de, wPlayerFutureSightDamage ld a, [hBattleTurn] and a jr z, .StoreDamage ld de, wEnemyFutureSightDamage .StoreDamage: ld hl, CurDamage ld a, [hl] ld [de], a ld [hl], 0 inc hl inc de ld a, [hl] ld [de], a ld [hl], 0 jp EndMoveEffect .failed pop bc call ResetDamage call AnimateFailedMove call PrintButItFailed jp EndMoveEffect ; 37d94 BattleCommand_ThunderAccuracy: ; 37d94 ; thunderaccuracy ld a, BATTLE_VARS_MOVE_TYPE call GetBattleVarAddr inc hl ld a, [Weather] cp WEATHER_RAIN jr z, .rain cp WEATHER_SUN ret nz ld [hl], 50 percent + 1 ret .rain ; Redundant with CheckHit guranteeing hit ld [hl], 100 percent ret ; 37daa CheckHiddenOpponent: ; 37daa ; BUG: This routine should account for Lock-On and Mind Reader. ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND ret ; 37db2 GetUserItem: ; 37db2 ; Return the effect of the user's item in bc, and its id at hl. ld hl, BattleMonItem ld a, [hBattleTurn] and a jr z, .go ld hl, EnemyMonItem .go ld b, [hl] jp GetItemHeldEffect ; 37dc1 GetOpponentItem: ; 37dc1 ; Return the effect of the opponent's item in bc, and its id at hl. ld hl, EnemyMonItem ld a, [hBattleTurn] and a jr z, .go ld hl, BattleMonItem .go ld b, [hl] jp GetItemHeldEffect ; 37dd0 GetItemHeldEffect: ; 37dd0 ; Return the effect of item b in bc. ld a, b and a ret z push hl ld hl, ItemAttributes + ITEMATTR_EFFECT dec a ld c, a ld b, 0 ld a, ITEMATTR_STRUCT_LENGTH call AddNTimes ld a, BANK(ItemAttributes) call GetFarHalfword ld b, l ld c, h pop hl ret ; 37de9 AnimateCurrentMoveEitherSide: ; 37de9 push hl push de push bc ld a, [wKickCounter] push af call BattleCommand_LowerSub pop af ld [wKickCounter], a call PlayDamageAnim call BattleCommand_RaiseSub pop bc pop de pop hl ret ; 37e01 AnimateCurrentMove: ; 37e01 push hl push de push bc ld a, [wKickCounter] push af call BattleCommand_LowerSub pop af ld [wKickCounter], a call LoadMoveAnim call BattleCommand_RaiseSub pop bc pop de pop hl ret ; 37e19 PlayDamageAnim: ; 37e19 xor a ld [FXAnimID + 1], a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar and a ret z ld [FXAnimID], a ld a, [hBattleTurn] and a ld a, BATTLEANIM_ENEMY_DAMAGE jr z, .player ld a, BATTLEANIM_PLAYER_DAMAGE .player ld [wNumHits], a jp PlayUserBattleAnim ; 37e36 LoadMoveAnim: ; 37e36 xor a ld [wNumHits], a ld [FXAnimID + 1], a ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVar and a ret z ; fallthrough ; 37e44 LoadAnim: ; 37e44 ld [FXAnimID], a ; fallthrough ; 37e47 PlayUserBattleAnim: ; 37e47 push hl push de push bc callfar PlayBattleAnim pop bc pop de pop hl ret ; 37e54 PlayOpponentBattleAnim: ; 37e54 ld a, e ld [FXAnimID], a ld a, d ld [FXAnimID + 1], a xor a ld [wNumHits], a push hl push de push bc call BattleCommand_SwitchTurn callfar PlayBattleAnim call BattleCommand_SwitchTurn pop bc pop de pop hl ret ; 37e73 CallBattleCore: ; 37e73 ld a, BANK(BattleCore) rst FarCall ret ; 37e77 AnimateFailedMove: ; 37e77 call BattleCommand_LowerSub call BattleCommand_MoveDelay jp BattleCommand_RaiseSub ; 37e80 BattleCommand_MoveDelay: ; 37e80 ; movedelay ; Wait 40 frames. ld c, 40 jp DelayFrames ; 37e85 BattleCommand_ClearText: ; 37e85 ; cleartext ; Used in multi-hit moves. ld hl, .text jp BattleTextBox .text db "@" ; 37e8c SkipToBattleCommand: ; 37e8c ; Skip over commands until reaching command b. ld a, [BattleScriptBufferAddress + 1] ld h, a ld a, [BattleScriptBufferAddress] ld l, a .loop ld a, [hli] cp b jr nz, .loop ld a, h ld [BattleScriptBufferAddress + 1], a ld a, l ld [BattleScriptBufferAddress], a ret ; 37ea1 GetMoveAttr: ; 37ea1 ; Assuming hl = Moves + x, return attribute x of move a. push bc ld bc, MOVE_LENGTH call AddNTimes call GetMoveByte pop bc ret ; 37ead GetMoveData: ; 37ead ; Copy move struct a to de. ld hl, Moves ld bc, MOVE_LENGTH call AddNTimes ld a, Bank(Moves) jp FarCopyBytes ; 37ebb GetMoveByte: ; 37ebb ld a, BANK(Moves) jp GetFarByte ; 37ec0 DisappearUser: ; 37ec0 farcall _DisappearUser ret ; 37ec7 AppearUserLowerSub: ; 37ec7 farcall _AppearUserLowerSub ret ; 37ece AppearUserRaiseSub: ; 37ece farcall _AppearUserRaiseSub ret ; 37ed5 _CheckBattleScene: ; 37ed5 ; Checks the options. Returns carry if battle animations are disabled. push hl push de push bc farcall CheckBattleScene pop bc pop de pop hl ret ; 37ee2