Files
pokecrystal/engine/battle/effect_commands.asm
i0brendan0 0e45563497 Add Fix for Lock On Status Moves
These changes should fix the status move and secondary effects not working if the opponent is flying or digging but has been locked on.
2018-02-19 02:54:13 -06:00

10017 lines
143 KiB
NASM

DoPlayerTurn: ; 34000
call SetPlayerTurn
ld a, [wBattlePlayerAction]
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, wBattleScriptBuffer
.GetMoveEffect:
ld a, BANK(MoveEffects)
call GetFarByte
inc hl
ld [de], a
inc de
cp -1
jr nz, .GetMoveEffect
; Start at the first command.
ld hl, wBattleScriptBuffer
ld a, l
ld [wBattleScriptBufferAddress], a
ld a, h
ld [wBattleScriptBufferAddress + 1], a
.ReadMoveEffectCommand:
; ld a, [wBattleScriptBufferAddress++]
ld a, [wBattleScriptBufferAddress]
ld l, a
ld a, [wBattleScriptBufferAddress + 1]
ld h, a
ld a, [hli]
push af
ld a, l
ld [wBattleScriptBufferAddress], a
ld a, h
ld [wBattleScriptBufferAddress + 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 [wAttackMissed], a
ld [wEffectFailed], a
ld [wKickCounter], a
ld [wAlreadyDisobeyed], a
ld [wAlreadyFailed], a
ld [wSomeoneIsRampaging], a
ld a, EFFECTIVE
ld [wTypeModifier], a
ld a, [hBattleTurn]
and a
jp nz, CheckEnemyTurn
CheckPlayerTurn:
ld hl, wPlayerSubStatus4
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, wBattleMonStatus
ld a, [hl]
and SLP
jr z, .not_asleep
dec a
ld [wBattleMonStatus], 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, wPlayerSubStatus1
res SUBSTATUS_NIGHTMARE, [hl]
jr .not_asleep
.fast_asleep
ld hl, FastAsleepText
call StdBattleTextBox
; Snore and Sleep Talk bypass sleep.
ld a, [wCurPlayerMove]
cp SNORE
jr z, .not_asleep
cp SLEEP_TALK
jr z, .not_asleep
call CantMove
jp EndTurn
.not_asleep
ld hl, wBattleMonStatus
bit FRZ, [hl]
jr z, .not_frozen
; Flame Wheel and Sacred Fire thaw the user.
ld a, [wCurPlayerMove]
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, wPlayerSubStatus3
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, wPlayerDisableCount
ld a, [hl]
and a
jr z, .not_disabled
dec a
ld [hl], a
and $f
jr nz, .not_disabled
ld [hl], a
ld [wDisabledMove], a
ld hl, DisabledNoMoreText
call StdBattleTextBox
.not_disabled
ld a, [wPlayerSubStatus3]
add a
jr nc, .not_confused
ld hl, wPlayerConfuseCount
dec [hl]
jr nz, .confused
ld hl, wPlayerSubStatus3
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 50 percent + 1
jr nc, .not_confused
; clear confusion-dependent substatus
ld hl, wPlayerSubStatus3
ld a, [hl]
and 1 << SUBSTATUS_CONFUSED
ld [hl], a
call HitConfusion
call CantMove
jp EndTurn
.not_confused
ld a, [wPlayerSubStatus1]
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 50 percent + 1
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, [wDisabledMove]
and a
jr z, .no_disabled_move
; Are we using the disabled move?
ld hl, wCurPlayerMove
cp [hl]
jr nz, .no_disabled_move
call MoveDisabled
call CantMove
jp EndTurn
.no_disabled_move
ld hl, wBattleMonStatus
bit PAR, [hl]
ret z
; 25% chance to be fully paralyzed
call BattleRandom
cp 25 percent
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, wEnemySubStatus4
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, wEnemyMonStatus
ld a, [hl]
and SLP
jr z, .not_asleep
dec a
ld [wEnemyMonStatus], 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, wEnemySubStatus1
res SUBSTATUS_NIGHTMARE, [hl]
jr .not_asleep
.fast_asleep
; Snore and Sleep Talk bypass sleep.
ld a, [wCurEnemyMove]
cp SNORE
jr z, .not_asleep
cp SLEEP_TALK
jr z, .not_asleep
call CantMove
jp EndTurn
.not_asleep
ld hl, wEnemyMonStatus
bit FRZ, [hl]
jr z, .not_frozen
; Flame Wheel and Sacred Fire thaw the user.
ld a, [wCurEnemyMove]
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, wEnemySubStatus3
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, wEnemyDisableCount
ld a, [hl]
and a
jr z, .not_disabled
dec a
ld [hl], a
and $f
jr nz, .not_disabled
ld [hl], a
ld [wEnemyDisabledMove], a
ld hl, DisabledNoMoreText
call StdBattleTextBox
.not_disabled
ld a, [wEnemySubStatus3]
add a ; bit SUBSTATUS_CONFUSED
jr nc, .not_confused
ld hl, wEnemyConfuseCount
dec [hl]
jr nz, .confused
ld hl, wEnemySubStatus3
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, wEnemySubStatus3
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, [wEnemySubStatus1]
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, [wEnemyDisabledMove]
and a
jr z, .no_disabled_move
; Are we using the disabled move?
ld hl, wCurEnemyMove
cp [hl]
jr nz, .no_disabled_move
call MoveDisabled
call CantMove
jp EndTurn
.no_disabled_move
ld hl, wEnemyMonStatus
bit PAR, [hl]
ret z
; 25% chance to be fully paralyzed
call BattleRandom
cp 25 percent
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 [wCriticalHit], 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, [wAlreadyDisobeyed]
and a
ret nz
xor a
ld [wAlreadyDisobeyed], a
; No obedience in link battles
; (since no handling exists for enemy)
ld a, [wLinkMode]
and a
ret nz
ld a, [wInBattleTowerBattle]
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, [wPlayerID]
cp [hl]
jr nz, .obeylevel
inc hl
ld a, [wPlayerID + 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, [wBattleMonLevel]
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 [wBattleMonStatus], a
ld hl, BeganToNapText
jr .Print
.DoNothing:
; 4 random choices
call BattleRandom
and %11
ld hl, LoafingAroundText
and a ; 0
jr z, .Print
ld hl, WontObeyText
dec a ; 1
jr z, .Print
ld hl, TurnedAwayText
dec a ; 2
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, [wBattleMonMoves + 1]
and a
jr z, .DoNothing
; Don't bother trying to handle Disable.
ld a, [wDisabledMove]
and a
jr nz, .DoNothing
ld hl, wBattleMonPP
ld de, wBattleMonMoves
ld b, 0
ld c, NUM_MOVES
.GetTotalPP:
ld a, [hli]
and PP_MASK
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, wBattleMonPP
ld a, [wCurMoveNum]
ld e, a
ld d, 0
add hl, de
; Can't use another move if only one move has PP.
ld a, [hl]
and PP_MASK
cp b
jr z, .DoNothing
; Make sure we can actually use the move once we get there.
ld a, 1
ld [wAlreadyDisobeyed], a
ld a, [w2DMenuNumRows]
ld b, a
; Save the move we originally picked for afterward.
ld a, [wCurMoveNum]
ld c, a
push af
.RandomMove:
call BattleRandom
maskbits 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 [wCurMoveNum], a
ld hl, wBattleMonPP
ld e, a
ld d, 0
add hl, de
ld a, [hl]
and PP_MASK
jr z, .RandomMove
; Use it.
ld a, [wCurMoveNum]
ld c, a
ld b, 0
ld hl, wBattleMonMoves
add hl, bc
ld a, [hl]
ld [wCurPlayerMove], a
call SetPlayerTurn
call UpdateMoveData
call DoMove
; Restore original move choice.
pop af
ld [wCurMoveNum], a
.EndDisobedience:
xor a
ld [wLastPlayerMove], a
ld [wLastPlayerCounterMove], a
; Break Encore too.
ld hl, wPlayerSubStatus5
res SUBSTATUS_ENCORED, [hl]
xor a
ld [wPlayerEncoreCount], a
jp EndMoveEffect
; 3451f
IgnoreSleepOnly: ; 3451f
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
; Snore and Sleep Talk bypass sleep.
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, wBattleMonPP
ld de, wPlayerSubStatus3
ld bc, wPlayerTurnsTaken
ld a, [hBattleTurn]
and a
jr z, .proceed
ld hl, wEnemyMonPP
ld de, wEnemySubStatus3
ld bc, wEnemyTurnsTaken
.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, wPartyMon1PP
ld a, [wCurBattleMon]
jr z, .player
; mimic this part entirely if wildbattle
ld a, [wBattleMode]
dec a
jr z, .wild
ld hl, wOTPartyMon1PP
ld a, [wCurOTMon]
.player
call GetPartyLocation
push hl
call CheckMimicUsed
pop hl
ret c
.consume_pp
ld a, [hBattleTurn]
and a
ld a, [wCurMoveNum]
jr z, .okay
ld a, [wCurEnemyMoveNum]
.okay
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and PP_MASK
jr z, .out_of_pp
dec [hl]
ld b, 0
ret
.wild
ld hl, wEnemyMonMoves
ld a, [wCurEnemyMoveNum]
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 -1
; 3460b
CheckMimicUsed: ; 3460b
ld a, [hBattleTurn]
and a
ld a, [wCurMoveNum]
jr z, .player
ld a, [wCurEnemyMoveNum]
.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 [wCriticalHit], a
ld a, BATTLE_VARS_MOVE_POWER
call GetBattleVar
and a
ret z
ld a, [hBattleTurn]
and a
ld hl, wEnemyMonItem
ld a, [wEnemyMonSpecies]
jr nz, .Item
ld hl, wBattleMonItem
ld a, [wBattleMonSpecies]
.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, CriticalHitMoves
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, CriticalHitChances
ld b, 0
add hl, bc
call BattleRandom
cp [hl]
ret nc
ld a, 1
ld [wCriticalHit], a
ret
INCLUDE "data/battle/critical_hits.asm"
; 346b2
BattleCommand_TripleKick: ; 346b2
; triplekick
ld a, [wKickCounter]
ld b, a
inc b
ld hl, wCurDamage + 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, wBattleMonType1
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wEnemyMonType1
ld a, [hli]
ld d, a
ld e, [hl]
ld a, [hBattleTurn]
and a
jr z, .go ; Who Attacks and who Defends
ld hl, wEnemyMonType1
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wBattleMonType1
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, wCurDamage + 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 [wCurDamage], a
ld a, l
ld [wCurDamage + 1], a
ld hl, wTypeModifier
set 7, [hl]
.SkipStab:
ld a, BATTLE_VARS_MOVE_TYPE
call GetBattleVar
ld b, a
ld hl, TypeMatchups
.TypesLoop:
ld a, [hli]
cp -1
jr z, .end
; foresight
cp -2
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, [wTypeModifier]
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 [wAttackMissed], a
xor a
.NotImmune:
ld [hMultiplier], a
add b
ld [wTypeModifier], a
xor a
ld [hMultiplicand + 0], a
ld hl, wCurDamage
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, [wTypeModifier]
and %10000000
or b
ld [wTypeModifier], a
ret
; 347c8
BattleCheckTypeMatchup: ; 347c8
ld hl, wEnemyMonType1
ld a, [hBattleTurn]
and a
jr z, CheckTypeMatchup
ld hl, wBattleMonType1
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 -1
jr z, .End
cp -2
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 [wTypeModifier], a
inc a
ld [wAttackMissed], a
ret
.reset
ld [wTypeMatchup], a
ret
; 3484e
INCLUDE "engine/battle/ai/switch.asm"
INCLUDE "data/battle/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, wCurDamage
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 85 percent + 1
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, wCurDamage
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 -1
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 [wAttackMissed], 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, [wBattleWeather]
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, [wPlayerAccLevel]
ld b, a
ld a, [wEnemyEvaLevel]
ld c, a
jr z, .got_acc_eva
ld hl, wEnemyMoveStruct + MOVE_ACC
ld a, [wEnemyAccLevel]
ld b, a
ld a, [wPlayerEvaLevel]
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, MAX_STAT_LEVEL + 1
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, AccuracyLevelMultipliers
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
INCLUDE "data/battle/accuracy_multipliers.asm"
; 34ecc
BattleCommand_EffectChance: ; 34ecc
; effectchance
xor a
ld [wEffectFailed], 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 [wEffectFailed], 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 [wFXAnimID + 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, [wAttackMissed]
and a
jp nz, BattleCommand_MoveDelay
ld a, [hBattleTurn]
and a
ld de, wPlayerRolloutCount
ld a, BATTLEANIM_ENEMY_DAMAGE
jr z, .got_rollout_count
ld de, wEnemyRolloutCount
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, [wAttackMissed]
and a
jp nz, BattleCommand_MoveDelay
xor a
jr BattleCommand_StatUpDownAnim
; 34fdb
BattleCommand_StatDownAnim: ; 34fdb
ld a, [wAttackMissed]
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 [wFXAnimID + 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, [wAttackMissed]
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, wPlayerDamageTaken + 1
ld a, [hBattleTurn]
and a
jr nz, .damage_taken
ld de, wEnemyDamageTaken + 1
.damage_taken
ld a, [wCurDamage + 1]
ld b, a
ld a, [de]
add b
ld [de], a
dec de
ld a, [wCurDamage]
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, [wTypeModifier]
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, [wCriticalHit]
cp -1
jr nz, .got_text
ld hl, UnaffectedText
.got_text
call FailText_CheckOpponentProtect
xor a
ld [wCriticalHit], a
ld a, BATTLE_VARS_MOVE_EFFECT
call GetBattleVar
cp EFFECT_JUMP_KICK
ret nz
ld a, [wTypeModifier]
and $7f
ret z
ld hl, wCurDamage
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, [wAttackMissed]
and a
ret z
ld a, [wTypeModifier]
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, [wCriticalHit]
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 [wCriticalHit], a
.wait
ld c, 20
jp DelayFrames
.texts
dw CriticalHitText
dw OneHitKOText
; 35197
BattleCommand_StartLoop: ; 35197
; startloop
ld hl, wPlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyRolloutCount
.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, [wTypeModifier]
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, wEnemyMonHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wBattleMonHP
.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, wEnemyMonMaxHP + 1
bccoord 2, 2 ; hp bar
ld a, 0
jr nz, .got_max_hp
ld hl, wBattleMonMaxHP + 1
bccoord 10, 9 ; hp bar
ld a, 1
.got_max_hp
ld [wWhichHPBar], a
ld a, [hld]
ld [wBuffer1], a
ld a, [hld]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer3], a
xor a
ld [hld], a
ld a, [hl]
ld [wBuffer4], a
xor a
ld [hl], a
ld [wBuffer5], a
ld [wBuffer6], a
ld h, b
ld l, c
predef AnimateHPBar
call RefreshBattleHuds
call BattleCommand_SwitchTurn
xor a
ld [wNumHits], a
ld [wFXAnimID + 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, [wAttackMissed]
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, [wCurDamage]
ld h, a
ld b, a
ld a, [wCurDamage + 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 [wCurDamage], a
ld a, l
ld [wCurDamage + 1], a
ret
; 352a3
EndMoveEffect: ; 352a3
ld a, [wBattleScriptBufferAddress]
ld l, a
ld a, [wBattleScriptBufferAddress + 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, [wTempEnemyMonSpecies]
.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, wEnemyMonDefense
ld a, [hli]
ld b, a
ld c, [hl]
ld a, [wEnemyScreens]
bit SCREENS_REFLECT, a
jr z, .physicalcrit
sla c
rl b
.physicalcrit
ld hl, wBattleMonAttack
call GetDamageStatsCritical
jr c, .thickclub
ld hl, wEnemyDefense
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wPlayerAttack
jr .thickclub
.special
ld hl, wEnemyMonSpclDef
ld a, [hli]
ld b, a
ld c, [hl]
ld a, [wEnemyScreens]
bit SCREENS_LIGHT_SCREEN, a
jr z, .specialcrit
sla c
rl b
.specialcrit
ld hl, wBattleMonSpclAtk
call GetDamageStatsCritical
jr c, .lightball
ld hl, wEnemySpDef
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wPlayerSpAtk
.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, [wBattleMonLevel]
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, [wCriticalHit]
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, [wPlayerSAtkLevel]
ld b, a
ld a, [wEnemySDefLevel]
jr nc, .end
; physical
ld a, [wPlayerAtkLevel]
ld b, a
ld a, [wEnemyDefLevel]
jr .end
.enemy
ld a, [wEnemyMoveStructType]
cp SPECIAL
; special
ld a, [wEnemySAtkLevel]
ld b, a
ld a, [wPlayerSDefLevel]
jr nc, .end
; physical
ld a, [wEnemyAtkLevel]
ld b, a
ld a, [wPlayerDefLevel]
.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, [wTempEnemyMonSpecies]
.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, wBattleMonDefense
ld a, [hli]
ld b, a
ld c, [hl]
ld a, [wPlayerScreens]
bit SCREENS_REFLECT, a
jr z, .physicalcrit
sla c
rl b
.physicalcrit
ld hl, wEnemyMonAttack
call GetDamageStatsCritical
jr c, .thickclub
ld hl, wPlayerDefense
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wEnemyAttack
jr .thickclub
.Special:
ld hl, wBattleMonSpclDef
ld a, [hli]
ld b, a
ld c, [hl]
ld a, [wPlayerScreens]
bit SCREENS_LIGHT_SCREEN, a
jr z, .specialcrit
sla c
rl b
.specialcrit
ld hl, wEnemyMonSpclAtk
call GetDamageStatsCritical
jr c, .lightball
ld hl, wPlayerSpDef
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wEnemySpAtk
.lightball
call LightBallBoost
jr .done
.thickclub
call ThickClubBoost
.done
call TruncateHL_BC
ld a, [wEnemyMonLevel]
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, [wPlayerSubStatus3]
bit SUBSTATUS_IN_LOOP, a
jr nz, .next_mon
ld c, 20
call DelayFrames
xor a
ld [wPlayerRolloutCount], a
ld [wd002], a
ld [wBeatUpHitAtLeastOnce], a
jr .got_mon
.next_mon
ld a, [wPlayerRolloutCount]
ld b, a
ld a, [wPartyCount]
sub b
ld [wd002], a
.got_mon
ld a, [wd002]
ld hl, wPartyMonNicknames
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, [wCurBattleMon]
; BUG: this can desynchronize link battles
; Change "cp [hl]" to "cp c" to fix
cp [hl]
ld hl, wBattleMonStatus
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, [wEnemyMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseDefense]
ld c, a
push bc
ld a, MON_SPECIES
call GetBeatupMonLocation
ld a, [hl]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseAttack]
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, [wEnemySubStatus3]
bit SUBSTATUS_IN_LOOP, a
jr nz, .not_first_enemy_beatup
xor a
ld [wEnemyRolloutCount], a
ld [wd002], a
ld [wBeatUpHitAtLeastOnce], a
jr .enemy_continue
.not_first_enemy_beatup
ld a, [wEnemyRolloutCount]
ld b, a
ld a, [wOTPartyCount]
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, [wInBattleTowerBattle]
and a
jr nz, .link_or_tower
ld a, [wd002]
ld c, a
ld b, 0
ld hl, wOTPartySpecies
add hl, bc
ld a, [hl]
ld [wNamedObjectIndexBuffer], a
call GetPokemonName
jr .got_enemy_nick
.link_or_tower
ld a, [wd002]
ld hl, wOTPartyMonNicknames
ld bc, NAME_LENGTH
call AddNTimes
ld de, wStringBuffer1
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, [wCurOTMon]
cp b
ld hl, wEnemyMonStatus
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, [wEnemyMonSpecies]
ld [wNamedObjectIndexBuffer], a
call GetPokemonName
ld hl, BeatUpAttackText
call StdBattleTextBox
jp EnemyAttackDamage
.finish_beatup
ld hl, BeatUpAttackText
call StdBattleTextBox
ld a, [wBattleMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseDefense]
ld c, a
push bc
ld a, MON_SPECIES
call GetBeatupMonLocation
ld a, [hl]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseAttack]
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, wPartyMon1Species
jr z, .got_species
ld hl, wOTPartyMon1Species
.got_species
ld a, [wd002]
add hl, bc
call GetPartyLocation
pop bc
ret
BattleCommand_ClearMissDamage: ; 355d5
; clearmissdamage
ld a, [wAttackMissed]
and a
ret z
jp ResetDamage
; 355dd
HitSelfInConfusion: ; 355dd
call ResetDamage
ld a, [hBattleTurn]
and a
ld hl, wBattleMonDefense
ld de, wPlayerScreens
ld a, [wBattleMonLevel]
jr z, .got_it
ld hl, wEnemyMonDefense
ld de, wEnemyScreens
ld a, [wEnemyMonLevel]
.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 -1
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 wCurDamage (capped at 997).
ld hl, wCurDamage
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, [wCriticalHit]
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
INCLUDE "data/battle/type_boost_items.asm"
BattleCommand_ConstantDamage: ; 35726
; constantdamage
ld hl, wBattleMonLevel
ld a, [hBattleTurn]
and a
jr z, .got_turn
ld hl, wEnemyMonLevel
.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, wEnemyMonHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wBattleMonHP
.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, wCurDamage
ld [hli], a
ld [hl], b
ret
.reversal
ld hl, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .reversal_got_hp
ld hl, wEnemyMonHP
.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 [wAttackMissed], 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, wStringBuffer1
call GetMoveData
ld a, [wStringBuffer1 + MOVE_POWER]
and a
ret z
ld a, [wStringBuffer1 + MOVE_TYPE]
cp SPECIAL
ret nc
ld hl, wCurDamage
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 [wAttackMissed], a
ret
; 35864
BattleCommand_Encore: ; 35864
; encore
ld hl, wEnemyMonMoves
ld de, wEnemyEncoreCount
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wBattleMonMoves
ld de, wPlayerEncoreCount
.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, wBattleMonPP - wBattleMonMoves - 1
add hl, bc
ld a, [hl]
and PP_MASK
jp z, .failed
ld a, [wAttackMissed]
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, [wLastPlayerMove]
ld b, a
ld c, 0
ld hl, wBattleMonMoves
.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 [wCurMoveNum], a
ld a, b
ld [wCurPlayerMove], a
dec a
ld de, wPlayerMoveStruct
call GetMoveData
jr .finish_move
.force_last_enemy_move
push hl
ld a, [wLastEnemyMove]
ld b, a
ld c, 0
ld hl, wEnemyMonMoves
.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 [wCurEnemyMoveNum], a
ld a, b
ld [wCurEnemyMove], 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, [wAttackMissed]
and a
jp nz, .ButItFailed
call CheckSubstituteOpp
jp nz, .ButItFailed
call AnimateCurrentMove
ld hl, wBattleMonMaxHP + 1
ld de, wEnemyMonMaxHP + 1
call .PlayerShareHP
ld a, $1
ld [wWhichHPBar], a
hlcoord 10, 9
predef AnimateHPBar
ld hl, wEnemyMonHP
ld a, [hli]
ld [wBuffer4], a
ld a, [hli]
ld [wBuffer3], a
ld a, [hli]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer1], 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 [wBuffer1], a
ld a, [hld]
ld [wBuffer2], a
ld a, [hld]
ld b, a
ld [wBuffer3], a
ld a, [hl]
ld [wBuffer4], a
dec de
dec de
ld a, [de]
dec de
add b
ld [wCurDamage + 1], a
ld b, [hl]
ld a, [de]
adc b
srl a
ld [wCurDamage], a
ld a, [wCurDamage + 1]
rr a
ld [wCurDamage + 1], a
inc hl
inc hl
inc hl
inc de
inc de
inc de
.EnemyShareHP: ; 359ac
ld c, [hl]
dec hl
ld a, [wCurDamage + 1]
sub c
ld b, [hl]
dec hl
ld a, [wCurDamage]
sbc b
jr nc, .skip
ld a, [wCurDamage]
ld b, a
ld a, [wCurDamage + 1]
ld c, a
.skip
ld a, c
ld [hld], a
ld [wBuffer5], a
ld a, b
ld [hli], a
ld [wBuffer6], 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 [wAttackMissed], a
call FailSnore
jp EndMoveEffect
; 359e6
BattleCommand_Conversion2: ; 359e6
; conversion2
ld a, [wAttackMissed]
and a
jr nz, .failed
ld hl, wBattleMonType1
ld a, [hBattleTurn]
and a
jr z, .got_type
ld hl, wEnemyMonType1
.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, [wAttackMissed]
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, wBattleMonMoves
ld a, [hBattleTurn]
and a
jr z, .get_last_move
ld hl, wEnemyMonMoves
.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, wBattleMonPP - wBattleMonMoves
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, [wAttackMissed]
and a
jr nz, .fail
ld a, [hBattleTurn]
and a
ld hl, wBattleMonMoves + 1
ld a, [wDisabledMove]
ld d, a
jr z, .got_moves
ld hl, wEnemyMonMoves + 1
ld a, [wEnemyDisabledMove]
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
maskbits 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, [wDisabledMove]
jr z, .got_move_2
ld a, [wEnemyDisabledMove]
.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, [wAttackMissed]
and a
jp nz, .failed
ld bc, PARTYMON_STRUCT_LENGTH ; ????
ld hl, wEnemyMonMoves
ld a, [hBattleTurn]
and a
jr z, .got_moves
ld hl, wBattleMonMoves
.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, wBattleMonPP - wBattleMonMoves
add hl, bc
pop bc
ld a, [hl]
and PP_MASK
jr z, .failed
push bc
call GetMoveName
; lose 2-5 PP
call BattleRandom
and %11
inc a
inc a
ld b, a
ld a, [hl]
and PP_MASK
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, wEnemyMonHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wBattleMonHP
.got_hp
ld de, wCurDamage
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, [wCriticalHit]
cp 2
jr nz, .carry
xor a
ld [wCriticalHit], 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, wPartyMon1Status
ld a, [hBattleTurn]
and a
jr z, .got_status
ld de, wOTPartyMon1Status
.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 [wFXAnimID], a
ld a, d
ld [wFXAnimID + 1], a
ld c, 3
call DelayFrames
callfar PlayBattleAnim
ret
; 35d1c
EnemyHurtItself: ; 35d1c
ld hl, wCurDamage
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, [wEnemySubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
jp nz, SelfInflictDamageToSubstitute
.mimic_sub_check
ld a, [hld]
ld b, a
ld a, [wEnemyMonHP + 1]
ld [wBuffer3], a
sub b
ld [wEnemyMonHP + 1], a
ld a, [hl]
ld b, a
ld a, [wEnemyMonHP]
ld [wBuffer4], a
sbc b
ld [wEnemyMonHP], a
jr nc, .mimic_faint
ld a, [wBuffer4]
ld [hli], a
ld a, [wBuffer3]
ld [hl], a
xor a
ld hl, wEnemyMonHP
ld [hli], a
ld [hl], a
.mimic_faint
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer1], a
ld hl, wEnemyMonHP
ld a, [hli]
ld [wBuffer6], a
ld a, [hl]
ld [wBuffer5], a
hlcoord 2, 2
xor a
ld [wWhichHPBar], a
predef AnimateHPBar
.did_no_damage
jp RefreshBattleHuds
; 35d7e
PlayerHurtItself: ; 35d7e
ld hl, wCurDamage
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, [wPlayerSubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
jp nz, SelfInflictDamageToSubstitute
.mimic_sub_check
ld a, [hld]
ld b, a
ld a, [wBattleMonHP + 1]
ld [wBuffer3], a
sub b
ld [wBattleMonHP + 1], a
ld [wBuffer5], a
ld b, [hl]
ld a, [wBattleMonHP]
ld [wBuffer4], a
sbc b
ld [wBattleMonHP], a
ld [wBuffer6], a
jr nc, .mimic_faint
ld a, [wBuffer4]
ld [hli], a
ld a, [wBuffer3]
ld [hl], a
xor a
ld hl, wBattleMonHP
ld [hli], a
ld [hl], a
ld hl, wBuffer5
ld [hli], a
ld [hl], a
.mimic_faint
ld hl, wBattleMonMaxHP
ld a, [hli]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer1], 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, wEnemySubstituteHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld de, wPlayerSubstituteHP
.got_hp
ld hl, wCurDamage
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 [wCurMove], 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, [wAttackMissed]
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, [wInBattleTowerBattle]
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, [wInBattleTowerBattle]
and a
jr nz, .dont_fail
; Not locked-on by the enemy
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_LOCK_ON, a
jr nz, .dont_fail
call BattleRandom
cp 25 percent + 1 ; 25% chance AI fails
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, [wTypeModifier]
and $7f
ret z
call CheckIfTargetIsPoisonType
ret z
call GetOpponentItem
ld a, b
cp HELD_PREVENT_POISON
ret z
ld a, [wEffectFailed]
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, [wTypeModifier]
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, [wInBattleTowerBattle]
and a
jr nz, .mimic_random
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_LOCK_ON, a
jr nz, .mimic_random
call BattleRandom
cp 25 percent + 1 ; 25% chance AI fails
jr c, .failed
.mimic_random
call CheckSubstituteOpp
jr nz, .failed
ld a, [wAttackMissed]
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, wEnemyToxicCount
jr z, .ok
ld de, wPlayerToxicCount
.ok
ld a, BATTLE_VARS_MOVE_EFFECT
call GetBattleVar
cp EFFECT_TOXIC
ret
; 35fe1
CheckIfTargetIsPoisonType: ; 35fe1
ld de, wEnemyMonType1
ld a, [hBattleTurn]
and a
jr z, .ok
ld de, wBattleMonType1
.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, wCurDamage
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, wBattleMonHP
ld de, wBattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .battlemonhp
ld hl, wEnemyMonHP
ld de, wEnemyMonMaxHP
.battlemonhp
ld bc, wBuffer4
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 [wBuffer5], a
ld a, [hDividend]
ld b, [hl]
adc b
ld [hli], a
ld [wBuffer6], 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 [wBuffer5], a
dec de
ld a, [de]
ld [hli], a
ld [wBuffer6], 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, [wTypeModifier]
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, [wEffectFailed]
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, [wCurOTMon]
ld hl, wOTPartyMon1Status
jr z, .ok
ld hl, wPartyMon1Status
ld a, [wCurBattleMon]
.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, [wTypeModifier]
and $7f
ret z
ld a, [wBattleWeather]
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, [wEffectFailed]
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, [wTypeModifier]
and $7f
ret z
call GetOpponentItem
ld a, b
cp HELD_PREVENT_PARALYZE
ret z
ld a, [wEffectFailed]
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, [wFailedMessage]
and a
ret nz
jp StatUpAnimation
; 361ef
CheckIfStatCanBeRaised: ; 361ef
ld a, b
ld [wLoweredStat], a
ld hl, wPlayerStatLevels
ld a, [hBattleTurn]
and a
jr z, .got_stat_levels
ld hl, wEnemyStatLevels
.got_stat_levels
ld a, [wAttackMissed]
and a
jp nz, .stat_raise_failed
ld a, [wEffectFailed]
and a
jp nz, .stat_raise_failed
ld a, [wLoweredStat]
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, [wLoweredStat]
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, wBattleMonStats + 1
ld de, wPlayerStats
ld a, [hBattleTurn]
and a
jr z, .got_stats_pointer
ld hl, wEnemyMonStats + 1
ld de, wEnemyStats
.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 [wFailedMessage], a
ret
; 3626e
.stats_already_max ; 3626e
pop hl
dec [hl]
; fallthrough
; 36270
.cant_raise_stat ; 36270
ld a, $2
ld [wFailedMessage], a
ld a, $1
ld [wAttackMissed], a
ret
; 3627b
.stat_raise_failed ; 3627b
ld a, $1
ld [wFailedMessage], 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 [wLoweredStat], a
call CheckMist
jp nz, .Mist
ld hl, wEnemyStatLevels
ld a, [hBattleTurn]
and a
jr z, .GetStatLevel
ld hl, wPlayerStatLevels
.GetStatLevel:
; Attempt to lower the stat.
ld a, [wLoweredStat]
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, [wLoweredStat]
and $f0
jr z, .ComputerMiss
dec b
jr nz, .ComputerMiss
inc b
.ComputerMiss:
; Computer opponents have a 25% chance of failing.
ld a, [hBattleTurn]
and a
jr z, .DidntMiss
ld a, [wLinkMode]
and a
jr nz, .DidntMiss
ld a, [wInBattleTowerBattle]
and a
jr nz, .DidntMiss
; Lock-On still always works.
ld a, [wPlayerSubStatus5]
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 25 percent + 1 ; 25% chance AI fails
jr c, .Failed
.DidntMiss:
call CheckSubstituteOpp
jr nz, .Failed
ld a, [wAttackMissed]
and a
jr nz, .Failed
ld a, [wEffectFailed]
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, wEnemyMonAttack + 1
ld de, wEnemyStats
ld a, [hBattleTurn]
and a
jr z, .do_enemy
ld hl, wBattleMonAttack + 1
ld de, wPlayerStats
.do_enemy
call TryLowerStat
pop hl
jr z, .CouldntLower
.Hit:
xor a
ld [wFailedMessage], a
ret
.CouldntLower:
inc [hl]
.CantLower:
ld a, 3
ld [wFailedMessage], a
ld a, 1
ld [wAttackMissed], a
ret
.Failed:
ld a, 1
ld [wFailedMessage], a
ld [wAttackMissed], a
ret
.Mist:
ld a, 2
ld [wFailedMessage], a
ld a, 1
ld [wAttackMissed], 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, [wFailedMessage]
and a
ret nz
ld a, [wLoweredStat]
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, [wLoweredStat]
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, [wFailedMessage]
and a
ret nz
ld a, [wLoweredStat]
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, [wLoweredStat]
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, [wFailedMessage]
and a
ret z
push af
call BattleCommand_MoveDelay
pop af
dec a
jp z, TryPrintButItFailed
ld a, [wLoweredStat]
and $f
ld b, a
inc b
call GetStatName
ld hl, WontRiseAnymoreText
jp StdBattleTextBox
; 3646a
BattleCommand_StatDownFailText: ; 3646a
; statdownfailtext
ld a, [wFailedMessage]
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, [wLoweredStat]
and $f
ld b, a
inc b
call GetStatName
ld hl, WontDropAnymoreText
jp StdBattleTextBox
; 3648f
GetStatName: ; 3648f
ld hl, StatNames
ld c, "@"
.CheckName:
dec b
jr z, .Copy
.GetName:
ld a, [hli]
cp c
jr z, .CheckName
jr .GetName
.Copy:
ld de, wStringBuffer2
ld bc, wStringBuffer3 - wStringBuffer2
jp CopyBytes
INCLUDE "data/battle/stat_names.asm"
INCLUDE "data/battle/stat_multipliers.asm"
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 [wAttackMissed], a
ret
; 36532
LowerStat: ; 36532
ld [wLoweredStat], a
ld hl, wPlayerStatLevels
ld a, [hBattleTurn]
and a
jr z, .got_target
ld hl, wEnemyStatLevels
.got_target
ld a, [wLoweredStat]
and $f
ld c, a
ld b, 0
add hl, bc
ld b, [hl]
dec b
jr z, .cant_lower_anymore
ld a, [wLoweredStat]
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, wBattleMonStats + 1
ld de, wPlayerStats
ld a, [hBattleTurn]
and a
jr z, .got_target_2
ld hl, wEnemyMonStats + 1
ld de, wEnemyStats
.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 [wFailedMessage], a
ret
.failed
inc [hl]
.cant_lower_anymore
ld a, 2
ld [wFailedMessage], a
ret
; 3658f
BattleCommand_TriStatusChance: ; 3658f
; tristatuschance
call BattleCommand_EffectChance
.loop
; 1/3 chance of each status
call BattleRandom
swap a
and %11
jr z, .loop
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, wPlayerAtkLevel
ld de, wPlayerStats
ld bc, wBattleMonAttack
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, wEnemyAtkLevel
ld de, wEnemyStats
ld bc, wEnemyMonAttack
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, wPlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .check_still_storing_energy
ld hl, wEnemyRolloutCount
.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, wPlayerDamageTaken + 1
ld de, wPlayerCharging ; player
ld a, [hBattleTurn]
and a
jr z, .player
ld hl, wEnemyDamageTaken + 1
ld de, wEnemyCharging ; enemy
.player
ld a, [hld]
add a
ld b, a
ld [wCurDamage + 1], a
ld a, [hl]
rl a
ld [wCurDamage], a
jr nc, .not_maxed
ld a, $ff
ld [wCurDamage], a
ld [wCurDamage + 1], a
.not_maxed
or b
jr nz, .built_up_something
ld a, 1
ld [wAttackMissed], 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, wPlayerDamageTaken
ld bc, wPlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .got_damage
ld de, wEnemyDamageTaken
ld bc, wEnemyRolloutCount
.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, wPlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .player
ld de, wEnemyRolloutCount
.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, wPlayerRolloutCount
ld a, [hBattleTurn]
and a
jr z, .ok
ld de, wEnemyRolloutCount
.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, [wBattleType]
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, [wCurPartyLevel]
ld b, a
ld a, [wBattleMonLevel]
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, [wBattleMonLevel]
ld b, a
ld a, [wCurPartyLevel]
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, [wBattleType]
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, [wAttackMissed]
and a
jr nz, .missed
ld a, [wBattleMode]
dec a
jr nz, .trainer
ld a, [wCurPartyLevel]
ld b, a
ld a, [wBattleMonLevel]
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, [wOTPartyCount]
ld b, a
ld a, [wCurOTMon]
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, wOTPartyMon1HP
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, [wAttackMissed]
and a
jr nz, .player_miss
ld a, [wBattleMode]
dec a
jr nz, .vs_trainer
ld a, [wBattleMonLevel]
ld b, a
ld a, [wCurPartyLevel]
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, [wPartyCount]
ld b, a
ld a, [wCurBattleMon]
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, wPartyMon1HP
call GetPartyLocation
ld a, [hli]
or [hl]
pop bc
pop de
jr z, .random_loop_trainer_playeristarget
ld a, d
ld [wCurPartyMon], 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, [wPartyCount]
ld d, a
ld e, 0
ld bc, PARTYMON_STRUCT_LENGTH
.loop
ld a, [wCurBattleMon]
cp e
jr z, .next
ld a, e
ld hl, wPartyMon1HP
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, wPlayerRolloutCount
ld bc, wPlayerDamageTaken
ld a, [hBattleTurn]
and a
jr z, .got_addrs
ld de, wEnemyRolloutCount
ld bc, wEnemyDamageTaken
.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, [wPartyCount]
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, [wOTPartyCount]
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, [wBattleScriptBufferAddress + 1]
ld h, a
ld a, [wBattleScriptBufferAddress]
ld l, a
.not_critical
ld a, [hld]
cp critical_command
jr nz, .not_critical
inc hl
ld a, h
ld [wBattleScriptBufferAddress + 1], a
ld a, l
ld [wBattleScriptBufferAddress], a
ret
; 36a82
BattleCommand_FakeOut: ; 36a82
ld a, [wAttackMissed]
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 [wAttackMissed], 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, [wEffectFailed]
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, [wAttackMissed]
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, [wTypeModifier]
and $7f
jr z, .no_effect
ld hl, wEnemyMonLevel
ld de, wBattleMonLevel
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, wCurDamage
ld a, $ff
ld [hli], a
ld [hl], a
ld a, $2
ld [wCriticalHit], a
ret
.no_effect
ld a, $ff
ld [wCriticalHit], a
ld a, $1
ld [wAttackMissed], 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, [wAlreadyDisobeyed]
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, [wAttackMissed]
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
; trapped for 2-5 turns
and %11
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, wBattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wEnemyMonMaxHP
.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, [wCurDamage]
ld b, a
ld a, [wCurDamage + 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 [wBuffer2], a
ld a, [hl]
ld [wBuffer1], a
dec hl
dec hl
ld a, [hl]
ld [wBuffer3], a
sub c
ld [hld], a
ld [wBuffer5], a
ld a, [hl]
ld [wBuffer4], a
sbc b
ld [hl], a
ld [wBuffer6], a
jr nc, .dont_ko
xor a
ld [hli], a
ld [hl], a
ld hl, wBuffer5
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, [wEffectFailed]
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, [wAttackMissed]
and a
jr nz, BattleCommand_Confuse_CheckSnore_Swagger_ConfuseHit
BattleCommand_FinishConfusingTarget: ; 36d70
ld bc, wEnemyConfuseCount
ld a, [hBattleTurn]
and a
jr z, .got_confuse_count
ld bc, wPlayerConfuseCount
.got_confuse_count
set SUBSTATUS_CONFUSED, [hl]
; confused for 2-5 turns
call BattleRandom
and %11
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, [wTypeModifier]
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, [wInBattleTowerBattle]
and a
jr nz, .dont_sample_failure
ld a, [wPlayerSubStatus5]
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, [wAttackMissed]
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, wEnemyMonType1
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wBattleMonType1
.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, wBattleMonMaxHP
ld de, wPlayerSubstituteHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wEnemyMonMaxHP
ld de, wEnemySubstituteHP
.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 [wFXAnimID + 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, wCurDamage + 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, [wAttackMissed]
and a
jr nz, .fail
ld hl, wBattleMonMoves
ld a, [hBattleTurn]
and a
jr z, .player_turn
ld hl, wEnemyMonMoves
.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, wBattleMonPP - wBattleMonMoves
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, [wAttackMissed]
and a
jr nz, .evaded
call CheckSubstituteOpp
jr nz, .evaded
ld de, wEnemyMonType1
ld a, [hBattleTurn]
and a
jr z, .ok
ld de, wBattleMonType1
.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 StubbedTrainerRankings_Splash
jp PrintNothingHappened
; 36fed
BattleCommand_Disable: ; 36fed
; disable
ld a, [wAttackMissed]
and a
jr nz, .failed
ld de, wEnemyDisableCount
ld hl, wEnemyMonMoves
ld a, [hBattleTurn]
and a
jr z, .got_moves
ld de, wPlayerDisableCount
ld hl, wBattleMonMoves
.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, wEnemyMonPP
jr z, .got_pp
ld hl, wBattleMonPP
.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, wDisabledMove
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, wStringBuffer1
ld [hli], a
ld a, [hBattleTurn]
and a
ld a, [wBattleMonLevel]
jr z, .ok
ld a, [wEnemyMonLevel]
.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, wBattleMonMoves
ld de, wBattleMonType1
ld a, [hBattleTurn]
and a
jr z, .got_moves
ld hl, wEnemyMonMoves
ld de, wEnemyMonType1
.got_moves
push de
ld c, 0
ld de, wStringBuffer1
.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, wStringBuffer1
.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
maskbits NUM_MOVES
ld c, a
ld b, 0
ld hl, wStringBuffer1
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, wPlayerStatLevels
call .Fill
ld hl, wEnemyStatLevels
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, wPlayerStatLevelsEnd - wPlayerStatLevels
.next
ld [hli], a
dec b
jr nz, .next
ret
; 3713e
BattleCommand_Heal: ; 3713e
; heal
ld de, wBattleMonHP
ld hl, wBattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld de, wEnemyMonHP
ld hl, wEnemyMonMaxHP
.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 [wEnemyDisableCount], a
ld [wEnemyDisabledMove], a
ret
.player
xor a
ld [wPlayerDisableCount], a
ld [wDisabledMove], a
ret
; 372fc
BattleCommand_Screen: ; 372fc
; screen
ld hl, wPlayerScreens
ld bc, wPlayerLightScreenCount
ld a, [hBattleTurn]
and a
jr z, .got_screens_pointer
ld hl, wEnemyScreens
ld bc, wEnemyLightScreenCount
.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, [wAlreadyFailed]
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 StubbedTrainerRankings_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, wBattleMonMoves
ld a, [hBattleTurn]
and a
jr z, .ok
ld de, wEnemyMonMoves
.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 [wAlreadyDisobeyed], 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, wPlayerFuryCutterCount
ld a, [hBattleTurn]
and a
jr z, .go
ld hl, wEnemyFuryCutterCount
.go
ld a, [wAttackMissed]
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, wCurDamage + 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, wPlayerFuryCutterCount
ld a, [hBattleTurn]
and a
jr z, .reset
ld hl, wEnemyFuryCutterCount
.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, wBattleMonHappiness
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHappiness
.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, wBattleMonHappiness
ld a, [hBattleTurn]
and a
jr z, .got_happiness
ld hl, wEnemyMonHappiness
.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, wPlayerScreens
ld de, wPlayerSafeguardCount
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyScreens
ld de, wEnemySafeguardCount
.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, wEnemyScreens
ld a, [hBattleTurn]
and a
jr z, .got_turn
ld hl, wPlayerScreens
.got_turn
bit SCREENS_SAFEGUARD, [hl]
pop hl
ret
; 37972
BattleCommand_CheckSafeguard: ; 37972
; checksafeguard
ld hl, wEnemyScreens
ld a, [hBattleTurn]
and a
jr z, .got_turn
ld hl, wPlayerScreens
.got_turn
bit SCREENS_SAFEGUARD, [hl]
ret z
ld a, 1
ld [wAttackMissed], 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 [wBattlePlayerAction], a
call LoadStandardMenuDataHeader
ld hl, LinkBattleSendReceiveAction
call CallBattleCore
call CloseWindow
xor a
ld [wBattlePlayerAction], a
ret
; 37a82
BatonPass_LinkEnemySwitch: ; 37a82
ld a, [wLinkMode]
and a
ret z
call LoadStandardMenuDataHeader
ld hl, LinkBattleSendReceiveAction
call CallBattleCore
ld a, [wOTPartyCount]
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, [wCurOTMon]
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, wPlayerSubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, wEnemySubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, wPlayerSubStatus5
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, wPartyMon1HP
ld a, [wPartyCount]
ld d, a
ld a, [wCurBattleMon]
ld e, a
jr CheckAnyOtherAliveMons
; 37af6
CheckAnyOtherAliveEnemyMons: ; 37af6
ld hl, wOTPartyMon1HP
ld a, [wOTPartyCount]
ld d, a
ld a, [wCurOTMon]
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, wCurDamage + 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, wPlayerScreens
ld de, wPlayerWrapCount
ld a, [hBattleTurn]
and a
jr z, .got_screens_wrap
ld hl, wEnemyScreens
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, wBattleMonMaxHP
ld de, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .start
ld hl, wEnemyMonMaxHP
ld de, wEnemyMonHP
.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, .checkWeather
ld a, [wTimeOfDay]
cp b
jr z, .checkWeather
dec c ; double
.checkWeather:
ld a, [wBattleWeather]
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, [wAttackMissed]
and a
ret nz
farcall HiddenPowerDamage
ret
; 37bf4
BattleCommand_StartRain: ; 37bf4
; startrain
ld a, WEATHER_RAIN
ld [wBattleWeather], a
ld a, 5
ld [wWeatherCount], a
call AnimateCurrentMove
ld hl, DownpourText
jp StdBattleTextBox
; 37c07
BattleCommand_StartSun: ; 37c07
; startsun
ld a, WEATHER_SUN
ld [wBattleWeather], a
ld a, 5
ld [wWeatherCount], 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, [wAttackMissed]
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, wEnemyStatLevels
ld de, wPlayerStatLevels
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 [wAttackMissed], 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, wStringBuffer1
call GetMoveData
ld a, [wStringBuffer1 + 2]
and a
ret z
ld a, [wStringBuffer1 + 3]
cp SPECIAL
ret c
ld hl, wCurDamage
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 [wAttackMissed], 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, wCurDamage + 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, [wBattleWeather]
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 [wCurDamage], a
ld a, [de]
ld [wCurDamage + 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, wCurDamage
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, [wBattleWeather]
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.
; Uncomment the lines below to fix.
; ld a, BATTLE_VARS_SUBSTATUS5_OPP
; call GetBattleVar
; bit SUBSTATUS_LOCK_ON, a
; ret z
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, wBattleMonItem
ld a, [hBattleTurn]
and a
jr z, .go
ld hl, wEnemyMonItem
.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, wEnemyMonItem
ld a, [hBattleTurn]
and a
jr z, .go
ld hl, wBattleMonItem
.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 [wFXAnimID + 1], a
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
and a
ret z
ld [wFXAnimID], 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 [wFXAnimID + 1], a
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
and a
ret z
; fallthrough
; 37e44
LoadAnim: ; 37e44
ld [wFXAnimID], 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 [wFXAnimID], a
ld a, d
ld [wFXAnimID + 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, [wBattleScriptBufferAddress + 1]
ld h, a
ld a, [wBattleScriptBufferAddress]
ld l, a
.loop
ld a, [hli]
cp b
jr nz, .loop
ld a, h
ld [wBattleScriptBufferAddress + 1], a
ld a, l
ld [wBattleScriptBufferAddress], 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