pokecrystal-board/engine/battle/core.asm
mid-kid e8bc86d1fe Pkmn -> Mon
Since we're aiming for consistency across the codebase, I believe it
includes a uniform way to refer to the creatures this game consists of
in the labels of the code.
The only exceptions to this rule are labels referring to things named
through the use of the <PK><MN> or <PKMN> characters, in which case PKMN
is used.

Most of this was already consistent enoughâ„¢, I just picked the
convention with the most occurences and fixed the outliers.
2018-02-22 17:39:06 +01:00

9447 lines
146 KiB
NASM

; Core components of the battle engine.
BattleCore:
DoBattle: ; 3c000
xor a
ld [wBattleParticipantsNotFainted], a
ld [wBattleParticipantsIncludingFainted], a
ld [wBattlePlayerAction], a
ld [wBattleEnded], a
inc a
ld [wBattleHasJustStarted], a
ld hl, wOTPartyMon1HP
ld bc, PARTYMON_STRUCT_LENGTH - 1
ld d, BATTLEACTION_SWITCH1 - 1
.loop
inc d
ld a, [hli]
or [hl]
jr nz, .alive
add hl, bc
jr .loop
.alive
ld a, d
ld [wBattleAction], a
ld a, [wLinkMode]
and a
jr z, .not_linked
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr z, .player_2
.not_linked
ld a, [wBattleMode]
dec a
jr z, .wild
xor a
ld [wEnemySwitchMonIndex], a
call NewEnemyMonStatus
call ResetEnemyStatLevels
call BreakAttraction
call EnemySwitch
.wild
ld c, 40
call DelayFrames
.player_2
call LoadTileMapToTempTileMap
call CheckPlayerPartyForFitMon
ld a, d
and a
jp z, LostBattle
call Call_LoadTempTileMapToTileMap
ld a, [wBattleType]
cp BATTLETYPE_DEBUG
jp z, .tutorial_debug
cp BATTLETYPE_TUTORIAL
jp z, .tutorial_debug
xor a
ld [wCurPartyMon], a
.loop2
call CheckIfCurPartyMonIsFitToFight
jr nz, .alive2
ld hl, wCurPartyMon
inc [hl]
jr .loop2
.alive2
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
inc a
ld hl, wPartySpecies - 1
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [wCurPartySpecies], a
ld [wTempBattleMonSpecies], a
hlcoord 1, 5
ld a, 9
call SlideBattlePicOut
call LoadTileMapToTempTileMap
call ResetBattleParticipants
call InitBattleMon
call ResetPlayerStatLevels
call SendOutMonText
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
call SetPlayerTurn
call SpikesDamage
ld a, [wLinkMode]
and a
jr z, .not_linked_2
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr nz, .not_linked_2
xor a
ld [wEnemySwitchMonIndex], a
call NewEnemyMonStatus
call ResetEnemyStatLevels
call BreakAttraction
call EnemySwitch
call SetEnemyTurn
call SpikesDamage
.not_linked_2
jp BattleTurn
.tutorial_debug
jp BattleMenu
; 3c0e5
WildFled_EnemyFled_LinkBattleCanceled: ; 3c0e5
call Call_LoadTempTileMapToTileMap
ld a, [wBattleResult]
and $c0
add $2
ld [wBattleResult], a
ld a, [wLinkMode]
and a
ld hl, BattleText_WildFled
jr z, .print_text
ld a, [wBattleResult]
and $c0
ld [wBattleResult], a
ld hl, BattleText_EnemyFled
call CheckMobileBattleError
jr nc, .print_text
ld hl, wcd2a
bit 4, [hl]
jr nz, .skip_text
ld hl, BattleText_LinkErrorBattleCanceled
.print_text
call StdBattleTextBox
.skip_text
call StopDangerSound
call CheckMobileBattleError
jr c, .skip_sfx
ld de, SFX_RUN
call PlaySFX
.skip_sfx
call SetPlayerTurn
ld a, 1
ld [wBattleEnded], a
ret
; 3c12f
BattleTurn: ; 3c12f
.loop
call Stubbed_Function3c1bf
call CheckContestBattleOver
jp c, .quit
xor a
ld [wPlayerIsSwitching], a
ld [wEnemyIsSwitching], a
ld [wBattleHasJustStarted], a
ld [wPlayerJustGotFrozen], a
ld [wEnemyJustGotFrozen], a
ld [wCurDamage], a
ld [wCurDamage + 1], a
call HandleBerserkGene
call UpdateBattleMonInParty
farcall AIChooseMove
call IsMobileBattle
jr nz, .not_disconnected
farcall Function100da5
farcall StartMobileInactivityTimer
farcall Function100dd8
jp c, .quit
.not_disconnected
call CheckPlayerLockedIn
jr c, .skip_iteration
.loop1
call BattleMenu
jr c, .quit
ld a, [wBattleEnded]
and a
jr nz, .quit
ld a, [wForcedSwitch] ; roared/whirlwinded/teleported
and a
jr nz, .quit
.skip_iteration
call ParsePlayerAction
jr nz, .loop1
call EnemyTriesToFlee
jr c, .quit
call DetermineMoveOrder
jr c, .false
call Battle_EnemyFirst
jr .proceed
.false
call Battle_PlayerFirst
.proceed
call CheckMobileBattleError
jr c, .quit
ld a, [wForcedSwitch]
and a
jr nz, .quit
ld a, [wBattleEnded]
and a
jr nz, .quit
call HandleBetweenTurnEffects
ld a, [wBattleEnded]
and a
jr nz, .quit
jp .loop
.quit
ret
; 3c1bf
Stubbed_Function3c1bf:
ret
ld a, 5 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
call GetSRAMBank
ld hl, $a89b ; address of MBC30 bank
inc [hl]
jr nz, .finish
dec hl
inc [hl]
jr nz, .finish
dec [hl]
inc hl
dec [hl]
.finish
call CloseSRAM
ret
; 3c1d6
HandleBetweenTurnEffects: ; 3c1d6
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .CheckEnemyFirst
call CheckFaint_PlayerThenEnemy
ret c
call HandleFutureSight
call CheckFaint_PlayerThenEnemy
ret c
call HandleWeather
call CheckFaint_PlayerThenEnemy
ret c
call HandleWrap
call CheckFaint_PlayerThenEnemy
ret c
call HandlePerishSong
call CheckFaint_PlayerThenEnemy
ret c
jr .NoMoreFaintingConditions
.CheckEnemyFirst:
call CheckFaint_EnemyThenPlayer
ret c
call HandleFutureSight
call CheckFaint_EnemyThenPlayer
ret c
call HandleWeather
call CheckFaint_EnemyThenPlayer
ret c
call HandleWrap
call CheckFaint_EnemyThenPlayer
ret c
call HandlePerishSong
call CheckFaint_EnemyThenPlayer
ret c
.NoMoreFaintingConditions:
call HandleLeftovers
call HandleMysteryberry
call HanleDefrost
call HandleSafeguard
call HandleScreens
call HandleStatBoostingHeldItems
call HandleHealingItems
call UpdateBattleMonInParty
call LoadTileMapToTempTileMap
jp HandleEncore
; 3c23c
CheckFaint_PlayerThenEnemy: ; 3c23c
call HasPlayerFainted
jr nz, .PlayerNotFainted
call HandlePlayerMonFaint
ld a, [wBattleEnded]
and a
jr nz, .BattleIsOver
.PlayerNotFainted:
call HasEnemyFainted
jr nz, .BattleContinues
call HandleEnemyMonFaint
ld a, [wBattleEnded]
and a
jr nz, .BattleIsOver
.BattleContinues:
and a
ret
.BattleIsOver:
scf
ret
; 3c25c
CheckFaint_EnemyThenPlayer: ; 3c25c
call HasEnemyFainted
jr nz, .EnemyNotFainted
call HandleEnemyMonFaint
ld a, [wBattleEnded]
and a
jr nz, .BattleIsOver
.EnemyNotFainted:
call HasPlayerFainted
jr nz, .BattleContinues
call HandlePlayerMonFaint
ld a, [wBattleEnded]
and a
jr nz, .BattleIsOver
.BattleContinues:
and a
ret
.BattleIsOver:
scf
ret
; 3c27c
HandleBerserkGene: ; 3c27c
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .reverse
call .player
jr .enemy
.reverse
call .enemy
; jr .player
.player
call SetPlayerTurn
ld de, wPartyMon1Item
ld a, [wCurBattleMon]
ld b, a
jr .go
.enemy
call SetEnemyTurn
ld de, wOTPartyMon1Item
ld a, [wCurOTMon]
ld b, a
; jr .go
.go
push de
push bc
callfar GetUserItem
ld a, [hl]
ld [wd265], a
sub BERSERK_GENE
pop bc
pop de
ret nz
ld [hl], a
ld h, d
ld l, e
ld a, b
call GetPartyLocation
xor a
ld [hl], a
ld a, BATTLE_VARS_SUBSTATUS3
call GetBattleVarAddr
push af
set SUBSTATUS_CONFUSED, [hl]
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVarAddr
push hl
push af
xor a
ld [hl], a
ld [wAttackMissed], a
ld [wEffectFailed], a
farcall BattleCommand_AttackUp2
pop af
pop hl
ld [hl], a
call GetItemName
ld hl, BattleText_UsersStringBuffer1Activated
call StdBattleTextBox
callfar BattleCommand_StatUpMessage
pop af
bit SUBSTATUS_CONFUSED, a
ret nz
xor a
ld [wNumHits], a
ld de, ANIM_CONFUSED
call Call_PlayBattleAnim_OnlyIfVisible
call SwitchTurnCore
ld hl, BecameConfusedText
jp StdBattleTextBox
; 3c300
EnemyTriesToFlee: ; 3c300
ld a, [wLinkMode]
and a
jr z, .not_linked
ld a, [wBattleAction]
cp BATTLEACTION_FORFEIT
jr z, .forfeit
.not_linked
and a
ret
.forfeit
call WildFled_EnemyFled_LinkBattleCanceled
scf
ret
; 3c314
DetermineMoveOrder: ; 3c314
ld a, [wLinkMode]
and a
jr z, .use_move
ld a, [wBattleAction]
cp BATTLEACTION_E
jr z, .use_move
cp BATTLEACTION_D
jr z, .use_move
sub BATTLEACTION_SWITCH1
jr c, .use_move
ld a, [wBattlePlayerAction]
cp $2
jr nz, .switch
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr z, .player_2
call BattleRandom
cp 1 + (50 percent)
jp c, .player_first
jp .enemy_first
.player_2
call BattleRandom
cp 1 + (50 percent)
jp c, .enemy_first
jp .player_first
.switch
callfar AI_Switch
call SetEnemyTurn
call SpikesDamage
jp .enemy_first
.use_move
ld a, [wBattlePlayerAction]
and a
jp nz, .player_first
call CompareMovePriority
jr z, .equal_priority
jp c, .player_first ; player goes first
jp .enemy_first
.equal_priority
call SetPlayerTurn
callfar GetUserItem
push bc
callfar GetOpponentItem
pop de
ld a, d
cp HELD_QUICK_CLAW
jr nz, .player_no_quick_claw
ld a, b
cp HELD_QUICK_CLAW
jr z, .both_have_quick_claw
call BattleRandom
cp e
jr nc, .speed_check
jp .player_first
.player_no_quick_claw
ld a, b
cp HELD_QUICK_CLAW
jr nz, .speed_check
call BattleRandom
cp c
jr nc, .speed_check
jp .enemy_first
.both_have_quick_claw
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr z, .player_2b
call BattleRandom
cp c
jp c, .enemy_first
call BattleRandom
cp e
jp c, .player_first
jr .speed_check
.player_2b
call BattleRandom
cp e
jp c, .player_first
call BattleRandom
cp c
jp c, .enemy_first
jr .speed_check
.speed_check
ld de, wBattleMonSpeed
ld hl, wEnemyMonSpeed
ld c, 2
call StringCmp
jr z, .speed_tie
jp nc, .player_first
jp .enemy_first
.speed_tie
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr z, .player_2c
call BattleRandom
cp 1 + (50 percent)
jp c, .player_first
jp .enemy_first
.player_2c
call BattleRandom
cp 1 + (50 percent)
jp c, .enemy_first
.player_first
scf
ret
; 3c3f3
.enemy_first ; 3c3f3
and a
ret
; 3c3f5
CheckContestBattleOver: ; 3c3f5
ld a, [wBattleType]
cp BATTLETYPE_CONTEST
jr nz, .contest_not_over
ld a, [wParkBallsRemaining]
and a
jr nz, .contest_not_over
ld a, [wBattleResult]
and $c0
add $2
ld [wBattleResult], a
scf
ret
.contest_not_over
and a
ret
; 3c410
CheckPlayerLockedIn: ; 3c410
ld a, [wPlayerSubStatus4]
and 1 << SUBSTATUS_RECHARGE
jp nz, .quit
ld hl, wEnemySubStatus3
res SUBSTATUS_FLINCHED, [hl]
ld hl, wPlayerSubStatus3
res SUBSTATUS_FLINCHED, [hl]
ld a, [hl]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE
jp nz, .quit
ld hl, wPlayerSubStatus1
bit SUBSTATUS_ROLLOUT, [hl]
jp nz, .quit
and a
ret
.quit
scf
ret
; 3c434
ParsePlayerAction: ; 3c434
call CheckPlayerLockedIn
jp c, .locked_in
ld hl, wPlayerSubStatus5
bit SUBSTATUS_ENCORED, [hl]
jr z, .not_encored
ld a, [wLastPlayerMove]
ld [wCurPlayerMove], a
jr .encored
.not_encored
ld a, [wBattlePlayerAction]
cp $2
jr z, .reset_rage
and a
jr nz, .reset_bide
ld a, [wPlayerSubStatus3]
and 1 << SUBSTATUS_BIDE
jr nz, .locked_in
xor a
ld [wMoveSelectionMenuType], a
inc a ; POUND
ld [wFXAnimID], a
call MoveSelectionScreen
push af
call Call_LoadTempTileMapToTileMap
call UpdateBattleHuds
ld a, [wCurPlayerMove]
cp STRUGGLE
jr z, .struggle
call PlayClickSFX
.struggle
ld a, $1
ld [hBGMapMode], a
pop af
ret nz
.encored
call SetPlayerTurn
callfar UpdateMoveData
xor a
ld [wPlayerCharging], a
ld a, [wPlayerMoveStruct + MOVE_EFFECT]
cp EFFECT_FURY_CUTTER
jr z, .continue_fury_cutter
xor a
ld [wPlayerFuryCutterCount], a
.continue_fury_cutter
ld a, [wPlayerMoveStruct + MOVE_EFFECT]
cp EFFECT_RAGE
jr z, .continue_rage
ld hl, wPlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
xor a
ld [wPlayerRageCounter], a
.continue_rage
ld a, [wPlayerMoveStruct + MOVE_EFFECT]
cp EFFECT_PROTECT
jr z, .continue_protect
cp EFFECT_ENDURE
jr z, .continue_protect
xor a
ld [wPlayerProtectCount], a
jr .continue_protect
.reset_bide
ld hl, wPlayerSubStatus3
res SUBSTATUS_BIDE, [hl]
.locked_in
xor a
ld [wPlayerFuryCutterCount], a
ld [wPlayerProtectCount], a
ld [wPlayerRageCounter], a
ld hl, wPlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
.continue_protect
call ParseEnemyAction
xor a
ret
.reset_rage
xor a
ld [wPlayerFuryCutterCount], a
ld [wPlayerProtectCount], a
ld [wPlayerRageCounter], a
ld hl, wPlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
xor a
ret
; 3c4df
HandleEncore: ; 3c4df
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player_1
call .do_player
jr .do_enemy
.player_1
call .do_enemy
.do_player
ld hl, wPlayerSubStatus5
bit SUBSTATUS_ENCORED, [hl]
ret z
ld a, [wPlayerEncoreCount]
dec a
ld [wPlayerEncoreCount], a
jr z, .end_player_encore
ld hl, wBattleMonPP
ld a, [wCurMoveNum]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and PP_MASK
ret nz
.end_player_encore
ld hl, wPlayerSubStatus5
res SUBSTATUS_ENCORED, [hl]
call SetEnemyTurn
ld hl, BattleText_TargetsEncoreEnded
jp StdBattleTextBox
.do_enemy
ld hl, wEnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
ret z
ld a, [wEnemyEncoreCount]
dec a
ld [wEnemyEncoreCount], a
jr z, .end_enemy_encore
ld hl, wEnemyMonPP
ld a, [wCurEnemyMoveNum]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and PP_MASK
ret nz
.end_enemy_encore
ld hl, wEnemySubStatus5
res SUBSTATUS_ENCORED, [hl]
call SetPlayerTurn
ld hl, BattleText_TargetsEncoreEnded
jp StdBattleTextBox
; 3c543
TryEnemyFlee: ; 3c543
ld a, [wBattleMode]
dec a
jr nz, .Stay
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_CANT_RUN, a
jr nz, .Stay
ld a, [wEnemyWrapCount]
and a
jr nz, .Stay
ld a, [wEnemyMonStatus]
and 1 << FRZ | SLP
jr nz, .Stay
ld a, [wTempEnemyMonSpecies]
ld de, 1
ld hl, AlwaysFleeMons
call IsInArray
jr c, .Flee
call BattleRandom
ld b, a
cp 1 + (50 percent)
jr nc, .Stay
push bc
ld a, [wTempEnemyMonSpecies]
ld de, 1
ld hl, OftenFleeMons
call IsInArray
pop bc
jr c, .Flee
ld a, b
cp 1 + (10 percent)
jr nc, .Stay
ld a, [wTempEnemyMonSpecies]
ld de, 1
ld hl, SometimesFleeMons
call IsInArray
jr c, .Flee
.Stay:
and a
ret
.Flee:
scf
ret
; 3c59a
INCLUDE "data/wild/flee_mons.asm"
CompareMovePriority: ; 3c5b4
; Compare the priority of the player and enemy's moves.
; Return carry if the player goes first, or z if they match.
ld a, [wCurPlayerMove]
call GetMovePriority
ld b, a
push bc
ld a, [wCurEnemyMove]
call GetMovePriority
pop bc
cp b
ret
; 3c5c5
GetMovePriority: ; 3c5c5
; Return the priority (0-3) of move a.
ld b, a
; Vital Throw goes last.
cp VITAL_THROW
ld a, 0
ret z
call GetMoveEffect
ld hl, MoveEffectPriorities
.loop
ld a, [hli]
cp b
jr z, .done
inc hl
cp -1
jr nz, .loop
ld a, BASE_PRIORITY
ret
.done
ld a, [hl]
ret
; 3c5df
INCLUDE "data/moves/effects_priorities.asm"
GetMoveEffect: ; 3c5ec
ld a, b
dec a
ld hl, Moves + MOVE_EFFECT
ld bc, MOVE_LENGTH
call AddNTimes
ld a, BANK(Moves)
call GetFarByte
ld b, a
ret
; 3c5fe
Battle_EnemyFirst: ; 3c5fe
call LoadTileMapToTempTileMap
call TryEnemyFlee
jp c, WildFled_EnemyFled_LinkBattleCanceled
call SetEnemyTurn
ld a, $1
ld [wEnemyGoesFirst], a
callfar AI_SwitchOrTryItem
jr c, .switch_item
call EnemyTurn_EndOpponentProtectEndureDestinyBond
call CheckMobileBattleError
ret c
ld a, [wForcedSwitch]
and a
ret nz
call HasPlayerFainted
jp z, HandlePlayerMonFaint
call HasEnemyFainted
jp z, HandleEnemyMonFaint
.switch_item
call SetEnemyTurn
call ResidualDamage
jp z, HandleEnemyMonFaint
call RefreshBattleHuds
call PlayerTurn_EndOpponentProtectEndureDestinyBond
call CheckMobileBattleError
ret c
ld a, [wForcedSwitch]
and a
ret nz
call HasEnemyFainted
jp z, HandleEnemyMonFaint
call HasPlayerFainted
jp z, HandlePlayerMonFaint
call SetPlayerTurn
call ResidualDamage
jp z, HandlePlayerMonFaint
call RefreshBattleHuds
xor a
ld [wBattlePlayerAction], a
ret
; 3c664
Battle_PlayerFirst: ; 3c664
xor a
ld [wEnemyGoesFirst], a
call SetEnemyTurn
callfar AI_SwitchOrTryItem
push af
call PlayerTurn_EndOpponentProtectEndureDestinyBond
pop bc
ld a, [wForcedSwitch]
and a
ret nz
call CheckMobileBattleError
ret c
call HasEnemyFainted
jp z, HandleEnemyMonFaint
call HasPlayerFainted
jp z, HandlePlayerMonFaint
push bc
call SetPlayerTurn
call ResidualDamage
pop bc
jp z, HandlePlayerMonFaint
push bc
call RefreshBattleHuds
pop af
jr c, .switched_or_used_item
call LoadTileMapToTempTileMap
call TryEnemyFlee
jp c, WildFled_EnemyFled_LinkBattleCanceled
call EnemyTurn_EndOpponentProtectEndureDestinyBond
call CheckMobileBattleError
ret c
ld a, [wForcedSwitch]
and a
ret nz
call HasPlayerFainted
jp z, HandlePlayerMonFaint
call HasEnemyFainted
jp z, HandleEnemyMonFaint
.switched_or_used_item
call SetEnemyTurn
call ResidualDamage
jp z, HandleEnemyMonFaint
call RefreshBattleHuds
xor a
ld [wBattlePlayerAction], a
ret
; 3c6cf
PlayerTurn_EndOpponentProtectEndureDestinyBond: ; 3c6cf
call SetPlayerTurn
call EndUserDestinyBond
callfar DoPlayerTurn
jp EndOpponentProtectEndureDestinyBond
; 3c6de
EnemyTurn_EndOpponentProtectEndureDestinyBond: ; 3c6de
call SetEnemyTurn
call EndUserDestinyBond
callfar DoEnemyTurn
jp EndOpponentProtectEndureDestinyBond
; 3c6ed
EndOpponentProtectEndureDestinyBond: ; 3c6ed
ld a, BATTLE_VARS_SUBSTATUS1_OPP
call GetBattleVarAddr
res SUBSTATUS_PROTECT, [hl]
res SUBSTATUS_ENDURE, [hl]
ld a, BATTLE_VARS_SUBSTATUS5_OPP
call GetBattleVarAddr
res SUBSTATUS_DESTINY_BOND, [hl]
ret
; 3c6fe
EndUserDestinyBond: ; 3c6fe
ld a, BATTLE_VARS_SUBSTATUS5
call GetBattleVarAddr
res SUBSTATUS_DESTINY_BOND, [hl]
ret
; 3c706
HasUserFainted: ; 3c706
ld a, [hBattleTurn]
and a
jr z, HasPlayerFainted
HasEnemyFainted: ; 3c70b
ld hl, wEnemyMonHP
jr CheckIfHPIsZero
HasPlayerFainted: ; 3c710
ld hl, wBattleMonHP
CheckIfHPIsZero: ; 3c713
ld a, [hli]
or [hl]
ret
; 3c716
ResidualDamage: ; 3c716
; Return z if the user fainted before
; or as a result of residual damage.
; For Sandstorm damage, see HandleWeather.
call HasUserFainted
ret z
ld a, BATTLE_VARS_STATUS
call GetBattleVar
and 1 << PSN | 1 << BRN
jr z, .did_psn_brn
ld hl, HurtByPoisonText
ld de, ANIM_PSN
and 1 << BRN
jr z, .got_anim
ld hl, HurtByBurnText
ld de, ANIM_BRN
.got_anim
push de
call StdBattleTextBox
pop de
xor a
ld [wNumHits], a
call Call_PlayBattleAnim_OnlyIfVisible
call GetEighthMaxHP
ld de, wPlayerToxicCount
ld a, [hBattleTurn]
and a
jr z, .check_toxic
ld de, wEnemyToxicCount
.check_toxic
ld a, BATTLE_VARS_SUBSTATUS5
call GetBattleVar
bit SUBSTATUS_TOXIC, a
jr z, .did_toxic
call GetSixteenthMaxHP
ld a, [de]
inc a
ld [de], a
ld hl, 0
.add
add hl, bc
dec a
jr nz, .add
ld b, h
ld c, l
.did_toxic
call SubtractHPFromUser
.did_psn_brn
call HasUserFainted
jp z, .fainted
ld a, BATTLE_VARS_SUBSTATUS4
call GetBattleVarAddr
bit SUBSTATUS_LEECH_SEED, [hl]
jr z, .not_seeded
call SwitchTurnCore
xor a
ld [wNumHits], a
ld de, ANIM_SAP
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVar
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
call z, Call_PlayBattleAnim_OnlyIfVisible
call SwitchTurnCore
call GetEighthMaxHP
call SubtractHPFromUser
ld a, $1
ld [hBGMapMode], a
call RestoreHP
ld hl, LeechSeedSapsText
call StdBattleTextBox
.not_seeded
call HasUserFainted
jr z, .fainted
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVarAddr
bit SUBSTATUS_NIGHTMARE, [hl]
jr z, .not_nightmare
xor a
ld [wNumHits], a
ld de, ANIM_IN_NIGHTMARE
call Call_PlayBattleAnim_OnlyIfVisible
call GetQuarterMaxHP
call SubtractHPFromUser
ld hl, HasANightmareText
call StdBattleTextBox
.not_nightmare
call HasUserFainted
jr z, .fainted
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVarAddr
bit SUBSTATUS_CURSE, [hl]
jr z, .not_cursed
xor a
ld [wNumHits], a
ld de, ANIM_IN_NIGHTMARE
call Call_PlayBattleAnim_OnlyIfVisible
call GetQuarterMaxHP
call SubtractHPFromUser
ld hl, HurtByCurseText
call StdBattleTextBox
.not_cursed
ld hl, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .check_fainted
ld hl, wEnemyMonHP
.check_fainted
ld a, [hli]
or [hl]
ret nz
.fainted
call RefreshBattleHuds
ld c, 20
call DelayFrames
xor a
ret
; 3c801
HandlePerishSong: ; 3c801
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .EnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.EnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
ld hl, wPlayerPerishCount
ld a, [hBattleTurn]
and a
jr z, .got_count
ld hl, wEnemyPerishCount
.got_count
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVar
bit SUBSTATUS_PERISH, a
ret z
dec [hl]
ld a, [hl]
ld [wd265], a
push af
ld hl, PerishCountText
call StdBattleTextBox
pop af
ret nz
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVarAddr
res SUBSTATUS_PERISH, [hl]
ld a, [hBattleTurn]
and a
jr nz, .kill_enemy
ld hl, wBattleMonHP
xor a
ld [hli], a
ld [hl], a
ld hl, wPartyMon1HP
ld a, [wCurBattleMon]
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
ret
.kill_enemy
ld hl, wEnemyMonHP
xor a
ld [hli], a
ld [hl], a
ld a, [wBattleMode]
dec a
ret z
ld hl, wOTPartyMon1HP
ld a, [wCurOTMon]
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
ret
; 3c874
HandleWrap: ; 3c874
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .EnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.EnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
ld hl, wPlayerWrapCount
ld de, wPlayerTrappingMove
ld a, [hBattleTurn]
and a
jr z, .got_addrs
ld hl, wEnemyWrapCount
ld de, wEnemyTrappingMove
.got_addrs
ld a, [hl]
and a
ret z
ld a, BATTLE_VARS_SUBSTATUS4
call GetBattleVar
bit SUBSTATUS_SUBSTITUTE, a
ret nz
ld a, [de]
ld [wd265], a
ld [wFXAnimID], a
call GetMoveName
dec [hl]
jr z, .release_from_bounds
ld a, BATTLE_VARS_SUBSTATUS3
call GetBattleVar
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
jr nz, .skip_anim
call SwitchTurnCore
xor a
ld [wNumHits], a
ld [wFXAnimID + 1], a
predef PlayBattleAnim
call SwitchTurnCore
.skip_anim
call GetSixteenthMaxHP
call SubtractHPFromUser
ld hl, BattleText_UsersHurtByStringBuffer1
jr .print_text
.release_from_bounds
ld hl, BattleText_UserWasReleasedFromStringBuffer1
.print_text
jp StdBattleTextBox
; 3c8e4
SwitchTurnCore: ; 3c8e4
ld a, [hBattleTurn]
xor 1
ld [hBattleTurn], a
ret
; 3c8eb
HandleLeftovers: ; 3c8eb
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .DoEnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.DoEnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
callfar GetUserItem
ld a, [hl]
ld [wd265], a
call GetItemName
ld a, b
cp HELD_LEFTOVERS
ret nz
ld hl, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wEnemyMonHP
.got_hp
; Don't restore if we're already at max HP
ld a, [hli]
ld b, a
ld a, [hli]
ld c, a
ld a, [hli]
cp b
jr nz, .restore
ld a, [hl]
cp c
ret z
.restore
call GetSixteenthMaxHP
call SwitchTurnCore
call RestoreHP
ld hl, BattleText_TargetRecoveredWithItem
jp StdBattleTextBox
; 3c93c
HandleMysteryberry: ; 3c93c
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .DoEnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.DoEnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
callfar GetUserItem
ld a, b
cp HELD_RESTORE_PP
jr nz, .quit
ld hl, wPartyMon1PP
ld a, [wCurBattleMon]
call GetPartyLocation
ld d, h
ld e, l
ld hl, wPartyMon1Moves
ld a, [wCurBattleMon]
call GetPartyLocation
ld a, [hBattleTurn]
and a
jr z, .wild
ld de, wWildMonPP
ld hl, wWildMonMoves
ld a, [wBattleMode]
dec a
jr z, .wild
ld hl, wOTPartyMon1PP
ld a, [wCurOTMon]
call GetPartyLocation
ld d, h
ld e, l
ld hl, wOTPartyMon1Moves
ld a, [wCurOTMon]
call GetPartyLocation
.wild
ld c, $0
.loop
ld a, [hl]
and a
jr z, .quit
ld a, [de]
and PP_MASK
jr z, .restore
inc hl
inc de
inc c
ld a, c
cp NUM_MOVES
jr nz, .loop
.quit
ret
.restore
; lousy hack
ld a, [hl]
cp SKETCH
ld b, 1
jr z, .sketch
ld b, 5
.sketch
ld a, [de]
add b
ld [de], a
push bc
push bc
ld a, [hl]
ld [wd265], a
ld de, wBattleMonMoves - 1
ld hl, wBattleMonPP
ld a, [hBattleTurn]
and a
jr z, .player_pp
ld de, wEnemyMonMoves - 1
ld hl, wEnemyMonPP
.player_pp
inc de
pop bc
ld b, 0
add hl, bc
push hl
ld h, d
ld l, e
add hl, bc
pop de
pop bc
ld a, [wd265]
cp [hl]
jr nz, .skip_checks
ld a, [hBattleTurn]
and a
ld a, [wPlayerSubStatus5]
jr z, .check_transform
ld a, [wEnemySubStatus5]
.check_transform
bit SUBSTATUS_TRANSFORMED, a
jr nz, .skip_checks
ld a, [de]
add b
ld [de], a
.skip_checks
callfar GetUserItem
ld a, [hl]
ld [wd265], a
xor a
ld [hl], a
call GetPartymonItem
ld a, [hBattleTurn]
and a
jr z, .consume_item
ld a, [wBattleMode]
dec a
jr z, .skip_consumption
call GetOTPartymonItem
.consume_item
xor a
ld [hl], a
.skip_consumption
call GetItemName
call SwitchTurnCore
call ItemRecoveryAnim
call SwitchTurnCore
ld hl, BattleText_UserRecoveredPPUsing
jp StdBattleTextBox
; 3ca26
HandleFutureSight: ; 3ca26
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .enemy_first
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.enemy_first
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
ld hl, wPlayerFutureSightCount
ld a, [hBattleTurn]
and a
jr z, .okay
ld hl, wEnemyFutureSightCount
.okay
ld a, [hl]
and a
ret z
dec a
ld [hl], a
cp $1
ret nz
ld hl, BattleText_TargetWasHitByFutureSight
call StdBattleTextBox
ld a, BATTLE_VARS_MOVE
call GetBattleVarAddr
push af
ld a, FUTURE_SIGHT
ld [hl], a
callfar UpdateMoveData
xor a
ld [wAttackMissed], a
ld [wAlreadyDisobeyed], a
ld a, 10
ld [wTypeModifier], a
callfar DoMove
xor a
ld [wCurDamage], a
ld [wCurDamage + 1], a
ld a, BATTLE_VARS_MOVE
call GetBattleVarAddr
pop af
ld [hl], a
call UpdateBattleMonInParty
jp UpdateEnemyMonInParty
; 3ca8f
HanleDefrost: ; 3ca8f
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .enemy_first
call .do_player_turn
jr .do_enemy_turn
.enemy_first
call .do_enemy_turn
.do_player_turn
ld a, [wBattleMonStatus]
bit FRZ, a
ret z
ld a, [wPlayerJustGotFrozen]
and a
ret nz
call BattleRandom
cp 10 percent
ret nc
xor a
ld [wBattleMonStatus], a
ld a, [wCurBattleMon]
ld hl, wPartyMon1Status
call GetPartyLocation
ld [hl], 0
call UpdateBattleHuds
call SetEnemyTurn
ld hl, DefrostedOpponentText
jp StdBattleTextBox
.do_enemy_turn
ld a, [wEnemyMonStatus]
bit FRZ, a
ret z
ld a, [wEnemyJustGotFrozen]
and a
ret nz
call BattleRandom
cp 10 percent
ret nc
xor a
ld [wEnemyMonStatus], a
ld a, [wBattleMode]
dec a
jr z, .wild
ld a, [wCurOTMon]
ld hl, wOTPartyMon1Status
call GetPartyLocation
ld [hl], 0
.wild
call UpdateBattleHuds
call SetPlayerTurn
ld hl, DefrostedOpponentText
jp StdBattleTextBox
; 3cafb
HandleSafeguard: ; 3cafb
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player1
call .CheckPlayer
jr .CheckEnemy
.player1
call .CheckEnemy
.CheckPlayer:
ld a, [wPlayerScreens]
bit SCREENS_SAFEGUARD, a
ret z
ld hl, wPlayerSafeguardCount
dec [hl]
ret nz
res SCREENS_SAFEGUARD, a
ld [wPlayerScreens], a
xor a
jr .print
.CheckEnemy:
ld a, [wEnemyScreens]
bit SCREENS_SAFEGUARD, a
ret z
ld hl, wEnemySafeguardCount
dec [hl]
ret nz
res SCREENS_SAFEGUARD, a
ld [wEnemyScreens], a
ld a, $1
.print
ld [hBattleTurn], a
ld hl, BattleText_SafeguardFaded
jp StdBattleTextBox
HandleScreens: ; 3cb36
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .Both
call .CheckPlayer
jr .CheckEnemy
.Both:
call .CheckEnemy
.CheckPlayer:
call SetPlayerTurn
ld de, .Your
call .Copy
ld hl, wPlayerScreens
ld de, wPlayerLightScreenCount
jr .TickScreens
.CheckEnemy:
call SetEnemyTurn
ld de, .Enemy
call .Copy
ld hl, wEnemyScreens
ld de, wEnemyLightScreenCount
.TickScreens:
bit SCREENS_LIGHT_SCREEN, [hl]
call nz, .LightScreenTick
bit SCREENS_REFLECT, [hl]
call nz, .ReflectTick
ret
.Copy:
ld hl, wStringBuffer1
jp CopyName2
; 3cb75
.Your:
db "Your@"
.Enemy:
db "Enemy@"
; 3cb80
.LightScreenTick: ; 3cb80
ld a, [de]
dec a
ld [de], a
ret nz
res SCREENS_LIGHT_SCREEN, [hl]
push hl
push de
ld hl, BattleText_MonsLightScreenFell
call StdBattleTextBox
pop de
pop hl
ret
; 3cb91
.ReflectTick: ; 3cb91
inc de
ld a, [de]
dec a
ld [de], a
ret nz
res SCREENS_REFLECT, [hl]
ld hl, BattleText_MonsReflectFaded
jp StdBattleTextBox
; 3cb9e
HandleWeather: ; 3cb9e
ld a, [wBattleWeather]
cp WEATHER_NONE
ret z
ld hl, wWeatherCount
dec [hl]
jr z, .ended
ld hl, .WeatherMessages
call .PrintWeatherMessage
ld a, [wBattleWeather]
cp WEATHER_SANDSTORM
ret nz
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .enemy_first
.player_first
call SetPlayerTurn
call .SandstormDamage
call SetEnemyTurn
jr .SandstormDamage
.enemy_first
call SetEnemyTurn
call .SandstormDamage
call SetPlayerTurn
.SandstormDamage:
ld a, BATTLE_VARS_SUBSTATUS3
call GetBattleVar
bit SUBSTATUS_UNDERGROUND, a
ret nz
ld hl, wBattleMonType1
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonType1
.ok
ld a, [hli]
cp ROCK
ret z
cp GROUND
ret z
cp STEEL
ret z
ld a, [hl]
cp ROCK
ret z
cp GROUND
ret z
cp STEEL
ret z
call SwitchTurnCore
xor a
ld [wNumHits], a
ld de, ANIM_IN_SANDSTORM
call Call_PlayBattleAnim
call SwitchTurnCore
call GetEighthMaxHP
call SubtractHPFromUser
ld hl, SandstormHitsText
jp StdBattleTextBox
.ended
ld hl, .WeatherEndedMessages
call .PrintWeatherMessage
xor a
ld [wBattleWeather], a
ret
.PrintWeatherMessage:
ld a, [wBattleWeather]
dec a
ld c, a
ld b, 0
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp StdBattleTextBox
; 3cc2d
.WeatherMessages:
dw BattleText_RainContinuesToFall
dw BattleText_TheSunlightIsStrong
dw BattleText_TheSandstormRages
.WeatherEndedMessages:
dw BattleText_TheRainStopped
dw BattleText_TheSunlightFaded
dw BattleText_TheSandstormSubsided
; 3cc39
SubtractHPFromTarget: ; 3cc39
call SubtractHP
jp UpdateHPBar
; 3cc3f
SubtractHPFromUser: ; 3cc3f
; Subtract HP from mon
call SubtractHP
jp UpdateHPBarBattleHuds
; 3cc45
SubtractHP: ; 3cc45
ld hl, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHP
.ok
inc 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
ret nc
ld a, [wBuffer3]
ld c, a
ld a, [wBuffer4]
ld b, a
xor a
ld [hli], a
ld [hl], a
ld [wBuffer5], a
ld [wBuffer6], a
ret
; 3cc76
GetSixteenthMaxHP: ; 3cc76
call GetQuarterMaxHP
; quarter result
srl c
srl c
; round up
ld a, c
and a
jr nz, .ok
inc c
.ok
ret
; 3cc83
GetEighthMaxHP: ; 3cc83
; output: bc
call GetQuarterMaxHP
; assumes nothing can have 1024 or more hp
; halve result
srl c
; round up
ld a, c
and a
jr nz, .end
inc c
.end
ret
; 3cc8e
GetQuarterMaxHP: ; 3cc8e
; output: bc
call GetMaxHP
; quarter result
srl b
rr c
srl b
rr c
; assumes nothing can have 1024 or more hp
; round up
ld a, c
and a
jr nz, .end
inc c
.end
ret
; 3cc9f
GetHalfMaxHP: ; 3cc9f
; output: bc
call GetMaxHP
; halve result
srl b
rr c
; floor = 1
ld a, c
or b
jr nz, .end
inc c
.end
ret
; 3ccac
GetMaxHP: ; 3ccac
; output: bc, wBuffer1-2
ld hl, wBattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonMaxHP
.ok
ld a, [hli]
ld [wBuffer2], a
ld b, a
ld a, [hl]
ld [wBuffer1], a
ld c, a
ret
; 3ccc2
Unreferenced_GetHalfHP: ; 3ccc2
ld hl, wBattleMonHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHP
.ok
ld a, [hli]
ld b, a
ld a, [hli]
ld c, a
srl b
rr c
ld a, [hli]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer1], a
ret
; 3ccde
CheckUserHasEnoughHP: ; 3ccde
ld hl, wBattleMonHP + 1
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHP + 1
.ok
ld a, c
sub [hl]
dec hl
ld a, b
sbc [hl]
ret
; 3ccef
RestoreHP ; 3ccef
ld hl, wEnemyMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wBattleMonMaxHP
.ok
ld a, [hli]
ld [wBuffer2], a
ld a, [hld]
ld [wBuffer1], a
dec hl
ld a, [hl]
ld [wBuffer3], a
add c
ld [hld], a
ld [wBuffer5], a
ld a, [hl]
ld [wBuffer4], a
adc b
ld [hli], a
ld [wBuffer6], a
ld a, [wBuffer1]
ld c, a
ld a, [hld]
sub c
ld a, [wBuffer2]
ld b, a
ld a, [hl]
sbc b
jr c, .asm_3cd2d
ld a, b
ld [hli], a
ld [wBuffer6], a
ld a, c
ld [hl], a
ld [wBuffer5], a
.asm_3cd2d
call SwitchTurnCore
call UpdateHPBarBattleHuds
jp SwitchTurnCore
; 3cd36
UpdateHPBarBattleHuds: ; 3cd36
call UpdateHPBar
jp UpdateBattleHuds
; 3cd3c
UpdateHPBar: ; 3cd3c
hlcoord 10, 9
ld a, [hBattleTurn]
and a
ld a, 1
jr z, .ok
hlcoord 2, 2
xor a
.ok
push bc
ld [wWhichHPBar], a
predef AnimateHPBar
pop bc
ret
; 3cd55
HandleEnemyMonFaint: ; 3cd55
call FaintEnemyPokemon
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
call z, FaintYourPokemon
xor a
ld [wWhichMonFaintedFirst], a
call UpdateBattleStateAndExperienceAfterEnemyFaint
call CheckPlayerPartyForFitMon
ld a, d
and a
jp z, LostBattle
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
call nz, UpdatePlayerHUD
ld a, $1
ld [hBGMapMode], a
ld c, 60
call DelayFrames
ld a, [wBattleMode]
dec a
jr nz, .trainer
ld a, 1
ld [wBattleEnded], a
ret
.trainer
call CheckEnemyTrainerDefeated
jp z, WinTrainerBattle
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
jr nz, .player_mon_not_fainted
call AskUseNextPokemon
jr nc, .dont_flee
ld a, 1
ld [wBattleEnded], a
ret
.dont_flee
call ForcePlayerMonChoice
call CheckMobileBattleError
jp c, WildFled_EnemyFled_LinkBattleCanceled
ld a, $1
ld [wBattlePlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
jr DoubleSwitch
.player_mon_not_fainted
ld a, $1
ld [wBattlePlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
xor a
ld [wBattlePlayerAction], a
ret
; 3cdca
DoubleSwitch: ; 3cdca
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player_1
call ClearSprites
hlcoord 1, 0
lb bc, 4, 10
call ClearBox
call PlayerPartyMonEntrance
ld a, $1
call EnemyPartyMonEntrance
jr .done
.player_1
ld a, [wCurPartyMon]
push af
ld a, $1
call EnemyPartyMonEntrance
call ClearSprites
call LoadTileMapToTempTileMap
pop af
ld [wCurPartyMon], a
call PlayerPartyMonEntrance
.done
xor a
ld [wBattlePlayerAction], a
ret
; 3ce01
UpdateBattleStateAndExperienceAfterEnemyFaint: ; 3ce01
call UpdateBattleMonInParty
ld a, [wBattleMode]
dec a
jr z, .wild
ld a, [wCurOTMon]
ld hl, wOTPartyMon1HP
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
.wild
ld hl, wPlayerSubStatus3
res SUBSTATUS_IN_LOOP, [hl]
xor a
ld hl, wEnemyDamageTaken
ld [hli], a
ld [hl], a
call NewEnemyMonStatus
call BreakAttraction
ld a, [wBattleMode]
dec a
jr z, .wild2
jr .trainer
.wild2
call StopDangerSound
ld a, $1
ld [wBattleLowHealthAlarm], a
.trainer
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
jr nz, .player_mon_did_not_faint
ld a, [wWhichMonFaintedFirst]
and a
jr nz, .player_mon_did_not_faint
call PlayerMonFaintHappinessMod
.player_mon_did_not_faint
call CheckPlayerPartyForFitMon
ld a, d
and a
ret z
ld a, [wBattleMode]
dec a
call z, PlayVictoryMusic
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld a, [wBattleResult]
and $c0
ld [wBattleResult], a
call IsAnyMonHoldingExpShare
jr z, .skip_exp
ld hl, wEnemyMonBaseStats
ld b, wEnemyMonEnd - wEnemyMonBaseStats
.loop
srl [hl]
inc hl
dec b
jr nz, .loop
.skip_exp
ld hl, wEnemyMonBaseStats
ld de, wBackupEnemyMonBaseStats
ld bc, wEnemyMonEnd - wEnemyMonBaseStats
call CopyBytes
xor a
ld [wGivingExperienceToExpShareHolders], a
call GiveExperiencePoints
call IsAnyMonHoldingExpShare
ret z
ld a, [wBattleParticipantsNotFainted]
push af
ld a, d
ld [wBattleParticipantsNotFainted], a
ld hl, wBackupEnemyMonBaseStats
ld de, wEnemyMonBaseStats
ld bc, wEnemyMonEnd - wEnemyMonBaseStats
call CopyBytes
ld a, $1
ld [wGivingExperienceToExpShareHolders], a
call GiveExperiencePoints
pop af
ld [wBattleParticipantsNotFainted], a
ret
; 3ceaa
IsAnyMonHoldingExpShare: ; 3ceaa
ld a, [wPartyCount]
ld b, a
ld hl, wPartyMon1
ld c, 1
ld d, 0
.loop
push hl
push bc
ld bc, MON_HP
add hl, bc
ld a, [hli]
or [hl]
pop bc
pop hl
jr z, .next
push hl
push bc
ld bc, MON_ITEM
add hl, bc
pop bc
ld a, [hl]
pop hl
cp EXP_SHARE
jr nz, .next
ld a, d
or c
ld d, a
.next
sla c
push de
ld de, PARTYMON_STRUCT_LENGTH
add hl, de
pop de
dec b
jr nz, .loop
ld a, d
ld e, 0
ld b, PARTY_LENGTH
.loop2
srl a
jr nc, .okay
inc e
.okay
dec b
jr nz, .loop2
ld a, e
and a
ret
; 3ceec
StopDangerSound: ; 3ceec
xor a
ld [wLowHealthAlarm], a
ret
; 3cef1
FaintYourPokemon: ; 3cef1
call StopDangerSound
call WaitSFX
ld a, $f0
ld [wCryTracks], a
ld a, [wBattleMonSpecies]
call PlayStereoCry
call PlayerMonFaintedAnimation
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
ld hl, BattleText_MonFainted
jp StdBattleTextBox
; 3cf14
FaintEnemyPokemon: ; 3cf14
call WaitSFX
ld de, SFX_KINESIS
call PlaySFX
call EnemyMonFaintedAnimation
ld de, SFX_FAINT
call PlaySFX
hlcoord 1, 0
lb bc, 4, 10
call ClearBox
ld hl, BattleText_EnemyMonFainted
jp StdBattleTextBox
; 3cf35
CheckEnemyTrainerDefeated: ; 3cf35
ld a, [wOTPartyCount]
ld b, a
xor a
ld hl, wOTPartyMon1HP
ld de, PARTYMON_STRUCT_LENGTH
.loop
or [hl]
inc hl
or [hl]
dec hl
add hl, de
dec b
jr nz, .loop
and a
ret
; 3cf4a
HandleEnemySwitch: ; 3cf4a
ld hl, wEnemyHPPal
ld e, HP_BAR_LENGTH_PX
call UpdateHPPal
call WaitBGMap
farcall EnemySwitch_TrainerHud
ld a, [wLinkMode]
and a
jr z, .not_linked
call LinkBattleSendReceiveAction
ld a, [wBattleAction]
cp BATTLEACTION_FORFEIT
ret z
call Call_LoadTempTileMapToTileMap
.not_linked
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
ld a, $0
jr nz, EnemyPartyMonEntrance
inc a
ret
; 3cf78
EnemyPartyMonEntrance: ; 3cf78
push af
xor a
ld [wEnemySwitchMonIndex], a
call NewEnemyMonStatus
call ResetEnemyStatLevels
call BreakAttraction
pop af
and a
jr nz, .set
call EnemySwitch
jr .done_switch
.set
call EnemySwitch_SetMode
.done_switch
call ResetBattleParticipants
call SetEnemyTurn
call SpikesDamage
xor a
ld [wEnemyMoveStruct + MOVE_ANIM], a
ld [wBattlePlayerAction], a
inc a
ret
; 3cfa4
WinTrainerBattle: ; 3cfa4
; Player won the battle
call StopDangerSound
ld a, $1
ld [wBattleLowHealthAlarm], a
ld [wBattleEnded], a
ld a, [wLinkMode]
and a
ld a, b
call z, PlayVictoryMusic
callfar Battle_GetTrainerName
ld hl, BattleText_EnemyWasDefeated
call StdBattleTextBox
call IsMobileBattle
jr z, .mobile
ld a, [wLinkMode]
and a
ret nz
ld a, [wInBattleTowerBattle]
bit 0, a
jr nz, .battle_tower
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
ld a, [wBattleType]
cp BATTLETYPE_CANLOSE
jr nz, .skip_heal
predef HealParty
.skip_heal
ld a, [wMonStatusFlags]
bit 0, a
jr nz, .skip_win_loss_text
call PrintWinLossText
.skip_win_loss_text
jp .GiveMoney
.mobile
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
ld c, $4 ; win
farcall Mobile_PrintOpponentBattleMessage
ret
.battle_tower
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
call EmptyBattleTextBox
ld c, BATTLETOWERTEXT_LOSS_TEXT
farcall BattleTowerText
call WaitPressAorB_BlinkCursor
ld hl, wPayDayMoney
ld a, [hli]
or [hl]
inc hl
or [hl]
ret nz
call ClearTileMap
call ClearBGPalettes
ret
.GiveMoney:
ld a, [wAmuletCoin]
and a
call nz, .DoubleReward
call .CheckMaxedOutMomMoney
push af
ld a, $0
jr nc, .okay
ld a, [wMomSavingMoney]
and $7
cp $3
jr nz, .okay
inc a
.okay
ld b, a
ld c, $4
.loop
ld a, b
and a
jr z, .loop2
call .SendMoneyToMom
dec c
dec b
jr .loop
.loop2
ld a, c
and a
jr z, .done
call .AddMoneyToWallet
dec c
jr .loop2
.done
call .DoubleReward
call .DoubleReward
pop af
jr nc, .KeepItAll
ld a, [wMomSavingMoney]
and $7
jr z, .KeepItAll
ld hl, .SentToMomTexts
dec a
ld c, a
ld b, 0
add hl, bc
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp StdBattleTextBox
.KeepItAll:
ld hl, GotMoneyForWinningText
jp StdBattleTextBox
; 3d081
.SendMoneyToMom: ; 3d081
push bc
ld hl, wBattleReward + 2
ld de, wMomsMoney + 2
call AddBattleMoneyToAccount
pop bc
ret
; 3d08d
.AddMoneyToWallet: ; 3d08d
push bc
ld hl, wBattleReward + 2
ld de, wMoney + 2
call AddBattleMoneyToAccount
pop bc
ret
; 3d099
.DoubleReward: ; 3d099
ld hl, wBattleReward + 2
sla [hl]
dec hl
rl [hl]
dec hl
rl [hl]
ret nc
ld a, $ff
ld [hli], a
ld [hli], a
ld [hl], a
ret
; 3d0ab
.SentToMomTexts: ; 3d0ab
dw SentSomeToMomText
dw SentHalfToMomText
dw SentAllToMomText
; 3d0b1
.CheckMaxedOutMomMoney: ; 3d0b1
ld hl, wMomsMoney + 2
ld a, [hld]
cp LOW(MAX_MONEY)
ld a, [hld]
sbc HIGH(MAX_MONEY) ; mid
ld a, [hl]
sbc HIGH(MAX_MONEY >> 8)
ret
; 3d0be
AddBattleMoneyToAccount: ; 3d0be
ld c, $3
and a
push de
push hl
push bc
ld b, h
ld c, l
farcall StubbedTrainerRankings_AddToBattlePayouts
pop bc
pop hl
.loop
ld a, [de]
adc [hl]
ld [de], a
dec de
dec hl
dec c
jr nz, .loop
pop hl
ld a, [hld]
cp LOW(MAX_MONEY)
ld a, [hld]
sbc HIGH(MAX_MONEY) ; mid
ld a, [hl]
sbc HIGH(MAX_MONEY >> 8)
ret c
ld [hl], HIGH(MAX_MONEY >> 8)
inc hl
ld [hl], HIGH(MAX_MONEY) ; mid
inc hl
ld [hl], LOW(MAX_MONEY)
ret
; 3d0ea
PlayVictoryMusic: ; 3d0ea
push de
ld de, MUSIC_NONE
call PlayMusic
call DelayFrame
ld de, MUSIC_WILD_VICTORY
ld a, [wBattleMode]
dec a
jr nz, .trainer_victory
push de
call IsAnyMonHoldingExpShare
pop de
jr nz, .play_music
ld hl, wPayDayMoney
ld a, [hli]
or [hl]
jr nz, .play_music
ld a, [wBattleParticipantsNotFainted]
and a
jr z, .lost
jr .play_music
.trainer_victory
ld de, MUSIC_GYM_VICTORY
call IsGymLeader
jr c, .play_music
ld de, MUSIC_TRAINER_VICTORY
.play_music
call PlayMusic
.lost
pop de
ret
; 3d123
IsKantoGymLeader: ; 0x3d123
ld hl, KantoGymLeaders
jr IsGymLeaderCommon
IsGymLeader: ; 0x3d128
ld hl, GymLeaders
IsGymLeaderCommon:
push de
ld a, [wOtherTrainerClass]
ld de, $1
call IsInArray
pop de
ret
; 0x3d137
INCLUDE "data/trainers/leaders.asm"
HandlePlayerMonFaint: ; 3d14e
call FaintYourPokemon
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
call z, FaintEnemyPokemon
ld a, $1
ld [wWhichMonFaintedFirst], a
call PlayerMonFaintHappinessMod
call CheckPlayerPartyForFitMon
ld a, d
and a
jp z, LostBattle
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
jr nz, .notfainted
call UpdateBattleStateAndExperienceAfterEnemyFaint
ld a, [wBattleMode]
dec a
jr nz, .trainer
ld a, $1
ld [wBattleEnded], a
ret
.trainer
call CheckEnemyTrainerDefeated
jp z, WinTrainerBattle
.notfainted
call AskUseNextPokemon
jr nc, .switch
ld a, $1
ld [wBattleEnded], a
ret
.switch
call ForcePlayerMonChoice
call CheckMobileBattleError
jp c, WildFled_EnemyFled_LinkBattleCanceled
ld a, c
and a
ret nz
ld a, $1
ld [wBattlePlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
jp DoubleSwitch
; 3d1aa
PlayerMonFaintHappinessMod: ; 3d1aa
ld a, [wCurBattleMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, RESET_FLAG
predef SmallFarFlagAction
ld hl, wEnemySubStatus3
res SUBSTATUS_IN_LOOP, [hl]
xor a
ld [wLowHealthAlarm], a
ld hl, wPlayerDamageTaken
ld [hli], a
ld [hl], a
ld [wBattleMonStatus], a
call UpdateBattleMonInParty
ld c, HAPPINESS_FAINTED
; If TheirLevel > (YourLevel + 30), use a different parameter
ld a, [wBattleMonLevel]
add 30
ld b, a
ld a, [wEnemyMonLevel]
cp b
jr c, .got_param
ld c, HAPPINESS_BEATENBYSTRONGFOE
.got_param
ld a, [wCurBattleMon]
ld [wCurPartyMon], a
callfar ChangeHappiness
ld a, [wBattleResult]
and %11000000
add $1
ld [wBattleResult], a
ld a, [wWhichMonFaintedFirst]
and a
ret z
ret ; ??????????
; 3d1f8
AskUseNextPokemon: ; 3d1f8
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
; We don't need to be here if we're in a Trainer battle,
; as that decision is made for us.
ld a, [wBattleMode]
and a
dec a
ret nz
ld hl, BattleText_UseNextMon
call StdBattleTextBox
.loop
lb bc, 1, 7
call PlaceYesNoBox
ld a, [wMenuCursorY]
jr c, .pressed_b
and a
ret
.pressed_b
ld a, [wMenuCursorY]
cp $1 ; YES
jr z, .loop
ld hl, wPartyMon1Speed
ld de, wEnemyMonSpeed
jp TryToRunAwayFromBattle
; 3d227
ForcePlayerMonChoice: ; 3d227
call EmptyBattleTextBox
call LoadStandardMenuDataHeader
call SetUpBattlePartyMenu_NoLoop
call ForcePickPartyMonInBattle
ld a, [wLinkMode]
and a
jr z, .skip_link
ld a, $1
ld [wBattlePlayerAction], a
call LinkBattleSendReceiveAction
.skip_link
xor a
ld [wBattlePlayerAction], a
call CheckMobileBattleError
jr c, .enemy_fainted_mobile_error
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
jr nz, .send_out_pokemon
.enemy_fainted_mobile_error
call ClearSprites
call ClearBGPalettes
call _LoadHPBar
call ExitMenu
call LoadTileMapToTempTileMap
call WaitBGMap
call GetMemSGBLayout
call SetPalettes
xor a
ld c, a
ret
.send_out_pokemon
call ClearSprites
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call ClearPalettes
call DelayFrame
call _LoadHPBar
call CloseWindow
call GetMemSGBLayout
call SetPalettes
call SendOutMonText
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
call SetPlayerTurn
call SpikesDamage
ld a, $1
and a
ld c, a
ret
; 3d2b3
PlayerPartyMonEntrance: ; 3d2b3
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call SendOutMonText
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
call SetPlayerTurn
jp SpikesDamage
; 3d2e0
CheckMobileBattleError: ; 3d2e0
ld a, [wLinkMode]
cp LINK_MOBILE
jr nz, .not_mobile ; It's not a mobile battle
ld a, [wcd2b]
and a
jr z, .not_mobile
; We have a mobile battle and something else happened
scf
ret
.not_mobile
xor a
ret
; 3d2f1
IsMobileBattle: ; 3d2f1
ld a, [wLinkMode]
cp LINK_MOBILE
ret
; 3d2f7
SetUpBattlePartyMenu_NoLoop: ; 3d2f7
call ClearBGPalettes
SetUpBattlePartyMenu: ; switch to fullscreen menu?
farcall LoadPartyMenuGFX
farcall InitPartyMenuWithCancel
farcall InitPartyMenuBGPal7
farcall InitPartyMenuGFX
ret
; 3d313
JumpToPartyMenuAndPrintText: ; 3d313
farcall WritePartyMenuTilemap
farcall PrintPartyMenuText
call WaitBGMap
call SetPalettes
call DelayFrame
ret
; 3d329
SelectBattleMon: ; 3d329
call IsMobileBattle
jr z, .mobile
farcall PartyMenuSelect
ret
.mobile
farcall Mobile_PartyMenuSelect
ret
; 3d33c
PickPartyMonInBattle: ; 3d33c
.loop
ld a, PARTYMENUACTION_SWITCH ; Which PKMN?
ld [wPartyMenuActionText], a
call JumpToPartyMenuAndPrintText
call SelectBattleMon
ret c
call CheckIfCurPartyMonIsFitToFight
jr z, .loop
xor a
ret
; 3d34f
SwitchMonAlreadyOut: ; 3d34f
ld hl, wCurBattleMon
ld a, [wCurPartyMon]
cp [hl]
jr nz, .notout
ld hl, BattleText_MonIsAlreadyOut
call StdBattleTextBox
scf
ret
.notout
xor a
ret
; 3d362
ForcePickPartyMonInBattle: ; 3d362
; Can't back out.
.pick
call PickPartyMonInBattle
ret nc
call CheckMobileBattleError
ret c
ld de, SFX_WRONG
call PlaySFX
call WaitSFX
jr .pick
; 3d375
PickSwitchMonInBattle: ; 3d375
.pick
call PickPartyMonInBattle
ret c
call SwitchMonAlreadyOut
jr c, .pick
xor a
ret
; 3d380
ForcePickSwitchMonInBattle: ; 3d380
; Can't back out.
.pick
call ForcePickPartyMonInBattle
call CheckMobileBattleError
ret c
call SwitchMonAlreadyOut
jr c, .pick
xor a
ret
; 3d38e
LostBattle: ; 3d38e
ld a, 1
ld [wBattleEnded], a
ld a, [wInBattleTowerBattle]
bit 0, a
jr nz, .battle_tower
ld a, [wBattleType]
cp BATTLETYPE_CANLOSE
jr nz, .not_canlose
; Remove the enemy from the screen.
hlcoord 0, 0
lb bc, 8, 21
call ClearBox
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
ld a, [wMonStatusFlags]
bit 0, a
jr nz, .skip_win_loss_text
call PrintWinLossText
.skip_win_loss_text
ret
.battle_tower
; Remove the enemy from the screen.
hlcoord 0, 0
lb bc, 8, 21
call ClearBox
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
call EmptyBattleTextBox
ld c, BATTLETOWERTEXT_WIN_TEXT
farcall BattleTowerText
call WaitPressAorB_BlinkCursor
call ClearTileMap
call ClearBGPalettes
ret
.not_canlose
ld a, [wLinkMode]
and a
jr nz, .LostLinkBattle
; Greyscale
ld b, SCGB_BATTLE_GRAYSCALE
call GetSGBLayout
call SetPalettes
jr .end
.LostLinkBattle:
call UpdateEnemyMonInParty
call CheckEnemyTrainerDefeated
jr nz, .not_tied
ld hl, TiedAgainstText
ld a, [wBattleResult]
and $c0
add 2
ld [wBattleResult], a
jr .text
.not_tied
ld hl, LostAgainstText
call IsMobileBattle
jr z, .mobile
.text
call StdBattleTextBox
.end
scf
ret
.mobile
; Remove the enemy from the screen.
hlcoord 0, 0
lb bc, 8, 21
call ClearBox
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
ld c, $3 ; lost
farcall Mobile_PrintOpponentBattleMessage
scf
ret
; 3d432
EnemyMonFaintedAnimation: ; 3d432
hlcoord 12, 5
decoord 12, 6
jp MonFaintedAnimation
; 3d43b
PlayerMonFaintedAnimation: ; 3d43b
hlcoord 1, 10
decoord 1, 11
jp MonFaintedAnimation
; 3d444
MonFaintedAnimation: ; 3d444
ld a, [wcfbe]
push af
set 6, a
ld [wcfbe], a
ld b, 7
.OuterLoop:
push bc
push de
push hl
ld b, 6
.InnerLoop:
push bc
push hl
push de
ld bc, 7
call CopyBytes
pop de
pop hl
ld bc, -SCREEN_WIDTH
add hl, bc
push hl
ld h, d
ld l, e
add hl, bc
ld d, h
ld e, l
pop hl
pop bc
dec b
jr nz, .InnerLoop
ld bc, 20
add hl, bc
ld de, .Spaces
call PlaceString
ld c, 2
call DelayFrames
pop hl
pop de
pop bc
dec b
jr nz, .OuterLoop
pop af
ld [wcfbe], a
ret
; 3d488
.Spaces:
db " @"
; 3d490
SlideBattlePicOut: ; 3d490
ld [hMapObjectIndexBuffer], a
ld c, a
.loop
push bc
push hl
ld b, $7
.loop2
push hl
call .DoFrame
pop hl
ld de, SCREEN_WIDTH
add hl, de
dec b
jr nz, .loop2
ld c, 2
call DelayFrames
pop hl
pop bc
dec c
jr nz, .loop
ret
; 3d4ae
.DoFrame: ; 3d4ae
ld a, [hMapObjectIndexBuffer]
ld c, a
cp $8
jr nz, .back
.forward
ld a, [hli]
ld [hld], a
dec hl
dec c
jr nz, .forward
ret
.back
ld a, [hld]
ld [hli], a
inc hl
dec c
jr nz, .back
ret
; 3d4c3
ForceEnemySwitch: ; 3d4c3
call ResetEnemyBattleVars
ld a, [wEnemySwitchMonIndex]
dec a
ld b, a
call LoadEnemyMonToSwitchTo
call ClearEnemyMonBox
call NewEnemyMonStatus
call ResetEnemyStatLevels
call Function_SetEnemyMonAndSendOutAnimation
call BreakAttraction
call ResetBattleParticipants
ret
; 3d4e1
EnemySwitch: ; 3d4e1
call CheckWhetherToAskSwitch
jr nc, EnemySwitch_SetMode
; Shift Mode
call ResetEnemyBattleVars
call CheckWhetherSwitchmonIsPredetermined
jr c, .skip
call FindMonInOTPartyToSwitchIntoBattle
.skip
; 'b' contains the PartyNr of the mon the AI will switch to
call LoadEnemyMonToSwitchTo
call OfferSwitch
push af
call ClearEnemyMonBox
call Function_BattleTextEnemySentOut
call Function_SetEnemyMonAndSendOutAnimation
pop af
ret c
; If we're here, then we're switching too
xor a
ld [wBattleParticipantsNotFainted], a
ld [wBattleParticipantsIncludingFainted], a
ld [wBattlePlayerAction], a
inc a
ld [wEnemyIsSwitching], a
call LoadTileMapToTempTileMap
jp PlayerSwitch
; 3d517
EnemySwitch_SetMode: ; 3d517
call ResetEnemyBattleVars
call CheckWhetherSwitchmonIsPredetermined
jr c, .skip
call FindMonInOTPartyToSwitchIntoBattle
.skip
; 'b' contains the PartyNr of the mon the AI will switch to
call LoadEnemyMonToSwitchTo
ld a, 1
ld [wEnemyIsSwitching], a
call ClearEnemyMonBox
call Function_BattleTextEnemySentOut
jp Function_SetEnemyMonAndSendOutAnimation
; 3d533
CheckWhetherSwitchmonIsPredetermined: ; 3d533
; returns carry if: ???
ld a, [wLinkMode]
and a
jr z, .not_linked
ld a, [wBattleAction]
sub BATTLEACTION_SWITCH1
ld b, a
jr .return_carry
.not_linked
ld a, [wEnemySwitchMonIndex]
and a
jr z, .check_wBattleHasJustStarted
dec a
ld b, a
jr .return_carry
.check_wBattleHasJustStarted
ld a, [wBattleHasJustStarted]
and a
ld b, $0
jr nz, .return_carry
and a
ret
.return_carry
scf
ret
; 3d557
ResetEnemyBattleVars: ; 3d557
; and draw empty TextBox
xor a
ld [wLastPlayerCounterMove], a
ld [wLastEnemyCounterMove], a
ld [wLastEnemyMove], a
ld [wCurEnemyMove], a
dec a
ld [wEnemyItemState], a
xor a
ld [wPlayerWrapCount], a
hlcoord 18, 0
ld a, 8
call SlideBattlePicOut
call EmptyBattleTextBox
jp LoadStandardMenuDataHeader
; 3d57a
ResetBattleParticipants: ; 3d57a
xor a
ld [wBattleParticipantsNotFainted], a
ld [wBattleParticipantsIncludingFainted], a
AddBattleParticipant: ; 3d581
ld a, [wCurBattleMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, SET_FLAG
push bc
predef SmallFarFlagAction
pop bc
ld hl, wBattleParticipantsIncludingFainted
predef_jump SmallFarFlagAction
; 3d599
FindMonInOTPartyToSwitchIntoBattle: ; 3d599
ld b, $ff
ld a, $1
ld [wBuffer1], a
ld [wBuffer2], a
.loop
ld hl, wBuffer1
sla [hl]
inc hl
sla [hl]
inc b
ld a, [wOTPartyCount]
cp b
jp z, ScoreMonTypeMatchups
ld a, [wCurOTMon]
cp b
jr z, .discourage
ld hl, wOTPartyMon1HP
push bc
ld a, b
call GetPartyLocation
ld a, [hli]
ld c, a
ld a, [hl]
or c
pop bc
jr z, .discourage
call LookUpTheEffectivenessOfEveryMove
call IsThePlayerMonTypesEffectiveAgainstOTMon
jr .loop
.discourage
ld hl, wBuffer2
set 0, [hl]
jr .loop
; 3d5d7
LookUpTheEffectivenessOfEveryMove: ; 3d5d7
push bc
ld hl, wOTPartyMon1Moves
ld a, b
call GetPartyLocation
pop bc
ld e, NUM_MOVES + 1
.loop
dec e
jr z, .done
ld a, [hli]
and a
jr z, .done
push hl
push de
push bc
dec a
ld hl, Moves
ld bc, MOVE_LENGTH
call AddNTimes
ld de, wEnemyMoveStruct
ld a, BANK(Moves)
call FarCopyBytes
call SetEnemyTurn
callfar BattleCheckTypeMatchup
pop bc
pop de
pop hl
ld a, [wd265] ; Get The Effectiveness Modifier
cp 10 + 1 ; 1.0 + 0.1
jr c, .loop
ld hl, wBuffer1
set 0, [hl]
ret
.done
ret
; 3d618
IsThePlayerMonTypesEffectiveAgainstOTMon: ; 3d618
; Calculates the effectiveness of the types of the PlayerMon
; against the OTMon
push bc
ld hl, wOTPartyCount
ld a, b
inc a
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
dec a
ld hl, BaseData + BASE_TYPES
ld bc, BASE_DATA_SIZE
call AddNTimes
ld de, wEnemyMonType
ld bc, BASE_CATCH_RATE - BASE_TYPES
ld a, BANK(BaseData)
call FarCopyBytes
ld a, [wBattleMonType1]
ld [wPlayerMoveStruct + MOVE_TYPE], a
call SetPlayerTurn
callfar BattleCheckTypeMatchup
ld a, [wd265]
cp 10 + 1 ; 1.0 + 0.1
jr nc, .super_effective
ld a, [wBattleMonType2]
ld [wPlayerMoveStruct + MOVE_TYPE], a
callfar BattleCheckTypeMatchup
ld a, [wd265]
cp 10 + 1 ; 1.0 + 0.1
jr nc, .super_effective
pop bc
ret
.super_effective
pop bc
ld hl, wBuffer1
bit 0, [hl]
jr nz, .reset
inc hl
set 0, [hl]
ret
.reset
res 0, [hl]
ret
; 3d672
ScoreMonTypeMatchups: ; 3d672
.loop1
ld hl, wBuffer1
sla [hl]
inc hl
sla [hl]
jr nc, .loop1
ld a, [wOTPartyCount]
ld b, a
ld c, [hl]
.loop2
sla c
jr nc, .okay
dec b
jr z, .loop5
jr .loop2
.okay
ld a, [wBuffer1]
and a
jr z, .okay2
ld b, $ff
ld c, a
.loop3
inc b
sla c
jr nc, .loop3
jr .quit
.okay2
ld b, $ff
ld a, [wBuffer2]
ld c, a
.loop4
inc b
sla c
jr c, .loop4
jr .quit
.loop5
ld a, [wOTPartyCount]
ld b, a
call BattleRandom
and $7
cp b
jr nc, .loop5
ld b, a
ld a, [wCurOTMon]
cp b
jr z, .loop5
ld hl, wOTPartyMon1HP
push bc
ld a, b
call GetPartyLocation
pop bc
ld a, [hli]
ld c, a
ld a, [hl]
or c
jr z, .loop5
.quit
ret
; 3d6ca
LoadEnemyMonToSwitchTo: ; 3d6ca
; 'b' contains the PartyNr of the mon the AI will switch to
ld a, b
ld [wCurPartyMon], a
ld hl, wOTPartyMon1Level
call GetPartyLocation
ld a, [hl]
ld [wCurPartyLevel], a
ld a, [wCurPartyMon]
inc a
ld hl, wOTPartyCount
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [wTempEnemyMonSpecies], a
ld [wCurPartySpecies], a
call LoadEnemyMon
ld a, [wCurPartySpecies]
cp UNOWN
jr nz, .skip_unown
ld a, [wFirstUnownSeen]
and a
jr nz, .skip_unown
ld hl, wEnemyMonDVs
predef GetUnownLetter
ld a, [wUnownLetter]
ld [wFirstUnownSeen], a
.skip_unown
ld hl, wEnemyMonHP
ld a, [hli]
ld [wEnemyHPAtTimeOfPlayerSwitch], a
ld a, [hl]
ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a
ret
; 3d714
CheckWhetherToAskSwitch: ; 3d714
ld a, [wBattleHasJustStarted]
dec a
jp z, .return_nc
ld a, [wPartyCount]
dec a
jp z, .return_nc
ld a, [wLinkMode]
and a
jp nz, .return_nc
ld a, [wOptions]
bit BATTLE_SHIFT, a
jr nz, .return_nc
ld a, [wCurPartyMon]
push af
ld a, [wCurBattleMon]
ld [wCurPartyMon], a
farcall CheckCurPartyMonFainted
pop bc
ld a, b
ld [wCurPartyMon], a
jr c, .return_nc
scf
ret
.return_nc
and a
ret
; 3d74b
OfferSwitch: ; 3d74b
ld a, [wCurPartyMon]
push af
callfar Battle_GetTrainerName
ld hl, BattleText_EnemyIsAboutToUseWillPlayerChangeMon
call StdBattleTextBox
lb bc, 1, 7
call PlaceYesNoBox
ld a, [wMenuCursorY]
dec a
jr nz, .said_no
call SetUpBattlePartyMenu_NoLoop
call PickSwitchMonInBattle
jr c, .canceled_switch
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
call ClearPalettes
call DelayFrame
call _LoadHPBar
pop af
ld [wCurPartyMon], a
xor a
ld [wCurEnemyMove], a
ld [wCurPlayerMove], a
and a
ret
.canceled_switch
call ClearPalettes
call DelayFrame
call _LoadHPBar
.said_no
pop af
ld [wCurPartyMon], a
scf
ret
; 3d7a0
ClearEnemyMonBox: ; 3d7a0
xor a
ld [hBGMapMode], a
call ExitMenu
call ClearSprites
hlcoord 1, 0
lb bc, 4, 10
call ClearBox
call WaitBGMap
jp FinishBattleAnim
; 3d7b8
Function_BattleTextEnemySentOut: ; 3d7b8
callfar Battle_GetTrainerName
ld hl, BattleText_EnemySentOut
call StdBattleTextBox
jp WaitBGMap
; 3d7c7
Function_SetEnemyMonAndSendOutAnimation: ; 3d7c7
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld [wCurSpecies], a
call GetBaseData
ld a, OTPARTYMON
ld [wMonType], a
predef CopyMonToTempMon
call GetEnemyMonFrontpic
xor a
ld [wNumHits], a
ld [wBattleAnimParam], a
call SetEnemyTurn
ld de, ANIM_SEND_OUT_MON
call Call_PlayBattleAnim
call BattleCheckEnemyShininess
jr nc, .not_shiny
ld a, 1 ; shiny anim
ld [wBattleAnimParam], a
ld de, ANIM_SEND_OUT_MON
call Call_PlayBattleAnim
.not_shiny
ld bc, wTempMonSpecies
farcall CheckFaintedFrzSlp
jr c, .skip_cry
farcall CheckBattleScene
jr c, .cry_no_anim
hlcoord 12, 0
ld d, $0
ld e, ANIM_MON_SLOW
predef AnimateFrontpic
jr .skip_cry
.cry_no_anim
ld a, $f
ld [wCryTracks], a
ld a, [wTempEnemyMonSpecies]
call PlayStereoCry
.skip_cry
call UpdateEnemyHUD
ld a, $1
ld [hBGMapMode], a
ret
; 3d834
NewEnemyMonStatus: ; 3d834
xor a
ld [wLastPlayerCounterMove], a
ld [wLastEnemyCounterMove], a
ld [wLastEnemyMove], a
ld hl, wEnemySubStatus1
rept 4
ld [hli], a
endr
ld [hl], a
ld [wEnemyDisableCount], a
ld [wEnemyFuryCutterCount], a
ld [wEnemyProtectCount], a
ld [wEnemyRageCounter], a
ld [wEnemyDisabledMove], a
ld [wEnemyMinimized], a
ld [wPlayerWrapCount], a
ld [wEnemyWrapCount], a
ld [wEnemyTurnsTaken], a
ld hl, wPlayerSubStatus5
res SUBSTATUS_CANT_RUN, [hl]
ret
; 3d867
ResetEnemyStatLevels: ; 3d867
ld a, BASE_STAT_LEVEL
ld b, NUM_LEVEL_STATS
ld hl, wEnemyStatLevels
.loop
ld [hli], a
dec b
jr nz, .loop
ret
; 3d873
CheckPlayerPartyForFitMon: ; 3d873
; Has the player any mon in his Party that can fight?
ld a, [wPartyCount]
ld e, a
xor a
ld hl, wPartyMon1HP
ld bc, wPartyMon2 - (wPartyMon1 + 1)
.loop
or [hl]
inc hl
or [hl]
add hl, bc
dec e
jr nz, .loop
ld d, a
ret
; 3d887
CheckIfCurPartyMonIsFitToFight: ; 3d887
ld a, [wCurPartyMon]
ld hl, wPartyMon1HP
call GetPartyLocation
ld a, [hli]
or [hl]
ret nz
ld a, [wBattleHasJustStarted]
and a
jr nz, .finish_fail
ld hl, wPartySpecies
ld a, [wCurPartyMon]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
cp EGG
ld hl, BattleText_AnEGGCantBattle
jr z, .print_textbox
ld hl, BattleText_TheresNoWillToBattle
.print_textbox
call StdBattleTextBox
.finish_fail
xor a
ret
; 3d8b3
TryToRunAwayFromBattle: ; 3d8b3
; Run away from battle, with or without item
ld a, [wBattleType]
cp BATTLETYPE_DEBUG
jp z, .can_escape
cp BATTLETYPE_CONTEST
jp z, .can_escape
cp BATTLETYPE_TRAP
jp z, .cant_escape
cp BATTLETYPE_CELEBI
jp z, .cant_escape
cp BATTLETYPE_SHINY
jp z, .cant_escape
cp BATTLETYPE_SUICUNE
jp z, .cant_escape
ld a, [wLinkMode]
and a
jp nz, .can_escape
ld a, [wBattleMode]
dec a
jp nz, .cant_run_from_trainer
ld a, [wEnemySubStatus5]
bit SUBSTATUS_CANT_RUN, a
jp nz, .cant_escape
ld a, [wPlayerWrapCount]
and a
jp nz, .cant_escape
push hl
push de
ld a, [wBattleMonItem]
ld [wd265], a
ld b, a
callfar GetItemHeldEffect
ld a, b
cp HELD_ESCAPE
pop de
pop hl
jr nz, .no_flee_item
call SetPlayerTurn
call GetItemName
ld hl, BattleText_UserFledUsingAStringBuffer1
call StdBattleTextBox
jp .can_escape
.no_flee_item
ld a, [wNumFleeAttempts]
inc a
ld [wNumFleeAttempts], a
ld a, [hli]
ld [hStringCmpString2 + 0], a
ld a, [hl]
ld [hStringCmpString2 + 1], a
ld a, [de]
inc de
ld [hStringCmpString1 + 0], a
ld a, [de]
ld [hStringCmpString1 + 1], a
call Call_LoadTempTileMapToTileMap
ld de, hStringCmpString2
ld hl, hStringCmpString1
ld c, $2
call StringCmp
jr nc, .can_escape
xor a
ld [hMultiplicand], a
ld a, $20
ld [hMultiplier], a
call Multiply
ld a, [hProduct + 2]
ld [hDividend + 0], a
ld a, [hProduct + 3]
ld [hDividend + 1], a
ld a, [hStringCmpString1 + 0]
ld b, a
ld a, [hStringCmpString1 + 1]
srl b
rr a
srl b
rr a
and a
jr z, .can_escape
ld [hDivisor], a
ld b, 2
call Divide
ld a, [hQuotient + 1]
and a
jr nz, .can_escape
ld a, [wNumFleeAttempts]
ld c, a
.loop
dec c
jr z, .cant_escape_2
ld b, 30
ld a, [hQuotient + 2]
add b
ld [hQuotient + 2], a
jr c, .can_escape
jr .loop
.cant_escape_2
call BattleRandom
ld b, a
ld a, [hQuotient + 2]
cp b
jr nc, .can_escape
ld a, $1
ld [wBattlePlayerAction], a
ld hl, BattleText_CantEscape2
jr .print_inescapable_text
.cant_escape
ld hl, BattleText_CantEscape
jr .print_inescapable_text
.cant_run_from_trainer
ld hl, BattleText_TheresNoEscapeFromTrainerBattle
.print_inescapable_text
call StdBattleTextBox
ld a, $1
ld [wFailedToFlee], a
call LoadTileMapToTempTileMap
and a
ret
.can_escape
ld a, [wLinkMode]
and a
ld a, DRAW
jr z, .fled
call LoadTileMapToTempTileMap
xor a
ld [wBattlePlayerAction], a
ld a, $f
ld [wCurMoveNum], a
xor a
ld [wCurPlayerMove], a
call LinkBattleSendReceiveAction
call Call_LoadTempTileMapToTileMap
call CheckMobileBattleError
jr c, .mobile
; Got away safely
ld a, [wBattleAction]
cp BATTLEACTION_FORFEIT
ld a, DRAW
jr z, .fled
dec a
.fled
ld b, a
ld a, [wBattleResult]
and $c0
add b
ld [wBattleResult], a
call StopDangerSound
push de
ld de, SFX_RUN
call WaitPlaySFX
pop de
call WaitSFX
ld hl, BattleText_GotAwaySafely
call StdBattleTextBox
call WaitSFX
call LoadTileMapToTempTileMap
scf
ret
.mobile
call StopDangerSound
ld hl, wcd2a
bit 4, [hl]
jr nz, .skip_link_error
ld hl, BattleText_LinkErrorBattleCanceled
call StdBattleTextBox
.skip_link_error
call WaitSFX
call LoadTileMapToTempTileMap
scf
ret
; 3da0d
InitBattleMon: ; 3da0d
ld a, MON_SPECIES
call GetPartyParamLocation
ld de, wBattleMonSpecies
ld bc, MON_ID
call CopyBytes
ld bc, MON_DVS - MON_ID
add hl, bc
ld de, wBattleMonDVs
ld bc, MON_PKRUS - MON_DVS
call CopyBytes
inc hl
inc hl
inc hl
ld de, wBattleMonLevel
ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
call CopyBytes
ld a, [wBattleMonSpecies]
ld [wTempBattleMonSpecies], a
ld [wCurPartySpecies], a
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseType1]
ld [wBattleMonType1], a
ld a, [wBaseType2]
ld [wBattleMonType2], a
ld hl, wPartyMonNicknames
ld a, [wCurBattleMon]
call SkipNames
ld de, wBattleMonNick
ld bc, MON_NAME_LENGTH
call CopyBytes
ld hl, wBattleMonAttack
ld de, wPlayerStats
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
call ApplyStatusEffectOnPlayerStats
call BadgeStatBoosts
ret
; 3da74
BattleCheckPlayerShininess: ; 3da74
call GetPartyMonDVs
jr BattleCheckShininess
BattleCheckEnemyShininess: ; 3da79
call GetEnemyMonDVs
BattleCheckShininess: ; 3da7c
ld b, h
ld c, l
callfar CheckShininess
ret
; 3da85
GetPartyMonDVs: ; 3da85
ld hl, wBattleMonDVs
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
ret z
ld hl, wPartyMon1DVs
ld a, [wCurBattleMon]
jp GetPartyLocation
; 3da97
GetEnemyMonDVs: ; 3da97
ld hl, wEnemyMonDVs
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
ret z
ld hl, wEnemyBackupDVs
ld a, [wBattleMode]
dec a
ret z
ld hl, wOTPartyMon1DVs
ld a, [wCurOTMon]
jp GetPartyLocation
; 3dab1
ResetPlayerStatLevels: ; 3dab1
ld a, BASE_STAT_LEVEL
ld b, NUM_LEVEL_STATS
ld hl, wPlayerStatLevels
.loop
ld [hli], a
dec b
jr nz, .loop
ret
; 3dabd
InitEnemyMon: ; 3dabd
ld a, [wCurPartyMon]
ld hl, wOTPartyMon1Species
call GetPartyLocation
ld de, wEnemyMonSpecies
ld bc, MON_ID
call CopyBytes
ld bc, MON_DVS - MON_ID
add hl, bc
ld de, wEnemyMonDVs
ld bc, MON_PKRUS - MON_DVS
call CopyBytes
inc hl
inc hl
inc hl
ld de, wEnemyMonLevel
ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
call CopyBytes
ld a, [wEnemyMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld hl, wOTPartyMonNicknames
ld a, [wCurPartyMon]
call SkipNames
ld de, wEnemyMonNick
ld bc, MON_NAME_LENGTH
call CopyBytes
ld hl, wEnemyMonAttack
ld de, wEnemyStats
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
call ApplyStatusEffectOnEnemyStats
ld hl, wBaseType1
ld de, wEnemyMonType1
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld hl, wBaseStats
ld de, wEnemyMonBaseStats
ld b, 5
.loop
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .loop
ld a, [wCurPartyMon]
ld [wCurOTMon], a
ret
; 3db32
SwitchPlayerMon: ; 3db32
call ClearSprites
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
ret
; 3db5f
SendOutPlayerMon: ; 3db5f
ld hl, wBattleMonDVs
predef GetUnownLetter
hlcoord 1, 5
ld b, 7
ld c, 8
call ClearBox
call WaitBGMap
xor a
ld [hBGMapMode], a
call GetBattleMonBackpic
xor a
ld [hGraphicStartTile], a
ld [wBattleMenuCursorBuffer], a
ld [wCurMoveNum], a
ld [wTypeModifier], a
ld [wPlayerMoveStruct + MOVE_ANIM], a
ld [wLastPlayerCounterMove], a
ld [wLastEnemyCounterMove], a
ld [wLastPlayerMove], a
call CheckAmuletCoin
call FinishBattleAnim
xor a
ld [wEnemyWrapCount], a
call SetPlayerTurn
xor a
ld [wNumHits], a
ld [wBattleAnimParam], a
ld de, ANIM_SEND_OUT_MON
call Call_PlayBattleAnim
call BattleCheckPlayerShininess
jr nc, .not_shiny
ld a, 1
ld [wBattleAnimParam], a
ld de, ANIM_SEND_OUT_MON
call Call_PlayBattleAnim
.not_shiny
ld a, MON_SPECIES
call GetPartyParamLocation
ld b, h
ld c, l
farcall CheckFaintedFrzSlp
jr c, .statused
ld a, $f0
ld [wCryTracks], a
ld a, [wCurPartySpecies]
call PlayStereoCry
.statused
call UpdatePlayerHUD
ld a, $1
ld [hBGMapMode], a
ret
; 3dbde
NewBattleMonStatus: ; 3dbde
xor a
ld [wLastPlayerCounterMove], a
ld [wLastEnemyCounterMove], a
ld [wLastPlayerMove], a
ld hl, wPlayerSubStatus1
rept 4
ld [hli], a
endr
ld [hl], a
ld hl, wPlayerUsedMoves
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld [wPlayerDisableCount], a
ld [wPlayerFuryCutterCount], a
ld [wPlayerProtectCount], a
ld [wPlayerRageCounter], a
ld [wDisabledMove], a
ld [wPlayerMinimized], a
ld [wEnemyWrapCount], a
ld [wPlayerWrapCount], a
ld [wPlayerTurnsTaken], a
ld hl, wEnemySubStatus5
res SUBSTATUS_CANT_RUN, [hl]
ret
; 3dc18
BreakAttraction: ; 3dc18
ld hl, wPlayerSubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, wEnemySubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ret
; 3dc23
SpikesDamage: ; 3dc23
ld hl, wPlayerScreens
ld de, wBattleMonType
ld bc, UpdatePlayerHUD
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyScreens
ld de, wEnemyMonType
ld bc, UpdateEnemyHUD
.ok
bit SCREENS_SPIKES, [hl]
ret z
; Flying-types aren't affected by Spikes.
ld a, [de]
cp FLYING
ret z
inc de
ld a, [de]
cp FLYING
ret z
push bc
ld hl, BattleText_UserHurtBySpikes ; "hurt by SPIKES!"
call StdBattleTextBox
call GetEighthMaxHP
call SubtractHPFromTarget
pop hl
call .hl
jp WaitBGMap
.hl
jp hl
; 3dc5b
PursuitSwitch: ; 3dc5b
ld a, BATTLE_VARS_MOVE
call GetBattleVar
ld b, a
call GetMoveEffect
ld a, b
cp EFFECT_PURSUIT
jr nz, .done
ld a, [wCurBattleMon]
push af
ld hl, DoPlayerTurn
ld a, [hBattleTurn]
and a
jr z, .do_turn
ld hl, DoEnemyTurn
ld a, [wLastPlayerMon]
ld [wCurBattleMon], a
.do_turn
ld a, BANK(DoPlayerTurn)
rst FarCall
ld a, BATTLE_VARS_MOVE
call GetBattleVarAddr
ld a, $ff
ld [hl], a
pop af
ld [wCurBattleMon], a
ld a, [hBattleTurn]
and a
jr z, .check_enemy_fainted
ld a, [wLastPlayerMon]
call UpdateBattleMon
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
jr nz, .done
ld a, $f0
ld [wCryTracks], a
ld a, [wBattleMonSpecies]
call PlayStereoCry
ld a, [wLastPlayerMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, RESET_FLAG
predef SmallFarFlagAction
call PlayerMonFaintedAnimation
ld hl, BattleText_MonFainted
jr .done_fainted
.check_enemy_fainted
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
jr nz, .done
ld de, SFX_KINESIS
call PlaySFX
call WaitSFX
ld de, SFX_FAINT
call PlaySFX
call WaitSFX
call EnemyMonFaintedAnimation
ld hl, BattleText_EnemyMonFainted
.done_fainted
call StdBattleTextBox
scf
ret
.done
and a
ret
; 3dce6
RecallPlayerMon: ; 3dce6
ld a, [hBattleTurn]
push af
xor a
ld [hBattleTurn], a
ld [wNumHits], a
ld de, ANIM_RETURN_MON
call Call_PlayBattleAnim
pop af
ld [hBattleTurn], a
ret
; 3dcf9
HandleHealingItems: ; 3dcf9
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player_1
call SetPlayerTurn
call HandleHPHealingItem
call UseHeldStatusHealingItem
call UseConfusionHealingItem
call SetEnemyTurn
call HandleHPHealingItem
call UseHeldStatusHealingItem
jp UseConfusionHealingItem
.player_1
call SetEnemyTurn
call HandleHPHealingItem
call UseHeldStatusHealingItem
call UseConfusionHealingItem
call SetPlayerTurn
call HandleHPHealingItem
call UseHeldStatusHealingItem
jp UseConfusionHealingItem
; 3dd2f
HandleHPHealingItem: ; 3dd2f
callfar GetOpponentItem
ld a, b
cp HELD_BERRY
ret nz
ld de, wEnemyMonHP + 1
ld hl, wEnemyMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .go
ld de, wBattleMonHP + 1
ld hl, wBattleMonMaxHP
.go
; If, and only if, Pokemon's HP is less than half max, use the item.
; Store current HP in Buffer 3/4
push bc
ld a, [de]
ld [wBuffer3], a
add a
ld c, a
dec de
ld a, [de]
inc de
ld [wBuffer4], a
adc a
ld b, a
ld a, b
cp [hl]
ld a, c
pop bc
jr z, .equal
jr c, .less
ret
.equal
inc hl
cp [hl]
dec hl
ret nc
.less
call ItemRecoveryAnim
; store max HP in wBuffer1/2
ld a, [hli]
ld [wBuffer2], a
ld a, [hl]
ld [wBuffer1], a
ld a, [de]
add c
ld [wBuffer5], a
ld c, a
dec de
ld a, [de]
adc $0
ld [wBuffer6], a
ld b, a
ld a, [hld]
cp c
ld a, [hl]
sbc b
jr nc, .okay
ld a, [hli]
ld [wBuffer6], a
ld a, [hl]
ld [wBuffer5], a
.okay
ld a, [wBuffer6]
ld [de], a
inc de
ld a, [wBuffer5]
ld [de], a
ld a, [hBattleTurn]
ld [wWhichHPBar], a
and a
hlcoord 2, 2
jr z, .got_hp_bar_coords
hlcoord 10, 9
.got_hp_bar_coords
ld [wWhichHPBar], a
predef AnimateHPBar
UseOpponentItem:
call RefreshBattleHuds
callfar GetOpponentItem
ld a, [hl]
ld [wNamedObjectIndexBuffer], a
call GetItemName
callfar ConsumeHeldItem
ld hl, RecoveredUsingText
jp StdBattleTextBox
; 3ddc8
ItemRecoveryAnim: ; 3ddc8
push hl
push de
push bc
call EmptyBattleTextBox
ld a, RECOVER
ld [wFXAnimID], a
call SwitchTurnCore
xor a
ld [wNumHits], a
ld [wFXAnimID + 1], a
predef PlayBattleAnim
call SwitchTurnCore
pop bc
pop de
pop hl
ret
; 3dde9
UseHeldStatusHealingItem: ; 3dde9
callfar GetOpponentItem
ld hl, .Statuses
.loop
ld a, [hli]
cp $ff
ret z
inc hl
cp b
jr nz, .loop
dec hl
ld b, [hl]
ld a, BATTLE_VARS_STATUS_OPP
call GetBattleVarAddr
and b
ret z
xor a
ld [hl], a
push bc
call UpdateOpponentInParty
pop bc
ld a, BATTLE_VARS_SUBSTATUS5_OPP
call GetBattleVarAddr
and [hl]
res SUBSTATUS_TOXIC, [hl]
ld a, BATTLE_VARS_SUBSTATUS1_OPP
call GetBattleVarAddr
and [hl]
res SUBSTATUS_NIGHTMARE, [hl]
ld a, b
cp ALL_STATUS
jr nz, .skip_confuse
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVarAddr
res SUBSTATUS_CONFUSED, [hl]
.skip_confuse
ld hl, CalcEnemyStats
ld a, [hBattleTurn]
and a
jr z, .got_pointer
ld hl, CalcPlayerStats
.got_pointer
call SwitchTurnCore
ld a, BANK(CalcEnemyStats)
rst FarCall
call SwitchTurnCore
call ItemRecoveryAnim
call UseOpponentItem
ld a, $1
and a
ret
; 3de44
.Statuses: ; 3de44
db HELD_HEAL_POISON, 1 << PSN
db HELD_HEAL_FREEZE, 1 << FRZ
db HELD_HEAL_BURN, 1 << BRN
db HELD_HEAL_SLEEP, SLP
db HELD_HEAL_PARALYZE, 1 << PAR
db HELD_HEAL_STATUS, ALL_STATUS
db -1 ; end
; 3de51
UseConfusionHealingItem: ; 3de51
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVar
bit SUBSTATUS_CONFUSED, a
ret z
callfar GetOpponentItem
ld a, b
cp HELD_HEAL_CONFUSION
jr z, .heal_status
cp HELD_HEAL_STATUS
ret nz
.heal_status
ld a, [hl]
ld [wd265], a
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVarAddr
res SUBSTATUS_CONFUSED, [hl]
call GetItemName
call ItemRecoveryAnim
ld hl, BattleText_ItemHealedConfusion
call StdBattleTextBox
ld a, [hBattleTurn]
and a
jr nz, .do_partymon
call GetOTPartymonItem
xor a
ld [bc], a
ld a, [wBattleMode]
dec a
ret z
ld [hl], $0
ret
.do_partymon
call GetPartymonItem
xor a
ld [bc], a
ld [hl], a
ret
; 3de97
HandleStatBoostingHeldItems: ; 3de97
; The effects handled here are not used in-game.
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player_1
call .DoPlayer
jp .DoEnemy
.player_1
call .DoEnemy
jp .DoPlayer
; 3dea9
.DoPlayer: ; 3dea9
call GetPartymonItem
ld a, $0
jp .HandleItem
; 3deb1
.DoEnemy: ; 3deb1
call GetOTPartymonItem
ld a, $1
.HandleItem: ; 3deb6
ld [hBattleTurn], a
ld d, h
ld e, l
push de
push bc
ld a, [bc]
ld b, a
callfar GetItemHeldEffect
ld hl, .StatUpItems
.loop
ld a, [hli]
cp $ff
jr z, .finish
inc hl
inc hl
cp b
jr nz, .loop
pop bc
ld a, [bc]
ld [wd265], a
push bc
dec hl
dec hl
ld a, [hli]
ld h, [hl]
ld l, a
ld a, BANK(BattleCommand_AttackUp)
rst FarCall
pop bc
pop de
ld a, [wFailedMessage]
and a
ret nz
xor a
ld [bc], a
ld [de], a
call GetItemName
ld hl, BattleText_UsersStringBuffer1Activated
call StdBattleTextBox
callfar BattleCommand_StatUpMessage
ret
.finish
pop bc
pop de
ret
; 3defc
.StatUpItems:
dbw HELD_ATTACK_UP, BattleCommand_AttackUp
dbw HELD_DEFENSE_UP, BattleCommand_DefenseUp
dbw HELD_SPEED_UP, BattleCommand_SpeedUp
dbw HELD_SP_ATTACK_UP, BattleCommand_SpecialAttackUp
dbw HELD_SP_DEFENSE_UP, BattleCommand_SpecialDefenseUp
dbw HELD_ACCURACY_UP, BattleCommand_AccuracyUp
dbw HELD_EVASION_UP, BattleCommand_EvasionUp
db -1 ; end
; 3df12
GetPartymonItem: ; 3df12
ld hl, wPartyMon1Item
ld a, [wCurBattleMon]
call GetPartyLocation
ld bc, wBattleMonItem
ret
; 3df1f
GetOTPartymonItem: ; 3df1f
ld hl, wOTPartyMon1Item
ld a, [wCurOTMon]
call GetPartyLocation
ld bc, wEnemyMonItem
ret
; 3df2c
UpdateBattleHUDs: ; 3df2c
push hl
push de
push bc
call DrawPlayerHUD
ld hl, wPlayerHPPal
call SetHPPal
call CheckDanger
call DrawEnemyHUD
ld hl, wEnemyHPPal
call SetHPPal
pop bc
pop de
pop hl
ret
; 3df48
UpdatePlayerHUD:: ; 3df48
push hl
push de
push bc
call DrawPlayerHUD
call UpdatePlayerHPPal
call CheckDanger
pop bc
pop de
pop hl
ret
; 3df58
DrawPlayerHUD: ; 3df58
xor a
ld [hBGMapMode], a
; Clear the area
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
farcall DrawPlayerHUDBorder
hlcoord 18, 9
ld [hl], $73 ; vertical bar
call PrintPlayerHUD
; HP bar
hlcoord 10, 9
ld b, 1
xor a ; PARTYMON
ld [wMonType], a
predef DrawPlayerHP
; Exp bar
push de
ld a, [wCurBattleMon]
ld hl, wPartyMon1Exp + 2
call GetPartyLocation
ld d, h
ld e, l
hlcoord 10, 11
ld a, [wTempMonLevel]
ld b, a
call FillInExpBar
pop de
ret
; 3df98
UpdatePlayerHPPal: ; 3df98
ld hl, wPlayerHPPal
jp UpdateHPPal
; 3df9e
CheckDanger: ; 3df9e
ld hl, wBattleMonHP
ld a, [hli]
or [hl]
jr z, .no_danger
ld a, [wBattleLowHealthAlarm]
and a
jr nz, .done
ld a, [wPlayerHPPal]
cp HP_RED
jr z, .danger
.no_danger
ld hl, wLowHealthAlarm
res DANGER_ON_F, [hl]
jr .done
.danger
ld hl, wLowHealthAlarm
set DANGER_ON_F, [hl]
.done
ret
; 3dfbf
PrintPlayerHUD: ; 3dfbf
ld de, wBattleMonNick
hlcoord 10, 7
call ret_3e138
call PlaceString
push bc
ld a, [wCurBattleMon]
ld hl, wPartyMon1DVs
call GetPartyLocation
ld de, wTempMonDVs
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld hl, wBattleMonLevel
ld de, wTempMonLevel
ld bc, $11
call CopyBytes
ld a, [wCurBattleMon]
ld hl, wPartyMon1Species
call GetPartyLocation
ld a, [hl]
ld [wCurPartySpecies], a
ld [wCurSpecies], a
call GetBaseData
pop hl
dec hl
ld a, TEMPMON
ld [wMonType], a
callfar GetGender
ld a, " "
jr c, .got_gender_char
ld a, "♂"
jr nz, .got_gender_char
ld a, "♀"
.got_gender_char
hlcoord 17, 8
ld [hl], a
hlcoord 14, 8
push af ; back up gender
push hl
ld de, wBattleMonStatus
predef PlaceNonFaintStatus
pop hl
pop bc
ret nz
ld a, b
cp " "
jr nz, .copy_level ; male or female
dec hl ; genderless
.copy_level
ld a, [wBattleMonLevel]
ld [wTempMonLevel], a
jp PrintLevel
; 3e036
UpdateEnemyHUD:: ; 3e036
push hl
push de
push bc
call DrawEnemyHUD
call UpdateEnemyHPPal
pop bc
pop de
pop hl
ret
; 3e043
DrawEnemyHUD: ; 3e043
xor a
ld [hBGMapMode], a
hlcoord 1, 0
lb bc, 4, 11
call ClearBox
farcall DrawEnemyHUDBorder
ld a, [wTempEnemyMonSpecies]
ld [wCurSpecies], a
ld [wCurPartySpecies], a
call GetBaseData
ld de, wEnemyMonNick
hlcoord 1, 0
call ret_3e138
call PlaceString
ld h, b
ld l, c
dec hl
ld hl, wEnemyMonDVs
ld de, wTempMonDVs
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr z, .ok
ld hl, wEnemyBackupDVs
.ok
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld a, TEMPMON
ld [wMonType], a
callfar GetGender
ld a, " "
jr c, .got_gender
ld a, "♂"
jr nz, .got_gender
ld a, "♀"
.got_gender
hlcoord 9, 1
ld [hl], a
hlcoord 6, 1
push af
push hl
ld de, wEnemyMonStatus
predef PlaceNonFaintStatus
pop hl
pop bc
jr nz, .skip_level
ld a, b
cp " "
jr nz, .print_level
dec hl
.print_level
ld a, [wEnemyMonLevel]
ld [wTempMonLevel], a
call PrintLevel
.skip_level
ld hl, wEnemyMonHP
ld a, [hli]
ld [hMultiplicand + 1], a
ld a, [hld]
ld [hMultiplicand + 2], a
or [hl]
jr nz, .not_fainted
ld c, a
ld e, a
ld d, HP_BAR_LENGTH
jp .draw_bar
.not_fainted
xor a
ld [hMultiplicand], a
ld a, HP_BAR_LENGTH_PX
ld [hMultiplier], a
call Multiply
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld b, a
ld a, [hl]
ld [hMultiplier], a
ld a, b
and a
jr z, .less_than_256_max
ld a, [hMultiplier]
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 [hProduct + 3], a
ld a, b
ld [hProduct + 2], a
.less_than_256_max
ld a, [hProduct + 2]
ld [hDividend + 0], a
ld a, [hProduct + 3]
ld [hDividend + 1], a
ld a, 2
ld b, a
call Divide
ld a, [hQuotient + 2]
ld e, a
ld a, HP_BAR_LENGTH
ld d, a
ld c, a
.draw_bar
xor a
ld [wWhichHPBar], a
hlcoord 2, 2
ld b, 0
call DrawBattleHPBar
ret
; 3e127
UpdateEnemyHPPal: ; 3e127
ld hl, wEnemyHPPal
call UpdateHPPal
ret
; 3e12e
UpdateHPPal: ; 3e12e
ld b, [hl]
call SetHPPal
ld a, [hl]
cp b
ret z
jp FinishBattleAnim
; 3e138
ret_3e138: ; 3e138
ret
; 3e139
BattleMenu: ; 3e139
xor a
ld [hBGMapMode], a
call LoadTempTileMapToTileMap
ld a, [wBattleType]
cp BATTLETYPE_DEBUG
jr z, .ok
cp BATTLETYPE_TUTORIAL
jr z, .ok
call EmptyBattleTextBox
call UpdateBattleHuds
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
.ok
.loop
ld a, [wBattleType]
cp BATTLETYPE_CONTEST
jr nz, .not_contest
farcall ContestBattleMenu
jr .next
.not_contest
; Auto input: choose "ITEM"
ld a, [wInputType]
or a
jr z, .skip_dude_pack_select
farcall _DudeAutoInput_DownA
.skip_dude_pack_select
call LoadBattleMenu2
ret c
.next
ld a, $1
ld [hBGMapMode], a
ld a, [wBattleMenuCursorBuffer]
cp $1
jp z, BattleMenu_Fight
cp $3
jp z, BattleMenu_Pack
cp $2
jp z, BattleMenu_PKMN
cp $4
jp z, BattleMenu_Run
jr .loop
; 3e192
BattleMenu_Fight: ; 3e192
xor a
ld [wNumFleeAttempts], a
call Call_LoadTempTileMapToTileMap
and a
ret
; 3e19b
LoadBattleMenu2: ; 3e19b
call IsMobileBattle
jr z, .mobile
farcall LoadBattleMenu
and a
ret
.mobile
farcall Function100b12
ld a, [wcd2b]
and a
ret z
ld hl, wcd2a
bit 4, [hl]
jr nz, .error
ld hl, BattleText_LinkErrorBattleCanceled
call StdBattleTextBox
ld c, 60
call DelayFrames
.error
scf
ret
; 3e1c7
BattleMenu_Pack: ; 3e1c7
ld a, [wLinkMode]
and a
jp nz, .ItemsCantBeUsed
ld a, [wInBattleTowerBattle]
and a
jp nz, .ItemsCantBeUsed
call LoadStandardMenuDataHeader
ld a, [wBattleType]
cp BATTLETYPE_TUTORIAL
jr z, .tutorial
cp BATTLETYPE_CONTEST
jr z, .contest
farcall BattlePack
ld a, [wBattlePlayerAction]
and a
jr z, .didnt_use_item
jr .got_item
.tutorial
farcall TutorialPack
ld a, POKE_BALL
ld [wCurItem], a
call DoItemEffect
jr .got_item
.contest
ld a, PARK_BALL
ld [wCurItem], a
call DoItemEffect
.got_item
call .UseItem
ret
.didnt_use_item
call ClearPalettes
call DelayFrame
call _LoadBattleFontsHPBar
call GetBattleMonBackpic
call GetEnemyMonFrontpic
call ExitMenu
call WaitBGMap
call FinishBattleAnim
call LoadTileMapToTempTileMap
jp BattleMenu
; 3e22b
.ItemsCantBeUsed: ; 3e22b
ld hl, BattleText_ItemsCantBeUsedHere
call StdBattleTextBox
jp BattleMenu
; 3e234
.UseItem: ; 3e234
ld a, [wWildMon]
and a
jr nz, .run
callfar CheckItemPocket
ld a, [wItemAttributeParamBuffer]
cp BALL
jr z, .ball
call ClearBGPalettes
.ball
xor a
ld [hBGMapMode], a
call _LoadBattleFontsHPBar
call ClearSprites
ld a, [wBattleType]
cp BATTLETYPE_TUTORIAL
jr z, .tutorial2
call GetBattleMonBackpic
.tutorial2
call GetEnemyMonFrontpic
ld a, $1
ld [wMenuCursorY], a
call ExitMenu
call UpdateBattleHUDs
call WaitBGMap
call LoadTileMapToTempTileMap
call ClearWindowData
call FinishBattleAnim
and a
ret
.run
xor a
ld [wWildMon], a
ld a, [wBattleResult]
and $c0
ld [wBattleResult], a
call ClearWindowData
call SetPalettes
scf
ret
; 3e28d
BattleMenu_PKMN: ; 3e28d
call LoadStandardMenuDataHeader
BattleMenuPKMN_ReturnFromStats:
call ExitMenu
call LoadStandardMenuDataHeader
call ClearBGPalettes
BattleMenuPKMN_Loop:
call SetUpBattlePartyMenu
xor a
ld [wPartyMenuActionText], a
call JumpToPartyMenuAndPrintText
call SelectBattleMon
jr c, .Cancel
.loop
farcall FreezeMonIcons
call .GetMenu
jr c, .PressedB
call PlaceHollowCursor
ld a, [wMenuCursorY]
cp $1 ; SWITCH
jp z, TryPlayerSwitch
cp $2 ; STATS
jr z, .Stats
cp $3 ; CANCEL
jr z, .Cancel
jr .loop
.PressedB:
call CheckMobileBattleError
jr c, .Cancel
jr BattleMenuPKMN_Loop
.Stats:
call Battle_StatsScreen
call CheckMobileBattleError
jr c, .Cancel
jp BattleMenuPKMN_ReturnFromStats
.Cancel:
call ClearSprites
call ClearPalettes
call DelayFrame
call _LoadHPBar
call CloseWindow
call LoadTileMapToTempTileMap
call GetMemSGBLayout
call SetPalettes
jp BattleMenu
; 3e2f5
.GetMenu: ; 3e2f5
call IsMobileBattle
jr z, .mobile
farcall BattleMonMenu
ret
.mobile
farcall MobileBattleMonMenu
ret
; 3e308
Battle_StatsScreen: ; 3e308
call DisableLCD
ld hl, vTiles2 tile $31
ld de, vTiles0
ld bc, $11 tiles
call CopyBytes
ld hl, vTiles2
ld de, vTiles0 tile $11
ld bc, $31 tiles
call CopyBytes
call EnableLCD
call ClearSprites
call LowVolume
xor a ; PARTYMON
ld [wMonType], a
farcall BattleStatsScreenInit
call MaxVolume
call DisableLCD
ld hl, vTiles0
ld de, vTiles2 tile $31
ld bc, $11 tiles
call CopyBytes
ld hl, vTiles0 tile $11
ld de, vTiles2
ld bc, $31 tiles
call CopyBytes
call EnableLCD
ret
; 3e358
TryPlayerSwitch: ; 3e358
ld a, [wCurBattleMon]
ld d, a
ld a, [wCurPartyMon]
cp d
jr nz, .check_trapped
ld hl, BattleText_MonIsAlreadyOut
call StdBattleTextBox
jp BattleMenuPKMN_Loop
.check_trapped
ld a, [wPlayerWrapCount]
and a
jr nz, .trapped
ld a, [wEnemySubStatus5]
bit SUBSTATUS_CANT_RUN, a
jr z, .try_switch
.trapped
ld hl, BattleText_MonCantBeRecalled
call StdBattleTextBox
jp BattleMenuPKMN_Loop
.try_switch
call CheckIfCurPartyMonIsFitToFight
jp z, BattleMenuPKMN_Loop
ld a, [wCurBattleMon]
ld [wLastPlayerMon], a
ld a, $2
ld [wBattlePlayerAction], a
call ClearPalettes
call DelayFrame
call ClearSprites
call _LoadHPBar
call CloseWindow
call GetMemSGBLayout
call SetPalettes
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
PlayerSwitch: ; 3e3ad
ld a, 1
ld [wPlayerIsSwitching], a
ld a, [wLinkMode]
and a
jr z, .not_linked
call LoadStandardMenuDataHeader
call LinkBattleSendReceiveAction
call CloseWindow
.not_linked
call ParseEnemyAction
ld a, [wLinkMode]
and a
jr nz, .linked
.switch
call BattleMonEntrance
and a
ret
.linked
ld a, [wBattleAction]
cp BATTLEACTION_E
jp z, .switch
cp BATTLEACTION_D
jp z, .switch
cp BATTLEACTION_SWITCH1
jp c, .switch
cp BATTLEACTION_FORFEIT
jr nz, .dont_run
call WildFled_EnemyFled_LinkBattleCanceled
ret
.dont_run
ld a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .player_1
call BattleMonEntrance
call EnemyMonEntrance
and a
ret
.player_1
call EnemyMonEntrance
call BattleMonEntrance
and a
ret
; 3e3ff
EnemyMonEntrance: ; 3e3ff
callfar AI_Switch
call SetEnemyTurn
jp SpikesDamage
; 3e40b
BattleMonEntrance: ; 3e40b
call WithdrawMonText
ld c, 50
call DelayFrames
ld hl, wPlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
call SetEnemyTurn
call PursuitSwitch
jr c, .ok
call RecallPlayerMon
.ok
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
ld a, [wCurBattleMon]
ld [wCurPartyMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call SendOutMonText
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
call SetPlayerTurn
call SpikesDamage
ld a, $2
ld [wMenuCursorY], a
ret
; 3e459
PassedBattleMonEntrance: ; 3e459
ld c, 50
call DelayFrames
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
ld a, [wCurPartyMon]
ld [wCurBattleMon], a
call AddBattleParticipant
call InitBattleMon
xor a
ld [wd265], a
call ApplyStatLevelMultiplierOnAllStats
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
call SetPlayerTurn
jp SpikesDamage
; 3e489
BattleMenu_Run: ; 3e489
call Call_LoadTempTileMapToTileMap
ld a, $3
ld [wMenuCursorY], a
ld hl, wBattleMonSpeed
ld de, wEnemyMonSpeed
call TryToRunAwayFromBattle
ld a, $0
ld [wFailedToFlee], a
ret c
ld a, [wBattlePlayerAction]
and a
ret nz
jp BattleMenu
; 3e4a8
CheckAmuletCoin: ; 3e4a8
ld a, [wBattleMonItem]
ld b, a
callfar GetItemHeldEffect
ld a, b
cp HELD_AMULET_COIN
ret nz
ld a, 1
ld [wAmuletCoin], a
ret
; 3e4bc
MoveSelectionScreen: ; 3e4bc
call IsMobileBattle
jr nz, .not_mobile
farcall MobileMoveSelectionScreen
ret
.not_mobile
ld hl, wEnemyMonMoves
ld a, [wMoveSelectionMenuType]
dec a
jr z, .got_menu_type
dec a
jr z, .ether_elixer_menu
call CheckPlayerHasUsableMoves
ret z ; use Struggle
ld hl, wBattleMonMoves
jr .got_menu_type
.ether_elixer_menu
ld a, MON_MOVES
call GetPartyParamLocation
.got_menu_type
ld de, wListMoves_MoveIndicesBuffer
ld bc, NUM_MOVES
call CopyBytes
xor a
ld [hBGMapMode], a
hlcoord 4, 17 - NUM_MOVES - 1
ld b, 4
ld c, 14
ld a, [wMoveSelectionMenuType]
cp $2
jr nz, .got_dims
hlcoord 4, 17 - NUM_MOVES - 1 - 4
ld b, 4
ld c, 14
.got_dims
call TextBox
hlcoord 6, 17 - NUM_MOVES
ld a, [wMoveSelectionMenuType]
cp $2
jr nz, .got_start_coord
hlcoord 6, 17 - NUM_MOVES - 4
.got_start_coord
ld a, SCREEN_WIDTH
ld [wBuffer1], a
predef ListMoves
ld b, 5
ld a, [wMoveSelectionMenuType]
cp $2
ld a, 17 - NUM_MOVES
jr nz, .got_default_coord
ld b, 5
ld a, 17 - NUM_MOVES - 4
.got_default_coord
ld [w2DMenuCursorInitY], a
ld a, b
ld [w2DMenuCursorInitX], a
ld a, [wMoveSelectionMenuType]
cp $1
jr z, .skip_inc
ld a, [wCurMoveNum]
inc a
.skip_inc
ld [wMenuCursorY], a
ld a, $1
ld [wMenuCursorX], a
ld a, [wNumMoves]
inc a
ld [w2DMenuNumRows], a
ld a, $1
ld [w2DMenuNumCols], a
ld c, $2c
ld a, [wMoveSelectionMenuType]
dec a
ld b, D_DOWN | D_UP | A_BUTTON
jr z, .okay
dec a
ld b, D_DOWN | D_UP | A_BUTTON | B_BUTTON
jr z, .okay
ld a, [wLinkMode]
and a
jr nz, .okay
ld b, D_DOWN | D_UP | A_BUTTON | B_BUTTON | SELECT
.okay
ld a, b
ld [wMenuJoypadFilter], a
ld a, c
ld [w2DMenuFlags1], a
xor a
ld [w2DMenuFlags2], a
ld a, $10
ld [w2DMenuCursorOffsets], a
.menu_loop
ld a, [wMoveSelectionMenuType]
and a
jr z, .battle_player_moves
dec a
jr nz, .interpret_joypad
hlcoord 11, 14
ld de, .string_3e61c
call PlaceString
jr .interpret_joypad
.battle_player_moves
call MoveInfoBox
ld a, [wMoveSwapBuffer]
and a
jr z, .interpret_joypad
hlcoord 5, 13
ld bc, SCREEN_WIDTH
dec a
call AddNTimes
ld [hl], "â–·"
.interpret_joypad
ld a, $1
ld [hBGMapMode], a
call ScrollingMenuJoypad
bit D_UP_F, a
jp nz, .pressed_up
bit D_DOWN_F, a
jp nz, .pressed_down
bit SELECT_F, a
jp nz, .pressed_select
bit B_BUTTON_F, a
; A button
push af
xor a
ld [wMoveSwapBuffer], a
ld a, [wMenuCursorY]
dec a
ld [wMenuCursorY], a
ld b, a
ld a, [wMoveSelectionMenuType]
dec a
jr nz, .not_enemy_moves_process_b
pop af
ret
.not_enemy_moves_process_b
dec a
ld a, b
ld [wCurMoveNum], a
jr nz, .use_move
pop af
ret
.use_move
pop af
ret nz
ld hl, wBattleMonPP
ld a, [wMenuCursorY]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and PP_MASK
jr z, .no_pp_left
ld a, [wPlayerDisableCount]
swap a
and $f
dec a
cp c
jr z, .move_disabled
ld a, [wUnusedPlayerLockedMove]
and a
jr nz, .skip2
ld a, [wMenuCursorY]
ld hl, wBattleMonMoves
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
.skip2
ld [wCurPlayerMove], a
xor a
ret
.move_disabled
ld hl, BattleText_TheMoveIsDisabled
jr .place_textbox_start_over
.no_pp_left
ld hl, BattleText_TheresNoPPLeftForThisMove
.place_textbox_start_over
call StdBattleTextBox
call Call_LoadTempTileMapToTileMap
jp MoveSelectionScreen
; 3e61c
.string_3e61c ; 3e61c
db "@"
; 3e61d
.pressed_up
ld a, [wMenuCursorY]
and a
jp nz, .menu_loop
ld a, [wNumMoves]
inc a
ld [wMenuCursorY], a
jp .menu_loop
; 3e62e
.pressed_down ; 3e62e
ld a, [wMenuCursorY]
ld b, a
ld a, [wNumMoves]
inc a
inc a
cp b
jp nz, .menu_loop
ld a, $1
ld [wMenuCursorY], a
jp .menu_loop
; 3e643
.pressed_select ; 3e643
ld a, [wMoveSwapBuffer]
and a
jr z, .start_swap
ld hl, wBattleMonMoves
call .swap_bytes
ld hl, wBattleMonPP
call .swap_bytes
ld hl, wPlayerDisableCount
ld a, [hl]
swap a
and $f
ld b, a
ld a, [wMenuCursorY]
cp b
jr nz, .not_swapping_disabled_move
ld a, [hl]
and $f
ld b, a
ld a, [wMoveSwapBuffer]
swap a
add b
ld [hl], a
jr .swap_moves_in_party_struct
.not_swapping_disabled_move
ld a, [wMoveSwapBuffer]
cp b
jr nz, .swap_moves_in_party_struct
ld a, [hl]
and $f
ld b, a
ld a, [wMenuCursorY]
swap a
add b
ld [hl], a
.swap_moves_in_party_struct
; Fixes the COOLTRAINER glitch
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .transformed
ld hl, wPartyMon1Moves
ld a, [wCurBattleMon]
call GetPartyLocation
push hl
call .swap_bytes
pop hl
ld bc, MON_PP - MON_MOVES
add hl, bc
call .swap_bytes
.transformed
xor a
ld [wMoveSwapBuffer], a
jp MoveSelectionScreen
.swap_bytes
push hl
ld a, [wMoveSwapBuffer]
dec a
ld c, a
ld b, 0
add hl, bc
ld d, h
ld e, l
pop hl
ld a, [wMenuCursorY]
dec a
ld c, a
ld b, 0
add hl, bc
ld a, [de]
ld b, [hl]
ld [hl], a
ld a, b
ld [de], a
ret
.start_swap
ld a, [wMenuCursorY]
ld [wMoveSwapBuffer], a
jp MoveSelectionScreen
; 3e6c8
MoveInfoBox: ; 3e6c8
xor a
ld [hBGMapMode], a
hlcoord 0, 8
ld b, 3
ld c, 9
call TextBox
call MobileTextBorder
ld a, [wPlayerDisableCount]
and a
jr z, .not_disabled
swap a
and $f
ld b, a
ld a, [wMenuCursorY]
cp b
jr nz, .not_disabled
hlcoord 1, 10
ld de, .Disabled
call PlaceString
jr .done
.not_disabled
ld hl, wMenuCursorY
dec [hl]
call SetPlayerTurn
ld hl, wBattleMonMoves
ld a, [wMenuCursorY]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [wCurPlayerMove], a
ld a, [wCurBattleMon]
ld [wCurPartyMon], a
ld a, WILDMON
ld [wMonType], a
callfar GetMaxPPOfMove
ld hl, wMenuCursorY
ld c, [hl]
inc [hl]
ld b, 0
ld hl, wBattleMonPP
add hl, bc
ld a, [hl]
and PP_MASK
ld [wStringBuffer1], a
call .PrintPP
hlcoord 1, 9
ld de, .Type
call PlaceString
hlcoord 7, 11
ld [hl], "/"
callfar UpdateMoveData
ld a, [wPlayerMoveStruct + MOVE_ANIM]
ld b, a
hlcoord 2, 10
predef PrintMoveType
.done
ret
; 3e74f
.Disabled:
db "Disabled!@"
.Type:
db "TYPE/@"
; 3e75f
.PrintPP: ; 3e75f
hlcoord 5, 11
ld a, [wLinkMode] ; What's the point of this check?
cp LINK_MOBILE
jr c, .ok
hlcoord 5, 11
.ok
push hl
ld de, wStringBuffer1
lb bc, 1, 2
call PrintNum
pop hl
inc hl
inc hl
ld [hl], "/"
inc hl
ld de, wNamedObjectIndexBuffer
lb bc, 1, 2
call PrintNum
ret
; 3e786
CheckPlayerHasUsableMoves: ; 3e786
ld a, STRUGGLE
ld [wCurPlayerMove], a
ld a, [wPlayerDisableCount]
and a
ld hl, wBattleMonPP
jr nz, .disabled
ld a, [hli]
or [hl]
inc hl
or [hl]
inc hl
or [hl]
and PP_MASK
ret nz
jr .force_struggle
.disabled
swap a
and $f
ld b, a
ld d, NUM_MOVES + 1
xor a
.loop
dec d
jr z, .done
ld c, [hl]
inc hl
dec b
jr z, .loop
or c
jr .loop
.done
; Bug: this will result in a move with PP Up confusing the game.
and a ; should be "and PP_MASK"
ret nz
.force_struggle
ld hl, BattleText_MonHasNoMovesLeft
call StdBattleTextBox
ld c, 60
call DelayFrames
xor a
ret
; 3e7c1
ParseEnemyAction: ; 3e7c1
ld a, [wEnemyIsSwitching]
and a
ret nz
ld a, [wLinkMode]
and a
jr z, .not_linked
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld a, [wBattlePlayerAction]
and a
call z, LinkBattleSendReceiveAction
call Call_LoadTempTileMapToTileMap
ld a, [wBattleAction]
cp BATTLEACTION_E
jp z, .struggle
cp BATTLEACTION_D
jp z, .battle_action_d
cp BATTLEACTION_SWITCH1
jp nc, ResetVarsForSubstatusRage
ld [wCurEnemyMoveNum], a
ld c, a
ld a, [wEnemySubStatus1]
bit SUBSTATUS_ROLLOUT, a
jp nz, .skip_load
ld a, [wEnemySubStatus3]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE
jp nz, .skip_load
ld hl, wEnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
ld a, [wLastEnemyMove]
jp nz, .finish
ld hl, wEnemyMonMoves
ld b, 0
add hl, bc
ld a, [hl]
jp .finish
.not_linked
ld hl, wEnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
jr z, .skip_encore
ld a, [wLastEnemyMove]
jp .finish
.skip_encore
call CheckEnemyLockedIn
jp nz, ResetVarsForSubstatusRage
jr .continue
.battle_action_d
ld a, $ff
jr .finish
.continue
ld hl, wEnemyMonMoves
ld de, wEnemyMonPP
ld b, NUM_MOVES
.loop
ld a, [hl]
and a
jp z, .struggle
ld a, [wEnemyDisabledMove]
cp [hl]
jr z, .disabled
ld a, [de]
and PP_MASK
jr nz, .enough_pp
.disabled
inc hl
inc de
dec b
jr nz, .loop
jr .struggle
.enough_pp
ld a, [wBattleMode]
dec a
jr nz, .skip_load
; wild
.loop2
ld hl, wEnemyMonMoves
call BattleRandom
maskbits NUM_MOVES
ld c, a
ld b, 0
add hl, bc
ld a, [wEnemyDisableCount]
swap a
and $f
dec a
cp c
jr z, .loop2
ld a, [hl]
and a
jr z, .loop2
ld hl, wEnemyMonPP
add hl, bc
ld b, a
ld a, [hl]
and PP_MASK
jr z, .loop2
ld a, c
ld [wCurEnemyMoveNum], a
ld a, b
.finish
ld [wCurEnemyMove], a
.skip_load
call SetEnemyTurn
callfar UpdateMoveData
call CheckEnemyLockedIn
jr nz, .raging
xor a
ld [wEnemyCharging], a
.raging
ld a, [wEnemyMoveStruct + MOVE_EFFECT]
cp EFFECT_FURY_CUTTER
jr z, .fury_cutter
xor a
ld [wEnemyFuryCutterCount], a
.fury_cutter
ld a, [wEnemyMoveStruct + MOVE_EFFECT]
cp EFFECT_RAGE
jr z, .no_rage
ld hl, wEnemySubStatus4
res SUBSTATUS_RAGE, [hl]
xor a
ld [wEnemyRageCounter], a
.no_rage
ld a, [wEnemyMoveStruct + MOVE_EFFECT]
cp EFFECT_PROTECT
ret z
cp EFFECT_ENDURE
ret z
xor a
ld [wEnemyProtectCount], a
ret
.struggle
ld a, STRUGGLE
jr .finish
; 3e8c1
ResetVarsForSubstatusRage: ; 3e8c1
xor a
ld [wEnemyFuryCutterCount], a
ld [wEnemyProtectCount], a
ld [wEnemyRageCounter], a
ld hl, wEnemySubStatus4
res SUBSTATUS_RAGE, [hl]
ret
; 3e8d1
CheckEnemyLockedIn: ; 3e8d1
ld a, [wEnemySubStatus4]
and 1 << SUBSTATUS_RECHARGE
ret nz
ld hl, wEnemySubStatus3
ld a, [hl]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE
ret nz
ld hl, wEnemySubStatus1
bit SUBSTATUS_ROLLOUT, [hl]
ret
; 3e8e4
LinkBattleSendReceiveAction: ; 3e8e4
farcall _LinkBattleSendReceiveAction
ret
; 3e8eb
LoadEnemyMon: ; 3e8eb
; Initialize enemy monster parameters
; To do this we pull the species from wTempEnemyMonSpecies
; Notes:
; BattleRandom is used to ensure sync between Game Boys
; Clear the whole enemy mon struct (wEnemyMon)
xor a
ld hl, wEnemyMonSpecies
ld bc, wEnemyMonEnd - wEnemyMon
call ByteFill
; We don't need to be here if we're in a link battle
ld a, [wLinkMode]
and a
jp nz, InitEnemyMon
; and also not in a BattleTower-Battle
ld a, [wInBattleTowerBattle] ; ????
bit 0, a
jp nz, InitEnemyMon
; Make sure everything knows what species we're working with
ld a, [wTempEnemyMonSpecies]
ld [wEnemyMonSpecies], a
ld [wCurSpecies], a
ld [wCurPartySpecies], a
; Grab the BaseData for this species
call GetBaseData
; Let's get the item:
; Is the item predetermined?
ld a, [wBattleMode]
dec a
jr z, .WildItem
; If we're in a trainer battle, the item is in the party struct
ld a, [wCurPartyMon]
ld hl, wOTPartyMon1Item
call GetPartyLocation ; bc = PartyMon[wCurPartyMon] - wPartyMons
ld a, [hl]
jr .UpdateItem
.WildItem:
; In a wild battle, we pull from the item slots in BaseData
; Force Item1
; Used for Ho-Oh, Lugia and Snorlax encounters
ld a, [wBattleType]
cp BATTLETYPE_FORCEITEM
ld a, [wBaseItems]
jr z, .UpdateItem
; Failing that, it's all up to chance
; Effective chances:
; 75% None
; 23% Item1
; 2% Item2
; 25% chance of getting an item
call BattleRandom
cp 1 + (75 percent)
ld a, NO_ITEM
jr c, .UpdateItem
; From there, an 8% chance for Item2
call BattleRandom
cp 8 percent ; 8% of 25% = 2% Item2
ld a, [wBaseItems]
jr nc, .UpdateItem
ld a, [wBaseItems+1]
.UpdateItem:
ld [wEnemyMonItem], a
; Initialize DVs
; If we're in a trainer battle, DVs are predetermined
ld a, [wBattleMode]
and a
jr z, .InitDVs
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr z, .InitDVs
; Unknown
ld hl, wEnemyBackupDVs
ld de, wEnemyMonDVs
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
jp .Happiness
.InitDVs:
; Trainer DVs
; All trainers have preset DVs, determined by class
; See GetTrainerDVs for more on that
farcall GetTrainerDVs
; These are the DVs we'll use if we're actually in a trainer battle
ld a, [wBattleMode]
dec a
jr nz, .UpdateDVs
; Wild DVs
; Here's where the fun starts
; Roaming monsters (Entei, Raikou) work differently
; They have their own structs, which are shorter than normal
ld a, [wBattleType]
cp BATTLETYPE_ROAMING
jr nz, .NotRoaming
; Grab HP
call GetRoamMonHP
ld a, [hl]
; Check if the HP has been initialized
and a
; We'll do something with the result in a minute
push af
; Grab DVs
call GetRoamMonDVs
inc hl
ld a, [hld]
ld c, a
ld b, [hl]
; Get back the result of our check
pop af
; If the RoamMon struct has already been initialized, we're done
jr nz, .UpdateDVs
; If it hasn't, we need to initialize the DVs
; (HP is initialized at the end of the battle)
call GetRoamMonDVs
inc hl
call BattleRandom
ld [hld], a
ld c, a
call BattleRandom
ld [hl], a
ld b, a
; We're done with DVs
jr .UpdateDVs
.NotRoaming:
; Register a contains wBattleType
; Forced shiny battle type
; Used by Red Gyarados at Lake of Rage
cp BATTLETYPE_SHINY
jr nz, .GenerateDVs
ld b, ATKDEFDV_SHINY ; $ea
ld c, SPDSPCDV_SHINY ; $aa
jr .UpdateDVs
.GenerateDVs:
; Generate new random DVs
call BattleRandom
ld b, a
call BattleRandom
ld c, a
.UpdateDVs:
; Input DVs in register bc
ld hl, wEnemyMonDVs
ld a, b
ld [hli], a
ld [hl], c
; We've still got more to do if we're dealing with a wild monster
ld a, [wBattleMode]
dec a
jr nz, .Happiness
; Species-specfic:
; Unown
ld a, [wTempEnemyMonSpecies]
cp UNOWN
jr nz, .Magikarp
; Get letter based on DVs
ld hl, wEnemyMonDVs
predef GetUnownLetter
; Can't use any letters that haven't been unlocked
; If combined with forced shiny battletype, causes an infinite loop
call CheckUnownLetter
jr c, .GenerateDVs ; try again
.Magikarp:
; These filters are untranslated.
; They expect at wMagikarpLength a 2-byte value in mm,
; but the value is in feet and inches (one byte each).
; The first filter is supposed to make very large Magikarp even rarer,
; by targeting those 1600 mm (= 5'3") or larger.
; After the conversion to feet, it is unable to target any,
; since the largest possible Magikarp is 5'3", and $0503 = 1283 mm.
ld a, [wTempEnemyMonSpecies]
cp MAGIKARP
jr nz, .Happiness
; Get Magikarp's length
ld de, wEnemyMonDVs
ld bc, wPlayerID
callfar CalcMagikarpLength
; No reason to keep going if length > 1536 mm (i.e. if HIGH(length) > 6 feet)
ld a, [wMagikarpLength]
cp HIGH(1536) ; should be "cp 5", since 1536 mm = 5'0", but HIGH(1536) = 6
jr nz, .CheckMagikarpArea
; 5% chance of skipping both size checks
call Random
cp 5 percent
jr c, .CheckMagikarpArea
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 3 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1616) ; should be "cp 3", since 1616 mm = 5'3", but LOW(1616) = 80
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp 20 percent - 1
jr c, .CheckMagikarpArea
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 2 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1600) ; should be "cp 2", since 1600 mm = 5'2", but LOW(1600) = 64
jr nc, .GenerateDVs
.CheckMagikarpArea:
; The "jr z" checks are supposed to be "jr nz".
; Instead, all maps in GROUP_LAKE_OF_RAGE (Mahogany area)
; and Routes 20 and 44 are treated as Lake of Rage.
; This also means Lake of Rage Magikarp can be smaller than ones
; caught elsewhere rather than the other way around.
; Intended behavior enforces a minimum size at Lake of Rage.
; The real behavior prevents a minimum size in the Lake of Rage area.
; Moreover, due to the check not being translated to feet+inches, all Magikarp
; smaller than 4'0" may be caught by the filter, a lot more than intended.
ld a, [wMapGroup]
cp GROUP_LAKE_OF_RAGE
jr z, .Happiness
ld a, [wMapNumber]
cp MAP_LAKE_OF_RAGE
jr z, .Happiness
; 40% chance of not flooring
call Random
cp 40 percent - 2
jr c, .Happiness
; Try again if length < 1024 mm (i.e. if HIGH(length) < 3 feet)
ld a, [wMagikarpLength]
cp HIGH(1024) ; should be "cp 3", since 1024 mm = 3'4", but HIGH(1024) = 4
jr c, .GenerateDVs ; try again
; Finally done with DVs
.Happiness:
; Set happiness
ld a, BASE_HAPPINESS
ld [wEnemyMonHappiness], a
; Set level
ld a, [wCurPartyLevel]
ld [wEnemyMonLevel], a
; Fill stats
ld de, wEnemyMonMaxHP
ld b, FALSE
ld hl, wEnemyMonDVs - (MON_DVS - MON_STAT_EXP + 1) ; wLinkBattleRNs + 7 ; ?
predef CalcMonStats
; If we're in a trainer battle,
; get the rest of the parameters from the party struct
ld a, [wBattleMode]
cp TRAINER_BATTLE
jr z, .OpponentParty
; If we're in a wild battle, check wild-specific stuff
and a
jr z, .TreeMon
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jp nz, .Moves
.TreeMon:
; If we're headbutting trees, some monsters enter battle asleep
call CheckSleepingTreeMon
ld a, TREEMON_SLEEP_TURNS
jr c, .UpdateStatus
; Otherwise, no status
xor a
.UpdateStatus:
ld hl, wEnemyMonStatus
ld [hli], a
; Unused byte
xor a
ld [hli], a
; Full HP..
ld a, [wEnemyMonMaxHP]
ld [hli], a
ld a, [wEnemyMonMaxHP + 1]
ld [hl], a
; ..unless it's a RoamMon
ld a, [wBattleType]
cp BATTLETYPE_ROAMING
jr nz, .Moves
; Grab HP
call GetRoamMonHP
ld a, [hl]
; Check if it's been initialized again
and a
jr z, .InitRoamHP
; Update from the struct if it has
ld a, [hl]
ld [wEnemyMonHP + 1], a
jr .Moves
.InitRoamHP:
; HP only uses the lo byte in the RoamMon struct since
; Raikou/Entei/Suicune will have < 256 hp at level 40
ld a, [wEnemyMonHP + 1]
ld [hl], a
jr .Moves
.OpponentParty:
; Get HP from the party struct
ld hl, (wOTPartyMon1HP + 1)
ld a, [wCurPartyMon]
call GetPartyLocation
ld a, [hld]
ld [wEnemyMonHP + 1], a
ld a, [hld]
ld [wEnemyMonHP], a
; Make sure everything knows which monster the opponent is using
ld a, [wCurPartyMon]
ld [wCurOTMon], a
; Get status from the party struct
dec hl
ld a, [hl] ; OTPartyMonStatus
ld [wEnemyMonStatus], a
.Moves:
ld hl, wBaseType1
ld de, wEnemyMonType1
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
; Get moves
ld de, wEnemyMonMoves
; Are we in a trainer battle?
ld a, [wBattleMode]
cp TRAINER_BATTLE
jr nz, .WildMoves
; Then copy moves from the party struct
ld hl, wOTPartyMon1Moves
ld a, [wCurPartyMon]
call GetPartyLocation
ld bc, NUM_MOVES
call CopyBytes
jr .PP
.WildMoves:
; Clear wEnemyMonMoves
xor a
ld h, d
ld l, e
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
; Make sure the predef knows this isn't a partymon
ld [wEvolutionOldSpecies], a
; Fill moves based on level
predef FillMoves
.PP:
; Trainer battle?
ld a, [wBattleMode]
cp TRAINER_BATTLE
jr z, .TrainerPP
; Fill wild PP
ld hl, wEnemyMonMoves
ld de, wEnemyMonPP
predef FillPP
jr .Finish
.TrainerPP:
; Copy PP from the party struct
ld hl, wOTPartyMon1PP
ld a, [wCurPartyMon]
call GetPartyLocation
ld de, wEnemyMonPP
ld bc, NUM_MOVES
call CopyBytes
.Finish:
; Only the first five base stats are copied..
ld hl, wBaseStats
ld de, wEnemyMonBaseStats
ld b, wBaseSpecialDefense - wBaseStats
.loop
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .loop
ld a, [wBaseCatchRate]
ld [de], a
inc de
ld a, [wBaseExp]
ld [de], a
ld a, [wTempEnemyMonSpecies]
ld [wd265], a
call GetPokemonName
; Did we catch it?
ld a, [wBattleMode]
and a
ret z
; Update enemy nick
ld hl, wStringBuffer1
ld de, wEnemyMonNick
ld bc, MON_NAME_LENGTH
call CopyBytes
; Saw this mon
ld a, [wTempEnemyMonSpecies]
dec a
ld c, a
ld b, SET_FLAG
ld hl, wPokedexSeen
predef SmallFarFlagAction
ld hl, wEnemyMonStats
ld de, wEnemyStats
ld bc, wEnemyMonStatsEnd - wEnemyMonStats
call CopyBytes
ret
; 3eb38
CheckSleepingTreeMon: ; 3eb38
; Return carry if species is in the list
; for the current time of day
; Don't do anything if this isn't a tree encounter
ld a, [wBattleType]
cp BATTLETYPE_TREE
jr nz, .NotSleeping
; Get list for the time of day
ld hl, AsleepTreeMonsMorn
ld a, [wTimeOfDay]
cp DAY_F
jr c, .Check
ld hl, AsleepTreeMonsDay
jr z, .Check
ld hl, AsleepTreeMonsNite
.Check:
ld a, [wTempEnemyMonSpecies]
ld de, 1 ; length of species id
call IsInArray
; If it's a match, the opponent is asleep
ret c
.NotSleeping:
and a
ret
INCLUDE "data/wild/treemons_asleep.asm"
CheckUnownLetter: ; 3eb75
; Return carry if the Unown letter hasn't been unlocked yet
ld a, [wUnlockedUnowns]
ld c, a
ld de, 0
.loop
; Don't check this set unless it's been unlocked
srl c
jr nc, .next
; Is our letter in the set?
ld hl, .LetterSets
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
push de
ld a, [wUnownLetter]
ld de, 1
push bc
call IsInArray
pop bc
pop de
jr c, .match
.next
; Make sure we haven't gone past the end of the table
inc e
inc e
ld a, e
cp .Set1 - .LetterSets
jr c, .loop
; Hasn't been unlocked, or the letter is invalid
scf
ret
.match
; Valid letter
and a
ret
.LetterSets:
dw .Set1
dw .Set2
dw .Set3
dw .Set4
.Set1:
; A B C D E F G H I J K
db 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, $ff
.Set2:
; L M N O P Q R
db 12, 13, 14, 15, 16, 17, 18, $ff
.Set3:
; S T U V W
db 19, 20, 21, 22, 23, $ff
.Set4:
; X Y Z
db 24, 25, 26, $ff
; 3ebc7
Unreferenced_SwapBattlerLevels: ; 3ebc7
push bc
ld a, [wBattleMonLevel]
ld b, a
ld a, [wEnemyMonLevel]
ld [wBattleMonLevel], a
ld a, b
ld [wEnemyMonLevel], a
pop bc
ret
; 3ebd8
BattleWinSlideInEnemyTrainerFrontpic: ; 3ebd8
xor a
ld [wTempEnemyMonSpecies], a
call FinishBattleAnim
ld a, [wOtherTrainerClass]
ld [wTrainerClass], a
ld de, vTiles2
callfar GetTrainerPic
hlcoord 19, 0
ld c, 0
.outer_loop
inc c
ld a, c
cp 7
ret z
xor a
ld [hBGMapMode], a
ld [hBGMapThird], a
ld d, $0
push bc
push hl
.inner_loop
call .CopyColumn
inc hl
ld a, 7
add d
ld d, a
dec c
jr nz, .inner_loop
ld a, $1
ld [hBGMapMode], a
ld c, 4
call DelayFrames
pop hl
pop bc
dec hl
jr .outer_loop
; 3ec1a
.CopyColumn: ; 3ec1a
push hl
push de
push bc
ld e, 7
.loop
ld [hl], d
ld bc, SCREEN_WIDTH
add hl, bc
inc d
dec e
jr nz, .loop
pop bc
pop de
pop hl
ret
; 3ec2c
ApplyStatusEffectOnPlayerStats: ; 3ec2c
ld a, 1
jr ApplyStatusEffectOnStats
; 3ec30
ApplyStatusEffectOnEnemyStats: ; 3ec30
xor a
; 3ec31
ApplyStatusEffectOnStats: ; 3ec31
ld [hBattleTurn], a
call ApplyPrzEffectOnSpeed
jp ApplyBrnEffectOnAttack
; 3ec39
ApplyPrzEffectOnSpeed: ; 3ec39
ld a, [hBattleTurn]
and a
jr z, .enemy
ld a, [wBattleMonStatus]
and 1 << PAR
ret z
ld hl, wBattleMonSpeed + 1
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
srl a
rr b
ld [hli], a
or b
jr nz, .player_ok
ld b, $1 ; min speed
.player_ok
ld [hl], b
ret
.enemy
ld a, [wEnemyMonStatus]
and 1 << PAR
ret z
ld hl, wEnemyMonSpeed + 1
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
srl a
rr b
ld [hli], a
or b
jr nz, .enemy_ok
ld b, $1 ; min speed
.enemy_ok
ld [hl], b
ret
; 3ec76
ApplyBrnEffectOnAttack: ; 3ec76
ld a, [hBattleTurn]
and a
jr z, .enemy
ld a, [wBattleMonStatus]
and 1 << BRN
ret z
ld hl, wBattleMonAttack + 1
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
ld [hli], a
or b
jr nz, .player_ok
ld b, $1 ; min attack
.player_ok
ld [hl], b
ret
.enemy
ld a, [wEnemyMonStatus]
and 1 << BRN
ret z
ld hl, wEnemyMonAttack + 1
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
ld [hli], a
or b
jr nz, .enemy_ok
ld b, $1 ; min attack
.enemy_ok
ld [hl], b
ret
; 3ecab
ApplyStatLevelMultiplierOnAllStats: ; 3ecab
; Apply StatLevelMultipliers on all 5 Stats
ld c, 0
.stat_loop
call ApplyStatLevelMultiplier
inc c
ld a, c
cp 5
jr nz, .stat_loop
ret
; 3ecb7
ApplyStatLevelMultiplier: ; 3ecb7
push bc
push bc
ld a, [wd265]
and a
ld a, c
ld hl, wBattleMonAttack
ld de, wPlayerStats
ld bc, wPlayerAtkLevel
jr z, .got_pointers
ld hl, wEnemyMonAttack
ld de, wEnemyStats
ld bc, wEnemyAtkLevel
.got_pointers
add c
ld c, a
jr nc, .okay
inc b
.okay
ld a, [bc]
pop bc
ld b, a
push bc
sla c
ld b, 0
add hl, bc
ld a, c
add e
ld e, a
jr nc, .okay2
inc d
.okay2
pop bc
push hl
ld hl, .StatLevelMultipliers
dec b
sla b
ld c, b
ld b, 0
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
ld a, [hli]
ld [hMultiplier], a
call Multiply
ld a, [hl]
ld [hDivisor], a
ld b, $4
call Divide
pop hl
; Cap at 999.
ld a, [hQuotient + 2]
sub LOW(MAX_STAT_VALUE)
ld a, [hQuotient + 1]
sbc HIGH(MAX_STAT_VALUE)
jp c, .okay3
ld a, HIGH(MAX_STAT_VALUE)
ld [hQuotient + 1], a
ld a, LOW(MAX_STAT_VALUE)
ld [hQuotient + 2], a
.okay3
ld a, [hQuotient + 1]
ld [hli], a
ld b, a
ld a, [hQuotient + 2]
ld [hl], a
or b
jr nz, .okay4
inc [hl]
.okay4
pop bc
ret
; 3ed2b
.StatLevelMultipliers:
; /
db 25, 100 ; 25%
db 28, 100 ; 28%
db 33, 100 ; 33%
db 40, 100 ; 40%
db 50, 100 ; 50%
db 66, 100 ; 66%
db 1, 1 ; 100%
db 15, 10 ; 150%
db 2, 1 ; 200%
db 25, 10 ; 250%
db 3, 1 ; 300%
db 35, 10 ; 350%
db 4, 1 ; 400%
; 3ed45
BadgeStatBoosts: ; 3ed45
; Raise the stats of the battle mon in wBattleMon
; depending on which badges have been obtained.
; Every other badge boosts a stat, starting from the first.
; ZephyrBadge: Attack
; PlainBadge: Speed
; MineralBadge: Defense
; GlacierBadge: Special Attack
; RisingBadge: Special Defense
; The boosted stats are in order, except PlainBadge and MineralBadge's boosts are swapped.
ld a, [wLinkMode]
and a
ret nz
ld a, [wInBattleTowerBattle]
and a
ret nz
ld a, [wJohtoBadges]
; Swap badges 3 (PlainBadge) and 5 (MineralBadge).
ld d, a
and (1 << PLAINBADGE)
add a
add a
ld b, a
ld a, d
and (1 << MINERALBADGE)
rrca
rrca
ld c, a
ld a, d
and ((1 << ZEPHYRBADGE) | (1 << HIVEBADGE) | (1 << FOGBADGE) | (1 << STORMBADGE) | (1 << GLACIERBADGE) | (1 << RISINGBADGE))
or b
or c
ld b, a
ld hl, wBattleMonAttack
ld c, 4
.CheckBadge:
ld a, b
srl b
call c, BoostStat
inc hl
inc hl
; Check every other badge.
srl b
dec c
jr nz, .CheckBadge
; And the last one (RisingBadge) too.
srl a
call c, BoostStat
ret
; 3ed7c
BoostStat: ; 3ed7c
; Raise stat at hl by 1/8.
ld a, [hli]
ld d, a
ld e, [hl]
srl d
rr e
srl d
rr e
srl d
rr e
ld a, [hl]
add e
ld [hld], a
ld a, [hl]
adc d
ld [hli], a
; Cap at 999.
ld a, [hld]
sub LOW(MAX_STAT_VALUE)
ld a, [hl]
sbc HIGH(MAX_STAT_VALUE)
ret c
ld a, HIGH(MAX_STAT_VALUE)
ld [hli], a
ld a, LOW(MAX_STAT_VALUE)
ld [hld], a
ret
; 3ed9f
_LoadBattleFontsHPBar: ; 3ed9f
callfar LoadBattleFontsHPBar
ret
; 3eda6
_LoadHPBar: ; 3eda6
callfar LoadHPBar
ret
; 3edad
Unreferenced_LoadHPExpBarGFX:
ld de, EnemyHPBarBorderGFX
ld hl, vTiles2 tile $6c
lb bc, BANK(EnemyHPBarBorderGFX), 4
call Get1bpp
ld de, HPExpBarBorderGFX
ld hl, vTiles2 tile $73
lb bc, BANK(HPExpBarBorderGFX), 6
call Get1bpp
ld de, ExpBarGFX
ld hl, vTiles2 tile $55
lb bc, BANK(ExpBarGFX), 8
jp Get2bpp
; 3edd1
EmptyBattleTextBox: ; 3edd1
ld hl, .empty
jp BattleTextBox
.empty
db "@"
; 3edd8
_BattleRandom:: ; 3edd8
; If the normal RNG is used in a link battle it'll desync.
; To circumvent this a shared PRNG is used instead.
; But if we're in a non-link battle we're safe to use it
ld a, [wLinkMode]
and a
jp z, Random
; The PRNG operates in streams of 10 values.
; Which value are we trying to pull?
push hl
push bc
ld a, [wLinkBattleRNCount]
ld c, a
ld b, 0
ld hl, wLinkBattleRNs
add hl, bc
inc a
ld [wLinkBattleRNCount], a
; If we haven't hit the end yet, we're good
cp 10 - 1 ; Exclude last value. See the closing comment
ld a, [hl]
pop bc
pop hl
ret c
; If we have, we have to generate new pseudorandom data
; Instead of having multiple PRNGs, ten seeds are used
push hl
push bc
push af
; Reset count to 0
xor a
ld [wLinkBattleRNCount], a
ld hl, wLinkBattleRNs
ld b, 10 ; number of seeds
; Generate next number in the sequence for each seed
; a[n+1] = (a[n] * 5 + 1) % 256
.loop
; get last #
ld a, [hl]
; a * 5 + 1
ld c, a
add a
add a
add c
inc a
; update #
ld [hli], a
dec b
jr nz, .loop
; This has the side effect of pulling the last value first,
; then wrapping around. As a result, when we check to see if
; we've reached the end, we check the one before it.
pop af
pop bc
pop hl
ret
; 3ee0f
Call_PlayBattleAnim_OnlyIfVisible: ; 3ee0f
ld a, BATTLE_VARS_SUBSTATUS3
call GetBattleVar
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
ret nz
; 3ee17
Call_PlayBattleAnim: ; 3ee17
ld a, e
ld [wFXAnimID], a
ld a, d
ld [wFXAnimID + 1], a
call WaitBGMap
predef_jump PlayBattleAnim
; 3ee27
FinishBattleAnim: ; 3ee27
push af
push bc
push de
push hl
ld b, SCGB_BATTLE_COLORS
call GetSGBLayout
call SetPalettes
call DelayFrame
pop hl
pop de
pop bc
pop af
ret
; 3ee3b
GiveExperiencePoints: ; 3ee3b
; Give experience.
; Don't give experience if linked or in the Battle Tower.
ld a, [wLinkMode]
and a
ret nz
ld a, [wInBattleTowerBattle]
bit 0, a
ret nz
call .EvenlyDivideExpAmongParticipants
xor a
ld [wCurPartyMon], a
ld bc, wPartyMon1Species
.loop
ld hl, MON_HP
add hl, bc
ld a, [hli]
or [hl]
jp z, .skip_stats ; fainted
push bc
ld hl, wBattleParticipantsNotFainted
ld a, [wCurPartyMon]
ld c, a
ld b, CHECK_FLAG
ld d, $0
predef SmallFarFlagAction
ld a, c
and a
pop bc
jp z, .skip_stats
; give stat exp
ld hl, MON_STAT_EXP + 1
add hl, bc
ld d, h
ld e, l
ld hl, wEnemyMonBaseStats - 1
push bc
ld c, $5
.loop1
inc hl
ld a, [de]
add [hl]
ld [de], a
jr nc, .okay1
dec de
ld a, [de]
inc a
jr z, .next
ld [de], a
inc de
.okay1
push hl
push bc
ld a, MON_PKRUS
call GetPartyParamLocation
ld a, [hl]
and a
pop bc
pop hl
jr z, .skip
ld a, [de]
add [hl]
ld [de], a
jr nc, .skip
dec de
ld a, [de]
inc a
jr z, .next
ld [de], a
inc de
jr .skip
.next
ld a, $ff
ld [de], a
inc de
ld [de], a
.skip
inc de
inc de
dec c
jr nz, .loop1
xor a
ld [hMultiplicand + 0], a
ld [hMultiplicand + 1], a
ld a, [wEnemyMonBaseExp]
ld [hMultiplicand + 2], a
ld a, [wEnemyMonLevel]
ld [hMultiplier], a
call Multiply
ld a, 7
ld [hDivisor], a
ld b, 4
call Divide
; Boost Experience for traded Pokemon
pop bc
ld hl, MON_ID
add hl, bc
ld a, [wPlayerID]
cp [hl]
jr nz, .boosted
inc hl
ld a, [wPlayerID + 1]
cp [hl]
ld a, $0
jr z, .no_boost
.boosted
call BoostExp
ld a, $1
.no_boost
; Boost experience for a Trainer Battle
ld [wStringBuffer2 + 2], a
ld a, [wBattleMode]
dec a
call nz, BoostExp
; Boost experience for Lucky Egg
push bc
ld a, MON_ITEM
call GetPartyParamLocation
ld a, [hl]
cp LUCKY_EGG
call z, BoostExp
ld a, [hQuotient + 2]
ld [wStringBuffer2 + 1], a
ld a, [hQuotient + 1]
ld [wStringBuffer2], a
ld a, [wCurPartyMon]
ld hl, wPartyMonNicknames
call GetNick
ld hl, Text_MonGainedExpPoint
call BattleTextBox
ld a, [wStringBuffer2 + 1]
ld [hQuotient + 2], a
ld a, [wStringBuffer2]
ld [hQuotient + 1], a
pop bc
call AnimateExpBar
push bc
call LoadTileMapToTempTileMap
pop bc
ld hl, MON_STAT_EXP - 1
add hl, bc
ld d, [hl]
ld a, [hQuotient + 2]
add d
ld [hld], a
ld d, [hl]
ld a, [hQuotient + 1]
adc d
ld [hl], a
jr nc, .skip2
dec hl
inc [hl]
jr nz, .skip2
ld a, $ff
ld [hli], a
ld [hli], a
ld [hl], a
.skip2
ld a, [wCurPartyMon]
ld e, a
ld d, $0
ld hl, wPartySpecies
add hl, de
ld a, [hl]
ld [wCurSpecies], a
call GetBaseData
push bc
ld d, MAX_LEVEL
callfar CalcExpAtLevel
pop bc
ld hl, MON_STAT_EXP - 1
add hl, bc
push bc
ld a, [hQuotient]
ld b, a
ld a, [hQuotient + 1]
ld c, a
ld a, [hQuotient + 2]
ld d, a
ld a, [hld]
sub d
ld a, [hld]
sbc c
ld a, [hl]
sbc b
jr c, .not_max_exp
ld a, b
ld [hli], a
ld a, c
ld [hli], a
ld a, d
ld [hld], a
.not_max_exp
xor a ; PARTYMON
ld [wMonType], a
predef CopyMonToTempMon
callfar CalcLevel
pop bc
ld hl, MON_LEVEL
add hl, bc
ld a, [hl]
cp MAX_LEVEL
jp nc, .skip_stats
cp d
jp z, .skip_stats
; <NICKNAME> grew to level ##!
ld [wTempLevel], a
ld a, [wCurPartyLevel]
push af
ld a, d
ld [wCurPartyLevel], a
ld [hl], a
ld hl, MON_SPECIES
add hl, bc
ld a, [hl]
ld [wCurSpecies], a
ld [wd265], a
call GetBaseData
ld hl, MON_MAXHP + 1
add hl, bc
ld a, [hld]
ld e, a
ld d, [hl]
push de
ld hl, MON_MAXHP
add hl, bc
ld d, h
ld e, l
ld hl, MON_STAT_EXP - 1
add hl, bc
push bc
ld b, TRUE
predef CalcMonStats
pop bc
pop de
ld hl, MON_MAXHP + 1
add hl, bc
ld a, [hld]
sub e
ld e, a
ld a, [hl]
sbc d
ld d, a
dec hl
ld a, [hl]
add e
ld [hld], a
ld a, [hl]
adc d
ld [hl], a
ld a, [wCurBattleMon]
ld d, a
ld a, [wCurPartyMon]
cp d
jr nz, .skip_animation
ld de, wBattleMonHP
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld de, wBattleMonMaxHP
push bc
ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP
call CopyBytes
pop bc
ld hl, MON_LEVEL
add hl, bc
ld a, [hl]
ld [wBattleMonLevel], a
ld a, [wPlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .transformed
ld hl, MON_ATK
add hl, bc
ld de, wPlayerStats
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
.transformed
xor a
ld [wd265], a
call ApplyStatLevelMultiplierOnAllStats
callfar ApplyStatusEffectOnPlayerStats
callfar BadgeStatBoosts
callfar UpdatePlayerHUD
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld a, $1
ld [hBGMapMode], a
.skip_animation
farcall LevelUpHappinessMod
ld a, [wCurBattleMon]
ld b, a
ld a, [wCurPartyMon]
cp b
jr z, .skip_animation2
ld de, SFX_HIT_END_OF_EXP_BAR
call PlaySFX
call WaitSFX
ld hl, BattleText_StringBuffer1GrewToLevel
call StdBattleTextBox
call LoadTileMapToTempTileMap
.skip_animation2
xor a ; PARTYMON
ld [wMonType], a
predef CopyMonToTempMon
hlcoord 9, 0
ld b, $a
ld c, $9
call TextBox
hlcoord 11, 1
ld bc, 4
predef PrintTempMonStats
ld c, $1e
call DelayFrames
call WaitPressAorB_BlinkCursor
call Call_LoadTempTileMapToTileMap
xor a ; PARTYMON
ld [wMonType], a
ld a, [wCurSpecies]
ld [wd265], a
ld a, [wCurPartyLevel]
push af
ld c, a
ld a, [wTempLevel]
ld b, a
.level_loop
inc b
ld a, b
ld [wCurPartyLevel], a
push bc
predef LearnLevelMoves
pop bc
ld a, b
cp c
jr nz, .level_loop
pop af
ld [wCurPartyLevel], a
ld hl, wEvolvableFlags
ld a, [wCurPartyMon]
ld c, a
ld b, SET_FLAG
predef SmallFarFlagAction
pop af
ld [wCurPartyLevel], a
.skip_stats
ld a, [wPartyCount]
ld b, a
ld a, [wCurPartyMon]
inc a
cp b
jr z, .done
ld [wCurPartyMon], a
ld a, MON_SPECIES
call GetPartyParamLocation
ld b, h
ld c, l
jp .loop
.done
jp ResetBattleParticipants
; 3f0d4
.EvenlyDivideExpAmongParticipants:
; count number of battle participants
ld a, [wBattleParticipantsNotFainted]
ld b, a
ld c, PARTY_LENGTH
ld d, 0
.count_loop
xor a
srl b
adc d
ld d, a
dec c
jr nz, .count_loop
cp 2
ret c
ld [wd265], a
ld hl, wEnemyMonBaseStats
ld c, wEnemyMonEnd - wEnemyMonBaseStats
.count_loop2
xor a
ld [hDividend + 0], a
ld a, [hl]
ld [hDividend + 1], a
ld a, [wd265]
ld [hDivisor], a
ld b, 2
call Divide
ld a, [hQuotient + 2]
ld [hli], a
dec c
jr nz, .count_loop2
ret
; 3f106
BoostExp: ; 3f106
; Multiply experience by 1.5x
push bc
; load experience value
ld a, [hProduct + 2]
ld b, a
ld a, [hProduct + 3]
ld c, a
; halve it
srl b
rr c
; add it back to the whole exp value
add c
ld [hProduct + 3], a
ld a, [hProduct + 2]
adc b
ld [hProduct + 2], a
pop bc
ret
; 3f11b
Text_MonGainedExpPoint: ; 3f11b
text_jump Text_Gained
start_asm
ld hl, TextJump_StringBuffer2ExpPoints
ld a, [wStringBuffer2 + 2] ; IsTradedMon
and a
ret z
ld hl, TextJump_ABoostedStringBuffer2ExpPoints
ret
; 3f12c
TextJump_ABoostedStringBuffer2ExpPoints: ; 3f12c
text_jump Text_ABoostedStringBuffer2ExpPoints
db "@"
; 3f131
TextJump_StringBuffer2ExpPoints: ; 3f131
text_jump Text_StringBuffer2ExpPoints
db "@"
; 3f136
AnimateExpBar: ; 3f136
push bc
ld hl, wCurPartyMon
ld a, [wCurBattleMon]
cp [hl]
jp nz, .finish
ld a, [wBattleMonLevel]
cp MAX_LEVEL
jp nc, .finish
ld a, [hProduct + 3]
ld [wd004], a
push af
ld a, [hProduct + 2]
ld [wd003], a
push af
xor a
ld [wd002], a
xor a ; PARTYMON
ld [wMonType], a
predef CopyMonToTempMon
ld a, [wTempMonLevel]
ld b, a
ld e, a
push de
ld de, wTempMonExp + 2
call CalcExpBar
push bc
ld hl, wTempMonExp + 2
ld a, [wd004]
add [hl]
ld [hld], a
ld a, [wd003]
adc [hl]
ld [hld], a
jr nc, .NoOverflow
inc [hl]
jr nz, .NoOverflow
ld a, $ff
ld [hli], a
ld [hli], a
ld [hl], a
.NoOverflow:
ld d, MAX_LEVEL
callfar CalcExpAtLevel
ld a, [hProduct + 1]
ld b, a
ld a, [hProduct + 2]
ld c, a
ld a, [hProduct + 3]
ld d, a
ld hl, wTempMonExp + 2
ld a, [hld]
sub d
ld a, [hld]
sbc c
ld a, [hl]
sbc b
jr c, .AlreadyAtMaxExp
ld a, b
ld [hli], a
ld a, c
ld [hli], a
ld a, d
ld [hld], a
.AlreadyAtMaxExp:
callfar CalcLevel
ld a, d
pop bc
pop de
ld d, a
cp e
jr nc, .LoopLevels
ld a, e
ld d, a
.LoopLevels:
ld a, e
cp MAX_LEVEL
jr nc, .FinishExpBar
cp d
jr z, .FinishExpBar
inc a
ld [wTempMonLevel], a
ld [wCurPartyLevel], a
ld [wBattleMonLevel], a
push de
call .PlayExpBarSound
ld c, $40
call .LoopBarAnimation
call PrintPlayerHUD
ld hl, wBattleMonNick
ld de, wStringBuffer1
ld bc, MON_NAME_LENGTH
call CopyBytes
call TerminateExpBarSound
ld de, SFX_HIT_END_OF_EXP_BAR
call PlaySFX
farcall AnimateEndOfExpBar
call WaitSFX
ld hl, BattleText_StringBuffer1GrewToLevel
call StdBattleTextBox
pop de
inc e
ld b, $0
jr .LoopLevels
.FinishExpBar:
push bc
ld b, d
ld de, wTempMonExp + 2
call CalcExpBar
ld a, b
pop bc
ld c, a
call .PlayExpBarSound
call .LoopBarAnimation
call TerminateExpBarSound
pop af
ld [hProduct + 2], a
pop af
ld [hProduct + 3], a
.finish
pop bc
ret
.PlayExpBarSound:
push bc
call WaitSFX
ld de, SFX_EXP_BAR
call PlaySFX
ld c, 10
call DelayFrames
pop bc
ret
.LoopBarAnimation:
ld d, 3
dec b
.anim_loop
inc b
push bc
push de
hlcoord 17, 11
call PlaceExpBar
pop de
ld a, $1
ld [hBGMapMode], a
ld c, d
call DelayFrames
xor a
ld [hBGMapMode], a
pop bc
ld a, c
cp b
jr z, .end_animation
inc b
push bc
push de
hlcoord 17, 11
call PlaceExpBar
pop de
ld a, $1
ld [hBGMapMode], a
ld c, d
call DelayFrames
xor a
ld [hBGMapMode], a
dec d
jr nz, .min_number_of_frames
ld d, 1
.min_number_of_frames
pop bc
ld a, c
cp b
jr nz, .anim_loop
.end_animation
ld a, $1
ld [hBGMapMode], a
ret
SendOutMonText: ; 3f26d
ld a, [wLinkMode]
and a
jr z, .not_linked
ld hl, JumpText_GoMon ; If we're in a LinkBattle print just "Go <PlayerMon>"
ld a, [wBattleHasJustStarted] ; unless this (unidentified) variable is set
and a
jr nz, .skip_to_textbox
.not_linked
; Depending on the HP of the enemy mon, the game prints a different text
ld hl, wEnemyMonHP
ld a, [hli]
or [hl]
ld hl, JumpText_GoMon
jr z, .skip_to_textbox
; compute enemy helth remaining as a percentage
xor a
ld [hMultiplicand + 0], a
ld hl, wEnemyMonHP
ld a, [hli]
ld [wEnemyHPAtTimeOfPlayerSwitch], a
ld [hMultiplicand + 1], a
ld a, [hl]
ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a
ld [hMultiplicand + 2], a
ld a, 25
ld [hMultiplier], a
call Multiply
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld b, [hl]
srl a
rr b
srl a
rr b
ld a, b
ld b, 4
ld [hDivisor], a
call Divide
ld a, [hQuotient + 2]
ld hl, JumpText_GoMon
cp 70
jr nc, .skip_to_textbox
ld hl, JumpText_DoItMon
cp 40
jr nc, .skip_to_textbox
ld hl, JumpText_GoForItMon
cp 10
jr nc, .skip_to_textbox
ld hl, JumpText_YourFoesWeakGetmMon
.skip_to_textbox
jp BattleTextBox
; 3f2d1
JumpText_GoMon: ; 3f2d1
text_jump Text_GoMon
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2d6
JumpText_DoItMon: ; 3f2d8
text_jump Text_DoItMon
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2dd
JumpText_GoForItMon: ; 3f2df
text_jump Text_GoForItMon
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2e4
JumpText_YourFoesWeakGetmMon: ; 3f2e6
text_jump Text_YourFoesWeakGetmMon
start_asm
Function_TextJump_BattleMonNick01: ; 3f2eb
ld hl, TextJump_BattleMonNick01
ret
; 3f2ef
TextJump_BattleMonNick01: ; 3f2ef
text_jump Text_BattleMonNick01
db "@"
; 3f2f4
WithdrawMonText: ; 3f2f4
ld hl, .WithdrawMonText
jp BattleTextBox
.WithdrawMonText:
text_jump Text_BattleMonNickComma
start_asm
; Print text to withdraw mon
; depending on HP the message is different
push de
push bc
ld hl, wEnemyMonHP + 1
ld de, wEnemyHPAtTimeOfPlayerSwitch + 1
ld b, [hl]
dec hl
ld a, [de]
sub b
ld [hMultiplicand + 2], a
dec de
ld b, [hl]
ld a, [de]
sbc b
ld [hMultiplicand + 1], a
ld a, 25
ld [hMultiplier], a
call Multiply
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld b, [hl]
srl a
rr b
srl a
rr b
ld a, b
ld b, 4
ld [hDivisor], a
call Divide
pop bc
pop de
ld a, [hQuotient + 2]
ld hl, TextJump_ThatsEnoughComeBack
and a
ret z
ld hl, TextJump_ComeBack
cp 30
ret c
ld hl, TextJump_OKComeBack
cp 70
ret c
ld hl, TextJump_GoodComeBack
ret
; 3f348
TextJump_ThatsEnoughComeBack: ; 3f348
text_jump Text_ThatsEnoughComeBack
db "@"
; 3f34d
TextJump_OKComeBack: ; 3f34d
text_jump Text_OKComeBack
db "@"
; 3f352
TextJump_GoodComeBack: ; 3f352
text_jump Text_GoodComeBack
db "@"
; 3f357
Unreferenced_TextJump_ComeBack: ; 3f357
; this function doesn't seem to be used
ld hl, TextJump_ComeBack
ret
; 3f35b
TextJump_ComeBack: ; 3f35b
text_jump Text_ComeBack
db "@"
; 3f360
Unreferenced_HandleSafariAngerEatingStatus:
ld hl, wSafariMonEating
ld a, [hl]
and a
jr z, .angry
dec [hl]
ld hl, BattleText_WildMonIsEating
jr .finish
.angry
dec hl ; wSafariMonAngerCount
ld a, [hl]
and a
ret z
dec [hl]
ld hl, BattleText_WildMonIsAngry
jr nz, .finish
push hl
ld a, [wEnemyMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseCatchRate]
ld [wEnemyMonCatchRate], a
pop hl
.finish
push hl
call Call_LoadTempTileMapToTileMap
pop hl
jp StdBattleTextBox
; 3f390
FillInExpBar: ; 3f390
push hl
call CalcExpBar
pop hl
ld de, 7
add hl, de
jp PlaceExpBar
; 3f39c
CalcExpBar: ; 3f39c
; Calculate the percent exp between this level and the next
; Level in b
push de
ld d, b
push de
callfar CalcExpAtLevel
pop de
; exp at current level gets pushed to the stack
ld hl, hMultiplicand
ld a, [hli]
push af
ld a, [hli]
push af
ld a, [hl]
push af
; next level
inc d
callfar CalcExpAtLevel
; back up the next level exp, and subtract the two levels
ld hl, hMultiplicand + 2
ld a, [hl]
ld [hMathBuffer + 2], a
pop bc
sub b
ld [hld], a
ld a, [hl]
ld [hMathBuffer + 1], a
pop bc
sbc b
ld [hld], a
ld a, [hl]
ld [hMathBuffer], a
pop bc
sbc b
ld [hl], a
pop de
ld hl, hMultiplicand + 1
ld a, [hli]
push af
ld a, [hl]
push af
; get the amount of exp remaining to the next level
ld a, [de]
dec de
ld c, a
ld a, [hMathBuffer + 2]
sub c
ld [hld], a
ld a, [de]
dec de
ld b, a
ld a, [hMathBuffer + 1]
sbc b
ld [hld], a
ld a, [de]
ld c, a
ld a, [hMathBuffer]
sbc c
ld [hld], a
xor a
ld [hl], a
; multiply by 64
ld a, $40
ld [hMultiplier], a
call Multiply
pop af
ld c, a
pop af
ld b, a
.loop
ld a, b
and a
jr z, .done
srl b
rr c
ld hl, hProduct
srl [hl]
inc hl
rr [hl]
inc hl
rr [hl]
inc hl
rr [hl]
jr .loop
.done
ld a, c
ld [hDivisor], a
ld b, 4
call Divide
ld a, [hQuotient + 2]
ld b, a
ld a, $40
sub b
ld b, a
ret
; 3f41c
PlaceExpBar: ; 3f41c
ld c, $8 ; number of tiles
.loop1
ld a, b
sub $8
jr c, .next
ld b, a
ld a, $6a ; full bar
ld [hld], a
dec c
jr z, .finish
jr .loop1
.next
add $8
jr z, .loop2
add $54 ; tile to the left of small exp bar tile
jr .skip
.loop2
ld a, $62 ; empty bar
.skip
ld [hld], a
ld a, $62 ; empty bar
dec c
jr nz, .loop2
.finish
ret
; 3f43d
GetBattleMonBackpic: ; 3f43d
ld a, [wPlayerSubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
ld hl, BattleAnimCmd_RaiseSub
jr nz, GetBattleMonBackpic_DoAnim ; substitute
DropPlayerSub: ; 3f447
ld a, [wPlayerMinimized]
and a
ld hl, BattleAnimCmd_MinimizeOpp
jr nz, GetBattleMonBackpic_DoAnim
ld a, [wCurPartySpecies]
push af
ld a, [wBattleMonSpecies]
ld [wCurPartySpecies], a
ld hl, wBattleMonDVs
predef GetUnownLetter
ld de, vTiles2 tile $31
predef GetMonBackpic
pop af
ld [wCurPartySpecies], a
ret
; 3f46f
GetBattleMonBackpic_DoAnim: ; 3f46f
ld a, [hBattleTurn]
push af
xor a
ld [hBattleTurn], a
ld a, BANK(BattleAnimCommands)
rst FarCall
pop af
ld [hBattleTurn], a
ret
; 3f47c
GetEnemyMonFrontpic: ; 3f47c
ld a, [wEnemySubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
ld hl, BattleAnimCmd_RaiseSub
jr nz, GetEnemyMonFrontpic_DoAnim
DropEnemySub: ; 3f486
ld a, [wEnemyMinimized]
and a
ld hl, BattleAnimCmd_MinimizeOpp
jr nz, GetEnemyMonFrontpic_DoAnim
ld a, [wCurPartySpecies]
push af
ld a, [wEnemyMonSpecies]
ld [wCurSpecies], a
ld [wCurPartySpecies], a
call GetBaseData
ld hl, wEnemyMonDVs
predef GetUnownLetter
ld de, vTiles2
predef GetAnimatedFrontpic
pop af
ld [wCurPartySpecies], a
ret
; 3f4b4
GetEnemyMonFrontpic_DoAnim: ; 3f4b4
ld a, [hBattleTurn]
push af
call SetEnemyTurn
ld a, BANK(BattleAnimCommands)
rst FarCall
pop af
ld [hBattleTurn], a
ret
; 3f4c1
StartBattle: ; 3f4c1
; This check prevents you from entering a battle without any Pokemon.
; Those using walk-through-walls to bypass getting a Pokemon experience
; the effects of this check.
ld a, [wPartyCount]
and a
ret z
ld a, [wTimeOfDayPal]
push af
call BattleIntro
call DoBattle
call ExitBattle
pop af
ld [wTimeOfDayPal], a
scf
ret
; 3f4d9
Unreferenced_DoBattle: ; 3f4d9
call DoBattle
ret
; 3f4dd
BattleIntro: ; 3f4dd
farcall StubbedTrainerRankings_Battles ; mobile
call LoadTrainerOrWildMonPic
xor a
ld [wTempBattleMonSpecies], a
ld [wBattleMenuCursorBuffer], a
xor a
ld [hMapAnims], a
farcall PlayBattleMusic
farcall ShowLinkBattleParticipants
farcall FindFirstAliveMonAndStartBattle
call DisableSpriteUpdates
farcall ClearBattleRAM
call InitEnemy
call BackUpBGMap2
ld b, SCGB_BATTLE_GRAYSCALE
call GetSGBLayout
ld hl, rLCDC
res rLCDC_WINDOW_TILEMAP, [hl] ; select 9800-9BFF
call InitBattleDisplay
call BattleStartMessage
ld hl, rLCDC
set rLCDC_WINDOW_TILEMAP, [hl] ; select 9C00-9FFF
xor a
ld [hBGMapMode], a
call EmptyBattleTextBox
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
hlcoord 1, 0
lb bc, 4, 10
call ClearBox
call ClearSprites
ld a, [wBattleMode]
cp WILD_BATTLE
call z, UpdateEnemyHUD
ld a, $1
ld [hBGMapMode], a
ret
; 3f54e
LoadTrainerOrWildMonPic: ; 3f54e
ld a, [wOtherTrainerClass]
and a
jr nz, .Trainer
ld a, [wTempWildMonSpecies]
ld [wCurPartySpecies], a
.Trainer:
ld [wTempEnemyMonSpecies], a
ret
; 3f55e
InitEnemy: ; 3f55e
ld a, [wOtherTrainerClass]
and a
jp nz, InitEnemyTrainer ; trainer
jp InitEnemyWildmon ; wild
; 3f568
BackUpBGMap2: ; 3f568
ld a, [rSVBK]
push af
ld a, BANK(wDecompressScratch)
ld [rSVBK], a
ld hl, wDecompressScratch
ld bc, $40 tiles ; vBGMap3 - vBGMap2
ld a, $2
call ByteFill
ld a, [rVBK]
push af
ld a, $1
ld [rVBK], a
ld de, wDecompressScratch
hlbgcoord 0, 0 ; vBGMap2
lb bc, BANK(BackUpBGMap2), $40
call Request2bpp
pop af
ld [rVBK], a
pop af
ld [rSVBK], a
ret
; 3f594
InitEnemyTrainer: ; 3f594
ld [wTrainerClass], a
farcall StubbedTrainerRankings_TrainerBattles
xor a
ld [wTempEnemyMonSpecies], a
callfar GetTrainerAttributes
callfar ReadTrainerParty
; RIVAL1's first mon has no held item
ld a, [wTrainerClass]
cp RIVAL1
jr nz, .ok
xor a
ld [wOTPartyMon1Item], a
.ok
ld de, vTiles2
callfar GetTrainerPic
xor a
ld [hGraphicStartTile], a
dec a
ld [wEnemyItemState], a
hlcoord 12, 0
lb bc, 7, 7
predef PlaceGraphic
ld a, -1
ld [wCurOTMon], a
ld a, TRAINER_BATTLE
ld [wBattleMode], a
call IsGymLeader
jr nc, .done
xor a
ld [wCurPartyMon], a
ld a, [wPartyCount]
ld b, a
.partyloop
push bc
ld a, MON_HP
call GetPartyParamLocation
ld a, [hli]
or [hl]
jr z, .skipfaintedmon
ld c, HAPPINESS_GYMBATTLE
callfar ChangeHappiness
.skipfaintedmon
pop bc
dec b
jr z, .done
ld hl, wCurPartyMon
inc [hl]
jr .partyloop
.done
ret
; 3f607
InitEnemyWildmon: ; 3f607
ld a, WILD_BATTLE
ld [wBattleMode], a
farcall StubbedTrainerRankings_WildBattles
call LoadEnemyMon
ld hl, wEnemyMonMoves
ld de, wWildMonMoves
ld bc, NUM_MOVES
call CopyBytes
ld hl, wEnemyMonPP
ld de, wWildMonPP
ld bc, NUM_MOVES
call CopyBytes
ld hl, wEnemyMonDVs
predef GetUnownLetter
ld a, [wCurPartySpecies]
cp UNOWN
jr nz, .skip_unown
ld a, [wFirstUnownSeen]
and a
jr nz, .skip_unown
ld a, [wUnownLetter]
ld [wFirstUnownSeen], a
.skip_unown
ld de, vTiles2
predef GetAnimatedFrontpic
xor a
ld [wTrainerClass], a
ld [hGraphicStartTile], a
hlcoord 12, 0
lb bc, 7, 7
predef PlaceGraphic
ret
; 3f662
Unreferenced_Function3f662: ; 3f662
ld hl, wEnemyMonMoves
ld de, wListMoves_MoveIndicesBuffer
ld b, NUM_MOVES
.loop
ld a, [de]
inc de
ld [hli], a
and a
jr z, .clearpp
push bc
push hl
push hl
dec a
ld hl, Moves + MOVE_PP
ld bc, MOVE_LENGTH
call AddNTimes
ld a, BANK(Moves)
call GetFarByte
pop hl
ld bc, wEnemyMonPP - (wEnemyMonMoves + 1)
add hl, bc
ld [hl], a
pop hl
pop bc
dec b
jr nz, .loop
ret
.clear
xor a
ld [hli], a
.clearpp
push bc
push hl
ld bc, wEnemyMonPP - (wEnemyMonMoves + 1)
add hl, bc
xor a
ld [hl], a
pop hl
pop bc
dec b
jr nz, .clear
ret
; 3f69e
ExitBattle: ; 3f69e
call .HandleEndOfBattle
call CleanUpBattleRAM
ret
; 3f6a5
.HandleEndOfBattle: ; 3f6a5
ld a, [wLinkMode]
and a
jr z, .not_linked
call ShowLinkBattleParticipantsAfterEnd
ld c, 150
call DelayFrames
call DisplayLinkBattleResult
ret
.not_linked
ld a, [wBattleResult]
and $f
ret nz
call CheckPayDay
xor a
ld [wForceEvolution], a
predef EvolveAfterBattle
farcall GivePokerusAndConvertBerries
ret
; 3f6d0
CleanUpBattleRAM: ; 3f6d0
call BattleEnd_HandleRoamMons
xor a
ld [wLowHealthAlarm], a
ld [wBattleMode], a
ld [wBattleType], a
ld [wAttackMissed], a
ld [wTempWildMonSpecies], a
ld [wOtherTrainerClass], a
ld [wFailedToFlee], a
ld [wNumFleeAttempts], a
ld [wForcedSwitch], a
ld [wPartyMenuCursor], a
ld [wKeyItemsPocketCursor], a
ld [wItemsPocketCursor], a
ld [wBattleMenuCursorBuffer], a
ld [wCurMoveNum], a
ld [wBallsPocketCursor], a
ld [wLastPocket], a
ld [wMenuScrollPosition], a
ld [wKeyItemsPocketScrollPosition], a
ld [wItemsPocketScrollPosition], a
ld [wBallsPocketScrollPosition], a
ld hl, wPlayerSubStatus1
ld b, wEnemyFuryCutterCount - wPlayerSubStatus1
.loop
ld [hli], a
dec b
jr nz, .loop
call WaitSFX
ret
; 3f71d
CheckPayDay: ; 3f71d
ld hl, wPayDayMoney
ld a, [hli]
or [hl]
inc hl
or [hl]
ret z
ld a, [wAmuletCoin]
and a
jr z, .okay
ld hl, wPayDayMoney + 2
sla [hl]
dec hl
rl [hl]
dec hl
rl [hl]
jr nc, .okay
ld a, $ff
ld [hli], a
ld [hli], a
ld [hl], a
.okay
ld hl, wPayDayMoney + 2
ld de, wMoney + 2
call AddBattleMoneyToAccount
ld hl, BattleText_PlayerPickedUpPayDayMoney
call StdBattleTextBox
ld a, [wInBattleTowerBattle]
bit 0, a
ret z
call ClearTileMap
call ClearBGPalettes
ret
; 3f759
ShowLinkBattleParticipantsAfterEnd: ; 3f759
farcall StubbedTrainerRankings_LinkBattles
farcall BackupMobileEventIndex
ld a, [wCurOTMon]
ld hl, wOTPartyMon1Status
call GetPartyLocation
ld a, [wEnemyMonStatus]
ld [hl], a
call ClearTileMap
farcall _ShowLinkBattleParticipants
ret
; 3f77c
DisplayLinkBattleResult: ; 3f77c
farcall CheckMobileBattleError
jp c, .Mobile_InvalidBattle
call IsMobileBattle2
jr nz, .proceed
ld hl, wcd2a
bit 4, [hl]
jr z, .proceed
farcall DetermineLinkBattleResult
.proceed
ld a, [wBattleResult]
and $f
cp $1
jr c, .victory
jr z, .loss
farcall StubbedTrainerRankings_ColosseumDraws
ld de, .Draw
jr .store_result
.victory
farcall StubbedTrainerRankings_ColosseumWins
ld de, .Win
jr .store_result
.loss
farcall StubbedTrainerRankings_ColosseumLosses
ld de, .Lose
jr .store_result
.store_result
hlcoord 6, 8
call PlaceString
farcall BackupMobileEventIndex
ld c, 200
call DelayFrames
ld a, BANK(sLinkBattleStats)
call GetSRAMBank
call AddLastMobileBattleToLinkRecord
call ReadAndPrintLinkBattleRecord
call CloseSRAM
call IsMobileBattle2
jr z, .mobile
call WaitPressAorB_BlinkCursor
call ClearTileMap
ret
.mobile
ld c, 200
call DelayFrames
call ClearTileMap
ret
; 3f7f7
.Win:
db "YOU WIN@"
.Lose:
db "YOU LOSE@"
.Draw:
db " DRAW@"
; 3f80f
.Mobile_InvalidBattle: ; 3f80f
hlcoord 6, 8
ld de, .Invalid
call PlaceString
ld c, 200
call DelayFrames
call ClearTileMap
ret
; 3f821
.Invalid:
db "INVALID BATTLE@"
; 3f830
IsMobileBattle2: ; 3f830
ld a, [wLinkMode]
cp LINK_MOBILE
ret
; 3f836
DisplayLinkRecord: ; 3f836
ld a, BANK(sLinkBattleStats)
call GetSRAMBank
call ReadAndPrintLinkBattleRecord
call CloseSRAM
hlcoord 0, 0, wAttrMap
xor a
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
call ByteFill
call WaitBGMap2
ld b, SCGB_DIPLOMA
call GetSGBLayout
call SetPalettes
ld c, 8
call DelayFrames
call WaitPressAorB_BlinkCursor
ret
; 3f85f
ReadAndPrintLinkBattleRecord: ; 3f85f
call ClearTileMap
call ClearSprites
call .PrintBattleRecord
hlcoord 0, 8
ld b, 5
ld de, sLinkBattleRecord + 2
.loop
push bc
push hl
push de
ld a, [de]
and a
jr z, .PrintFormatString
ld a, [wSavedAtLeastOnce]
and a
jr z, .PrintFormatString
push hl
push hl
ld h, d
ld l, e
ld de, wd002
ld bc, 10
call CopyBytes
ld a, "@"
ld [de], a
inc de
ld bc, 6
call CopyBytes
ld de, wd002
pop hl
call PlaceString
pop hl
ld de, 26
add hl, de
push hl
ld de, wd00d
lb bc, 2, 4
call PrintNum
pop hl
ld de, 5
add hl, de
push hl
ld de, wd00f
lb bc, 2, 4
call PrintNum
pop hl
ld de, 5
add hl, de
ld de, wd011
lb bc, 2, 4
call PrintNum
jr .next
.PrintFormatString:
ld de, .Format
call PlaceString
.next
pop hl
ld bc, 18
add hl, bc
ld d, h
ld e, l
pop hl
ld bc, 2 * SCREEN_WIDTH
add hl, bc
pop bc
dec b
jr nz, .loop
ret
.PrintBattleRecord:
hlcoord 1, 0
ld de, .Record
call PlaceString
hlcoord 0, 6
ld de, .Result
call PlaceString
hlcoord 0, 2
ld de, .Total
call PlaceString
hlcoord 6, 4
ld de, sLinkBattleWins
call .PrintZerosIfNoSaveFileExists
jr c, .quit
lb bc, 2, 4
call PrintNum
hlcoord 11, 4
ld de, sLinkBattleLosses
call .PrintZerosIfNoSaveFileExists
lb bc, 2, 4
call PrintNum
hlcoord 16, 4
ld de, sLinkBattleDraws
call .PrintZerosIfNoSaveFileExists
lb bc, 2, 4
call PrintNum
.quit
ret
.PrintZerosIfNoSaveFileExists:
ld a, [wSavedAtLeastOnce]
and a
ret nz
ld de, .Scores
call PlaceString
scf
ret
; 3f938
.Scores:
db " 0 0 0@"
; 3f947
.Format: ; 3f947
db " --- <LNBRK>"
db " - - -@"
.Record: ; 3f964
db "<PLAYER>'s RECORD@"
.Result: ; 3f96e
db "RESULT WIN LOSE DRAW@"
.Total: ; 3f983
db "TOTAL WIN LOSE DRAW@"
; 3f998
BattleEnd_HandleRoamMons: ; 3f998
ld a, [wBattleType]
cp BATTLETYPE_ROAMING
jr nz, .not_roaming
ld a, [wBattleResult]
and $f
jr z, .caught_or_defeated_roam_mon
call GetRoamMonHP
ld a, [wEnemyMonHP + 1]
ld [hl], a
jr .update_roam_mons
.caught_or_defeated_roam_mon
call GetRoamMonHP
ld [hl], $0
call GetRoamMonMapGroup
ld [hl], $ff
call GetRoamMonMapNumber
ld [hl], $ff
call GetRoamMonSpecies
ld [hl], $0
ret
.not_roaming
call BattleRandom
and $f
ret nz
.update_roam_mons
callfar UpdateRoamMons
ret
; 3f9d1
GetRoamMonMapGroup: ; 3f9d1
ld a, [wTempEnemyMonSpecies]
ld b, a
ld a, [wRoamMon1Species]
cp b
ld hl, wRoamMon1MapGroup
ret z
ld a, [wRoamMon2Species]
cp b
ld hl, wRoamMon2MapGroup
ret z
ld hl, wRoamMon3MapGroup
ret
; 3f9e9
GetRoamMonMapNumber: ; 3f9e9
ld a, [wTempEnemyMonSpecies]
ld b, a
ld a, [wRoamMon1Species]
cp b
ld hl, wRoamMon1MapNumber
ret z
ld a, [wRoamMon2Species]
cp b
ld hl, wRoamMon2MapNumber
ret z
ld hl, wRoamMon3MapNumber
ret
; 3fa01
GetRoamMonHP: ; 3fa01
; output: hl = wRoamMonHP
ld a, [wTempEnemyMonSpecies]
ld b, a
ld a, [wRoamMon1Species]
cp b
ld hl, wRoamMon1HP
ret z
ld a, [wRoamMon2Species]
cp b
ld hl, wRoamMon2HP
ret z
ld hl, wRoamMon3HP
ret
; 3fa19
GetRoamMonDVs: ; 3fa19
; output: hl = wRoamMonDVs
ld a, [wTempEnemyMonSpecies]
ld b, a
ld a, [wRoamMon1Species]
cp b
ld hl, wRoamMon1DVs
ret z
ld a, [wRoamMon2Species]
cp b
ld hl, wRoamMon2DVs
ret z
ld hl, wRoamMon3DVs
ret
; 3fa31
GetRoamMonSpecies: ; 3fa31
ld a, [wTempEnemyMonSpecies]
ld hl, wRoamMon1Species
cp [hl]
ret z
ld hl, wRoamMon2Species
cp [hl]
ret z
ld hl, wRoamMon3Species
ret
; 3fa42
AddLastMobileBattleToLinkRecord: ; 3fa42
ld hl, wOTPlayerID
ld de, wStringBuffer1
ld bc, 2
call CopyBytes
ld hl, wOTPlayerName
ld bc, NAME_LENGTH - 1
call CopyBytes
ld hl, sLinkBattleResults
call .StoreResult
ld hl, sLinkBattleRecord
ld d, 5
.loop
push hl
inc hl
inc hl
ld a, [hl]
dec hl
dec hl
and a
jr z, .copy
push de
ld bc, 12
ld de, wStringBuffer1
call CompareLong
pop de
pop hl
jr c, .done
ld bc, 18
add hl, bc
dec d
jr nz, .loop
ld bc, -18
add hl, bc
push hl
.copy
ld d, h
ld e, l
ld hl, wStringBuffer1
ld bc, 12
call CopyBytes
ld b, 6
xor a
.loop2
ld [de], a
inc de
dec b
jr nz, .loop2
pop hl
.done
call .StoreResult
call .FindOpponentAndAppendRecord
ret
; 3faa0
.StoreResult: ; 3faa0
ld a, [wBattleResult]
and $f
cp $1
ld bc, sLinkBattleWins + 1 - sLinkBattleResults
jr c, .okay
ld bc, sLinkBattleLosses + 1 - sLinkBattleResults
jr z, .okay
ld bc, sLinkBattleDraws + 1 - sLinkBattleResults
.okay
add hl, bc
call .CheckOverflow
ret nc
inc [hl]
ret nz
dec hl
inc [hl]
ret
; 3fabe
.CheckOverflow: ; 3fabe
dec hl
ld a, [hl]
inc hl
cp HIGH(MAX_LINK_RECORD)
ret c
ld a, [hl]
cp LOW(MAX_LINK_RECORD)
ret
; 3fac8
.FindOpponentAndAppendRecord: ; 3fac8
ld b, 5
ld hl, sLinkBattleRecord + 17
ld de, wd002
.loop3
push bc
push de
push hl
call .LoadPointer
pop hl
ld a, e
pop de
ld [de], a
inc de
ld a, b
ld [de], a
inc de
ld a, c
ld [de], a
inc de
ld bc, 18
add hl, bc
pop bc
dec b
jr nz, .loop3
ld b, $0
ld c, $1
.loop4
ld a, b
add b
add b
ld e, a
ld d, $0
ld hl, wd002
add hl, de
push hl
ld a, c
add c
add c
ld e, a
ld d, $0
ld hl, wd002
add hl, de
ld d, h
ld e, l
pop hl
push bc
ld c, 3
call StringCmp
pop bc
jr z, .equal
jr nc, .done2
.equal
inc c
ld a, c
cp $5
jr nz, .loop4
inc b
ld c, b
inc c
ld a, b
cp $4
jr nz, .loop4
ret
.done2
push bc
ld a, b
ld bc, 18
ld hl, sLinkBattleRecord
call AddNTimes
push hl
ld de, wd002
ld bc, 18
call CopyBytes
pop hl
pop bc
push hl
ld a, c
ld bc, 18
ld hl, sLinkBattleRecord
call AddNTimes
pop de
push hl
ld bc, 18
call CopyBytes
ld hl, wd002
ld bc, 18
pop de
call CopyBytes
ret
; 3fb54
.LoadPointer: ; 3fb54
ld e, $0
ld a, [hld]
ld c, a
ld a, [hld]
ld b, a
ld a, [hld]
add c
ld c, a
ld a, [hld]
adc b
ld b, a
jr nc, .okay2
inc e
.okay2
ld a, [hld]
add c
ld c, a
ld a, [hl]
adc b
ld b, a
ret nc
inc e
ret
; 3fb6c
InitBattleDisplay: ; 3fb6c
call .InitBackPic
hlcoord 0, 12
ld b, 4
ld c, 18
call TextBox
farcall MobileTextBorder
hlcoord 1, 5
lb bc, 3, 7
call ClearBox
call LoadStandardFont
call _LoadBattleFontsHPBar
call .BlankBGMap
xor a
ld [hMapAnims], a
ld [hSCY], a
ld a, $90
ld [hWY], a
ld [rWY], a
call WaitBGMap
xor a
ld [hBGMapMode], a
farcall BattleIntroSlidingPics
ld a, $1
ld [hBGMapMode], a
ld a, $31
ld [hGraphicStartTile], a
hlcoord 2, 6
lb bc, 6, 6
predef PlaceGraphic
xor a
ld [hWY], a
ld [rWY], a
call WaitBGMap
call HideSprites
ld b, SCGB_BATTLE_COLORS
call GetSGBLayout
call SetPalettes
ld a, $90
ld [hWY], a
xor a
ld [hSCX], a
ret
; 3fbd6
.BlankBGMap: ; 3fbd6
ld a, [rSVBK]
push af
ld a, BANK(wDecompressScratch)
ld [rSVBK], a
ld hl, wDecompressScratch
ld bc, wScratchAttrMap - wDecompressScratch
ld a, " "
call ByteFill
ld de, wDecompressScratch
hlbgcoord 0, 0
lb bc, BANK(.BlankBGMap), $40
call Request2bpp
pop af
ld [rSVBK], a
ret
; 3fbf8
.InitBackPic: ; 3fbf8
call GetTrainerBackpic
call CopyBackpic
ret
; 3fbff
GetTrainerBackpic: ; 3fbff
; Load the player character's backpic (6x6) into VRAM starting from vTiles2 tile $31.
; Special exception for Dude.
ld b, BANK(DudeBackpic)
ld hl, DudeBackpic
ld a, [wBattleType]
cp BATTLETYPE_TUTORIAL
jr z, .Decompress
; What gender are we?
ld a, [wPlayerSpriteSetupFlags]
bit 2, a ; transformed to male
jr nz, .Chris
ld a, [wPlayerGender]
bit 0, a
jr z, .Chris
; It's a girl.
farcall GetKrisBackpic
ret
.Chris:
; It's a boy.
ld b, BANK(ChrisBackpic)
ld hl, ChrisBackpic
.Decompress:
ld de, vTiles2 tile $31
ld c, 7 * 7
predef DecompressGet2bpp
ret
; 3fc30
CopyBackpic: ; 3fc30
ld a, [rSVBK]
push af
ld a, BANK(wDecompressScratch)
ld [rSVBK], a
ld hl, vTiles0
ld de, vTiles2 tile $31
ld a, [hROMBank]
ld b, a
ld c, $31
call Get2bpp
pop af
ld [rSVBK], a
call .LoadTrainerBackpicAsOAM
ld a, $31
ld [hGraphicStartTile], a
hlcoord 2, 6
lb bc, 6, 6
predef PlaceGraphic
ret
; 3fc5b
.LoadTrainerBackpicAsOAM: ; 3fc5b
ld hl, wVirtualOAMSprite00
xor a
ld [hMapObjectIndexBuffer], a
ld b, 6
ld e, (SCREEN_WIDTH + 1) * TILE_WIDTH
.outer_loop
ld c, 3
ld d, 8 * TILE_WIDTH
.inner_loop
ld [hl], d ; y
inc hl
ld [hl], e ; x
inc hl
ld a, [hMapObjectIndexBuffer]
ld [hli], a ; tile id
inc a
ld [hMapObjectIndexBuffer], a
ld a, PAL_BATTLE_OB_PLAYER
ld [hli], a ; attributes
ld a, d
add 1 * TILE_WIDTH
ld d, a
dec c
jr nz, .inner_loop
ld a, [hMapObjectIndexBuffer]
add $3
ld [hMapObjectIndexBuffer], a
ld a, e
add 1 * TILE_WIDTH
ld e, a
dec b
jr nz, .outer_loop
ret
; 3fc8b
BattleStartMessage: ; 3fc8b
ld a, [wBattleMode]
dec a
jr z, .wild
ld de, SFX_SHINE
call PlaySFX
call WaitSFX
ld c, 20
call DelayFrames
farcall Battle_GetTrainerName
ld hl, WantsToBattleText
jr .PlaceBattleStartText
.wild
call BattleCheckEnemyShininess
jr nc, .not_shiny
xor a
ld [wNumHits], a
ld a, 1
ld [hBattleTurn], a
ld a, 1
ld [wBattleAnimParam], a
ld de, ANIM_SEND_OUT_MON
call Call_PlayBattleAnim
.not_shiny
farcall CheckSleepingTreeMon
jr c, .skip_cry
farcall CheckBattleScene
jr c, .cry_no_anim
hlcoord 12, 0
ld d, $0
ld e, ANIM_MON_NORMAL
predef AnimateFrontpic
jr .skip_cry ; cry is played during the animation
.cry_no_anim
ld a, $0f
ld [wCryTracks], a
ld a, [wTempEnemyMonSpecies]
call PlayStereoCry
.skip_cry
ld a, [wBattleType]
cp BATTLETYPE_FISH
jr nz, .NotFishing
farcall StubbedTrainerRankings_HookedEncounters
ld hl, HookedPokemonAttackedText
jr .PlaceBattleStartText
.NotFishing:
ld hl, PokemonFellFromTreeText
cp BATTLETYPE_TREE
jr z, .PlaceBattleStartText
ld hl, WildCelebiAppearedText
cp BATTLETYPE_CELEBI
jr z, .PlaceBattleStartText
ld hl, WildPokemonAppearedText
.PlaceBattleStartText:
push hl
farcall BattleStart_TrainerHuds
pop hl
call StdBattleTextBox
call IsMobileBattle2
ret nz
ld c, $2 ; start
farcall Mobile_PrintOpponentBattleMessage
ret
; 3fd26