; Core components of the battle engine.
BattleCore:
DoBattle:
	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, [wBattleType]
	cp BATTLETYPE_DEBUG
	jp z, .tutorial_debug
	xor a
	ld [wCurPartyMon], a
.loop2
	call CheckIfCurPartyMonIsStillAlive
	jr nz, .alive2
	ld hl, wCurPartyMon
	inc [hl]
	jr .loop2

.alive2
	ld a, [CurBattleMon]
	ld [LastPlayerMon], a
	ld a, [wCurPartyMon]
	ld [CurBattleMon], a
	inc a
	ld hl, wPartySpecies - 1
	ld c, a
	ld b, 0
	add hl, bc
	ld a, [hl]
	ld [wCurPartySpecies], a
	ld [TempBattleMonSpecies], a

	CheckEngine ENGINE_POKEMON_MODE
	jr nz, .skipSlideOut
	hlcoord 1, 5
	ld a, 9
	call SlideBattlePicOut
	call LoadTileMapToTempTileMap
.skipSlideOut
	call InitBattleMon
	call ResetBattleParticipants
	call ResetPlayerStatLevels
	call SendOutPkmnText
	call NewBattleMonStatus
	call BreakAttraction
	CheckEngine ENGINE_POKEMON_MODE
	jr z, .regularSendOut
	call SendOutPlayerMon_PModeBattleStart
	jr .continue
.regularSendOut
	call SendOutPlayerMon
.continue
	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

WildFled_EnemyFled_LinkBattleCanceled:
	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

.print_text
	call StdBattleTextBox
	call StopDangerSound

	ld de, SFX_RUN
	call PlaySFX

	call SetPlayerTurn
	ld a, 1
	ld [BattleEnded], a
	ret

BattleTurn:
.loop
	xor a
	ld [wPlayerIsSwitching], a
	ld [wEnemyIsSwitching], a
	ld [wBattleHasJustStarted], a
	ld [wPlayerJustGotFrozen], a
	ld [wEnemyJustGotFrozen], a
	dec a
	ld [wLastBallShakes], a
	call ResetDamage

	call AbilityOnMonEntrance
	call HandleBerserkGene
	call UpdateBattleMonInParty
	callba AIChooseMove

	call CheckPlayerLockedIn
	jr c, .skip_iteration
.loop1
	call BattleMenu
	ret c
	ld a, [BattleEnded]
	and a
	ret nz
	ld a, [wForcedSwitch] ; roared/whirlwinded/teleported
	and a
	ret nz
.skip_iteration
	call ParsePlayerAction
	jr nz, .loop1

	call EnemyTriesToFlee
	ret c

	ld a, [wBattleTurns]
	cp 200
	jr nc, .too_long
	inc a
	ld [wBattleTurns], a
.too_long
	call DetermineMoveOrder
	jr c, .player_first
	call Battle_EnemyFirst
	jr .proceed
.player_first
	call Battle_PlayerFirst
.proceed

	ld a, [wForcedSwitch]
	and a
	ret nz

	ld a, [BattleEnded]
	and a
	ret nz
	call HandleEndTurnEffects
	ld a, [BattleEnded]
	and a
	jp z, .loop
	ret

HandleEndTurnEffects:
	ld a, [wBattleHasJustStarted]
	and a
	ret nz
	call CheckFaint
	ret c
	call EndTurn_ResidualDamage
	call CheckFaint
	ret c
	call EndTurn_FutureSight
	call CheckFaint
	ret c
	call HandleWeather
	call CheckFaint
	ret c
	call EndTurn_Wrap
	call CheckFaint
	ret c
	call EndTurn_PerishSong

	call EndTurn_Leftovers
	call EndTurn_Mysteryberry
	call EndTurn_Defrost
	call EndTurn_Safeguard
	call EndTurn_Screens
	call EndTurn_StatBoostingHeldItems
	call EndTurn_HealingItems
	call EndTurn_Abilities
	call UpdateBattleMonInParty
	call UpdateEnemyMonInParty
	call LoadTileMapToTempTileMap
	jp EndTurn_Encore

CheckFaint:
	call SetPlayerTurn
	call CheckSpeed
	jr nz, CheckFaint_EnemyThenPlayer
CheckFaint_PlayerThenEnemy:
	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

CheckFaint_EnemyThenPlayer:
	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

HandleBerserkGene:
	ld a, [hLinkPlayerNumber]
	cp $1
	jr z, .reverse

	call .player
	jr .enemy

.reverse
	call .enemy
.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
.go
	push de
	push bc
	call GetUserItem ; this is in ROM0
	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
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_OWN_TEMPO
	jr z, .protected
	set SUBSTATUS_CONFUSED, [hl]
.protected
	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
	callba BattleCommand_StatUpMessage
	pop af
	bit SUBSTATUS_CONFUSED, a
	ret nz
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_OWN_TEMPO
	ret z
	xor a
	ld [wNumHits], a
	ld de, ANIM_CONFUSED
	call Call_PlayBattleAnim_OnlyIfVisible
	call SwitchTurn
	ld hl, BecameConfusedText
	jp StdBattleTextBox

EnemyTriesToFlee:
	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

DetermineMoveOrder:
	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
	and 1
	jp z, .player_first
	jp .enemy_first

.player_2
	call BattleRandom
	and 1
	jp z, .enemy_first
	jp .player_first

.switch
	callba AI_Switch
	jp .enemy_first

.use_move
	ld a, [wPlayerSubStatus2]
	bit SUBSTATUS_GUARDING, a
	jp nz, .player_first
	ld a, [wPlayerAction]
	and a
	jp nz, .player_first
	call CompareMovePriority
	jp c, .player_first ; player goes first
	jp nz, .enemy_first

.equal_priority
	call CheckSpeedWithQuickClaw
	jr nz, .enemy_first
.player_first
	scf
	ret

.enemy_first
	and a
	ret

CheckSpeedWithQuickClaw:
; Does CheckSpeed, but Quick Claw overrides speed
	ld a, [hBattleTurn]
	push af

	; Figure out what quick claw message if applicable to give first
	call SetPlayerTurn
	call CheckSpeed
	call nz, SetEnemyTurn

	ld d, 0
	call .do_it
	call SwitchTurn
	call .do_it
	pop af
	ld [hBattleTurn], a
	ld a, d ; +1: player, -1: enemy, 0: both/neither
	and a
	jr z, CheckSpeed
	dec a
	ret
.do_it
	push de
	call GetUserItem
	pop de
	ld a, b
	cp HELD_QUICK_CLAW
	ret nz
	call BattleRandom
	cp c
	ret nc
	push de
	call SwitchTurn
	call ItemRecoveryAnim
	call SwitchTurn
	call GetUserItem
	ld a, [hl]
	ld [wNamedObjectIndexBuffer], a
	call GetItemName
	ld hl, BattleText_UserItemLetItMoveFirst
	call StdBattleTextBox
	pop de
	inc d
	ld a, [hBattleTurn]
	and a
	ret z
	dec d
	dec d
	ret

CheckSpeed:
; Compares speed stat, applying items and stat changes, and see who ends up on top.
; Returns z if player goes first, nz if enemy goes first, randomly on a tie (which also
; sets carry). If Quick Claw checks are relevant, use CheckSpeedWithQuickClaw.
	; Stall overrides everything else here
	ld b, 0
	call GetPlayerAbility
	cp ABILITY_STALL
	jr nz, .no_player_stall
	inc b
.no_player_stall
	call GetEnemyAbility
	cp ABILITY_STALL
	jr nz, .no_enemy_stall
	dec b
.no_enemy_stall
	ld a, b
	dec b
	jr z, .enemy_first
	inc a
	jr z, .player_first

	; Now check in general
	ld a, [hBattleTurn]
	push af
	call SetPlayerTurn
	call GetSpeed
	push bc
	call SetEnemyTurn
	call GetSpeed
	pop de
	pop af

	; restore turn
	ld [hBattleTurn], a

	; bc is enemy speed, de player
	ld a, b
	cp d
	jr c, .player_first
	jr nz, .enemy_first
	ld a, c
	cp e
	jr c, .player_first
	jr nz, .enemy_first

	; Speed is equal, so randomize. Account for linking.
	ld a, [hLinkPlayerNumber]
	cp 2
	ld b, 0
	jr z, .secondary_player
	ld b, 1
.secondary_player
	call BattleRandom
	and 1
	xor b
	scf
	ret
.player_first
	xor a
	ret
.enemy_first
	or 1
	ret

GetSpeed:
; Set bc to speed. Stat changes and paralysis has already been taken care of.
; This can be called if an user is fainted, by design and intentionally.
	push hl
	ld a, [hBattleTurn]
	and a
	ld hl, BattleMonSpeed
	ld de, BattleMonItem
	jr z, .got_speed
	ld hl, EnemyMonSpeed
	ld de, EnemyMonItem
.got_speed
	ld a, [hli]
	ld b, a
	ld c, [hl]

	; Apply Unburden
	ld a, BATTLE_VARS_SUBSTATUS2
	call GetBattleVar
	bit SUBSTATUS_UNBURDEN, a
	jr z, .unburden_done
	sla b
	rl c
.unburden_done
	ld a, [de]
	cp MACHO_BRACE
	jr nz, .notMachoBrace
	srl b
	rr c
.notMachoBrace
	
	call GetUserAbility_IgnoreMoldBreaker
	ld hl, .Abilities
	ld e, 3
	push bc
	call IsInArray
	pop bc
	call c, CallLocalPointer_AfterIsInArray
	pop hl
	ret

.Abilities
	dbw ABILITY_SWIFT_SWIM, .SwiftSwim
	dbw ABILITY_CHLOROPHYLL, .Chlorophyll
	dbw ABILITY_QUICK_FEET, .QuickFeet
	db -1

.SwiftSwim
	ld h, WEATHER_RAIN
	jr .WeatherAbility
.Chlorophyll
	ld h, WEATHER_SUN
.WeatherAbility
	call GetWeatherAfterAbilities
	cp h
	ret nz
	sla b
	rl c
	ret

.QuickFeet
	ld a, BATTLE_VARS_STATUS
	call GetBattleVar
	and a
	ret z
	ld h, b
	ld l, c
	srl b
	rr c
	add hl, bc
	ld b, h
	ld c, l
	ret

CheckPlayerLockedIn:
	ld a, [wPlayerSubStatus4]
	bit SUBSTATUS_RECHARGE, a
	jr nz, .quit

	ld hl, wEnemySubStatus3
	res SUBSTATUS_FLINCHED, [hl]
	ld hl, wPlayerSubStatus3
	res SUBSTATUS_FLINCHED, [hl]
	ld a, [hld]
	and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE
	jr nz, .quit
	ld a, [hld]
	bit SUBSTATUS_GUARDING, a
	jr nz, .quit
	bit SUBSTATUS_ROLLOUT, [hl]
	jr nz, .quit

	and a
	ret

.quit
	scf
	ret

ParsePlayerAction:
	call CheckPlayerLockedIn
	jp c, .locked_in
	ld hl, wPlayerSubStatus5
	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, .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
	callba 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, wPlayerSubStatus4
	res SUBSTATUS_RAGE, [hl]

.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

.locked_in
	xor a
	ld [PlayerFuryCutterCount], a
	ld [PlayerProtectCount], a
	ld hl, wPlayerSubStatus4
	res SUBSTATUS_RAGE, [hl]

.continue_protect
	call ParseEnemyAction
	xor a
	ret

.reset_rage
	xor a
	ld [PlayerFuryCutterCount], a
	ld [PlayerProtectCount], a
	ld hl, wPlayerSubStatus4
	res SUBSTATUS_RAGE, [hl]
	ret

EndTurn_Encore:
	call CheckSpeed
	jr z, .player_first

	call .do_enemy
.do_player
	ld hl, wPlayerSubStatus5
	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, wPlayerSubStatus5
	res SUBSTATUS_ENCORED, [hl]
	call SetEnemyTurn
	ld hl, BattleText_TargetsEncoreEnded
	jp StdBattleTextBox

.player_first
	call .do_player
.do_enemy
	ld hl, wEnemySubStatus5
	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, wEnemySubStatus5
	res SUBSTATUS_ENCORED, [hl]
	call SetPlayerTurn
	ld hl, BattleText_TargetsEncoreEnded
	jp StdBattleTextBox

TryEnemyFlee:
	ld a, [wBattleMode]
	dec a
	and a
	ret nz

	ld a, [wPlayerSubStatus5]
	bit SUBSTATUS_CANT_RUN, a
	ret nz

	ld a, [wEnemySubStatus2]
	bit SUBSTATUS_FINAL_CHANCE, a
	ret nz

	ld a, [wEnemyWrapCount]
	and a
	ret nz

	ld a, [EnemyMonStatus]
	and 1 << FRZ | SLP
	ret nz

	call CheckPlayerArenaTrap
	ccf
	ret nc

	CheckEngine ENGINE_PARK_MINIGAME
	jr nz, .check_park_minigame_flee

	ld a, [TempEnemyMonSpecies]
	ld hl, .flee_mon_list
	ld e, 2
	call IsInArray
	ret nc

	inc hl
	call RandomPercentage ; no need for BattleRandom since this is a wild battle
	cp [hl]
	ret ;carry if the mon flees

.check_park_minigame_flee
	ld a, [wLastBallShakes]
	sub -5
	ret nc ; if the subtraction doesn't carry (i.e., the addition would have), [wLastBallShakes] wasn't positive to begin with, meaning no ball was used
	ld hl, hMultiplier
	ld [hld], a
	ld a, [EnemyMonCatchRate]
	ld [hld], a
	ld [hl], 3
	push hl
	predef Multiply
	pop hl
	call Random ; no need for BattleRandom since this is a wild battle
	cp [hl]
	ret nz
	inc hl
	call Random
	cp [hl]
	ret

.flee_mon_list
	;  species,     %
	db MAGNEMITE,   5
	db TANGELA,     5
	db -1

CompareMovePriority:
; Compare the priority of the player and enemy's moves.
; Return carry if the player goes first, or z if they match.
	ld a, [PlayerAbility]
	cp ABILITY_STALL
	jr z, .PlayerStall
	ld a, [EnemyAbility]
	cp ABILITY_STALL
	jr z, .EnemyStall
.ComparePriorities:
	ld a, [CurPlayerMove]
	call GetMovePriority
	ld b, a
	push bc
	ld a, [CurEnemyMove]
	call GetMovePriority
	pop bc
	cp b
	ret

.PlayerStall
	ld a, [EnemyAbility]
	cp ABILITY_STALL
	jr z, .ComparePriorities
	; Only player has Stall
	call .ComparePriorities
	ret nz
	inc a
	ret

.EnemyStall
	; Only enemy has Stall
	call .ComparePriorities
	ret nz
	scf
	ret

GetMovePriority:
; Return the priority (0-3) of move a.

	ld b, a

	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

MoveEffectPriorities:
	db EFFECT_PROTECT,      3
	db EFFECT_ENDURE,       3
	db EFFECT_PRIORITY_HIT, 2
	db EFFECT_WHIRLWIND,    0
	db EFFECT_COUNTER,      0
	; db EFFECT_MIRROR_COAT,  0
	db -1

GetMoveEffect:
	ld a, b
	dec a
	ld hl, Moves + MOVE_EFFECT
	ld bc, MOVE_LENGTH
	rst AddNTimes
	ld a, BANK(Moves)
	call GetFarByte
	ld b, a
	ret

Battle_EnemyFirst:
	call LoadTileMapToTempTileMap
	call TryEnemyFlee
	jp c, WildFled_EnemyFled_LinkBattleCanceled
	call SetEnemyTurn
	ld a, $1
	ld [wEnemyGoesFirst], a
	callba AI_SwitchOrTryItem
	jr c, .switch_item
	call EnemyTurn_EndOpponentProtectEndureDestinyBondGuarding
	ld a, [wForcedSwitch]
	and a
	ret nz
	call HasPlayerFainted
	jp z, HandlePlayerMonFaint
	call HasEnemyFainted
	jp z, HandleEnemyMonFaint

.switch_item
	call RefreshBattleHuds
	call PlayerTurn_EndOpponentProtectEndureDestinyBondGuarding
	ld a, [wForcedSwitch]
	and a
	ret nz
	call HasEnemyFainted
	jp z, HandleEnemyMonFaint
	call HasPlayerFainted
	jp z, HandlePlayerMonFaint
	call RefreshBattleHuds
	xor a
	ld [wPlayerAction], a
	ret

