pokecrystal/battle/core.asm

9544 lines
144 KiB
NASM

; Core components of the battle engine.
BattleCore:
DoBattle: ; 3c000
xor a
ld [wBattleParticipantsNotFainted], a
ld [wBattleParticipantsIncludingFainted], a
ld [wPlayerAction], a
ld [BattleEnded], a
inc a
ld [wBattleHasJustStarted], a
ld hl, OTPartyMon1HP
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, [hLinkPlayerNumber]
cp $2
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 CheckPlayerPartyForFitPkmn
ld a, d
and a
jp z, LostBattle
call Call_LoadTempTileMapToTileMap
ld a, [BattleType]
cp BATTLETYPE_DEBUG
jp z, .tutorial_debug
cp BATTLETYPE_TUTORIAL
jp z, .tutorial_debug
xor a
ld [CurPartyMon], a
.loop2
call CheckIfCurPartyMonIsFitToFight
jr nz, .alive2
ld hl, CurPartyMon
inc [hl]
jr .loop2
.alive2
ld a, [CurBattleMon]
ld [LastPlayerMon], a
ld a, [CurPartyMon]
ld [CurBattleMon], a
inc a
ld hl, PartySpecies - 1
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [CurPartySpecies], a
ld [TempBattleMonSpecies], a
hlcoord 1, 5
ld a, 9
call SlideBattlePicOut
call LoadTileMapToTempTileMap
call ResetBattleParticipants
call InitBattleMon
call ResetPlayerStatLevels
call SendOutPkmnText
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, [hLinkPlayerNumber]
cp $2
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 [BattleEnded], a
ret
; 3c12f
BattleTurn: ; 3c12f
.loop
call MobileFn_3c1bf
call CheckContestBattleOver
jp c, .quit
xor a
ld [wPlayerIsSwitching], a
ld [wEnemyIsSwitching], a
ld [wBattleHasJustStarted], a
ld [wPlayerJustGotFrozen], a
ld [wEnemyJustGotFrozen], a
ld [CurDamage], a
ld [CurDamage + 1], a
call HandleBerserkGene
call UpdateBattleMonInParty
callba AIChooseMove
call IsMobileBattle
jr nz, .not_disconnected
callba Function100da5
callba StartMobileInactivityTimer
callba Function100dd8
jp c, .quit
.not_disconnected
call CheckPlayerLockedIn
jr c, .skip_iteration
.loop1
call BattleMenu
jr c, .quit
ld a, [BattleEnded]
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, [BattleEnded]
and a
jr nz, .quit
call HandleBetweenTurnEffects
ld a, [BattleEnded]
and a
jr nz, .quit
jp .loop
.quit
ret
; 3c1bf
MobileFn_3c1bf: mobile
ld a, $5
call GetSRAMBank
ld hl, $a89b ; s5_a89b
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, [hLinkPlayerNumber]
cp $1
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, [BattleEnded]
and a
jr nz, .BattleIsOver
.PlayerNotFainted:
call HasEnemyFainted
jr nz, .BattleContinues
call HandleEnemyMonFaint
ld a, [BattleEnded]
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, [BattleEnded]
and a
jr nz, .BattleIsOver
.EnemyNotFainted:
call HasPlayerFainted
jr nz, .BattleContinues
call HandlePlayerMonFaint
ld a, [BattleEnded]
and a
jr nz, .BattleIsOver
.BattleContinues:
and a
ret
.BattleIsOver:
scf
ret
; 3c27c
HandleBerserkGene: ; 3c27c
ld a, [hLinkPlayerNumber]
cp $1
jr z, .reverse
call .player
jr .enemy
.reverse
call .enemy
; jr .player
.player
call SetPlayerTurn
ld de, PartyMon1Item
ld a, [CurBattleMon]
ld b, a
jr .go
.enemy
call SetEnemyTurn
ld de, OTPartyMon1Item
ld a, [CurOTMon]
ld b, a
; jr .go
.go
push de
push bc
callab 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 [AttackMissed], a
ld [EffectFailed], a
callba BattleCommand_AttackUp2
pop af
pop hl
ld [hl], a
call GetItemName
ld hl, BattleText_UsersStringBuffer1Activated
call StdBattleTextBox
callab 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, [wPlayerAction]
cp $2
jr nz, .switch
ld a, [hLinkPlayerNumber]
cp $2
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
callab AI_Switch
call SetEnemyTurn
call SpikesDamage
jp .enemy_first
.use_move
ld a, [wPlayerAction]
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
callab GetUserItem
push bc
callab 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, [hLinkPlayerNumber]
cp $2
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, BattleMonSpeed
ld hl, EnemyMonSpeed
ld c, 2
call StringCmp
jr z, .speed_tie
jp nc, .player_first
jp .enemy_first
.speed_tie
ld a, [hLinkPlayerNumber]
cp $2
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, [BattleType]
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, [PlayerSubStatus4]
and 1 << SUBSTATUS_RECHARGE
jp nz, .quit
ld hl, EnemySubStatus3
res SUBSTATUS_FLINCHED, [hl]
ld hl, PlayerSubStatus3
res SUBSTATUS_FLINCHED, [hl]
ld a, [hl]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE
jp nz, .quit
ld hl, PlayerSubStatus1
bit SUBSTATUS_ROLLOUT, [hl]
jp nz, .quit
and a
ret
.quit
scf
ret
; 3c434
ParsePlayerAction: ; 3c434
call CheckPlayerLockedIn
jp c, .locked_in
ld hl, PlayerSubStatus5
bit SUBSTATUS_ENCORED, [hl]
jr z, .not_encored
ld a, [LastPlayerMove]
ld [CurPlayerMove], a
jr .encored
.not_encored
ld a, [wPlayerAction]
cp $2
jr z, .reset_rage
and a
jr nz, .reset_bide
ld a, [PlayerSubStatus3]
and 1 << SUBSTATUS_BIDE
jr nz, .locked_in
xor a
ld [wMoveSelectionMenuType], a
inc a ; POUND
ld [FXAnimIDLo], a
call MoveSelectionScreen
push af
call Call_LoadTempTileMapToTileMap
call UpdateBattleHuds
ld a, [CurPlayerMove]
cp STRUGGLE
jr z, .struggle
call PlayClickSFX
.struggle
ld a, $1
ld [hBGMapMode], a
pop af
ret nz
.encored
call SetPlayerTurn
callab UpdateMoveData
xor a
ld [wPlayerCharging], a
ld a, [wPlayerMoveStruct + MOVE_EFFECT]
cp EFFECT_FURY_CUTTER
jr z, .continue_fury_cutter
xor a
ld [PlayerFuryCutterCount], a
.continue_fury_cutter
ld a, [wPlayerMoveStruct + MOVE_EFFECT]
cp EFFECT_RAGE
jr z, .continue_rage
ld hl, PlayerSubStatus4
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 [PlayerProtectCount], a
jr .continue_protect
.reset_bide
ld hl, PlayerSubStatus3
res SUBSTATUS_BIDE, [hl]
.locked_in
xor a
ld [PlayerFuryCutterCount], a
ld [PlayerProtectCount], a
ld [wPlayerRageCounter], a
ld hl, PlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
.continue_protect
call ParseEnemyAction
xor a
ret
.reset_rage
xor a
ld [PlayerFuryCutterCount], a
ld [PlayerProtectCount], a
ld [wPlayerRageCounter], a
ld hl, PlayerSubStatus4
res SUBSTATUS_RAGE, [hl]
xor a
ret
; 3c4df
HandleEncore: ; 3c4df
ld a, [hLinkPlayerNumber]
cp $1
jr z, .player_1
call .do_player
jr .do_enemy
.player_1
call .do_enemy
.do_player
ld hl, PlayerSubStatus5
bit SUBSTATUS_ENCORED, [hl]
ret z
ld a, [PlayerEncoreCount]
dec a
ld [PlayerEncoreCount], a
jr z, .end_player_encore
ld hl, BattleMonPP
ld a, [CurMoveNum]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and $3f
ret nz
.end_player_encore
ld hl, PlayerSubStatus5
res SUBSTATUS_ENCORED, [hl]
call SetEnemyTurn
ld hl, BattleText_TargetsEncoreEnded
jp StdBattleTextBox
.do_enemy
ld hl, EnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
ret z
ld a, [EnemyEncoreCount]
dec a
ld [EnemyEncoreCount], a
jr z, .end_enemy_encore
ld hl, EnemyMonPP
ld a, [CurEnemyMoveNum]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and $3f
ret nz
.end_enemy_encore
ld hl, EnemySubStatus5
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, [PlayerSubStatus5]
bit SUBSTATUS_CANT_RUN, a
jr nz, .Stay
ld a, [wEnemyWrapCount]
and a
jr nz, .Stay
ld a, [EnemyMonStatus]
and 1 << FRZ | SLP
jr nz, .Stay
ld a, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
ld de, 1
ld hl, SometimesFleeMons
call IsInArray
jr c, .Flee
.Stay:
and a
ret
.Flee:
scf
ret
; 3c59a
FleeMons:
SometimesFleeMons: ; 3c59a
db MAGNEMITE
db GRIMER
db TANGELA
db MR__MIME
db EEVEE
db PORYGON
db DRATINI
db DRAGONAIR
db TOGETIC
db UMBREON
db UNOWN
db SNUBBULL
db HERACROSS
db -1
OftenFleeMons: ; 3c5a8
db CUBONE
db ARTICUNO
db ZAPDOS
db MOLTRES
db QUAGSIRE
db DELIBIRD
db PHANPY
db TEDDIURSA
db -1
AlwaysFleeMons: ; 3c5b1
db RAIKOU
db ENTEI
; db SUICUNE
db -1
; 3c5b4
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, [CurPlayerMove]
call GetMovePriority
ld b, a
push bc
ld a, [CurEnemyMove]
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, 1
ret
.done
ld a, [hl]
ret
; 3c5df
MoveEffectPriorities: ; 3c5df
db EFFECT_PROTECT, 3
db EFFECT_ENDURE, 3
db EFFECT_PRIORITY_HIT, 2
db EFFECT_FORCE_SWITCH, 0
db EFFECT_COUNTER, 0
db EFFECT_MIRROR_COAT, 0
db -1
; 3c5ec
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
callab 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 [wPlayerAction], a
ret
; 3c664
Battle_PlayerFirst: ; 3c664
xor a
ld [wEnemyGoesFirst], a
call SetEnemyTurn
callab 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 [wPlayerAction], a
ret
; 3c6cf
PlayerTurn_EndOpponentProtectEndureDestinyBond: ; 3c6cf
call SetPlayerTurn
call EndUserDestinyBond
callab DoPlayerTurn
jp EndOpponentProtectEndureDestinyBond
; 3c6de
EnemyTurn_EndOpponentProtectEndureDestinyBond: ; 3c6de
call SetEnemyTurn
call EndUserDestinyBond
callab 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, EnemyMonHP
jr CheckIfHPIsZero
HasPlayerFainted: ; 3c710
ld hl, BattleMonHP
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, PlayerToxicCount
ld a, [hBattleTurn]
and a
jr z, .check_toxic
ld de, EnemyToxicCount
.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, BattleMonHP
ld a, [hBattleTurn]
and a
jr z, .check_fainted
ld hl, EnemyMonHP
.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, [hLinkPlayerNumber]
cp $1
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, PlayerPerishCount
ld a, [hBattleTurn]
and a
jr z, .got_count
ld hl, EnemyPerishCount
.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, BattleMonHP
xor a
ld [hli], a
ld [hl], a
ld hl, PartyMon1HP
ld a, [CurBattleMon]
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
ret
.kill_enemy
ld hl, EnemyMonHP
xor a
ld [hli], a
ld [hl], a
ld a, [wBattleMode]
dec a
ret z
ld hl, OTPartyMon1HP
ld a, [CurOTMon]
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
ret
; 3c874
HandleWrap: ; 3c874
ld a, [hLinkPlayerNumber]
cp $1
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 [FXAnimIDLo], 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 [FXAnimIDHi], 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, [hLinkPlayerNumber]
cp $1
jr z, .DoEnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.DoEnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
callab GetUserItem
ld a, [hl]
ld [wd265], a
call GetItemName
ld a, b
cp HELD_LEFTOVERS
ret nz
ld hl, BattleMonHP
ld a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, EnemyMonHP
.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, [hLinkPlayerNumber]
cp $1
jr z, .DoEnemyFirst
call SetPlayerTurn
call .do_it
call SetEnemyTurn
jp .do_it
.DoEnemyFirst:
call SetEnemyTurn
call .do_it
call SetPlayerTurn
.do_it
callab GetUserItem
ld a, b
cp HELD_RESTORE_PP
jr nz, .quit
ld hl, PartyMon1PP
ld a, [CurBattleMon]
call GetPartyLocation
ld d, h
ld e, l
ld hl, PartyMon1Moves
ld a, [CurBattleMon]
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, OTPartyMon1PP
ld a, [CurOTMon]
call GetPartyLocation
ld d, h
ld e, l
ld hl, OTPartyMon1Moves
ld a, [CurOTMon]
call GetPartyLocation
.wild
ld c, $0
.loop
ld a, [hl]
and a
jr z, .quit
ld a, [de]
and $3f
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, BattleMonMoves - 1
ld hl, BattleMonPP
ld a, [hBattleTurn]
and a
jr z, .player_pp
ld de, EnemyMonMoves - 1
ld hl, EnemyMonPP
.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, [PlayerSubStatus5]
jr z, .check_transform
ld a, [EnemySubStatus5]
.check_transform
bit SUBSTATUS_TRANSFORMED, a
jr nz, .skip_checks
ld a, [de]
add b
ld [de], a
.skip_checks
callab 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, [hLinkPlayerNumber]
cp $1
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
callab UpdateMoveData
xor a
ld [AttackMissed], a
ld [AlreadyDisobeyed], a
ld a, 10
ld [TypeModifier], a
callab DoMove
xor a
ld [CurDamage], a
ld [CurDamage + 1], a
ld a, BATTLE_VARS_MOVE
call GetBattleVarAddr
pop af
ld [hl], a
call UpdateBattleMonInParty
jp UpdateEnemyMonInParty
; 3ca8f
HanleDefrost: ; 3ca8f
ld a, [hLinkPlayerNumber]
cp $1
jr z, .enemy_first
call .do_player_turn
jr .do_enemy_turn
.enemy_first
call .do_enemy_turn
.do_player_turn
ld a, [BattleMonStatus]
bit FRZ, a
ret z
ld a, [wPlayerJustGotFrozen]
and a
ret nz
call BattleRandom
cp 10 percent
ret nc
xor a
ld [BattleMonStatus], a
ld a, [CurBattleMon]
ld hl, PartyMon1Status
call GetPartyLocation
ld [hl], 0
call UpdateBattleHuds
call SetEnemyTurn
ld hl, DefrostedOpponentText
jp StdBattleTextBox
.do_enemy_turn
ld a, [EnemyMonStatus]
bit FRZ, a
ret z
ld a, [wEnemyJustGotFrozen]
and a
ret nz
call BattleRandom
cp 10 percent
ret nc
xor a
ld [EnemyMonStatus], a
ld a, [wBattleMode]
dec a
jr z, .wild
ld a, [CurOTMon]
ld hl, OTPartyMon1Status
call GetPartyLocation
ld [hl], 0
.wild
call UpdateBattleHuds
call SetPlayerTurn
ld hl, DefrostedOpponentText
jp StdBattleTextBox
; 3cafb
HandleSafeguard: ; 3cafb
ld a, [hLinkPlayerNumber]
cp $1
jr z, .player1
call .CheckPlayer
jr .CheckEnemy
.player1
call .CheckEnemy
.CheckPlayer:
ld a, [PlayerScreens]
bit SCREENS_SAFEGUARD, a
ret z
ld hl, PlayerSafeguardCount
dec [hl]
ret nz
res SCREENS_SAFEGUARD, a
ld [PlayerScreens], a
xor a
jr .print
.CheckEnemy:
ld a, [EnemyScreens]
bit SCREENS_SAFEGUARD, a
ret z
ld hl, EnemySafeguardCount
dec [hl]
ret nz
res SCREENS_SAFEGUARD, a
ld [EnemyScreens], a
ld a, $1
.print
ld [hBattleTurn], a
ld hl, BattleText_SafeguardFaded
jp StdBattleTextBox
HandleScreens: ; 3cb36
ld a, [hLinkPlayerNumber]
cp 1
jr z, .Both
call .CheckPlayer
jr .CheckEnemy
.Both:
call .CheckEnemy
.CheckPlayer:
call SetPlayerTurn
ld de, .Your
call .Copy
ld hl, PlayerScreens
ld de, PlayerLightScreenCount
jr .TickScreens
.CheckEnemy:
call SetEnemyTurn
ld de, .Enemy
call .Copy
ld hl, EnemyScreens
ld de, EnemyLightScreenCount
.TickScreens:
bit SCREENS_LIGHT_SCREEN, [hl]
call nz, .LightScreenTick
bit SCREENS_REFLECT, [hl]
call nz, .ReflectTick
ret
.Copy:
ld hl, StringBuffer1
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_PkmnLightScreenFell
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_PkmnReflectFaded
jp StdBattleTextBox
; 3cb9e
HandleWeather: ; 3cb9e
ld a, [Weather]
cp WEATHER_NONE
ret z
ld hl, WeatherCount
dec [hl]
jr z, .ended
ld hl, .WeatherMessages
call .PrintWeatherMessage
ld a, [Weather]
cp WEATHER_SANDSTORM
ret nz
ld a, [hLinkPlayerNumber]
cp 1
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, BattleMonType1
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyMonType1
.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 [Weather], a
ret
.PrintWeatherMessage:
ld a, [Weather]
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 Pkmn
call SubtractHP
jp UpdateHPBarBattleHuds
; 3cc45
SubtractHP: ; 3cc45
ld hl, BattleMonHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyMonHP
.ok
inc hl
ld a, [hl]
ld [Buffer3], a
sub c
ld [hld], a
ld [Buffer5], a
ld a, [hl]
ld [Buffer4], a
sbc b
ld [hl], a
ld [Buffer6], a
ret nc
ld a, [Buffer3]
ld c, a
ld a, [Buffer4]
ld b, a
xor a
ld [hli], a
ld [hl], a
ld [Buffer5], a
ld [Buffer6], 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, Buffer1-2
ld hl, BattleMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyMonMaxHP
.ok
ld a, [hli]
ld [Buffer2], a
ld b, a
ld a, [hl]
ld [Buffer1], a
ld c, a
ret
; 3ccc2
GetHalfHP: ; 3ccc2
; unreferenced
ld hl, BattleMonHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyMonHP
.ok
ld a, [hli]
ld b, a
ld a, [hli]
ld c, a
srl b
rr c
ld a, [hli]
ld [Buffer2], a
ld a, [hl]
ld [Buffer1], a
ret
; 3ccde
CheckUserHasEnoughHP: ; 3ccde
ld hl, BattleMonHP + 1
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyMonHP + 1
.ok
ld a, c
sub [hl]
dec hl
ld a, b
sbc [hl]
ret
; 3ccef
RestoreHP ; 3ccef
ld hl, EnemyMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, BattleMonMaxHP
.ok
ld a, [hli]
ld [Buffer2], a
ld a, [hld]
ld [Buffer1], a
dec hl
ld a, [hl]
ld [Buffer3], a
add c
ld [hld], a
ld [Buffer5], a
ld a, [hl]
ld [Buffer4], a
adc b
ld [hli], a
ld [Buffer6], a
ld a, [Buffer1]
ld c, a
ld a, [hld]
sub c
ld a, [Buffer2]
ld b, a
ld a, [hl]
sbc b
jr c, .asm_3cd2d
ld a, b
ld [hli], a
ld [Buffer6], a
ld a, c
ld [hl], a
ld [Buffer5], 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, BattleMonHP
ld a, [hli]
or [hl]
call z, FaintYourPokemon
xor a
ld [wWhichMonFaintedFirst], a
call UpdateBattleStateAndExperienceAfterEnemyFaint
call CheckPlayerPartyForFitPkmn
ld a, d
and a
jp z, LostBattle
ld hl, BattleMonHP
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 [BattleEnded], a
ret
.trainer
call CheckEnemyTrainerDefeated
jp z, WinTrainerBattle
ld hl, BattleMonHP
ld a, [hli]
or [hl]
jr nz, .player_mon_not_fainted
call AskUseNextPokemon
jr nc, .dont_flee
ld a, 1
ld [BattleEnded], a
ret
.dont_flee
call ForcePlayerMonChoice
call CheckMobileBattleError
jp c, WildFled_EnemyFled_LinkBattleCanceled
ld a, $1
ld [wPlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
jr DoubleSwitch
.player_mon_not_fainted
ld a, $1
ld [wPlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
xor a
ld [wPlayerAction], a
ret
; 3cdca
DoubleSwitch: ; 3cdca
ld a, [hLinkPlayerNumber]
cp $1
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, [CurPartyMon]
push af
ld a, $1
call EnemyPartyMonEntrance
call ClearSprites
call LoadTileMapToTempTileMap
pop af
ld [CurPartyMon], a
call PlayerPartyMonEntrance
.done
xor a
ld [wPlayerAction], a
ret
; 3ce01
UpdateBattleStateAndExperienceAfterEnemyFaint: ; 3ce01
call UpdateBattleMonInParty
ld a, [wBattleMode]
dec a
jr z, .wild
ld a, [CurOTMon]
ld hl, OTPartyMon1HP
call GetPartyLocation
xor a
ld [hli], a
ld [hl], a
.wild
ld hl, PlayerSubStatus3
res SUBSTATUS_IN_LOOP, [hl]
xor a
ld hl, EnemyDamageTaken
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 [wDanger], a
.trainer
ld hl, BattleMonHP
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 CheckPlayerPartyForFitPkmn
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, EnemyMonBaseStats
ld b, EnemyMonEnd - EnemyMonBaseStats
.loop
srl [hl]
inc hl
dec b
jr nz, .loop
.skip_exp
ld hl, EnemyMonBaseStats
ld de, wBackupEnemyMonBaseStats
ld bc, EnemyMonEnd - EnemyMonBaseStats
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, EnemyMonBaseStats
ld bc, EnemyMonEnd - EnemyMonBaseStats
call CopyBytes
ld a, $1
ld [wGivingExperienceToExpShareHolders], a
call GiveExperiencePoints
pop af
ld [wBattleParticipantsNotFainted], a
ret
; 3ceaa
IsAnyMonHoldingExpShare: ; 3ceaa
ld a, [PartyCount]
ld b, a
ld hl, PartyMon1
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 [Danger], a
ret
; 3cef1
FaintYourPokemon: ; 3cef1
call StopDangerSound
call WaitSFX
ld a, $f0
ld [CryTracks], a
ld a, [BattleMonSpecies]
call PlayStereoCry
call PlayerMonFaintedAnimation
hlcoord 9, 7
lb bc, 5, 11
call ClearBox
ld hl, BattleText_PkmnFainted
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_EnemyPkmnFainted
jp StdBattleTextBox
; 3cf35
CheckEnemyTrainerDefeated: ; 3cf35
ld a, [OTPartyCount]
ld b, a
xor a
ld hl, OTPartyMon1HP
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, EnemyHPPal
ld e, HP_BAR_LENGTH_PX
call UpdateHPPal
call WaitBGMap
callba 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, BattleMonHP
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 [wPlayerAction], a
inc a
ret
; 3cfa4
WinTrainerBattle: ; 3cfa4
; Player won the battle
call StopDangerSound
ld a, $1
ld [wDanger], a
ld [BattleEnded], a
ld a, [wLinkMode]
and a
ld a, b
call z, PlayVictoryMusic
callab Battle_GetTrainerName
ld hl, BattleText_EnemyWasDefeated
call StdBattleTextBox
call IsMobileBattle
jr z, .mobile
ld a, [wLinkMode]
and a
ret nz
ld a, [InBattleTowerBattle]
bit 0, a
jr nz, .battle_tower
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
ld a, [BattleType]
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
callba Mobile_PrintOpponentBattleMessage
ret
.battle_tower
call BattleWinSlideInEnemyTrainerFrontpic
ld c, 40
call DelayFrames
call EmptyBattleTextBox
ld c, $3
callba 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, Money + 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 999999 % $100
ld a, [hld]
sbc 999999 / $100 % $100
ld a, [hl]
sbc 999999 / $10000 % $100
ret
; 3d0be
AddBattleMoneyToAccount: ; 3d0be
ld c, $3
and a
push de
push hl
push bc
ld b, h
ld c, l
callba TrainerRankings_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 999999 % $100
ld a, [hld]
sbc 999999 / $100 % $100
ld a, [hl]
sbc 999999 / $10000 % $100
ret c
ld [hl], 999999 / $10000 % $100
inc hl
ld [hl], 999999 / $100 % $100
inc hl
ld [hl], 999999 % $100
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 IsJohtoGymLeader
jr c, .play_music
ld de, MUSIC_TRAINER_VICTORY
.play_music
call PlayMusic
.lost
pop de
ret
; 3d123
; These functions check if the current opponent is a gym leader or one of a
; few other special trainers.
; Note: KantoGymLeaders is a subset of JohtoGymLeaders. If you wish to
; differentiate between the two, call IsKantoGymLeader first.
; The Lance and Red entries are unused for music checks; those trainers are
; accounted for elsewhere.
IsKantoGymLeader: ; 0x3d123
ld hl, KantoGymLeaders
jr IsGymLeaderCommon
IsJohtoGymLeader: ; 0x3d128
ld hl, JohtoGymLeaders
IsGymLeaderCommon:
push de
ld a, [OtherTrainerClass]
ld de, $0001
call IsInArray
pop de
ret
; 0x3d137
JohtoGymLeaders:
db FALKNER
db WHITNEY
db BUGSY
db MORTY
db PRYCE
db JASMINE
db CHUCK
db CLAIR
db WILL
db BRUNO
db KAREN
db KOGA
; fallthrough
; these two entries are unused
db CHAMPION
db RED
; fallthrough
KantoGymLeaders:
db BROCK
db MISTY
db LT_SURGE
db ERIKA
db JANINE
db SABRINA
db BLAINE
db BLUE
db -1
HandlePlayerMonFaint: ; 3d14e
call FaintYourPokemon
ld hl, EnemyMonHP
ld a, [hli]
or [hl]
call z, FaintEnemyPokemon
ld a, $1
ld [wWhichMonFaintedFirst], a
call PlayerMonFaintHappinessMod
call CheckPlayerPartyForFitPkmn
ld a, d
and a
jp z, LostBattle
ld hl, EnemyMonHP
ld a, [hli]
or [hl]
jr nz, .notfainted
call UpdateBattleStateAndExperienceAfterEnemyFaint
ld a, [wBattleMode]
dec a
jr nz, .trainer
ld a, $1
ld [BattleEnded], a
ret
.trainer
call CheckEnemyTrainerDefeated
jp z, WinTrainerBattle
.notfainted
call AskUseNextPokemon
jr nc, .switch
ld a, $1
ld [BattleEnded], a
ret
.switch
call ForcePlayerMonChoice
call CheckMobileBattleError
jp c, WildFled_EnemyFled_LinkBattleCanceled
ld a, c
and a
ret nz
ld a, $1
ld [wPlayerAction], a
call HandleEnemySwitch
jp z, WildFled_EnemyFled_LinkBattleCanceled
jp DoubleSwitch
; 3d1aa
PlayerMonFaintHappinessMod: ; 3d1aa
ld a, [CurBattleMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, RESET_FLAG
predef FlagPredef
ld hl, EnemySubStatus3
res SUBSTATUS_IN_LOOP, [hl]
xor a
ld [Danger], a
ld hl, PlayerDamageTaken
ld [hli], a
ld [hl], a
ld [BattleMonStatus], a
call UpdateBattleMonInParty
ld c, HAPPINESS_FAINTED
; If TheirLevel > (YourLevel + 30), use a different parameter
ld a, [BattleMonLevel]
add 30
ld b, a
ld a, [EnemyMonLevel]
cp b
jr c, .got_param
ld c, HAPPINESS_BEATENBYSTRONGFOE
.got_param
ld a, [CurBattleMon]
ld [CurPartyMon], a
callab 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, PartyMon1Speed
ld de, EnemyMonSpeed
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 [wPlayerAction], a
call LinkBattleSendReceiveAction
.skip_link
xor a
ld [wPlayerAction], a
call CheckMobileBattleError
jr c, .enemy_fainted_mobile_error
ld hl, EnemyMonHP
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, [CurBattleMon]
ld [LastPlayerMon], a
ld a, [CurPartyMon]
ld [CurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call ClearPalettes
call DelayFrame
call _LoadHPBar
call CloseWindow
call GetMemSGBLayout
call SetPalettes
call SendOutPkmnText
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, [CurBattleMon]
ld [LastPlayerMon], a
ld a, [CurPartyMon]
ld [CurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call SendOutPkmnText
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?
callba LoadPartyMenuGFX
callba InitPartyMenuWithCancel
callba InitPartyMenuBGPal7
callba InitPartyMenuGFX
ret
; 3d313
JumpToPartyMenuAndPrintText: ; 3d313
callba WritePartyMenuTilemap
callba PrintPartyMenuText
call WaitBGMap
call SetPalettes
call DelayFrame
ret
; 3d329
SelectBattleMon: ; 3d329
call IsMobileBattle
jr z, .mobile
callba PartyMenuSelect
ret
.mobile
callba Mobile_PartyMenuSelect
ret
; 3d33c
PickPartyMonInBattle: ; 3d33c
.loop
ld a, $2 ; Which PKMN?
ld [PartyMenuActionText], a
call JumpToPartyMenuAndPrintText
call SelectBattleMon
ret c
call CheckIfCurPartyMonIsFitToFight
jr z, .loop
xor a
ret
; 3d34f
SwitchMonAlreadyOut: ; 3d34f
ld hl, CurBattleMon
ld a, [CurPartyMon]
cp [hl]
jr nz, .notout
ld hl, BattleText_PkmnIsAlreadyOut
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 [BattleEnded], a
ld a, [InBattleTowerBattle]
bit 0, a
jr nz, .battle_tower
ld a, [BattleType]
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, 2
callba 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
callba 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 LoadEnemyPkmnToSwitchTo
call ClearEnemyMonBox
call NewEnemyMonStatus
call ResetEnemyStatLevels
call Function_SetEnemyPkmnAndSendOutAnimation
call BreakAttraction
call ResetBattleParticipants
ret
; 3d4e1
EnemySwitch: ; 3d4e1
call CheckWhetherToAskSwitch
jr nc, EnemySwitch_SetMode
; Shift Mode
call ResetEnemyBattleVars
call CheckWhetherSwitchmonIsPredetermined
jr c, .skip
call FindPkmnInOTPartyToSwitchIntoBattle
.skip
; 'b' contains the PartyNr of the Pkmn the AI will switch to
call LoadEnemyPkmnToSwitchTo
call OfferSwitch
push af
call ClearEnemyMonBox
call Function_BattleTextEnemySentOut
call Function_SetEnemyPkmnAndSendOutAnimation
pop af
ret c
; If we're here, then we're switching too
xor a
ld [wBattleParticipantsNotFainted], a
ld [wBattleParticipantsIncludingFainted], a
ld [wPlayerAction], a
inc a
ld [wEnemyIsSwitching], a
call LoadTileMapToTempTileMap
jp PlayerSwitch
; 3d517
EnemySwitch_SetMode: ; 3d517
call ResetEnemyBattleVars
call CheckWhetherSwitchmonIsPredetermined
jr c, .skip
call FindPkmnInOTPartyToSwitchIntoBattle
.skip
; 'b' contains the PartyNr of the Pkmn the AI will switch to
call LoadEnemyPkmnToSwitchTo
ld a, 1
ld [wEnemyIsSwitching], a
call ClearEnemyMonBox
call Function_BattleTextEnemySentOut
jp Function_SetEnemyPkmnAndSendOutAnimation
; 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 [LastPlayerCounterMove], a
ld [LastEnemyCounterMove], a
ld [LastEnemyMove], a
ld [CurEnemyMove], 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, [CurBattleMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, SET_FLAG
push bc
predef FlagPredef
pop bc
ld hl, wBattleParticipantsIncludingFainted
predef_jump FlagPredef
; 3d599
FindPkmnInOTPartyToSwitchIntoBattle: ; 3d599
ld b, $ff
ld a, $1
ld [Buffer1], a
ld [Buffer2], a
.loop
ld hl, Buffer1
sla [hl]
inc hl
sla [hl]
inc b
ld a, [OTPartyCount]
cp b
jp z, ScoreMonTypeMatchups
ld a, [CurOTMon]
cp b
jr z, .discourage
ld hl, OTPartyMon1HP
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 IsThePlayerPkmnTypesEffectiveAgainstOTPkmn
jr .loop
.discourage
ld hl, Buffer2
set 0, [hl]
jr .loop
; 3d5d7
LookUpTheEffectivenessOfEveryMove: ; 3d5d7
push bc
ld hl, OTPartyMon1Moves
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
callab 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, Buffer1
set 0, [hl]
ret
.done
ret
; 3d618
IsThePlayerPkmnTypesEffectiveAgainstOTPkmn: ; 3d618
; Calculates the effectiveness of the types of the PlayerPkmn
; against the OTPkmn
push bc
ld hl, OTPartyCount
ld a, b
inc a
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
dec a
ld hl, BaseData + 7 ; type
ld bc, BaseData1 - BaseData0
call AddNTimes
ld de, EnemyMonType
ld bc, 2
ld a, BANK(BaseData)
call FarCopyBytes
ld a, [BattleMonType1]
ld [wPlayerMoveStruct + MOVE_TYPE], a
call SetPlayerTurn
callab BattleCheckTypeMatchup
ld a, [wd265]
cp 10 + 1 ; 1.0 + 0.1
jr nc, .super_effective
ld a, [BattleMonType2]
ld [wPlayerMoveStruct + MOVE_TYPE], a
callab BattleCheckTypeMatchup
ld a, [wd265]
cp 10 + 1 ; 1.0 + 0.1
jr nc, .super_effective
pop bc
ret
.super_effective
pop bc
ld hl, Buffer1
bit 0, [hl]
jr nz, .reset
inc hl
set 0, [hl]
ret
.reset
res 0, [hl]
ret
; 3d672
ScoreMonTypeMatchups: ; 3d672
.loop1
ld hl, Buffer1
sla [hl]
inc hl
sla [hl]
jr nc, .loop1
ld a, [OTPartyCount]
ld b, a
ld c, [hl]
.loop2
sla c
jr nc, .okay
dec b
jr z, .loop5
jr .loop2
.okay
ld a, [Buffer1]
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, [Buffer2]
ld c, a
.loop4
inc b
sla c
jr c, .loop4
jr .quit
.loop5
ld a, [OTPartyCount]
ld b, a
call BattleRandom
and $7
cp b
jr nc, .loop5
ld b, a
ld a, [CurOTMon]
cp b
jr z, .loop5
ld hl, OTPartyMon1HP
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
LoadEnemyPkmnToSwitchTo: ; 3d6ca
; 'b' contains the PartyNr of the Pkmn the AI will switch to
ld a, b
ld [CurPartyMon], a
ld hl, OTPartyMon1Level
call GetPartyLocation
ld a, [hl]
ld [CurPartyLevel], a
ld a, [CurPartyMon]
inc a
ld hl, OTPartyCount
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [TempEnemyMonSpecies], a
ld [CurPartySpecies], a
call LoadEnemyMon
ld a, [CurPartySpecies]
cp UNOWN
jr nz, .skip_unown
ld a, [wFirstUnownSeen]
and a
jr nz, .skip_unown
ld hl, EnemyMonDVs
predef GetUnownLetter
ld a, [UnownLetter]
ld [wFirstUnownSeen], a
.skip_unown
ld hl, EnemyMonHP
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, [PartyCount]
dec a
jp z, .return_nc
ld a, [wLinkMode]
and a
jp nz, .return_nc
ld a, [Options]
bit BATTLE_SHIFT, a
jr nz, .return_nc
ld a, [CurPartyMon]
push af
ld a, [CurBattleMon]
ld [CurPartyMon], a
callba CheckCurPartyMonFainted
pop bc
ld a, b
ld [CurPartyMon], a
jr c, .return_nc
scf
ret
.return_nc
and a
ret
; 3d74b
OfferSwitch: ; 3d74b
ld a, [CurPartyMon]
push af
callab Battle_GetTrainerName
ld hl, BattleText_EnemyIsAboutToUseWillPlayerChangePkmn
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, [CurBattleMon]
ld [LastPlayerMon], a
ld a, [CurPartyMon]
ld [CurBattleMon], a
call ClearPalettes
call DelayFrame
call _LoadHPBar
pop af
ld [CurPartyMon], a
xor a
ld [CurEnemyMove], a
ld [CurPlayerMove], a
and a
ret
.canceled_switch
call ClearPalettes
call DelayFrame
call _LoadHPBar
.said_no
pop af
ld [CurPartyMon], 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
callab Battle_GetTrainerName
ld hl, BattleText_EnemySentOut
call StdBattleTextBox
jp WaitBGMap
; 3d7c7
Function_SetEnemyPkmnAndSendOutAnimation: ; 3d7c7
ld a, [TempEnemyMonSpecies]
ld [CurPartySpecies], a
ld [CurSpecies], a
call GetBaseData
ld a, OTPARTYMON
ld [MonType], a
predef CopyPkmnToTempMon
call GetMonFrontpic
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, TempMonSpecies
callba CheckFaintedFrzSlp
jr c, .skip_cry
callba 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 [CryTracks], a
ld a, [TempEnemyMonSpecies]
call PlayStereoCry
.skip_cry
call UpdateEnemyHUD
ld a, $1
ld [hBGMapMode], a
ret
; 3d834
NewEnemyMonStatus: ; 3d834
xor a
ld [LastPlayerCounterMove], a
ld [LastEnemyCounterMove], a
ld [LastEnemyMove], a
ld hl, EnemySubStatus1
rept 4
ld [hli], a
endr
ld [hl], a
ld [EnemyDisableCount], a
ld [EnemyFuryCutterCount], a
ld [EnemyProtectCount], a
ld [wEnemyRageCounter], a
ld [EnemyDisabledMove], a
ld [wEnemyMinimized], a
ld [wPlayerWrapCount], a
ld [wEnemyWrapCount], a
ld [EnemyTurnsTaken], a
ld hl, PlayerSubStatus5
res SUBSTATUS_CANT_RUN, [hl]
ret
; 3d867
ResetEnemyStatLevels: ; 3d867
ld a, BASE_STAT_LEVEL
ld b, NUM_LEVEL_STATS
ld hl, EnemyStatLevels
.loop
ld [hli], a
dec b
jr nz, .loop
ret
; 3d873
CheckPlayerPartyForFitPkmn: ; 3d873
; Has the player any Pkmn in his Party that can fight?
ld a, [PartyCount]
ld e, a
xor a
ld hl, PartyMon1HP
ld bc, PartyMon2 - (PartyMon1 + 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, [CurPartyMon]
ld hl, PartyMon1HP
call GetPartyLocation
ld a, [hli]
or [hl]
ret nz
ld a, [wBattleHasJustStarted]
and a
jr nz, .finish_fail
ld hl, PartySpecies
ld a, [CurPartyMon]
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, [BattleType]
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, [EnemySubStatus5]
bit SUBSTATUS_CANT_RUN, a
jp nz, .cant_escape
ld a, [wPlayerWrapCount]
and a
jp nz, .cant_escape
push hl
push de
ld a, [BattleMonItem]
ld [wd265], a
ld b, a
callab 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 [wPlayerAction], 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 [wPlayerAction], a
ld a, $f
ld [CurMoveNum], a
xor a
ld [CurPlayerMove], 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, BattleMonSpecies
ld bc, MON_ID
call CopyBytes
ld bc, MON_DVS - MON_ID
add hl, bc
ld de, BattleMonDVs
ld bc, MON_PKRUS - MON_DVS
call CopyBytes
inc hl
inc hl
inc hl
ld de, BattleMonLevel
ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
call CopyBytes
ld a, [BattleMonSpecies]
ld [TempBattleMonSpecies], a
ld [CurPartySpecies], a
ld [CurSpecies], a
call GetBaseData
ld a, [BaseType1]
ld [BattleMonType1], a
ld a, [BaseType2]
ld [BattleMonType2], a
ld hl, PartyMonNicknames
ld a, [CurBattleMon]
call SkipNames
ld de, BattleMonNick
ld bc, PKMN_NAME_LENGTH
call CopyBytes
ld hl, BattleMonAttack
ld de, PlayerStats
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
callab CheckShininess
ret
; 3da85
GetPartyMonDVs: ; 3da85
ld hl, BattleMonDVs
ld a, [PlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
ret z
ld hl, PartyMon1DVs
ld a, [CurBattleMon]
jp GetPartyLocation
; 3da97
GetEnemyMonDVs: ; 3da97
ld hl, EnemyMonDVs
ld a, [EnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
ret z
ld hl, wEnemyBackupDVs
ld a, [wBattleMode]
dec a
ret z
ld hl, OTPartyMon1DVs
ld a, [CurOTMon]
jp GetPartyLocation
; 3dab1
ResetPlayerStatLevels: ; 3dab1
ld a, BASE_STAT_LEVEL
ld b, NUM_LEVEL_STATS
ld hl, PlayerStatLevels
.loop
ld [hli], a
dec b
jr nz, .loop
ret
; 3dabd
InitEnemyMon: ; 3dabd
ld a, [CurPartyMon]
ld hl, OTPartyMon1Species
call GetPartyLocation
ld de, EnemyMonSpecies
ld bc, MON_ID
call CopyBytes
ld bc, MON_DVS - MON_ID
add hl, bc
ld de, EnemyMonDVs
ld bc, MON_PKRUS - MON_DVS
call CopyBytes
inc hl
inc hl
inc hl
ld de, EnemyMonLevel
ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
call CopyBytes
ld a, [EnemyMonSpecies]
ld [CurSpecies], a
call GetBaseData
ld hl, OTPartyMonNicknames
ld a, [CurPartyMon]
call SkipNames
ld de, EnemyMonNick
ld bc, PKMN_NAME_LENGTH
call CopyBytes
ld hl, EnemyMonAttack
ld de, EnemyStats
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
call ApplyStatusEffectOnEnemyStats
ld hl, BaseType1
ld de, EnemyMonType1
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld hl, BaseStats
ld de, EnemyMonBaseStats
ld b, 5
.loop
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .loop
ld a, [CurPartyMon]
ld [CurOTMon], a
ret
; 3db32
SwitchPlayerMon: ; 3db32
call ClearSprites
ld a, [CurBattleMon]
ld [LastPlayerMon], a
ld a, [CurPartyMon]
ld [CurBattleMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call NewBattleMonStatus
call BreakAttraction
call SendOutPlayerMon
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld hl, EnemyMonHP
ld a, [hli]
or [hl]
ret
; 3db5f
SendOutPlayerMon: ; 3db5f
ld hl, BattleMonDVs
predef GetUnownLetter
hlcoord 1, 5
ld b, 7
ld c, 8
call ClearBox
call WaitBGMap
xor a
ld [hBGMapMode], a
call GetMonBackpic
xor a
ld [hGraphicStartTile], a
ld [wd0d2], a
ld [CurMoveNum], a
ld [TypeModifier], a
ld [wPlayerMoveStruct + MOVE_ANIM], a
ld [LastPlayerCounterMove], a
ld [LastEnemyCounterMove], a
ld [LastPlayerMove], 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
callba CheckFaintedFrzSlp
jr c, .statused
ld a, $f0
ld [CryTracks], a
ld a, [CurPartySpecies]
call PlayStereoCry
.statused
call UpdatePlayerHUD
ld a, $1
ld [hBGMapMode], a
ret
; 3dbde
NewBattleMonStatus: ; 3dbde
xor a
ld [LastPlayerCounterMove], a
ld [LastEnemyCounterMove], a
ld [LastPlayerMove], a
ld hl, PlayerSubStatus1
rept 4
ld [hli], a
endr
ld [hl], a
ld hl, PlayerUsedMoves
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld [PlayerDisableCount], a
ld [PlayerFuryCutterCount], a
ld [PlayerProtectCount], a
ld [wPlayerRageCounter], a
ld [DisabledMove], a
ld [wPlayerMinimized], a
ld [wEnemyWrapCount], a
ld [wPlayerWrapCount], a
ld [PlayerTurnsTaken], a
ld hl, EnemySubStatus5
res SUBSTATUS_CANT_RUN, [hl]
ret
; 3dc18
BreakAttraction: ; 3dc18
ld hl, PlayerSubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, EnemySubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ret
; 3dc23
SpikesDamage: ; 3dc23
ld hl, PlayerScreens
ld de, BattleMonType
ld bc, UpdatePlayerHUD
ld a, [hBattleTurn]
and a
jr z, .ok
ld hl, EnemyScreens
ld de, EnemyMonType
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, [CurBattleMon]
push af
ld hl, DoPlayerTurn
ld a, [hBattleTurn]
and a
jr z, .do_turn
ld hl, DoEnemyTurn
ld a, [LastPlayerMon]
ld [CurBattleMon], 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 [CurBattleMon], a
ld a, [hBattleTurn]
and a
jr z, .check_enemy_fainted
ld a, [LastPlayerMon]
call UpdateBattleMon
ld hl, BattleMonHP
ld a, [hli]
or [hl]
jr nz, .done
ld a, $f0
ld [CryTracks], a
ld a, [BattleMonSpecies]
call PlayStereoCry
ld a, [LastPlayerMon]
ld c, a
ld hl, wBattleParticipantsNotFainted
ld b, RESET_FLAG
predef FlagPredef
call PlayerMonFaintedAnimation
ld hl, BattleText_PkmnFainted
jr .done_fainted
.check_enemy_fainted
ld hl, EnemyMonHP
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_EnemyPkmnFainted
.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, [hLinkPlayerNumber]
cp $1
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
callab GetOpponentItem
ld a, b
cp $1
ret nz
ld de, EnemyMonHP + 1
ld hl, EnemyMonMaxHP
ld a, [hBattleTurn]
and a
jr z, .go
ld de, BattleMonHP + 1
ld hl, BattleMonMaxHP
.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 [Buffer3], a
add a
ld c, a
dec de
ld a, [de]
inc de
ld [Buffer4], 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 Buffer1/2
ld a, [hli]
ld [Buffer2], a
ld a, [hl]
ld [Buffer1], a
ld a, [de]
add c
ld [Buffer5], a
ld c, a
dec de
ld a, [de]
adc $0
ld [Buffer6], a
ld b, a
ld a, [hld]
cp c
ld a, [hl]
sbc b
jr nc, .okay
ld a, [hli]
ld [Buffer6], a
ld a, [hl]
ld [Buffer5], a
.okay
ld a, [Buffer6]
ld [de], a
inc de
ld a, [Buffer5]
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
callab GetOpponentItem
ld a, [hl]
ld [wNamedObjectIndexBuffer], a
call GetItemName
callab ConsumeHeldItem
ld hl, RecoveredUsingText
jp StdBattleTextBox
; 3ddc8
ItemRecoveryAnim: ; 3ddc8
push hl
push de
push bc
call EmptyBattleTextBox
ld a, RECOVER
ld [FXAnimIDLo], a
call SwitchTurnCore
xor a
ld [wNumHits], a
ld [FXAnimIDHi], a
predef PlayBattleAnim
call SwitchTurnCore
pop bc
pop de
pop hl
ret
; 3dde9
UseHeldStatusHealingItem: ; 3dde9
callab 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 $ff
; 3de51
UseConfusionHealingItem: ; 3de51
ld a, BATTLE_VARS_SUBSTATUS3_OPP
call GetBattleVar
bit SUBSTATUS_CONFUSED, a
ret z
callab 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, [hLinkPlayerNumber]
cp $1
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
callab 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, [FailedMessage]
and a
ret nz
xor a
ld [bc], a
ld [de], a
call GetItemName
ld hl, BattleText_UsersStringBuffer1Activated
call StdBattleTextBox
callab 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 $ff
; 3df12
GetPartymonItem: ; 3df12
ld hl, PartyMon1Item
ld a, [CurBattleMon]
call GetPartyLocation
ld bc, BattleMonItem
ret
; 3df1f
GetOTPartymonItem: ; 3df1f
ld hl, OTPartyMon1Item
ld a, [CurOTMon]
call GetPartyLocation
ld bc, EnemyMonItem
ret
; 3df2c
UpdateBattleHUDs: ; 3df2c
push hl
push de
push bc
call DrawPlayerHUD
ld hl, PlayerHPPal
call SetHPPal
call CheckDanger
call DrawEnemyHUD
ld hl, EnemyHPPal
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
callba DrawPlayerHUDBorder
hlcoord 18, 9
ld [hl], $73 ; vertical bar
call PrintPlayerHUD
; HP bar
hlcoord 10, 9
ld b, 1
xor a ; PARTYMON
ld [MonType], a
predef DrawPlayerHP
; Exp bar
push de
ld a, [CurBattleMon]
ld hl, PartyMon1Exp + 2
call GetPartyLocation
ld d, h
ld e, l
hlcoord 10, 11
ld a, [TempMonLevel]
ld b, a
call FillInExpBar
pop de
ret
; 3df98
UpdatePlayerHPPal: ; 3df98
ld hl, PlayerHPPal
jp UpdateHPPal
; 3df9e
CheckDanger: ; 3df9e
ld hl, BattleMonHP
ld a, [hli]
or [hl]
jr z, .no_danger
ld a, [wDanger]
and a
jr nz, .done
ld a, [PlayerHPPal]
cp HP_RED
jr z, .danger
.no_danger
ld hl, Danger
res 7, [hl]
jr .done
.danger
ld hl, Danger
set 7, [hl]
.done
ret
; 3dfbf
PrintPlayerHUD: ; 3dfbf
ld de, BattleMonNick
hlcoord 10, 7
call ret_3e138
call PlaceString
push bc
ld a, [CurBattleMon]
ld hl, PartyMon1DVs
call GetPartyLocation
ld de, TempMonDVs
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
ld hl, BattleMonLevel
ld de, TempMonLevel
ld bc, $0011
call CopyBytes
ld a, [CurBattleMon]
ld hl, PartyMon1Species
call GetPartyLocation
ld a, [hl]
ld [CurPartySpecies], a
ld [CurSpecies], a
call GetBaseData
pop hl
dec hl
ld a, TEMPMON
ld [MonType], a
callab 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, BattleMonStatus
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, [BattleMonLevel]
ld [TempMonLevel], 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
callba DrawEnemyHUDBorder
ld a, [TempEnemyMonSpecies]
ld [CurSpecies], a
ld [CurPartySpecies], a
call GetBaseData
ld de, EnemyMonNick
hlcoord 1, 0
call ret_3e138
call PlaceString
ld h, b
ld l, c
dec hl
ld hl, EnemyMonDVs
ld de, TempMonDVs
ld a, [EnemySubStatus5]
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 [MonType], a
callab 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, EnemyMonStatus
predef PlaceNonFaintStatus
pop hl
pop bc
jr nz, .skip_level
ld a, b
cp " "
jr nz, .print_level
dec hl
.print_level
ld a, [EnemyMonLevel]
ld [TempMonLevel], a
call PrintLevel
.skip_level
ld hl, EnemyMonHP
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, EnemyMonMaxHP
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, EnemyHPPal
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, [BattleType]
cp BATTLETYPE_DEBUG
jr z, .ok
cp BATTLETYPE_TUTORIAL
jr z, .ok
call EmptyBattleTextBox
call UpdateBattleHuds
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
.ok
.loop
ld a, [BattleType]
cp BATTLETYPE_CONTEST
jr nz, .not_contest
callba ContestBattleMenu
jr .next
.not_contest
; Auto input: choose "ITEM"
ld a, [InputType]
or a
jr z, .skip_dude_pack_select
callba _DudeAutoInput_DownA
.skip_dude_pack_select
call LoadBattleMenu2
ret c
.next
ld a, $1
ld [hBGMapMode], a
ld a, [wd0d2]
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
callba LoadBattleMenu
and a
ret
.mobile
callba 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, [InBattleTowerBattle]
and a
jp nz, .ItemsCantBeUsed
call LoadStandardMenuDataHeader
ld a, [BattleType]
cp BATTLETYPE_TUTORIAL
jr z, .tutorial
cp BATTLETYPE_CONTEST
jr z, .contest
callba BattlePack
ld a, [wPlayerAction]
and a
jr z, .didnt_use_item
jr .got_item
.tutorial
callba TutorialPack
ld a, POKE_BALL
ld [CurItem], a
call DoItemEffect
jr .got_item
.contest
ld a, PARK_BALL
ld [CurItem], a
call DoItemEffect
.got_item
call .UseItem
ret
.didnt_use_item
call ClearPalettes
call DelayFrame
call _LoadBattleFontsHPBar
call GetMonBackpic
call GetMonFrontpic
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
callab CheckItemPocket
ld a, [wItemAttributeParamBuffer]
cp BALL
jr z, .ball
call ClearBGPalettes
.ball
xor a
ld [hBGMapMode], a
call _LoadBattleFontsHPBar
call ClearSprites
ld a, [BattleType]
cp BATTLETYPE_TUTORIAL
jr z, .tutorial2
call GetMonBackpic
.tutorial2
call GetMonFrontpic
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 [PartyMenuActionText], a
call JumpToPartyMenuAndPrintText
call SelectBattleMon
jr c, .Cancel
.loop
callba 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
callba BattleMonMenu
ret
.mobile
callba 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 [MonType], a
callba 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, [CurBattleMon]
ld d, a
ld a, [CurPartyMon]
cp d
jr nz, .check_trapped
ld hl, BattleText_PkmnIsAlreadyOut
call StdBattleTextBox
jp BattleMenuPKMN_Loop
.check_trapped
ld a, [wPlayerWrapCount]
and a
jr nz, .trapped
ld a, [EnemySubStatus5]
bit SUBSTATUS_CANT_RUN, a
jr z, .try_switch
.trapped
ld hl, BattleText_PkmnCantBeRecalled
call StdBattleTextBox
jp BattleMenuPKMN_Loop
.try_switch
call CheckIfCurPartyMonIsFitToFight
jp z, BattleMenuPKMN_Loop
ld a, [CurBattleMon]
ld [LastPlayerMon], a
ld a, $2
ld [wPlayerAction], a
call ClearPalettes
call DelayFrame
call ClearSprites
call _LoadHPBar
call CloseWindow
call GetMemSGBLayout
call SetPalettes
ld a, [CurPartyMon]
ld [CurBattleMon], 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, [hLinkPlayerNumber]
cp $1
jr z, .player_1
call BattleMonEntrance
call EnemyMonEntrance
and a
ret
.player_1
call EnemyMonEntrance
call BattleMonEntrance
and a
ret
; 3e3ff
EnemyMonEntrance: ; 3e3ff
callab AI_Switch
call SetEnemyTurn
jp SpikesDamage
; 3e40b
BattleMonEntrance: ; 3e40b
call WithdrawPkmnText
ld c, 50
call DelayFrames
ld hl, PlayerSubStatus4
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, [CurBattleMon]
ld [CurPartyMon], a
call AddBattleParticipant
call InitBattleMon
call ResetPlayerStatLevels
call SendOutPkmnText
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, [CurPartyMon]
ld [CurBattleMon], 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, BattleMonSpeed
ld de, EnemyMonSpeed
call TryToRunAwayFromBattle
ld a, $0
ld [wFailedToFlee], a
ret c
ld a, [wPlayerAction]
and a
ret nz
jp BattleMenu
; 3e4a8
CheckAmuletCoin: ; 3e4a8
ld a, [BattleMonItem]
ld b, a
callab 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
callba MobileMoveSelectionScreen
ret
.not_mobile
ld hl, EnemyMonMoves
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, BattleMonMoves
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 [Buffer1], 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, [CurMoveNum]
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 [CurMoveNum], a
jr nz, .use_move
pop af
ret
.use_move
pop af
ret nz
ld hl, BattleMonPP
ld a, [wMenuCursorY]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
and $3f
jr z, .no_pp_left
ld a, [PlayerDisableCount]
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, BattleMonMoves
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
.skip2
ld [CurPlayerMove], 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, BattleMonMoves
call .swap_bytes
ld hl, BattleMonPP
call .swap_bytes
ld hl, PlayerDisableCount
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, [PlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .transformed
ld hl, PartyMon1Moves
ld a, [CurBattleMon]
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, [PlayerDisableCount]
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, BattleMonMoves
ld a, [wMenuCursorY]
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [CurPlayerMove], a
ld a, [CurBattleMon]
ld [CurPartyMon], a
ld a, WILDMON
ld [MonType], a
callab GetMaxPPOfMove
ld hl, wMenuCursorY
ld c, [hl]
inc [hl]
ld b, 0
ld hl, BattleMonPP
add hl, bc
ld a, [hl]
and $3f
ld [StringBuffer1], a
call .PrintPP
hlcoord 1, 9
ld de, .Type
call PlaceString
hlcoord 7, 11
ld [hl], "/"
callab 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, StringBuffer1
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 [CurPlayerMove], a
ld a, [PlayerDisableCount]
and a
ld hl, BattleMonPP
jr nz, .disabled
ld a, [hli]
or [hl]
inc hl
or [hl]
inc hl
or [hl]
and $3f
ret nz
jr .force_struggle
.disabled
swap a
and $f
ld b, a
ld d, $5
xor a
.loop
dec d
jr z, .done
ld c, [hl]
inc hl
dec b
jr z, .loop
or c
jr .loop
.done
and a ; This is probably a bug, and will result in a move with PP Up confusing the game.
ret nz
.force_struggle
ld hl, BattleText_PkmnHasNoMovesLeft
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, [wPlayerAction]
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 [CurEnemyMoveNum], a
ld c, a
ld a, [EnemySubStatus1]
bit SUBSTATUS_ROLLOUT, a
jp nz, .skip_load
ld a, [EnemySubStatus3]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE
jp nz, .skip_load
ld hl, EnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
ld a, [LastEnemyMove]
jp nz, .finish
ld hl, EnemyMonMoves
ld b, 0
add hl, bc
ld a, [hl]
jp .finish
.not_linked
ld hl, EnemySubStatus5
bit SUBSTATUS_ENCORED, [hl]
jr z, .skip_encore
ld a, [LastEnemyMove]
jp .finish
.skip_encore
call CheckEnemyLockedIn
jp nz, ResetVarsForSubstatusRage
jr .continue
.battle_action_d
ld a, $ff
jr .finish
.continue
ld hl, EnemyMonMoves
ld de, EnemyMonPP
ld b, NUM_MOVES
.loop
ld a, [hl]
and a
jp z, .struggle
ld a, [EnemyDisabledMove]
cp [hl]
jr z, .disabled
ld a, [de]
and $3f
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, EnemyMonMoves
call BattleRandom
and 3 ; TODO factor in NUM_MOVES
ld c, a
ld b, 0
add hl, bc
ld a, [EnemyDisableCount]
swap a
and $f
dec a
cp c
jr z, .loop2
ld a, [hl]
and a
jr z, .loop2
ld hl, EnemyMonPP
add hl, bc
ld b, a
ld a, [hl]
and $3f
jr z, .loop2
ld a, c
ld [CurEnemyMoveNum], a
ld a, b
.finish
ld [CurEnemyMove], a
.skip_load
call SetEnemyTurn
callab 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 [EnemyFuryCutterCount], a
.fury_cutter
ld a, [wEnemyMoveStruct + MOVE_EFFECT]
cp EFFECT_RAGE
jr z, .no_rage
ld hl, EnemySubStatus4
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 [EnemyProtectCount], a
ret
.struggle
ld a, STRUGGLE
jr .finish
; 3e8c1
ResetVarsForSubstatusRage: ; 3e8c1
xor a
ld [EnemyFuryCutterCount], a
ld [EnemyProtectCount], a
ld [wEnemyRageCounter], a
ld hl, EnemySubStatus4
res SUBSTATUS_RAGE, [hl]
ret
; 3e8d1
CheckEnemyLockedIn: ; 3e8d1
ld a, [EnemySubStatus4]
and 1 << SUBSTATUS_RECHARGE
ret nz
ld hl, EnemySubStatus3
ld a, [hl]
and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE
ret nz
ld hl, EnemySubStatus1
bit SUBSTATUS_ROLLOUT, [hl]
ret
; 3e8e4
LinkBattleSendReceiveAction: ; 3e8e4
callba _LinkBattleSendReceiveAction
ret
; 3e8eb
LoadEnemyMon: ; 3e8eb
; Initialize enemy monster parameters
; To do this we pull the species from TempEnemyMonSpecies
; Notes:
; BattleRandom is used to ensure sync between Game Boys
; Clear the whole EnemyMon struct
xor a
ld hl, EnemyMonSpecies
ld bc, EnemyMonEnd - EnemyMon
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, [InBattleTowerBattle] ; ????
bit 0, a
jp nz, InitEnemyMon
; Make sure everything knows what species we're working with
ld a, [TempEnemyMonSpecies]
ld [EnemyMonSpecies], a
ld [CurSpecies], a
ld [CurPartySpecies], 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, [CurPartyMon]
ld hl, OTPartyMon1Item
call GetPartyLocation ; bc = PartyMon[CurPartyMon] - PartyMons
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, [BattleType]
cp BATTLETYPE_FORCEITEM
ld a, [BaseItems]
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 a, 1 + (75 percent)
ld a, NO_ITEM
jr c, .UpdateItem
; From there, an 8% chance for Item2
call BattleRandom
cp a, 8 percent ; 8% of 25% = 2% Item2
ld a, [BaseItems]
jr nc, .UpdateItem
ld a, [BaseItems+1]
.UpdateItem:
ld [EnemyMonItem], a
; Initialize DVs
; If we're in a trainer battle, DVs are predetermined
ld a, [wBattleMode]
and a
jr z, .InitDVs
ld a, [EnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr z, .InitDVs
; Unknown
ld hl, wEnemyBackupDVs
ld de, EnemyMonDVs
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
callba 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, [BattleType]
cp a, 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 BattleType
; Forced shiny battle type
; Used by Red Gyarados at Lake of Rage
cp a, 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, EnemyMonDVs
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, [TempEnemyMonSpecies]
cp a, UNOWN
jr nz, .Magikarp
; Get letter based on DVs
ld hl, EnemyMonDVs
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:
; Skimming this part recommended
ld a, [TempEnemyMonSpecies]
cp a, MAGIKARP
jr nz, .Happiness
; Get Magikarp's length
ld de, EnemyMonDVs
ld bc, PlayerID
callab CalcMagikarpLength
; We're clear if the length is < 1536
ld a, [MagikarpLength]
cp a, $06 ; $600 = 1536
jr nz, .CheckMagikarpArea
; 5% chance of skipping size checks
call Random
cp a, $0c ; / $100
jr c, .CheckMagikarpArea
; Try again if > 1614
ld a, [MagikarpLength + 1]
cp a, $50
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp a, $32 ; / $100
jr c, .CheckMagikarpArea
; Try again if > 1598
ld a, [MagikarpLength + 1]
cp a, $40
jr nc, .GenerateDVs
.CheckMagikarpArea:
; The z checks are supposed to be 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 size flooring in the Lake of Rage area
ld a, [MapGroup]
cp a, GROUP_LAKE_OF_RAGE
jr z, .Happiness
ld a, [MapNumber]
cp a, MAP_LAKE_OF_RAGE
jr z, .Happiness
; 40% chance of not flooring
call Random
cp a, $64 ; / $100
jr c, .Happiness
; Floor at length 1024
ld a, [MagikarpLength]
cp a, 1024 >> 8
jr c, .GenerateDVs ; try again
; Finally done with DVs
.Happiness:
; Set happiness
ld a, BASE_HAPPINESS
ld [EnemyMonHappiness], a
; Set level
ld a, [CurPartyLevel]
ld [EnemyMonLevel], a
; Fill stats
ld de, EnemyMonMaxHP
ld b, FALSE
ld hl, EnemyMonDVs - (MON_DVS - MON_STAT_EXP + 1) ; LinkBattleRNs + 7 ; ?
predef CalcPkmnStats
; If we're in a trainer battle,
; get the rest of the parameters from the party struct
ld a, [wBattleMode]
cp a, TRAINER_BATTLE
jr z, .OpponentParty
; If we're in a wild battle, check wild-specific stuff
and a
jr z, .TreeMon
ld a, [EnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jp nz, .Moves
.TreeMon:
; If we're headbutting trees, some monsters enter battle asleep
call CheckSleepingTreeMon
ld a, SLP ; Asleep for 7 turns
jr c, .UpdateStatus
; Otherwise, no status
xor a
.UpdateStatus:
ld hl, EnemyMonStatus
ld [hli], a
; Unused byte
xor a
ld [hli], a
; Full HP..
ld a, [EnemyMonMaxHP]
ld [hli], a
ld a, [EnemyMonMaxHP + 1]
ld [hl], a
; ..unless it's a RoamMon
ld a, [BattleType]
cp a, 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 [EnemyMonHP + 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, [EnemyMonHP + 1]
ld [hl], a
jr .Moves
.OpponentParty:
; Get HP from the party struct
ld hl, (OTPartyMon1HP + 1)
ld a, [CurPartyMon]
call GetPartyLocation
ld a, [hld]
ld [EnemyMonHP + 1], a
ld a, [hld]
ld [EnemyMonHP], a
; Make sure everything knows which monster the opponent is using
ld a, [CurPartyMon]
ld [CurOTMon], a
; Get status from the party struct
dec hl
ld a, [hl] ; OTPartyMonStatus
ld [EnemyMonStatus], a
.Moves:
ld hl, BaseType1
ld de, EnemyMonType1
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
; Get moves
ld de, EnemyMonMoves
; Are we in a trainer battle?
ld a, [wBattleMode]
cp a, TRAINER_BATTLE
jr nz, .WildMoves
; Then copy moves from the party struct
ld hl, OTPartyMon1Moves
ld a, [CurPartyMon]
call GetPartyLocation
ld bc, NUM_MOVES
call CopyBytes
jr .PP
.WildMoves:
; Clear EnemyMonMoves
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 [MagikarpLength], a
; Fill moves based on level
predef FillMoves
.PP:
; Trainer battle?
ld a, [wBattleMode]
cp a, TRAINER_BATTLE
jr z, .TrainerPP
; Fill wild PP
ld hl, EnemyMonMoves
ld de, EnemyMonPP
predef FillPP
jr .Finish
.TrainerPP:
; Copy PP from the party struct
ld hl, OTPartyMon1PP
ld a, [CurPartyMon]
call GetPartyLocation
ld de, EnemyMonPP
ld bc, NUM_MOVES
call CopyBytes
.Finish:
; Only the first five base stats are copied..
ld hl, BaseStats
ld de, EnemyMonBaseStats
ld b, BaseSpecialDefense - BaseStats
.loop
ld a, [hli]
ld [de], a
inc de
dec b
jr nz, .loop
ld a, [BaseCatchRate]
ld [de], a
inc de
ld a, [BaseExp]
ld [de], a
ld a, [TempEnemyMonSpecies]
ld [wd265], a
call GetPokemonName
; Did we catch it?
ld a, [wBattleMode]
and a
ret z
; Update enemy nick
ld hl, StringBuffer1
ld de, EnemyMonNick
ld bc, PKMN_NAME_LENGTH
call CopyBytes
; Saw this mon
ld a, [TempEnemyMonSpecies]
dec a
ld c, a
ld b, SET_FLAG
ld hl, PokedexSeen
predef FlagPredef
ld hl, EnemyMonStats
ld de, EnemyStats
ld bc, EnemyMonStatsEnd - EnemyMonStats
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, [BattleType]
cp a, BATTLETYPE_TREE
jr nz, .NotSleeping
; Get list for the time of day
ld hl, .Morn
ld a, [TimeOfDay]
cp a, DAY
jr c, .Check
ld hl, .Day
jr z, .Check
ld hl, .Nite
.Check:
ld a, [TempEnemyMonSpecies]
ld de, 1 ; length of species id
call IsInArray
; If it's a match, the opponent is asleep
ret c
.NotSleeping:
and a
ret
.Nite:
db CATERPIE
db METAPOD
db BUTTERFREE
db WEEDLE
db KAKUNA
db BEEDRILL
db SPEAROW
db EKANS
db EXEGGCUTE
db LEDYBA
db AIPOM
db -1 ; end
.Day:
db VENONAT
db HOOTHOOT
db NOCTOWL
db SPINARAK
db HERACROSS
db -1 ; end
.Morn:
db VENONAT
db HOOTHOOT
db NOCTOWL
db SPINARAK
db HERACROSS
db -1 ; end
; 3eb75
CheckUnownLetter: ; 3eb75
; Return carry if the Unown letter hasn't been unlocked yet
ld a, [UnlockedUnowns]
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, [UnownLetter]
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 a, .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
SwapBattlerLevels: ; 3ebc7
; unreferenced
push bc
ld a, [BattleMonLevel]
ld b, a
ld a, [EnemyMonLevel]
ld [BattleMonLevel], a
ld a, b
ld [EnemyMonLevel], a
pop bc
ret
; 3ebd8
BattleWinSlideInEnemyTrainerFrontpic: ; 3ebd8
xor a
ld [TempEnemyMonSpecies], a
call FinishBattleAnim
ld a, [OtherTrainerClass]
ld [TrainerClass], a
ld de, VTiles2
callab 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, [BattleMonStatus]
and 1 << PAR
ret z
ld hl, BattleMonSpeed + 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, [EnemyMonStatus]
and 1 << PAR
ret z
ld hl, EnemyMonSpeed + 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, [BattleMonStatus]
and 1 << BRN
ret z
ld hl, BattleMonAttack + 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, [EnemyMonStatus]
and 1 << BRN
ret z
ld hl, EnemyMonAttack + 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, BattleMonAttack
ld de, PlayerStats
ld bc, PlayerAtkLevel
jr z, .got_pointers
ld hl, EnemyMonAttack
ld de, EnemyStats
ld bc, EnemyAtkLevel
.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 999 % $100
ld a, [hQuotient + 1]
sbc 999 / $100
jp c, .okay3
ld a, 999 / $100
ld [hQuotient + 1], a
ld a, 999 % $100
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 BattleMon stats 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, [InBattleTowerBattle]
and a
ret nz
ld a, [JohtoBadges]
; 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, BattleMonAttack
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 999 % $100
ld a, [hl]
sbc 999 / $100
ret c
ld a, 999 / $100
ld [hli], a
ld a, 999 % $100
ld [hld], a
ret
; 3ed9f
_LoadBattleFontsHPBar: ; 3ed9f
callab LoadBattleFontsHPBar
ret
; 3eda6
_LoadHPBar: ; 3eda6
callab LoadHPBar
ret
; 3edad
LoadHPExpBarGFX: ; unreferenced
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, [LinkBattleRNCount]
ld c, a
ld b, 0
ld hl, LinkBattleRNs
add hl, bc
inc a
ld [LinkBattleRNCount], 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 [LinkBattleRNCount], a
ld hl, LinkBattleRNs
ld b, 10 ; number of seeds
; Generate next number in the sequence for each seed
; The algorithm takes the form *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 [FXAnimIDLo], a
ld a, d
ld [FXAnimIDHi], 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, [InBattleTowerBattle]
bit 0, a
ret nz
call .EvenlyDivideExpAmongParticipants
xor a
ld [CurPartyMon], a
ld bc, PartyMon1Species
.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, [CurPartyMon]
ld c, a
ld b, CHECK_FLAG
ld d, $0
predef FlagPredef
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, EnemyMonBaseStats - 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, [EnemyMonBaseExp]
ld [hMultiplicand + 2], a
ld a, [EnemyMonLevel]
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, [PlayerID]
cp [hl]
jr nz, .boosted
inc hl
ld a, [PlayerID + 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 [StringBuffer2 + 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 [StringBuffer2 + 1], a
ld a, [hQuotient + 1]
ld [StringBuffer2], a
ld a, [CurPartyMon]
ld hl, PartyMonNicknames
call GetNick
ld hl, Text_PkmnGainedExpPoint
call BattleTextBox
ld a, [StringBuffer2 + 1]
ld [hQuotient + 2], a
ld a, [StringBuffer2]
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, [CurPartyMon]
ld e, a
ld d, $0
ld hl, PartySpecies
add hl, de
ld a, [hl]
ld [CurSpecies], a
call GetBaseData
push bc
ld d, MAX_LEVEL
callab 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 [MonType], a
predef CopyPkmnToTempMon
callab 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, [CurPartyLevel]
push af
ld a, d
ld [CurPartyLevel], a
ld [hl], a
ld hl, MON_SPECIES
add hl, bc
ld a, [hl]
ld [CurSpecies], 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 CalcPkmnStats
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, [CurBattleMon]
ld d, a
ld a, [CurPartyMon]
cp d
jr nz, .skip_animation
ld de, BattleMonHP
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
ld de, BattleMonMaxHP
push bc
ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP
call CopyBytes
pop bc
ld hl, MON_LEVEL
add hl, bc
ld a, [hl]
ld [BattleMonLevel], a
ld a, [PlayerSubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .transformed
ld hl, MON_ATK
add hl, bc
ld de, PlayerStats
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
.transformed
xor a
ld [wd265], a
call ApplyStatLevelMultiplierOnAllStats
callab ApplyStatusEffectOnPlayerStats
callab BadgeStatBoosts
callab UpdatePlayerHUD
call EmptyBattleTextBox
call LoadTileMapToTempTileMap
ld a, $1
ld [hBGMapMode], a
.skip_animation
callba LevelUpHappinessMod
ld a, [CurBattleMon]
ld b, a
ld a, [CurPartyMon]
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 [MonType], a
predef CopyPkmnToTempMon
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 [MonType], a
ld a, [CurSpecies]
ld [wd265], a
ld a, [CurPartyLevel]
push af
ld c, a
ld a, [wTempLevel]
ld b, a
.level_loop
inc b
ld a, b
ld [CurPartyLevel], a
push bc
predef LearnLevelMoves
pop bc
ld a, b
cp c
jr nz, .level_loop
pop af
ld [CurPartyLevel], a
ld hl, EvolvableFlags
ld a, [CurPartyMon]
ld c, a
ld b, SET_FLAG
predef FlagPredef
pop af
ld [CurPartyLevel], a
.skip_stats
ld a, [PartyCount]
ld b, a
ld a, [CurPartyMon]
inc a
cp b
jr z, .done
ld [CurPartyMon], 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, EnemyMonBaseStats
ld c, EnemyMonEnd - EnemyMonBaseStats
.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_PkmnGainedExpPoint: ; 3f11b
text_jump Text_Gained
start_asm
ld hl, TextJump_StringBuffer2ExpPoints
ld a, [StringBuffer2 + 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, CurPartyMon
ld a, [CurBattleMon]
cp [hl]
jp nz, .finish
ld a, [BattleMonLevel]
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 [MonType], a
predef CopyPkmnToTempMon
ld a, [TempMonLevel]
ld b, a
ld e, a
push de
ld de, TempMonExp + 2
call CalcExpBar
push bc
ld hl, TempMonExp + 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
callab CalcExpAtLevel
ld a, [hProduct + 1]
ld b, a
ld a, [hProduct + 2]
ld c, a
ld a, [hProduct + 3]
ld d, a
ld hl, TempMonExp + 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:
callab 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 [TempMonLevel], a
ld [CurPartyLevel], a
ld [BattleMonLevel], a
push de
call .PlayExpBarSound
ld c, $40
call .LoopBarAnimation
call PrintPlayerHUD
ld hl, BattleMonNick
ld de, StringBuffer1
ld bc, PKMN_NAME_LENGTH
call CopyBytes
call TerminateExpBarSound
ld de, SFX_HIT_END_OF_EXP_BAR
call PlaySFX
callba 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, TempMonExp + 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
SendOutPkmnText: ; 3f26d
ld a, [wLinkMode]
and a
jr z, .not_linked
ld hl, JumpText_GoPkmn ; 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 Pkmn, the game prints a different text
ld hl, EnemyMonHP
ld a, [hli]
or [hl]
ld hl, JumpText_GoPkmn
jr z, .skip_to_textbox
; compute enemy helth remaining as a percentage
xor a
ld [hMultiplicand + 0], a
ld hl, EnemyMonHP
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, EnemyMonMaxHP
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_GoPkmn
cp 70
jr nc, .skip_to_textbox
ld hl, JumpText_DoItPkmn
cp 40
jr nc, .skip_to_textbox
ld hl, JumpText_GoForItPkmn
cp 10
jr nc, .skip_to_textbox
ld hl, JumpText_YourFoesWeakGetmPkmn
.skip_to_textbox
jp BattleTextBox
; 3f2d1
JumpText_GoPkmn: ; 3f2d1
text_jump Text_GoPkmn
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2d6
JumpText_DoItPkmn: ; 3f2d8
text_jump Text_DoItPkmn
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2dd
JumpText_GoForItPkmn: ; 3f2df
text_jump Text_GoForItPkmn
start_asm
jr Function_TextJump_BattleMonNick01
; 3f2e4
JumpText_YourFoesWeakGetmPkmn: ; 3f2e6
text_jump Text_YourFoesWeakGetmPkmn
start_asm
Function_TextJump_BattleMonNick01: ; 3f2eb
ld hl, TextJump_BattleMonNick01
ret
; 3f2ef
TextJump_BattleMonNick01: ; 3f2ef
text_jump Text_BattleMonNick01
db "@"
; 3f2f4
WithdrawPkmnText: ; 3f2f4
ld hl, .WithdrawPkmnText
jp BattleTextBox
.WithdrawPkmnText:
text_jump Text_BattleMonNickComma
start_asm
; Print text to withdraw Pkmn
; depending on HP the message is different
push de
push bc
ld hl, EnemyMonHP + 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, EnemyMonMaxHP
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
UnusedFunction_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
HandleSafariAngerEatingStatus: ; unreferenced
ld hl, wSafariMonEating
ld a, [hl]
and a
jr z, .angry
dec [hl]
ld hl, BattleText_WildPkmnIsEating
jr .finish
.angry
dec hl ; wSafariMonAngerCount
ld a, [hl]
and a
ret z
dec [hl]
ld hl, BattleText_WildPkmnIsAngry
jr nz, .finish
push hl
ld a, [EnemyMonSpecies]
ld [CurSpecies], a
call GetBaseData
ld a, [BaseCatchRate]
ld [EnemyMonCatchRate], 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
callab 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
callab 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
GetMonBackpic: ; 3f43d
ld a, [PlayerSubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
ld hl, BattleAnimCmd_RaiseSub
jr nz, GetBackpic_DoAnim ; substitute
DropPlayerSub: ; 3f447
ld a, [wPlayerMinimized]
and a
ld hl, BattleAnimCmd_MinimizeOpp
jr nz, GetBackpic_DoAnim
ld a, [CurPartySpecies]
push af
ld a, [BattleMonSpecies]
ld [CurPartySpecies], a
ld hl, BattleMonDVs
predef GetUnownLetter
ld de, VTiles2 tile $31
predef GetBackpic
pop af
ld [CurPartySpecies], a
ret
; 3f46f
GetBackpic_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
GetMonFrontpic: ; 3f47c
ld a, [EnemySubStatus4]
bit SUBSTATUS_SUBSTITUTE, a
ld hl, BattleAnimCmd_RaiseSub
jr nz, GetFrontpic_DoAnim
DropEnemySub: ; 3f486
ld a, [wEnemyMinimized]
and a
ld hl, BattleAnimCmd_MinimizeOpp
jr nz, GetFrontpic_DoAnim
ld a, [CurPartySpecies]
push af
ld a, [EnemyMonSpecies]
ld [CurSpecies], a
ld [CurPartySpecies], a
call GetBaseData
ld hl, EnemyMonDVs
predef GetUnownLetter
ld de, VTiles2
predef FrontpicPredef
pop af
ld [CurPartySpecies], a
ret
; 3f4b4
GetFrontpic_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, [PartyCount]
and a
ret z
ld a, [TimeOfDayPal]
push af
call BattleIntro
call DoBattle
call ExitBattle
pop af
ld [TimeOfDayPal], a
scf
ret
; 3f4d9
_DoBattle: ; 3f4d9
; unreferenced
call DoBattle
ret
; 3f4dd
BattleIntro: ; 3f4dd
callba TrainerRankings_Battles ; mobile
call LoadTrainerOrWildMonPic
xor a
ld [TempBattleMonSpecies], a
ld [wd0d2], a
xor a
ld [hMapAnims], a
callba PlayBattleMusic
callba ShowLinkBattleParticipants
callba FindFirstAliveMonAndStartBattle
call DisableSpriteUpdates
callba ClearBattleRAM
call InitEnemy
call BackUpVBGMap2
ld b, SCGB_BATTLE_GRAYSCALE
call GetSGBLayout
ld hl, rLCDC
res 6, [hl]
call InitBattleDisplay
call BattleStartMessage
ld hl, rLCDC
set 6, [hl]
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, [OtherTrainerClass]
and a
jr nz, .Trainer
ld a, [TempWildMonSpecies]
ld [CurPartySpecies], a
.Trainer:
ld [TempEnemyMonSpecies], a
ret
; 3f55e
InitEnemy: ; 3f55e
ld a, [OtherTrainerClass]
and a
jp nz, InitEnemyTrainer ; trainer
jp InitEnemyWildmon ; wild
; 3f568
BackUpVBGMap2: ; 3f568
ld a, [rSVBK]
push af
ld a, $6 ; 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(BackUpVBGMap2), $40
call Request2bpp
pop af
ld [rVBK], a
pop af
ld [rSVBK], a
ret
; 3f594
InitEnemyTrainer: ; 3f594
ld [TrainerClass], a
callba TrainerRankings_TrainerBattles
xor a
ld [TempEnemyMonSpecies], a
callab GetTrainerAttributes
callab ReadTrainerParty
ld a, [TrainerClass]
cp RIVAL1
jr nz, .ok
xor a
ld [OTPartyMon1Item], a
.ok
ld de, VTiles2
callab GetTrainerPic
xor a
ld [hGraphicStartTile], a
dec a
ld [wEnemyItemState], a
hlcoord 12, 0
lb bc, 7, 7
predef PlaceGraphic
ld a, -1
ld [CurOTMon], a
ld a, TRAINER_BATTLE
ld [wBattleMode], a
call IsJohtoGymLeader
jr nc, .done
xor a
ld [CurPartyMon], a
ld a, [PartyCount]
ld b, a
.partyloop
push bc
ld a, MON_HP
call GetPartyParamLocation
ld a, [hli]
or [hl]
jr z, .skipfaintedmon
ld c, HAPPINESS_GYMBATTLE
callab ChangeHappiness
.skipfaintedmon
pop bc
dec b
jr z, .done
ld hl, CurPartyMon
inc [hl]
jr .partyloop
.done
ret
; 3f607
InitEnemyWildmon: ; 3f607
ld a, WILD_BATTLE
ld [wBattleMode], a
callba TrainerRankings_WildBattles
call LoadEnemyMon
ld hl, EnemyMonMoves
ld de, wWildMonMoves
ld bc, NUM_MOVES
call CopyBytes
ld hl, EnemyMonPP
ld de, wWildMonPP
ld bc, NUM_MOVES
call CopyBytes
ld hl, EnemyMonDVs
predef GetUnownLetter
ld a, [CurPartySpecies]
cp UNOWN
jr nz, .skip_unown
ld a, [wFirstUnownSeen]
and a
jr nz, .skip_unown
ld a, [UnownLetter]
ld [wFirstUnownSeen], a
.skip_unown
ld de, VTiles2
predef FrontpicPredef
xor a
ld [TrainerClass], a
ld [hGraphicStartTile], a
hlcoord 12, 0
lb bc, 7, 7
predef PlaceGraphic
ret
; 3f662
Function3f662: ; 3f662
; XXX
ld hl, EnemyMonMoves
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, EnemyMonPP - (EnemyMonMoves + 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, EnemyMonPP - (EnemyMonMoves + 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
callba GivePokerusAndConvertBerries
ret
; 3f6d0
CleanUpBattleRAM: ; 3f6d0
call BattleEnd_HandleRoamMons
xor a
ld [Danger], a
ld [wBattleMode], a
ld [BattleType], a
ld [AttackMissed], a
ld [TempWildMonSpecies], a
ld [OtherTrainerClass], a
ld [wFailedToFlee], a
ld [wNumFleeAttempts], a
ld [wForcedSwitch], a
ld [wPartyMenuCursor], a
ld [wKeyItemsPocketCursor], a
ld [wItemsPocketCursor], a
ld [wd0d2], a
ld [CurMoveNum], a
ld [wBallsPocketCursor], a
ld [wLastPocket], a
ld [wMenuScrollPosition], a
ld [wKeyItemsPocketScrollPosition], a
ld [wItemsPocketScrollPosition], a
ld [wBallsPocketScrollPosition], a
ld hl, PlayerSubStatus1
ld b, EnemyFuryCutterCount - PlayerSubStatus1
.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, Money + 2
call AddBattleMoneyToAccount
ld hl, BattleText_PlayerPickedUpPayDayMoney
call StdBattleTextBox
ld a, [InBattleTowerBattle]
bit 0, a
ret z
call ClearTileMap
call ClearBGPalettes
ret
; 3f759
ShowLinkBattleParticipantsAfterEnd: ; 3f759
callba TrainerRankings_LinkBattles
callba BackupMobileEventIndex
ld a, [CurOTMon]
ld hl, OTPartyMon1Status
call GetPartyLocation
ld a, [EnemyMonStatus]
ld [hl], a
call ClearTileMap
callba _ShowLinkBattleParticipants
ret
; 3f77c
DisplayLinkBattleResult: ; 3f77c
callba CheckMobileBattleError
jp c, .Mobile_InvalidBattle
call IsMobileBattle2
jr nz, .proceed
ld hl, wcd2a
bit 4, [hl]
jr z, .proceed
callba DetermineLinkBattleResult
.proceed
ld a, [wBattleResult]
and $f
cp $1
jr c, .victory
jr z, .loss
callba TrainerRankings_ColosseumDraws
ld de, .Draw
jr .store_result
.victory
callba TrainerRankings_ColosseumWins
ld de, .Win
jr .store_result
.loss
callba TrainerRankings_ColosseumLosses
ld de, .Lose
jr .store_result
.store_result
hlcoord 6, 8
call PlaceString
callba 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, AttrMap
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, [BattleType]
cp BATTLETYPE_ROAMING
jr nz, .not_roaming
ld a, [wBattleResult]
and $f
jr z, .caught_or_defeated_roam_mon
call GetRoamMonHP
ld a, [EnemyMonHP + 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
callab UpdateRoamMons
ret
; 3f9d1
GetRoamMonMapGroup: ; 3f9d1
ld a, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
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, [TempEnemyMonSpecies]
ld hl, wRoamMon1Species
cp [hl]
ret z
ld hl, wRoamMon2Species
cp [hl]
ret z
ld hl, wRoamMon3Species
ret
; 3fa42
AddLastMobileBattleToLinkRecord: ; 3fa42
ld hl, OTPlayerID
ld de, StringBuffer1
ld bc, 2
call CopyBytes
ld hl, OTPlayerName
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, StringBuffer1
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, StringBuffer1
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 9999 / $100
ret c
ld a, [hl]
cp 9999 % $100
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
callba 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
callba 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, $6
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, [BattleType]
cp BATTLETYPE_TUTORIAL
jr z, .Decompress
; What gender are we?
ld a, [wPlayerSpriteSetupFlags]
bit 2, a ; transformed to male
jr nz, .Chris
ld a, [PlayerGender]
bit 0, a
jr z, .Chris
; It's a girl.
callba GetKrisBackpic
ret
.Chris:
; It's a boy.
ld b, BANK(ChrisBackpic)
ld hl, ChrisBackpic
.Decompress:
ld de, VTiles2 tile $31
ld c, $31
predef DecompressPredef
ret
; 3fc30
CopyBackpic: ; 3fc30
ld a, [rSVBK]
push af
ld a, $6
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, Sprites
xor a
ld [hMapObjectIndexBuffer], a
ld b, $6
ld e, 21 * 8
.outer_loop
ld c, $3
ld d, 8 * 8
.inner_loop
ld [hl], d
inc hl
ld [hl], e
inc hl
ld a, [hMapObjectIndexBuffer]
ld [hli], a
inc a
ld [hMapObjectIndexBuffer], a
ld a, $1
ld [hli], a
ld a, d
add $8
ld d, a
dec c
jr nz, .inner_loop
ld a, [hMapObjectIndexBuffer]
add $3
ld [hMapObjectIndexBuffer], a
ld a, e
add $8
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
callba 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
callba CheckSleepingTreeMon
jr c, .skip_cry
callba 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 [CryTracks], a
ld a, [TempEnemyMonSpecies]
call PlayStereoCry
.skip_cry
ld a, [BattleType]
cp BATTLETYPE_FISH
jr nz, .NotFishing
callba TrainerRankings_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
callba BattleStart_TrainerHuds
pop hl
call StdBattleTextBox
call IsMobileBattle2
ret nz
ld c, $2 ; start
callba Mobile_PrintOpponentBattleMessage
ret
; 3fd26