pokecrystal-board/engine/battle/effect_commands.asm
mid-kid d4025863cf Rename some battle commands
`hittarget` was misleading, as it doesn't actually "hit" the target, it
only plays the animation. As such, I've renamed it to `moveanim`.

`checkfaint` has nothing to do with checking if the user or target has
fainted, instead, it applies wCurDamage onto the target's HP, hitting
the substitute if applicable. I've renamed the command to `applydamage`
and all of its subfunctions accordingly.
2018-04-04 23:27:40 +02:00

7516 lines
108 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 50 percent + 1
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, TRUE
call DoEnemyDamage
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 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, [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, TRUE
call DoPlayerDamage
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
INCLUDE "engine/battle/move_effects/triple_kick.asm"
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/types/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_MoveAnim: ; 34f57
; moveanim
call BattleCommand_LowerSub
call BattleCommand_MoveAnimNoSub
jp BattleCommand_RaiseSub
; 34f60
BattleCommand_MoveAnimNoSub: ; 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, .alternate_anim
cp EFFECT_CONVERSION
jr z, .alternate_anim
cp EFFECT_DOUBLE_HIT
jr z, .alternate_anim
cp EFFECT_POISON_MULTI_HIT
jr z, .alternate_anim
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, .clear_sprite
cp DIG
ret nz
.clear_sprite
jp AppearUserLowerSub
.alternate_anim
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_ApplyDamage: ; 3505e
; applydamage
ld a, BATTLE_VARS_SUBSTATUS1_OPP
call GetBattleVar
bit SUBSTATUS_ENDURE, a
jr z, .focus_band
call BattleCommand_FalseSwipe
ld b, 0
jr nc, .damage
ld b, 1
jr .damage
.focus_band
call GetOpponentItem
ld a, b
cp HELD_FOCUS_BAND
ld b, 0
jr nz, .damage
call BattleRandom
cp c
jr nc, .damage
call BattleCommand_FalseSwipe
ld b, 0
jr nc, .damage
ld b, 2
.damage
push bc
call .update_damage_taken
ld c, FALSE
ld a, [hBattleTurn]
and a
jr nz, .damage_player
call DoEnemyDamage
jr .done_damage
.damage_player
call DoPlayerDamage
.done_damage
pop bc
ld a, b
and a
ret z
dec a
jr nz, .focus_band_text
ld hl, EnduredText
jp StdBattleTextBox
.focus_band_text
call GetOpponentItem
ld a, [hl]
ld [wNamedObjectIndexBuffer], a
call GetItemName
ld hl, HungOnText
jp StdBattleTextBox
.update_damage_taken
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, .got_damage_taken
ld de, wEnemyDamageTaken + 1
.got_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, TRUE
ld a, [hBattleTurn]
and a
jp nz, DoEnemyDamage
jp DoPlayerDamage
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
BattleCommand_BideFailText: ; 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, $ffff
.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
INCLUDE "engine/battle/move_effects/beat_up.asm"
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/types/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, FlailReversalPower
.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
INCLUDE "data/moves/flail_reversal_power.asm"
INCLUDE "engine/battle/move_effects/counter.asm"
INCLUDE "engine/battle/move_effects/encore.asm"
INCLUDE "engine/battle/move_effects/pain_split.asm"
INCLUDE "engine/battle/move_effects/snore.asm"
INCLUDE "engine/battle/move_effects/conversion2.asm"
INCLUDE "engine/battle/move_effects/lock_on.asm"
INCLUDE "engine/battle/move_effects/sketch.asm"
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
INCLUDE "engine/battle/move_effects/sleep_talk.asm"
INCLUDE "engine/battle/move_effects/destiny_bond.asm"
INCLUDE "engine/battle/move_effects/spite.asm"
INCLUDE "engine/battle/move_effects/false_swipe.asm"
INCLUDE "engine/battle/move_effects/heal_bell.asm"
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
DoEnemyDamage: ; 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, .ignore_substitute
ld a, [wEnemySubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
jp nz, DoSubstituteDamage
.ignore_substitute
; Substract wCurDamage from wEnemyMonHP.
; store original HP in little endian wBuffer3/4
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, .no_underflow
ld a, [wBuffer4]
ld [hli], a
ld a, [wBuffer3]
ld [hl], a
xor a
ld hl, wEnemyMonHP
ld [hli], a
ld [hl], a
.no_underflow
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
DoPlayerDamage: ; 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, .ignore_substitute
ld a, [wPlayerSubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
jp nz, DoSubstituteDamage
.ignore_substitute
; Substract wCurDamage from wBattleMonHP.
; store original HP in little endian wBuffer3/4
; store new HP in little endian wBuffer5/6
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, .no_underflow
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
.no_underflow
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
DoSubstituteDamage: ; 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, .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 25 percent + 1 ; 25% chance AI fails
jr c, .failed
.dont_sample_failure
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
; Divide damage by 2, store it in hDividend
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, .at_least_one
ld a, 1
ld [hDividend + 1], a
.at_least_one
ld hl, wBattleMonHP
ld de, wBattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .battlemonhp
ld hl, wEnemyMonHP
ld de, wEnemyMonMaxHP
.battlemonhp
; Store current HP in little endian wBuffer3/4
ld bc, wBuffer4
ld a, [hli]
ld [bc], a
ld a, [hl]
dec bc
ld [bc], a
; Store max HP in little endian wBuffer1/2
ld a, [de]
dec bc
ld [bc], a
inc de
ld a, [de]
dec bc
ld [bc], a
; Add hDividend to current HP and copy it to little endian wBuffer5/6
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, .max_hp
; Substract current HP from max HP (to see if we have more than max HP)
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, .finish
.max_hp
; Load max HP into current HP and copy it to little endian wBuffer5/6
ld a, [de]
ld [hld], a
ld [wBuffer5], a
dec de
ld a, [de]
ld [hli], a
ld [wBuffer6], a
inc de
.finish
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
INCLUDE "engine/battle/move_effects/bide.asm"
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
INCLUDE "engine/battle/move_effects/teleport.asm"
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 '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 BattleCommand_BeatUpFailText
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_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
INCLUDE "engine/battle/move_effects/mist.asm"
INCLUDE "engine/battle/move_effects/focus_energy.asm"
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 25 percent + 1 ; 25% chance AI fails
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
INCLUDE "engine/battle/move_effects/substitute.asm"
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
INCLUDE "engine/battle/move_effects/rage.asm"
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
INCLUDE "engine/battle/move_effects/mimic.asm"
INCLUDE "engine/battle/move_effects/leech_seed.asm"
INCLUDE "engine/battle/move_effects/splash.asm"
INCLUDE "engine/battle/move_effects/disable.asm"
INCLUDE "engine/battle/move_effects/pay_day.asm"
INCLUDE "engine/battle/move_effects/conversion.asm"
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/move_effects/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
FailMove:
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
INCLUDE "engine/battle/move_effects/selfdestruct.asm"
INCLUDE "engine/battle/move_effects/mirror_move.asm"
INCLUDE "engine/battle/move_effects/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/move_effects/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/move_effects/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/move_effects/curse.asm"
INCLUDE "engine/battle/move_effects/protect.asm"
INCLUDE "engine/battle/move_effects/endure.asm"
INCLUDE "engine/battle/move_effects/spikes.asm"
INCLUDE "engine/battle/move_effects/foresight.asm"
INCLUDE "engine/battle/move_effects/perish_song.asm"
INCLUDE "engine/battle/move_effects/sandstorm.asm"
INCLUDE "engine/battle/move_effects/rollout.asm"
BattleCommand5d: ; 37791
; unused
ret
; 37792
INCLUDE "engine/battle/move_effects/fury_cutter.asm"
INCLUDE "engine/battle/move_effects/attract.asm"
INCLUDE "engine/battle/move_effects/return.asm"
INCLUDE "engine/battle/move_effects/present.asm"
INCLUDE "engine/battle/move_effects/frustration.asm"
INCLUDE "engine/battle/move_effects/safeguard.asm"
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
INCLUDE "engine/battle/move_effects/magnitude.asm"
INCLUDE "engine/battle/move_effects/baton_pass.asm"
INCLUDE "engine/battle/move_effects/pursuit.asm"
INCLUDE "engine/battle/move_effects/rapid_spin.asm"
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, .Weather
ld a, [wTimeOfDay]
cp b
jr z, .Weather
dec c ; double
.Weather:
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
INCLUDE "engine/battle/move_effects/hidden_power.asm"
INCLUDE "engine/battle/move_effects/rain_dance.asm"
INCLUDE "engine/battle/move_effects/sunny_day.asm"
INCLUDE "engine/battle/move_effects/belly_drum.asm"
INCLUDE "engine/battle/move_effects/psych_up.asm"
INCLUDE "engine/battle/move_effects/mirror_coat.asm"
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
INCLUDE "engine/battle/move_effects/future_sight.asm"
INCLUDE "engine/battle/move_effects/thunder.asm"
CheckHiddenOpponent: ; 37daa
; BUG: This routine should account for Lock-On and Mind Reader.
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVar
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
ret
; 37db2
GetUserItem: ; 37db2
; Return the effect of the user's item in bc, and its id at hl.
ld hl, 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