Battle_PlayerFirst:
	xor a
	ld [wEnemyGoesFirst], a
	call SetEnemyTurn
	callba AI_SwitchOrTryItem
	push af
	call PlayerTurn_EndOpponentProtectEndureDestinyBondGuarding
	pop bc
	ld a, [wForcedSwitch]
	and a
	ret nz
	call HasEnemyFainted
	jp z, HandleEnemyMonFaint
	call HasPlayerFainted
	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_EndOpponentProtectEndureDestinyBondGuarding
	ld a, [wForcedSwitch]
	and a
	ret nz
	call HasPlayerFainted
	jp z, HandlePlayerMonFaint
	call HasEnemyFainted
	jp z, HandleEnemyMonFaint

.switched_or_used_item
	call RefreshBattleHuds
	xor a
	ld [wPlayerAction], a
	ret

PlayerTurn_EndOpponentProtectEndureDestinyBondGuarding:
	call SetPlayerTurn
	call EndUserDestinyBond
	callba DoPlayerTurn
	jr EndOpponentProtectEndureDestinyBondGuarding

EnemyTurn_EndOpponentProtectEndureDestinyBondGuarding:
	call SetEnemyTurn
	call EndUserDestinyBond
	callba DoEnemyTurn

EndOpponentProtectEndureDestinyBondGuarding:
	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]
	ld a, BATTLE_VARS_SUBSTATUS2_OPP
	call GetBattleVarAddr
	res SUBSTATUS_GUARDING, [hl]
	ret

EndUserDestinyBond:
	ld a, BATTLE_VARS_SUBSTATUS5
	call GetBattleVarAddr
	res SUBSTATUS_DESTINY_BOND, [hl]
	ret

HasUserFainted:
	ld a, [hBattleTurn]
	and a
	jr z, HasPlayerFainted
HasEnemyFainted:
	ld hl, EnemyMonHP
	jr CheckIfHPIsZero

HasPlayerFainted:
	ld hl, BattleMonHP
	; fallthrough

CheckIfHPIsZero:
	ld a, [hli]
	or [hl]
	ret

SetFastestTurn:
	call CheckSpeed
	jp nz, SetEnemyTurn
	jp SetPlayerTurn

EndTurn_ResidualDamage:
; Return z if the user fainted before
; or as a result of residual damage.
; For Sandstorm damage, see HandleWeather.
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.do_it
	call HasUserFainted
	ret z

	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_SHED_SKIN
	jr nz, .skip_shed_skin

	ld a, BATTLE_VARS_STATUS
	call GetBattleVarAddr
	and a
	jp z, .did_psn_brn

	call BattleRandom
	cp 30 percent
	jr nc, .skip_shed_skin

	ld [hl], 0
	call UpdateUserInParty
	call UpdateBattleHUDs
	ld hl, ShedSkinText
	call StdBattleTextBox
	jp .did_psn_brn

.skip_shed_skin

	ld a, BATTLE_VARS_STATUS
	call GetBattleVar
	and 1 << PSN | 1 << BRN
	jp z, .did_psn_brn

	ld hl, HurtByPoisonText
	ld de, ANIM_PSN
	and 1 << BRN
	jr nz, .check_brn
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_POISON_HEAL
	jr nz, .got_anim
	ld hl, PoisonHealText
	ld de, NO_MOVE
	jr .got_anim

.check_brn
	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 a, BATTLE_VARS_STATUS
	call GetBattleVar
	bit BRN, a
	jr nz, .burn
	ld de, PlayerToxicCount
	ld a, [hBattleTurn]
	and a
	jr z, .check_toxic
	ld de, EnemyToxicCount
.check_toxic

	ld a, BATTLE_VARS_SEMISTATUS
	call GetBattleVar
	bit SEMISTATUS_TOXIC, a
	jr z, .psn_check_poison_heal
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_POISON_HEAL
	push af
	ld a, [de]
	inc a
	ld [de], a
	pop af
	jr z, .heal

	srl b
	rr c
	ld a, b
	or c
	jr nz, .okay_toxic
	inc c
.okay_toxic
	ld a, [de]
	ld hl, 0
	rst AddNTimes
	ld b, h
	ld c, l
	jr .deal_damage

.psn_check_poison_heal
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_POISON_HEAL
	jr z, .heal
	jr .deal_damage

.burn
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_HEATPROOF
	jr nz, .deal_damage
	srl b
	rr c
	ld a, b
	or c
	jr nz, .deal_damage
	inc c
.deal_damage
	call SubtractHPFromUser
	jr .did_psn_brn

.heal
	call RestoreUserHP
.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 SwitchTurn
	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 SwitchTurn

	call GetEighthMaxHP
	call SubtractHPFromUser
	ld a, $1
	ld [hBGMapMode], a
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_LIQUID_OOZE
	ld de, RestoreOpponentHP
	ld hl, LeechSeedSapsText
	jr nz, .print
	ld de, SubtractHPFromTarget
	ld hl, LiquidOozeHurtsText
.print
	push hl
	call _de_
	pop hl
	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

EndTurn_PerishSong:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.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
	push hl
	ld a, BATTLE_VARS_SUBSTATUS2
	call GetBattleVar
	bit SUBSTATUS_FINAL_CHANCE, a
	jr z, .pop
	pop hl
	ld hl, FinalChanceText
	jr .print

.pop
	pop hl
.print
	call StdBattleTextBox
	pop af
	jr z, .kill_mon

	ld a, BATTLE_VARS_SUBSTATUS2
	call GetBattleVar
	bit SUBSTATUS_FINAL_CHANCE, a
	ret z

	; Final Chance healing animation
	ld de, FINAL_CHANCE
	ld a, 1
	ld [wBattleAnimParam], a
	xor a
	ld [wNumHits], a
	call Call_PlayBattleAnim_OnlyIfVisible

	ld a, BATTLE_VARS_SUBSTATUS3
	call GetBattleVarAddr
	res SUBSTATUS_CONFUSED, [hl]
	ld a, BATTLE_VARS_SEMISTATUS
	call GetBattleVarAddr
	res SEMISTATUS_TOXIC, [hl]
	ld a, [hBattleTurn]
	and a
	ld hl, BattleMonHP
	ld de, BattleMonStatus
	jr z, .okay
	ld hl, EnemyMonHP
	ld de, EnemyMonStatus
.okay
	xor a
	ld [de], a
	ld d, h
	ld e, l
	ld a, [hli]
	ld [wCurHPAnimOldHP + 1], a
	ld a, [hli]
	ld [wCurHPAnimOldHP], a
	ld a, [hli]
	ld [de], a
	inc de
	ld [wCurHPAnimMaxHP + 1], a
	ld [wCurHPAnimNewHP + 1], a
	ld a, [hl]
	ld [de], a
	ld [wCurHPAnimMaxHP], a
	ld [wCurHPAnimNewHP], a
	call UpdateHPBarBattleHuds
	call UpdateUserInParty
	ld hl, FinalChanceHealedText
	jp StdBattleTextBox

.kill_mon
	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

EndTurn_Wrap:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.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 SwitchTurn
	xor a
	ld [wNumHits], a
	ld [FXAnimIDHi], a
	predef PlayBattleAnim
	call SwitchTurn

.skip_anim
	call GetEighthMaxHP
	call SubtractHPFromUser
	ld hl, BattleText_UsersHurtByStringBuffer1
	jr .print_text

.release_from_bounds
	ld hl, BattleText_UserWasReleasedFromStringBuffer1

.print_text
	jp StdBattleTextBox

EndTurn_Leftovers:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.do_it
	call GetUserItem ; this is in ROM0
	ld a, b
	cp HELD_LEFTOVERS
	ret nz
	ld a, [hl]
	ld [wd265], a
	call GetItemName

	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 SwitchTurn
	call RestoreOpponentHP
	ld hl, BattleText_TargetRecoveredWithItem
	call StdBattleTextBox
	jp SwitchTurn

EndTurn_Mysteryberry:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.do_it
	call GetUserItem ; this is in ROM0
	ld a, b
	cp HELD_RESTORE_PP
	ret nz
	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
	ret z
	ld a, [de]
	and $3f
	jr z, .restore
	inc hl
	inc de
	inc c
	ld a, c
	cp NUM_MOVES
	jr nz, .loop
	ret

.restore
	; lousy hack
	ld a, [hl]
	ld b, 5
	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, [wPlayerSubStatus5]
	jr z, .check_transform
	ld a, [wEnemySubStatus5]
.check_transform
	bit SUBSTATUS_TRANSFORMED, a
	jr nz, .skip_checks
	ld a, [de]
	add b
	ld [de], a
.skip_checks
	call GetUserItem ; this is in ROM0
	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 SwitchTurn
	call ItemRecoveryAnim
	call SwitchTurn
	ld hl, BattleText_UserRecoveredPPUsing
	jp StdBattleTextBox

EndTurn_FutureSight:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.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

	callba UpdateMoveData
	xor a
	ld [AttackMissed], a
	ld [AlreadyDisobeyed], a
	ld a, 10
	ld [TypeModifier], a
	callba DoMove
	call ResetDamage

	ld a, BATTLE_VARS_MOVE
	call GetBattleVarAddr
	pop af
	ld [hl], a

	call UpdateBattleMonInParty
	jp UpdateEnemyMonInParty

EndTurn_Defrost:
	call CheckSpeed
	jr z, .player_first
	call .do_enemy_turn
.do_player_turn
	ld a, [BattleMonStatus]
	bit FRZ, a
	ret z

	ld a, [wPlayerJustGotFrozen]
	and a
	ret nz

	ld a, [EnemyAbility]
	cp ABILITY_MOLD_BREAKER
	jr z, .sample_player
	ld a, [PlayerAbility]
	cp ABILITY_MAGMA_ARMOR
	jr z, .succeed_player
.sample_player
	call BattleRandom
	cp 10 percent
	ret nc
.succeed_player
	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

.player_first
	call .do_player_turn
.do_enemy_turn
	ld a, [EnemyMonStatus]
	bit FRZ, a
	ret z
	ld a, [wEnemyJustGotFrozen]
	and a
	ret nz

	ld a, [PlayerAbility]
	cp ABILITY_MOLD_BREAKER
	jr z, .sample_enemy
	ld a, [EnemyAbility]
	cp ABILITY_MAGMA_ARMOR
	jr z, .succeed_enemy
.sample_enemy
	call BattleRandom
	cp 10 percent
	ret nc
.succeed_enemy
	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

EndTurn_Safeguard:
	call CheckSpeed
	jr z, .player_first
	call .CheckEnemy
.CheckPlayer
	ld a, [wPlayerScreens]
	bit SCREENS_SAFEGUARD, a
	ret z
	ld hl, PlayerSafeguardCount
	dec [hl]
	ret nz
	res SCREENS_SAFEGUARD, a
	ld [wPlayerScreens], a
	xor a
	jr .print

.player_first
	call .CheckPlayer
.CheckEnemy
	ld a, [wEnemyScreens]
	bit SCREENS_SAFEGUARD, a
	ret z
	ld hl, EnemySafeguardCount
	dec [hl]
	ret nz
	res SCREENS_SAFEGUARD, a
	ld [wEnemyScreens], a
	ld a, $1

.print
	ld [hBattleTurn], a
	ld hl, BattleText_SafeguardFaded
	jp StdBattleTextBox

EndTurn_Screens:
	call CheckSpeed
	jr z, .player_first
	call .CheckEnemy
.CheckPlayer
	call SetPlayerTurn
	ld de, .Your
	call .Copy
	ld hl, wPlayerScreens
	ld de, PlayerLightScreenCount
	jr .TickScreens

.player_first
	call .CheckPlayer
.CheckEnemy
	call SetEnemyTurn
	ld de, .Enemy
	call .Copy
	ld hl, wEnemyScreens
	ld de, EnemyLightScreenCount

.TickScreens
	bit SCREENS_LIGHT_SCREEN, [hl]
	call nz, .LightScreenTick
	bit SCREENS_REFLECT, [hl]
	ret z
.ReflectTick
	inc de
	ld a, [de]
	dec a
	ld [de], a
	ret nz
	res SCREENS_REFLECT, [hl]
	ld hl, BattleText_PkmnReflectFaded
	jp StdBattleTextBox

.Copy
	ld hl, wStringBuffer1
	jp CopyName2

.Your
	db "Your@"
.Enemy
	db "Enemy@"

.LightScreenTick
	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

HandleWeather:
	call GetWeatherAfterAbilities
	jr nz, .weather_ok

	; Tick down weather as usual but be quiet about the effect fading.
	ld a, [Weather]
	and a
	ret z
	ld hl, WeatherCount
	dec [hl]
	ret nz
	ld [Weather], a
	ret

.weather_ok
	call GetWeatherAfterAbilities
	and a ; cp WEATHER_NONE
	ret z

	ld hl, WeatherCount
	dec [hl]
	jp z, .ended

	ld hl, .WeatherMessages
	call .PrintWeatherMessage

	xor a
	ld [wNumHits], a
	call PlayWeatherAnimation

	; Now handle weather effects
	call SetFastestTurn
	call .effects
	call SwitchTurn

.effects
	call GetWeatherAfterAbilities
	cp WEATHER_SUN
	jp z, DrySkinCheck
	cp WEATHER_RAIN
	jp z, RainDishCheck
	cp WEATHER_SANDSTORM
	jr z, .hail_sandstorm
	cp WEATHER_HAIL
	ret nz
.hail_sandstorm
	ld a, BATTLE_VARS_SUBSTATUS3
	call GetBattleVar
	bit SUBSTATUS_UNDERGROUND, a
	ret nz

	ld a, [Weather]
	cp WEATHER_HAIL
	jr nz, .sandstorm
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_ICE_BODY
	jr nz, .no_ability
	call CheckFullHP
	ret z
	call GetSixteenthMaxHP
	call RestoreUserHP
	ld hl, IceBodyText
	jp StdBattleTextBox

.sandstorm
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_SAND_VEIL
	ret z

.no_ability
	call GetUserItem ; this is in ROM0
	ld a, b
	cp HELD_SAFE_GOGGLES
	ret z

	ld hl, BattleMonType1
	ld a, [hBattleTurn]
	and a
	jr z, .ok
	ld hl, EnemyMonType1
.ok
	ld a, [Weather]
	cp WEATHER_SANDSTORM
	jr z, .sandstorm_types
	ld a, [hli]
	cp ICE
	ret z
	ld a, [hl]
	cp ICE
	ret z
	jr .damage

.sandstorm_types
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_SAND_VEIL
	ret z
	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
.damage
	call SwitchTurn
	xor a
	ld [wNumHits], a
	ld hl, SandstormHitsText
	ld a, [Weather]
	cp WEATHER_SANDSTORM
	jr z, .got_anim
	ld hl, HailHitsText
.got_anim
	push hl

	ld a, 1
	ld [wNumHits], a
	ld a, 10
	ld [TypeModifier], a
	ld de, ANIM_ENEMY_DAMAGE
	ld a, [hBattleTurn]
	and a
	jr z, .animate_damage
	ld de, ANIM_PLAYER_DAMAGE
.animate_damage
	call Call_PlayBattleAnim

	call SwitchTurn
	call GetEighthMaxHP
	call SubtractHPFromUser

	pop hl
	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

.WeatherMessages
	dw BattleText_RainContinuesToFall
	dw BattleText_TheSunlightIsStrong
	dw BattleText_TheSandstormRages
	dw BattleText_HailContinuesToFall
.WeatherEndedMessages
	dw BattleText_TheRainStopped
	dw BattleText_TheSunlightFaded
	dw BattleText_TheSandstormSubsided
	dw BattleText_TheHailStopped

PlayWeatherAnimation:
	call CheckBattleScene
	ret c
	ld a, [Weather]
	dec a
	ld e, a
	ld d, 0
	ld hl, .WeatherAnimations
	add hl, de
	add hl, de
	ld a, [hli]
	ld d, [hl]
	ld e, a
	jp Call_PlayBattleAnim

.WeatherAnimations
	dw RAIN_DANCE
	dw SUNNY_DAY
	dw ANIM_IN_SANDSTORM
	dw ANIM_IN_HAILSTORM

DrySkinCheck:
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_DRY_SKIN
	ret nz
	ld [wd265], a
	call GetAbilityName
	call GetEighthMaxHP
	call SubtractHPFromUser
	ld hl, AbilityHurtText
	jp StdBattleTextBox

RainDishCheck:
	call CheckFullHP
	ret z
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_DRY_SKIN
	jr z, .DrySkinRain
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_RAIN_DISH
	ret nz
	ld [wd265], a
	call GetAbilityName
	call GetSixteenthMaxHP
	call RestoreUserHP
	ld hl, AbilityRestoreHPText
	jp StdBattleTextBox

.DrySkinRain
	ld [wd265], a
	call GetAbilityName
	call GetEighthMaxHP
	call RestoreUserHP
	ld hl, AbilityRestoreHPText
	jp StdBattleTextBox

