diff options
-rw-r--r-- | charmap.asm | 11 | ||||
-rw-r--r-- | constants/battle_constants.asm | 1 | ||||
-rw-r--r-- | data/battle/effect_command_pointers.asm | 181 | ||||
-rw-r--r-- | data/battle/stat_multipliers_2.asm | 20 | ||||
-rwxr-xr-x | data/text/common_1.asm | 16 | ||||
-rw-r--r-- | data/wild/unlocked_unowns.asm | 24 | ||||
-rw-r--r-- | engine/battle/core.asm | 4106 | ||||
-rw-r--r-- | engine/battle/sliding_intro.asm | 57 | ||||
-rwxr-xr-x | engine/events/specials.asm | 2 | ||||
-rwxr-xr-x | engine/items/item_effects.asm | 8 | ||||
-rwxr-xr-x | engine/items/pack.asm | 92 | ||||
-rw-r--r-- | engine/pokemon/correct_nick_errors.asm | 2 | ||||
-rw-r--r-- | engine/pokemon/learn.asm | 2 | ||||
-rw-r--r-- | gfx/battle/dude.2bpp.lz | bin | 0 -> 320 bytes | |||
-rw-r--r-- | gfx/player/chris_back.2bpp.lz | bin | 0 -> 400 bytes | |||
-rw-r--r-- | home/text.asm | 2 | ||||
-rw-r--r-- | main.asm | 153 | ||||
-rw-r--r-- | pokegold.link | 4 | ||||
-rw-r--r-- | pokesilver.link | 4 | ||||
-rwxr-xr-x | sram.asm | 35 | ||||
-rw-r--r-- | wram.asm | 58 |
21 files changed, 4572 insertions, 206 deletions
diff --git a/charmap.asm b/charmap.asm index 595c7cf3..31283ae3 100644 --- a/charmap.asm +++ b/charmap.asm @@ -1,9 +1,12 @@ -; Control characters - charmap "<START>", $00 +; $00-$16 are TX_* constants (see macros/scripts/text.asm) + +; Control characters (see home/text.asm) + charmap "<NULL>", $00 charmap "<PLAY_G>", $14 ; <PLAYER> + gender - charmap "<DAY>", $15 + charmap "<MOBILE>", $15 + charmap "<CR>", $16 charmap "¯", $1f - charmap "<LNBRK>", $22 + charmap "<LF>", $22 charmap "<POKE>", $24 charmap "%", $25 charmap "<RED>", $38 diff --git a/constants/battle_constants.asm b/constants/battle_constants.asm index 5442e2c3..ba373a0a 100644 --- a/constants/battle_constants.asm +++ b/constants/battle_constants.asm @@ -15,6 +15,7 @@ MIN_NEUTRAL_DAMAGE EQU 2 ; turns that sleep lasts REST_SLEEP_TURNS EQU 2 +TREEMON_SLEEP_TURNS EQU 7 ; default move priority BASE_PRIORITY EQU 1 diff --git a/data/battle/effect_command_pointers.asm b/data/battle/effect_command_pointers.asm new file mode 100644 index 00000000..d5c044d7 --- /dev/null +++ b/data/battle/effect_command_pointers.asm @@ -0,0 +1,181 @@ +; battle commands are defined in engine/battle/effect_commands.asm + + dw 0 ; padding + +BattleCommandPointers: +; entries correspond to macros/scripts/battle_commands.asm + dw BattleCommand_CheckTurn + dw BattleCommand_CheckObedience + dw BattleCommand_UsedMoveText + dw BattleCommand_DoTurn + dw BattleCommand_Critical + dw BattleCommand_DamageStats + dw BattleCommand_Stab + dw BattleCommand_DamageVariation + dw BattleCommand_CheckHit + dw BattleCommand_LowerSub + dw BattleCommand_MoveAnimNoSub + dw BattleCommand_RaiseSub + dw BattleCommand_FailureText + dw BattleCommand_ApplyDamage + dw BattleCommand_CriticalText + dw BattleCommand_SuperEffectiveText + dw BattleCommand_CheckFaint + dw BattleCommand_BuildOpponentRage + dw BattleCommand_PoisonTarget + dw BattleCommand_SleepTarget + dw BattleCommand_DrainTarget + dw BattleCommand_EatDream + dw BattleCommand_BurnTarget + dw BattleCommand_FreezeTarget + dw BattleCommand_ParalyzeTarget + dw BattleCommand_Selfdestruct + dw BattleCommand_MirrorMove + dw BattleCommand_StatUp + dw BattleCommand_StatDown + dw BattleCommand_PayDay + dw BattleCommand_Conversion + dw BattleCommand_ResetStats + dw BattleCommand_StoreEnergy + dw BattleCommand_UnleashEnergy + dw BattleCommand_ForceSwitch + dw BattleCommand_EndLoop + dw BattleCommand_FlinchTarget + dw BattleCommand_OHKO + dw BattleCommand_Recoil + dw BattleCommand_Mist + dw BattleCommand_FocusEnergy + dw BattleCommand_Confuse + dw BattleCommand_ConfuseTarget + dw BattleCommand_Heal + dw BattleCommand_Transform + dw BattleCommand_Screen + dw BattleCommand_Poison + dw BattleCommand_Paralyze + dw BattleCommand_Substitute + dw BattleCommand_RechargeNextTurn + dw BattleCommand_Mimic + dw BattleCommand_Metronome + dw BattleCommand_LeechSeed + dw BattleCommand_Splash + dw BattleCommand_Disable + dw BattleCommand_ClearText + dw BattleCommand_Charge + dw BattleCommand_CheckCharge + dw BattleCommand_TrapTarget + dw BattleCommand3c + dw BattleCommand_Rampage + dw BattleCommand_CheckRampage + dw BattleCommand_ConstantDamage + dw BattleCommand_Counter + dw BattleCommand_Encore + dw BattleCommand_PainSplit + dw BattleCommand_Snore + dw BattleCommand_Conversion2 + dw BattleCommand_LockOn + dw BattleCommand_Sketch + dw BattleCommand_DefrostOpponent + dw BattleCommand_SleepTalk + dw BattleCommand_DestinyBond + dw BattleCommand_Spite + dw BattleCommand_FalseSwipe + dw BattleCommand_HealBell + dw BattleCommand_HeldFlinch + dw BattleCommand_TripleKick + dw BattleCommand_KickCounter + dw BattleCommand_Thief + dw BattleCommand_ArenaTrap + dw BattleCommand_Nightmare + dw BattleCommand_Defrost + dw BattleCommand_Curse + dw BattleCommand_Protect + dw BattleCommand_Spikes + dw BattleCommand_Foresight + dw BattleCommand_PerishSong + dw BattleCommand_StartSandstorm + dw BattleCommand_Endure + dw BattleCommand_CheckCurl + dw BattleCommand_RolloutPower + dw BattleCommand5d + dw BattleCommand_FuryCutter + dw BattleCommand_Attract + dw BattleCommand_HappinessPower + dw BattleCommand_Present + dw BattleCommand_DamageCalc + dw BattleCommand_FrustrationPower + dw BattleCommand_Safeguard + dw BattleCommand_CheckSafeguard + dw BattleCommand_GetMagnitude + dw BattleCommand_BatonPass + dw BattleCommand_Pursuit + dw BattleCommand_ClearHazards + dw BattleCommand_HealMorn + dw BattleCommand_HealDay + dw BattleCommand_HealNite + dw BattleCommand_HiddenPower + dw BattleCommand_StartRain + dw BattleCommand_StartSun + dw BattleCommand_AttackUp + dw BattleCommand_DefenseUp + dw BattleCommand_SpeedUp + dw BattleCommand_SpecialAttackUp + dw BattleCommand_SpecialDefenseUp + dw BattleCommand_AccuracyUp + dw BattleCommand_EvasionUp + dw BattleCommand_AttackUp2 + dw BattleCommand_DefenseUp2 + dw BattleCommand_SpeedUp2 + dw BattleCommand_SpecialAttackUp2 + dw BattleCommand_SpecialDefenseUp2 + dw BattleCommand_AccuracyUp2 + dw BattleCommand_EvasionUp2 + dw BattleCommand_AttackDown + dw BattleCommand_DefenseDown + dw BattleCommand_SpeedDown + dw BattleCommand_SpecialAttackDown + dw BattleCommand_SpecialDefenseDown + dw BattleCommand_AccuracyDown + dw BattleCommand_EvasionDown + dw BattleCommand_AttackDown2 + dw BattleCommand_DefenseDown2 + dw BattleCommand_SpeedDown2 + dw BattleCommand_SpecialAttackDown2 + dw BattleCommand_SpecialDefenseDown2 + dw BattleCommand_AccuracyDown2 + dw BattleCommand_EvasionDown2 + dw BattleCommand_StatUpMessage + dw BattleCommand_StatDownMessage + dw BattleCommand_StatUpFailText + dw BattleCommand_StatDownFailText + dw BattleCommand_EffectChance + dw BattleCommand_StatDownAnim + dw BattleCommand_StatUpAnim + dw BattleCommand_SwitchTurn + dw BattleCommand_FakeOut + dw BattleCommand_BellyDrum + dw BattleCommand_PsychUp + dw BattleCommand_Rage + dw BattleCommand_DoubleFlyingDamage + dw BattleCommand_DoubleUndergroundDamage + dw BattleCommand_MirrorCoat + dw BattleCommand_CheckFutureSight + dw BattleCommand_FutureSight + dw BattleCommand_DoubleMinimizeDamage + dw BattleCommand_SkipSunCharge + dw BattleCommand_ThunderAccuracy + dw BattleCommand_Teleport + dw BattleCommand_BeatUp + dw BattleCommand_RageDamage + dw BattleCommand_ResetTypeMatchup + dw BattleCommand_AllStatsUp + dw BattleCommand_BideFailText + dw BattleCommand_RaiseSubNoAnim + dw BattleCommand_LowerSubNoAnim + dw BattleCommand_BeatUpFailText + dw BattleCommand_ClearMissDamage + dw BattleCommand_MoveDelay + dw BattleCommand_MoveAnim + dw BattleCommand_TriStatusChance + dw BattleCommand_SuperEffectiveLoopText + dw BattleCommand_StartLoop + dw BattleCommand_Curl diff --git a/data/battle/stat_multipliers_2.asm b/data/battle/stat_multipliers_2.asm new file mode 100644 index 00000000..3f3dc234 --- /dev/null +++ b/data/battle/stat_multipliers_2.asm @@ -0,0 +1,20 @@ +; Multiplier ratios for all stats from modifier -6 to +6 +; (except accuracy, see data/battle/accuracy_multipliers.asm). + +; This table is identical to data/battle/stat_multipliers.asm. +; This one is used by ApplyStatLevelMultiplier. + +StatLevelMultipliers_Applied: + db 25, 100 ; -6 = 25% + db 28, 100 ; -5 = 28% + db 33, 100 ; -4 = 33% + db 40, 100 ; -3 = 40% + db 50, 100 ; -2 = 50% + db 66, 100 ; -1 = 66% + db 1, 1 ; 0 = 100% + db 15, 10 ; +1 = 150% + db 2, 1 ; +2 = 200% + db 25, 10 ; +3 = 250% + db 3, 1 ; +4 = 300% + db 35, 10 ; +5 = 350% + db 4, 1 ; +6 = 400% diff --git a/data/text/common_1.asm b/data/text/common_1.asm index 69e3c49e..ca1a8e9a 100755 --- a/data/text/common_1.asm +++ b/data/text/common_1.asm @@ -1633,7 +1633,7 @@ Text_Gained:: text_ram wStringBuffer1 text " gained@@" -Text_ABoostedStringBuffer2ExpPoints:: +_BoostedExpPointsText:: text_start line "a boosted" cont "@" @@ -1641,7 +1641,7 @@ Text_ABoostedStringBuffer2ExpPoints:: text " EXP. Points!" prompt -Text_StringBuffer2ExpPoints:: +_ExpPointsText:: text_start line "@" text_decimal wStringBuffer2, 2, 4 @@ -1674,29 +1674,31 @@ Text_YourFoesWeakGetmMon:: text "!" done -Text_ThatsEnoughComeBack:: +Text_BattleMonNickComma:: text_ram wBattleMonNick text ",@@" + +_ThatsEnoughComeBackText:: text " that's" line "enough! Come back!" done -Text_OKComeBack:: +_OKComeBackText:: text " OK!" line "Come back!" done -Text_GoodComeBack:: +_GoodComeBackText:: text " good!" line "Come back!" done -Text_ComeBack:: +_ComeBackText:: text " come" line "back!" done -BattleText_PlayerPickedUpPayDayMoney: +_PlayerPickedUpPayDayMoney:: text "<PLAYER> picked up" line "¥@" text_decimal wPayDayMoney, 3, 6 diff --git a/data/wild/unlocked_unowns.asm b/data/wild/unlocked_unowns.asm new file mode 100644 index 00000000..d09064c4 --- /dev/null +++ b/data/wild/unlocked_unowns.asm @@ -0,0 +1,24 @@ +unown_set: MACRO +rept _NARG + db UNOWN_\1 + shift +endr + db -1 +ENDM + +UnlockedUnownLetterSets: +; entries correspond to wUnlockedUnowns bits + dw .Set_A_K ; ENGINE_UNLOCKED_UNOWNS_A_TO_K + dw .Set_L_R ; ENGINE_UNLOCKED_UNOWNS_L_TO_R + dw .Set_S_W ; ENGINE_UNLOCKED_UNOWNS_S_TO_W + dw .Set_X_Z ; ENGINE_UNLOCKED_UNOWNS_X_TO_Z +.End + +.Set_A_K: + unown_set A, B, C, D, E, F, G, H, I, J, K +.Set_L_R: + unown_set L, M, N, O, P, Q, R +.Set_S_W: + unown_set S, T, U, V, W +.Set_X_Z: + unown_set X, Y, Z diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 04769f46..734d151b 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -4621,3 +4621,4109 @@ UpdateHPPal: ret_3df99: ret + +BattleMenu: + xor a + ldh [hBGMapMode], a + call LoadTempTilemapToTilemap + + ld a, [wBattleType] + cp BATTLETYPE_DEBUG + jr z, .ok + cp BATTLETYPE_TUTORIAL + jr z, .ok + call UpdateBattleHuds + call EmptyBattleTextbox + call LoadTilemapToTempTilemap +.ok + +.loop + ld a, [wBattleType] + cp BATTLETYPE_CONTEST + jr nz, .not_contest + callfar ContestBattleMenu + jr .next +.not_contest + + ; Auto input: choose "ITEM" + ld a, [wInputType] + or a + jr z, .skip_dude_pack_select + farcall _DudeAutoInput_DownA +.skip_dude_pack_select + callfar LoadBattleMenu + +.next + ld a, $1 + ldh [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 + +BattleMenu_Fight: + xor a + ld [wNumFleeAttempts], a + call SafeLoadTempTilemapToTilemap + and a + ret + +BattleMenu_Pack: + ld a, [wLinkMode] + and a + jp nz, .ItemsCantBeUsed + + call LoadStandardMenuHeader + + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jr z, .tutorial + cp BATTLETYPE_CONTEST + jr z, .contest + + farcall BattlePack + ld a, [wBattlePlayerAction] + and a ; BATTLEPLAYERACTION_USEMOVE? + jr z, .didnt_use_item + jr .got_item + +.tutorial + farcall TutorialPack + ld a, POKE_BALL + ld [wCurItem], a + call DoItemEffect + jr .got_item + +.contest + ld a, PARK_BALL + ld [wCurItem], a + call DoItemEffect + +.got_item + call .UseItem + ret + +.didnt_use_item + call ClearPalettes + call DelayFrame + call _LoadBattleFontsHPBar + call GetBattleMonBackpic + call GetEnemyMonFrontpic + call ExitMenu + call WaitBGMap + call FinishBattleAnim + call LoadTilemapToTempTilemap + jp BattleMenu + +.ItemsCantBeUsed: + ld hl, BattleText_ItemsCantBeUsedHere + call StdBattleTextbox + jp BattleMenu + +.UseItem: + ld a, [wWildMon] + and a + jr nz, .run + callfar CheckItemPocket + ld a, [wItemAttributeParamBuffer] + cp BALL + jr z, .ball + call ClearBGPalettes + +.ball + xor a + ldh [hBGMapMode], a + call _LoadBattleFontsHPBar + call ClearSprites + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jr z, .tutorial2 + call GetBattleMonBackpic + +.tutorial2 + call GetEnemyMonFrontpic + ld a, $1 + ld [wMenuCursorY], a + call ExitMenu + call UpdateBattleHUDs + call WaitBGMap + call LoadTilemapToTempTilemap + call ClearWindowData + call FinishBattleAnim + and a + ret + +.run + xor a + ld [wWildMon], a + ld a, [wBattleResult] + and BATTLERESULT_BITMASK + ld [wBattleResult], a ; WIN + call ClearWindowData + call SetPalettes + scf + ret + +BattleMenu_PKMN: + call LoadStandardMenuHeader +BattleMenuPKMN_ReturnFromStats: + call ExitMenu + call LoadStandardMenuHeader + call ClearBGPalettes +BattleMenuPKMN_Loop: + farcall LoadPartyMenuGFX + farcall InitPartyMenuWithCancel + farcall InitPartyMenuGFX + xor a + ld [wPartyMenuActionText], a + farcall WritePartyMenuTilemap + farcall PrintPartyMenuText + call WaitBGMap + call SetPalettes + call DelayFrame + farcall PartyMenuSelect + jr c, .Cancel +.loop + callfar FreezeMonIcons + callfar GetMenu + jr c, BattleMenuPKMN_Loop + 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 + +.Stats: + call Battle_StatsScreen + jp BattleMenuPKMN_ReturnFromStats + +.Cancel: + call ClearSprites + call ClearPalettes + call DelayFrame + call _LoadHPBar + call CloseWindow + call LoadTilemapToTempTilemap + call GetMemSGBLayout + call SetPalettes + jp BattleMenu + +Battle_StatsScreen: + call DisableLCD + + ld hl, vTiles2 tile $31 + ld de, vTiles0 + ld bc, $11 tiles + call CopyBytes + + ld hl, vTiles2 + ld de, vTiles0 tile $11 + ld bc, $31 tiles + call CopyBytes + + call EnableLCD + + call ClearSprites + call LowVolume + xor a ; PARTYMON + ld [wMonType], a + ld hl, wPartyMons + predef StatsScreenInit + 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 + +TryPlayerSwitch: + ld a, [wCurBattleMon] + ld d, a + ld a, [wCurPartyMon] + cp d + jr nz, .check_trapped + ld hl, BattleText_MonIsAlreadyOut + call StdBattleTextbox + jp BattleMenuPKMN_Loop + +.check_trapped + ld a, [wPlayerWrapCount] + and a + jr nz, .trapped + ld a, [wEnemySubStatus5] + bit SUBSTATUS_CANT_RUN, a + jr z, .try_switch + +.trapped + ld hl, BattleText_MonCantBeRecalled + call StdBattleTextbox + jp BattleMenuPKMN_Loop + +.try_switch + call CheckIfCurPartyMonIsFitToFight + jp z, BattleMenuPKMN_Loop + ld a, [wCurBattleMon] + ld [wLastPlayerMon], a + ld a, BATTLEPLAYERACTION_SWITCH + ld [wBattlePlayerAction], a + call ClearPalettes + call DelayFrame + call ClearSprites + call _LoadHPBar + call CloseWindow + call GetMemSGBLayout + call SetPalettes + ld a, [wCurPartyMon] + ld [wCurBattleMon], a +PlayerSwitch: + ld a, 1 + ld [wPlayerIsSwitching], a + ld a, [wLinkMode] + and a + jr z, .not_linked + call LoadStandardMenuHeader + 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_STRUGGLE + jp z, .switch + cp BATTLEACTION_SKIPTURN + jp z, .switch + cp BATTLEACTION_SWITCH1 + jp c, .switch + cp BATTLEACTION_FORFEIT + jr nz, .dont_run + call WildFled_EnemyFled_LinkBattleCanceled + ret + +.dont_run + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_1 + call BattleMonEntrance + call EnemyMonEntrance + and a + ret + +.player_1 + call EnemyMonEntrance + call BattleMonEntrance + and a + ret + +EnemyMonEntrance: + callfar AI_Switch + call SetEnemyTurn + jp SpikesDamage + +BattleMonEntrance: + call WithdrawMonText + + ld c, 50 + call DelayFrames + + ld hl, wPlayerSubStatus4 + res SUBSTATUS_RAGE, [hl] + + call SetEnemyTurn + call PursuitSwitch + jr c, .ok + call RecallPlayerMon +.ok + + hlcoord 9, 7 + lb bc, 5, 11 + call ClearBox + + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + call AddBattleParticipant + call InitBattleMon + call ResetPlayerStatLevels + call SendOutMonText + call NewBattleMonStatus + call BreakAttraction + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + call SetPlayerTurn + call SpikesDamage + ld a, $2 + ld [wMenuCursorY], a + ret + +PassedBattleMonEntrance: + ld c, 50 + call DelayFrames + + hlcoord 9, 7 + lb bc, 5, 11 + call ClearBox + + ld a, [wCurPartyMon] + ld [wCurBattleMon], a + call AddBattleParticipant + call InitBattleMon + xor a ; FALSE + ld [wApplyStatLevelMultipliersToEnemy], a + call ApplyStatLevelMultiplierOnAllStats + call SendOutPlayerMon + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + call SetPlayerTurn + jp SpikesDamage + +BattleMenu_Run: + call SafeLoadTempTilemapToTilemap + ld a, $3 + ld [wMenuCursorY], a + ld hl, wBattleMonSpeed + ld de, wEnemyMonSpeed + call TryToRunAwayFromBattle + ld a, FALSE + ld [wFailedToFlee], a + ret c + ld a, [wBattlePlayerAction] + and a ; BATTLEPLAYERACTION_USEMOVE? + ret nz + jp BattleMenu + +CheckAmuletCoin: + ld a, [wBattleMonItem] + ld b, a + callfar GetItemHeldEffect + ld a, b + cp HELD_AMULET_COIN + ret nz + ld a, 1 + ld [wAmuletCoin], a + ret + +MoveSelectionScreen: + ld hl, wEnemyMonMoves + ld a, [wMoveSelectionMenuType] + dec a + jr z, .got_menu_type + dec a + jr z, .ether_elixer_menu + call .CheckPlayerHasUsableMoves + ret z ; use Struggle + ld hl, wBattleMonMoves + jr .got_menu_type + +.ether_elixer_menu + ld a, MON_MOVES + call GetPartyParamLocation + +.got_menu_type + ld de, wListMoves_MoveIndicesBuffer + ld bc, NUM_MOVES + call CopyBytes + xor a + ldh [hBGMapMode], a + + hlcoord 4, 17 - NUM_MOVES - 1 + ld b, 4 + ld c, 14 + ld a, [wMoveSelectionMenuType] + cp $2 + jr nz, .got_dims + hlcoord 4, 17 - NUM_MOVES - 1 - 4 + ld b, 4 + ld c, 14 +.got_dims + call Textbox + + hlcoord 6, 17 - NUM_MOVES + ld a, [wMoveSelectionMenuType] + cp $2 + jr nz, .got_start_coord + hlcoord 6, 17 - NUM_MOVES - 4 +.got_start_coord + ld a, SCREEN_WIDTH + ld [wBuffer1], a + predef ListMoves + + ld b, 5 + ld a, [wMoveSelectionMenuType] + cp $2 + ld a, 17 - NUM_MOVES + jr nz, .got_default_coord + ld b, 5 + ld a, 17 - NUM_MOVES - 4 + +.got_default_coord + ld [w2DMenuCursorInitY], a + ld a, b + ld [w2DMenuCursorInitX], a + ld a, [wMoveSelectionMenuType] + cp $1 + jr z, .skip_inc + ld a, [wCurMoveNum] + inc a + +.skip_inc + ld [wMenuCursorY], a + ld a, 1 + ld [wMenuCursorX], a + ld a, [wNumMoves] + inc a + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld c, STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP + 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] + cp LINK_COLOSSEUM + jr z, .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 + ldh [hBGMapMode], a + call ScrollingMenuJoypad + bit D_UP_F, a + jp nz, .pressed_up + bit D_DOWN_F, a + jp nz, .pressed_down + bit SELECT_F, a + jp nz, .pressed_select + bit B_BUTTON_F, a + ; A button + push af + + xor a + ld [wMoveSwapBuffer], a + ld a, [wMenuCursorY] + dec a + ld [wMenuCursorY], a + ld b, a + ld a, [wMoveSelectionMenuType] + dec a + jr nz, .not_enemy_moves_process_b + + pop af + ret + +.not_enemy_moves_process_b + dec a + ld a, b + ld [wCurMoveNum], a + jr nz, .use_move + + pop af + ret + +.use_move + pop af + ret nz + + ld hl, wBattleMonPP + ld a, [wMenuCursorY] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + and PP_MASK + jr z, .no_pp_left + ld a, [wPlayerDisableCount] + swap a + and $f + dec a + cp c + jr z, .move_disabled + ld a, [wUnusedPlayerLockedMove] + and a + jr nz, .skip2 + ld a, [wMenuCursorY] + ld hl, wBattleMonMoves + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + +.skip2 + ld [wCurPlayerMove], a + xor a + ret + +.move_disabled + ld hl, BattleText_TheMoveIsDisabled + jr .place_textbox_start_over + +.no_pp_left + ld hl, BattleText_TheresNoPPLeftForThisMove + +.place_textbox_start_over + call StdBattleTextbox + call SafeLoadTempTilemapToTilemap + jp MoveSelectionScreen + +.string_3e61c + db "@" + +.pressed_up + ld a, [wMenuCursorY] + and a + jp nz, .menu_loop + ld a, [wNumMoves] + inc a + ld [wMenuCursorY], a + jp .menu_loop + +.pressed_down + ld a, [wMenuCursorY] + ld b, a + ld a, [wNumMoves] + inc a + inc a + cp b + jp nz, .menu_loop + ld a, $1 + ld [wMenuCursorY], a + jp .menu_loop + +.CheckPlayerHasUsableMoves: + ld a, STRUGGLE + ld [wCurPlayerMove], a + ld a, [wPlayerDisableCount] + and a + ld hl, wBattleMonPP + jr nz, .disabled + + ld a, [hli] + or [hl] + inc hl + or [hl] + inc hl + or [hl] + and PP_MASK + ret nz + jr .force_struggle + +.disabled + swap a + and $f + ld b, a + ld d, NUM_MOVES + 1 + xor a +.loop + dec d + jr z, .done + ld c, [hl] + inc hl + dec b + jr z, .loop + or c + jr .loop + +.done + ; Bug: this will result in a move with PP Up confusing the game. + and a ; should be "and PP_MASK" + ret nz + +.force_struggle + ld hl, BattleText_MonHasNoMovesLeft + call StdBattleTextbox + ld c, 60 + call DelayFrames + xor a + ret + +.pressed_select + ld a, [wMoveSwapBuffer] + and a + jr z, .start_swap + ld hl, wBattleMonMoves + call .swap_bytes + ld hl, wBattleMonPP + call .swap_bytes + ld hl, wPlayerDisableCount + ld a, [hl] + swap a + and $f + ld b, a + ld a, [wMenuCursorY] + cp b + jr nz, .not_swapping_disabled_move + ld a, [hl] + and $f + ld b, a + ld a, [wMoveSwapBuffer] + swap a + add b + ld [hl], a + jr .swap_moves_in_party_struct + +.not_swapping_disabled_move + ld a, [wMoveSwapBuffer] + cp b + jr nz, .swap_moves_in_party_struct + ld a, [hl] + and $f + ld b, a + ld a, [wMenuCursorY] + swap a + add b + ld [hl], a + +.swap_moves_in_party_struct +; Fixes the COOLTRAINER glitch + ld a, [wPlayerSubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr nz, .transformed + ld hl, wPartyMon1Moves + ld a, [wCurBattleMon] + call GetPartyLocation + push hl + call .swap_bytes + pop hl + ld bc, MON_PP - MON_MOVES + add hl, bc + call .swap_bytes + +.transformed + xor a + ld [wMoveSwapBuffer], a + jp MoveSelectionScreen + +.swap_bytes + push hl + ld a, [wMoveSwapBuffer] + dec a + ld c, a + ld b, 0 + add hl, bc + ld d, h + ld e, l + pop hl + ld a, [wMenuCursorY] + dec a + ld c, a + ld b, 0 + add hl, bc + ld a, [de] + ld b, [hl] + ld [hl], a + ld a, b + ld [de], a + ret + +.start_swap + ld a, [wMenuCursorY] + ld [wMoveSwapBuffer], a + jp MoveSelectionScreen + +MoveInfoBox: + xor a + ldh [hBGMapMode], a + + hlcoord 0, 8 + ld b, 3 + ld c, 9 + call Textbox + + ld a, [wPlayerDisableCount] + and a + jr z, .not_disabled + + swap a + and $f + ld b, a + ld a, [wMenuCursorY] + cp b + jr nz, .not_disabled + + hlcoord 1, 10 + ld de, .Disabled + call PlaceString + jr .done + +.not_disabled + ld hl, wMenuCursorY + dec [hl] + call SetPlayerTurn + ld hl, wBattleMonMoves + ld a, [wMenuCursorY] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wCurPlayerMove], a + + ld a, [wCurBattleMon] + ld [wCurPartyMon], a + ld a, WILDMON + ld [wMonType], a + callfar GetMaxPPOfMove + + ld hl, wMenuCursorY + ld c, [hl] + inc [hl] + ld b, 0 + ld hl, wBattleMonPP + add hl, bc + ld a, [hl] + and PP_MASK + ld [wStringBuffer1], a + hlcoord 1, 9 + ld de, .Type + call PlaceString + + hlcoord 7, 11 + ld [hl], "/" + hlcoord 5, 11 + ld de, wStringBuffer1 + lb bc, 1, 2 + call PrintNum + + hlcoord 8, 11 + ld de, wNamedObjectIndexBuffer + lb bc, 1, 2 + call PrintNum + + callfar UpdateMoveData + ld a, [wPlayerMoveStruct + MOVE_ANIM] + ld b, a + hlcoord 2, 10 + predef PrintMoveType + +.done + ret + +.Disabled: + db "Disabled!@" +.Type: + db "TYPE/@" + +ParseEnemyAction: + ld a, [wEnemyIsSwitching] + and a + ret nz + ld a, [wLinkMode] + and a + jr z, .not_linked + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + ld a, [wBattlePlayerAction] + and a ; BATTLEPLAYERACTION_USEMOVE? + call z, LinkBattleSendReceiveAction + call SafeLoadTempTilemapToTilemap + ld a, [wBattleAction] + cp BATTLEACTION_STRUGGLE + jp z, .struggle + cp BATTLEACTION_SKIPTURN + jp z, .skip_turn + cp BATTLEACTION_SWITCH1 + jp nc, ResetVarsForSubstatusRage + ld [wCurEnemyMoveNum], a + ld c, a + ld a, [wEnemySubStatus1] + bit SUBSTATUS_ROLLOUT, a + jp nz, .skip_load + ld a, [wEnemySubStatus3] + and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE + jp nz, .skip_load + + ld hl, wEnemySubStatus5 + bit SUBSTATUS_ENCORED, [hl] + ld a, [wLastEnemyMove] + jp nz, .finish + ld hl, wEnemyMonMoves + ld b, 0 + add hl, bc + ld a, [hl] + jp .finish + +.not_linked + ld hl, wEnemySubStatus5 + bit SUBSTATUS_ENCORED, [hl] + jr z, .skip_encore + ld a, [wLastEnemyMove] + jp .finish + +.skip_encore + call CheckEnemyLockedIn + jp nz, ResetVarsForSubstatusRage + jr .continue + +.skip_turn + ld a, $ff + jr .finish + +.continue + ld hl, wEnemyMonMoves + ld de, wEnemyMonPP + ld b, NUM_MOVES +.loop + ld a, [hl] + and a + jp z, .struggle + ld a, [wEnemyDisabledMove] + cp [hl] + jr z, .disabled + ld a, [de] + and PP_MASK + jr nz, .enough_pp + +.disabled + inc hl + inc de + dec b + jr nz, .loop + jr .struggle + +.enough_pp + ld a, [wBattleMode] + dec a + jr nz, .skip_load +; wild +.loop2 + ld hl, wEnemyMonMoves + call BattleRandom + maskbits NUM_MOVES + ld c, a + ld b, 0 + add hl, bc + ld a, [wEnemyDisableCount] + swap a + and $f + dec a + cp c + jr z, .loop2 + ld a, [hl] + and a + jr z, .loop2 + ld hl, wEnemyMonPP + add hl, bc + ld b, a + ld a, [hl] + and PP_MASK + jr z, .loop2 + ld a, c + ld [wCurEnemyMoveNum], a + ld a, b + +.finish + ld [wCurEnemyMove], a + +.skip_load + call SetEnemyTurn + callfar UpdateMoveData + call CheckEnemyLockedIn + jr nz, .raging + xor a + ld [wEnemyCharging], a + +.raging + ld a, [wEnemyMoveStruct + MOVE_EFFECT] + cp EFFECT_FURY_CUTTER + jr z, .fury_cutter + xor a + ld [wEnemyFuryCutterCount], a + +.fury_cutter + ld a, [wEnemyMoveStruct + MOVE_EFFECT] + cp EFFECT_RAGE + jr z, .no_rage + ld hl, wEnemySubStatus4 + res SUBSTATUS_RAGE, [hl] + xor a + ld [wEnemyRageCounter], a + +.no_rage + ld a, [wEnemyMoveStruct + MOVE_EFFECT] + cp EFFECT_PROTECT + ret z + cp EFFECT_ENDURE + ret z + xor a + ld [wEnemyProtectCount], a + ret + +.struggle + ld a, STRUGGLE + jr .finish + +ResetVarsForSubstatusRage: + xor a + ld [wEnemyFuryCutterCount], a + ld [wEnemyProtectCount], a + ld [wEnemyRageCounter], a + ld hl, wEnemySubStatus4 + res SUBSTATUS_RAGE, [hl] + ret + +CheckEnemyLockedIn: + ld a, [wEnemySubStatus4] + and 1 << SUBSTATUS_RECHARGE + ret nz + + ld hl, wEnemySubStatus3 + ld a, [hl] + and 1 << SUBSTATUS_CHARGED | 1 << SUBSTATUS_RAMPAGE | 1 << SUBSTATUS_BIDE + ret nz + + ld hl, wEnemySubStatus1 + bit SUBSTATUS_ROLLOUT, [hl] + ret + +LinkBattleSendReceiveAction: + ld a, $ff + ld [wOtherPlayerLinkAction], a + ld a, [wBattlePlayerAction] + and a ; BATTLEPLAYERACTION_USEMOVE? + jr nz, .switch + ld a, [wCurPlayerMove] + cp STRUGGLE + ld b, BATTLEACTION_STRUGGLE + jr z, .struggle + dec b + inc a + jr z, .struggle + ld a, [wCurMoveNum] + jr .use_move + +.switch + ld a, [wCurPartyMon] + add BATTLEACTION_SWITCH1 + ld b, a + +.struggle + ld a, b + +.use_move + ld [wPlayerLinkAction], a + callfar PlaceWaitingText + +.waiting + call LinkTransfer + call DelayFrame + ld a, [wOtherPlayerLinkAction] + inc a + jr z, .waiting + + ld b, 10 +.receive + call DelayFrame + call LinkTransfer + dec b + jr nz, .receive + + ld b, 10 +.acknowledge + call DelayFrame + call LinkDataReceived + dec b + jr nz, .acknowledge + + ret + +LoadEnemyMon: +; Initialize enemy monster parameters +; To do this we pull the species from wTempEnemyMonSpecies + +; Notes: +; BattleRandom is used to ensure sync between Game Boys + +; Clear the whole enemy mon struct (wEnemyMon) + xor a + ld hl, wEnemyMonSpecies + ld bc, wEnemyMonEnd - wEnemyMon + call ByteFill + +; We don't need to be here if we're in a link battle + ld a, [wLinkMode] + and a + jp nz, InitEnemyMon + +; Make sure everything knows what species we're working with + ld a, [wTempEnemyMonSpecies] + ld [wEnemyMonSpecies], a + ld [wCurSpecies], a + ld [wCurPartySpecies], a + +; Grab the BaseData for this species + call GetBaseData + +; Let's get the item: + +; Is the item predetermined? + ld a, [wBattleMode] + dec a + jr z, .WildItem + +; If we're in a trainer battle, the item is in the party struct + ld a, [wCurPartyMon] + ld hl, wOTPartyMon1Item + call GetPartyLocation ; bc = PartyMon[wCurPartyMon] - wPartyMons + ld a, [hl] + jr .UpdateItem + +.WildItem: +; In a wild battle, we pull from the item slots in BaseData + +; Force Item1 +; Used for Ho-Oh, Lugia and Snorlax encounters + ld a, [wBattleType] + cp BATTLETYPE_FORCEITEM + ld a, [wBaseItem1] + 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 75 percent + 1 + 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, [wBaseItem1] + jr nc, .UpdateItem + ld a, [wBaseItem2] + +.UpdateItem: + ld [wEnemyMonItem], a + +; Initialize DVs + +; If we're in a trainer battle, DVs are predetermined + ld a, [wBattleMode] + and a + jr z, .InitDVs + + ld a, [wEnemySubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr z, .InitDVs + +; Unknown + ld hl, wEnemyBackupDVs + ld de, wEnemyMonDVs + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + jp .Happiness + +.InitDVs: +; Trainer DVs + +; All trainers have preset DVs, determined by class +; See GetTrainerDVs for more on that + farcall GetTrainerDVs +; These are the DVs we'll use if we're actually in a trainer battle + ld a, [wBattleMode] + dec a + jr nz, .UpdateDVs + +; Wild DVs +; Here's where the fun starts + +; Roaming monsters (Entei, Raikou, Suicune) work differently +; They have their own structs, which are shorter than normal + ld a, [wBattleType] + cp BATTLETYPE_ROAMING + jr nz, .NotRoaming + +; Grab HP + call GetRoamMonHP + ld a, [hl] +; Check if the HP has been initialized + and a +; We'll do something with the result in a minute + push af + +; Grab DVs + call GetRoamMonDVs + inc hl + ld a, [hld] + ld c, a + ld b, [hl] + +; Get back the result of our check + pop af +; If the RoamMon struct has already been initialized, we're done + jr nz, .UpdateDVs + +; If it hasn't, we need to initialize the DVs +; (HP is initialized at the end of the battle) + call GetRoamMonDVs + inc hl + call BattleRandom + ld [hld], a + ld c, a + call BattleRandom + ld [hl], a + ld b, a +; We're done with DVs + jr .UpdateDVs + +.NotRoaming: +; Register a contains wBattleType + +; Forced shiny battle type +; Used by Red Gyarados at Lake of Rage + cp BATTLETYPE_SHINY + jr nz, .GenerateDVs + + ld b, ATKDEFDV_SHINY ; $ea + ld c, SPDSPCDV_SHINY ; $aa + jr .UpdateDVs + +.GenerateDVs: +; Generate new random DVs + call BattleRandom + ld b, a + call BattleRandom + ld c, a + +.UpdateDVs: +; Input DVs in register bc + ld hl, wEnemyMonDVs + ld a, b + ld [hli], a + ld [hl], c + +; We've still got more to do if we're dealing with a wild monster + ld a, [wBattleMode] + dec a + jr nz, .Happiness + +; Species-specfic: + +; Unown + ld a, [wTempEnemyMonSpecies] + cp UNOWN + jr nz, .Magikarp + +; Get letter based on DVs + ld hl, wEnemyMonDVs + predef GetUnownLetter +; Can't use any letters that haven't been unlocked +; If combined with forced shiny battletype, causes an infinite loop + call CheckUnownLetter + jr c, .GenerateDVs ; try again + +.Magikarp: +; These filters are untranslated. +; They expect at wMagikarpLength a 2-byte value in mm, +; but the value is in feet and inches (one byte each). + +; The first filter is supposed to make very large Magikarp even rarer, +; by targeting those 1600 mm (= 5'3") or larger. +; After the conversion to feet, it is unable to target any, +; since the largest possible Magikarp is 5'3", and $0503 = 1283 mm. + ld a, [wTempEnemyMonSpecies] + cp MAGIKARP + jr nz, .Happiness + +; Get Magikarp's length + ld de, wEnemyMonDVs + ld bc, wPlayerID + callfar CalcMagikarpLength + +; No reason to keep going if length > 1536 mm (i.e. if HIGH(length) > 6 feet) + ld a, [wMagikarpLength] + cp HIGH(1536) ; should be "cp 5", since 1536 mm = 5'0", but HIGH(1536) = 6 + jr nz, .CheckMagikarpArea + +; 5% chance of skipping both size checks + call Random + cp 5 percent + jr c, .CheckMagikarpArea +; Try again if length >= 1616 mm (i.e. if LOW(length) >= 4 inches) + ld a, [wMagikarpLength + 1] + cp LOW(1616) ; should be "cp 4", since 1616 mm = 5'4", but LOW(1616) = 80 + jr nc, .GenerateDVs + +; 20% chance of skipping this check + call Random + cp 20 percent - 1 + jr c, .CheckMagikarpArea +; Try again if length >= 1600 mm (i.e. if LOW(length) >= 3 inches) + ld a, [wMagikarpLength + 1] + cp LOW(1600) ; should be "cp 3", since 1600 mm = 5'3", but LOW(1600) = 64 + jr nc, .GenerateDVs + +.CheckMagikarpArea: +; The "jr z" checks are supposed to be "jr nz". + +; Instead, all maps in GROUP_LAKE_OF_RAGE (Mahogany area) +; and Routes 20 and 44 are treated as Lake of Rage. + +; This also means Lake of Rage Magikarp can be smaller than ones +; caught elsewhere rather than the other way around. + +; Intended behavior enforces a minimum size at Lake of Rage. +; The real behavior prevents a minimum size in the Lake of Rage area. + +; Moreover, due to the check not being translated to feet+inches, all Magikarp +; smaller than 4'0" may be caught by the filter, a lot more than intended. + ld a, [wMapGroup] + cp GROUP_LAKE_OF_RAGE + jr z, .Happiness + ld a, [wMapNumber] + cp MAP_LAKE_OF_RAGE + jr z, .Happiness +; 40% chance of not flooring + call Random + cp 40 percent - 2 + jr c, .Happiness +; Try again if length < 1024 mm (i.e. if HIGH(length) < 3 feet) + ld a, [wMagikarpLength] + cp HIGH(1024) ; should be "cp 3", since 1024 mm = 3'4", but HIGH(1024) = 4 + jr c, .GenerateDVs ; try again + +; Finally done with DVs + +.Happiness: +; Set happiness + ld a, BASE_HAPPINESS + ld [wEnemyMonHappiness], a +; Set level + ld a, [wCurPartyLevel] + ld [wEnemyMonLevel], a +; Fill stats + ld de, wEnemyMonMaxHP + ld b, FALSE + ld hl, wEnemyMonDVs - (MON_DVS - MON_STAT_EXP + 1) ; wLinkBattleRNs + 7 ; ? + predef CalcMonStats + +; If we're in a trainer battle, +; get the rest of the parameters from the party struct + ld a, [wBattleMode] + cp TRAINER_BATTLE + jr z, .OpponentParty + +; If we're in a wild battle, check wild-specific stuff + and a + jr z, .TreeMon + + ld a, [wEnemySubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr nz, .Moves + +.TreeMon: +; If we're headbutting trees, some monsters enter battle asleep + ld a, [wTempEnemyMonSpecies] + +; Hoothoot/Noctowl are asleep if MORN/DAY + cp HOOTHOOT + jr z, .sleeping_if_not_nite + cp NOCTOWL + jr z, .sleeping_if_not_nite + +; Pidgey/Spearow are asleep if NITE + cp PIDGEY + jr z, .sleeping_if_nite + cp SPEAROW + jr z, .sleeping_if_nite + +; Other species are never asleep + jr .not_sleeping + +.sleeping_if_not_nite + ld a, [wTimeOfDay] + cp NITE_F + jr nz, .sleeping + jr .not_sleeping + +.sleeping_if_nite + ld a, [wTimeOfDay] + cp NITE_F + jr z, .sleeping + jr .not_sleeping + +.sleeping + ld a, TREEMON_SLEEP_TURNS + jr .UpdateStatus + +.not_sleeping + xor a + +.UpdateStatus: + ld hl, wEnemyMonStatus + ld [hli], a + +; Unused byte + xor a + ld [hli], a + +; Full HP.. + ld a, [wEnemyMonMaxHP] + ld [hli], a + ld a, [wEnemyMonMaxHP + 1] + ld [hl], a + +; ..unless it's a RoamMon + ld a, [wBattleType] + cp BATTLETYPE_ROAMING + jr nz, .Moves + +; Grab HP + call GetRoamMonHP + ld a, [hl] +; Check if it's been initialized again + and a + jr z, .InitRoamHP +; Update from the struct if it has + ld a, [hl] + ld [wEnemyMonHP + 1], a + jr .Moves + +.InitRoamHP: +; HP only uses the lo byte in the RoamMon struct since +; Raikou and Entei will have < 256 hp at level 40 + ld a, [wEnemyMonHP + 1] + ld [hl], a + jr .Moves + +.OpponentParty: +; Get HP from the party struct + ld hl, (wOTPartyMon1HP + 1) + ld a, [wCurPartyMon] + call GetPartyLocation + ld a, [hld] + ld [wEnemyMonHP + 1], a + ld a, [hld] + ld [wEnemyMonHP], a + +; Make sure everything knows which monster the opponent is using + ld a, [wCurPartyMon] + ld [wCurOTMon], a + +; Get status from the party struct + dec hl + ld a, [hl] ; OTPartyMonStatus + ld [wEnemyMonStatus], a + +.Moves: + ld hl, wBaseType1 + ld de, wEnemyMonType1 + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + +; Get moves + ld de, wEnemyMonMoves +; Are we in a trainer battle? + ld a, [wBattleMode] + cp TRAINER_BATTLE + jr nz, .WildMoves +; Then copy moves from the party struct + ld hl, wOTPartyMon1Moves + ld a, [wCurPartyMon] + call GetPartyLocation + ld bc, NUM_MOVES + call CopyBytes + jr .PP + +.WildMoves: +; Clear wEnemyMonMoves + xor a + ld h, d + ld l, e + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a +; Make sure the predef knows this isn't a partymon + ld [wEvolutionOldSpecies], a +; Fill moves based on level + predef FillMoves + +.PP: +; Trainer battle? + ld a, [wBattleMode] + cp TRAINER_BATTLE + jr z, .TrainerPP + +; Fill wild PP + ld hl, wEnemyMonMoves + ld de, wEnemyMonPP + predef FillPP + jr .Finish + +.TrainerPP: +; Copy PP from the party struct + ld hl, wOTPartyMon1PP + ld a, [wCurPartyMon] + call GetPartyLocation + ld de, wEnemyMonPP + ld bc, NUM_MOVES + call CopyBytes + +.Finish: +; Only the first five base stats are copied.. + ld hl, wBaseStats + ld de, wEnemyMonBaseStats + ld b, wBaseSpecialDefense - wBaseStats +.loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop + + ld a, [wBaseCatchRate] + ld [de], a + inc de + + ld a, [wBaseExp] + ld [de], a + + ld a, [wTempEnemyMonSpecies] + ld [wNamedObjectIndexBuffer], a + + call GetPokemonName + +; Did we catch it? + ld a, [wBattleMode] + and a + ret z + +; Update enemy nick + ld hl, wStringBuffer1 + ld de, wEnemyMonNick + ld bc, MON_NAME_LENGTH + call CopyBytes + +; Saw this mon + ld a, [wTempEnemyMonSpecies] + dec a + ld c, a + ld b, SET_FLAG + ld hl, wPokedexSeen + predef SmallFarFlagAction + + ld hl, wEnemyMonStats + ld de, wEnemyStats + ld bc, wEnemyMonStatsEnd - wEnemyMonStats + call CopyBytes + + ret + +CheckUnownLetter: +; Return carry if the Unown letter hasn't been unlocked yet + + ld a, [wUnlockedUnowns] + ld c, a + ld de, 0 + +.loop + +; Don't check this set unless it's been unlocked + srl c + jr nc, .next + +; Is our letter in the set? + ld hl, UnlockedUnownLetterSets + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + + push de + ld a, [wUnownLetter] + ld de, 1 + push bc + call IsInArray + pop bc + pop de + + jr c, .match + +.next +; Make sure we haven't gone past the end of the table + inc e + inc e + ld a, e + cp UnlockedUnownLetterSets.End - UnlockedUnownLetterSets + jr c, .loop + +; Hasn't been unlocked, or the letter is invalid + scf + ret + +.match +; Valid letter + and a + ret + +INCLUDE "data/wild/unlocked_unowns.asm" + +Unreferenced_SwapBattlerLevels: + push bc + ld a, [wBattleMonLevel] + ld b, a + ld a, [wEnemyMonLevel] + ld [wBattleMonLevel], a + ld a, b + ld [wEnemyMonLevel], a + pop bc + ret + +BattleWinSlideInEnemyTrainerFrontpic: + xor a + ld [wTempEnemyMonSpecies], a + call FinishBattleAnim + ld a, [wOtherTrainerClass] + ld [wTrainerClass], a + ld de, vTiles2 + callfar GetTrainerPic + hlcoord 19, 0 + ld c, 0 + +.outer_loop + inc c + ld a, c + cp 7 + ret z + xor a + ldh [hBGMapMode], a + ldh [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 + ldh [hBGMapMode], a + ld c, 4 + call DelayFrames + pop hl + pop bc + dec hl + jr .outer_loop + +.CopyColumn: + push hl + push de + push bc + ld e, 7 + +.loop + ld [hl], d + ld bc, SCREEN_WIDTH + add hl, bc + inc d + dec e + jr nz, .loop + + pop bc + pop de + pop hl + ret + +ApplyStatusEffectOnPlayerStats: + ld a, 1 + jr ApplyStatusEffectOnStats + +ApplyStatusEffectOnEnemyStats: + xor a + +ApplyStatusEffectOnStats: + ldh [hBattleTurn], a + call ApplyPrzEffectOnSpeed + jp ApplyBrnEffectOnAttack + +ApplyPrzEffectOnSpeed: + ldh a, [hBattleTurn] + and a + jr z, .enemy + ld a, [wBattleMonStatus] + and 1 << PAR + ret z + ld hl, wBattleMonSpeed + 1 + ld a, [hld] + ld b, a + ld a, [hl] + srl a + rr b + srl a + rr b + ld [hli], a + or b + jr nz, .player_ok + ld b, $1 ; min speed + +.player_ok + ld [hl], b + ret + +.enemy + ld a, [wEnemyMonStatus] + and 1 << PAR + ret z + ld hl, wEnemyMonSpeed + 1 + ld a, [hld] + ld b, a + ld a, [hl] + srl a + rr b + srl a + rr b + ld [hli], a + or b + jr nz, .enemy_ok + ld b, $1 ; min speed + +.enemy_ok + ld [hl], b + ret + +ApplyBrnEffectOnAttack: + ldh a, [hBattleTurn] + and a + jr z, .enemy + ld a, [wBattleMonStatus] + and 1 << BRN + ret z + ld hl, wBattleMonAttack + 1 + ld a, [hld] + ld b, a + ld a, [hl] + srl a + rr b + ld [hli], a + or b + jr nz, .player_ok + ld b, $1 ; min attack + +.player_ok + ld [hl], b + ret + +.enemy + ld a, [wEnemyMonStatus] + and 1 << BRN + ret z + ld hl, wEnemyMonAttack + 1 + ld a, [hld] + ld b, a + ld a, [hl] + srl a + rr b + ld [hli], a + or b + jr nz, .enemy_ok + ld b, $1 ; min attack + +.enemy_ok + ld [hl], b + ret + +ApplyStatLevelMultiplierOnAllStats: +; Apply StatLevelMultipliers on all 5 Stats + ld c, 0 +.stat_loop + call ApplyStatLevelMultiplier + inc c + ld a, c + cp NUM_BATTLE_STATS + jr nz, .stat_loop + ret + +ApplyStatLevelMultiplier: + push bc + push bc + ld a, [wApplyStatLevelMultipliersToEnemy] + and a + ld a, c + ld hl, wBattleMonAttack + ld de, wPlayerStats + ld bc, wPlayerAtkLevel + jr z, .got_pointers + ld hl, wEnemyMonAttack + ld de, wEnemyStats + ld bc, wEnemyAtkLevel + +.got_pointers + add c + ld c, a + jr nc, .okay + inc b +.okay + ld a, [bc] + pop bc + ld b, a + push bc + sla c + ld b, 0 + add hl, bc + ld a, c + add e + ld e, a + jr nc, .okay2 + inc d +.okay2 + pop bc + push hl + ld hl, StatLevelMultipliers_Applied + dec b + sla b + ld c, b + ld b, 0 + add hl, bc + xor a + ldh [hMultiplicand + 0], a + ld a, [de] + ldh [hMultiplicand + 1], a + inc de + ld a, [de] + ldh [hMultiplicand + 2], a + ld a, [hli] + ldh [hMultiplier], a + call Multiply + ld a, [hl] + ldh [hDivisor], a + ld b, 4 + call Divide + pop hl + +; Cap at 999. + ldh a, [hQuotient + 3] + sub LOW(MAX_STAT_VALUE) + ldh a, [hQuotient + 2] + sbc HIGH(MAX_STAT_VALUE) + jp c, .okay3 + + ld a, HIGH(MAX_STAT_VALUE) + ldh [hQuotient + 2], a + ld a, LOW(MAX_STAT_VALUE) + ldh [hQuotient + 3], a + +.okay3 + ldh a, [hQuotient + 2] + ld [hli], a + ld b, a + ldh a, [hQuotient + 3] + ld [hl], a + or b + jr nz, .okay4 + inc [hl] + +.okay4 + pop bc + ret + +INCLUDE "data/battle/stat_multipliers_2.asm" + +BadgeStatBoosts: +; Raise the stats of the battle mon in wBattleMon +; depending on which badges have been obtained. + +; Every other badge boosts a stat, starting from the first. +; GlacierBadge also boosts Special Defense, although the relevant code is buggy (see below). + +; ZephyrBadge: Attack +; PlainBadge: Speed +; MineralBadge: Defense +; GlacierBadge: Special Attack and 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, [wJohtoBadges] + +; Swap badges 3 (PlainBadge) and 5 (MineralBadge). + ld d, a + and (1 << PLAINBADGE) + add a + add a + ld b, a + ld a, d + and (1 << MINERALBADGE) + rrca + rrca + ld c, a + ld a, d + and ((1 << ZEPHYRBADGE) | (1 << HIVEBADGE) | (1 << FOGBADGE) | (1 << STORMBADGE) | (1 << GLACIERBADGE) | (1 << RISINGBADGE)) + or b + or c + ld b, a + + ld hl, wBattleMonAttack + ld c, 4 +.CheckBadge: + ld a, b + srl b + call c, BoostStat + inc hl + inc hl +; Check every other badge. + srl b + dec c + jr nz, .CheckBadge +; Check GlacierBadge again for Special Defense. +; This check is buggy because it assumes that a is set by the "ld a, b" in the above loop, +; but it can actually be overwritten by the call to BoostStat. + srl a + call c, BoostStat + ret + +BoostStat: +; Raise stat at hl by 1/8. + + ld a, [hli] + ld d, a + ld e, [hl] + srl d + rr e + srl d + rr e + srl d + rr e + ld a, [hl] + add e + ld [hld], a + ld a, [hl] + adc d + ld [hli], a + +; Cap at 999. + ld a, [hld] + sub LOW(MAX_STAT_VALUE) + ld a, [hl] + sbc HIGH(MAX_STAT_VALUE) + ret c + ld a, HIGH(MAX_STAT_VALUE) + ld [hli], a + ld a, LOW(MAX_STAT_VALUE) + ld [hld], a + ret + +_LoadBattleFontsHPBar: + callfar LoadBattleFontsHPBar + ret + +_LoadHPBar: + callfar LoadHPBar + ret + +Unreferenced_LoadHPExpBarGFX: + ld de, EnemyHPBarBorderGFX + ld hl, vTiles2 tile $6c + lb bc, BANK(EnemyHPBarBorderGFX), 4 + call Get1bpp + ld de, HPExpBarBorderGFX + ld hl, vTiles2 tile $73 + lb bc, BANK(HPExpBarBorderGFX), 6 + call Get1bpp + ld de, ExpBarGFX + ld hl, vTiles2 tile $55 + lb bc, BANK(ExpBarGFX), 8 + jp Get2bpp + +EmptyBattleTextbox: + ld hl, .empty + jp PrintText + +.empty: + text_end + +_BattleRandom:: +; If the normal RNG is used in a link battle it'll desync. +; To circumvent this a shared PRNG is used instead. + +; But if we're in a non-link battle we're safe to use it + ld a, [wLinkMode] + and a + jp z, Random + +; The PRNG operates in streams of 10 values. + +; Which value are we trying to pull? + push hl + push bc + ld a, [wLinkBattleRNCount] + ld c, a + ld b, 0 + ld hl, wLinkBattleRNs + add hl, bc + inc a + ld [wLinkBattleRNCount], a + +; If we haven't hit the end yet, we're good + cp 10 - 1 ; Exclude last value. See the closing comment + ld a, [hl] + pop bc + pop hl + ret c + +; If we have, we have to generate new pseudorandom data +; Instead of having multiple PRNGs, ten seeds are used + push hl + push bc + push af + +; Reset count to 0 + xor a + ld [wLinkBattleRNCount], a + ld hl, wLinkBattleRNs + ld b, 10 ; number of seeds + +; Generate next number in the sequence for each seed +; a[n+1] = (a[n] * 5 + 1) % 256 +.loop + ; get last # + ld a, [hl] + + ; a * 5 + 1 + ld c, a + add a + add a + add c + inc a + + ; update # + ld [hli], a + dec b + jr nz, .loop + +; This has the side effect of pulling the last value first, +; then wrapping around. As a result, when we check to see if +; we've reached the end, we check the one before it. + + pop af + pop bc + pop hl + ret + +Call_PlayBattleAnim_OnlyIfVisible: + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + ret nz + +Call_PlayBattleAnim: + ld a, e + ld [wFXAnimID], a + ld a, d + ld [wFXAnimID + 1], a + call WaitBGMap + predef_jump PlayBattleAnim + +FinishBattleAnim: + 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 + +GiveExperiencePoints: +; Give experience. +; Don't give experience if linked or in the Battle Tower. + ld a, [wLinkMode] + and a + ret nz + + call .EvenlyDivideExpAmongParticipants + xor a + ld [wCurPartyMon], a + ld bc, wPartyMon1Species + +.loop + ld hl, MON_HP + add hl, bc + ld a, [hli] + or [hl] + jp z, .next_mon ; fainted + + push bc + ld hl, wBattleParticipantsNotFainted + ld a, [wCurPartyMon] + ld c, a + ld b, CHECK_FLAG + ld d, 0 + predef SmallFarFlagAction + ld a, c + and a + pop bc + jp z, .next_mon + +; give stat exp + ld hl, MON_STAT_EXP + 1 + add hl, bc + ld d, h + ld e, l + ld hl, wEnemyMonBaseStats - 1 + push bc + ld c, NUM_EXP_STATS +.stat_exp_loop + inc hl + ld a, [de] + add [hl] + ld [de], a + jr nc, .no_carry_stat_exp + dec de + ld a, [de] + inc a + jr z, .stat_exp_maxed_out + ld [de], a + inc de + +.no_carry_stat_exp + push hl + push bc + ld a, MON_PKRUS + call GetPartyParamLocation + ld a, [hl] + and a + pop bc + pop hl + jr z, .stat_exp_awarded + ld a, [de] + add [hl] + ld [de], a + jr nc, .stat_exp_awarded + dec de + ld a, [de] + inc a + jr z, .stat_exp_maxed_out + ld [de], a + inc de + jr .stat_exp_awarded + +.stat_exp_maxed_out + ld a, $ff + ld [de], a + inc de + ld [de], a + +.stat_exp_awarded + inc de + inc de + dec c + jr nz, .stat_exp_loop + xor a + ldh [hMultiplicand + 0], a + ldh [hMultiplicand + 1], a + ld a, [wEnemyMonBaseExp] + ldh [hMultiplicand + 2], a + ld a, [wEnemyMonLevel] + ldh [hMultiplier], a + call Multiply + ld a, 7 + ldh [hDivisor], a + ld b, 4 + call Divide +; Boost Experience for traded Pokemon + pop bc + ld hl, MON_ID + add hl, bc + ld a, [wPlayerID] + cp [hl] + jr nz, .boosted + inc hl + ld a, [wPlayerID + 1] + cp [hl] + ld a, 0 + jr z, .no_boost + +.boosted + call BoostExp + ld a, 1 + +.no_boost +; Boost experience for a Trainer Battle + ld [wStringBuffer2 + 2], a + ld a, [wBattleMode] + dec a + call nz, BoostExp +; Boost experience for Lucky Egg + push bc + ld a, MON_ITEM + call GetPartyParamLocation + ld a, [hl] + cp LUCKY_EGG + call z, BoostExp + ldh a, [hQuotient + 3] + ld [wStringBuffer2 + 1], a + ldh a, [hQuotient + 2] + ld [wStringBuffer2], a + ld a, [wCurPartyMon] + ld hl, wPartyMonNicknames + call GetNick + ld hl, Text_MonGainedExpPoint + call PrintText + ld a, [wStringBuffer2 + 1] + ldh [hQuotient + 3], a + ld a, [wStringBuffer2] + ldh [hQuotient + 2], a + pop bc + call AnimateExpBar + push bc + call LoadTilemapToTempTilemap + pop bc + ld hl, MON_EXP + 2 + add hl, bc + ld d, [hl] + ldh a, [hQuotient + 3] + add d + ld [hld], a + ld d, [hl] + ldh a, [hQuotient + 2] + adc d + ld [hl], a + jr nc, .no_exp_overflow + dec hl + inc [hl] + +.no_exp_overflow + ld a, [wCurPartyMon] + ld e, a + ld d, 0 + ld hl, wPartySpecies + add hl, de + ld a, [hl] + ld [wCurSpecies], a + call GetBaseData + push bc + ld d, MAX_LEVEL + callfar CalcExpAtLevel + pop bc + ld hl, MON_EXP + 2 + add hl, bc + push bc + ldh a, [hQuotient + 1] + ld b, a + ldh a, [hQuotient + 2] + ld c, a + ldh a, [hQuotient + 3] + 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 +; Check if the mon leveled up + xor a ; PARTYMON + ld [wMonType], a + predef CopyMonToTempMon + callfar CalcLevel + pop bc + ld hl, MON_LEVEL + add hl, bc + ld a, [hl] + cp d + jp z, .next_mon +; <NICKNAME> grew to level ##! + ld [wTempLevel], a + ld a, [wCurPartyLevel] + push af + ld a, d + ld [wCurPartyLevel], a + ld [hl], a + ld hl, MON_SPECIES + add hl, bc + ld a, [hl] + ld [wCurSpecies], a + ld [wTempSpecies], a ; unused? + call GetBaseData + ld hl, MON_MAXHP + 1 + add hl, bc + ld a, [hld] + ld e, a + ld d, [hl] + push de + ld hl, MON_MAXHP + add hl, bc + ld d, h + ld e, l + ld hl, MON_STAT_EXP - 1 + add hl, bc + push bc + ld b, TRUE + predef CalcMonStats + pop bc + pop de + ld hl, MON_MAXHP + 1 + add hl, bc + ld a, [hld] + sub e + ld e, a + ld a, [hl] + sbc d + ld d, a + dec hl + ld a, [hl] + add e + ld [hld], a + ld a, [hl] + adc d + ld [hl], a + ld a, [wCurBattleMon] + ld d, a + ld a, [wCurPartyMon] + cp d + jr nz, .skip_active_mon_update + ld de, wBattleMonHP + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + ld de, wBattleMonMaxHP + push bc + ld bc, PARTYMON_STRUCT_LENGTH - MON_MAXHP + call CopyBytes + pop bc + ld hl, MON_LEVEL + add hl, bc + ld a, [hl] + ld [wBattleMonLevel], a + ld a, [wPlayerSubStatus5] + bit SUBSTATUS_TRANSFORMED, a + jr nz, .transformed + ld hl, MON_ATK + add hl, bc + ld de, wPlayerStats + ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK + call CopyBytes + +.transformed + xor a ; FALSE + ld [wApplyStatLevelMultipliersToEnemy], a + call ApplyStatLevelMultiplierOnAllStats + callfar ApplyStatusEffectOnPlayerStats + callfar BadgeStatBoosts + callfar UpdatePlayerHUD + call EmptyBattleTextbox + call LoadTilemapToTempTilemap + ld a, $1 + ldh [hBGMapMode], a + +.skip_active_mon_update + ; level up happiness mod + ld c, 1 + callfar ChangeHappiness + ld a, [wCurBattleMon] + ld b, a + ld a, [wCurPartyMon] + cp b + jr z, .skip_exp_bar_animation + ld de, SFX_HIT_END_OF_EXP_BAR + call PlaySFX + call WaitSFX + ld hl, BattleText_StringBuffer1GrewToLevel + call StdBattleTextbox + call LoadTilemapToTempTilemap + +.skip_exp_bar_animation + xor a ; PARTYMON + ld [wMonType], a + predef CopyMonToTempMon + hlcoord 9, 0 + ld b, 10 + ld c, 9 + call Textbox + hlcoord 11, 1 + ld bc, 4 + predef PrintTempMonStats + ld c, 30 + call DelayFrames + call WaitPressAorB_BlinkCursor + call SafeLoadTempTilemapToTilemap + xor a ; PARTYMON + ld [wMonType], a + ld a, [wCurSpecies] + ld [wTempSpecies], a ; unused? + ld a, [wCurPartyLevel] + push af + ld c, a + ld a, [wTempLevel] + ld b, a + +.level_loop + inc b + ld a, b + ld [wCurPartyLevel], a + push bc + predef LearnLevelMoves + pop bc + ld a, b + cp c + jr nz, .level_loop + pop af + ld [wCurPartyLevel], a + ld hl, wEvolvableFlags + ld a, [wCurPartyMon] + ld c, a + ld b, SET_FLAG + predef SmallFarFlagAction + pop af + ld [wCurPartyLevel], a + +.next_mon + ld a, [wPartyCount] + ld b, a + ld a, [wCurPartyMon] + inc a + cp b + jr z, .done + ld [wCurPartyMon], a + ld a, MON_SPECIES + call GetPartyParamLocation + ld b, h + ld c, l + jp .loop + +.done + jp ResetBattleParticipants + +.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 [wTempByteValue], a + ld hl, wEnemyMonBaseStats + ld c, wEnemyMonEnd - wEnemyMonBaseStats +.base_stat_division_loop + xor a + ldh [hDividend + 0], a + ld a, [hl] + ldh [hDividend + 1], a + ld a, [wTempByteValue] + ldh [hDivisor], a + ld b, 2 + call Divide + ldh a, [hQuotient + 3] + ld [hli], a + dec c + jr nz, .base_stat_division_loop + ret + +BoostExp: +; Multiply experience by 1.5x + push bc +; load experience value + ldh a, [hProduct + 2] + ld b, a + ldh a, [hProduct + 3] + ld c, a +; halve it + srl b + rr c +; add it back to the whole exp value + add c + ldh [hProduct + 3], a + ldh a, [hProduct + 2] + adc b + ldh [hProduct + 2], a + pop bc + ret + +Text_MonGainedExpPoint: + text_far Text_Gained + text_asm + ld hl, ExpPointsText + ld a, [wStringBuffer2 + 2] ; IsTradedMon + and a + ret z + + ld hl, BoostedExpPointsText + ret + +BoostedExpPointsText: + text_far _BoostedExpPointsText + text_end + +ExpPointsText: + text_far _ExpPointsText + text_end + +AnimateExpBar: + push bc + + ld hl, wCurPartyMon + ld a, [wCurBattleMon] + cp [hl] + jp nz, .finish + + ld a, [wBattleMonLevel] + cp MAX_LEVEL + jp z, .finish + + ldh a, [hProduct + 3] + ld [wceef], a + push af + ldh a, [hProduct + 2] + ld [wceee], a + push af + xor a + ld [wceed], a + xor a ; PARTYMON + ld [wMonType], a + predef CopyMonToTempMon + ld a, [wTempMonLevel] + ld b, a + ld e, a + push de + ld de, wTempMonExp + 2 + call CalcExpBar + push bc + ld hl, wTempMonExp + 2 + ld a, [wceef] + add [hl] + ld [hld], a + ld a, [wceee] + adc [hl] + ld [hld], a + jr nc, .NoOverflow + inc [hl] + +.NoOverflow: + ld d, MAX_LEVEL + callfar CalcExpAtLevel + ldh a, [hProduct + 1] + ld b, a + ldh a, [hProduct + 2] + ld c, a + ldh a, [hProduct + 3] + ld d, a + ld hl, wTempMonExp + 2 + ld a, [hld] + sub d + ld a, [hld] + sbc c + ld a, [hl] + sbc b + jr c, .AlreadyAtMaxExp + ld a, b + ld [hli], a + ld a, c + ld [hli], a + ld a, d + ld [hld], a + +.AlreadyAtMaxExp: + callfar CalcLevel + ld a, d + pop bc + pop de + ld d, a + +.LoopLevels: + ld a, e + cp d + jr z, .FinishExpBar + inc a + ld [wTempMonLevel], a + ld [wCurPartyLevel], a + ld [wBattleMonLevel], a + push de + call .PlayExpBarSound + ld c, $40 + call .LoopBarAnimation + call PrintPlayerHUD + ld hl, wBattleMonNick + ld de, wStringBuffer1 + ld bc, MON_NAME_LENGTH + call CopyBytes + call TerminateExpBarSound + ld de, SFX_HIT_END_OF_EXP_BAR + call PlaySFX + farcall AnimateEndOfExpBar + call WaitSFX + ld hl, BattleText_StringBuffer1GrewToLevel + call StdBattleTextbox + pop de + inc e + ld b, $0 + jr .LoopLevels + +.FinishExpBar: + push bc + ld b, d + ld de, wTempMonExp + 2 + call CalcExpBar + ld a, b + pop bc + ld c, a + call .PlayExpBarSound + call .LoopBarAnimation + call TerminateExpBarSound + pop af + ldh [hProduct + 2], a + pop af + ldh [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 + ldh [hBGMapMode], a + ld c, d + call DelayFrames + xor a + ldh [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 + ldh [hBGMapMode], a + ld c, d + call DelayFrames + xor a + ldh [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 + ldh [hBGMapMode], a + ret + +SendOutMonText: + ld a, [wLinkMode] + and a + jr z, .not_linked + + ld hl, JumpText_GoMon ; If we're in a LinkBattle print just "Go <PlayerMon>" + + ld a, [wBattleHasJustStarted] ; unless this (unidentified) variable is set + and a + jr nz, .skip_to_textbox + +.not_linked +; Depending on the HP of the enemy mon, the game prints a different text + ld hl, wEnemyMonHP + ld a, [hli] + or [hl] + ld hl, JumpText_GoMon + jr z, .skip_to_textbox + + ; compute enemy helth remaining as a percentage + xor a + ldh [hMultiplicand + 0], a + ld hl, wEnemyMonHP + ld a, [hli] + ld [wEnemyHPAtTimeOfPlayerSwitch], a + ldh [hMultiplicand + 1], a + ld a, [hl] + ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a + ldh [hMultiplicand + 2], a + ld a, 25 + ldh [hMultiplier], a + call Multiply + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b + ld a, b + ld b, 4 + ldh [hDivisor], a + call Divide + + ldh a, [hQuotient + 3] + ld hl, JumpText_GoMon + cp 70 + jr nc, .skip_to_textbox + + ld hl, JumpText_DoItMon + cp 40 + jr nc, .skip_to_textbox + + ld hl, JumpText_GoForItMon + cp 10 + jr nc, .skip_to_textbox + + ld hl, JumpText_YourFoesWeakGetmMon +.skip_to_textbox + jp PrintText + +JumpText_GoMon: + text_far Text_GoMon + text_end + +JumpText_DoItMon: + text_far Text_DoItMon + text_end + +JumpText_GoForItMon: + text_far Text_GoForItMon + text_end + +JumpText_YourFoesWeakGetmMon: + text_far Text_YourFoesWeakGetmMon + text_end + +WithdrawMonText: + ld hl, .WithdrawMonText + jp PrintText + +.WithdrawMonText: + text_far Text_BattleMonNickComma + text_asm +; Print text to withdraw mon +; depending on HP the message is different + push de + push bc + ld hl, wEnemyMonHP + 1 + ld de, wEnemyHPAtTimeOfPlayerSwitch + 1 + ld b, [hl] + dec hl + ld a, [de] + sub b + ldh [hMultiplicand + 2], a + dec de + ld b, [hl] + ld a, [de] + sbc b + ldh [hMultiplicand + 1], a + ld a, 25 + ldh [hMultiplier], a + call Multiply + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b + ld a, b + ld b, 4 + ldh [hDivisor], a + call Divide + pop bc + pop de + ldh a, [hQuotient + 3] + ld hl, ThatsEnoughComeBackText + and a + ret z + + ld hl, ComeBackText + cp 30 + ret c + + ld hl, OKComeBackText + cp 70 + ret c + + ld hl, GoodComeBackText + ret + +ThatsEnoughComeBackText: + text_far _ThatsEnoughComeBackText + text_end + +OKComeBackText: + text_far _OKComeBackText + text_end + +GoodComeBackText: + text_far _GoodComeBackText + text_end + +ComeBackText: + text_far _ComeBackText + text_end + +Unreferenced_HandleSafariAngerEatingStatus: + ld hl, wSafariMonEating + ld a, [hl] + and a + jr z, .angry + dec [hl] + ld hl, BattleText_WildMonIsEating + jr .finish + +.angry + dec hl ; wSafariMonAngerCount + ld a, [hl] + and a + ret z + dec [hl] + ld hl, BattleText_WildMonIsAngry + jr nz, .finish + push hl + ld a, [wEnemyMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseCatchRate] + ld [wEnemyMonCatchRate], a + pop hl + +.finish + push hl + call SafeLoadTempTilemapToTilemap + pop hl + jp StdBattleTextbox + +FillInExpBar: + push hl + call CalcExpBar + pop hl + ld de, 7 + add hl, de + jp PlaceExpBar + +CalcExpBar: +; Calculate the percent exp between this level and the next +; Level in b + push de + ld d, b + push de + callfar CalcExpAtLevel + pop de +; exp at current level gets pushed to the stack + ld hl, hMultiplicand + ld a, [hli] + push af + ld a, [hli] + push af + ld a, [hl] + push af +; next level + inc d + callfar CalcExpAtLevel +; back up the next level exp, and subtract the two levels + ld hl, hMultiplicand + 2 + ld a, [hl] + ldh [hMathBuffer + 2], a + pop bc + sub b + ld [hld], a + ld a, [hl] + ldh [hMathBuffer + 1], a + pop bc + sbc b + ld [hld], a + ld a, [hl] + ldh [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 + ldh a, [hMathBuffer + 2] + sub c + ld [hld], a + ld a, [de] + dec de + ld b, a + ldh a, [hMathBuffer + 1] + sbc b + ld [hld], a + ld a, [de] + ld c, a + ldh a, [hMathBuffer] + sbc c + ld [hld], a + xor a + ld [hl], a + ld a, 64 + ldh [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 + ldh [hDivisor], a + ld b, 4 + call Divide + ldh a, [hQuotient + 3] + ld b, a + ld a, $40 + sub b + ld b, a + ret + +PlaceExpBar: + 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 + +GetBattleMonBackpic: + ld a, [wPlayerSubStatus4] + bit SUBSTATUS_SUBSTITUTE, a + ld hl, BattleAnimCmd_RaiseSub + jr nz, GetBattleMonBackpic_DoAnim ; substitute + +DropPlayerSub: + ld a, [wPlayerMinimized] + and a + ld hl, BattleAnimCmd_MinimizeOpp + jr nz, GetBattleMonBackpic_DoAnim + ld a, [wCurPartySpecies] + push af + ld a, [wBattleMonSpecies] + ld [wCurPartySpecies], a + ld hl, wBattleMonDVs + predef GetUnownLetter + ld de, vTiles2 tile $31 + predef GetMonBackpic + pop af + ld [wCurPartySpecies], a + ret + +GetBattleMonBackpic_DoAnim: + ldh a, [hBattleTurn] + push af + xor a + ldh [hBattleTurn], a + ld a, BANK("Move Animations") + rst FarCall + pop af + ldh [hBattleTurn], a + ret + +GetEnemyMonFrontpic: + ld a, [wEnemySubStatus4] + bit SUBSTATUS_SUBSTITUTE, a + ld hl, BattleAnimCmd_RaiseSub + jr nz, GetEnemyMonFrontpic_DoAnim + +DropEnemySub: + ld a, [wEnemyMinimized] + and a + ld hl, BattleAnimCmd_MinimizeOpp + jr nz, GetEnemyMonFrontpic_DoAnim + + ld a, [wCurPartySpecies] + push af + ld a, [wEnemyMonSpecies] + ld [wCurSpecies], a + ld [wCurPartySpecies], a + call GetBaseData + ld hl, wEnemyMonDVs + predef GetUnownLetter + ld de, vTiles2 + predef GetMonFrontpic + pop af + ld [wCurPartySpecies], a + ret + +GetEnemyMonFrontpic_DoAnim: + ldh a, [hBattleTurn] + push af + call SetEnemyTurn + ld a, BANK(BattleAnimCmd_MinimizeOpp) + rst FarCall + pop af + ldh [hBattleTurn], a + ret + +StartBattle: +; This check prevents you from entering a battle without any Pokemon. +; Those using walk-through-walls to bypass getting a Pokemon experience +; the effects of this check. + ld a, [wPartyCount] + and a + ret z + + ld a, [wOtherTrainerClass] + and a + jr nz, .battle_intro + + ld a, [wTempWildMonSpecies] + ld [wCurPartySpecies], a + +.battle_intro + ld [wTempEnemyMonSpecies], a + ld a, [wTimeOfDayPal] + push af + xor a + ldh [hMapAnims], a + xor a + ld [wTempBattleMonSpecies], a + ld [wBattleMenuCursorBuffer], a + farcall PlayBattleMusic + ld a, 0 + ld [wSpriteUpdatesEnabled], a + call ShowLinkBattleParticipants + farcall ClearBattleRAM + ld hl, rLCDC + res rLCDC_WINDOW_TILEMAP, [hl] ; select 9800-9BFF + ld a, [wOtherTrainerClass] + and a + jr nz, .trainer + + call InitEnemyWildmon + jr .back_up_bgmap2 + +.trainer + call InitEnemyTrainer + +.back_up_bgmap2 + ld b, 0 + call GetSGBLayout + ld hl, wVramState + res 0, [hl] + call InitBattleDisplay + call BattleStartMessage + xor a + ldh [hBGMapMode], a + ld hl, rLCDC + set rLCDC_WINDOW_TILEMAP, [hl] ; select 9C00-9FFF + call EmptyBattleTextbox + hlcoord 9, 7 + lb bc, 5, 11 + call ClearBox + hlcoord 1, 0 + lb bc, 4, 10 + call ClearBox + call ClearSprites + ld a, [wEnemyMonEnd] + cp WILD_BATTLE + call z, UpdateEnemyHUD + ld a, $1 + ldh [hBGMapMode], a + call DoBattle + call ExitBattle + pop af + ld [wTimeOfDayPal], a + scf + ret + +InitEnemyTrainer: + ld [wTrainerClass], a + xor a + ld [wTempEnemyMonSpecies], a + callfar GetTrainerAttributes + callfar ReadTrainerParty + + ; RIVAL1's first mon has no held item + ld a, [wTrainerClass] + cp RIVAL1 + jr nz, .ok + xor a + ld [wOTPartyMon1Item], a + +.ok: + ld de, vTiles2 + callfar GetTrainerPic + xor a + ldh [hGraphicStartTile], a + dec a + ld [wEnemyItemState], a + hlcoord 12, 0 + lb bc, 7, 7 + predef PlaceGraphic + ld a, -1 + ld [wCurOTMon], a + ld a, TRAINER_BATTLE + ld [wBattleMode], a + + call IsGymLeader + jr nc, .done + xor a + ld [wCurPartyMon], a + ld a, [wPartyCount] + ld b, a +.partyloop + push bc + ld a, MON_HP + call GetPartyParamLocation + ld a, [hli] + or [hl] + jr z, .skipfaintedmon + ld c, HAPPINESS_GYMBATTLE + callfar ChangeHappiness +.skipfaintedmon + pop bc + dec b + jr z, .done + ld hl, wCurPartyMon + inc [hl] + jr .partyloop +.done + ret + +InitEnemyWildmon: + ld a, WILD_BATTLE + ld [wBattleMode], a + call LoadEnemyMon + ld hl, wEnemyMonMoves + ld de, wWildMonMoves + ld bc, NUM_MOVES + call CopyBytes + ld hl, wEnemyMonPP + ld de, wWildMonPP + ld bc, NUM_MOVES + call CopyBytes + ld hl, wEnemyMonDVs + predef GetUnownLetter + ld a, [wCurPartySpecies] + cp UNOWN + jr nz, .skip_unown + ld a, [wFirstUnownSeen] + and a + jr nz, .skip_unown + ld a, [wUnownLetter] + ld [wFirstUnownSeen], a +.skip_unown + ld de, vTiles2 + predef GetMonFrontpic + xor a + ld [wTrainerClass], a + ldh [hGraphicStartTile], a + hlcoord 12, 0 + lb bc, 7, 7 + predef PlaceGraphic + ret + +Unreferenced_Function3f41a: + ld hl, wEnemyMonMoves + ld de, wListMoves_MoveIndicesBuffer + ld b, NUM_MOVES +.loop + ld a, [de] + inc de + ld [hli], a + and a + jr z, .clearpp + + push bc + push hl + + push hl + dec a + ld hl, Moves + MOVE_PP + ld bc, MOVE_LENGTH + call AddNTimes + ld a, BANK(Moves) + call GetFarByte + pop hl + + ld bc, wEnemyMonPP - (wEnemyMonMoves + 1) + add hl, bc + ld [hl], a + + pop hl + pop bc + + dec b + jr nz, .loop + ret + +.clear + xor a + ld [hli], a + +.clearpp + push bc + push hl + ld bc, wEnemyMonPP - (wEnemyMonMoves + 1) + add hl, bc + xor a + ld [hl], a + pop hl + pop bc + dec b + jr nz, .clear + ret + +ExitBattle: + call IsLinkBattle + jr nz, .handle_end_of_battle + call ShowLinkBattleParticipantsAfterEnd + jr .clean_up_battle_ram + +.handle_end_of_battle + ld a, [wBattleResult] + and $f + jr nz, .clean_up_battle_ram + ; WIN + call CheckPayDay + xor a + ld [wForceEvolution], a + predef EvolveAfterBattle + farcall GivePokerusAndConvertBerries + +.clean_up_battle_ram + call BattleEnd_HandleRoamMons + xor a + ld [wLowHealthAlarm], a + ld [wBattleMode], a + ld [wBattleType], a + ld [wAttackMissed], a + ld [wTempWildMonSpecies], a + ld [wOtherTrainerClass], a + ld [wFailedToFlee], a + ld [wNumFleeAttempts], a + ld [wForcedSwitch], a + ld [wPartyMenuCursor], a + ld [wKeyItemsPocketCursor], a + ld [wItemsPocketCursor], a + ld [wBattleMenuCursorBuffer], a + ld [wCurMoveNum], a + ld [wBallsPocketCursor], a + ld [wLastPocket], a + ld [wMenuScrollPosition], a + ld [wKeyItemsPocketScrollPosition], a + ld [wItemsPocketScrollPosition], a + ld [wBallsPocketScrollPosition], a + ld hl, wPlayerSubStatus1 + ld b, wEnemyFuryCutterCount - wPlayerSubStatus1 +.loop + ld [hli], a + dec b + jr nz, .loop + call WaitSFX + ret + +CheckPayDay: + ld hl, wPayDayMoney + ld a, [hli] + or [hl] + inc hl + or [hl] + ret z + ld a, [wAmuletCoin] + and a + jr z, .okay + ld hl, wPayDayMoney + 2 + sla [hl] + dec hl + rl [hl] + dec hl + rl [hl] + jr nc, .okay + ld a, $ff + ld [hli], a + ld [hli], a + ld [hl], a + +.okay + ld hl, wPayDayMoney + 2 + ld de, wMoney + 2 + call AddBattleMoneyToAccount + ld hl, BattleText_PlayerPickedUpPayDayMoney + call StdBattleTextbox + ret + +PlayerPickedUpPayDayMoney: + text_far _PlayerPickedUpPayDayMoney + text_end + +ShowLinkBattleParticipantsAfterEnd: + ld a, [wCurOTMon] + ld hl, wOTPartyMon1Status + call GetPartyLocation + ld a, [wEnemyMonStatus] + ld [hl], a + call ClearTilemap + farcall _ShowLinkBattleParticipants + ld a, [wBattleResult] + and $f + cp LOSE + ld de, .Win + jr c, .store_result + ld de, .Lose + jr z, .store_result + ; DRAW + ld de, .Draw + +.store_result + hlcoord 6, 8 + call PlaceString + ld c, 200 + call DelayFrames + + ld a, BANK(sLinkBattleStats) + call OpenSRAM + + call AddLastMobileBattleToLinkRecord + call ReadAndPrintLinkBattleRecord + + call CloseSRAM + + call WaitPressAorB_BlinkCursor + call ClearTilemap + ret + +.Win: + db "YOU WIN@" +.Lose: + db "YOU LOSE@" +.Draw: + db " DRAW@" + +_DisplayLinkRecord: + ld a, BANK(sLinkBattleStats) + call OpenSRAM + + call ReadAndPrintLinkBattleRecord + + call CloseSRAM + hlcoord 0, 0, wAttrmap + xor a + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + call ByteFill + call WaitBGMap2 + ld b, SCGB_DIPLOMA + call GetSGBLayout + call SetPalettes + ld c, 8 + call DelayFrames + call WaitPressAorB_BlinkCursor + ret + +ReadAndPrintLinkBattleRecord: + call ClearTilemap + call ClearSprites + call .PrintBattleRecord + hlcoord 0, 8 + ld b, 5 + ld de, sLinkBattleRecord + 2 +.loop + push bc + push hl + push de + ld a, [de] + and a + jr z, .PrintFormatString + ld a, [wSavedAtLeastOnce] + and a + jr z, .PrintFormatString + push hl + push hl + ld h, d + ld l, e + ld de, wceed + ld bc, 10 + call CopyBytes + ld a, "@" + ld [de], a + inc de + ld bc, 6 + call CopyBytes + ld de, wceed + pop hl + call PlaceString + pop hl + ld de, 26 + add hl, de + push hl + ld de, wcef8 + lb bc, 2, 4 + call PrintNum + pop hl + ld de, 5 + add hl, de + push hl + ld de, wcefa + lb bc, 2, 4 + call PrintNum + pop hl + ld de, 5 + add hl, de + ld de, wcefc + 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 + + 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 + ret + +.Scores: + db "<NULL><NULL>" +.Format: + db " --- <LF>" + db " - - -@" +.Record: + db "<PLAYER>'s RECORD@" +.Result: + db "RESULT WIN LOSE DRAW@" +.Total: + db "TOTAL WIN LOSE DRAW@" + +BattleEnd_HandleRoamMons: + ld a, [wBattleType] + cp BATTLETYPE_ROAMING + jr nz, .not_roaming + ld a, [wBattleResult] + and $f + jr z, .caught_or_defeated_roam_mon ; WIN + call GetRoamMonHP + ld a, [wEnemyMonHP + 1] + ld [hl], a + jr .update_roam_mons + +.caught_or_defeated_roam_mon + call GetRoamMonHP + ld [hl], 0 + call GetRoamMonMapGroup + ld [hl], GROUP_N_A + call GetRoamMonMapNumber + ld [hl], MAP_N_A + call GetRoamMonSpecies + ld [hl], 0 + ret + +.not_roaming + call BattleRandom + and $f + ret nz + +.update_roam_mons + callfar UpdateRoamMons + ret + +GetRoamMonMapGroup: + ld a, [wTempEnemyMonSpecies] + ld b, a + ld a, [wRoamMon1Species] + cp b + ld hl, wRoamMon1MapGroup + ret z + ld a, [wRoamMon2Species] + cp b + ld hl, wRoamMon2MapGroup + ret z + ld hl, wRoamMon3MapGroup + ret + +GetRoamMonMapNumber: + ld a, [wTempEnemyMonSpecies] + ld b, a + ld a, [wRoamMon1Species] + cp b + ld hl, wRoamMon1MapNumber + ret z + ld a, [wRoamMon2Species] + cp b + ld hl, wRoamMon2MapNumber + ret z + ld hl, wRoamMon3MapNumber + ret + +GetRoamMonHP: +; output: hl = wRoamMonHP + ld a, [wTempEnemyMonSpecies] + ld b, a + ld a, [wRoamMon1Species] + cp b + ld hl, wRoamMon1HP + ret z + ld a, [wRoamMon2Species] + cp b + ld hl, wRoamMon2HP + ret z + ld hl, wRoamMon3HP + ret + +GetRoamMonDVs: +; output: hl = wRoamMonDVs + ld a, [wTempEnemyMonSpecies] + ld b, a + ld a, [wRoamMon1Species] + cp b + ld hl, wRoamMon1DVs + ret z + ld a, [wRoamMon2Species] + cp b + ld hl, wRoamMon2DVs + ret z + ld hl, wRoamMon3DVs + ret + +GetRoamMonSpecies: + ld a, [wTempEnemyMonSpecies] + ld hl, wRoamMon1Species + cp [hl] + ret z + ld hl, wRoamMon2Species + cp [hl] + ret z + ld hl, wRoamMon3Species + ret + +AddLastMobileBattleToLinkRecord: + ld hl, wOTPlayerID + ld de, wStringBuffer1 + ld bc, 2 + call CopyBytes + ld hl, wOTPlayerName + ld bc, NAME_LENGTH - 1 + call CopyBytes + ld hl, sLinkBattleStats - 12 + call .StoreResult + ld hl, sLinkBattleRecord + ld d, 5 +.loop + push hl + inc hl + inc hl + ld a, [hl] + dec hl + dec hl + and a + jr z, .copy + push de + ld bc, 12 + ld de, wStringBuffer1 + call CompareBytesLong + pop de + pop hl + jr c, .done + ld bc, 18 + add hl, bc + dec d + jr nz, .loop + ld bc, -18 + add hl, bc + push hl + +.copy + ld d, h + ld e, l + ld hl, wStringBuffer1 + ld bc, 12 + call CopyBytes + ld b, 6 + xor a +.loop2 + ld [de], a + inc de + dec b + jr nz, .loop2 + pop hl + +.done + call .StoreResult + call .FindOpponentAndAppendRecord + ret +.StoreResult: + ld a, [wBattleResult] + and $f + cp LOSE + ld bc, sLinkBattleWins + 1 - (sLinkBattleStats - 12) + jr c, .okay ; WIN + ld bc, sLinkBattleLosses + 1 - (sLinkBattleStats - 12) + jr z, .okay ; LOSE + ; DRAW + ld bc, sLinkBattleDraws + 1 - (sLinkBattleStats - 12) +.okay + add hl, bc + call .CheckOverflow + ret nc + inc [hl] + ret nz + dec hl + inc [hl] + ret + +.CheckOverflow: + dec hl + ld a, [hl] + inc hl + cp HIGH(MAX_LINK_RECORD) + ret c + ld a, [hl] + cp LOW(MAX_LINK_RECORD) + ret + +.FindOpponentAndAppendRecord: + ld b, 5 + ld hl, sLinkBattleRecord + 17 + ld de, wceed +.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, wceed + add hl, de + push hl + ld a, c + add c + add c + ld e, a + ld d, $0 + ld hl, wceed + add hl, de + ld d, h + ld e, l + pop hl + push bc + ld c, 3 + call CompareBytes + 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, wceed + 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, wceed + ld bc, 18 + pop de + call CopyBytes + ret + +.LoadPointer: + ld e, $0 + ld a, [hld] + ld c, a + ld a, [hld] + ld b, a + ld a, [hld] + add c + ld c, a + ld a, [hld] + adc b + ld b, a + jr nc, .okay2 + inc e + +.okay2 + ld a, [hld] + add c + ld c, a + ld a, [hl] + adc b + ld b, a + ret nc + inc e + ret + +InitBattleDisplay: + call InitBackPic + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call Textbox + hlcoord 1, 5 + lb bc, 3, 7 + call ClearBox + call LoadStandardFont + call _LoadBattleFontsHPBar + call .BlankBGMap + xor a + ldh [hMapAnims], a + ldh [hSCY], a + ld a, $90 + ldh [hWY], a + ldh [rWY], a + call WaitBGMap + xor a + ldh [hBGMapMode], a + call BattleIntroSlidingPics + ld a, $1 + ldh [hBGMapMode], a + ld a, $31 + ldh [hGraphicStartTile], a + hlcoord 2, 6 + lb bc, 6, 6 + predef PlaceGraphic + xor a + ldh [hWY], a + ldh [rWY], a + call WaitBGMap + call HideSprites + ld b, SCGB_BATTLE_COLORS + call GetSGBLayout + call SetPalettes + ld a, $90 + ldh [hWY], a + xor a + ldh [hSCX], a + ret + +.BlankBGMap: + ld a, BANK(sDecompressScratch) + call OpenSRAM + + ld hl, sDecompressScratch + ld bc, sScratchAttrmap - sDecompressScratch + ld a, " " + call ByteFill + + ld de, sDecompressScratch + hlbgcoord 0, 0 + lb bc, BANK(.BlankBGMap), $40 + call Request2bpp + call CloseSRAM + ret + +INCLUDE "engine/battle/sliding_intro.asm" + +InitBackPic: + call GetTrainerBackpic + call CopyBackpic + ret + +GetTrainerBackpic: + ld hl, ChrisBackpic + ld a, [wBattleType] + cp BATTLETYPE_TUTORIAL + jr nz, .ok + ld hl, DudeBackpic + +.ok: + ld de, vTiles2 tile $31 + ld b, BANK(ChrisBackpic) + ld c, 7 * 7 + predef DecompressGet2bpp + ret + +CopyBackpic: + ld a, BANK(sDecompressBuffer) + call OpenSRAM + ld hl, vTiles3 + ld de, sDecompressBuffer + ldh a, [hROMBank] + ld b, a + ld c, 7 * 7 + call Request2bpp + call CloseSRAM + call .LoadTrainerBackpicAsOAM + ld a, 7 * 7 + ldh [hGraphicStartTile], a + hlcoord 2, 6 + lb bc, 6, 6 + predef PlaceGraphic + ret + +.LoadTrainerBackpicAsOAM: + ld hl, wVirtualOAMSprite00 + xor a + ldh [hMapObjectIndexBuffer], a + ld b, 6 + ld e, (SCREEN_WIDTH + 1) * TILE_WIDTH +.outer_loop + ld c, 3 + ld d, 8 * TILE_WIDTH +.inner_loop + ld [hl], d ; y + inc hl + ld [hl], e ; x + inc hl + ldh a, [hMapObjectIndexBuffer] + ld [hli], a ; tile id + inc a + ldh [hMapObjectIndexBuffer], a + ld a, PAL_BATTLE_OB_PLAYER + ld [hli], a ; attributes + ld a, d + add 1 * TILE_WIDTH + ld d, a + dec c + jr nz, .inner_loop + ldh a, [hMapObjectIndexBuffer] + add $3 + ldh [hMapObjectIndexBuffer], a + ld a, e + add 1 * TILE_WIDTH + ld e, a + dec b + jr nz, .outer_loop + ret + +ChrisBackpic: +INCBIN "gfx/player/chris_back.2bpp.lz" + +DudeBackpic: +INCBIN "gfx/battle/dude.2bpp.lz" + +BattleStartMessage: + ld a, [wBattleMode] + dec a + jr z, .wild + + ld de, SFX_SHINE + call PlaySFX + call WaitSFX + + ld c, 20 + call DelayFrames + + callfar Battle_GetTrainerName + + ld hl, WantsToBattleText + jr .PlaceBattleStartText + +.wild + call BattleCheckEnemyShininess + jr nc, .not_shiny + + xor a + ld [wNumHits], a + ld a, 1 + ldh [hBattleTurn], a + ld a, 1 + ld [wBattleAnimParam], a + ld de, ANIM_SEND_OUT_MON + call Call_PlayBattleAnim + +.not_shiny + ld a, $f + ld [wCryTracks], a + ld a, [wTempEnemyMonSpecies] + call PlayStereoCry + ld hl, HookedPokemonAttackedText + ld a, [wBattleType] + cp BATTLETYPE_FISH + jr z, .PlaceBattleStartText + ld hl, PokemonFellFromTreeText + cp BATTLETYPE_TREE + jr z, .PlaceBattleStartText + ld hl, WildPokemonAppearedText + +.PlaceBattleStartText: + push hl + farcall BattleStart_TrainerHuds + pop hl + call StdBattleTextbox + ret + +ShowLinkBattleParticipants: + call IsLinkBattle + jr nz, .ok + farcall _ShowLinkBattleParticipants + call ClearTilemap + call ClearSprites + +.ok + xor a + ldh [hMapAnims], a + call DelayFrame + predef DoBattleTransition + call _LoadBattleFontsHPBar + ld a, $1 + ldh [hBGMapMode], a + call ClearSprites + call ClearTilemap + xor a + ldh [hBGMapMode], a + ldh [hWY], a + ldh [rWY], a + ldh [hMapAnims], a + ret + +IsLinkBattle: + push bc + push af + ld a, [wLinkMode] + cp LINK_COLOSSEUM + pop bc + ld a, b + pop bc + ret diff --git a/engine/battle/sliding_intro.asm b/engine/battle/sliding_intro.asm new file mode 100644 index 00000000..f872a8de --- /dev/null +++ b/engine/battle/sliding_intro.asm @@ -0,0 +1,57 @@ +BattleIntroSlidingPics: + ld b, $70 + ld c, $90 + ld a, c + ldh [hSCX], a + call DelayFrame + ld a, %11100100 + call DmgToCgbBGPals + lb de, %11100100, %11100100 + call DmgToCgbObjPals + +.loop1 + push bc + ld h, b + ld l, $40 + call .subfunction2 + ld h, $00 + ld l, $60 + call .subfunction2 + call .subfunction1 + pop bc + ld a, c + ldh [hSCX], a + inc b + inc b + dec c + dec c + jr nz, .loop1 + ret + +.subfunction1 + push bc + ld hl, wVirtualOAMSprite00XCoord + ld c, $12 ; 18 + ld de, SPRITEOAMSTRUCT_LENGTH +.loop2 + dec [hl] + dec [hl] + add hl, de + dec c + jr nz, .loop2 + pop bc + ret + +.subfunction2 +.loop3 + ldh a, [rLY] + cp l + jr nz, .loop3 + ld a, h + ldh [rSCX], a + +.loop4 + ldh a, [rLY] + cp h + jr z, .loop4 + ret diff --git a/engine/events/specials.asm b/engine/events/specials.asm index 605346b4..e030f68a 100755 --- a/engine/events/specials.asm +++ b/engine/events/specials.asm @@ -241,7 +241,7 @@ UnownPrinter: ; c427 (3:4427) DisplayLinkRecord: ; c434 (3:4434) call FadeToMenu - farcall Function3f55d + farcall _DisplayLinkRecord call ExitAllMenus ret diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index 6735ec16..ac360409 100755 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -1023,7 +1023,7 @@ WaterStone: ; ee63 cp EVERSTONE jr z, .failed ld a, $1 - ld [wd0d2], a + ld [wForceEvolution], a farcall EvolvePokemon ; 10:61db ld a, [wd154] and a @@ -1218,7 +1218,7 @@ RareCandy: ; ef68 (3:6f68) ld [wd151], a predef LearnLevelMoves xor a - ld [wd0d2], a + ld [wForceEvolution], a farcall EvolvePokemon jp Functionf7dc @@ -2307,7 +2307,7 @@ Functionf6f6: ; f6f6 (3:76f6) jr z, .asm_f715 call Functionf72f jr z, .asm_f715 - ld hl, wcee1 + ld hl, wMenuCursorX inc [hl] .asm_f715 ld hl, wMenuCursorY @@ -2315,7 +2315,7 @@ Functionf6f6: ; f6f6 (3:76f6) pop bc dec b jr nz, .asm_f6fe - ld a, [wcee1] + ld a, [wMenuCursorX] and a jp nz, asm_f699 Functionf724: ; f724 (3:7724) diff --git a/engine/items/pack.asm b/engine/items/pack.asm index 8edd2555..5225362a 100755 --- a/engine/items/pack.asm +++ b/engine/items/pack.asm @@ -13,7 +13,7 @@ Pack: .asm_1044a ld a, [wce65] - ld [wcfc8], a + ld [wLastPocket], a ld hl, wOptions res NO_TEXT_SCROLL, [hl] ret @@ -58,15 +58,15 @@ Pack_InitItemsPocket: Pack_ItemsPocketMenu: ld hl, ItemsPocketMenuDataHeader call CopyMenuHeader - ld a, [wcfca] + ld a, [wItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfcf] + ld a, [wItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfcf], a + ld [wItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfca], a + ld [wItemsPocketCursor], a .asm_104b7 ld b, $7 ld c, $3 @@ -87,15 +87,15 @@ Pack_InitKeyItemsPocket: Pack_KeyItemsPocketMenu: ld hl, KeyItemsPocketMenuDataHeader ; $4e9a call CopyMenuHeader - ld a, [wcfcb] + ld a, [wKeyItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd0] + ld a, [wKeyItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd0], a + ld [wKeyItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcb], a + ld [wKeyItemsPocketCursor], a ld b, $3 ld c, $7 call Function10cef @@ -211,15 +211,15 @@ Pack_InitBallsPocket: Pack_BallsPocketMenu: ld hl, BallsPocketMenuDataHeader ; $4eca call CopyMenuHeader - ld a, [wcfcc] + ld a, [wBallsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd1] + ld a, [wBallsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd1], a + ld [wBallsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcc], a + ld [wBallsPocketCursor], a ld b, $1 ld c, $5 call Function10cef @@ -504,20 +504,20 @@ Function107cd: .asm_107da xor a - ld [wcfcc], a - ld [wcfd1], a + ld [wBallsPocketCursor], a + ld [wBallsPocketScrollPosition], a ret .asm_107e2 xor a - ld [wcfca], a - ld [wcfcf], a + ld [wItemsPocketCursor], a + ld [wItemsPocketScrollPosition], a ret .asm_107ea xor a - ld [wcfcb], a - ld [wcfd0], a + ld [wKeyItemsPocketCursor], a + ld [wKeyItemsPocketScrollPosition], a ret RegisterItem: @@ -630,7 +630,7 @@ BattlePack: .asm_108dd ld a, [wce65] - ld [wcfc8], a + ld [wLastPocket], a ld hl, wOptions res 4, [hl] ret @@ -675,15 +675,15 @@ BattlePack_InitItemsPocket: BattlePack_ItemsPocketMenu: ld hl, $4e6a call CopyMenuHeader - ld a, [wcfca] + ld a, [wItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfcf] + ld a, [wItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfcf], a + ld [wItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfca], a + ld [wItemsPocketCursor], a ld b, $7 ld c, $3 call Function10cef @@ -703,15 +703,15 @@ BattlePack_InitKeyItemsPocket: BattlePack_KeyItemsPocketMenu: ld hl, $4e9a call CopyMenuHeader - ld a, [wcfcb] + ld a, [wKeyItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd0] + ld a, [wKeyItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd0], a + ld [wKeyItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcb], a + ld [wKeyItemsPocketCursor], a ld b, $3 ld c, $7 call Function10cef @@ -754,15 +754,15 @@ BattlePack_InitBallsPocket: BattlePack_BallsPocketMenu: ld hl, $4eca call CopyMenuHeader - ld a, [wcfcc] + ld a, [wBallsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd1] + ld a, [wBallsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd1], a + ld [wBallsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcc], a + ld [wBallsPocketCursor], a ld b, $1 ld c, $5 call Function10cef @@ -893,7 +893,7 @@ BattlePack_QuitSubmenu: Function10aba: ; 10aba (4:4aba) xor a ld [wce63], a - ld a, [wcfc8] + ld a, [wLastPocket] and $3 ld [wCurPocket], a inc a @@ -942,15 +942,15 @@ DepositOrSell_ItemPocket: call Function10b92 ld hl, PC_Mart_ItemsPocketMenuDataHeader ; $4e82 call CopyMenuHeader - ld a, [wcfca] + ld a, [wItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfcf] + ld a, [wItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfcf], a + ld [wItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfca], a + ld [wItemsPocketCursor], a ret DepositOrSell_KeyItemsPocket: @@ -958,15 +958,15 @@ DepositOrSell_KeyItemsPocket: call Function10b92 ld hl, PC_Mart_KeyItemsPocketMenuDataHeader ; $4eb2 call CopyMenuHeader - ld a, [wcfcb] + ld a, [wKeyItemsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd0] + ld a, [wKeyItemsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd0], a + ld [wKeyItemsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcb], a + ld [wKeyItemsPocketCursor], a ret DepositOrSell_TMHMPocket: @@ -983,15 +983,15 @@ DepositOrSell_BallsPocket: call Function10b92 ld hl, PC_Mart_BallsPocketMenuDataHeader ; $4ee2 call CopyMenuHeader - ld a, [wcfcc] + ld a, [wBallsPocketCursor] ld [wMenuCursorBuffer], a - ld a, [wcfd1] + ld a, [wBallsPocketScrollPosition] ld [wMenuScrollPosition], a call ScrollingMenu ld a, [wMenuScrollPosition] - ld [wcfd1], a + ld [wBallsPocketScrollPosition], a ld a, [wMenuCursorY] - ld [wcfcc], a + ld [wBallsPocketCursor], a ret Function10b92: ; 10b92 (4:4b92) @@ -1059,7 +1059,7 @@ TutorialPack: ld a, [wInputType] or a jr z, .asm_10bfa - farcall DudeAutoInput_RightA ; 70:4dee + farcall _DudeAutoInput_RightA ; 70:4dee .asm_10bfa call Function10c07 call Function10b9f diff --git a/engine/pokemon/correct_nick_errors.asm b/engine/pokemon/correct_nick_errors.asm index 0f264a36..c8056251 100644 --- a/engine/pokemon/correct_nick_errors.asm +++ b/engine/pokemon/correct_nick_errors.asm @@ -43,7 +43,7 @@ CorrectNickErrors:: ; 677e (1:677e) ; table defining which characters are actually text commands ; format: ; ≥ < - db "<START>", $04 + 1 + db "<NULL>", $04 + 1 db "<PLAY_G>", $18 + 1 db $1d, "%" + 1 db $35, "<GREEN>" + 1 diff --git a/engine/pokemon/learn.asm b/engine/pokemon/learn.asm index 65816783..fe6ff121 100644 --- a/engine/pokemon/learn.asm +++ b/engine/pokemon/learn.asm @@ -136,7 +136,7 @@ LearnMove: ld a, $1 ld [w2DMenuNumCols], a ld [wMenuCursorY], a - ld [wcee1], a + ld [wMenuCursorX], a ld a, $3 ld [wMenuJoypadFilter], a ld a, $20 diff --git a/gfx/battle/dude.2bpp.lz b/gfx/battle/dude.2bpp.lz Binary files differnew file mode 100644 index 00000000..b8e96a09 --- /dev/null +++ b/gfx/battle/dude.2bpp.lz diff --git a/gfx/player/chris_back.2bpp.lz b/gfx/player/chris_back.2bpp.lz Binary files differnew file mode 100644 index 00000000..aec84bba --- /dev/null +++ b/gfx/player/chris_back.2bpp.lz diff --git a/home/text.asm b/home/text.asm index 628bc0f6..c296e378 100644 --- a/home/text.asm +++ b/home/text.asm @@ -213,7 +213,7 @@ ENDM dict "<TM>", TMChar dict "<TRNER>", TrainerChar dict $23, PlaceKougeki - dict "<LNBRK>", HalfLineChar + dict "<LF>", HalfLineChar dict "<CONT>", ContText dict "<……>", SixDotsChar dict "<DONE>", DoneText @@ -154,7 +154,13 @@ StartMenu_PrintBugContestStatus: Function24b8d: dr $24b8d, $24c89 MonSubmenu: - dr $24c89, $24f20 + dr $24c89, $24e09 +GetMenu:: + dr $24e09, $24e62 +LoadBattleMenu:: + dr $24e62, $24e72 +ContestBattleMenu:: + dr $24e72, $24f20 SelectQuantityToToss: dr $24f20, $24f2a SelectQuantityToBuy: @@ -259,13 +265,17 @@ JohtoGrassWildMons: dr $2ab35, $2bee3 SECTION "bankb", ROMX - dr $2c000, $2c045 + dr $2c000, $2c033 +BattleStart_TrainerHuds: + dr $2c033, $2c045 EnemySwitch_TrainerHud: dr $2c045, $2c0c8 DrawPlayerHUDBorder: dr $2c0c8, $2c0f8 DrawEnemyHUDBorder: - dr $2c0f8, $2c225 + dr $2c0f8, $2c1e4 +_ShowLinkBattleParticipants: + dr $2c1e4, $2c225 INCLUDE "engine/battle/ai/redundant.asm" MoveDeletion: dr $2c352, $2c57a @@ -278,7 +288,9 @@ ChooseMonToLearnTMHM: TeachTMHM: dr $2c672, $2c943 PrintMoveDesc:: - dr $2c943, $2ca31 + dr $2c943, $2c95d +GivePokerusAndConvertBerries:: + dr $2c95d, $2ca31 SECTION "bankc", ROMX dr $30000, $33d81 @@ -300,75 +312,8 @@ INCLUDE "engine/battle/read_trainer_party.asm" SECTION "Battle Core", ROMX INCLUDE "engine/battle/core.asm" +INCLUDE "data/battle/effect_command_pointers.asm" -BattleMenu: - dr $3df9a, $3e1e4 - -PlayerSwitch: - dr $3e1e4, $3e290 -PassedBattleMonEntrance: - dr $3e290, $3e2df -CheckAmuletCoin: - dr $3e2df, $3e2f3 -MoveSelectionScreen: - dr $3e2f3, $3e5d8 -ParseEnemyAction: - dr $3e5d8, $3e6e8 -CheckEnemyLockedIn:: - dr $3e6e8, $3e6fb -LinkBattleSendReceiveAction: - dr $3e6fb, $3e74b -LoadEnemyMon: - dr $3e74b, $3ea16 -BattleWinSlideInEnemyTrainerFrontpic: - dr $3ea16, $3ea6a -ApplyStatusEffectOnPlayerStats: - dr $3ea6a, $3ea6e -ApplyStatusEffectOnEnemyStats: - dr $3ea6e, $3ea77 -ApplyPrzEffectOnSpeed: - dr $3ea77, $3eab4 -ApplyBrnEffectOnAttack: - dr $3eab4, $3eae9 -ApplyStatLevelMultiplierOnAllStats: - dr $3eae9, $3eb83 -BadgeStatBoosts: - dr $3eb83, $3ebd8 -_LoadBattleFontsHPBar: - dr $3ebd8, $3ebdf -_LoadHPBar: - dr $3ebdf, $3ec0a -EmptyBattleTextbox: - dr $3ec0a, $3ec11 -_BattleRandom:: - dr $3ec11, $3ec48 -Call_PlayBattleAnim_OnlyIfVisible: - dr $3ec48, $3ec50 -Call_PlayBattleAnim: - dr $3ec50, $3ec60 -FinishBattleAnim: - dr $3ec60, $3ec74 -GiveExperiencePoints: - dr $3ec74, $3f086 - -SendOutMonText: - dr $3f086, $3f196 -FillInExpBar:: - dr $3f196, $3f243 -GetBattleMonBackpic:: - dr $3f243, $3f24d -DropPlayerSub: - dr $3f24d, $3f282 -GetEnemyMonFrontpic:: - dr $3f282, $3f28c -DropEnemySub: - dr $3f28c, $3f2c7 -StartBattle:: - dr $3f2c7, $3f55d -Function3f55d: - dr $3f55d, $3fd3d -BattleCommandPointers: - dr $3fd3d, $3fe9b SECTION "bank10", ROMX @@ -396,7 +341,11 @@ SECTION "bank11", ROMX INCLUDE "engine/battle/ai/move.asm" dr $441c2, $44360 PokedexDataPointerTable:: - dr $44360, $44648 + dr $44360, $44556 +PlayBattleMusic:: + dr $44556, $445f2 +ClearBattleRAM:: + dr $445f2, $44648 PlaceGraphic:: dr $44648, $44679 SendMailToPC:: @@ -559,28 +508,37 @@ PlaySpriteAnimations: dr $8d18a, $8d1f7 _InitSpriteAnimStruct:: dr $8d1f7, $8d332 -_ReinitSpriteAnimFrame:: IF DEF(_GOLD) - dr $8d332, $8e774 +_ReinitSpriteAnimFrame:: + dr $8d332, $8e6fd +AnimateEndOfExpBar:: + dr $8e6fd, $8e774 ClearSpriteAnims2:: dr $8e774, $8e78b LoadOverworldMonIcon:: dr $8e78b, $8e79f LoadMenuMonIcon:: - dr $8e79f, $8e922 + dr $8e79f, $8e8fb +FreezeMonIcons:: + dr $8e8fb, $8e922 UnfreezeMonIcons:: dr $8e922, $8e93d HoldSwitchmonIcon:: dr $8e93d, $8fe43 ELIF DEF(_SILVER) - dr $8d332, $8e75a +_ReinitSpriteAnimFrame:: + dr $8d332, $8e6e3 +AnimateEndOfExpBar:: + dr $8e6e3, $8e75a ClearSpriteAnims2:: dr $8e75a, $8e771 LoadOverworldMonIcon:: dr $8e771, $8e785 LoadMenuMonIcon:: - dr $8e785, $8e908 + dr $8e785, $8e8e1 +FreezeMonIcons:: + dr $8e8e1, $8e908 UnfreezeMonIcons:: dr $8e908, $8e923 HoldSwitchmonIcon:: @@ -693,7 +651,7 @@ INCLUDE "data/moves/animations.asm" LoadPoisonBGPals:: dr $cbc76, $cbdba -SECTION "bank33", ROMX +SECTION "Move Animations", ROMX DisplayCaughtContestMonStats: dr $cc000, $cc0c8 @@ -705,7 +663,11 @@ DummyPredef39:: PlayBattleAnim:: dr $cc0d7, $cc283 ClearBattleAnims:: - dr $cc283, $cfce3 + dr $cc283, $cc5f7 +BattleAnimCmd_RaiseSub:: + dr $cc5f7, $cc67c +BattleAnimCmd_MinimizeOpp:: + dr $cc67c, $cfce3 SECTION "bank36", ROMX dr $d8000, $d8400 @@ -772,9 +734,19 @@ Functionf8000:: Functionf800c:: dr $f800c, $f8032 _LoadFontsBattleExtra:: - dr $f8032, $f80d9 + dr $f8032, $f8066 +LoadBattleFontsHPBar:: + dr $f8066, $f8081 +LoadHPBar:: + dr $f8081, $f80d9 LoadStatsScreenPageTilesGFX:: - dr $f80d9, $fb4be + dr $f80d9, $f8bb2 +EnemyHPBarBorderGFX:: + dr $f8bb2, $f8bd2 +HPExpBarBorderGFX:: + dr $f8bd2, $f8c02 +ExpBarGFX:: + dr $f8c02, $fb4be TileCollisionTable:: dr $fb4be, $fb5be @@ -793,7 +765,9 @@ ConvertMon_1to2:: UpdateUnownDex: dr $fbb22, $fbc3c CheckMagikarpLength: - dr $fbc3c, $fbdd6 + dr $fbc3c, $fbd00 +CalcMagikarpLength:: + dr $fbd00, $fbdd6 MagikarpHouseSign: dr $fbdd6, $fbdf1 HiddenPowerDamage: @@ -853,14 +827,15 @@ Function1c0a7b:: dr $1c0a7b, $1c0de9 _DudeAutoInput_A:: dr $1c0de9, $1c0dee +_DudeAutoInput_RightA:: + dr $1c0dee, $1c0df3 +_DudeAutoInput_DownA:: + dr $1c0df3, $1c168b -IF DEF(_GOLD) -DudeAutoInput_RightA:: - dr $1c0dee, $1c168b -ELIF DEF(_SILVER) -DudeAutoInput_RightA:: - dr $1c0dee, $1c168c +IF DEF(_SILVER) + dr $1c168b, $1c168c ENDC + SECTION "bank7f", ROMX dr $1ffdf8, $200000 diff --git a/pokegold.link b/pokegold.link index ecbf1577..952b76df 100644 --- a/pokegold.link +++ b/pokegold.link @@ -141,8 +141,7 @@ ROMX $32 org $4000 "bank32" ROMX $33 - org $4000 - "bank33" + "Move Animations" "Extra Songs 2" ROMX $36 org $4000 @@ -297,7 +296,6 @@ VRAM $00 VRAM $01 SRAM $00 "Scratch" - "Decompress Buffer" org $a600 "SRAM Bank 0" "Backup Save 1" diff --git a/pokesilver.link b/pokesilver.link index ecbf1577..952b76df 100644 --- a/pokesilver.link +++ b/pokesilver.link @@ -141,8 +141,7 @@ ROMX $32 org $4000 "bank32" ROMX $33 - org $4000 - "bank33" + "Move Animations" "Extra Songs 2" ROMX $36 org $4000 @@ -297,7 +296,6 @@ VRAM $00 VRAM $01 SRAM $00 "Scratch" - "Decompress Buffer" org $a600 "SRAM Bank 0" "Backup Save 1" @@ -1,11 +1,13 @@ SECTION "Scratch", SRAM -sDecompressScratch:: ds $188 ; a000 +UNION ; a000 +sScratchTilemap:: ds BG_MAP_WIDTH * BG_MAP_HEIGHT +sScratchAttrmap:: ds $200 - -SECTION "Decompress Buffer", SRAM - -sDecompressBuffer:: ds 7 * 7 * $10 ; a188 +NEXTU ; a000 +sDecompressScratch:: ds $188 +sDecompressBuffer:: ds 7 * 7 tiles ; a188 +ENDU SECTION "SRAM Bank 0", SRAM @@ -82,15 +84,17 @@ sLuckyIDNumber:: dw SECTION "Backup Save 1", SRAM +; ac6b sBackupPlayerData3:: ds wPlayerDataEnd - wPlayerData3 +; b0e8 sBackupPokemonData:: ds wPokemonDataEnd - wPokemonData +; b5c7 sBackupPlayerData1:: ds wPlayerData1End - wPlayerData SECTION "SRAM Stack", SRAM sStackTop:: dw - s0_b7ef:: db s0_b7f0:: db @@ -122,15 +126,15 @@ sCheckValue2:: db ; loaded with SAVE_CHECK_VALUE_2, used to check save corruptio SECTION "Active Box", SRAM -sBox:: curbox sBox +sBox:: curbox sBox ; ad6c SECTION "Link Battle Data", SRAM sLinkBattleStats:: -sLinkBattleWins:: dw -sLinkBattleLosses:: dw -sLinkBattleDraws:: dw +sLinkBattleWins:: dw ; b1ba +sLinkBattleLosses:: dw ; b1bc +sLinkBattleDraws:: dw ; b1be sLinkBattleRecord:: sLinkBattleRecord1:: link_battle_record sLinkBattleRecord1 @@ -143,7 +147,7 @@ sLinkBattleStatsEnd:: SECTION "SRAM Hall of Fame", SRAM -sHallOfFame:: +sHallOfFame:: ; b21a sHallOfFame01:: hall_of_fame sHallOfFame01 sHallOfFame02:: hall_of_fame sHallOfFame02 sHallOfFame03:: hall_of_fame sHallOfFame03 @@ -179,6 +183,7 @@ sHallOfFameEnd:: SECTION "Backup Save 2", SRAM +; bd96 sBackupPlayerData2:: ds wPlayerData2End - wPlayerData2 @@ -206,12 +211,10 @@ sBox14:: box sBox14 SECTION "Backup Save 3", SRAM +; be30 sBackupOptions:: ds wOptionsEnd - wOptions - sBackupCheckValue1:: db ; loaded with SAVE_CHECK_VALUE_1, used to check save corruption - -sBackupCurMapData:: ds wCurMapDataEnd - wCurMapData - +; be39 +sBackupCurMapData:: ds wCurMapDataEnd - wCurMapData sBackupChecksum:: dw - sBackupCheckValue2:: db ; loaded with SAVE_CHECK_VALUE_2, used to check save corruption @@ -1809,11 +1809,11 @@ wPlayerTurnsTaken:: db ; cbbb wcbbc:: ds 1 ; cbbc wPlayerSubstituteHP:: db ; cbbd wEnemySubstituteHP:: db ; cbbe -wcbbf:: ds 1 ; cbbf +wUnusedPlayerLockedMove:: db ; cbbf wcbc0:: ds 1 ; cbc0 -wCurPlayerMove:: ds 1 ; cbc1 -wCurEnemyMove:: ds 1 ; cbc2 -wcbc3:: ds 1 ; cbc3 +wCurPlayerMove:: db ; cbc1 +wCurEnemyMove:: db ; cbc2 +wLinkBattleRNCount:: db ; cbc3 wEnemyItemState:: db ; cbc4 wcbc5:: ds 1 ; cbc5 wcbc6:: ds 1 ; cbc6 @@ -1822,7 +1822,7 @@ wEnemyHPAtTimeOfPlayerSwitch:: dw ; cbc8 wPayDayMoney:: ds 3 ; cbca wcbcd:: ds 1 ; cbcd -wcbce:: ds 1 ; cbce +wSafariMonEating:: db ; cbce wcbcf:: ds 1 ; cbcf wEnemyBackupDVs:: dw wAlreadyDisobeyed:: db ; cbd2 @@ -1866,7 +1866,7 @@ wPlayerUsedMoves:: ; cbf0 wEnemyAISwitchScore:: db ; cbf4 wEnemySwitchMonParam:: db ; cbf5 wEnemySwitchMonIndex:: db ; cbf6 -wcbf7:: ds 1 ; cbf7 +wTempLevel:: db ; cbf7 wLastPlayerMon:: db ; cbf8 wLastPlayerMove:: db ; cbf9 wLastEnemyMove:: db ; cbfa @@ -2287,8 +2287,8 @@ w2DMenuFlags2:: db ; cedd w2DMenuCursorOffsets:: db ; cede wMenuJoypadFilter:: db ; cedf w2DMenuDataEnd:: -wMenuCursorY:: ds 1 ; cee0 -wcee1:: ds 1 ; cee1 +wMenuCursorY:: db ; cee0 +wMenuCursorX:: db ; cee1 wcee2:: ds 1 ; cee2 wCursorCurrentTile:: ds 1 ; cee3 wcee4:: ds 1 ; cee4 @@ -2553,18 +2553,18 @@ NEXTU wBattleMenuCursorBuffer:: dw ; cfc4 wCurBattleMon:: db ; cfc6 wCurMoveNum:: db; cfc7 -wcfc8:: ds 1 ; cfc8 +wLastPocket:: db ; cfc8 wPartyMenuCursor:: ds 1 ; cfc9 ENDU -wcfca:: ds 1 ; cfca -wcfcb:: ds 1 ; cfcb -wcfcc:: ds 1 ; cfcc +wItemsPocketCursor:: db ; cfca +wKeyItemsPocketCursor:: db ; cfcb +wBallsPocketCursor:: db ; cfcc wcfcd:: ds 1 ; cfcd wcfce:: ds 1 ; cfce -wcfcf:: ds 1 ; cfcf -wcfd0:: ds 1 ; cfd0 -wcfd1:: ds 1 ; cfd1 +wItemsPocketScrollPosition:: db ; cfcf +wKeyItemsPocketScrollPosition:: db; cfd0 +wBallsPocketScrollPosition:: db ; cfd1 wcfd2:: ds 1 ; cfd2 wSwitchMon:: @@ -2789,8 +2789,8 @@ wd0cc:: ds 1 ; d0cc wd0cd:: ds 1 ; d0cd wd0ce:: ds 1 ; d0ce wTilesetPalettes:: dw ; d0cf -wd0d1:: ds 1 ; d0d1 -wd0d2:: ds 1 ; d0d2 +wEvolvableFlags:: db ; d0d1 +wForceEvolution:: db ; d0d2 UNION ; d0d3 ; general-purpose buffers @@ -2814,6 +2814,13 @@ wCurHPAnimLowHP:: db ; d0de wCurHPAnimHighHP:: db ; d0df NEXTU ; d0d3 +; evolution data +wEvolutionOldSpecies:: db ; d0d3 +wEvolutionNewSpecies:: db ; d0d4 +wEvolutionPicOffset:: db ; d0d5 +wEvolutionCanceled:: db ; d0d6 + +NEXTU ; d0d3 ; miscellaneous wMagikarpLength:: dw wSelectedDecoration:: db @@ -2822,19 +2829,10 @@ wOtherDecoration:: db wCurEnemyItem:: db ENDU ; d0e0 -wd0e0:: ds 1 ; d0e0 -wd0e1:: ds 1 ; d0e1 -wd0e2:: ds 1 ; d0e2 -wd0e3:: ds 1 ; d0e3 -wd0e4:: ds 1 ; d0e4 -wd0e5:: ds 1 ; d0e5 -wd0e6:: ds 1 ; d0e6 -wd0e7:: ds 1 ; d0e7 -wd0e8:: ds 1 ; d0e8 -wd0e9:: ds 1 ; d0e9 -wd0ea:: ds 1 ; d0ea -wd0eb:: ds 1 ; d0eb -wd0ec:: ds 1 ; d0ec + ds 3 + +wLinkBattleRNs:: ds 10 ; d0e3 + wTempEnemyMonSpecies:: db ; d0ed wTempBattleMonSpecies:: db ; d0ee |