diff options
author | entrpntr <entrpntr@gmail.com> | 2020-04-19 21:36:23 -0400 |
---|---|---|
committer | entrpntr <entrpntr@gmail.com> | 2020-04-19 21:36:23 -0400 |
commit | 0def3b67fa0a64bc2e2778c99c53e1a77cbf302c (patch) | |
tree | c70beb8a39f122cad0753a2f4974ac6d1712e3f6 | |
parent | 7b63a9c032a130a08fc554b9b6790fe47d170530 (diff) |
Start adding engine/battle/core.asm.
-rw-r--r-- | constants/battle_constants.asm | 3 | ||||
-rw-r--r-- | data/battle/held_heal_status.asm | 10 | ||||
-rw-r--r-- | data/battle/held_stat_up.asm | 9 | ||||
-rw-r--r-- | data/moves/effects_priorities.asm | 8 | ||||
-rw-r--r-- | data/trainers/leaders.asm | 32 | ||||
-rw-r--r-- | data/wild/flee_mons.asm | 35 | ||||
-rw-r--r-- | engine/battle/core.asm | 4623 | ||||
-rwxr-xr-x | engine/gfx/cgb_layouts.asm | 2 | ||||
-rwxr-xr-x | engine/gfx/color.asm | 6 | ||||
-rwxr-xr-x | engine/gfx/sgb_layouts.asm | 2 | ||||
-rwxr-xr-x | engine/items/item_effects.asm | 12 | ||||
-rw-r--r-- | engine/pokemon/bills_pc_top.asm | 2 | ||||
-rwxr-xr-x | engine/pokemon/move_mon.asm | 4 | ||||
-rw-r--r-- | home/map.asm | 4 | ||||
-rw-r--r-- | main.asm | 115 | ||||
-rw-r--r-- | wram.asm | 119 |
16 files changed, 4845 insertions, 141 deletions
diff --git a/constants/battle_constants.asm b/constants/battle_constants.asm index 796697db..5442e2c3 100644 --- a/constants/battle_constants.asm +++ b/constants/battle_constants.asm @@ -16,6 +16,9 @@ MIN_NEUTRAL_DAMAGE EQU 2 ; turns that sleep lasts REST_SLEEP_TURNS EQU 2 +; default move priority +BASE_PRIORITY EQU 1 + ; type effectiveness factors, scaled by 10 SUPER_EFFECTIVE EQU 20 MORE_EFFECTIVE EQU 15 diff --git a/data/battle/held_heal_status.asm b/data/battle/held_heal_status.asm new file mode 100644 index 00000000..ac11b645 --- /dev/null +++ b/data/battle/held_heal_status.asm @@ -0,0 +1,10 @@ +; See also data/items/heal_status.asm + +HeldStatusHealingEffects: + db HELD_HEAL_POISON, 1 << PSN + db HELD_HEAL_FREEZE, 1 << FRZ + db HELD_HEAL_BURN, 1 << BRN + db HELD_HEAL_SLEEP, SLP + db HELD_HEAL_PARALYZE, 1 << PAR + db HELD_HEAL_STATUS, ALL_STATUS + db -1 ; end diff --git a/data/battle/held_stat_up.asm b/data/battle/held_stat_up.asm new file mode 100644 index 00000000..4f28c0d0 --- /dev/null +++ b/data/battle/held_stat_up.asm @@ -0,0 +1,9 @@ +HeldStatUpItems: + dbw HELD_ATTACK_UP, BattleCommand_AttackUp + dbw HELD_DEFENSE_UP, BattleCommand_DefenseUp + dbw HELD_SPEED_UP, BattleCommand_SpeedUp + dbw HELD_SP_ATTACK_UP, BattleCommand_SpecialAttackUp + dbw HELD_SP_DEFENSE_UP, BattleCommand_SpecialDefenseUp + dbw HELD_ACCURACY_UP, BattleCommand_AccuracyUp + dbw HELD_EVASION_UP, BattleCommand_EvasionUp + db -1 ; end diff --git a/data/moves/effects_priorities.asm b/data/moves/effects_priorities.asm new file mode 100644 index 00000000..dfdb636a --- /dev/null +++ b/data/moves/effects_priorities.asm @@ -0,0 +1,8 @@ +MoveEffectPriorities: + db EFFECT_PROTECT, 3 + db EFFECT_ENDURE, 3 + db EFFECT_PRIORITY_HIT, 2 + db EFFECT_FORCE_SWITCH, 0 + db EFFECT_COUNTER, 0 + db EFFECT_MIRROR_COAT, 0 + db -1 diff --git a/data/trainers/leaders.asm b/data/trainers/leaders.asm new file mode 100644 index 00000000..a41f641e --- /dev/null +++ b/data/trainers/leaders.asm @@ -0,0 +1,32 @@ +; These lists determine the battle music and victory music, and whether to +; award HAPPINESS_GYMBATTLE for winning. + +; Note: CHAMPION and RED are unused for battle music checks, since they are +; accounted for prior to the list check. + +GymLeaders: + db FALKNER + db WHITNEY + db BUGSY + db MORTY + db PRYCE + db JASMINE + db CHUCK + db CLAIR + db WILL + db BRUNO + db KAREN + db KOGA + db CHAMPION + db RED +; fallthrough +KantoGymLeaders: + db BROCK + db MISTY + db LT_SURGE + db ERIKA + db JANINE + db SABRINA + db BLAINE + db BLUE + db -1 diff --git a/data/wild/flee_mons.asm b/data/wild/flee_mons.asm new file mode 100644 index 00000000..1c3700fd --- /dev/null +++ b/data/wild/flee_mons.asm @@ -0,0 +1,35 @@ +FleeMons: +; referenced by TryEnemyFlee and FastBallMultiplier + +SometimesFleeMons: + db MAGNEMITE + db GRIMER + db TANGELA + db MR__MIME + db EEVEE + db PORYGON + db DRATINI + db DRAGONAIR + db TOGETIC + db UMBREON + db UNOWN + db SNUBBULL + db HERACROSS + db -1 + +OftenFleeMons: + db CUBONE + db ARTICUNO + db ZAPDOS + db MOLTRES + db QUAGSIRE + db DELIBIRD + db PHANPY + db TEDDIURSA + db -1 + +AlwaysFleeMons: + db RAIKOU + db ENTEI + db SUICUNE + db -1 diff --git a/engine/battle/core.asm b/engine/battle/core.asm new file mode 100644 index 00000000..04769f46 --- /dev/null +++ b/engine/battle/core.asm @@ -0,0 +1,4623 @@ +; Core components of the battle engine. + +DoBattle: + xor a + ld [wBattleParticipantsNotFainted], a + ld [wBattleParticipantsIncludingFainted], a + ld [wBattlePlayerAction], a + ld [wBattleEnded], a + inc a + ld [wBattleHasJustStarted], a + ld hl, wOTPartyMon1HP + ld bc, PARTYMON_STRUCT_LENGTH - 1 + ld d, BATTLEACTION_SWITCH1 - 1 +.loop + inc d + ld a, [hli] + or [hl] + jr nz, .alive + add hl, bc + jr .loop + +.alive + ld a, d + ld [wBattleAction], a + ld a, [wLinkMode] + and a + jr z, .not_linked + + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .player_2 + +.not_linked + ld a, [wBattleMode] + dec a + jr z, .wild + xor a + ld [wEnemySwitchMonIndex], a + call NewEnemyMonStatus + call ResetEnemyStatLevels + call BreakAttraction + call EnemySwitch + +.wild + ld c, 40 + call DelayFrames + +.player_2 + call LoadTilemapToTempTilemap + call CheckPlayerPartyForFitMon + ld a, d + and a + jp z, LostBattle + call SafeLoadTempTilemapToTilemap + ld a, [wBattleType] + cp BATTLETYPE_DEBUG + jp z, .tutorial_debug + cp BATTLETYPE_TUTORIAL + jp z, .tutorial_debug + xor a + ld [wCurPartyMon], a +.loop2 + call CheckIfCurPartyMonIsFitToFight + jr nz, .alive2 + ld hl, wCurPartyMon + inc [hl] + jr .loop2 + +.alive2 + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + inc a + ld hl, wPartySpecies - 1 + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wCurPartySpecies], a + ld [wTempBattleMonSpecies], a + hlcoord 1, 5 + ld a, 9 + call SlideBattlePicOut + call LoadTilemapToTempTilemap + call ResetBattleParticipants + call InitBattleMon + call ResetPlayerStatLevels + call SendOutMonText + call NewBattleMonStatus + call BreakAttraction + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + call SetPlayerTurn + call SpikesDamage + ld a, [wLinkMode] + and a + jr z, .not_linked_2 + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .not_linked_2 + xor a + ld [wEnemySwitchMonIndex], a + call NewEnemyMonStatus + call ResetEnemyStatLevels + call BreakAttraction + call EnemySwitch + call SetEnemyTurn + call SpikesDamage + +.not_linked_2 + jp BattleTurn + +.tutorial_debug + jp BattleMenu + +WildFled_EnemyFled_LinkBattleCanceled: + call SafeLoadTempTilemapToTilemap + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + add DRAW + ld [wBattleResult], a + ld a, [wLinkMode] + and a + ld hl, BattleText_WildFled + jr z, .print_text + + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + ld [wBattleResult], a ; WIN + ld hl, BattleText_EnemyFled + +.print_text + call StdBattleTextbox + call StopDangerSound + ld de, SFX_RUN + call PlaySFX + call SetPlayerTurn + callfar DummyPredef38 + ld a, 1 + ld [wBattleEnded], a + ret + +BattleTurn: +.loop + call CheckContestBattleOver + jr c, .quit + + xor a + ld [wPlayerIsSwitching], a + ld [wEnemyIsSwitching], a + ld [wBattleHasJustStarted], a + ld [wPlayerJustGotFrozen], a + ld [wEnemyJustGotFrozen], a + ld [wCurDamage], a + ld [wCurDamage + 1], a + + call HandleBerserkGene + call UpdateBattleMonInParty + farcall AIChooseMove + call CheckPlayerLockedIn + jr c, .skip_iteration +.loop1 + call BattleMenu + jr c, .quit + ld a, [wBattleEnded] + and a + jr nz, .quit + ld a, [wForcedSwitch] ; roared/whirlwinded/teleported + and a + jr nz, .quit +.skip_iteration + call ParsePlayerAction + jr nz, .loop1 + + call EnemyTriesToFlee + jr c, .quit + + call DetermineMoveOrder + jr c, .false + call Battle_EnemyFirst + jr .proceed +.false + call Battle_PlayerFirst +.proceed + ld a, [wForcedSwitch] + and a + jr nz, .quit + + ld a, [wBattleEnded] + and a + jr nz, .quit + + call HandleBetweenTurnEffects + ld a, [wBattleEnded] + and a + jr nz, .quit + jr .loop + +.quit + ret + +HandleBetweenTurnEffects: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .CheckEnemyFirst + call CheckFaint_PlayerThenEnemy + ret c + call HandleFutureSight + call CheckFaint_PlayerThenEnemy + ret c + call HandleWeather + call CheckFaint_PlayerThenEnemy + ret c + call HandleWrap + call CheckFaint_PlayerThenEnemy + ret c + call HandlePerishSong + call CheckFaint_PlayerThenEnemy + ret c + jr .NoMoreFaintingConditions + +.CheckEnemyFirst: + call CheckFaint_EnemyThenPlayer + ret c + call HandleFutureSight + call CheckFaint_EnemyThenPlayer + ret c + call HandleWeather + call CheckFaint_EnemyThenPlayer + ret c + call HandleWrap + call CheckFaint_EnemyThenPlayer + ret c + call HandlePerishSong + call CheckFaint_EnemyThenPlayer + ret c + +.NoMoreFaintingConditions: + call HandleLeftovers + call HandleMysteryberry + call HandleDefrost + call HandleSafeguard + call HandleScreens + call HandleStatBoostingHeldItems + call HandleHealingItems + call UpdateBattleMonInParty + call LoadTilemapToTempTilemap + jp HandleEncore + +CheckFaint_PlayerThenEnemy: + call HasPlayerFainted + jr nz, .PlayerNotFainted + call HandlePlayerMonFaint + ld a, [wBattleEnded] + and a + jr nz, .BattleIsOver + +.PlayerNotFainted: + call HasEnemyFainted + jr nz, .BattleContinues + call HandleEnemyMonFaint + ld a, [wBattleEnded] + and a + jr nz, .BattleIsOver + +.BattleContinues: + and a + ret + +.BattleIsOver: + scf + ret + +CheckFaint_EnemyThenPlayer: + call HasEnemyFainted + jr nz, .EnemyNotFainted + call HandleEnemyMonFaint + ld a, [wBattleEnded] + and a + jr nz, .BattleIsOver + +.EnemyNotFainted: + call HasPlayerFainted + jr nz, .BattleContinues + call HandlePlayerMonFaint + ld a, [wBattleEnded] + and a + jr nz, .BattleIsOver + +.BattleContinues: + and a + ret + +.BattleIsOver: + scf + ret + +HandleBerserkGene: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .reverse + + call .player + jr .enemy + +.reverse + call .enemy + ; fallthrough + +.player + call SetPlayerTurn + ld de, wPartyMon1Item + ld a, [wCurBattleMon] + ld b, a + jr .go + +.enemy + call SetEnemyTurn + ld de, wOTPartyMon1Item + ld a, [wCurOTMon] + ld b, a + ; fallthrough + +.go + push de + push bc + callfar GetUserItem + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + sub BERSERK_GENE + pop bc + pop de + ret nz + + ld [hl], a + + ld h, d + ld l, e + ld a, b + call GetPartyLocation + xor a + ld [hl], a + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVarAddr + push af + set SUBSTATUS_CONFUSED, [hl] + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVarAddr + push hl + push af + xor a + ld [hl], a + ld [wAttackMissed], a + ld [wEffectFailed], a + farcall BattleCommand_AttackUp2 + pop af + pop hl + ld [hl], a + call GetItemName + ld hl, BattleText_UsersStringBuffer1Activated + call StdBattleTextbox + callfar BattleCommand_StatUpMessage + pop af + bit SUBSTATUS_CONFUSED, a + ret nz + xor a + ld [wNumHits], a + ld de, ANIM_CONFUSED + call Call_PlayBattleAnim_OnlyIfVisible + call SwitchTurnCore + ld hl, BecameConfusedText + jp StdBattleTextbox + +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_STRUGGLE + jr z, .use_move + cp BATTLEACTION_SKIPTURN + jr z, .use_move + sub BATTLEACTION_SWITCH1 + jr c, .use_move + ld a, [wBattlePlayerAction] + cp BATTLEPLAYERACTION_SWITCH + jr nz, .switch + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .player_2 + + call BattleRandom + cp 50 percent + 1 + jp c, .player_first + jp .enemy_first + +.player_2 + call BattleRandom + cp 50 percent + 1 + jp c, .enemy_first + jp .player_first + +.switch + callfar AI_Switch + call SetEnemyTurn + call SpikesDamage + jp .enemy_first + +.use_move + ld a, [wBattlePlayerAction] + and a ; BATTLEPLAYERACTION_USEMOVE? + jp nz, .player_first + call CompareMovePriority + jr z, .equal_priority + jp c, .player_first ; player goes first + jp .enemy_first + +.equal_priority + call SetPlayerTurn + callfar GetUserItem + push bc + callfar GetOpponentItem + pop de + ld a, d + cp HELD_QUICK_CLAW + jr nz, .player_no_quick_claw + ld a, b + cp HELD_QUICK_CLAW + jr z, .both_have_quick_claw + call BattleRandom + cp e + jr nc, .speed_check + jp .player_first + +.player_no_quick_claw + ld a, b + cp HELD_QUICK_CLAW + jr nz, .speed_check + call BattleRandom + cp c + jr nc, .speed_check + jp .enemy_first + +.both_have_quick_claw + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .player_2b + call BattleRandom + cp c + jp c, .enemy_first + call BattleRandom + cp e + jp c, .player_first + jr .speed_check + +.player_2b + call BattleRandom + cp e + jp c, .player_first + call BattleRandom + cp c + jp c, .enemy_first + jr .speed_check + +.speed_check + ld de, wBattleMonSpeed + ld hl, wEnemyMonSpeed + ld c, 2 + call CompareBytes + jr z, .speed_tie + jp nc, .player_first + jp .enemy_first + +.speed_tie + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .player_2c + call BattleRandom + cp 50 percent + 1 + jp c, .player_first + jp .enemy_first + +.player_2c + call BattleRandom + cp 50 percent + 1 + jp c, .enemy_first +.player_first + scf + ret + +.enemy_first + and a + ret + +CheckContestBattleOver: + ld a, [wBattleType] + cp BATTLETYPE_CONTEST + jr nz, .contest_not_over + ld a, [wParkBallsRemaining] + and a + jr nz, .contest_not_over + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + add DRAW + ld [wBattleResult], a + scf + ret + +.contest_not_over + and a + ret + +CheckPlayerLockedIn: + ld a, [wPlayerSubStatus4] + and 1 << SUBSTATUS_RECHARGE + jp nz, .quit + + ld hl, wEnemySubStatus3 + res SUBSTATUS_FLINCHED, [hl] + ld hl, wPlayerSubStatus3 + res SUBSTATUS_FLINCHED, [hl] + + ld a, [hl] + and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE + jp nz, .quit + + ld hl, wPlayerSubStatus1 + bit SUBSTATUS_ROLLOUT, [hl] + jp nz, .quit + + and a + ret + +.quit + scf + ret + +ParsePlayerAction: + call CheckPlayerLockedIn + jp c, .locked_in + ld hl, wPlayerSubStatus5 + bit SUBSTATUS_ENCORED, [hl] + jr z, .not_encored + ld a, [wLastPlayerMove] + ld [wCurPlayerMove], a + jr .encored + +.not_encored + ld a, [wBattlePlayerAction] + cp BATTLEPLAYERACTION_SWITCH + jr z, .reset_rage + and a + jr nz, .reset_bide + ld a, [wPlayerSubStatus3] + and 1 << SUBSTATUS_BIDE + jr nz, .locked_in + xor a + ld [wMoveSelectionMenuType], a + inc a ; POUND + ld [wFXAnimID], a + call MoveSelectionScreen + push af + call SafeLoadTempTilemapToTilemap + call UpdateBattleHuds + ld a, [wCurPlayerMove] + cp STRUGGLE + jr z, .struggle + call PlayClickSFX + +.struggle + ld a, $1 + ldh [hBGMapMode], a + pop af + ret nz + +.encored + call SetPlayerTurn + callfar UpdateMoveData + xor a + ld [wPlayerCharging], a + ld a, [wPlayerMoveStruct + MOVE_EFFECT] + cp EFFECT_FURY_CUTTER + jr z, .continue_fury_cutter + xor a + ld [wPlayerFuryCutterCount], a + +.continue_fury_cutter + ld a, [wPlayerMoveStruct + MOVE_EFFECT] + cp EFFECT_RAGE + jr z, .continue_rage + ld hl, wPlayerSubStatus4 + res SUBSTATUS_RAGE, [hl] + xor a + ld [wPlayerRageCounter], a + +.continue_rage + ld a, [wPlayerMoveStruct + MOVE_EFFECT] + cp EFFECT_PROTECT + jr z, .continue_protect + cp EFFECT_ENDURE + jr z, .continue_protect + xor a + ld [wPlayerProtectCount], a + jr .continue_protect + +.reset_bide + ld hl, wPlayerSubStatus3 + res SUBSTATUS_BIDE, [hl] + +.locked_in + xor a + ld [wPlayerFuryCutterCount], a + ld [wPlayerProtectCount], a + ld [wPlayerRageCounter], a + ld hl, wPlayerSubStatus4 + res SUBSTATUS_RAGE, [hl] + +.continue_protect + call ParseEnemyAction + xor a + ret + +.reset_rage + xor a + ld [wPlayerFuryCutterCount], a + ld [wPlayerProtectCount], a + ld [wPlayerRageCounter], a + ld hl, wPlayerSubStatus4 + res SUBSTATUS_RAGE, [hl] + xor a + ret + +HandleEncore: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_1 + call .do_player + jr .do_enemy + +.player_1 + call .do_enemy +.do_player + ld hl, wPlayerSubStatus5 + bit SUBSTATUS_ENCORED, [hl] + ret z + ld a, [wPlayerEncoreCount] + dec a + ld [wPlayerEncoreCount], a + jr z, .end_player_encore + ld hl, wBattleMonPP + ld a, [wCurMoveNum] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + and PP_MASK + ret nz + +.end_player_encore + ld hl, wPlayerSubStatus5 + res SUBSTATUS_ENCORED, [hl] + call SetEnemyTurn + ld hl, BattleText_TargetsEncoreEnded + jp StdBattleTextbox + +.do_enemy + ld hl, wEnemySubStatus5 + bit SUBSTATUS_ENCORED, [hl] + ret z + ld a, [wEnemyEncoreCount] + dec a + ld [wEnemyEncoreCount], a + jr z, .end_enemy_encore + ld hl, wEnemyMonPP + ld a, [wCurEnemyMoveNum] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + and PP_MASK + ret nz + +.end_enemy_encore + ld hl, wEnemySubStatus5 + res SUBSTATUS_ENCORED, [hl] + call SetPlayerTurn + ld hl, BattleText_TargetsEncoreEnded + jp StdBattleTextbox + +TryEnemyFlee: + ld a, [wBattleMode] + dec a + jr nz, .Stay + + ld a, [wPlayerSubStatus5] + bit SUBSTATUS_CANT_RUN, a + jr nz, .Stay + + ld a, [wEnemyWrapCount] + and a + jr nz, .Stay + + ld a, [wEnemyMonStatus] + and 1 << FRZ | SLP + jr nz, .Stay + + ld a, [wTempEnemyMonSpecies] + ld de, 1 + ld hl, AlwaysFleeMons + call IsInArray + jr c, .Flee + + call BattleRandom + ld b, a + cp 50 percent + 1 + jr nc, .Stay + + push bc + ld a, [wTempEnemyMonSpecies] + ld de, 1 + ld hl, OftenFleeMons + call IsInArray + pop bc + jr c, .Flee + + ld a, b + cp 10 percent + 1 + jr nc, .Stay + + ld a, [wTempEnemyMonSpecies] + ld de, 1 + ld hl, SometimesFleeMons + call IsInArray + jr c, .Flee + +.Stay: + and a + ret + +.Flee: + scf + ret + +INCLUDE "data/wild/flee_mons.asm" + +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, [wCurPlayerMove] + call GetMovePriority + ld b, a + push bc + ld a, [wCurEnemyMove] + call GetMovePriority + pop bc + cp b + ret + +GetMovePriority: +; Return the priority (0-3) of move a. + + ld b, a + + ; Vital Throw goes last. + cp VITAL_THROW + ld a, 0 + ret z + + call GetMoveEffect + ld hl, MoveEffectPriorities +.loop + ld a, [hli] + cp b + jr z, .done + inc hl + cp -1 + jr nz, .loop + + ld a, BASE_PRIORITY + ret + +.done + ld a, [hl] + ret + +INCLUDE "data/moves/effects_priorities.asm" + +GetMoveEffect: + ld a, b + dec a + ld hl, Moves + MOVE_EFFECT + ld bc, MOVE_LENGTH + call AddNTimes + ld a, BANK(Moves) + call GetFarByte + ld b, a + ret + +Battle_EnemyFirst: + call LoadTilemapToTempTilemap + call TryEnemyFlee + jp c, WildFled_EnemyFled_LinkBattleCanceled + call SetEnemyTurn + ld a, $1 + ld [wEnemyGoesFirst], a + callfar AI_SwitchOrTryItem + jr c, .switch_item + call EnemyTurn_EndOpponentProtectEndureDestinyBond + ld a, [wForcedSwitch] + and a + ret nz + call HasPlayerFainted + jp z, HandlePlayerMonFaint + call HasEnemyFainted + jp z, HandleEnemyMonFaint + +.switch_item + call SetEnemyTurn + call ResidualDamage + jp z, HandleEnemyMonFaint + call RefreshBattleHuds + call PlayerTurn_EndOpponentProtectEndureDestinyBond + ld a, [wForcedSwitch] + and a + ret nz + call HasEnemyFainted + jp z, HandleEnemyMonFaint + call HasPlayerFainted + jp z, HandlePlayerMonFaint + call SetPlayerTurn + call ResidualDamage + jp z, HandlePlayerMonFaint + call RefreshBattleHuds + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ret + +Battle_PlayerFirst: + xor a + ld [wEnemyGoesFirst], a + call SetEnemyTurn + callfar AI_SwitchOrTryItem + push af + call PlayerTurn_EndOpponentProtectEndureDestinyBond + pop bc + ld a, [wForcedSwitch] + and a + ret nz + call HasEnemyFainted + jp z, HandleEnemyMonFaint + call HasPlayerFainted + jp z, HandlePlayerMonFaint + push bc + call SetPlayerTurn + call ResidualDamage + pop bc + jp z, HandlePlayerMonFaint + push bc + call RefreshBattleHuds + pop af + jr c, .switched_or_used_item + call LoadTilemapToTempTilemap + call TryEnemyFlee + jp c, WildFled_EnemyFled_LinkBattleCanceled + call EnemyTurn_EndOpponentProtectEndureDestinyBond + ld a, [wForcedSwitch] + and a + ret nz + call HasPlayerFainted + jp z, HandlePlayerMonFaint + call HasEnemyFainted + jp z, HandleEnemyMonFaint + +.switched_or_used_item + call SetEnemyTurn + call ResidualDamage + jp z, HandleEnemyMonFaint + call RefreshBattleHuds + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ret + +PlayerTurn_EndOpponentProtectEndureDestinyBond: + call SetPlayerTurn + call EndUserDestinyBond + callfar DoPlayerTurn + jp EndOpponentProtectEndureDestinyBond + +EnemyTurn_EndOpponentProtectEndureDestinyBond: + call SetEnemyTurn + call EndUserDestinyBond + callfar DoEnemyTurn + jp EndOpponentProtectEndureDestinyBond + +EndOpponentProtectEndureDestinyBond: + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + res SUBSTATUS_PROTECT, [hl] + res SUBSTATUS_ENDURE, [hl] + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + res SUBSTATUS_DESTINY_BOND, [hl] + ret + +EndUserDestinyBond: + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVarAddr + res SUBSTATUS_DESTINY_BOND, [hl] + ret + +HasUserFainted: + ldh a, [hBattleTurn] + and a + jr z, HasPlayerFainted +HasEnemyFainted: + ld hl, wEnemyMonHP + jr CheckIfHPIsZero + +HasPlayerFainted: + ld hl, wBattleMonHP + +CheckIfHPIsZero: + ld a, [hli] + or [hl] + ret + +ResidualDamage: +; Return z if the user fainted before +; or as a result of residual damage. +; For Sandstorm damage, see HandleWeather. + + call HasUserFainted + ret z + + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and 1 << PSN | 1 << BRN + jr z, .did_psn_brn + + ld hl, HurtByPoisonText + ld de, ANIM_PSN + and 1 << BRN + jr z, .got_anim + ld hl, HurtByBurnText + ld de, ANIM_BRN +.got_anim + + push de + call StdBattleTextbox + pop de + + xor a + ld [wNumHits], a + call Call_PlayBattleAnim_OnlyIfVisible + call GetEighthMaxHP + ld de, wPlayerToxicCount + ldh a, [hBattleTurn] + and a + jr z, .check_toxic + ld de, wEnemyToxicCount +.check_toxic + + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVar + bit SUBSTATUS_TOXIC, a + jr z, .did_toxic + call GetSixteenthMaxHP + ld a, [de] + inc a + ld [de], a + ld hl, 0 +.add + add hl, bc + dec a + jr nz, .add + ld b, h + ld c, l +.did_toxic + + call SubtractHPFromUser +.did_psn_brn + + call HasUserFainted + jp z, .fainted + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVarAddr + bit SUBSTATUS_LEECH_SEED, [hl] + jr z, .not_seeded + + call SwitchTurnCore + xor a + ld [wNumHits], a + ld de, ANIM_SAP + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + call z, Call_PlayBattleAnim_OnlyIfVisible + call SwitchTurnCore + + call GetEighthMaxHP + call SubtractHPFromUser + ld a, $1 + ldh [hBGMapMode], a + call RestoreHP + ld hl, LeechSeedSapsText + call StdBattleTextbox +.not_seeded + + call HasUserFainted + jr z, .fainted + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + bit SUBSTATUS_NIGHTMARE, [hl] + jr z, .not_nightmare + xor a + ld [wNumHits], a + ld de, ANIM_IN_NIGHTMARE + call Call_PlayBattleAnim_OnlyIfVisible + call GetQuarterMaxHP + call SubtractHPFromUser + ld hl, HasANightmareText + call StdBattleTextbox +.not_nightmare + + call HasUserFainted + jr z, .fainted + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + bit SUBSTATUS_CURSE, [hl] + jr z, .not_cursed + + xor a + ld [wNumHits], a + ld de, ANIM_IN_NIGHTMARE + call Call_PlayBattleAnim_OnlyIfVisible + call GetQuarterMaxHP + call SubtractHPFromUser + ld hl, HurtByCurseText + call StdBattleTextbox + +.not_cursed + ld hl, wBattleMonHP + ldh a, [hBattleTurn] + and a + jr z, .check_fainted + ld hl, wEnemyMonHP + +.check_fainted + ld a, [hli] + or [hl] + ret nz + +.fainted + call RefreshBattleHuds + ld c, 20 + call DelayFrames + xor a + ret + +HandlePerishSong: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .EnemyFirst + call SetPlayerTurn + call .do_it + call SetEnemyTurn + jp .do_it + +.EnemyFirst: + call SetEnemyTurn + call .do_it + call SetPlayerTurn + +.do_it + ld hl, wPlayerPerishCount + ldh a, [hBattleTurn] + and a + jr z, .got_count + ld hl, wEnemyPerishCount + +.got_count + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVar + bit SUBSTATUS_PERISH, a + ret z + dec [hl] + ld a, [hl] + ld [wDeciramBuffer], a + push af + ld hl, PerishCountText + call StdBattleTextbox + pop af + ret nz + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res SUBSTATUS_PERISH, [hl] + ldh a, [hBattleTurn] + and a + jr nz, .kill_enemy + ld hl, wBattleMonHP + xor a + ld [hli], a + ld [hl], a + ld hl, wPartyMon1HP + ld a, [wCurBattleMon] + call GetPartyLocation + xor a + ld [hli], a + ld [hl], a + ret + +.kill_enemy + ld hl, wEnemyMonHP + xor a + ld [hli], a + ld [hl], a + ld a, [wBattleMode] + dec a + ret z + ld hl, wOTPartyMon1HP + ld a, [wCurOTMon] + call GetPartyLocation + xor a + ld [hli], a + ld [hl], a + ret + +HandleWrap: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .EnemyFirst + call SetPlayerTurn + call .do_it + call SetEnemyTurn + jp .do_it + +.EnemyFirst: + call SetEnemyTurn + call .do_it + call SetPlayerTurn + +.do_it + ld hl, wPlayerWrapCount + ld de, wPlayerTrappingMove + ldh 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 [wNamedObjectIndexBuffer], a + ld [wFXAnimID], a + call GetMoveName + dec [hl] + jr z, .release_from_bounds + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + jr nz, .skip_anim + + call SwitchTurnCore + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + predef PlayBattleAnim + call SwitchTurnCore + +.skip_anim + call GetSixteenthMaxHP + call SubtractHPFromUser + ld hl, BattleText_UsersHurtByStringBuffer1 + jr .print_text + +.release_from_bounds + ld hl, BattleText_UserWasReleasedFromStringBuffer1 + +.print_text + jp StdBattleTextbox + +SwitchTurnCore: + ldh a, [hBattleTurn] + xor 1 + ldh [hBattleTurn], a + ret + +HandleLeftovers: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .DoEnemyFirst + call SetPlayerTurn + call .do_it + call SetEnemyTurn + jp .do_it + +.DoEnemyFirst: + call SetEnemyTurn + call .do_it + call SetPlayerTurn +.do_it + + callfar GetUserItem + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetItemName + ld a, b + cp HELD_LEFTOVERS + ret nz + + ld hl, wBattleMonHP + ldh a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wEnemyMonHP + +.got_hp +; Don't restore if we're already at max HP + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a + ld a, [hli] + cp b + jr nz, .restore + ld a, [hl] + cp c + ret z + +.restore + call GetSixteenthMaxHP + call SwitchTurnCore + call RestoreHP + ld hl, BattleText_TargetRecoveredWithItem + jp StdBattleTextbox + +HandleMysteryberry: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .DoEnemyFirst + call SetPlayerTurn + call .do_it + call SetEnemyTurn + jp .do_it + +.DoEnemyFirst: + call SetEnemyTurn + call .do_it + call SetPlayerTurn + +.do_it + callfar GetUserItem + ld a, b + cp HELD_RESTORE_PP + jr nz, .quit + ld hl, wPartyMon1PP + ld a, [wCurBattleMon] + call GetPartyLocation + ld d, h + ld e, l + ld hl, wPartyMon1Moves + ld a, [wCurBattleMon] + call GetPartyLocation + ldh a, [hBattleTurn] + and a + jr z, .wild + ld de, wWildMonPP + ld hl, wWildMonMoves + ld a, [wBattleMode] + dec a + jr z, .wild + ld hl, wOTPartyMon1PP + ld a, [wCurOTMon] + call GetPartyLocation + ld d, h + ld e, l + ld hl, wOTPartyMon1Moves + ld a, [wCurOTMon] + call GetPartyLocation + +.wild + ld c, $0 +.loop + ld a, [hl] + and a + jr z, .quit + ld a, [de] + and PP_MASK + jr z, .restore + inc hl + inc de + inc c + ld a, c + cp NUM_MOVES + jr nz, .loop + +.quit + ret + +.restore + ; lousy hack + ld a, [hl] + cp SKETCH + ld b, 1 + jr z, .sketch + ld b, 5 +.sketch + ld a, [de] + add b + ld [de], a + push bc + push bc + ld a, [hl] + ld [wTempByteValue], a + ld de, wBattleMonMoves - 1 + ld hl, wBattleMonPP + ldh a, [hBattleTurn] + and a + jr z, .player_pp + ld de, wEnemyMonMoves - 1 + ld hl, wEnemyMonPP +.player_pp + inc de + pop bc + ld b, 0 + add hl, bc + push hl + ld h, d + ld l, e + add hl, bc + pop de + pop bc + + ld a, [wTempByteValue] + cp [hl] + jr nz, .skip_checks + ldh a, [hBattleTurn] + and a + ld a, [wPlayerSubStatus5] + jr z, .check_transform + ld a, [wEnemySubStatus5] +.check_transform + bit SUBSTATUS_TRANSFORMED, a + jr nz, .skip_checks + ld a, [de] + add b + ld [de], a +.skip_checks + callfar GetUserItem + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + xor a + ld [hl], a + call GetPartymonItem + ldh a, [hBattleTurn] + and a + jr z, .consume_item + ld a, [wBattleMode] + dec a + jr z, .skip_consumption + call GetOTPartymonItem + +.consume_item + xor a + ld [hl], a + +.skip_consumption + call GetItemName + call SwitchTurnCore + call ItemRecoveryAnim + call SwitchTurnCore + ld hl, BattleText_UserRecoveredPPUsing + jp StdBattleTextbox + +HandleFutureSight: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .enemy_first + call SetPlayerTurn + call .do_it + call SetEnemyTurn + jp .do_it + +.enemy_first + call SetEnemyTurn + call .do_it + call SetPlayerTurn + +.do_it + ld hl, wPlayerFutureSightCount + ldh a, [hBattleTurn] + and a + jr z, .okay + ld hl, wEnemyFutureSightCount + +.okay + ld a, [hl] + and a + ret z + dec a + ld [hl], a + cp $1 + ret nz + + ld hl, BattleText_TargetWasHitByFutureSight + call StdBattleTextbox + + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + push af + ld a, FUTURE_SIGHT + ld [hl], a + + callfar UpdateMoveData + xor a + ld [wAttackMissed], a + ld [wAlreadyDisobeyed], a + ld a, EFFECTIVE + ld [wTypeModifier], a + callfar DoMove + xor a + ld [wCurDamage], a + ld [wCurDamage + 1], a + + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + pop af + ld [hl], a + + call UpdateBattleMonInParty + jp UpdateEnemyMonInParty + +HandleDefrost: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .enemy_first + call .do_player_turn + jr .do_enemy_turn + +.enemy_first + call .do_enemy_turn +.do_player_turn + ld a, [wBattleMonStatus] + bit FRZ, a + ret z + + ld a, [wPlayerJustGotFrozen] + and a + ret nz + + call BattleRandom + cp 10 percent + ret nc + xor a + ld [wBattleMonStatus], a + ld a, [wCurBattleMon] + ld hl, wPartyMon1Status + call GetPartyLocation + ld [hl], 0 + call UpdateBattleHuds + call SetEnemyTurn + ld hl, DefrostedOpponentText + jp StdBattleTextbox + +.do_enemy_turn + ld a, [wEnemyMonStatus] + bit FRZ, a + ret z + ld a, [wEnemyJustGotFrozen] + and a + ret nz + call BattleRandom + cp 10 percent + ret nc + xor a + ld [wEnemyMonStatus], a + + ld a, [wBattleMode] + dec a + jr z, .wild + ld a, [wCurOTMon] + ld hl, wOTPartyMon1Status + call GetPartyLocation + ld [hl], 0 +.wild + + call UpdateBattleHuds + call SetPlayerTurn + ld hl, DefrostedOpponentText + jp StdBattleTextbox + +HandleSafeguard: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player1 + call .CheckPlayer + jr .CheckEnemy + +.player1 + call .CheckEnemy +.CheckPlayer: + ld a, [wPlayerScreens] + bit SCREENS_SAFEGUARD, a + ret z + ld hl, wPlayerSafeguardCount + dec [hl] + ret nz + res SCREENS_SAFEGUARD, a + ld [wPlayerScreens], a + xor a + jr .print + +.CheckEnemy: + ld a, [wEnemyScreens] + bit SCREENS_SAFEGUARD, a + ret z + ld hl, wEnemySafeguardCount + dec [hl] + ret nz + res SCREENS_SAFEGUARD, a + ld [wEnemyScreens], a + ld a, $1 + +.print + ldh [hBattleTurn], a + ld hl, BattleText_SafeguardFaded + jp StdBattleTextbox + +HandleScreens: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .Both + call .CheckPlayer + jr .CheckEnemy + +.Both: + call .CheckEnemy + +.CheckPlayer: + call SetPlayerTurn + ld de, .Your + call .Copy + ld hl, wPlayerScreens + ld de, wPlayerLightScreenCount + jr .TickScreens + +.CheckEnemy: + call SetEnemyTurn + ld de, .Enemy + call .Copy + ld hl, wEnemyScreens + ld de, wEnemyLightScreenCount + +.TickScreens: + bit SCREENS_LIGHT_SCREEN, [hl] + call nz, .LightScreenTick + bit SCREENS_REFLECT, [hl] + call nz, .ReflectTick + ret + +.Copy: + ld hl, wStringBuffer1 + jp CopyName2 + +.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_MonsLightScreenFell + call StdBattleTextbox + pop de + pop hl + ret + +.ReflectTick: + inc de + ld a, [de] + dec a + ld [de], a + ret nz + res SCREENS_REFLECT, [hl] + ld hl, BattleText_MonsReflectFaded + jp StdBattleTextbox + +HandleWeather: + ld a, [wBattleWeather] + cp WEATHER_NONE + ret z + + ld hl, wWeatherCount + dec [hl] + jr z, .ended + + ld hl, .WeatherMessages + call .PrintWeatherMessage + + ld a, [wBattleWeather] + cp WEATHER_SANDSTORM + ret nz + + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .enemy_first + +.player_first + call SetPlayerTurn + call .SandstormDamage + call SetEnemyTurn + jr .SandstormDamage + +.enemy_first + call SetEnemyTurn + call .SandstormDamage + call SetPlayerTurn + +.SandstormDamage: + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + bit SUBSTATUS_UNDERGROUND, a + ret nz + + ld hl, wBattleMonType1 + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonType1 +.ok + ld a, [hli] + cp ROCK + ret z + cp GROUND + ret z + cp STEEL + ret z + + ld a, [hl] + cp ROCK + ret z + cp GROUND + ret z + cp STEEL + ret z + + call SwitchTurnCore + xor a + ld [wNumHits], a + ld de, ANIM_IN_SANDSTORM + call Call_PlayBattleAnim + call SwitchTurnCore + call GetEighthMaxHP + call SubtractHPFromUser + + ld hl, SandstormHitsText + jp StdBattleTextbox + +.ended + ld hl, .WeatherEndedMessages + call .PrintWeatherMessage + xor a + ld [wBattleWeather], a + ret + +.PrintWeatherMessage: + ld a, [wBattleWeather] + dec a + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + jp StdBattleTextbox + +.WeatherMessages: +; entries correspond to WEATHER_* constants + dw BattleText_RainContinuesToFall + dw BattleText_TheSunlightIsStrong + dw BattleText_TheSandstormRages + +.WeatherEndedMessages: +; entries correspond to WEATHER_* constants + dw BattleText_TheRainStopped + dw BattleText_TheSunlightFaded + dw BattleText_TheSandstormSubsided + +SubtractHPFromTarget: + call SubtractHP + jp UpdateHPBar + +SubtractHPFromUser: +; Subtract HP from mon + call SubtractHP + jp UpdateHPBarBattleHuds + +SubtractHP: + ld hl, wBattleMonHP + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonHP +.ok + inc hl + ld a, [hl] + ld [wBuffer3], a + sub c + ld [hld], a + ld [wBuffer5], a + ld a, [hl] + ld [wBuffer4], a + sbc b + ld [hl], a + ld [wBuffer6], a + ret nc + + ld a, [wBuffer3] + ld c, a + ld a, [wBuffer4] + ld b, a + xor a + ld [hli], a + ld [hl], a + ld [wBuffer5], a + ld [wBuffer6], a + ret + +GetSixteenthMaxHP: + call GetQuarterMaxHP +; quarter result + srl c + srl c +; at least 1 + ld a, c + and a + jr nz, .ok + inc c +.ok + ret + +GetEighthMaxHP: +; output: bc + call GetQuarterMaxHP +; assumes nothing can have 1024 or more hp +; halve result + srl c +; at least 1 + ld a, c + and a + jr nz, .end + inc c +.end + ret + +GetQuarterMaxHP: +; output: bc + call GetMaxHP + +; quarter result + srl b + rr c + srl b + rr c + +; assumes nothing can have 1024 or more hp +; at least 1 + ld a, c + and a + jr nz, .end + inc c +.end + ret + +GetHalfMaxHP: +; output: bc + call GetMaxHP + +; halve result + srl b + rr c + +; at least 1 + ld a, c + or b + jr nz, .end + inc c +.end + ret + +GetMaxHP: +; output: bc, wBuffer1-2 + + ld hl, wBattleMonMaxHP + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonMaxHP +.ok + ld a, [hli] + ld [wBuffer2], a + ld b, a + + ld a, [hl] + ld [wBuffer1], a + ld c, a + ret + +Unreferenced_GetHalfHP: + ld hl, wBattleMonHP + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonHP +.ok + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a + srl b + rr c + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + ret + +CheckUserHasEnoughHP: + ld hl, wBattleMonHP + 1 + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyMonHP + 1 +.ok + ld a, c + sub [hl] + dec hl + ld a, b + sbc [hl] + ret + +RestoreHP: + ld hl, wEnemyMonMaxHP + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wBattleMonMaxHP +.ok + ld a, [hli] + ld [wBuffer2], a + ld a, [hld] + ld [wBuffer1], a + dec hl + ld a, [hl] + ld [wBuffer3], a + add c + ld [hld], a + ld [wBuffer5], a + ld a, [hl] + ld [wBuffer4], a + adc b + ld [hli], a + ld [wBuffer6], a + + ld a, [wBuffer1] + ld c, a + ld a, [hld] + sub c + ld a, [wBuffer2] + ld b, a + ld a, [hl] + sbc b + jr c, .asm_3cd2d + ld a, b + ld [hli], a + ld [wBuffer6], a + ld a, c + ld [hl], a + ld [wBuffer5], a +.asm_3cd2d + + call SwitchTurnCore + call UpdateHPBarBattleHuds + jp SwitchTurnCore + +UpdateHPBarBattleHuds: + call UpdateHPBar + jp UpdateBattleHuds + +UpdateHPBar: + hlcoord 10, 9 + ldh a, [hBattleTurn] + and a + ld a, 1 + jr z, .ok + hlcoord 2, 2 + xor a +.ok + push bc + ld [wWhichHPBar], a + predef AnimateHPBar + pop bc + ret + +HandleEnemyMonFaint: + call FaintEnemyPokemon + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + call z, FaintYourPokemon + xor a + ld [wWhichMonFaintedFirst], a + call UpdateBattleStateAndExperienceAfterEnemyFaint + call CheckPlayerPartyForFitMon + ld a, d + and a + jp z, LostBattle + + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + call nz, UpdatePlayerHUD + + ld a, $1 + ldh [hBGMapMode], a + ld c, 60 + call DelayFrames + + ld a, [wBattleMode] + dec a + jr nz, .trainer + + ld a, 1 + ld [wBattleEnded], a + ret + +.trainer + call CheckEnemyTrainerDefeated + jp z, WinTrainerBattle + + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + jr nz, .player_mon_not_fainted + + call AskUseNextPokemon + jr nc, .dont_flee + + ld a, 1 + ld [wBattleEnded], a + ret + +.dont_flee + call ForcePlayerMonChoice + ld a, BATTLEPLAYERACTION_USEITEM + ld [wBattlePlayerAction], a + call HandleEnemySwitch + jp z, WildFled_EnemyFled_LinkBattleCanceled + jr DoubleSwitch + +.player_mon_not_fainted + ld a, BATTLEPLAYERACTION_USEITEM + ld [wBattlePlayerAction], a + call HandleEnemySwitch + jp z, WildFled_EnemyFled_LinkBattleCanceled + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ret + +DoubleSwitch: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_1 + call ClearSprites + hlcoord 1, 0 + lb bc, 4, 10 + call ClearBox + call PlayerPartyMonEntrance + ld a, $1 + call EnemyPartyMonEntrance + jr .done + +.player_1 + ld a, [wCurPartyMon] + push af + ld a, $1 + call EnemyPartyMonEntrance + call ClearSprites + call LoadTilemapToTempTilemap + pop af + ld [wCurPartyMon], a + call PlayerPartyMonEntrance + +.done + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ret + +UpdateBattleStateAndExperienceAfterEnemyFaint: + call UpdateBattleMonInParty + ld a, [wBattleMode] + dec a + jr z, .wild + ld a, [wCurOTMon] + ld hl, wOTPartyMon1HP + call GetPartyLocation + xor a + ld [hli], a + ld [hl], a + +.wild + ld hl, wPlayerSubStatus3 + res SUBSTATUS_IN_LOOP, [hl] + xor a + ld hl, wEnemyDamageTaken + ld [hli], a + ld [hl], a + call NewEnemyMonStatus + call BreakAttraction + ld a, [wBattleMode] + dec a + jr z, .wild2 + jr .trainer + +.wild2 + call StopDangerSound + ld a, $1 + ld [wBattleLowHealthAlarm], a + +.trainer + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + jr nz, .player_mon_did_not_faint + ld a, [wWhichMonFaintedFirst] + and a + jr nz, .player_mon_did_not_faint + call UpdateFaintedPlayerMon + +.player_mon_did_not_faint + call CheckPlayerPartyForFitMon + ld a, d + and a + ret z + ld a, [wBattleMode] + dec a + call z, PlayVictoryMusic + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + ld [wBattleResult], a ; WIN + call IsAnyMonHoldingExpShare + jr z, .skip_exp + ld hl, wEnemyMonBaseStats + ld b, wEnemyMonEnd - wEnemyMonBaseStats +.loop + srl [hl] + inc hl + dec b + jr nz, .loop + +.skip_exp + ld hl, wEnemyMonBaseStats + ld de, wBackupEnemyMonBaseStats + ld bc, wEnemyMonEnd - wEnemyMonBaseStats + call CopyBytes + xor a + ld [wGivingExperienceToExpShareHolders], a + call GiveExperiencePoints + call IsAnyMonHoldingExpShare + ret z + + ld a, [wBattleParticipantsNotFainted] + push af + ld a, d + ld [wBattleParticipantsNotFainted], a + ld hl, wBackupEnemyMonBaseStats + ld de, wEnemyMonBaseStats + ld bc, wEnemyMonEnd - wEnemyMonBaseStats + call CopyBytes + ld a, $1 + ld [wGivingExperienceToExpShareHolders], a + call GiveExperiencePoints + pop af + ld [wBattleParticipantsNotFainted], a + ret + +IsAnyMonHoldingExpShare: + ld a, [wPartyCount] + ld b, a + ld hl, wPartyMon1 + ld c, 1 + ld d, 0 +.loop + push hl + push bc + ld bc, MON_HP + add hl, bc + ld a, [hli] + or [hl] + pop bc + pop hl + jr z, .next + + push hl + push bc + ld bc, MON_ITEM + add hl, bc + pop bc + ld a, [hl] + pop hl + + cp EXP_SHARE + jr nz, .next + ld a, d + or c + ld d, a + +.next + sla c + push de + ld de, PARTYMON_STRUCT_LENGTH + add hl, de + pop de + dec b + jr nz, .loop + + ld a, d + ld e, 0 + ld b, PARTY_LENGTH +.loop2 + srl a + jr nc, .okay + inc e + +.okay + dec b + jr nz, .loop2 + ld a, e + and a + ret + +StopDangerSound: + xor a + ld [wLowHealthAlarm], a + ret + +FaintYourPokemon: + call StopDangerSound + call WaitSFX + ld a, $f0 + ld [wCryTracks], a + ld a, [wBattleMonSpecies] + call PlayStereoCry + call PlayerMonFaintedAnimation + hlcoord 9, 7 + lb bc, 5, 11 + call ClearBox + ld hl, BattleText_MonFainted + jp StdBattleTextbox + +FaintEnemyPokemon: + call WaitSFX + ld de, SFX_KINESIS + call PlaySFX + call EnemyMonFaintedAnimation + ld de, SFX_FAINT + call PlaySFX + hlcoord 1, 0 + lb bc, 4, 10 + call ClearBox + ld hl, BattleText_EnemyMonFainted + jp StdBattleTextbox + +CheckEnemyTrainerDefeated: + ld a, [wOTPartyCount] + ld b, a + xor a + ld hl, wOTPartyMon1HP + ld de, PARTYMON_STRUCT_LENGTH + +.loop + or [hl] + inc hl + or [hl] + dec hl + add hl, de + dec b + jr nz, .loop + + and a + ret + +HandleEnemySwitch: + ld hl, wEnemyHPPal + ld e, HP_BAR_LENGTH_PX + call UpdateHPPal + call WaitBGMap + farcall EnemySwitch_TrainerHud + ld a, [wLinkMode] + and a + jr z, .not_linked + + call LinkBattleSendReceiveAction + ld a, [wBattleAction] + cp BATTLEACTION_FORFEIT + ret z + + call SafeLoadTempTilemapToTilemap + +.not_linked + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + ld a, $0 + jr nz, EnemyPartyMonEntrance + inc a + ret + +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 [wBattlePlayerAction], a + inc a + ret + +WinTrainerBattle: +; Player won the battle + call StopDangerSound + ld a, $1 + ld [wBattleLowHealthAlarm], a + ld [wBattleEnded], a + ld a, [wLinkMode] + and a + ld a, b + call z, PlayVictoryMusic + callfar Battle_GetTrainerName + ld hl, BattleText_EnemyWasDefeated + call StdBattleTextbox + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + ret z + + call BattleWinSlideInEnemyTrainerFrontpic + ld c, 40 + call DelayFrames + ld a, [wBattleType] + cp BATTLETYPE_CANLOSE + jr nz, .skip_heal + predef HealParty +.skip_heal + ld a, [wDebugFlags] + bit DEBUG_BATTLE_F, a + jr nz, .GiveMoney + call PrintWinLossText + +.GiveMoney: + ld a, [wAmuletCoin] + and a + call nz, .DoubleReward + call .CheckMaxedOutMomMoney + push af + ld a, FALSE + jr nc, .okay + ld a, [wMomSavingMoney] + and MOM_SAVING_MONEY_MASK + cp (1 << MOM_SAVING_SOME_MONEY_F) | (1 << MOM_SAVING_HALF_MONEY_F) + jr nz, .okay + inc a ; TRUE + +.okay + ld b, a + ld c, 4 +.loop + ld a, b + and a + jr z, .loop2 + call .AddMoneyToMom + dec c + dec b + jr .loop + +.loop2 + ld a, c + and a + jr z, .done + call .AddMoneyToWallet + dec c + jr .loop2 + +.done + call .DoubleReward + call .DoubleReward + pop af + jr nc, .KeepItAll + ld a, [wMomSavingMoney] + and MOM_SAVING_MONEY_MASK + 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 + +.AddMoneyToMom: + push bc + ld hl, wBattleReward + 2 + ld de, wMomsMoney + 2 + call AddBattleMoneyToAccount + pop bc + ret + +.AddMoneyToWallet: + push bc + ld hl, wBattleReward + 2 + ld de, wMoney + 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: +; entries correspond to MOM_SAVING_* constants + dw SentSomeToMomText + dw SentHalfToMomText + dw SentAllToMomText + +.CheckMaxedOutMomMoney: + ld hl, wMomsMoney + 2 + ld a, [hld] + cp LOW(MAX_MONEY) + ld a, [hld] + sbc HIGH(MAX_MONEY) ; mid + ld a, [hl] + sbc HIGH(MAX_MONEY >> 8) + ret + +AddBattleMoneyToAccount: + ld c, 3 + and a + push de +.loop + ld a, [de] + adc [hl] + ld [de], a + dec de + dec hl + dec c + jr nz, .loop + pop hl + ld a, [hld] + cp LOW(MAX_MONEY) + ld a, [hld] + sbc HIGH(MAX_MONEY) ; mid + ld a, [hl] + sbc HIGH(MAX_MONEY >> 8) + ret c + ld [hl], HIGH(MAX_MONEY >> 8) + inc hl + ld [hl], HIGH(MAX_MONEY) ; mid + inc hl + ld [hl], LOW(MAX_MONEY) + ret + +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 hl, wPayDayMoney + ld a, [hli] + or [hl] + jr nz, .play_music + ld a, [wBattleParticipantsNotFainted] + and a + jr z, .lost + jr .play_music + +.trainer_victory + ld de, MUSIC_GYM_VICTORY + call IsGymLeader + jr c, .play_music + ld de, MUSIC_TRAINER_VICTORY + +.play_music + call PlayMusic + +.lost + pop de + ret + +IsKantoGymLeader: + ld hl, KantoGymLeaders + jr IsGymLeaderCommon + +IsGymLeader: + ld hl, GymLeaders +IsGymLeaderCommon: + push de + ld a, [wOtherTrainerClass] + ld de, 1 + call IsInArray + pop de + ret + +INCLUDE "data/trainers/leaders.asm" + +HandlePlayerMonFaint: + call FaintYourPokemon + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + call z, FaintEnemyPokemon + ld a, $1 + ld [wWhichMonFaintedFirst], a + call UpdateFaintedPlayerMon + call CheckPlayerPartyForFitMon + ld a, d + and a + jp z, LostBattle + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + jr nz, .notfainted + call UpdateBattleStateAndExperienceAfterEnemyFaint + ld a, [wBattleMode] + dec a + jr nz, .trainer + ld a, $1 + ld [wBattleEnded], a + ret + +.trainer + call CheckEnemyTrainerDefeated + jp z, WinTrainerBattle + +.notfainted + call AskUseNextPokemon + jr nc, .switch + ld a, $1 + ld [wBattleEnded], a + ret + +.switch + call ForcePlayerMonChoice + ret nz + ld a, BATTLEPLAYERACTION_USEITEM + ld [wBattlePlayerAction], a + call HandleEnemySwitch + jp z, WildFled_EnemyFled_LinkBattleCanceled + jp DoubleSwitch + +UpdateFaintedPlayerMon: + ld a, [wCurBattleMon] + ld c, a + ld hl, wBattleParticipantsNotFainted + ld b, RESET_FLAG + predef SmallFarFlagAction + ld hl, wEnemySubStatus3 + res SUBSTATUS_IN_LOOP, [hl] + xor a + ld [wLowHealthAlarm], a + ld hl, wPlayerDamageTaken + ld [hli], a + ld [hl], a + ld [wBattleMonStatus], a + call UpdateBattleMonInParty + ld c, HAPPINESS_FAINTED + ; If TheirLevel > (YourLevel + 30), use a different parameter + ld a, [wBattleMonLevel] + add 30 + ld b, a + ld a, [wEnemyMonLevel] + cp b + jr c, .got_param + ld c, HAPPINESS_BEATENBYSTRONGFOE + +.got_param + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + callfar ChangeHappiness + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + add LOSE + ld [wBattleResult], a + ld a, [wWhichMonFaintedFirst] + and a + ret z + 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, wPartyMon1Speed + ld de, wEnemyMonSpeed + jp TryToRunAwayFromBattle + +ForcePlayerMonChoice: + call EmptyBattleTextbox + call LoadStandardMenuHeader + call SetUpBattlePartyMenu_NoLoop + call ForcePickPartyMonInBattle + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr nz, .skip_link + ld a, BATTLEPLAYERACTION_USEITEM + ld [wBattlePlayerAction], a + call LinkBattleSendReceiveAction + +.skip_link + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + jr nz, .send_out_pokemon + + call ClearSprites + call ClearBGPalettes + call _LoadHPBar + call ExitMenu + call LoadTilemapToTempTilemap + call WaitBGMap + call GetMemSGBLayout + call SetPalettes + xor a + ret + +.send_out_pokemon + call ClearSprites + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + call AddBattleParticipant + call InitBattleMon + call ResetPlayerStatLevels + call ClearPalettes + call DelayFrame + call _LoadHPBar + call CloseWindow + call GetMemSGBLayout + call SetPalettes + call SendOutMonText + call NewBattleMonStatus + call BreakAttraction + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + call SetPlayerTurn + call SpikesDamage + ld a, $1 + and a + ret + +PlayerPartyMonEntrance: + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + call AddBattleParticipant + call InitBattleMon + call ResetPlayerStatLevels + call SendOutMonText + call NewBattleMonStatus + call BreakAttraction + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + call SetPlayerTurn + jp SpikesDamage + +SetUpBattlePartyMenu_NoLoop: + call ClearBGPalettes +SetUpBattlePartyMenu: ; switch to fullscreen menu? + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX + ret + +PickPartyMonInBattle: +.loop + ld a, PARTYMENUACTION_SWITCH + ld [wPartyMenuActionText], a + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes + call DelayFrame + farcall PartyMenuSelect + ret c + call CheckIfCurPartyMonIsFitToFight + jr z, .loop + xor a + ret + +SwitchMonAlreadyOut: + ld hl, wCurBattleMon + ld a, [wCurPartyMon] + cp [hl] + jr nz, .notout + + ld hl, BattleText_MonIsAlreadyOut + call StdBattleTextbox + scf + ret + +.notout + xor a + ret + +ForcePickPartyMonInBattle: +; Can't back out. + +.pick + call PickPartyMonInBattle + ret nc + + ld de, SFX_WRONG + call PlaySFX + call WaitSFX + 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 [wBattleEnded], a + 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, [wDebugFlags] + bit DEBUG_BATTLE_F, a + jr nz, .skip_win_loss_text + call PrintWinLossText +.skip_win_loss_text + ret + +.not_canlose + ld a, [wLinkMode] + and a + jr nz, .LostLinkBattle + +; Greyscale + ld b, SCGB_BATTLE_GRAYSCALE + call GetSGBLayout + call SetPalettes + jr .end + +.LostLinkBattle: + call UpdateEnemyMonInParty + call CheckEnemyTrainerDefeated + jr nz, .not_tied + ld hl, TiedAgainstText + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + add DRAW + ld [wBattleResult], a + jr .text + +.not_tied + ld hl, LostAgainstText + +.text + call StdBattleTextbox + +.end + scf + ret + +EnemyMonFaintedAnimation: + hlcoord 12, 5 + decoord 12, 6 + jp MonFaintedAnimation + +PlayerMonFaintedAnimation: + hlcoord 1, 10 + decoord 1, 11 + jp MonFaintedAnimation + +MonFaintedAnimation: + ld a, [wd8ba] + push af + set 6, a + ld [wd8ba], a + ld b, 7 + +.OuterLoop: + push bc + push de + push hl + ld b, 6 + +.InnerLoop: + push bc + push hl + push de + ld bc, 7 + call CopyBytes + pop de + pop hl + ld bc, -SCREEN_WIDTH + add hl, bc + push hl + ld h, d + ld l, e + add hl, bc + ld d, h + ld e, l + pop hl + pop bc + dec b + jr nz, .InnerLoop + + ld bc, 20 + add hl, bc + ld de, .Spaces + call PlaceString + ld c, 2 + call DelayFrames + pop hl + pop de + pop bc + dec b + jr nz, .OuterLoop + + pop af + ld [wd8ba], a + ret + +.Spaces: + db " @" + +SlideBattlePicOut: + ldh [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: + ldh 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 LoadEnemyMonToSwitchTo + call ClearEnemyMonBox + call NewEnemyMonStatus + call ResetEnemyStatLevels + call Function_SetEnemyMonAndSendOutAnimation + call BreakAttraction + call ResetBattleParticipants + ret + +EnemySwitch: + call CheckWhetherToAskSwitch + jr nc, EnemySwitch_SetMode + ; Shift Mode + call ResetEnemyBattleVars + call CheckWhetherSwitchmonIsPredetermined + jr c, .skip + call FindMonInOTPartyToSwitchIntoBattle +.skip + ; 'b' contains the PartyNr of the mon the AI will switch to + call LoadEnemyMonToSwitchTo + call OfferSwitch + push af + call ClearEnemyMonBox + call Function_BattleTextEnemySentOut + call Function_SetEnemyMonAndSendOutAnimation + pop af + ret c + ; If we're here, then we're switching too + xor a + ld [wBattleParticipantsNotFainted], a + ld [wBattleParticipantsIncludingFainted], a + ld [wBattlePlayerAction], a + inc a + ld [wEnemyIsSwitching], a + call LoadTilemapToTempTilemap + jp PlayerSwitch + +EnemySwitch_SetMode: + call ResetEnemyBattleVars + call CheckWhetherSwitchmonIsPredetermined + jr c, .skip + call FindMonInOTPartyToSwitchIntoBattle +.skip + ; 'b' contains the PartyNr of the mon the AI will switch to + call LoadEnemyMonToSwitchTo + ld a, 1 + ld [wEnemyIsSwitching], a + call ClearEnemyMonBox + call Function_BattleTextEnemySentOut + jp Function_SetEnemyMonAndSendOutAnimation + +CheckWhetherSwitchmonIsPredetermined: +; returns carry if: ??? + ld a, [wLinkMode] + and a + jr z, .not_linked + + ld a, [wBattleAction] + sub BATTLEACTION_SWITCH1 + ld b, a + jr .return_carry + +.not_linked + ld a, [wEnemySwitchMonIndex] + and a + jr z, .check_wBattleHasJustStarted + + dec a + ld b, a + jr .return_carry + +.check_wBattleHasJustStarted + ld a, [wBattleHasJustStarted] + and a + ld b, $0 + jr nz, .return_carry + + and a + ret + +.return_carry + scf + ret + +ResetEnemyBattleVars: +; and draw empty Textbox + xor a + ld [wLastPlayerCounterMove], a + ld [wLastEnemyCounterMove], a + ld [wLastEnemyMove], a + ld [wCurEnemyMove], a + dec a + ld [wEnemyItemState], a + xor a + ld [wPlayerWrapCount], a + hlcoord 18, 0 + ld a, 8 + call SlideBattlePicOut + call EmptyBattleTextbox + jp LoadStandardMenuHeader + +ResetBattleParticipants: + xor a + ld [wBattleParticipantsNotFainted], a + ld [wBattleParticipantsIncludingFainted], a +AddBattleParticipant: + ld a, [wCurBattleMon] + ld c, a + ld hl, wBattleParticipantsNotFainted + ld b, SET_FLAG + push bc + predef SmallFarFlagAction + pop bc + ld hl, wBattleParticipantsIncludingFainted + predef_jump SmallFarFlagAction + +FindMonInOTPartyToSwitchIntoBattle: + ld b, -1 + ld a, $1 + ld [wBuffer1], a + ld [wBuffer2], a +.loop + ld hl, wBuffer1 + sla [hl] + inc hl + sla [hl] + inc b + ld a, [wOTPartyCount] + cp b + jp z, ScoreMonTypeMatchups + ld a, [wCurOTMon] + cp b + jr z, .discourage + ld hl, wOTPartyMon1HP + push bc + ld a, b + call GetPartyLocation + ld a, [hli] + ld c, a + ld a, [hl] + or c + pop bc + jr z, .discourage + call LookUpTheEffectivenessOfEveryMove + call IsThePlayerMonTypesEffectiveAgainstOTMon + jr .loop + +.discourage + ld hl, wBuffer2 + set 0, [hl] + jr .loop + +LookUpTheEffectivenessOfEveryMove: + push bc + ld hl, wOTPartyMon1Moves + ld a, b + call GetPartyLocation + pop bc + ld e, NUM_MOVES + 1 +.loop + dec e + jr z, .done + ld a, [hli] + and a + jr z, .done + push hl + push de + push bc + dec a + ld hl, Moves + ld bc, MOVE_LENGTH + call AddNTimes + ld de, wEnemyMoveStruct + ld a, BANK(Moves) + call FarCopyBytes + call SetEnemyTurn + callfar BattleCheckTypeMatchup + pop bc + pop de + pop hl + ld a, [wTypeMatchup] + cp EFFECTIVE + 1 + jr c, .loop + ld hl, wBuffer1 + set 0, [hl] + ret +.done + ret + +IsThePlayerMonTypesEffectiveAgainstOTMon: +; Calculates the effectiveness of the types of the PlayerMon +; against the OTMon + push bc + ld hl, wOTPartyCount + ld a, b + inc a + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + dec a + ld hl, BaseData + BASE_TYPES + ld bc, BASE_DATA_SIZE + call AddNTimes + ld de, wEnemyMonType + ld bc, BASE_CATCH_RATE - BASE_TYPES + ld a, BANK(BaseData) + call FarCopyBytes + ld a, [wBattleMonType1] + ld [wPlayerMoveStruct + MOVE_TYPE], a + call SetPlayerTurn + callfar BattleCheckTypeMatchup + ld a, [wTypeMatchup] + cp EFFECTIVE + 1 + jr nc, .super_effective + ld a, [wBattleMonType2] + ld [wPlayerMoveStruct + MOVE_TYPE], a + callfar BattleCheckTypeMatchup + ld a, [wTypeMatchup] + cp EFFECTIVE + 1 + jr nc, .super_effective + pop bc + ret + +.super_effective + pop bc + ld hl, wBuffer1 + bit 0, [hl] + jr nz, .reset + inc hl + set 0, [hl] + ret + +.reset + res 0, [hl] + ret + +ScoreMonTypeMatchups: +.loop1 + ld hl, wBuffer1 + sla [hl] + inc hl + sla [hl] + jr nc, .loop1 + ld a, [wOTPartyCount] + ld b, a + ld c, [hl] +.loop2 + sla c + jr nc, .okay + dec b + jr z, .loop5 + jr .loop2 + +.okay + ld a, [wBuffer1] + and a + jr z, .okay2 + ld b, -1 + ld c, a +.loop3 + inc b + sla c + jr nc, .loop3 + jr .quit + +.okay2 + ld b, -1 + ld a, [wBuffer2] + ld c, a +.loop4 + inc b + sla c + jr c, .loop4 + jr .quit + +.loop5 + call BattleRandom + and $7 + cp 6 + jr nc, .loop5 + ld b, a + ld a, [wCurOTMon] + cp b + jr z, .loop5 + ld hl, wOTPartyMon1HP + push bc + ld a, b + call GetPartyLocation + pop bc + ld a, [hli] + ld c, a + ld a, [hl] + or c + jr z, .loop5 + +.quit + ret + +LoadEnemyMonToSwitchTo: + ; 'b' contains the PartyNr of the mon the AI will switch to + ld a, b + ld [wCurPartyMon], a + ld hl, wOTPartyMon1Level + call GetPartyLocation + ld a, [hl] + ld [wCurPartyLevel], a + ld a, [wCurPartyMon] + inc a + ld hl, wOTPartyCount + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wTempEnemyMonSpecies], a + ld [wCurPartySpecies], a + call LoadEnemyMon + + ld a, [wCurPartySpecies] + cp UNOWN + jr nz, .skip_unown + ld a, [wFirstUnownSeen] + and a + jr nz, .skip_unown + ld hl, wEnemyMonDVs + predef GetUnownLetter + ld a, [wUnownLetter] + ld [wFirstUnownSeen], a +.skip_unown + + ld hl, wEnemyMonHP + ld a, [hli] + ld [wEnemyHPAtTimeOfPlayerSwitch], a + ld a, [hl] + ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a + ret + +CheckWhetherToAskSwitch: + ld a, [wBattleHasJustStarted] + dec a + jp z, .return_nc + ld a, [wPartyCount] + dec a + jp z, .return_nc + ld a, [wLinkMode] + and a + jp nz, .return_nc + ld a, [wOptions] + bit BATTLE_SHIFT, a + jr nz, .return_nc + ld a, [wCurPartyMon] + push af + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + farcall CheckCurPartyMonFainted + pop bc + ld a, b + ld [wCurPartyMon], a + jr c, .return_nc + scf + ret + +.return_nc + and a + ret + +OfferSwitch: + ld a, [wCurPartyMon] + push af + callfar Battle_GetTrainerName + ld hl, BattleText_EnemyIsAboutToUseWillPlayerChangeMon + call StdBattleTextbox + lb bc, 1, 7 + call PlaceYesNoBox + ld a, [wMenuCursorY] + dec a + jr nz, .said_no + call SetUpBattlePartyMenu_NoLoop + call PickSwitchMonInBattle + jr c, .canceled_switch + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + call ClearPalettes + call DelayFrame + call _LoadHPBar + pop af + ld [wCurPartyMon], a + xor a + ld [wCurEnemyMove], a + ld [wCurPlayerMove], a + and a + ret + +.canceled_switch + call ClearPalettes + call DelayFrame + call _LoadHPBar + +.said_no + pop af + ld [wCurPartyMon], a + scf + ret + +ClearEnemyMonBox: + xor a + ldh [hBGMapMode], a + call ExitMenu + call ClearSprites + hlcoord 1, 0 + lb bc, 4, 10 + call ClearBox + call WaitBGMap + jp FinishBattleAnim + +Function_BattleTextEnemySentOut: + callfar Battle_GetTrainerName + ld hl, BattleText_EnemySentOut + jp StdBattleTextbox + +Function_SetEnemyMonAndSendOutAnimation: + ld a, [wTempEnemyMonSpecies] + ld [wCurPartySpecies], a + ld [wCurSpecies], a + call GetBaseData + ld a, OTPARTYMON + ld [wMonType], a + predef CopyMonToTempMon + call GetEnemyMonFrontpic + + xor a + ld [wNumHits], a + ld [wBattleAnimParam], a + call SetEnemyTurn + ld de, ANIM_SEND_OUT_MON + call Call_PlayBattleAnim + + call BattleCheckEnemyShininess + jr nc, .cry_no_anim + + ld a, 1 ; shiny anim + ld [wBattleAnimParam], a + ld de, ANIM_SEND_OUT_MON + call Call_PlayBattleAnim + +.cry_no_anim + ld a, $f + ld [wCryTracks], a + ld a, [wTempEnemyMonSpecies] + call PlayStereoCry + call UpdateEnemyHUD + ld a, $1 + ldh [hBGMapMode], a + ret + +NewEnemyMonStatus: + xor a + ld [wLastPlayerCounterMove], a + ld [wLastEnemyCounterMove], a + ld [wLastEnemyMove], a + ld hl, wEnemySubStatus1 +rept 4 + ld [hli], a +endr + ld [hl], a + ld [wEnemyDisableCount], a + ld [wEnemyFuryCutterCount], a + ld [wEnemyProtectCount], a + ld [wEnemyRageCounter], a + ld [wEnemyDisabledMove], a + ld [wEnemyMinimized], a + ld [wPlayerWrapCount], a + ld [wEnemyWrapCount], a + ld [wEnemyTurnsTaken], a + ld hl, wPlayerSubStatus5 + res SUBSTATUS_CANT_RUN, [hl] + ret + +ResetEnemyStatLevels: + ld a, BASE_STAT_LEVEL + ld b, NUM_LEVEL_STATS + ld hl, wEnemyStatLevels +.loop + ld [hli], a + dec b + jr nz, .loop + ret + +CheckPlayerPartyForFitMon: +; Has the player any mon in his Party that can fight? + ld a, [wPartyCount] + ld e, a + xor a + ld hl, wPartyMon1HP + ld bc, PARTYMON_STRUCT_LENGTH - 1 +.loop + or [hl] + inc hl ; + 1 + or [hl] + add hl, bc + dec e + jr nz, .loop + ld d, a + ret + +CheckIfCurPartyMonIsFitToFight: + ld a, [wCurPartyMon] + ld hl, wPartyMon1HP + call GetPartyLocation + ld a, [hli] + or [hl] + ret nz + + ld a, [wBattleHasJustStarted] + and a + jr nz, .finish_fail + ld hl, wPartySpecies + ld a, [wCurPartyMon] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + cp EGG + ld hl, BattleText_AnEGGCantBattle + jr z, .print_textbox + + ld hl, BattleText_TheresNoWillToBattle + +.print_textbox + call StdBattleTextbox + +.finish_fail + xor a + ret + +TryToRunAwayFromBattle: +; Run away from battle, with or without item + ld a, [wBattleType] + cp BATTLETYPE_DEBUG + jp z, .can_escape + cp BATTLETYPE_CONTEST + jp z, .can_escape + cp BATTLETYPE_TRAP + jp z, .cant_escape + cp BATTLETYPE_SHINY + jp z, .cant_escape + + ld a, [wLinkMode] + and a + jp nz, .can_escape + + ld a, [wBattleMode] + dec a + jp nz, .cant_run_from_trainer + + ld a, [wEnemySubStatus5] + bit SUBSTATUS_CANT_RUN, a + jp nz, .cant_escape + + ld a, [wPlayerWrapCount] + and a + jp nz, .cant_escape + + push hl + push de + ld a, [wBattleMonItem] + ld [wNamedObjectIndexBuffer], a + ld b, a + callfar GetItemHeldEffect + ld a, b + cp HELD_ESCAPE + pop de + pop hl + jr nz, .no_flee_item + + call SetPlayerTurn + call GetItemName + ld hl, BattleText_UserFledUsingAStringBuffer1 + call StdBattleTextbox + jp .can_escape + +.no_flee_item + ld a, [wNumFleeAttempts] + inc a + ld [wNumFleeAttempts], a + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hl] + ldh [hMultiplicand + 2], a + ld a, [de] + inc de + ldh [hEnemyMonSpeed + 0], a + ld a, [de] + ldh [hEnemyMonSpeed + 1], a + call SafeLoadTempTilemapToTilemap + ld de, hMultiplicand + 1 + ld hl, hEnemyMonSpeed + ld c, 2 + call CompareBytes + jr nc, .can_escape + + xor a + ldh [hMultiplicand + 0], a + ld a, 32 + ldh [hMultiplier], a + call Multiply + ldh a, [hProduct + 2] + ldh [hDividend + 0], a + ldh a, [hProduct + 3] + ldh [hDividend + 1], a + ldh a, [hEnemyMonSpeed + 0] + ld b, a + ldh a, [hEnemyMonSpeed + 1] + srl b + rr a + srl b + rr a + and a + jr z, .can_escape + ldh [hDivisor], a + ld b, 2 + call Divide + ldh a, [hQuotient + 2] + and a + jr nz, .can_escape + ld a, [wNumFleeAttempts] + ld c, a +.loop + dec c + jr z, .cant_escape_2 + ld b, 30 + ldh a, [hQuotient + 3] + add b + ldh [hQuotient + 3], a + jr c, .can_escape + jr .loop + +.cant_escape_2 + call BattleRandom + ld b, a + ldh a, [hQuotient + 3] + cp b + jr nc, .can_escape + ld a, BATTLEPLAYERACTION_USEITEM + ld [wBattlePlayerAction], a + ld hl, BattleText_CantEscape2 + jr .print_inescapable_text + +.cant_escape + ld hl, BattleText_CantEscape + jr .print_inescapable_text + +.cant_run_from_trainer + ld hl, BattleText_TheresNoEscapeFromTrainerBattle + +.print_inescapable_text + call StdBattleTextbox + ld a, TRUE + ld [wFailedToFlee], a + call LoadTilemapToTempTilemap + and a + ret + +.can_escape + ld a, [wLinkMode] + and a + ld a, DRAW + jr z, .fled + call LoadTilemapToTempTilemap + xor a ; BATTLEPLAYERACTION_USEMOVE + ld [wBattlePlayerAction], a + ld a, $f + ld [wCurMoveNum], a + xor a + ld [wCurPlayerMove], a + call LinkBattleSendReceiveAction + call SafeLoadTempTilemapToTilemap + + ; Got away safely + ld a, [wBattleAction] + cp BATTLEACTION_FORFEIT + ld a, DRAW + jr z, .fled + dec a ; LOSE +.fled + ld b, a + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + add b + ld [wBattleResult], a + call StopDangerSound + push de + ld de, SFX_RUN + call WaitPlaySFX + pop de + call WaitSFX + ld hl, BattleText_GotAwaySafely + call StdBattleTextbox + call WaitSFX + call LoadTilemapToTempTilemap + scf + ret + +InitBattleMon: + ld a, MON_SPECIES + call GetPartyParamLocation + ld de, wBattleMonSpecies + ld bc, MON_ID + call CopyBytes + ld bc, MON_DVS - MON_ID + add hl, bc + ld de, wBattleMonDVs + ld bc, MON_PKRUS - MON_DVS + call CopyBytes + inc hl + inc hl + inc hl + ld de, wBattleMonLevel + ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL + call CopyBytes + ld a, [wBattleMonSpecies] + ld [wTempBattleMonSpecies], a + ld [wCurPartySpecies], a + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseType1] + ld [wBattleMonType1], a + ld a, [wBaseType2] + ld [wBattleMonType2], a + ld hl, wPartyMonNicknames + ld a, [wCurBattleMon] + call SkipNames + ld de, wBattleMonNick + ld bc, MON_NAME_LENGTH + call CopyBytes + ld hl, wBattleMonAttack + ld de, wPlayerStats + ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK + call CopyBytes + call ApplyStatusEffectOnPlayerStats + call BadgeStatBoosts + ret + +BattleCheckPlayerShininess: + call GetPartyMonDVs + jr BattleCheckShininess + +BattleCheckEnemyShininess: + call GetEnemyMonDVs + +BattleCheckShininess: + ld b, h + ld c, l + callfar CheckShininess + ret + +GetPartyMonDVs: + ld hl, wBattleMonDVs + ld a, [wPlayerSubStatus5] + bit SUBSTATUS_TRANSFORMED, a + ret z + ld hl, wPartyMon1DVs + ld a, [wCurBattleMon] + jp GetPartyLocation + +GetEnemyMonDVs: + ld hl, wEnemyMonDVs + ld a, [wEnemySubStatus5] + bit SUBSTATUS_TRANSFORMED, a + ret z + ld hl, wEnemyBackupDVs + ld a, [wBattleMode] + dec a + ret z + ld hl, wOTPartyMon1DVs + ld a, [wCurOTMon] + jp GetPartyLocation + +ResetPlayerStatLevels: + ld a, BASE_STAT_LEVEL + ld b, NUM_LEVEL_STATS + ld hl, wPlayerStatLevels +.loop + ld [hli], a + dec b + jr nz, .loop + ret + +InitEnemyMon: + ld a, [wCurPartyMon] + ld hl, wOTPartyMon1Species + call GetPartyLocation + ld de, wEnemyMonSpecies + ld bc, MON_ID + call CopyBytes + ld bc, MON_DVS - MON_ID + add hl, bc + ld de, wEnemyMonDVs + ld bc, MON_PKRUS - MON_DVS + call CopyBytes + inc hl + inc hl + inc hl + ld de, wEnemyMonLevel + ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL + call CopyBytes + ld a, [wEnemyMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld hl, wOTPartyMonNicknames + ld a, [wCurPartyMon] + call SkipNames + ld de, wEnemyMonNick + ld bc, MON_NAME_LENGTH + call CopyBytes + ld hl, wEnemyMonAttack + ld de, wEnemyStats + ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK + call CopyBytes + call ApplyStatusEffectOnEnemyStats + ld hl, wBaseType1 + ld de, wEnemyMonType1 + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + ld hl, wBaseStats + ld de, wEnemyMonBaseStats + ld b, 5 +.loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop + ld a, [wCurPartyMon] + ld [wCurOTMon], a + ret + +SwitchPlayerMon: + call ClearSprites + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + call AddBattleParticipant + call InitBattleMon + call ResetPlayerStatLevels + call NewBattleMonStatus + call BreakAttraction + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + ret + +SendOutPlayerMon: + ld hl, wBattleMonDVs + predef GetUnownLetter + hlcoord 1, 5 + ld b, 7 + ld c, 8 + call ClearBox + call WaitBGMap + xor a + ldh [hBGMapMode], a + call GetBattleMonBackpic + xor a + ldh [hGraphicStartTile], a + ld [wBattleMenuCursorBuffer], a + ld [wCurMoveNum], a + ld [wTypeModifier], a + ld [wPlayerMoveStruct + MOVE_ANIM], a + ld [wLastPlayerCounterMove], a + ld [wLastEnemyCounterMove], a + ld [wLastPlayerMove], a + call CheckAmuletCoin + call FinishBattleAnim + xor a + ld [wEnemyWrapCount], a + call SetPlayerTurn + xor a + ld [wNumHits], a + ld [wBattleAnimParam], a + ld de, ANIM_SEND_OUT_MON + call Call_PlayBattleAnim + call BattleCheckPlayerShininess + jr nc, .not_shiny + ld a, 1 + ld [wBattleAnimParam], a + ld de, ANIM_SEND_OUT_MON + call Call_PlayBattleAnim + +.not_shiny + ld a, $f0 + ld [wCryTracks], a + ld a, [wCurPartySpecies] + call PlayStereoCry + call UpdatePlayerHUD + ld a, $1 + ldh [hBGMapMode], a + ret + +NewBattleMonStatus: + xor a + ld [wLastPlayerCounterMove], a + ld [wLastEnemyCounterMove], a + ld [wLastPlayerMove], a + ld hl, wPlayerSubStatus1 +rept 4 + ld [hli], a +endr + ld [hl], a + ld hl, wPlayerUsedMoves + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld [wPlayerDisableCount], a + ld [wPlayerFuryCutterCount], a + ld [wPlayerProtectCount], a + ld [wPlayerRageCounter], a + ld [wDisabledMove], a + ld [wPlayerMinimized], a + ld [wEnemyWrapCount], a + ld [wPlayerWrapCount], a + ld [wPlayerTurnsTaken], a + ld hl, wEnemySubStatus5 + res SUBSTATUS_CANT_RUN, [hl] + ret + +BreakAttraction: + ld hl, wPlayerSubStatus1 + res SUBSTATUS_IN_LOVE, [hl] + ld hl, wEnemySubStatus1 + res SUBSTATUS_IN_LOVE, [hl] + ret + +SpikesDamage: + ld hl, wPlayerScreens + ld de, wBattleMonType + ld bc, UpdatePlayerHUD + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyScreens + ld de, wEnemyMonType + ld bc, UpdateEnemyHUD +.ok + + bit SCREENS_SPIKES, [hl] + ret z + + ; Flying-types aren't affected by Spikes. + ld a, [de] + cp FLYING + ret z + inc de + ld a, [de] + cp FLYING + ret z + + push bc + + ld hl, BattleText_UserHurtBySpikes ; "hurt by SPIKES!" + call StdBattleTextbox + + call GetEighthMaxHP + call SubtractHPFromTarget + + pop hl + call .hl + + jp WaitBGMap + +.hl + jp hl + +PursuitSwitch: + ld a, BATTLE_VARS_MOVE + call GetBattleVar + ld b, a + call GetMoveEffect + ld a, b + cp EFFECT_PURSUIT + jr nz, .done + + ld a, [wCurBattleMon] + push af + + ld hl, DoPlayerTurn + ldh a, [hBattleTurn] + and a + jr z, .do_turn + ld hl, DoEnemyTurn + ld a, [wLastPlayerMon] + ld [wCurBattleMon], a +.do_turn + ld a, BANK(DoPlayerTurn) ; aka BANK(DoEnemyTurn) + rst FarCall + + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + ld a, $ff + ld [hl], a + + pop af + ld [wCurBattleMon], a + + ldh a, [hBattleTurn] + and a + jr z, .check_enemy_fainted + + ld a, [wLastPlayerMon] + call UpdateBattleMon + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + jr nz, .done + + ld a, $f0 + ld [wCryTracks], a + ld a, [wBattleMonSpecies] + call PlayStereoCry + ld a, [wLastPlayerMon] + ld c, a + ld hl, wBattleParticipantsNotFainted + ld b, RESET_FLAG + predef SmallFarFlagAction + call PlayerMonFaintedAnimation + ld hl, BattleText_MonFainted + jr .done_fainted + +.check_enemy_fainted + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + jr nz, .done + + ld de, SFX_KINESIS + call PlaySFX + call WaitSFX + ld de, SFX_FAINT + call PlaySFX + call WaitSFX + call EnemyMonFaintedAnimation + ld hl, BattleText_EnemyMonFainted + +.done_fainted + call StdBattleTextbox + scf + ret + +.done + and a + ret + +RecallPlayerMon: + ldh a, [hBattleTurn] + push af + xor a + ldh [hBattleTurn], a + ld [wNumHits], a + ld de, ANIM_RETURN_MON + call Call_PlayBattleAnim + pop af + ldh [hBattleTurn], a + ret + +HandleHealingItems: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_1 + call SetPlayerTurn + call HandleHPHealingItem + call UseHeldStatusHealingItem + call UseConfusionHealingItem + call SetEnemyTurn + call HandleHPHealingItem + call UseHeldStatusHealingItem + jp UseConfusionHealingItem + +.player_1 + call SetEnemyTurn + call HandleHPHealingItem + call UseHeldStatusHealingItem + call UseConfusionHealingItem + call SetPlayerTurn + call HandleHPHealingItem + call UseHeldStatusHealingItem + jp UseConfusionHealingItem + +HandleHPHealingItem: + callfar GetOpponentItem + ld a, b + cp HELD_BERRY + ret nz + ld de, wEnemyMonHP + 1 + ld hl, wEnemyMonMaxHP + ldh a, [hBattleTurn] + and a + jr z, .go + ld de, wBattleMonHP + 1 + ld hl, wBattleMonMaxHP + +.go +; If, and only if, Pokemon's HP is less than half max, use the item. +; Store current HP in Buffer 3/4 + push bc + ld a, [de] + ld [wBuffer3], a + add a + ld c, a + dec de + ld a, [de] + inc de + ld [wBuffer4], a + adc a + ld b, a + ld a, b + cp [hl] + ld a, c + pop bc + jr z, .equal + jr c, .less + ret + +.equal + inc hl + cp [hl] + dec hl + ret nc + +.less + call ItemRecoveryAnim + ; store max HP in wBuffer1/2 + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + ld a, [de] + add c + ld [wBuffer5], a + ld c, a + dec de + ld a, [de] + adc 0 + ld [wBuffer6], a + ld b, a + ld a, [hld] + cp c + ld a, [hl] + sbc b + jr nc, .okay + ld a, [hli] + ld [wBuffer6], a + ld a, [hl] + ld [wBuffer5], a + +.okay + ld a, [wBuffer6] + ld [de], a + inc de + ld a, [wBuffer5] + ld [de], a + ldh a, [hBattleTurn] + ld [wWhichHPBar], a + and a + hlcoord 2, 2 + jr z, .got_hp_bar_coords + hlcoord 10, 9 + +.got_hp_bar_coords + ld [wWhichHPBar], a + predef AnimateHPBar +UseOpponentItem: + call RefreshBattleHuds + callfar GetOpponentItem + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetItemName + callfar ConsumeHeldItem + ld hl, RecoveredUsingText + jp StdBattleTextbox + +ItemRecoveryAnim: + push hl + push de + push bc + call EmptyBattleTextbox + ld a, RECOVER + ld [wFXAnimID], a + call SwitchTurnCore + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + predef PlayBattleAnim + call SwitchTurnCore + pop bc + pop de + pop hl + ret + +UseHeldStatusHealingItem: + callfar GetOpponentItem + ld hl, HeldStatusHealingEffects +.loop + ld a, [hli] + cp $ff + ret z + inc hl + cp b + jr nz, .loop + dec hl + ld b, [hl] + ld a, BATTLE_VARS_STATUS_OPP + call GetBattleVarAddr + and b + ret z + xor a + ld [hl], a + push bc + call UpdateOpponentInParty + pop bc + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + and [hl] + res SUBSTATUS_TOXIC, [hl] + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVarAddr + and [hl] + res SUBSTATUS_NIGHTMARE, [hl] + ld a, b + cp ALL_STATUS + jr nz, .skip_confuse + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVarAddr + res SUBSTATUS_CONFUSED, [hl] + +.skip_confuse + ld hl, CalcEnemyStats + ldh a, [hBattleTurn] + and a + jr z, .got_pointer + ld hl, CalcPlayerStats + +.got_pointer + call SwitchTurnCore + ld a, BANK(CalcPlayerStats) ; aka BANK(CalcEnemyStats) + rst FarCall + call SwitchTurnCore + call ItemRecoveryAnim + call UseOpponentItem + ld a, $1 + and a + ret + +INCLUDE "data/battle/held_heal_status.asm" + +UseConfusionHealingItem: + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVar + bit SUBSTATUS_CONFUSED, a + ret z + callfar GetOpponentItem + ld a, b + cp HELD_HEAL_CONFUSION + jr z, .heal_status + cp HELD_HEAL_STATUS + ret nz + +.heal_status + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVarAddr + res SUBSTATUS_CONFUSED, [hl] + call GetItemName + call ItemRecoveryAnim + ld hl, BattleText_ItemHealedConfusion + call StdBattleTextbox + ldh 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 + +HandleStatBoostingHeldItems: +; The effects handled here are not used in-game. + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_1 + call .DoPlayer + jp .DoEnemy + +.player_1 + call .DoEnemy + jp .DoPlayer + +.DoPlayer: + call GetPartymonItem + ld a, $0 + jp .HandleItem + +.DoEnemy: + call GetOTPartymonItem + ld a, $1 +.HandleItem: + ldh [hBattleTurn], a + ld d, h + ld e, l + push de + push bc + ld a, [bc] + ld b, a + callfar GetItemHeldEffect + ld hl, HeldStatUpItems +.loop + ld a, [hli] + cp -1 + jr z, .finish + inc hl + inc hl + cp b + jr nz, .loop + pop bc + ld a, [bc] + ld [wNamedObjectIndexBuffer], a + push bc + dec hl + dec hl + ld a, [hli] + ld h, [hl] + ld l, a + ld a, BANK(BattleCommand_AttackUp) + rst FarCall + pop bc + pop de + ld a, [wFailedMessage] + and a + ret nz + xor a + ld [bc], a + ld [de], a + call GetItemName + ld hl, BattleText_UsersStringBuffer1Activated + call StdBattleTextbox + callfar BattleCommand_StatUpMessage + ret + +.finish + pop bc + pop de + ret + +INCLUDE "data/battle/held_stat_up.asm" + +GetPartymonItem: + ld hl, wPartyMon1Item + ld a, [wCurBattleMon] + call GetPartyLocation + ld bc, wBattleMonItem + ret + +GetOTPartymonItem: + ld hl, wOTPartyMon1Item + ld a, [wCurOTMon] + call GetPartyLocation + ld bc, wEnemyMonItem + ret + +UpdateBattleHUDs: + push hl + push de + push bc + call DrawPlayerHUD + ld hl, wPlayerHPPal + call SetHPPal + call CheckDanger + call DrawEnemyHUD + ld hl, wEnemyHPPal + call SetHPPal + pop bc + pop de + pop hl + ret + +UpdatePlayerHUD:: + push hl + push de + push bc + call DrawPlayerHUD + call UpdatePlayerHPPal + call CheckDanger + pop bc + pop de + pop hl + ret + +DrawPlayerHUD: + xor a + ldh [hBGMapMode], a + + ; Clear the area + hlcoord 9, 7 + lb bc, 5, 11 + call ClearBox + + farcall DrawPlayerHUDBorder + + hlcoord 18, 9 + ld [hl], $73 ; vertical bar + call PrintPlayerHUD + + ; HP bar + hlcoord 10, 9 + ld b, 1 + xor a ; PARTYMON + ld [wMonType], a + predef DrawPlayerHP + + ; Exp bar + push de + ld a, [wCurBattleMon] + ld hl, wPartyMon1Exp + 2 + call GetPartyLocation + ld d, h + ld e, l + + hlcoord 10, 11 + ld a, [wTempMonLevel] + ld b, a + call FillInExpBar + pop de + ret + +UpdatePlayerHPPal: + ld hl, wPlayerHPPal + jp UpdateHPPal + +CheckDanger: + ld hl, wBattleMonHP + ld a, [hli] + or [hl] + jr z, .no_danger + ld a, [wBattleLowHealthAlarm] + and a + jr nz, .done + ld a, [wPlayerHPPal] + cp HP_RED + jr z, .danger + +.no_danger + ld hl, wLowHealthAlarm + res DANGER_ON_F, [hl] + jr .done + +.danger + ld hl, wLowHealthAlarm + set DANGER_ON_F, [hl] + +.done + ret + +PrintPlayerHUD: + ld de, wBattleMonNick + hlcoord 10, 7 + call ret_3df99 + call PlaceString + + push bc + + ld a, [wCurBattleMon] + ld hl, wPartyMon1DVs + call GetPartyLocation + ld de, wTempMonDVs + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + ld hl, wBattleMonLevel + ld de, wTempMonLevel + ld bc, $11 + call CopyBytes + ld a, [wCurBattleMon] + ld hl, wPartyMon1Species + call GetPartyLocation + ld a, [hl] + ld [wCurPartySpecies], a + ld [wCurSpecies], a + call GetBaseData + + pop hl + dec hl + + ld a, TEMPMON + ld [wMonType], a + callfar GetGender + ld a, " " + jr c, .got_gender_char + ld a, "♂" + jr nz, .got_gender_char + ld a, "♀" + +.got_gender_char + hlcoord 17, 8 + ld [hl], a + hlcoord 14, 8 + push af ; back up gender + push hl + ld de, wBattleMonStatus + predef PlaceNonFaintStatus + pop hl + pop bc + ret nz + ld a, b + cp " " + jr nz, .copy_level ; male or female + dec hl ; genderless + +.copy_level + ld a, [wBattleMonLevel] + ld [wTempMonLevel], a + jp PrintLevel + +UpdateEnemyHUD:: + push hl + push de + push bc + call DrawEnemyHUD + call UpdateEnemyHPPal + pop bc + pop de + pop hl + ret + +DrawEnemyHUD: + xor a + ldh [hBGMapMode], a + + hlcoord 1, 0 + lb bc, 4, 11 + call ClearBox + + farcall DrawEnemyHUDBorder + + ld a, [wTempEnemyMonSpecies] + ld [wCurSpecies], a + ld [wCurPartySpecies], a + call GetBaseData + ld de, wEnemyMonNick + hlcoord 1, 0 + call ret_3df99 + call PlaceString + ld h, b + ld l, c + dec hl + + ld hl, wEnemyMonDVs + ld de, wTempMonDVs + ld a, [wEnemySubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr z, .ok + ld hl, wEnemyBackupDVs +.ok + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + + ld a, TEMPMON + ld [wMonType], a + callfar GetGender + ld a, " " + jr c, .got_gender + ld a, "♂" + jr nz, .got_gender + ld a, "♀" + +.got_gender + hlcoord 9, 1 + ld [hl], a + + hlcoord 6, 1 + push af + push hl + ld de, wEnemyMonStatus + predef PlaceNonFaintStatus + pop hl + pop bc + jr nz, .skip_level + ld a, b + cp " " + jr nz, .print_level + dec hl +.print_level + ld a, [wEnemyMonLevel] + ld [wTempMonLevel], a + call PrintLevel +.skip_level + + ld hl, wEnemyMonHP + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hld] + ldh [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 + ldh [hMultiplicand + 0], a + ld a, HP_BAR_LENGTH_PX + ldh [hMultiplier], a + call Multiply + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld b, a + ld a, [hl] + ldh [hMultiplier], a + ld a, b + and a + jr z, .less_than_256_max + ldh a, [hMultiplier] + srl b + rr a + srl b + rr a + ldh [hDivisor], a + ldh a, [hProduct + 2] + ld b, a + srl b + ldh a, [hProduct + 3] + rr a + srl b + rr a + ldh [hProduct + 3], a + ld a, b + ldh [hProduct + 2], a + +.less_than_256_max + ldh a, [hProduct + 2] + ldh [hDividend + 0], a + ldh a, [hProduct + 3] + ldh [hDividend + 1], a + ld a, 2 + ld b, a + call Divide + ldh a, [hQuotient + 3] + ld e, a + ld a, HP_BAR_LENGTH + ld d, a + ld c, a + +.draw_bar + xor a + ld [wWhichHPBar], a + hlcoord 2, 2 + ld b, 0 + call DrawBattleHPBar + ret + +UpdateEnemyHPPal: + ld hl, wEnemyHPPal + call UpdateHPPal + ret + +UpdateHPPal: + ld b, [hl] + call SetHPPal + ld a, [hl] + cp b + ret z + jp FinishBattleAnim + +ret_3df99: + ret diff --git a/engine/gfx/cgb_layouts.asm b/engine/gfx/cgb_layouts.asm index cbc8d203..4392fed1 100755 --- a/engine/gfx/cgb_layouts.asm +++ b/engine/gfx/cgb_layouts.asm @@ -84,7 +84,7 @@ Function9399: ; 9399 (2:5399) call Function9bba push hl call Function9adb - ld a, [wcc9a] + ld a, [wEnemyHPPal] ld l, a ld h, $0 add hl, hl diff --git a/engine/gfx/color.asm b/engine/gfx/color.asm index 10507851..a807ff09 100755 --- a/engine/gfx/color.asm +++ b/engine/gfx/color.asm @@ -586,17 +586,17 @@ Function9b9c: ; 9b9c (2:5b9c) Function9ba9: ; 9ba9 (2:5ba9) push de - farcall Function3d8f5 + farcall GetPartyMonDVs ld c, l ld b, h - ld a, [wd0ee] + ld a, [wTempBattleMonSpecies] call Function9bcb pop de ret Function9bba: ; 9bba (2:5bba) push de - farcall Function3d907 + farcall GetEnemyMonDVs ld c, l ld b, h ld a, [wTempEnemyMonSpecies] diff --git a/engine/gfx/sgb_layouts.asm b/engine/gfx/sgb_layouts.asm index e94ad9fc..623bbbca 100755 --- a/engine/gfx/sgb_layouts.asm +++ b/engine/gfx/sgb_layouts.asm @@ -81,7 +81,7 @@ Function8c97: ; 8c97 (2:4c97) ld [wccae], a ld a, [hl] ld [wccaf], a - ld a, [wcc9a] + ld a, [wEnemyHPPal] ld l, a ld h, $0 add hl, hl diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index bf35d84e..6735ec16 100755 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -226,7 +226,7 @@ UltraBall: ; e926 res NO_TEXT_SCROLL, [hl] ld hl, Text_UsedItem ; $7884 call PrintText - ld a, [wd114] + ld a, [wEnemyMonCatchRate] ld b, a ld a, [wBattleType] cp BATTLETYPE_TUTORIAL @@ -835,11 +835,11 @@ LoveBallMultiplier: ; Reality: multiply catch rate by 8 if mons are of same species, same sex ld a, [wTempEnemyMonSpecies] ld c, a - ld a, [wd0ee] + ld a, [wTempBattleMonSpecies] cp c ret nz push bc - ld a, [wd0ee] + ld a, [wTempBattleMonSpecies] ld [wCurPartySpecies], a xor a ld [wMonType], a @@ -1409,7 +1409,7 @@ Functionf12c: ; f12c (3:712c) ld a, [wCurPartyMon] ld c, a ld d, $0 - ld hl, wcbda + ld hl, wBattleParticipantsIncludingFainted ld b, CHECK_FLAG predef SmallFarFlagAction ld a, c @@ -1417,7 +1417,7 @@ Functionf12c: ; f12c (3:712c) jr z, .asm_f15a ld a, [wCurPartyMon] ld c, a - ld hl, wcb42 + ld hl, wBattleParticipantsNotFainted ld b, SET_FLAG predef SmallFarFlagAction .asm_f15a @@ -2183,7 +2183,7 @@ PPUp: ; f606 (3:7606) xor a ld [wCurMoveNum], a ld a, $2 - ld [wd11f], a + ld [wMoveSelectionMenuType], a ld a, $f ld hl, $62f3 rst FarCall diff --git a/engine/pokemon/bills_pc_top.asm b/engine/pokemon/bills_pc_top.asm index 38cfc479..25166209 100644 --- a/engine/pokemon/bills_pc_top.asm +++ b/engine/pokemon/bills_pc_top.asm @@ -337,7 +337,7 @@ Function65b4: swap a or b ld b, a - ld a, [wd12d] + ld a, [wBaseGender] cp b ld a, $1 jr c, .asm_e63d diff --git a/engine/pokemon/move_mon.asm b/engine/pokemon/move_mon.asm index 26b0f0b9..39e6ea47 100755 --- a/engine/pokemon/move_mon.asm +++ b/engine/pokemon/move_mon.asm @@ -69,7 +69,7 @@ GeneratePartyMonStats: ld a, [wCurPartySpecies] ld [wCurSpecies], a call GetBaseData - ld a, [wd120] + ld a, [wBaseDexNo] ld [de], a inc de ld a, [wBattleMode] @@ -1288,7 +1288,7 @@ CalcMonStatC: ; e181 ld a, b ld d, a push hl - ld hl, wd121 + ld hl, wBaseStats dec hl ; has to be decreased, because 'c' begins with 1 ld b, $0 add hl, bc diff --git a/home/map.asm b/home/map.asm index a5d84a5c..c210f03d 100644 --- a/home/map.asm +++ b/home/map.asm @@ -1029,8 +1029,8 @@ GetMapScreenCoords:: ret LoadBlockData:: - ld hl, wOverworldMap - ld bc, wOverworldMapEnd - wOverworldMap + ld hl, wOverworldMapBlocks + ld bc, wOverworldMapBlocksEnd - wOverworldMapBlocks ld a, $0 call ByteFill call ChangeMap @@ -182,7 +182,9 @@ ToggleDecorationsVisibility: dr $27216, $27271 INCLUDE "engine/battle/read_trainer_dvs.asm" ReturnToBattle_UseBall_: - dr $27307, $2739f + dr $27307, $2733d +ConsumeHeldItem: + dr $2733d, $2739f INCLUDE "data/moves/effects.asm" SECTION "banka", ROMX @@ -257,7 +259,13 @@ JohtoGrassWildMons: dr $2ab35, $2bee3 SECTION "bankb", ROMX - dr $2c000, $2c225 + dr $2c000, $2c045 +EnemySwitch_TrainerHud: + dr $2c045, $2c0c8 +DrawPlayerHUDBorder: + dr $2c0c8, $2c0f8 +DrawEnemyHUDBorder: + dr $2c0f8, $2c225 INCLUDE "engine/battle/ai/redundant.asm" MoveDeletion: dr $2c352, $2c57a @@ -290,75 +298,34 @@ INCLUDE "engine/battle/read_trainer_party.asm" SECTION "Battle Core", ROMX - dr $3c000, $3c551 -FleeMons:: - dr $3c551, $3c5a4 -GetMoveEffect: - dr $3c5a4, $3cbe7 -SubtractHPFromUser: - dr $3cbe7, $3cc2b -GetEighthMaxHP: - dr $3cc2b, $3cc36 -GetQuarterMaxHP: - dr $3cc36, $3cc47 -GetHalfMaxHP: - dr $3cc47, $3cc54 -GetMaxHP: - dr $3cc54, $3cc86 -CheckUserHasEnoughHP: - dr $3cc86, $3cc97 -RestoreHP: - dr $3cc97, $3d224 - -SetUpBattlePartyMenu_NoLoop: - dr $3d224, $3d28f -ForcePickSwitchMonInBattle: - dr $3d28f, $3d381 -ForceEnemySwitch: - dr $3d381, $3d39f -EnemySwitch: - dr $3d39f, $3d3d5 -EnemySwitch_SetMode: - dr $3d3d5, $3d438 -ResetBattleParticipants: - dr $3d438, $3d6cb -NewEnemyMonStatus: - dr $3d6cb, $3d6fe -ResetEnemyStatLevels: - dr $3d6fe, $3d70a -CheckPlayerPartyForFitMon:: - dr $3d70a, $3d8f5 -Function3d8f5: - dr $3d8f5, $3d907 -Function3d907: - dr $3d907, $3d9a2 -SwitchPlayerMon: - dr $3d9a2, $3da84 -SpikesDamage: - dr $3da84, $3dabc -PursuitSwitch: - dr $3dabc, $3dc4a -UseHeldStatusHealingItem: - dr $3dc4a, $3dcb2 -UseConfusionHealingItem: - dr $3dcb2, $3dda9 -UpdatePlayerHUD:: - dr $3dda9, $3ddb9 -DrawPlayerHUD: - dr $3ddb9, $3de97 -UpdateEnemyHUD:: - dr $3de97, $3dea4 -DrawEnemyHUD: - dr $3dea4, $3e290 +INCLUDE "engine/battle/core.asm" + +BattleMenu: + dr $3df9a, $3e1e4 + +PlayerSwitch: + dr $3e1e4, $3e290 PassedBattleMonEntrance: - dr $3e290, $3e6e8 + dr $3e290, $3e2df +CheckAmuletCoin: + dr $3e2df, $3e2f3 +MoveSelectionScreen: + dr $3e2f3, $3e5d8 +ParseEnemyAction: + dr $3e5d8, $3e6e8 CheckEnemyLockedIn:: dr $3e6e8, $3e6fb LinkBattleSendReceiveAction: dr $3e6fb, $3e74b LoadEnemyMon: - dr $3e74b, $3ea77 + dr $3e74b, $3ea16 +BattleWinSlideInEnemyTrainerFrontpic: + dr $3ea16, $3ea6a +ApplyStatusEffectOnPlayerStats: + dr $3ea6a, $3ea6e +ApplyStatusEffectOnEnemyStats: + dr $3ea6e, $3ea77 ApplyPrzEffectOnSpeed: dr $3ea77, $3eab4 ApplyBrnEffectOnAttack: @@ -368,10 +335,24 @@ ApplyStatLevelMultiplierOnAllStats: BadgeStatBoosts: dr $3eb83, $3ebd8 _LoadBattleFontsHPBar: - dr $3ebd8, $3ec11 + dr $3ebd8, $3ebdf +_LoadHPBar: + dr $3ebdf, $3ec0a +EmptyBattleTextbox: + dr $3ec0a, $3ec11 _BattleRandom:: - dr $3ec11, $3f196 - + dr $3ec11, $3ec48 +Call_PlayBattleAnim_OnlyIfVisible: + dr $3ec48, $3ec50 +Call_PlayBattleAnim: + dr $3ec50, $3ec60 +FinishBattleAnim: + dr $3ec60, $3ec74 +GiveExperiencePoints: + dr $3ec74, $3f086 + +SendOutMonText: + dr $3f086, $3f196 FillInExpBar:: dr $3f196, $3f243 GetBattleMonBackpic:: @@ -635,7 +635,6 @@ wc6fd:: ds 1 ; c6fd wc6fe:: ds 1 ; c6fe wc6ff:: ds 1 ; c6ff -wOverworldMap:: wOverworldMapBlocks:: wLYOverrides:: wHallOfFamePokemonList:: @@ -1676,7 +1675,7 @@ wOTClassName:: ds NAME_LENGTH ; cb34 wcb3f:: ds 1 ; cb3f wcb40:: ds 1 ; cb40 wCurOTMon:: ds 1 ; cb41 -wcb42:: ds 1 ; cb42 +wBattleParticipantsNotFainted:: db ; cb42 wTypeModifier:: db ; cb43 wCriticalHit:: db ; cb44 wAttackMissed:: db ; cb45 @@ -1819,8 +1818,7 @@ wEnemyItemState:: db ; cbc4 wcbc5:: ds 1 ; cbc5 wcbc6:: ds 1 ; cbc6 wCurEnemyMoveNum:: db ; cbc7 -wcbc8:: ds 1 ; cbc8 -wcbc9:: ds 1 ; cbc9 +wEnemyHPAtTimeOfPlayerSwitch:: dw ; cbc8 wPayDayMoney:: ds 3 ; cbca wcbcd:: ds 1 ; cbcd @@ -1830,7 +1828,7 @@ wEnemyBackupDVs:: dw wAlreadyDisobeyed:: db ; cbd2 wDisabledMove:: db ; cbd3 wEnemyDisabledMove:: db ; cbd4 -wcbd5:: ds 1 ; cbd5 +wWhichMonFaintedFirst:: db ; cbd5 ; exists so you can't counter on switch wLastPlayerCounterMove:: db ; cbd6 @@ -1838,8 +1836,8 @@ wLastEnemyCounterMove:: db ; cbd7 wEnemyMinimized:: db ; cbd8 wAlreadyFailed:: db ; cbd9 -wcbda:: ds 1 ; cbda -wcbdb:: ds 1 ; cbdb +wBattleParticipantsIncludingFainted:: db ; cbda +wBattleLowHealthAlarm:: db ; cbdb wPlayerMinimized:: db ; cbdc wPlayerScreens:: db ; cbdd wEnemyScreens:: db ; cbde @@ -1869,17 +1867,13 @@ wEnemyAISwitchScore:: db ; cbf4 wEnemySwitchMonParam:: db ; cbf5 wEnemySwitchMonIndex:: db ; cbf6 wcbf7:: ds 1 ; cbf7 -wcbf8:: ds 1 ; cbf8 -wLastPlayerMove:: ds 1 ; cbf9 -wLastEnemyMove:: ds 1 ; cbfa +wLastPlayerMon:: db ; cbf8 +wLastPlayerMove:: db ; cbf9 +wLastEnemyMove:: db ; cbfa wPlayerFutureSightCount:: db ; cbfb wEnemyFutureSightCount:: db ; cbfc -wcbfd:: ds 1 ; cbfd -wcbfe:: ds 1 ; cbfe -wcbff:: ds 1 ; cbff -wcc00:: ds 1 ; cc00 -wcc01:: ds 1 ; cc01 -wcc02:: ds 1 ; cc02 +wGivingExperienceToExpShareHolders:: db ; cbfd +wBackupEnemyMonBaseStats:: ds 5 ; cbfe wcc03:: ds 1 ; cc03 wcc04:: ds 1 ; cc04 wPlayerFutureSightDamage:: dw ; cc05 @@ -1893,17 +1887,25 @@ wPlayerWrapCount:: db ; cc0e wEnemyWrapCount:: db ; cc0f wPlayerCharging:: db ; cc10 wEnemyCharging:: db ; cc11 -wcc12:: ds 1 ; cc12 -wWildMonMoves:: ds 1 ; cc13 -wOverworldMapEnd:: - ds NUM_MOVES +- 1 +wBattleEnded:: db ; cc12 + +UNION +wWildMonMoves:: ; cc13 + ds NUM_MOVES +NEXTU + ds 1 +wOverworldMapBlocksEnd:: + ds NUM_MOVES - 1 +ENDU + wWildMonPP:: ds NUM_MOVES ; cc17 -wcc1b:: ds 1 ; cc1b +wAmuletCoin:: db ; cc1b wSomeoneIsRampaging:: db ; cc1c wPlayerJustGotFrozen:: db ; cc1d wEnemyJustGotFrozen:: db ; cc1e -wcc1f:: ds 1 ; cc1f + ds 1 + ENDU ; cc20 SECTION "Video", WRAM0 @@ -2029,7 +2031,7 @@ wcc96:: ds 1 ; cc96 wcc97:: ds 1 ; cc97 wColorLayoutPredefID:: ds 1 ; cc98 wPlayerHPPal:: db ; cc99 -wcc9a:: ds 1 ; cc9a +wEnemyHPPal:: db ; cc9a wcc9b:: ds 1 ; cc9b wcc9c:: ds 1 ; cc9c wcc9d:: ds 1 ; cc9d @@ -2833,18 +2835,14 @@ wd0e9:: ds 1 ; d0e9 wd0ea:: ds 1 ; d0ea wd0eb:: ds 1 ; d0eb wd0ec:: ds 1 ; d0ec -wTempEnemyMonSpecies:: ds 1 ; d0ed -wd0ee:: ds 1 ; d0ee +wTempEnemyMonSpecies:: db ; d0ed +wTempBattleMonSpecies:: db ; d0ee wEnemyMon:: battle_struct wEnemyMon ; d0ef - -wd10f:: ds 1 ; d10f -wd110:: ds 1 ; d110 -wd111:: ds 1 ; d111 -wd112:: ds 1 ; d112 -wd113:: ds 1 ; d113 -wd114:: ds 1 ; d114 -wd115:: ds 1 ; d115 +wEnemyMonBaseStats:: ds 5 ; d10f +wEnemyMonCatchRate:: db ; d114 +wEnemyMonBaseExp:: db ; d115 +wEnemyMonEnd:: wBattleMode:: ds 1 ; d116 wTempWildMonSpecies:: db ; d117 @@ -2859,34 +2857,34 @@ wOtherTrainerID:: db ; d11b wForcedSwitch:: db ; d11c wTrainerClass:: db ; d11d wUnownLetter:: db ; d11e -wd11f:: ds 1 ; d11f +wMoveSelectionMenuType:: db ; d11f -wBaseDexNo:: ; d120 wCurBaseData:: ; d120 -wd120:: ds 1 ; d120 -wd121:: ds 1 ; d121 +wBaseDexNo:: db ; d120 +wBaseStats:: ; d121 +wBaseHP:: db ; d121 wBaseAttack:: db ; d122 wBaseDefense:: db ; d123 -wd124:: ds 1 ; d124 -wd125:: ds 1 ; d125 -wd126:: ds 1 ; d126 -wBaseType:: db ; d127 -wd128:: ds 1 ; d128 -wd129:: ds 1 ; d129 -wd12a:: ds 1 ; d12a -wd12b:: ds 1 ; d12b -wd12c:: ds 1 ; d12c -wd12d:: ds 1 ; d12d -wd12e:: ds 1 ; d12e +wBaseSpeed:: db ; d124 +wBaseSpecialAttack:: db ; d125 +wBaseSpecialDefense:: db ; d126 +wBaseType:: ; d127 +wBaseType1:: db ; d127 +wBaseType2:: db ; d128 +wBaseCatchRate:: db ; d129 +wBaseExp:: db ; d12a +wBaseItems:: ; d12b +wBaseItem1:: db ; d12b +wBaseItem2:: db ; d12c +wBaseGender:: db ; d12d +wBaseUnknown1:: db ; d12e wBaseEggSteps:: db ; d12f -wd130:: ds 1 ; d130 +wBaseUnknown2:: db ; d130 wBasePicSize:: db ; d131 -wBaseUnusedFrontpic:: db ; d132 -wd133:: ds 1 ; d133 -wd134:: ds 1 ; d134 -wd135:: ds 1 ; d135 -wd136:: ds 1 ; d136 -wBaseEggGroups:: db +wBaseUnusedFrontpic:: dw ; d132 +wBaseUnusedBackpic:: dw ; d134 +wBaseGrowthRate:: db ; d136 +wBaseEggGroups:: db ; d137 wd138:: ds 1 ; d138 wd139:: ds 1 ; d139 wd13a:: ds 1 ; d13a @@ -2931,8 +2929,8 @@ wUsePPUp:: wd151:: db ; d151 -wd152:: ds 1 ; d152 -wd153:: ds 1 ; d153 +wFailedToFlee:: db ; d152 +wNumFleeAttempts:: db ; d153 wd154:: ds 1 ; d154 wROMBankBackup:: ds 1 ; d155 wBuffer:: ds 1 ; d156 @@ -3534,7 +3532,12 @@ wd8b6:: ds 1 ; d8b6 wd8b7:: ds 1 ; d8b7 wGameTimerPause:: ds 1 ; d8b8 wd8b9:: ds 1 ; d8b9 -wd8ba:: ds 1 ; d8ba +wd8ba:: ; d8ba +; bits 4, 6, or 7 can be used to disable joypad input +; bit 4 +; bit 6: mon fainted? +; bit 7: SGB flag? + db wd8bb:: ds 1 ; d8bb wCurBox:: ds 1 ; d8bc |