CheckFullHP:
; Returns z if HP is full
	push bc
	push de
	push hl
	ld a, [hBattleTurn]
	and a
	ld de, BattleMonHP
	ld hl, BattleMonMaxHP
	jr z, .got_hp
	ld de, EnemyMonHP
	ld hl, EnemyMonMaxHP
.got_hp
	ld c, 2
	call StringCmp
	pop hl
	pop de
	pop bc
	ret

SubtractHPFromTarget:
	call SwitchTurn
	push bc
	call GetMaxHP
	pop bc
	call SubtractHP
	call UpdateHPBarBattleHuds
	jp SwitchTurn

SubtractHPFromUser:
; Subtract HP from Pkmn
	call SubtractHP
	jp UpdateHPBarBattleHuds

SubtractHP:
	ld hl, BattleMonHP
	ld a, [hBattleTurn]
	and a
	jr z, .ok
	ld hl, EnemyMonHP
.ok
	inc hl
	ld a, [hl]
	ld [wCurHPAnimOldHP], a
	sub c
	ld [hld], a
	ld [wCurHPAnimNewHP], a
	ld a, [hl]
	ld [wCurHPAnimOldHP + 1], a
	sbc b
	ld [hl], a
	ld [wCurHPAnimNewHP + 1], a
	ret nc

	ld a, [wCurHPAnimOldHP]
	ld c, a
	ld a, [wCurHPAnimOldHP + 1]
	ld b, a
	xor a
	ld [hli], a
	ld [hl], a
	ld [wCurHPAnimNewHP], a
	ld [wCurHPAnimNewHP + 1], a
	ret

GetSixteenthMaxHP:
	call GetQuarterMaxHP
	; quarter result
	srl c
	srl c
	; round up
	ld a, c
	and a
	ret nz
	inc c
	ret

GetEighthMaxHP:
; output: bc
	call GetQuarterMaxHP
; assumes nothing can have 1024 or more hp
; halve result
	srl c
; round up
	ld a, c
	and a
	ret nz
	inc c
	ret

GetThirdMaxHP:
	call GetMaxHP
	ld a, b
	ld [hDividend], a
	ld a, c
	ld [hDividend + 1], a
	ld a, 3
	ld [hDivisor], a
	ld b, 2
	predef Divide
	ld a, [hQuotient + 1]
	ld b, a
	ld a, [hQuotient + 2]
	ld c, a
	or b
	ret nz
	inc c
	ret

GetQuarterMaxHP:
; 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
	ret nz
	inc c
	ret

GetHalfMaxHP:
; output: bc
	call GetMaxHP

; halve result
	srl b
	rr c

; floor = 1
	ld a, c
	or b
	ret nz
	inc c
	ret

GetMaxHP:
; output: bc, wCurHPAnimMaxHP

	ld hl, BattleMonMaxHP
	ld a, [hBattleTurn]
	and a
	jr z, .ok
	ld hl, EnemyMonMaxHP
.ok
	ld a, [hli]
	ld [wCurHPAnimMaxHP + 1], a
	ld b, a

	ld a, [hl]
	ld [wCurHPAnimMaxHP], a
	ld c, a
	ret

CheckUserHasEnoughHP:
	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

RestoreUserHP:
	call SwitchTurn
	call RestoreOpponentHP
	jp SwitchTurn

RestoreOpponentHP:
	ld hl, EnemyMonMaxHP
	ld a, [hBattleTurn]
	and a
	jr z, RestoreHP
	ld hl, BattleMonMaxHP
RestoreHP:
	ld a, [hli]
	ld [wCurHPAnimMaxHP + 1], a
	ld a, [hld]
	ld [wCurHPAnimMaxHP], a
	dec hl
	ld a, [hl]
	ld [wCurHPAnimOldHP], a
	add c
	ld [hld], a
	ld [wCurHPAnimNewHP], a
	ld a, [hl]
	ld [wCurHPAnimOldHP + 1], a
	adc b
	ld [hli], a
	ld [wCurHPAnimNewHP + 1], a

	ld a, [wCurHPAnimMaxHP]
	ld c, a
	ld a, [hld]
	sub c
	ld a, [wCurHPAnimMaxHP + 1]
	ld b, a
	ld a, [hl]
	sbc b
	jr c, .maxed
	ld a, b
	ld [hli], a
	ld [wCurHPAnimNewHP + 1], a
	ld a, c
	ld [hl], a
	ld [wCurHPAnimNewHP], a
.maxed

	call SwitchTurn
	call UpdateHPBarBattleHuds
	jp SwitchTurn

UpdateHPBarBattleHuds:
	call UpdateHPBar
	jp UpdateBattleHuds

UpdateHPBar:
	hlcoord 9, 9
	ld a, [hBattleTurn]
	and a
	ld a, 1
	jr z, .ok
	hlcoord 0, 2
	xor a
.ok
	push bc
	ld [wWhichHPBar], a
	predef AnimateHPBar
	pop bc
	ret

HandleEnemyMonFaint:
	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, [wBattleMode]
	dec a
	jr nz, .trainer
	callba CheckPickup
	call .UpdateBGMapWithSecondDelay
	ld a, 1
	ld [BattleEnded], a
	ret

.trainer
	call .UpdateBGMapWithSecondDelay
	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

	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

.UpdateBGMapWithSecondDelay:
	ld a, $1
	ld [hBGMapMode], a
	ld c, 60
	jp DelayFrames

DoubleSwitch:
	ld a, [hLinkPlayerNumber]
	cp $1
	jr z, .player_1
	call ClearSprites
	hlcoord 0, 1
	lb bc, 3, 11
	call ClearBox
	call PlayerPartyMonEntrance
	ld a, $1
	call EnemyPartyMonEntrance
	jr .done

.player_1
	ld a, [wCurPartyMon]
	push af
	ld a, $1
	call EnemyPartyMonEntrance
	call ClearSprites
	call LoadTileMapToTempTileMap
	pop af
	ld [wCurPartyMon], a
	call PlayerPartyMonEntrance

.done
	xor a
	ld [wPlayerAction], a
	ret

GetEnemyFaintedText:
	ld hl, BattleText_EnemyPkmnFainted
	ld a, [wBattleMode]
	dec a
	ret nz
	ld hl, BattleText_WildPkmnFainted
	ret

StopDangerSound:
	xor a
	ld [Danger], a
	ret

FaintYourPokemon:
	call StopDangerSound
	call WaitSFX
	ld a, $f0
	ld [CryTracks], a
	ld a, [BattleMonSpecies]
	call PlayFaintingCry
	call WaitSFX
	ld de, SFX_KINESIS
	call PlaySFX
	call PlayerMonFaintedAnimation
	ld de, SFX_FAINT
	call PlaySFX
	hlcoord 9, 7
	lb bc, 5, 11
	call ClearBox
	ld hl, BattleText_PkmnFainted
	jp StdBattleTextBox

FaintEnemyPokemon:
	call WaitSFX
	ld a, $0f
	ld [CryTracks], a
	ld a, [EnemyMonSpecies]
	call PlayFaintingCry
	call WaitSFX
	ld de, SFX_KINESIS
	call PlaySFX
	call EnemyMonFaintedAnimation
	ld de, SFX_FAINT
	call PlaySFX
	hlcoord 0, 1
	lb bc, 3, 11
	call ClearBox
	call GetEnemyFaintedText
	jp StdBattleTextBox

CheckEnemyTrainerDefeated:
	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

HandleEnemySwitch:
	ld hl, EnemyHPPal
	ld e, HP_BAR_LENGTH_PX
	call UpdateHPPal
	call ApplyTilemapInVBlank
	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, $1
	jr nz, .okay
	and a
	ret

.okay
	xor a
EnemyPartyMonEntrance:
	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

WinTrainerBattle:
; 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
	callba Battle_GetTrainerName
	ld hl, BattleText_EnemyWasDefeated
	call StdBattleTextBox

	ld a, [wLinkMode]
	and a
	ret nz

	ld a, [InBattleTowerBattle]
	rra
	jr c, .battle_tower

	call BattleWinSlideInEnemyTrainerFrontpic
	ld c, 40
	call DelayFrames
	ld a, [wBattleType]
	cp BATTLETYPE_CANLOSE
	jr nz, .skip_heal
	ld a, [InBattleTowerBattle]
	bit 2, a
	jr nz, .skip_heal
	predef HealParty
.skip_heal
	ld a, [wMonStatusFlags]
	rra
	call nc, PrintWinLossText
	ld a, [InBattleTowerBattle]
	bit 2, a
	ret nz
	callba CheckPickup
	jp HandleBattleReward

.battle_tower
	call BattleWinSlideInEnemyTrainerFrontpic
	ld c, 40
	call DelayFrames
	call EmptyBattleTextBox
	ld c, $3
	callba BattleTowerText
	call WaitPressAorB_BlinkCursor
	call ClearTileMap
	jp ClearBGPalettes

HandleBattleReward:
	CheckEngine ENGINE_POKEMON_MODE
	ret nz
	CheckEngine ENGINE_HYPER_SHARE_ENABLED
	ret nz
	ld a, [wAmuletCoin]
	and a
	call nz, .DoubleReward
	call .CheckMaxedOutMomMoney
	push af
	ld a, $0
	jr nc, .okay
	ld a, [wBankSavingMoney]
	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, [wBankSavingMoney]
	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

.SendMoneyToMom
	push bc
	ld hl, wBattleReward + 2
	ld de, wBankMoney + 2
	call AddBattleMoneyToAccount
	pop bc
	ret

.AddMoneyToWallet
	push bc
	ld hl, wBattleReward + 2
	ld de, Money + 2
	call AddBattleMoneyToAccount
	pop bc
	ret

.DoubleReward
	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

.SentToMomTexts
	dw SentSomeToMomText
	dw SentHalfToMomText
	dw SentAllToMomText

.CheckMaxedOutMomMoney
	ld hl, wBankMoney + 2
	ld a, [hld]
	cp 999999 % $100
	ld a, [hld]
	sbc 999999 / $100 % $100
	ld a, [hl]
	sbc 999999 / $10000 % $100
	ret

AddBattleMoneyToAccount:
	ld c, $3
	and a
	push de
	push hl
	push bc
	ld b, h
	ld c, l
	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

PlayVictoryMusic:
	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 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

; 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.

; Arguments:
; [OtherTrainerClass]
; Returns:
; c if in array

IsKantoGymLeader:
	ld hl, KantoGymLeaders
	jr IsGymLeaderCommon

IsJohtoGymLeader:
	ld hl, JohtoGymLeaders
	jr IsGymLeaderCommon

IsRijonGymLeader:
	ld hl, RijonGymLeaders
	jr IsGymLeaderCommon

IsNaljoGymLeader:
	ld hl, NaljoGymLeaders
IsGymLeaderCommon:
	push de
	ld a, [OtherTrainerClass]
	call IsInSingularArray
	pop de
	ret

JohtoGymLeaders:
	db BUGSY
	db WHITNEY
	db GOLD

NaljoGymLeaders:
	db JOSIAH
	db BROOKLYN
	db RINJI
	db EDISON
	db AYAKA
	db CADENCE
	db ANDRE
	db BRUCE
	db YUKI
	db SORA
	db MURA
	db DAICHI
; fallthrough
; these two entries are unused
	db CHAMPION
	db RED
; fallthrough
RijonGymLeaders:
	db KARPMAN
	db LILY
	db SPARKY
	db LOIS
	db KOJI
	db SHERYL
	db JOE
	db SILVER

KantoGymLeaders:
	db SABRINA
	db BLUE
	db BROWN
	db -1

HandlePlayerMonFaint:
	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
	ld a, c
	and a
	ret nz
	ld a, $1
	ld [wPlayerAction], a
	call HandleEnemySwitch
	jp z, WildFled_EnemyFled_LinkBattleCanceled
	jp DoubleSwitch

PlayerMonFaintHappinessMod:
	ld a, [CurBattleMon]
	ld c, a
	ld hl, wBattleParticipantsNotFainted
	ld b, RESET_FLAG
	predef FlagAction
	ld hl, wEnemySubStatus3
	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 [wCurPartyMon], a
	callba ChangeHappiness
	ld a, [wBattleResult]
	and %11000000
	add $1
	ld [wBattleResult], a
	ld a, [wWhichMonFaintedFirst]
	and a
	ret

AskUseNextPokemon:
	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

ForcePlayerMonChoice:
	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
	ld hl, EnemyMonHP
	ld a, [hli]
	or [hl]
	jr nz, .send_out_pokemon

	call ClearSprites
	call ClearBGPalettes
	call _LoadHPBar
	call ExitMenu
	call LoadTileMapToTempTileMap
	call ApplyTilemapInVBlank
	ld b, SCGB_RAM
	predef GetSGBLayout
	call SetPalettes
	xor a
	ld c, a
	ret

.send_out_pokemon
	call ClearSprites
	ld a, [CurBattleMon]
	ld [LastPlayerMon], a
	ld a, [wCurPartyMon]
	ld [CurBattleMon], a
	call AddBattleParticipant
	call InitBattleMon
	call ResetPlayerStatLevels
	call ClearPalettes
	call DelayFrame
	call _LoadHPBar
	call CloseWindow
	ld b, SCGB_RAM
	predef GetSGBLayout
	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

PlayerPartyMonEntrance:
	ld a, [CurBattleMon]
	ld [LastPlayerMon], a
	ld a, [wCurPartyMon]
	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

SetUpBattlePartyMenu_NoLoop:
	call ClearBGPalettes
SetUpBattlePartyMenu: ; switch to fullscreen menu?
	callba LoadPartyMenuGFX
	callba InitPartyMenuWithCancel
	callba InitPartyMenuBGPal7
	jpba InitPartyMenuGFX

JumpToPartyMenuAndPrintText:
	callba WritePartyMenuTilemap
	callba PrintPartyMenuText
	call ApplyTilemapInVBlank
	call SetPalettes
	jp DelayFrame

SelectBattleMon:
	jpba PartyMenuSelect

PickPartyMonInBattle:
.loop
	ld a, $2 ; Which PKMN?
	ld [wPartyMenuActionText], a
	call JumpToPartyMenuAndPrintText
	call SelectBattleMon
	ret c
	call CheckIfCurPartyMonIsStillAlive
	jr z, .loop
	xor a
	ret

SwitchMonAlreadyOut:
	ld hl, CurBattleMon
	ld a, [wCurPartyMon]
	cp [hl]
	jr nz, .notout

	ld hl, BattleText_PkmnIsAlreadyOut
	call StdBattleTextBox
	scf
	ret

.notout
	xor a
	ret

ForcePickPartyMonInBattle:
; Can't back out.

.pick
	call PickPartyMonInBattle
	ret nc

	ld de, SFX_WRONG
	call PlayWaitSFX
	jr .pick

PickSwitchMonInBattle:
.pick
	call PickPartyMonInBattle
	ret c
	call SwitchMonAlreadyOut
	jr c, .pick
	xor a
	ret

ForcePickSwitchMonInBattle:
; Can't back out.

.pick
	call ForcePickPartyMonInBattle
	call SwitchMonAlreadyOut
	jr c, .pick

	xor a
	ret

LostBattle:
	ld a, 1
	ld [BattleEnded], a

	ld a, [InBattleTowerBattle]
	rra
	jr c, .battle_tower

	ld a, [wBattleType]
	cp BATTLETYPE_CANLOSE
	jr nz, .not_canlose

; Remove the enemy from the screen.
	hlcoord 0, 0
	lb bc, 8, 21
	call ClearBox
	call BattleWinSlideInEnemyTrainerFrontpic

	ld c, 40
	call DelayFrames

	ld a, [wMonStatusFlags]
	rra
	jp nc, PrintWinLossText
	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
	jp ClearBGPalettes

.not_canlose
	ld a, [wLinkMode]
	and a
	jr nz, .LostLinkBattle

; Greyscale
	ld b, SCGB_BATTLE_GRAYSCALE
	predef 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
.text
	call StdBattleTextBox

.end
	scf
	ret

EnemyMonFaintedAnimation:
	hlcoord 12, 5
	decoord 12, 6
	jr MonFaintedAnimation

PlayerMonFaintedAnimation:
	hlcoord 1, 10
	decoord 1, 11
	; fallthrough

MonFaintedAnimation:
; disable joypad
	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
	rst 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 PlaceText
	call Delay2
	pop hl
	pop de
	pop bc
	dec b
	jr nz, .OuterLoop

	pop af
	ld [wcfbe], a
	ret

.Spaces
	db TX_COMPRESSED, $92, $49
	db $25, $34

SlideBattlePicOut:
	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

.DoFrame
	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

