; Core components of the battle engine. BattleCore: DoBattle: ; 3c000 xor a ld [wBattleParticipantsNotFainted], a ld [wBattleParticipantsIncludingFainted], a ld [wPlayerAction], a ld [BattleEnded], a inc a ld [wBattleHasJustStarted], a ld hl, OTPartyMon1HP ld bc, PARTYMON_STRUCT_LENGTH - 1 ld d, BATTLEACTION_SWITCH1 - 1 .loop inc d ld a, [hli] or [hl] jr nz, .alive add hl, bc jr .loop .alive ld a, d ld [wBattleAction], a ld a, [wLinkMode] and a jr z, .not_linked ld a, [hLinkPlayerNumber] cp $2 jr z, .player_2 .not_linked ld a, [wBattleMode] dec a jr z, .wild xor a ld [wEnemySwitchMonIndex], a call NewEnemyMonStatus call ResetEnemyStatLevels call BreakAttraction call EnemySwitch .wild ld c, 40 call DelayFrames .player_2 call LoadTileMapToTempTileMap call CheckPlayerPartyForFitPkmn ld a, d and a jp z, LostBattle call Call_LoadTempTileMapToTileMap ld a, [BattleType] cp BATTLETYPE_DEBUG jp z, .tutorial_debug cp BATTLETYPE_TUTORIAL jp z, .tutorial_debug xor a ld [CurPartyMon], a .loop2 call CheckIfCurPartyMonIsFitToFight jr nz, .alive2 ld hl, CurPartyMon inc [hl] jr .loop2 .alive2 ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, [CurPartyMon] ld [CurBattleMon], a inc a ld hl, PartySpecies - 1 ld c, a ld b, 0 add hl, bc ld a, [hl] ld [CurPartySpecies], a ld [TempBattleMonSpecies], a hlcoord 1, 5 ld a, 9 call SlideBattlePicOut call LoadTileMapToTempTileMap call ResetBattleParticipants call InitBattleMon call ResetPlayerStatLevels call SendOutPkmnText call NewBattleMonStatus call BreakAttraction call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap call SetPlayerTurn call SpikesDamage ld a, [wLinkMode] and a jr z, .not_linked_2 ld a, [hLinkPlayerNumber] cp $2 jr nz, .not_linked_2 xor a ld [wEnemySwitchMonIndex], a call NewEnemyMonStatus call ResetEnemyStatLevels call BreakAttraction call EnemySwitch call SetEnemyTurn call SpikesDamage .not_linked_2 jp BattleTurn .tutorial_debug jp BattleMenu ; 3c0e5 WildFled_EnemyFled_LinkBattleCanceled: ; 3c0e5 call Call_LoadTempTileMapToTileMap ld a, [wBattleResult] and $c0 add $2 ld [wBattleResult], a ld a, [wLinkMode] and a ld hl, BattleText_WildFled jr z, .print_text ld a, [wBattleResult] and $c0 ld [wBattleResult], a ld hl, BattleText_EnemyFled call CheckMobileBattleError jr nc, .print_text ld hl, wcd2a bit 4, [hl] jr nz, .skip_text ld hl, BattleText_LinkErrorBattleCanceled .print_text call StdBattleTextBox .skip_text call StopDangerSound call CheckMobileBattleError jr c, .skip_sfx ld de, SFX_RUN call PlaySFX .skip_sfx call SetPlayerTurn ld a, 1 ld [BattleEnded], a ret ; 3c12f BattleTurn: ; 3c12f .loop call MobileFn_3c1bf call CheckContestBattleOver jp c, .quit xor a ld [wPlayerIsSwitching], a ld [wEnemyIsSwitching], a ld [wBattleHasJustStarted], a ld [wPlayerJustGotFrozen], a ld [wEnemyJustGotFrozen], a ld [CurDamage], a ld [CurDamage + 1], a call HandleBerserkGene call UpdateBattleMonInParty callba AIChooseMove call IsMobileBattle jr nz, .not_disconnected callba Function100da5 callba StartMobileInactivityTimer callba Function100dd8 jp c, .quit .not_disconnected call CheckPlayerLockedIn jr c, .skip_iteration .loop1 call BattleMenu jr c, .quit ld a, [BattleEnded] and a jr nz, .quit ld a, [wForcedSwitch] ; roared/whirlwinded/teleported and a jr nz, .quit .skip_iteration call ParsePlayerAction jr nz, .loop1 call EnemyTriesToFlee jr c, .quit call DetermineMoveOrder jr c, .false call Battle_EnemyFirst jr .proceed .false call Battle_PlayerFirst .proceed call CheckMobileBattleError jr c, .quit ld a, [wForcedSwitch] and a jr nz, .quit ld a, [BattleEnded] and a jr nz, .quit call HandleBetweenTurnEffects ld a, [BattleEnded] and a jr nz, .quit jp .loop .quit ret ; 3c1bf MobileFn_3c1bf: mobile ld a, $5 call GetSRAMBank ld hl, $a89b ; s5_a89b inc [hl] jr nz, .finish dec hl inc [hl] jr nz, .finish dec [hl] inc hl dec [hl] .finish call CloseSRAM ret ; 3c1d6 HandleBetweenTurnEffects: ; 3c1d6 ld a, [hLinkPlayerNumber] cp $1 jr z, .CheckEnemyFirst call CheckFaint_PlayerThenEnemy ret c call HandleFutureSight call CheckFaint_PlayerThenEnemy ret c call HandleWeather call CheckFaint_PlayerThenEnemy ret c call HandleWrap call CheckFaint_PlayerThenEnemy ret c call HandlePerishSong call CheckFaint_PlayerThenEnemy ret c jr .NoMoreFaintingConditions .CheckEnemyFirst: call CheckFaint_EnemyThenPlayer ret c call HandleFutureSight call CheckFaint_EnemyThenPlayer ret c call HandleWeather call CheckFaint_EnemyThenPlayer ret c call HandleWrap call CheckFaint_EnemyThenPlayer ret c call HandlePerishSong call CheckFaint_EnemyThenPlayer ret c .NoMoreFaintingConditions: call HandleLeftovers call HandleMysteryberry call HanleDefrost call HandleSafeguard call HandleScreens call HandleStatBoostingHeldItems call HandleHealingItems call UpdateBattleMonInParty call LoadTileMapToTempTileMap jp HandleEncore ; 3c23c CheckFaint_PlayerThenEnemy: ; 3c23c call HasPlayerFainted jr nz, .PlayerNotFainted call HandlePlayerMonFaint ld a, [BattleEnded] and a jr nz, .BattleIsOver .PlayerNotFainted: call HasEnemyFainted jr nz, .BattleContinues call HandleEnemyMonFaint ld a, [BattleEnded] and a jr nz, .BattleIsOver .BattleContinues: and a ret .BattleIsOver: scf ret ; 3c25c CheckFaint_EnemyThenPlayer: ; 3c25c call HasEnemyFainted jr nz, .EnemyNotFainted call HandleEnemyMonFaint ld a, [BattleEnded] and a jr nz, .BattleIsOver .EnemyNotFainted: call HasPlayerFainted jr nz, .BattleContinues call HandlePlayerMonFaint ld a, [BattleEnded] and a jr nz, .BattleIsOver .BattleContinues: and a ret .BattleIsOver: scf ret ; 3c27c HandleBerserkGene: ; 3c27c ld a, [hLinkPlayerNumber] cp $1 jr z, .reverse call .player jr .enemy .reverse call .enemy ; jr .player .player call SetPlayerTurn ld de, PartyMon1Item ld a, [CurBattleMon] ld b, a jr .go .enemy call SetEnemyTurn ld de, OTPartyMon1Item ld a, [CurOTMon] ld b, a ; jr .go .go push de push bc callab GetUserItem ld a, [hl] ld [wd265], a sub BERSERK_GENE pop bc pop de ret nz ld [hl], a ld h, d ld l, e ld a, b call GetPartyLocation xor a ld [hl], a ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVarAddr push af set SUBSTATUS_CONFUSED, [hl] ld a, BATTLE_VARS_MOVE_ANIM call GetBattleVarAddr push hl push af xor a ld [hl], a ld [AttackMissed], a ld [EffectFailed], a callba BattleCommand_AttackUp2 pop af pop hl ld [hl], a call GetItemName ld hl, BattleText_UsersStringBuffer1Activated call StdBattleTextBox callab BattleCommand_StatUpMessage pop af bit SUBSTATUS_CONFUSED, a ret nz xor a ld [wNumHits], a ld de, ANIM_CONFUSED call Call_PlayBattleAnim_OnlyIfVisible call SwitchTurnCore ld hl, BecameConfusedText jp StdBattleTextBox ; 3c300 EnemyTriesToFlee: ; 3c300 ld a, [wLinkMode] and a jr z, .not_linked ld a, [wBattleAction] cp BATTLEACTION_FORFEIT jr z, .forfeit .not_linked and a ret .forfeit call WildFled_EnemyFled_LinkBattleCanceled scf ret ; 3c314 DetermineMoveOrder: ; 3c314 ld a, [wLinkMode] and a jr z, .use_move ld a, [wBattleAction] cp BATTLEACTION_E jr z, .use_move cp BATTLEACTION_D jr z, .use_move sub BATTLEACTION_SWITCH1 jr c, .use_move ld a, [wPlayerAction] cp $2 jr nz, .switch ld a, [hLinkPlayerNumber] cp $2 jr z, .player_2 call BattleRandom cp 1 + (50 percent) jp c, .player_first jp .enemy_first .player_2 call BattleRandom cp 1 + (50 percent) jp c, .enemy_first jp .player_first .switch callab AI_Switch call SetEnemyTurn call SpikesDamage jp .enemy_first .use_move ld a, [wPlayerAction] and a jp nz, .player_first call CompareMovePriority jr z, .equal_priority jp c, .player_first ; player goes first jp .enemy_first .equal_priority call SetPlayerTurn callab GetUserItem push bc callab GetOpponentItem pop de ld a, d cp HELD_QUICK_CLAW jr nz, .player_no_quick_claw ld a, b cp HELD_QUICK_CLAW jr z, .both_have_quick_claw call BattleRandom cp e jr nc, .speed_check jp .player_first .player_no_quick_claw ld a, b cp HELD_QUICK_CLAW jr nz, .speed_check call BattleRandom cp c jr nc, .speed_check jp .enemy_first .both_have_quick_claw ld a, [hLinkPlayerNumber] cp $2 jr z, .player_2b call BattleRandom cp c jp c, .enemy_first call BattleRandom cp e jp c, .player_first jr .speed_check .player_2b call BattleRandom cp e jp c, .player_first call BattleRandom cp c jp c, .enemy_first jr .speed_check .speed_check ld de, BattleMonSpeed ld hl, EnemyMonSpeed ld c, 2 call StringCmp jr z, .speed_tie jp nc, .player_first jp .enemy_first .speed_tie ld a, [hLinkPlayerNumber] cp $2 jr z, .player_2c call BattleRandom cp 1 + (50 percent) jp c, .player_first jp .enemy_first .player_2c call BattleRandom cp 1 + (50 percent) jp c, .enemy_first .player_first scf ret ; 3c3f3 .enemy_first ; 3c3f3 and a ret ; 3c3f5 CheckContestBattleOver: ; 3c3f5 ld a, [BattleType] cp BATTLETYPE_CONTEST jr nz, .contest_not_over ld a, [wParkBallsRemaining] and a jr nz, .contest_not_over ld a, [wBattleResult] and $c0 add $2 ld [wBattleResult], a scf ret .contest_not_over and a ret ; 3c410 CheckPlayerLockedIn: ; 3c410 ld a, [PlayerSubStatus4] and 1 << SUBSTATUS_RECHARGE jp nz, .quit ld hl, EnemySubStatus3 res SUBSTATUS_FLINCHED, [hl] ld hl, PlayerSubStatus3 res SUBSTATUS_FLINCHED, [hl] ld a, [hl] and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE jp nz, .quit ld hl, PlayerSubStatus1 bit SUBSTATUS_ROLLOUT, [hl] jp nz, .quit and a ret .quit scf ret ; 3c434 ParsePlayerAction: ; 3c434 call CheckPlayerLockedIn jp c, .locked_in ld hl, PlayerSubStatus5 bit SUBSTATUS_ENCORED, [hl] jr z, .not_encored ld a, [LastPlayerMove] ld [CurPlayerMove], a jr .encored .not_encored ld a, [wPlayerAction] cp $2 jr z, .reset_rage and a jr nz, .reset_bide ld a, [PlayerSubStatus3] and 1 << SUBSTATUS_BIDE jr nz, .locked_in xor a ld [wMoveSelectionMenuType], a inc a ; POUND ld [FXAnimID], a call MoveSelectionScreen push af call Call_LoadTempTileMapToTileMap call UpdateBattleHuds ld a, [CurPlayerMove] cp STRUGGLE jr z, .struggle call PlayClickSFX .struggle ld a, $1 ld [hBGMapMode], a pop af ret nz .encored call SetPlayerTurn callab UpdateMoveData xor a ld [wPlayerCharging], a ld a, [wPlayerMoveStruct + MOVE_EFFECT] cp EFFECT_FURY_CUTTER jr z, .continue_fury_cutter xor a ld [PlayerFuryCutterCount], a .continue_fury_cutter ld a, [wPlayerMoveStruct + MOVE_EFFECT] cp EFFECT_RAGE jr z, .continue_rage ld hl, PlayerSubStatus4 res SUBSTATUS_RAGE, [hl] xor a ld [wPlayerRageCounter], a .continue_rage ld a, [wPlayerMoveStruct + MOVE_EFFECT] cp EFFECT_PROTECT jr z, .continue_protect cp EFFECT_ENDURE jr z, .continue_protect xor a ld [PlayerProtectCount], a jr .continue_protect .reset_bide ld hl, PlayerSubStatus3 res SUBSTATUS_BIDE, [hl] .locked_in xor a ld [PlayerFuryCutterCount], a ld [PlayerProtectCount], a ld [wPlayerRageCounter], a ld hl, PlayerSubStatus4 res SUBSTATUS_RAGE, [hl] .continue_protect call ParseEnemyAction xor a ret .reset_rage xor a ld [PlayerFuryCutterCount], a ld [PlayerProtectCount], a ld [wPlayerRageCounter], a ld hl, PlayerSubStatus4 res SUBSTATUS_RAGE, [hl] xor a ret ; 3c4df HandleEncore: ; 3c4df ld a, [hLinkPlayerNumber] cp $1 jr z, .player_1 call .do_player jr .do_enemy .player_1 call .do_enemy .do_player ld hl, PlayerSubStatus5 bit SUBSTATUS_ENCORED, [hl] ret z ld a, [PlayerEncoreCount] dec a ld [PlayerEncoreCount], a jr z, .end_player_encore ld hl, BattleMonPP ld a, [CurMoveNum] ld c, a ld b, 0 add hl, bc ld a, [hl] and $3f ret nz .end_player_encore ld hl, PlayerSubStatus5 res SUBSTATUS_ENCORED, [hl] call SetEnemyTurn ld hl, BattleText_TargetsEncoreEnded jp StdBattleTextBox .do_enemy ld hl, EnemySubStatus5 bit SUBSTATUS_ENCORED, [hl] ret z ld a, [EnemyEncoreCount] dec a ld [EnemyEncoreCount], a jr z, .end_enemy_encore ld hl, EnemyMonPP ld a, [CurEnemyMoveNum] ld c, a ld b, 0 add hl, bc ld a, [hl] and $3f ret nz .end_enemy_encore ld hl, EnemySubStatus5 res SUBSTATUS_ENCORED, [hl] call SetPlayerTurn ld hl, BattleText_TargetsEncoreEnded jp StdBattleTextBox ; 3c543 TryEnemyFlee: ; 3c543 ld a, [wBattleMode] dec a jr nz, .Stay ld a, [PlayerSubStatus5] bit SUBSTATUS_CANT_RUN, a jr nz, .Stay ld a, [wEnemyWrapCount] and a jr nz, .Stay ld a, [EnemyMonStatus] and 1 << FRZ | SLP jr nz, .Stay ld a, [TempEnemyMonSpecies] ld de, 1 ld hl, AlwaysFleeMons call IsInArray jr c, .Flee call BattleRandom ld b, a cp 1 + (50 percent) jr nc, .Stay push bc ld a, [TempEnemyMonSpecies] ld de, 1 ld hl, OftenFleeMons call IsInArray pop bc jr c, .Flee ld a, b cp 1 + (10 percent) jr nc, .Stay ld a, [TempEnemyMonSpecies] ld de, 1 ld hl, SometimesFleeMons call IsInArray jr c, .Flee .Stay: and a ret .Flee: scf ret ; 3c59a FleeMons: SometimesFleeMons: ; 3c59a db MAGNEMITE db GRIMER db TANGELA db MR__MIME db EEVEE db PORYGON db DRATINI db DRAGONAIR db TOGETIC db UMBREON db UNOWN db SNUBBULL db HERACROSS db -1 OftenFleeMons: ; 3c5a8 db CUBONE db ARTICUNO db ZAPDOS db MOLTRES db QUAGSIRE db DELIBIRD db PHANPY db TEDDIURSA db -1 AlwaysFleeMons: ; 3c5b1 db RAIKOU db ENTEI ; db SUICUNE db -1 ; 3c5b4 CompareMovePriority: ; 3c5b4 ; Compare the priority of the player and enemy's moves. ; Return carry if the player goes first, or z if they match. ld a, [CurPlayerMove] call GetMovePriority ld b, a push bc ld a, [CurEnemyMove] call GetMovePriority pop bc cp b ret ; 3c5c5 GetMovePriority: ; 3c5c5 ; Return the priority (0-3) of move a. ld b, a ; Vital throw goes last. cp VITAL_THROW ld a, 0 ret z call GetMoveEffect ld hl, MoveEffectPriorities .loop ld a, [hli] cp b jr z, .done inc hl cp -1 jr nz, .loop ld a, 1 ret .done ld a, [hl] ret ; 3c5df MoveEffectPriorities: ; 3c5df db EFFECT_PROTECT, 3 db EFFECT_ENDURE, 3 db EFFECT_PRIORITY_HIT, 2 db EFFECT_FORCE_SWITCH, 0 db EFFECT_COUNTER, 0 db EFFECT_MIRROR_COAT, 0 db -1 ; 3c5ec GetMoveEffect: ; 3c5ec ld a, b dec a ld hl, Moves + MOVE_EFFECT ld bc, MOVE_LENGTH call AddNTimes ld a, BANK(Moves) call GetFarByte ld b, a ret ; 3c5fe Battle_EnemyFirst: ; 3c5fe call LoadTileMapToTempTileMap call TryEnemyFlee jp c, WildFled_EnemyFled_LinkBattleCanceled call SetEnemyTurn ld a, $1 ld [wEnemyGoesFirst], a callab AI_SwitchOrTryItem jr c, .switch_item call EnemyTurn_EndOpponentProtectEndureDestinyBond call CheckMobileBattleError ret c ld a, [wForcedSwitch] and a ret nz call HasPlayerFainted jp z, HandlePlayerMonFaint call HasEnemyFainted jp z, HandleEnemyMonFaint .switch_item call SetEnemyTurn call ResidualDamage jp z, HandleEnemyMonFaint call RefreshBattleHuds call PlayerTurn_EndOpponentProtectEndureDestinyBond call CheckMobileBattleError ret c ld a, [wForcedSwitch] and a ret nz call HasEnemyFainted jp z, HandleEnemyMonFaint call HasPlayerFainted jp z, HandlePlayerMonFaint call SetPlayerTurn call ResidualDamage jp z, HandlePlayerMonFaint call RefreshBattleHuds xor a ld [wPlayerAction], a ret ; 3c664 Battle_PlayerFirst: ; 3c664 xor a ld [wEnemyGoesFirst], a call SetEnemyTurn callab AI_SwitchOrTryItem push af call PlayerTurn_EndOpponentProtectEndureDestinyBond pop bc ld a, [wForcedSwitch] and a ret nz call CheckMobileBattleError ret c call HasEnemyFainted jp z, HandleEnemyMonFaint call HasPlayerFainted jp z, HandlePlayerMonFaint push bc call SetPlayerTurn call ResidualDamage pop bc jp z, HandlePlayerMonFaint push bc call RefreshBattleHuds pop af jr c, .switched_or_used_item call LoadTileMapToTempTileMap call TryEnemyFlee jp c, WildFled_EnemyFled_LinkBattleCanceled call EnemyTurn_EndOpponentProtectEndureDestinyBond call CheckMobileBattleError ret c ld a, [wForcedSwitch] and a ret nz call HasPlayerFainted jp z, HandlePlayerMonFaint call HasEnemyFainted jp z, HandleEnemyMonFaint .switched_or_used_item call SetEnemyTurn call ResidualDamage jp z, HandleEnemyMonFaint call RefreshBattleHuds xor a ld [wPlayerAction], a ret ; 3c6cf PlayerTurn_EndOpponentProtectEndureDestinyBond: ; 3c6cf call SetPlayerTurn call EndUserDestinyBond callab DoPlayerTurn jp EndOpponentProtectEndureDestinyBond ; 3c6de EnemyTurn_EndOpponentProtectEndureDestinyBond: ; 3c6de call SetEnemyTurn call EndUserDestinyBond callab DoEnemyTurn jp EndOpponentProtectEndureDestinyBond ; 3c6ed EndOpponentProtectEndureDestinyBond: ; 3c6ed ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVarAddr res SUBSTATUS_PROTECT, [hl] res SUBSTATUS_ENDURE, [hl] ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr res SUBSTATUS_DESTINY_BOND, [hl] ret ; 3c6fe EndUserDestinyBond: ; 3c6fe ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVarAddr res SUBSTATUS_DESTINY_BOND, [hl] ret ; 3c706 HasUserFainted: ; 3c706 ld a, [hBattleTurn] and a jr z, HasPlayerFainted HasEnemyFainted: ; 3c70b ld hl, EnemyMonHP jr CheckIfHPIsZero HasPlayerFainted: ; 3c710 ld hl, BattleMonHP CheckIfHPIsZero: ; 3c713 ld a, [hli] or [hl] ret ; 3c716 ResidualDamage: ; 3c716 ; Return z if the user fainted before ; or as a result of residual damage. ; For Sandstorm damage, see HandleWeather. call HasUserFainted ret z ld a, BATTLE_VARS_STATUS call GetBattleVar and 1 << PSN | 1 << BRN jr z, .did_psn_brn ld hl, HurtByPoisonText ld de, ANIM_PSN and 1 << BRN jr z, .got_anim ld hl, HurtByBurnText ld de, ANIM_BRN .got_anim push de call StdBattleTextBox pop de xor a ld [wNumHits], a call Call_PlayBattleAnim_OnlyIfVisible call GetEighthMaxHP ld de, PlayerToxicCount ld a, [hBattleTurn] and a jr z, .check_toxic ld de, EnemyToxicCount .check_toxic ld a, BATTLE_VARS_SUBSTATUS5 call GetBattleVar bit SUBSTATUS_TOXIC, a jr z, .did_toxic call GetSixteenthMaxHP ld a, [de] inc a ld [de], a ld hl, 0 .add add hl, bc dec a jr nz, .add ld b, h ld c, l .did_toxic call SubtractHPFromUser .did_psn_brn call HasUserFainted jp z, .fainted ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVarAddr bit SUBSTATUS_LEECH_SEED, [hl] jr z, .not_seeded call SwitchTurnCore xor a ld [wNumHits], a ld de, ANIM_SAP ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND call z, Call_PlayBattleAnim_OnlyIfVisible call SwitchTurnCore call GetEighthMaxHP call SubtractHPFromUser ld a, $1 ld [hBGMapMode], a call RestoreHP ld hl, LeechSeedSapsText call StdBattleTextBox .not_seeded call HasUserFainted jr z, .fainted ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr bit SUBSTATUS_NIGHTMARE, [hl] jr z, .not_nightmare xor a ld [wNumHits], a ld de, ANIM_IN_NIGHTMARE call Call_PlayBattleAnim_OnlyIfVisible call GetQuarterMaxHP call SubtractHPFromUser ld hl, HasANightmareText call StdBattleTextBox .not_nightmare call HasUserFainted jr z, .fainted ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr bit SUBSTATUS_CURSE, [hl] jr z, .not_cursed xor a ld [wNumHits], a ld de, ANIM_IN_NIGHTMARE call Call_PlayBattleAnim_OnlyIfVisible call GetQuarterMaxHP call SubtractHPFromUser ld hl, HurtByCurseText call StdBattleTextBox .not_cursed ld hl, BattleMonHP ld a, [hBattleTurn] and a jr z, .check_fainted ld hl, EnemyMonHP .check_fainted ld a, [hli] or [hl] ret nz .fainted call RefreshBattleHuds ld c, 20 call DelayFrames xor a ret ; 3c801 HandlePerishSong: ; 3c801 ld a, [hLinkPlayerNumber] cp $1 jr z, .EnemyFirst call SetPlayerTurn call .do_it call SetEnemyTurn jp .do_it .EnemyFirst: call SetEnemyTurn call .do_it call SetPlayerTurn .do_it ld hl, PlayerPerishCount ld a, [hBattleTurn] and a jr z, .got_count ld hl, EnemyPerishCount .got_count ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVar bit SUBSTATUS_PERISH, a ret z dec [hl] ld a, [hl] ld [wd265], a push af ld hl, PerishCountText call StdBattleTextBox pop af ret nz ld a, BATTLE_VARS_SUBSTATUS1 call GetBattleVarAddr res SUBSTATUS_PERISH, [hl] ld a, [hBattleTurn] and a jr nz, .kill_enemy ld hl, BattleMonHP xor a ld [hli], a ld [hl], a ld hl, PartyMon1HP ld a, [CurBattleMon] call GetPartyLocation xor a ld [hli], a ld [hl], a ret .kill_enemy ld hl, EnemyMonHP xor a ld [hli], a ld [hl], a ld a, [wBattleMode] dec a ret z ld hl, OTPartyMon1HP ld a, [CurOTMon] call GetPartyLocation xor a ld [hli], a ld [hl], a ret ; 3c874 HandleWrap: ; 3c874 ld a, [hLinkPlayerNumber] cp $1 jr z, .EnemyFirst call SetPlayerTurn call .do_it call SetEnemyTurn jp .do_it .EnemyFirst: call SetEnemyTurn call .do_it call SetPlayerTurn .do_it ld hl, wPlayerWrapCount ld de, wPlayerTrappingMove ld a, [hBattleTurn] and a jr z, .got_addrs ld hl, wEnemyWrapCount ld de, wEnemyTrappingMove .got_addrs ld a, [hl] and a ret z ld a, BATTLE_VARS_SUBSTATUS4 call GetBattleVar bit SUBSTATUS_SUBSTITUTE, a ret nz ld a, [de] ld [wd265], a ld [FXAnimID], 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 [FXAnimID + 1], a predef PlayBattleAnim call SwitchTurnCore .skip_anim call GetSixteenthMaxHP call SubtractHPFromUser ld hl, BattleText_UsersHurtByStringBuffer1 jr .print_text .release_from_bounds ld hl, BattleText_UserWasReleasedFromStringBuffer1 .print_text jp StdBattleTextBox ; 3c8e4 SwitchTurnCore: ; 3c8e4 ld a, [hBattleTurn] xor 1 ld [hBattleTurn], a ret ; 3c8eb HandleLeftovers: ; 3c8eb ld a, [hLinkPlayerNumber] cp $1 jr z, .DoEnemyFirst call SetPlayerTurn call .do_it call SetEnemyTurn jp .do_it .DoEnemyFirst: call SetEnemyTurn call .do_it call SetPlayerTurn .do_it callab GetUserItem ld a, [hl] ld [wd265], a call GetItemName ld a, b cp HELD_LEFTOVERS ret nz ld hl, BattleMonHP ld a, [hBattleTurn] and a jr z, .got_hp ld hl, EnemyMonHP .got_hp ; Don't restore if we're already at max HP ld a, [hli] ld b, a ld a, [hli] ld c, a ld a, [hli] cp b jr nz, .restore ld a, [hl] cp c ret z .restore call GetSixteenthMaxHP call SwitchTurnCore call RestoreHP ld hl, BattleText_TargetRecoveredWithItem jp StdBattleTextBox ; 3c93c HandleMysteryberry: ; 3c93c ld a, [hLinkPlayerNumber] cp $1 jr z, .DoEnemyFirst call SetPlayerTurn call .do_it call SetEnemyTurn jp .do_it .DoEnemyFirst: call SetEnemyTurn call .do_it call SetPlayerTurn .do_it callab GetUserItem ld a, b cp HELD_RESTORE_PP jr nz, .quit ld hl, PartyMon1PP ld a, [CurBattleMon] call GetPartyLocation ld d, h ld e, l ld hl, PartyMon1Moves ld a, [CurBattleMon] call GetPartyLocation ld a, [hBattleTurn] and a jr z, .wild ld de, wWildMonPP ld hl, wWildMonMoves ld a, [wBattleMode] dec a jr z, .wild ld hl, OTPartyMon1PP ld a, [CurOTMon] call GetPartyLocation ld d, h ld e, l ld hl, OTPartyMon1Moves ld a, [CurOTMon] call GetPartyLocation .wild ld c, $0 .loop ld a, [hl] and a jr z, .quit ld a, [de] and $3f jr z, .restore inc hl inc de inc c ld a, c cp NUM_MOVES jr nz, .loop .quit ret .restore ; lousy hack ld a, [hl] cp SKETCH ld b, 1 jr z, .sketch ld b, 5 .sketch ld a, [de] add b ld [de], a push bc push bc ld a, [hl] ld [wd265], a ld de, BattleMonMoves - 1 ld hl, BattleMonPP ld a, [hBattleTurn] and a jr z, .player_pp ld de, EnemyMonMoves - 1 ld hl, EnemyMonPP .player_pp inc de pop bc ld b, 0 add hl, bc push hl ld h, d ld l, e add hl, bc pop de pop bc ld a, [wd265] cp [hl] jr nz, .skip_checks ld a, [hBattleTurn] and a ld a, [PlayerSubStatus5] jr z, .check_transform ld a, [EnemySubStatus5] .check_transform bit SUBSTATUS_TRANSFORMED, a jr nz, .skip_checks ld a, [de] add b ld [de], a .skip_checks callab GetUserItem ld a, [hl] ld [wd265], a xor a ld [hl], a call GetPartymonItem ld a, [hBattleTurn] and a jr z, .consume_item ld a, [wBattleMode] dec a jr z, .skip_consumption call GetOTPartymonItem .consume_item xor a ld [hl], a .skip_consumption call GetItemName call SwitchTurnCore call ItemRecoveryAnim call SwitchTurnCore ld hl, BattleText_UserRecoveredPPUsing jp StdBattleTextBox ; 3ca26 HandleFutureSight: ; 3ca26 ld a, [hLinkPlayerNumber] cp $1 jr z, .enemy_first call SetPlayerTurn call .do_it call SetEnemyTurn jp .do_it .enemy_first call SetEnemyTurn call .do_it call SetPlayerTurn .do_it ld hl, wPlayerFutureSightCount ld a, [hBattleTurn] and a jr z, .okay ld hl, wEnemyFutureSightCount .okay ld a, [hl] and a ret z dec a ld [hl], a cp $1 ret nz ld hl, BattleText_TargetWasHitByFutureSight call StdBattleTextBox ld a, BATTLE_VARS_MOVE call GetBattleVarAddr push af ld a, FUTURE_SIGHT ld [hl], a callab UpdateMoveData xor a ld [AttackMissed], a ld [AlreadyDisobeyed], a ld a, 10 ld [TypeModifier], a callab DoMove xor a ld [CurDamage], a ld [CurDamage + 1], a ld a, BATTLE_VARS_MOVE call GetBattleVarAddr pop af ld [hl], a call UpdateBattleMonInParty jp UpdateEnemyMonInParty ; 3ca8f HanleDefrost: ; 3ca8f ld a, [hLinkPlayerNumber] cp $1 jr z, .enemy_first call .do_player_turn jr .do_enemy_turn .enemy_first call .do_enemy_turn .do_player_turn ld a, [BattleMonStatus] bit FRZ, a ret z ld a, [wPlayerJustGotFrozen] and a ret nz call BattleRandom cp 10 percent ret nc xor a ld [BattleMonStatus], a ld a, [CurBattleMon] ld hl, PartyMon1Status call GetPartyLocation ld [hl], 0 call UpdateBattleHuds call SetEnemyTurn ld hl, DefrostedOpponentText jp StdBattleTextBox .do_enemy_turn ld a, [EnemyMonStatus] bit FRZ, a ret z ld a, [wEnemyJustGotFrozen] and a ret nz call BattleRandom cp 10 percent ret nc xor a ld [EnemyMonStatus], a ld a, [wBattleMode] dec a jr z, .wild ld a, [CurOTMon] ld hl, OTPartyMon1Status call GetPartyLocation ld [hl], 0 .wild call UpdateBattleHuds call SetPlayerTurn ld hl, DefrostedOpponentText jp StdBattleTextBox ; 3cafb HandleSafeguard: ; 3cafb ld a, [hLinkPlayerNumber] cp $1 jr z, .player1 call .CheckPlayer jr .CheckEnemy .player1 call .CheckEnemy .CheckPlayer: ld a, [PlayerScreens] bit SCREENS_SAFEGUARD, a ret z ld hl, PlayerSafeguardCount dec [hl] ret nz res SCREENS_SAFEGUARD, a ld [PlayerScreens], a xor a jr .print .CheckEnemy: ld a, [EnemyScreens] bit SCREENS_SAFEGUARD, a ret z ld hl, EnemySafeguardCount dec [hl] ret nz res SCREENS_SAFEGUARD, a ld [EnemyScreens], a ld a, $1 .print ld [hBattleTurn], a ld hl, BattleText_SafeguardFaded jp StdBattleTextBox HandleScreens: ; 3cb36 ld a, [hLinkPlayerNumber] cp 1 jr z, .Both call .CheckPlayer jr .CheckEnemy .Both: call .CheckEnemy .CheckPlayer: call SetPlayerTurn ld de, .Your call .Copy ld hl, PlayerScreens ld de, PlayerLightScreenCount jr .TickScreens .CheckEnemy: call SetEnemyTurn ld de, .Enemy call .Copy ld hl, EnemyScreens ld de, EnemyLightScreenCount .TickScreens: bit SCREENS_LIGHT_SCREEN, [hl] call nz, .LightScreenTick bit SCREENS_REFLECT, [hl] call nz, .ReflectTick ret .Copy: ld hl, StringBuffer1 jp CopyName2 ; 3cb75 .Your: db "Your@" .Enemy: db "Enemy@" ; 3cb80 .LightScreenTick: ; 3cb80 ld a, [de] dec a ld [de], a ret nz res SCREENS_LIGHT_SCREEN, [hl] push hl push de ld hl, BattleText_PkmnLightScreenFell call StdBattleTextBox pop de pop hl ret ; 3cb91 .ReflectTick: ; 3cb91 inc de ld a, [de] dec a ld [de], a ret nz res SCREENS_REFLECT, [hl] ld hl, BattleText_PkmnReflectFaded jp StdBattleTextBox ; 3cb9e HandleWeather: ; 3cb9e ld a, [Weather] cp WEATHER_NONE ret z ld hl, WeatherCount dec [hl] jr z, .ended ld hl, .WeatherMessages call .PrintWeatherMessage ld a, [Weather] cp WEATHER_SANDSTORM ret nz ld a, [hLinkPlayerNumber] cp 1 jr z, .enemy_first .player_first call SetPlayerTurn call .SandstormDamage call SetEnemyTurn jr .SandstormDamage .enemy_first call SetEnemyTurn call .SandstormDamage call SetPlayerTurn .SandstormDamage: ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar bit SUBSTATUS_UNDERGROUND, a ret nz ld hl, BattleMonType1 ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonType1 .ok ld a, [hli] cp ROCK ret z cp GROUND ret z cp STEEL ret z ld a, [hl] cp ROCK ret z cp GROUND ret z cp STEEL ret z call SwitchTurnCore xor a ld [wNumHits], a ld de, ANIM_IN_SANDSTORM call Call_PlayBattleAnim call SwitchTurnCore call GetEighthMaxHP call SubtractHPFromUser ld hl, SandstormHitsText jp StdBattleTextBox .ended ld hl, .WeatherEndedMessages call .PrintWeatherMessage xor a ld [Weather], a ret .PrintWeatherMessage: ld a, [Weather] dec a ld c, a ld b, 0 add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a jp StdBattleTextBox ; 3cc2d .WeatherMessages: dw BattleText_RainContinuesToFall dw BattleText_TheSunlightIsStrong dw BattleText_TheSandstormRages .WeatherEndedMessages: dw BattleText_TheRainStopped dw BattleText_TheSunlightFaded dw BattleText_TheSandstormSubsided ; 3cc39 SubtractHPFromTarget: ; 3cc39 call SubtractHP jp UpdateHPBar ; 3cc3f SubtractHPFromUser: ; 3cc3f ; Subtract HP from Pkmn call SubtractHP jp UpdateHPBarBattleHuds ; 3cc45 SubtractHP: ; 3cc45 ld hl, BattleMonHP ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonHP .ok inc hl ld a, [hl] ld [Buffer3], a sub c ld [hld], a ld [Buffer5], a ld a, [hl] ld [Buffer4], a sbc b ld [hl], a ld [Buffer6], a ret nc ld a, [Buffer3] ld c, a ld a, [Buffer4] ld b, a xor a ld [hli], a ld [hl], a ld [Buffer5], a ld [Buffer6], a ret ; 3cc76 GetSixteenthMaxHP: ; 3cc76 call GetQuarterMaxHP ; quarter result srl c srl c ; round up ld a, c and a jr nz, .ok inc c .ok ret ; 3cc83 GetEighthMaxHP: ; 3cc83 ; output: bc call GetQuarterMaxHP ; assumes nothing can have 1024 or more hp ; halve result srl c ; round up ld a, c and a jr nz, .end inc c .end ret ; 3cc8e GetQuarterMaxHP: ; 3cc8e ; output: bc call GetMaxHP ; quarter result srl b rr c srl b rr c ; assumes nothing can have 1024 or more hp ; round up ld a, c and a jr nz, .end inc c .end ret ; 3cc9f GetHalfMaxHP: ; 3cc9f ; output: bc call GetMaxHP ; halve result srl b rr c ; floor = 1 ld a, c or b jr nz, .end inc c .end ret ; 3ccac GetMaxHP: ; 3ccac ; output: bc, Buffer1-2 ld hl, BattleMonMaxHP ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonMaxHP .ok ld a, [hli] ld [Buffer2], a ld b, a ld a, [hl] ld [Buffer1], a ld c, a ret ; 3ccc2 GetHalfHP: ; 3ccc2 ; unreferenced ld hl, BattleMonHP ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonHP .ok ld a, [hli] ld b, a ld a, [hli] ld c, a srl b rr c ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a ret ; 3ccde CheckUserHasEnoughHP: ; 3ccde ld hl, BattleMonHP + 1 ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyMonHP + 1 .ok ld a, c sub [hl] dec hl ld a, b sbc [hl] ret ; 3ccef RestoreHP ; 3ccef ld hl, EnemyMonMaxHP ld a, [hBattleTurn] and a jr z, .ok ld hl, BattleMonMaxHP .ok ld a, [hli] ld [Buffer2], a ld a, [hld] ld [Buffer1], a dec hl ld a, [hl] ld [Buffer3], a add c ld [hld], a ld [Buffer5], a ld a, [hl] ld [Buffer4], a adc b ld [hli], a ld [Buffer6], a ld a, [Buffer1] ld c, a ld a, [hld] sub c ld a, [Buffer2] ld b, a ld a, [hl] sbc b jr c, .asm_3cd2d ld a, b ld [hli], a ld [Buffer6], a ld a, c ld [hl], a ld [Buffer5], a .asm_3cd2d call SwitchTurnCore call UpdateHPBarBattleHuds jp SwitchTurnCore ; 3cd36 UpdateHPBarBattleHuds: ; 3cd36 call UpdateHPBar jp UpdateBattleHuds ; 3cd3c UpdateHPBar: ; 3cd3c hlcoord 10, 9 ld a, [hBattleTurn] and a ld a, 1 jr z, .ok hlcoord 2, 2 xor a .ok push bc ld [wWhichHPBar], a predef AnimateHPBar pop bc ret ; 3cd55 HandleEnemyMonFaint: ; 3cd55 call FaintEnemyPokemon ld hl, BattleMonHP ld a, [hli] or [hl] call z, FaintYourPokemon xor a ld [wWhichMonFaintedFirst], a call UpdateBattleStateAndExperienceAfterEnemyFaint call CheckPlayerPartyForFitPkmn ld a, d and a jp z, LostBattle ld hl, BattleMonHP ld a, [hli] or [hl] call nz, UpdatePlayerHUD ld a, $1 ld [hBGMapMode], a ld c, 60 call DelayFrames ld a, [wBattleMode] dec a jr nz, .trainer ld a, 1 ld [BattleEnded], a ret .trainer call CheckEnemyTrainerDefeated jp z, WinTrainerBattle ld hl, BattleMonHP ld a, [hli] or [hl] jr nz, .player_mon_not_fainted call AskUseNextPokemon jr nc, .dont_flee ld a, 1 ld [BattleEnded], a ret .dont_flee call ForcePlayerMonChoice call CheckMobileBattleError jp c, WildFled_EnemyFled_LinkBattleCanceled ld a, $1 ld [wPlayerAction], a call HandleEnemySwitch jp z, WildFled_EnemyFled_LinkBattleCanceled jr DoubleSwitch .player_mon_not_fainted ld a, $1 ld [wPlayerAction], a call HandleEnemySwitch jp z, WildFled_EnemyFled_LinkBattleCanceled xor a ld [wPlayerAction], a ret ; 3cdca DoubleSwitch: ; 3cdca ld a, [hLinkPlayerNumber] cp $1 jr z, .player_1 call ClearSprites hlcoord 1, 0 lb bc, 4, 10 call ClearBox call PlayerPartyMonEntrance ld a, $1 call EnemyPartyMonEntrance jr .done .player_1 ld a, [CurPartyMon] push af ld a, $1 call EnemyPartyMonEntrance call ClearSprites call LoadTileMapToTempTileMap pop af ld [CurPartyMon], a call PlayerPartyMonEntrance .done xor a ld [wPlayerAction], a ret ; 3ce01 UpdateBattleStateAndExperienceAfterEnemyFaint: ; 3ce01 call UpdateBattleMonInParty ld a, [wBattleMode] dec a jr z, .wild ld a, [CurOTMon] ld hl, OTPartyMon1HP call GetPartyLocation xor a ld [hli], a ld [hl], a .wild ld hl, PlayerSubStatus3 res SUBSTATUS_IN_LOOP, [hl] xor a ld hl, EnemyDamageTaken ld [hli], a ld [hl], a call NewEnemyMonStatus call BreakAttraction ld a, [wBattleMode] dec a jr z, .wild2 jr .trainer .wild2 call StopDangerSound ld a, $1 ld [wDanger], a .trainer ld hl, BattleMonHP ld a, [hli] or [hl] jr nz, .player_mon_did_not_faint ld a, [wWhichMonFaintedFirst] and a jr nz, .player_mon_did_not_faint call PlayerMonFaintHappinessMod .player_mon_did_not_faint call CheckPlayerPartyForFitPkmn ld a, d and a ret z ld a, [wBattleMode] dec a call z, PlayVictoryMusic call EmptyBattleTextBox call LoadTileMapToTempTileMap ld a, [wBattleResult] and $c0 ld [wBattleResult], a call IsAnyMonHoldingExpShare jr z, .skip_exp ld hl, EnemyMonBaseStats ld b, EnemyMonEnd - EnemyMonBaseStats .loop srl [hl] inc hl dec b jr nz, .loop .skip_exp ld hl, EnemyMonBaseStats ld de, wBackupEnemyMonBaseStats ld bc, EnemyMonEnd - EnemyMonBaseStats call CopyBytes xor a ld [wGivingExperienceToExpShareHolders], a call GiveExperiencePoints call IsAnyMonHoldingExpShare ret z ld a, [wBattleParticipantsNotFainted] push af ld a, d ld [wBattleParticipantsNotFainted], a ld hl, wBackupEnemyMonBaseStats ld de, EnemyMonBaseStats ld bc, EnemyMonEnd - EnemyMonBaseStats call CopyBytes ld a, $1 ld [wGivingExperienceToExpShareHolders], a call GiveExperiencePoints pop af ld [wBattleParticipantsNotFainted], a ret ; 3ceaa IsAnyMonHoldingExpShare: ; 3ceaa ld a, [PartyCount] ld b, a ld hl, PartyMon1 ld c, 1 ld d, 0 .loop push hl push bc ld bc, MON_HP add hl, bc ld a, [hli] or [hl] pop bc pop hl jr z, .next push hl push bc ld bc, MON_ITEM add hl, bc pop bc ld a, [hl] pop hl cp EXP_SHARE jr nz, .next ld a, d or c ld d, a .next sla c push de ld de, PARTYMON_STRUCT_LENGTH add hl, de pop de dec b jr nz, .loop ld a, d ld e, 0 ld b, PARTY_LENGTH .loop2 srl a jr nc, .okay inc e .okay dec b jr nz, .loop2 ld a, e and a ret ; 3ceec StopDangerSound: ; 3ceec xor a ld [Danger], a ret ; 3cef1 FaintYourPokemon: ; 3cef1 call StopDangerSound call WaitSFX ld a, $f0 ld [CryTracks], a ld a, [BattleMonSpecies] call PlayStereoCry call PlayerMonFaintedAnimation hlcoord 9, 7 lb bc, 5, 11 call ClearBox ld hl, BattleText_PkmnFainted jp StdBattleTextBox ; 3cf14 FaintEnemyPokemon: ; 3cf14 call WaitSFX ld de, SFX_KINESIS call PlaySFX call EnemyMonFaintedAnimation ld de, SFX_FAINT call PlaySFX hlcoord 1, 0 lb bc, 4, 10 call ClearBox ld hl, BattleText_EnemyPkmnFainted jp StdBattleTextBox ; 3cf35 CheckEnemyTrainerDefeated: ; 3cf35 ld a, [OTPartyCount] ld b, a xor a ld hl, OTPartyMon1HP ld de, PARTYMON_STRUCT_LENGTH .loop or [hl] inc hl or [hl] dec hl add hl, de dec b jr nz, .loop and a ret ; 3cf4a HandleEnemySwitch: ; 3cf4a ld hl, EnemyHPPal ld e, HP_BAR_LENGTH_PX call UpdateHPPal call WaitBGMap callba EnemySwitch_TrainerHud ld a, [wLinkMode] and a jr z, .not_linked call LinkBattleSendReceiveAction ld a, [wBattleAction] cp BATTLEACTION_FORFEIT ret z call Call_LoadTempTileMapToTileMap .not_linked ld hl, BattleMonHP ld a, [hli] or [hl] ld a, $0 jr nz, EnemyPartyMonEntrance inc a ret ; 3cf78 EnemyPartyMonEntrance: ; 3cf78 push af xor a ld [wEnemySwitchMonIndex], a call NewEnemyMonStatus call ResetEnemyStatLevels call BreakAttraction pop af and a jr nz, .set call EnemySwitch jr .done_switch .set call EnemySwitch_SetMode .done_switch call ResetBattleParticipants call SetEnemyTurn call SpikesDamage xor a ld [wEnemyMoveStruct + MOVE_ANIM], a ld [wPlayerAction], a inc a ret ; 3cfa4 WinTrainerBattle: ; 3cfa4 ; Player won the battle call StopDangerSound ld a, $1 ld [wDanger], a ld [BattleEnded], a ld a, [wLinkMode] and a ld a, b call z, PlayVictoryMusic callab Battle_GetTrainerName ld hl, BattleText_EnemyWasDefeated call StdBattleTextBox call IsMobileBattle jr z, .mobile ld a, [wLinkMode] and a ret nz ld a, [InBattleTowerBattle] bit 0, a jr nz, .battle_tower call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames ld a, [BattleType] cp BATTLETYPE_CANLOSE jr nz, .skip_heal predef HealParty .skip_heal ld a, [wMonStatusFlags] bit 0, a jr nz, .skip_win_loss_text call PrintWinLossText .skip_win_loss_text jp .GiveMoney .mobile call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames ld c, $4 ; win callba Mobile_PrintOpponentBattleMessage ret .battle_tower call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames call EmptyBattleTextBox ld c, $3 callba BattleTowerText call WaitPressAorB_BlinkCursor ld hl, wPayDayMoney ld a, [hli] or [hl] inc hl or [hl] ret nz call ClearTileMap call ClearBGPalettes ret .GiveMoney: ld a, [wAmuletCoin] and a call nz, .DoubleReward call .CheckMaxedOutMomMoney push af ld a, $0 jr nc, .okay ld a, [wMomSavingMoney] and $7 cp $3 jr nz, .okay inc a .okay ld b, a ld c, $4 .loop ld a, b and a jr z, .loop2 call .SendMoneyToMom dec c dec b jr .loop .loop2 ld a, c and a jr z, .done call .AddMoneyToWallet dec c jr .loop2 .done call .DoubleReward call .DoubleReward pop af jr nc, .KeepItAll ld a, [wMomSavingMoney] and $7 jr z, .KeepItAll ld hl, .SentToMomTexts dec a ld c, a ld b, 0 add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a jp StdBattleTextBox .KeepItAll: ld hl, GotMoneyForWinningText jp StdBattleTextBox ; 3d081 .SendMoneyToMom: ; 3d081 push bc ld hl, wBattleReward + 2 ld de, wMomsMoney + 2 call AddBattleMoneyToAccount pop bc ret ; 3d08d .AddMoneyToWallet: ; 3d08d push bc ld hl, wBattleReward + 2 ld de, Money + 2 call AddBattleMoneyToAccount pop bc ret ; 3d099 .DoubleReward: ; 3d099 ld hl, wBattleReward + 2 sla [hl] dec hl rl [hl] dec hl rl [hl] ret nc ld a, $ff ld [hli], a ld [hli], a ld [hl], a ret ; 3d0ab .SentToMomTexts: ; 3d0ab dw SentSomeToMomText dw SentHalfToMomText dw SentAllToMomText ; 3d0b1 .CheckMaxedOutMomMoney: ; 3d0b1 ld hl, wMomsMoney + 2 ld a, [hld] cp 999999 % $100 ld a, [hld] sbc 999999 / $100 % $100 ld a, [hl] sbc 999999 / $10000 % $100 ret ; 3d0be AddBattleMoneyToAccount: ; 3d0be ld c, $3 and a push de push hl push bc ld b, h ld c, l callba TrainerRankings_AddToBattlePayouts pop bc pop hl .loop ld a, [de] adc [hl] ld [de], a dec de dec hl dec c jr nz, .loop pop hl ld a, [hld] cp 999999 % $100 ld a, [hld] sbc 999999 / $100 % $100 ld a, [hl] sbc 999999 / $10000 % $100 ret c ld [hl], 999999 / $10000 % $100 inc hl ld [hl], 999999 / $100 % $100 inc hl ld [hl], 999999 % $100 ret ; 3d0ea PlayVictoryMusic: ; 3d0ea push de ld de, MUSIC_NONE call PlayMusic call DelayFrame ld de, MUSIC_WILD_VICTORY ld a, [wBattleMode] dec a jr nz, .trainer_victory push de call IsAnyMonHoldingExpShare pop de jr nz, .play_music ld hl, wPayDayMoney ld a, [hli] or [hl] jr nz, .play_music ld a, [wBattleParticipantsNotFainted] and a jr z, .lost jr .play_music .trainer_victory ld de, MUSIC_GYM_VICTORY call IsJohtoGymLeader jr c, .play_music ld de, MUSIC_TRAINER_VICTORY .play_music call PlayMusic .lost pop de ret ; 3d123 ; These functions check if the current opponent is a gym leader or one of a ; few other special trainers. ; Note: KantoGymLeaders is a subset of JohtoGymLeaders. If you wish to ; differentiate between the two, call IsKantoGymLeader first. ; The Lance and Red entries are unused for music checks; those trainers are ; accounted for elsewhere. IsKantoGymLeader: ; 0x3d123 ld hl, KantoGymLeaders jr IsGymLeaderCommon IsJohtoGymLeader: ; 0x3d128 ld hl, JohtoGymLeaders IsGymLeaderCommon: push de ld a, [OtherTrainerClass] ld de, $0001 call IsInArray pop de ret ; 0x3d137 JohtoGymLeaders: db FALKNER db WHITNEY db BUGSY db MORTY db PRYCE db JASMINE db CHUCK db CLAIR db WILL db BRUNO db KAREN db KOGA ; fallthrough ; these two entries are unused db CHAMPION db RED ; fallthrough KantoGymLeaders: db BROCK db MISTY db LT_SURGE db ERIKA db JANINE db SABRINA db BLAINE db BLUE db -1 HandlePlayerMonFaint: ; 3d14e call FaintYourPokemon ld hl, EnemyMonHP ld a, [hli] or [hl] call z, FaintEnemyPokemon ld a, $1 ld [wWhichMonFaintedFirst], a call PlayerMonFaintHappinessMod call CheckPlayerPartyForFitPkmn ld a, d and a jp z, LostBattle ld hl, EnemyMonHP ld a, [hli] or [hl] jr nz, .notfainted call UpdateBattleStateAndExperienceAfterEnemyFaint ld a, [wBattleMode] dec a jr nz, .trainer ld a, $1 ld [BattleEnded], a ret .trainer call CheckEnemyTrainerDefeated jp z, WinTrainerBattle .notfainted call AskUseNextPokemon jr nc, .switch ld a, $1 ld [BattleEnded], a ret .switch call ForcePlayerMonChoice call CheckMobileBattleError jp c, WildFled_EnemyFled_LinkBattleCanceled ld a, c and a ret nz ld a, $1 ld [wPlayerAction], a call HandleEnemySwitch jp z, WildFled_EnemyFled_LinkBattleCanceled jp DoubleSwitch ; 3d1aa PlayerMonFaintHappinessMod: ; 3d1aa ld a, [CurBattleMon] ld c, a ld hl, wBattleParticipantsNotFainted ld b, RESET_FLAG predef FlagPredef ld hl, EnemySubStatus3 res SUBSTATUS_IN_LOOP, [hl] xor a ld [Danger], a ld hl, PlayerDamageTaken ld [hli], a ld [hl], a ld [BattleMonStatus], a call UpdateBattleMonInParty ld c, HAPPINESS_FAINTED ; If TheirLevel > (YourLevel + 30), use a different parameter ld a, [BattleMonLevel] add 30 ld b, a ld a, [EnemyMonLevel] cp b jr c, .got_param ld c, HAPPINESS_BEATENBYSTRONGFOE .got_param ld a, [CurBattleMon] ld [CurPartyMon], a callab ChangeHappiness ld a, [wBattleResult] and %11000000 add $1 ld [wBattleResult], a ld a, [wWhichMonFaintedFirst] and a ret z ret ; ?????????? ; 3d1f8 AskUseNextPokemon: ; 3d1f8 call EmptyBattleTextBox call LoadTileMapToTempTileMap ; We don't need to be here if we're in a Trainer battle, ; as that decision is made for us. ld a, [wBattleMode] and a dec a ret nz ld hl, BattleText_UseNextMon call StdBattleTextBox .loop lb bc, 1, 7 call PlaceYesNoBox ld a, [wMenuCursorY] jr c, .pressed_b and a ret .pressed_b ld a, [wMenuCursorY] cp $1 ; YES jr z, .loop ld hl, PartyMon1Speed ld de, EnemyMonSpeed jp TryToRunAwayFromBattle ; 3d227 ForcePlayerMonChoice: ; 3d227 call EmptyBattleTextBox call LoadStandardMenuDataHeader call SetUpBattlePartyMenu_NoLoop call ForcePickPartyMonInBattle ld a, [wLinkMode] and a jr z, .skip_link ld a, $1 ld [wPlayerAction], a call LinkBattleSendReceiveAction .skip_link xor a ld [wPlayerAction], a call CheckMobileBattleError jr c, .enemy_fainted_mobile_error ld hl, EnemyMonHP ld a, [hli] or [hl] jr nz, .send_out_pokemon .enemy_fainted_mobile_error call ClearSprites call ClearBGPalettes call _LoadHPBar call ExitMenu call LoadTileMapToTempTileMap call WaitBGMap call GetMemSGBLayout call SetPalettes xor a ld c, a ret .send_out_pokemon call ClearSprites ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, [CurPartyMon] ld [CurBattleMon], a call AddBattleParticipant call InitBattleMon call ResetPlayerStatLevels call ClearPalettes call DelayFrame call _LoadHPBar call CloseWindow call GetMemSGBLayout call SetPalettes call SendOutPkmnText call NewBattleMonStatus call BreakAttraction call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap call SetPlayerTurn call SpikesDamage ld a, $1 and a ld c, a ret ; 3d2b3 PlayerPartyMonEntrance: ; 3d2b3 ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, [CurPartyMon] ld [CurBattleMon], a call AddBattleParticipant call InitBattleMon call ResetPlayerStatLevels call SendOutPkmnText call NewBattleMonStatus call BreakAttraction call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap call SetPlayerTurn jp SpikesDamage ; 3d2e0 CheckMobileBattleError: ; 3d2e0 ld a, [wLinkMode] cp LINK_MOBILE jr nz, .not_mobile ; It's not a mobile battle ld a, [wcd2b] and a jr z, .not_mobile ; We have a mobile battle and something else happened scf ret .not_mobile xor a ret ; 3d2f1 IsMobileBattle: ; 3d2f1 ld a, [wLinkMode] cp LINK_MOBILE ret ; 3d2f7 SetUpBattlePartyMenu_NoLoop: ; 3d2f7 call ClearBGPalettes SetUpBattlePartyMenu: ; switch to fullscreen menu? callba LoadPartyMenuGFX callba InitPartyMenuWithCancel callba InitPartyMenuBGPal7 callba InitPartyMenuGFX ret ; 3d313 JumpToPartyMenuAndPrintText: ; 3d313 callba WritePartyMenuTilemap callba PrintPartyMenuText call WaitBGMap call SetPalettes call DelayFrame ret ; 3d329 SelectBattleMon: ; 3d329 call IsMobileBattle jr z, .mobile callba PartyMenuSelect ret .mobile callba Mobile_PartyMenuSelect ret ; 3d33c PickPartyMonInBattle: ; 3d33c .loop ld a, PARTYMENUACTION_SWITCH ; Which PKMN? ld [PartyMenuActionText], a call JumpToPartyMenuAndPrintText call SelectBattleMon ret c call CheckIfCurPartyMonIsFitToFight jr z, .loop xor a ret ; 3d34f SwitchMonAlreadyOut: ; 3d34f ld hl, CurBattleMon ld a, [CurPartyMon] cp [hl] jr nz, .notout ld hl, BattleText_PkmnIsAlreadyOut call StdBattleTextBox scf ret .notout xor a ret ; 3d362 ForcePickPartyMonInBattle: ; 3d362 ; Can't back out. .pick call PickPartyMonInBattle ret nc call CheckMobileBattleError ret c ld de, SFX_WRONG call PlaySFX call WaitSFX jr .pick ; 3d375 PickSwitchMonInBattle: ; 3d375 .pick call PickPartyMonInBattle ret c call SwitchMonAlreadyOut jr c, .pick xor a ret ; 3d380 ForcePickSwitchMonInBattle: ; 3d380 ; Can't back out. .pick call ForcePickPartyMonInBattle call CheckMobileBattleError ret c call SwitchMonAlreadyOut jr c, .pick xor a ret ; 3d38e LostBattle: ; 3d38e ld a, 1 ld [BattleEnded], a ld a, [InBattleTowerBattle] bit 0, a jr nz, .battle_tower ld a, [BattleType] cp BATTLETYPE_CANLOSE jr nz, .not_canlose ; Remove the enemy from the screen. hlcoord 0, 0 lb bc, 8, 21 call ClearBox call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames ld a, [wMonStatusFlags] bit 0, a jr nz, .skip_win_loss_text call PrintWinLossText .skip_win_loss_text ret .battle_tower ; Remove the enemy from the screen. hlcoord 0, 0 lb bc, 8, 21 call ClearBox call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames call EmptyBattleTextBox ld c, 2 callba BattleTowerText call WaitPressAorB_BlinkCursor call ClearTileMap call ClearBGPalettes ret .not_canlose ld a, [wLinkMode] and a jr nz, .LostLinkBattle ; Greyscale ld b, SCGB_BATTLE_GRAYSCALE call GetSGBLayout call SetPalettes jr .end .LostLinkBattle: call UpdateEnemyMonInParty call CheckEnemyTrainerDefeated jr nz, .not_tied ld hl, TiedAgainstText ld a, [wBattleResult] and $c0 add 2 ld [wBattleResult], a jr .text .not_tied ld hl, LostAgainstText call IsMobileBattle jr z, .mobile .text call StdBattleTextBox .end scf ret .mobile ; Remove the enemy from the screen. hlcoord 0, 0 lb bc, 8, 21 call ClearBox call BattleWinSlideInEnemyTrainerFrontpic ld c, 40 call DelayFrames ld c, $3 ; lost callba Mobile_PrintOpponentBattleMessage scf ret ; 3d432 EnemyMonFaintedAnimation: ; 3d432 hlcoord 12, 5 decoord 12, 6 jp MonFaintedAnimation ; 3d43b PlayerMonFaintedAnimation: ; 3d43b hlcoord 1, 10 decoord 1, 11 jp MonFaintedAnimation ; 3d444 MonFaintedAnimation: ; 3d444 ld a, [wcfbe] push af set 6, a ld [wcfbe], a ld b, 7 .OuterLoop: push bc push de push hl ld b, 6 .InnerLoop: push bc push hl push de ld bc, 7 call CopyBytes pop de pop hl ld bc, -SCREEN_WIDTH add hl, bc push hl ld h, d ld l, e add hl, bc ld d, h ld e, l pop hl pop bc dec b jr nz, .InnerLoop ld bc, 20 add hl, bc ld de, .Spaces call PlaceString ld c, 2 call DelayFrames pop hl pop de pop bc dec b jr nz, .OuterLoop pop af ld [wcfbe], a ret ; 3d488 .Spaces: db " @" ; 3d490 SlideBattlePicOut: ; 3d490 ld [hMapObjectIndexBuffer], a ld c, a .loop push bc push hl ld b, $7 .loop2 push hl call .DoFrame pop hl ld de, SCREEN_WIDTH add hl, de dec b jr nz, .loop2 ld c, 2 call DelayFrames pop hl pop bc dec c jr nz, .loop ret ; 3d4ae .DoFrame: ; 3d4ae ld a, [hMapObjectIndexBuffer] ld c, a cp $8 jr nz, .back .forward ld a, [hli] ld [hld], a dec hl dec c jr nz, .forward ret .back ld a, [hld] ld [hli], a inc hl dec c jr nz, .back ret ; 3d4c3 ForceEnemySwitch: ; 3d4c3 call ResetEnemyBattleVars ld a, [wEnemySwitchMonIndex] dec a ld b, a call LoadEnemyPkmnToSwitchTo call ClearEnemyMonBox call NewEnemyMonStatus call ResetEnemyStatLevels call Function_SetEnemyPkmnAndSendOutAnimation call BreakAttraction call ResetBattleParticipants ret ; 3d4e1 EnemySwitch: ; 3d4e1 call CheckWhetherToAskSwitch jr nc, EnemySwitch_SetMode ; Shift Mode call ResetEnemyBattleVars call CheckWhetherSwitchmonIsPredetermined jr c, .skip call FindPkmnInOTPartyToSwitchIntoBattle .skip ; 'b' contains the PartyNr of the Pkmn the AI will switch to call LoadEnemyPkmnToSwitchTo call OfferSwitch push af call ClearEnemyMonBox call Function_BattleTextEnemySentOut call Function_SetEnemyPkmnAndSendOutAnimation pop af ret c ; If we're here, then we're switching too xor a ld [wBattleParticipantsNotFainted], a ld [wBattleParticipantsIncludingFainted], a ld [wPlayerAction], a inc a ld [wEnemyIsSwitching], a call LoadTileMapToTempTileMap jp PlayerSwitch ; 3d517 EnemySwitch_SetMode: ; 3d517 call ResetEnemyBattleVars call CheckWhetherSwitchmonIsPredetermined jr c, .skip call FindPkmnInOTPartyToSwitchIntoBattle .skip ; 'b' contains the PartyNr of the Pkmn the AI will switch to call LoadEnemyPkmnToSwitchTo ld a, 1 ld [wEnemyIsSwitching], a call ClearEnemyMonBox call Function_BattleTextEnemySentOut jp Function_SetEnemyPkmnAndSendOutAnimation ; 3d533 CheckWhetherSwitchmonIsPredetermined: ; 3d533 ; returns carry if: ??? ld a, [wLinkMode] and a jr z, .not_linked ld a, [wBattleAction] sub BATTLEACTION_SWITCH1 ld b, a jr .return_carry .not_linked ld a, [wEnemySwitchMonIndex] and a jr z, .check_wBattleHasJustStarted dec a ld b, a jr .return_carry .check_wBattleHasJustStarted ld a, [wBattleHasJustStarted] and a ld b, $0 jr nz, .return_carry and a ret .return_carry scf ret ; 3d557 ResetEnemyBattleVars: ; 3d557 ; and draw empty TextBox xor a ld [LastPlayerCounterMove], a ld [LastEnemyCounterMove], a ld [LastEnemyMove], a ld [CurEnemyMove], a dec a ld [wEnemyItemState], a xor a ld [wPlayerWrapCount], a hlcoord 18, 0 ld a, 8 call SlideBattlePicOut call EmptyBattleTextBox jp LoadStandardMenuDataHeader ; 3d57a ResetBattleParticipants: ; 3d57a xor a ld [wBattleParticipantsNotFainted], a ld [wBattleParticipantsIncludingFainted], a AddBattleParticipant: ; 3d581 ld a, [CurBattleMon] ld c, a ld hl, wBattleParticipantsNotFainted ld b, SET_FLAG push bc predef FlagPredef pop bc ld hl, wBattleParticipantsIncludingFainted predef_jump FlagPredef ; 3d599 FindPkmnInOTPartyToSwitchIntoBattle: ; 3d599 ld b, $ff ld a, $1 ld [Buffer1], a ld [Buffer2], a .loop ld hl, Buffer1 sla [hl] inc hl sla [hl] inc b ld a, [OTPartyCount] cp b jp z, ScoreMonTypeMatchups ld a, [CurOTMon] cp b jr z, .discourage ld hl, OTPartyMon1HP push bc ld a, b call GetPartyLocation ld a, [hli] ld c, a ld a, [hl] or c pop bc jr z, .discourage call LookUpTheEffectivenessOfEveryMove call IsThePlayerPkmnTypesEffectiveAgainstOTPkmn jr .loop .discourage ld hl, Buffer2 set 0, [hl] jr .loop ; 3d5d7 LookUpTheEffectivenessOfEveryMove: ; 3d5d7 push bc ld hl, OTPartyMon1Moves ld a, b call GetPartyLocation pop bc ld e, NUM_MOVES + 1 .loop dec e jr z, .done ld a, [hli] and a jr z, .done push hl push de push bc dec a ld hl, Moves ld bc, MOVE_LENGTH call AddNTimes ld de, wEnemyMoveStruct ld a, BANK(Moves) call FarCopyBytes call SetEnemyTurn callab BattleCheckTypeMatchup pop bc pop de pop hl ld a, [wd265] ; Get The Effectiveness Modifier cp 10 + 1 ; 1.0 + 0.1 jr c, .loop ld hl, Buffer1 set 0, [hl] ret .done ret ; 3d618 IsThePlayerPkmnTypesEffectiveAgainstOTPkmn: ; 3d618 ; Calculates the effectiveness of the types of the PlayerPkmn ; against the OTPkmn push bc ld hl, OTPartyCount ld a, b inc a ld c, a ld b, 0 add hl, bc ld a, [hl] dec a ld hl, BaseData + BASE_TYPES ld bc, BASE_DATA_SIZE call AddNTimes ld de, EnemyMonType ld bc, 2 ld a, BANK(BaseData) call FarCopyBytes ld a, [BattleMonType1] ld [wPlayerMoveStruct + MOVE_TYPE], a call SetPlayerTurn callab BattleCheckTypeMatchup ld a, [wd265] cp 10 + 1 ; 1.0 + 0.1 jr nc, .super_effective ld a, [BattleMonType2] ld [wPlayerMoveStruct + MOVE_TYPE], a callab BattleCheckTypeMatchup ld a, [wd265] cp 10 + 1 ; 1.0 + 0.1 jr nc, .super_effective pop bc ret .super_effective pop bc ld hl, Buffer1 bit 0, [hl] jr nz, .reset inc hl set 0, [hl] ret .reset res 0, [hl] ret ; 3d672 ScoreMonTypeMatchups: ; 3d672 .loop1 ld hl, Buffer1 sla [hl] inc hl sla [hl] jr nc, .loop1 ld a, [OTPartyCount] ld b, a ld c, [hl] .loop2 sla c jr nc, .okay dec b jr z, .loop5 jr .loop2 .okay ld a, [Buffer1] and a jr z, .okay2 ld b, $ff ld c, a .loop3 inc b sla c jr nc, .loop3 jr .quit .okay2 ld b, $ff ld a, [Buffer2] ld c, a .loop4 inc b sla c jr c, .loop4 jr .quit .loop5 ld a, [OTPartyCount] ld b, a call BattleRandom and $7 cp b jr nc, .loop5 ld b, a ld a, [CurOTMon] cp b jr z, .loop5 ld hl, OTPartyMon1HP push bc ld a, b call GetPartyLocation pop bc ld a, [hli] ld c, a ld a, [hl] or c jr z, .loop5 .quit ret ; 3d6ca LoadEnemyPkmnToSwitchTo: ; 3d6ca ; 'b' contains the PartyNr of the Pkmn the AI will switch to ld a, b ld [CurPartyMon], a ld hl, OTPartyMon1Level call GetPartyLocation ld a, [hl] ld [CurPartyLevel], a ld a, [CurPartyMon] inc a ld hl, OTPartyCount ld c, a ld b, 0 add hl, bc ld a, [hl] ld [TempEnemyMonSpecies], a ld [CurPartySpecies], a call LoadEnemyMon ld a, [CurPartySpecies] cp UNOWN jr nz, .skip_unown ld a, [wFirstUnownSeen] and a jr nz, .skip_unown ld hl, EnemyMonDVs predef GetUnownLetter ld a, [UnownLetter] ld [wFirstUnownSeen], a .skip_unown ld hl, EnemyMonHP ld a, [hli] ld [wEnemyHPAtTimeOfPlayerSwitch], a ld a, [hl] ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a ret ; 3d714 CheckWhetherToAskSwitch: ; 3d714 ld a, [wBattleHasJustStarted] dec a jp z, .return_nc ld a, [PartyCount] dec a jp z, .return_nc ld a, [wLinkMode] and a jp nz, .return_nc ld a, [Options] bit BATTLE_SHIFT, a jr nz, .return_nc ld a, [CurPartyMon] push af ld a, [CurBattleMon] ld [CurPartyMon], a callba CheckCurPartyMonFainted pop bc ld a, b ld [CurPartyMon], a jr c, .return_nc scf ret .return_nc and a ret ; 3d74b OfferSwitch: ; 3d74b ld a, [CurPartyMon] push af callab Battle_GetTrainerName ld hl, BattleText_EnemyIsAboutToUseWillPlayerChangePkmn call StdBattleTextBox lb bc, 1, 7 call PlaceYesNoBox ld a, [wMenuCursorY] dec a jr nz, .said_no call SetUpBattlePartyMenu_NoLoop call PickSwitchMonInBattle jr c, .canceled_switch ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, [CurPartyMon] ld [CurBattleMon], a call ClearPalettes call DelayFrame call _LoadHPBar pop af ld [CurPartyMon], a xor a ld [CurEnemyMove], a ld [CurPlayerMove], a and a ret .canceled_switch call ClearPalettes call DelayFrame call _LoadHPBar .said_no pop af ld [CurPartyMon], a scf ret ; 3d7a0 ClearEnemyMonBox: ; 3d7a0 xor a ld [hBGMapMode], a call ExitMenu call ClearSprites hlcoord 1, 0 lb bc, 4, 10 call ClearBox call WaitBGMap jp FinishBattleAnim ; 3d7b8 Function_BattleTextEnemySentOut: ; 3d7b8 callab Battle_GetTrainerName ld hl, BattleText_EnemySentOut call StdBattleTextBox jp WaitBGMap ; 3d7c7 Function_SetEnemyPkmnAndSendOutAnimation: ; 3d7c7 ld a, [TempEnemyMonSpecies] ld [CurPartySpecies], a ld [CurSpecies], a call GetBaseData ld a, OTPARTYMON ld [MonType], a predef CopyPkmnToTempMon call GetMonFrontpic xor a ld [wNumHits], a ld [wBattleAnimParam], a call SetEnemyTurn ld de, ANIM_SEND_OUT_MON call Call_PlayBattleAnim call BattleCheckEnemyShininess jr nc, .not_shiny ld a, 1 ; shiny anim ld [wBattleAnimParam], a ld de, ANIM_SEND_OUT_MON call Call_PlayBattleAnim .not_shiny ld bc, TempMonSpecies callba CheckFaintedFrzSlp jr c, .skip_cry callba CheckBattleScene jr c, .cry_no_anim hlcoord 12, 0 ld d, $0 ld e, ANIM_MON_SLOW predef AnimateFrontpic jr .skip_cry .cry_no_anim ld a, $f ld [CryTracks], a ld a, [TempEnemyMonSpecies] call PlayStereoCry .skip_cry call UpdateEnemyHUD ld a, $1 ld [hBGMapMode], a ret ; 3d834 NewEnemyMonStatus: ; 3d834 xor a ld [LastPlayerCounterMove], a ld [LastEnemyCounterMove], a ld [LastEnemyMove], a ld hl, EnemySubStatus1 rept 4 ld [hli], a endr ld [hl], a ld [EnemyDisableCount], a ld [EnemyFuryCutterCount], a ld [EnemyProtectCount], a ld [wEnemyRageCounter], a ld [EnemyDisabledMove], a ld [wEnemyMinimized], a ld [wPlayerWrapCount], a ld [wEnemyWrapCount], a ld [EnemyTurnsTaken], a ld hl, PlayerSubStatus5 res SUBSTATUS_CANT_RUN, [hl] ret ; 3d867 ResetEnemyStatLevels: ; 3d867 ld a, BASE_STAT_LEVEL ld b, NUM_LEVEL_STATS ld hl, EnemyStatLevels .loop ld [hli], a dec b jr nz, .loop ret ; 3d873 CheckPlayerPartyForFitPkmn: ; 3d873 ; Has the player any Pkmn in his Party that can fight? ld a, [PartyCount] ld e, a xor a ld hl, PartyMon1HP ld bc, PartyMon2 - (PartyMon1 + 1) .loop or [hl] inc hl or [hl] add hl, bc dec e jr nz, .loop ld d, a ret ; 3d887 CheckIfCurPartyMonIsFitToFight: ; 3d887 ld a, [CurPartyMon] ld hl, PartyMon1HP call GetPartyLocation ld a, [hli] or [hl] ret nz ld a, [wBattleHasJustStarted] and a jr nz, .finish_fail ld hl, PartySpecies ld a, [CurPartyMon] ld c, a ld b, 0 add hl, bc ld a, [hl] cp EGG ld hl, BattleText_AnEGGCantBattle jr z, .print_textbox ld hl, BattleText_TheresNoWillToBattle .print_textbox call StdBattleTextBox .finish_fail xor a ret ; 3d8b3 TryToRunAwayFromBattle: ; 3d8b3 ; Run away from battle, with or without item ld a, [BattleType] cp BATTLETYPE_DEBUG jp z, .can_escape cp BATTLETYPE_CONTEST jp z, .can_escape cp BATTLETYPE_TRAP jp z, .cant_escape cp BATTLETYPE_CELEBI jp z, .cant_escape cp BATTLETYPE_SHINY jp z, .cant_escape cp BATTLETYPE_SUICUNE jp z, .cant_escape ld a, [wLinkMode] and a jp nz, .can_escape ld a, [wBattleMode] dec a jp nz, .cant_run_from_trainer ld a, [EnemySubStatus5] bit SUBSTATUS_CANT_RUN, a jp nz, .cant_escape ld a, [wPlayerWrapCount] and a jp nz, .cant_escape push hl push de ld a, [BattleMonItem] ld [wd265], a ld b, a callab GetItemHeldEffect ld a, b cp HELD_ESCAPE pop de pop hl jr nz, .no_flee_item call SetPlayerTurn call GetItemName ld hl, BattleText_UserFledUsingAStringBuffer1 call StdBattleTextBox jp .can_escape .no_flee_item ld a, [wNumFleeAttempts] inc a ld [wNumFleeAttempts], a ld a, [hli] ld [hStringCmpString2 + 0], a ld a, [hl] ld [hStringCmpString2 + 1], a ld a, [de] inc de ld [hStringCmpString1 + 0], a ld a, [de] ld [hStringCmpString1 + 1], a call Call_LoadTempTileMapToTileMap ld de, hStringCmpString2 ld hl, hStringCmpString1 ld c, $2 call StringCmp jr nc, .can_escape xor a ld [hMultiplicand], a ld a, $20 ld [hMultiplier], a call Multiply ld a, [hProduct + 2] ld [hDividend + 0], a ld a, [hProduct + 3] ld [hDividend + 1], a ld a, [hStringCmpString1 + 0] ld b, a ld a, [hStringCmpString1 + 1] srl b rr a srl b rr a and a jr z, .can_escape ld [hDivisor], a ld b, 2 call Divide ld a, [hQuotient + 1] and a jr nz, .can_escape ld a, [wNumFleeAttempts] ld c, a .loop dec c jr z, .cant_escape_2 ld b, 30 ld a, [hQuotient + 2] add b ld [hQuotient + 2], a jr c, .can_escape jr .loop .cant_escape_2 call BattleRandom ld b, a ld a, [hQuotient + 2] cp b jr nc, .can_escape ld a, $1 ld [wPlayerAction], a ld hl, BattleText_CantEscape2 jr .print_inescapable_text .cant_escape ld hl, BattleText_CantEscape jr .print_inescapable_text .cant_run_from_trainer ld hl, BattleText_TheresNoEscapeFromTrainerBattle .print_inescapable_text call StdBattleTextBox ld a, $1 ld [wFailedToFlee], a call LoadTileMapToTempTileMap and a ret .can_escape ld a, [wLinkMode] and a ld a, DRAW jr z, .fled call LoadTileMapToTempTileMap xor a ld [wPlayerAction], a ld a, $f ld [CurMoveNum], a xor a ld [CurPlayerMove], a call LinkBattleSendReceiveAction call Call_LoadTempTileMapToTileMap call CheckMobileBattleError jr c, .mobile ; Got away safely ld a, [wBattleAction] cp BATTLEACTION_FORFEIT ld a, DRAW jr z, .fled dec a .fled ld b, a ld a, [wBattleResult] and $c0 add b ld [wBattleResult], a call StopDangerSound push de ld de, SFX_RUN call WaitPlaySFX pop de call WaitSFX ld hl, BattleText_GotAwaySafely call StdBattleTextBox call WaitSFX call LoadTileMapToTempTileMap scf ret .mobile call StopDangerSound ld hl, wcd2a bit 4, [hl] jr nz, .skip_link_error ld hl, BattleText_LinkErrorBattleCanceled call StdBattleTextBox .skip_link_error call WaitSFX call LoadTileMapToTempTileMap scf ret ; 3da0d InitBattleMon: ; 3da0d ld a, MON_SPECIES call GetPartyParamLocation ld de, BattleMonSpecies ld bc, MON_ID call CopyBytes ld bc, MON_DVS - MON_ID add hl, bc ld de, BattleMonDVs ld bc, MON_PKRUS - MON_DVS call CopyBytes inc hl inc hl inc hl ld de, BattleMonLevel ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL call CopyBytes ld a, [BattleMonSpecies] ld [TempBattleMonSpecies], a ld [CurPartySpecies], a ld [CurSpecies], a call GetBaseData ld a, [BaseType1] ld [BattleMonType1], a ld a, [BaseType2] ld [BattleMonType2], a ld hl, PartyMonNicknames ld a, [CurBattleMon] call SkipNames ld de, BattleMonNick ld bc, PKMN_NAME_LENGTH call CopyBytes ld hl, BattleMonAttack ld de, PlayerStats ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK call CopyBytes call ApplyStatusEffectOnPlayerStats call BadgeStatBoosts ret ; 3da74 BattleCheckPlayerShininess: ; 3da74 call GetPartyMonDVs jr BattleCheckShininess BattleCheckEnemyShininess: ; 3da79 call GetEnemyMonDVs BattleCheckShininess: ; 3da7c ld b, h ld c, l callab CheckShininess ret ; 3da85 GetPartyMonDVs: ; 3da85 ld hl, BattleMonDVs ld a, [PlayerSubStatus5] bit SUBSTATUS_TRANSFORMED, a ret z ld hl, PartyMon1DVs ld a, [CurBattleMon] jp GetPartyLocation ; 3da97 GetEnemyMonDVs: ; 3da97 ld hl, EnemyMonDVs ld a, [EnemySubStatus5] bit SUBSTATUS_TRANSFORMED, a ret z ld hl, wEnemyBackupDVs ld a, [wBattleMode] dec a ret z ld hl, OTPartyMon1DVs ld a, [CurOTMon] jp GetPartyLocation ; 3dab1 ResetPlayerStatLevels: ; 3dab1 ld a, BASE_STAT_LEVEL ld b, NUM_LEVEL_STATS ld hl, PlayerStatLevels .loop ld [hli], a dec b jr nz, .loop ret ; 3dabd InitEnemyMon: ; 3dabd ld a, [CurPartyMon] ld hl, OTPartyMon1Species call GetPartyLocation ld de, EnemyMonSpecies ld bc, MON_ID call CopyBytes ld bc, MON_DVS - MON_ID add hl, bc ld de, EnemyMonDVs ld bc, MON_PKRUS - MON_DVS call CopyBytes inc hl inc hl inc hl ld de, EnemyMonLevel ld bc, PARTYMON_STRUCT_LENGTH - MON_LEVEL call CopyBytes ld a, [EnemyMonSpecies] ld [CurSpecies], a call GetBaseData ld hl, OTPartyMonNicknames ld a, [CurPartyMon] call SkipNames ld de, EnemyMonNick ld bc, PKMN_NAME_LENGTH call CopyBytes ld hl, EnemyMonAttack ld de, EnemyStats ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK call CopyBytes call ApplyStatusEffectOnEnemyStats ld hl, BaseType1 ld de, EnemyMonType1 ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a ld hl, BaseStats ld de, EnemyMonBaseStats ld b, 5 .loop ld a, [hli] ld [de], a inc de dec b jr nz, .loop ld a, [CurPartyMon] ld [CurOTMon], a ret ; 3db32 SwitchPlayerMon: ; 3db32 call ClearSprites ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, [CurPartyMon] ld [CurBattleMon], a call AddBattleParticipant call InitBattleMon call ResetPlayerStatLevels call NewBattleMonStatus call BreakAttraction call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap ld hl, EnemyMonHP ld a, [hli] or [hl] ret ; 3db5f SendOutPlayerMon: ; 3db5f ld hl, BattleMonDVs predef GetUnownLetter hlcoord 1, 5 ld b, 7 ld c, 8 call ClearBox call WaitBGMap xor a ld [hBGMapMode], a call GetMonBackpic xor a ld [hGraphicStartTile], a ld [wBattleMenuCursorBuffer], a ld [CurMoveNum], a ld [TypeModifier], a ld [wPlayerMoveStruct + MOVE_ANIM], a ld [LastPlayerCounterMove], a ld [LastEnemyCounterMove], a ld [LastPlayerMove], a call CheckAmuletCoin call FinishBattleAnim xor a ld [wEnemyWrapCount], a call SetPlayerTurn xor a ld [wNumHits], a ld [wBattleAnimParam], a ld de, ANIM_SEND_OUT_MON call Call_PlayBattleAnim call BattleCheckPlayerShininess jr nc, .not_shiny ld a, 1 ld [wBattleAnimParam], a ld de, ANIM_SEND_OUT_MON call Call_PlayBattleAnim .not_shiny ld a, MON_SPECIES call GetPartyParamLocation ld b, h ld c, l callba CheckFaintedFrzSlp jr c, .statused ld a, $f0 ld [CryTracks], a ld a, [CurPartySpecies] call PlayStereoCry .statused call UpdatePlayerHUD ld a, $1 ld [hBGMapMode], a ret ; 3dbde NewBattleMonStatus: ; 3dbde xor a ld [LastPlayerCounterMove], a ld [LastEnemyCounterMove], a ld [LastPlayerMove], a ld hl, PlayerSubStatus1 rept 4 ld [hli], a endr ld [hl], a ld hl, PlayerUsedMoves ld [hli], a ld [hli], a ld [hli], a ld [hl], a ld [PlayerDisableCount], a ld [PlayerFuryCutterCount], a ld [PlayerProtectCount], a ld [wPlayerRageCounter], a ld [DisabledMove], a ld [wPlayerMinimized], a ld [wEnemyWrapCount], a ld [wPlayerWrapCount], a ld [PlayerTurnsTaken], a ld hl, EnemySubStatus5 res SUBSTATUS_CANT_RUN, [hl] ret ; 3dc18 BreakAttraction: ; 3dc18 ld hl, PlayerSubStatus1 res SUBSTATUS_IN_LOVE, [hl] ld hl, EnemySubStatus1 res SUBSTATUS_IN_LOVE, [hl] ret ; 3dc23 SpikesDamage: ; 3dc23 ld hl, PlayerScreens ld de, BattleMonType ld bc, UpdatePlayerHUD ld a, [hBattleTurn] and a jr z, .ok ld hl, EnemyScreens ld de, EnemyMonType ld bc, UpdateEnemyHUD .ok bit SCREENS_SPIKES, [hl] ret z ; Flying-types aren't affected by Spikes. ld a, [de] cp FLYING ret z inc de ld a, [de] cp FLYING ret z push bc ld hl, BattleText_UserHurtBySpikes ; "hurt by SPIKES!" call StdBattleTextBox call GetEighthMaxHP call SubtractHPFromTarget pop hl call .hl jp WaitBGMap .hl jp hl ; 3dc5b PursuitSwitch: ; 3dc5b ld a, BATTLE_VARS_MOVE call GetBattleVar ld b, a call GetMoveEffect ld a, b cp EFFECT_PURSUIT jr nz, .done ld a, [CurBattleMon] push af ld hl, DoPlayerTurn ld a, [hBattleTurn] and a jr z, .do_turn ld hl, DoEnemyTurn ld a, [LastPlayerMon] ld [CurBattleMon], a .do_turn ld a, BANK(DoPlayerTurn) rst FarCall ld a, BATTLE_VARS_MOVE call GetBattleVarAddr ld a, $ff ld [hl], a pop af ld [CurBattleMon], a ld a, [hBattleTurn] and a jr z, .check_enemy_fainted ld a, [LastPlayerMon] call UpdateBattleMon ld hl, BattleMonHP ld a, [hli] or [hl] jr nz, .done ld a, $f0 ld [CryTracks], a ld a, [BattleMonSpecies] call PlayStereoCry ld a, [LastPlayerMon] ld c, a ld hl, wBattleParticipantsNotFainted ld b, RESET_FLAG predef FlagPredef call PlayerMonFaintedAnimation ld hl, BattleText_PkmnFainted jr .done_fainted .check_enemy_fainted ld hl, EnemyMonHP ld a, [hli] or [hl] jr nz, .done ld de, SFX_KINESIS call PlaySFX call WaitSFX ld de, SFX_FAINT call PlaySFX call WaitSFX call EnemyMonFaintedAnimation ld hl, BattleText_EnemyPkmnFainted .done_fainted call StdBattleTextBox scf ret .done and a ret ; 3dce6 RecallPlayerMon: ; 3dce6 ld a, [hBattleTurn] push af xor a ld [hBattleTurn], a ld [wNumHits], a ld de, ANIM_RETURN_MON call Call_PlayBattleAnim pop af ld [hBattleTurn], a ret ; 3dcf9 HandleHealingItems: ; 3dcf9 ld a, [hLinkPlayerNumber] cp $1 jr z, .player_1 call SetPlayerTurn call HandleHPHealingItem call UseHeldStatusHealingItem call UseConfusionHealingItem call SetEnemyTurn call HandleHPHealingItem call UseHeldStatusHealingItem jp UseConfusionHealingItem .player_1 call SetEnemyTurn call HandleHPHealingItem call UseHeldStatusHealingItem call UseConfusionHealingItem call SetPlayerTurn call HandleHPHealingItem call UseHeldStatusHealingItem jp UseConfusionHealingItem ; 3dd2f HandleHPHealingItem: ; 3dd2f callab GetOpponentItem ld a, b cp $1 ret nz ld de, EnemyMonHP + 1 ld hl, EnemyMonMaxHP ld a, [hBattleTurn] and a jr z, .go ld de, BattleMonHP + 1 ld hl, BattleMonMaxHP .go ; If, and only if, Pokemon's HP is less than half max, use the item. ; Store current HP in Buffer 3/4 push bc ld a, [de] ld [Buffer3], a add a ld c, a dec de ld a, [de] inc de ld [Buffer4], a adc a ld b, a ld a, b cp [hl] ld a, c pop bc jr z, .equal jr c, .less ret .equal inc hl cp [hl] dec hl ret nc .less call ItemRecoveryAnim ; store max HP in Buffer1/2 ld a, [hli] ld [Buffer2], a ld a, [hl] ld [Buffer1], a ld a, [de] add c ld [Buffer5], a ld c, a dec de ld a, [de] adc $0 ld [Buffer6], a ld b, a ld a, [hld] cp c ld a, [hl] sbc b jr nc, .okay ld a, [hli] ld [Buffer6], a ld a, [hl] ld [Buffer5], a .okay ld a, [Buffer6] ld [de], a inc de ld a, [Buffer5] ld [de], a ld a, [hBattleTurn] ld [wWhichHPBar], a and a hlcoord 2, 2 jr z, .got_hp_bar_coords hlcoord 10, 9 .got_hp_bar_coords ld [wWhichHPBar], a predef AnimateHPBar UseOpponentItem: call RefreshBattleHuds callab GetOpponentItem ld a, [hl] ld [wNamedObjectIndexBuffer], a call GetItemName callab ConsumeHeldItem ld hl, RecoveredUsingText jp StdBattleTextBox ; 3ddc8 ItemRecoveryAnim: ; 3ddc8 push hl push de push bc call EmptyBattleTextBox ld a, RECOVER ld [FXAnimID], a call SwitchTurnCore xor a ld [wNumHits], a ld [FXAnimID + 1], a predef PlayBattleAnim call SwitchTurnCore pop bc pop de pop hl ret ; 3dde9 UseHeldStatusHealingItem: ; 3dde9 callab GetOpponentItem ld hl, .Statuses .loop ld a, [hli] cp $ff ret z inc hl cp b jr nz, .loop dec hl ld b, [hl] ld a, BATTLE_VARS_STATUS_OPP call GetBattleVarAddr and b ret z xor a ld [hl], a push bc call UpdateOpponentInParty pop bc ld a, BATTLE_VARS_SUBSTATUS5_OPP call GetBattleVarAddr and [hl] res SUBSTATUS_TOXIC, [hl] ld a, BATTLE_VARS_SUBSTATUS1_OPP call GetBattleVarAddr and [hl] res SUBSTATUS_NIGHTMARE, [hl] ld a, b cp ALL_STATUS jr nz, .skip_confuse ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr res SUBSTATUS_CONFUSED, [hl] .skip_confuse ld hl, CalcEnemyStats ld a, [hBattleTurn] and a jr z, .got_pointer ld hl, CalcPlayerStats .got_pointer call SwitchTurnCore ld a, BANK(CalcEnemyStats) rst FarCall call SwitchTurnCore call ItemRecoveryAnim call UseOpponentItem ld a, $1 and a ret ; 3de44 .Statuses: ; 3de44 db HELD_HEAL_POISON, 1 << PSN db HELD_HEAL_FREEZE, 1 << FRZ db HELD_HEAL_BURN, 1 << BRN db HELD_HEAL_SLEEP, SLP db HELD_HEAL_PARALYZE, 1 << PAR db HELD_HEAL_STATUS, ALL_STATUS db $ff ; 3de51 UseConfusionHealingItem: ; 3de51 ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVar bit SUBSTATUS_CONFUSED, a ret z callab GetOpponentItem ld a, b cp HELD_HEAL_CONFUSION jr z, .heal_status cp HELD_HEAL_STATUS ret nz .heal_status ld a, [hl] ld [wd265], a ld a, BATTLE_VARS_SUBSTATUS3_OPP call GetBattleVarAddr res SUBSTATUS_CONFUSED, [hl] call GetItemName call ItemRecoveryAnim ld hl, BattleText_ItemHealedConfusion call StdBattleTextBox ld a, [hBattleTurn] and a jr nz, .do_partymon call GetOTPartymonItem xor a ld [bc], a ld a, [wBattleMode] dec a ret z ld [hl], $0 ret .do_partymon call GetPartymonItem xor a ld [bc], a ld [hl], a ret ; 3de97 HandleStatBoostingHeldItems: ; 3de97 ; The effects handled here are not used in-game. ld a, [hLinkPlayerNumber] cp $1 jr z, .player_1 call .DoPlayer jp .DoEnemy .player_1 call .DoEnemy jp .DoPlayer ; 3dea9 .DoPlayer: ; 3dea9 call GetPartymonItem ld a, $0 jp .HandleItem ; 3deb1 .DoEnemy: ; 3deb1 call GetOTPartymonItem ld a, $1 .HandleItem: ; 3deb6 ld [hBattleTurn], a ld d, h ld e, l push de push bc ld a, [bc] ld b, a callab GetItemHeldEffect ld hl, .StatUpItems .loop ld a, [hli] cp $ff jr z, .finish inc hl inc hl cp b jr nz, .loop pop bc ld a, [bc] ld [wd265], a push bc dec hl dec hl ld a, [hli] ld h, [hl] ld l, a ld a, BANK(BattleCommand_AttackUp) rst FarCall pop bc pop de ld a, [FailedMessage] and a ret nz xor a ld [bc], a ld [de], a call GetItemName ld hl, BattleText_UsersStringBuffer1Activated call StdBattleTextBox callab BattleCommand_StatUpMessage ret .finish pop bc pop de ret ; 3defc .StatUpItems: dbw HELD_ATTACK_UP, BattleCommand_AttackUp dbw HELD_DEFENSE_UP, BattleCommand_DefenseUp dbw HELD_SPEED_UP, BattleCommand_SpeedUp dbw HELD_SP_ATTACK_UP, BattleCommand_SpecialAttackUp dbw HELD_SP_DEFENSE_UP, BattleCommand_SpecialDefenseUp dbw HELD_ACCURACY_UP, BattleCommand_AccuracyUp dbw HELD_EVASION_UP, BattleCommand_EvasionUp db $ff ; 3df12 GetPartymonItem: ; 3df12 ld hl, PartyMon1Item ld a, [CurBattleMon] call GetPartyLocation ld bc, BattleMonItem ret ; 3df1f GetOTPartymonItem: ; 3df1f ld hl, OTPartyMon1Item ld a, [CurOTMon] call GetPartyLocation ld bc, EnemyMonItem ret ; 3df2c UpdateBattleHUDs: ; 3df2c push hl push de push bc call DrawPlayerHUD ld hl, PlayerHPPal call SetHPPal call CheckDanger call DrawEnemyHUD ld hl, EnemyHPPal call SetHPPal pop bc pop de pop hl ret ; 3df48 UpdatePlayerHUD:: ; 3df48 push hl push de push bc call DrawPlayerHUD call UpdatePlayerHPPal call CheckDanger pop bc pop de pop hl ret ; 3df58 DrawPlayerHUD: ; 3df58 xor a ld [hBGMapMode], a ; Clear the area hlcoord 9, 7 lb bc, 5, 11 call ClearBox callba DrawPlayerHUDBorder hlcoord 18, 9 ld [hl], $73 ; vertical bar call PrintPlayerHUD ; HP bar hlcoord 10, 9 ld b, 1 xor a ; PARTYMON ld [MonType], a predef DrawPlayerHP ; Exp bar push de ld a, [CurBattleMon] ld hl, PartyMon1Exp + 2 call GetPartyLocation ld d, h ld e, l hlcoord 10, 11 ld a, [TempMonLevel] ld b, a call FillInExpBar pop de ret ; 3df98 UpdatePlayerHPPal: ; 3df98 ld hl, PlayerHPPal jp UpdateHPPal ; 3df9e CheckDanger: ; 3df9e ld hl, BattleMonHP ld a, [hli] or [hl] jr z, .no_danger ld a, [wDanger] and a jr nz, .done ld a, [PlayerHPPal] cp HP_RED jr z, .danger .no_danger ld hl, Danger res 7, [hl] jr .done .danger ld hl, Danger set 7, [hl] .done ret ; 3dfbf PrintPlayerHUD: ; 3dfbf ld de, BattleMonNick hlcoord 10, 7 call ret_3e138 call PlaceString push bc ld a, [CurBattleMon] ld hl, PartyMon1DVs call GetPartyLocation ld de, TempMonDVs ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a ld hl, BattleMonLevel ld de, TempMonLevel ld bc, $0011 call CopyBytes ld a, [CurBattleMon] ld hl, PartyMon1Species call GetPartyLocation ld a, [hl] ld [CurPartySpecies], a ld [CurSpecies], a call GetBaseData pop hl dec hl ld a, TEMPMON ld [MonType], a callab GetGender ld a, " " jr c, .got_gender_char ld a, "♂" jr nz, .got_gender_char ld a, "♀" .got_gender_char hlcoord 17, 8 ld [hl], a hlcoord 14, 8 push af ; back up gender push hl ld de, BattleMonStatus predef PlaceNonFaintStatus pop hl pop bc ret nz ld a, b cp " " jr nz, .copy_level ; male or female dec hl ; genderless .copy_level ld a, [BattleMonLevel] ld [TempMonLevel], a jp PrintLevel ; 3e036 UpdateEnemyHUD:: ; 3e036 push hl push de push bc call DrawEnemyHUD call UpdateEnemyHPPal pop bc pop de pop hl ret ; 3e043 DrawEnemyHUD: ; 3e043 xor a ld [hBGMapMode], a hlcoord 1, 0 lb bc, 4, 11 call ClearBox callba DrawEnemyHUDBorder ld a, [TempEnemyMonSpecies] ld [CurSpecies], a ld [CurPartySpecies], a call GetBaseData ld de, EnemyMonNick hlcoord 1, 0 call ret_3e138 call PlaceString ld h, b ld l, c dec hl ld hl, EnemyMonDVs ld de, TempMonDVs ld a, [EnemySubStatus5] bit SUBSTATUS_TRANSFORMED, a jr z, .ok ld hl, wEnemyBackupDVs .ok ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a ld a, TEMPMON ld [MonType], a callab GetGender ld a, " " jr c, .got_gender ld a, "♂" jr nz, .got_gender ld a, "♀" .got_gender hlcoord 9, 1 ld [hl], a hlcoord 6, 1 push af push hl ld de, EnemyMonStatus predef PlaceNonFaintStatus pop hl pop bc jr nz, .skip_level ld a, b cp " " jr nz, .print_level dec hl .print_level ld a, [EnemyMonLevel] ld [TempMonLevel], a call PrintLevel .skip_level ld hl, EnemyMonHP ld a, [hli] ld [hMultiplicand + 1], a ld a, [hld] ld [hMultiplicand + 2], a or [hl] jr nz, .not_fainted ld c, a ld e, a ld d, HP_BAR_LENGTH jp .draw_bar .not_fainted xor a ld [hMultiplicand], a ld a, HP_BAR_LENGTH_PX ld [hMultiplier], a call Multiply ld hl, EnemyMonMaxHP ld a, [hli] ld b, a ld a, [hl] ld [hMultiplier], a ld a, b and a jr z, .less_than_256_max ld a, [hMultiplier] srl b rr a srl b rr a ld [hDivisor], a ld a, [hProduct + 2] ld b, a srl b ld a, [hProduct + 3] rr a srl b rr a ld [hProduct + 3], a ld a, b ld [hProduct + 2], a .less_than_256_max ld a, [hProduct + 2] ld [hDividend + 0], a ld a, [hProduct + 3] ld [hDividend + 1], a ld a, 2 ld b, a call Divide ld a, [hQuotient + 2] ld e, a ld a, HP_BAR_LENGTH ld d, a ld c, a .draw_bar xor a ld [wWhichHPBar], a hlcoord 2, 2 ld b, 0 call DrawBattleHPBar ret ; 3e127 UpdateEnemyHPPal: ; 3e127 ld hl, EnemyHPPal call UpdateHPPal ret ; 3e12e UpdateHPPal: ; 3e12e ld b, [hl] call SetHPPal ld a, [hl] cp b ret z jp FinishBattleAnim ; 3e138 ret_3e138: ; 3e138 ret ; 3e139 BattleMenu: ; 3e139 xor a ld [hBGMapMode], a call LoadTempTileMapToTileMap ld a, [BattleType] cp BATTLETYPE_DEBUG jr z, .ok cp BATTLETYPE_TUTORIAL jr z, .ok call EmptyBattleTextBox call UpdateBattleHuds call EmptyBattleTextBox call LoadTileMapToTempTileMap .ok .loop ld a, [BattleType] cp BATTLETYPE_CONTEST jr nz, .not_contest callba ContestBattleMenu jr .next .not_contest ; Auto input: choose "ITEM" ld a, [InputType] or a jr z, .skip_dude_pack_select callba _DudeAutoInput_DownA .skip_dude_pack_select call LoadBattleMenu2 ret c .next ld a, $1 ld [hBGMapMode], a ld a, [wBattleMenuCursorBuffer] cp $1 jp z, BattleMenu_Fight cp $3 jp z, BattleMenu_Pack cp $2 jp z, BattleMenu_PKMN cp $4 jp z, BattleMenu_Run jr .loop ; 3e192 BattleMenu_Fight: ; 3e192 xor a ld [wNumFleeAttempts], a call Call_LoadTempTileMapToTileMap and a ret ; 3e19b LoadBattleMenu2: ; 3e19b call IsMobileBattle jr z, .mobile callba LoadBattleMenu and a ret .mobile callba Function100b12 ld a, [wcd2b] and a ret z ld hl, wcd2a bit 4, [hl] jr nz, .error ld hl, BattleText_LinkErrorBattleCanceled call StdBattleTextBox ld c, 60 call DelayFrames .error scf ret ; 3e1c7 BattleMenu_Pack: ; 3e1c7 ld a, [wLinkMode] and a jp nz, .ItemsCantBeUsed ld a, [InBattleTowerBattle] and a jp nz, .ItemsCantBeUsed call LoadStandardMenuDataHeader ld a, [BattleType] cp BATTLETYPE_TUTORIAL jr z, .tutorial cp BATTLETYPE_CONTEST jr z, .contest callba BattlePack ld a, [wPlayerAction] and a jr z, .didnt_use_item jr .got_item .tutorial callba TutorialPack ld a, POKE_BALL ld [CurItem], a call DoItemEffect jr .got_item .contest ld a, PARK_BALL ld [CurItem], a call DoItemEffect .got_item call .UseItem ret .didnt_use_item call ClearPalettes call DelayFrame call _LoadBattleFontsHPBar call GetMonBackpic call GetMonFrontpic call ExitMenu call WaitBGMap call FinishBattleAnim call LoadTileMapToTempTileMap jp BattleMenu ; 3e22b .ItemsCantBeUsed: ; 3e22b ld hl, BattleText_ItemsCantBeUsedHere call StdBattleTextBox jp BattleMenu ; 3e234 .UseItem: ; 3e234 ld a, [wWildMon] and a jr nz, .run callab CheckItemPocket ld a, [wItemAttributeParamBuffer] cp BALL jr z, .ball call ClearBGPalettes .ball xor a ld [hBGMapMode], a call _LoadBattleFontsHPBar call ClearSprites ld a, [BattleType] cp BATTLETYPE_TUTORIAL jr z, .tutorial2 call GetMonBackpic .tutorial2 call GetMonFrontpic ld a, $1 ld [wMenuCursorY], a call ExitMenu call UpdateBattleHUDs call WaitBGMap call LoadTileMapToTempTileMap call ClearWindowData call FinishBattleAnim and a ret .run xor a ld [wWildMon], a ld a, [wBattleResult] and $c0 ld [wBattleResult], a call ClearWindowData call SetPalettes scf ret ; 3e28d BattleMenu_PKMN: ; 3e28d call LoadStandardMenuDataHeader BattleMenuPKMN_ReturnFromStats: call ExitMenu call LoadStandardMenuDataHeader call ClearBGPalettes BattleMenuPKMN_Loop: call SetUpBattlePartyMenu xor a ld [PartyMenuActionText], a call JumpToPartyMenuAndPrintText call SelectBattleMon jr c, .Cancel .loop callba FreezeMonIcons call .GetMenu jr c, .PressedB call PlaceHollowCursor ld a, [wMenuCursorY] cp $1 ; SWITCH jp z, TryPlayerSwitch cp $2 ; STATS jr z, .Stats cp $3 ; CANCEL jr z, .Cancel jr .loop .PressedB: call CheckMobileBattleError jr c, .Cancel jr BattleMenuPKMN_Loop .Stats: call Battle_StatsScreen call CheckMobileBattleError jr c, .Cancel jp BattleMenuPKMN_ReturnFromStats .Cancel: call ClearSprites call ClearPalettes call DelayFrame call _LoadHPBar call CloseWindow call LoadTileMapToTempTileMap call GetMemSGBLayout call SetPalettes jp BattleMenu ; 3e2f5 .GetMenu: ; 3e2f5 call IsMobileBattle jr z, .mobile callba BattleMonMenu ret .mobile callba MobileBattleMonMenu ret ; 3e308 Battle_StatsScreen: ; 3e308 call DisableLCD ld hl, VTiles2 tile $31 ld de, VTiles0 ld bc, $11 tiles call CopyBytes ld hl, VTiles2 ld de, VTiles0 tile $11 ld bc, $31 tiles call CopyBytes call EnableLCD call ClearSprites call LowVolume xor a ; PARTYMON ld [MonType], a callba BattleStatsScreenInit call MaxVolume call DisableLCD ld hl, VTiles0 ld de, VTiles2 tile $31 ld bc, $11 tiles call CopyBytes ld hl, VTiles0 tile $11 ld de, VTiles2 ld bc, $31 tiles call CopyBytes call EnableLCD ret ; 3e358 TryPlayerSwitch: ; 3e358 ld a, [CurBattleMon] ld d, a ld a, [CurPartyMon] cp d jr nz, .check_trapped ld hl, BattleText_PkmnIsAlreadyOut call StdBattleTextBox jp BattleMenuPKMN_Loop .check_trapped ld a, [wPlayerWrapCount] and a jr nz, .trapped ld a, [EnemySubStatus5] bit SUBSTATUS_CANT_RUN, a jr z, .try_switch .trapped ld hl, BattleText_PkmnCantBeRecalled call StdBattleTextBox jp BattleMenuPKMN_Loop .try_switch call CheckIfCurPartyMonIsFitToFight jp z, BattleMenuPKMN_Loop ld a, [CurBattleMon] ld [LastPlayerMon], a ld a, $2 ld [wPlayerAction], a call ClearPalettes call DelayFrame call ClearSprites call _LoadHPBar call CloseWindow call GetMemSGBLayout call SetPalettes ld a, [CurPartyMon] ld [CurBattleMon], a PlayerSwitch: ; 3e3ad ld a, 1 ld [wPlayerIsSwitching], a ld a, [wLinkMode] and a jr z, .not_linked call LoadStandardMenuDataHeader call LinkBattleSendReceiveAction call CloseWindow .not_linked call ParseEnemyAction ld a, [wLinkMode] and a jr nz, .linked .switch call BattleMonEntrance and a ret .linked ld a, [wBattleAction] cp BATTLEACTION_E jp z, .switch cp BATTLEACTION_D jp z, .switch cp BATTLEACTION_SWITCH1 jp c, .switch cp BATTLEACTION_FORFEIT jr nz, .dont_run call WildFled_EnemyFled_LinkBattleCanceled ret .dont_run ld a, [hLinkPlayerNumber] cp $1 jr z, .player_1 call BattleMonEntrance call EnemyMonEntrance and a ret .player_1 call EnemyMonEntrance call BattleMonEntrance and a ret ; 3e3ff EnemyMonEntrance: ; 3e3ff callab AI_Switch call SetEnemyTurn jp SpikesDamage ; 3e40b BattleMonEntrance: ; 3e40b call WithdrawPkmnText ld c, 50 call DelayFrames ld hl, PlayerSubStatus4 res SUBSTATUS_RAGE, [hl] call SetEnemyTurn call PursuitSwitch jr c, .ok call RecallPlayerMon .ok hlcoord 9, 7 lb bc, 5, 11 call ClearBox ld a, [CurBattleMon] ld [CurPartyMon], a call AddBattleParticipant call InitBattleMon call ResetPlayerStatLevels call SendOutPkmnText call NewBattleMonStatus call BreakAttraction call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap call SetPlayerTurn call SpikesDamage ld a, $2 ld [wMenuCursorY], a ret ; 3e459 PassedBattleMonEntrance: ; 3e459 ld c, 50 call DelayFrames hlcoord 9, 7 lb bc, 5, 11 call ClearBox ld a, [CurPartyMon] ld [CurBattleMon], a call AddBattleParticipant call InitBattleMon xor a ld [wd265], a call ApplyStatLevelMultiplierOnAllStats call SendOutPlayerMon call EmptyBattleTextBox call LoadTileMapToTempTileMap call SetPlayerTurn jp SpikesDamage ; 3e489 BattleMenu_Run: ; 3e489 call Call_LoadTempTileMapToTileMap ld a, $3 ld [wMenuCursorY], a ld hl, BattleMonSpeed ld de, EnemyMonSpeed call TryToRunAwayFromBattle ld a, $0 ld [wFailedToFlee], a ret c ld a, [wPlayerAction] and a ret nz jp BattleMenu ; 3e4a8 CheckAmuletCoin: ; 3e4a8 ld a, [BattleMonItem] ld b, a callab GetItemHeldEffect ld a, b cp HELD_AMULET_COIN ret nz ld a, 1 ld [wAmuletCoin], a ret ; 3e4bc MoveSelectionScreen: ; 3e4bc call IsMobileBattle jr nz, .not_mobile callba MobileMoveSelectionScreen ret .not_mobile ld hl, EnemyMonMoves ld a, [wMoveSelectionMenuType] dec a jr z, .got_menu_type dec a jr z, .ether_elixer_menu call CheckPlayerHasUsableMoves ret z ; use Struggle ld hl, BattleMonMoves jr .got_menu_type .ether_elixer_menu ld a, MON_MOVES call GetPartyParamLocation .got_menu_type ld de, wListMoves_MoveIndicesBuffer ld bc, NUM_MOVES call CopyBytes xor a ld [hBGMapMode], a hlcoord 4, 17 - NUM_MOVES - 1 ld b, 4 ld c, 14 ld a, [wMoveSelectionMenuType] cp $2 jr nz, .got_dims hlcoord 4, 17 - NUM_MOVES - 1 - 4 ld b, 4 ld c, 14 .got_dims call TextBox hlcoord 6, 17 - NUM_MOVES ld a, [wMoveSelectionMenuType] cp $2 jr nz, .got_start_coord hlcoord 6, 17 - NUM_MOVES - 4 .got_start_coord ld a, SCREEN_WIDTH ld [Buffer1], a predef ListMoves ld b, 5 ld a, [wMoveSelectionMenuType] cp $2 ld a, 17 - NUM_MOVES jr nz, .got_default_coord ld b, 5 ld a, 17 - NUM_MOVES - 4 .got_default_coord ld [w2DMenuCursorInitY], a ld a, b ld [w2DMenuCursorInitX], a ld a, [wMoveSelectionMenuType] cp $1 jr z, .skip_inc ld a, [CurMoveNum] inc a .skip_inc ld [wMenuCursorY], a ld a, $1 ld [wMenuCursorX], a ld a, [wNumMoves] inc a ld [w2DMenuNumRows], a ld a, $1 ld [w2DMenuNumCols], a ld c, $2c ld a, [wMoveSelectionMenuType] dec a ld b, D_DOWN | D_UP | A_BUTTON jr z, .okay dec a ld b, D_DOWN | D_UP | A_BUTTON | B_BUTTON jr z, .okay ld a, [wLinkMode] and a jr nz, .okay ld b, D_DOWN | D_UP | A_BUTTON | B_BUTTON | SELECT .okay ld a, b ld [wMenuJoypadFilter], a ld a, c ld [w2DMenuFlags1], a xor a ld [w2DMenuFlags2], a ld a, $10 ld [w2DMenuCursorOffsets], a .menu_loop ld a, [wMoveSelectionMenuType] and a jr z, .battle_player_moves dec a jr nz, .interpret_joypad hlcoord 11, 14 ld de, .string_3e61c call PlaceString jr .interpret_joypad .battle_player_moves call MoveInfoBox ld a, [wMoveSwapBuffer] and a jr z, .interpret_joypad hlcoord 5, 13 ld bc, SCREEN_WIDTH dec a call AddNTimes ld [hl], "▷" .interpret_joypad ld a, $1 ld [hBGMapMode], a call ScrollingMenuJoypad bit D_UP_F, a jp nz, .pressed_up bit D_DOWN_F, a jp nz, .pressed_down bit SELECT_F, a jp nz, .pressed_select bit B_BUTTON_F, a ; A button push af xor a ld [wMoveSwapBuffer], a ld a, [wMenuCursorY] dec a ld [wMenuCursorY], a ld b, a ld a, [wMoveSelectionMenuType] dec a jr nz, .not_enemy_moves_process_b pop af ret .not_enemy_moves_process_b dec a ld a, b ld [CurMoveNum], a jr nz, .use_move pop af ret .use_move pop af ret nz ld hl, BattleMonPP ld a, [wMenuCursorY] ld c, a ld b, 0 add hl, bc ld a, [hl] and $3f jr z, .no_pp_left ld a, [PlayerDisableCount] swap a and $f dec a cp c jr z, .move_disabled ld a, [wUnusedPlayerLockedMove] and a jr nz, .skip2 ld a, [wMenuCursorY] ld hl, BattleMonMoves ld c, a ld b, 0 add hl, bc ld a, [hl] .skip2 ld [CurPlayerMove], a xor a ret .move_disabled ld hl, BattleText_TheMoveIsDisabled jr .place_textbox_start_over .no_pp_left ld hl, BattleText_TheresNoPPLeftForThisMove .place_textbox_start_over call StdBattleTextBox call Call_LoadTempTileMapToTileMap jp MoveSelectionScreen ; 3e61c .string_3e61c ; 3e61c db "@" ; 3e61d .pressed_up ld a, [wMenuCursorY] and a jp nz, .menu_loop ld a, [wNumMoves] inc a ld [wMenuCursorY], a jp .menu_loop ; 3e62e .pressed_down ; 3e62e ld a, [wMenuCursorY] ld b, a ld a, [wNumMoves] inc a inc a cp b jp nz, .menu_loop ld a, $1 ld [wMenuCursorY], a jp .menu_loop ; 3e643 .pressed_select ; 3e643 ld a, [wMoveSwapBuffer] and a jr z, .start_swap ld hl, BattleMonMoves call .swap_bytes ld hl, BattleMonPP call .swap_bytes ld hl, PlayerDisableCount ld a, [hl] swap a and $f ld b, a ld a, [wMenuCursorY] cp b jr nz, .not_swapping_disabled_move ld a, [hl] and $f ld b, a ld a, [wMoveSwapBuffer] swap a add b ld [hl], a jr .swap_moves_in_party_struct .not_swapping_disabled_move ld a, [wMoveSwapBuffer] cp b jr nz, .swap_moves_in_party_struct ld a, [hl] and $f ld b, a ld a, [wMenuCursorY] swap a add b ld [hl], a .swap_moves_in_party_struct ; Fixes the COOLTRAINER glitch ld a, [PlayerSubStatus5] bit SUBSTATUS_TRANSFORMED, a jr nz, .transformed ld hl, PartyMon1Moves ld a, [CurBattleMon] call GetPartyLocation push hl call .swap_bytes pop hl ld bc, MON_PP - MON_MOVES add hl, bc call .swap_bytes .transformed xor a ld [wMoveSwapBuffer], a jp MoveSelectionScreen .swap_bytes push hl ld a, [wMoveSwapBuffer] dec a ld c, a ld b, 0 add hl, bc ld d, h ld e, l pop hl ld a, [wMenuCursorY] dec a ld c, a ld b, 0 add hl, bc ld a, [de] ld b, [hl] ld [hl], a ld a, b ld [de], a ret .start_swap ld a, [wMenuCursorY] ld [wMoveSwapBuffer], a jp MoveSelectionScreen ; 3e6c8 MoveInfoBox: ; 3e6c8 xor a ld [hBGMapMode], a hlcoord 0, 8 ld b, 3 ld c, 9 call TextBox call MobileTextBorder ld a, [PlayerDisableCount] and a jr z, .not_disabled swap a and $f ld b, a ld a, [wMenuCursorY] cp b jr nz, .not_disabled hlcoord 1, 10 ld de, .Disabled call PlaceString jr .done .not_disabled ld hl, wMenuCursorY dec [hl] call SetPlayerTurn ld hl, BattleMonMoves ld a, [wMenuCursorY] ld c, a ld b, 0 add hl, bc ld a, [hl] ld [CurPlayerMove], a ld a, [CurBattleMon] ld [CurPartyMon], a ld a, WILDMON ld [MonType], a callab GetMaxPPOfMove ld hl, wMenuCursorY ld c, [hl] inc [hl] ld b, 0 ld hl, BattleMonPP add hl, bc ld a, [hl] and $3f ld [StringBuffer1], a call .PrintPP hlcoord 1, 9 ld de, .Type call PlaceString hlcoord 7, 11 ld [hl], "/" callab UpdateMoveData ld a, [wPlayerMoveStruct + MOVE_ANIM] ld b, a hlcoord 2, 10 predef PrintMoveType .done ret ; 3e74f .Disabled: db "Disabled!@" .Type: db "TYPE/@" ; 3e75f .PrintPP: ; 3e75f hlcoord 5, 11 ld a, [wLinkMode] ; What's the point of this check? cp LINK_MOBILE jr c, .ok hlcoord 5, 11 .ok push hl ld de, StringBuffer1 lb bc, 1, 2 call PrintNum pop hl inc hl inc hl ld [hl], "/" inc hl ld de, wNamedObjectIndexBuffer lb bc, 1, 2 call PrintNum ret ; 3e786 CheckPlayerHasUsableMoves: ; 3e786 ld a, STRUGGLE ld [CurPlayerMove], a ld a, [PlayerDisableCount] and a ld hl, BattleMonPP jr nz, .disabled ld a, [hli] or [hl] inc hl or [hl] inc hl or [hl] and $3f ret nz jr .force_struggle .disabled swap a and $f ld b, a ld d, NUM_MOVES + 1 xor a .loop dec d jr z, .done ld c, [hl] inc hl dec b jr z, .loop or c jr .loop .done ; Bug: this will result in a move with PP Up confusing the game. ; Replace with "and $3f" to fix. and a ret nz .force_struggle ld hl, BattleText_PkmnHasNoMovesLeft call StdBattleTextBox ld c, 60 call DelayFrames xor a ret ; 3e7c1 ParseEnemyAction: ; 3e7c1 ld a, [wEnemyIsSwitching] and a ret nz ld a, [wLinkMode] and a jr z, .not_linked call EmptyBattleTextBox call LoadTileMapToTempTileMap ld a, [wPlayerAction] and a call z, LinkBattleSendReceiveAction call Call_LoadTempTileMapToTileMap ld a, [wBattleAction] cp BATTLEACTION_E jp z, .struggle cp BATTLEACTION_D jp z, .battle_action_d cp BATTLEACTION_SWITCH1 jp nc, ResetVarsForSubstatusRage ld [CurEnemyMoveNum], a ld c, a ld a, [EnemySubStatus1] bit SUBSTATUS_ROLLOUT, a jp nz, .skip_load ld a, [EnemySubStatus3] and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE jp nz, .skip_load ld hl, EnemySubStatus5 bit SUBSTATUS_ENCORED, [hl] ld a, [LastEnemyMove] jp nz, .finish ld hl, EnemyMonMoves ld b, 0 add hl, bc ld a, [hl] jp .finish .not_linked ld hl, EnemySubStatus5 bit SUBSTATUS_ENCORED, [hl] jr z, .skip_encore ld a, [LastEnemyMove] jp .finish .skip_encore call CheckEnemyLockedIn jp nz, ResetVarsForSubstatusRage jr .continue .battle_action_d ld a, $ff jr .finish .continue ld hl, EnemyMonMoves ld de, EnemyMonPP ld b, NUM_MOVES .loop ld a, [hl] and a jp z, .struggle ld a, [EnemyDisabledMove] cp [hl] jr z, .disabled ld a, [de] and $3f jr nz, .enough_pp .disabled inc hl inc de dec b jr nz, .loop jr .struggle .enough_pp ld a, [wBattleMode] dec a jr nz, .skip_load ; wild .loop2 ld hl, EnemyMonMoves call BattleRandom and 3 ; TODO factor in NUM_MOVES ld c, a ld b, 0 add hl, bc ld a, [EnemyDisableCount] swap a and $f dec a cp c jr z, .loop2 ld a, [hl] and a jr z, .loop2 ld hl, EnemyMonPP add hl, bc ld b, a ld a, [hl] and $3f jr z, .loop2 ld a, c ld [CurEnemyMoveNum], a ld a, b .finish ld [CurEnemyMove], a .skip_load call SetEnemyTurn callab UpdateMoveData call CheckEnemyLockedIn jr nz, .raging xor a ld [wEnemyCharging], a .raging ld a, [wEnemyMoveStruct + MOVE_EFFECT] cp EFFECT_FURY_CUTTER jr z, .fury_cutter xor a ld [EnemyFuryCutterCount], a .fury_cutter ld a, [wEnemyMoveStruct + MOVE_EFFECT] cp EFFECT_RAGE jr z, .no_rage ld hl, EnemySubStatus4 res SUBSTATUS_RAGE, [hl] xor a ld [wEnemyRageCounter], a .no_rage ld a, [wEnemyMoveStruct + MOVE_EFFECT] cp EFFECT_PROTECT ret z cp EFFECT_ENDURE ret z xor a ld [EnemyProtectCount], a ret .struggle ld a, STRUGGLE jr .finish ; 3e8c1 ResetVarsForSubstatusRage: ; 3e8c1 xor a ld [EnemyFuryCutterCount], a ld [EnemyProtectCount], a ld [wEnemyRageCounter], a ld hl, EnemySubStatus4 res SUBSTATUS_RAGE, [hl] ret ; 3e8d1 CheckEnemyLockedIn: ; 3e8d1 ld a, [EnemySubStatus4] and 1 << SUBSTATUS_RECHARGE ret nz ld hl, EnemySubStatus3 ld a, [hl] and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE ret nz ld hl, EnemySubStatus1 bit SUBSTATUS_ROLLOUT, [hl] ret ; 3e8e4 LinkBattleSendReceiveAction: ; 3e8e4 callba _LinkBattleSendReceiveAction ret ; 3e8eb LoadEnemyMon: ; 3e8eb ; Initialize enemy monster parameters ; To do this we pull the species from TempEnemyMonSpecies ; Notes: ; BattleRandom is used to ensure sync between Game Boys ; Clear the whole EnemyMon struct xor a ld hl, EnemyMonSpecies ld bc, EnemyMonEnd - EnemyMon call ByteFill ; We don't need to be here if we're in a link battle ld a, [wLinkMode] and a jp nz, InitEnemyMon ; and also not in a BattleTower-Battle ld a, [InBattleTowerBattle] ; ???? bit 0, a jp nz, InitEnemyMon ; Make sure everything knows what species we're working with ld a, [TempEnemyMonSpecies] ld [EnemyMonSpecies], a ld [CurSpecies], a ld [CurPartySpecies], a ; Grab the BaseData for this species call GetBaseData ; Let's get the item: ; Is the item predetermined? ld a, [wBattleMode] dec a jr z, .WildItem ; If we're in a trainer battle, the item is in the party struct ld a, [CurPartyMon] ld hl, OTPartyMon1Item call GetPartyLocation ; bc = PartyMon[CurPartyMon] - PartyMons ld a, [hl] jr .UpdateItem .WildItem: ; In a wild battle, we pull from the item slots in BaseData ; Force Item1 ; Used for Ho-Oh, Lugia and Snorlax encounters ld a, [BattleType] cp BATTLETYPE_FORCEITEM ld a, [BaseItems] jr z, .UpdateItem ; Failing that, it's all up to chance ; Effective chances: ; 75% None ; 23% Item1 ; 2% Item2 ; 25% chance of getting an item call BattleRandom cp 1 + (75 percent) ld a, NO_ITEM jr c, .UpdateItem ; From there, an 8% chance for Item2 call BattleRandom cp 8 percent ; 8% of 25% = 2% Item2 ld a, [BaseItems] jr nc, .UpdateItem ld a, [BaseItems+1] .UpdateItem: ld [EnemyMonItem], a ; Initialize DVs ; If we're in a trainer battle, DVs are predetermined ld a, [wBattleMode] and a jr z, .InitDVs ld a, [EnemySubStatus5] bit SUBSTATUS_TRANSFORMED, a jr z, .InitDVs ; Unknown ld hl, wEnemyBackupDVs ld de, EnemyMonDVs ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a jp .Happiness .InitDVs: ; Trainer DVs ; All trainers have preset DVs, determined by class ; See GetTrainerDVs for more on that callba GetTrainerDVs ; These are the DVs we'll use if we're actually in a trainer battle ld a, [wBattleMode] dec a jr nz, .UpdateDVs ; Wild DVs ; Here's where the fun starts ; Roaming monsters (Entei, Raikou) work differently ; They have their own structs, which are shorter than normal ld a, [BattleType] cp BATTLETYPE_ROAMING jr nz, .NotRoaming ; Grab HP call GetRoamMonHP ld a, [hl] ; Check if the HP has been initialized and a ; We'll do something with the result in a minute push af ; Grab DVs call GetRoamMonDVs inc hl ld a, [hld] ld c, a ld b, [hl] ; Get back the result of our check pop af ; If the RoamMon struct has already been initialized, we're done jr nz, .UpdateDVs ; If it hasn't, we need to initialize the DVs ; (HP is initialized at the end of the battle) call GetRoamMonDVs inc hl call BattleRandom ld [hld], a ld c, a call BattleRandom ld [hl], a ld b, a ; We're done with DVs jr .UpdateDVs .NotRoaming: ; Register a contains BattleType ; Forced shiny battle type ; Used by Red Gyarados at Lake of Rage cp BATTLETYPE_SHINY jr nz, .GenerateDVs ld b, ATKDEFDV_SHINY ; $ea ld c, SPDSPCDV_SHINY ; $aa jr .UpdateDVs .GenerateDVs: ; Generate new random DVs call BattleRandom ld b, a call BattleRandom ld c, a .UpdateDVs: ; Input DVs in register bc ld hl, EnemyMonDVs ld a, b ld [hli], a ld [hl], c ; We've still got more to do if we're dealing with a wild monster ld a, [wBattleMode] dec a jr nz, .Happiness ; Species-specfic: ; Unown ld a, [TempEnemyMonSpecies] cp UNOWN jr nz, .Magikarp ; Get letter based on DVs ld hl, EnemyMonDVs predef GetUnownLetter ; Can't use any letters that haven't been unlocked ; If combined with forced shiny battletype, causes an infinite loop call CheckUnownLetter jr c, .GenerateDVs ; try again .Magikarp: ; Skimming this part recommended ld a, [TempEnemyMonSpecies] cp MAGIKARP jr nz, .Happiness ; Get Magikarp's length ld de, EnemyMonDVs ld bc, PlayerID callab CalcMagikarpLength ; We're clear if the length is < 1536 ld a, [wMagikarpLength] cp $06 ; $600 = 1536 jr nz, .CheckMagikarpArea ; 5% chance of skipping size checks call Random cp $0c ; / $100 jr c, .CheckMagikarpArea ; Try again if > 1614 ld a, [wMagikarpLength + 1] cp $50 jr nc, .GenerateDVs ; 20% chance of skipping this check call Random cp $32 ; / $100 jr c, .CheckMagikarpArea ; Try again if > 1598 ld a, [wMagikarpLength + 1] cp $40 jr nc, .GenerateDVs .CheckMagikarpArea: ; The z checks are supposed to be nz ; Instead, all maps in GROUP_LAKE_OF_RAGE (mahogany area) ; and routes 20 and 44 are treated as Lake of Rage ; This also means Lake of Rage Magikarp can be smaller than ones ; caught elsewhere rather than the other way around ; Intended behavior enforces a minimum size at Lake of Rage ; The real behavior prevents size flooring in the Lake of Rage area ld a, [MapGroup] cp GROUP_LAKE_OF_RAGE jr z, .Happiness ld a, [MapNumber] cp MAP_LAKE_OF_RAGE jr z, .Happiness ; 40% chance of not flooring call Random cp $64 ; / $100 jr c, .Happiness ; Floor at length 1024 ld a, [wMagikarpLength] cp 1024 >> 8 jr c, .GenerateDVs ; try again ; Finally done with DVs .Happiness: ; Set happiness ld a, BASE_HAPPINESS ld [EnemyMonHappiness], a ; Set level ld a, [CurPartyLevel] ld [EnemyMonLevel], a ; Fill stats ld de, EnemyMonMaxHP ld b, FALSE ld hl, EnemyMonDVs - (MON_DVS - MON_STAT_EXP + 1) ; LinkBattleRNs + 7 ; ? predef CalcPkmnStats ; If we're in a trainer battle, ; get the rest of the parameters from the party struct ld a, [wBattleMode] cp TRAINER_BATTLE jr z, .OpponentParty ; If we're in a wild battle, check wild-specific stuff and a jr z, .TreeMon ld a, [EnemySubStatus5] bit SUBSTATUS_TRANSFORMED, a jp nz, .Moves .TreeMon: ; If we're headbutting trees, some monsters enter battle asleep call CheckSleepingTreeMon ld a, SLP ; Asleep for 7 turns jr c, .UpdateStatus ; Otherwise, no status xor a .UpdateStatus: ld hl, EnemyMonStatus ld [hli], a ; Unused byte xor a ld [hli], a ; Full HP.. ld a, [EnemyMonMaxHP] ld [hli], a ld a, [EnemyMonMaxHP + 1] ld [hl], a ; ..unless it's a RoamMon ld a, [BattleType] cp BATTLETYPE_ROAMING jr nz, .Moves ; Grab HP call GetRoamMonHP ld a, [hl] ; Check if it's been initialized again and a jr z, .InitRoamHP ; Update from the struct if it has ld a, [hl] ld [EnemyMonHP + 1], a jr .Moves .InitRoamHP: ; HP only uses the lo byte in the RoamMon struct since ; Raikou/Entei/Suicune will have < 256 hp at level 40 ld a, [EnemyMonHP + 1] ld [hl], a jr .Moves .OpponentParty: ; Get HP from the party struct ld hl, (OTPartyMon1HP + 1) ld a, [CurPartyMon] call GetPartyLocation ld a, [hld] ld [EnemyMonHP + 1], a ld a, [hld] ld [EnemyMonHP], a ; Make sure everything knows which monster the opponent is using ld a, [CurPartyMon] ld [CurOTMon], a ; Get status from the party struct dec hl ld a, [hl] ; OTPartyMonStatus ld [EnemyMonStatus], a .Moves: ld hl, BaseType1 ld de, EnemyMonType1 ld a, [hli] ld [de], a inc de ld a, [hl] ld [de], a ; Get moves ld de, EnemyMonMoves ; Are we in a trainer battle? ld a, [wBattleMode] cp TRAINER_BATTLE jr nz, .WildMoves ; Then copy moves from the party struct ld hl, OTPartyMon1Moves ld a, [CurPartyMon] call GetPartyLocation ld bc, NUM_MOVES call CopyBytes jr .PP .WildMoves: ; Clear EnemyMonMoves xor a ld h, d ld l, e ld [hli], a ld [hli], a ld [hli], a ld [hl], a ; Make sure the predef knows this isn't a partymon ld [wEvolutionOldSpecies], a ; Fill moves based on level predef FillMoves .PP: ; Trainer battle? ld a, [wBattleMode] cp TRAINER_BATTLE jr z, .TrainerPP ; Fill wild PP ld hl, EnemyMonMoves ld de, EnemyMonPP predef FillPP jr .Finish .TrainerPP: ; Copy PP from the party struct ld hl, OTPartyMon1PP ld a, [CurPartyMon] call GetPartyLocation ld de, EnemyMonPP ld bc, NUM_MOVES call CopyBytes .Finish: ; Only the first five base stats are copied.. ld hl, BaseStats ld de, EnemyMonBaseStats ld b, BaseSpecialDefense - BaseStats .loop ld a, [hli] ld [de], a inc de dec b jr nz, .loop ld a, [BaseCatchRate] ld [de], a inc de ld a, [BaseExp] ld [de], a ld a, [TempEnemyMonSpecies] ld [wd265], a call GetPokemonName ; Did we catch it? ld a, [wBattleMode] and a ret z ; Update enemy nick ld hl, StringBuffer1 ld de, EnemyMonNick ld bc, PKMN_NAME_LENGTH call CopyBytes ; Saw this mon ld a, [TempEnemyMonSpecies] dec a ld c, a ld b, SET_FLAG ld hl, PokedexSeen predef FlagPredef ld hl, EnemyMonStats ld de, EnemyStats ld bc, EnemyMonStatsEnd - EnemyMonStats call CopyBytes ret ; 3eb38 CheckSleepingTreeMon: ; 3eb38 ; Return carry if species is in the list ; for the current time of day ; Don't do anything if this isn't a tree encounter ld a, [BattleType] cp BATTLETYPE_TREE jr nz, .NotSleeping ; Get list for the time of day ld hl, .Morn ld a, [TimeOfDay] cp DAY_F jr c, .Check ld hl, .Day jr z, .Check ld hl, .Nite .Check: ld a, [TempEnemyMonSpecies] ld de, 1 ; length of species id call IsInArray ; If it's a match, the opponent is asleep ret c .NotSleeping: and a ret .Nite: db CATERPIE db METAPOD db BUTTERFREE db WEEDLE db KAKUNA db BEEDRILL db SPEAROW db EKANS db EXEGGCUTE db LEDYBA db AIPOM db -1 ; end .Day: db VENONAT db HOOTHOOT db NOCTOWL db SPINARAK db HERACROSS db -1 ; end .Morn: db VENONAT db HOOTHOOT db NOCTOWL db SPINARAK db HERACROSS db -1 ; end ; 3eb75 CheckUnownLetter: ; 3eb75 ; Return carry if the Unown letter hasn't been unlocked yet ld a, [UnlockedUnowns] ld c, a ld de, 0 .loop ; Don't check this set unless it's been unlocked srl c jr nc, .next ; Is our letter in the set? ld hl, .LetterSets add hl, de ld a, [hli] ld h, [hl] ld l, a push de ld a, [UnownLetter] ld de, 1 push bc call IsInArray pop bc pop de jr c, .match .next ; Make sure we haven't gone past the end of the table inc e inc e ld a, e cp .Set1 - .LetterSets jr c, .loop ; Hasn't been unlocked, or the letter is invalid scf ret .match ; Valid letter and a ret .LetterSets: dw .Set1 dw .Set2 dw .Set3 dw .Set4 .Set1: ; A B C D E F G H I J K db 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, $ff .Set2: ; L M N O P Q R db 12, 13, 14, 15, 16, 17, 18, $ff .Set3: ; S T U V W db 19, 20, 21, 22, 23, $ff .Set4: ; X Y Z db 24, 25, 26, $ff ; 3ebc7 SwapBattlerLevels: ; 3ebc7 ; unreferenced push bc ld a, [BattleMonLevel] ld b, a ld a, [EnemyMonLevel] ld [BattleMonLevel], a ld a, b ld [EnemyMonLevel], a pop bc ret ; 3ebd8 BattleWinSlideInEnemyTrainerFrontpic: ; 3ebd8 xor a ld [TempEnemyMonSpecies], a call FinishBattleAnim ld a, [OtherTrainerClass] ld [TrainerClass], a ld de, VTiles2 callab GetTrainerPic hlcoord 19, 0 ld c, 0 .outer_loop inc c ld a, c cp 7 ret z xor a ld [hBGMapMode], a ld [hBGMapThird], a ld d, $0 push bc push hl .inner_loop call .CopyColumn inc hl ld a, 7 add d ld d, a dec c jr nz, .inner_loop ld a, $1 ld [hBGMapMode], a ld c, 4 call DelayFrames pop hl pop bc dec hl jr .outer_loop ; 3ec1a .CopyColumn: ; 3ec1a push hl push de push bc ld e, 7 .loop ld [hl], d ld bc, SCREEN_WIDTH add hl, bc inc d dec e jr nz, .loop pop bc pop de pop hl ret ; 3ec2c ApplyStatusEffectOnPlayerStats: ; 3ec2c ld a, 1 jr ApplyStatusEffectOnStats ; 3ec30 ApplyStatusEffectOnEnemyStats: ; 3ec30 xor a ; 3ec31 ApplyStatusEffectOnStats: ; 3ec31 ld [hBattleTurn], a call ApplyPrzEffectOnSpeed jp ApplyBrnEffectOnAttack ; 3ec39 ApplyPrzEffectOnSpeed: ; 3ec39 ld a, [hBattleTurn] and a jr z, .enemy ld a, [BattleMonStatus] and 1 << PAR ret z ld hl, BattleMonSpeed + 1 ld a, [hld] ld b, a ld a, [hl] srl a rr b srl a rr b ld [hli], a or b jr nz, .player_ok ld b, $1 ; min speed .player_ok ld [hl], b ret .enemy ld a, [EnemyMonStatus] and 1 << PAR ret z ld hl, EnemyMonSpeed + 1 ld a, [hld] ld b, a ld a, [hl] srl a rr b srl a rr b ld [hli], a or b jr nz, .enemy_ok ld b, $1 ; min speed .enemy_ok ld [hl], b ret ; 3ec76 ApplyBrnEffectOnAttack: ; 3ec76 ld a, [hBattleTurn] and a jr z, .enemy ld a, [BattleMonStatus] and 1 << BRN ret z ld hl, BattleMonAttack + 1 ld a, [hld] ld b, a ld a, [hl] srl a rr b ld [hli], a or b jr nz, .player_ok ld b, $1 ; min attack .player_ok ld [hl], b ret .enemy ld a, [EnemyMonStatus] and 1 << BRN ret z ld hl, EnemyMonAttack + 1 ld a, [hld] ld b, a ld a, [hl] srl a rr b ld [hli], a or b jr nz, .enemy_ok ld b, $1 ; min attack .enemy_ok ld [hl], b ret ; 3ecab ApplyStatLevelMultiplierOnAllStats: ; 3ecab ; Apply StatLevelMultipliers on all 5 Stats ld c, 0 .stat_loop call ApplyStatLevelMultiplier inc c ld a, c cp 5 jr nz, .stat_loop ret ; 3ecb7 ApplyStatLevelMultiplier: ; 3ecb7 push bc push bc ld a, [wd265] and a ld a, c ld hl, BattleMonAttack ld de, PlayerStats ld bc, PlayerAtkLevel jr z, .got_pointers ld hl, EnemyMonAttack ld de, EnemyStats ld bc, EnemyAtkLevel .got_pointers add c ld c, a jr nc, .okay inc b .okay ld a, [bc] pop bc ld b, a push bc sla c ld b, 0 add hl, bc ld a, c add e ld e, a jr nc, .okay2 inc d .okay2 pop bc push hl ld hl, .StatLevelMultipliers dec b sla b ld c, b ld b, 0 add hl, bc xor a ld [hMultiplicand + 0], a ld a, [de] ld [hMultiplicand + 1], a inc de ld a, [de] ld [hMultiplicand + 2], a ld a, [hli] ld [hMultiplier], a call Multiply ld a, [hl] ld [hDivisor], a ld b, $4 call Divide pop hl ; Cap at 999. ld a, [hQuotient + 2] sub 999 % $100 ld a, [hQuotient + 1] sbc 999 / $100 jp c, .okay3 ld a, 999 / $100 ld [hQuotient + 1], a ld a, 999 % $100 ld [hQuotient + 2], a .okay3 ld a, [hQuotient + 1] ld [hli], a ld b, a ld a, [hQuotient + 2] ld [hl], a or b jr nz, .okay4 inc [hl] .okay4 pop bc ret ; 3ed2b .StatLevelMultipliers: ; / db 25, 100 ; 25% db 28, 100 ; 28% db 33, 100 ; 33% db 40, 100 ; 40% db 50, 100 ; 50% db 66, 100 ; 66% db 1, 1 ; 100% db 15, 10 ; 150% db 2, 1 ; 200% db 25, 10 ; 250% db 3, 1 ; 300% db 35, 10 ; 350% db 4, 1 ; 400% ; 3ed45 BadgeStatBoosts: ; 3ed45 ; Raise BattleMon stats depending on which badges have been obtained. ; Every other badge boosts a stat, starting from the first. ; ZephyrBadge: Attack ; PlainBadge: Speed ; MineralBadge: Defense ; GlacierBadge: Special Attack ; RisingBadge: Special Defense ; The boosted stats are in order, except PlainBadge and MineralBadge's boosts are swapped. ld a, [wLinkMode] and a ret nz ld a, [InBattleTowerBattle] and a ret nz ld a, [JohtoBadges] ; Swap badges 3 (PlainBadge) and 5 (MineralBadge). ld d, a and (1 << PLAINBADGE) add a add a ld b, a ld a, d and (1 << MINERALBADGE) rrca rrca ld c, a ld a, d and ((1 << ZEPHYRBADGE) | (1 << HIVEBADGE) | (1 << FOGBADGE) | (1 << STORMBADGE) | (1 << GLACIERBADGE) | (1 << RISINGBADGE)) or b or c ld b, a ld hl, BattleMonAttack ld c, 4 .CheckBadge: ld a, b srl b call c, BoostStat inc hl inc hl ; Check every other badge. srl b dec c jr nz, .CheckBadge ; And the last one (RisingBadge) too. srl a call c, BoostStat ret ; 3ed7c BoostStat: ; 3ed7c ; Raise stat at hl by 1/8. ld a, [hli] ld d, a ld e, [hl] srl d rr e srl d rr e srl d rr e ld a, [hl] add e ld [hld], a ld a, [hl] adc d ld [hli], a ; Cap at 999. ld a, [hld] sub 999 % $100 ld a, [hl] sbc 999 / $100 ret c ld a, 999 / $100 ld [hli], a ld a, 999 % $100 ld [hld], a ret ; 3ed9f _LoadBattleFontsHPBar: ; 3ed9f callab LoadBattleFontsHPBar ret ; 3eda6 _LoadHPBar: ; 3eda6 callab LoadHPBar ret ; 3edad LoadHPExpBarGFX: ; unreferenced ld de, EnemyHPBarBorderGFX ld hl, VTiles2 tile $6c lb bc, BANK(EnemyHPBarBorderGFX), 4 call Get1bpp ld de, HPExpBarBorderGFX ld hl, VTiles2 tile $73 lb bc, BANK(HPExpBarBorderGFX), 6 call Get1bpp ld de, ExpBarGFX ld hl, VTiles2 tile $55 lb bc, BANK(ExpBarGFX), 8 jp Get2bpp ; 3edd1 EmptyBattleTextBox: ; 3edd1 ld hl, .empty jp BattleTextBox .empty db "@" ; 3edd8 _BattleRandom:: ; 3edd8 ; If the normal RNG is used in a link battle it'll desync. ; To circumvent this a shared PRNG is used instead. ; But if we're in a non-link battle we're safe to use it ld a, [wLinkMode] and a jp z, Random ; The PRNG operates in streams of 10 values. ; Which value are we trying to pull? push hl push bc ld a, [LinkBattleRNCount] ld c, a ld b, 0 ld hl, LinkBattleRNs add hl, bc inc a ld [LinkBattleRNCount], a ; If we haven't hit the end yet, we're good cp 10 - 1 ; Exclude last value. See the closing comment ld a, [hl] pop bc pop hl ret c ; If we have, we have to generate new pseudorandom data ; Instead of having multiple PRNGs, ten seeds are used push hl push bc push af ; Reset count to 0 xor a ld [LinkBattleRNCount], a ld hl, LinkBattleRNs ld b, 10 ; number of seeds ; Generate next number in the sequence for each seed ; The algorithm takes the form *5 + 1 % 256 .loop ; get last # ld a, [hl] ; a * 5 + 1 ld c, a add a add a add c inc a ; update # ld [hli], a dec b jr nz, .loop ; This has the side effect of pulling the last value first, ; then wrapping around. As a result, when we check to see if ; we've reached the end, we check the one before it. pop af pop bc pop hl ret ; 3ee0f Call_PlayBattleAnim_OnlyIfVisible: ; 3ee0f ld a, BATTLE_VARS_SUBSTATUS3 call GetBattleVar and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND ret nz ; 3ee17 Call_PlayBattleAnim: ; 3ee17 ld a, e ld [FXAnimID], a ld a, d ld [FXAnimID + 1], a call WaitBGMap predef_jump PlayBattleAnim ; 3ee27 FinishBattleAnim: ; 3ee27 push af push bc push de push hl ld b, SCGB_BATTLE_COLORS call GetSGBLayout call SetPalettes call DelayFrame pop hl pop de pop bc pop af ret ; 3ee3b GiveExperiencePoints: ; 3ee3b ; Give experience. ; Don't give experience if linked or in the Battle Tower. ld a, [wLinkMode] and a ret nz ld a, [InBattleTowerBattle] bit 0, a ret nz call .EvenlyDivideExpAmongParticipants xor a ld [CurPartyMon], a ld bc, PartyMon1Species .loop ld hl, MON_HP add hl, bc ld a, [hli] or [hl] jp z, .skip_stats ; fainted push bc ld hl, wBattleParticipantsNotFainted ld a, [CurPartyMon] ld c, a ld b, CHECK_FLAG ld d, $0 predef FlagPredef ld a, c and a pop bc jp z, .skip_stats ; give stat exp ld hl, MON_STAT_EXP + 1 add hl, bc ld d, h ld e, l ld hl, EnemyMonBaseStats - 1 push bc ld c, $5 .loop1 inc hl ld a, [de] add [hl] ld [de], a jr nc, .okay1 dec de ld a, [de] inc a jr z, .next ld [de], a inc de .okay1 push hl push bc ld a, MON_PKRUS call GetPartyParamLocation ld a, [hl] and a pop bc pop hl jr z, .skip ld a, [de] add [hl] ld [de], a jr nc, .skip dec de ld a, [de] inc a jr z, .next ld [de], a inc de jr .skip .next ld a, $ff ld [de], a inc de ld [de], a .skip inc de inc de dec c jr nz, .loop1 xor a ld [hMultiplicand + 0], a ld [hMultiplicand + 1], a ld a, [EnemyMonBaseExp] ld [hMultiplicand + 2], a ld a, [EnemyMonLevel] ld [hMultiplier], a call Multiply ld a, 7 ld [hDivisor], a ld b, 4 call Divide ; Boost Experience for traded Pokemon pop bc ld hl, MON_ID add hl, bc ld a, [PlayerID] cp [hl] jr nz, .boosted inc hl ld a, [PlayerID + 1] cp [hl] ld a, $0 jr z, .no_boost .boosted call BoostExp ld a, $1 .no_boost ; Boost experience for a Trainer Battle ld [StringBuffer2 + 2], a ld a, [wBattleMode] dec a call nz, BoostExp ; Boost experience for Lucky Egg push bc ld a, MON_ITEM call GetPartyParamLocation ld a, [hl] cp LUCKY_EGG call z, BoostExp ld a, [hQuotient + 2] ld [StringBuffer2 + 1], a ld a, [hQuotient + 1] ld [StringBuffer2], a ld a, [CurPartyMon] ld hl, PartyMonNicknames call GetNick ld hl, Text_PkmnGainedExpPoint call BattleTextBox ld a, [StringBuffer2 + 1] ld [hQuotient + 2], a ld a, [StringBuffer2] ld [hQuotient + 1], a pop bc call AnimateExpBar push bc call LoadTileMapToTempTileMap pop bc ld hl, MON_STAT_EXP - 1 add hl, bc ld d, [hl] ld a, [hQuotient + 2] add d ld [hld], a ld d, [hl] ld a, [hQuotient + 1] adc d ld [hl], a jr nc, .skip2 dec hl inc [hl] jr nz, .skip2 ld a, $ff ld [hli], a ld [hli], a ld [hl], a .skip2 ld a, [CurPartyMon] ld e, a ld d, $0 ld hl, PartySpecies add hl, de ld a, [hl] ld [CurSpecies], a call GetBaseData push bc ld d, MAX_LEVEL callab CalcExpAtLevel pop bc ld hl, MON_STAT_EXP - 1 add hl, bc push bc ld a, [hQuotient] ld b, a ld a, [hQuotient + 1] ld c, a ld a, [hQuotient + 2] ld d, a ld a, [hld] sub d ld a, [hld] sbc c ld a, [hl] sbc b jr c, .not_max_exp ld a, b ld [hli], a ld a, c ld [hli], a ld a, d ld [hld], a .not_max_exp xor a ; PARTYMON ld [MonType], a predef CopyPkmnToTempMon callab CalcLevel pop bc ld hl, MON_LEVEL add hl, bc ld a, [hl] cp MAX_LEVEL jp nc, .skip_stats cp d jp z, .skip_stats ; grew to level ##! ld [wTempLevel], a ld a, [CurPartyLevel] push af ld a, d ld [CurPartyLevel], a ld [hl], a ld hl, MON_SPECIES add hl, bc ld a, [hl] ld [CurSpecies], a ld [wd265], a call GetBaseData ld hl, MON_MAXHP + 1 add hl, bc ld a, [hld] ld e, a ld d, [hl] push de ld hl, MON_MAXHP add hl, bc ld d, h ld e, l ld hl, MON_STAT_EXP - 1 add hl, bc push bc ld b, TRUE predef CalcPkmnStats pop bc pop de ld hl, MON_MAXHP + 1 add hl, bc ld a, [hld] sub e ld e, a ld a, [hl] sbc d ld d, a dec hl ld a, [hl] add e ld [hld], a ld a, [hl] adc d ld [hl], a ld a, [CurBattleMon] ld d, a ld a, [CurPartyMon] cp d jr nz, .skip_animation ld de, BattleMonHP ld a, [hli] ld [de], a inc de ld a, [hli] ld [de], a ld de, BattleMonMaxHP push bc ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP call CopyBytes pop bc ld hl, MON_LEVEL add hl, bc ld a, [hl] ld [BattleMonLevel], a ld a, [PlayerSubStatus5] bit SUBSTATUS_TRANSFORMED, a jr nz, .transformed ld hl, MON_ATK add hl, bc ld de, PlayerStats ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK call CopyBytes .transformed xor a ld [wd265], a call ApplyStatLevelMultiplierOnAllStats callab ApplyStatusEffectOnPlayerStats callab BadgeStatBoosts callab UpdatePlayerHUD call EmptyBattleTextBox call LoadTileMapToTempTileMap ld a, $1 ld [hBGMapMode], a .skip_animation callba LevelUpHappinessMod ld a, [CurBattleMon] ld b, a ld a, [CurPartyMon] cp b jr z, .skip_animation2 ld de, SFX_HIT_END_OF_EXP_BAR call PlaySFX call WaitSFX ld hl, BattleText_StringBuffer1GrewToLevel call StdBattleTextBox call LoadTileMapToTempTileMap .skip_animation2 xor a ; PARTYMON ld [MonType], a predef CopyPkmnToTempMon hlcoord 9, 0 ld b, $a ld c, $9 call TextBox hlcoord 11, 1 ld bc, 4 predef PrintTempMonStats ld c, $1e call DelayFrames call WaitPressAorB_BlinkCursor call Call_LoadTempTileMapToTileMap xor a ; PARTYMON ld [MonType], a ld a, [CurSpecies] ld [wd265], a ld a, [CurPartyLevel] push af ld c, a ld a, [wTempLevel] ld b, a .level_loop inc b ld a, b ld [CurPartyLevel], a push bc predef LearnLevelMoves pop bc ld a, b cp c jr nz, .level_loop pop af ld [CurPartyLevel], a ld hl, EvolvableFlags ld a, [CurPartyMon] ld c, a ld b, SET_FLAG predef FlagPredef pop af ld [CurPartyLevel], a .skip_stats ld a, [PartyCount] ld b, a ld a, [CurPartyMon] inc a cp b jr z, .done ld [CurPartyMon], a ld a, MON_SPECIES call GetPartyParamLocation ld b, h ld c, l jp .loop .done jp ResetBattleParticipants ; 3f0d4 .EvenlyDivideExpAmongParticipants: ; count number of battle participants ld a, [wBattleParticipantsNotFainted] ld b, a ld c, PARTY_LENGTH ld d, 0 .count_loop xor a srl b adc d ld d, a dec c jr nz, .count_loop cp 2 ret c ld [wd265], a ld hl, EnemyMonBaseStats ld c, EnemyMonEnd - EnemyMonBaseStats .count_loop2 xor a ld [hDividend + 0], a ld a, [hl] ld [hDividend + 1], a ld a, [wd265] ld [hDivisor], a ld b, 2 call Divide ld a, [hQuotient + 2] ld [hli], a dec c jr nz, .count_loop2 ret ; 3f106 BoostExp: ; 3f106 ; Multiply experience by 1.5x push bc ; load experience value ld a, [hProduct + 2] ld b, a ld a, [hProduct + 3] ld c, a ; halve it srl b rr c ; add it back to the whole exp value add c ld [hProduct + 3], a ld a, [hProduct + 2] adc b ld [hProduct + 2], a pop bc ret ; 3f11b Text_PkmnGainedExpPoint: ; 3f11b text_jump Text_Gained start_asm ld hl, TextJump_StringBuffer2ExpPoints ld a, [StringBuffer2 + 2] ; IsTradedMon and a ret z ld hl, TextJump_ABoostedStringBuffer2ExpPoints ret ; 3f12c TextJump_ABoostedStringBuffer2ExpPoints: ; 3f12c text_jump Text_ABoostedStringBuffer2ExpPoints db "@" ; 3f131 TextJump_StringBuffer2ExpPoints: ; 3f131 text_jump Text_StringBuffer2ExpPoints db "@" ; 3f136 AnimateExpBar: ; 3f136 push bc ld hl, CurPartyMon ld a, [CurBattleMon] cp [hl] jp nz, .finish ld a, [BattleMonLevel] cp MAX_LEVEL jp nc, .finish ld a, [hProduct + 3] ld [wd004], a push af ld a, [hProduct + 2] ld [wd003], a push af xor a ld [wd002], a xor a ; PARTYMON ld [MonType], a predef CopyPkmnToTempMon ld a, [TempMonLevel] ld b, a ld e, a push de ld de, TempMonExp + 2 call CalcExpBar push bc ld hl, TempMonExp + 2 ld a, [wd004] add [hl] ld [hld], a ld a, [wd003] adc [hl] ld [hld], a jr nc, .NoOverflow inc [hl] jr nz, .NoOverflow ld a, $ff ld [hli], a ld [hli], a ld [hl], a .NoOverflow: ld d, MAX_LEVEL callab CalcExpAtLevel ld a, [hProduct + 1] ld b, a ld a, [hProduct + 2] ld c, a ld a, [hProduct + 3] ld d, a ld hl, TempMonExp + 2 ld a, [hld] sub d ld a, [hld] sbc c ld a, [hl] sbc b jr c, .AlreadyAtMaxExp ld a, b ld [hli], a ld a, c ld [hli], a ld a, d ld [hld], a .AlreadyAtMaxExp: callab CalcLevel ld a, d pop bc pop de ld d, a cp e jr nc, .LoopLevels ld a, e ld d, a .LoopLevels: ld a, e cp MAX_LEVEL jr nc, .FinishExpBar cp d jr z, .FinishExpBar inc a ld [TempMonLevel], a ld [CurPartyLevel], a ld [BattleMonLevel], a push de call .PlayExpBarSound ld c, $40 call .LoopBarAnimation call PrintPlayerHUD ld hl, BattleMonNick ld de, StringBuffer1 ld bc, PKMN_NAME_LENGTH call CopyBytes call TerminateExpBarSound ld de, SFX_HIT_END_OF_EXP_BAR call PlaySFX callba AnimateEndOfExpBar call WaitSFX ld hl, BattleText_StringBuffer1GrewToLevel call StdBattleTextBox pop de inc e ld b, $0 jr .LoopLevels .FinishExpBar: push bc ld b, d ld de, TempMonExp + 2 call CalcExpBar ld a, b pop bc ld c, a call .PlayExpBarSound call .LoopBarAnimation call TerminateExpBarSound pop af ld [hProduct + 2], a pop af ld [hProduct + 3], a .finish pop bc ret .PlayExpBarSound: push bc call WaitSFX ld de, SFX_EXP_BAR call PlaySFX ld c, 10 call DelayFrames pop bc ret .LoopBarAnimation: ld d, 3 dec b .anim_loop inc b push bc push de hlcoord 17, 11 call PlaceExpBar pop de ld a, $1 ld [hBGMapMode], a ld c, d call DelayFrames xor a ld [hBGMapMode], a pop bc ld a, c cp b jr z, .end_animation inc b push bc push de hlcoord 17, 11 call PlaceExpBar pop de ld a, $1 ld [hBGMapMode], a ld c, d call DelayFrames xor a ld [hBGMapMode], a dec d jr nz, .min_number_of_frames ld d, 1 .min_number_of_frames pop bc ld a, c cp b jr nz, .anim_loop .end_animation ld a, $1 ld [hBGMapMode], a ret SendOutPkmnText: ; 3f26d ld a, [wLinkMode] and a jr z, .not_linked ld hl, JumpText_GoPkmn ; If we're in a LinkBattle print just "Go " ld a, [wBattleHasJustStarted] ; unless this (unidentified) variable is set and a jr nz, .skip_to_textbox .not_linked ; Depending on the HP of the enemy Pkmn, the game prints a different text ld hl, EnemyMonHP ld a, [hli] or [hl] ld hl, JumpText_GoPkmn jr z, .skip_to_textbox ; compute enemy helth remaining as a percentage xor a ld [hMultiplicand + 0], a ld hl, EnemyMonHP ld a, [hli] ld [wEnemyHPAtTimeOfPlayerSwitch], a ld [hMultiplicand + 1], a ld a, [hl] ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a ld [hMultiplicand + 2], a ld a, 25 ld [hMultiplier], a call Multiply ld hl, EnemyMonMaxHP ld a, [hli] ld b, [hl] srl a rr b srl a rr b ld a, b ld b, 4 ld [hDivisor], a call Divide ld a, [hQuotient + 2] ld hl, JumpText_GoPkmn cp 70 jr nc, .skip_to_textbox ld hl, JumpText_DoItPkmn cp 40 jr nc, .skip_to_textbox ld hl, JumpText_GoForItPkmn cp 10 jr nc, .skip_to_textbox ld hl, JumpText_YourFoesWeakGetmPkmn .skip_to_textbox jp BattleTextBox ; 3f2d1 JumpText_GoPkmn: ; 3f2d1 text_jump Text_GoPkmn start_asm jr Function_TextJump_BattleMonNick01 ; 3f2d6 JumpText_DoItPkmn: ; 3f2d8 text_jump Text_DoItPkmn start_asm jr Function_TextJump_BattleMonNick01 ; 3f2dd JumpText_GoForItPkmn: ; 3f2df text_jump Text_GoForItPkmn start_asm jr Function_TextJump_BattleMonNick01 ; 3f2e4 JumpText_YourFoesWeakGetmPkmn: ; 3f2e6 text_jump Text_YourFoesWeakGetmPkmn start_asm Function_TextJump_BattleMonNick01: ; 3f2eb ld hl, TextJump_BattleMonNick01 ret ; 3f2ef TextJump_BattleMonNick01: ; 3f2ef text_jump Text_BattleMonNick01 db "@" ; 3f2f4 WithdrawPkmnText: ; 3f2f4 ld hl, .WithdrawPkmnText jp BattleTextBox .WithdrawPkmnText: text_jump Text_BattleMonNickComma start_asm ; Print text to withdraw Pkmn ; depending on HP the message is different push de push bc ld hl, EnemyMonHP + 1 ld de, wEnemyHPAtTimeOfPlayerSwitch + 1 ld b, [hl] dec hl ld a, [de] sub b ld [hMultiplicand + 2], a dec de ld b, [hl] ld a, [de] sbc b ld [hMultiplicand + 1], a ld a, 25 ld [hMultiplier], a call Multiply ld hl, EnemyMonMaxHP ld a, [hli] ld b, [hl] srl a rr b srl a rr b ld a, b ld b, 4 ld [hDivisor], a call Divide pop bc pop de ld a, [hQuotient + 2] ld hl, TextJump_ThatsEnoughComeBack and a ret z ld hl, TextJump_ComeBack cp 30 ret c ld hl, TextJump_OKComeBack cp 70 ret c ld hl, TextJump_GoodComeBack ret ; 3f348 TextJump_ThatsEnoughComeBack: ; 3f348 text_jump Text_ThatsEnoughComeBack db "@" ; 3f34d TextJump_OKComeBack: ; 3f34d text_jump Text_OKComeBack db "@" ; 3f352 TextJump_GoodComeBack: ; 3f352 text_jump Text_GoodComeBack db "@" ; 3f357 UnusedFunction_TextJump_ComeBack: ; 3f357 ; this function doesn't seem to be used ld hl, TextJump_ComeBack ret ; 3f35b TextJump_ComeBack: ; 3f35b text_jump Text_ComeBack db "@" ; 3f360 HandleSafariAngerEatingStatus: ; unreferenced ld hl, wSafariMonEating ld a, [hl] and a jr z, .angry dec [hl] ld hl, BattleText_WildPkmnIsEating jr .finish .angry dec hl ; wSafariMonAngerCount ld a, [hl] and a ret z dec [hl] ld hl, BattleText_WildPkmnIsAngry jr nz, .finish push hl ld a, [EnemyMonSpecies] ld [CurSpecies], a call GetBaseData ld a, [BaseCatchRate] ld [EnemyMonCatchRate], a pop hl .finish push hl call Call_LoadTempTileMapToTileMap pop hl jp StdBattleTextBox ; 3f390 FillInExpBar: ; 3f390 push hl call CalcExpBar pop hl ld de, 7 add hl, de jp PlaceExpBar ; 3f39c CalcExpBar: ; 3f39c ; Calculate the percent exp between this level and the next ; Level in b push de ld d, b push de callab CalcExpAtLevel pop de ; exp at current level gets pushed to the stack ld hl, hMultiplicand ld a, [hli] push af ld a, [hli] push af ld a, [hl] push af ; next level inc d callab CalcExpAtLevel ; back up the next level exp, and subtract the two levels ld hl, hMultiplicand + 2 ld a, [hl] ld [hMathBuffer + 2], a pop bc sub b ld [hld], a ld a, [hl] ld [hMathBuffer + 1], a pop bc sbc b ld [hld], a ld a, [hl] ld [hMathBuffer], a pop bc sbc b ld [hl], a pop de ld hl, hMultiplicand + 1 ld a, [hli] push af ld a, [hl] push af ; get the amount of exp remaining to the next level ld a, [de] dec de ld c, a ld a, [hMathBuffer + 2] sub c ld [hld], a ld a, [de] dec de ld b, a ld a, [hMathBuffer + 1] sbc b ld [hld], a ld a, [de] ld c, a ld a, [hMathBuffer] sbc c ld [hld], a xor a ld [hl], a ; multiply by 64 ld a, $40 ld [hMultiplier], a call Multiply pop af ld c, a pop af ld b, a .loop ld a, b and a jr z, .done srl b rr c ld hl, hProduct srl [hl] inc hl rr [hl] inc hl rr [hl] inc hl rr [hl] jr .loop .done ld a, c ld [hDivisor], a ld b, 4 call Divide ld a, [hQuotient + 2] ld b, a ld a, $40 sub b ld b, a ret ; 3f41c PlaceExpBar: ; 3f41c ld c, $8 ; number of tiles .loop1 ld a, b sub $8 jr c, .next ld b, a ld a, $6a ; full bar ld [hld], a dec c jr z, .finish jr .loop1 .next add $8 jr z, .loop2 add $54 ; tile to the left of small exp bar tile jr .skip .loop2 ld a, $62 ; empty bar .skip ld [hld], a ld a, $62 ; empty bar dec c jr nz, .loop2 .finish ret ; 3f43d GetMonBackpic: ; 3f43d ld a, [PlayerSubStatus4] bit SUBSTATUS_SUBSTITUTE, a ld hl, BattleAnimCmd_RaiseSub jr nz, GetBackpic_DoAnim ; substitute DropPlayerSub: ; 3f447 ld a, [wPlayerMinimized] and a ld hl, BattleAnimCmd_MinimizeOpp jr nz, GetBackpic_DoAnim ld a, [CurPartySpecies] push af ld a, [BattleMonSpecies] ld [CurPartySpecies], a ld hl, BattleMonDVs predef GetUnownLetter ld de, VTiles2 tile $31 predef GetBackpic pop af ld [CurPartySpecies], a ret ; 3f46f GetBackpic_DoAnim: ; 3f46f ld a, [hBattleTurn] push af xor a ld [hBattleTurn], a ld a, BANK(BattleAnimCommands) rst FarCall pop af ld [hBattleTurn], a ret ; 3f47c GetMonFrontpic: ; 3f47c ld a, [EnemySubStatus4] bit SUBSTATUS_SUBSTITUTE, a ld hl, BattleAnimCmd_RaiseSub jr nz, GetFrontpic_DoAnim DropEnemySub: ; 3f486 ld a, [wEnemyMinimized] and a ld hl, BattleAnimCmd_MinimizeOpp jr nz, GetFrontpic_DoAnim ld a, [CurPartySpecies] push af ld a, [EnemyMonSpecies] ld [CurSpecies], a ld [CurPartySpecies], a call GetBaseData ld hl, EnemyMonDVs predef GetUnownLetter ld de, VTiles2 predef FrontpicPredef pop af ld [CurPartySpecies], a ret ; 3f4b4 GetFrontpic_DoAnim: ; 3f4b4 ld a, [hBattleTurn] push af call SetEnemyTurn ld a, BANK(BattleAnimCommands) rst FarCall pop af ld [hBattleTurn], a ret ; 3f4c1 StartBattle: ; 3f4c1 ; This check prevents you from entering a battle without any Pokemon. ; Those using walk-through-walls to bypass getting a Pokemon experience ; the effects of this check. ld a, [PartyCount] and a ret z ld a, [TimeOfDayPal] push af call BattleIntro call DoBattle call ExitBattle pop af ld [TimeOfDayPal], a scf ret ; 3f4d9 _DoBattle: ; 3f4d9 ; unreferenced call DoBattle ret ; 3f4dd BattleIntro: ; 3f4dd callba TrainerRankings_Battles ; mobile call LoadTrainerOrWildMonPic xor a ld [TempBattleMonSpecies], a ld [wBattleMenuCursorBuffer], a xor a ld [hMapAnims], a callba PlayBattleMusic callba ShowLinkBattleParticipants callba FindFirstAliveMonAndStartBattle call DisableSpriteUpdates callba ClearBattleRAM call InitEnemy call BackUpVBGMap2 ld b, SCGB_BATTLE_GRAYSCALE call GetSGBLayout ld hl, rLCDC res 6, [hl] call InitBattleDisplay call BattleStartMessage ld hl, rLCDC set 6, [hl] xor a ld [hBGMapMode], a call EmptyBattleTextBox hlcoord 9, 7 lb bc, 5, 11 call ClearBox hlcoord 1, 0 lb bc, 4, 10 call ClearBox call ClearSprites ld a, [wBattleMode] cp WILD_BATTLE call z, UpdateEnemyHUD ld a, $1 ld [hBGMapMode], a ret ; 3f54e LoadTrainerOrWildMonPic: ; 3f54e ld a, [OtherTrainerClass] and a jr nz, .Trainer ld a, [TempWildMonSpecies] ld [CurPartySpecies], a .Trainer: ld [TempEnemyMonSpecies], a ret ; 3f55e InitEnemy: ; 3f55e ld a, [OtherTrainerClass] and a jp nz, InitEnemyTrainer ; trainer jp InitEnemyWildmon ; wild ; 3f568 BackUpVBGMap2: ; 3f568 ld a, [rSVBK] push af ld a, $6 ; BANK(wDecompressScratch) ld [rSVBK], a ld hl, wDecompressScratch ld bc, $40 tiles ; VBGMap3 - VBGMap2 ld a, $2 call ByteFill ld a, [rVBK] push af ld a, $1 ld [rVBK], a ld de, wDecompressScratch hlbgcoord 0, 0 ; VBGMap2 lb bc, BANK(BackUpVBGMap2), $40 call Request2bpp pop af ld [rVBK], a pop af ld [rSVBK], a ret ; 3f594 InitEnemyTrainer: ; 3f594 ld [TrainerClass], a callba TrainerRankings_TrainerBattles xor a ld [TempEnemyMonSpecies], a callab GetTrainerAttributes callab ReadTrainerParty ld a, [TrainerClass] cp RIVAL1 jr nz, .ok xor a ld [OTPartyMon1Item], a .ok ld de, VTiles2 callab GetTrainerPic xor a ld [hGraphicStartTile], a dec a ld [wEnemyItemState], a hlcoord 12, 0 lb bc, 7, 7 predef PlaceGraphic ld a, -1 ld [CurOTMon], a ld a, TRAINER_BATTLE ld [wBattleMode], a call IsJohtoGymLeader jr nc, .done xor a ld [CurPartyMon], a ld a, [PartyCount] ld b, a .partyloop push bc ld a, MON_HP call GetPartyParamLocation ld a, [hli] or [hl] jr z, .skipfaintedmon ld c, HAPPINESS_GYMBATTLE callab ChangeHappiness .skipfaintedmon pop bc dec b jr z, .done ld hl, CurPartyMon inc [hl] jr .partyloop .done ret ; 3f607 InitEnemyWildmon: ; 3f607 ld a, WILD_BATTLE ld [wBattleMode], a callba TrainerRankings_WildBattles call LoadEnemyMon ld hl, EnemyMonMoves ld de, wWildMonMoves ld bc, NUM_MOVES call CopyBytes ld hl, EnemyMonPP ld de, wWildMonPP ld bc, NUM_MOVES call CopyBytes ld hl, EnemyMonDVs predef GetUnownLetter ld a, [CurPartySpecies] cp UNOWN jr nz, .skip_unown ld a, [wFirstUnownSeen] and a jr nz, .skip_unown ld a, [UnownLetter] ld [wFirstUnownSeen], a .skip_unown ld de, VTiles2 predef FrontpicPredef xor a ld [TrainerClass], a ld [hGraphicStartTile], a hlcoord 12, 0 lb bc, 7, 7 predef PlaceGraphic ret ; 3f662 Function3f662: ; 3f662 ; XXX ld hl, EnemyMonMoves ld de, wListMoves_MoveIndicesBuffer ld b, NUM_MOVES .loop ld a, [de] inc de ld [hli], a and a jr z, .clearpp push bc push hl push hl dec a ld hl, Moves + MOVE_PP ld bc, MOVE_LENGTH call AddNTimes ld a, BANK(Moves) call GetFarByte pop hl ld bc, EnemyMonPP - (EnemyMonMoves + 1) add hl, bc ld [hl], a pop hl pop bc dec b jr nz, .loop ret .clear xor a ld [hli], a .clearpp push bc push hl ld bc, EnemyMonPP - (EnemyMonMoves + 1) add hl, bc xor a ld [hl], a pop hl pop bc dec b jr nz, .clear ret ; 3f69e ExitBattle: ; 3f69e call .HandleEndOfBattle call CleanUpBattleRAM ret ; 3f6a5 .HandleEndOfBattle: ; 3f6a5 ld a, [wLinkMode] and a jr z, .not_linked call ShowLinkBattleParticipantsAfterEnd ld c, 150 call DelayFrames call DisplayLinkBattleResult ret .not_linked ld a, [wBattleResult] and $f ret nz call CheckPayDay xor a ld [wForceEvolution], a predef EvolveAfterBattle callba GivePokerusAndConvertBerries ret ; 3f6d0 CleanUpBattleRAM: ; 3f6d0 call BattleEnd_HandleRoamMons xor a ld [Danger], a ld [wBattleMode], a ld [BattleType], a ld [AttackMissed], a ld [TempWildMonSpecies], a ld [OtherTrainerClass], a ld [wFailedToFlee], a ld [wNumFleeAttempts], a ld [wForcedSwitch], a ld [wPartyMenuCursor], a ld [wKeyItemsPocketCursor], a ld [wItemsPocketCursor], a ld [wBattleMenuCursorBuffer], a ld [CurMoveNum], a ld [wBallsPocketCursor], a ld [wLastPocket], a ld [wMenuScrollPosition], a ld [wKeyItemsPocketScrollPosition], a ld [wItemsPocketScrollPosition], a ld [wBallsPocketScrollPosition], a ld hl, PlayerSubStatus1 ld b, EnemyFuryCutterCount - PlayerSubStatus1 .loop ld [hli], a dec b jr nz, .loop call WaitSFX ret ; 3f71d CheckPayDay: ; 3f71d ld hl, wPayDayMoney ld a, [hli] or [hl] inc hl or [hl] ret z ld a, [wAmuletCoin] and a jr z, .okay ld hl, wPayDayMoney + 2 sla [hl] dec hl rl [hl] dec hl rl [hl] jr nc, .okay ld a, $ff ld [hli], a ld [hli], a ld [hl], a .okay ld hl, wPayDayMoney + 2 ld de, Money + 2 call AddBattleMoneyToAccount ld hl, BattleText_PlayerPickedUpPayDayMoney call StdBattleTextBox ld a, [InBattleTowerBattle] bit 0, a ret z call ClearTileMap call ClearBGPalettes ret ; 3f759 ShowLinkBattleParticipantsAfterEnd: ; 3f759 callba TrainerRankings_LinkBattles callba BackupMobileEventIndex ld a, [CurOTMon] ld hl, OTPartyMon1Status call GetPartyLocation ld a, [EnemyMonStatus] ld [hl], a call ClearTileMap callba _ShowLinkBattleParticipants ret ; 3f77c DisplayLinkBattleResult: ; 3f77c callba CheckMobileBattleError jp c, .Mobile_InvalidBattle call IsMobileBattle2 jr nz, .proceed ld hl, wcd2a bit 4, [hl] jr z, .proceed callba DetermineLinkBattleResult .proceed ld a, [wBattleResult] and $f cp $1 jr c, .victory jr z, .loss callba TrainerRankings_ColosseumDraws ld de, .Draw jr .store_result .victory callba TrainerRankings_ColosseumWins ld de, .Win jr .store_result .loss callba TrainerRankings_ColosseumLosses ld de, .Lose jr .store_result .store_result hlcoord 6, 8 call PlaceString callba BackupMobileEventIndex ld c, 200 call DelayFrames ld a, BANK(sLinkBattleStats) call GetSRAMBank call AddLastMobileBattleToLinkRecord call ReadAndPrintLinkBattleRecord call CloseSRAM call IsMobileBattle2 jr z, .mobile call WaitPressAorB_BlinkCursor call ClearTileMap ret .mobile ld c, 200 call DelayFrames call ClearTileMap ret ; 3f7f7 .Win: db "YOU WIN@" .Lose: db "YOU LOSE@" .Draw: db " DRAW@" ; 3f80f .Mobile_InvalidBattle: ; 3f80f hlcoord 6, 8 ld de, .Invalid call PlaceString ld c, 200 call DelayFrames call ClearTileMap ret ; 3f821 .Invalid: db "INVALID BATTLE@" ; 3f830 IsMobileBattle2: ; 3f830 ld a, [wLinkMode] cp LINK_MOBILE ret ; 3f836 DisplayLinkRecord: ; 3f836 ld a, BANK(sLinkBattleStats) call GetSRAMBank call ReadAndPrintLinkBattleRecord call CloseSRAM hlcoord 0, 0, AttrMap xor a ld bc, SCREEN_WIDTH * SCREEN_HEIGHT call ByteFill call WaitBGMap2 ld b, SCGB_DIPLOMA call GetSGBLayout call SetPalettes ld c, 8 call DelayFrames call WaitPressAorB_BlinkCursor ret ; 3f85f ReadAndPrintLinkBattleRecord: ; 3f85f call ClearTileMap call ClearSprites call .PrintBattleRecord hlcoord 0, 8 ld b, 5 ld de, sLinkBattleRecord + 2 .loop push bc push hl push de ld a, [de] and a jr z, .PrintFormatString ld a, [wSavedAtLeastOnce] and a jr z, .PrintFormatString push hl push hl ld h, d ld l, e ld de, wd002 ld bc, 10 call CopyBytes ld a, "@" ld [de], a inc de ld bc, 6 call CopyBytes ld de, wd002 pop hl call PlaceString pop hl ld de, 26 add hl, de push hl ld de, wd00d lb bc, 2, 4 call PrintNum pop hl ld de, 5 add hl, de push hl ld de, wd00f lb bc, 2, 4 call PrintNum pop hl ld de, 5 add hl, de ld de, wd011 lb bc, 2, 4 call PrintNum jr .next .PrintFormatString: ld de, .Format call PlaceString .next pop hl ld bc, 18 add hl, bc ld d, h ld e, l pop hl ld bc, 2 * SCREEN_WIDTH add hl, bc pop bc dec b jr nz, .loop ret .PrintBattleRecord: hlcoord 1, 0 ld de, .Record call PlaceString hlcoord 0, 6 ld de, .Result call PlaceString hlcoord 0, 2 ld de, .Total call PlaceString hlcoord 6, 4 ld de, sLinkBattleWins call .PrintZerosIfNoSaveFileExists jr c, .quit lb bc, 2, 4 call PrintNum hlcoord 11, 4 ld de, sLinkBattleLosses call .PrintZerosIfNoSaveFileExists lb bc, 2, 4 call PrintNum hlcoord 16, 4 ld de, sLinkBattleDraws call .PrintZerosIfNoSaveFileExists lb bc, 2, 4 call PrintNum .quit ret .PrintZerosIfNoSaveFileExists: ld a, [wSavedAtLeastOnce] and a ret nz ld de, .Scores call PlaceString scf ret ; 3f938 .Scores: db " 0 0 0@" ; 3f947 .Format: ; 3f947 db " --- " db " - - -@" .Record: ; 3f964 db "'s RECORD@" .Result: ; 3f96e db "RESULT WIN LOSE DRAW@" .Total: ; 3f983 db "TOTAL WIN LOSE DRAW@" ; 3f998 BattleEnd_HandleRoamMons: ; 3f998 ld a, [BattleType] cp BATTLETYPE_ROAMING jr nz, .not_roaming ld a, [wBattleResult] and $f jr z, .caught_or_defeated_roam_mon call GetRoamMonHP ld a, [EnemyMonHP + 1] ld [hl], a jr .update_roam_mons .caught_or_defeated_roam_mon call GetRoamMonHP ld [hl], $0 call GetRoamMonMapGroup ld [hl], $ff call GetRoamMonMapNumber ld [hl], $ff call GetRoamMonSpecies ld [hl], $0 ret .not_roaming call BattleRandom and $f ret nz .update_roam_mons callab UpdateRoamMons ret ; 3f9d1 GetRoamMonMapGroup: ; 3f9d1 ld a, [TempEnemyMonSpecies] ld b, a ld a, [wRoamMon1Species] cp b ld hl, wRoamMon1MapGroup ret z ld a, [wRoamMon2Species] cp b ld hl, wRoamMon2MapGroup ret z ld hl, wRoamMon3MapGroup ret ; 3f9e9 GetRoamMonMapNumber: ; 3f9e9 ld a, [TempEnemyMonSpecies] ld b, a ld a, [wRoamMon1Species] cp b ld hl, wRoamMon1MapNumber ret z ld a, [wRoamMon2Species] cp b ld hl, wRoamMon2MapNumber ret z ld hl, wRoamMon3MapNumber ret ; 3fa01 GetRoamMonHP: ; 3fa01 ; output: hl = wRoamMonHP ld a, [TempEnemyMonSpecies] ld b, a ld a, [wRoamMon1Species] cp b ld hl, wRoamMon1HP ret z ld a, [wRoamMon2Species] cp b ld hl, wRoamMon2HP ret z ld hl, wRoamMon3HP ret ; 3fa19 GetRoamMonDVs: ; 3fa19 ; output: hl = wRoamMonDVs ld a, [TempEnemyMonSpecies] ld b, a ld a, [wRoamMon1Species] cp b ld hl, wRoamMon1DVs ret z ld a, [wRoamMon2Species] cp b ld hl, wRoamMon2DVs ret z ld hl, wRoamMon3DVs ret ; 3fa31 GetRoamMonSpecies: ; 3fa31 ld a, [TempEnemyMonSpecies] ld hl, wRoamMon1Species cp [hl] ret z ld hl, wRoamMon2Species cp [hl] ret z ld hl, wRoamMon3Species ret ; 3fa42 AddLastMobileBattleToLinkRecord: ; 3fa42 ld hl, OTPlayerID ld de, StringBuffer1 ld bc, 2 call CopyBytes ld hl, OTPlayerName ld bc, NAME_LENGTH - 1 call CopyBytes ld hl, sLinkBattleResults call .StoreResult ld hl, sLinkBattleRecord ld d, 5 .loop push hl inc hl inc hl ld a, [hl] dec hl dec hl and a jr z, .copy push de ld bc, 12 ld de, StringBuffer1 call CompareLong pop de pop hl jr c, .done ld bc, 18 add hl, bc dec d jr nz, .loop ld bc, -18 add hl, bc push hl .copy ld d, h ld e, l ld hl, StringBuffer1 ld bc, 12 call CopyBytes ld b, 6 xor a .loop2 ld [de], a inc de dec b jr nz, .loop2 pop hl .done call .StoreResult call .FindOpponentAndAppendRecord ret ; 3faa0 .StoreResult: ; 3faa0 ld a, [wBattleResult] and $f cp $1 ld bc, sLinkBattleWins + 1 - sLinkBattleResults jr c, .okay ld bc, sLinkBattleLosses + 1 - sLinkBattleResults jr z, .okay ld bc, sLinkBattleDraws + 1 - sLinkBattleResults .okay add hl, bc call .CheckOverflow ret nc inc [hl] ret nz dec hl inc [hl] ret ; 3fabe .CheckOverflow: ; 3fabe dec hl ld a, [hl] inc hl cp 9999 / $100 ret c ld a, [hl] cp 9999 % $100 ret ; 3fac8 .FindOpponentAndAppendRecord: ; 3fac8 ld b, 5 ld hl, sLinkBattleRecord + 17 ld de, wd002 .loop3 push bc push de push hl call .LoadPointer pop hl ld a, e pop de ld [de], a inc de ld a, b ld [de], a inc de ld a, c ld [de], a inc de ld bc, 18 add hl, bc pop bc dec b jr nz, .loop3 ld b, $0 ld c, $1 .loop4 ld a, b add b add b ld e, a ld d, $0 ld hl, wd002 add hl, de push hl ld a, c add c add c ld e, a ld d, $0 ld hl, wd002 add hl, de ld d, h ld e, l pop hl push bc ld c, 3 call StringCmp pop bc jr z, .equal jr nc, .done2 .equal inc c ld a, c cp $5 jr nz, .loop4 inc b ld c, b inc c ld a, b cp $4 jr nz, .loop4 ret .done2 push bc ld a, b ld bc, 18 ld hl, sLinkBattleRecord call AddNTimes push hl ld de, wd002 ld bc, 18 call CopyBytes pop hl pop bc push hl ld a, c ld bc, 18 ld hl, sLinkBattleRecord call AddNTimes pop de push hl ld bc, 18 call CopyBytes ld hl, wd002 ld bc, 18 pop de call CopyBytes ret ; 3fb54 .LoadPointer: ; 3fb54 ld e, $0 ld a, [hld] ld c, a ld a, [hld] ld b, a ld a, [hld] add c ld c, a ld a, [hld] adc b ld b, a jr nc, .okay2 inc e .okay2 ld a, [hld] add c ld c, a ld a, [hl] adc b ld b, a ret nc inc e ret ; 3fb6c InitBattleDisplay: ; 3fb6c call .InitBackPic hlcoord 0, 12 ld b, 4 ld c, 18 call TextBox callba MobileTextBorder hlcoord 1, 5 lb bc, 3, 7 call ClearBox call LoadStandardFont call _LoadBattleFontsHPBar call .BlankBGMap xor a ld [hMapAnims], a ld [hSCY], a ld a, $90 ld [hWY], a ld [rWY], a call WaitBGMap xor a ld [hBGMapMode], a callba BattleIntroSlidingPics ld a, $1 ld [hBGMapMode], a ld a, $31 ld [hGraphicStartTile], a hlcoord 2, 6 lb bc, 6, 6 predef PlaceGraphic xor a ld [hWY], a ld [rWY], a call WaitBGMap call HideSprites ld b, SCGB_BATTLE_COLORS call GetSGBLayout call SetPalettes ld a, $90 ld [hWY], a xor a ld [hSCX], a ret ; 3fbd6 .BlankBGMap: ; 3fbd6 ld a, [rSVBK] push af ld a, $6 ld [rSVBK], a ld hl, wDecompressScratch ld bc, wScratchAttrMap - wDecompressScratch ld a, " " call ByteFill ld de, wDecompressScratch hlbgcoord 0, 0 lb bc, BANK(.BlankBGMap), $40 call Request2bpp pop af ld [rSVBK], a ret ; 3fbf8 .InitBackPic: ; 3fbf8 call GetTrainerBackpic call CopyBackpic ret ; 3fbff GetTrainerBackpic: ; 3fbff ; Load the player character's backpic (6x6) into VRAM starting from VTiles2 tile $31. ; Special exception for Dude. ld b, BANK(DudeBackpic) ld hl, DudeBackpic ld a, [BattleType] cp BATTLETYPE_TUTORIAL jr z, .Decompress ; What gender are we? ld a, [wPlayerSpriteSetupFlags] bit 2, a ; transformed to male jr nz, .Chris ld a, [PlayerGender] bit 0, a jr z, .Chris ; It's a girl. callba GetKrisBackpic ret .Chris: ; It's a boy. ld b, BANK(ChrisBackpic) ld hl, ChrisBackpic .Decompress: ld de, VTiles2 tile $31 ld c, $31 predef DecompressPredef ret ; 3fc30 CopyBackpic: ; 3fc30 ld a, [rSVBK] push af ld a, $6 ld [rSVBK], a ld hl, VTiles0 ld de, VTiles2 tile $31 ld a, [hROMBank] ld b, a ld c, $31 call Get2bpp pop af ld [rSVBK], a call .LoadTrainerBackpicAsOAM ld a, $31 ld [hGraphicStartTile], a hlcoord 2, 6 lb bc, 6, 6 predef PlaceGraphic ret ; 3fc5b .LoadTrainerBackpicAsOAM: ; 3fc5b ld hl, Sprites xor a ld [hMapObjectIndexBuffer], a ld b, $6 ld e, 21 * 8 .outer_loop ld c, $3 ld d, 8 * 8 .inner_loop ld [hl], d inc hl ld [hl], e inc hl ld a, [hMapObjectIndexBuffer] ld [hli], a inc a ld [hMapObjectIndexBuffer], a ld a, $1 ld [hli], a ld a, d add $8 ld d, a dec c jr nz, .inner_loop ld a, [hMapObjectIndexBuffer] add $3 ld [hMapObjectIndexBuffer], a ld a, e add $8 ld e, a dec b jr nz, .outer_loop ret ; 3fc8b BattleStartMessage: ; 3fc8b ld a, [wBattleMode] dec a jr z, .wild ld de, SFX_SHINE call PlaySFX call WaitSFX ld c, 20 call DelayFrames callba Battle_GetTrainerName ld hl, WantsToBattleText jr .PlaceBattleStartText .wild call BattleCheckEnemyShininess jr nc, .not_shiny xor a ld [wNumHits], a ld a, 1 ld [hBattleTurn], a ld a, 1 ld [wBattleAnimParam], a ld de, ANIM_SEND_OUT_MON call Call_PlayBattleAnim .not_shiny callba CheckSleepingTreeMon jr c, .skip_cry callba CheckBattleScene jr c, .cry_no_anim hlcoord 12, 0 ld d, $0 ld e, ANIM_MON_NORMAL predef AnimateFrontpic jr .skip_cry ; cry is played during the animation .cry_no_anim ld a, $0f ld [CryTracks], a ld a, [TempEnemyMonSpecies] call PlayStereoCry .skip_cry ld a, [BattleType] cp BATTLETYPE_FISH jr nz, .NotFishing callba TrainerRankings_HookedEncounters ld hl, HookedPokemonAttackedText jr .PlaceBattleStartText .NotFishing: ld hl, PokemonFellFromTreeText cp BATTLETYPE_TREE jr z, .PlaceBattleStartText ld hl, WildCelebiAppearedText cp BATTLETYPE_CELEBI jr z, .PlaceBattleStartText ld hl, WildPokemonAppearedText .PlaceBattleStartText: push hl callba BattleStart_TrainerHuds pop hl call StdBattleTextBox call IsMobileBattle2 ret nz ld c, $2 ; start callba Mobile_PrintOpponentBattleMessage ret ; 3fd26