ForceEnemySwitch:
	call ResetEnemyBattleVars
	ld a, [wEnemySwitchMonIndex]
	dec a
	ld b, a
	call LoadEnemyPkmnToSwitchTo
	call ClearEnemyMonBox
	call NewEnemyMonStatus
	call ResetEnemyStatLevels
	call Function_SetEnemyPkmnAndSendOutAnimation
	call BreakAttraction
	jp ResetBattleParticipants

EnemySwitch:
	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
	jp c, EnemyAbilityOnMonEntrance
	; 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

EnemySwitch_SetMode:
	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

CheckWhetherSwitchmonIsPredetermined:
; Returns index of enemy switchmon in b (0-5).
; Sets carry if:
;     Link opponent is switching
;     Enemy is switching to Pokemon 1-5
;     Enemy is switching to Pokemon 0 at the very start of battle
	ld a, [wLinkMode]
	and a
	jr z, .not_linked

	ld a, [wBattleAction]
	sub BATTLEACTION_SWITCH1
	ld b, a
	scf
	ret

.not_linked
	ld a, [wEnemySwitchMonIndex]
	and a
	jr z, .first_mon_to_be_sent_out

	dec a
	ld b, a
	scf
	ret

.first_mon_to_be_sent_out
	ld b, a
	ld a, [wBattleHasJustStarted]
	and a
	ret z
	scf
	ret

ResetEnemyBattleVars:
; and draw empty TextBox
	xor a
	ld [LastEnemyCounterMove], a
	ld [LastPlayerCounterMove], 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

ResetBattleParticipants:
	xor a
	ld [wBattleParticipantsNotFainted], a
	ld [wBattleParticipantsIncludingFainted], a
AddBattleParticipant:
	ld a, [CurBattleMon]
	ld c, a
	ld hl, wBattleParticipantsNotFainted
	ld b, SET_FLAG
	push bc
	predef FlagAction
	pop bc
	ld hl, wBattleParticipantsIncludingFainted
	predef_jump FlagAction

FindPkmnInOTPartyToSwitchIntoBattle:
	callba GetSwitchScores
	ld a, [wEnemySwitchMonParam]
	ld b, a
	ret

LoadEnemyPkmnToSwitchTo:
	; 'b' contains the PartyNr of the Pkmn the AI will switch to
	ld a, [EnemyAbility]
	cp ABILITY_NATURAL_CURE
	jr nz, .no_heal
	push bc
	ld a, [CurOTMon]
	ld hl, OTPartyMon1Status
	call GetPartyLocation
	ld [hl], 0
	pop bc
.no_heal
	ld a, b
	ld [wCurPartyMon], a
	ld hl, OTPartyMon1Level
	call GetPartyLocation
	ld a, [hl]
	ld [CurPartyLevel], a
	ld a, [wCurPartyMon]
	inc a
	ld hl, OTPartyCount
	ld c, a
	ld b, 0
	add hl, bc
	ld a, [hl]
	ld [TempEnemyMonSpecies], a
	ld [wCurPartySpecies], a
	call LoadEnemyMon

	ld a, [wCurPartySpecies]
	ld hl, EnemyMonHP
	ld a, [hli]
	ld [wEnemyHPAtTimeOfPlayerSwitch], a
	ld a, [hl]
	ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a
	ret

CheckWhetherToAskSwitch:
; Determine whether to bring up the shift dialogue.
;  c: Yes (SHIFT)
; nc: No  (SET)

	; Don't ask if this is the very start of the battle.
	ld a, [wBattleHasJustStarted]
	dec a
	ret z

	; Don't ask if you only have one party member.
	ld a, [wPartyCount]
	dec a
	ret z

	; Don't ask in a link battle.
	ld a, [wLinkMode]
	and a
	ret nz

	; Don't ask if you're on SET mode.
	ld a, [wOptions]
	bit BATTLE_SHIFT, a
	ret nz

	; Don't ask if your Pokemon fainted as well.
	ld a, [wCurPartyMon]
	push af
	ld a, [CurBattleMon]
	ld [wCurPartyMon], a
	callba CheckIfOnlyAliveMonIsCurPartyMon
	pop bc
	ld a, b
	ld [wCurPartyMon], a
	jr c, .return_nc
	scf
	ret

.return_nc
	and a
	ret

OfferSwitch:
	ld a, [wCurPartyMon]
	push af
	callba 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, [wCurPartyMon]
	ld [CurBattleMon], a
	call ClearPalettes
	call DelayFrame
	call _LoadHPBar
	pop af
	ld [wCurPartyMon], 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 [wCurPartyMon], a
	scf
	ret

ClearEnemyMonBox:
	xor a
	ld [hBGMapMode], a
	call ExitMenu
	call ClearSprites
	hlcoord 0, 1
	lb bc, 3, 11
	call ClearBox
	call ApplyTilemapInVBlank
	jp FinishBattleAnim

Function_BattleTextEnemySentOut:
	callba Battle_GetTrainerName
	ld hl, BattleText_EnemySentOut
	call StdBattleTextBox
	jp ApplyTilemapInVBlank

Function_SetEnemyPkmnAndSendOutAnimation:
	ld a, [TempEnemyMonSpecies]
	ld [wCurPartySpecies], a
	ld [wCurSpecies], a
	call GetBaseData
	ld a, OTPARTYMON
	ld [wMonType], 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
	;call 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

NewEnemyMonStatus:
	xor a
	ld [LastEnemyCounterMove], a
	ld [LastPlayerCounterMove], a
	ld [LastEnemyMove], a
	ld hl, wEnemySubStatus1
rept 4
	ld [hli], a
endr
	ld [hl], a
	ld [EnemyDisableCount], a
	ld [EnemyFuryCutterCount], a
	ld [EnemyProtectCount], a
	ld [EnemyDisabledMove], a
	ld [wEnemyMinimized], a
	ld [wPlayerWrapCount], a
	ld [wEnemyWrapCount], a
	ld [EnemyTurnsTaken], a
	ld hl, wPlayerSubStatus5
	res SUBSTATUS_CANT_RUN, [hl]
	ret

ResetEnemyStatLevels:
	ld a, BASE_STAT_LEVEL
	ld b, NUM_LEVEL_STATS - 1
	ld hl, EnemyStatLevels
.loop
	ld [hli], a
	dec b
	jr nz, .loop
	jp ApplyEnemyMonRingEffect

CheckPlayerPartyForFitPkmn:
; Has the player any Pkmn in his Party that can fight?
	ld a, [wPartyCount]
	ld e, a
	xor a
	ld hl, PartyMon1HP
	ld bc, wPartyMon2 - (wPartyMon1 + 1)
.asm_3d87e
	or [hl]
	inc hl
	or [hl]
	add hl, bc
	dec e
	jr nz, .asm_3d87e
	ld d, a
	ret

CheckIfCurPartyMonIsStillAlive:
	ld a, [wCurPartyMon]
	ld hl, PartyMon1HP
	call GetPartyLocation
	ld a, [hli]
	or [hl]
	ret nz

	ld a, [wBattleHasJustStarted]
	and a
	jr nz, .no_text
	ld hl, wPartySpecies
	ld a, [wCurPartyMon]
	ld c, a
	ld b, 0
	add hl, bc
	ld a, [hl]
	cp EGG
	ld hl, BattleText_AnEGGCantBattle
	jr z, .print_text

	ld hl, BattleText_TheresNoWillToBattle

.print_text
	call StdBattleTextBox

.no_text
	xor a
	ret

TryToRunAwayFromBattle:
; Run away from battle, with or without item
	ld a, [wBattleType]
	cp BATTLETYPE_DEBUG
	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
	call CheckIfInEagulouParkBattle
	jp z, .can_escape

	ld a, [wLinkMode]
	and a
	jp nz, .can_escape

	ld a, [wBattleMode]
	dec a
	jp nz, .cant_run_from_trainer

	ld a, [wEnemySubStatus5]
	bit SUBSTATUS_CANT_RUN, a
	jp nz, .cant_escape
	ld a, [wPlayerSubStatus2]
	bit SUBSTATUS_FINAL_CHANCE, a
	jp nz, .cant_escape

	call CheckEnemyArenaTrap
	jp c, .cant_escape

	ld a, [wPlayerWrapCount]
	and a
	jp nz, .cant_escape

	push hl
	push de
	ld a, [BattleMonItem]
	ld [wd265], a
	ld b, a
	call GetItemHeldEffect ; this is in ROM0
	ld a, b
	cp HELD_ESCAPE
	pop de
	pop hl
	jr nz, .no_flee_item

	call GetItemName
	jr .flee_using_text

.no_flee_item
	ld a, [PlayerAbility]
	ld [wd265], a
	cp ABILITY_RUN_AWAY
	jr nz, .no_flee_ability
	call GetAbilityName
.flee_using_text
	call SetPlayerTurn
	ld hl, BattleText_UserFledUsingItsStringBuffer1
	call StdBattleTextBox
	jp .can_escape

.no_flee_ability
	ld a, [wNumFleeAttempts]
	inc a
	ld [wNumFleeAttempts], a

	ld a, [hli]
	ld l, [hl]
	ld h, a

	ld a, [de]
	ld b, a
	inc de
	ld a, [de]
	ld e, a
	ld d, b
; hl = player speed
; de = enemy speed

	push hl
	push de
	call Call_LoadTempTileMapToTileMap
	pop de
	pop hl

; compare hl and de
	ld a, l
	sub e
	ld a, h
	sbc d
	jr nc, .can_escape
; multiply player speed by 32
	add hl, hl ; x2
	add hl, hl ; x4
	add hl, hl ; x8
	add hl, hl ; x16
	add hl, hl ; x32

; store PSpeed*32 into dividend
	ld a, h
	ld [hDividend], a
	ld a, l
	ld [hDividend + 1], a

; divide ESpeed by 4
	srl d
	rr e
	srl d
	rr e
	ld a, e
	and a ; prevent division by 0
	jr z, .can_escape
; calculate PSpeed*32/(ESpeed/4)
	ld [hDivisor], a
	ld b, 2
	predef Divide
	ld a, [hQuotient + 1]
	and a ; player can escape if result is greater than 255
	jr nz, .can_escape
	ld a, [wNumFleeAttempts]
	ld c, a
	ld a, [hQuotient + 2]
	jr .handleLoop
.loop
	add 30
	jr c, .can_escape
.handleLoop
	dec c
	jr nz, .loop
	ld c, a
	call BattleRandom
	ld b, a
	ld a, c
	cp b
	jr nc, .can_escape
	ld a, $1
	ld [wPlayerAction], a
	ld hl, BattleText_CantEscape
	jr .print_inescapable_text

.cant_escape
	ld hl, BattleText_CantEscape
	jr .print_inescapable_text

.cant_run_from_trainer
	ld a, [InBattleTowerBattle]
	and $5
	jr nz, .ask_forfeit
.dont_ask_forfeit
	ld hl, BattleText_TheresNoEscapeFromTrainerBattle

.print_inescapable_text
	call StdBattleTextBox
.didnt_flee
	ld a, $1
	ld [wFailedToFlee], a
	call LoadTileMapToTempTileMap
	and a
	ret

.ask_forfeit
	ld hl, BattleText_ForfeitChallenge
	call StdBattleTextBox
	call YesNoBox
	jr c, .didnt_flee

.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

	; 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
	ld a, [InBattleTowerBattle]
	and a
	jr nz, .forfeited
	push de
	ld de, SFX_RUN
	call WaitPlaySFX
	pop de
	call WaitSFX
	ld hl, BattleText_GotAwaySafely
	call StdBattleTextBox
	call WaitSFX
.forfeited
	call LoadTileMapToTempTileMap
	scf
	ret

InitBattleMon:
	ld a, 1
	ld [wPlayerJustSentMonOut], a
	ld a, MON_SPECIES
	call GetPartyParamLocation
	ld de, BattleMonSpecies
	ld bc, MON_ID
	rst CopyBytes
	ld bc, MON_DVS - MON_ID
	add hl, bc
	ld de, BattleMonDVs
	ld bc, MON_PKRUS - MON_DVS
	rst CopyBytes
	inc hl
	inc hl
	inc hl
	ld de, BattleMonLevel
	ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
	rst CopyBytes
	ld a, [BattleMonSpecies]
	ld [TempBattleMonSpecies], a
	ld [wCurPartySpecies], a
	ld [wCurSpecies], a
	call GetBaseData
	ld a, [BaseType1]
	ld [BattleMonType1], a
	ld a, [BaseType2]
	ld [BattleMonType2], a
	ld hl, wPartyMonNicknames
	ld a, [CurBattleMon]
	call SkipNames
	ld de, BattleMonNick
	ld bc, PKMN_NAME_LENGTH
	rst CopyBytes
	ld hl, BattleMonAttack
	ld de, PlayerStats
	ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
	rst CopyBytes
	call CalcPlayerAbility
	call ApplyStatusEffectOnPlayerStats
	jpba BadgeStatBoosts

BattleCheckPlayerShininess:
	call GetPartyMonDVs
	jpba CheckShininessHL

BattleCheckEnemyShininess:
	call GetEnemyMonDVs
	jpba CheckShininessHL

GetPartyMonDVs:
	ld hl, BattleMonDVs
	ld a, [wPlayerSubStatus5]
	bit SUBSTATUS_TRANSFORMED, a
	ret z
	ld hl, PartyMon1DVs
	ld a, [CurBattleMon]
	jp GetPartyLocation

GetEnemyMonDVs:
	ld hl, EnemyMonDVs
	ld a, [wEnemySubStatus5]
	bit SUBSTATUS_TRANSFORMED, a
	ret z
	ld hl, wEnemyBackupDVs
	ld a, [wBattleMode]
	dec a
	ret z
	ld hl, OTPartyMon1DVs
	ld a, [CurOTMon]
	jp GetPartyLocation

ResetPlayerStatLevels:
	ld a, BASE_STAT_LEVEL
	ld b, NUM_LEVEL_STATS - 1
	ld hl, PlayerStatLevels
.loop
	ld [hli], a
	dec b
	jr nz, .loop
	jp ApplyBattleMonRingEffect

_ApplyHeldRingEffect::
; Can be farcalled, so we can't use a
	ld a, b
	push hl
	ld hl, .StatRings
	ld e, 2
	call IsInArray
	jr nc, .nope
	inc hl
	ld a, [hl]
	swap a
	and $f
	ld c, a
	ld a, [hl]
	and $f
	ld e, a
	pop hl
	push hl
	ld b, 0
	add hl, bc
	ld a, [hl]
	cp 13
	jr nc, .skip
	inc [hl]
.skip
	pop hl
	ld d, 0
	add hl, de
	ld a, [hl]
	cp 2
	ret c
	dec [hl]
	ret

.nope
	pop hl
	ret

.StatRings
statring: MACRO
	db \1
	dn \2, \3
ENDM
	statring GRASS_RING,     SP_DEFENSE, DEFENSE
	statring FIRE_RING,      DEFENSE,    SP_DEFENSE
	statring WATER_RING,     ATTACK,     EVASION
	statring THUNDER_RING,   SP_ATTACK,  ACCURACY
	statring MOON_RING,      EVASION,    SPEED
	statring SHINY_RING,     ACCURACY,   EVASION
	statring DAWN_RING,      SPEED,      ACCURACY
	db $ff

InitEnemyMon:
	ld a, [wCurPartyMon]
	ld hl, OTPartyMon1Species
	call GetPartyLocation
	ld de, EnemyMonSpecies
	ld bc, MON_ID
	rst CopyBytes
	ld bc, MON_DVS - MON_ID
	add hl, bc
	ld de, EnemyMonDVs
	ld bc, MON_PKRUS - MON_DVS
	rst CopyBytes
	inc hl
	inc hl
	inc hl
	ld de, EnemyMonLevel
	ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL
	rst CopyBytes
	ld a, [EnemyMonSpecies]
	ld [wCurSpecies], a
	call GetBaseData
	ld hl, OTPartyMonNicknames
	ld a, [wCurPartyMon]
	call SkipNames
	ld de, EnemyMonNick
	ld bc, PKMN_NAME_LENGTH
	rst CopyBytes
	ld hl, EnemyMonAttack
	ld de, EnemyStats
	ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
	rst CopyBytes
	call CalcEnemyAbility
	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, [wCurPartyMon]
	ld [CurOTMon], a
	ret

SwitchPlayerMon:
	call ClearSprites
	ld a, [CurBattleMon]
	ld [LastPlayerMon], a
	ld a, [wCurPartyMon]
	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

SendOutPlayerMon_PModeBattleStart:
	call SendOutPlayerMon_InitVars
	jr SendOutPlayerMon_continue

SendOutPlayerMon:
	hlcoord 1, 5
	lb bc, 7, 8
	call ClearBox
	call ApplyTilemapInVBlank
	xor a
	ld [hBGMapMode], a
	call GetMonBackpic
	call SendOutPlayerMon_InitVars
	ld de, ANIM_SEND_OUT_MON
	call Call_PlayBattleAnim
SendOutPlayerMon_continue:
	call BattleCheckPlayerShininess
	jr nc, .notShiny
	ld a, 1
	ld [wBattleAnimParam], a
	ld de, ANIM_SEND_OUT_MON
	call Call_PlayBattleAnim
.notShiny
	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, [wCurPartySpecies]
	call PlayStereoCry

.statused
	call UpdatePlayerHUD
	ld a, $1
	ld [hBGMapMode], a
	ret

SendOutPlayerMon_InitVars:
	xor a
	ld [hGraphicStartTile], a
	ld [wd0d2], a
	ld [CurMoveNum], a
	ld [TypeModifier], a
	ld [wPlayerMoveStruct + MOVE_ANIM], a
	ld [LastEnemyCounterMove], a
	ld [LastPlayerCounterMove], a
	ld [LastPlayerMove], a
	call CheckAmuletCoin
	call FinishBattleAnim
	xor a
	ld [wEnemyWrapCount], a
	call SetPlayerTurn
	xor a
	ld [wNumHits], a
	ld [wBattleAnimParam], a
	ret

NewBattleMonStatus:
	xor a
	ld [LastEnemyCounterMove], a
	ld [LastPlayerCounterMove], a
	ld [LastPlayerMove], a
	ld hl, wPlayerSubStatus1
	ld [hli], a
	ld [hli], a
	ld [hli], a
	ld [hli], a
	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 [DisabledMove], a
	ld [wPlayerMinimized], a
	ld [wEnemyWrapCount], a
	ld [wPlayerWrapCount], a
	ld [PlayerTurnsTaken], a
	ld hl, wEnemySubStatus5
	res SUBSTATUS_CANT_RUN, [hl]
	ret

BreakAttraction:
	ld hl, wPlayerSubStatus1
	res SUBSTATUS_IN_LOVE, [hl]
	ld hl, wEnemySubStatus1
	res SUBSTATUS_IN_LOVE, [hl]
	ret

SpikesDamage_CheckMoldBreaker:
; Called when a Pokémon with Mold Breaker uses Roar/Whirlwind. This
; is neccessary because it negates Levitate but can't be checked
; unconditionally since other kind of switches ignore MB as usual.
	call GetUserAbility
	jr SpikesDamage_GotUserAbility
SpikesDamage:
	call GetUserAbility_IgnoreMoldBreaker
SpikesDamage_GotUserAbility:
	cp ABILITY_LEVITATE
	ret z
	ld hl, wPlayerScreens
	ld de, BattleMonType
	ld bc, UpdatePlayerHUD
	ld a, [hBattleTurn]
	and a
	jr z, .ok
	ld hl, wEnemyScreens
	ld de, EnemyMonType
	ld bc, UpdateEnemyHUD
.ok
	bit SCREENS_LAVA_POOL, [hl]
	jr z, .spikes
	push hl
	push de
	push bc

	ld a, [de]
	cp FIRE
	jr z, .no_pool
	cp FLYING
	jr z, .no_pool
	inc de
	ld a, [de]
	cp FIRE
	jr z, .no_pool
	cp FLYING
	jr z, .no_pool

	call GetUserItem ; this is in ROM0
	ld a, b
	cp HELD_PREVENT_BURN
	jr z, .no_pool

	callba SafeCheckSafeguard
	jr nz, .no_pool

	; already statused
	ld a, BATTLE_VARS_STATUS
	call GetBattleVar
	and a
	jr nz, .no_pool

	; Lava Pool residual animation
	call SwitchTurn
	ld de, LAVA_POOL
	ld a, 1
	ld [wBattleAnimParam], a
;	xor a
;	ld [wNumHits], a
	call Call_PlayBattleAnim_OnlyIfVisible
	call SwitchTurn

	ld a, BATTLE_VARS_STATUS
	call GetBattleVarAddr
	set BRN, [hl]
	call UpdateUserInParty
	call ApplyBrnEffectOnAttack
	ld de, ANIM_BRN
	call Call_PlayBattleAnim_OnlyIfVisible

	ld hl, BattleText_UserBurnedByLavaPool
	call StdBattleTextBox

	pop hl
	push hl
	call _hl_
	call ApplyTilemapInVBlank

.no_pool
	pop bc
	pop de
	pop hl
.spikes
	ld a, [hl]
	and $3
	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

	ld a, [hl]
	and $3

	push bc
	push af

	ld hl, BattleText_UserHurtBySpikes ; "hurt by SPIKES!"
	call StdBattleTextBox

	pop af
	add a
	cpl
	add 11
	ld [hDivisor], a
	call GetMaxHP
	ld a, b
	ld [hDividend], a
	ld a, c
	ld [hDividend + 1], a
	ld b, 2
	predef Divide
	ld a, [hQuotient + 1]
	ld b, a
	ld a, [hQuotient + 2]
	ld c, a
	or b
	jr nz, .damage
	inc c
.damage
	call SubtractHPFromUser

	pop hl
	call _hl_

	jp ApplyTilemapInVBlank

PursuitSwitch:
	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 a, [LastPlayerMon]
	ld [CurBattleMon], a
	ld hl, DoEnemyTurn
.do_turn
	ld a, BANK(DoPlayerTurn)
	call FarCall_hl

	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 FlagAction
	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 PlayWaitSFX
	ld de, SFX_FAINT
	call PlayWaitSFX
	call EnemyMonFaintedAnimation
	call GetEnemyFaintedText

.done_fainted
	call StdBattleTextBox
	scf
	ret

.done
	and a
	ret

RecallPlayerMon:
	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

EndTurn_HealingItems:
	call SetFastestTurn
	call .do_it
	call SwitchTurn
.do_it
	call UseHeldStatusHealingItem
	call UseConfusionHealingItem
	; fallthrough
HandleHPHealingItem:
	call GetOpponentItem ; this is in ROM0
	ld a, b
	cp HELD_BERRY
	ret nz
	call SwitchTurn
	ld a, [hl]
	cp SITRUS_BERRY
	jr nz, .not_sitrus_berry
	call GetQuarterMaxHP
.not_sitrus_berry
	push bc
	call GetThirdMaxHP ; hl = max hp + 1, bc = max(1, (1/3) * ([max hp]))
	ld d, b
	ld e, c
	pop bc
	call SwitchTurn
	dec hl
	dec hl
	ld a, [hld]
	ld [wCurHPAnimOldHP], a
	ld a, [hli]
	ld [wCurHPAnimOldHP + 1], a
	cp d
	jr c, .go
	ret nz
	ld a, [hl]
	cp e
	jr z, .go
	ret nc
.go
	ld a, [hld]
	add c
	ld c, a
	ld a, [hli]
	adc 0
	ld b, a
	push hl
	inc hl
	inc hl
	ld a, [hld]
	cp c
	ld a, [hl]
	sbc b
	jr nc, .load_bc
	ld b, [hl]
	inc hl
	ld c, [hl]
.load_bc
	push bc
	ld a, c
	ld [wCurHPAnimNewHP], a
	ld a, b
	ld [wCurHPAnimNewHP + 1], a
	call ItemRecoveryAnim
	ld a, [hBattleTurn]
	ld [wWhichHPBar], a
	and a
	hlcoord 0, 2
	jr z, .got_hp_bar_coords
	hlcoord 9, 9

.got_hp_bar_coords
	ld [wWhichHPBar], a
	predef AnimateHPBar
	pop bc
	pop hl
	ld [hl], c
	dec hl
	ld [hl], b
UseOpponentItem:
	call RefreshBattleHuds
	call GetOpponentItem ; this is in ROM0
	ld a, [hl]
	ld [wNamedObjectIndexBuffer], a
	call GetItemName
	callba ConsumeHeldItem
	ld a, c
	ld hl, PowerHerbText
	cp HELD_POWER_HERB
	jr z, .okay
	ld a, [wStringBuffer1]
	ld hl, .Vowels
	call IsInSingularArray
	ld hl, RecoveredUsingText
	jr nc, .okay
	ld hl, RecoveredUsingText2
.okay
	call StdBattleTextBox
	call GetTargetAbility
	cp ABILITY_UNBURDEN
	ret nz
	ld a, BATTLE_VARS_SUBSTATUS2_OPP
	call GetBattleVarAddr
	set SUBSTATUS_UNBURDEN, [hl]
	ret

.Vowels
	db "AEIOUaeiou"
	db -1

ItemRecoveryAnim:
	push hl
	push de
	push bc
	call EmptyBattleTextBox
	ld a, RECOVER
	ld [FXAnimIDLo], a
	call SwitchTurn
	xor a
	ld [wNumHits], a
	ld [FXAnimIDHi], a
	predef PlayBattleAnim
	call SwitchTurn
	pop bc
	pop de
	pop hl
	ret

UseHeldStatusHealingItem:
	call GetOpponentItem ; this is in ROM0
	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_SEMISTATUS_OPP
	call GetBattleVarAddr
	res SEMISTATUS_TOXIC, [hl]
	ld a, BATTLE_VARS_SUBSTATUS1_OPP
	call GetBattleVarAddr
	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 SwitchTurn
	ld a, BANK(CalcEnemyStats)
	call FarCall_hl
	call SwitchTurn
	call ItemRecoveryAnim
	call UseOpponentItem
	ld a, $1
	and a
	ret

.Statuses
	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

UseConfusionHealingItem:
	ld a, BATTLE_VARS_SUBSTATUS3_OPP
	call GetBattleVar
	bit SUBSTATUS_CONFUSED, a
	ret z
	call GetOpponentItem ; this is in ROM0
	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

EndTurn_StatBoostingHeldItems:
; The effects handled here are not used in-game.
	call CheckSpeed
	jr z, .player_first
	call .CheckEnemy
.CheckPlayer
	call GetPartymonItem
	ld a, $0
	jp .HandleItem

.player_first
	call .CheckPlayer
.CheckEnemy
	call GetOTPartymonItem
	ld a, $1
.HandleItem
	ld [hBattleTurn], a
	ld d, h
	ld e, l
	push de
	push bc
	ld a, [bc]
	ld b, a
	call GetItemHeldEffect ; this is in ROM0
	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, BANK(BattleCommand_AttackUp)
	call FarCall_Pointer
	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
	jpba BattleCommand_StatUpMessage

.finish
	pop bc
	pop de
	ret

.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

GetPartymonItem:
	ld hl, PartyMon1Item
	ld a, [CurBattleMon]
	call GetPartyLocation
	ld bc, BattleMonItem
	ret

GetOTPartymonItem:
	ld hl, OTPartyMon1Item
	ld a, [CurOTMon]
	call GetPartyLocation
	ld bc, EnemyMonItem
	ret

UpdateBattleHUDs:
	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

UpdatePlayerHUD::
	push hl
	push de
	push bc
	call DrawPlayerHUD
	call UpdatePlayerHPPal
	call CheckDanger
	pop bc
	pop de
	pop hl
	ret

DrawPlayerHUD:
	xor a
	ld [hBGMapMode], a

	; Clear the area
	hlcoord 9, 7
	lb bc, 5, 11
	call ClearBox

	hlcoord 9, 11
	ld [hl], $74
	hlcoord 19, 10
	ld [hl], $73
	hlcoord 19, 11
	ld [hl], $5e

	hlcoord 18, 9
	ld [hl], $73 ; vertical bar
	call PrintPlayerHUD

	; HP bar
	hlcoord 9, 9
	ld b, 1
	xor a ; PARTYMON
	ld [wMonType], 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

UpdatePlayerHPPal:
	ld hl, PlayerHPPal
	jp UpdateHPPal

CheckDanger:
	ld hl, BattleMonHP
	ld a, [hli]
	or [hl]
	jr z, .no_danger
	ld a, [wDanger]
	and a
	ret nz
	ld a, [PlayerHPPal]
	cp HP_RED
	jr z, .danger

.no_danger
	ld hl, Danger
	ld [hl], $00
	ret

.danger
	ld hl, Danger
	set 7, [hl]
	ret

PrintPlayerHUD:
	ld de, BattleMonNick
	hlcoord 10, 7
	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
	rst CopyBytes
	ld a, [CurBattleMon]
	ld hl, PartyMon1Species
	call GetPartyLocation
	ld a, [hl]
	ld [wCurPartySpecies], a
	ld [wCurSpecies], a
	call GetBaseData

	pop hl
	dec hl

	ld a, BREEDMON
	ld [wMonType], a
	callba GetGender
	ld a, " "
	jr c, .got_gender_char
	ld a, "♂"
	jr nz, .got_gender_char
	ld a, "♀"

.got_gender_char
	hlcoord 14, 8
	ld [hl], a
; TODO: place status icon instead of text
	hlcoord 10, 8
	ld de, BattleMonStatus
	predef PlaceNonFaintStatus
	hlcoord 16, 8
	ld a, [BattleMonLevel]
	ld [TempMonLevel], a
	jp PrintLevel

_UpdateBattleHuds::
	call UpdatePlayerHUD
	; fallthrough

UpdateEnemyHUD::
	push hl
	push de
	push bc
	call DrawEnemyHUD
	call UpdateEnemyHPPal
	pop bc
	pop de
	pop hl
	ret

DrawEnemyHUD:
	xor a
	ld [hBGMapMode], a

	hlcoord 0, 1
	lb bc, 3, 11
	call ClearBox

	ld a, [wBattleMode]
	dec a
	jr nz, .skip
	ld a, [TempEnemyMonSpecies]
	dec a
	call CheckCaughtMon
	jr z, .skip
	hlcoord 0, 3
	ld [hl], $5f

.skip
	ld a, [TempEnemyMonSpecies]
	ld [wCurSpecies], a
	ld [wCurPartySpecies], a
	call GetBaseData
	ld de, EnemyMonNick
	hlcoord 1, 1
	call PlaceString
	ld h, b
	ld l, c
	dec hl

	ld hl, EnemyMonDVs
	ld de, TempMonDVs
	ld a, [wEnemySubStatus5]
	bit SUBSTATUS_TRANSFORMED, a
	jr z, .ok
	ld hl, wEnemyBackupDVs
.ok
	ld a, [hli]
	ld [de], a
	inc de
	ld a, [hl]
	ld [de], a

	ld a, BREEDMON
	ld [wMonType], a
	callba GetGender
	ld a, " "
	jr c, .got_gender
	ld a, "♂"
	jr nz, .got_gender
	ld a, "♀"

.got_gender
	hlcoord 5, 3
	ld [hl], a

; TODO: place status icon instead of text
	hlcoord 7, 3
	ld de, EnemyMonStatus
	predef PlaceNonFaintStatus
	hlcoord 1, 3
	ld a, [EnemyMonLevel]
	ld [TempMonLevel], a
	call PrintLevel

	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
	predef Multiply
	ld hl, EnemyMonMaxHP
	ld a, [hli]
	ld [hDivisor], a
	ld a, [hl]
	ld [hDivisor + 1], a
	predef DivideLong
	ld a, [hLongQuotient + 3]
	ld e, a
	ld a, HP_BAR_LENGTH
	ld d, a
	ld c, a

.draw_bar
	xor a
	ld [wWhichHPBar], a
	hlcoord 0, 2
	ld b, 0
	jp DrawBattleHPBar

UpdateEnemyHPPal:
	ld hl, EnemyHPPal
	; fallthrough

UpdateHPPal:
	ld b, [hl]
	call SetHPPal
	ld a, [hl]
	cp b
	ret z
	jp FinishBattleAnim

BattleMenu:
	xor a
	ld [hBGMapMode], a
	call LoadTempTileMapToTileMap

	ld a, [wBattleType]
	cp BATTLETYPE_DEBUG
	jr z, .ok
	call EmptyBattleTextBox
	call UpdateBattleHuds
	call EmptyBattleTextBox
	call LoadTileMapToTempTileMap
.ok

.loop
	callba LoadBattleMenu
	ld a, $1
	ld [hBGMapMode], a
	ld a, [wd0d2]
	dec a
	jp z, BattleMenu_Fight
	dec a
	jp z, BattleMenu_PKMN
	dec a
	jp z, BattleMenu_PackOrGuard
	dec a
	jr nz, .loop
	; fallthrough

BattleMenu_Run:
	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
	jr z, BattleMenu
	ret

BattleMenu_Guard:
	ld hl, wPlayerSubStatus2
	set SUBSTATUS_GUARDING, [hl]

; fallthrough
BattleMenu_Fight:
	call CheckIfInEagulouParkBattle
	jr z, .eagulouParkBattle
	xor a
	ld [wNumFleeAttempts], a
	call Call_LoadTempTileMapToTileMap
	and a
	ret
.eagulouParkBattle
	ld hl, BattleText_BattleCantFightEagulou
	call StdBattleTextBox
	jr BattleMenu

BattleMenu_PackOrGuard:
	ld a, [wLinkMode]
	and a
	jp nz, .ItemsCantBeUsed

	CheckEngine ENGINE_POKEMON_MODE
	jr nz, BattleMenu_Guard
	ld a, [InBattleTowerBattle]
	and 5
	jp nz, .ItemsCantBeUsed

	call LoadStandardMenuDataHeader

	callba BattlePack
	ld a, [wPlayerAction]
	and a
	jp nz, .UseItem

.didnt_use_item
	call ClearPalettes
	call DelayFrame
	call _LoadBattleFontsHPBar
	call GetMonBackpic
	call GetMonFrontpic
	call ExitMenu
	call ApplyTilemapInVBlank
	call FinishBattleAnim
	call LoadTileMapToTempTileMap
	jp BattleMenu

.ItemsCantBeUsed
	ld hl, BattleText_ItemsCantBeUsedHere
	call StdBattleTextBox
	jp BattleMenu

.UseItem
	ld a, [wWildMon]
	and a
	jr nz, .run
	callba CheckItemPocket
	ld a, [wItemAttributeParamBuffer]
	cp BALL
	call nz, ClearBGPalettes
	xor a
	ld [hBGMapMode], a
	call _LoadBattleFontsHPBar
	call ClearSprites
	ld a, [wBattleType]
	call GetMonBackpic
	call GetMonFrontpic
	ld a, $1
	ld [wMenuCursorY], a
	call ExitMenu
	call UpdateBattleHUDs
	call ApplyTilemapInVBlank
	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

BattleMenu_PKMNFinalChance:
	ld hl, BattleText_NoSwitchFinalChance
	call StdBattleTextBox
	jp BattleMenu

BattleMenu_PKMN:
	ld a, [wPlayerSubStatus2]
	bit SUBSTATUS_FINAL_CHANCE, a
	jr nz, BattleMenu_PKMNFinalChance

	call LoadStandardMenuDataHeader
BattleMenuPKMN_ReturnFromStats:
	call ExitMenu
	call LoadStandardMenuDataHeader
	call ClearBGPalettes
BattleMenuPKMN_Loop:
	call SetUpBattlePartyMenu
	xor a
	ld [wPartyMenuActionText], a
	call JumpToPartyMenuAndPrintText
	call SelectBattleMon
	jr c, .Cancel
.loop
	callba FreezeMonIcons
	callba BattleMonMenu
	jr c, BattleMenuPKMN_Loop
	call PlaceHollowCursor
	ld a, [wMenuCursorY]
	dec a ; SWITCH
	jp z, TryPlayerSwitch
	dec a ; STATS
	jr z, .Stats
	dec a ; CANCEL
	jr nz, .loop

.Cancel
	call ClearSprites
	call ClearPalettes
	call DelayFrame
	call _LoadHPBar
	call CloseWindow
	call LoadTileMapToTempTileMap
	ld b, SCGB_RAM
	predef GetSGBLayout
	call SetPalettes
	jp BattleMenu

.Stats
	call Battle_StatsScreen
	jp BattleMenuPKMN_ReturnFromStats

Battle_StatsScreen:
	call DisableLCD
	ld hl, vBGTiles tile $31
	ld de, vObjTiles
	ld bc, $0110
	rst CopyBytes
	ld hl, vBGTiles
	ld de, vObjTiles tile $11
	ld bc, $31 tiles
	rst CopyBytes
	call EnableLCD
	call ClearSprites
	call LowVolume
	xor a ; PARTYMON
	ld [wMonType], a
	callba BattleStatsScreenInit
	call MaxVolume
	call DisableLCD
	ld hl, vObjTiles
	ld de, vBGTiles tile $31
	ld bc, $11 tiles
	rst CopyBytes
	ld hl, vObjTiles tile $11
	ld de, vBGTiles
	ld bc, $31 tiles
	rst CopyBytes
	jp EnableLCD

TryPlayerSwitch:
	ld a, [CurBattleMon]
	ld d, a
	ld a, [wCurPartyMon]
	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
	call CheckEnemyArenaTrap
	jr c, .trapped
	ld a, [wEnemySubStatus5]
	bit SUBSTATUS_CANT_RUN, a
	jr z, .try_switch
	ld a, [wPlayerSubStatus2]
	bit SUBSTATUS_FINAL_CHANCE, a
	jr z, .try_switch

.trapped
	ld hl, BattleText_PkmnCantBeRecalled
	call StdBattleTextBox
	jp BattleMenuPKMN_Loop

.try_switch
	call CheckIfCurPartyMonIsStillAlive
	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
	ld b, SCGB_RAM
	predef GetSGBLayout
	call SetPalettes
	ld a, [wCurPartyMon]
	ld [CurBattleMon], a
PlayerSwitch:
	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 CheckPlayerNaturalCure
	call BattleMonEntrance
	call AbilityOnMonEntrance
	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
	jp WildFled_EnemyFled_LinkBattleCanceled

.dont_run
	ld a, [hLinkPlayerNumber]
	cp $1
	jr z, .player_1
	call BattleMonEntrance
	callba AI_Switch
	and a
	ret

.player_1
	callba AI_Switch
	call BattleMonEntrance
	and a
	ret

BattleMonEntrance:
	call WithdrawPkmnText

	ld c, 50
	call DelayFrames

	ld hl, wPlayerSubStatus4
	res SUBSTATUS_RAGE, [hl]

	call SetEnemyTurn
	call PursuitSwitch
	jr c, .ok
	call RecallPlayerMon
.ok

	hlcoord 9, 7
	lb bc, 5, 11
	call ClearBox

	ld a, [CurBattleMon]
	ld [wCurPartyMon], 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

PassedBattleMonEntrance:
	ld c, 50
	call DelayFrames

	hlcoord 9, 7
	lb bc, 5, 11
	call ClearBox

	ld a, [wCurPartyMon]
	ld [CurBattleMon], a
	call AddBattleParticipant
	call InitBattleMon
	xor a
	ld [wd265], a
	call ApplyStatLevelMultiplierOnAllStats
	call SendOutPlayerMon
	call EmptyBattleTextBox
	call LoadTileMapToTempTileMap
	call SetPlayerTurn
	jp SpikesDamage

CheckAmuletCoin:
	ld hl, BattleMonItem
	ld de, PlayerAbility
	ld b, a
	call GetItemHeldEffect ; this is in ROM0
	ld a, b
	cp HELD_AMULET_COIN
	ret nz
	ld a, 1
	ld [wAmuletCoin], a
	ret

MoveSelectionScreen:
	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
	rst CopyBytes
	xor a
	ld [hBGMapMode], a

	hlcoord 4, 17 - NUM_MOVES - 1
	lb bc, 4, 14
	ld a, [wMoveSelectionMenuType]
	cp $2
	jr nz, .got_dims
	hlcoord 4, 17 - NUM_MOVES - 1 - 4
	lb bc, 4, 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 [wCurHPAnimMaxHP], 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, A_BUTTON | D_UP | D_DOWN ; $c1
	jr z, .okay
	dec a
	ld b, A_BUTTON | B_BUTTON | D_UP | D_DOWN ; $c3
	jr z, .okay
	ld a, [wLinkMode]
	and a
	jr nz, .okay
	ld b, A_BUTTON | B_BUTTON | SELECT | D_UP | D_DOWN ; $c7

.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
	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
	rst AddNTimes
	ld [hl], "▷"

.interpret_joypad
	ld a, $1
	ld [hBGMapMode], a
	call DoMenuJoypadLoop
	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
	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

.pressed_up
	ld a, [wMenuCursorY]
	and a
	jp nz, .menu_loop
	ld a, [wNumMoves]
	inc a
	ld [wMenuCursorY], a
	jp .menu_loop

.pressed_down
	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

.pressed_select
	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, [wPlayerSubStatus5]
	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

MoveInfoBox:
	xor a
	ld [hBGMapMode], a

	hlcoord 0, 8
	lb bc, 3, 9
	call TextBox

	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 PlaceText
	ret

.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 [wCurPartyMon], a
	ld a, WILDMON
	ld [wMonType], a
	callba GetMaxPPOfMove

	ld hl, wMenuCursorY
	ld c, [hl]
	inc [hl]
	ld b, 0
	ld hl, BattleMonPP
	add hl, bc
	ld a, [hl]
	and $3f
	ld [wStringBuffer1], a
	call .PrintPP

	hlcoord 1, 9
	ld de, .Type
	call PlaceText

	hlcoord 7, 11
	ld [hl], "/"

	callba UpdateMoveData
	ld a, [wPlayerMoveStruct + MOVE_ANIM]
	ld b, a
	hlcoord 2, 10
	predef PrintMoveType
	ret

.Disabled
	db TX_COMPRESSED, $e0, $1a, $35, $5f, $4f, $3c
	db $69, $a0
.Type
	text "TYPE/"
	done

.PrintPP
	hlcoord 5, 11
	push hl
	ld de, wStringBuffer1
	lb bc, 1, 2
	call PrintNum
	pop hl
	inc hl
	inc hl
	ld [hl], "/"
	inc hl
	ld de, wNamedObjectIndexBuffer
	lb bc, 1, 2
	jp PrintNum

CheckPlayerHasUsableMoves:
	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
	ret nz

.force_struggle
	ld hl, BattleText_PkmnHasNoMovesLeft
	call StdBattleTextBox
	ld c, 60
	call DelayFrames
	xor a
	ret

ParseEnemyAction:
	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, [wEnemySubStatus1]
	bit SUBSTATUS_ROLLOUT, a
	jp nz, .skip_load
	ld a, [wEnemySubStatus3]
	and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE ; | 1 << SUBSTATUS_BIDE
	jp nz, .skip_load

	ld hl, wEnemySubStatus5
	bit SUBSTATUS_ENCORED, [hl]
	ld a, [LastEnemyMove]
	jp nz, .finish
	ld hl, EnemyMonMoves
	ld b, 0
	add hl, bc
	ld a, [hl]
	jp .finish

.not_linked
	ld hl, wEnemySubStatus5
	bit SUBSTATUS_ENCORED, [hl]
	jr z, .skip_encore
	ld a, [LastEnemyMove]
	jp .finish

.skip_encore
	call CheckSubStatus_RechargeChargedRampageBideRollout
	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
	callba UpdateMoveData
	call CheckSubStatus_RechargeChargedRampageBideRollout
	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, wEnemySubStatus4
	res SUBSTATUS_RAGE, [hl]

.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

ResetVarsForSubStatusRage:
	xor a
	ld [EnemyFuryCutterCount], a
	ld [EnemyProtectCount], a
	ld hl, wEnemySubStatus4
	res SUBSTATUS_RAGE, [hl]
	ret

CheckSubStatus_RechargeChargedRampageBideRollout:
	ld a, [wEnemySubStatus4]
	and 1 << SUBSTATUS_RECHARGE
	ret nz

	ld hl, wEnemySubStatus3
	ld a, [hl]
	and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE ; | 1 << SUBSTATUS_BIDE
	ret nz

	ld hl, wEnemySubStatus1
	bit SUBSTATUS_ROLLOUT, [hl]
	ret

LinkBattleSendReceiveAction:
	jpba _LinkBattleSendReceiveAction

LoadEnemyMon:
; 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
	ld a, 1
	ld [wEnemyJustSentMonOut], a

; We don't need to be here if we're in a link battle
	ld a, [wLinkMode]
	and a
	jp nz, InitEnemyMon

; and also in a BattleTower-Battle
	ld a, [InBattleTowerBattle]
	and 5
	jp nz, InitEnemyMon

; Check ability of top party mon and store into b. Used for Compoundeyes. This needs to
; be done before the wildmon species metadata is loaded since this also needs to load
; species metadata on its own
	ld hl, wPartyMon1 ; Yes, always the lead, even if fainted
	call CalcPartyMonAbility
	ld b, a

; Make sure everything knows what species we're working with
	ld a, [TempEnemyMonSpecies]
	ld [EnemyMonSpecies], a
	ld [wCurSpecies], a
	ld [wCurPartySpecies], a

; Grab the BaseData for this species. Preserve bc (partymon1 ability)
	push bc
	call GetBaseData
	pop bc

; Let's get the item:

; Is the item predetermined?
	ld a, [wBattleMode]
	dec a
	jr z, .WildItem

; If we're in a trainer battle, the item is in the party struct
	ld a, [wCurPartyMon]
	ld hl, OTPartyMon1Item
	call GetPartyLocation ; bc = PartyMon[wCurPartyMon] - wPartyMons
	ld a, [hl]
	jr .UpdateItem

.WildItem
; In a wild battle, we pull from the item slots in BaseData

; Force Item1
; Used for Ho-Oh, Lugia and Snorlax encounters
	ld a, [wWildMonCustomItem]
	and a
	jr z, .notCustomItem
	ld [EnemyMonItem], a
	xor a
	ld [wWildMonCustomItem], a
	jr .afterEnemyItem
.notCustomItem
	ld a, [wBattleType]
	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

; Chance of getting an item: 37.5%/25% with/without Compoundeyes
	ld a, b
	ld c, $40
	cp ABILITY_COMPOUNDEYES
	jr nz, .no_compoundeyes
	set 5, c ; c = $60
.no_compoundeyes
	call BattleRandom
	cp c
	ld a, NO_ITEM
	jr nc, .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
.afterEnemyItem
; Initialize DVs

; If we're in a trainer battle, DVs are predetermined
	ld a, [wBattleMode]
	and a
	jr z, .InitDVs

	ld a, [wEnemySubStatus5]
	bit SUBSTATUS_TRANSFORMED, a
	jr z, .InitDVs

; Unknown
	ld hl, wEnemyBackupDVs
	ld de, 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, [wBattleType]
	cp a, BATTLETYPE_ROAMING
	jr nz, .NotRoaming

; Grab HP
	ld hl, wRoamMon1HP
	ld a, [hli]
; Check if the HP has been initialized
	or [hl]
; We'll do something with the result in a minute
	push af

; Grab DVs
	ld hl, wRoamMon1DVs + 1
	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)
	ld hl, wRoamMon1DVs + 1
	call BattleRandom
	ld [hld], a
	ld c, a
	call BattleRandom
	ld [hl], a
	ld b, a
; We're done with DVs
	jr .UpdateDVs

.NotRoaming
; Register a contains wBattleType

; Forced shiny battle type
; Used by Red Gyarados at Lake of Rage
	cp a, BATTLETYPE_SHINY
	jr nz, .check_park_minigame

	ld b, ATKDEFDV_SHINY ; $ea
	ld c, SPDSPCDV_SHINY ; $aa
	jr .UpdateDVs

.check_park_minigame
; If we're in the park minigame, DVs are already generated
	CheckEngine ENGINE_PARK_MINIGAME
	jr z, .GenerateDVs
	ld hl, wParkMinigameCurrentSpotDVs
	ld a, [hli]
	ld b, a
	ld c, [hl]
	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

.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_STAT_EXP - 1) - (MON_DVS)
	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, [wEnemySubStatus5]
	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, [wBattleType]
	cp a, BATTLETYPE_ROAMING
	jr nz, .Moves

; Grab HP
	ld hl, wRoamMon1HP
	ld a, [hli]
; Check if it's been initialized again
	or [hl]
	jr z, .InitRoamHP
; Update from the struct if it has
	ld a, [hl]
	ld [EnemyMonHP + 1], a
	jr .Moves

.InitRoamHP
	ld a, [EnemyMonHP + 1]
	ld [hld], a
	ld a, [EnemyMonHP]
	ld [hl], a
	jr .Moves

.OpponentParty
; Get HP from the party struct
	ld hl, (OTPartyMon1HP + 1)
	ld a, [wCurPartyMon]
	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, [wCurPartyMon]
	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 TRAINER_BATTLE
	jr nz, .WildMoves
; Then copy moves from the party struct
	ld hl, OTPartyMon1Moves
	ld a, [wCurPartyMon]
	call GetPartyLocation
	ld bc, NUM_MOVES
	rst CopyBytes
	jr .PP

.WildMoves
; Clear EnemyMonMoves
	ld a, [wWildMonCustomMoves]
	and a
	jr z, .notCustom
	ld hl, wWildMonCustomMoves
	ld bc, NUM_MOVES
	rst CopyBytes
	xor a
	ld [wWildMonCustomMoves], a
	jr .PP
.notCustom
	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 [wFillMoves_IsPartyMon], 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, [wCurPartyMon]
	call GetPartyLocation
	ld de, EnemyMonPP
	ld bc, NUM_MOVES
	rst 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, wStringBuffer1
	ld de, EnemyMonNick
	ld bc, PKMN_NAME_LENGTH
	rst CopyBytes

; Saw this mon
	ld a, [TempEnemyMonSpecies]
	dec a
	ld c, a
	ld b, SET_FLAG
	ld hl, PokedexSeen
	predef FlagAction

	ld hl, EnemyMonStats
	ld de, EnemyStats
	ld bc, EnemyMonStatsEnd - EnemyMonStats
	rst CopyBytes

	jp CalcEnemyAbility

CheckSleepingTreeMon:
; Return carry if species is in the list
; for the current time of day

; Don't do anything if this isn't a tree encounter
	ld a, [wBattleType]
	cp 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]
	call IsInSingularArray
; If it's a match, the opponent is asleep
	ret c

.NotSleeping
	and a
	ret

.Nite
	db CATERPIE
	db METAPOD
	db BUTTERFREE
	db EXEGGCUTE
	db -1 ; end

.Day
	db VENONAT
	db SPINARAK
	db -1 ; end

.Morn
	db VENONAT
	db SPINARAK
	db -1 ; end

BattleWinSlideInEnemyTrainerFrontpic:
	xor a
	ld [TempEnemyMonSpecies], a
	call FinishBattleAnim
	ld a, [OtherTrainerClass]
	ld [TrainerClass], a
	ld de, vBGTiles
	predef GetTrainerPic
	hlcoord 19, 0
	ld c, 0

.outer_loop
	inc c
	ld a, c
	cp 7
	ret z
	xor a
	ld [hBGMapMode], a
	ld [hBGMapHalf], a
	ld d, a
	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, 3
	call DelayFrames
	pop hl
	pop bc
	dec hl
	jr .outer_loop

.CopyColumn
	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

ApplyStatusEffectOnPlayerStats:
	ld a, 1
	jr ApplyStatusEffectOnStats

ApplyStatusEffectOnEnemyStats:
	xor a
	; fallthrough

ApplyStatusEffectOnStats:
	ld [hBattleTurn], a
	call ApplyPrzEffectOnSpeed
	jp ApplyBrnEffectOnAttack

ApplyPrzEffectOnSpeed:
	ld a, [hBattleTurn]
	and a
	jr z, .enemy
	ld a, [BattleMonStatus]
	and 1 << PAR
	ret z
	ld a, [PlayerAbility]
	cp ABILITY_QUICK_FEET
	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 a, [EnemyAbility]
	cp ABILITY_QUICK_FEET
	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

ApplyBrnEffectOnAttack:
; Guts ignore Burn penalties
	call GetTargetAbility
	cp ABILITY_GUTS
	ret z

	ld a, [hBattleTurn]
	and a
	ld hl, EnemyMonAttack
	ld a, [EnemyMonStatus]
	jr z, .checkEnemy
	ld hl, BattleMonAttack
	ld a, [BattleMonStatus]
.checkEnemy
	and 1 << BRN
	ret z
	srl [hl]
	inc hl
	rr [hl]
	ret

ApplyStatLevelMultiplierOnAllStats:
; 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

ApplyStatLevelMultiplier:
	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
	predef Multiply
	ld a, [hl]
	ld [hDivisor], a
	ld b, $4
	predef Divide
	pop hl

	; cap at 2,560. This is purely a failsafe, as the maximum legal value is 2,432.
	ld a, [hQuotient + 1]
	cp 10
	jp c, .okay3

	ld a, 10
	ld [hQuotient + 1], a
	xor a
	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

.StatLevelMultipliers
;	     /
	db 1, 4 ; 25%
	db 2, 7 ; 29%
	db 1, 3 ; 33%
	db 2, 5 ; 40%
	db 1, 2 ; 50%
	db 2, 3 ; 67%

	db 1, 1 ; 100%

	db 3, 2 ; 150%
	db 2, 1 ; 200%
	db 5, 2 ; 250%
	db 3, 1 ; 300%
	db 7, 2 ; 350%
	db 4, 1 ; 400%

_LoadBattleFontsHPBar:
	jpba LoadBattleFontsHPBar

_LoadHPBar:
	jpba LoadHPBar

EmptyBattleTextBox:
	ld hl, GenericDummyString
	jp BattleTextBox

_BattleRandom::
; If the normal RNG is used in a link battle it'll desync.
; To circumvent this a shared PRNG is used instead.

; 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

Call_PlayBattleAnim_OnlyIfVisible:
	ld a, BATTLE_VARS_SUBSTATUS3
	call GetBattleVar
	and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
	ret nz
	; fallthrough

Call_PlayBattleAnim:
	ld a, e
	ld [FXAnimIDLo], a
	ld a, d
	ld [FXAnimIDHi], a
	or e
	ret z
	call ApplyTilemapInVBlank
	predef_jump PlayBattleAnim

FinishBattleAnim:
	push af
	push bc
	push de
	push hl
	ld b, SCGB_BATTLE_COLORS
	predef GetSGBLayout
	call SetPalettes
	call DelayFrame
	pop hl
	pop de
	pop bc
	pop af
	ret

UpdateBattleStateAndExperienceAfterEnemyFaint:
	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, wPlayerSubStatus3
	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
	call z, 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

CatchPokemon_GiveExperience:
; Don't give experience if linked or in the Battle Tower.
	ld a, [wLinkMode]
	and a
	ret nz

	ld a, [InBattleTowerBattle]
	and 5
	ret nz

	CheckEngine ENGINE_HYPER_SHARE_ENABLED
	jp nz, GiveExperiencePoints

	call IsAnyMonHoldingExpShare
	ld a, [wBattleParticipantsNotFainted]
	push af
	or d
	ld [wBattleParticipantsNotFainted], a
	call GiveExperiencePoints
	pop af
	ld [wBattleParticipantsNotFainted], a
	ret

INCLUDE "battle/experience.asm"

SendOutPkmnText:
	CheckEngine ENGINE_POKEMON_MODE
	ret nz

	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 we're in the middle of the battle
	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, 100
	ld [hMultiplier], a
	predef Multiply
	ld hl, EnemyMonMaxHP
	ld a, [hli]
	ld [hDivisor], a
	ld a, [hl]
	ld [hDivisor + 1], a
	predef DivideLong

	ld a, [hLongQuotient + 3]
	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

JumpText_GoPkmn:
	text_far Text_GoPkmn
	start_asm
	jr Function_TextJump_BattleMonNick01

JumpText_DoItPkmn:
	text_far Text_DoItPkmn
	start_asm
	jr Function_TextJump_BattleMonNick01

JumpText_GoForItPkmn:
	text_far Text_GoForItPkmn
	start_asm
	jr Function_TextJump_BattleMonNick01

JumpText_YourFoesWeakGetmPkmn:
	text_far Text_YourFoesWeakGetmPkmn
	start_asm
Function_TextJump_BattleMonNick01:
	ld hl, TextJump_BattleMonNick01
	ret

TextJump_BattleMonNick01:
	text_jump Text_BattleMonNick01

WithdrawPkmnText:
	ld hl, .WithdrawPkmnText
	jp BattleTextBox

.WithdrawPkmnText
	text_far 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
	sbc a ; sign-extend the value, so negative numbers give a huge result
	ld [hMultiplicand], a
	ld a, 100
	ld [hMultiplier], a
	predef Multiply
	ld a, [hli]
	ld [hDivisor], a
	ld a, [hl]
	ld [hDivisor + 1], a
	predef DivideLong
	pop bc
	pop de
	ld a, [hLongQuotient + 2] ; negative differences give huge results when dividing, that overflow one byte
	ld hl, TextJump_ThatsEnoughComeBack
	and a
	ret nz
	ld a, [hLongQuotient + 3]
	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

TextJump_ThatsEnoughComeBack:
	text_jump Text_ThatsEnoughComeBack

TextJump_OKComeBack:
	text_jump Text_OKComeBack

TextJump_GoodComeBack:
	text_jump Text_GoodComeBack

TextJump_ComeBack:
	text_jump Text_ComeBack

GetMonBackpic:
	ld a, [wPlayerSubStatus4]
	bit SUBSTATUS_SUBSTITUTE, a
	ld hl, BattleAnimCmd_RaiseSub
	jr nz, GetBackpic_DoAnim ; substitute
	; fallthrough

DropPlayerSub:
	ld a, [wPlayerMinimized]
	and a
	ld hl, BattleAnimCmd_MinimizeOpp
	jr nz, GetBackpic_DoAnim
	ld a, [wCurPartySpecies]
	push af
	ld a, [BattleMonSpecies]
	ld [wCurPartySpecies], a
	ld de, vBGTiles tile $31
	predef GetBackpic
	pop af
	ld [wCurPartySpecies], a
	ret

GetBackpic_DoAnim:
	ld a, [hBattleTurn]
	push af
	xor a
	ld [hBattleTurn], a
	ld a, BANK(BattleAnimCommands)
	call FarCall_hl
	pop af
	ld [hBattleTurn], a
	ret

GetMonFrontpic:
	ld a, [wEnemySubStatus4]
	bit SUBSTATUS_SUBSTITUTE, a
	ld hl, BattleAnimCmd_RaiseSub
	jr nz, GetFrontpic_DoAnim

DropEnemySub:
	ld a, [wEnemyMinimized]
	and a
	ld hl, BattleAnimCmd_MinimizeOpp
	jr nz, GetFrontpic_DoAnim

	ld a, [wCurPartySpecies]
	push af
	ld a, [EnemyMonSpecies]
	ld [wCurSpecies], a
	ld [wCurPartySpecies], a
	call GetBaseData
	ld de, vBGTiles
	predef GetAnimatedFrontpic
	pop af
	ld [wCurPartySpecies], a
	ret

GetFrontpic_DoAnim:
	ld a, [hBattleTurn]
	push af
	call SetEnemyTurn
	ld a, BANK(BattleAnimCommands)
	call FarCall_hl
	pop af
	ld [hBattleTurn], a
	ret

StartBattle:
; 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.
	call CancelMapSign
	ld a, [wPartyCount]
	and a
	ret z

	ld a, [TimeOfDayPal]
	push af
	call BattleIntro
	ld c, STOPWATCH_BATTLE
	callba RestartStopwatch
	call DoBattle
	ld hl, wStopwatchControl
	res STOPWATCH_BATTLE, [hl]
	call ExitBattle
	pop af
	ld [TimeOfDayPal], a
	call .UpdateBattleCounter
	call .UpdateBattleTotalTime
	scf
	ret
.UpdateBattleCounter:
	ld a, [wBattleResult]
	and 15
	ret nz
	ld hl, wBattlesWonCounter
	inc [hl]
	ret nz
	rept 2
		inc hl
		inc [hl]
		ret nz
	endr
	ld a, $ff
	ld [hld], a
	ld [hld], a
	ld [hl], a
	ret
.UpdateBattleTotalTime:
	lb bc, STOPWATCH_READ_FORMATTED, STOPWATCH_BATTLE
	callba ReadStopwatch
	ld hl, wTotalBattleTime + 5
	ld a, [hl]
	add a, e
	cp 100
	jr c, .noCarryHundredths
	sub 100
.noCarryHundredths
	ccf
	ld [hld], a
	ld a, [hl]
	adc d
	cp 60
	jr c, .noCarrySeconds
	sub 60
.noCarrySeconds
	ccf
	ld [hld], a
	ld a, [hl]
	adc c
	cp 60
	jr c, .noCarryMinutes
	sub 60
.noCarryMinutes
	ccf
	ld [hld], a
	ld a, [hLongQuotient + 3]
	adc [hl]
	ld [hld], a
	ld a, [hLongQuotient + 2]
	adc [hl]
	ld [hld], a
	ret nc
	inc [hl]
	ret

BattleIntro:
	call LoadTrainerOrWildMonPic
	xor a
	ld [TempBattleMonSpecies], a
	ld [wd0d2], a
	ld [hMapAnims], a
	callba DoBattleStartFunctions
	call InitEnemy
	call BackUpvBGAttrs
	ld b, SCGB_BATTLE_GRAYSCALE
	predef 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 0, 1
	lb bc, 3, 11
	call ClearBox
	call ClearSprites
	ld a, [wBattleMode]
	cp WILD_BATTLE
	call z, UpdateEnemyHUD
	ld a, $1
	ld [hBGMapMode], a
	ret

LoadTrainerOrWildMonPic:
	ld a, [OtherTrainerClass]
	and a
	jr nz, .Trainer
	ld a, [TempWildMonSpecies]
	ld [wCurPartySpecies], a

.Trainer
	ld [TempEnemyMonSpecies], a
	ret

InitEnemy:
	ld a, [OtherTrainerClass]
	and a
	jp nz, InitEnemyTrainer ; trainer
	jp InitEnemyWildmon ; wild

BackUpvBGAttrs:
	ld a, [rSVBK]
	push af
	wbk BANK(wDecompressScratch)
	ld hl, wDecompressScratch
	ld bc, $40 tiles ; vWindowAttrs - vBGAttrs
	ld a, $2
	call ByteFill
	ld a, [rVBK]
	push af
	vbk BANK(vBGAttrs)
	ld de, wDecompressScratch
	hlbgcoord 0, 0 ; vBGAttrs
	lb bc, BANK(BackUpvBGAttrs), $40
	call Request2bpp
	pop af
	ld [rVBK], a
	pop af
	ld [rSVBK], a
	ret

InitEnemyTrainer:
	ld [TrainerClass], a
	xor a
	ld [TempEnemyMonSpecies], a
	callba GetTrainerAttributes
	callba ReadTrainerParty

	ld a, [TrainerClass]
	cp RIVAL1
	jr nz, .ok
	xor a
	ld [OTPartyMon1Item], a
.ok

	ld de, vBGTiles
	predef 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
	ret nc
	xor a
	ld [wCurPartyMon], a
	ld a, [wPartyCount]
	ld b, a
.partyloop
	push bc
	ld a, MON_HP
	call GetPartyParamLocation
	ld a, [hli]
	or [hl]
	jr z, .skipfaintedmon
	ld c, HAPPINESS_GYMBATTLE
	callba ChangeHappiness
.skipfaintedmon
	pop bc
	dec b
	ret z
	ld hl, wCurPartyMon
	inc [hl]
	jr .partyloop

InitEnemyWildmon:
	ld a, WILD_BATTLE
	ld [wBattleMode], a
	call LoadEnemyMon
	ld hl, EnemyMonMoves
	ld de, wWildMonMoves
	ld bc, NUM_MOVES
	rst CopyBytes
	ld hl, EnemyMonPP
	ld de, wWildMonPP
	ld bc, NUM_MOVES
	rst CopyBytes
	ld a, [wCurPartySpecies]
	ld de, vBGTiles
	predef GetAnimatedFrontpic
	xor a
	ld [TrainerClass], a
	ld [hGraphicStartTile], a
	hlcoord 12, 0
	lb bc, 7, 7
	predef_jump PlaceGraphic

ExitBattle:
	call .HandleEndOfBattle
	call BattleEnd_HandleRoamMons
	xor a
	ld [Danger], a
	ld [wBattleMode], a
	ld [wBattleType], 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 [wRespawnableEventMonBaseIndex], a
	ld hl, wPlayerSubStatus1
	ld b, EnemyFuryCutterCount - wPlayerSubStatus1
.loop
	ld [hli], a
	dec b
	jr nz, .loop
	jp WaitSFX

.HandleEndOfBattle
	ld a, [wLinkMode]
	and a
	jr z, .notLinked
	call ShowLinkBattleParticipantsAfterEnd
	ld c, 150
	call DelayFrames
	jp DetermineLinkBattleResult

.notLinked
	ld a, [wBattleResult]
	and $f
	ret nz
	call PostBattleUpdateParty
	xor a
	ld [wForceEvolution], a
	callba EvolveAfterBattle
	jpba GivePokerusAndConvertBerries

PostBattleUpdateParty:
; Does party updates after battle -- Natural Cure status heal and Stat Exp recalculation
	ld a, [wPartyCount]
.loop
	dec a
	push af
	ld [wCurPartyMon], a
	xor a
	call GetPartyParamLocation
	call CalcPartyMonAbility
	cp ABILITY_NATURAL_CURE
	jr nz, .natural_cure_done
	ld a, MON_STATUS
	call GetPartyParamLocation
	ld [hl], 0
.natural_cure_done
	callba UpdatePkmnStats
	pop af
	jr nz, .loop
	ret

ShowLinkBattleParticipantsAfterEnd:
	ld a, [CurOTMon]
	ld hl, OTPartyMon1Status
	call GetPartyLocation
	ld a, [EnemyMonStatus]
	ld [hl], a
	call ClearTileMap
	jpba _ShowLinkBattleParticipants

DetermineLinkBattleResult:
	callba _DetermineLinkBattleResult

	ld a, [wBattleResult]
	and $f
	cp $1
	jr c, .victory
	jr z, .loss
	ld de, .Draw
	jr .storeResult

.victory
	ld de, .Win
	jr .storeResult

.loss
	ld de, .Lose

.storeResult
	hlcoord 6, 8
	call PlaceText
	ld c, 200
	call DelayFrames

	sbk BANK(sLinkBattleStats)

	call AddLastLinkBattleToLinkRecord
	call ReadAndPrintLinkBattleRecord

	scls
	call WaitPressAorB_BlinkCursor
	jp ClearTileMap

.Win
	text "YOU WIN"
	done
.Lose
	text "YOU LOSE"
	done
.Draw
	text "  DRAW"
	done

DisplayLinkRecord:
	sbk BANK(sLinkBattleStats)

	call ReadAndPrintLinkBattleRecord

	scls
	hlcoord 0, 0, AttrMap
	xor a
	ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
	call ByteFill
	call ApplyAttrAndTilemapInVBlank
	ld b, SCGB_SCROLLINGMENU
	predef GetSGBLayout
	call SetPalettes
	ld c, 8
	call DelayFrames
	jp WaitPressAorB_BlinkCursor

ReadAndPrintLinkBattleRecord:
	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, wBufferMonNick
	ld bc, 10
	rst CopyBytes
	ld a, "@"
	ld [de], a
	inc de
	ld bc, 6
	rst CopyBytes
	ld de, wBufferMonNick
	pop hl
	call PlaceString
	pop hl
	ld de, 26
	add hl, de
	push hl
	ld de, wBufferMonOT
	lb bc, 2, 4
	push bc
	call PrintNum
	pop bc
	pop hl
	ld de, 5
	add hl, de
	push hl
	ld de, wBufferMonOT + 2
	push bc
	call PrintNum
	pop bc
	pop hl
	ld de, 5
	add hl, de
	ld de, wBufferMonOT + 4
	call PrintNum
	jr .next

.PrintFormatString
	ld de, .Format
	call PlaceText
.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 PlaceText

	hlcoord 0, 6
	ld de, .Result
	call PlaceText

	hlcoord 0, 2
	ld de, .Total
	call PlaceText

	hlcoord 6, 4
	ld de, sLinkBattleWins
	call .PrintZerosIfNoSaveFileExists
	ret c

	lb bc, 2, 4
	push bc
	call PrintNum

	hlcoord 11, 4
	ld de, sLinkBattleLosses
	call .PrintZerosIfNoSaveFileExists

	pop bc
	push bc
	call PrintNum

	hlcoord 16, 4
	ld de, sLinkBattleDraws
	call .PrintZerosIfNoSaveFileExists

	pop bc
	jp PrintNum

.PrintZerosIfNoSaveFileExists
	ld a, [wSavedAtLeastOnce]
	and a
	ret nz
	ld de, .zero_scores
	call PlaceText
	scf
	ret

.zero_scores
	db TX_COMPRESSED, $92, $0b, $12, $48, $2c, $49, $20
	db $b1, $4d

.Format
	db TX_COMPRESSED, $90, $08, $10, $32
	db $09, $ac, $0e, $49, $24, $92, $01, $92, $40, $32, $48
	db $06, $9a
.Record
	text "<PLAYER>'s RECORD"
	done
.Result
	text "RESULT WIN LOSE DRAW"
	done
.Total
	text "TOTAL  WIN LOSE DRAW"
	done

BattleEnd_HandleRoamMons:
	ld a, [wBattleType]
	cp BATTLETYPE_ROAMING
	jr nz, .not_roaming
	ld a, [wBattleResult]
	and $f
	jr z, .caught_or_defeated_roam_mon
	ld hl, wRoamMon1HP
	ld a, [EnemyMonHP]
	ld [hli],  a
	ld a, [EnemyMonHP + 1]
	ld [hl], a
	jr .update_roam_mons

.caught_or_defeated_roam_mon
	ld hl, wRoamMon1HP
	xor a
	ld [hli], a
	ld [hl], a
	dec a
	ld hl, wRoamMon1MapGroup
	ld [hl], a
	ld hl, wRoamMon1MapNumber
	ld [hl], a
	inc a
	ld hl, wRoamMon1Species
	ld [hl], a
	ret

.not_roaming
	call BattleRandom
	and $f
	ret nz

.update_roam_mons
	jpba UpdateRoamMons

AddLastLinkBattleToLinkRecord:
	ld hl, OTPlayerID
	ld de, wStringBuffer1
	ld bc, 2
	rst CopyBytes
	ld hl, OTPlayerName
	ld bc, NAME_LENGTH - 1
	rst CopyBytes
	ld hl, sLinkBattleResults
	call .StoreResult
	ld hl, sLinkBattleRecord
	ld d, 5
.loop
	push hl
	inc hl
	inc hl
	ld a, [hld]
	dec hl
	and a
	jr z, .copy
	push de
	ld c, 12
	ld de, wStringBuffer1
	call StringCmp
	pop de
	pop hl
	jr z, .done
	ld bc, 18
	add hl, bc
	dec d
	jr nz, .loop
	ld bc, -18
	add hl, bc
	push hl

.copy
	ld d, h
	ld e, l
	ld hl, wStringBuffer1
	ld bc, 12
	rst CopyBytes
	ld b, 6
	xor a
.loop2
	ld [de], a
	inc de
	dec b
	jr nz, .loop2
	pop hl

.done
	call .StoreResult
	jp .FindOpponentAndAppendRecord

.StoreResult
	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

.CheckOverflow
	dec hl
	ld a, [hl]
	inc hl
	cp 9999 / $100
	ret c
	ld a, [hl]
	cp 9999 % $100
	ret

.FindOpponentAndAppendRecord
	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
	lb bc, $0, $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 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
	rst AddNTimes
	push hl
	ld de, wd002
	ld bc, 18
	rst CopyBytes
	pop hl
	pop bc
	push hl
	ld a, c
	ld bc, 18
	ld hl, sLinkBattleRecord
	rst AddNTimes
	pop de
	push hl
	ld bc, 18
	rst CopyBytes
	ld hl, wd002
	ld bc, 18
	pop de
	rst CopyBytes
	ret

.LoadPointer
	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

InitBattleDisplay:
	call .InitBackPic
	hlcoord 0, 12
	lb bc, 4, 18
	call TextBox
	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 ApplyTilemapInVBlank
	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 ApplyTilemapInVBlank
	call HideSprites
	ld b, SCGB_BATTLE_COLORS
	predef GetSGBLayout
	call SetPalettes
	ld a, $90
	ld [hWY], a
	xor a
	ld [hSCX], a
	ret

.BlankBGMap
	ld a, [rSVBK]
	push af
	wbk BANK(wDecompressScratch)

	ld hl, wDecompressScratch
	ld bc, wBackupAttrMap - wDecompressScratch
	ld a, " "
	call ByteFill

	ld de, wDecompressScratch
	hlbgcoord 0, 0
	lb bc, BANK(InitBattleDisplay), $40
	call Request2bpp

	pop af
	ld [rSVBK], a
	ret

.InitBackPic
	CheckEngine ENGINE_POKEMON_MODE
	jr z, .playerBackpic

	ld hl, PartyMon1HP
	ld de, PARTYMON_STRUCT_LENGTH - 1
	ld c, 0
	jr .handleLoop
.loop
	add hl, de
	inc c
.handleLoop
	ld a, [hli]
	or [hl]
	jr z, .loop
	ld b, $0
	ld hl, wPartySpecies
	add hl, bc
	ld a, [wCurPartySpecies]
	push af
	ld a, [hl]
	ld [wCurPartySpecies], a
	ld [TempBattleMonSpecies], a
	ld de, vBGTiles tile $31
	predef GetBackpic
	pop af
	ld [wCurPartySpecies], a
	jr .continue

.playerBackpic
	callba GetPlayerBackpic
.continue
	ld hl, vObjTiles
	ld de, vBGTiles tile $31
	lb bc, BANK(InitBattleDisplay), 7 * 7
	call Get2bpp
	call .LoadTrainerBackpicAsOAM
	ld a, $31
	ld [hGraphicStartTile], a
	hlcoord 2, 6
	lb bc, 6, 6
	predef_jump PlaceGraphic

.LoadTrainerBackpicAsOAM
	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 a, d
	ld [hli], a
	ld a, e
	ld [hli], a
	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

BattleStartMessage:
	ld a, [wBattleMode]
	dec a
	jr z, .wild

	ld de, SFX_SHINE
	call PlayWaitSFX

	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 [wBattleAnimParam], a
	ld de, ANIM_SEND_OUT_MON
	call Call_PlayBattleAnim

.not_shiny
	callba CheckSleepingTreeMon
	jr c, .skip_cry

	;call CheckBattleScene
	;jr c, .cry_no_anim

	hlcoord 12, 0
	lb de, $0, ANIM_MON_NORMAL
	predef AnimateFrontpic
	jr .skip_cry ; cry is played during the animation

.cry_no_anim
	call DelayFrame
	ld a, $0f
	ld [CryTracks], a
	ld a, [TempEnemyMonSpecies]
	call PlayStereoCry

.skip_cry
	ld a, [wBattleType]
	cp BATTLETYPE_FISH
	jr nz, .NotFishing

	ld hl, HookedPokemonAttackedText
	jr .PlaceBattleStartText

.NotFishing
	ld hl, PokemonFellFromTreeText
	cp BATTLETYPE_TREE
	jr z, .PlaceBattleStartText
	ld hl, WildPokemonAppearedText

.PlaceBattleStartText
	push hl
	callba BattleStart_TrainerHuds
	pop hl
	jp StdBattleTextBox

AbilityOnMonEntrance:
	ld a, [hLinkPlayerNumber]
	cp $1
	jr z, .reverse

	call PlayerAbilityOnMonEntrance
	jr EnemyAbilityOnMonEntrance

.reverse
	call EnemyAbilityOnMonEntrance
PlayerAbilityOnMonEntrance:
	call SetPlayerTurn
	ld hl, wPlayerJustSentMonOut
	jr CheckAbilityOnMonEntrance

EnemyAbilityOnMonEntrance:
	call SetEnemyTurn
	ld hl, wEnemyJustSentMonOut

CheckAbilityOnMonEntrance:
	ld a, [hl]
	and a
	ld [hl], 0
	jr nz, .DoAbilityCheck

	; If we have Trace, check anyway. This allows a mon that failed to trace an ability
	; earlier to do so later on in the match (this is how Trace is supposed to work).
	call GetUserAbility_IgnoreMoldBreaker
	cp ABILITY_TRACE
	ret nz

.DoAbilityCheck:
	ld a, [wBattleTurnTemp]
	push af
	ld a, [hBattleTurn]
	ld [wBattleTurnTemp], a
	call GetUserAbility_IgnoreMoldBreaker
	ld [wMoveIsAnAbility], a
	ld hl, .Abilities
	ld e, 3
	call IsInArray
	jr nc, .skip
	call CallLocalPointer_AfterIsInArray
.skip
	xor a
	ld [wMoveIsAnAbility], a
	pop af
	ld [wBattleTurnTemp], a
	ret

.Abilities
	dbw ABILITY_INTIMIDATE, .Intimidate
	dbw ABILITY_PRESSURE, .Pressure
	dbw ABILITY_DRIZZLE, .Drizzle
	dbw ABILITY_DROUGHT, .Drought
	dbw ABILITY_SAND_STREAM, .SandStream
	dbw ABILITY_SNOW_WARNING, .SnowWarning
	dbw ABILITY_TRACE, .Trace
	dbw ABILITY_MOLD_BREAKER, .MoldBreaker
	dbw ABILITY_FRISK, .Frisk
	dbw ABILITY_DOWNLOAD, .Download
	dbw ABILITY_AIR_LOCK, .AirLock
	dbw ABILITY_NATURAL_CURE, .NaturalCure
	db -1

.NaturalCure
	ld a, BATTLE_VARS_STATUS
	call GetBattleVarAddr
	ld [hl], 0
	jp UpdateUserInParty

.Intimidate
	ld a, [hBattleTurn]
	and a
	ld hl, wPlayerMoveStructEffect
	jr z, .okay
	ld hl, wEnemyMoveStructEffect
.okay
	ld [hl], EFFECT_ATTACK_DOWN
	callba BattleCommand_AttackDown
	callba BattleCommand_StatDownMessage
	jpba BattleCommand_StatDownFailText

.Pressure
	ld hl, PressureText
	jp StdBattleTextBox

.Drizzle
	jpba DrizzleFunction

.Drought
	jpba DroughtFunction

.SandStream
	jpba SandStreamFunction

.SnowWarning
	jpba SnowWarningFunction

.Trace
	ld a, [hBattleTurn]
	and a
	ld hl, PlayerAbility
	ld de, EnemyAbility
	jr z, .got_trace_ability
	push hl
	ld h, d
	ld l, e
	pop de
.got_trace_ability
	ld a, [de]
	and a
	call z, CalcTargetAbility
	cp ABILITY_TRACE
	ret z
	ld [hl], a
	ld [wd265], a
	ld [wMoveIsAnAbility], a
	call GetAbilityName
	ld hl, TraceText
	call StdBattleTextBox
	jp .DoAbilityCheck

.MoldBreaker
	ld hl, BreaksTheMoldText
	jp StdBattleTextBox

.Frisk
	call GetOpponentItem
	ld a, [hl]
	and a
	ret z
	ld [wd265], a
	call GetItemName
	ld hl, FriskText
	jp StdBattleTextBox

.Download
	ld hl, EnemyMonDefense + 1
	ld de, EnemyMonSpclDef + 1
	ld a, [hBattleTurn]
	and a
	jr z, .got_enemy_defs
	ld hl, BattleMonDefense + 1
	ld de, BattleMonSpclDef + 1
.got_enemy_defs
	ld a, [de]
	cp [hl]
	jr c, .boost_special
	jr nz, .boost_physical
	dec de
	dec hl
	ld a, [de]
	cp [hl]
	jr c, .boost_special
	jr nz, .boost_physical
.boost_special
	callba BattleCommand_SpecialAttackUp
	jr .afterFarCall
.boost_physical
	callba BattleCommand_AttackUp
.afterFarCall
	ld a, [FailedMessage]
	and a
	ret nz
	ld a, [wMoveIsAnAbility]
	ld [wd265], a
	call GetAbilityName
	ld hl, DownloadText
	call StdBattleTextBox
	jpba BattleCommand_StatUpMessage

.AirLock
	ld hl, AirLockText
	jp StdBattleTextBox

CheckPlayerArenaTrap:
	ld a, [PlayerAbility]
	cp ABILITY_MAGNET_PULL
	jr z, CheckEnemyIsSteelTypeForMagnetPull
	cp ABILITY_ARENA_TRAP
	jr nz, _NotArenaTrap
	ld a, [EnemyAbility]
	cp ABILITY_LEVITATE
	ret z
	ld hl, EnemyMonType
	jr ArenaTrapTypeCheck

CheckEnemyArenaTrap:
	ld a, [EnemyAbility]
	cp ABILITY_MAGNET_PULL
	jr z, CheckPlayerIsSteelTypeForMagnetPull
	cp ABILITY_ARENA_TRAP
	jr nz, _NotArenaTrap
	ld a, [PlayerAbility]
	cp ABILITY_LEVITATE
	ret z
	ld hl, BattleMonType
	jr ArenaTrapTypeCheck

_NotArenaTrap:
	and a
	ret

ArenaTrapTypeCheck:
	ld a, [hli]
	call .TypeCheck
	ret z
	ld a, [hl]
.TypeCheck
	cp FLYING
	ret z
	cp BIRD
	ret z
	cp GHOST
	ret z
	scf
	ret

CheckEnemyIsSteelTypeForMagnetPull:
	ld hl, EnemyMonType
	jr CheckOpponentIsSteelTypeForMagnetPull

CheckPlayerIsSteelTypeForMagnetPull:
	ld hl, BattleMonType
CheckOpponentIsSteelTypeForMagnetPull:
	ld a, [hli]
	cp STEEL
	jr z, .steel
	ld a, [hl]
	cp STEEL
	jr z, .steel
	and a
	ret

.steel
	scf
	ret

EndTurn_Abilities:
	call SetFastestTurn
	call .do_it
	call SwitchTurn

.do_it
	call GetUserAbility_IgnoreMoldBreaker
	and a
	ret z
	ld [wMoveIsAnAbility], a
	ld hl, .Abilities
	ld e, 4
	call IsInArray
	jr nc, .nope
	call FarPointerCall_AfterIsInArray
.nope
	xor a
	ld [wMoveIsAnAbility], a
	ret

.Abilities
	db ABILITY_MOODY
	dba BattleCommand_Moody
	db ABILITY_SPEED_BOOST
	dba DoSpeedUpCommandWithStatUpMessage
	db $ff

