summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rwxr-xr-xengine/HoF_room_pc.asm270
-rwxr-xr-xengine/battle/core.asm8719
-rwxr-xr-xengine/battle/end_of_battle.asm88
-rw-r--r--engine/battle/link_battle_versus_text.asm23
-rw-r--r--engine/battle/print_type.asm2
-rw-r--r--engine/battle/save_trainer_name.asm112
-rw-r--r--engine/battle/trainer_ai.asm2
-rwxr-xr-xengine/cable_club.asm977
-rwxr-xr-xengine/clear_save.asm23
-rwxr-xr-xengine/evolve_trade.asm44
-rwxr-xr-xengine/hall_of_fame.asm288
-rwxr-xr-xengine/hidden_object_functions17.asm475
-rwxr-xr-xengine/hidden_object_functions7.asm467
-rwxr-xr-xengine/in_game_trades.asm2
-rwxr-xr-xengine/items/items.asm2989
-rwxr-xr-xengine/learn_move.asm226
-rw-r--r--engine/menu/bills_pc.asm554
-rwxr-xr-xengine/menu/diploma.asm113
-rw-r--r--engine/menu/draw_start_menu.asm89
-rwxr-xr-xengine/menu/league_pc.asm120
-rwxr-xr-xengine/menu/main_menu.asm712
-rwxr-xr-xengine/menu/naming_screen.asm512
-rwxr-xr-xengine/menu/party_menu.asm325
-rwxr-xr-xengine/menu/players_pc.asm303
-rwxr-xr-xengine/menu/pokedex.asm665
-rwxr-xr-xengine/menu/prize_menu.asm306
-rwxr-xr-xengine/menu/start_sub_menus.asm854
-rwxr-xr-xengine/menu/status_screen.asm481
-rw-r--r--engine/menu/text_box.asm767
-rwxr-xr-xengine/menu/vending_machine.asm139
-rwxr-xr-xengine/oak_speech2.asm272
-rw-r--r--engine/overworld/movement.asm880
-rwxr-xr-xengine/overworld/pokemart.asm272
-rw-r--r--engine/print_waiting_text.asm20
-rwxr-xr-xengine/save.asm708
-rwxr-xr-xengine/slot_machine.asm892
-rwxr-xr-xengine/status_ailments.asm46
-rwxr-xr-xengine/titlescreen.asm403
-rwxr-xr-xengine/town_map.asm619
-rwxr-xr-xengine/trade.asm853
40 files changed, 3 insertions, 25609 deletions
diff --git a/engine/HoF_room_pc.asm b/engine/HoF_room_pc.asm
deleted file mode 100755
index 7e08631c..00000000
--- a/engine/HoF_room_pc.asm
+++ /dev/null
@@ -1,270 +0,0 @@
-HallOfFamePC:
- callba AnimateHallOfFame
- call ClearScreen
- ld c, 100
- call DelayFrames
- call DisableLCD
- ld hl, vFont
- ld bc, $800 / 2
- call ZeroMemory
- ld hl, vChars2 + $600
- ld bc, $200 / 2
- call ZeroMemory
- ld hl, vChars2 + $7e0
- ld bc, $10
- ld a, $ff
- call FillMemory
- coord hl, 0, 0
- call FillFourRowsWithBlack
- coord hl, 0, 14
- call FillFourRowsWithBlack
- ld a, %11000000
- ld [rBGP], a
- call EnableLCD
- ld a, $ff
- call PlaySoundWaitForCurrent
- ld c, BANK(Music_Credits)
- ld a, MUSIC_CREDITS
- call PlayMusic
- ld c, 128
- call DelayFrames
- xor a
- ld [wUnusedCD3D], a ; not read
- ld [wNumCreditsMonsDisplayed], a
- jp Credits
-
-FadeInCreditsText:
- ld hl, HoFGBPalettes
- ld b, 4
-.loop
- ld a, [hli]
- ld [rBGP], a
- ld c, 5
- call DelayFrames
- dec b
- jr nz, .loop
- ret
-
-DisplayCreditsMon:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call SaveScreenTilesToBuffer1
- call FillMiddleOfScreenWithWhite
-
- ; display the next monster from CreditsMons
- ld hl, wNumCreditsMonsDisplayed
- ld c, [hl] ; how many monsters have we displayed so far?
- inc [hl]
- ld b, 0
- ld hl, CreditsMons
- add hl, bc ; go that far in the list of monsters and get the next one
- ld a, [hl]
- ld [wcf91], a
- ld [wd0b5], a
- coord hl, 8, 6
- call GetMonHeader
- call LoadFrontSpriteByMonIndex
- ld hl, vBGMap0 + $c
- call CreditsCopyTileMapToVRAM
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call LoadScreenTilesFromBuffer1
- ld hl, vBGMap0
- call CreditsCopyTileMapToVRAM
- ld a, $A7
- ld [rWX], a
- ld hl, vBGMap1
- call CreditsCopyTileMapToVRAM
- call FillMiddleOfScreenWithWhite
- ld a, %11111100 ; make the mon a black silhouette
- ld [rBGP], a
-
-; scroll the mon left by one tile 7 times
- ld bc, 7
-.scrollLoop1
- call ScrollCreditsMonLeft
- dec c
- jr nz, .scrollLoop1
-
-; scroll the mon left by one tile 20 times
-; This time, we have to move the window left too in order to hide the text that
-; is wrapping around to the right side of the screen.
- ld c, 20
-.scrollLoop2
- call ScrollCreditsMonLeft
- ld a, [rWX]
- sub 8
- ld [rWX], a
- dec c
- jr nz, .scrollLoop2
-
- xor a
- ld [hWY], a
- ld a, %11000000
- ld [rBGP], a
- ret
-
-INCLUDE "data/credit_mons.asm"
-
-ScrollCreditsMonLeft:
- ld h, b
- ld l, $20
- call ScrollCreditsMonLeft_SetSCX
- ld h, $0
- ld l, $70
- call ScrollCreditsMonLeft_SetSCX
- ld a, b
- add $8
- ld b, a
- ret
-
-ScrollCreditsMonLeft_SetSCX:
- ld a, [rLY]
- cp l
- jr nz, ScrollCreditsMonLeft_SetSCX
- ld a, h
- ld [rSCX], a
-.loop
- ld a, [rLY]
- cp h
- jr z, .loop
- ret
-
-HoFGBPalettes:
- db %11000000
- db %11010000
- db %11100000
- db %11110000
-
-CreditsCopyTileMapToVRAM:
- ld a, l
- ld [H_AUTOBGTRANSFERDEST], a
- ld a, h
- ld [H_AUTOBGTRANSFERDEST + 1], a
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- jp Delay3
-
-ZeroMemory:
-; zero bc bytes at hl
- ld [hl], 0
- inc hl
- inc hl
- dec bc
- ld a, b
- or c
- jr nz, ZeroMemory
- ret
-
-FillFourRowsWithBlack:
- ld bc, SCREEN_WIDTH * 4
- ld a, $7e
- jp FillMemory
-
-FillMiddleOfScreenWithWhite:
- coord hl, 0, 4
- ld bc, SCREEN_WIDTH * 10
- ld a, " "
- jp FillMemory
-
-Credits:
- ld de, CreditsOrder
- push de
-.nextCreditsScreen
- pop de
- coord hl, 9, 6
- push hl
- call FillMiddleOfScreenWithWhite
- pop hl
-.nextCreditsCommand
- ld a, [de]
- inc de
- push de
- cp $ff
- jr z, .fadeInTextAndShowMon
- cp $fe
- jr z, .showTextAndShowMon
- cp $fd
- jr z, .fadeInText
- cp $fc
- jr z, .showText
- cp $fb
- jr z, .showCopyrightText
- cp $fa
- jr z, .showTheEnd
- push hl
- push hl
- ld hl, CreditsTextPointers
- add a
- ld c, a
- ld b, 0
- add hl, bc
- ld e, [hl]
- inc hl
- ld d, [hl]
- ld a, [de]
- inc de
- ld c, a
- ld b, $ff
- pop hl
- add hl, bc
- call PlaceString
- pop hl
- ld bc, SCREEN_WIDTH * 2
- add hl, bc
- pop de
- jr .nextCreditsCommand
-.fadeInTextAndShowMon
- call FadeInCreditsText
- ld c, 90
- jr .next1
-.showTextAndShowMon
- ld c, 110
-.next1
- call DelayFrames
- call DisplayCreditsMon
- jr .nextCreditsScreen
-.fadeInText
- call FadeInCreditsText
- ld c, 120
- jr .next2
-.showText
- ld c, 140
-.next2
- call DelayFrames
- jr .nextCreditsScreen
-.showCopyrightText
- push de
- callba LoadCopyrightTiles
- pop de
- pop de
- jr .nextCreditsCommand
-.showTheEnd
- ld c, 16
- call DelayFrames
- call FillMiddleOfScreenWithWhite
- pop de
- ld de, TheEndGfx
- ld hl, vChars2 + $600
- lb bc, BANK(TheEndGfx), (TheEndGfxEnd - TheEndGfx) / $10
- call CopyVideoData
- coord hl, 4, 8
- ld de, TheEndTextString
- call PlaceString
- coord hl, 4, 9
- inc de
- call PlaceString
- jp FadeInCreditsText
-
-TheEndTextString:
-; "T H E E N D"
- db $60," ",$62," ",$64," ",$64," ",$66," ",$68,"@"
- db $61," ",$63," ",$65," ",$65," ",$67," ",$69,"@"
-
-INCLUDE "data/credits_order.asm"
-
-INCLUDE "text/credits_text.asm"
-
-TheEndGfx:
- INCBIN "gfx/theend.2bpp"
-TheEndGfxEnd:
diff --git a/engine/battle/core.asm b/engine/battle/core.asm
deleted file mode 100755
index 9265503d..00000000
--- a/engine/battle/core.asm
+++ /dev/null
@@ -1,8719 +0,0 @@
-BattleCore:
-
-; These are move effects (second value from the Moves table in bank $E).
-ResidualEffects1:
-; most non-side effects
- db CONVERSION_EFFECT
- db HAZE_EFFECT
- db SWITCH_AND_TELEPORT_EFFECT
- db MIST_EFFECT
- db FOCUS_ENERGY_EFFECT
- db CONFUSION_EFFECT
- db HEAL_EFFECT
- db TRANSFORM_EFFECT
- db LIGHT_SCREEN_EFFECT
- db REFLECT_EFFECT
- db POISON_EFFECT
- db PARALYZE_EFFECT
- db SUBSTITUTE_EFFECT
- db MIMIC_EFFECT
- db LEECH_SEED_EFFECT
- db SPLASH_EFFECT
- db -1
-SetDamageEffects:
-; moves that do damage but not through normal calculations
-; e.g., Super Fang, Psywave
- db SUPER_FANG_EFFECT
- db SPECIAL_DAMAGE_EFFECT
- db -1
-ResidualEffects2:
-; non-side effects not included in ResidualEffects1
-; stat-affecting moves, sleep-inflicting moves, and Bide
-; e.g., Meditate, Bide, Hypnosis
- db $01
- db ATTACK_UP1_EFFECT
- db DEFENSE_UP1_EFFECT
- db SPEED_UP1_EFFECT
- db SPECIAL_UP1_EFFECT
- db ACCURACY_UP1_EFFECT
- db EVASION_UP1_EFFECT
- db ATTACK_DOWN1_EFFECT
- db DEFENSE_DOWN1_EFFECT
- db SPEED_DOWN1_EFFECT
- db SPECIAL_DOWN1_EFFECT
- db ACCURACY_DOWN1_EFFECT
- db EVASION_DOWN1_EFFECT
- db BIDE_EFFECT
- db SLEEP_EFFECT
- db ATTACK_UP2_EFFECT
- db DEFENSE_UP2_EFFECT
- db SPEED_UP2_EFFECT
- db SPECIAL_UP2_EFFECT
- db ACCURACY_UP2_EFFECT
- db EVASION_UP2_EFFECT
- db ATTACK_DOWN2_EFFECT
- db DEFENSE_DOWN2_EFFECT
- db SPEED_DOWN2_EFFECT
- db SPECIAL_DOWN2_EFFECT
- db ACCURACY_DOWN2_EFFECT
- db EVASION_DOWN2_EFFECT
- db -1
-AlwaysHappenSideEffects:
-; Attacks that aren't finished after they faint the opponent.
- db DRAIN_HP_EFFECT
- db EXPLODE_EFFECT
- db DREAM_EATER_EFFECT
- db PAY_DAY_EFFECT
- db TWO_TO_FIVE_ATTACKS_EFFECT
- db $1E
- db ATTACK_TWICE_EFFECT
- db RECOIL_EFFECT
- db TWINEEDLE_EFFECT
- db RAGE_EFFECT
- db -1
-SpecialEffects:
-; Effects from arrays 2, 4, and 5B, minus Twineedle and Rage.
-; Includes all effects that do not need to be called at the end of
-; ExecutePlayerMove (or ExecuteEnemyMove), because they have already been handled
- db DRAIN_HP_EFFECT
- db EXPLODE_EFFECT
- db DREAM_EATER_EFFECT
- db PAY_DAY_EFFECT
- db SWIFT_EFFECT
- db TWO_TO_FIVE_ATTACKS_EFFECT
- db $1E
- db CHARGE_EFFECT
- db SUPER_FANG_EFFECT
- db SPECIAL_DAMAGE_EFFECT
- db FLY_EFFECT
- db ATTACK_TWICE_EFFECT
- db JUMP_KICK_EFFECT
- db RECOIL_EFFECT
- ; fallthrough to Next EffectsArray
-SpecialEffectsCont:
-; damaging moves whose effect is executed prior to damage calculation
- db THRASH_PETAL_DANCE_EFFECT
- db TRAPPING_EFFECT
- db -1
-
-SlidePlayerAndEnemySilhouettesOnScreen:
- call LoadPlayerBackPic
- ld a, MESSAGE_BOX ; the usual text box at the bottom of the screen
- ld [wTextBoxID], a
- call DisplayTextBoxID
- coord hl, 1, 5
- lb bc, 3, 7
- call ClearScreenArea
- call DisableLCD
- call LoadFontTilePatterns
- call LoadHudAndHpBarAndStatusTilePatterns
- ld hl, vBGMap0
- ld bc, $400
-.clearBackgroundLoop
- ld a, " "
- ld [hli], a
- dec bc
- ld a, b
- or c
- jr nz, .clearBackgroundLoop
-; copy the work RAM tile map to VRAM
- coord hl, 0, 0
- ld de, vBGMap0
- ld b, 18 ; number of rows
-.copyRowLoop
- ld c, 20 ; number of columns
-.copyColumnLoop
- ld a, [hli]
- ld [de], a
- inc e
- dec c
- jr nz, .copyColumnLoop
- ld a, 12 ; number of off screen tiles to the right of screen in VRAM
- add e ; skip the off screen tiles
- ld e, a
- jr nc, .noCarry
- inc d
-.noCarry
- dec b
- jr nz, .copyRowLoop
- call EnableLCD
- ld a, $90
- ld [hWY], a
- ld [rWY], a
- xor a
- ld [hTilesetType], a
- ld [hSCY], a
- dec a
- ld [wUpdateSpritesEnabled], a
- call Delay3
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld b, $70
- ld c, $90
- ld a, c
- ld [hSCX], a
- call DelayFrame
- ld a, %11100100 ; inverted palette for silhouette effect
- ld [rBGP], a
- ld [rOBP0], a
- ld [rOBP1], a
-.slideSilhouettesLoop ; slide silhouettes of the player's pic and the enemy's pic onto the screen
- ld h, b
- ld l, $40
- call SetScrollXForSlidingPlayerBodyLeft ; begin background scrolling on line $40
- inc b
- inc b
- ld h, $0
- ld l, $60
- call SetScrollXForSlidingPlayerBodyLeft ; end background scrolling on line $60
- call SlidePlayerHeadLeft
- ld a, c
- ld [hSCX], a
- dec c
- dec c
- jr nz, .slideSilhouettesLoop
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, $31
- ld [hStartTileID], a
- coord hl, 1, 5
- predef CopyUncompressedPicToTilemap
- xor a
- ld [hWY], a
- ld [rWY], a
- inc a
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- ld b, SET_PAL_BATTLE
- call RunPaletteCommand
- call HideSprites
- jpab PrintBeginningBattleText
-
-; when a battle is starting, silhouettes of the player's pic and the enemy's pic are slid onto the screen
-; the lower of the player's pic (his body) is part of the background, but his head is a sprite
-; the reason for this is that it shares Y coordinates with the lower part of the enemy pic, so background scrolling wouldn't work for both pics
-; instead, the enemy pic is part of the background and uses the scroll register, while the player's head is a sprite and is slid by changing its X coordinates in a loop
-SlidePlayerHeadLeft:
- push bc
- ld hl, wOAMBuffer + $01
- ld c, $15 ; number of OAM entries
- ld de, $4 ; size of OAM entry
-.loop
- dec [hl] ; decrement X
- dec [hl] ; decrement X
- add hl, de ; next OAM entry
- dec c
- jr nz, .loop
- pop bc
- ret
-
-SetScrollXForSlidingPlayerBodyLeft:
- ld a, [rLY]
- cp l
- jr nz, SetScrollXForSlidingPlayerBodyLeft
- ld a, h
- ld [rSCX], a
-.loop
- ld a, [rLY]
- cp h
- jr z, .loop
- ret
-
-StartBattle:
- xor a
- ld [wPartyGainExpFlags], a
- ld [wPartyFoughtCurrentEnemyFlags], a
- ld [wActionResultOrTookBattleTurn], a
- inc a
- ld [wFirstMonsNotOutYet], a
- ld hl, wEnemyMon1HP
- ld bc, wEnemyMon2 - wEnemyMon1 - 1
- ld d, $3
-.findFirstAliveEnemyMonLoop
- inc d
- ld a, [hli]
- or [hl]
- jr nz, .foundFirstAliveEnemyMon
- add hl, bc
- jr .findFirstAliveEnemyMonLoop
-.foundFirstAliveEnemyMon
- ld a, d
- ld [wSerialExchangeNybbleReceiveData], a
- ld a, [wIsInBattle]
- dec a ; is it a trainer battle?
- call nz, EnemySendOutFirstMon ; if it is a trainer battle, send out enemy mon
- ld c, 40
- call DelayFrames
- call SaveScreenTilesToBuffer1
-.checkAnyPartyAlive
- call AnyPartyAlive
- ld a, d
- and a
- jp z, HandlePlayerBlackOut ; jump if no mon is alive
- call LoadScreenTilesFromBuffer1
- ld a, [wBattleType]
- and a ; is it a normal battle?
- jp z, .playerSendOutFirstMon ; if so, send out player mon
-; safari zone battle
-.displaySafariZoneBattleMenu
- call DisplayBattleMenu
- ret c ; return if the player ran from battle
- ld a, [wActionResultOrTookBattleTurn]
- and a ; was the item used successfully?
- jr z, .displaySafariZoneBattleMenu ; if not, display the menu again; XXX does this ever jump?
- ld a, [wNumSafariBalls]
- and a
- jr nz, .notOutOfSafariBalls
- call LoadScreenTilesFromBuffer1
- ld hl, .outOfSafariBallsText
- jp PrintText
-.notOutOfSafariBalls
- callab PrintSafariZoneBattleText
- ld a, [wEnemyMonSpeed + 1]
- add a
- ld b, a ; init b (which is later compared with random value) to (enemy speed % 256) * 2
- jp c, EnemyRan ; if (enemy speed % 256) > 127, the enemy runs
- ld a, [wSafariBaitFactor]
- and a ; is bait factor 0?
- jr z, .checkEscapeFactor
-; bait factor is not 0
-; divide b by 4 (making the mon less likely to run)
- srl b
- srl b
-.checkEscapeFactor
- ld a, [wSafariEscapeFactor]
- and a ; is escape factor 0?
- jr z, .compareWithRandomValue
-; escape factor is not 0
-; multiply b by 2 (making the mon more likely to run)
- sla b
- jr nc, .compareWithRandomValue
-; cap b at 255
- ld b, $ff
-.compareWithRandomValue
- call Random
- cp b
- jr nc, .checkAnyPartyAlive
- jr EnemyRan ; if b was greater than the random value, the enemy runs
-
-.outOfSafariBallsText
- TX_FAR _OutOfSafariBallsText
- db "@"
-
-.playerSendOutFirstMon
- xor a
- ld [wWhichPokemon], a
-.findFirstAliveMonLoop
- call HasMonFainted
- jr nz, .foundFirstAliveMon
-; fainted, go to the next one
- ld hl, wWhichPokemon
- inc [hl]
- jr .findFirstAliveMonLoop
-.foundFirstAliveMon
- ld a, [wWhichPokemon]
- ld [wPlayerMonNumber], a
- inc a
- ld hl, wPartySpecies - 1
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl] ; species
- ld [wcf91], a
- ld [wBattleMonSpecies2], a
- call LoadScreenTilesFromBuffer1
- coord hl, 1, 5
- ld a, $9
- call SlideTrainerPicOffScreen
- call SaveScreenTilesToBuffer1
- ld a, [wWhichPokemon]
- ld c, a
- ld b, FLAG_SET
- push bc
- ld hl, wPartyGainExpFlags
- predef FlagActionPredef
- ld hl, wPartyFoughtCurrentEnemyFlags
- pop bc
- predef FlagActionPredef
- call LoadBattleMonFromParty
- call LoadScreenTilesFromBuffer1
- call SendOutMon
- jr MainInBattleLoop
-
-; wild mon or link battle enemy ran from battle
-EnemyRan:
- call LoadScreenTilesFromBuffer1
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ld hl, WildRanText
- jr nz, .printText
-; link battle
- xor a
- ld [wBattleResult], a
- ld hl, EnemyRanText
-.printText
- call PrintText
- ld a, SFX_RUN
- call PlaySoundWaitForCurrent
- xor a
- ld [H_WHOSETURN], a
- jpab AnimationSlideEnemyMonOff
-
-WildRanText:
- TX_FAR _WildRanText
- db "@"
-
-EnemyRanText:
- TX_FAR _EnemyRanText
- db "@"
-
-MainInBattleLoop:
- call ReadPlayerMonCurHPAndStatus
- ld hl, wBattleMonHP
- ld a, [hli]
- or [hl] ; is battle mon HP 0?
- jp z, HandlePlayerMonFainted ; if battle mon HP is 0, jump
- ld hl, wEnemyMonHP
- ld a, [hli]
- or [hl] ; is enemy mon HP 0?
- jp z, HandleEnemyMonFainted ; if enemy mon HP is 0, jump
- call SaveScreenTilesToBuffer1
- xor a
- ld [wFirstMonsNotOutYet], a
- ld a, [wPlayerBattleStatus2]
- and (1 << NEEDS_TO_RECHARGE) | (1 << USING_RAGE) ; check if the player is using Rage or needs to recharge
- jr nz, .selectEnemyMove
-; the player is not using Rage and doesn't need to recharge
- ld hl, wEnemyBattleStatus1
- res FLINCHED, [hl] ; reset flinch bit
- ld hl, wPlayerBattleStatus1
- res FLINCHED, [hl] ; reset flinch bit
- ld a, [hl]
- and (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) ; check if the player is thrashing about or charging for an attack
- jr nz, .selectEnemyMove ; if so, jump
-; the player is neither thrashing about nor charging for an attack
- call DisplayBattleMenu ; show battle menu
- ret c ; return if player ran from battle
- ld a, [wEscapedFromBattle]
- and a
- ret nz ; return if pokedoll was used to escape from battle
- ld a, [wBattleMonStatus]
- and (1 << FRZ) | SLP ; is mon frozen or asleep?
- jr nz, .selectEnemyMove ; if so, jump
- ld a, [wPlayerBattleStatus1]
- and (1 << STORING_ENERGY) | (1 << USING_TRAPPING_MOVE) ; check player is using Bide or using a multi-turn attack like wrap
- jr nz, .selectEnemyMove ; if so, jump
- ld a, [wEnemyBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; check if enemy is using a multi-turn attack like wrap
- jr z, .selectPlayerMove ; if not, jump
-; enemy is using a multi-turn attack like wrap, so player is trapped and cannot execute a move
- ld a, $ff
- ld [wPlayerSelectedMove], a
- jr .selectEnemyMove
-.selectPlayerMove
- ld a, [wActionResultOrTookBattleTurn]
- and a ; has the player already used the turn (e.g. by using an item, trying to run or switching pokemon)
- jr nz, .selectEnemyMove
- ld [wMoveMenuType], a
- inc a
- ld [wAnimationID], a
- xor a
- ld [wMenuItemToSwap], a
- call MoveSelectionMenu
- push af
- call LoadScreenTilesFromBuffer1
- call DrawHUDsAndHPBars
- pop af
- jr nz, MainInBattleLoop ; if the player didn't select a move, jump
-.selectEnemyMove
- call SelectEnemyMove
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .noLinkBattle
-; link battle
- ld a, [wSerialExchangeNybbleReceiveData]
- cp LINKBATTLE_RUN
- jp z, EnemyRan
- cp LINKBATTLE_STRUGGLE
- jr z, .noLinkBattle
- cp LINKBATTLE_NO_ACTION
- jr z, .noLinkBattle
- sub 4
- jr c, .noLinkBattle
-; the link battle enemy has switched mons
- ld a, [wPlayerBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; check if using multi-turn move like Wrap
- jr z, .specialMoveNotUsed
- ld a, [wPlayerMoveListIndex]
- ld hl, wBattleMonMoves
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- cp METRONOME ; a MIRROR MOVE check is missing, might lead to a desync in link battles
- ; when combined with multi-turn moves
- jr nz, .specialMoveNotUsed
- ld [wPlayerSelectedMove], a
-.specialMoveNotUsed
- callab SwitchEnemyMon
-.noLinkBattle
- ld a, [wPlayerSelectedMove]
- cp QUICK_ATTACK
- jr nz, .playerDidNotUseQuickAttack
- ld a, [wEnemySelectedMove]
- cp QUICK_ATTACK
- jr z, .compareSpeed ; if both used Quick Attack
- jp .playerMovesFirst ; if player used Quick Attack and enemy didn't
-.playerDidNotUseQuickAttack
- ld a, [wEnemySelectedMove]
- cp QUICK_ATTACK
- jr z, .enemyMovesFirst ; if enemy used Quick Attack and player didn't
- ld a, [wPlayerSelectedMove]
- cp COUNTER
- jr nz, .playerDidNotUseCounter
- ld a, [wEnemySelectedMove]
- cp COUNTER
- jr z, .compareSpeed ; if both used Counter
- jr .enemyMovesFirst ; if player used Counter and enemy didn't
-.playerDidNotUseCounter
- ld a, [wEnemySelectedMove]
- cp COUNTER
- jr z, .playerMovesFirst ; if enemy used Counter and player didn't
-.compareSpeed
- ld de, wBattleMonSpeed ; player speed value
- ld hl, wEnemyMonSpeed ; enemy speed value
- ld c, $2
- call StringCmp ; compare speed values
- jr z, .speedEqual
- jr nc, .playerMovesFirst ; if player is faster
- jr .enemyMovesFirst ; if enemy is faster
-.speedEqual ; 50/50 chance for both players
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- jr z, .invertOutcome
- call BattleRandom
- cp $80
- jr c, .playerMovesFirst
- jr .enemyMovesFirst
-.invertOutcome
- call BattleRandom
- cp $80
- jr c, .enemyMovesFirst
- jr .playerMovesFirst
-.enemyMovesFirst
- ld a, $1
- ld [H_WHOSETURN], a
- callab TrainerAI
- jr c, .AIActionUsedEnemyFirst
- call ExecuteEnemyMove
- ld a, [wEscapedFromBattle]
- and a ; was Teleport, Road, or Whirlwind used to escape from battle?
- ret nz ; if so, return
- ld a, b
- and a
- jp z, HandlePlayerMonFainted
-.AIActionUsedEnemyFirst
- call HandlePoisonBurnLeechSeed
- jp z, HandleEnemyMonFainted
- call DrawHUDsAndHPBars
- call ExecutePlayerMove
- ld a, [wEscapedFromBattle]
- and a ; was Teleport, Road, or Whirlwind used to escape from battle?
- ret nz ; if so, return
- ld a, b
- and a
- jp z, HandleEnemyMonFainted
- call HandlePoisonBurnLeechSeed
- jp z, HandlePlayerMonFainted
- call DrawHUDsAndHPBars
- call CheckNumAttacksLeft
- jp MainInBattleLoop
-.playerMovesFirst
- call ExecutePlayerMove
- ld a, [wEscapedFromBattle]
- and a ; was Teleport, Road, or Whirlwind used to escape from battle?
- ret nz ; if so, return
- ld a, b
- and a
- jp z, HandleEnemyMonFainted
- call HandlePoisonBurnLeechSeed
- jp z, HandlePlayerMonFainted
- call DrawHUDsAndHPBars
- ld a, $1
- ld [H_WHOSETURN], a
- callab TrainerAI
- jr c, .AIActionUsedPlayerFirst
- call ExecuteEnemyMove
- ld a, [wEscapedFromBattle]
- and a ; was Teleport, Road, or Whirlwind used to escape from battle?
- ret nz ; if so, return
- ld a, b
- and a
- jp z, HandlePlayerMonFainted
-.AIActionUsedPlayerFirst
- call HandlePoisonBurnLeechSeed
- jp z, HandleEnemyMonFainted
- call DrawHUDsAndHPBars
- call CheckNumAttacksLeft
- jp MainInBattleLoop
-
-HandlePoisonBurnLeechSeed:
- ld hl, wBattleMonHP
- ld de, wBattleMonStatus
- ld a, [H_WHOSETURN]
- and a
- jr z, .playersTurn
- ld hl, wEnemyMonHP
- ld de, wEnemyMonStatus
-.playersTurn
- ld a, [de]
- and (1 << BRN) | (1 << PSN)
- jr z, .notBurnedOrPoisoned
- push hl
- ld hl, HurtByPoisonText
- ld a, [de]
- and 1 << BRN
- jr z, .poisoned
- ld hl, HurtByBurnText
-.poisoned
- call PrintText
- xor a
- ld [wAnimationType], a
- ld a, BURN_PSN_ANIM
- call PlayMoveAnimation ; play burn/poison animation
- pop hl
- call HandlePoisonBurnLeechSeed_DecreaseOwnHP
-.notBurnedOrPoisoned
- ld de, wPlayerBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .playersTurn2
- ld de, wEnemyBattleStatus2
-.playersTurn2
- ld a, [de]
- add a
- jr nc, .notLeechSeeded
- push hl
- ld a, [H_WHOSETURN]
- push af
- xor $1
- ld [H_WHOSETURN], a
- xor a
- ld [wAnimationType], a
- ld a, ABSORB
- call PlayMoveAnimation ; play leech seed animation (from opposing mon)
- pop af
- ld [H_WHOSETURN], a
- pop hl
- call HandlePoisonBurnLeechSeed_DecreaseOwnHP
- call HandlePoisonBurnLeechSeed_IncreaseEnemyHP
- push hl
- ld hl, HurtByLeechSeedText
- call PrintText
- pop hl
-.notLeechSeeded
- ld a, [hli]
- or [hl]
- ret nz ; test if fainted
- call DrawHUDsAndHPBars
- ld c, 20
- call DelayFrames
- xor a
- ret
-
-HurtByPoisonText:
- TX_FAR _HurtByPoisonText
- db "@"
-
-HurtByBurnText:
- TX_FAR _HurtByBurnText
- db "@"
-
-HurtByLeechSeedText:
- TX_FAR _HurtByLeechSeedText
- db "@"
-
-; decreases the mon's current HP by 1/16 of the Max HP (multiplied by number of toxic ticks if active)
-; note that the toxic ticks are considered even if the damage is not poison (hence the Leech Seed glitch)
-; hl: HP pointer
-; bc (out): total damage
-HandlePoisonBurnLeechSeed_DecreaseOwnHP:
- push hl
- push hl
- ld bc, $e ; skip to max HP
- add hl, bc
- ld a, [hli] ; load max HP
- ld [wHPBarMaxHP+1], a
- ld b, a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- ld c, a
- srl b
- rr c
- srl b
- rr c
- srl c
- srl c ; c = max HP/16 (assumption: HP < 1024)
- ld a, c
- and a
- jr nz, .nonZeroDamage
- inc c ; damage is at least 1
-.nonZeroDamage
- ld hl, wPlayerBattleStatus3
- ld de, wPlayerToxicCounter
- ld a, [H_WHOSETURN]
- and a
- jr z, .playersTurn
- ld hl, wEnemyBattleStatus3
- ld de, wEnemyToxicCounter
-.playersTurn
- bit BADLY_POISONED, [hl]
- jr z, .noToxic
- ld a, [de] ; increment toxic counter
- inc a
- ld [de], a
- ld hl, $0000
-.toxicTicksLoop
- add hl, bc
- dec a
- jr nz, .toxicTicksLoop
- ld b, h ; bc = damage * toxic counter
- ld c, l
-.noToxic
- pop hl
- inc hl
- ld a, [hl] ; subtract total damage from current HP
- ld [wHPBarOldHP], a
- sub c
- ld [hld], a
- ld [wHPBarNewHP], a
- ld a, [hl]
- ld [wHPBarOldHP+1], a
- sbc b
- ld [hl], a
- ld [wHPBarNewHP+1], a
- jr nc, .noOverkill
- xor a ; overkill: zero HP
- ld [hli], a
- ld [hl], a
- ld [wHPBarNewHP], a
- ld [wHPBarNewHP+1], a
-.noOverkill
- call UpdateCurMonHPBar
- pop hl
- ret
-
-; adds bc to enemy HP
-; bc isn't updated if HP subtracted was capped to prevent overkill
-HandlePoisonBurnLeechSeed_IncreaseEnemyHP:
- push hl
- ld hl, wEnemyMonMaxHP
- ld a, [H_WHOSETURN]
- and a
- jr z, .playersTurn
- ld hl, wBattleMonMaxHP
-.playersTurn
- ld a, [hli]
- ld [wHPBarMaxHP+1], a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- ld de, wBattleMonHP - wBattleMonMaxHP
- add hl, de ; skip back from max hp to current hp
- ld a, [hl]
- ld [wHPBarOldHP], a ; add bc to current HP
- add c
- ld [hld], a
- ld [wHPBarNewHP], a
- ld a, [hl]
- ld [wHPBarOldHP+1], a
- adc b
- ld [hli], a
- ld [wHPBarNewHP+1], a
- ld a, [wHPBarMaxHP]
- ld c, a
- ld a, [hld]
- sub c
- ld a, [wHPBarMaxHP+1]
- ld b, a
- ld a, [hl]
- sbc b
- jr c, .noOverfullHeal
- ld a, b ; overfull heal, set HP to max HP
- ld [hli], a
- ld [wHPBarNewHP+1], a
- ld a, c
- ld [hl], a
- ld [wHPBarNewHP], a
-.noOverfullHeal
- ld a, [H_WHOSETURN]
- xor $1
- ld [H_WHOSETURN], a
- call UpdateCurMonHPBar
- ld a, [H_WHOSETURN]
- xor $1
- ld [H_WHOSETURN], a
- pop hl
- ret
-
-UpdateCurMonHPBar:
- coord hl, 10, 9 ; tile pointer to player HP bar
- ld a, [H_WHOSETURN]
- and a
- ld a, $1
- jr z, .playersTurn
- coord hl, 2, 2 ; tile pointer to enemy HP bar
- xor a
-.playersTurn
- push bc
- ld [wHPBarType], a
- predef UpdateHPBar2
- pop bc
- ret
-
-CheckNumAttacksLeft:
- ld a, [wPlayerNumAttacksLeft]
- and a
- jr nz, .checkEnemy
-; player has 0 attacks left
- ld hl, wPlayerBattleStatus1
- res USING_TRAPPING_MOVE, [hl] ; player not using multi-turn attack like wrap any more
-.checkEnemy
- ld a, [wEnemyNumAttacksLeft]
- and a
- ret nz
-; enemy has 0 attacks left
- ld hl, wEnemyBattleStatus1
- res USING_TRAPPING_MOVE, [hl] ; enemy not using multi-turn attack like wrap any more
- ret
-
-HandleEnemyMonFainted:
- xor a
- ld [wInHandlePlayerMonFainted], a
- call FaintEnemyPokemon
- call AnyPartyAlive
- ld a, d
- and a
- jp z, HandlePlayerBlackOut ; if no party mons are alive, the player blacks out
- ld hl, wBattleMonHP
- ld a, [hli]
- or [hl] ; is battle mon HP zero?
- call nz, DrawPlayerHUDAndHPBar ; if battle mon HP is not zero, draw player HD and HP bar
- ld a, [wIsInBattle]
- dec a
- ret z ; return if it's a wild battle
- call AnyEnemyPokemonAliveCheck
- jp z, TrainerBattleVictory
- ld hl, wBattleMonHP
- ld a, [hli]
- or [hl] ; does battle mon have 0 HP?
- jr nz, .skipReplacingBattleMon ; if not, skip replacing battle mon
- call DoUseNextMonDialogue ; this call is useless in a trainer battle. it shouldn't be here
- ret c
- call ChooseNextMon
-.skipReplacingBattleMon
- ld a, $1
- ld [wActionResultOrTookBattleTurn], a
- call ReplaceFaintedEnemyMon
- jp z, EnemyRan
- xor a
- ld [wActionResultOrTookBattleTurn], a
- jp MainInBattleLoop
-
-FaintEnemyPokemon:
- call ReadPlayerMonCurHPAndStatus
- ld a, [wIsInBattle]
- dec a
- jr z, .wild
- ld a, [wEnemyMonPartyPos]
- ld hl, wEnemyMon1HP
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- xor a
- ld [hli], a
- ld [hl], a
-.wild
- ld hl, wPlayerBattleStatus1
- res ATTACKING_MULTIPLE_TIMES, [hl]
-; Bug. This only zeroes the high byte of the player's accumulated damage,
-; setting the accumulated damage to itself mod 256 instead of 0 as was probably
-; intended. That alone is problematic, but this mistake has another more severe
-; effect. This function's counterpart for when the player mon faints,
-; RemoveFaintedPlayerMon, zeroes both the high byte and the low byte. In a link
-; battle, the other player's Game Boy will call that function in response to
-; the enemy mon (the player mon from the other side's perspective) fainting,
-; and the states of the two Game Boys will go out of sync unless the damage
-; was congruent to 0 modulo 256.
- xor a
- ld [wPlayerBideAccumulatedDamage], a
- ld hl, wEnemyStatsToDouble ; clear enemy statuses
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wEnemyDisabledMove], a
- ld [wEnemyDisabledMoveNumber], a
- ld [wEnemyMonMinimized], a
- ld hl, wPlayerUsedMove
- ld [hli], a
- ld [hl], a
- coord hl, 12, 5
- coord de, 12, 6
- call SlideDownFaintedMonPic
- coord hl, 0, 0
- lb bc, 4, 11
- call ClearScreenArea
- ld a, [wIsInBattle]
- dec a
- jr z, .wild_win
- xor a
- ld [wFrequencyModifier], a
- ld [wTempoModifier], a
- ld a, SFX_FAINT_FALL
- call PlaySoundWaitForCurrent
-.sfxwait
- ld a, [wChannelSoundIDs + Ch4]
- cp SFX_FAINT_FALL
- jr z, .sfxwait
- ld a, SFX_FAINT_THUD
- call PlaySound
- call WaitForSoundToFinish
- jr .sfxplayed
-.wild_win
- call EndLowHealthAlarm
- ld a, MUSIC_DEFEATED_WILD_MON
- call PlayBattleVictoryMusic
-.sfxplayed
-; bug: win sfx is played for wild battles before checking for player mon HP
-; this can lead to odd scenarios where both player and enemy faint, as the win sfx plays yet the player never won the battle
- ld hl, wBattleMonHP
- ld a, [hli]
- or [hl]
- jr nz, .playermonnotfaint
- ld a, [wInHandlePlayerMonFainted]
- and a ; was this called by HandlePlayerMonFainted?
- jr nz, .playermonnotfaint ; if so, don't call RemoveFaintedPlayerMon twice
- call RemoveFaintedPlayerMon
-.playermonnotfaint
- call AnyPartyAlive
- ld a, d
- and a
- ret z
- ld hl, EnemyMonFaintedText
- call PrintText
- call PrintEmptyString
- call SaveScreenTilesToBuffer1
- xor a
- ld [wBattleResult], a
- ld b, EXP_ALL
- call IsItemInBag
- push af
- jr z, .giveExpToMonsThatFought ; if no exp all, then jump
-
-; the player has exp all
-; first, we halve the values that determine exp gain
-; the enemy mon base stats are added to stat exp, so they are halved
-; the base exp (which determines normal exp) is also halved
- ld hl, wEnemyMonBaseStats
- ld b, $7
-.halveExpDataLoop
- srl [hl]
- inc hl
- dec b
- jr nz, .halveExpDataLoop
-
-; give exp (divided evenly) to the mons that actually fought in battle against the enemy mon that has fainted
-; if exp all is in the bag, this will be only be half of the stat exp and normal exp, due to the above loop
-.giveExpToMonsThatFought
- xor a
- ld [wBoostExpByExpAll], a
- callab GainExperience
- pop af
- ret z ; return if no exp all
-
-; the player has exp all
-; now, set the gain exp flag for every party member
-; half of the total stat exp and normal exp will divided evenly amongst every party member
- ld a, $1
- ld [wBoostExpByExpAll], a
- ld a, [wPartyCount]
- ld b, 0
-.gainExpFlagsLoop
- scf
- rl b
- dec a
- jr nz, .gainExpFlagsLoop
- ld a, b
- ld [wPartyGainExpFlags], a
- jpab GainExperience
-
-EnemyMonFaintedText:
- TX_FAR _EnemyMonFaintedText
- db "@"
-
-EndLowHealthAlarm:
-; This function is called when the player has the won the battle. It turns off
-; the low health alarm and prevents it from reactivating until the next battle.
- xor a
- ld [wLowHealthAlarm], a ; turn off low health alarm
- ld [wChannelSoundIDs + Ch4], a
- inc a
- ld [wLowHealthAlarmDisabled], a ; prevent it from reactivating
- ret
-
-AnyEnemyPokemonAliveCheck:
- ld a, [wEnemyPartyCount]
- ld b, a
- xor a
- ld hl, wEnemyMon1HP
- ld de, wEnemyMon2 - wEnemyMon1
-.nextPokemon
- or [hl]
- inc hl
- or [hl]
- dec hl
- add hl, de
- dec b
- jr nz, .nextPokemon
- and a
- ret
-
-; stores whether enemy ran in Z flag
-ReplaceFaintedEnemyMon:
- ld hl, wEnemyHPBarColor
- ld e, $30
- call GetBattleHealthBarColor
- callab DrawEnemyPokeballs
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
-; link battle
- call LinkBattleExchangeData
- ld a, [wSerialExchangeNybbleReceiveData]
- cp LINKBATTLE_RUN
- ret z
- call LoadScreenTilesFromBuffer1
-.notLinkBattle
- call EnemySendOut
- xor a
- ld [wEnemyMoveNum], a
- ld [wActionResultOrTookBattleTurn], a
- ld [wAILayer2Encouragement], a
- inc a ; reset Z flag
- ret
-
-TrainerBattleVictory:
- call EndLowHealthAlarm
- ld b, MUSIC_DEFEATED_GYM_LEADER
- ld a, [wGymLeaderNo]
- and a
- jr nz, .gymleader
- ld b, MUSIC_DEFEATED_TRAINER
-.gymleader
- ld a, [wTrainerClass]
- cp SONY3 ; final battle against rival
- jr nz, .notrival
- ld b, MUSIC_DEFEATED_GYM_LEADER
- ld hl, wFlags_D733
- set 1, [hl]
-.notrival
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ld a, b
- call nz, PlayBattleVictoryMusic
- ld hl, TrainerDefeatedText
- call PrintText
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ret z
- call ScrollTrainerPicAfterBattle
- ld c, 40
- call DelayFrames
- call PrintEndBattleText
-; win money
- ld hl, MoneyForWinningText
- call PrintText
- ld de, wPlayerMoney + 2
- ld hl, wAmountMoneyWon + 2
- ld c, $3
- predef_jump AddBCDPredef
-
-MoneyForWinningText:
- TX_FAR _MoneyForWinningText
- db "@"
-
-TrainerDefeatedText:
- TX_FAR _TrainerDefeatedText
- db "@"
-
-PlayBattleVictoryMusic:
- push af
- ld a, $ff
- ld [wNewSoundID], a
- call PlaySoundWaitForCurrent
- ld c, BANK(Music_DefeatedTrainer)
- pop af
- call PlayMusic
- jp Delay3
-
-HandlePlayerMonFainted:
- ld a, 1
- ld [wInHandlePlayerMonFainted], a
- call RemoveFaintedPlayerMon
- call AnyPartyAlive ; test if any more mons are alive
- ld a, d
- and a
- jp z, HandlePlayerBlackOut
- ld hl, wEnemyMonHP
- ld a, [hli]
- or [hl] ; is enemy mon's HP 0?
- jr nz, .doUseNextMonDialogue ; if not, jump
-; the enemy mon has 0 HP
- call FaintEnemyPokemon
- ld a, [wIsInBattle]
- dec a
- ret z ; if wild encounter, battle is over
- call AnyEnemyPokemonAliveCheck
- jp z, TrainerBattleVictory
-.doUseNextMonDialogue
- call DoUseNextMonDialogue
- ret c ; return if the player ran from battle
- call ChooseNextMon
- jp nz, MainInBattleLoop ; if the enemy mon has more than 0 HP, go back to battle loop
-; the enemy mon has 0 HP
- ld a, $1
- ld [wActionResultOrTookBattleTurn], a
- call ReplaceFaintedEnemyMon
- jp z, EnemyRan ; if enemy ran from battle rather than sending out another mon, jump
- xor a
- ld [wActionResultOrTookBattleTurn], a
- jp MainInBattleLoop
-
-; resets flags, slides mon's pic down, plays cry, and prints fainted message
-RemoveFaintedPlayerMon:
- ld a, [wPlayerMonNumber]
- ld c, a
- ld hl, wPartyGainExpFlags
- ld b, FLAG_RESET
- predef FlagActionPredef ; clear gain exp flag for fainted mon
- ld hl, wEnemyBattleStatus1
- res 2, [hl] ; reset "attacking multiple times" flag
- ld a, [wLowHealthAlarm]
- bit 7, a ; skip sound flag (red bar (?))
- jr z, .skipWaitForSound
- ld a, $ff
- ld [wLowHealthAlarm], a ;disable low health alarm
- call WaitForSoundToFinish
-.skipWaitForSound
-; a is 0, so this zeroes the enemy's accumulated damage.
- ld hl, wEnemyBideAccumulatedDamage
- ld [hli], a
- ld [hl], a
- ld [wBattleMonStatus], a
- call ReadPlayerMonCurHPAndStatus
- coord hl, 9, 7
- lb bc, 5, 11
- call ClearScreenArea
- coord hl, 1, 10
- coord de, 1, 11
- call SlideDownFaintedMonPic
- ld a, $1
- ld [wBattleResult], a
-
-; When the player mon and enemy mon faint at the same time and the fact that the
-; enemy mon has fainted is detected first (e.g. when the player mon knocks out
-; the enemy mon using a move with recoil and faints due to the recoil), don't
-; play the player mon's cry or show the "[player mon] fainted!" message.
- ld a, [wInHandlePlayerMonFainted]
- and a ; was this called by HandleEnemyMonFainted?
- ret z ; if so, return
-
- ld a, [wBattleMonSpecies]
- call PlayCry
- ld hl, PlayerMonFaintedText
- jp PrintText
-
-PlayerMonFaintedText:
- TX_FAR _PlayerMonFaintedText
- db "@"
-
-; asks if you want to use next mon
-; stores whether you ran in C flag
-DoUseNextMonDialogue:
- call PrintEmptyString
- call SaveScreenTilesToBuffer1
- ld a, [wIsInBattle]
- and a
- dec a
- ret nz ; return if it's a trainer battle
- ld hl, UseNextMonText
- call PrintText
-.displayYesNoBox
- coord hl, 13, 9
- lb bc, 10, 14
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, [wMenuExitMethod]
- cp CHOSE_SECOND_ITEM ; did the player choose NO?
- jr z, .tryRunning ; if the player chose NO, try running
- and a ; reset carry
- ret
-.tryRunning
- ld a, [wCurrentMenuItem]
- and a
- jr z, .displayYesNoBox ; xxx when does this happen?
- ld hl, wPartyMon1Speed
- ld de, wEnemyMonSpeed
- jp TryRunningFromBattle
-
-UseNextMonText:
- TX_FAR _UseNextMonText
- db "@"
-
-; choose next player mon to send out
-; stores whether enemy mon has no HP left in Z flag
-ChooseNextMon:
- ld a, BATTLE_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call DisplayPartyMenu
-.checkIfMonChosen
- jr nc, .monChosen
-.goBackToPartyMenu
- call GoBackToPartyMenu
- jr .checkIfMonChosen
-.monChosen
- call HasMonFainted
- jr z, .goBackToPartyMenu ; if mon fainted, you have to choose another
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
- inc a
- ld [wActionResultOrTookBattleTurn], a
- call LinkBattleExchangeData
-.notLinkBattle
- xor a
- ld [wActionResultOrTookBattleTurn], a
- call ClearSprites
- ld a, [wWhichPokemon]
- ld [wPlayerMonNumber], a
- ld c, a
- ld hl, wPartyGainExpFlags
- ld b, FLAG_SET
- push bc
- predef FlagActionPredef
- pop bc
- ld hl, wPartyFoughtCurrentEnemyFlags
- predef FlagActionPredef
- call LoadBattleMonFromParty
- call GBPalWhiteOut
- call LoadHudTilePatterns
- call LoadScreenTilesFromBuffer1
- call RunDefaultPaletteCommand
- call GBPalNormal
- call SendOutMon
- ld hl, wEnemyMonHP
- ld a, [hli]
- or [hl]
- ret
-
-; called when player is out of usable mons.
-; prints appropriate lose message, sets carry flag if player blacked out (special case for initial rival fight)
-HandlePlayerBlackOut:
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr z, .notSony1Battle
- ld a, [wCurOpponent]
- cp OPP_SONY1
- jr nz, .notSony1Battle
- coord hl, 0, 0 ; sony 1 battle
- lb bc, 8, 21
- call ClearScreenArea
- call ScrollTrainerPicAfterBattle
- ld c, 40
- call DelayFrames
- ld hl, Sony1WinText
- call PrintText
- ld a, [wCurMap]
- cp OAKS_LAB
- ret z ; starter battle in oak's lab: don't black out
-.notSony1Battle
- ld b, SET_PAL_BATTLE_BLACK
- call RunPaletteCommand
- ld hl, PlayerBlackedOutText2
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .noLinkBattle
- ld hl, LinkBattleLostText
-.noLinkBattle
- call PrintText
- ld a, [wd732]
- res 5, a
- ld [wd732], a
- call ClearScreen
- scf
- ret
-
-Sony1WinText:
- TX_FAR _Sony1WinText
- db "@"
-
-PlayerBlackedOutText2:
- TX_FAR _PlayerBlackedOutText2
- db "@"
-
-LinkBattleLostText:
- TX_FAR _LinkBattleLostText
- db "@"
-
-; slides pic of fainted mon downwards until it disappears
-; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing
-SlideDownFaintedMonPic:
- ld a, [wd730]
- push af
- set 6, a
- ld [wd730], a
- ld b, 7 ; number of times to slide
-.slideStepLoop ; each iteration, the mon is slid down one row
- push bc
- push de
- push hl
- ld b, 6 ; number of rows
-.rowLoop
- push bc
- push hl
- push de
- ld bc, $7
- call CopyData
- pop de
- pop hl
- ld bc, -SCREEN_WIDTH
- add hl, bc
- push hl
- ld h, d
- ld l, e
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- pop bc
- dec b
- jr nz, .rowLoop
- ld bc, SCREEN_WIDTH
- add hl, bc
- ld de, SevenSpacesText
- call PlaceString
- ld c, 2
- call DelayFrames
- pop hl
- pop de
- pop bc
- dec b
- jr nz, .slideStepLoop
- pop af
- ld [wd730], a
- ret
-
-SevenSpacesText:
- db " @"
-
-; slides the player or enemy trainer off screen
-; a is the number of tiles to slide it horizontally (always 9 for the player trainer or 8 for the enemy trainer)
-; if a is 8, the slide is to the right, else it is to the left
-; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing
-SlideTrainerPicOffScreen:
- ld [hSlideAmount], a
- ld c, a
-.slideStepLoop ; each iteration, the trainer pic is slid one tile left/right
- push bc
- push hl
- ld b, 7 ; number of rows
-.rowLoop
- push hl
- ld a, [hSlideAmount]
- ld c, a
-.columnLoop
- ld a, [hSlideAmount]
- cp 8
- jr z, .slideRight
-.slideLeft ; slide player sprite off screen
- ld a, [hld]
- ld [hli], a
- inc hl
- jr .nextColumn
-.slideRight ; slide enemy trainer sprite off screen
- ld a, [hli]
- ld [hld], a
- dec hl
-.nextColumn
- dec c
- jr nz, .columnLoop
- pop hl
- ld de, 20
- add hl, de
- dec b
- jr nz, .rowLoop
- ld c, 2
- call DelayFrames
- pop hl
- pop bc
- dec c
- jr nz, .slideStepLoop
- ret
-
-; send out a trainer's mon
-EnemySendOut:
- ld hl, wPartyGainExpFlags
- xor a
- ld [hl], a
- ld a, [wPlayerMonNumber]
- ld c, a
- ld b, FLAG_SET
- push bc
- predef FlagActionPredef
- ld hl, wPartyFoughtCurrentEnemyFlags
- xor a
- ld [hl], a
- pop bc
- predef FlagActionPredef
-
-; don't change wPartyGainExpFlags or wPartyFoughtCurrentEnemyFlags
-EnemySendOutFirstMon:
- xor a
- ld hl, wEnemyStatsToDouble ; clear enemy statuses
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wEnemyDisabledMove], a
- ld [wEnemyDisabledMoveNumber], a
- ld [wEnemyMonMinimized], a
- ld hl, wPlayerUsedMove
- ld [hli], a
- ld [hl], a
- dec a
- ld [wAICount], a
- ld hl, wPlayerBattleStatus1
- res 5, [hl]
- coord hl, 18, 0
- ld a, 8
- call SlideTrainerPicOffScreen
- call PrintEmptyString
- call SaveScreenTilesToBuffer1
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .next
- ld a, [wSerialExchangeNybbleReceiveData]
- sub 4
- ld [wWhichPokemon], a
- jr .next3
-.next
- ld b, $FF
-.next2
- inc b
- ld a, [wEnemyMonPartyPos]
- cp b
- jr z, .next2
- ld hl, wEnemyMon1
- ld a, b
- ld [wWhichPokemon], a
- push bc
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- pop bc
- inc hl
- ld a, [hli]
- ld c, a
- ld a, [hl]
- or c
- jr z, .next2
-.next3
- ld a, [wWhichPokemon]
- ld hl, wEnemyMon1Level
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld a, [hl]
- ld [wCurEnemyLVL], a
- ld a, [wWhichPokemon]
- inc a
- ld hl, wEnemyPartyCount
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- ld [wEnemyMonSpecies2], a
- ld [wcf91], a
- call LoadEnemyMonData
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld [wLastSwitchInEnemyMonHP], a
- ld a, [hl]
- ld [wLastSwitchInEnemyMonHP + 1], a
- ld a, 1
- ld [wCurrentMenuItem], a
- ld a, [wFirstMonsNotOutYet]
- dec a
- jr z, .next4
- ld a, [wPartyCount]
- dec a
- jr z, .next4
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr z, .next4
- ld a, [wOptions]
- bit 6, a
- jr nz, .next4
- ld hl, TrainerAboutToUseText
- call PrintText
- coord hl, 0, 7
- lb bc, 8, 1
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, [wCurrentMenuItem]
- and a
- jr nz, .next4
- ld a, BATTLE_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call DisplayPartyMenu
-.next9
- ld a, 1
- ld [wCurrentMenuItem], a
- jr c, .next7
- ld hl, wPlayerMonNumber
- ld a, [wWhichPokemon]
- cp [hl]
- jr nz, .next6
- ld hl, AlreadyOutText
- call PrintText
-.next8
- call GoBackToPartyMenu
- jr .next9
-.next6
- call HasMonFainted
- jr z, .next8
- xor a
- ld [wCurrentMenuItem], a
-.next7
- call GBPalWhiteOut
- call LoadHudTilePatterns
- call LoadScreenTilesFromBuffer1
-.next4
- call ClearSprites
- coord hl, 0, 0
- lb bc, 4, 11
- call ClearScreenArea
- ld b, SET_PAL_BATTLE
- call RunPaletteCommand
- call GBPalNormal
- ld hl, TrainerSentOutText
- call PrintText
- ld a, [wEnemyMonSpecies2]
- ld [wcf91], a
- ld [wd0b5], a
- call GetMonHeader
- ld de, vFrontPic
- call LoadMonFrontSprite
- ld a, -$31
- ld [hStartTileID], a
- coord hl, 15, 6
- predef AnimateSendingOutMon
- ld a, [wEnemyMonSpecies2]
- call PlayCry
- call DrawEnemyHUDAndHPBar
- ld a, [wCurrentMenuItem]
- and a
- ret nz
- xor a
- ld [wPartyGainExpFlags], a
- ld [wPartyFoughtCurrentEnemyFlags], a
- call SaveScreenTilesToBuffer1
- jp SwitchPlayerMon
-
-TrainerAboutToUseText:
- TX_FAR _TrainerAboutToUseText
- db "@"
-
-TrainerSentOutText:
- TX_FAR _TrainerSentOutText
- db "@"
-
-; tests if the player has any pokemon that are not fainted
-; sets d = 0 if all fainted, d != 0 if some mons are still alive
-AnyPartyAlive:
- ld a, [wPartyCount]
- ld e, a
- xor a
- ld hl, wPartyMon1HP
- ld bc, wPartyMon2 - wPartyMon1 - 1
-.partyMonsLoop
- or [hl]
- inc hl
- or [hl]
- add hl, bc
- dec e
- jr nz, .partyMonsLoop
- ld d, a
- ret
-
-; tests if player mon has fainted
-; stores whether mon has fainted in Z flag
-HasMonFainted:
- ld a, [wWhichPokemon]
- ld hl, wPartyMon1HP
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hli]
- or [hl]
- ret nz
- ld a, [wFirstMonsNotOutYet]
- and a
- jr nz, .done
- ld hl, NoWillText
- call PrintText
-.done
- xor a
- ret
-
-NoWillText:
- TX_FAR _NoWillText
- db "@"
-
-; try to run from battle (hl = player speed, de = enemy speed)
-; stores whether the attempt was successful in carry flag
-TryRunningFromBattle:
- call IsGhostBattle
- jp z, .canEscape ; jump if it's a ghost battle
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jp z, .canEscape ; jump if it's a safari battle
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jp z, .canEscape
- ld a, [wIsInBattle]
- dec a
- jr nz, .trainerBattle ; jump if it's a trainer battle
- ld a, [wNumRunAttempts]
- inc a
- ld [wNumRunAttempts], a
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [H_MULTIPLICAND + 2], a
- ld a, [de]
- ld [hEnemySpeed], a
- inc de
- ld a, [de]
- ld [hEnemySpeed + 1], a
- call LoadScreenTilesFromBuffer1
- ld de, H_MULTIPLICAND + 1
- ld hl, hEnemySpeed
- ld c, 2
- call StringCmp
- jr nc, .canEscape ; jump if player speed greater than enemy speed
- xor a
- ld [H_MULTIPLICAND], a
- ld a, 32
- ld [H_MULTIPLIER], a
- call Multiply ; multiply player speed by 32
- ld a, [H_PRODUCT + 2]
- ld [H_DIVIDEND], a
- ld a, [H_PRODUCT + 3]
- ld [H_DIVIDEND + 1], a
- ld a, [hEnemySpeed]
- ld b, a
- ld a, [hEnemySpeed + 1]
-; divide enemy speed by 4
- srl b
- rr a
- srl b
- rr a
- and a
- jr z, .canEscape ; jump if enemy speed divided by 4, mod 256 is 0
- ld [H_DIVISOR], a ; ((enemy speed / 4) % 256)
- ld b, $2
- call Divide ; divide (player speed * 32) by ((enemy speed / 4) % 256)
- ld a, [H_QUOTIENT + 2]
- and a ; is the quotient greater than 256?
- jr nz, .canEscape ; if so, the player can escape
- ld a, [wNumRunAttempts]
- ld c, a
-; add 30 to the quotient for each run attempt
-.loop
- dec c
- jr z, .compareWithRandomValue
- ld b, 30
- ld a, [H_QUOTIENT + 3]
- add b
- ld [H_QUOTIENT + 3], a
- jr c, .canEscape
- jr .loop
-.compareWithRandomValue
- call BattleRandom
- ld b, a
- ld a, [H_QUOTIENT + 3]
- cp b
- jr nc, .canEscape ; if the random value was less than or equal to the quotient
- ; plus 30 times the number of attempts, the player can escape
-; can't escape
- ld a, $1
- ld [wActionResultOrTookBattleTurn], a ; you lose your turn when you can't escape
- ld hl, CantEscapeText
- jr .printCantEscapeOrNoRunningText
-.trainerBattle
- ld hl, NoRunningText
-.printCantEscapeOrNoRunningText
- call PrintText
- ld a, 1
- ld [wForcePlayerToChooseMon], a
- call SaveScreenTilesToBuffer1
- and a ; reset carry
- ret
-.canEscape
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ld a, $2
- jr nz, .playSound
-; link battle
- call SaveScreenTilesToBuffer1
- xor a
- ld [wActionResultOrTookBattleTurn], a
- ld a, LINKBATTLE_RUN
- ld [wPlayerMoveListIndex], a
- call LinkBattleExchangeData
- call LoadScreenTilesFromBuffer1
- ld a, [wSerialExchangeNybbleReceiveData]
- cp LINKBATTLE_RUN
- ld a, $2
- jr z, .playSound
- dec a
-.playSound
- ld [wBattleResult], a
- ld a, SFX_RUN
- call PlaySoundWaitForCurrent
- ld hl, GotAwayText
- call PrintText
- call WaitForSoundToFinish
- call SaveScreenTilesToBuffer1
- scf ; set carry
- ret
-
-CantEscapeText:
- TX_FAR _CantEscapeText
- db "@"
-
-NoRunningText:
- TX_FAR _NoRunningText
- db "@"
-
-GotAwayText:
- TX_FAR _GotAwayText
- db "@"
-
-; copies from party data to battle mon data when sending out a new player mon
-LoadBattleMonFromParty:
- ld a, [wWhichPokemon]
- ld bc, wPartyMon2 - wPartyMon1
- ld hl, wPartyMon1Species
- call AddNTimes
- ld de, wBattleMonSpecies
- ld bc, wBattleMonDVs - wBattleMonSpecies
- call CopyData
- ld bc, wPartyMon1DVs - wPartyMon1OTID
- add hl, bc
- ld de, wBattleMonDVs
- ld bc, NUM_DVS
- call CopyData
- ld de, wBattleMonPP
- ld bc, NUM_MOVES
- call CopyData
- ld de, wBattleMonLevel
- ld bc, wBattleMonPP - wBattleMonLevel
- call CopyData
- ld a, [wBattleMonSpecies2]
- ld [wd0b5], a
- call GetMonHeader
- ld hl, wPartyMonNicks
- ld a, [wPlayerMonNumber]
- call SkipFixedLengthTextEntries
- ld de, wBattleMonNick
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wBattleMonLevel
- ld de, wPlayerMonUnmodifiedLevel ; block of memory used for unmodified stats
- ld bc, 1 + NUM_STATS * 2
- call CopyData
- call ApplyBurnAndParalysisPenaltiesToPlayer
- call ApplyBadgeStatBoosts
- ld a, $7 ; default stat modifier
- ld b, NUM_STAT_MODS
- ld hl, wPlayerMonAttackMod
-.statModLoop
- ld [hli], a
- dec b
- jr nz, .statModLoop
- ret
-
-; copies from enemy party data to current enemy mon data when sending out a new enemy mon
-LoadEnemyMonFromParty:
- ld a, [wWhichPokemon]
- ld bc, wEnemyMon2 - wEnemyMon1
- ld hl, wEnemyMons
- call AddNTimes
- ld de, wEnemyMonSpecies
- ld bc, wEnemyMonDVs - wEnemyMonSpecies
- call CopyData
- ld bc, wEnemyMon1DVs - wEnemyMon1OTID
- add hl, bc
- ld de, wEnemyMonDVs
- ld bc, NUM_DVS
- call CopyData
- ld de, wEnemyMonPP
- ld bc, NUM_MOVES
- call CopyData
- ld de, wEnemyMonLevel
- ld bc, wEnemyMonPP - wEnemyMonLevel
- call CopyData
- ld a, [wEnemyMonSpecies]
- ld [wd0b5], a
- call GetMonHeader
- ld hl, wEnemyMonNicks
- ld a, [wWhichPokemon]
- call SkipFixedLengthTextEntries
- ld de, wEnemyMonNick
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wEnemyMonLevel
- ld de, wEnemyMonUnmodifiedLevel ; block of memory used for unmodified stats
- ld bc, 1 + NUM_STATS * 2
- call CopyData
- call ApplyBurnAndParalysisPenaltiesToEnemy
- ld hl, wMonHBaseStats
- ld de, wEnemyMonBaseStats
- ld b, NUM_STATS
-.copyBaseStatsLoop
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .copyBaseStatsLoop
- ld a, $7 ; default stat modifier
- ld b, NUM_STAT_MODS
- ld hl, wEnemyMonStatMods
-.statModLoop
- ld [hli], a
- dec b
- jr nz, .statModLoop
- ld a, [wWhichPokemon]
- ld [wEnemyMonPartyPos], a
- ret
-
-SendOutMon:
- callab PrintSendOutMonMessage
- ld hl, wEnemyMonHP
- ld a, [hli]
- or [hl] ; is enemy mon HP zero?
- jp z, .skipDrawingEnemyHUDAndHPBar; if HP is zero, skip drawing the HUD and HP bar
- call DrawEnemyHUDAndHPBar
-.skipDrawingEnemyHUDAndHPBar
- call DrawPlayerHUDAndHPBar
- predef LoadMonBackPic
- xor a
- ld [hStartTileID], a
- ld hl, wBattleAndStartSavedMenuItem
- ld [hli], a
- ld [hl], a
- ld [wBoostExpByExpAll], a
- ld [wDamageMultipliers], a
- ld [wPlayerMoveNum], a
- ld hl, wPlayerUsedMove
- ld [hli], a
- ld [hl], a
- ld hl, wPlayerStatsToDouble
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wPlayerDisabledMove], a
- ld [wPlayerDisabledMoveNumber], a
- ld [wPlayerMonMinimized], a
- ld b, SET_PAL_BATTLE
- call RunPaletteCommand
- ld hl, wEnemyBattleStatus1
- res USING_TRAPPING_MOVE, [hl]
- ld a, $1
- ld [H_WHOSETURN], a
- ld a, POOF_ANIM
- call PlayMoveAnimation
- coord hl, 4, 11
- predef AnimateSendingOutMon
- ld a, [wcf91]
- call PlayCry
- call PrintEmptyString
- jp SaveScreenTilesToBuffer1
-
-; show 2 stages of the player mon getting smaller before disappearing
-AnimateRetreatingPlayerMon:
- coord hl, 1, 5
- lb bc, 7, 7
- call ClearScreenArea
- coord hl, 3, 7
- lb bc, 5, 5
- xor a
- ld [wDownscaledMonSize], a
- ld [hBaseTileID], a
- predef CopyDownscaledMonTiles
- ld c, 4
- call DelayFrames
- call .clearScreenArea
- coord hl, 4, 9
- lb bc, 3, 3
- ld a, 1
- ld [wDownscaledMonSize], a
- xor a
- ld [hBaseTileID], a
- predef CopyDownscaledMonTiles
- call Delay3
- call .clearScreenArea
- ld a, $4c
- Coorda 5, 11
-.clearScreenArea
- coord hl, 1, 5
- lb bc, 7, 7
- jp ClearScreenArea
-
-; reads player's current mon's HP into wBattleMonHP
-ReadPlayerMonCurHPAndStatus:
- ld a, [wPlayerMonNumber]
- ld hl, wPartyMon1HP
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld d, h
- ld e, l
- ld hl, wBattleMonHP
- ld bc, $4 ; 2 bytes HP, 1 byte unknown (unused?), 1 byte status
- jp CopyData
-
-DrawHUDsAndHPBars:
- call DrawPlayerHUDAndHPBar
- jp DrawEnemyHUDAndHPBar
-
-DrawPlayerHUDAndHPBar:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 9, 7
- lb bc, 5, 11
- call ClearScreenArea
- callab PlacePlayerHUDTiles
- coord hl, 18, 9
- ld [hl], $73
- ld de, wBattleMonNick
- coord hl, 10, 7
- call CenterMonName
- call PlaceString
- ld hl, wBattleMonSpecies
- ld de, wLoadedMon
- ld bc, wBattleMonDVs - wBattleMonSpecies
- call CopyData
- ld hl, wBattleMonLevel
- ld de, wLoadedMonLevel
- ld bc, wBattleMonPP - wBattleMonLevel
- call CopyData
- coord hl, 14, 8
- push hl
- inc hl
- ld de, wLoadedMonStatus
- call PrintStatusConditionNotFainted
- pop hl
- jr nz, .doNotPrintLevel
- call PrintLevel
-.doNotPrintLevel
- ld a, [wLoadedMonSpecies]
- ld [wcf91], a
- coord hl, 10, 9
- predef DrawHP
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld hl, wPlayerHPBarColor
- call GetBattleHealthBarColor
- ld hl, wBattleMonHP
- ld a, [hli]
- or [hl]
- jr z, .fainted
- ld a, [wLowHealthAlarmDisabled]
- and a ; has the alarm been disabled because the player has already won?
- ret nz ; if so, return
- ld a, [wPlayerHPBarColor]
- cp HP_BAR_RED
- jr z, .setLowHealthAlarm
-.fainted
- ld hl, wLowHealthAlarm
- bit 7, [hl] ;low health alarm enabled?
- ld [hl], $0
- ret z
- xor a
- ld [wChannelSoundIDs + Ch4], a
- ret
-.setLowHealthAlarm
- ld hl, wLowHealthAlarm
- set 7, [hl] ;enable low health alarm
- ret
-
-DrawEnemyHUDAndHPBar:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 0, 0
- lb bc, 4, 12
- call ClearScreenArea
- callab PlaceEnemyHUDTiles
- ld de, wEnemyMonNick
- coord hl, 1, 0
- call CenterMonName
- call PlaceString
- coord hl, 4, 1
- push hl
- inc hl
- ld de, wEnemyMonStatus
- call PrintStatusConditionNotFainted
- pop hl
- jr nz, .skipPrintLevel ; if the mon has a status condition, skip printing the level
- ld a, [wEnemyMonLevel]
- ld [wLoadedMonLevel], a
- call PrintLevel
-.skipPrintLevel
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hld]
- ld [H_MULTIPLICAND + 2], a
- or [hl] ; is current HP zero?
- jr nz, .hpNonzero
-; current HP is 0
-; set variables for DrawHPBar
- ld c, a
- ld e, a
- ld d, $6
- jp .drawHPBar
-.hpNonzero
- xor a
- ld [H_MULTIPLICAND], a
- ld a, 48
- ld [H_MULTIPLIER], a
- call Multiply ; multiply current HP by 48
- ld hl, wEnemyMonMaxHP
- ld a, [hli]
- ld b, a
- ld a, [hl]
- ld [H_DIVISOR], a
- ld a, b
- and a ; is max HP > 255?
- jr z, .doDivide
-; if max HP > 255, scale both (current HP * 48) and max HP by dividing by 4 so that max HP fits in one byte
-; (it needs to be one byte so it can be used as the divisor for the Divide function)
- ld a, [H_DIVISOR]
- srl b
- rr a
- srl b
- rr a
- ld [H_DIVISOR], a
- ld a, [H_PRODUCT + 2]
- ld b, a
- srl b
- ld a, [H_PRODUCT + 3]
- rr a
- srl b
- rr a
- ld [H_PRODUCT + 3], a
- ld a, b
- ld [H_PRODUCT + 2], a
-.doDivide
- ld a, [H_PRODUCT + 2]
- ld [H_DIVIDEND], a
- ld a, [H_PRODUCT + 3]
- ld [H_DIVIDEND + 1], a
- ld a, $2
- ld b, a
- call Divide ; divide (current HP * 48) by max HP
- ld a, [H_QUOTIENT + 3]
-; set variables for DrawHPBar
- ld e, a
- ld a, $6
- ld d, a
- ld c, a
-.drawHPBar
- xor a
- ld [wHPBarType], a
- coord hl, 2, 2
- call DrawHPBar
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld hl, wEnemyHPBarColor
-
-GetBattleHealthBarColor:
- ld b, [hl]
- call GetHealthBarColor
- ld a, [hl]
- cp b
- ret z
- ld b, SET_PAL_BATTLE
- jp RunPaletteCommand
-
-; center's mon's name on the battle screen
-; if the name is 1 or 2 letters long, it is printed 2 spaces more to the right than usual
-; (i.e. for names longer than 4 letters)
-; if the name is 3 or 4 letters long, it is printed 1 space more to the right than usual
-; (i.e. for names longer than 4 letters)
-CenterMonName:
- push de
- inc hl
- inc hl
- ld b, $2
-.loop
- inc de
- ld a, [de]
- cp "@"
- jr z, .done
- inc de
- ld a, [de]
- cp "@"
- jr z, .done
- dec hl
- dec b
- jr nz, .loop
-.done
- pop de
- ret
-
-DisplayBattleMenu:
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- ld a, [wBattleType]
- and a
- jr nz, .nonstandardbattle
- call DrawHUDsAndHPBars
- call PrintEmptyString
- call SaveScreenTilesToBuffer1
-.nonstandardbattle
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- ld a, BATTLE_MENU_TEMPLATE
- jr nz, .menuselected
- ld a, SAFARI_BATTLE_MENU_TEMPLATE
-.menuselected
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, [wBattleType]
- dec a
- jp nz, .handleBattleMenuInput ; handle menu input if it's not the old man tutorial
-; the following happens for the old man tutorial
- ld hl, wPlayerName
- ld de, wGrassRate
- ld bc, NAME_LENGTH
- call CopyData ; temporarily save the player name in unused space,
- ; which is supposed to get overwritten when entering a
- ; map with wild Pokémon. Due to an oversight, the data
- ; may not get overwritten (cinnabar) and the infamous
- ; Missingno. glitch can show up.
- ld hl, .oldManName
- ld de, wPlayerName
- ld bc, NAME_LENGTH
- call CopyData
-; the following simulates the keystrokes by drawing menus on screen
- coord hl, 9, 14
- ld [hl], "▶"
- ld c, 80
- call DelayFrames
- ld [hl], " "
- coord hl, 9, 16
- ld [hl], "▶"
- ld c, 50
- call DelayFrames
- ld [hl], "▷"
- ld a, $2 ; select the "ITEM" menu
- jp .upperLeftMenuItemWasNotSelected
-.oldManName
- db "OLD MAN@"
-.handleBattleMenuInput
- ld a, [wBattleAndStartSavedMenuItem]
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- sub 2 ; check if the cursor is in the left column
- jr c, .leftColumn
-; cursor is in the right column
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- jr .rightColumn
-.leftColumn ; put cursor in left column of menu
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- ld a, " "
- jr z, .safariLeftColumn
-; put cursor in left column for normal battle menu (i.e. when it's not a Safari battle)
- Coorda 15, 14 ; clear upper cursor position in right column
- Coorda 15, 16 ; clear lower cursor position in right column
- ld b, $9 ; top menu item X
- jr .leftColumn_WaitForInput
-.safariLeftColumn
- Coorda 13, 14
- Coorda 13, 16
- coord hl, 7, 14
- ld de, wNumSafariBalls
- lb bc, 1, 2
- call PrintNumber
- ld b, $1 ; top menu item X
-.leftColumn_WaitForInput
- ld hl, wTopMenuItemY
- ld a, $e
- ld [hli], a ; wTopMenuItemY
- ld a, b
- ld [hli], a ; wTopMenuItemX
- inc hl
- inc hl
- ld a, $1
- ld [hli], a ; wMaxMenuItem
- ld [hl], D_RIGHT | A_BUTTON ; wMenuWatchedKeys
- call HandleMenuInput
- bit 4, a ; check if right was pressed
- jr nz, .rightColumn
- jr .AButtonPressed ; the A button was pressed
-.rightColumn ; put cursor in right column of menu
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- ld a, " "
- jr z, .safariRightColumn
-; put cursor in right column for normal battle menu (i.e. when it's not a Safari battle)
- Coorda 9, 14 ; clear upper cursor position in left column
- Coorda 9, 16 ; clear lower cursor position in left column
- ld b, $f ; top menu item X
- jr .rightColumn_WaitForInput
-.safariRightColumn
- Coorda 1, 14 ; clear upper cursor position in left column
- Coorda 1, 16 ; clear lower cursor position in left column
- coord hl, 7, 14
- ld de, wNumSafariBalls
- lb bc, 1, 2
- call PrintNumber
- ld b, $d ; top menu item X
-.rightColumn_WaitForInput
- ld hl, wTopMenuItemY
- ld a, $e
- ld [hli], a ; wTopMenuItemY
- ld a, b
- ld [hli], a ; wTopMenuItemX
- inc hl
- inc hl
- ld a, $1
- ld [hli], a ; wMaxMenuItem
- ld a, D_LEFT | A_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- call HandleMenuInput
- bit 5, a ; check if left was pressed
- jr nz, .leftColumn ; if left was pressed, jump
- ld a, [wCurrentMenuItem]
- add $2 ; if we're in the right column, the actual id is +2
- ld [wCurrentMenuItem], a
-.AButtonPressed
- call PlaceUnfilledArrowMenuCursor
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- ld a, [wCurrentMenuItem]
- ld [wBattleAndStartSavedMenuItem], a
- jr z, .handleMenuSelection
-; not Safari battle
-; swap the IDs of the item menu and party menu (this is probably because they swapped the positions
-; of these menu items in first generation English versions)
- cp $1 ; was the item menu selected?
- jr nz, .notItemMenu
-; item menu was selected
- inc a ; increment a to 2
- jr .handleMenuSelection
-.notItemMenu
- cp $2 ; was the party menu selected?
- jr nz, .handleMenuSelection
-; party menu selected
- dec a ; decrement a to 1
-.handleMenuSelection
- and a
- jr nz, .upperLeftMenuItemWasNotSelected
-; the upper left menu item was selected
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr z, .throwSafariBallWasSelected
-; the "FIGHT" menu was selected
- xor a
- ld [wNumRunAttempts], a
- jp LoadScreenTilesFromBuffer1 ; restore saved screen and return
-.throwSafariBallWasSelected
- ld a, SAFARI_BALL
- ld [wcf91], a
- jr UseBagItem
-
-.upperLeftMenuItemWasNotSelected ; a menu item other than the upper left item was selected
- cp $2
- jp nz, PartyMenuOrRockOrRun
-
-; either the bag (normal battle) or bait (safari battle) was selected
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
-
-; can't use items in link battles
- ld hl, ItemsCantBeUsedHereText
- call PrintText
- jp DisplayBattleMenu
-
-.notLinkBattle
- call SaveScreenTilesToBuffer2
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr nz, BagWasSelected
-
-; bait was selected
- ld a, SAFARI_BAIT
- ld [wcf91], a
- jr UseBagItem
-
-BagWasSelected:
- call LoadScreenTilesFromBuffer1
- ld a, [wBattleType]
- and a ; is it a normal battle?
- jr nz, .next
-
-; normal battle
- call DrawHUDsAndHPBars
-.next
- ld a, [wBattleType]
- dec a ; is it the old man tutorial?
- jr nz, DisplayPlayerBag ; no, it is a normal battle
- ld hl, OldManItemList
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- jr DisplayBagMenu
-
-OldManItemList:
- db 1 ; # items
- db POKE_BALL, 50
- db -1
-
-DisplayPlayerBag:
- ; get the pointer to player's bag when in a normal battle
- ld hl, wNumBagItems
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
-
-DisplayBagMenu:
- xor a
- ld [wPrintItemPrices], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- ld a, [wBagSavedMenuItem]
- ld [wCurrentMenuItem], a
- call DisplayListMenuID
- ld a, [wCurrentMenuItem]
- ld [wBagSavedMenuItem], a
- ld a, $0
- ld [wMenuWatchMovingOutOfBounds], a
- ld [wMenuItemToSwap], a
- jp c, DisplayBattleMenu ; go back to battle menu if an item was not selected
-
-UseBagItem:
- ; either use an item from the bag or use a safari zone item
- ld a, [wcf91]
- ld [wd11e], a
- call GetItemName
- call CopyStringToCF4B ; copy name
- xor a
- ld [wPseudoItemID], a
- call UseItem
- call LoadHudTilePatterns
- call ClearSprites
- xor a
- ld [wCurrentMenuItem], a
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr z, .checkIfMonCaptured
-
- ld a, [wActionResultOrTookBattleTurn]
- and a ; was the item used successfully?
- jp z, BagWasSelected ; if not, go back to the bag menu
-
- ld a, [wPlayerBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; is the player using a multi-turn move like wrap?
- jr z, .checkIfMonCaptured
- ld hl, wPlayerNumAttacksLeft
- dec [hl]
- jr nz, .checkIfMonCaptured
- ld hl, wPlayerBattleStatus1
- res USING_TRAPPING_MOVE, [hl] ; not using multi-turn move any more
-
-.checkIfMonCaptured
- ld a, [wCapturedMonSpecies]
- and a ; was the enemy mon captured with a ball?
- jr nz, .returnAfterCapturingMon
-
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr z, .returnAfterUsingItem_NoCapture
-; not a safari battle
- call LoadScreenTilesFromBuffer1
- call DrawHUDsAndHPBars
- call Delay3
-.returnAfterUsingItem_NoCapture
-
- call GBPalNormal
- and a ; reset carry
- ret
-
-.returnAfterCapturingMon
- call GBPalNormal
- xor a
- ld [wCapturedMonSpecies], a
- ld a, $2
- ld [wBattleResult], a
- scf ; set carry
- ret
-
-ItemsCantBeUsedHereText:
- TX_FAR _ItemsCantBeUsedHereText
- db "@"
-
-PartyMenuOrRockOrRun:
- dec a ; was Run selected?
- jp nz, BattleMenu_RunWasSelected
-; party menu or rock was selected
- call SaveScreenTilesToBuffer2
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr nz, .partyMenuWasSelected
-; safari battle
- ld a, SAFARI_ROCK
- ld [wcf91], a
- jp UseBagItem
-.partyMenuWasSelected
- call LoadScreenTilesFromBuffer1
- xor a ; NORMAL_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- ld [wMenuItemToSwap], a
- call DisplayPartyMenu
-.checkIfPartyMonWasSelected
- jp nc, .partyMonWasSelected ; if a party mon was selected, jump, else we quit the party menu
-.quitPartyMenu
- call ClearSprites
- call GBPalWhiteOut
- call LoadHudTilePatterns
- call LoadScreenTilesFromBuffer2
- call RunDefaultPaletteCommand
- call GBPalNormal
- jp DisplayBattleMenu
-.partyMonDeselected
- coord hl, 11, 11
- ld bc, 6 * SCREEN_WIDTH + 9
- ld a, " "
- call FillMemory
- xor a ; NORMAL_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call GoBackToPartyMenu
- jr .checkIfPartyMonWasSelected
-.partyMonWasSelected
- ld a, SWITCH_STATS_CANCEL_MENU_TEMPLATE
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld hl, wTopMenuItemY
- ld a, $c
- ld [hli], a ; wTopMenuItemY
- ld [hli], a ; wTopMenuItemX
- xor a
- ld [hli], a ; wCurrentMenuItem
- inc hl
- ld a, $2
- ld [hli], a ; wMaxMenuItem
- ld a, B_BUTTON | A_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- xor a
- ld [hl], a ; wLastMenuItem
- call HandleMenuInput
- bit 1, a ; was A pressed?
- jr nz, .partyMonDeselected ; if B was pressed, jump
-; A was pressed
- call PlaceUnfilledArrowMenuCursor
- ld a, [wCurrentMenuItem]
- cp $2 ; was Cancel selected?
- jr z, .quitPartyMenu ; if so, quit the party menu entirely
- and a ; was Switch selected?
- jr z, .switchMon ; if so, jump
-; Stats was selected
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- ld hl, wPartyMon1
- call ClearSprites
-; display the two status screens
- predef StatusScreen
- predef StatusScreen2
-; now we need to reload the enemy mon pic
- ld a, [wEnemyBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a ; does the enemy mon have a substitute?
- ld hl, AnimationSubstitute
- jr nz, .doEnemyMonAnimation
-; enemy mon doesn't have substitute
- ld a, [wEnemyMonMinimized]
- and a ; has the enemy mon used Minimise?
- ld hl, AnimationMinimizeMon
- jr nz, .doEnemyMonAnimation
-; enemy mon is not minimised
- ld a, [wEnemyMonSpecies]
- ld [wcf91], a
- ld [wd0b5], a
- call GetMonHeader
- ld de, vFrontPic
- call LoadMonFrontSprite
- jr .enemyMonPicReloaded
-.doEnemyMonAnimation
- ld b, BANK(AnimationSubstitute) ; BANK(AnimationMinimizeMon)
- call Bankswitch
-.enemyMonPicReloaded ; enemy mon pic has been reloaded, so return to the party menu
- jp .partyMenuWasSelected
-.switchMon
- ld a, [wPlayerMonNumber]
- ld d, a
- ld a, [wWhichPokemon]
- cp d ; check if the mon to switch to is already out
- jr nz, .notAlreadyOut
-; mon is already out
- ld hl, AlreadyOutText
- call PrintText
- jp .partyMonDeselected
-.notAlreadyOut
- call HasMonFainted
- jp z, .partyMonDeselected ; can't switch to fainted mon
- ld a, $1
- ld [wActionResultOrTookBattleTurn], a
- call GBPalWhiteOut
- call ClearSprites
- call LoadHudTilePatterns
- call LoadScreenTilesFromBuffer1
- call RunDefaultPaletteCommand
- call GBPalNormal
-; fall through to SwitchPlayerMon
-
-SwitchPlayerMon:
- callab RetreatMon
- ld c, 50
- call DelayFrames
- call AnimateRetreatingPlayerMon
- ld a, [wWhichPokemon]
- ld [wPlayerMonNumber], a
- ld c, a
- ld b, FLAG_SET
- push bc
- ld hl, wPartyGainExpFlags
- predef FlagActionPredef
- pop bc
- ld hl, wPartyFoughtCurrentEnemyFlags
- predef FlagActionPredef
- call LoadBattleMonFromParty
- call SendOutMon
- call SaveScreenTilesToBuffer1
- ld a, $2
- ld [wCurrentMenuItem], a
- and a
- ret
-
-AlreadyOutText:
- TX_FAR _AlreadyOutText
- db "@"
-
-BattleMenu_RunWasSelected:
- call LoadScreenTilesFromBuffer1
- ld a, $3
- ld [wCurrentMenuItem], a
- ld hl, wBattleMonSpeed
- ld de, wEnemyMonSpeed
- call TryRunningFromBattle
- ld a, 0
- ld [wForcePlayerToChooseMon], a
- ret c
- ld a, [wActionResultOrTookBattleTurn]
- and a
- ret nz ; return if the player couldn't escape
- jp DisplayBattleMenu
-
-MoveSelectionMenu:
- ld a, [wMoveMenuType]
- dec a
- jr z, .mimicmenu
- dec a
- jr z, .relearnmenu
- jr .regularmenu
-
-.loadmoves
- ld de, wMoves
- ld bc, NUM_MOVES
- call CopyData
- callab FormatMovesString
- ret
-
-.writemoves
- ld de, wMovesString
- ld a, [hFlags_0xFFF6]
- set 2, a
- ld [hFlags_0xFFF6], a
- call PlaceString
- ld a, [hFlags_0xFFF6]
- res 2, a
- ld [hFlags_0xFFF6], a
- ret
-
-.regularmenu
- call AnyMoveToSelect
- ret z
- ld hl, wBattleMonMoves
- call .loadmoves
- coord hl, 4, 12
- ld b, 4
- ld c, 14
- di ; out of pure coincidence, it is possible for vblank to occur between the di and ei
- ; so it is necessary to put the di ei block to not cause tearing
- call TextBoxBorder
- coord hl, 4, 12
- ld [hl], $7a
- coord hl, 10, 12
- ld [hl], $7e
- ei
- coord hl, 6, 13
- call .writemoves
- ld b, $5
- ld a, $c
- jr .menuset
-.mimicmenu
- ld hl, wEnemyMonMoves
- call .loadmoves
- coord hl, 0, 7
- ld b, 4
- ld c, 14
- call TextBoxBorder
- coord hl, 2, 8
- call .writemoves
- ld b, $1
- ld a, $7
- jr .menuset
-.relearnmenu
- ld a, [wWhichPokemon]
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- call .loadmoves
- coord hl, 4, 7
- ld b, 4
- ld c, 14
- call TextBoxBorder
- coord hl, 6, 8
- call .writemoves
- ld b, $5
- ld a, $7
-.menuset
- ld hl, wTopMenuItemY
- ld [hli], a ; wTopMenuItemY
- ld a, b
- ld [hli], a ; wTopMenuItemX
- ld a, [wMoveMenuType]
- cp $1
- jr z, .selectedmoveknown
- ld a, $1
- jr nc, .selectedmoveknown
- ld a, [wPlayerMoveListIndex]
- inc a
-.selectedmoveknown
- ld [hli], a ; wCurrentMenuItem
- inc hl ; wTileBehindCursor untouched
- ld a, [wNumMovesMinusOne]
- inc a
- inc a
- ld [hli], a ; wMaxMenuItem
- ld a, [wMoveMenuType]
- dec a
- ld b, D_UP | D_DOWN | A_BUTTON
- jr z, .matchedkeyspicked
- dec a
- ld b, D_UP | D_DOWN | A_BUTTON | B_BUTTON
- jr z, .matchedkeyspicked
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr z, .matchedkeyspicked
- ld a, [wFlags_D733]
- bit BIT_TEST_BATTLE, a
- ld b, D_UP | D_DOWN | A_BUTTON | B_BUTTON | SELECT
- jr z, .matchedkeyspicked
- ld b, $ff
-.matchedkeyspicked
- ld a, b
- ld [hli], a ; wMenuWatchedKeys
- ld a, [wMoveMenuType]
- cp $1
- jr z, .movelistindex1
- ld a, [wPlayerMoveListIndex]
- inc a
-.movelistindex1
- ld [hl], a
-; fallthrough
-
-SelectMenuItem:
- ld a, [wMoveMenuType]
- and a
- jr z, .battleselect
- dec a
- jr nz, .select
- coord hl, 1, 14
- ld de, WhichTechniqueString
- call PlaceString
- jr .select
-.battleselect
- ld a, [wFlags_D733]
- bit BIT_TEST_BATTLE, a
- jr nz, .select
- call PrintMenuItem
- ld a, [wMenuItemToSwap]
- and a
- jr z, .select
- coord hl, 5, 13
- dec a
- ld bc, SCREEN_WIDTH
- call AddNTimes
- ld [hl], "▷"
-.select
- ld hl, hFlags_0xFFF6
- set 1, [hl]
- call HandleMenuInput
- ld hl, hFlags_0xFFF6
- res 1, [hl]
- bit 6, a
- jp nz, SelectMenuItem_CursorUp ; up
- bit 7, a
- jp nz, SelectMenuItem_CursorDown ; down
- bit 2, a
- jp nz, SwapMovesInMenu ; select
- bit 1, a ; B, but was it reset above?
- push af
- xor a
- ld [wMenuItemToSwap], a
- ld a, [wCurrentMenuItem]
- dec a
- ld [wCurrentMenuItem], a
- ld b, a
- ld a, [wMoveMenuType]
- dec a ; if not mimic
- jr nz, .notB
- pop af
- ret
-.notB
- dec a
- ld a, b
- ld [wPlayerMoveListIndex], a
- jr nz, .moveselected
- pop af
- ret
-.moveselected
- pop af
- ret nz
- ld hl, wBattleMonPP
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hl]
- and $3f
- jr z, .noPP
- ld a, [wPlayerDisabledMove]
- swap a
- and $f
- dec a
- cp c
- jr z, .disabled
- ld a, [wPlayerBattleStatus3]
- bit 3, a ; transformed
- jr nz, .dummy ; game freak derp
-.dummy
- ld a, [wCurrentMenuItem]
- ld hl, wBattleMonMoves
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hl]
- ld [wPlayerSelectedMove], a
- xor a
- ret
-.disabled
- ld hl, MoveDisabledText
- jr .print
-.noPP
- ld hl, MoveNoPPText
-.print
- call PrintText
- call LoadScreenTilesFromBuffer1
- jp MoveSelectionMenu
-
-MoveNoPPText:
- TX_FAR _MoveNoPPText
- db "@"
-
-MoveDisabledText:
- TX_FAR _MoveDisabledText
- db "@"
-
-WhichTechniqueString:
- db "WHICH TECHNIQUE?@"
-
-SelectMenuItem_CursorUp:
- ld a, [wCurrentMenuItem]
- and a
- jp nz, SelectMenuItem
- call EraseMenuCursor
- ld a, [wNumMovesMinusOne]
- inc a
- ld [wCurrentMenuItem], a
- jp SelectMenuItem
-
-SelectMenuItem_CursorDown:
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wNumMovesMinusOne]
- inc a
- inc a
- cp b
- jp nz, SelectMenuItem
- call EraseMenuCursor
- ld a, $1
- ld [wCurrentMenuItem], a
- jp SelectMenuItem
-
-AnyMoveToSelect:
-; return z and Struggle as the selected move if all moves have 0 PP and/or are disabled
- ld a, STRUGGLE
- ld [wPlayerSelectedMove], a
- ld a, [wPlayerDisabledMove]
- and a
- ld hl, wBattleMonPP
- jr nz, .handleDisabledMove
- ld a, [hli]
- or [hl]
- inc hl
- or [hl]
- inc hl
- or [hl]
- and $3f
- ret nz
- jr .noMovesLeft
-.handleDisabledMove
- swap a
- and $f ; get disabled move
- ld b, a
- ld d, NUM_MOVES + 1
- xor a
-.handleDisabledMovePPLoop
- dec d
- jr z, .allMovesChecked
- ld c, [hl] ; get move PP
- inc hl
- dec b ; is this the disabled move?
- jr z, .handleDisabledMovePPLoop ; if so, ignore its PP value
- or c
- jr .handleDisabledMovePPLoop
-.allMovesChecked
- and a ; any PP left?
- ret nz ; return if a move has PP left
-.noMovesLeft
- ld hl, NoMovesLeftText
- call PrintText
- ld c, 60
- call DelayFrames
- xor a
- ret
-
-NoMovesLeftText:
- TX_FAR _NoMovesLeftText
- db "@"
-
-SwapMovesInMenu:
- ld a, [wMenuItemToSwap]
- and a
- jr z, .noMenuItemSelected
- ld hl, wBattleMonMoves
- call .swapBytes ; swap moves
- ld hl, wBattleMonPP
- call .swapBytes ; swap move PP
-; update the index of the disabled move if necessary
- ld hl, wPlayerDisabledMove
- ld a, [hl]
- swap a
- and $f
- ld b, a
- ld a, [wCurrentMenuItem]
- cp b
- jr nz, .next
- ld a, [hl]
- and $f
- ld b, a
- ld a, [wMenuItemToSwap]
- swap a
- add b
- ld [hl], a
- jr .swapMovesInPartyMon
-.next
- ld a, [wMenuItemToSwap]
- cp b
- jr nz, .swapMovesInPartyMon
- ld a, [hl]
- and $f
- ld b, a
- ld a, [wCurrentMenuItem]
- swap a
- add b
- ld [hl], a
-.swapMovesInPartyMon
- ld hl, wPartyMon1Moves
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- push hl
- call .swapBytes ; swap moves
- pop hl
- ld bc, wPartyMon1PP - wPartyMon1Moves
- add hl, bc
- call .swapBytes ; swap move PP
- xor a
- ld [wMenuItemToSwap], a ; deselect the item
- jp MoveSelectionMenu
-.swapBytes
- push hl
- ld a, [wMenuItemToSwap]
- dec a
- ld c, a
- ld b, 0
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [wCurrentMenuItem]
- 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
-.noMenuItemSelected
- ld a, [wCurrentMenuItem]
- ld [wMenuItemToSwap], a ; select the current menu item for swapping
- jp MoveSelectionMenu
-
-PrintMenuItem:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 0, 8
- ld b, 3
- ld c, 9
- call TextBoxBorder
- ld a, [wPlayerDisabledMove]
- and a
- jr z, .notDisabled
- swap a
- and $f
- ld b, a
- ld a, [wCurrentMenuItem]
- cp b
- jr nz, .notDisabled
- coord hl, 1, 10
- ld de, DisabledText
- call PlaceString
- jr .moveDisabled
-.notDisabled
- ld hl, wCurrentMenuItem
- dec [hl]
- xor a
- ld [H_WHOSETURN], a
- ld hl, wBattleMonMoves
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, $0 ; which item in the menu is the cursor pointing to? (0-3)
- add hl, bc ; point to the item (move) in memory
- ld a, [hl]
- ld [wPlayerSelectedMove], a ; update wPlayerSelectedMove even if the move
- ; isn't actually selected (just pointed to by the cursor)
- ld a, [wPlayerMonNumber]
- ld [wWhichPokemon], a
- ld a, BATTLE_MON_DATA
- ld [wMonDataLocation], a
- callab GetMaxPP
- ld hl, wCurrentMenuItem
- ld c, [hl]
- inc [hl]
- ld b, $0
- ld hl, wBattleMonPP
- add hl, bc
- ld a, [hl]
- and $3f
- ld [wcd6d], a
-; print TYPE/<type> and <curPP>/<maxPP>
- coord hl, 1, 9
- ld de, TypeText
- call PlaceString
- coord hl, 7, 11
- ld [hl], "/"
- coord hl, 5, 9
- ld [hl], "/"
- coord hl, 5, 11
- ld de, wcd6d
- lb bc, 1, 2
- call PrintNumber
- coord hl, 8, 11
- ld de, wMaxPP
- lb bc, 1, 2
- call PrintNumber
- call GetCurrentMove
- coord hl, 2, 10
- predef PrintMoveType
-.moveDisabled
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- jp Delay3
-
-DisabledText:
- db "disabled!@"
-
-TypeText:
- db "TYPE@"
-
-SelectEnemyMove:
- ld a, [wLinkState]
- sub LINK_STATE_BATTLING
- jr nz, .noLinkBattle
-; link battle
- call SaveScreenTilesToBuffer1
- call LinkBattleExchangeData
- call LoadScreenTilesFromBuffer1
- ld a, [wSerialExchangeNybbleReceiveData]
- cp LINKBATTLE_STRUGGLE
- jp z, .linkedOpponentUsedStruggle
- cp LINKBATTLE_NO_ACTION
- jr z, .unableToSelectMove
- cp 4
- ret nc
- ld [wEnemyMoveListIndex], a
- ld c, a
- ld hl, wEnemyMonMoves
- ld b, 0
- add hl, bc
- ld a, [hl]
- jr .done
-.noLinkBattle
- ld a, [wEnemyBattleStatus2]
- and (1 << NEEDS_TO_RECHARGE) | (1 << USING_RAGE) ; need to recharge or using rage
- ret nz
- ld hl, wEnemyBattleStatus1
- ld a, [hl]
- and (1 << CHARGING_UP) | (1 << THRASHING_ABOUT) ; using a charging move or thrash/petal dance
- ret nz
- ld a, [wEnemyMonStatus]
- and SLP | 1 << FRZ ; sleeping or frozen
- ret nz
- ld a, [wEnemyBattleStatus1]
- and (1 << USING_TRAPPING_MOVE) | (1 << STORING_ENERGY) ; using a trapping move like wrap or bide
- ret nz
- ld a, [wPlayerBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; caught in player's trapping move (e.g. wrap)
- jr z, .canSelectMove
-.unableToSelectMove
- ld a, $ff
- jr .done
-.canSelectMove
- ld hl, wEnemyMonMoves+1 ; 2nd enemy move
- ld a, [hld]
- and a
- jr nz, .atLeastTwoMovesAvailable
- ld a, [wEnemyDisabledMove]
- and a
- ld a, STRUGGLE ; struggle if the only move is disabled
- jr nz, .done
-.atLeastTwoMovesAvailable
- ld a, [wIsInBattle]
- dec a
- jr z, .chooseRandomMove ; wild encounter
- callab AIEnemyTrainerChooseMoves
-.chooseRandomMove
- push hl
- call BattleRandom
- ld b, $1
- cp $3f ; select move 1, [0,3e] (63/256 chance)
- jr c, .moveChosen
- inc hl
- inc b
- cp $7f ; select move 2, [3f,7e] (64/256 chance)
- jr c, .moveChosen
- inc hl
- inc b
- cp $be ; select move 3, [7f,bd] (63/256 chance)
- jr c, .moveChosen
- inc hl
- inc b ; select move 4, [be,ff] (66/256 chance)
-.moveChosen
- ld a, b
- dec a
- ld [wEnemyMoveListIndex], a
- ld a, [wEnemyDisabledMove]
- swap a
- and $f
- cp b
- ld a, [hl]
- pop hl
- jr z, .chooseRandomMove ; move disabled, try again
- and a
- jr z, .chooseRandomMove ; move non-existant, try again
-.done
- ld [wEnemySelectedMove], a
- ret
-.linkedOpponentUsedStruggle
- ld a, STRUGGLE
- jr .done
-
-; this appears to exchange data with the other gameboy during link battles
-LinkBattleExchangeData:
- ld a, $ff
- ld [wSerialExchangeNybbleReceiveData], a
- ld a, [wPlayerMoveListIndex]
- cp LINKBATTLE_RUN ; is the player running from battle?
- jr z, .doExchange
- ld a, [wActionResultOrTookBattleTurn]
- and a ; is the player switching in another mon?
- jr nz, .switching
-; the player used a move
- ld a, [wPlayerSelectedMove]
- cp STRUGGLE
- ld b, LINKBATTLE_STRUGGLE
- jr z, .next
- dec b ; LINKBATTLE_NO_ACTION
- inc a ; does move equal -1 (i.e. no action)?
- jr z, .next
- ld a, [wPlayerMoveListIndex]
- jr .doExchange
-.switching
- ld a, [wWhichPokemon]
- add 4
- ld b, a
-.next
- ld a, b
-.doExchange
- ld [wSerialExchangeNybbleSendData], a
- callab PrintWaitingText
-.syncLoop1
- call Serial_ExchangeNybble
- call DelayFrame
- ld a, [wSerialExchangeNybbleReceiveData]
- inc a
- jr z, .syncLoop1
- ld b, 10
-.syncLoop2
- call DelayFrame
- call Serial_ExchangeNybble
- dec b
- jr nz, .syncLoop2
- ld b, 10
-.syncLoop3
- call DelayFrame
- call Serial_SendZeroByte
- dec b
- jr nz, .syncLoop3
- ret
-
-ExecutePlayerMove:
- xor a
- ld [H_WHOSETURN], a ; set player's turn
- ld a, [wPlayerSelectedMove]
- inc a
- jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn
- xor a
- ld [wMoveMissed], a
- ld [wMonIsDisobedient], a
- ld [wMoveDidntMiss], a
- ld a, $a
- ld [wDamageMultipliers], a
- ld a, [wActionResultOrTookBattleTurn]
- and a ; has the player already used the turn (e.g. by using an item, trying to run or switching pokemon)
- jp nz, ExecutePlayerMoveDone
- call PrintGhostText
- jp z, ExecutePlayerMoveDone
- call CheckPlayerStatusConditions
- jr nz, .playerHasNoSpecialCondition
- jp hl
-.playerHasNoSpecialCondition
- call GetCurrentMove
- ld hl, wPlayerBattleStatus1
- bit CHARGING_UP, [hl] ; charging up for attack
- jr nz, PlayerCanExecuteChargingMove
- call CheckForDisobedience
- jp z, ExecutePlayerMoveDone
-
-CheckIfPlayerNeedsToChargeUp:
- ld a, [wPlayerMoveEffect]
- cp CHARGE_EFFECT
- jp z, JumpMoveEffect
- cp FLY_EFFECT
- jp z, JumpMoveEffect
- jr PlayerCanExecuteMove
-
-; in-battle stuff
-PlayerCanExecuteChargingMove:
- ld hl, wPlayerBattleStatus1
- res CHARGING_UP, [hl] ; reset charging up and invulnerability statuses if mon was charging up for an attack
- ; being fully paralyzed or hurting oneself in confusion removes charging up status
- ; resulting in the Pokemon being invulnerable for the whole battle
- res INVULNERABLE, [hl]
-PlayerCanExecuteMove:
- call PrintMonName1Text
- ld hl, DecrementPP
- ld de, wPlayerSelectedMove ; pointer to the move just used
- ld b, BANK(DecrementPP)
- call Bankswitch
- ld a, [wPlayerMoveEffect] ; effect of the move just used
- ld hl, ResidualEffects1
- ld de, 1
- call IsInArray
- jp c, JumpMoveEffect ; ResidualEffects1 moves skip damage calculation and accuracy tests
- ; unless executed as part of their exclusive effect functions
- ld a, [wPlayerMoveEffect]
- ld hl, SpecialEffectsCont
- ld de, 1
- call IsInArray
- call c, JumpMoveEffect ; execute the effects of SpecialEffectsCont moves (e.g. Wrap, Thrash) but don't skip anything
-PlayerCalcMoveDamage:
- ld a, [wPlayerMoveEffect]
- ld hl, SetDamageEffects
- ld de, 1
- call IsInArray
- jp c, .moveHitTest ; SetDamageEffects moves (e.g. Seismic Toss and Super Fang) skip damage calculation
- call CriticalHitTest
- call HandleCounterMove
- jr z, handleIfPlayerMoveMissed
- call GetDamageVarsForPlayerAttack
- call CalculateDamage
- jp z, playerCheckIfFlyOrChargeEffect ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest
- ; for these moves, accuracy tests will only occur if they are called as part of the effect itself
- call AdjustDamageForMoveType
- call RandomizeDamage
-.moveHitTest
- call MoveHitTest
-handleIfPlayerMoveMissed:
- ld a, [wMoveMissed]
- and a
- jr z, getPlayerAnimationType
- ld a, [wPlayerMoveEffect]
- sub EXPLODE_EFFECT
- jr z, playPlayerMoveAnimation ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
- jr playerCheckIfFlyOrChargeEffect
-getPlayerAnimationType:
- ld a, [wPlayerMoveEffect]
- and a
- ld a, 4 ; move has no effect other than dealing damage
- jr z, playPlayerMoveAnimation
- ld a, 5 ; move has effect
-playPlayerMoveAnimation:
- push af
- ld a, [wPlayerBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a
- ld hl, HideSubstituteShowMonAnim
- ld b, BANK(HideSubstituteShowMonAnim)
- call nz, Bankswitch
- pop af
- ld [wAnimationType], a
- ld a, [wPlayerMoveNum]
- call PlayMoveAnimation
- call HandleExplodingAnimation
- call DrawPlayerHUDAndHPBar
- ld a, [wPlayerBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a
- ld hl, ReshowSubstituteAnim
- ld b, BANK(ReshowSubstituteAnim)
- call nz, Bankswitch
- jr MirrorMoveCheck
-playerCheckIfFlyOrChargeEffect:
- ld c, 30
- call DelayFrames
- ld a, [wPlayerMoveEffect]
- cp FLY_EFFECT
- jr z, .playAnim
- cp CHARGE_EFFECT
- jr z, .playAnim
- jr MirrorMoveCheck
-.playAnim
- xor a
- ld [wAnimationType], a
- ld a, STATUS_AFFECTED_ANIM
- call PlayMoveAnimation
-MirrorMoveCheck:
- ld a, [wPlayerMoveEffect]
- cp MIRROR_MOVE_EFFECT
- jr nz, .metronomeCheck
- call MirrorMoveCopyMove
- jp z, ExecutePlayerMoveDone
- xor a
- ld [wMonIsDisobedient], a
- jp CheckIfPlayerNeedsToChargeUp ; if Mirror Move was successful go back to damage calculation for copied move
-.metronomeCheck
- cp METRONOME_EFFECT
- jr nz, .next
- call MetronomePickMove
- jp CheckIfPlayerNeedsToChargeUp ; Go back to damage calculation for the move picked by Metronome
-.next
- ld a, [wPlayerMoveEffect]
- ld hl, ResidualEffects2
- ld de, 1
- call IsInArray
- jp c, JumpMoveEffect ; done here after executing effects of ResidualEffects2
- ld a, [wMoveMissed]
- and a
- jr z, .moveDidNotMiss
- call PrintMoveFailureText
- ld a, [wPlayerMoveEffect]
- cp EXPLODE_EFFECT ; even if Explosion or Selfdestruct missed, its effect still needs to be activated
- jr z, .notDone
- jp ExecutePlayerMoveDone ; otherwise, we're done if the move missed
-.moveDidNotMiss
- call ApplyAttackToEnemyPokemon
- call PrintCriticalOHKOText
- callab DisplayEffectiveness
- ld a, 1
- ld [wMoveDidntMiss], a
-.notDone
- ld a, [wPlayerMoveEffect]
- ld hl, AlwaysHappenSideEffects
- ld de, 1
- call IsInArray
- call c, JumpMoveEffect ; not done after executing effects of AlwaysHappenSideEffects
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld b, [hl]
- or b
- ret z ; don't do anything else if the enemy fainted
- call HandleBuildingRage
-
- ld hl, wPlayerBattleStatus1
- bit ATTACKING_MULTIPLE_TIMES, [hl]
- jr z, .executeOtherEffects
- ld a, [wPlayerNumAttacksLeft]
- dec a
- ld [wPlayerNumAttacksLeft], a
- jp nz, getPlayerAnimationType ; for multi-hit moves, apply attack until PlayerNumAttacksLeft hits 0 or the enemy faints.
- ; damage calculation and accuracy tests only happen for the first hit
- res ATTACKING_MULTIPLE_TIMES, [hl] ; clear attacking multiple times status when all attacks are over
- ld hl, MultiHitText
- call PrintText
- xor a
- ld [wPlayerNumHits], a
-.executeOtherEffects
- ld a, [wPlayerMoveEffect]
- and a
- jp z, ExecutePlayerMoveDone
- ld hl, SpecialEffects
- ld de, 1
- call IsInArray
- call nc, JumpMoveEffect ; move effects not included in SpecialEffects or in either of the ResidualEffect arrays,
- ; which are the effects not covered yet. Rage effect will be executed for a second time (though it's irrelevant).
- ; Includes side effects that only need to be called if the target didn't faint.
- ; Responsible for executing Twineedle's second side effect (poison).
- jp ExecutePlayerMoveDone
-
-MultiHitText:
- TX_FAR _MultiHitText
- db "@"
-
-ExecutePlayerMoveDone:
- xor a
- ld [wActionResultOrTookBattleTurn], a
- ld b, 1
- ret
-
-PrintGhostText:
-; print the ghost battle messages
- call IsGhostBattle
- ret nz
- ld a, [H_WHOSETURN]
- and a
- jr nz, .Ghost
- ld a, [wBattleMonStatus] ; player’s turn
- and SLP | (1 << FRZ)
- ret nz
- ld hl, ScaredText
- call PrintText
- xor a
- ret
-.Ghost ; ghost’s turn
- ld hl, GetOutText
- call PrintText
- xor a
- ret
-
-ScaredText:
- TX_FAR _ScaredText
- db "@"
-
-GetOutText:
- TX_FAR _GetOutText
- db "@"
-
-IsGhostBattle:
- ld a, [wIsInBattle]
- dec a
- ret nz
- ld a, [wCurMap]
- cp POKEMONTOWER_1
- jr c, .next
- cp LAVENDER_HOUSE_1
- jr nc, .next
- ld b, SILPH_SCOPE
- call IsItemInBag
- ret z
-.next
- ld a, 1
- and a
- ret
-
-; checks for various status conditions affecting the player mon
-; stores whether the mon cannot use a move this turn in Z flag
-CheckPlayerStatusConditions:
- ld hl, wBattleMonStatus
- ld a, [hl]
- and SLP ; sleep mask
- jr z, .FrozenCheck
-; sleeping
- dec a
- ld [wBattleMonStatus], a ; decrement number of turns left
- and a
- jr z, .WakeUp ; if the number of turns hit 0, wake up
-; fast asleep
- xor a
- ld [wAnimationType], a
- ld a, SLP_ANIM - 1
- call PlayMoveAnimation
- ld hl, FastAsleepText
- call PrintText
- jr .sleepDone
-.WakeUp
- ld hl, WokeUpText
- call PrintText
-.sleepDone
- xor a
- ld [wPlayerUsedMove], a
- ld hl, ExecutePlayerMoveDone ; player can't move this turn
- jp .returnToHL
-
-.FrozenCheck
- bit FRZ, [hl] ; frozen?
- jr z, .HeldInPlaceCheck
- ld hl, IsFrozenText
- call PrintText
- xor a
- ld [wPlayerUsedMove], a
- ld hl, ExecutePlayerMoveDone ; player can't move this turn
- jp .returnToHL
-
-.HeldInPlaceCheck
- ld a, [wEnemyBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; is enemy using a mult-turn move like wrap?
- jp z, .FlinchedCheck
- ld hl, CantMoveText
- call PrintText
- ld hl, ExecutePlayerMoveDone ; player can't move this turn
- jp .returnToHL
-
-.FlinchedCheck
- ld hl, wPlayerBattleStatus1
- bit FLINCHED, [hl]
- jp z, .HyperBeamCheck
- res FLINCHED, [hl] ; reset player's flinch status
- ld hl, FlinchedText
- call PrintText
- ld hl, ExecutePlayerMoveDone ; player can't move this turn
- jp .returnToHL
-
-.HyperBeamCheck
- ld hl, wPlayerBattleStatus2
- bit NEEDS_TO_RECHARGE, [hl]
- jr z, .AnyMoveDisabledCheck
- res NEEDS_TO_RECHARGE, [hl] ; reset player's recharge status
- ld hl, MustRechargeText
- call PrintText
- ld hl, ExecutePlayerMoveDone ; player can't move this turn
- jp .returnToHL
-
-.AnyMoveDisabledCheck
- ld hl, wPlayerDisabledMove
- ld a, [hl]
- and a
- jr z, .ConfusedCheck
- dec a
- ld [hl], a
- and $f ; did Disable counter hit 0?
- jr nz, .ConfusedCheck
- ld [hl], a
- ld [wPlayerDisabledMoveNumber], a
- ld hl, DisabledNoMoreText
- call PrintText
-
-.ConfusedCheck
- ld a, [wPlayerBattleStatus1]
- add a ; is player confused?
- jr nc, .TriedToUseDisabledMoveCheck
- ld hl, wPlayerConfusedCounter
- dec [hl]
- jr nz, .IsConfused
- ld hl, wPlayerBattleStatus1
- res CONFUSED, [hl] ; if confused counter hit 0, reset confusion status
- ld hl, ConfusedNoMoreText
- call PrintText
- jr .TriedToUseDisabledMoveCheck
-.IsConfused
- ld hl, IsConfusedText
- call PrintText
- xor a
- ld [wAnimationType], a
- ld a, CONF_ANIM - 1
- call PlayMoveAnimation
- call BattleRandom
- cp $80 ; 50% chance to hurt itself
- jr c, .TriedToUseDisabledMoveCheck
- ld hl, wPlayerBattleStatus1
- ld a, [hl]
- and 1 << CONFUSED ; if mon hurts itself, clear every other status from wPlayerBattleStatus1
- ld [hl], a
- call HandleSelfConfusionDamage
- jr .MonHurtItselfOrFullyParalysed
-
-.TriedToUseDisabledMoveCheck
-; prevents a disabled move that was selected before being disabled from being used
- ld a, [wPlayerDisabledMoveNumber]
- and a
- jr z, .ParalysisCheck
- ld hl, wPlayerSelectedMove
- cp [hl]
- jr nz, .ParalysisCheck
- call PrintMoveIsDisabledText
- ld hl, ExecutePlayerMoveDone ; if a disabled move was somehow selected, player can't move this turn
- jp .returnToHL
-
-.ParalysisCheck
- ld hl, wBattleMonStatus
- bit PAR, [hl]
- jr z, .BideCheck
- call BattleRandom
- cp $3F ; 25% to be fully paralyzed
- jr nc, .BideCheck
- ld hl, FullyParalyzedText
- call PrintText
-
-.MonHurtItselfOrFullyParalysed
- ld hl, wPlayerBattleStatus1
- ld a, [hl]
- ; clear bide, thrashing, charging up, and trapping moves such as warp (already cleared for confusion damage)
- and $ff ^ ((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE))
- ld [hl], a
- ld a, [wPlayerMoveEffect]
- cp FLY_EFFECT
- jr z, .FlyOrChargeEffect
- cp CHARGE_EFFECT
- jr z, .FlyOrChargeEffect
- jr .NotFlyOrChargeEffect
-
-.FlyOrChargeEffect
- xor a
- ld [wAnimationType], a
- ld a, STATUS_AFFECTED_ANIM
- call PlayMoveAnimation
-.NotFlyOrChargeEffect
- ld hl, ExecutePlayerMoveDone
- jp .returnToHL ; if using a two-turn move, we need to recharge the first turn
-
-.BideCheck
- ld hl, wPlayerBattleStatus1
- bit STORING_ENERGY, [hl] ; is mon using bide?
- jr z, .ThrashingAboutCheck
- xor a
- ld [wPlayerMoveNum], a
- ld hl, wDamage
- ld a, [hli]
- ld b, a
- ld c, [hl]
- ld hl, wPlayerBideAccumulatedDamage + 1
- ld a, [hl]
- add c ; accumulate damage taken
- ld [hld], a
- ld a, [hl]
- adc b
- ld [hl], a
- ld hl, wPlayerNumAttacksLeft
- dec [hl] ; did Bide counter hit 0?
- jr z, .UnleashEnergy
- ld hl, ExecutePlayerMoveDone
- jp .returnToHL ; unless mon unleashes energy, can't move this turn
-.UnleashEnergy
- ld hl, wPlayerBattleStatus1
- res STORING_ENERGY, [hl] ; not using bide any more
- ld hl, UnleashedEnergyText
- call PrintText
- ld a, 1
- ld [wPlayerMovePower], a
- ld hl, wPlayerBideAccumulatedDamage + 1
- ld a, [hld]
- add a
- ld b, a
- ld [wDamage + 1], a
- ld a, [hl]
- rl a ; double the damage
- ld [wDamage], a
- or b
- jr nz, .next
- ld a, 1
- ld [wMoveMissed], a
-.next
- xor a
- ld [hli], a
- ld [hl], a
- ld a, BIDE
- ld [wPlayerMoveNum], a
- ld hl, handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
- jp .returnToHL
-
-.ThrashingAboutCheck
- bit THRASHING_ABOUT, [hl] ; is mon using thrash or petal dance?
- jr z, .MultiturnMoveCheck
- ld a, THRASH
- ld [wPlayerMoveNum], a
- ld hl, ThrashingAboutText
- call PrintText
- ld hl, wPlayerNumAttacksLeft
- dec [hl] ; did Thrashing About counter hit 0?
- ld hl, PlayerCalcMoveDamage ; skip DecrementPP
- jp nz, .returnToHL
- push hl
- ld hl, wPlayerBattleStatus1
- res THRASHING_ABOUT, [hl] ; no longer thrashing about
- set CONFUSED, [hl] ; confused
- call BattleRandom
- and 3
- inc a
- inc a ; confused for 2-5 turns
- ld [wPlayerConfusedCounter], a
- pop hl ; skip DecrementPP
- jp .returnToHL
-
-.MultiturnMoveCheck
- bit USING_TRAPPING_MOVE, [hl] ; is mon using multi-turn move?
- jp z, .RageCheck
- ld hl, AttackContinuesText
- call PrintText
- ld a, [wPlayerNumAttacksLeft]
- dec a ; did multi-turn move end?
- ld [wPlayerNumAttacksLeft], a
- ld hl, getPlayerAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit),
- ; DecrementPP and MoveHitTest
- jp nz, .returnToHL
- jp .returnToHL
-
-.RageCheck
- ld a, [wPlayerBattleStatus2]
- bit USING_RAGE, a ; is mon using rage?
- jp z, .checkPlayerStatusConditionsDone ; if we made it this far, mon can move normally this turn
- ld a, RAGE
- ld [wd11e], a
- call GetMoveName
- call CopyStringToCF4B
- xor a
- ld [wPlayerMoveEffect], a
- ld hl, PlayerCanExecuteMove
- jp .returnToHL
-
-.returnToHL
- xor a
- ret
-
-.checkPlayerStatusConditionsDone
- ld a, $1
- and a
- ret
-
-FastAsleepText:
- TX_FAR _FastAsleepText
- db "@"
-
-WokeUpText:
- TX_FAR _WokeUpText
- db "@"
-
-IsFrozenText:
- TX_FAR _IsFrozenText
- db "@"
-
-FullyParalyzedText:
- TX_FAR _FullyParalyzedText
- db "@"
-
-FlinchedText:
- TX_FAR _FlinchedText
- db "@"
-
-MustRechargeText:
- TX_FAR _MustRechargeText
- db "@"
-
-DisabledNoMoreText:
- TX_FAR _DisabledNoMoreText
- db "@"
-
-IsConfusedText:
- TX_FAR _IsConfusedText
- db "@"
-
-HurtItselfText:
- TX_FAR _HurtItselfText
- db "@"
-
-ConfusedNoMoreText:
- TX_FAR _ConfusedNoMoreText
- db "@"
-
-SavingEnergyText:
- TX_FAR _SavingEnergyText
- db "@"
-
-UnleashedEnergyText:
- TX_FAR _UnleashedEnergyText
- db "@"
-
-ThrashingAboutText:
- TX_FAR _ThrashingAboutText
- db "@"
-
-AttackContinuesText:
- TX_FAR _AttackContinuesText
- db "@"
-
-CantMoveText:
- TX_FAR _CantMoveText
- db "@"
-
-PrintMoveIsDisabledText:
- ld hl, wPlayerSelectedMove
- ld de, wPlayerBattleStatus1
- ld a, [H_WHOSETURN]
- and a
- jr z, .removeChargingUp
- inc hl
- ld de, wEnemyBattleStatus1
-.removeChargingUp
- ld a, [de]
- res CHARGING_UP, a ; end the pokemon's
- ld [de], a
- ld a, [hl]
- ld [wd11e], a
- call GetMoveName
- ld hl, MoveIsDisabledText
- jp PrintText
-
-MoveIsDisabledText:
- TX_FAR _MoveIsDisabledText
- db "@"
-
-HandleSelfConfusionDamage:
- ld hl, HurtItselfText
- call PrintText
- ld hl, wEnemyMonDefense
- ld a, [hli]
- push af
- ld a, [hld]
- push af
- ld a, [wBattleMonDefense]
- ld [hli], a
- ld a, [wBattleMonDefense + 1]
- ld [hl], a
- ld hl, wPlayerMoveEffect
- push hl
- ld a, [hl]
- push af
- xor a
- ld [hli], a
- ld [wCriticalHitOrOHKO], a ; self-inflicted confusion damage can't be a Critical Hit
- ld a, 40 ; 40 base power
- ld [hli], a
- xor a
- ld [hl], a
- call GetDamageVarsForPlayerAttack
- call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage,
- ; and MoveHitTest (always hits)
- pop af
- pop hl
- ld [hl], a
- ld hl, wEnemyMonDefense + 1
- pop af
- ld [hld], a
- pop af
- ld [hl], a
- xor a
- ld [wAnimationType], a
- inc a
- ld [H_WHOSETURN], a
- call PlayMoveAnimation
- call DrawPlayerHUDAndHPBar
- xor a
- ld [H_WHOSETURN], a
- jp ApplyDamageToPlayerPokemon
-
-PrintMonName1Text:
- ld hl, MonName1Text
- jp PrintText
-
-; this function wastes time calling DetermineExclamationPointTextNum
-; and choosing between Used1Text and Used2Text, even though
-; those text strings are identical and both continue at PrintInsteadText
-; this likely had to do with Japanese grammar that got translated,
-; but the functionality didn't get removed
-MonName1Text:
- TX_FAR _MonName1Text
- TX_ASM
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveNum]
- ld hl, wPlayerUsedMove
- jr z, .playerTurn
- ld a, [wEnemyMoveNum]
- ld hl, wEnemyUsedMove
-.playerTurn
- ld [hl], a
- ld [wd11e], a
- call DetermineExclamationPointTextNum
- ld a, [wMonIsDisobedient]
- and a
- ld hl, Used2Text
- ret nz
- ld a, [wd11e]
- cp 3
- ld hl, Used2Text
- ret c
- ld hl, Used1Text
- ret
-
-Used1Text:
- TX_FAR _Used1Text
- TX_ASM
- jr PrintInsteadText
-
-Used2Text:
- TX_FAR _Used2Text
- TX_ASM
- ; fall through
-
-PrintInsteadText:
- ld a, [wMonIsDisobedient]
- and a
- jr z, PrintMoveName
- ld hl, InsteadText
- ret
-
-InsteadText:
- TX_FAR _InsteadText
- TX_ASM
- ; fall through
-
-PrintMoveName:
- ld hl, _PrintMoveName
- ret
-
-_PrintMoveName:
- TX_FAR _CF4BText
- TX_ASM
- ld hl, ExclamationPointPointerTable
- ld a, [wd11e] ; exclamation point num
- add a
- push bc
- ld b, $0
- ld c, a
- add hl, bc
- pop bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ret
-
-ExclamationPointPointerTable:
- dw ExclamationPoint1Text
- dw ExclamationPoint2Text
- dw ExclamationPoint3Text
- dw ExclamationPoint4Text
- dw ExclamationPoint5Text
-
-ExclamationPoint1Text:
- TX_FAR _ExclamationPoint1Text
- db "@"
-
-ExclamationPoint2Text:
- TX_FAR _ExclamationPoint2Text
- db "@"
-
-ExclamationPoint3Text:
- TX_FAR _ExclamationPoint3Text
- db "@"
-
-ExclamationPoint4Text:
- TX_FAR _ExclamationPoint4Text
- db "@"
-
-ExclamationPoint5Text:
- TX_FAR _ExclamationPoint5Text
- db "@"
-
-; this function does nothing useful
-; if the move being used is in set [1-4] from ExclamationPointMoveSets,
-; use ExclamationPoint[1-4]Text
-; otherwise, use ExclamationPoint5Text
-; but all five text strings are identical
-; this likely had to do with Japanese grammar that got translated,
-; but the functionality didn't get removed
-DetermineExclamationPointTextNum:
- push bc
- ld a, [wd11e] ; move ID
- ld c, a
- ld b, $0
- ld hl, ExclamationPointMoveSets
-.loop
- ld a, [hli]
- cp $ff
- jr z, .done
- cp c
- jr z, .done
- and a
- jr nz, .loop
- inc b
- jr .loop
-.done
- ld a, b
- ld [wd11e], a ; exclamation point num
- pop bc
- ret
-
-ExclamationPointMoveSets:
- db SWORDS_DANCE, GROWTH
- db $00
- db RECOVER, BIDE, SELFDESTRUCT, AMNESIA
- db $00
- db MEDITATE, AGILITY, TELEPORT, MIMIC, DOUBLE_TEAM, BARRAGE
- db $00
- db POUND, SCRATCH, VICEGRIP, WING_ATTACK, FLY, BIND, SLAM, HORN_ATTACK, BODY_SLAM
- db WRAP, THRASH, TAIL_WHIP, LEER, BITE, GROWL, ROAR, SING, PECK, COUNTER
- db STRENGTH, ABSORB, STRING_SHOT, EARTHQUAKE, FISSURE, DIG, TOXIC, SCREECH, HARDEN
- db MINIMIZE, WITHDRAW, DEFENSE_CURL, METRONOME, LICK, CLAMP, CONSTRICT, POISON_GAS
- db LEECH_LIFE, BUBBLE, FLASH, SPLASH, ACID_ARMOR, FURY_SWIPES, REST, SHARPEN, SLASH, SUBSTITUTE
- db $00
- db $FF ; terminator
-
-PrintMoveFailureText:
- ld de, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- jr z, .playersTurn
- ld de, wEnemyMoveEffect
-.playersTurn
- ld hl, DoesntAffectMonText
- ld a, [wDamageMultipliers]
- and $7f
- jr z, .gotTextToPrint
- ld hl, AttackMissedText
- ld a, [wCriticalHitOrOHKO]
- cp $ff
- jr nz, .gotTextToPrint
- ld hl, UnaffectedText
-.gotTextToPrint
- push de
- call PrintText
- xor a
- ld [wCriticalHitOrOHKO], a
- pop de
- ld a, [de]
- cp JUMP_KICK_EFFECT
- ret nz
-
- ; if you get here, the mon used jump kick or hi jump kick and missed
- ld hl, wDamage ; since the move missed, wDamage will always contain 0 at this point.
- ; Thus, recoil damage will always be equal to 1
- ; even if it was intended to be potential damage/8.
- ld a, [hli]
- ld b, [hl]
- srl a
- rr b
- srl a
- rr b
- srl a
- rr b
- ld [hl], b
- dec hl
- ld [hli], a
- or b
- jr nz, .applyRecoil
- inc a
- ld [hl], a
-.applyRecoil
- ld hl, KeptGoingAndCrashedText
- call PrintText
- ld b, $4
- predef PredefShakeScreenHorizontally
- ld a, [H_WHOSETURN]
- and a
- jr nz, .enemyTurn
- jp ApplyDamageToPlayerPokemon
-.enemyTurn
- jp ApplyDamageToEnemyPokemon
-
-AttackMissedText:
- TX_FAR _AttackMissedText
- db "@"
-
-KeptGoingAndCrashedText:
- TX_FAR _KeptGoingAndCrashedText
- db "@"
-
-UnaffectedText:
- TX_FAR _UnaffectedText
- db "@"
-
-PrintDoesntAffectText:
- ld hl, DoesntAffectMonText
- jp PrintText
-
-DoesntAffectMonText:
- TX_FAR _DoesntAffectMonText
- db "@"
-
-; if there was a critical hit or an OHKO was successful, print the corresponding text
-PrintCriticalOHKOText:
- ld a, [wCriticalHitOrOHKO]
- and a
- jr z, .done ; do nothing if there was no critical hit or successful OHKO
- dec a
- add a
- ld hl, CriticalOHKOTextPointers
- ld b, $0
- ld c, a
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- call PrintText
- xor a
- ld [wCriticalHitOrOHKO], a
-.done
- ld c, 20
- jp DelayFrames
-
-CriticalOHKOTextPointers:
- dw CriticalHitText
- dw OHKOText
-
-CriticalHitText:
- TX_FAR _CriticalHitText
- db "@"
-
-OHKOText:
- TX_FAR _OHKOText
- db "@"
-
-; checks if a traded mon will disobey due to lack of badges
-; stores whether the mon will use a move in Z flag
-CheckForDisobedience:
- xor a
- ld [wMonIsDisobedient], a
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .checkIfMonIsTraded
- ld a, $1
- and a
- ret
-; compare the mon's original trainer ID with the player's ID to see if it was traded
-.checkIfMonIsTraded
- ld hl, wPartyMon1OTID
- ld bc, wPartyMon2 - wPartyMon1
- ld a, [wPlayerMonNumber]
- call AddNTimes
- ld a, [wPlayerID]
- cp [hl]
- jr nz, .monIsTraded
- inc hl
- ld a, [wPlayerID + 1]
- cp [hl]
- jp z, .canUseMove
-; it was traded
-.monIsTraded
-; what level might disobey?
- ld hl, wObtainedBadges
- bit 7, [hl]
- ld a, 101
- jr nz, .next
- bit 5, [hl]
- ld a, 70
- jr nz, .next
- bit 3, [hl]
- ld a, 50
- jr nz, .next
- bit 1, [hl]
- ld a, 30
- jr nz, .next
- ld a, 10
-.next
- ld b, a
- ld c, a
- ld a, [wBattleMonLevel]
- ld d, a
- add b
- ld b, a
- jr nc, .noCarry
- ld b, $ff ; cap b at $ff
-.noCarry
- ld a, c
- cp d
- jp nc, .canUseMove
-.loop1
- call BattleRandom
- swap a
- cp b
- jr nc, .loop1
- cp c
- jp c, .canUseMove
-.loop2
- call BattleRandom
- cp b
- jr nc, .loop2
- cp c
- jr c, .useRandomMove
- ld a, d
- sub c
- ld b, a
- call BattleRandom
- swap a
- sub b
- jr c, .monNaps
- cp b
- jr nc, .monDoesNothing
- ld hl, WontObeyText
- call PrintText
- call HandleSelfConfusionDamage
- jp .cannotUseMove
-.monNaps
- call BattleRandom
- add a
- swap a
- and SLP ; sleep mask
- jr z, .monNaps ; keep trying until we get at least 1 turn of sleep
- ld [wBattleMonStatus], a
- ld hl, BeganToNapText
- jr .printText
-.monDoesNothing
- call BattleRandom
- and $3
- ld hl, LoafingAroundText
- and a
- jr z, .printText
- ld hl, WontObeyText
- dec a
- jr z, .printText
- ld hl, TurnedAwayText
- dec a
- jr z, .printText
- ld hl, IgnoredOrdersText
-.printText
- call PrintText
- jr .cannotUseMove
-.useRandomMove
- ld a, [wBattleMonMoves + 1]
- and a ; is the second move slot empty?
- jr z, .monDoesNothing ; mon will not use move if it only knows one move
- ld a, [wPlayerDisabledMoveNumber]
- and a
- jr nz, .monDoesNothing
- ld a, [wPlayerSelectedMove]
- cp STRUGGLE
- jr z, .monDoesNothing ; mon will not use move if struggling
-; check if only one move has remaining PP
- ld hl, wBattleMonPP
- push hl
- ld a, [hli]
- and $3f
- ld b, a
- ld a, [hli]
- and $3f
- add b
- ld b, a
- ld a, [hli]
- and $3f
- add b
- ld b, a
- ld a, [hl]
- and $3f
- add b
- pop hl
- push af
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hl]
- and $3f
- ld b, a
- pop af
- cp b
- jr z, .monDoesNothing ; mon will not use move if only one move has remaining PP
- ld a, $1
- ld [wMonIsDisobedient], a
- ld a, [wMaxMenuItem]
- ld b, a
- ld a, [wCurrentMenuItem]
- ld c, a
-.chooseMove
- call BattleRandom
- and $3
- cp b
- jr nc, .chooseMove ; if the random number is greater than the move count, choose another
- cp c
- jr z, .chooseMove ; if the random number matches the move the player selected, choose another
- ld [wCurrentMenuItem], a
- ld hl, wBattleMonPP
- ld e, a
- ld d, $0
- add hl, de
- ld a, [hl]
- and a ; does the move have any PP left?
- jr z, .chooseMove ; if the move has no PP left, choose another
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, $0
- ld hl, wBattleMonMoves
- add hl, bc
- ld a, [hl]
- ld [wPlayerSelectedMove], a
- call GetCurrentMove
-.canUseMove
- ld a, $1
- and a; clear Z flag
- ret
-.cannotUseMove
- xor a ; set Z flag
- ret
-
-LoafingAroundText:
- TX_FAR _LoafingAroundText
- db "@"
-
-BeganToNapText:
- TX_FAR _BeganToNapText
- db "@"
-
-WontObeyText:
- TX_FAR _WontObeyText
- db "@"
-
-TurnedAwayText:
- TX_FAR _TurnedAwayText
- db "@"
-
-IgnoredOrdersText:
- TX_FAR _IgnoredOrdersText
- db "@"
-
-; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the player mon
-GetDamageVarsForPlayerAttack:
- xor a
- ld hl, wDamage ; damage to eventually inflict, initialise to zero
- ldi [hl], a
- ld [hl], a
- ld hl, wPlayerMovePower
- ld a, [hli]
- and a
- ld d, a ; d = move power
- ret z ; return if move power is zero
- ld a, [hl] ; a = [wPlayerMoveType]
- cp FIRE ; types >= FIRE are all special
- jr nc, .specialAttack
-.physicalAttack
- ld hl, wEnemyMonDefense
- ld a, [hli]
- ld b, a
- ld c, [hl] ; bc = enemy defense
- ld a, [wEnemyBattleStatus3]
- bit HAS_REFLECT_UP, a ; check for Reflect
- jr z, .physicalAttackCritCheck
-; if the enemy has used Reflect, double the enemy's defense
- sla c
- rl b
-.physicalAttackCritCheck
- ld hl, wBattleMonAttack
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .scaleStats
-; in the case of a critical hit, reset the player's attack and the enemy's defense to their base values
- ld c, 3 ; defense stat
- call GetEnemyMonStat
- ld a, [H_PRODUCT + 2]
- ld b, a
- ld a, [H_PRODUCT + 3]
- ld c, a
- push bc
- ld hl, wPartyMon1Attack
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- pop bc
- jr .scaleStats
-.specialAttack
- ld hl, wEnemyMonSpecial
- ld a, [hli]
- ld b, a
- ld c, [hl] ; bc = enemy special
- ld a, [wEnemyBattleStatus3]
- bit HAS_LIGHT_SCREEN_UP, a ; check for Light Screen
- jr z, .specialAttackCritCheck
-; if the enemy has used Light Screen, double the enemy's special
- sla c
- rl b
-; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if
-; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen
-.specialAttackCritCheck
- ld hl, wBattleMonSpecial
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .scaleStats
-; in the case of a critical hit, reset the player's and enemy's specials to their base values
- ld c, 5 ; special stat
- call GetEnemyMonStat
- ld a, [H_PRODUCT + 2]
- ld b, a
- ld a, [H_PRODUCT + 3]
- ld c, a
- push bc
- ld hl, wPartyMon1Special
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- pop bc
-; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4
-; this allows values with up to 10 bits (values up to 1023) to be handled
-; anything larger will wrap around
-.scaleStats
- ld a, [hli]
- ld l, [hl]
- ld h, a ; hl = player's offensive stat
- or b ; is either high byte nonzero?
- jr z, .next ; if not, we don't need to scale
-; bc /= 4 (scale enemy's defensive stat)
- srl b
- rr c
- srl b
- rr c
-; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation
-; hl /= 4 (scale player's offensive stat)
- srl h
- rr l
- srl h
- rr l
- ld a, l
- or h ; is the player's offensive stat 0?
- jr nz, .next
- inc l ; if the player's offensive stat is 0, bump it up to 1
-.next
- ld b, l ; b = player's offensive stat (possibly scaled)
- ; (c already contains enemy's defensive stat (possibly scaled))
- ld a, [wBattleMonLevel]
- ld e, a ; e = level
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .done
- sla e ; double level if it was a critical hit
-.done
- ld a, 1
- and a
- ret
-
-; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the enemy mon
-GetDamageVarsForEnemyAttack:
- ld hl, wDamage ; damage to eventually inflict, initialise to zero
- xor a
- ld [hli], a
- ld [hl], a
- ld hl, wEnemyMovePower
- ld a, [hli]
- ld d, a ; d = move power
- and a
- ret z ; return if move power is zero
- ld a, [hl] ; a = [wEnemyMoveType]
- cp FIRE ; types >= FIRE are all special
- jr nc, .specialAttack
-.physicalAttack
- ld hl, wBattleMonDefense
- ld a, [hli]
- ld b, a
- ld c, [hl] ; bc = player defense
- ld a, [wPlayerBattleStatus3]
- bit HAS_REFLECT_UP, a ; check for Reflect
- jr z, .physicalAttackCritCheck
-; if the player has used Reflect, double the player's defense
- sla c
- rl b
-.physicalAttackCritCheck
- ld hl, wEnemyMonAttack
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .scaleStats
-; in the case of a critical hit, reset the player's defense and the enemy's attack to their base values
- ld hl, wPartyMon1Defense
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hli]
- ld b, a
- ld c, [hl]
- push bc
- ld c, 2 ; attack stat
- call GetEnemyMonStat
- ld hl, H_PRODUCT + 2
- pop bc
- jr .scaleStats
-.specialAttack
- ld hl, wBattleMonSpecial
- ld a, [hli]
- ld b, a
- ld c, [hl]
- ld a, [wPlayerBattleStatus3]
- bit HAS_LIGHT_SCREEN_UP, a ; check for Light Screen
- jr z, .specialAttackCritCheck
-; if the player has used Light Screen, double the player's special
- sla c
- rl b
-; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if
-; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen
-.specialAttackCritCheck
- ld hl, wEnemyMonSpecial
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .scaleStats
-; in the case of a critical hit, reset the player's and enemy's specials to their base values
- ld hl, wPartyMon1Special
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hli]
- ld b, a
- ld c, [hl]
- push bc
- ld c, 5 ; special stat
- call GetEnemyMonStat
- ld hl, H_PRODUCT + 2
- pop bc
-; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4
-; this allows values with up to 10 bits (values up to 1023) to be handled
-; anything larger will wrap around
-.scaleStats
- ld a, [hli]
- ld l, [hl]
- ld h, a ; hl = enemy's offensive stat
- or b ; is either high byte nonzero?
- jr z, .next ; if not, we don't need to scale
-; bc /= 4 (scale player's defensive stat)
- srl b
- rr c
- srl b
- rr c
-; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation
-; hl /= 4 (scale enemy's offensive stat)
- srl h
- rr l
- srl h
- rr l
- ld a, l
- or h ; is the enemy's offensive stat 0?
- jr nz, .next
- inc l ; if the enemy's offensive stat is 0, bump it up to 1
-.next
- ld b, l ; b = enemy's offensive stat (possibly scaled)
- ; (c already contains player's defensive stat (possibly scaled))
- ld a, [wEnemyMonLevel]
- ld e, a
- ld a, [wCriticalHitOrOHKO]
- and a ; check for critical hit
- jr z, .done
- sla e ; double level if it was a critical hit
-.done
- ld a, $1
- and a
- and a
- ret
-
-; get stat c of enemy mon
-; c: stat to get (HP=1,Attack=2,Defense=3,Speed=4,Special=5)
-GetEnemyMonStat:
- push de
- push bc
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
- ld hl, wEnemyMon1Stats
- dec c
- sla c
- ld b, $0
- add hl, bc
- ld a, [wEnemyMonPartyPos]
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [H_MULTIPLICAND + 2], a
- pop bc
- pop de
- ret
-.notLinkBattle
- ld a, [wEnemyMonLevel]
- ld [wCurEnemyLVL], a
- ld a, [wEnemyMonSpecies]
- ld [wd0b5], a
- call GetMonHeader
- ld hl, wEnemyMonDVs
- ld de, wLoadedMonSpeedExp
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- pop bc
- ld b, $0
- ld hl, wLoadedMonSpeedExp - $b ; this base address makes CalcStat look in [wLoadedMonSpeedExp] for DVs
- call CalcStat
- pop de
- ret
-
-CalculateDamage:
-; input:
-; b: attack
-; c: opponent defense
-; d: base power
-; e: level
-
- ld a, [H_WHOSETURN] ; whose turn?
- and a
- ld a, [wPlayerMoveEffect]
- jr z, .effect
- ld a, [wEnemyMoveEffect]
-.effect
-
-; EXPLODE_EFFECT halves defense.
- cp EXPLODE_EFFECT
- jr nz, .ok
- srl c
- jr nz, .ok
- inc c ; ...with a minimum value of 1 (used as a divisor later on)
-.ok
-
-; Multi-hit attacks may or may not have 0 bp.
- cp TWO_TO_FIVE_ATTACKS_EFFECT
- jr z, .skipbp
- cp $1e
- jr z, .skipbp
-
-; Calculate OHKO damage based on remaining HP.
- cp OHKO_EFFECT
- jp z, JumpToOHKOMoveEffect
-
-; Don't calculate damage for moves that don't do any.
- ld a, d ; base power
- and a
- ret z
-.skipbp
-
- xor a
- ld hl, H_DIVIDEND
- ldi [hl], a
- ldi [hl], a
- ld [hl], a
-
-; Multiply level by 2
- ld a, e ; level
- add a
- jr nc, .nc
- push af
- ld a, 1
- ld [hl], a
- pop af
-.nc
- inc hl
- ldi [hl], a
-
-; Divide by 5
- ld a, 5
- ldd [hl], a
- push bc
- ld b, 4
- call Divide
- pop bc
-
-; Add 2
- inc [hl]
- inc [hl]
-
- inc hl ; multiplier
-
-; Multiply by attack base power
- ld [hl], d
- call Multiply
-
-; Multiply by attack stat
- ld [hl], b
- call Multiply
-
-; Divide by defender's defense stat
- ld [hl], c
- ld b, 4
- call Divide
-
-; Divide by 50
- ld [hl], 50
- ld b, 4
- call Divide
-
- ld hl, wDamage
- ld b, [hl]
- ld a, [H_QUOTIENT + 3]
- add b
- ld [H_QUOTIENT + 3], a
- jr nc, .asm_3dfd0
-
- ld a, [H_QUOTIENT + 2]
- inc a
- ld [H_QUOTIENT + 2], a
- and a
- jr z, .asm_3e004
-
-.asm_3dfd0
- ld a, [H_QUOTIENT]
- ld b, a
- ld a, [H_QUOTIENT + 1]
- or a
- jr nz, .asm_3e004
-
- ld a, [H_QUOTIENT + 2]
- cp 998 / $100
- jr c, .asm_3dfe8
- cp 998 / $100 + 1
- jr nc, .asm_3e004
- ld a, [H_QUOTIENT + 3]
- cp 998 % $100
- jr nc, .asm_3e004
-
-.asm_3dfe8
- inc hl
- ld a, [H_QUOTIENT + 3]
- ld b, [hl]
- add b
- ld [hld], a
-
- ld a, [H_QUOTIENT + 2]
- ld b, [hl]
- adc b
- ld [hl], a
- jr c, .asm_3e004
-
- ld a, [hl]
- cp 998 / $100
- jr c, .asm_3e00a
- cp 998 / $100 + 1
- jr nc, .asm_3e004
- inc hl
- ld a, [hld]
- cp 998 % $100
- jr c, .asm_3e00a
-
-.asm_3e004
-; cap at 997
- ld a, 997 / $100
- ld [hli], a
- ld a, 997 % $100
- ld [hld], a
-
-.asm_3e00a
-; add 2
- inc hl
- ld a, [hl]
- add 2
- ld [hld], a
- jr nc, .done
- inc [hl]
-
-.done
-; minimum damage is 1
- ld a, 1
- and a
- ret
-
-JumpToOHKOMoveEffect:
- call JumpMoveEffect
- ld a, [wMoveMissed]
- dec a
- ret
-
-
-UnusedHighCriticalMoves:
- db KARATE_CHOP
- db RAZOR_LEAF
- db CRABHAMMER
- db SLASH
- db $FF
-
-; determines if attack is a critical hit
-; azure heights claims "the fastest pokémon (who are,not coincidentally,
-; among the most popular) tend to CH about 20 to 25% of the time."
-CriticalHitTest:
- xor a
- ld [wCriticalHitOrOHKO], a
- ld a, [H_WHOSETURN]
- and a
- ld a, [wEnemyMonSpecies]
- jr nz, .handleEnemy
- ld a, [wBattleMonSpecies]
-.handleEnemy
- ld [wd0b5], a
- call GetMonHeader
- ld a, [wMonHBaseSpeed]
- ld b, a
- srl b ; (effective (base speed/2))
- ld a, [H_WHOSETURN]
- and a
- ld hl, wPlayerMovePower
- ld de, wPlayerBattleStatus2
- jr z, .calcCriticalHitProbability
- ld hl, wEnemyMovePower
- ld de, wEnemyBattleStatus2
-.calcCriticalHitProbability
- ld a, [hld] ; read base power from RAM
- and a
- ret z ; do nothing if zero
- dec hl
- ld c, [hl] ; read move id
- ld a, [de]
- bit GETTING_PUMPED, a ; test for focus energy
- jr nz, .focusEnergyUsed ; bug: using focus energy causes a shift to the right instead of left,
- ; resulting in 1/4 the usual crit chance
- sla b ; (effective (base speed/2)*2)
- jr nc, .noFocusEnergyUsed
- ld b, $ff ; cap at 255/256
- jr .noFocusEnergyUsed
-.focusEnergyUsed
- srl b
-.noFocusEnergyUsed
- ld hl, HighCriticalMoves ; table of high critical hit moves
-.Loop
- ld a, [hli] ; read move from move table
- cp c ; does it match the move about to be used?
- jr z, .HighCritical ; if so, the move about to be used is a high critical hit ratio move
- inc a ; move on to the next move, FF terminates loop
- jr nz, .Loop ; check the next move in HighCriticalMoves
- srl b ; /2 for regular move (effective (base speed / 2))
- jr .SkipHighCritical ; continue as a normal move
-.HighCritical
- sla b ; *2 for high critical hit moves
- jr nc, .noCarry
- ld b, $ff ; cap at 255/256
-.noCarry
- sla b ; *4 for high critical move (effective (base speed/2)*8))
- jr nc, .SkipHighCritical
- ld b, $ff
-.SkipHighCritical
- call BattleRandom ; generates a random value, in "a"
- rlc a
- rlc a
- rlc a
- cp b ; check a against calculated crit rate
- ret nc ; no critical hit if no borrow
- ld a, $1
- ld [wCriticalHitOrOHKO], a ; set critical hit flag
- ret
-
-; high critical hit moves
-HighCriticalMoves:
- db KARATE_CHOP
- db RAZOR_LEAF
- db CRABHAMMER
- db SLASH
- db $FF
-
-
-; function to determine if Counter hits and if so, how much damage it does
-HandleCounterMove:
-; The variables checked by Counter are updated whenever the cursor points to a new move in the battle selection menu.
-; This is irrelevant for the opponent's side outside of link battles, since the move selection is controlled by the AI.
-; However, in the scenario where the player switches out and the opponent uses Counter,
-; the outcome may be affected by the player's actions in the move selection menu prior to switching the Pokemon.
-; This might also lead to desync glitches in link battles.
-
- ld a, [H_WHOSETURN] ; whose turn
- and a
-; player's turn
- ld hl, wEnemySelectedMove
- ld de, wEnemyMovePower
- ld a, [wPlayerSelectedMove]
- jr z, .next
-; enemy's turn
- ld hl, wPlayerSelectedMove
- ld de, wPlayerMovePower
- ld a, [wEnemySelectedMove]
-.next
- cp COUNTER
- ret nz ; return if not using Counter
- ld a, $01
- ld [wMoveMissed], a ; initialize the move missed variable to true (it is set to false below if the move hits)
- ld a, [hl]
- cp COUNTER
- ret z ; miss if the opponent's last selected move is Counter.
- ld a, [de]
- and a
- ret z ; miss if the opponent's last selected move's Base Power is 0.
-; check if the move the target last selected was Normal or Fighting type
- inc de
- ld a, [de]
- and a ; normal type
- jr z, .counterableType
- cp FIGHTING
- jr z, .counterableType
-; if the move wasn't Normal or Fighting type, miss
- xor a
- ret
-.counterableType
- ld hl, wDamage
- ld a, [hli]
- or [hl]
- ret z ; If we made it here, Counter still misses if the last move used in battle did no damage to its target.
- ; wDamage is shared by both players, so Counter may strike back damage dealt by the Counter user itself
- ; if the conditions meet, even though 99% of the times damage will come from the target.
-; if it did damage, double it
- ld a, [hl]
- add a
- ldd [hl], a
- ld a, [hl]
- adc a
- ld [hl], a
- jr nc, .noCarry
-; damage is capped at 0xFFFF
- ld a, $ff
- ld [hli], a
- ld [hl], a
-.noCarry
- xor a
- ld [wMoveMissed], a
- call MoveHitTest ; do the normal move hit test in addition to Counter's special rules
- xor a
- ret
-
-ApplyAttackToEnemyPokemon:
- ld a, [wPlayerMoveEffect]
- cp OHKO_EFFECT
- jr z, ApplyDamageToEnemyPokemon
- cp SUPER_FANG_EFFECT
- jr z, .superFangEffect
- cp SPECIAL_DAMAGE_EFFECT
- jr z, .specialDamage
- ld a, [wPlayerMovePower]
- and a
- jp z, ApplyAttackToEnemyPokemonDone ; no attack to apply if base power is 0
- jr ApplyDamageToEnemyPokemon
-.superFangEffect
-; set the damage to half the target's HP
- ld hl, wEnemyMonHP
- ld de, wDamage
- ld a, [hli]
- srl a
- ld [de], a
- inc de
- ld b, a
- ld a, [hl]
- rr a
- ld [de], a
- or b
- jr nz, ApplyDamageToEnemyPokemon
-; make sure Super Fang's damage is always at least 1
- ld a, $01
- ld [de], a
- jr ApplyDamageToEnemyPokemon
-.specialDamage
- ld hl, wBattleMonLevel
- ld a, [hl]
- ld b, a ; Seismic Toss deals damage equal to the user's level
- ld a, [wPlayerMoveNum]
- cp SEISMIC_TOSS
- jr z, .storeDamage
- cp NIGHT_SHADE
- jr z, .storeDamage
- ld b, SONICBOOM_DAMAGE ; 20
- cp SONICBOOM
- jr z, .storeDamage
- ld b, DRAGON_RAGE_DAMAGE ; 40
- cp DRAGON_RAGE
- jr z, .storeDamage
-; Psywave
- ld a, [hl]
- ld b, a
- srl a
- add b
- ld b, a ; b = level * 1.5
-; loop until a random number in the range [1, b) is found
-.loop
- call BattleRandom
- and a
- jr z, .loop
- cp b
- jr nc, .loop
- ld b, a
-.storeDamage ; store damage value at b
- ld hl, wDamage
- xor a
- ld [hli], a
- ld a, b
- ld [hl], a
-
-ApplyDamageToEnemyPokemon:
- ld hl, wDamage
- ld a, [hli]
- ld b, a
- ld a, [hl]
- or b
- jr z, ApplyAttackToEnemyPokemonDone ; we're done if damage is 0
- ld a, [wEnemyBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a ; does the enemy have a substitute?
- jp nz, AttackSubstitute
-; subtract the damage from the pokemon's current HP
-; also, save the current HP at wHPBarOldHP
- ld a, [hld]
- ld b, a
- ld a, [wEnemyMonHP + 1]
- ld [wHPBarOldHP], a
- sub b
- ld [wEnemyMonHP + 1], a
- ld a, [hl]
- ld b, a
- ld a, [wEnemyMonHP]
- ld [wHPBarOldHP+1], a
- sbc b
- ld [wEnemyMonHP], a
- jr nc, .animateHpBar
-; if more damage was done than the current HP, zero the HP and set the damage (wDamage)
-; equal to how much HP the pokemon had before the attack
- ld a, [wHPBarOldHP+1]
- ld [hli], a
- ld a, [wHPBarOldHP]
- ld [hl], a
- xor a
- ld hl, wEnemyMonHP
- ld [hli], a
- ld [hl], a
-.animateHpBar
- ld hl, wEnemyMonMaxHP
- ld a, [hli]
- ld [wHPBarMaxHP+1], a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld [wHPBarNewHP+1], a
- ld a, [hl]
- ld [wHPBarNewHP], a
- coord hl, 2, 2
- xor a
- ld [wHPBarType], a
- predef UpdateHPBar2 ; animate the HP bar shortening
-ApplyAttackToEnemyPokemonDone:
- jp DrawHUDsAndHPBars
-
-ApplyAttackToPlayerPokemon:
- ld a, [wEnemyMoveEffect]
- cp OHKO_EFFECT
- jr z, ApplyDamageToPlayerPokemon
- cp SUPER_FANG_EFFECT
- jr z, .superFangEffect
- cp SPECIAL_DAMAGE_EFFECT
- jr z, .specialDamage
- ld a, [wEnemyMovePower]
- and a
- jp z, ApplyAttackToPlayerPokemonDone
- jr ApplyDamageToPlayerPokemon
-.superFangEffect
-; set the damage to half the target's HP
- ld hl, wBattleMonHP
- ld de, wDamage
- ld a, [hli]
- srl a
- ld [de], a
- inc de
- ld b, a
- ld a, [hl]
- rr a
- ld [de], a
- or b
- jr nz, ApplyDamageToPlayerPokemon
-; make sure Super Fang's damage is always at least 1
- ld a, $01
- ld [de], a
- jr ApplyDamageToPlayerPokemon
-.specialDamage
- ld hl, wEnemyMonLevel
- ld a, [hl]
- ld b, a
- ld a, [wEnemyMoveNum]
- cp SEISMIC_TOSS
- jr z, .storeDamage
- cp NIGHT_SHADE
- jr z, .storeDamage
- ld b, SONICBOOM_DAMAGE
- cp SONICBOOM
- jr z, .storeDamage
- ld b, DRAGON_RAGE_DAMAGE
- cp DRAGON_RAGE
- jr z, .storeDamage
-; Psywave
- ld a, [hl]
- ld b, a
- srl a
- add b
- ld b, a ; b = attacker's level * 1.5
-; loop until a random number in the range [0, b) is found
-; this differs from the range when the player attacks, which is [1, b)
-; it's possible for the enemy to do 0 damage with Psywave, but the player always does at least 1 damage
-.loop
- call BattleRandom
- cp b
- jr nc, .loop
- ld b, a
-.storeDamage
- ld hl, wDamage
- xor a
- ld [hli], a
- ld a, b
- ld [hl], a
-
-ApplyDamageToPlayerPokemon:
- ld hl, wDamage
- ld a, [hli]
- ld b, a
- ld a, [hl]
- or b
- jr z, ApplyAttackToPlayerPokemonDone ; we're done if damage is 0
- ld a, [wPlayerBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a ; does the player have a substitute?
- jp nz, AttackSubstitute
-; subtract the damage from the pokemon's current HP
-; also, save the current HP at wHPBarOldHP and the new HP at wHPBarNewHP
- ld a, [hld]
- ld b, a
- ld a, [wBattleMonHP + 1]
- ld [wHPBarOldHP], a
- sub b
- ld [wBattleMonHP + 1], a
- ld [wHPBarNewHP], a
- ld b, [hl]
- ld a, [wBattleMonHP]
- ld [wHPBarOldHP+1], a
- sbc b
- ld [wBattleMonHP], a
- ld [wHPBarNewHP+1], a
- jr nc, .animateHpBar
-; if more damage was done than the current HP, zero the HP and set the damage (wDamage)
-; equal to how much HP the pokemon had before the attack
- ld a, [wHPBarOldHP+1]
- ld [hli], a
- ld a, [wHPBarOldHP]
- ld [hl], a
- xor a
- ld hl, wBattleMonHP
- ld [hli], a
- ld [hl], a
- ld hl, wHPBarNewHP
- ld [hli], a
- ld [hl], a
-.animateHpBar
- ld hl, wBattleMonMaxHP
- ld a, [hli]
- ld [wHPBarMaxHP+1], a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- coord hl, 10, 9
- ld a, $01
- ld [wHPBarType], a
- predef UpdateHPBar2 ; animate the HP bar shortening
-ApplyAttackToPlayerPokemonDone:
- jp DrawHUDsAndHPBars
-
-AttackSubstitute:
-; Unlike the two ApplyAttackToPokemon functions, Attack Substitute is shared by player and enemy.
-; Self-confusion damage as well as Hi-Jump Kick and Jump Kick recoil cause a momentary turn swap before being applied.
-; If the user has a Substitute up and would take damage because of that,
-; damage will be applied to the other player's Substitute.
-; Normal recoil such as from Double-Edge isn't affected by this glitch,
-; because this function is never called in that case.
-
- ld hl, SubstituteTookDamageText
- call PrintText
-; values for player turn
- ld de, wEnemySubstituteHP
- ld bc, wEnemyBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .applyDamageToSubstitute
-; values for enemy turn
- ld de, wPlayerSubstituteHP
- ld bc, wPlayerBattleStatus2
-.applyDamageToSubstitute
- ld hl, wDamage
- ld a, [hli]
- and a
- jr nz, .substituteBroke ; damage > 0xFF always breaks substitutes
-; subtract damage from HP of substitute
- ld a, [de]
- sub [hl]
- ld [de], a
- ret nc
-.substituteBroke
-; If the target's Substitute breaks, wDamage isn't updated with the amount of HP
-; the Substitute had before being attacked.
- ld h, b
- ld l, c
- res HAS_SUBSTITUTE_UP, [hl] ; unset the substitute bit
- ld hl, SubstituteBrokeText
- call PrintText
-; flip whose turn it is for the next function call
- ld a, [H_WHOSETURN]
- xor $01
- ld [H_WHOSETURN], a
- callab HideSubstituteShowMonAnim ; animate the substitute breaking
-; flip the turn back to the way it was
- ld a, [H_WHOSETURN]
- xor $01
- ld [H_WHOSETURN], a
- ld hl, wPlayerMoveEffect ; value for player's turn
- and a
- jr z, .nullifyEffect
- ld hl, wEnemyMoveEffect ; value for enemy's turn
-.nullifyEffect
- xor a
- ld [hl], a ; zero the effect of the attacker's move
- jp DrawHUDsAndHPBars
-
-SubstituteTookDamageText:
- TX_FAR _SubstituteTookDamageText
- db "@"
-
-SubstituteBrokeText:
- TX_FAR _SubstituteBrokeText
- db "@"
-
-; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked
-HandleBuildingRage:
-; values for the player turn
- ld hl, wEnemyBattleStatus2
- ld de, wEnemyMonStatMods
- ld bc, wEnemyMoveNum
- ld a, [H_WHOSETURN]
- and a
- jr z, .next
-; values for the enemy turn
- ld hl, wPlayerBattleStatus2
- ld de, wPlayerMonStatMods
- ld bc, wPlayerMoveNum
-.next
- bit USING_RAGE, [hl] ; is the pokemon being attacked under the effect of Rage?
- ret z ; return if not
- ld a, [de]
- cp $0d ; maximum stat modifier value
- ret z ; return if attack modifier is already maxed
- ld a, [H_WHOSETURN]
- xor $01 ; flip turn for the stat modifier raising function
- ld [H_WHOSETURN], a
-; temporarily change the target pokemon's move to $00 and the effect to the one
-; that causes the attack modifier to go up one stage
- ld h, b
- ld l, c
- ld [hl], $00 ; null move number
- inc hl
- ld [hl], ATTACK_UP1_EFFECT
- push hl
- ld hl, BuildingRageText
- call PrintText
- call StatModifierUpEffect ; stat modifier raising function
- pop hl
- xor a
- ldd [hl], a ; null move effect
- ld a, RAGE
- ld [hl], a ; restore the target pokemon's move number to Rage
- ld a, [H_WHOSETURN]
- xor $01 ; flip turn back to the way it was
- ld [H_WHOSETURN], a
- ret
-
-BuildingRageText:
- TX_FAR _BuildingRageText
- db "@"
-
-; copy last move for Mirror Move
-; sets zero flag on failure and unsets zero flag on success
-MirrorMoveCopyMove:
-; Mirror Move makes use of ccf1 (wPlayerUsedMove) and ccf2 (wEnemyUsedMove) addresses,
-; which are mainly used to print the "[Pokemon] used [Move]" text.
-; Both are set to 0 whenever a new Pokemon is sent out
-; ccf1 is also set to 0 whenever the player is fast asleep or frozen solid.
-; ccf2 is also set to 0 whenever the enemy is fast asleep or frozen solid.
-
- ld a, [H_WHOSETURN]
- and a
-; values for player turn
- ld a, [wEnemyUsedMove]
- ld hl, wPlayerSelectedMove
- ld de, wPlayerMoveNum
- jr z, .next
-; values for enemy turn
- ld a, [wPlayerUsedMove]
- ld de, wEnemyMoveNum
- ld hl, wEnemySelectedMove
-.next
- ld [hl], a
- cp MIRROR_MOVE ; did the target Pokemon last use Mirror Move, and miss?
- jr z, .mirrorMoveFailed
- and a ; has the target selected any move yet?
- jr nz, ReloadMoveData
-.mirrorMoveFailed
- ld hl, MirrorMoveFailedText
- call PrintText
- xor a
- ret
-
-MirrorMoveFailedText:
- TX_FAR _MirrorMoveFailedText
- db "@"
-
-; function used to reload move data for moves like Mirror Move and Metronome
-ReloadMoveData:
- ld [wd11e], a
- dec a
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld a, BANK(Moves)
- call FarCopyData ; copy the move's stats
- call IncrementMovePP
-; the follow two function calls are used to reload the move name
- call GetMoveName
- call CopyStringToCF4B
- ld a, $01
- and a
- ret
-
-; function that picks a random move for metronome
-MetronomePickMove:
- xor a
- ld [wAnimationType], a
- ld a, METRONOME
- call PlayMoveAnimation ; play Metronome's animation
-; values for player turn
- ld de, wPlayerMoveNum
- ld hl, wPlayerSelectedMove
- ld a, [H_WHOSETURN]
- and a
- jr z, .pickMoveLoop
-; values for enemy turn
- ld de, wEnemyMoveNum
- ld hl, wEnemySelectedMove
-; loop to pick a random number in the range [1, $a5) to be the move used by Metronome
-.pickMoveLoop
- call BattleRandom
- and a
- jr z, .pickMoveLoop
- cp NUM_ATTACKS + 1 ; max normal move number + 1 (this is Struggle's move number)
- jr nc, .pickMoveLoop
- cp METRONOME
- jr z, .pickMoveLoop
- ld [hl], a
- jr ReloadMoveData
-
-; this function increments the current move's PP
-; it's used to prevent moves that run another move within the same turn
-; (like Mirror Move and Metronome) from losing 2 PP
-IncrementMovePP:
- ld a, [H_WHOSETURN]
- and a
-; values for player turn
- ld hl, wBattleMonPP
- ld de, wPartyMon1PP
- ld a, [wPlayerMoveListIndex]
- jr z, .next
-; values for enemy turn
- ld hl, wEnemyMonPP
- ld de, wEnemyMon1PP
- ld a, [wEnemyMoveListIndex]
-.next
- ld b, $00
- ld c, a
- add hl, bc
- inc [hl] ; increment PP in the currently battling pokemon memory location
- ld h, d
- ld l, e
- add hl, bc
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMonNumber] ; value for player turn
- jr z, .updatePP
- ld a, [wEnemyMonPartyPos] ; value for enemy turn
-.updatePP
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- inc [hl] ; increment PP in the party memory location
- ret
-
-; function to adjust the base damage of an attack to account for type effectiveness
-AdjustDamageForMoveType:
-; values for player turn
- ld hl, wBattleMonType
- ld a, [hli]
- ld b, a ; b = type 1 of attacker
- ld c, [hl] ; c = type 2 of attacker
- ld hl, wEnemyMonType
- ld a, [hli]
- ld d, a ; d = type 1 of defender
- ld e, [hl] ; e = type 2 of defender
- ld a, [wPlayerMoveType]
- ld [wMoveType], a
- ld a, [H_WHOSETURN]
- and a
- jr z, .next
-; values for enemy turn
- ld hl, wEnemyMonType
- ld a, [hli]
- ld b, a ; b = type 1 of attacker
- ld c, [hl] ; c = type 2 of attacker
- ld hl, wBattleMonType
- ld a, [hli]
- ld d, a ; d = type 1 of defender
- ld e, [hl] ; e = type 2 of defender
- ld a, [wEnemyMoveType]
- ld [wMoveType], a
-.next
- ld a, [wMoveType]
- cp b ; does the move type match type 1 of the attacker?
- jr z, .sameTypeAttackBonus
- cp c ; does the move type match type 2 of the attacker?
- jr z, .sameTypeAttackBonus
- jr .skipSameTypeAttackBonus
-.sameTypeAttackBonus
-; if the move type matches one of the attacker's types
- ld hl, wDamage + 1
- ld a, [hld]
- ld h, [hl]
- ld l, a ; hl = damage
- ld b, h
- ld c, l ; bc = damage
- srl b
- rr c ; bc = floor(0.5 * damage)
- add hl, bc ; hl = floor(1.5 * damage)
-; store damage
- ld a, h
- ld [wDamage], a
- ld a, l
- ld [wDamage + 1], a
- ld hl, wDamageMultipliers
- set 7, [hl]
-.skipSameTypeAttackBonus
- ld a, [wMoveType]
- ld b, a
- ld hl, TypeEffects
-.loop
- ld a, [hli] ; a = "attacking type" of the current type pair
- cp $ff
- jr z, .done
- cp b ; does move type match "attacking type"?
- jr nz, .nextTypePair
- ld a, [hl] ; a = "defending type" of the current type pair
- cp d ; does type 1 of defender match "defending type"?
- jr z, .matchingPairFound
- cp e ; does type 2 of defender match "defending type"?
- jr z, .matchingPairFound
- jr .nextTypePair
-.matchingPairFound
-; if the move type matches the "attacking type" and one of the defender's types matches the "defending type"
- push hl
- push bc
- inc hl
- ld a, [wDamageMultipliers]
- and $80
- ld b, a
- ld a, [hl] ; a = damage multiplier
- ld [H_MULTIPLIER], a
- add b
- ld [wDamageMultipliers], a
- xor a
- ld [H_MULTIPLICAND], a
- ld hl, wDamage
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hld]
- ld [H_MULTIPLICAND + 2], a
- call Multiply
- ld a, 10
- ld [H_DIVISOR], a
- ld b, $04
- call Divide
- ld a, [H_QUOTIENT + 2]
- ld [hli], a
- ld b, a
- ld a, [H_QUOTIENT + 3]
- ld [hl], a
- or b ; is damage 0?
- jr nz, .skipTypeImmunity
-.typeImmunity
-; if damage is 0, make the move miss
-; this only occurs if a move that would do 2 or 3 damage is 0.25x effective against the target
- inc a
- ld [wMoveMissed], a
-.skipTypeImmunity
- pop bc
- pop hl
-.nextTypePair
- inc hl
- inc hl
- jp .loop
-.done
- ret
-
-; function to tell how effective the type of an enemy attack is on the player's current pokemon
-; this doesn't take into account the effects that dual types can have
-; (e.g. 4x weakness / resistance, weaknesses and resistances canceling)
-; the result is stored in [wTypeEffectiveness]
-; ($05 is not very effective, $10 is neutral, $14 is super effective)
-; as far is can tell, this is only used once in some AI code to help decide which move to use
-AIGetTypeEffectiveness:
- ld a, [wEnemyMoveType]
- ld d, a ; d = type of enemy move
- ld hl, wBattleMonType
- ld b, [hl] ; b = type 1 of player's pokemon
- inc hl
- ld c, [hl] ; c = type 2 of player's pokemon
- ld a, $10
- ld [wTypeEffectiveness], a ; initialize to neutral effectiveness
- ld hl, TypeEffects
-.loop
- ld a, [hli]
- cp $ff
- ret z
- cp d ; match the type of the move
- jr nz, .nextTypePair1
- ld a, [hli]
- cp b ; match with type 1 of pokemon
- jr z, .done
- cp c ; or match with type 2 of pokemon
- jr z, .done
- jr .nextTypePair2
-.nextTypePair1
- inc hl
-.nextTypePair2
- inc hl
- jr .loop
-.done
- ld a, [hl]
- ld [wTypeEffectiveness], a ; store damage multiplier
- ret
-
-INCLUDE "data/type_effects.asm"
-
-; some tests that need to pass for a move to hit
-MoveHitTest:
-; player's turn
- ld hl, wEnemyBattleStatus1
- ld de, wPlayerMoveEffect
- ld bc, wEnemyMonStatus
- ld a, [H_WHOSETURN]
- and a
- jr z, .dreamEaterCheck
-; enemy's turn
- ld hl, wPlayerBattleStatus1
- ld de, wEnemyMoveEffect
- ld bc, wBattleMonStatus
-.dreamEaterCheck
- ld a, [de]
- cp DREAM_EATER_EFFECT
- jr nz, .swiftCheck
- ld a, [bc]
- and SLP ; is the target pokemon sleeping?
- jp z, .moveMissed
-.swiftCheck
- ld a, [de]
- cp SWIFT_EFFECT
- ret z ; Swift never misses (interestingly, Azure Heights lists this is a myth, but it appears to be true)
- call CheckTargetSubstitute ; substitute check (note that this overwrites a)
- jr z, .checkForDigOrFlyStatus
-; this code is buggy. it's supposed to prevent HP draining moves from working on substitutes.
-; since $7b79 overwrites a with either $00 or $01, it never works.
- cp DRAIN_HP_EFFECT
- jp z, .moveMissed
- cp DREAM_EATER_EFFECT
- jp z, .moveMissed
-.checkForDigOrFlyStatus
- bit INVULNERABLE, [hl]
- jp nz, .moveMissed
- ld a, [H_WHOSETURN]
- and a
- jr nz, .enemyTurn
-.playerTurn
-; this checks if the move effect is disallowed by mist
- ld a, [wPlayerMoveEffect]
- cp ATTACK_DOWN1_EFFECT
- jr c, .skipEnemyMistCheck
- cp HAZE_EFFECT + 1
- jr c, .enemyMistCheck
- cp ATTACK_DOWN2_EFFECT
- jr c, .skipEnemyMistCheck
- cp REFLECT_EFFECT + 1
- jr c, .enemyMistCheck
- jr .skipEnemyMistCheck
-.enemyMistCheck
-; if move effect is from $12 to $19 inclusive or $3a to $41 inclusive
-; i.e. the following moves
-; GROWL, TAIL WHIP, LEER, STRING SHOT, SAND-ATTACK, SMOKESCREEN, KINESIS,
-; FLASH, CONVERSION*, HAZE*, SCREECH, LIGHT SCREEN*, REFLECT*
-; the moves that are marked with an asterisk are not affected since this
-; function is not called when those moves are used
- ld a, [wEnemyBattleStatus2]
- bit PROTECTED_BY_MIST, a ; is mon protected by mist?
- jp nz, .moveMissed
-.skipEnemyMistCheck
- ld a, [wPlayerBattleStatus2]
- bit USING_X_ACCURACY, a ; is the player using X Accuracy?
- ret nz ; if so, always hit regardless of accuracy/evasion
- jr .calcHitChance
-.enemyTurn
- ld a, [wEnemyMoveEffect]
- cp ATTACK_DOWN1_EFFECT
- jr c, .skipPlayerMistCheck
- cp HAZE_EFFECT + 1
- jr c, .playerMistCheck
- cp ATTACK_DOWN2_EFFECT
- jr c, .skipPlayerMistCheck
- cp REFLECT_EFFECT + 1
- jr c, .playerMistCheck
- jr .skipPlayerMistCheck
-.playerMistCheck
-; similar to enemy mist check
- ld a, [wPlayerBattleStatus2]
- bit PROTECTED_BY_MIST, a ; is mon protected by mist?
- jp nz, .moveMissed
-.skipPlayerMistCheck
- ld a, [wEnemyBattleStatus2]
- bit USING_X_ACCURACY, a ; is the enemy using X Accuracy?
- ret nz ; if so, always hit regardless of accuracy/evasion
-.calcHitChance
- call CalcHitChance ; scale the move accuracy according to attacker's accuracy and target's evasion
- ld a, [wPlayerMoveAccuracy]
- ld b, a
- ld a, [H_WHOSETURN]
- and a
- jr z, .doAccuracyCheck
- ld a, [wEnemyMoveAccuracy]
- ld b, a
-.doAccuracyCheck
-; if the random number generated is greater than or equal to the scaled accuracy, the move misses
-; note that this means that even the highest accuracy is still just a 255/256 chance, not 100%
- call BattleRandom
- cp b
- jr nc, .moveMissed
- ret
-.moveMissed
- xor a
- ld hl, wDamage ; zero the damage
- ld [hli], a
- ld [hl], a
- inc a
- ld [wMoveMissed], a
- ld a, [H_WHOSETURN]
- and a
- jr z, .playerTurn2
-.enemyTurn2
- ld hl, wEnemyBattleStatus1
- res USING_TRAPPING_MOVE, [hl] ; end multi-turn attack e.g. wrap
- ret
-.playerTurn2
- ld hl, wPlayerBattleStatus1
- res USING_TRAPPING_MOVE, [hl] ; end multi-turn attack e.g. wrap
- ret
-
-; values for player turn
-CalcHitChance:
- ld hl, wPlayerMoveAccuracy
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMonAccuracyMod]
- ld b, a
- ld a, [wEnemyMonEvasionMod]
- ld c, a
- jr z, .next
-; values for enemy turn
- ld hl, wEnemyMoveAccuracy
- ld a, [wEnemyMonAccuracyMod]
- ld b, a
- ld a, [wPlayerMonEvasionMod]
- ld c, a
-.next
- ld a, $0e
- sub c
- ld c, a ; c = 14 - EVASIONMOD (this "reflects" the value over 7, so that an increase in the target's evasion
- ; decreases the hit chance instead of increasing the hit chance)
-; zero the high bytes of the multiplicand
- xor a
- ld [H_MULTIPLICAND], a
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [H_MULTIPLICAND + 2], a ; set multiplicand to move accuracy
- push hl
- ld d, $02 ; loop has two iterations
-; loop to do the calculations, the first iteration multiplies by the accuracy ratio and
-; the second iteration multiplies by the evasion ratio
-.loop
- push bc
- ld hl, StatModifierRatios ; stat modifier ratios
- dec b
- sla b
- ld c, b
- ld b, $00
- add hl, bc ; hl = address of stat modifier ratio
- pop bc
- ld a, [hli]
- ld [H_MULTIPLIER], a ; set multiplier to the numerator of the ratio
- call Multiply
- ld a, [hl]
- ld [H_DIVISOR], a ; set divisor to the the denominator of the ratio
- ; (the dividend is the product of the previous multiplication)
- ld b, $04 ; number of bytes in the dividend
- call Divide
- ld a, [H_QUOTIENT + 3]
- ld b, a
- ld a, [H_QUOTIENT + 2]
- or b
- jp nz, .nextCalculation
-; make sure the result is always at least one
- ld [H_QUOTIENT + 2], a
- ld a, $01
- ld [H_QUOTIENT + 3], a
-.nextCalculation
- ld b, c
- dec d
- jr nz, .loop
- ld a, [H_QUOTIENT + 2]
- and a ; is the calculated hit chance over 0xFF?
- ld a, [H_QUOTIENT + 3]
- jr z, .storeAccuracy
-; if calculated hit chance over 0xFF
- ld a, $ff ; set the hit chance to 0xFF
-.storeAccuracy
- pop hl
- ld [hl], a ; store the hit chance in the move accuracy variable
- ret
-
-; multiplies damage by a random percentage from ~85% to 100%
-RandomizeDamage:
- ld hl, wDamage
- ld a, [hli]
- and a
- jr nz, .DamageGreaterThanOne
- ld a, [hl]
- cp 2
- ret c ; return if damage is equal to 0 or 1
-.DamageGreaterThanOne
- xor a
- ld [H_MULTIPLICAND], a
- dec hl
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [H_MULTIPLICAND + 2], a
-; loop until a random number greater than or equal to 217 is generated
-.loop
- call BattleRandom
- rrca
- cp 217
- jr c, .loop
- ld [H_MULTIPLIER], a
- call Multiply ; multiply damage by the random number, which is in the range [217, 255]
- ld a, 255
- ld [H_DIVISOR], a
- ld b, $4
- call Divide ; divide the result by 255
-; store the modified damage
- ld a, [H_QUOTIENT + 2]
- ld hl, wDamage
- ld [hli], a
- ld a, [H_QUOTIENT + 3]
- ld [hl], a
- ret
-
-; for more detailed commentary, see equivalent function for player side (ExecutePlayerMove)
-ExecuteEnemyMove:
- ld a, [wEnemySelectedMove]
- inc a
- jp z, ExecuteEnemyMoveDone
- call PrintGhostText
- jp z, ExecuteEnemyMoveDone
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .executeEnemyMove
- ld b, $1
- ld a, [wSerialExchangeNybbleReceiveData]
- cp LINKBATTLE_STRUGGLE
- jr z, .executeEnemyMove
- cp 4
- ret nc
-.executeEnemyMove
- ld hl, wAILayer2Encouragement
- inc [hl]
- xor a
- ld [wMoveMissed], a
- ld [wMoveDidntMiss], a
- ld a, $a
- ld [wDamageMultipliers], a
- call CheckEnemyStatusConditions
- jr nz, .enemyHasNoSpecialConditions
- jp hl
-.enemyHasNoSpecialConditions
- ld hl, wEnemyBattleStatus1
- bit CHARGING_UP, [hl] ; is the enemy charging up for attack?
- jr nz, EnemyCanExecuteChargingMove ; if so, jump
- call GetCurrentMove
-
-CheckIfEnemyNeedsToChargeUp:
- ld a, [wEnemyMoveEffect]
- cp CHARGE_EFFECT
- jp z, JumpMoveEffect
- cp FLY_EFFECT
- jp z, JumpMoveEffect
- jr EnemyCanExecuteMove
-EnemyCanExecuteChargingMove:
- ld hl, wEnemyBattleStatus1
- res CHARGING_UP, [hl] ; no longer charging up for attack
- res INVULNERABLE, [hl] ; no longer invulnerable to typical attacks
- ld a, [wEnemyMoveNum]
- ld [wd0b5], a
- ld a, BANK(MoveNames)
- ld [wPredefBank], a
- ld a, MOVE_NAME
- ld [wNameListType], a
- call GetName
- ld de, wcd6d
- call CopyStringToCF4B
-EnemyCanExecuteMove:
- xor a
- ld [wMonIsDisobedient], a
- call PrintMonName1Text
- ld a, [wEnemyMoveEffect]
- ld hl, ResidualEffects1
- ld de, $1
- call IsInArray
- jp c, JumpMoveEffect
- ld a, [wEnemyMoveEffect]
- ld hl, SpecialEffectsCont
- ld de, $1
- call IsInArray
- call c, JumpMoveEffect
-EnemyCalcMoveDamage:
- call SwapPlayerAndEnemyLevels
- ld a, [wEnemyMoveEffect]
- ld hl, SetDamageEffects
- ld de, $1
- call IsInArray
- jp c, EnemyMoveHitTest
- call CriticalHitTest
- call HandleCounterMove
- jr z, handleIfEnemyMoveMissed
- call SwapPlayerAndEnemyLevels
- call GetDamageVarsForEnemyAttack
- call SwapPlayerAndEnemyLevels
- call CalculateDamage
- jp z, EnemyCheckIfFlyOrChargeEffect
- call AdjustDamageForMoveType
- call RandomizeDamage
-
-EnemyMoveHitTest:
- call MoveHitTest
-handleIfEnemyMoveMissed:
- ld a, [wMoveMissed]
- and a
- jr z, .moveDidNotMiss
- ld a, [wEnemyMoveEffect]
- cp EXPLODE_EFFECT
- jr z, handleExplosionMiss
- jr EnemyCheckIfFlyOrChargeEffect
-.moveDidNotMiss
- call SwapPlayerAndEnemyLevels
-
-GetEnemyAnimationType:
- ld a, [wEnemyMoveEffect]
- and a
- ld a, $1
- jr z, playEnemyMoveAnimation
- ld a, $2
- jr playEnemyMoveAnimation
-handleExplosionMiss:
- call SwapPlayerAndEnemyLevels
- xor a
-playEnemyMoveAnimation:
- push af
- ld a, [wEnemyBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a ; does mon have a substitute?
- ld hl, HideSubstituteShowMonAnim
- ld b, BANK(HideSubstituteShowMonAnim)
- call nz, Bankswitch
- pop af
- ld [wAnimationType], a
- ld a, [wEnemyMoveNum]
- call PlayMoveAnimation
- call HandleExplodingAnimation
- call DrawEnemyHUDAndHPBar
- ld a, [wEnemyBattleStatus2]
- bit HAS_SUBSTITUTE_UP, a ; does mon have a substitute?
- ld hl, ReshowSubstituteAnim
- ld b, BANK(ReshowSubstituteAnim)
- call nz, Bankswitch ; slide the substitute's sprite out
- jr EnemyCheckIfMirrorMoveEffect
-
-EnemyCheckIfFlyOrChargeEffect:
- call SwapPlayerAndEnemyLevels
- ld c, 30
- call DelayFrames
- ld a, [wEnemyMoveEffect]
- cp FLY_EFFECT
- jr z, .playAnim
- cp CHARGE_EFFECT
- jr z, .playAnim
- jr EnemyCheckIfMirrorMoveEffect
-.playAnim
- xor a
- ld [wAnimationType], a
- ld a, STATUS_AFFECTED_ANIM
- call PlayMoveAnimation
-EnemyCheckIfMirrorMoveEffect:
- ld a, [wEnemyMoveEffect]
- cp MIRROR_MOVE_EFFECT
- jr nz, .notMirrorMoveEffect
- call MirrorMoveCopyMove
- jp z, ExecuteEnemyMoveDone
- jp CheckIfEnemyNeedsToChargeUp
-.notMirrorMoveEffect
- cp METRONOME_EFFECT
- jr nz, .notMetronomeEffect
- call MetronomePickMove
- jp CheckIfEnemyNeedsToChargeUp
-.notMetronomeEffect
- ld a, [wEnemyMoveEffect]
- ld hl, ResidualEffects2
- ld de, $1
- call IsInArray
- jp c, JumpMoveEffect
- ld a, [wMoveMissed]
- and a
- jr z, .moveDidNotMiss
- call PrintMoveFailureText
- ld a, [wEnemyMoveEffect]
- cp EXPLODE_EFFECT
- jr z, .handleExplosionMiss
- jp ExecuteEnemyMoveDone
-.moveDidNotMiss
- call ApplyAttackToPlayerPokemon
- call PrintCriticalOHKOText
- callab DisplayEffectiveness
- ld a, 1
- ld [wMoveDidntMiss], a
-.handleExplosionMiss
- ld a, [wEnemyMoveEffect]
- ld hl, AlwaysHappenSideEffects
- ld de, $1
- call IsInArray
- call c, JumpMoveEffect
- ld hl, wBattleMonHP
- ld a, [hli]
- ld b, [hl]
- or b
- ret z
- call HandleBuildingRage
- ld hl, wEnemyBattleStatus1
- bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon hitting multiple times? (example: double kick)
- jr z, .notMultiHitMove
- push hl
- ld hl, wEnemyNumAttacksLeft
- dec [hl]
- pop hl
- jp nz, GetEnemyAnimationType
- res ATTACKING_MULTIPLE_TIMES, [hl] ; mon is no longer hitting multiple times
- ld hl, HitXTimesText
- call PrintText
- xor a
- ld [wEnemyNumHits], a
-.notMultiHitMove
- ld a, [wEnemyMoveEffect]
- and a
- jr z, ExecuteEnemyMoveDone
- ld hl, SpecialEffects
- ld de, $1
- call IsInArray
- call nc, JumpMoveEffect
- jr ExecuteEnemyMoveDone
-
-HitXTimesText:
- TX_FAR _HitXTimesText
- db "@"
-
-ExecuteEnemyMoveDone:
- ld b, $1
- ret
-
-; checks for various status conditions affecting the enemy mon
-; stores whether the mon cannot use a move this turn in Z flag
-CheckEnemyStatusConditions:
- ld hl, wEnemyMonStatus
- ld a, [hl]
- and SLP ; sleep mask
- jr z, .checkIfFrozen
- dec a ; decrement number of turns left
- ld [wEnemyMonStatus], a
- and a
- jr z, .wokeUp ; if the number of turns hit 0, wake up
- ld hl, FastAsleepText
- call PrintText
- xor a
- ld [wAnimationType], a
- ld a, SLP_ANIM
- call PlayMoveAnimation
- jr .sleepDone
-.wokeUp
- ld hl, WokeUpText
- call PrintText
-.sleepDone
- xor a
- ld [wEnemyUsedMove], a
- ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
- jp .enemyReturnToHL
-.checkIfFrozen
- bit FRZ, [hl]
- jr z, .checkIfTrapped
- ld hl, IsFrozenText
- call PrintText
- xor a
- ld [wEnemyUsedMove], a
- ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
- jp .enemyReturnToHL
-.checkIfTrapped
- ld a, [wPlayerBattleStatus1]
- bit USING_TRAPPING_MOVE, a ; is the player using a multi-turn attack like warp
- jp z, .checkIfFlinched
- ld hl, CantMoveText
- call PrintText
- ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
- jp .enemyReturnToHL
-.checkIfFlinched
- ld hl, wEnemyBattleStatus1
- bit FLINCHED, [hl] ; check if enemy mon flinched
- jp z, .checkIfMustRecharge
- res FLINCHED, [hl]
- ld hl, FlinchedText
- call PrintText
- ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
- jp .enemyReturnToHL
-.checkIfMustRecharge
- ld hl, wEnemyBattleStatus2
- bit NEEDS_TO_RECHARGE, [hl] ; check if enemy mon has to recharge after using a move
- jr z, .checkIfAnyMoveDisabled
- res NEEDS_TO_RECHARGE, [hl]
- ld hl, MustRechargeText
- call PrintText
- ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
- jp .enemyReturnToHL
-.checkIfAnyMoveDisabled
- ld hl, wEnemyDisabledMove
- ld a, [hl]
- and a
- jr z, .checkIfConfused
- dec a ; decrement disable counter
- ld [hl], a
- and $f ; did disable counter hit 0?
- jr nz, .checkIfConfused
- ld [hl], a
- ld [wEnemyDisabledMoveNumber], a
- ld hl, DisabledNoMoreText
- call PrintText
-.checkIfConfused
- ld a, [wEnemyBattleStatus1]
- add a ; check if enemy mon is confused
- jp nc, .checkIfTriedToUseDisabledMove
- ld hl, wEnemyConfusedCounter
- dec [hl]
- jr nz, .isConfused
- ld hl, wEnemyBattleStatus1
- res CONFUSED, [hl] ; if confused counter hit 0, reset confusion status
- ld hl, ConfusedNoMoreText
- call PrintText
- jp .checkIfTriedToUseDisabledMove
-.isConfused
- ld hl, IsConfusedText
- call PrintText
- xor a
- ld [wAnimationType], a
- ld a, CONF_ANIM
- call PlayMoveAnimation
- call BattleRandom
- cp $80
- jr c, .checkIfTriedToUseDisabledMove
- ld hl, wEnemyBattleStatus1
- ld a, [hl]
- and 1 << CONFUSED ; if mon hurts itself, clear every other status from wEnemyBattleStatus1
- ld [hl], a
- ld hl, HurtItselfText
- call PrintText
- ld hl, wBattleMonDefense
- ld a, [hli]
- push af
- ld a, [hld]
- push af
- ld a, [wEnemyMonDefense]
- ld [hli], a
- ld a, [wEnemyMonDefense + 1]
- ld [hl], a
- ld hl, wEnemyMoveEffect
- push hl
- ld a, [hl]
- push af
- xor a
- ld [hli], a
- ld [wCriticalHitOrOHKO], a
- ld a, 40
- ld [hli], a
- xor a
- ld [hl], a
- call GetDamageVarsForEnemyAttack
- call CalculateDamage
- pop af
- pop hl
- ld [hl], a
- ld hl, wBattleMonDefense + 1
- pop af
- ld [hld], a
- pop af
- ld [hl], a
- xor a
- ld [wAnimationType], a
- ld [H_WHOSETURN], a
- ld a, POUND
- call PlayMoveAnimation
- ld a, $1
- ld [H_WHOSETURN], a
- call ApplyDamageToEnemyPokemon
- jr .monHurtItselfOrFullyParalysed
-.checkIfTriedToUseDisabledMove
-; prevents a disabled move that was selected before being disabled from being used
- ld a, [wEnemyDisabledMoveNumber]
- and a
- jr z, .checkIfParalysed
- ld hl, wEnemySelectedMove
- cp [hl]
- jr nz, .checkIfParalysed
- call PrintMoveIsDisabledText
- ld hl, ExecuteEnemyMoveDone ; if a disabled move was somehow selected, player can't move this turn
- jp .enemyReturnToHL
-.checkIfParalysed
- ld hl, wEnemyMonStatus
- bit PAR, [hl]
- jr z, .checkIfUsingBide
- call BattleRandom
- cp $3f ; 25% to be fully paralysed
- jr nc, .checkIfUsingBide
- ld hl, FullyParalyzedText
- call PrintText
-.monHurtItselfOrFullyParalysed
- ld hl, wEnemyBattleStatus1
- ld a, [hl]
- ; clear bide, thrashing about, charging up, and multi-turn moves such as warp
- and $ff ^ ((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE))
- ld [hl], a
- ld a, [wEnemyMoveEffect]
- cp FLY_EFFECT
- jr z, .flyOrChargeEffect
- cp CHARGE_EFFECT
- jr z, .flyOrChargeEffect
- jr .notFlyOrChargeEffect
-.flyOrChargeEffect
- xor a
- ld [wAnimationType], a
- ld a, STATUS_AFFECTED_ANIM
- call PlayMoveAnimation
-.notFlyOrChargeEffect
- ld hl, ExecuteEnemyMoveDone
- jp .enemyReturnToHL ; if using a two-turn move, enemy needs to recharge the first turn
-.checkIfUsingBide
- ld hl, wEnemyBattleStatus1
- bit STORING_ENERGY, [hl] ; is mon using bide?
- jr z, .checkIfThrashingAbout
- xor a
- ld [wEnemyMoveNum], a
- ld hl, wDamage
- ld a, [hli]
- ld b, a
- ld c, [hl]
- ld hl, wEnemyBideAccumulatedDamage + 1
- ld a, [hl]
- add c ; accumulate damage taken
- ld [hld], a
- ld a, [hl]
- adc b
- ld [hl], a
- ld hl, wEnemyNumAttacksLeft
- dec [hl] ; did Bide counter hit 0?
- jr z, .unleashEnergy
- ld hl, ExecuteEnemyMoveDone
- jp .enemyReturnToHL ; unless mon unleashes energy, can't move this turn
-.unleashEnergy
- ld hl, wEnemyBattleStatus1
- res STORING_ENERGY, [hl] ; not using bide any more
- ld hl, UnleashedEnergyText
- call PrintText
- ld a, $1
- ld [wEnemyMovePower], a
- ld hl, wEnemyBideAccumulatedDamage + 1
- ld a, [hld]
- add a
- ld b, a
- ld [wDamage + 1], a
- ld a, [hl]
- rl a ; double the damage
- ld [wDamage], a
- or b
- jr nz, .next
- ld a, $1
- ld [wMoveMissed], a
-.next
- xor a
- ld [hli], a
- ld [hl], a
- ld a, BIDE
- ld [wEnemyMoveNum], a
- call SwapPlayerAndEnemyLevels
- ld hl, handleIfEnemyMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
- jp .enemyReturnToHL
-.checkIfThrashingAbout
- bit THRASHING_ABOUT, [hl] ; is mon using thrash or petal dance?
- jr z, .checkIfUsingMultiturnMove
- ld a, THRASH
- ld [wEnemyMoveNum], a
- ld hl, ThrashingAboutText
- call PrintText
- ld hl, wEnemyNumAttacksLeft
- dec [hl] ; did Thrashing About counter hit 0?
- ld hl, EnemyCalcMoveDamage ; skip DecrementPP
- jp nz, .enemyReturnToHL
- push hl
- ld hl, wEnemyBattleStatus1
- res THRASHING_ABOUT, [hl] ; mon is no longer using thrash or petal dance
- set CONFUSED, [hl] ; mon is now confused
- call BattleRandom
- and $3
- inc a
- inc a ; confused for 2-5 turns
- ld [wEnemyConfusedCounter], a
- pop hl ; skip DecrementPP
- jp .enemyReturnToHL
-.checkIfUsingMultiturnMove
- bit USING_TRAPPING_MOVE, [hl] ; is mon using multi-turn move?
- jp z, .checkIfUsingRage
- ld hl, AttackContinuesText
- call PrintText
- ld hl, wEnemyNumAttacksLeft
- dec [hl] ; did multi-turn move end?
- ld hl, GetEnemyAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit),
- ; DecrementPP and MoveHitTest
- jp nz, .enemyReturnToHL
- jp .enemyReturnToHL
-.checkIfUsingRage
- ld a, [wEnemyBattleStatus2]
- bit USING_RAGE, a ; is mon using rage?
- jp z, .checkEnemyStatusConditionsDone ; if we made it this far, mon can move normally this turn
- ld a, RAGE
- ld [wd11e], a
- call GetMoveName
- call CopyStringToCF4B
- xor a
- ld [wEnemyMoveEffect], a
- ld hl, EnemyCanExecuteMove
- jp .enemyReturnToHL
-.enemyReturnToHL
- xor a ; set Z flag
- ret
-.checkEnemyStatusConditionsDone
- ld a, $1
- and a ; clear Z flag
- ret
-
-GetCurrentMove:
- ld a, [H_WHOSETURN]
- and a
- jp z, .player
- ld de, wEnemyMoveNum
- ld a, [wEnemySelectedMove]
- jr .selected
-.player
- ld de, wPlayerMoveNum
- ld a, [wFlags_D733]
- bit BIT_TEST_BATTLE, a
- ld a, [wTestBattlePlayerSelectedMove]
- jr nz, .selected
- ld a, [wPlayerSelectedMove]
-.selected
- ld [wd0b5], a
- dec a
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld a, BANK(Moves)
- call FarCopyData
-
- ld a, BANK(MoveNames)
- ld [wPredefBank], a
- ld a, MOVE_NAME
- ld [wNameListType], a
- call GetName
- ld de, wcd6d
- jp CopyStringToCF4B
-
-LoadEnemyMonData:
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jp z, LoadEnemyMonFromParty
- ld a, [wEnemyMonSpecies2]
- ld [wEnemyMonSpecies], a
- ld [wd0b5], a
- call GetMonHeader
- ld a, [wEnemyBattleStatus3]
- bit TRANSFORMED, a ; is enemy mon transformed?
- ld hl, wTransformedEnemyMonOriginalDVs ; original DVs before transforming
- ld a, [hli]
- ld b, [hl]
- jr nz, .storeDVs
- ld a, [wIsInBattle]
- cp $2 ; is it a trainer battle?
-; fixed DVs for trainer mon
- ld a, $98
- ld b, $88
- jr z, .storeDVs
-; random DVs for wild mon
- call BattleRandom
- ld b, a
- call BattleRandom
-.storeDVs
- ld hl, wEnemyMonDVs
- ld [hli], a
- ld [hl], b
- ld de, wEnemyMonLevel
- ld a, [wCurEnemyLVL]
- ld [de], a
- inc de
- ld b, $0
- ld hl, wEnemyMonHP
- push hl
- call CalcStats
- pop hl
- ld a, [wIsInBattle]
- cp $2 ; is it a trainer battle?
- jr z, .copyHPAndStatusFromPartyData
- ld a, [wEnemyBattleStatus3]
- bit TRANSFORMED, a ; is enemy mon transformed?
- jr nz, .copyTypes ; if transformed, jump
-; if it's a wild mon and not transformed, init the current HP to max HP and the status to 0
- ld a, [wEnemyMonMaxHP]
- ld [hli], a
- ld a, [wEnemyMonMaxHP+1]
- ld [hli], a
- xor a
- inc hl
- ld [hl], a ; init status to 0
- jr .copyTypes
-; if it's a trainer mon, copy the HP and status from the enemy party data
-.copyHPAndStatusFromPartyData
- ld hl, wEnemyMon1HP
- ld a, [wWhichPokemon]
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld a, [hli]
- ld [wEnemyMonHP], a
- ld a, [hli]
- ld [wEnemyMonHP + 1], a
- ld a, [wWhichPokemon]
- ld [wEnemyMonPartyPos], a
- inc hl
- ld a, [hl]
- ld [wEnemyMonStatus], a
- jr .copyTypes
-.copyTypes
- ld hl, wMonHTypes
- ld de, wEnemyMonType
- ld a, [hli] ; copy type 1
- ld [de], a
- inc de
- ld a, [hli] ; copy type 2
- ld [de], a
- inc de
- ld a, [hli] ; copy catch rate
- ld [de], a
- inc de
- ld a, [wIsInBattle]
- cp $2 ; is it a trainer battle?
- jr nz, .copyStandardMoves
-; if it's a trainer battle, copy moves from enemy party data
- ld hl, wEnemyMon1Moves
- ld a, [wWhichPokemon]
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld bc, NUM_MOVES
- call CopyData
- jr .loadMovePPs
-.copyStandardMoves
-; for a wild mon, first copy default moves from the mon header
- ld hl, wMonHMoves
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- dec de
- dec de
- dec de
- xor a
- ld [wLearningMovesFromDayCare], a
- predef WriteMonMoves ; get moves based on current level
-.loadMovePPs
- ld hl, wEnemyMonMoves
- ld de, wEnemyMonPP - 1
- predef LoadMovePPs
- ld hl, wMonHBaseStats
- ld de, wEnemyMonBaseStats
- ld b, NUM_STATS
-.copyBaseStatsLoop
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .copyBaseStatsLoop
- ld hl, wMonHCatchRate
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl] ; base exp
- ld [de], a
- ld a, [wEnemyMonSpecies2]
- ld [wd11e], a
- call GetMonName
- ld hl, wcd6d
- ld de, wEnemyMonNick
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wEnemyMonSpecies2]
- ld [wd11e], a
- predef IndexToPokedex
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_SET
- ld hl, wPokedexSeen
- predef FlagActionPredef ; mark this mon as seen in the pokedex
- ld hl, wEnemyMonLevel
- ld de, wEnemyMonUnmodifiedLevel
- ld bc, 1 + NUM_STATS * 2
- call CopyData
- ld a, $7 ; default stat mod
- ld b, NUM_STAT_MODS ; number of stat mods
- ld hl, wEnemyMonStatMods
-.statModLoop
- ld [hli], a
- dec b
- jr nz, .statModLoop
- ret
-
-; calls BattleTransition to show the battle transition animation and initializes some battle variables
-DoBattleTransitionAndInitBattleVariables:
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .next
-; link battle
- xor a
- ld [wMenuJoypadPollCount], a
- callab DisplayLinkBattleVersusTextBox
- ld a, $1
- ld [wUpdateSpritesEnabled], a
- call ClearScreen
-.next
- call DelayFrame
- predef BattleTransition
- callab LoadHudAndHpBarAndStatusTilePatterns
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, $ff
- ld [wUpdateSpritesEnabled], a
- call ClearSprites
- call ClearScreen
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld [hWY], a
- ld [rWY], a
- ld [hTilesetType], a
- ld hl, wPlayerStatsToDouble
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wPlayerDisabledMove], a
- ret
-
-; swaps the level values of the BattleMon and EnemyMon structs
-SwapPlayerAndEnemyLevels:
- push bc
- ld a, [wBattleMonLevel]
- ld b, a
- ld a, [wEnemyMonLevel]
- ld [wBattleMonLevel], a
- ld a, b
- ld [wEnemyMonLevel], a
- pop bc
- ret
-
-; loads either red back pic or old man back pic
-; also writes OAM data and loads tile patterns for the Red or Old Man back sprite's head
-; (for use when scrolling the player sprite and enemy's silhouettes on screen)
-LoadPlayerBackPic:
- ld a, [wBattleType]
- dec a ; is it the old man tutorial?
- ld de, RedPicBack
- jr nz, .next
- ld de, OldManPic
-.next
- ld a, BANK(RedPicBack)
- call UncompressSpriteFromDE
- predef ScaleSpriteByTwo
- ld hl, wOAMBuffer
- xor a
- ld [hOAMTile], a ; initial tile number
- ld b, $7 ; 7 columns
- ld e, $a0 ; X for the left-most column
-.loop ; each loop iteration writes 3 OAM entries in a vertical column
- ld c, $3 ; 3 tiles per column
- ld d, $38 ; Y for the top of each column
-.innerLoop ; each loop iteration writes 1 OAM entry in the column
- ld [hl], d ; OAM Y
- inc hl
- ld [hl], e ; OAM X
- ld a, $8 ; height of tile
- add d ; increase Y by height of tile
- ld d, a
- inc hl
- ld a, [hOAMTile]
- ld [hli], a ; OAM tile number
- inc a ; increment tile number
- ld [hOAMTile], a
- inc hl
- dec c
- jr nz, .innerLoop
- ld a, [hOAMTile]
- add $4 ; increase tile number by 4
- ld [hOAMTile], a
- ld a, $8 ; width of tile
- add e ; increase X by width of tile
- ld e, a
- dec b
- jr nz, .loop
- ld de, vBackPic
- call InterlaceMergeSpriteBuffers
- ld a, $a
- ld [$0], a
- xor a
- ld [$4000], a
- ld hl, vSprites
- ld de, sSpriteBuffer1
- ld a, [H_LOADEDROMBANK]
- ld b, a
- ld c, 7 * 7
- call CopyVideoData
- xor a
- ld [$0], a
- ld a, $31
- ld [hStartTileID], a
- coord hl, 1, 5
- predef_jump CopyUncompressedPicToTilemap
-
-; does nothing since no stats are ever selected (barring glitches)
-DoubleOrHalveSelectedStats:
- callab DoubleSelectedStats
- jpab HalveSelectedStats
-
-ScrollTrainerPicAfterBattle:
- jpab _ScrollTrainerPicAfterBattle
-
-ApplyBurnAndParalysisPenaltiesToPlayer:
- ld a, $1
- jr ApplyBurnAndParalysisPenalties
-
-ApplyBurnAndParalysisPenaltiesToEnemy:
- xor a
-
-ApplyBurnAndParalysisPenalties:
- ld [H_WHOSETURN], a
- call QuarterSpeedDueToParalysis
- jp HalveAttackDueToBurn
-
-QuarterSpeedDueToParalysis:
- ld a, [H_WHOSETURN]
- and a
- jr z, .playerTurn
-.enemyTurn ; quarter the player's speed
- ld a, [wBattleMonStatus]
- and 1 << PAR
- ret z ; return if player not paralysed
- 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, .storePlayerSpeed
- ld b, 1 ; give the player a minimum of at least one speed point
-.storePlayerSpeed
- ld [hl], b
- ret
-.playerTurn ; quarter the enemy's speed
- ld a, [wEnemyMonStatus]
- and 1 << PAR
- ret z ; return if enemy not paralysed
- 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, .storeEnemySpeed
- ld b, 1 ; give the enemy a minimum of at least one speed point
-.storeEnemySpeed
- ld [hl], b
- ret
-
-HalveAttackDueToBurn:
- ld a, [H_WHOSETURN]
- and a
- jr z, .playerTurn
-.enemyTurn ; halve the player's attack
- ld a, [wBattleMonStatus]
- and 1 << BRN
- ret z ; return if player not burnt
- ld hl, wBattleMonAttack + 1
- ld a, [hld]
- ld b, a
- ld a, [hl]
- srl a
- rr b
- ld [hli], a
- or b
- jr nz, .storePlayerAttack
- ld b, 1 ; give the player a minimum of at least one attack point
-.storePlayerAttack
- ld [hl], b
- ret
-.playerTurn ; halve the enemy's attack
- ld a, [wEnemyMonStatus]
- and 1 << BRN
- ret z ; return if enemy not burnt
- ld hl, wEnemyMonAttack + 1
- ld a, [hld]
- ld b, a
- ld a, [hl]
- srl a
- rr b
- ld [hli], a
- or b
- jr nz, .storeEnemyAttack
- ld b, 1 ; give the enemy a minimum of at least one attack point
-.storeEnemyAttack
- ld [hl], b
- ret
-
-CalculateModifiedStats:
- ld c, 0
-.loop
- call CalculateModifiedStat
- inc c
- ld a, c
- cp NUM_STATS - 1
- jr nz, .loop
- ret
-
-; calculate modified stat for stat c (0 = attack, 1 = defense, 2 = speed, 3 = special)
-CalculateModifiedStat:
- push bc
- push bc
- ld a, [wCalculateWhoseStats]
- and a
- ld a, c
- ld hl, wBattleMonAttack
- ld de, wPlayerMonUnmodifiedAttack
- ld bc, wPlayerMonStatMods
- jr z, .next
- ld hl, wEnemyMonAttack
- ld de, wEnemyMonUnmodifiedAttack
- ld bc, wEnemyMonStatMods
-.next
- add c
- ld c, a
- jr nc, .noCarry1
- inc b
-.noCarry1
- 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, .noCarry2
- inc d
-.noCarry2
- pop bc
- push hl
- ld hl, StatModifierRatios
- dec b
- sla b
- ld c, b
- ld b, 0
- add hl, bc
- xor a
- ld [H_MULTIPLICAND], a
- ld a, [de]
- ld [H_MULTIPLICAND + 1], a
- inc de
- ld a, [de]
- ld [H_MULTIPLICAND + 2], a
- ld a, [hli]
- ld [H_MULTIPLIER], a
- call Multiply
- ld a, [hl]
- ld [H_DIVISOR], a
- ld b, $4
- call Divide
- pop hl
- ld a, [H_DIVIDEND + 3]
- sub 999 % $100
- ld a, [H_DIVIDEND + 2]
- sbc 999 / $100
- jp c, .storeNewStatValue
-; cap the stat at 999
- ld a, 999 / $100
- ld [H_DIVIDEND + 2], a
- ld a, 999 % $100
- ld [H_DIVIDEND + 3], a
-.storeNewStatValue
- ld a, [H_DIVIDEND + 2]
- ld [hli], a
- ld b, a
- ld a, [H_DIVIDEND + 3]
- ld [hl], a
- or b
- jr nz, .done
- inc [hl] ; if the stat is 0, bump it up to 1
-.done
- pop bc
- ret
-
-ApplyBadgeStatBoosts:
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ret z ; return if link battle
- ld a, [wObtainedBadges]
- ld b, a
- ld hl, wBattleMonAttack
- ld c, $4
-; the boost is applied for badges whose bit position is even
-; the order of boosts matches the order they are laid out in RAM
-; Boulder (bit 0) - attack
-; Thunder (bit 2) - defense
-; Soul (bit 4) - speed
-; Volcano (bit 6) - special
-.loop
- srl b
- call c, .applyBoostToStat
- inc hl
- inc hl
- srl b
- dec c
- jr nz, .loop
- ret
-
-; multiply stat at hl by 1.125
-; cap stat at 999
-.applyBoostToStat
- 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
- ld a, [hld]
- sub 999 % $100
- ld a, [hl]
- sbc 999 / $100
- ret c
- ld a, 999 / $100
- ld [hli], a
- ld a, 999 % $100
- ld [hld], a
- ret
-
-LoadHudAndHpBarAndStatusTilePatterns:
- call LoadHpBarAndStatusTilePatterns
-
-LoadHudTilePatterns:
- ld a, [rLCDC]
- add a ; is LCD disabled?
- jr c, .lcdEnabled
-.lcdDisabled
- ld hl, BattleHudTiles1
- ld de, vChars2 + $6d0
- ld bc, BattleHudTiles1End - BattleHudTiles1
- ld a, BANK(BattleHudTiles1)
- call FarCopyDataDouble
- ld hl, BattleHudTiles2
- ld de, vChars2 + $730
- ld bc, BattleHudTiles3End - BattleHudTiles2
- ld a, BANK(BattleHudTiles2)
- jp FarCopyDataDouble
-.lcdEnabled
- ld de, BattleHudTiles1
- ld hl, vChars2 + $6d0
- lb bc, BANK(BattleHudTiles1), (BattleHudTiles1End - BattleHudTiles1) / $8
- call CopyVideoDataDouble
- ld de, BattleHudTiles2
- ld hl, vChars2 + $730
- lb bc, BANK(BattleHudTiles2), (BattleHudTiles3End - BattleHudTiles2) / $8
- jp CopyVideoDataDouble
-
-PrintEmptyString:
- ld hl, .emptyString
- jp PrintText
-.emptyString
- db "@"
-
-
-BattleRandom:
-; Link battles use a shared PRNG.
-
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jp nz, Random
-
- push hl
- push bc
- ld a, [wLinkBattleRandomNumberListIndex]
- ld c, a
- ld b, 0
- ld hl, wLinkBattleRandomNumberList
- add hl, bc
- inc a
- ld [wLinkBattleRandomNumberListIndex], a
- cp 9
- ld a, [hl]
- pop bc
- pop hl
- ret c
-
-; if we picked the last seed, we need to recalculate the nine seeds
- push hl
- push bc
- push af
-
-; point to seed 0 so we pick the first number the next time
- xor a
- ld [wLinkBattleRandomNumberListIndex], a
-
- ld hl, wLinkBattleRandomNumberList
- ld b, 9
-.loop
- ld a, [hl]
- ld c, a
-; multiply by 5
- add a
- add a
- add c
-; add 1
- inc a
- ld [hli], a
- dec b
- jr nz, .loop
-
- pop af
- pop bc
- pop hl
- ret
-
-
-HandleExplodingAnimation:
- ld a, [H_WHOSETURN]
- and a
- ld hl, wEnemyMonType1
- ld de, wEnemyBattleStatus1
- ld a, [wPlayerMoveNum]
- jr z, .player
- ld hl, wBattleMonType1
- ld de, wEnemyBattleStatus1
- ld a, [wEnemyMoveNum]
-.player
- cp SELFDESTRUCT
- jr z, .isExplodingMove
- cp EXPLOSION
- ret nz
-.isExplodingMove
- ld a, [de]
- bit INVULNERABLE, a ; fly/dig
- ret nz
- ld a, [hli]
- cp GHOST
- ret z
- ld a, [hl]
- cp GHOST
- ret z
- ld a, [wMoveMissed]
- and a
- ret nz
- ld a, 5
- ld [wAnimationType], a
-
-PlayMoveAnimation:
- ld [wAnimationID], a
- call Delay3
- predef_jump MoveAnimation
-
-InitBattle:
- ld a, [wCurOpponent]
- and a
- jr z, DetermineWildOpponent
-
-InitOpponent:
- ld a, [wCurOpponent]
- ld [wcf91], a
- ld [wEnemyMonSpecies2], a
- jr InitBattleCommon
-
-DetermineWildOpponent:
- ld a, [wd732]
- bit 1, a
- jr z, .asm_3ef2f
- ld a, [hJoyHeld]
- bit 1, a ; B button pressed?
- ret nz
-.asm_3ef2f
- ld a, [wNumberOfNoRandomBattleStepsLeft]
- and a
- ret nz
- callab TryDoWildEncounter
- ret nz
-InitBattleCommon:
- ld a, [wMapPalOffset]
- push af
- ld hl, wLetterPrintingDelayFlags
- ld a, [hl]
- push af
- res 1, [hl]
- callab InitBattleVariables
- ld a, [wEnemyMonSpecies2]
- sub 200
- jp c, InitWildBattle
- ld [wTrainerClass], a
- call GetTrainerInformation
- callab ReadTrainer
- call DoBattleTransitionAndInitBattleVariables
- call _LoadTrainerPic
- xor a
- ld [wEnemyMonSpecies2], a
- ld [hStartTileID], a
- dec a
- ld [wAICount], a
- coord hl, 12, 0
- predef CopyUncompressedPicToTilemap
- ld a, $ff
- ld [wEnemyMonPartyPos], a
- ld a, $2
- ld [wIsInBattle], a
- jp _InitBattleCommon
-
-InitWildBattle:
- ld a, $1
- ld [wIsInBattle], a
- call LoadEnemyMonData
- call DoBattleTransitionAndInitBattleVariables
- ld a, [wCurOpponent]
- cp MAROWAK
- jr z, .isGhost
- call IsGhostBattle
- jr nz, .isNoGhost
-.isGhost
- ld hl, wMonHSpriteDim
- ld a, $66
- ld [hli], a ; write sprite dimensions
- ld bc, GhostPic
- ld a, c
- ld [hli], a ; write front sprite pointer
- ld [hl], b
- ld hl, wEnemyMonNick ; set name to "GHOST"
- ld a, "G"
- ld [hli], a
- ld a, "H"
- ld [hli], a
- ld a, "O"
- ld [hli], a
- ld a, "S"
- ld [hli], a
- ld a, "T"
- ld [hli], a
- ld [hl], "@"
- ld a, [wcf91]
- push af
- ld a, MON_GHOST
- ld [wcf91], a
- ld de, vFrontPic
- call LoadMonFrontSprite ; load ghost sprite
- pop af
- ld [wcf91], a
- jr .spriteLoaded
-.isNoGhost
- ld de, vFrontPic
- call LoadMonFrontSprite ; load mon sprite
-.spriteLoaded
- xor a
- ld [wTrainerClass], a
- ld [hStartTileID], a
- coord hl, 12, 0
- predef CopyUncompressedPicToTilemap
-
-; common code that executes after init battle code specific to trainer or wild battles
-_InitBattleCommon:
- ld b, SET_PAL_BATTLE_BLACK
- call RunPaletteCommand
- call SlidePlayerAndEnemySilhouettesOnScreen
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld hl, .emptyString
- call PrintText
- call SaveScreenTilesToBuffer1
- call ClearScreen
- ld a, $98
- ld [H_AUTOBGTRANSFERDEST + 1], a
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- ld a, $9c
- ld [H_AUTOBGTRANSFERDEST + 1], a
- call LoadScreenTilesFromBuffer1
- coord hl, 9, 7
- lb bc, 5, 10
- call ClearScreenArea
- coord hl, 1, 0
- lb bc, 4, 10
- call ClearScreenArea
- call ClearSprites
- ld a, [wIsInBattle]
- dec a ; is it a wild battle?
- call z, DrawEnemyHUDAndHPBar ; draw enemy HUD and HP bar if it's a wild battle
- call StartBattle
- callab EndOfBattle
- pop af
- ld [wLetterPrintingDelayFlags], a
- pop af
- ld [wMapPalOffset], a
- ld a, [wSavedTilesetType]
- ld [hTilesetType], a
- scf
- ret
-.emptyString
- db "@"
-
-_LoadTrainerPic:
-; wd033-wd034 contain pointer to pic
- ld a, [wTrainerPicPointer]
- ld e, a
- ld a, [wTrainerPicPointer + 1]
- ld d, a ; de contains pointer to trainer pic
- ld a, [wLinkState]
- and a
- ld a, Bank(TrainerPics) ; this is where all the trainer pics are (not counting Red's)
- jr z, .loadSprite
- ld a, Bank(RedPicFront)
-.loadSprite
- call UncompressSpriteFromDE
- ld de, vFrontPic
- ld a, $77
- ld c, a
- jp LoadUncompressedSpriteData
-
-; unreferenced
-ResetCryModifiers:
- xor a
- ld [wFrequencyModifier], a
- ld [wTempoModifier], a
- jp PlaySound
-
-; animates the mon "growing" out of the pokeball
-AnimateSendingOutMon:
- ld a, [wPredefRegisters]
- ld h, a
- ld a, [wPredefRegisters + 1]
- ld l, a
- ld a, [hStartTileID]
- ld [hBaseTileID], a
- ld b, $4c
- ld a, [wIsInBattle]
- and a
- jr z, .notInBattle
- add b
- ld [hl], a
- call Delay3
- ld bc, -(SCREEN_WIDTH * 2 + 1)
- add hl, bc
- ld a, 1
- ld [wDownscaledMonSize], a
- lb bc, 3, 3
- predef CopyDownscaledMonTiles
- ld c, 4
- call DelayFrames
- ld bc, -(SCREEN_WIDTH * 2 + 1)
- add hl, bc
- xor a
- ld [wDownscaledMonSize], a
- lb bc, 5, 5
- predef CopyDownscaledMonTiles
- ld c, 5
- call DelayFrames
- ld bc, -(SCREEN_WIDTH * 2 + 1)
- jr .next
-.notInBattle
- ld bc, -(SCREEN_WIDTH * 6 + 3)
-.next
- add hl, bc
- ld a, [hBaseTileID]
- add $31
- jr CopyUncompressedPicToHL
-
-CopyUncompressedPicToTilemap:
- ld a, [wPredefRegisters]
- ld h, a
- ld a, [wPredefRegisters + 1]
- ld l, a
- ld a, [hStartTileID]
-CopyUncompressedPicToHL:
- lb bc, 7, 7
- ld de, SCREEN_WIDTH
- push af
- ld a, [wSpriteFlipped]
- and a
- jr nz, .flipped
- pop af
-.loop
- push bc
- push hl
-.innerLoop
- ld [hl], a
- add hl, de
- inc a
- dec c
- jr nz, .innerLoop
- pop hl
- inc hl
- pop bc
- dec b
- jr nz, .loop
- ret
-
-.flipped
- push bc
- ld b, 0
- dec c
- add hl, bc
- pop bc
- pop af
-.flippedLoop
- push bc
- push hl
-.flippedInnerLoop
- ld [hl], a
- add hl, de
- inc a
- dec c
- jr nz, .flippedInnerLoop
- pop hl
- dec hl
- pop bc
- dec b
- jr nz, .flippedLoop
- ret
-
-LoadMonBackPic:
-; Assumes the monster's attributes have
-; been loaded with GetMonHeader.
- ld a, [wBattleMonSpecies2]
- ld [wcf91], a
- coord hl, 1, 5
- ld b, 7
- ld c, 8
- call ClearScreenArea
- ld hl, wMonHBackSprite - wMonHeader
- call UncompressMonSprite
- predef ScaleSpriteByTwo
- ld de, vBackPic
- call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite
- ld hl, vSprites
- ld de, vBackPic
- ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied
- ld a, [H_LOADEDROMBANK]
- ld b, a
- jp CopyVideoData
-
-JumpMoveEffect:
- call _JumpMoveEffect
- ld b, $1
- ret
-
-_JumpMoveEffect:
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveEffect]
- jr z, .next1
- ld a, [wEnemyMoveEffect]
-.next1
- dec a ; subtract 1, there is no special effect for 00
- add a ; x2, 16bit pointers
- ld hl, MoveEffectPointerTable
- ld b, 0
- ld c, a
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- jp hl ; jump to special effect handler
-
-MoveEffectPointerTable:
- dw SleepEffect ; unused effect
- dw PoisonEffect ; POISON_SIDE_EFFECT1
- dw DrainHPEffect ; DRAIN_HP_EFFECT
- dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT1
- dw FreezeBurnParalyzeEffect ; FREEZE_SIDE_EFFECT
- dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT1
- dw ExplodeEffect ; EXPLODE_EFFECT
- dw DrainHPEffect ; DREAM_EATER_EFFECT
- dw $0000 ; MIRROR_MOVE_EFFECT
- dw StatModifierUpEffect ; ATTACK_UP1_EFFECT
- dw StatModifierUpEffect ; DEFENSE_UP1_EFFECT
- dw StatModifierUpEffect ; SPEED_UP1_EFFECT
- dw StatModifierUpEffect ; SPECIAL_UP1_EFFECT
- dw StatModifierUpEffect ; ACCURACY_UP1_EFFECT
- dw StatModifierUpEffect ; EVASION_UP1_EFFECT
- dw PayDayEffect ; PAY_DAY_EFFECT
- dw $0000 ; SWIFT_EFFECT
- dw StatModifierDownEffect ; ATTACK_DOWN1_EFFECT
- dw StatModifierDownEffect ; DEFENSE_DOWN1_EFFECT
- dw StatModifierDownEffect ; SPEED_DOWN1_EFFECT
- dw StatModifierDownEffect ; SPECIAL_DOWN1_EFFECT
- dw StatModifierDownEffect ; ACCURACY_DOWN1_EFFECT
- dw StatModifierDownEffect ; EVASION_DOWN1_EFFECT
- dw ConversionEffect ; CONVERSION_EFFECT
- dw HazeEffect ; HAZE_EFFECT
- dw BideEffect ; BIDE_EFFECT
- dw ThrashPetalDanceEffect ; THRASH_PETAL_DANCE_EFFECT
- dw SwitchAndTeleportEffect ; SWITCH_AND_TELEPORT_EFFECT
- dw TwoToFiveAttacksEffect ; TWO_TO_FIVE_ATTACKS_EFFECT
- dw TwoToFiveAttacksEffect ; unused effect
- dw FlinchSideEffect ; FLINCH_SIDE_EFFECT1
- dw SleepEffect ; SLEEP_EFFECT
- dw PoisonEffect ; POISON_SIDE_EFFECT2
- dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT2
- dw FreezeBurnParalyzeEffect ; unused effect
- dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT2
- dw FlinchSideEffect ; FLINCH_SIDE_EFFECT2
- dw OneHitKOEffect ; OHKO_EFFECT
- dw ChargeEffect ; CHARGE_EFFECT
- dw $0000 ; SUPER_FANG_EFFECT
- dw $0000 ; SPECIAL_DAMAGE_EFFECT
- dw TrappingEffect ; TRAPPING_EFFECT
- dw ChargeEffect ; FLY_EFFECT
- dw TwoToFiveAttacksEffect ; ATTACK_TWICE_EFFECT
- dw $0000 ; JUMP_KICK_EFFECT
- dw MistEffect ; MIST_EFFECT
- dw FocusEnergyEffect ; FOCUS_ENERGY_EFFECT
- dw RecoilEffect ; RECOIL_EFFECT
- dw ConfusionEffect ; CONFUSION_EFFECT
- dw StatModifierUpEffect ; ATTACK_UP2_EFFECT
- dw StatModifierUpEffect ; DEFENSE_UP2_EFFECT
- dw StatModifierUpEffect ; SPEED_UP2_EFFECT
- dw StatModifierUpEffect ; SPECIAL_UP2_EFFECT
- dw StatModifierUpEffect ; ACCURACY_UP2_EFFECT
- dw StatModifierUpEffect ; EVASION_UP2_EFFECT
- dw HealEffect ; HEAL_EFFECT
- dw TransformEffect ; TRANSFORM_EFFECT
- dw StatModifierDownEffect ; ATTACK_DOWN2_EFFECT
- dw StatModifierDownEffect ; DEFENSE_DOWN2_EFFECT
- dw StatModifierDownEffect ; SPEED_DOWN2_EFFECT
- dw StatModifierDownEffect ; SPECIAL_DOWN2_EFFECT
- dw StatModifierDownEffect ; ACCURACY_DOWN2_EFFECT
- dw StatModifierDownEffect ; EVASION_DOWN2_EFFECT
- dw ReflectLightScreenEffect ; LIGHT_SCREEN_EFFECT
- dw ReflectLightScreenEffect ; REFLECT_EFFECT
- dw PoisonEffect ; POISON_EFFECT
- dw ParalyzeEffect ; PARALYZE_EFFECT
- dw StatModifierDownEffect ; ATTACK_DOWN_SIDE_EFFECT
- dw StatModifierDownEffect ; DEFENSE_DOWN_SIDE_EFFECT
- dw StatModifierDownEffect ; SPEED_DOWN_SIDE_EFFECT
- dw StatModifierDownEffect ; SPECIAL_DOWN_SIDE_EFFECT
- dw StatModifierDownEffect ; unused effect
- dw StatModifierDownEffect ; unused effect
- dw StatModifierDownEffect ; unused effect
- dw StatModifierDownEffect ; unused effect
- dw ConfusionSideEffect ; CONFUSION_SIDE_EFFECT
- dw TwoToFiveAttacksEffect ; TWINEEDLE_EFFECT
- dw $0000 ; unused effect
- dw SubstituteEffect ; SUBSTITUTE_EFFECT
- dw HyperBeamEffect ; HYPER_BEAM_EFFECT
- dw RageEffect ; RAGE_EFFECT
- dw MimicEffect ; MIMIC_EFFECT
- dw $0000 ; METRONOME_EFFECT
- dw LeechSeedEffect ; LEECH_SEED_EFFECT
- dw SplashEffect ; SPLASH_EFFECT
- dw DisableEffect ; DISABLE_EFFECT
-
-SleepEffect:
- ld de, wEnemyMonStatus
- ld bc, wEnemyBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jp z, .sleepEffect
- ld de, wBattleMonStatus
- ld bc, wPlayerBattleStatus2
-
-.sleepEffect
- ld a, [bc]
- bit NEEDS_TO_RECHARGE, a ; does the target need to recharge? (hyper beam)
- res NEEDS_TO_RECHARGE, a ; target no longer needs to recharge
- ld [bc], a
- jr nz, .setSleepCounter ; if the target had to recharge, all hit tests will be skipped
- ; including the event where the target already has another status
- ld a, [de]
- ld b, a
- and $7
- jr z, .notAlreadySleeping ; can't affect a mon that is already asleep
- ld hl, AlreadyAsleepText
- jp PrintText
-.notAlreadySleeping
- ld a, b
- and a
- jr nz, .didntAffect ; can't affect a mon that is already statused
- push de
- call MoveHitTest ; apply accuracy tests
- pop de
- ld a, [wMoveMissed]
- and a
- jr nz, .didntAffect
-.setSleepCounter
-; set target's sleep counter to a random number between 1 and 7
- call BattleRandom
- and $7
- jr z, .setSleepCounter
- ld [de], a
- call PlayCurrentMoveAnimation2
- ld hl, FellAsleepText
- jp PrintText
-.didntAffect
- jp PrintDidntAffectText
-
-FellAsleepText:
- TX_FAR _FellAsleepText
- db "@"
-
-AlreadyAsleepText:
- TX_FAR _AlreadyAsleepText
- db "@"
-
-PoisonEffect:
- ld hl, wEnemyMonStatus
- ld de, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- jr z, .poisonEffect
- ld hl, wBattleMonStatus
- ld de, wEnemyMoveEffect
-.poisonEffect
- call CheckTargetSubstitute
- jr nz, .noEffect ; can't poison a substitute target
- ld a, [hli]
- ld b, a
- and a
- jr nz, .noEffect ; miss if target is already statused
- ld a, [hli]
- cp POISON ; can't poison a poison-type target
- jr z, .noEffect
- ld a, [hld]
- cp POISON ; can't poison a poison-type target
- jr z, .noEffect
- ld a, [de]
- cp POISON_SIDE_EFFECT1
- ld b, $34 ; ~20% chance of poisoning
- jr z, .sideEffectTest
- cp POISON_SIDE_EFFECT2
- ld b, $67 ; ~40% chance of poisoning
- jr z, .sideEffectTest
- push hl
- push de
- call MoveHitTest ; apply accuracy tests
- pop de
- pop hl
- ld a, [wMoveMissed]
- and a
- jr nz, .didntAffect
- jr .inflictPoison
-.sideEffectTest
- call BattleRandom
- cp b ; was side effect successful?
- ret nc
-.inflictPoison
- dec hl
- set 3, [hl] ; mon is now poisoned
- push de
- dec de
- ld a, [H_WHOSETURN]
- and a
- ld b, ANIM_C7
- ld hl, wPlayerBattleStatus3
- ld a, [de]
- ld de, wPlayerToxicCounter
- jr nz, .ok
- ld b, ANIM_A9
- ld hl, wEnemyBattleStatus3
- ld de, wEnemyToxicCounter
-.ok
- cp TOXIC
- jr nz, .normalPoison ; done if move is not Toxic
- set BADLY_POISONED, [hl] ; else set Toxic battstatus
- xor a
- ld [de], a
- ld hl, BadlyPoisonedText
- jr .continue
-.normalPoison
- ld hl, PoisonedText
-.continue
- pop de
- ld a, [de]
- cp POISON_EFFECT
- jr z, .regularPoisonEffect
- ld a, b
- call PlayBattleAnimation2
- jp PrintText
-.regularPoisonEffect
- call PlayCurrentMoveAnimation2
- jp PrintText
-.noEffect
- ld a, [de]
- cp POISON_EFFECT
- ret nz
-.didntAffect
- ld c, 50
- call DelayFrames
- jp PrintDidntAffectText
-
-PoisonedText:
- TX_FAR _PoisonedText
- db "@"
-
-BadlyPoisonedText:
- TX_FAR _BadlyPoisonedText
- db "@"
-
-DrainHPEffect:
- jpab DrainHPEffect_
-
-ExplodeEffect:
- ld hl, wBattleMonHP
- ld de, wPlayerBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .faintUser
- ld hl, wEnemyMonHP
- ld de, wEnemyBattleStatus2
-.faintUser
- xor a
- ld [hli], a ; set the mon's HP to 0
- ld [hli], a
- inc hl
- ld [hl], a ; set mon's status to 0
- ld a, [de]
- res SEEDED, a ; clear mon's leech seed status
- ld [de], a
- ret
-
-FreezeBurnParalyzeEffect:
- xor a
- ld [wAnimationType], a
- call CheckTargetSubstitute ; test bit 4 of d063/d068 flags [target has substitute flag]
- ret nz ; return if they have a substitute, can't effect them
- ld a, [H_WHOSETURN]
- and a
- jp nz, opponentAttacker
- ld a, [wEnemyMonStatus]
- and a
- jp nz, CheckDefrost ; can't inflict status if opponent is already statused
- ld a, [wPlayerMoveType]
- ld b, a
- ld a, [wEnemyMonType1]
- cp b ; do target type 1 and move type match?
- ret z ; return if they match (an ice move can't freeze an ice-type, body slam can't paralyze a normal-type, etc.)
- ld a, [wEnemyMonType2]
- cp b ; do target type 2 and move type match?
- ret z ; return if they match
- ld a, [wPlayerMoveEffect]
- cp PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those
- ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance
- jr c, .next1 ; branch ahead if this is a 10% chance effect..
- ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance
- sub $1e ; subtract $1E to map to equivalent 10% chance effects
-.next1
- push af
- call BattleRandom ; get random 8bit value for probability test
- cp b
- pop bc
- ret nc ; do nothing if random value is >= 1A or 4D [no status applied]
- ld a, b ; what type of effect is this?
- cp BURN_SIDE_EFFECT1
- jr z, .burn
- cp FREEZE_SIDE_EFFECT
- jr z, .freeze
-; .paralyze
- ld a, 1 << PAR
- ld [wEnemyMonStatus], a
- call QuarterSpeedDueToParalysis ; quarter speed of affected mon
- ld a, ANIM_A9
- call PlayBattleAnimation
- jp PrintMayNotAttackText ; print paralysis text
-.burn
- ld a, 1 << BRN
- ld [wEnemyMonStatus], a
- call HalveAttackDueToBurn ; halve attack of affected mon
- ld a, ANIM_A9
- call PlayBattleAnimation
- ld hl, BurnedText
- jp PrintText
-.freeze
- call ClearHyperBeam ; resets hyper beam (recharge) condition from target
- ld a, 1 << FRZ
- ld [wEnemyMonStatus], a
- ld a, ANIM_A9
- call PlayBattleAnimation
- ld hl, FrozenText
- jp PrintText
-opponentAttacker:
- ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent
- and a
- jp nz, CheckDefrost
- ld a, [wEnemyMoveType]
- ld b, a
- ld a, [wBattleMonType1]
- cp b
- ret z
- ld a, [wBattleMonType2]
- cp b
- ret z
- ld a, [wEnemyMoveEffect]
- cp PARALYZE_SIDE_EFFECT1 + 1
- ld b, $1a
- jr c, .next1
- ld b, $4d
- sub $1e
-.next1
- push af
- call BattleRandom
- cp b
- pop bc
- ret nc
- ld a, b
- cp BURN_SIDE_EFFECT1
- jr z, .burn
- cp FREEZE_SIDE_EFFECT
- jr z, .freeze
- ld a, 1 << PAR
- ld [wBattleMonStatus], a
- call QuarterSpeedDueToParalysis
- jp PrintMayNotAttackText
-.burn
- ld a, 1 << BRN
- ld [wBattleMonStatus], a
- call HalveAttackDueToBurn
- ld hl, BurnedText
- jp PrintText
-.freeze
-; hyper beam bits aren't reseted for opponent's side
- ld a, 1 << FRZ
- ld [wBattleMonStatus], a
- ld hl, FrozenText
- jp PrintText
-
-BurnedText:
- TX_FAR _BurnedText
- db "@"
-
-FrozenText:
- TX_FAR _FrozenText
- db "@"
-
-CheckDefrost:
-; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target
- and 1 << FRZ ; are they frozen?
- ret z ; return if so
- ld a, [H_WHOSETURN]
- and a
- jr nz, .opponent
- ;player [attacker]
- ld a, [wPlayerMoveType]
- sub FIRE
- ret nz ; return if type of move used isn't fire
- ld [wEnemyMonStatus], a ; set opponent status to 00 ["defrost" a frozen monster]
- ld hl, wEnemyMon1Status
- ld a, [wEnemyMonPartyPos]
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- xor a
- ld [hl], a ; clear status in roster
- ld hl, FireDefrostedText
- jr .common
-.opponent
- ld a, [wEnemyMoveType] ; same as above with addresses swapped
- sub FIRE
- ret nz
- ld [wBattleMonStatus], a
- ld hl, wPartyMon1Status
- ld a, [wPlayerMonNumber]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- xor a
- ld [hl], a
- ld hl, FireDefrostedText
-.common
- jp PrintText
-
-FireDefrostedText:
- TX_FAR _FireDefrostedText
- db "@"
-
-StatModifierUpEffect:
- ld hl, wPlayerMonStatMods
- ld de, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- jr z, .statModifierUpEffect
- ld hl, wEnemyMonStatMods
- ld de, wEnemyMoveEffect
-.statModifierUpEffect
- ld a, [de]
- sub ATTACK_UP1_EFFECT
- cp EVASION_UP1_EFFECT + $3 - ATTACK_UP1_EFFECT ; covers all +1 effects
- jr c, .incrementStatMod
- sub ATTACK_UP2_EFFECT - ATTACK_UP1_EFFECT ; map +2 effects to equivalent +1 effect
-.incrementStatMod
- ld c, a
- ld b, $0
- add hl, bc
- ld b, [hl]
- inc b ; increment corresponding stat mod
- ld a, $d
- cp b ; can't raise stat past +6 ($d or 13)
- jp c, PrintNothingHappenedText
- ld a, [de]
- cp ATTACK_UP1_EFFECT + $8 ; is it a +2 effect?
- jr c, .ok
- inc b ; if so, increment stat mod again
- ld a, $d
- cp b ; unless it's already +6
- jr nc, .ok
- ld b, a
-.ok
- ld [hl], b
- ld a, c
- cp $4
- jr nc, UpdateStatDone ; jump if mod affected is evasion/accuracy
- push hl
- ld hl, wBattleMonAttack + 1
- ld de, wPlayerMonUnmodifiedAttack
- ld a, [H_WHOSETURN]
- and a
- jr z, .pointToStats
- ld hl, wEnemyMonAttack + 1
- ld de, wEnemyMonUnmodifiedAttack
-.pointToStats
- push bc
- sla c
- ld b, $0
- add hl, bc ; hl = modified stat
- ld a, c
- add e
- ld e, a
- jr nc, .checkIf999
- inc d ; de = unmodified (original) stat
-.checkIf999
- pop bc
- ld a, [hld]
- sub 999 % $100 ; check if stat is already 999
- jr nz, .recalculateStat
- ld a, [hl]
- sbc 999 / $100
- jp z, RestoreOriginalStatModifier
-.recalculateStat ; recalculate affected stat
- ; paralysis and burn penalties, as well as badge boosts are ignored
- push hl
- push bc
- ld hl, StatModifierRatios
- dec b
- sla b
- ld c, b
- ld b, $0
- add hl, bc
- pop bc
- xor a
- ld [H_MULTIPLICAND], a
- ld a, [de]
- ld [H_MULTIPLICAND + 1], a
- inc de
- ld a, [de]
- ld [H_MULTIPLICAND + 2], a
- ld a, [hli]
- ld [H_MULTIPLIER], a
- call Multiply
- ld a, [hl]
- ld [H_DIVISOR], a
- ld b, $4
- call Divide
- pop hl
-; cap at 999
- ld a, [H_PRODUCT + 3]
- sub 999 % $100
- ld a, [H_PRODUCT + 2]
- sbc 999 / $100
- jp c, UpdateStat
- ld a, 999 / $100
- ld [H_MULTIPLICAND + 1], a
- ld a, 999 % $100
- ld [H_MULTIPLICAND + 2], a
-
-UpdateStat:
- ld a, [H_PRODUCT + 2]
- ld [hli], a
- ld a, [H_PRODUCT + 3]
- ld [hl], a
- pop hl
-UpdateStatDone:
- ld b, c
- inc b
- call PrintStatText
- ld hl, wPlayerBattleStatus2
- ld de, wPlayerMoveNum
- ld bc, wPlayerMonMinimized
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3f4e6
- ld hl, wEnemyBattleStatus2
- ld de, wEnemyMoveNum
- ld bc, wEnemyMonMinimized
-.asm_3f4e6
- ld a, [de]
- cp MINIMIZE
- jr nz, .asm_3f4f9
- ; if a substitute is up, slide off the substitute and show the mon pic before
- ; playing the minimize animation
- bit HAS_SUBSTITUTE_UP, [hl]
- push af
- push bc
- ld hl, HideSubstituteShowMonAnim
- ld b, BANK(HideSubstituteShowMonAnim)
- push de
- call nz, Bankswitch
- pop de
-.asm_3f4f9
- call PlayCurrentMoveAnimation
- ld a, [de]
- cp MINIMIZE
- jr nz, .applyBadgeBoostsAndStatusPenalties
- pop bc
- ld a, $1
- ld [bc], a
- ld hl, ReshowSubstituteAnim
- ld b, BANK(ReshowSubstituteAnim)
- pop af
- call nz, Bankswitch
-.applyBadgeBoostsAndStatusPenalties
- ld a, [H_WHOSETURN]
- and a
- call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat,
- ; even to those not affected by the stat-up move (will be boosted further)
- ld hl, MonsStatsRoseText
- call PrintText
-
-; these shouldn't be here
- call QuarterSpeedDueToParalysis ; apply speed penalty to the player whose turn is not, if it's paralyzed
- jp HalveAttackDueToBurn ; apply attack penalty to the player whose turn is not, if it's burned
-
-RestoreOriginalStatModifier:
- pop hl
- dec [hl]
-
-PrintNothingHappenedText:
- ld hl, NothingHappenedText
- jp PrintText
-
-MonsStatsRoseText:
- TX_FAR _MonsStatsRoseText
- TX_ASM
- ld hl, GreatlyRoseText
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveEffect]
- jr z, .playerTurn
- ld a, [wEnemyMoveEffect]
-.playerTurn
- cp ATTACK_DOWN1_EFFECT
- ret nc
- ld hl, RoseText
- ret
-
-GreatlyRoseText:
- TX_DELAY
- TX_FAR _GreatlyRoseText
-; fallthrough
-RoseText:
- TX_FAR _RoseText
- db "@"
-
-StatModifierDownEffect:
- ld hl, wEnemyMonStatMods
- ld de, wPlayerMoveEffect
- ld bc, wEnemyBattleStatus1
- ld a, [H_WHOSETURN]
- and a
- jr z, .statModifierDownEffect
- ld hl, wPlayerMonStatMods
- ld de, wEnemyMoveEffect
- ld bc, wPlayerBattleStatus1
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr z, .statModifierDownEffect
- call BattleRandom
- cp $40 ; 1/4 chance to miss by in regular battle
- jp c, MoveMissed
-.statModifierDownEffect
- call CheckTargetSubstitute ; can't hit through substitute
- jp nz, MoveMissed
- ld a, [de]
- cp ATTACK_DOWN_SIDE_EFFECT
- jr c, .nonSideEffect
- call BattleRandom
- cp $55 ; 85/256 chance for side effects
- jp nc, CantLowerAnymore
- ld a, [de]
- sub ATTACK_DOWN_SIDE_EFFECT ; map each stat to 0-3
- jr .decrementStatMod
-.nonSideEffect ; non-side effects only
- push hl
- push de
- push bc
- call MoveHitTest ; apply accuracy tests
- pop bc
- pop de
- pop hl
- ld a, [wMoveMissed]
- and a
- jp nz, MoveMissed
- ld a, [bc]
- bit INVULNERABLE, a ; fly/dig
- jp nz, MoveMissed
- ld a, [de]
- sub ATTACK_DOWN1_EFFECT
- cp EVASION_DOWN1_EFFECT + $3 - ATTACK_DOWN1_EFFECT ; covers all -1 effects
- jr c, .decrementStatMod
- sub ATTACK_DOWN2_EFFECT - ATTACK_DOWN1_EFFECT ; map -2 effects to corresponding -1 effect
-.decrementStatMod
- ld c, a
- ld b, $0
- add hl, bc
- ld b, [hl]
- dec b ; dec corresponding stat mod
- jp z, CantLowerAnymore ; if stat mod is 1 (-6), can't lower anymore
- ld a, [de]
- cp ATTACK_DOWN2_EFFECT - $16 ; $24
- jr c, .ok
- cp EVASION_DOWN2_EFFECT + $5 ; $44
- jr nc, .ok
- dec b ; stat down 2 effects only (dec mod again)
- jr nz, .ok
- inc b ; increment mod to 1 (-6) if it would become 0 (-7)
-.ok
- ld [hl], b ; save modified mod
- ld a, c
- cp $4
- jr nc, UpdateLoweredStatDone ; jump for evasion/accuracy
- push hl
- push de
- ld hl, wEnemyMonAttack + 1
- ld de, wEnemyMonUnmodifiedAttack
- ld a, [H_WHOSETURN]
- and a
- jr z, .pointToStat
- ld hl, wBattleMonAttack + 1
- ld de, wPlayerMonUnmodifiedAttack
-.pointToStat
- push bc
- sla c
- ld b, $0
- add hl, bc ; hl = modified stat
- ld a, c
- add e
- ld e, a
- jr nc, .noCarry
- inc d ; de = unmodified stat
-.noCarry
- pop bc
- ld a, [hld]
- sub $1 ; can't lower stat below 1 (-6)
- jr nz, .recalculateStat
- ld a, [hl]
- and a
- jp z, CantLowerAnymore_Pop
-.recalculateStat
-; recalculate affected stat
-; paralysis and burn penalties, as well as badge boosts are ignored
- push hl
- push bc
- ld hl, StatModifierRatios
- dec b
- sla b
- ld c, b
- ld b, $0
- add hl, bc
- pop bc
- xor a
- ld [H_MULTIPLICAND], a
- ld a, [de]
- ld [H_MULTIPLICAND + 1], a
- inc de
- ld a, [de]
- ld [H_MULTIPLICAND + 2], a
- ld a, [hli]
- ld [H_MULTIPLIER], a
- call Multiply
- ld a, [hl]
- ld [H_DIVISOR], a
- ld b, $4
- call Divide
- pop hl
- ld a, [H_PRODUCT + 3]
- ld b, a
- ld a, [H_PRODUCT + 2]
- or b
- jp nz, UpdateLoweredStat
- ld [H_MULTIPLICAND + 1], a
- ld a, $1
- ld [H_MULTIPLICAND + 2], a
-
-UpdateLoweredStat:
- ld a, [H_PRODUCT + 2]
- ld [hli], a
- ld a, [H_PRODUCT + 3]
- ld [hl], a
- pop de
- pop hl
-UpdateLoweredStatDone:
- ld b, c
- inc b
- push de
- call PrintStatText
- pop de
- ld a, [de]
- cp $44
- jr nc, .ApplyBadgeBoostsAndStatusPenalties
- call PlayCurrentMoveAnimation2
-.ApplyBadgeBoostsAndStatusPenalties
- ld a, [H_WHOSETURN]
- and a
- call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat,
- ; even to those not affected by the stat-up move (will be boosted further)
- ld hl, MonsStatsFellText
- call PrintText
-
-; These where probably added given that a stat-down move affecting speed or attack will override
-; the stat penalties from paralysis and burn respectively.
-; But they are always called regardless of the stat affected by the stat-down move.
- call QuarterSpeedDueToParalysis
- jp HalveAttackDueToBurn
-
-CantLowerAnymore_Pop:
- pop de
- pop hl
- inc [hl]
-
-CantLowerAnymore:
- ld a, [de]
- cp ATTACK_DOWN_SIDE_EFFECT
- ret nc
- ld hl, NothingHappenedText
- jp PrintText
-
-MoveMissed:
- ld a, [de]
- cp $44
- ret nc
- jp ConditionalPrintButItFailed
-
-MonsStatsFellText:
- TX_FAR _MonsStatsFellText
- TX_ASM
- ld hl, FellText
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveEffect]
- jr z, .playerTurn
- ld a, [wEnemyMoveEffect]
-.playerTurn
-; check if the move's effect decreases a stat by 2
- cp BIDE_EFFECT
- ret c
- cp ATTACK_DOWN_SIDE_EFFECT
- ret nc
- ld hl, GreatlyFellText
- ret
-
-GreatlyFellText:
- TX_DELAY
- TX_FAR _GreatlyFellText
-; fallthrough
-FellText:
- TX_FAR _FellText
- db "@"
-
-PrintStatText:
- ld hl, StatsTextStrings
- ld c, "@"
-.findStatName_outer
- dec b
- jr z, .foundStatName
-.findStatName_inner
- ld a, [hli]
- cp c
- jr z, .findStatName_outer
- jr .findStatName_inner
-.foundStatName
- ld de, wcf4b
- ld bc, $a
- jp CopyData
-
-StatsTextStrings:
- db "ATTACK@"
- db "DEFENSE@"
- db "SPEED@"
- db "SPECIAL@"
- db "ACCURACY@"
- db "EVADE@"
-
-StatModifierRatios:
-; first byte is numerator, second byte is denominator
- db 25, 100 ; 0.25
- db 28, 100 ; 0.28
- db 33, 100 ; 0.33
- db 40, 100 ; 0.40
- db 50, 100 ; 0.50
- db 66, 100 ; 0.66
- db 1, 1 ; 1.00
- db 15, 10 ; 1.50
- db 2, 1 ; 2.00
- db 25, 10 ; 2.50
- db 3, 1 ; 3.00
- db 35, 10 ; 3.50
- db 4, 1 ; 4.00
-
-BideEffect:
- ld hl, wPlayerBattleStatus1
- ld de, wPlayerBideAccumulatedDamage
- ld bc, wPlayerNumAttacksLeft
- ld a, [H_WHOSETURN]
- and a
- jr z, .bideEffect
- ld hl, wEnemyBattleStatus1
- ld de, wEnemyBideAccumulatedDamage
- ld bc, wEnemyNumAttacksLeft
-.bideEffect
- set STORING_ENERGY, [hl] ; mon is now using bide
- xor a
- ld [de], a
- inc de
- ld [de], a
- ld [wPlayerMoveEffect], a
- ld [wEnemyMoveEffect], a
- call BattleRandom
- and $1
- inc a
- inc a
- ld [bc], a ; set Bide counter to 2 or 3 at random
- ld a, [H_WHOSETURN]
- add XSTATITEM_ANIM
- jp PlayBattleAnimation2
-
-ThrashPetalDanceEffect:
- ld hl, wPlayerBattleStatus1
- ld de, wPlayerNumAttacksLeft
- ld a, [H_WHOSETURN]
- and a
- jr z, .thrashPetalDanceEffect
- ld hl, wEnemyBattleStatus1
- ld de, wEnemyNumAttacksLeft
-.thrashPetalDanceEffect
- set THRASHING_ABOUT, [hl] ; mon is now using thrash/petal dance
- call BattleRandom
- and $1
- inc a
- inc a
- ld [de], a ; set thrash/petal dance counter to 2 or 3 at random
- ld a, [H_WHOSETURN]
- add ANIM_B0
- jp PlayBattleAnimation2
-
-SwitchAndTeleportEffect:
- ld a, [H_WHOSETURN]
- and a
- jr nz, .handleEnemy
- ld a, [wIsInBattle]
- dec a
- jr nz, .notWildBattle1
- ld a, [wCurEnemyLVL]
- ld b, a
- ld a, [wBattleMonLevel]
- cp b ; is the player's level greater than the enemy's level?
- jr nc, .playerMoveWasSuccessful ; if so, teleport will always succeed
- add b
- ld c, a
- inc c ; c = sum of player level and enemy level
-.rejectionSampleLoop1
- call BattleRandom
- cp c ; get a random number between 0 and c
- jr nc, .rejectionSampleLoop1
- srl b
- srl b ; b = enemyLevel / 4
- cp b ; is rand[0, playerLevel + enemyLevel) >= (enemyLevel / 4)?
- jr nc, .playerMoveWasSuccessful ; if so, allow teleporting
- ld c, 50
- call DelayFrames
- ld a, [wPlayerMoveNum]
- cp TELEPORT
- jp nz, PrintDidntAffectText
- jp PrintButItFailedText_
-.playerMoveWasSuccessful
- call ReadPlayerMonCurHPAndStatus
- xor a
- ld [wAnimationType], a
- inc a
- ld [wEscapedFromBattle], a
- ld a, [wPlayerMoveNum]
- jr .playAnimAndPrintText
-.notWildBattle1
- ld c, 50
- call DelayFrames
- ld hl, IsUnaffectedText
- ld a, [wPlayerMoveNum]
- cp TELEPORT
- jp nz, PrintText
- jp PrintButItFailedText_
-.handleEnemy
- ld a, [wIsInBattle]
- dec a
- jr nz, .notWildBattle2
- ld a, [wBattleMonLevel]
- ld b, a
- ld a, [wCurEnemyLVL]
- cp b
- jr nc, .enemyMoveWasSuccessful
- add b
- ld c, a
- inc c
-.rejectionSampleLoop2
- call BattleRandom
- cp c
- jr nc, .rejectionSampleLoop2
- srl b
- srl b
- cp b
- jr nc, .enemyMoveWasSuccessful
- ld c, 50
- call DelayFrames
- ld a, [wEnemyMoveNum]
- cp TELEPORT
- jp nz, PrintDidntAffectText
- jp PrintButItFailedText_
-.enemyMoveWasSuccessful
- call ReadPlayerMonCurHPAndStatus
- xor a
- ld [wAnimationType], a
- inc a
- ld [wEscapedFromBattle], a
- ld a, [wEnemyMoveNum]
- jr .playAnimAndPrintText
-.notWildBattle2
- ld c, 50
- call DelayFrames
- ld hl, IsUnaffectedText
- ld a, [wEnemyMoveNum]
- cp TELEPORT
- jp nz, PrintText
- jp ConditionalPrintButItFailed
-.playAnimAndPrintText
- push af
- call PlayBattleAnimation
- ld c, 20
- call DelayFrames
- pop af
- ld hl, RanFromBattleText
- cp TELEPORT
- jr z, .printText
- ld hl, RanAwayScaredText
- cp ROAR
- jr z, .printText
- ld hl, WasBlownAwayText
-.printText
- jp PrintText
-
-RanFromBattleText:
- TX_FAR _RanFromBattleText
- db "@"
-
-RanAwayScaredText:
- TX_FAR _RanAwayScaredText
- db "@"
-
-WasBlownAwayText:
- TX_FAR _WasBlownAwayText
- db "@"
-
-TwoToFiveAttacksEffect:
- ld hl, wPlayerBattleStatus1
- ld de, wPlayerNumAttacksLeft
- ld bc, wPlayerNumHits
- ld a, [H_WHOSETURN]
- and a
- jr z, .twoToFiveAttacksEffect
- ld hl, wEnemyBattleStatus1
- ld de, wEnemyNumAttacksLeft
- ld bc, wEnemyNumHits
-.twoToFiveAttacksEffect
- bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon attacking multiple times?
- ret nz
- set ATTACKING_MULTIPLE_TIMES, [hl] ; mon is now attacking multiple times
- ld hl, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- jr z, .setNumberOfHits
- ld hl, wEnemyMoveEffect
-.setNumberOfHits
- ld a, [hl]
- cp TWINEEDLE_EFFECT
- jr z, .twineedle
- cp ATTACK_TWICE_EFFECT
- ld a, $2 ; number of hits it's always 2 for ATTACK_TWICE_EFFECT
- jr z, .saveNumberOfHits
-; for TWO_TO_FIVE_ATTACKS_EFFECT 3/8 chance for 2 and 3 hits, and 1/8 chance for 4 and 5 hits
- call BattleRandom
- and $3
- cp $2
- jr c, .gotNumHits
-; if the number of hits was greater than 2, re-roll again for a lower chance
- call BattleRandom
- and $3
-.gotNumHits
- inc a
- inc a
-.saveNumberOfHits
- ld [de], a
- ld [bc], a
- ret
-.twineedle
- ld a, POISON_SIDE_EFFECT1
- ld [hl], a ; set Twineedle's effect to poison effect
- jr .saveNumberOfHits
-
-FlinchSideEffect:
- call CheckTargetSubstitute
- ret nz
- ld hl, wEnemyBattleStatus1
- ld de, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- jr z, .flinchSideEffect
- ld hl, wPlayerBattleStatus1
- ld de, wEnemyMoveEffect
-.flinchSideEffect
- ld a, [de]
- cp FLINCH_SIDE_EFFECT1
- ld b, $1a ; ~10% chance of flinch
- jr z, .gotEffectChance
- ld b, $4d ; ~30% chance of flinch
-.gotEffectChance
- call BattleRandom
- cp b
- ret nc
- set FLINCHED, [hl] ; set mon's status to flinching
- call ClearHyperBeam
- ret
-
-OneHitKOEffect:
- jpab OneHitKOEffect_
-
-ChargeEffect:
- ld hl, wPlayerBattleStatus1
- ld de, wPlayerMoveEffect
- ld a, [H_WHOSETURN]
- and a
- ld b, XSTATITEM_ANIM
- jr z, .chargeEffect
- ld hl, wEnemyBattleStatus1
- ld de, wEnemyMoveEffect
- ld b, ANIM_AF
-.chargeEffect
- set CHARGING_UP, [hl]
- ld a, [de]
- dec de ; de contains enemy or player MOVENUM
- cp FLY_EFFECT
- jr nz, .notFly
- set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig)
- ld b, TELEPORT ; load Teleport's animation
-.notFly
- ld a, [de]
- cp DIG
- jr nz, .notDigOrFly
- set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig)
- ld b, ANIM_C0
-.notDigOrFly
- xor a
- ld [wAnimationType], a
- ld a, b
- call PlayBattleAnimation
- ld a, [de]
- ld [wChargeMoveNum], a
- ld hl, ChargeMoveEffectText
- jp PrintText
-
-ChargeMoveEffectText:
- TX_FAR _ChargeMoveEffectText
- TX_ASM
- ld a, [wChargeMoveNum]
- cp RAZOR_WIND
- ld hl, MadeWhirlwindText
- jr z, .gotText
- cp SOLARBEAM
- ld hl, TookInSunlightText
- jr z, .gotText
- cp SKULL_BASH
- ld hl, LoweredItsHeadText
- jr z, .gotText
- cp SKY_ATTACK
- ld hl, SkyAttackGlowingText
- jr z, .gotText
- cp FLY
- ld hl, FlewUpHighText
- jr z, .gotText
- cp DIG
- ld hl, DugAHoleText
-.gotText
- ret
-
-MadeWhirlwindText:
- TX_FAR _MadeWhirlwindText
- db "@"
-
-TookInSunlightText:
- TX_FAR _TookInSunlightText
- db "@"
-
-LoweredItsHeadText:
- TX_FAR _LoweredItsHeadText
- db "@"
-
-SkyAttackGlowingText:
- TX_FAR _SkyAttackGlowingText
- db "@"
-
-FlewUpHighText:
- TX_FAR _FlewUpHighText
- db "@"
-
-DugAHoleText:
- TX_FAR _DugAHoleText
- db "@"
-
-TrappingEffect:
- ld hl, wPlayerBattleStatus1
- ld de, wPlayerNumAttacksLeft
- ld a, [H_WHOSETURN]
- and a
- jr z, .trappingEffect
- ld hl, wEnemyBattleStatus1
- ld de, wEnemyNumAttacksLeft
-.trappingEffect
- bit USING_TRAPPING_MOVE, [hl]
- ret nz
- call ClearHyperBeam ; since this effect is called before testing whether the move will hit,
- ; the target won't need to recharge even if the trapping move missed
- set USING_TRAPPING_MOVE, [hl] ; mon is now using a trapping move
- call BattleRandom ; 3/8 chance for 2 and 3 attacks, and 1/8 chance for 4 and 5 attacks
- and $3
- cp $2
- jr c, .setTrappingCounter
- call BattleRandom
- and $3
-.setTrappingCounter
- inc a
- ld [de], a
- ret
-
-MistEffect:
- jpab MistEffect_
-
-FocusEnergyEffect:
- jpab FocusEnergyEffect_
-
-RecoilEffect:
- jpab RecoilEffect_
-
-ConfusionSideEffect:
- call BattleRandom
- cp $19 ; ~10% chance
- ret nc
- jr ConfusionSideEffectSuccess
-
-ConfusionEffect:
- call CheckTargetSubstitute
- jr nz, ConfusionEffectFailed
- call MoveHitTest
- ld a, [wMoveMissed]
- and a
- jr nz, ConfusionEffectFailed
-
-ConfusionSideEffectSuccess:
- ld a, [H_WHOSETURN]
- and a
- ld hl, wEnemyBattleStatus1
- ld bc, wEnemyConfusedCounter
- ld a, [wPlayerMoveEffect]
- jr z, .confuseTarget
- ld hl, wPlayerBattleStatus1
- ld bc, wPlayerConfusedCounter
- ld a, [wEnemyMoveEffect]
-.confuseTarget
- bit CONFUSED, [hl] ; is mon confused?
- jr nz, ConfusionEffectFailed
- set CONFUSED, [hl] ; mon is now confused
- push af
- call BattleRandom
- and $3
- inc a
- inc a
- ld [bc], a ; confusion status will last 2-5 turns
- pop af
- cp CONFUSION_SIDE_EFFECT
- call nz, PlayCurrentMoveAnimation2
- ld hl, BecameConfusedText
- jp PrintText
-
-BecameConfusedText:
- TX_FAR _BecameConfusedText
- db "@"
-
-ConfusionEffectFailed:
- cp CONFUSION_SIDE_EFFECT
- ret z
- ld c, 50
- call DelayFrames
- jp ConditionalPrintButItFailed
-
-ParalyzeEffect:
- jpab ParalyzeEffect_
-
-SubstituteEffect:
- jpab SubstituteEffect_
-
-HyperBeamEffect:
- ld hl, wPlayerBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .hyperBeamEffect
- ld hl, wEnemyBattleStatus2
-.hyperBeamEffect
- set NEEDS_TO_RECHARGE, [hl] ; mon now needs to recharge
- ret
-
-ClearHyperBeam:
- push hl
- ld hl, wEnemyBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .playerTurn
- ld hl, wPlayerBattleStatus2
-.playerTurn
- res NEEDS_TO_RECHARGE, [hl] ; mon no longer needs to recharge
- pop hl
- ret
-
-RageEffect:
- ld hl, wPlayerBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .player
- ld hl, wEnemyBattleStatus2
-.player
- set USING_RAGE, [hl] ; mon is now in "rage" mode
- ret
-
-MimicEffect:
- ld c, 50
- call DelayFrames
- call MoveHitTest
- ld a, [wMoveMissed]
- and a
- jr nz, .mimicMissed
- ld a, [H_WHOSETURN]
- and a
- ld hl, wBattleMonMoves
- ld a, [wPlayerBattleStatus1]
- jr nz, .enemyTurn
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .letPlayerChooseMove
- ld hl, wEnemyMonMoves
- ld a, [wEnemyBattleStatus1]
-.enemyTurn
- bit INVULNERABLE, a
- jr nz, .mimicMissed
-.getRandomMove
- push hl
- call BattleRandom
- and $3
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hl]
- pop hl
- and a
- jr z, .getRandomMove
- ld d, a
- ld a, [H_WHOSETURN]
- and a
- ld hl, wBattleMonMoves
- ld a, [wPlayerMoveListIndex]
- jr z, .playerTurn
- ld hl, wEnemyMonMoves
- ld a, [wEnemyMoveListIndex]
- jr .playerTurn
-.letPlayerChooseMove
- ld a, [wEnemyBattleStatus1]
- bit INVULNERABLE, a
- jr nz, .mimicMissed
- ld a, [wCurrentMenuItem]
- push af
- ld a, $1
- ld [wMoveMenuType], a
- call MoveSelectionMenu
- call LoadScreenTilesFromBuffer1
- ld hl, wEnemyMonMoves
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, $0
- add hl, bc
- ld d, [hl]
- pop af
- ld hl, wBattleMonMoves
-.playerTurn
- ld c, a
- ld b, $0
- add hl, bc
- ld a, d
- ld [hl], a
- ld [wd11e], a
- call GetMoveName
- call PlayCurrentMoveAnimation
- ld hl, MimicLearnedMoveText
- jp PrintText
-.mimicMissed
- jp PrintButItFailedText_
-
-MimicLearnedMoveText:
- TX_FAR _MimicLearnedMoveText
- db "@"
-
-LeechSeedEffect:
- jpab LeechSeedEffect_
-
-SplashEffect:
- call PlayCurrentMoveAnimation
- jp PrintNoEffectText
-
-DisableEffect:
- call MoveHitTest
- ld a, [wMoveMissed]
- and a
- jr nz, .moveMissed
- ld de, wEnemyDisabledMove
- ld hl, wEnemyMonMoves
- ld a, [H_WHOSETURN]
- and a
- jr z, .disableEffect
- ld de, wPlayerDisabledMove
- ld hl, wBattleMonMoves
-.disableEffect
-; no effect if target already has a move disabled
- ld a, [de]
- and a
- jr nz, .moveMissed
-.pickMoveToDisable
- push hl
- call BattleRandom
- and $3
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hl]
- pop hl
- and a
- jr z, .pickMoveToDisable ; loop until a non-00 move slot is found
- ld [wd11e], a ; store move number
- push hl
- ld a, [H_WHOSETURN]
- and a
- ld hl, wBattleMonPP
- jr nz, .enemyTurn
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- pop hl ; wEnemyMonMoves
- jr nz, .playerTurnNotLinkBattle
-; .playerTurnLinkBattle
- push hl
- ld hl, wEnemyMonPP
-.enemyTurn
- push hl
- ld a, [hli]
- or [hl]
- inc hl
- or [hl]
- inc hl
- or [hl]
- and $3f
- pop hl ; wBattleMonPP or wEnemyMonPP
- jr z, .moveMissedPopHL ; nothing to do if all moves have no PP left
- add hl, bc
- ld a, [hl]
- pop hl
- and a
- jr z, .pickMoveToDisable ; pick another move if this one had 0 PP
-.playerTurnNotLinkBattle
-; non-link battle enemies have unlimited PP so the previous checks aren't needed
- call BattleRandom
- and $7
- inc a ; 1-8 turns disabled
- inc c ; move 1-4 will be disabled
- swap c
- add c ; map disabled move to high nibble of wEnemyDisabledMove / wPlayerDisabledMove
- ld [de], a
- call PlayCurrentMoveAnimation2
- ld hl, wPlayerDisabledMoveNumber
- ld a, [H_WHOSETURN]
- and a
- jr nz, .printDisableText
- inc hl ; wEnemyDisabledMoveNumber
-.printDisableText
- ld a, [wd11e] ; move number
- ld [hl], a
- call GetMoveName
- ld hl, MoveWasDisabledText
- jp PrintText
-.moveMissedPopHL
- pop hl
-.moveMissed
- jp PrintButItFailedText_
-
-MoveWasDisabledText:
- TX_FAR _MoveWasDisabledText
- db "@"
-
-PayDayEffect:
- jpab PayDayEffect_
-
-ConversionEffect:
- jpab ConversionEffect_
-
-HazeEffect:
- jpab HazeEffect_
-
-HealEffect:
- jpab HealEffect_
-
-TransformEffect:
- jpab TransformEffect_
-
-ReflectLightScreenEffect:
- jpab ReflectLightScreenEffect_
-
-NothingHappenedText:
- TX_FAR _NothingHappenedText
- db "@"
-
-PrintNoEffectText:
- ld hl, NoEffectText
- jp PrintText
-
-NoEffectText:
- TX_FAR _NoEffectText
- db "@"
-
-ConditionalPrintButItFailed:
- ld a, [wMoveDidntMiss]
- and a
- ret nz ; return if the side effect failed, yet the attack was successful
-
-PrintButItFailedText_:
- ld hl, ButItFailedText
- jp PrintText
-
-ButItFailedText:
- TX_FAR _ButItFailedText
- db "@"
-
-PrintDidntAffectText:
- ld hl, DidntAffectText
- jp PrintText
-
-DidntAffectText:
- TX_FAR _DidntAffectText
- db "@"
-
-IsUnaffectedText:
- TX_FAR _IsUnaffectedText
- db "@"
-
-PrintMayNotAttackText:
- ld hl, ParalyzedMayNotAttackText
- jp PrintText
-
-ParalyzedMayNotAttackText:
- TX_FAR _ParalyzedMayNotAttackText
- db "@"
-
-CheckTargetSubstitute:
- push hl
- ld hl, wEnemyBattleStatus2
- ld a, [H_WHOSETURN]
- and a
- jr z, .next1
- ld hl, wPlayerBattleStatus2
-.next1
- bit HAS_SUBSTITUTE_UP, [hl]
- pop hl
- ret
-
-PlayCurrentMoveAnimation2:
-; animation at MOVENUM will be played unless MOVENUM is 0
-; plays wAnimationType 3 or 6
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveNum]
- jr z, .notEnemyTurn
- ld a, [wEnemyMoveNum]
-.notEnemyTurn
- and a
- ret z
-
-PlayBattleAnimation2:
-; play animation ID at a and animation type 6 or 3
- ld [wAnimationID], a
- ld a, [H_WHOSETURN]
- and a
- ld a, $6
- jr z, .storeAnimationType
- ld a, $3
-.storeAnimationType
- ld [wAnimationType], a
- jp PlayBattleAnimationGotID
-
-PlayCurrentMoveAnimation:
-; animation at MOVENUM will be played unless MOVENUM is 0
-; resets wAnimationType
- xor a
- ld [wAnimationType], a
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerMoveNum]
- jr z, .notEnemyTurn
- ld a, [wEnemyMoveNum]
-.notEnemyTurn
- and a
- ret z
-
-PlayBattleAnimation:
-; play animation ID at a and predefined animation type
- ld [wAnimationID], a
-
-PlayBattleAnimationGotID:
-; play animation at wAnimationID
- push hl
- push de
- push bc
- predef MoveAnimation
- pop bc
- pop de
- pop hl
- ret
diff --git a/engine/battle/end_of_battle.asm b/engine/battle/end_of_battle.asm
deleted file mode 100755
index c77e3b39..00000000
--- a/engine/battle/end_of_battle.asm
+++ /dev/null
@@ -1,88 +0,0 @@
-EndOfBattle:
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
-; link battle
- ld a, [wEnemyMonPartyPos]
- ld hl, wEnemyMon1Status
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld a, [wEnemyMonStatus]
- ld [hl], a
- call ClearScreen
- callab DisplayLinkBattleVersusTextBox
- ld a, [wBattleResult]
- cp $1
- ld de, YouWinText
- jr c, .placeWinOrLoseString
- ld de, YouLoseText
- jr z, .placeWinOrLoseString
- ld de, DrawText
-.placeWinOrLoseString
- coord hl, 6, 8
- call PlaceString
- ld c, 200
- call DelayFrames
- jr .evolution
-.notLinkBattle
- ld a, [wBattleResult]
- and a
- jr nz, .resetVariables
- ld hl, wTotalPayDayMoney
- ld a, [hli]
- or [hl]
- inc hl
- or [hl]
- jr z, .evolution ; if pay day money is 0, jump
- ld de, wPlayerMoney + 2
- ld c, $3
- predef AddBCDPredef
- ld hl, PickUpPayDayMoneyText
- call PrintText
-.evolution
- xor a
- ld [wForceEvolution], a
- predef EvolutionAfterBattle
-.resetVariables
- xor a
- ld [wLowHealthAlarm], a ;disable low health alarm
- ld [wChannelSoundIDs + Ch4], a
- ld [wIsInBattle], a
- ld [wBattleType], a
- ld [wMoveMissed], a
- ld [wCurOpponent], a
- ld [wForcePlayerToChooseMon], a
- ld [wNumRunAttempts], a
- ld [wEscapedFromBattle], a
- ld hl, wPartyAndBillsPCSavedMenuItem
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wListScrollOffset], a
- ld hl, wPlayerStatsToDouble
- ld b, $18
-.loop
- ld [hli], a
- dec b
- jr nz, .loop
- ld hl, wd72c
- set 0, [hl]
- call WaitForSoundToFinish
- call GBPalWhiteOut
- ld a, $ff
- ld [wDestinationWarpID], a
- ret
-
-YouWinText:
- db "YOU WIN@"
-
-YouLoseText:
- db "YOU LOSE@"
-
-DrawText:
- db " DRAW@"
-
-PickUpPayDayMoneyText:
- TX_FAR _PickUpPayDayMoneyText
- db "@"
diff --git a/engine/battle/link_battle_versus_text.asm b/engine/battle/link_battle_versus_text.asm
deleted file mode 100644
index 76559117..00000000
--- a/engine/battle/link_battle_versus_text.asm
+++ /dev/null
@@ -1,23 +0,0 @@
-; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names
-DisplayLinkBattleVersusTextBox:
- call LoadTextBoxTilePatterns
- coord hl, 3, 4
- ld b, 7
- ld c, 12
- call TextBoxBorder
- coord hl, 4, 5
- ld de, wPlayerName
- call PlaceString
- coord hl, 4, 10
- ld de, wLinkEnemyTrainerName
- call PlaceString
-; place bold "VS" tiles between the names
- coord hl, 9, 8
- ld a, $69
- ld [hli], a
- ld [hl], $6a
- xor a
- ld [wUpdateSpritesEnabled], a
- callab SetupPlayerAndEnemyPokeballs
- ld c, 150
- jp DelayFrames
diff --git a/engine/battle/print_type.asm b/engine/battle/print_type.asm
index f717f871..fc66ceaa 100644
--- a/engine/battle/print_type.asm
+++ b/engine/battle/print_type.asm
@@ -49,4 +49,4 @@ PrintType_:
pop hl
jp PlaceString
-INCLUDE "text/type_names.asm"
+ inclang text/type_names.asm
diff --git a/engine/battle/save_trainer_name.asm b/engine/battle/save_trainer_name.asm
deleted file mode 100644
index 49d0429f..00000000
--- a/engine/battle/save_trainer_name.asm
+++ /dev/null
@@ -1,112 +0,0 @@
-SaveTrainerName:
- ld hl, TrainerNamePointers
- ld a, [wTrainerClass]
- dec a
- ld c, a
- ld b, 0
- add hl, bc
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, wcd6d
-.CopyCharacter
- ld a, [hli]
- ld [de], a
- inc de
- cp "@"
- jr nz, .CopyCharacter
- ret
-
-TrainerNamePointers:
-; what is the point of these?
- dw YoungsterName
- dw BugCatcherName
- dw LassName
- dw wTrainerName
- dw JrTrainerMName
- dw JrTrainerFName
- dw PokemaniacName
- dw SuperNerdName
- dw wTrainerName
- dw wTrainerName
- dw BurglarName
- dw EngineerName
- dw JugglerXName
- dw wTrainerName
- dw SwimmerName
- dw wTrainerName
- dw wTrainerName
- dw BeautyName
- dw wTrainerName
- dw RockerName
- dw JugglerName
- dw wTrainerName
- dw wTrainerName
- dw BlackbeltName
- dw wTrainerName
- dw ProfOakName
- dw ChiefName
- dw ScientistName
- dw wTrainerName
- dw RocketName
- dw CooltrainerMName
- dw CooltrainerFName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
- dw wTrainerName
-
-YoungsterName:
- db "YOUNGSTER@"
-BugCatcherName:
- db "BUG CATCHER@"
-LassName:
- db "LASS@"
-JrTrainerMName:
- db "JR.TRAINER♂@"
-JrTrainerFName:
- db "JR.TRAINER♀@"
-PokemaniacName:
- db "POKéMANIAC@"
-SuperNerdName:
- db "SUPER NERD@"
-BurglarName:
- db "BURGLAR@"
-EngineerName:
- db "ENGINEER@"
-JugglerXName:
- db "JUGGLER@"
-SwimmerName:
- db "SWIMMER@"
-BeautyName:
- db "BEAUTY@"
-RockerName:
- db "ROCKER@"
-JugglerName:
- db "JUGGLER@"
-BlackbeltName:
- db "BLACKBELT@"
-ProfOakName:
- db "PROF.OAK@"
-ChiefName:
- db "CHIEF@"
-ScientistName:
- db "SCIENTIST@"
-RocketName:
- db "ROCKET@"
-CooltrainerMName:
- db "COOLTRAINER♂@"
-CooltrainerFName:
- db "COOLTRAINER♀@"
diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm
index 6f699b9c..f3501209 100644
--- a/engine/battle/trainer_ai.asm
+++ b/engine/battle/trainer_ai.asm
@@ -326,7 +326,7 @@ TrainerClassMoveChoiceModifications:
INCLUDE "engine/battle/trainer_pic_money_pointers.asm"
-INCLUDE "text/trainer_names.asm"
+ inclang text/trainer_names.asm
INCLUDE "engine/battle/bank_e_misc.asm"
diff --git a/engine/cable_club.asm b/engine/cable_club.asm
deleted file mode 100755
index 3e72daa9..00000000
--- a/engine/cable_club.asm
+++ /dev/null
@@ -1,977 +0,0 @@
-; performs the appropriate action when the player uses the gameboy on the table in the Colosseum or Trade Center
-; In the Colosseum, it starts a battle. In the Trade Center, it displays the trade selection screen.
-; Before doing either action, it swaps random numbers, trainer names and party data with the other gameboy.
-CableClub_DoBattleOrTrade:
- ld c, 80
- call DelayFrames
- call ClearScreen
- call UpdateSprites
- call LoadFontTilePatterns
- call LoadHpBarAndStatusTilePatterns
- call LoadTrainerInfoTextBoxTiles
- coord hl, 3, 8
- ld b, 2
- ld c, 12
- call CableClub_TextBoxBorder
- coord hl, 4, 10
- ld de, PleaseWaitString
- call PlaceString
- ld hl, wPlayerNumHits
- xor a
- ld [hli], a
- ld [hl], $50
- ; fall through
-
-; This is called after completing a trade.
-CableClub_DoBattleOrTradeAgain:
- ld hl, wSerialPlayerDataBlock
- ld a, SERIAL_PREAMBLE_BYTE
- ld b, 6
-.writePlayerDataBlockPreambleLoop
- ld [hli], a
- dec b
- jr nz, .writePlayerDataBlockPreambleLoop
- ld hl, wSerialRandomNumberListBlock
- ld a, SERIAL_PREAMBLE_BYTE
- ld b, 7
-.writeRandomNumberListPreambleLoop
- ld [hli], a
- dec b
- jr nz, .writeRandomNumberListPreambleLoop
- ld b, 10
-.generateRandomNumberListLoop
- call Random
- cp SERIAL_PREAMBLE_BYTE ; all the random numbers have to be less than the preamble byte
- jr nc, .generateRandomNumberListLoop
- ld [hli], a
- dec b
- jr nz, .generateRandomNumberListLoop
- ld hl, wSerialPartyMonsPatchList
- ld a, SERIAL_PREAMBLE_BYTE
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld b, $c8
- xor a
-.zeroPlayerDataPatchListLoop
- ld [hli], a
- dec b
- jr nz, .zeroPlayerDataPatchListLoop
- ld hl, wGrassRate
- ld bc, wTrainerHeaderPtr - wGrassRate
-.zeroEnemyPartyLoop
- xor a
- ld [hli], a
- dec bc
- ld a, b
- or c
- jr nz, .zeroEnemyPartyLoop
- ld hl, wPartyMons - 1
- ld de, wSerialPartyMonsPatchList + 10
- ld bc, 0
-.patchPartyMonsLoop
- inc c
- ld a, c
- cp SERIAL_PREAMBLE_BYTE
- jr z, .startPatchListPart2
- ld a, b
- dec a ; are we in part 2 of the patch list?
- jr nz, .checkPlayerDataByte ; jump if in part 1
-; if we're in part 2
- ld a, c
- cp (wPartyMonOT - (wPartyMons - 1)) - (SERIAL_PREAMBLE_BYTE - 1)
- jr z, .finishedPatchingPlayerData
-.checkPlayerDataByte
- inc hl
- ld a, [hl]
- cp SERIAL_NO_DATA_BYTE
- jr nz, .patchPartyMonsLoop
-; if the player data byte matches SERIAL_NO_DATA_BYTE, patch it with $FF and record the offset in the patch list
- ld a, c
- ld [de], a
- inc de
- ld [hl], $ff
- jr .patchPartyMonsLoop
-.startPatchListPart2
- ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
- ld [de], a ; end of part 1
- inc de
- lb bc, 1, 0
- jr .patchPartyMonsLoop
-.finishedPatchingPlayerData
- ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
- ld [de], a ; end of part 2
- call Serial_SyncAndExchangeNybble
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- jr nz, .skipSendingTwoZeroBytes
-; if using internal clock
-; send two zero bytes for syncing purposes?
- call Delay3
- xor a
- ld [hSerialSendData], a
- ld a, START_TRANSFER_INTERNAL_CLOCK
- ld [rSC], a
- call DelayFrame
- xor a
- ld [hSerialSendData], a
- ld a, START_TRANSFER_INTERNAL_CLOCK
- ld [rSC], a
-.skipSendingTwoZeroBytes
- call Delay3
- ld a, (1 << SERIAL)
- ld [rIE], a
- ld hl, wSerialRandomNumberListBlock
- ld de, wSerialOtherGameboyRandomNumberListBlock
- ld bc, $11
- call Serial_ExchangeBytes
- ld a, SERIAL_NO_DATA_BYTE
- ld [de], a
- ld hl, wSerialPlayerDataBlock
- ld de, wSerialEnemyDataBlock
- ld bc, $1a8
- call Serial_ExchangeBytes
- ld a, SERIAL_NO_DATA_BYTE
- ld [de], a
- ld hl, wSerialPartyMonsPatchList
- ld de, wSerialEnemyMonsPatchList
- ld bc, $c8
- call Serial_ExchangeBytes
- ld a, (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK)
- ld [rIE], a
- ld a, $ff
- call PlaySound
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- jr z, .skipCopyingRandomNumberList ; the list generated by the gameboy clocking the connection is used by both gameboys
- ld hl, wSerialOtherGameboyRandomNumberListBlock
-.findStartOfRandomNumberListLoop
- ld a, [hli]
- and a
- jr z, .findStartOfRandomNumberListLoop
- cp SERIAL_PREAMBLE_BYTE
- jr z, .findStartOfRandomNumberListLoop
- cp SERIAL_NO_DATA_BYTE
- jr z, .findStartOfRandomNumberListLoop
- dec hl
- ld de, wLinkBattleRandomNumberList
- ld c, 10
-.copyRandomNumberListLoop
- ld a, [hli]
- cp SERIAL_NO_DATA_BYTE
- jr z, .copyRandomNumberListLoop
- ld [de], a
- inc de
- dec c
- jr nz, .copyRandomNumberListLoop
-.skipCopyingRandomNumberList
- ld hl, wSerialEnemyDataBlock + 3
-.findStartOfEnemyNameLoop
- ld a, [hli]
- and a
- jr z, .findStartOfEnemyNameLoop
- cp SERIAL_PREAMBLE_BYTE
- jr z, .findStartOfEnemyNameLoop
- cp SERIAL_NO_DATA_BYTE
- jr z, .findStartOfEnemyNameLoop
- dec hl
- ld de, wLinkEnemyTrainerName
- ld c, NAME_LENGTH
-.copyEnemyNameLoop
- ld a, [hli]
- cp SERIAL_NO_DATA_BYTE
- jr z, .copyEnemyNameLoop
- ld [de], a
- inc de
- dec c
- jr nz, .copyEnemyNameLoop
- ld de, wEnemyPartyCount
- ld bc, wTrainerHeaderPtr - wEnemyPartyCount
-.copyEnemyPartyLoop
- ld a, [hli]
- cp SERIAL_NO_DATA_BYTE
- jr z, .copyEnemyPartyLoop
- ld [de], a
- inc de
- dec bc
- ld a, b
- or c
- jr nz, .copyEnemyPartyLoop
- ld de, wSerialPartyMonsPatchList
- ld hl, wPartyMons
- ld c, 2 ; patch list has 2 parts
-.unpatchPartyMonsLoop
- ld a, [de]
- inc de
- and a
- jr z, .unpatchPartyMonsLoop
- cp SERIAL_PREAMBLE_BYTE
- jr z, .unpatchPartyMonsLoop
- cp SERIAL_NO_DATA_BYTE
- jr z, .unpatchPartyMonsLoop
- cp SERIAL_PATCH_LIST_PART_TERMINATOR
- jr z, .finishedPartyMonsPatchListPart
- push hl
- push bc
- ld b, 0
- dec a
- ld c, a
- add hl, bc
- ld a, SERIAL_NO_DATA_BYTE
- ld [hl], a
- pop bc
- pop hl
- jr .unpatchPartyMonsLoop
-.finishedPartyMonsPatchListPart
- ld hl, wPartyMons + (SERIAL_PREAMBLE_BYTE - 1)
- dec c ; is there another part?
- jr nz, .unpatchPartyMonsLoop
- ld de, wSerialEnemyMonsPatchList
- ld hl, wEnemyMons
- ld c, 2 ; patch list has 2 parts
-.unpatchEnemyMonsLoop
- ld a, [de]
- inc de
- and a
- jr z, .unpatchEnemyMonsLoop
- cp SERIAL_PREAMBLE_BYTE
- jr z, .unpatchEnemyMonsLoop
- cp SERIAL_NO_DATA_BYTE
- jr z, .unpatchEnemyMonsLoop
- cp SERIAL_PATCH_LIST_PART_TERMINATOR
- jr z, .finishedEnemyMonsPatchListPart
- push hl
- push bc
- ld b, 0
- dec a
- ld c, a
- add hl, bc
- ld a, SERIAL_NO_DATA_BYTE
- ld [hl], a
- pop bc
- pop hl
- jr .unpatchEnemyMonsLoop
-.finishedEnemyMonsPatchListPart
- ld hl, wEnemyMons + (SERIAL_PREAMBLE_BYTE - 1)
- dec c
- jr nz, .unpatchEnemyMonsLoop
- ld a, wEnemyMonOT % $100
- ld [wUnusedCF8D], a
- ld a, wEnemyMonOT / $100
- ld [wUnusedCF8D + 1], a
- xor a
- ld [wTradeCenterPointerTableIndex], a
- ld a, $ff
- call PlaySound
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- ld c, 66
- call z, DelayFrames ; delay if using internal clock
- ld a, [wLinkState]
- cp LINK_STATE_START_BATTLE
- ld a, LINK_STATE_TRADING
- ld [wLinkState], a
- jr nz, .trading
- ld a, LINK_STATE_BATTLING
- ld [wLinkState], a
- ld a, OPP_SONY1
- ld [wCurOpponent], a
- call ClearScreen
- call Delay3
- ld hl, wOptions
- res 7, [hl]
- predef InitOpponent
- predef HealParty
- jp ReturnToCableClubRoom
-.trading
- ld c, BANK(Music_GameCorner)
- ld a, MUSIC_GAME_CORNER
- call PlayMusic
- jr CallCurrentTradeCenterFunction
-
-PleaseWaitString:
- db "PLEASE WAIT!@"
-
-CallCurrentTradeCenterFunction:
- ld hl, TradeCenterPointerTable
- ld b, 0
- ld a, [wTradeCenterPointerTableIndex]
- cp $ff
- jp z, DisplayTitleScreen
- add a
- ld c, a
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- jp hl
-
-TradeCenter_SelectMon:
- call ClearScreen
- call LoadTrainerInfoTextBoxTiles
- call TradeCenter_DrawPartyLists
- call TradeCenter_DrawCancelBox
- xor a
- ld hl, wSerialSyncAndExchangeNybbleReceiveData
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wMenuWatchMovingOutOfBounds], a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [wMenuJoypadPollCount], a
- inc a
- ld [wSerialExchangeNybbleSendData], a
- jp .playerMonMenu
-.enemyMonMenu
- xor a
- ld [wMenuWatchMovingOutOfBounds], a
- inc a
- ld [wWhichTradeMonSelectionMenu], a
- ld a, D_DOWN | D_LEFT | A_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, [wEnemyPartyCount]
- ld [wMaxMenuItem], a
- ld a, 9
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
-.enemyMonMenu_HandleInput
- ld hl, hFlags_0xFFF6
- set 1, [hl]
- call HandleMenuInput
- ld hl, hFlags_0xFFF6
- res 1, [hl]
- and a
- jp z, .getNewInput
- bit 0, a ; A button pressed?
- jr z, .enemyMonMenu_ANotPressed
-; if A button pressed
- ld a, [wMaxMenuItem]
- ld c, a
- ld a, [wCurrentMenuItem]
- cp c
- jr c, .displayEnemyMonStats
- ld a, [wMaxMenuItem]
- dec a
- ld [wCurrentMenuItem], a
-.displayEnemyMonStats
- ld a, INIT_ENEMYOT_LIST
- ld [wInitListType], a
- callab InitList ; the list isn't used
- ld hl, wEnemyMons
- call TradeCenter_DisplayStats
- jp .getNewInput
-.enemyMonMenu_ANotPressed
- bit 5, a ; Left pressed?
- jr z, .enemyMonMenu_LeftNotPressed
-; if Left pressed, switch back to the player mon menu
- xor a ; player mon menu
- ld [wWhichTradeMonSelectionMenu], a
- ld a, [wMenuCursorLocation]
- ld l, a
- ld a, [wMenuCursorLocation + 1]
- ld h, a
- ld a, [wTileBehindCursor]
- ld [hl], a
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wPartyCount]
- dec a
- cp b
- jr nc, .playerMonMenu
- ld [wCurrentMenuItem], a
- jr .playerMonMenu
-.enemyMonMenu_LeftNotPressed
- bit 7, a ; Down pressed?
- jp z, .getNewInput
- jp .selectedCancelMenuItem ; jump if Down pressed
-.playerMonMenu
- xor a ; player mon menu
- ld [wWhichTradeMonSelectionMenu], a
- ld [wMenuWatchMovingOutOfBounds], a
- ld a, D_DOWN | D_RIGHT | A_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, [wPartyCount]
- ld [wMaxMenuItem], a
- ld a, 1
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
- coord hl, 1, 1
- lb bc, 6, 1
- call ClearScreenArea
-.playerMonMenu_HandleInput
- ld hl, hFlags_0xFFF6
- set 1, [hl]
- call HandleMenuInput
- ld hl, hFlags_0xFFF6
- res 1, [hl]
- and a ; was anything pressed?
- jr nz, .playerMonMenu_SomethingPressed
- jp .getNewInput
-.playerMonMenu_SomethingPressed
- bit 0, a ; A button pressed?
- jr z, .playerMonMenu_ANotPressed
- jp .chosePlayerMon ; jump if A button pressed
-; unreachable code
- ld a, INIT_PLAYEROT_LIST
- ld [wInitListType], a
- callab InitList ; the list isn't used
- call TradeCenter_DisplayStats
- jp .getNewInput
-.playerMonMenu_ANotPressed
- bit 4, a ; Right pressed?
- jr z, .playerMonMenu_RightNotPressed
-; if Right pressed, switch to the enemy mon menu
- ld a, $1 ; enemy mon menu
- ld [wWhichTradeMonSelectionMenu], a
- ld a, [wMenuCursorLocation]
- ld l, a
- ld a, [wMenuCursorLocation + 1]
- ld h, a
- ld a, [wTileBehindCursor]
- ld [hl], a
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wEnemyPartyCount]
- dec a
- cp b
- jr nc, .notPastLastEnemyMon
-; when switching to the enemy mon menu, if the menu selection would be past the last enemy mon, select the last enemy mon
- ld [wCurrentMenuItem], a
-.notPastLastEnemyMon
- jp .enemyMonMenu
-.playerMonMenu_RightNotPressed
- bit 7, a ; Down pressed?
- jr z, .getNewInput
- jp .selectedCancelMenuItem ; jump if Down pressed
-.getNewInput
- ld a, [wWhichTradeMonSelectionMenu]
- and a
- jp z, .playerMonMenu_HandleInput
- jp .enemyMonMenu_HandleInput
-.chosePlayerMon
- call SaveScreenTilesToBuffer1
- call PlaceUnfilledArrowMenuCursor
- ld a, [wMaxMenuItem]
- ld c, a
- ld a, [wCurrentMenuItem]
- cp c
- jr c, .displayStatsTradeMenu
- ld a, [wMaxMenuItem]
- dec a
-.displayStatsTradeMenu
- push af
- coord hl, 0, 14
- ld b, 2
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 2, 16
- ld de, .statsTrade
- call PlaceString
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [wMenuJoypadPollCount], a
- ld [wMaxMenuItem], a
- ld a, 16
- ld [wTopMenuItemY], a
-.selectStatsMenuItem
- ld a, " "
- Coorda 11, 16
- ld a, D_RIGHT | B_BUTTON | A_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 1
- ld [wTopMenuItemX], a
- call HandleMenuInput
- bit 4, a ; Right pressed?
- jr nz, .selectTradeMenuItem
- bit 1, a ; B button pressed?
- jr z, .displayPlayerMonStats
-.cancelPlayerMonChoice
- pop af
- ld [wCurrentMenuItem], a
- call LoadScreenTilesFromBuffer1
- jp .playerMonMenu
-.selectTradeMenuItem
- ld a, " "
- Coorda 1, 16
- ld a, D_LEFT | B_BUTTON | A_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 11
- ld [wTopMenuItemX], a
- call HandleMenuInput
- bit 5, a ; Left pressed?
- jr nz, .selectStatsMenuItem
- bit 1, a ; B button pressed?
- jr nz, .cancelPlayerMonChoice
- jr .choseTrade
-.displayPlayerMonStats
- pop af
- ld [wCurrentMenuItem], a
- ld a, INIT_PLAYEROT_LIST
- ld [wInitListType], a
- callab InitList ; the list isn't used
- call TradeCenter_DisplayStats
- call LoadScreenTilesFromBuffer1
- jp .playerMonMenu
-.choseTrade
- call PlaceUnfilledArrowMenuCursor
- pop af
- ld [wCurrentMenuItem], a
- ld [wTradingWhichPlayerMon], a
- ld [wSerialExchangeNybbleSendData], a
- call Serial_PrintWaitingTextAndSyncAndExchangeNybble
- ld a, [wSerialSyncAndExchangeNybbleReceiveData]
- cp $f
- jp z, CallCurrentTradeCenterFunction ; go back to the beginning of the trade selection menu if the other person cancelled
- ld [wTradingWhichEnemyMon], a
- call TradeCenter_PlaceSelectedEnemyMonMenuCursor
- ld a, $1 ; TradeCenter_Trade
- ld [wTradeCenterPointerTableIndex], a
- jp CallCurrentTradeCenterFunction
-.statsTrade
- db "STATS TRADE@"
-.selectedCancelMenuItem
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wMaxMenuItem]
- cp b
- jp nz, .getNewInput
- ld a, [wMenuCursorLocation]
- ld l, a
- ld a, [wMenuCursorLocation + 1]
- ld h, a
- ld a, " "
- ld [hl], a
-.cancelMenuItem_Loop
- ld a, "▶" ; filled arrow cursor
- Coorda 1, 16
-.cancelMenuItem_JoypadLoop
- call JoypadLowSensitivity
- ld a, [hJoy5]
- and a ; pressed anything?
- jr z, .cancelMenuItem_JoypadLoop
- bit 0, a ; A button pressed?
- jr nz, .cancelMenuItem_APressed
- bit 6, a ; Up pressed?
- jr z, .cancelMenuItem_JoypadLoop
-; if Up pressed
- ld a, " "
- Coorda 1, 16
- ld a, [wPartyCount]
- dec a
- ld [wCurrentMenuItem], a
- jp .playerMonMenu
-.cancelMenuItem_APressed
- ld a, "▷" ; unfilled arrow cursor
- Coorda 1, 16
- ld a, $f
- ld [wSerialExchangeNybbleSendData], a
- call Serial_PrintWaitingTextAndSyncAndExchangeNybble
- ld a, [wSerialSyncAndExchangeNybbleReceiveData]
- cp $f ; did the other person choose Cancel too?
- jr nz, .cancelMenuItem_Loop
- ; fall through
-
-ReturnToCableClubRoom:
- call GBPalWhiteOutWithDelay3
- ld hl, wFontLoaded
- ld a, [hl]
- push af
- push hl
- res 0, [hl]
- xor a
- ld [wd72d], a
- dec a
- ld [wDestinationWarpID], a
- call LoadMapData
- callba ClearVariablesOnEnterMap
- pop hl
- pop af
- ld [hl], a
- call GBFadeInFromWhite
- ret
-
-TradeCenter_DrawCancelBox:
- coord hl, 11, 15
- ld a, $7e
- ld bc, 2 * SCREEN_WIDTH + 9
- call FillMemory
- coord hl, 0, 15
- ld b, 1
- ld c, 9
- call CableClub_TextBoxBorder
- coord hl, 2, 16
- ld de, CancelTextString
- jp PlaceString
-
-CancelTextString:
- db "CANCEL@"
-
-TradeCenter_PlaceSelectedEnemyMonMenuCursor:
- ld a, [wSerialSyncAndExchangeNybbleReceiveData]
- coord hl, 1, 9
- ld bc, SCREEN_WIDTH
- call AddNTimes
- ld [hl], "▷" ; cursor
- ret
-
-TradeCenter_DisplayStats:
- ld a, [wCurrentMenuItem]
- ld [wWhichPokemon], a
- predef StatusScreen
- predef StatusScreen2
- call GBPalNormal
- call LoadTrainerInfoTextBoxTiles
- call TradeCenter_DrawPartyLists
- jp TradeCenter_DrawCancelBox
-
-TradeCenter_DrawPartyLists:
- coord hl, 0, 0
- ld b, 6
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 0, 8
- ld b, 6
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 5, 0
- ld de, wPlayerName
- call PlaceString
- coord hl, 5, 8
- ld de, wLinkEnemyTrainerName
- call PlaceString
- coord hl, 2, 1
- ld de, wPartySpecies
- call TradeCenter_PrintPartyListNames
- coord hl, 2, 9
- ld de, wEnemyPartyMons
- ; fall through
-
-TradeCenter_PrintPartyListNames:
- ld c, $0
-.loop
- ld a, [de]
- cp $ff
- ret z
- ld [wd11e], a
- push bc
- push hl
- push de
- push hl
- ld a, c
- ld [$ff95], a
- call GetMonName
- pop hl
- call PlaceString
- pop de
- inc de
- pop hl
- ld bc, 20
- add hl, bc
- pop bc
- inc c
- jr .loop
-
-TradeCenter_Trade:
- ld c, 100
- call DelayFrames
- xor a
- ld [wSerialExchangeNybbleSendData + 1], a ; unnecessary
- ld [wSerialExchangeNybbleReceiveData], a
- ld [wMenuWatchMovingOutOfBounds], a
- ld [wMenuJoypadPollCount], a
- coord hl, 0, 12
- ld b, 4
- ld c, 18
- call CableClub_TextBoxBorder
- ld a, [wTradingWhichPlayerMon]
- ld hl, wPartySpecies
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- ld [wd11e], a
- call GetMonName
- ld hl, wcd6d
- ld de, wNameOfPlayerMonToBeTraded
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wTradingWhichEnemyMon]
- ld hl, wEnemyPartyMons
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- ld [wd11e], a
- call GetMonName
- ld hl, WillBeTradedText
- coord bc, 1, 14
- call TextCommandProcessor
- call SaveScreenTilesToBuffer1
- coord hl, 10, 7
- lb bc, 8, 11
- ld a, TRADE_CANCEL_MENU
- ld [wTwoOptionMenuID], a
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- call LoadScreenTilesFromBuffer1
- ld a, [wCurrentMenuItem]
- and a
- jr z, .tradeConfirmed
-; if trade cancelled
- ld a, $1
- ld [wSerialExchangeNybbleSendData], a
- coord hl, 0, 12
- ld b, 4
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 1, 14
- ld de, TradeCanceled
- call PlaceString
- call Serial_PrintWaitingTextAndSyncAndExchangeNybble
- jp .tradeCancelled
-.tradeConfirmed
- ld a, $2
- ld [wSerialExchangeNybbleSendData], a
- call Serial_PrintWaitingTextAndSyncAndExchangeNybble
- ld a, [wSerialSyncAndExchangeNybbleReceiveData]
- dec a ; did the other person cancel?
- jr nz, .doTrade
-; if the other person cancelled
- coord hl, 0, 12
- ld b, 4
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 1, 14
- ld de, TradeCanceled
- call PlaceString
- jp .tradeCancelled
-.doTrade
- ld a, [wTradingWhichPlayerMon]
- ld hl, wPartyMonOT
- call SkipFixedLengthTextEntries
- ld de, wTradedPlayerMonOT
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wPartyMon1Species
- ld a, [wTradingWhichPlayerMon]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld bc, wPartyMon1OTID - wPartyMon1
- add hl, bc
- ld a, [hli]
- ld [wTradedPlayerMonOTID], a
- ld a, [hl]
- ld [wTradedPlayerMonOTID + 1], a
- ld a, [wTradingWhichEnemyMon]
- ld hl, wEnemyMonOT
- call SkipFixedLengthTextEntries
- ld de, wTradedEnemyMonOT
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wEnemyMons
- ld a, [wTradingWhichEnemyMon]
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld bc, wEnemyMon1OTID - wEnemyMon1
- add hl, bc
- ld a, [hli]
- ld [wTradedEnemyMonOTID], a
- ld a, [hl]
- ld [wTradedEnemyMonOTID + 1], a
- ld a, [wTradingWhichPlayerMon]
- ld [wWhichPokemon], a
- ld hl, wPartySpecies
- ld b, 0
- ld c, a
- add hl, bc
- ld a, [hl]
- ld [wTradedPlayerMonSpecies], a
- xor a
- ld [wRemoveMonFromBox], a
- call RemovePokemon
- ld a, [wTradingWhichEnemyMon]
- ld c, a
- ld [wWhichPokemon], a
- ld hl, wEnemyPartyMons
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hl]
- ld [wcf91], a
- ld hl, wEnemyMons
- ld a, c
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld de, wLoadedMon
- ld bc, wEnemyMon2 - wEnemyMon1
- call CopyData
- call AddEnemyMonToPlayerParty
- ld a, [wPartyCount]
- dec a
- ld [wWhichPokemon], a
- ld a, $1
- ld [wForceEvolution], a
- ld a, [wTradingWhichEnemyMon]
- ld hl, wEnemyPartyMons
- ld b, 0
- ld c, a
- add hl, bc
- ld a, [hl]
- ld [wTradedEnemyMonSpecies], a
- ld a, 10
- ld [wAudioFadeOutControl], a
- ld a, $2
- ld [wAudioSavedROMBank], a
- ld a, MUSIC_SAFARI_ZONE
- ld [wNewSoundID], a
- call PlaySound
- ld c, 100
- call DelayFrames
- call ClearScreen
- call LoadHpBarAndStatusTilePatterns
- xor a
- ld [wUnusedCC5B], a
- ld a, [hSerialConnectionStatus]
- cp USING_EXTERNAL_CLOCK
- jr z, .usingExternalClock
- predef InternalClockTradeAnim
- jr .tradeCompleted
-.usingExternalClock
- predef ExternalClockTradeAnim
-.tradeCompleted
- callab TryEvolvingMon
- call ClearScreen
- call LoadTrainerInfoTextBoxTiles
- call Serial_PrintWaitingTextAndSyncAndExchangeNybble
- ld c, 40
- call DelayFrames
- coord hl, 0, 12
- ld b, 4
- ld c, 18
- call CableClub_TextBoxBorder
- coord hl, 1, 14
- ld de, TradeCompleted
- call PlaceString
- predef SaveSAVtoSRAM2
- ld c, 50
- call DelayFrames
- xor a
- ld [wTradeCenterPointerTableIndex], a
- jp CableClub_DoBattleOrTradeAgain
-.tradeCancelled
- ld c, 100
- call DelayFrames
- xor a ; TradeCenter_SelectMon
- ld [wTradeCenterPointerTableIndex], a
- jp CallCurrentTradeCenterFunction
-
-WillBeTradedText:
- TX_FAR _WillBeTradedText
- db "@"
-
-TradeCompleted:
- db "Trade completed!@"
-
-TradeCanceled:
- db "Too bad! The trade"
- next "was canceled!@"
-
-TradeCenterPointerTable:
- dw TradeCenter_SelectMon
- dw TradeCenter_Trade
-
-CableClub_Run:
- ld a, [wLinkState]
- cp LINK_STATE_START_TRADE
- jr z, .doBattleOrTrade
- cp LINK_STATE_START_BATTLE
- jr z, .doBattleOrTrade
- cp LINK_STATE_RESET ; this is never used
- ret nz
- predef EmptyFunc3
- jp Init
-.doBattleOrTrade
- call CableClub_DoBattleOrTrade
- ld hl, Club_GFX
- ld a, h
- ld [wTilesetGfxPtr + 1], a
- ld a, l
- ld [wTilesetGfxPtr], a
- ld a, Bank(Club_GFX)
- ld [wTilesetBank], a
- ld hl, Club_Coll
- ld a, h
- ld [wTilesetCollisionPtr + 1], a
- ld a, l
- ld [wTilesetCollisionPtr], a
- xor a
- ld [wGrassRate], a
- inc a ; LINK_STATE_IN_CABLE_CLUB
- ld [wLinkState], a
- ld [hJoy5], a
- ld a, 10
- ld [wAudioFadeOutControl], a
- ld a, BANK(Music_Celadon)
- ld [wAudioSavedROMBank], a
- ld a, MUSIC_CELADON
- ld [wNewSoundID], a
- jp PlaySound
-
-EmptyFunc3:
- ret
-
-Diploma_TextBoxBorder:
- call GetPredefRegisters
-
-; b = height
-; c = width
-CableClub_TextBoxBorder:
- push hl
- ld a, $78 ; border upper left corner tile
- ld [hli], a
- inc a ; border top horizontal line tile
- call CableClub_DrawHorizontalLine
- inc a ; border upper right corner tile
- ld [hl], a
- pop hl
- ld de, 20
- add hl, de
-.loop
- push hl
- ld a, $7b ; border left vertical line tile
- ld [hli], a
- ld a, " "
- call CableClub_DrawHorizontalLine
- ld [hl], $77 ; border right vertical line tile
- pop hl
- ld de, 20
- add hl, de
- dec b
- jr nz, .loop
- ld a, $7c ; border lower left corner tile
- ld [hli], a
- ld a, $76 ; border bottom horizontal line tile
- call CableClub_DrawHorizontalLine
- ld [hl], $7d ; border lower right corner tile
- ret
-
-; c = width
-CableClub_DrawHorizontalLine:
- ld d, c
-.loop
- ld [hli], a
- dec d
- jr nz, .loop
- ret
-
-LoadTrainerInfoTextBoxTiles:
- ld de, TrainerInfoTextBoxTileGraphics
- ld hl, vChars2 + $760
- lb bc, BANK(TrainerInfoTextBoxTileGraphics), (TrainerInfoTextBoxTileGraphicsEnd - TrainerInfoTextBoxTileGraphics) / $10
- jp CopyVideoData
diff --git a/engine/clear_save.asm b/engine/clear_save.asm
deleted file mode 100755
index b47cd6c4..00000000
--- a/engine/clear_save.asm
+++ /dev/null
@@ -1,23 +0,0 @@
-DoClearSaveDialogue:
- call ClearScreen
- call RunDefaultPaletteCommand
- call LoadFontTilePatterns
- call LoadTextBoxTilePatterns
- ld hl, ClearSaveDataText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, NO_YES_MENU
- ld [wTwoOptionMenuID], a
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, [wCurrentMenuItem]
- and a
- jp z, Init
- callba ClearSAV
- jp Init
-
-ClearSaveDataText:
- TX_FAR _ClearSaveDataText
- db "@"
diff --git a/engine/evolve_trade.asm b/engine/evolve_trade.asm
deleted file mode 100755
index e17fc05c..00000000
--- a/engine/evolve_trade.asm
+++ /dev/null
@@ -1,44 +0,0 @@
-EvolveTradeMon:
-; Verify the TradeMon's species name before
-; attempting to initiate a trade evolution.
-
-; The names of the trade evolutions in Blue (JP)
-; are checked. In that version, TradeMons that
-; can evolve are Graveler and Haunter.
-
-; In localization, this check was translated
-; before monster names were finalized.
-; Then, Haunter's name was "Spectre".
-; Since its name no longer starts with
-; "SP", it is prevented from evolving.
-
-; This may have been why Red/Green's trades
-; were used instead, where none can evolve.
-
-; This was fixed in Yellow.
-
- ld a, [wInGameTradeReceiveMonName]
-
- ; GRAVELER
- cp "G"
- jr z, .ok
-
- ; "SPECTRE" (HAUNTER)
- cp "S"
- ret nz
- ld a, [wInGameTradeReceiveMonName + 1]
- cp "P"
- ret nz
-
-.ok
- ld a, [wPartyCount]
- dec a
- ld [wWhichPokemon], a
- ld a, $1
- ld [wForceEvolution], a
- ld a, LINK_STATE_TRADING
- ld [wLinkState], a
- callab TryEvolvingMon
- xor a ; LINK_STATE_NONE
- ld [wLinkState], a
- jp PlayDefaultMusic
diff --git a/engine/hall_of_fame.asm b/engine/hall_of_fame.asm
deleted file mode 100755
index 3c9b1723..00000000
--- a/engine/hall_of_fame.asm
+++ /dev/null
@@ -1,288 +0,0 @@
-AnimateHallOfFame:
- call HoFFadeOutScreenAndMusic
- call ClearScreen
- ld c, 100
- call DelayFrames
- call LoadFontTilePatterns
- call LoadTextBoxTilePatterns
- call DisableLCD
- ld hl, vBGMap0
- ld bc, $800
- ld a, " "
- call FillMemory
- call EnableLCD
- ld hl, rLCDC
- set 3, [hl]
- xor a
- ld hl, wHallOfFame
- ld bc, HOF_TEAM
- call FillMemory
- xor a
- ld [wUpdateSpritesEnabled], a
- ld [hTilesetType], a
- ld [wSpriteFlipped], a
- ld [wLetterPrintingDelayFlags], a ; no delay
- ld [wHoFMonOrPlayer], a ; mon
- inc a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld hl, wNumHoFTeams
- ld a, [hl]
- inc a
- jr z, .skipInc ; don't wrap around to 0
- inc [hl]
-.skipInc
- ld a, $90
- ld [hWY], a
- ld c, BANK(Music_HallOfFame)
- ld a, MUSIC_HALL_OF_FAME
- call PlayMusic
- ld hl, wPartySpecies
- ld c, $ff
-.partyMonLoop
- ld a, [hli]
- cp $ff
- jr z, .doneShowingParty
- inc c
- push hl
- push bc
- ld [wHoFMonSpecies], a
- ld a, c
- ld [wHoFPartyMonIndex], a
- ld hl, wPartyMon1Level
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hl]
- ld [wHoFMonLevel], a
- call HoFShowMonOrPlayer
- call HoFDisplayAndRecordMonInfo
- ld c, 80
- call DelayFrames
- coord hl, 2, 13
- ld b, 3
- ld c, 14
- call TextBoxBorder
- coord hl, 4, 15
- ld de, HallOfFameText
- call PlaceString
- ld c, 180
- call DelayFrames
- call GBFadeOutToWhite
- pop bc
- pop hl
- jr .partyMonLoop
-.doneShowingParty
- ld a, c
- inc a
- ld hl, wHallOfFame
- ld bc, HOF_MON
- call AddNTimes
- ld [hl], $ff
- call SaveHallOfFameTeams
- xor a
- ld [wHoFMonSpecies], a
- inc a
- ld [wHoFMonOrPlayer], a ; player
- call HoFShowMonOrPlayer
- call HoFDisplayPlayerStats
- call HoFFadeOutScreenAndMusic
- xor a
- ld [hWY], a
- ld hl, rLCDC
- res 3, [hl]
- ret
-
-HallOfFameText:
- db "HALL OF FAME@"
-
-HoFShowMonOrPlayer:
- call ClearScreen
- ld a, $d0
- ld [hSCY], a
- ld a, $c0
- ld [hSCX], a
- ld a, [wHoFMonSpecies]
- ld [wcf91], a
- ld [wd0b5], a
- ld [wBattleMonSpecies2], a
- ld [wWholeScreenPaletteMonSpecies], a
- ld a, [wHoFMonOrPlayer]
- and a
- jr z, .showMon
-; show player
- call HoFLoadPlayerPics
- jr .next1
-.showMon
- coord hl, 12, 5
- call GetMonHeader
- call LoadFrontSpriteByMonIndex
- predef LoadMonBackPic
-.next1
- ld b, SET_PAL_POKEMON_WHOLE_SCREEN
- ld c, 0
- call RunPaletteCommand
- ld a, %11100100
- ld [rBGP], a
- ld c, $31 ; back pic
- call HoFLoadMonPlayerPicTileIDs
- ld d, $a0
- ld e, 4
- ld a, [wOnSGB]
- and a
- jr z, .next2
- sla e ; scroll more slowly on SGB
-.next2
- call .ScrollPic ; scroll back pic left
- xor a
- ld [hSCY], a
- ld c, a ; front pic
- call HoFLoadMonPlayerPicTileIDs
- ld d, 0
- ld e, -4
-; scroll front pic right
-
-.ScrollPic
- call DelayFrame
- ld a, [hSCX]
- add e
- ld [hSCX], a
- cp d
- jr nz, .ScrollPic
- ret
-
-HoFDisplayAndRecordMonInfo:
- ld a, [wHoFPartyMonIndex]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- call HoFDisplayMonInfo
- jp HoFRecordMonInfo
-
-HoFDisplayMonInfo:
- coord hl, 0, 2
- ld b, 9
- ld c, 10
- call TextBoxBorder
- coord hl, 2, 6
- ld de, HoFMonInfoText
- call PlaceString
- coord hl, 1, 4
- ld de, wcd6d
- call PlaceString
- ld a, [wHoFMonLevel]
- coord hl, 8, 7
- call PrintLevelCommon
- ld a, [wHoFMonSpecies]
- ld [wd0b5], a
- coord hl, 3, 9
- predef PrintMonType
- ld a, [wHoFMonSpecies]
- jp PlayCry
-
-HoFMonInfoText:
- db "LEVEL/"
- next "TYPE1/"
- next "TYPE2/@"
-
-HoFLoadPlayerPics:
- ld de, RedPicFront
- ld a, BANK(RedPicFront)
- call UncompressSpriteFromDE
- ld hl, sSpriteBuffer1
- ld de, sSpriteBuffer0
- ld bc, $310
- call CopyData
- ld de, vFrontPic
- call InterlaceMergeSpriteBuffers
- ld de, RedPicBack
- ld a, BANK(RedPicBack)
- call UncompressSpriteFromDE
- predef ScaleSpriteByTwo
- ld de, vBackPic
- call InterlaceMergeSpriteBuffers
- ld c, $1
-
-HoFLoadMonPlayerPicTileIDs:
-; c = base tile ID
- ld b, 0
- coord hl, 12, 5
- predef_jump CopyTileIDsFromList
-
-HoFDisplayPlayerStats:
- SetEvent EVENT_HALL_OF_FAME_DEX_RATING
- predef DisplayDexRating
- coord hl, 0, 4
- ld b, 6
- ld c, 10
- call TextBoxBorder
- coord hl, 5, 0
- ld b, 2
- ld c, 9
- call TextBoxBorder
- coord hl, 7, 2
- ld de, wPlayerName
- call PlaceString
- coord hl, 1, 6
- ld de, HoFPlayTimeText
- call PlaceString
- coord hl, 5, 7
- ld de, wPlayTimeHours
- lb bc, 1, 3
- call PrintNumber
- ld [hl], $6d
- inc hl
- ld de, wPlayTimeMinutes
- lb bc, LEADING_ZEROES | 1, 2
- call PrintNumber
- coord hl, 1, 9
- ld de, HoFMoneyText
- call PlaceString
- coord hl, 4, 10
- ld de, wPlayerMoney
- ld c, $a3
- call PrintBCDNumber
- ld hl, DexSeenOwnedText
- call HoFPrintTextAndDelay
- ld hl, DexRatingText
- call HoFPrintTextAndDelay
- ld hl, wDexRatingText
-
-HoFPrintTextAndDelay:
- call PrintText
- ld c, 120
- jp DelayFrames
-
-HoFPlayTimeText:
- db "PLAY TIME@"
-
-HoFMoneyText:
- db "MONEY@"
-
-DexSeenOwnedText:
- TX_FAR _DexSeenOwnedText
- db "@"
-
-DexRatingText:
- TX_FAR _DexRatingText
- db "@"
-
-HoFRecordMonInfo:
- ld hl, wHallOfFame
- ld bc, HOF_MON
- ld a, [wHoFPartyMonIndex]
- call AddNTimes
- ld a, [wHoFMonSpecies]
- ld [hli], a
- ld a, [wHoFMonLevel]
- ld [hli], a
- ld e, l
- ld d, h
- ld hl, wcd6d
- ld bc, NAME_LENGTH
- jp CopyData
-
-HoFFadeOutScreenAndMusic:
- ld a, 10
- ld [wAudioFadeOutCounterReloadValue], a
- ld [wAudioFadeOutCounter], a
- ld a, $ff
- ld [wAudioFadeOutControl], a
- jp GBFadeOutToWhite
diff --git a/engine/hidden_object_functions17.asm b/engine/hidden_object_functions17.asm
deleted file mode 100755
index c1fa5aa4..00000000
--- a/engine/hidden_object_functions17.asm
+++ /dev/null
@@ -1,475 +0,0 @@
-PrintRedSNESText:
- call EnableAutoTextBoxDrawing
- tx_pre_jump RedBedroomSNESText
-
-RedBedroomSNESText:
- TX_FAR _RedBedroomSNESText
- db "@"
-
-OpenRedsPC:
- call EnableAutoTextBoxDrawing
- tx_pre_jump RedBedroomPCText
-
-RedBedroomPCText:
- TX_PLAYERS_PC
-
-Route15GateLeftBinoculars:
- ld a, [wSpriteStateData1 + 9]
- cp SPRITE_FACING_UP
- ret nz
- call EnableAutoTextBoxDrawing
- tx_pre Route15UpstairsBinocularsText
- ld a, ARTICUNO
- ld [wcf91], a
- call PlayCry
- jp DisplayMonFrontSpriteInBox
-
-Route15UpstairsBinocularsText:
- TX_FAR _Route15UpstairsBinocularsText
- db "@"
-
-AerodactylFossil:
- ld a, FOSSIL_AERODACTYL
- ld [wcf91], a
- call DisplayMonFrontSpriteInBox
- call EnableAutoTextBoxDrawing
- tx_pre AerodactylFossilText
- ret
-
-AerodactylFossilText:
- TX_FAR _AerodactylFossilText
- db "@"
-
-KabutopsFossil:
- ld a, FOSSIL_KABUTOPS
- ld [wcf91], a
- call DisplayMonFrontSpriteInBox
- call EnableAutoTextBoxDrawing
- tx_pre KabutopsFossilText
- ret
-
-KabutopsFossilText:
- TX_FAR _KabutopsFossilText
- db "@"
-
-DisplayMonFrontSpriteInBox:
-; Displays a pokemon's front sprite in a pop-up window.
-; [wcf91] = pokemon internal id number
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- xor a
- ld [hWY], a
- call SaveScreenTilesToBuffer1
- ld a, MON_SPRITE_POPUP
- ld [wTextBoxID], a
- call DisplayTextBoxID
- call UpdateSprites
- ld a, [wcf91]
- ld [wd0b5], a
- call GetMonHeader
- ld de, vChars1 + $310
- call LoadMonFrontSprite
- ld a, $80
- ld [hStartTileID], a
- coord hl, 10, 11
- predef AnimateSendingOutMon
- call WaitForTextScrollButtonPress
- call LoadScreenTilesFromBuffer1
- call Delay3
- ld a, $90
- ld [hWY], a
- ret
-
-PrintBlackboardLinkCableText:
- call EnableAutoTextBoxDrawing
- ld a, $1
- ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- ld a, [wHiddenObjectFunctionArgument]
- call PrintPredefTextID
- ret
-
-LinkCableHelp:
- TX_ASM
- call SaveScreenTilesToBuffer1
- ld hl, LinkCableHelpText1
- call PrintText
- xor a
- ld [wMenuItemOffset], a ; not used
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 3
- ld [wMaxMenuItem], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
-.linkHelpLoop
- ld hl, wd730
- set 6, [hl]
- coord hl, 0, 0
- ld b, 8
- ld c, 13
- call TextBoxBorder
- coord hl, 2, 2
- ld de, HowToLinkText
- call PlaceString
- ld hl, LinkCableHelpText2
- call PrintText
- call HandleMenuInput
- bit 1, a ; pressed b
- jr nz, .exit
- ld a, [wCurrentMenuItem]
- cp 3 ; pressed a on "STOP READING"
- jr z, .exit
- ld hl, wd730
- res 6, [hl]
- ld hl, LinkCableInfoTexts
- add a
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hli]
- ld h, [hl]
- ld l, a
- call PrintText
- jp .linkHelpLoop
-.exit
- ld hl, wd730
- res 6, [hl]
- call LoadScreenTilesFromBuffer1
- jp TextScriptEnd
-
-LinkCableHelpText1:
- TX_FAR _LinkCableHelpText1
- db "@"
-
-LinkCableHelpText2:
- TX_FAR _LinkCableHelpText2
- db "@"
-
-HowToLinkText:
- db "HOW TO LINK"
- next "COLOSSEUM"
- next "TRADE CENTER"
- next "STOP READING@"
-
-LinkCableInfoTexts:
- dw LinkCableInfoText1
- dw LinkCableInfoText2
- dw LinkCableInfoText3
-
-LinkCableInfoText1:
- TX_FAR _LinkCableInfoText1
- db "@"
-
-LinkCableInfoText2:
- TX_FAR _LinkCableInfoText2
- db "@"
-
-LinkCableInfoText3:
- TX_FAR _LinkCableInfoText3
- db "@"
-
-ViridianSchoolBlackboard:
- TX_ASM
- call SaveScreenTilesToBuffer1
- ld hl, ViridianSchoolBlackboardText1
- call PrintText
- xor a
- ld [wMenuItemOffset], a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 2
- ld [wMaxMenuItem], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
-.blackboardLoop
- ld hl, wd730
- set 6, [hl]
- coord hl, 0, 0
- lb bc, 6, 10
- call TextBoxBorder
- coord hl, 1, 2
- ld de, StatusAilmentText1
- call PlaceString
- coord hl, 6, 2
- ld de, StatusAilmentText2
- call PlaceString
- ld hl, ViridianSchoolBlackboardText2
- call PrintText
- call HandleMenuInput ; pressing up and down is handled in here
- bit 1, a ; pressed b
- jr nz, .exitBlackboard
- bit 4, a ; pressed right
- jr z, .didNotPressRight
- ; move cursor to right column
- ld a, 2
- ld [wMaxMenuItem], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 6
- ld [wTopMenuItemX], a
- ld a, 3 ; in the the right column, use an offset to prevent overlap
- ld [wMenuItemOffset], a
- jr .blackboardLoop
-.didNotPressRight
- bit 5, a ; pressed left
- jr z, .didNotPressLeftOrRight
- ; move cursor to left column
- ld a, 2
- ld [wMaxMenuItem], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
- xor a
- ld [wMenuItemOffset], a
- jr .blackboardLoop
-.didNotPressLeftOrRight
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wMenuItemOffset]
- add b
- cp 5 ; cursor is pointing to "QUIT"
- jr z, .exitBlackboard
- ; we must have pressed a on a status condition
- ; so print the text
- ld hl, wd730
- res 6, [hl]
- ld hl, ViridianBlackboardStatusPointers
- add a
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hli]
- ld h, [hl]
- ld l, a
- call PrintText
- jp .blackboardLoop
-.exitBlackboard
- ld hl, wd730
- res 6, [hl]
- call LoadScreenTilesFromBuffer1
- jp TextScriptEnd
-
-ViridianSchoolBlackboardText1:
- TX_FAR _ViridianSchoolBlackboardText1
- db "@"
-
-ViridianSchoolBlackboardText2:
- TX_FAR _ViridianSchoolBlackboardText2
- db "@"
-
-StatusAilmentText1:
- db " SLP"
- next " PSN"
- next " PAR@"
-
-StatusAilmentText2:
- db " BRN"
- next " FRZ"
- next " QUIT@@"
-
-ViridianBlackboardStatusPointers:
- dw ViridianBlackboardSleepText
- dw ViridianBlackboardPoisonText
- dw ViridianBlackboardPrlzText
- dw ViridianBlackboardBurnText
- dw ViridianBlackboardFrozenText
-
-ViridianBlackboardSleepText:
- TX_FAR _ViridianBlackboardSleepText
- db "@"
-
-ViridianBlackboardPoisonText:
- TX_FAR _ViridianBlackboardPoisonText
- db "@"
-
-ViridianBlackboardPrlzText:
- TX_FAR _ViridianBlackboardPrlzText
- db "@"
-
-ViridianBlackboardBurnText:
- TX_FAR _ViridianBlackboardBurnText
- db "@"
-
-ViridianBlackboardFrozenText:
- TX_FAR _ViridianBlackboardFrozenText
- db "@"
-
-PrintTrashText:
- call EnableAutoTextBoxDrawing
- tx_pre_jump VermilionGymTrashText
-
-VermilionGymTrashText:
- TX_FAR _VermilionGymTrashText
- db "@"
-
-GymTrashScript:
- call EnableAutoTextBoxDrawing
- ld a, [wHiddenObjectFunctionArgument]
- ld [wGymTrashCanIndex], a
-
-; Don't do the trash can puzzle if it's already been done.
- CheckEvent EVENT_2ND_LOCK_OPENED
- jr z, .ok
-
- tx_pre_jump VermilionGymTrashText
-
-.ok
- CheckEventReuseA EVENT_1ST_LOCK_OPENED
- jr nz, .trySecondLock
-
- ld a, [wFirstLockTrashCanIndex]
- ld b, a
- ld a, [wGymTrashCanIndex]
- cp b
- jr z, .openFirstLock
-
- tx_pre_id VermilionGymTrashText
- jr .done
-
-.openFirstLock
-; Next can is trying for the second switch.
- SetEvent EVENT_1ST_LOCK_OPENED
-
- ld hl, GymTrashCans
- ld a, [wGymTrashCanIndex]
- ; * 5
- ld b, a
- add a
- add a
- add b
-
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hli]
-
-; There is a bug in this code. It should calculate a value in the range [0, 3]
-; but if the mask and random number don't have any 1 bits in common, then
-; the result of the AND will be 0. When 1 is subtracted from that, the value
-; will become $ff. This will result in 255 being added to hl, which will cause
-; hl to point to one of the zero bytes that pad the end of the ROM bank.
-; Trash can 0 was intended to be able to have the second lock only when the
-; first lock was in trash can 1 or 3. However, due to this bug, trash can 0 can
-; have the second lock regardless of which trash can had the first lock.
-
- ld [hGymTrashCanRandNumMask], a
- push hl
- call Random
- swap a
- ld b, a
- ld a, [hGymTrashCanRandNumMask]
- and b
- dec a
- pop hl
-
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hl]
- and $f
- ld [wSecondLockTrashCanIndex], a
-
- tx_pre_id VermilionGymTrashSuccessText1
- jr .done
-
-.trySecondLock
- ld a, [wSecondLockTrashCanIndex]
- ld b, a
- ld a, [wGymTrashCanIndex]
- cp b
- jr z, .openSecondLock
-
-; Reset the cans.
- ResetEvent EVENT_1ST_LOCK_OPENED
- call Random
-
- and $e
- ld [wFirstLockTrashCanIndex], a
-
- tx_pre_id VermilionGymTrashFailText
- jr .done
-
-.openSecondLock
-; Completed the trash can puzzle.
- SetEvent EVENT_2ND_LOCK_OPENED
- ld hl, wCurrentMapScriptFlags
- set 6, [hl]
-
- tx_pre_id VermilionGymTrashSuccessText3
-
-.done
- jp PrintPredefTextID
-
-GymTrashCans:
-; byte 0: mask for random number
-; bytes 1-4: indices of the trash cans that can have the second lock
-; (but see the comment above explaining a bug regarding this)
-; Note that the mask is simply the number of valid trash can indices that
-; follow. The remaining bytes are filled with 0 to pad the length of each entry
-; to 5 bytes.
- db 2, 1, 3, 0, 0 ; 0
- db 3, 0, 2, 4, 0 ; 1
- db 2, 1, 5, 0, 0 ; 2
- db 3, 0, 4, 6, 0 ; 3
- db 4, 1, 3, 5, 7 ; 4
- db 3, 2, 4, 8, 0 ; 5
- db 3, 3, 7, 9, 0 ; 6
- db 4, 4, 6, 8, 10 ; 7
- db 3, 5, 7, 11, 0 ; 8
- db 3, 6, 10, 12, 0 ; 9
- db 4, 7, 9, 11, 13 ; 10
- db 3, 8, 10, 14, 0 ; 11
- db 2, 9, 13, 0, 0 ; 12
- db 3, 10, 12, 14, 0 ; 13
- db 2, 11, 13, 0, 0 ; 14
-
-VermilionGymTrashSuccessText1:
- TX_FAR _VermilionGymTrashSuccessText1
- TX_ASM
- call WaitForSoundToFinish
- ld a, SFX_SWITCH
- call PlaySound
- call WaitForSoundToFinish
- jp TextScriptEnd
-
-; unused
-VermilionGymTrashSuccessText2:
- TX_FAR _VermilionGymTrashSuccessText2
- db "@"
-
-; unused
-VermilionGymTrashSuccesPlaySfx:
- TX_ASM
- call WaitForSoundToFinish
- ld a, SFX_SWITCH
- call PlaySound
- call WaitForSoundToFinish
- jp TextScriptEnd
-
-VermilionGymTrashSuccessText3:
- TX_FAR _VermilionGymTrashSuccessText3
- TX_ASM
- call WaitForSoundToFinish
- ld a, SFX_GO_INSIDE
- call PlaySound
- call WaitForSoundToFinish
- jp TextScriptEnd
-
-VermilionGymTrashFailText:
- TX_FAR _VermilionGymTrashFailText
- TX_ASM
- call WaitForSoundToFinish
- ld a, SFX_DENIED
- call PlaySound
- call WaitForSoundToFinish
- jp TextScriptEnd
diff --git a/engine/hidden_object_functions7.asm b/engine/hidden_object_functions7.asm
deleted file mode 100755
index f04c1deb..00000000
--- a/engine/hidden_object_functions7.asm
+++ /dev/null
@@ -1,467 +0,0 @@
-PrintNewBikeText:
- call EnableAutoTextBoxDrawing
- tx_pre_jump NewBicycleText
-
-NewBicycleText:
- TX_FAR _NewBicycleText
- db "@"
-
-DisplayOakLabLeftPoster:
- call EnableAutoTextBoxDrawing
- tx_pre_jump PushStartText
-
-PushStartText:
- TX_FAR _PushStartText
- db "@"
-
-DisplayOakLabRightPoster:
- call EnableAutoTextBoxDrawing
- ld hl, wPokedexOwned
- ld b, wPokedexOwnedEnd - wPokedexOwned
- call CountSetBits
- ld a, [wNumSetBits]
- cp 2
- tx_pre_id SaveOptionText
- jr c, .ownLessThanTwo
- ; own two or more mon
- tx_pre_id StrengthsAndWeaknessesText
-.ownLessThanTwo
- jp PrintPredefTextID
-
-SaveOptionText:
- TX_FAR _SaveOptionText
- db "@"
-
-StrengthsAndWeaknessesText:
- TX_FAR _StrengthsAndWeaknessesText
- db "@"
-
-SafariZoneCheck:
- CheckEventHL EVENT_IN_SAFARI_ZONE ; if we are not in the Safari Zone,
- jr z, SafariZoneGameStillGoing ; don't bother printing game over text
- ld a, [wNumSafariBalls]
- and a
- jr z, SafariZoneGameOver
- jr SafariZoneGameStillGoing
-
-SafariZoneCheckSteps:
- ld a, [wSafariSteps]
- ld b, a
- ld a, [wSafariSteps + 1]
- ld c, a
- or b
- jr z, SafariZoneGameOver
- dec bc
- ld a, b
- ld [wSafariSteps], a
- ld a, c
- ld [wSafariSteps + 1], a
-SafariZoneGameStillGoing:
- xor a
- ld [wSafariZoneGameOver], a
- ret
-
-SafariZoneGameOver:
- call EnableAutoTextBoxDrawing
- xor a
- ld [wAudioFadeOutControl], a
- dec a
- call PlaySound
- ld c, BANK(SFX_Safari_Zone_PA)
- ld a, SFX_SAFARI_ZONE_PA
- call PlayMusic
-.waitForMusicToPlay
- ld a, [wChannelSoundIDs + Ch4]
- cp SFX_SAFARI_ZONE_PA
- jr nz, .waitForMusicToPlay
- ld a, TEXT_SAFARI_GAME_OVER
- ld [hSpriteIndexOrTextID], a
- call DisplayTextID
- xor a
- ld [wPlayerMovingDirection], a
- ld a, SAFARI_ZONE_ENTRANCE
- ld [hWarpDestinationMap], a
- ld a, $3
- ld [wDestinationWarpID], a
- ld a, $5
- ld [wSafariZoneEntranceCurScript], a
- SetEvent EVENT_SAFARI_GAME_OVER
- ld a, 1
- ld [wSafariZoneGameOver], a
- ret
-
-PrintSafariGameOverText:
- xor a
- ld [wJoyIgnore], a
- ld hl, SafariGameOverText
- jp PrintText
-
-SafariGameOverText:
- TX_ASM
- ld a, [wNumSafariBalls]
- and a
- jr z, .noMoreSafariBalls
- ld hl, TimesUpText
- call PrintText
-.noMoreSafariBalls
- ld hl, GameOverText
- call PrintText
- jp TextScriptEnd
-
-TimesUpText:
- TX_FAR _TimesUpText
- db "@"
-
-GameOverText:
- TX_FAR _GameOverText
- db "@"
-
-PrintCinnabarQuiz:
- ld a, [wSpriteStateData1 + 9]
- cp SPRITE_FACING_UP
- ret nz
- call EnableAutoTextBoxDrawing
- tx_pre_jump CinnabarGymQuiz
-
-CinnabarGymQuiz:
- TX_ASM
- xor a
- ld [wOpponentAfterWrongAnswer], a
- ld a, [wHiddenObjectFunctionArgument]
- push af
- and $f
- ld [hGymGateIndex], a
- pop af
- and $f0
- swap a
- ld [$ffdc], a
- ld hl, CinnabarGymQuizIntroText
- call PrintText
- ld a, [hGymGateIndex]
- dec a
- add a
- ld d, 0
- ld e, a
- ld hl, CinnabarQuizQuestions
- add hl, de
- ld a, [hli]
- ld h, [hl]
- ld l, a
- call PrintText
- ld a, 1
- ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- call CinnabarGymQuiz_1ea92
- jp TextScriptEnd
-
-CinnabarGymQuizIntroText:
- TX_FAR _CinnabarGymQuizIntroText
- db "@"
-
-CinnabarQuizQuestions:
- dw CinnabarQuizQuestionsText1
- dw CinnabarQuizQuestionsText2
- dw CinnabarQuizQuestionsText3
- dw CinnabarQuizQuestionsText4
- dw CinnabarQuizQuestionsText5
- dw CinnabarQuizQuestionsText6
-
-CinnabarQuizQuestionsText1:
- TX_FAR _CinnabarQuizQuestionsText1
- db "@"
-
-CinnabarQuizQuestionsText2:
- TX_FAR _CinnabarQuizQuestionsText2
- db "@"
-
-CinnabarQuizQuestionsText3:
- TX_FAR _CinnabarQuizQuestionsText3
- db "@"
-
-CinnabarQuizQuestionsText4:
- TX_FAR _CinnabarQuizQuestionsText4
- db "@"
-
-CinnabarQuizQuestionsText5:
- TX_FAR _CinnabarQuizQuestionsText5
- db "@"
-
-CinnabarQuizQuestionsText6:
- TX_FAR _CinnabarQuizQuestionsText6
- db "@"
-
-CinnabarGymGateFlagAction:
- EventFlagAddress hl, EVENT_CINNABAR_GYM_GATE0_UNLOCKED
- predef_jump FlagActionPredef
-
-CinnabarGymQuiz_1ea92:
- call YesNoChoice
- ld a, [$ffdc]
- ld c, a
- ld a, [wCurrentMenuItem]
- cp c
- jr nz, .wrongAnswer
- ld hl, wCurrentMapScriptFlags
- set 5, [hl]
- ld a, [hGymGateIndex]
- ld [$ffe0], a
- ld hl, CinnabarGymQuizCorrectText
- call PrintText
- ld a, [$ffe0]
- AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0
- ld c, a
- ld b, FLAG_SET
- call CinnabarGymGateFlagAction
- jp UpdateCinnabarGymGateTileBlocks_
-.wrongAnswer
- call WaitForSoundToFinish
- ld a, SFX_DENIED
- call PlaySound
- call WaitForSoundToFinish
- ld hl, CinnabarGymQuizIncorrectText
- call PrintText
- ld a, [hGymGateIndex]
- add $2
- AdjustEventBit EVENT_BEAT_CINNABAR_GYM_TRAINER_0, 2
- ld c, a
- ld b, FLAG_TEST
- EventFlagAddress hl, EVENT_BEAT_CINNABAR_GYM_TRAINER_0
- predef FlagActionPredef
- ld a, c
- and a
- ret nz
- ld a, [hGymGateIndex]
- add $2
- ld [wOpponentAfterWrongAnswer], a
- ret
-
-CinnabarGymQuizCorrectText:
- TX_SFX_ITEM_1
- TX_FAR _CinnabarGymQuizCorrectText
- TX_BLINK
- TX_ASM
-
- ld a, [$ffe0]
- AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0
- ld c, a
- ld b, FLAG_TEST
- call CinnabarGymGateFlagAction
- ld a, c
- and a
- jp nz, TextScriptEnd
- call WaitForSoundToFinish
- ld a, SFX_GO_INSIDE
- call PlaySound
- call WaitForSoundToFinish
- jp TextScriptEnd
-
-CinnabarGymQuizIncorrectText:
- TX_FAR _CinnabarGymQuizIncorrectText
- db "@"
-
-UpdateCinnabarGymGateTileBlocks_:
-; Update the overworld map with open floor blocks or locked gate blocks
-; depending on event flags.
- ld a, 6
- ld [hGymGateIndex], a
-.loop
- ld a, [hGymGateIndex]
- dec a
- add a
- add a
- ld d, 0
- ld e, a
- ld hl, CinnabarGymGateCoords
- add hl, de
- ld a, [hli]
- ld b, [hl]
- ld c, a
- inc hl
- ld a, [hl]
- ld [wGymGateTileBlock], a
- push bc
- ld a, [hGymGateIndex]
- ld [$ffe0], a
- AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0
- ld c, a
- ld b, FLAG_TEST
- call CinnabarGymGateFlagAction
- ld a, c
- and a
- jr nz, .unlocked
- ld a, [wGymGateTileBlock]
- jr .next
-.unlocked
- ld a, $e
-.next
- pop bc
- ld [wNewTileBlockID], a
- predef ReplaceTileBlock
- ld hl, hGymGateIndex
- dec [hl]
- jr nz, .loop
- ret
-
-CinnabarGymGateCoords:
- ; format: x-coord, y-coord, direction, padding
- ; direction: $54 = horizontal gate, $5f = vertical gate
- db $09,$03,$54,$00
- db $06,$03,$54,$00
- db $06,$06,$54,$00
- db $03,$08,$5f,$00
- db $02,$06,$54,$00
- db $02,$03,$54,$00
-
-PrintMagazinesText:
- call EnableAutoTextBoxDrawing
- tx_pre MagazinesText
- ret
-
-MagazinesText:
- TX_FAR _MagazinesText
- db "@"
-
-BillsHousePC:
- call EnableAutoTextBoxDrawing
- ld a, [wSpriteStateData1 + 9]
- cp SPRITE_FACING_UP
- ret nz
- CheckEvent EVENT_LEFT_BILLS_HOUSE_AFTER_HELPING
- jr nz, .displayBillsHousePokemonList
- CheckEventReuseA EVENT_USED_CELL_SEPARATOR_ON_BILL
- jr nz, .displayBillsHouseMonitorText
- CheckEventReuseA EVENT_BILL_SAID_USE_CELL_SEPARATOR
- jr nz, .doCellSeparator
-.displayBillsHouseMonitorText
- tx_pre_jump BillsHouseMonitorText
-.doCellSeparator
- ld a, $1
- ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- tx_pre BillsHouseInitiatedText
- ld c, 32
- call DelayFrames
- ld a, SFX_TINK
- call PlaySound
- call WaitForSoundToFinish
- ld c, 80
- call DelayFrames
- ld a, SFX_SHRINK
- call PlaySound
- call WaitForSoundToFinish
- ld c, 48
- call DelayFrames
- ld a, SFX_TINK
- call PlaySound
- call WaitForSoundToFinish
- ld c, 32
- call DelayFrames
- ld a, SFX_GET_ITEM_1
- call PlaySound
- call WaitForSoundToFinish
- call PlayDefaultMusic
- SetEvent EVENT_USED_CELL_SEPARATOR_ON_BILL
- ret
-.displayBillsHousePokemonList
- ld a, $1
- ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- tx_pre BillsHousePokemonList
- ret
-
-BillsHouseMonitorText:
- TX_FAR _BillsHouseMonitorText
- db "@"
-
-BillsHouseInitiatedText:
- TX_FAR _BillsHouseInitiatedText
- TX_BLINK
- TX_ASM
- ld a, $ff
- ld [wNewSoundID], a
- call PlaySound
- ld c, 16
- call DelayFrames
- ld a, SFX_SWITCH
- call PlaySound
- call WaitForSoundToFinish
- ld c, 60
- call DelayFrames
- jp TextScriptEnd
-
-BillsHousePokemonList:
- TX_ASM
- call SaveScreenTilesToBuffer1
- ld hl, BillsHousePokemonListText1
- call PrintText
- xor a
- ld [wMenuItemOffset], a ; not used
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 4
- ld [wMaxMenuItem], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
-.billsPokemonLoop
- ld hl, wd730
- set 6, [hl]
- coord hl, 0, 0
- ld b, 10
- ld c, 9
- call TextBoxBorder
- coord hl, 2, 2
- ld de, BillsMonListText
- call PlaceString
- ld hl, BillsHousePokemonListText2
- call PrintText
- call SaveScreenTilesToBuffer2
- call HandleMenuInput
- bit 1, a ; pressed b
- jr nz, .cancel
- ld a, [wCurrentMenuItem]
- add EEVEE
- cp EEVEE
- jr z, .displayPokedex
- cp FLAREON
- jr z, .displayPokedex
- cp JOLTEON
- jr z, .displayPokedex
- cp VAPOREON
- jr z, .displayPokedex
- jr .cancel
-.displayPokedex
- call DisplayPokedex
- call LoadScreenTilesFromBuffer2
- jr .billsPokemonLoop
-.cancel
- ld hl, wd730
- res 6, [hl]
- call LoadScreenTilesFromBuffer2
- jp TextScriptEnd
-
-BillsHousePokemonListText1:
- TX_FAR _BillsHousePokemonListText1
- db "@"
-
-BillsMonListText:
- db "EEVEE"
- next "FLAREON"
- next "JOLTEON"
- next "VAPOREON"
- next "CANCEL@"
-
-BillsHousePokemonListText2:
- TX_FAR _BillsHousePokemonListText2
- db "@"
-
-DisplayOakLabEmailText:
- ld a, [wSpriteStateData1 + 9]
- cp SPRITE_FACING_UP
- ret nz
- call EnableAutoTextBoxDrawing
- tx_pre_jump OakLabEmailText
-
-OakLabEmailText:
- TX_FAR _OakLabEmailText
- db "@"
diff --git a/engine/in_game_trades.asm b/engine/in_game_trades.asm
index c01bc3c3..1563e72f 100755
--- a/engine/in_game_trades.asm
+++ b/engine/in_game_trades.asm
@@ -84,7 +84,7 @@ InGameTrade_GetMonName:
ld bc, NAME_LENGTH
jp CopyData
-INCLUDE "data/trades.asm"
+ inclang data/trades.asm
InGameTrade_DoTrade:
xor a ; NORMAL_PARTY_MENU
diff --git a/engine/items/items.asm b/engine/items/items.asm
deleted file mode 100755
index 3bb2ec9e..00000000
--- a/engine/items/items.asm
+++ /dev/null
@@ -1,2989 +0,0 @@
-UseItem_:
- ld a, 1
- ld [wActionResultOrTookBattleTurn], a ; initialise to success value
- ld a, [wcf91] ;contains item_ID
- cp HM_01
- jp nc, ItemUseTMHM
- ld hl, ItemUsePtrTable
- dec a
- add a
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- jp hl
-
-ItemUsePtrTable:
- dw ItemUseBall ; MASTER_BALL
- dw ItemUseBall ; ULTRA_BALL
- dw ItemUseBall ; GREAT_BALL
- dw ItemUseBall ; POKE_BALL
- dw ItemUseTownMap ; TOWN_MAP
- dw ItemUseBicycle ; BICYCLE
- dw ItemUseSurfboard ; out-of-battle Surf effect
- dw ItemUseBall ; SAFARI_BALL
- dw ItemUsePokedex ; POKEDEX
- dw ItemUseEvoStone ; MOON_STONE
- dw ItemUseMedicine ; ANTIDOTE
- dw ItemUseMedicine ; BURN_HEAL
- dw ItemUseMedicine ; ICE_HEAL
- dw ItemUseMedicine ; AWAKENING
- dw ItemUseMedicine ; PARLYZ_HEAL
- dw ItemUseMedicine ; FULL_RESTORE
- dw ItemUseMedicine ; MAX_POTION
- dw ItemUseMedicine ; HYPER_POTION
- dw ItemUseMedicine ; SUPER_POTION
- dw ItemUseMedicine ; POTION
- dw ItemUseBait ; BOULDERBADGE
- dw ItemUseRock ; CASCADEBADGE
- dw UnusableItem ; THUNDERBADGE
- dw UnusableItem ; RAINBOWBADGE
- dw UnusableItem ; SOULBADGE
- dw UnusableItem ; MARSHBADGE
- dw UnusableItem ; VOLCANOBADGE
- dw UnusableItem ; EARTHBADGE
- dw ItemUseEscapeRope ; ESCAPE_ROPE
- dw ItemUseRepel ; REPEL
- dw UnusableItem ; OLD_AMBER
- dw ItemUseEvoStone ; FIRE_STONE
- dw ItemUseEvoStone ; THUNDER_STONE
- dw ItemUseEvoStone ; WATER_STONE
- dw ItemUseVitamin ; HP_UP
- dw ItemUseVitamin ; PROTEIN
- dw ItemUseVitamin ; IRON
- dw ItemUseVitamin ; CARBOS
- dw ItemUseVitamin ; CALCIUM
- dw ItemUseVitamin ; RARE_CANDY
- dw UnusableItem ; DOME_FOSSIL
- dw UnusableItem ; HELIX_FOSSIL
- dw UnusableItem ; SECRET_KEY
- dw UnusableItem
- dw UnusableItem ; BIKE_VOUCHER
- dw ItemUseXAccuracy ; X_ACCURACY
- dw ItemUseEvoStone ; LEAF_STONE
- dw ItemUseCardKey ; CARD_KEY
- dw UnusableItem ; NUGGET
- dw UnusableItem ; ??? PP_UP
- dw ItemUsePokedoll ; POKE_DOLL
- dw ItemUseMedicine ; FULL_HEAL
- dw ItemUseMedicine ; REVIVE
- dw ItemUseMedicine ; MAX_REVIVE
- dw ItemUseGuardSpec ; GUARD_SPEC
- dw ItemUseSuperRepel ; SUPER_REPL
- dw ItemUseMaxRepel ; MAX_REPEL
- dw ItemUseDireHit ; DIRE_HIT
- dw UnusableItem ; COIN
- dw ItemUseMedicine ; FRESH_WATER
- dw ItemUseMedicine ; SODA_POP
- dw ItemUseMedicine ; LEMONADE
- dw UnusableItem ; S_S_TICKET
- dw UnusableItem ; GOLD_TEETH
- dw ItemUseXStat ; X_ATTACK
- dw ItemUseXStat ; X_DEFEND
- dw ItemUseXStat ; X_SPEED
- dw ItemUseXStat ; X_SPECIAL
- dw ItemUseCoinCase ; COIN_CASE
- dw ItemUseOaksParcel ; OAKS_PARCEL
- dw ItemUseItemfinder ; ITEMFINDER
- dw UnusableItem ; SILPH_SCOPE
- dw ItemUsePokeflute ; POKE_FLUTE
- dw UnusableItem ; LIFT_KEY
- dw UnusableItem ; EXP_ALL
- dw ItemUseOldRod ; OLD_ROD
- dw ItemUseGoodRod ; GOOD_ROD
- dw ItemUseSuperRod ; SUPER_ROD
- dw ItemUsePPUp ; PP_UP (real one)
- dw ItemUsePPRestore ; ETHER
- dw ItemUsePPRestore ; MAX_ETHER
- dw ItemUsePPRestore ; ELIXER
- dw ItemUsePPRestore ; MAX_ELIXER
-
-ItemUseBall:
-
-; Balls can't be used out of battle.
- ld a, [wIsInBattle]
- and a
- jp z, ItemUseNotTime
-
-; Balls can't catch trainers' Pokémon.
- dec a
- jp nz, ThrowBallAtTrainerMon
-
-; If this is for the old man battle, skip checking if the party & box are full.
- ld a, [wBattleType]
- dec a
- jr z, .canUseBall
-
- ld a, [wPartyCount] ; is party full?
- cp PARTY_LENGTH
- jr nz, .canUseBall
- ld a, [wNumInBox] ; is box full?
- cp MONS_PER_BOX
- jp z, BoxFullCannotThrowBall
-
-.canUseBall
- xor a
- ld [wCapturedMonSpecies], a
-
- ld a, [wBattleType]
- cp BATTLE_TYPE_SAFARI
- jr nz, .skipSafariZoneCode
-
-.safariZone
- ld hl, wNumSafariBalls
- dec [hl] ; remove a Safari Ball
-
-.skipSafariZoneCode
- call RunDefaultPaletteCommand
-
- ld a, $43 ; successful capture value
- ld [wPokeBallAnimData], a
-
- call LoadScreenTilesFromBuffer1
- ld hl, ItemUseText00
- call PrintText
-
-; If the player is fighting an unidentified ghost, set the value that indicates
-; the Pokémon can't be caught and skip the capture calculations.
- callab IsGhostBattle
- ld b, $10 ; can't be caught value
- jp z, .setAnimData
-
- ld a, [wBattleType]
- dec a
- jr nz, .notOldManBattle
-
-.oldManBattle
- ld hl, wGrassRate
- ld de, wPlayerName
- ld bc, NAME_LENGTH
- call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch)
- jp .captured
-
-.notOldManBattle
-; If the player is fighting the ghost Marowak, set the value that indicates the
-; Pokémon can't be caught and skip the capture calculations.
- ld a, [wCurMap]
- cp POKEMONTOWER_6
- jr nz, .loop
- ld a, [wEnemyMonSpecies2]
- cp MAROWAK
- ld b, $10 ; can't be caught value
- jp z, .setAnimData
-
-; Get the first random number. Let it be called Rand1.
-; Rand1 must be within a certain range according the kind of ball being thrown.
-; The ranges are as follows.
-; Poké Ball: [0, 255]
-; Great Ball: [0, 200]
-; Ultra/Safari Ball: [0, 150]
-; Loop until an acceptable number is found.
-
-.loop
- call Random
- ld b, a
-
-; Get the item ID.
- ld hl, wcf91
- ld a, [hl]
-
-; The Master Ball always succeeds.
- cp MASTER_BALL
- jp z, .captured
-
-; Anything will do for the basic Poké Ball.
- cp POKE_BALL
- jr z, .checkForAilments
-
-; If it's a Great/Ultra/Safari Ball and Rand1 is greater than 200, try again.
- ld a, 200
- cp b
- jr c, .loop
-
-; Less than or equal to 200 is good enough for a Great Ball.
- ld a, [hl]
- cp GREAT_BALL
- jr z, .checkForAilments
-
-; If it's an Ultra/Safari Ball and Rand1 is greater than 150, try again.
- ld a, 150
- cp b
- jr c, .loop
-
-.checkForAilments
-; Pokémon can be caught more easily with a status ailment.
-; Depending on the status ailment, a certain value will be subtracted from
-; Rand1. Let this value be called Status.
-; The larger Status is, the more easily the Pokémon can be caught.
-; no status ailment: Status = 0
-; Burn/Paralysis/Poison: Status = 12
-; Freeze/Sleep: Status = 25
-; If Status is greater than Rand1, the Pokémon will be caught for sure.
- ld a, [wEnemyMonStatus]
- and a
- jr z, .skipAilmentValueSubtraction ; no ailments
- and 1 << FRZ | SLP
- ld c, 12
- jr z, .notFrozenOrAsleep
- ld c, 25
-.notFrozenOrAsleep
- ld a, b
- sub c
- jp c, .captured
- ld b, a
-
-.skipAilmentValueSubtraction
- push bc ; save (Rand1 - Status)
-
-; Calculate MaxHP * 255.
- xor a
- ld [H_MULTIPLICAND], a
- ld hl, wEnemyMonMaxHP
- ld a, [hli]
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [H_MULTIPLICAND + 2], a
- ld a, 255
- ld [H_MULTIPLIER], a
- call Multiply
-
-; Determine BallFactor. It's 8 for Great Balls and 12 for the others.
- ld a, [wcf91]
- cp GREAT_BALL
- ld a, 12
- jr nz, .skip1
- ld a, 8
-
-.skip1
-; Note that the results of all division operations are floored.
-
-; Calculate (MaxHP * 255) / BallFactor.
- ld [H_DIVISOR], a
- ld b, 4 ; number of bytes in dividend
- call Divide
-
-; Divide the enemy's current HP by 4. HP is not supposed to exceed 999 so
-; the result should fit in a. If the division results in a quotient of 0,
-; change it to 1.
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld b, a
- ld a, [hl]
- srl b
- rr a
- srl b
- rr a
- and a
- jr nz, .skip2
- inc a
-
-.skip2
-; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W.
- ld [H_DIVISOR], a
- ld b, 4
- call Divide
-
-; If W > 255, store 255 in [H_QUOTIENT + 3].
-; Let X = min(W, 255) = [H_QUOTIENT + 3].
- ld a, [H_QUOTIENT + 2]
- and a
- jr z, .skip3
- ld a, 255
- ld [H_QUOTIENT + 3], a
-
-.skip3
- pop bc ; b = Rand1 - Status
-
-; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon.
- ld a, [wEnemyMonActualCatchRate]
- cp b
- jr c, .failedToCapture
-
-; If W > 255, the ball captures the Pokémon.
- ld a, [H_QUOTIENT + 2]
- and a
- jr nz, .captured
-
- call Random ; Let this random number be called Rand2.
-
-; If Rand2 > X, the ball fails to capture the Pokémon.
- ld b, a
- ld a, [H_QUOTIENT + 3]
- cp b
- jr c, .failedToCapture
-
-.captured
- jr .skipShakeCalculations
-
-.failedToCapture
- ld a, [H_QUOTIENT + 3]
- ld [wPokeBallCaptureCalcTemp], a ; Save X.
-
-; Calculate CatchRate * 100.
- xor a
- ld [H_MULTIPLICAND], a
- ld [H_MULTIPLICAND + 1], a
- ld a, [wEnemyMonActualCatchRate]
- ld [H_MULTIPLICAND + 2], a
- ld a, 100
- ld [H_MULTIPLIER], a
- call Multiply
-
-; Determine BallFactor2.
-; Poké Ball: BallFactor2 = 255
-; Great Ball: BallFactor2 = 200
-; Ultra/Safari Ball: BallFactor2 = 150
- ld a, [wcf91]
- ld b, 255
- cp POKE_BALL
- jr z, .skip4
- ld b, 200
- cp GREAT_BALL
- jr z, .skip4
- ld b, 150
- cp ULTRA_BALL
- jr z, .skip4
-
-.skip4
-; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y.
- ld a, b
- ld [H_DIVISOR], a
- ld b, 4
- call Divide
-
-; If Y > 255, there are 3 shakes.
-; Note that this shouldn't be possible.
-; The maximum value of Y is (255 * 100) / 150 = 170.
- ld a, [H_QUOTIENT + 2]
- and a
- ld b, $63 ; 3 shakes
- jr nz, .setAnimData
-
-; Calculate X * Y.
- ld a, [wPokeBallCaptureCalcTemp]
- ld [H_MULTIPLIER], a
- call Multiply
-
-; Calculate (X * Y) / 255.
- ld a, 255
- ld [H_DIVISOR], a
- ld b, 4
- call Divide
-
-; Determine Status2.
-; no status ailment: Status2 = 0
-; Burn/Paralysis/Poison: Status2 = 5
-; Freeze/Sleep: Status2 = 10
- ld a, [wEnemyMonStatus]
- and a
- jr z, .skip5
- and 1 << FRZ | SLP
- ld b, 5
- jr z, .addAilmentValue
- ld b, 10
-
-.addAilmentValue
-; If the Pokémon has a status ailment, add Status2.
- ld a, [H_QUOTIENT + 3]
- add b
- ld [H_QUOTIENT + 3], a
-
-.skip5
-; Finally determine the number of shakes.
-; Let Z = ((X * Y) / 255) + Status2 = [H_QUOTIENT + 3].
-; The number of shakes depend on the range Z is in.
-; 0 ≤ Z < 10: 0 shakes (the ball misses)
-; 10 ≤ Z < 30: 1 shake
-; 30 ≤ Z < 70: 2 shakes
-; 70 ≤ Z: 3 shakes
- ld a, [H_QUOTIENT + 3]
- cp 10
- ld b, $20
- jr c, .setAnimData
- cp 30
- ld b, $61
- jr c, .setAnimData
- cp 70
- ld b, $62
- jr c, .setAnimData
- ld b, $63
-
-.setAnimData
- ld a, b
- ld [wPokeBallAnimData], a
-
-.skipShakeCalculations
- ld c, 20
- call DelayFrames
-
-; Do the animation.
- ld a, TOSS_ANIM
- ld [wAnimationID], a
- xor a
- ld [H_WHOSETURN], a
- ld [wAnimationType], a
- ld [wDamageMultipliers], a
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- push af
- predef MoveAnimation
- pop af
- ld [wcf91], a
- pop af
- ld [wWhichPokemon], a
-
-; Determine the message to display from the animation.
- ld a, [wPokeBallAnimData]
- cp $10
- ld hl, ItemUseBallText00
- jp z, .printMessage
- cp $20
- ld hl, ItemUseBallText01
- jp z, .printMessage
- cp $61
- ld hl, ItemUseBallText02
- jp z, .printMessage
- cp $62
- ld hl, ItemUseBallText03
- jp z, .printMessage
- cp $63
- ld hl, ItemUseBallText04
- jp z, .printMessage
-
-; Save current HP.
- ld hl, wEnemyMonHP
- ld a, [hli]
- push af
- ld a, [hli]
- push af
-
-; Save status ailment.
- inc hl
- ld a, [hl]
- push af
-
- push hl
-
-; If the Pokémon is transformed, the Pokémon is assumed to be a Ditto.
-; This is a bug because a wild Pokémon could have used Transform via
-; Mirror Move even though the only wild Pokémon that knows Transform is Ditto.
- ld hl, wEnemyBattleStatus3
- bit TRANSFORMED, [hl]
- jr z, .notTransformed
- ld a, DITTO
- ld [wEnemyMonSpecies2], a
- jr .skip6
-
-.notTransformed
-; If the Pokémon is not transformed, set the transformed bit and copy the
-; DVs to wTransformedEnemyMonOriginalDVs so that LoadEnemyMonData won't generate
-; new DVs.
- set TRANSFORMED, [hl]
- ld hl, wTransformedEnemyMonOriginalDVs
- ld a, [wEnemyMonDVs]
- ld [hli], a
- ld a, [wEnemyMonDVs + 1]
- ld [hl], a
-
-.skip6
- ld a, [wcf91]
- push af
- ld a, [wEnemyMonSpecies2]
- ld [wcf91], a
- ld a, [wEnemyMonLevel]
- ld [wCurEnemyLVL], a
- callab LoadEnemyMonData
- pop af
- ld [wcf91], a
- pop hl
- pop af
- ld [hld], a
- dec hl
- pop af
- ld [hld], a
- pop af
- ld [hl], a
- ld a, [wEnemyMonSpecies]
- ld [wCapturedMonSpecies], a
- ld [wcf91], a
- ld [wd11e], a
- ld a, [wBattleType]
- dec a ; is this the old man battle?
- jr z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon
-
- ld hl, ItemUseBallText05
- call PrintText
-
-; Add the caught Pokémon to the Pokédex.
- predef IndexToPokedex
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_TEST
- ld hl, wPokedexOwned
- predef FlagActionPredef
- ld a, c
- push af
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_SET
- predef FlagActionPredef
- pop af
-
- and a ; was the Pokémon already in the Pokédex?
- jr nz, .skipShowingPokedexData ; if so, don't show the Pokédex data
-
- ld hl, ItemUseBallText06
- call PrintText
- call ClearSprites
- ld a, [wEnemyMonSpecies]
- ld [wd11e], a
- predef ShowPokedexData
-
-.skipShowingPokedexData
- ld a, [wPartyCount]
- cp PARTY_LENGTH ; is party full?
- jr z, .sendToBox
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- call ClearSprites
- call AddPartyMon
- jr .done
-
-.sendToBox
- call ClearSprites
- call SendNewMonToBox
- ld hl, ItemUseBallText07
- CheckEvent EVENT_MET_BILL
- jr nz, .printTransferredToPCText
- ld hl, ItemUseBallText08
-.printTransferredToPCText
- call PrintText
- jr .done
-
-.oldManCaughtMon
- ld hl, ItemUseBallText05
-
-.printMessage
- call PrintText
- call ClearSprites
-
-.done
- ld a, [wBattleType]
- and a ; is this the old man battle?
- ret nz ; if so, don't remove a ball from the bag
-
-; Remove a ball from the bag.
- ld hl, wNumBagItems
- inc a
- ld [wItemQuantity], a
- jp RemoveItemFromInventory
-
-ItemUseBallText00:
-;"It dodged the thrown ball!"
-;"This pokemon can't be caught"
- TX_FAR _ItemUseBallText00
- db "@"
-ItemUseBallText01:
-;"You missed the pokemon!"
- TX_FAR _ItemUseBallText01
- db "@"
-ItemUseBallText02:
-;"Darn! The pokemon broke free!"
- TX_FAR _ItemUseBallText02
- db "@"
-ItemUseBallText03:
-;"Aww! It appeared to be caught!"
- TX_FAR _ItemUseBallText03
- db "@"
-ItemUseBallText04:
-;"Shoot! It was so close too!"
- TX_FAR _ItemUseBallText04
- db "@"
-ItemUseBallText05:
-;"All right! {MonName} was caught!"
-;play sound
- TX_FAR _ItemUseBallText05
- TX_SFX_CAUGHT_MON
- TX_BLINK
- db "@"
-ItemUseBallText07:
-;"X was transferred to Bill's PC"
- TX_FAR _ItemUseBallText07
- db "@"
-ItemUseBallText08:
-;"X was transferred to someone's PC"
- TX_FAR _ItemUseBallText08
- db "@"
-
-ItemUseBallText06:
-;"New DEX data will be added..."
-;play sound
- TX_FAR _ItemUseBallText06
- TX_SFX_DEX_PAGE_ADDED
- TX_BLINK
- db "@"
-
-ItemUseTownMap:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- jpba DisplayTownMap
-
-ItemUseBicycle:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- ld a, [wWalkBikeSurfState]
- ld [wWalkBikeSurfStateCopy], a
- cp 2 ; is the player surfing?
- jp z, ItemUseNotTime
- dec a ; is player already bicycling?
- jr nz, .tryToGetOnBike
-.getOffBike
- call ItemUseReloadOverworldData
- xor a
- ld [wWalkBikeSurfState], a ; change player state to walking
- call PlayDefaultMusic ; play walking music
- ld hl, GotOffBicycleText
- jr .printText
-.tryToGetOnBike
- call IsBikeRidingAllowed
- jp nc, NoCyclingAllowedHere
- call ItemUseReloadOverworldData
- xor a ; no keys pressed
- ld [hJoyHeld], a ; current joypad state
- inc a
- ld [wWalkBikeSurfState], a ; change player state to bicycling
- ld hl, GotOnBicycleText
- call PlayDefaultMusic ; play bike riding music
-.printText
- jp PrintText
-
-; used for Surf out-of-battle effect
-ItemUseSurfboard:
- ld a, [wWalkBikeSurfState]
- ld [wWalkBikeSurfStateCopy], a
- cp 2 ; is the player already surfing?
- jr z, .tryToStopSurfing
-.tryToSurf
- call IsNextTileShoreOrWater
- jp c, SurfingAttemptFailed
- ld hl, TilePairCollisionsWater
- call CheckForTilePairCollisions
- jp c, SurfingAttemptFailed
-.surf
- call .makePlayerMoveForward
- ld hl, wd730
- set 7, [hl]
- ld a, 2
- ld [wWalkBikeSurfState], a ; change player state to surfing
- call PlayDefaultMusic ; play surfing music
- ld hl, SurfingGotOnText
- jp PrintText
-.tryToStopSurfing
- xor a
- ld [hSpriteIndexOrTextID], a
- ld d, 16 ; talking range in pixels (normal range)
- call IsSpriteInFrontOfPlayer2
- res 7, [hl]
- ld a, [hSpriteIndexOrTextID]
- and a ; is there a sprite in the way?
- jr nz, .cannotStopSurfing
- ld hl, TilePairCollisionsWater
- call CheckForTilePairCollisions
- jr c, .cannotStopSurfing
- ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles
- ld a, [hli]
- ld h, [hl]
- ld l, a ; hl now points to passable tiles
- ld a, [wTileInFrontOfPlayer] ; tile in front of the player
- ld b, a
-.passableTileLoop
- ld a, [hli]
- cp b
- jr z, .stopSurfing
- cp $ff
- jr nz, .passableTileLoop
-.cannotStopSurfing
- ld hl, SurfingNoPlaceToGetOffText
- jp PrintText
-.stopSurfing
- call .makePlayerMoveForward
- ld hl, wd730
- set 7, [hl]
- xor a
- ld [wWalkBikeSurfState], a ; change player state to walking
- dec a
- ld [wJoyIgnore], a
- call PlayDefaultMusic ; play walking music
- jp LoadWalkingPlayerSpriteGraphics
-; uses a simulated button press to make the player move forward
-.makePlayerMoveForward
- ld a, [wPlayerDirection] ; direction the player is going
- bit PLAYER_DIR_BIT_UP, a
- ld b, D_UP
- jr nz, .storeSimulatedButtonPress
- bit PLAYER_DIR_BIT_DOWN, a
- ld b, D_DOWN
- jr nz, .storeSimulatedButtonPress
- bit PLAYER_DIR_BIT_LEFT, a
- ld b, D_LEFT
- jr nz, .storeSimulatedButtonPress
- ld b, D_RIGHT
-.storeSimulatedButtonPress
- ld a, b
- ld [wSimulatedJoypadStatesEnd], a
- xor a
- ld [wWastedByteCD39], a
- inc a
- ld [wSimulatedJoypadStatesIndex], a
- ret
-
-SurfingGotOnText:
- TX_FAR _SurfingGotOnText
- db "@"
-
-SurfingNoPlaceToGetOffText:
- TX_FAR _SurfingNoPlaceToGetOffText
- db "@"
-
-ItemUsePokedex:
- predef_jump ShowPokedexMenu
-
-ItemUseEvoStone:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- ld [wEvoStoneItemID], a
- push af
- ld a, EVO_STONE_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- ld a, $ff
- ld [wUpdateSpritesEnabled], a
- call DisplayPartyMenu
- pop bc
- jr c, .canceledItemUse
- ld a, b
- ld [wcf91], a
- ld a, $01
- ld [wForceEvolution], a
- ld a, SFX_HEAL_AILMENT
- call PlaySoundWaitForCurrent
- call WaitForSoundToFinish
- callab TryEvolvingMon ; try to evolve pokemon
- ld a, [wEvolutionOccurred]
- and a
- jr z, .noEffect
- pop af
- ld [wWhichPokemon], a
- ld hl, wNumBagItems
- ld a, 1 ; remove 1 stone
- ld [wItemQuantity], a
- jp RemoveItemFromInventory
-.noEffect
- call ItemUseNoEffect
-.canceledItemUse
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item not used
- pop af
- ret
-
-ItemUseVitamin:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
-
-ItemUseMedicine:
- ld a, [wPartyCount]
- and a
- jp z, .emptyParty
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- push af
- ld a, USE_ITEM_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- ld a, $ff
- ld [wUpdateSpritesEnabled], a
- ld a, [wPseudoItemID]
- and a ; using Softboiled?
- jr z, .notUsingSoftboiled
-; if using softboiled
- call GoBackToPartyMenu
- jr .getPartyMonDataAddress
-.emptyParty
- ld hl, .emptyPartyText
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item use failed
- jp PrintText
-.emptyPartyText
- text "You don't have"
- line "any #MON!"
- prompt
-.notUsingSoftboiled
- call DisplayPartyMenu
-.getPartyMonDataAddress
- jp c, .canceledItemUse
- ld hl, wPartyMons
- ld bc, wPartyMon2 - wPartyMon1
- ld a, [wWhichPokemon]
- call AddNTimes
- ld a, [wWhichPokemon]
- ld [wUsedItemOnWhichPokemon], a
- ld d, a
- ld a, [wcf91]
- ld e, a
- ld [wd0b5], a
- pop af
- ld [wcf91], a
- pop af
- ld [wWhichPokemon], a
- ld a, [wPseudoItemID]
- and a ; using Softboiled?
- jr z, .checkItemType
-; if using softboiled
- ld a, [wWhichPokemon]
- cp d ; is the pokemon trying to use softboiled on itself?
- jr z, ItemUseMedicine ; if so, force another choice
-.checkItemType
- ld a, [wcf91]
- cp REVIVE
- jr nc, .healHP ; if it's a Revive or Max Revive
- cp FULL_HEAL
- jr z, .cureStatusAilment ; if it's a Full Heal
- cp HP_UP
- jp nc, .useVitamin ; if it's a vitamin or Rare Candy
- cp FULL_RESTORE
- jr nc, .healHP ; if it's a Full Restore or one of the potions
-; fall through if it's one of the status-specific healing items
-.cureStatusAilment
- ld bc, wPartyMon1Status - wPartyMon1
- add hl, bc ; hl now points to status
- ld a, [wcf91]
- lb bc, ANTIDOTE_MSG, 1 << PSN
- cp ANTIDOTE
- jr z, .checkMonStatus
- lb bc, BURN_HEAL_MSG, 1 << BRN
- cp BURN_HEAL
- jr z, .checkMonStatus
- lb bc, ICE_HEAL_MSG, 1 << FRZ
- cp ICE_HEAL
- jr z, .checkMonStatus
- lb bc, AWAKENING_MSG, SLP
- cp AWAKENING
- jr z, .checkMonStatus
- lb bc, PARALYZ_HEAL_MSG, 1 << PAR
- cp PARLYZ_HEAL
- jr z, .checkMonStatus
- lb bc, FULL_HEAL_MSG, $ff ; Full Heal
-.checkMonStatus
- ld a, [hl] ; pokemon's status
- and c ; does the pokemon have a status ailment the item can cure?
- jp z, .healingItemNoEffect
-; if the pokemon has a status the item can heal
- xor a
- ld [hl], a ; remove the status ailment in the party data
- ld a, b
- ld [wPartyMenuTypeOrMessageID], a ; the message to display for the item used
- ld a, [wPlayerMonNumber]
- cp d ; is pokemon the item was used on active in battle?
- jp nz, .doneHealing
-; if it is active in battle
- xor a
- ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data
- push hl
- ld hl, wPlayerBattleStatus3
- res BADLY_POISONED, [hl] ; heal Toxic status
- pop hl
- ld bc, wPartyMon1Stats - wPartyMon1Status
- add hl, bc ; hl now points to party stats
- ld de, wBattleMonStats
- ld bc, NUM_STATS * 2
- call CopyData ; copy party stats to in-battle stat data
- predef DoubleOrHalveSelectedStats
- jp .doneHealing
-.healHP
- inc hl ; hl = address of current HP
- ld a, [hli]
- ld b, a
- ld [wHPBarOldHP+1], a
- ld a, [hl]
- ld c, a
- ld [wHPBarOldHP], a ; current HP stored at wHPBarOldHP (2 bytes, big-endian)
- or b
- jr nz, .notFainted
-.fainted
- ld a, [wcf91]
- cp REVIVE
- jr z, .updateInBattleFaintedData
- cp MAX_REVIVE
- jr z, .updateInBattleFaintedData
- jp .healingItemNoEffect
-.updateInBattleFaintedData
- ld a, [wIsInBattle]
- and a
- jr z, .compareCurrentHPToMaxHP
- push hl
- push de
- push bc
- ld a, [wUsedItemOnWhichPokemon]
- ld c, a
- ld hl, wPartyFoughtCurrentEnemyFlags
- ld b, FLAG_TEST
- predef FlagActionPredef
- ld a, c
- and a
- jr z, .next
- ld a, [wUsedItemOnWhichPokemon]
- ld c, a
- ld hl, wPartyGainExpFlags
- ld b, FLAG_SET
- predef FlagActionPredef
-.next
- pop bc
- pop de
- pop hl
- jr .compareCurrentHPToMaxHP
-.notFainted
- ld a, [wcf91]
- cp REVIVE
- jp z, .healingItemNoEffect
- cp MAX_REVIVE
- jp z, .healingItemNoEffect
-.compareCurrentHPToMaxHP
- push hl
- push bc
- ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1)
- add hl, bc ; hl now points to max HP
- pop bc
- ld a, [hli]
- cp b
- jr nz, .skipComparingLSB ; no need to compare the LSB's if the MSB's don't match
- ld a, [hl]
- cp c
-.skipComparingLSB
- pop hl
- jr nz, .notFullHP
-.fullHP ; if the pokemon's current HP equals its max HP
- ld a, [wcf91]
- cp FULL_RESTORE
- jp nz, .healingItemNoEffect
- inc hl
- inc hl
- ld a, [hld] ; status ailment
- and a ; does the pokemon have a status ailment?
- jp z, .healingItemNoEffect
- ld a, FULL_HEAL
- ld [wcf91], a
- dec hl
- dec hl
- dec hl
- jp .cureStatusAilment
-.notFullHP ; if the pokemon's current HP doesn't equal its max HP
- xor a
- ld [wLowHealthAlarm], a ;disable low health alarm
- ld [wChannelSoundIDs + Ch4], a
- push hl
- push de
- ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1)
- add hl, bc ; hl now points to max HP
- ld a, [hli]
- ld [wHPBarMaxHP+1], a
- ld a, [hl]
- ld [wHPBarMaxHP], a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian)
- ld a, [wPseudoItemID]
- and a ; using Softboiled?
- jp z, .notUsingSoftboiled2
-; if using softboiled
- ld hl, wHPBarMaxHP
- ld a, [hli]
- push af
- ld a, [hli]
- push af
- ld a, [hli]
- push af
- ld a, [hl]
- push af
- ld hl, wPartyMon1MaxHP
- ld a, [wWhichPokemon]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hli]
- ld [wHPBarMaxHP + 1], a
- ld [H_DIVIDEND], a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- ld [H_DIVIDEND + 1], a
- ld a, 5
- ld [H_DIVISOR], a
- ld b, 2 ; number of bytes
- call Divide ; get 1/5 of max HP of pokemon that used Softboiled
- ld bc, (wPartyMon1HP + 1) - (wPartyMon1MaxHP + 1)
- add hl, bc ; hl now points to LSB of current HP of pokemon that used Softboiled
-; subtract 1/5 of max HP from current HP of pokemon that used Softboiled
- ld a, [H_QUOTIENT + 3]
- push af
- ld b, a
- ld a, [hl]
- ld [wHPBarOldHP], a
- sub b
- ld [hld], a
- ld [wHPBarNewHP], a
- ld a, [H_QUOTIENT + 2]
- ld b, a
- ld a, [hl]
- ld [wHPBarOldHP+1], a
- sbc b
- ld [hl], a
- ld [wHPBarNewHP+1], a
- coord hl, 4, 1
- ld a, [wWhichPokemon]
- ld bc, 2 * SCREEN_WIDTH
- call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
- ld a, SFX_HEAL_HP
- call PlaySoundWaitForCurrent
- ld a, [hFlags_0xFFF6]
- set 0, a
- ld [hFlags_0xFFF6], a
- ld a, $02
- ld [wHPBarType], a
- predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
- ld a, [hFlags_0xFFF6]
- res 0, a
- ld [hFlags_0xFFF6], a
- pop af
- ld b, a ; store heal amount (1/5 of max HP)
- ld hl, wHPBarOldHP + 1
- pop af
- ld [hld], a
- pop af
- ld [hld], a
- pop af
- ld [hld], a
- pop af
- ld [hl], a
- jr .addHealAmount
-.notUsingSoftboiled2
- ld a, [wcf91]
- cp SODA_POP
- ld b, 60 ; Soda Pop heal amount
- jr z, .addHealAmount
- ld b, 80 ; Lemonade heal amount
- jr nc, .addHealAmount
- cp FRESH_WATER
- ld b, 50 ; Fresh Water heal amount
- jr z, .addHealAmount
- cp SUPER_POTION
- ld b, 200 ; Hyper Potion heal amount
- jr c, .addHealAmount
- ld b, 50 ; Super Potion heal amount
- jr z, .addHealAmount
- ld b, 20 ; Potion heal amount
-.addHealAmount
- pop de
- pop hl
- ld a, [hl]
- add b
- ld [hld], a
- ld [wHPBarNewHP], a
- ld a, [hl]
- ld [wHPBarNewHP+1], a
- jr nc, .noCarry
- inc [hl]
- ld a, [hl]
- ld [wHPBarNewHP + 1], a
-.noCarry
- push de
- inc hl
- ld d, h
- ld e, l ; de now points to current HP
- ld hl, (wPartyMon1MaxHP + 1) - (wPartyMon1HP + 1)
- add hl, de ; hl now points to max HP
- ld a, [wcf91]
- cp REVIVE
- jr z, .setCurrentHPToHalfMaxHP
- ld a, [hld]
- ld b, a
- ld a, [de]
- sub b
- dec de
- ld b, [hl]
- ld a, [de]
- sbc b
- jr nc, .setCurrentHPToMaxHp ; if current HP exceeds max HP after healing
- ld a, [wcf91]
- cp HYPER_POTION
- jr c, .setCurrentHPToMaxHp ; if using a Full Restore or Max Potion
- cp MAX_REVIVE
- jr z, .setCurrentHPToMaxHp ; if using a Max Revive
- jr .updateInBattleData
-.setCurrentHPToHalfMaxHP
- dec hl
- dec de
- ld a, [hli]
- srl a
- ld [de], a
- ld [wHPBarNewHP+1], a
- ld a, [hl]
- rr a
- inc de
- ld [de], a
- ld [wHPBarNewHP], a
- dec de
- jr .doneHealingPartyHP
-.setCurrentHPToMaxHp
- ld a, [hli]
- ld [de], a
- ld [wHPBarNewHP+1], a
- inc de
- ld a, [hl]
- ld [de], a
- ld [wHPBarNewHP], a
- dec de
-.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure
- ld a, [wcf91]
- cp FULL_RESTORE
- jr nz, .updateInBattleData
- ld bc, wPartyMon1Status - (wPartyMon1MaxHP + 1)
- add hl, bc
- xor a
- ld [hl], a ; remove the status ailment in the party data
-.updateInBattleData
- ld h, d
- ld l, e
- pop de
- ld a, [wPlayerMonNumber]
- cp d ; is pokemon the item was used on active in battle?
- jr nz, .calculateHPBarCoords
-; copy party HP to in-battle HP
- ld a, [hli]
- ld [wBattleMonHP], a
- ld a, [hld]
- ld [wBattleMonHP + 1], a
- ld a, [wcf91]
- cp FULL_RESTORE
- jr nz, .calculateHPBarCoords
- xor a
- ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data
-.calculateHPBarCoords
- ld hl, wOAMBuffer + $90
- ld bc, 2 * SCREEN_WIDTH
- inc d
-.calculateHPBarCoordsLoop
- add hl, bc
- dec d
- jr nz, .calculateHPBarCoordsLoop
- jr .doneHealing
-.healingItemNoEffect
- call ItemUseNoEffect
- jp .done
-.doneHealing
- ld a, [wPseudoItemID]
- and a ; using Softboiled?
- jr nz, .skipRemovingItem ; no item to remove if using Softboiled
- push hl
- call RemoveUsedItem
- pop hl
-.skipRemovingItem
- ld a, [wcf91]
- cp FULL_RESTORE
- jr c, .playStatusAilmentCuringSound
- cp FULL_HEAL
- jr z, .playStatusAilmentCuringSound
- ld a, SFX_HEAL_HP
- call PlaySoundWaitForCurrent
- ld a, [hFlags_0xFFF6]
- set 0, a
- ld [hFlags_0xFFF6], a
- ld a, $02
- ld [wHPBarType], a
- predef UpdateHPBar2 ; animate the HP bar lengthening
- ld a, [hFlags_0xFFF6]
- res 0, a
- ld [hFlags_0xFFF6], a
- ld a, REVIVE_MSG
- ld [wPartyMenuTypeOrMessageID], a
- ld a, [wcf91]
- cp REVIVE
- jr z, .showHealingItemMessage
- cp MAX_REVIVE
- jr z, .showHealingItemMessage
- ld a, POTION_MSG
- ld [wPartyMenuTypeOrMessageID], a
- jr .showHealingItemMessage
-.playStatusAilmentCuringSound
- ld a, SFX_HEAL_AILMENT
- call PlaySoundWaitForCurrent
-.showHealingItemMessage
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- dec a
- ld [wUpdateSpritesEnabled], a
- call RedrawPartyMenu ; redraws the party menu and displays the message
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld c, 50
- call DelayFrames
- call WaitForTextScrollButtonPress
- jr .done
-.canceledItemUse
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item use failed
- pop af
- pop af
-.done
- ld a, [wPseudoItemID]
- and a ; using Softboiled?
- ret nz ; if so, return
- call GBPalWhiteOut
- call z, RunDefaultPaletteCommand
- ld a, [wIsInBattle]
- and a
- ret nz
- jp ReloadMapData
-.useVitamin
- push hl
- ld a, [hl]
- ld [wd0b5], a
- ld [wd11e], a
- ld bc, wPartyMon1Level - wPartyMon1
- add hl, bc ; hl now points to level
- ld a, [hl] ; a = level
- ld [wCurEnemyLVL], a ; store level
- call GetMonHeader
- push de
- ld a, d
- ld hl, wPartyMonNicks
- call GetPartyMonName
- pop de
- pop hl
- ld a, [wcf91]
- cp RARE_CANDY
- jp z, .useRareCandy
- push hl
- sub HP_UP
- add a
- ld bc, wPartyMon1HPExp - wPartyMon1
- add hl, bc
- add l
- ld l, a
- jr nc, .noCarry2
- inc h
-.noCarry2
- ld a, 10
- ld b, a
- ld a, [hl] ; a = MSB of stat experience of the appropriate stat
- cp 100 ; is there already at least 25600 (256 * 100) stat experience?
- jr nc, .vitaminNoEffect ; if so, vitamins can't add any more
- add b ; add 2560 (256 * 10) stat experience
- jr nc, .noCarry3 ; a carry should be impossible here, so this will always jump
- ld a, 255
-.noCarry3
- ld [hl], a
- pop hl
- call .recalculateStats
- ld hl, VitaminText
- ld a, [wcf91]
- sub HP_UP - 1
- ld c, a
-.statNameLoop ; loop to get the address of the name of the stat the vitamin increases
- dec c
- jr z, .gotStatName
-.statNameInnerLoop
- ld a, [hli]
- ld b, a
- ld a, $50
- cp b
- jr nz, .statNameInnerLoop
- jr .statNameLoop
-.gotStatName
- ld de, wcf4b
- ld bc, 10
- call CopyData ; copy the stat's name to wcf4b
- ld a, SFX_HEAL_AILMENT
- call PlaySound
- ld hl, VitaminStatRoseText
- call PrintText
- jp RemoveUsedItem
-.vitaminNoEffect
- pop hl
- ld hl, VitaminNoEffectText
- call PrintText
- jp GBPalWhiteOut
-.recalculateStats
- ld bc, wPartyMon1Stats - wPartyMon1
- add hl, bc
- ld d, h
- ld e, l ; de now points to stats
- ld bc, (wPartyMon1Exp + 2) - wPartyMon1Stats
- add hl, bc ; hl now points to LSB of experience
- ld b, 1
- jp CalcStats ; recalculate stats
-.useRareCandy
- push hl
- ld bc, wPartyMon1Level - wPartyMon1
- add hl, bc ; hl now points to level
- ld a, [hl] ; a = level
- cp MAX_LEVEL
- jr z, .vitaminNoEffect ; can't raise level above 100
- inc a
- ld [hl], a ; store incremented level
- ld [wCurEnemyLVL], a
- push hl
- push de
- ld d, a
- callab CalcExperience ; calculate experience for next level and store it at $ff96
- pop de
- pop hl
- ld bc, wPartyMon1Exp - wPartyMon1Level
- add hl, bc ; hl now points to MSB of experience
-; update experience to minimum for new level
- ld a, [hExperience]
- ld [hli], a
- ld a, [hExperience + 1]
- ld [hli], a
- ld a, [hExperience + 2]
- ld [hl], a
- pop hl
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- push af
- push de
- push hl
- ld bc, wPartyMon1MaxHP - wPartyMon1
- add hl, bc ; hl now points to MSB of max HP
- ld a, [hli]
- ld b, a
- ld c, [hl]
- pop hl
- push bc
- push hl
- call .recalculateStats
- pop hl
- ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1
- add hl, bc ; hl now points to LSB of max HP
- pop bc
- ld a, [hld]
- sub c
- ld c, a
- ld a, [hl]
- sbc b
- ld b, a ; bc = the amount of max HP gained from leveling up
-; add the amount gained to the current HP
- ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
- add hl, de ; hl now points to LSB of current HP
- ld a, [hl]
- add c
- ld [hld], a
- ld a, [hl]
- adc b
- ld [hl], a
- ld a, RARE_CANDY_MSG
- ld [wPartyMenuTypeOrMessageID], a
- call RedrawPartyMenu
- pop de
- ld a, d
- ld [wWhichPokemon], a
- ld a, e
- ld [wd11e], a
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- call LoadMonData
- ld d, $01
- callab PrintStatsBox ; display new stats text box
- call WaitForTextScrollButtonPress ; wait for button press
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- predef LearnMoveFromLevelUp ; learn level up move, if any
- xor a
- ld [wForceEvolution], a
- callab TryEvolvingMon ; evolve pokemon, if appropriate
- ld a, $01
- ld [wUpdateSpritesEnabled], a
- pop af
- ld [wcf91], a
- pop af
- ld [wWhichPokemon], a
- jp RemoveUsedItem
-
-VitaminStatRoseText:
- TX_FAR _VitaminStatRoseText
- db "@"
-
-VitaminNoEffectText:
- TX_FAR _VitaminNoEffectText
- db "@"
-
-VitaminText:
- db "HEALTH@"
- db "ATTACK@"
- db "DEFENSE@"
- db "SPEED@"
- db "SPECIAL@"
-
-ItemUseBait:
- ld hl, ThrewBaitText
- call PrintText
- ld hl, wEnemyMonActualCatchRate ; catch rate
- srl [hl] ; halve catch rate
- ld a, BAIT_ANIM
- ld hl, wSafariBaitFactor ; bait factor
- ld de, wSafariEscapeFactor ; escape factor
- jr BaitRockCommon
-
-ItemUseRock:
- ld hl, ThrewRockText
- call PrintText
- ld hl, wEnemyMonActualCatchRate ; catch rate
- ld a, [hl]
- add a ; double catch rate
- jr nc, .noCarry
- ld a, $ff
-.noCarry
- ld [hl], a
- ld a, ROCK_ANIM
- ld hl, wSafariEscapeFactor ; escape factor
- ld de, wSafariBaitFactor ; bait factor
-
-BaitRockCommon:
- ld [wAnimationID], a
- xor a
- ld [wAnimationType], a
- ld [H_WHOSETURN], a
- ld [de], a ; zero escape factor (for bait), zero bait factor (for rock)
-.randomLoop ; loop until a random number less than 5 is generated
- call Random
- and 7
- cp 5
- jr nc, .randomLoop
- inc a ; increment the random number, giving a range from 1 to 5 inclusive
- ld b, a
- ld a, [hl]
- add b ; increase bait factor (for bait), increase escape factor (for rock)
- jr nc, .noCarry
- ld a, $ff
-.noCarry
- ld [hl], a
- predef MoveAnimation ; do animation
- ld c, 70
- jp DelayFrames
-
-ThrewBaitText:
- TX_FAR _ThrewBaitText
- db "@"
-
-ThrewRockText:
- TX_FAR _ThrewRockText
- db "@"
-
-; also used for Dig out-of-battle effect
-ItemUseEscapeRope:
- ld a, [wIsInBattle]
- and a
- jr nz, .notUsable
- ld a, [wCurMap]
- cp AGATHAS_ROOM
- jr z, .notUsable
- ld a, [wCurMapTileset]
- ld b, a
- ld hl, EscapeRopeTilesets
-.loop
- ld a, [hli]
- cp $ff
- jr z, .notUsable
- cp b
- jr nz, .loop
- ld hl, wd732
- set 3, [hl]
- set 6, [hl]
- ld hl, wd72e
- res 4, [hl]
- ResetEvent EVENT_IN_SAFARI_ZONE
- xor a
- ld [wNumSafariBalls], a
- ld [wSafariZoneEntranceCurScript], a
- inc a
- ld [wEscapedFromBattle], a
- ld [wActionResultOrTookBattleTurn], a ; item used
- ld a, [wPseudoItemID]
- and a ; using Dig?
- ret nz ; if so, return
- call ItemUseReloadOverworldData
- ld c, 30
- call DelayFrames
- jp RemoveUsedItem
-.notUsable
- jp ItemUseNotTime
-
-EscapeRopeTilesets:
- db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
- db $ff ; terminator
-
-ItemUseRepel:
- ld b, 100
-
-ItemUseRepelCommon:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- ld a, b
- ld [wRepelRemainingSteps], a
- jp PrintItemUseTextAndRemoveItem
-
-; handles X Accuracy item
-ItemUseXAccuracy:
- ld a, [wIsInBattle]
- and a
- jp z, ItemUseNotTime
- ld hl, wPlayerBattleStatus2
- set USING_X_ACCURACY, [hl] ; X Accuracy bit
- jp PrintItemUseTextAndRemoveItem
-
-; This function is bugged and never works. It always jumps to ItemUseNotTime.
-; The Card Key is handled in a different way.
-ItemUseCardKey:
- xor a
- ld [wUnusedD71F], a
- call GetTileAndCoordsInFrontOfPlayer
- ld a, [GetTileAndCoordsInFrontOfPlayer]
- cp $18
- jr nz, .next0
- ld hl, CardKeyTable1
- jr .next1
-.next0
- cp $24
- jr nz, .next2
- ld hl, CardKeyTable2
- jr .next1
-.next2
- cp $5e
- jp nz, ItemUseNotTime
- ld hl, CardKeyTable3
-.next1
- ld a, [wCurMap]
- ld b, a
-.loop
- ld a, [hli]
- cp $ff
- jp z, ItemUseNotTime
- cp b
- jr nz, .nextEntry1
- ld a, [hli]
- cp d
- jr nz, .nextEntry2
- ld a, [hli]
- cp e
- jr nz, .nextEntry3
- ld a, [hl]
- ld [wUnusedD71F], a
- jr .done
-.nextEntry1
- inc hl
-.nextEntry2
- inc hl
-.nextEntry3
- inc hl
- jr .loop
-.done
- ld hl, ItemUseText00
- call PrintText
- ld hl, wd728
- set 7, [hl]
- ret
-
-; These tables are probably supposed to be door locations in Silph Co.,
-; but they are unused.
-; The reason there are 3 tables is unknown.
-
-; Format:
-; 00: Map ID
-; 01: Y
-; 02: X
-; 03: ID?
-
-CardKeyTable1:
- db SILPH_CO_2F,$04,$04,$00
- db SILPH_CO_2F,$04,$05,$01
- db SILPH_CO_4F,$0C,$04,$02
- db SILPH_CO_4F,$0C,$05,$03
- db SILPH_CO_7F,$06,$0A,$04
- db SILPH_CO_7F,$06,$0B,$05
- db SILPH_CO_9F,$04,$12,$06
- db SILPH_CO_9F,$04,$13,$07
- db SILPH_CO_10F,$08,$0A,$08
- db SILPH_CO_10F,$08,$0B,$09
- db $ff
-
-CardKeyTable2:
- db SILPH_CO_3F,$08,$09,$0A
- db SILPH_CO_3F,$09,$09,$0B
- db SILPH_CO_5F,$04,$07,$0C
- db SILPH_CO_5F,$05,$07,$0D
- db SILPH_CO_6F,$0C,$05,$0E
- db SILPH_CO_6F,$0D,$05,$0F
- db SILPH_CO_8F,$08,$07,$10
- db SILPH_CO_8F,$09,$07,$11
- db SILPH_CO_9F,$08,$03,$12
- db SILPH_CO_9F,$09,$03,$13
- db $ff
-
-CardKeyTable3:
- db SILPH_CO_11F,$08,$09,$14
- db SILPH_CO_11F,$09,$09,$15
- db $ff
-
-ItemUsePokedoll:
- ld a, [wIsInBattle]
- dec a
- jp nz, ItemUseNotTime
- ld a, $01
- ld [wEscapedFromBattle], a
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseGuardSpec:
- ld a, [wIsInBattle]
- and a
- jp z, ItemUseNotTime
- ld hl, wPlayerBattleStatus2
- set PROTECTED_BY_MIST, [hl] ; Mist bit
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseSuperRepel:
- ld b, 200
- jp ItemUseRepelCommon
-
-ItemUseMaxRepel:
- ld b, 250
- jp ItemUseRepelCommon
-
-ItemUseDireHit:
- ld a, [wIsInBattle]
- and a
- jp z, ItemUseNotTime
- ld hl, wPlayerBattleStatus2
- set GETTING_PUMPED, [hl] ; Focus Energy bit
- jp PrintItemUseTextAndRemoveItem
-
-ItemUseXStat:
- ld a, [wIsInBattle]
- and a
- jr nz, .inBattle
- call ItemUseNotTime
- ld a, 2
- ld [wActionResultOrTookBattleTurn], a ; item not used
- ret
-.inBattle
- ld hl, wPlayerMoveNum
- ld a, [hli]
- push af ; save [wPlayerMoveNum]
- ld a, [hl]
- push af ; save [wPlayerMoveEffect]
- push hl
- ld a, [wcf91]
- sub X_ATTACK - ATTACK_UP1_EFFECT
- ld [hl], a ; store player move effect
- call PrintItemUseTextAndRemoveItem
- ld a, XSTATITEM_ANIM ; X stat item animation ID
- ld [wPlayerMoveNum], a
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- call Delay3
- xor a
- ld [H_WHOSETURN], a ; set turn to player's turn
- callba StatModifierUpEffect ; do stat increase move
- pop hl
- pop af
- ld [hld], a ; restore [wPlayerMoveEffect]
- pop af
- ld [hl], a ; restore [wPlayerMoveNum]
- ret
-
-ItemUsePokeflute:
- ld a, [wIsInBattle]
- and a
- jr nz, .inBattle
-; if not in battle
- call ItemUseReloadOverworldData
- ld a, [wCurMap]
- cp ROUTE_12
- jr nz, .notRoute12
- CheckEvent EVENT_BEAT_ROUTE12_SNORLAX
- jr nz, .noSnorlaxToWakeUp
-; if the player hasn't beaten Route 12 Snorlax
- ld hl, Route12SnorlaxFluteCoords
- call ArePlayerCoordsInArray
- jr nc, .noSnorlaxToWakeUp
- ld hl, PlayedFluteHadEffectText
- call PrintText
- SetEvent EVENT_FIGHT_ROUTE12_SNORLAX
- ret
-.notRoute12
- cp ROUTE_16
- jr nz, .noSnorlaxToWakeUp
- CheckEvent EVENT_BEAT_ROUTE16_SNORLAX
- jr nz, .noSnorlaxToWakeUp
-; if the player hasn't beaten Route 16 Snorlax
- ld hl, Route16SnorlaxFluteCoords
- call ArePlayerCoordsInArray
- jr nc, .noSnorlaxToWakeUp
- ld hl, PlayedFluteHadEffectText
- call PrintText
- SetEvent EVENT_FIGHT_ROUTE16_SNORLAX
- ret
-.noSnorlaxToWakeUp
- ld hl, PlayedFluteNoEffectText
- jp PrintText
-.inBattle
- xor a
- ld [wWereAnyMonsAsleep], a
- ld b, ~SLP & $ff
- ld hl, wPartyMon1Status
- call WakeUpEntireParty
- ld a, [wIsInBattle]
- dec a ; is it a trainer battle?
- jr z, .skipWakingUpEnemyParty
-; if it's a trainer battle
- ld hl, wEnemyMon1Status
- call WakeUpEntireParty
-.skipWakingUpEnemyParty
- ld hl, wBattleMonStatus
- ld a, [hl]
- and b ; remove Sleep status
- ld [hl], a
- ld hl, wEnemyMonStatus
- ld a, [hl]
- and b ; remove Sleep status
- ld [hl], a
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- ld a, [wWereAnyMonsAsleep]
- and a ; were any pokemon asleep before playing the flute?
- ld hl, PlayedFluteNoEffectText
- jp z, PrintText ; if no pokemon were asleep
-; if some pokemon were asleep
- ld hl, PlayedFluteHadEffectText
- call PrintText
- ld a, [wLowHealthAlarm]
- and $80
- jr nz, .skipMusic
- call WaitForSoundToFinish ; wait for sound to end
- callba Music_PokeFluteInBattle ; play in-battle pokeflute music
-.musicWaitLoop ; wait for music to finish playing
- ld a, [wChannelSoundIDs + Ch6]
- and a ; music off?
- jr nz, .musicWaitLoop
-.skipMusic
- ld hl, FluteWokeUpText
- jp PrintText
-
-; wakes up all party pokemon
-; INPUT:
-; hl must point to status of first pokemon in party (player's or enemy's)
-; b must equal ~SLP
-; [wWereAnyMonsAsleep] should be initialized to 0
-; OUTPUT:
-; [wWereAnyMonsAsleep]: set to 1 if any pokemon were asleep
-WakeUpEntireParty:
- ld de, 44
- ld c, 6
-.loop
- ld a, [hl]
- push af
- and SLP ; is pokemon asleep?
- jr z, .notAsleep
- ld a, 1
- ld [wWereAnyMonsAsleep], a ; indicate that a pokemon had to be woken up
-.notAsleep
- pop af
- and b ; remove Sleep status
- ld [hl], a
- add hl, de
- dec c
- jr nz, .loop
- ret
-
-; Format:
-; 00: Y
-; 01: X
-Route12SnorlaxFluteCoords:
- db 62,9 ; one space West of Snorlax
- db 61,10 ; one space North of Snorlax
- db 63,10 ; one space South of Snorlax
- db 62,11 ; one space East of Snorlax
- db $ff ; terminator
-
-; Format:
-; 00: Y
-; 01: X
-Route16SnorlaxFluteCoords:
- db 10,27 ; one space East of Snorlax
- db 10,25 ; one space West of Snorlax
- db $ff ; terminator
-
-PlayedFluteNoEffectText:
- TX_FAR _PlayedFluteNoEffectText
- db "@"
-
-FluteWokeUpText:
- TX_FAR _FluteWokeUpText
- db "@"
-
-PlayedFluteHadEffectText:
- TX_FAR _PlayedFluteHadEffectText
- TX_BLINK
- TX_ASM
- ld a, [wIsInBattle]
- and a
- jr nz, .done
-; play out-of-battle pokeflute music
- ld a, $ff
- call PlaySound ; turn off music
- ld a, SFX_POKEFLUTE
- ld c, BANK(SFX_Pokeflute)
- call PlayMusic
-.musicWaitLoop ; wait for music to finish playing
- ld a, [wChannelSoundIDs + Ch2]
- cp SFX_POKEFLUTE
- jr z, .musicWaitLoop
- call PlayDefaultMusic ; start playing normal music again
-.done
- jp TextScriptEnd ; end text
-
-ItemUseCoinCase:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- ld hl, CoinCaseNumCoinsText
- jp PrintText
-
-CoinCaseNumCoinsText:
- TX_FAR _CoinCaseNumCoinsText
- db "@"
-
-ItemUseOldRod:
- call FishingInit
- jp c, ItemUseNotTime
- lb bc, 5, MAGIKARP
- ld a, $1 ; set bite
- jr RodResponse
-
-ItemUseGoodRod:
- call FishingInit
- jp c, ItemUseNotTime
-.RandomLoop
- call Random
- srl a
- jr c, .SetBite
- and %11
- cp 2
- jr nc, .RandomLoop
- ; choose which monster appears
- ld hl, GoodRodMons
- add a
- ld c, a
- ld b, 0
- add hl, bc
- ld b, [hl]
- inc hl
- ld c, [hl]
- and a
-.SetBite
- ld a, 0
- rla
- xor 1
- jr RodResponse
-
-INCLUDE "data/good_rod.asm"
-
-ItemUseSuperRod:
- call FishingInit
- jp c, ItemUseNotTime
- call ReadSuperRodData
- ld a, e
-RodResponse:
- ld [wRodResponse], a
-
- dec a ; is there a bite?
- jr nz, .next
- ; if yes, store level and species data
- ld a, 1
- ld [wMoveMissed], a
- ld a, b ; level
- ld [wCurEnemyLVL], a
- ld a, c ; species
- ld [wCurOpponent], a
-
-.next
- ld hl, wWalkBikeSurfState
- ld a, [hl] ; store the value in a
- push af
- push hl
- ld [hl], 0
- callba FishingAnim
- pop hl
- pop af
- ld [hl], a
- ret
-
-; checks if fishing is possible and if so, runs initialization code common to all rods
-; unsets carry if fishing is possible, sets carry if not
-FishingInit:
- ld a, [wIsInBattle]
- and a
- jr z, .notInBattle
- scf ; can't fish during battle
- ret
-.notInBattle
- call IsNextTileShoreOrWater
- ret c
- ld a, [wWalkBikeSurfState]
- cp 2 ; Surfing?
- jr z, .surfing
- call ItemUseReloadOverworldData
- ld hl, ItemUseText00
- call PrintText
- ld a, SFX_HEAL_AILMENT
- call PlaySound
- ld c, 80
- call DelayFrames
- and a
- ret
-.surfing
- scf ; can't fish when surfing
- ret
-
-ItemUseOaksParcel:
- jp ItemUseNotYoursToUse
-
-ItemUseItemfinder:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- call ItemUseReloadOverworldData
- callba HiddenItemNear ; check for hidden items
- ld hl, ItemfinderFoundNothingText
- jr nc, .printText ; if no hidden items
- ld c, 4
-.loop
- ld a, SFX_HEALING_MACHINE
- call PlaySoundWaitForCurrent
- ld a, SFX_PURCHASE
- call PlaySoundWaitForCurrent
- dec c
- jr nz, .loop
- ld hl, ItemfinderFoundItemText
-.printText
- jp PrintText
-
-ItemfinderFoundItemText:
- TX_FAR _ItemfinderFoundItemText
- db "@"
-
-ItemfinderFoundNothingText:
- TX_FAR _ItemfinderFoundNothingText
- db "@"
-
-ItemUsePPUp:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
-
-ItemUsePPRestore:
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- ld [wPPRestoreItem], a
-.chooseMon
- xor a
- ld [wUpdateSpritesEnabled], a
- ld a, USE_ITEM_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call DisplayPartyMenu
- jr nc, .chooseMove
- jp .itemNotUsed
-.chooseMove
- ld a, [wPPRestoreItem]
- cp ELIXER
- jp nc, .useElixir ; if Elixir or Max Elixir
- ld a, $02
- ld [wMoveMenuType], a
- ld hl, RaisePPWhichTechniqueText
- ld a, [wPPRestoreItem]
- cp ETHER ; is it a PP Up?
- jr c, .printWhichTechniqueMessage ; if so, print the raise PP message
- ld hl, RestorePPWhichTechniqueText ; otherwise, print the restore PP message
-.printWhichTechniqueMessage
- call PrintText
- xor a
- ld [wPlayerMoveListIndex], a
- callab MoveSelectionMenu ; move selection menu
- ld a, 0
- ld [wPlayerMoveListIndex], a
- jr nz, .chooseMon
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- call GetSelectedMoveOffset
- push hl
- ld a, [hl]
- ld [wd11e], a
- call GetMoveName
- call CopyStringToCF4B ; copy name to wcf4b
- pop hl
- ld a, [wPPRestoreItem]
- cp ETHER
- jr nc, .useEther ; if Ether or Max Ether
-.usePPUp
- ld bc, wPartyMon1PP - wPartyMon1Moves
- add hl, bc
- ld a, [hl] ; move PP
- cp 3 << 6 ; have 3 PP Ups already been used?
- jr c, .PPNotMaxedOut
- ld hl, PPMaxedOutText
- call PrintText
- jr .chooseMove
-.PPNotMaxedOut
- ld a, [hl]
- add 1 << 6 ; increase PP Up count by 1
- ld [hl], a
- ld a, 1 ; 1 PP Up used
- ld [wd11e], a
- call RestoreBonusPP ; add the bonus PP to current PP
- ld hl, PPIncreasedText
- call PrintText
-.done
- pop af
- ld [wWhichPokemon], a
- call GBPalWhiteOut
- call RunDefaultPaletteCommand
- jp RemoveUsedItem
-.afterRestoringPP ; after using a (Max) Ether/Elixir
- ld a, [wWhichPokemon]
- ld b, a
- ld a, [wPlayerMonNumber]
- cp b ; is the pokemon whose PP was restored active in battle?
- jr nz, .skipUpdatingInBattleData
- ld hl, wPartyMon1PP
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld de, wBattleMonPP
- ld bc, 4
- call CopyData ; copy party data to in-battle data
-.skipUpdatingInBattleData
- ld a, SFX_HEAL_AILMENT
- call PlaySound
- ld hl, PPRestoredText
- call PrintText
- jr .done
-.useEther
- call .restorePP
- jr nz, .afterRestoringPP
- jp .noEffect
-; unsets zero flag if PP was restored, sets zero flag if not
-; however, this is bugged for Max Ethers and Max Elixirs (see below)
-.restorePP
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- call GetMaxPP
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- call GetSelectedMoveOffset
- ld bc, wPartyMon1PP - wPartyMon1Moves
- add hl, bc ; hl now points to move's PP
- ld a, [wMaxPP]
- ld b, a
- ld a, [wPPRestoreItem]
- cp MAX_ETHER
- jr z, .fullyRestorePP
- ld a, [hl] ; move PP
- and %00111111 ; lower 6 bit bits store current PP
- cp b ; does current PP equal max PP?
- ret z ; if so, return
- add 10 ; increase current PP by 10
-; b holds the max PP amount and b will hold the new PP amount.
-; So, if the new amount meets or exceeds the max amount,
-; cap the amount to the max amount by leaving b unchanged.
-; Otherwise, store the new amount in b.
- cp b ; does the new amount meet or exceed the maximum?
- jr nc, .storeNewAmount
- ld b, a
-.storeNewAmount
- ld a, [hl] ; move PP
- and %11000000 ; PP Up counter bits
- add b
- ld [hl], a
- ret
-.fullyRestorePP
- ld a, [hl] ; move PP
-; Note that this code has a bug. It doesn't mask out the upper two bits, which
-; are used to count how many PP Ups have been used on the move. So, Max Ethers
-; and Max Elixirs will not be detected as having no effect on a move with full
-; PP if the move has had any PP Ups used on it.
- cp b ; does current PP equal max PP?
- ret z
- jr .storeNewAmount
-.useElixir
-; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER
- ld hl, wPPRestoreItem
- dec [hl]
- dec [hl]
- xor a
- ld hl, wCurrentMenuItem
- ld [hli], a
- ld [hl], a ; zero the counter for number of moves that had their PP restored
- ld b, 4
-; loop through each move and restore PP
-.elixirLoop
- push bc
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- call GetSelectedMoveOffset
- ld a, [hl]
- and a ; does the current slot have a move?
- jr z, .nextMove
- call .restorePP
- jr z, .nextMove
-; if some PP was restored
- ld hl, wTileBehindCursor ; counter for number of moves that had their PP restored
- inc [hl]
-.nextMove
- ld hl, wCurrentMenuItem
- inc [hl]
- pop bc
- dec b
- jr nz, .elixirLoop
- ld a, [wTileBehindCursor]
- and a ; did any moves have their PP restored?
- jp nz, .afterRestoringPP
-.noEffect
- call ItemUseNoEffect
-.itemNotUsed
- call GBPalWhiteOut
- call RunDefaultPaletteCommand
- pop af
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item use failed
- ret
-
-RaisePPWhichTechniqueText:
- TX_FAR _RaisePPWhichTechniqueText
- db "@"
-
-RestorePPWhichTechniqueText:
- TX_FAR _RestorePPWhichTechniqueText
- db "@"
-
-PPMaxedOutText:
- TX_FAR _PPMaxedOutText
- db "@"
-
-PPIncreasedText:
- TX_FAR _PPIncreasedText
- db "@"
-
-PPRestoredText:
- TX_FAR _PPRestoredText
- db "@"
-
-; for items that can't be used from the Item menu
-UnusableItem:
- jp ItemUseNotTime
-
-ItemUseTMHM:
- ld a, [wIsInBattle]
- and a
- jp nz, ItemUseNotTime
- ld a, [wcf91]
- sub TM_01
- push af
- jr nc, .skipAdding
- add 55 ; if item is an HM, add 55
-.skipAdding
- inc a
- ld [wd11e], a
- predef TMToMove ; get move ID from TM/HM ID
- ld a, [wd11e]
- ld [wMoveNum], a
- call GetMoveName
- call CopyStringToCF4B ; copy name to wcf4b
- pop af
- ld hl, BootedUpTMText
- jr nc, .printBootedUpMachineText
- ld hl, BootedUpHMText
-.printBootedUpMachineText
- call PrintText
- ld hl, TeachMachineMoveText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wCurrentMenuItem]
- and a
- jr z, .useMachine
- ld a, 2
- ld [wActionResultOrTookBattleTurn], a ; item not used
- ret
-.useMachine
- ld a, [wWhichPokemon]
- push af
- ld a, [wcf91]
- push af
-.chooseMon
- ld hl, wcf4b
- ld de, wTempMoveNameBuffer
- ld bc, 14
- call CopyData ; save the move name because DisplayPartyMenu will overwrite it
- ld a, $ff
- ld [wUpdateSpritesEnabled], a
- ld a, TMHM_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call DisplayPartyMenu
- push af
- ld hl, wTempMoveNameBuffer
- ld de, wcf4b
- ld bc, 14
- call CopyData
- pop af
- jr nc, .checkIfAbleToLearnMove
-; if the player canceled teaching the move
- pop af
- pop af
- call GBPalWhiteOutWithDelay3
- call ClearSprites
- call RunDefaultPaletteCommand
- jp LoadScreenTilesFromBuffer1 ; restore saved screen
-.checkIfAbleToLearnMove
- predef CanLearnTM ; check if the pokemon can learn the move
- push bc
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- pop bc
- ld a, c
- and a ; can the pokemon learn the move?
- jr nz, .checkIfAlreadyLearnedMove
-; if the pokemon can't learn the move
- ld a, SFX_DENIED
- call PlaySoundWaitForCurrent
- ld hl, MonCannotLearnMachineMoveText
- call PrintText
- jr .chooseMon
-.checkIfAlreadyLearnedMove
- callab CheckIfMoveIsKnown ; check if the pokemon already knows the move
- jr c, .chooseMon
- predef LearnMove ; teach move
- pop af
- ld [wcf91], a
- pop af
- ld [wWhichPokemon], a
- ld a, b
- and a
- ret z
- ld a, [wcf91]
- call IsItemHM
- ret c
- jp RemoveUsedItem
-
-BootedUpTMText:
- TX_FAR _BootedUpTMText
- db "@"
-
-BootedUpHMText:
- TX_FAR _BootedUpHMText
- db "@"
-
-TeachMachineMoveText:
- TX_FAR _TeachMachineMoveText
- db "@"
-
-MonCannotLearnMachineMoveText:
- TX_FAR _MonCannotLearnMachineMoveText
- db "@"
-
-PrintItemUseTextAndRemoveItem:
- ld hl, ItemUseText00
- call PrintText
- ld a, SFX_HEAL_AILMENT
- call PlaySound
- call WaitForTextScrollButtonPress ; wait for button press
-
-RemoveUsedItem:
- ld hl, wNumBagItems
- ld a, 1 ; one item
- ld [wItemQuantity], a
- jp RemoveItemFromInventory
-
-ItemUseNoEffect:
- ld hl, ItemUseNoEffectText
- jr ItemUseFailed
-
-ItemUseNotTime:
- ld hl, ItemUseNotTimeText
- jr ItemUseFailed
-
-ItemUseNotYoursToUse:
- ld hl, ItemUseNotYoursToUseText
- jr ItemUseFailed
-
-ThrowBallAtTrainerMon:
- call RunDefaultPaletteCommand
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- call Delay3
- ld a, TOSS_ANIM
- ld [wAnimationID], a
- predef MoveAnimation ; do animation
- ld hl, ThrowBallAtTrainerMonText1
- call PrintText
- ld hl, ThrowBallAtTrainerMonText2
- call PrintText
- jr RemoveUsedItem
-
-NoCyclingAllowedHere:
- ld hl, NoCyclingAllowedHereText
- jr ItemUseFailed
-
-BoxFullCannotThrowBall:
- ld hl, BoxFullCannotThrowBallText
- jr ItemUseFailed
-
-SurfingAttemptFailed:
- ld hl, NoSurfingHereText
-
-ItemUseFailed:
- xor a
- ld [wActionResultOrTookBattleTurn], a ; item use failed
- jp PrintText
-
-ItemUseNotTimeText:
- TX_FAR _ItemUseNotTimeText
- db "@"
-
-ItemUseNotYoursToUseText:
- TX_FAR _ItemUseNotYoursToUseText
- db "@"
-
-ItemUseNoEffectText:
- TX_FAR _ItemUseNoEffectText
- db "@"
-
-ThrowBallAtTrainerMonText1:
- TX_FAR _ThrowBallAtTrainerMonText1
- db "@"
-
-ThrowBallAtTrainerMonText2:
- TX_FAR _ThrowBallAtTrainerMonText2
- db "@"
-
-NoCyclingAllowedHereText:
- TX_FAR _NoCyclingAllowedHereText
- db "@"
-
-NoSurfingHereText:
- TX_FAR _NoSurfingHereText
- db "@"
-
-BoxFullCannotThrowBallText:
- TX_FAR _BoxFullCannotThrowBallText
- db "@"
-
-ItemUseText00:
- TX_FAR _ItemUseText001
- TX_LINE
- TX_FAR _ItemUseText002
- db "@"
-
-GotOnBicycleText:
- TX_FAR _GotOnBicycleText1
- TX_LINE
- TX_FAR _GotOnBicycleText2
- db "@"
-
-GotOffBicycleText:
- TX_FAR _GotOffBicycleText1
- TX_LINE
- TX_FAR _GotOffBicycleText2
- db "@"
-
-; restores bonus PP (from PP Ups) when healing at a pokemon center
-; also, when a PP Up is used, it increases the current PP by one PP Up bonus
-; INPUT:
-; [wWhichPokemon] = index of pokemon in party
-; [wCurrentMenuItem] = index of move (when using a PP Up)
-RestoreBonusPP:
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- ld a, [wWhichPokemon]
- call AddNTimes
- push hl
- ld de, wNormalMaxPPList - 1
- predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wNormalMaxPPList
- pop hl
- ld c, wPartyMon1PP - wPartyMon1Moves
- ld b, 0
- add hl, bc ; hl now points to move 1 PP
- ld de, wNormalMaxPPList
- ld b, 0 ; initialize move counter to zero
-; loop through the pokemon's moves
-.loop
- inc b
- ld a, b
- cp 5 ; reached the end of the pokemon's moves?
- ret z ; if so, return
- ld a, [wUsingPPUp]
- dec a ; using a PP Up?
- jr nz, .skipMenuItemIDCheck
-; if using a PP Up, check if this is the move it's being used on
- ld a, [wCurrentMenuItem]
- inc a
- cp b
- jr nz, .nextMove
-.skipMenuItemIDCheck
- ld a, [hl]
- and %11000000 ; have any PP Ups been used?
- call nz, AddBonusPP ; if so, add bonus PP
-.nextMove
- inc hl
- inc de
- jr .loop
-
-; adds bonus PP from PP Ups to current PP
-; 1/5 of normal max PP (capped at 7) is added for each PP Up
-; INPUT:
-; [de] = normal max PP
-; [hl] = move PP
-AddBonusPP:
- push bc
- ld a, [de] ; normal max PP of move
- ld [H_DIVIDEND + 3], a
- xor a
- ld [H_DIVIDEND], a
- ld [H_DIVIDEND + 1], a
- ld [H_DIVIDEND + 2], a
- ld a, 5
- ld [H_DIVISOR], a
- ld b, 4
- call Divide
- ld a, [hl] ; move PP
- ld b, a
- swap a
- and %00001111
- srl a
- srl a
- ld c, a ; c = number of PP Ups used
-.loop
- ld a, [H_QUOTIENT + 3]
- cp 8 ; is the amount greater than or equal to 8?
- jr c, .addAmount
- ld a, 7 ; cap the amount at 7
-.addAmount
- add b
- ld b, a
- ld a, [wUsingPPUp]
- dec a ; is the player using a PP Up right now?
- jr z, .done ; if so, only add the bonus once
- dec c
- jr nz, .loop
-.done
- ld [hl], b
- pop bc
- ret
-
-; gets max PP of a pokemon's move (including PP from PP Ups)
-; INPUT:
-; [wWhichPokemon] = index of pokemon within party/box
-; [wMonDataLocation] = pokemon source
-; 00: player's party
-; 01: enemy's party
-; 02: current box
-; 03: daycare
-; 04: player's in-battle pokemon
-; [wCurrentMenuItem] = move index
-; OUTPUT:
-; [wMaxPP] = max PP
-GetMaxPP:
- ld a, [wMonDataLocation]
- and a
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- jr z, .sourceWithMultipleMon
- ld hl, wEnemyMon1Moves
- dec a
- jr z, .sourceWithMultipleMon
- ld hl, wBoxMon1Moves
- ld bc, wBoxMon2 - wBoxMon1
- dec a
- jr z, .sourceWithMultipleMon
- ld hl, wDayCareMonMoves
- dec a
- jr z, .sourceWithOneMon
- ld hl, wBattleMonMoves ; player's in-battle pokemon
-.sourceWithOneMon
- call GetSelectedMoveOffset2
- jr .next
-.sourceWithMultipleMon
- call GetSelectedMoveOffset
-.next
- ld a, [hl]
- dec a
- push hl
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld de, wcd6d
- ld a, BANK(Moves)
- call FarCopyData
- ld de, wcd6d + 5 ; PP is byte 5 of move data
- ld a, [de]
- ld b, a ; b = normal max PP
- pop hl
- push bc
- ld bc, wPartyMon1PP - wPartyMon1Moves ; PP offset if not player's in-battle pokemon data
- ld a, [wMonDataLocation]
- cp 4 ; player's in-battle pokemon?
- jr nz, .addPPOffset
- ld bc, wBattleMonPP - wBattleMonMoves ; PP offset if player's in-battle pokemon data
-.addPPOffset
- add hl, bc
- ld a, [hl] ; a = current PP
- and %11000000 ; get PP Up count
- pop bc
- or b ; place normal max PP in 6 lower bits of a
- ld h, d
- ld l, e
- inc hl ; hl = wcd73
- ld [hl], a
- xor a ; add the bonus for the existing PP Up count
- ld [wUsingPPUp], a
- call AddBonusPP ; add bonus PP from PP Ups
- ld a, [hl]
- and %00111111 ; mask out the PP Up count
- ld [wMaxPP], a ; store max PP
- ret
-
-GetSelectedMoveOffset:
- ld a, [wWhichPokemon]
- call AddNTimes
-
-GetSelectedMoveOffset2:
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, 0
- add hl, bc
- ret
-
-; confirms the item toss and then tosses the item
-; INPUT:
-; hl = address of inventory (either wNumBagItems or wNumBoxItems)
-; [wcf91] = item ID
-; [wWhichPokemon] = index of item within inventory
-; [wItemQuantity] = quantity to toss
-; OUTPUT:
-; clears carry flag if the item is tossed, sets carry flag if not
-TossItem_:
- push hl
- ld a, [wcf91]
- call IsItemHM
- pop hl
- jr c, .tooImportantToToss
- push hl
- call IsKeyItem_
- ld a, [wIsKeyItem]
- pop hl
- and a
- jr nz, .tooImportantToToss
- push hl
- ld a, [wcf91]
- ld [wd11e], a
- call GetItemName
- call CopyStringToCF4B ; copy name to wcf4b
- ld hl, IsItOKToTossItemText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wMenuExitMethod]
- cp CHOSE_SECOND_ITEM
- pop hl
- scf
- ret z ; return if the player chose No
-; if the player chose Yes
- push hl
- ld a, [wWhichPokemon]
- call RemoveItemFromInventory
- ld a, [wcf91]
- ld [wd11e], a
- call GetItemName
- call CopyStringToCF4B ; copy name to wcf4b
- ld hl, ThrewAwayItemText
- call PrintText
- pop hl
- and a
- ret
-.tooImportantToToss
- push hl
- ld hl, TooImportantToTossText
- call PrintText
- pop hl
- scf
- ret
-
-ThrewAwayItemText:
- TX_FAR _ThrewAwayItemText
- db "@"
-
-IsItOKToTossItemText:
- TX_FAR _IsItOKToTossItemText
- db "@"
-
-TooImportantToTossText:
- TX_FAR _TooImportantToTossText
- db "@"
-
-; checks if an item is a key item
-; INPUT:
-; [wcf91] = item ID
-; OUTPUT:
-; [wIsKeyItem] = result
-; 00: item is not key item
-; 01: item is key item
-IsKeyItem_:
- ld a, $01
- ld [wIsKeyItem], a
- ld a, [wcf91]
- cp HM_01 ; is the item an HM or TM?
- jr nc, .checkIfItemIsHM
-; if the item is not an HM or TM
- push af
- ld hl, KeyItemBitfield
- ld de, wBuffer
- ld bc, 15 ; only 11 bytes are actually used
- call CopyData
- pop af
- dec a
- ld c, a
- ld hl, wBuffer
- ld b, FLAG_TEST
- predef FlagActionPredef
- ld a, c
- and a
- ret nz
-.checkIfItemIsHM
- ld a, [wcf91]
- call IsItemHM
- ret c
- xor a
- ld [wIsKeyItem], a
- ret
-
-INCLUDE "data/key_items.asm"
-
-SendNewMonToBox:
- ld de, wNumInBox
- ld a, [de]
- inc a
- ld [de], a
- ld a, [wcf91]
- ld [wd0b5], a
- ld c, a
-.asm_e7b1
- inc de
- ld a, [de]
- ld b, a
- ld a, c
- ld c, b
- ld [de], a
- cp $ff
- jr nz, .asm_e7b1
- call GetMonHeader
- ld hl, wBoxMonOT
- ld bc, NAME_LENGTH
- ld a, [wNumInBox]
- dec a
- jr z, .asm_e7ee
- dec a
- call AddNTimes
- push hl
- ld bc, NAME_LENGTH
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [wNumInBox]
- dec a
- ld b, a
-.asm_e7db
- push bc
- push hl
- ld bc, NAME_LENGTH
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, -NAME_LENGTH
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e7db
-.asm_e7ee
- ld hl, wPlayerName
- ld de, wBoxMonOT
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wNumInBox]
- dec a
- jr z, .asm_e82a
- ld hl, wBoxMonNicks
- ld bc, NAME_LENGTH
- dec a
- call AddNTimes
- push hl
- ld bc, NAME_LENGTH
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [wNumInBox]
- dec a
- ld b, a
-.asm_e817
- push bc
- push hl
- ld bc, NAME_LENGTH
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, -NAME_LENGTH
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e817
-.asm_e82a
- ld hl, wBoxMonNicks
- ld a, NAME_MON_SCREEN
- ld [wNamingScreenType], a
- predef AskName
- ld a, [wNumInBox]
- dec a
- jr z, .asm_e867
- ld hl, wBoxMons
- ld bc, wBoxMon2 - wBoxMon1
- dec a
- call AddNTimes
- push hl
- ld bc, wBoxMon2 - wBoxMon1
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld a, [wNumInBox]
- dec a
- ld b, a
-.asm_e854
- push bc
- push hl
- ld bc, wBoxMon2 - wBoxMon1
- call CopyData
- pop hl
- ld d, h
- ld e, l
- ld bc, wBoxMon1 - wBoxMon2
- add hl, bc
- pop bc
- dec b
- jr nz, .asm_e854
-.asm_e867
- ld a, [wEnemyMonLevel]
- ld [wEnemyMonBoxLevel], a
- ld hl, wEnemyMon
- ld de, wBoxMon1
- ld bc, wEnemyMonDVs - wEnemyMon
- call CopyData
- ld hl, wPlayerID
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- inc de
- push de
- ld a, [wCurEnemyLVL]
- ld d, a
- callab CalcExperience
- pop de
- ld a, [hExperience]
- ld [de], a
- inc de
- ld a, [hExperience + 1]
- ld [de], a
- inc de
- ld a, [hExperience + 2]
- ld [de], a
- inc de
- xor a
- ld b, NUM_STATS * 2
-.asm_e89f
- ld [de], a
- inc de
- dec b
- jr nz, .asm_e89f
- ld hl, wEnemyMonDVs
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- ld hl, wEnemyMonPP
- ld b, NUM_MOVES
-.asm_e8b1
- ld a, [hli]
- inc de
- ld [de], a
- dec b
- jr nz, .asm_e8b1
- ret
-
-; checks if the tile in front of the player is a shore or water tile
-; used for surfing and fishing
-; unsets carry if it is, sets carry if not
-IsNextTileShoreOrWater:
- ld a, [wCurMapTileset]
- ld hl, WaterTilesets
- ld de, 1
- call IsInArray
- jr nc, .notShoreOrWater
- ld a, [wCurMapTileset]
- cp SHIP_PORT ; Vermilion Dock tileset
- ld a, [wTileInFrontOfPlayer] ; tile in front of player
- jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset
- cp $48 ; eastern shore tile in Safari Zone
- jr z, .shoreOrWater
- cp $32 ; usual eastern shore tile
- jr z, .shoreOrWater
-.skipShoreTiles
- cp $14 ; water tile
- jr z, .shoreOrWater
-.notShoreOrWater
- scf
- ret
-.shoreOrWater
- and a
- ret
-
-; tilesets with water
-WaterTilesets:
- db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU
- db $ff ; terminator
-
-ReadSuperRodData:
-; return e = 2 if no fish on this map
-; return e = 1 if a bite, bc = level,species
-; return e = 0 if no bite
- ld a, [wCurMap]
- ld de, 3 ; each fishing group is three bytes wide
- ld hl, SuperRodData
- call IsInArray
- jr c, .ReadFishingGroup
- ld e, $2 ; $2 if no fishing groups found
- ret
-
-.ReadFishingGroup
-; hl points to the fishing group entry in the index
- inc hl ; skip map id
-
- ; read fishing group address
- ld a, [hli]
- ld h, [hl]
- ld l, a
-
- ld b, [hl] ; how many mons in group
- inc hl ; point to data
- ld e, $0 ; no bite yet
-
-.RandomLoop
- call Random
- srl a
- ret c ; 50% chance of no battle
-
- and %11 ; 2-bit random number
- cp b
- jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate
-
- ; get the mon
- add a
- ld c, a
- ld b, $0
- add hl, bc
- ld b, [hl] ; level
- inc hl
- ld c, [hl] ; species
- ld e, $1 ; $1 if there's a bite
- ret
-
-INCLUDE "data/super_rod.asm"
-
-; reloads map view and processes sprite data
-; for items that cause the overworld to be displayed
-ItemUseReloadOverworldData:
- call LoadCurrentMapView
- jp UpdateSprites
-
-; creates a list at wBuffer of maps where the mon in [wd11e] can be found.
-; this is used by the pokedex to display locations the mon can be found on the map.
-FindWildLocationsOfMon:
- ld hl, WildDataPointers
- ld de, wBuffer
- ld c, $0
-.loop
- inc hl
- ld a, [hld]
- inc a
- jr z, .done
- push hl
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [hli]
- and a
- call nz, CheckMapForMon ; land
- ld a, [hli]
- and a
- call nz, CheckMapForMon ; water
- pop hl
- inc hl
- inc hl
- inc c
- jr .loop
-.done
- ld a, $ff ; list terminator
- ld [de], a
- ret
-
-CheckMapForMon:
- inc hl
- ld b, $a
-.loop
- ld a, [wd11e]
- cp [hl]
- jr nz, .nextEntry
- ld a, c
- ld [de], a
- inc de
-.nextEntry
- inc hl
- inc hl
- dec b
- jr nz, .loop
- dec hl
- ret
diff --git a/engine/learn_move.asm b/engine/learn_move.asm
deleted file mode 100755
index 53c7f87e..00000000
--- a/engine/learn_move.asm
+++ /dev/null
@@ -1,226 +0,0 @@
-LearnMove:
- call SaveScreenTilesToBuffer1
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- ld hl, wcd6d
- ld de, wLearnMoveMonName
- ld bc, NAME_LENGTH
- call CopyData
-
-DontAbandonLearning:
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2Moves - wPartyMon1Moves
- ld a, [wWhichPokemon]
- call AddNTimes
- ld d, h
- ld e, l
- ld b, NUM_MOVES
-.findEmptyMoveSlotLoop
- ld a, [hl]
- and a
- jr z, .next
- inc hl
- dec b
- jr nz, .findEmptyMoveSlotLoop
- push de
- call TryingToLearn
- pop de
- jp c, AbandonLearning
- push hl
- push de
- ld [wd11e], a
- call GetMoveName
- ld hl, OneTwoAndText
- call PrintText
- pop de
- pop hl
-.next
- ld a, [wMoveNum]
- ld [hl], a
- ld bc, wPartyMon1PP - wPartyMon1Moves
- add hl, bc
- push hl
- push de
- dec a
- ld hl, Moves
- ld bc, MoveEnd - Moves
- call AddNTimes
- ld de, wBuffer
- ld a, BANK(Moves)
- call FarCopyData
- ld a, [wBuffer + 5] ; a = move's max PP
- pop de
- pop hl
- ld [hl], a
- ld a, [wIsInBattle]
- and a
- jp z, PrintLearnedMove
- ld a, [wWhichPokemon]
- ld b, a
- ld a, [wPlayerMonNumber]
- cp b
- jp nz, PrintLearnedMove
- ld h, d
- ld l, e
- ld de, wBattleMonMoves
- ld bc, NUM_MOVES
- call CopyData
- ld bc, wPartyMon1PP - wPartyMon1OTID
- add hl, bc
- ld de, wBattleMonPP
- ld bc, NUM_MOVES
- call CopyData
- jp PrintLearnedMove
-
-AbandonLearning:
- ld hl, AbandonLearningText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wCurrentMenuItem]
- and a
- jp nz, DontAbandonLearning
- ld hl, DidNotLearnText
- call PrintText
- ld b, 0
- ret
-
-PrintLearnedMove:
- ld hl, LearnedMove1Text
- call PrintText
- ld b, 1
- ret
-
-TryingToLearn:
- push hl
- ld hl, TryingToLearnText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- pop hl
- ld a, [wCurrentMenuItem]
- rra
- ret c
- ld bc, -NUM_MOVES
- add hl, bc
- push hl
- ld de, wMoves
- ld bc, NUM_MOVES
- call CopyData
- callab FormatMovesString
- pop hl
-.loop
- push hl
- ld hl, WhichMoveToForgetText
- call PrintText
- coord hl, 4, 7
- ld b, 4
- ld c, 14
- call TextBoxBorder
- coord hl, 6, 8
- ld de, wMovesString
- ld a, [hFlags_0xFFF6]
- set 2, a
- ld [hFlags_0xFFF6], a
- call PlaceString
- ld a, [hFlags_0xFFF6]
- res 2, a
- ld [hFlags_0xFFF6], a
- ld hl, wTopMenuItemY
- ld a, 8
- ld [hli], a ; wTopMenuItemY
- ld a, 5
- ld [hli], a ; wTopMenuItemX
- xor a
- ld [hli], a ; wCurrentMenuItem
- inc hl
- ld a, [wNumMovesMinusOne]
- ld [hli], a ; wMaxMenuItem
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- ld [hl], 0 ; wLastMenuItem
- ld hl, hFlags_0xFFF6
- set 1, [hl]
- call HandleMenuInput
- ld hl, hFlags_0xFFF6
- res 1, [hl]
- push af
- call LoadScreenTilesFromBuffer1
- pop af
- pop hl
- bit 1, a ; pressed b
- jr nz, .cancel
- push hl
- ld a, [wCurrentMenuItem]
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- push af
- push bc
- call IsMoveHM
- pop bc
- pop de
- ld a, d
- jr c, .hm
- pop hl
- add hl, bc
- and a
- ret
-.hm
- ld hl, HMCantDeleteText
- call PrintText
- pop hl
- jr .loop
-.cancel
- scf
- ret
-
-LearnedMove1Text:
- TX_FAR _LearnedMove1Text
- TX_SFX_ITEM_1 ; plays SFX_GET_ITEM_1 in the party menu (rare candy) and plays SFX_LEVEL_UP in battle
- TX_BLINK
- db "@"
-
-WhichMoveToForgetText:
- TX_FAR _WhichMoveToForgetText
- db "@"
-
-AbandonLearningText:
- TX_FAR _AbandonLearningText
- db "@"
-
-DidNotLearnText:
- TX_FAR _DidNotLearnText
- db "@"
-
-TryingToLearnText:
- TX_FAR _TryingToLearnText
- db "@"
-
-OneTwoAndText:
- TX_FAR _OneTwoAndText
- TX_DELAY
- TX_ASM
- ld a, SFX_SWAP
- call PlaySoundWaitForCurrent
- ld hl, PoofText
- ret
-
-PoofText:
- TX_FAR _PoofText
- TX_DELAY
-ForgotAndText:
- TX_FAR _ForgotAndText
- db "@"
-
-HMCantDeleteText:
- TX_FAR _HMCantDeleteText
- db "@"
diff --git a/engine/menu/bills_pc.asm b/engine/menu/bills_pc.asm
deleted file mode 100644
index 85a546e1..00000000
--- a/engine/menu/bills_pc.asm
+++ /dev/null
@@ -1,554 +0,0 @@
-DisplayPCMainMenu::
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call SaveScreenTilesToBuffer2
- ld a, [wNumHoFTeams]
- and a
- jr nz, .leaguePCAvailable
- CheckEvent EVENT_GOT_POKEDEX
- jr z, .noOaksPC
- ld a, [wNumHoFTeams]
- and a
- jr nz, .leaguePCAvailable
- coord hl, 0, 0
- ld b, 8
- ld c, 14
- jr .next
-.noOaksPC
- coord hl, 0, 0
- ld b, 6
- ld c, 14
- jr .next
-.leaguePCAvailable
- coord hl, 0, 0
- ld b, 10
- ld c, 14
-.next
- call TextBoxBorder
- call UpdateSprites
- ld a, 3
- ld [wMaxMenuItem], a
- CheckEvent EVENT_MET_BILL
- jr nz, .metBill
- coord hl, 2, 2
- ld de, SomeonesPCText
- jr .next2
-.metBill
- coord hl, 2, 2
- ld de, BillsPCText
-.next2
- call PlaceString
- coord hl, 2, 4
- ld de, wPlayerName
- call PlaceString
- ld l, c
- ld h, b
- ld de, PlayersPCText
- call PlaceString
- CheckEvent EVENT_GOT_POKEDEX
- jr z, .noOaksPC2
- coord hl, 2, 6
- ld de, OaksPCText
- call PlaceString
- ld a, [wNumHoFTeams]
- and a
- jr z, .noLeaguePC
- ld a, 4
- ld [wMaxMenuItem], a
- coord hl, 2, 8
- ld de, PKMNLeaguePCText
- call PlaceString
- coord hl, 2, 10
- ld de, LogOffPCText
- jr .next3
-.noLeaguePC
- coord hl, 2, 8
- ld de, LogOffPCText
- jr .next3
-.noOaksPC2
- ld a, $2
- ld [wMaxMenuItem], a
- coord hl, 2, 6
- ld de, LogOffPCText
-.next3
- call PlaceString
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 2
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-SomeonesPCText: db "SOMEONE's PC@"
-BillsPCText: db "BILL's PC@"
-PlayersPCText: db "'s PC@"
-OaksPCText: db "PROF.OAK's PC@"
-PKMNLeaguePCText: db $4a, "LEAGUE@"
-LogOffPCText: db "LOG OFF@"
-
-BillsPC_::
- ld hl, wd730
- set 6, [hl]
- xor a
- ld [wParentMenuItem], a
- inc a ; MONSTER_NAME
- ld [wNameListType], a
- call LoadHpBarAndStatusTilePatterns
- ld a, [wListScrollOffset]
- push af
- ld a, [wFlags_0xcd60]
- bit 3, a ; accessing Bill's PC through another PC?
- jr nz, BillsPCMenu
-; accessing it directly
- ld a, $99
- call PlaySound
- ld hl, SwitchOnText
- call PrintText
-
-BillsPCMenu:
- ld a, [wParentMenuItem]
- ld [wCurrentMenuItem], a
- ld hl, vChars2 + $780
- ld de, PokeballTileGraphics
- lb bc, BANK(PokeballTileGraphics), $01
- call CopyVideoData
- call LoadScreenTilesFromBuffer2DisableBGTransfer
- coord hl, 0, 0
- ld b, 10
- ld c, 12
- call TextBoxBorder
- coord hl, 2, 2
- ld de, BillsPCMenuText
- call PlaceString
- ld hl, wTopMenuItemY
- ld a, 2
- ld [hli], a ; wTopMenuItemY
- dec a
- ld [hli], a ; wTopMenuItemX
- inc hl
- inc hl
- ld a, 4
- ld [hli], a ; wMaxMenuItem
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- xor a
- ld [hli], a ; wLastMenuItem
- ld [hli], a ; wPartyAndBillsPCSavedMenuItem
- ld hl, wListScrollOffset
- ld [hli], a ; wListScrollOffset
- ld [hl], a ; wMenuWatchMovingOutOfBounds
- ld [wPlayerMonNumber], a
- ld hl, WhatText
- call PrintText
- coord hl, 9, 14
- ld b, 2
- ld c, 9
- call TextBoxBorder
- ld a, [wCurrentBoxNum]
- and $7f
- cp 9
- jr c, .singleDigitBoxNum
-; two digit box num
- sub 9
- coord hl, 17, 16
- ld [hl], "1"
- add "0"
- jr .next
-.singleDigitBoxNum
- add "1"
-.next
- Coorda 18, 16
- coord hl, 10, 16
- ld de, BoxNoPCText
- call PlaceString
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- call HandleMenuInput
- bit 1, a
- jp nz, ExitBillsPC ; b button
- call PlaceUnfilledArrowMenuCursor
- ld a, [wCurrentMenuItem]
- ld [wParentMenuItem], a
- and a
- jp z, BillsPCWithdraw ; withdraw
- cp $1
- jp z, BillsPCDeposit ; deposit
- cp $2
- jp z, BillsPCRelease ; release
- cp $3
- jp z, BillsPCChangeBox ; change box
-
-ExitBillsPC:
- ld a, [wFlags_0xcd60]
- bit 3, a ; accessing Bill's PC through another PC?
- jr nz, .next
-; accessing it directly
- call LoadTextBoxTilePatterns
- ld a, $9a
- call PlaySound
- call WaitForSoundToFinish
-.next
- ld hl, wFlags_0xcd60
- res 5, [hl]
- call LoadScreenTilesFromBuffer2
- pop af
- ld [wListScrollOffset], a
- ld hl, wd730
- res 6, [hl]
- ret
-
-BillsPCDeposit:
- ld a, [wPartyCount]
- dec a
- jr nz, .partyLargeEnough
- ld hl, CantDepositLastMonText
- call PrintText
- jp BillsPCMenu
-.partyLargeEnough
- ld a, [wNumInBox]
- cp MONS_PER_BOX
- jr nz, .boxNotFull
- ld hl, BoxFullText
- call PrintText
- jp BillsPCMenu
-.boxNotFull
- ld hl, wPartyCount
- call DisplayMonListMenu
- jp c, BillsPCMenu
- call DisplayDepositWithdrawMenu
- jp nc, BillsPCMenu
- ld a, [wcf91]
- call GetCryData
- call PlaySoundWaitForCurrent
- ld a, PARTY_TO_BOX
- ld [wMoveMonType], a
- call MoveMon
- xor a
- ld [wRemoveMonFromBox], a
- call RemovePokemon
- call WaitForSoundToFinish
- ld hl, wBoxNumString
- ld a, [wCurrentBoxNum]
- and $7f
- cp 9
- jr c, .singleDigitBoxNum
- sub 9
- ld [hl], "1"
- inc hl
- add "0"
- jr .next
-.singleDigitBoxNum
- add "1"
-.next
- ld [hli], a
- ld [hl], "@"
- ld hl, MonWasStoredText
- call PrintText
- jp BillsPCMenu
-
-BillsPCWithdraw:
- ld a, [wNumInBox]
- and a
- jr nz, .boxNotEmpty
- ld hl, NoMonText
- call PrintText
- jp BillsPCMenu
-.boxNotEmpty
- ld a, [wPartyCount]
- cp PARTY_LENGTH
- jr nz, .partyNotFull
- ld hl, CantTakeMonText
- call PrintText
- jp BillsPCMenu
-.partyNotFull
- ld hl, wNumInBox
- call DisplayMonListMenu
- jp c, BillsPCMenu
- call DisplayDepositWithdrawMenu
- jp nc, BillsPCMenu
- ld a, [wWhichPokemon]
- ld hl, wBoxMonNicks
- call GetPartyMonName
- ld a, [wcf91]
- call GetCryData
- call PlaySoundWaitForCurrent
- xor a ; BOX_TO_PARTY
- ld [wMoveMonType], a
- call MoveMon
- ld a, 1
- ld [wRemoveMonFromBox], a
- call RemovePokemon
- call WaitForSoundToFinish
- ld hl, MonIsTakenOutText
- call PrintText
- jp BillsPCMenu
-
-BillsPCRelease:
- ld a, [wNumInBox]
- and a
- jr nz, .loop
- ld hl, NoMonText
- call PrintText
- jp BillsPCMenu
-.loop
- ld hl, wNumInBox
- call DisplayMonListMenu
- jp c, BillsPCMenu
- ld hl, OnceReleasedText
- call PrintText
- call YesNoChoice
- ld a, [wCurrentMenuItem]
- and a
- jr nz, .loop
- inc a
- ld [wRemoveMonFromBox], a
- call RemovePokemon
- call WaitForSoundToFinish
- ld a, [wcf91]
- call PlayCry
- ld hl, MonWasReleasedText
- call PrintText
- jp BillsPCMenu
-
-BillsPCChangeBox:
- callba ChangeBox
- jp BillsPCMenu
-
-DisplayMonListMenu:
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wPrintItemPrices], a
- ld [wListMenuID], a
- inc a ; MONSTER_NAME
- ld [wNameListType], a
- ld a, [wPartyAndBillsPCSavedMenuItem]
- ld [wCurrentMenuItem], a
- call DisplayListMenuID
- ld a, [wCurrentMenuItem]
- ld [wPartyAndBillsPCSavedMenuItem], a
- ret
-
-BillsPCMenuText:
- db "WITHDRAW ", $4a
- next "DEPOSIT ", $4a
- next "RELEASE ", $4a
- next "CHANGE BOX"
- next "SEE YA!"
- db "@"
-
-BoxNoPCText:
- db "BOX No.@"
-
-KnowsHMMove::
-; returns whether mon with party index [wWhichPokemon] knows an HM move
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- jr .next
-; unreachable
- ld hl, wBoxMon1Moves
- ld bc, wBoxMon2 - wBoxMon1
-.next
- ld a, [wWhichPokemon]
- call AddNTimes
- ld b, NUM_MOVES
-.loop
- ld a, [hli]
- push hl
- push bc
- ld hl, HMMoveArray
- ld de, 1
- call IsInArray
- pop bc
- pop hl
- ret c
- dec b
- jr nz, .loop
- and a
- ret
-
-HMMoveArray:
- db CUT
- db FLY
- db SURF
- db STRENGTH
- db FLASH
- db -1
-
-DisplayDepositWithdrawMenu:
- coord hl, 9, 10
- ld b, 6
- ld c, 9
- call TextBoxBorder
- ld a, [wParentMenuItem]
- and a ; was the Deposit or Withdraw item selected in the parent menu?
- ld de, DepositPCText
- jr nz, .next
- ld de, WithdrawPCText
-.next
- coord hl, 11, 12
- call PlaceString
- coord hl, 11, 14
- ld de, StatsCancelPCText
- call PlaceString
- ld hl, wTopMenuItemY
- ld a, 12
- ld [hli], a ; wTopMenuItemY
- ld a, 10
- ld [hli], a ; wTopMenuItemX
- xor a
- ld [hli], a ; wCurrentMenuItem
- inc hl
- ld a, 2
- ld [hli], a ; wMaxMenuItem
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- xor a
- ld [hl], a ; wLastMenuItem
- ld hl, wListScrollOffset
- ld [hli], a ; wListScrollOffset
- ld [hl], a ; wMenuWatchMovingOutOfBounds
- ld [wPlayerMonNumber], a
- ld [wPartyAndBillsPCSavedMenuItem], a
-.loop
- call HandleMenuInput
- bit 1, a ; pressed B?
- jr nz, .exit
- ld a, [wCurrentMenuItem]
- and a
- jr z, .choseDepositWithdraw
- dec a
- jr z, .viewStats
-.exit
- and a
- ret
-.choseDepositWithdraw
- scf
- ret
-.viewStats
- call SaveScreenTilesToBuffer1
- ld a, [wParentMenuItem]
- and a
- ld a, PLAYER_PARTY_DATA
- jr nz, .next2
- ld a, BOX_DATA
-.next2
- ld [wMonDataLocation], a
- predef StatusScreen
- predef StatusScreen2
- call LoadScreenTilesFromBuffer1
- call ReloadTilesetTilePatterns
- call RunDefaultPaletteCommand
- call LoadGBPal
- jr .loop
-
-DepositPCText: db "DEPOSIT@"
-WithdrawPCText: db "WITHDRAW@"
-StatsCancelPCText:
- db "STATS"
- next "CANCEL@"
-
-SwitchOnText:
- TX_FAR _SwitchOnText
- db "@"
-
-WhatText:
- TX_FAR _WhatText
- db "@"
-
-DepositWhichMonText:
- TX_FAR _DepositWhichMonText
- db "@"
-
-MonWasStoredText:
- TX_FAR _MonWasStoredText
- db "@"
-
-CantDepositLastMonText:
- TX_FAR _CantDepositLastMonText
- db "@"
-
-BoxFullText:
- TX_FAR _BoxFullText
- db "@"
-
-MonIsTakenOutText:
- TX_FAR _MonIsTakenOutText
- db "@"
-
-NoMonText:
- TX_FAR _NoMonText
- db "@"
-
-CantTakeMonText:
- TX_FAR _CantTakeMonText
- db "@"
-
-ReleaseWhichMonText:
- TX_FAR _ReleaseWhichMonText
- db "@"
-
-OnceReleasedText:
- TX_FAR _OnceReleasedText
- db "@"
-
-MonWasReleasedText:
- TX_FAR _MonWasReleasedText
- db "@"
-
-CableClubLeftGameboy::
- ld a, [hSerialConnectionStatus]
- cp USING_EXTERNAL_CLOCK
- ret z
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- cp SPRITE_FACING_RIGHT
- ret nz
- ld a, [wCurMap]
- cp TRADE_CENTER
- ld a, LINK_STATE_START_TRADE
- jr z, .next
- inc a ; LINK_STATE_START_BATTLE
-.next
- ld [wLinkState], a
- call EnableAutoTextBoxDrawing
- tx_pre_jump JustAMomentText
-
-CableClubRightGameboy::
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- ret z
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- cp SPRITE_FACING_LEFT
- ret nz
- ld a, [wCurMap]
- cp TRADE_CENTER
- ld a, LINK_STATE_START_TRADE
- jr z, .next
- inc a ; LINK_STATE_START_BATTLE
-.next
- ld [wLinkState], a
- call EnableAutoTextBoxDrawing
- tx_pre_jump JustAMomentText
-
-JustAMomentText::
- TX_FAR _JustAMomentText
- db "@"
-
- ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction
- cp SPRITE_FACING_UP
- ret nz
- call EnableAutoTextBoxDrawing
- tx_pre_jump OpenBillsPCText
-
-OpenBillsPCText::
- db $FD ; FuncTX_BillsPC
-
diff --git a/engine/menu/diploma.asm b/engine/menu/diploma.asm
deleted file mode 100755
index 09ba123e..00000000
--- a/engine/menu/diploma.asm
+++ /dev/null
@@ -1,113 +0,0 @@
-DisplayDiploma:
- call SaveScreenTilesToBuffer2
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- xor a
- ld [wUpdateSpritesEnabled], a
- ld hl, wd730
- set 6, [hl]
- call DisableLCD
- ld hl, CircleTile
- ld de, vChars2 + $700
- ld bc, $0010
- ld a, BANK(CircleTile)
- call FarCopyData2
- coord hl, 0, 0
- lb bc, 16, 18
- predef Diploma_TextBoxBorder
- ld hl, DiplomaTextPointersAndCoords
- ld c, $5
-.asm_56715
- push bc
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- ld a, [hli]
- push hl
- ld h, [hl]
- ld l, a
- call PlaceString
- pop hl
- inc hl
- pop bc
- dec c
- jr nz, .asm_56715
- coord hl, 10, 4
- ld de, wPlayerName
- call PlaceString
- callba DrawPlayerCharacter
-
-; Move the player 33 pixels right and set the priority bit so he appears
-; behind the background layer.
- ld hl, wOAMBuffer + $01
- lb bc, $80, $28
-.adjustPlayerGfxLoop
- ld a, [hl] ; X
- add 33
- ld [hli], a
- inc hl
- ld a, b
- ld [hli], a ; attributes
- inc hl
- dec c
- jr nz, .adjustPlayerGfxLoop
-
- call EnableLCD
- callba LoadTrainerInfoTextBoxTiles
- ld b, SET_PAL_GENERIC
- call RunPaletteCommand
- call Delay3
- call GBPalNormal
- ld a, $90
- ld [rOBP0], a
- call WaitForTextScrollButtonPress
- ld hl, wd730
- res 6, [hl]
- call GBPalWhiteOutWithDelay3
- call RestoreScreenTilesAndReloadTilePatterns
- call Delay3
- jp GBPalNormal
-
-UnusedPlayerNameLengthFunc:
-; Unused function that does a calculation involving the length of the player's
-; name.
- ld hl, wPlayerName
- ld bc, $ff00
-.loop
- ld a, [hli]
- cp "@"
- ret z
- dec c
- jr .loop
-
-DiplomaTextPointersAndCoords:
- dw DiplomaText
- dwCoord 5, 2
- dw DiplomaPlayer
- dwCoord 3, 4
- dw DiplomaEmptyText
- dwCoord 15, 4
- dw DiplomaCongrats
- dwCoord 2, 6
- dw DiplomaGameFreak
- dwCoord 9, 16
-
-DiplomaText:
- db $70,"Diploma",$70,"@"
-
-DiplomaPlayer:
- db "Player@"
-
-DiplomaEmptyText:
- db "@"
-
-DiplomaCongrats:
- db "Congrats! This"
- next "diploma certifies"
- next "that you have"
- next "completed your"
- next "#DEX.@"
-
-DiplomaGameFreak:
- db "GAME FREAK@"
diff --git a/engine/menu/draw_start_menu.asm b/engine/menu/draw_start_menu.asm
deleted file mode 100644
index 11777dc6..00000000
--- a/engine/menu/draw_start_menu.asm
+++ /dev/null
@@ -1,89 +0,0 @@
-; function that displays the start menu
-DrawStartMenu:
- CheckEvent EVENT_GOT_POKEDEX
-; menu with pokedex
- coord hl, 10, 0
- ld b, $0e
- ld c, $08
- jr nz, .drawTextBoxBorder
-; shorter menu if the player doesn't have the pokedex
- coord hl, 10, 0
- ld b, $0c
- ld c, $08
-.drawTextBoxBorder
- call TextBoxBorder
- ld a, D_DOWN | D_UP | START | B_BUTTON | A_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, $02
- ld [wTopMenuItemY], a ; Y position of first menu choice
- ld a, $0b
- ld [wTopMenuItemX], a ; X position of first menu choice
- ld a, [wBattleAndStartSavedMenuItem] ; remembered menu selection from last time
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- xor a
- ld [wMenuWatchMovingOutOfBounds], a
- ld hl, wd730
- set 6, [hl] ; no pauses between printing each letter
- coord hl, 12, 2
- CheckEvent EVENT_GOT_POKEDEX
-; case for not having pokedex
- ld a, $06
- jr z, .storeMenuItemCount
-; case for having pokedex
- ld de, StartMenuPokedexText
- call PrintStartMenuItem
- ld a, $07
-.storeMenuItemCount
- ld [wMaxMenuItem], a ; number of menu items
- ld de, StartMenuPokemonText
- call PrintStartMenuItem
- ld de, StartMenuItemText
- call PrintStartMenuItem
- ld de, wPlayerName ; player's name
- call PrintStartMenuItem
- ld a, [wd72e]
- bit 6, a ; is the player using the link feature?
-; case for not using link feature
- ld de, StartMenuSaveText
- jr z, .printSaveOrResetText
-; case for using link feature
- ld de, StartMenuResetText
-.printSaveOrResetText
- call PrintStartMenuItem
- ld de, StartMenuOptionText
- call PrintStartMenuItem
- ld de, StartMenuExitText
- call PlaceString
- ld hl, wd730
- res 6, [hl] ; turn pauses between printing letters back on
- ret
-
-StartMenuPokedexText:
- db "POKéDEX@"
-
-StartMenuPokemonText:
- db "POKéMON@"
-
-StartMenuItemText:
- db "ITEM@"
-
-StartMenuSaveText:
- db "SAVE@"
-
-StartMenuResetText:
- db "RESET@"
-
-StartMenuExitText:
- db "EXIT@"
-
-StartMenuOptionText:
- db "OPTION@"
-
-PrintStartMenuItem:
- push hl
- call PlaceString
- pop hl
- ld de, SCREEN_WIDTH * 2
- add hl, de
- ret
diff --git a/engine/menu/league_pc.asm b/engine/menu/league_pc.asm
deleted file mode 100755
index 170c0ef3..00000000
--- a/engine/menu/league_pc.asm
+++ /dev/null
@@ -1,120 +0,0 @@
-PKMNLeaguePC:
- ld hl, AccessedHoFPCText
- call PrintText
- ld hl, wd730
- set 6, [hl]
- push hl
- ld a, [wUpdateSpritesEnabled]
- push af
- ld a, [hTilesetType]
- push af
- xor a
- ld [hTilesetType], a
- ld [wSpriteFlipped], a
- ld [wUpdateSpritesEnabled], a
- ld [wHoFTeamIndex2], a
- ld [wHoFTeamNo], a
- ld a, [wNumHoFTeams]
- ld b, a
- cp HOF_TEAM_CAPACITY + 1
- jr c, .loop
-; If the total number of hall of fame teams is greater than the storage
-; capacity, then calculate the number of the first team that is still recorded.
- ld b, HOF_TEAM_CAPACITY
- sub b
- ld [wHoFTeamNo], a
-.loop
- ld hl, wHoFTeamNo
- inc [hl]
- push bc
- ld a, [wHoFTeamIndex2]
- ld [wHoFTeamIndex], a
- callba LoadHallOfFameTeams
- call LeaguePCShowTeam
- pop bc
- jr c, .doneShowingTeams
- ld hl, wHoFTeamIndex2
- inc [hl]
- ld a, [hl]
- cp b
- jr nz, .loop
-.doneShowingTeams
- pop af
- ld [hTilesetType], a
- pop af
- ld [wUpdateSpritesEnabled], a
- pop hl
- res 6, [hl]
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call RunDefaultPaletteCommand
- jp GBPalNormal
-
-LeaguePCShowTeam:
- ld c, PARTY_LENGTH
-.loop
- push bc
- call LeaguePCShowMon
- call WaitForTextScrollButtonPress
- ld a, [hJoyHeld]
- bit 1, a
- jr nz, .exit
- ld hl, wHallOfFame + HOF_MON
- ld de, wHallOfFame
- ld bc, HOF_TEAM - HOF_MON
- call CopyData
- pop bc
- ld a, [wHallOfFame + 0]
- cp $ff
- jr z, .done
- dec c
- jr nz, .loop
-.done
- and a
- ret
-.exit
- pop bc
- scf
- ret
-
-LeaguePCShowMon:
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- ld hl, wHallOfFame
- ld a, [hli]
- ld [wHoFMonSpecies], a
- ld [wcf91], a
- ld [wd0b5], a
- ld [wBattleMonSpecies2], a
- ld [wWholeScreenPaletteMonSpecies], a
- ld a, [hli]
- ld [wHoFMonLevel], a
- ld de, wcd6d
- ld bc, NAME_LENGTH
- call CopyData
- ld b, SET_PAL_POKEMON_WHOLE_SCREEN
- ld c, 0
- call RunPaletteCommand
- coord hl, 12, 5
- call GetMonHeader
- call LoadFrontSpriteByMonIndex
- call GBPalNormal
- coord hl, 0, 13
- ld b, 2
- ld c, $12
- call TextBoxBorder
- coord hl, 1, 15
- ld de, HallOfFameNoText
- call PlaceString
- coord hl, 16, 15
- ld de, wHoFTeamNo
- lb bc, 1, 3
- call PrintNumber
- jpba HoFDisplayMonInfo
-
-HallOfFameNoText:
- db "HALL OF FAME No @"
-
-AccessedHoFPCText:
- TX_FAR _AccessedHoFPCText
- db "@"
diff --git a/engine/menu/main_menu.asm b/engine/menu/main_menu.asm
deleted file mode 100755
index da2e98e4..00000000
--- a/engine/menu/main_menu.asm
+++ /dev/null
@@ -1,712 +0,0 @@
-MainMenu:
-; Check save file
- call InitOptions
- xor a
- ld [wOptionsInitialized], a
- inc a
- ld [wSaveFileStatus], a
- call CheckForPlayerNameInSRAM
- jr nc, .mainMenuLoop
-
- predef LoadSAV
-
-.mainMenuLoop
- ld c, 20
- call DelayFrames
- xor a ; LINK_STATE_NONE
- ld [wLinkState], a
- ld hl, wPartyAndBillsPCSavedMenuItem
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wDefaultMap], a
- ld hl, wd72e
- res 6, [hl]
- call ClearScreen
- call RunDefaultPaletteCommand
- call LoadTextBoxTilePatterns
- call LoadFontTilePatterns
- ld hl, wd730
- set 6, [hl]
- ld a, [wSaveFileStatus]
- cp 1
- jr z, .noSaveFile
-; there's a save file
- coord hl, 0, 0
- ld b, 6
- ld c, 13
- call TextBoxBorder
- coord hl, 2, 2
- ld de, ContinueText
- call PlaceString
- jr .next2
-.noSaveFile
- coord hl, 0, 0
- ld b, 4
- ld c, 13
- call TextBoxBorder
- coord hl, 2, 2
- ld de, NewGameText
- call PlaceString
-.next2
- ld hl, wd730
- res 6, [hl]
- call UpdateSprites
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [wMenuJoypadPollCount], a
- inc a
- ld [wTopMenuItemX], a
- inc a
- ld [wTopMenuItemY], a
- ld a, A_BUTTON | B_BUTTON | START
- ld [wMenuWatchedKeys], a
- ld a, [wSaveFileStatus]
- ld [wMaxMenuItem], a
- call HandleMenuInput
- bit 1, a ; pressed B?
- jp nz, DisplayTitleScreen ; if so, go back to the title screen
- ld c, 20
- call DelayFrames
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, [wSaveFileStatus]
- cp 2
- jp z, .skipInc
-; If there's no save file, increment the current menu item so that the numbers
-; are the same whether or not there's a save file.
- inc b
-.skipInc
- ld a, b
- and a
- jr z, .choseContinue
- cp 1
- jp z, StartNewGame
- call DisplayOptionMenu
- ld a, 1
- ld [wOptionsInitialized], a
- jp .mainMenuLoop
-.choseContinue
- call DisplayContinueGameInfo
- ld hl, wCurrentMapScriptFlags
- set 5, [hl]
-.inputLoop
- xor a
- ld [hJoyPressed], a
- ld [hJoyReleased], a
- ld [hJoyHeld], a
- call Joypad
- ld a, [hJoyHeld]
- bit 0, a
- jr nz, .pressedA
- bit 1, a
- jp nz, .mainMenuLoop ; pressed B
- jr .inputLoop
-.pressedA
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- ld a, PLAYER_DIR_DOWN
- ld [wPlayerDirection], a
- ld c, 10
- call DelayFrames
- ld a, [wNumHoFTeams]
- and a
- jp z, SpecialEnterMap
- ld a, [wCurMap] ; map ID
- cp HALL_OF_FAME
- jp nz, SpecialEnterMap
- xor a
- ld [wDestinationMap], a
- ld hl, wd732
- set 2, [hl] ; fly warp or dungeon warp
- call SpecialWarpIn
- jp SpecialEnterMap
-
-InitOptions:
- ld a, 1 ; no delay
- ld [wLetterPrintingDelayFlags], a
- ld a, 3 ; medium speed
- ld [wOptions], a
- ret
-
-LinkMenu:
- xor a
- ld [wLetterPrintingDelayFlags], a
- ld hl, wd72e
- set 6, [hl]
- ld hl, TextTerminator_6b20
- call PrintText
- call SaveScreenTilesToBuffer1
- ld hl, WhereWouldYouLikeText
- call PrintText
- coord hl, 5, 5
- ld b, $6
- ld c, $d
- call TextBoxBorder
- call UpdateSprites
- coord hl, 7, 7
- ld de, CableClubOptionsText
- call PlaceString
- xor a
- ld [wUnusedCD37], a
- ld [wd72d], a
- ld hl, wTopMenuItemY
- ld a, $7
- ld [hli], a
- ld a, $6
- ld [hli], a
- xor a
- ld [hli], a
- inc hl
- ld a, $2
- ld [hli], a
- inc a
- ; ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- xor a
- ld [hl], a
-.waitForInputLoop
- call HandleMenuInput
- and A_BUTTON | B_BUTTON
- add a
- add a
- ld b, a
- ld a, [wCurrentMenuItem]
- add b
- add $d0
- ld [wLinkMenuSelectionSendBuffer], a
- ld [wLinkMenuSelectionSendBuffer + 1], a
-.exchangeMenuSelectionLoop
- call Serial_ExchangeLinkMenuSelection
- ld a, [wLinkMenuSelectionReceiveBuffer]
- ld b, a
- and $f0
- cp $d0
- jr z, .asm_5c7d
- ld a, [wLinkMenuSelectionReceiveBuffer + 1]
- ld b, a
- and $f0
- cp $d0
- jr nz, .exchangeMenuSelectionLoop
-.asm_5c7d
- ld a, b
- and $c ; did the enemy press A or B?
- jr nz, .enemyPressedAOrB
-; the enemy didn't press A or B
- ld a, [wLinkMenuSelectionSendBuffer]
- and $c ; did the player press A or B?
- jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again
- jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection
-.enemyPressedAOrB
- ld a, [wLinkMenuSelectionSendBuffer]
- and $c ; did the player press A or B?
- jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection
-; the enemy and the player both pressed A or B
-; The gameboy that is clocking the connection wins.
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- jr z, .doneChoosingMenuSelection
-.useEnemyMenuSelection
- ld a, b
- ld [wLinkMenuSelectionSendBuffer], a
- and $3
- ld [wCurrentMenuItem], a
-.doneChoosingMenuSelection
- ld a, [hSerialConnectionStatus]
- cp USING_INTERNAL_CLOCK
- jr nz, .skipStartingTransfer
- call DelayFrame
- call DelayFrame
- ld a, START_TRANSFER_INTERNAL_CLOCK
- ld [rSC], a
-.skipStartingTransfer
- ld b, $7f
- ld c, $7f
- ld d, $ec
- ld a, [wLinkMenuSelectionSendBuffer]
- and (B_BUTTON << 2) ; was B button pressed?
- jr nz, .updateCursorPosition
-; A button was pressed
- ld a, [wCurrentMenuItem]
- cp $2
- jr z, .updateCursorPosition
- ld c, d
- ld d, b
- dec a
- jr z, .updateCursorPosition
- ld b, c
- ld c, d
-.updateCursorPosition
- ld a, b
- Coorda 6, 7
- ld a, c
- Coorda 6, 9
- ld a, d
- Coorda 6, 11
- ld c, 40
- call DelayFrames
- call LoadScreenTilesFromBuffer1
- ld a, [wLinkMenuSelectionSendBuffer]
- and (B_BUTTON << 2) ; was B button pressed?
- jr nz, .choseCancel ; cancel if B pressed
- ld a, [wCurrentMenuItem]
- cp $2
- jr z, .choseCancel
- xor a
- ld [wWalkBikeSurfState], a ; start walking
- ld a, [wCurrentMenuItem]
- and a
- ld a, COLOSSEUM
- jr nz, .next
- ld a, TRADE_CENTER
-.next
- ld [wd72d], a
- ld hl, PleaseWaitText
- call PrintText
- ld c, 50
- call DelayFrames
- ld hl, wd732
- res 1, [hl]
- ld a, [wDefaultMap]
- ld [wDestinationMap], a
- call SpecialWarpIn
- ld c, 20
- call DelayFrames
- xor a
- ld [wMenuJoypadPollCount], a
- ld [wSerialExchangeNybbleSendData], a
- inc a ; LINK_STATE_IN_CABLE_CLUB
- ld [wLinkState], a
- ld [wEnteringCableClub], a
- jr SpecialEnterMap
-.choseCancel
- xor a
- ld [wMenuJoypadPollCount], a
- call Delay3
- call CloseLinkConnection
- ld hl, LinkCanceledText
- call PrintText
- ld hl, wd72e
- res 6, [hl]
- ret
-
-WhereWouldYouLikeText:
- TX_FAR _WhereWouldYouLikeText
- db "@"
-
-PleaseWaitText:
- TX_FAR _PleaseWaitText
- db "@"
-
-LinkCanceledText:
- TX_FAR _LinkCanceledText
- db "@"
-
-StartNewGame:
- ld hl, wd732
- res 1, [hl]
- call OakSpeech
- ld c, 20
- call DelayFrames
-
-; enter map after using a special warp or loading the game from the main menu
-SpecialEnterMap:
- xor a
- ld [hJoyPressed], a
- ld [hJoyHeld], a
- ld [hJoy5], a
- ld [wd72d], a
- ld hl, wd732
- set 0, [hl] ; count play time
- call ResetPlayerSpriteData
- ld c, 20
- call DelayFrames
- ld a, [wEnteringCableClub]
- and a
- ret nz
- jp EnterMap
-
-ContinueText:
- db "CONTINUE", $4e
-
-NewGameText:
- db "NEW GAME"
- next "OPTION@"
-
-CableClubOptionsText:
- db "TRADE CENTER"
- next "COLOSSEUM"
- next "CANCEL@"
-
-DisplayContinueGameInfo:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 4, 7
- ld b, 8
- ld c, 14
- call TextBoxBorder
- coord hl, 5, 9
- ld de, SaveScreenInfoText
- call PlaceString
- coord hl, 12, 9
- ld de, wPlayerName
- call PlaceString
- coord hl, 17, 11
- call PrintNumBadges
- coord hl, 16, 13
- call PrintNumOwnedMons
- coord hl, 13, 15
- call PrintPlayTime
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld c, 30
- jp DelayFrames
-
-PrintSaveScreenText:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 4, 0
- ld b, $8
- ld c, $e
- call TextBoxBorder
- call LoadTextBoxTilePatterns
- call UpdateSprites
- coord hl, 5, 2
- ld de, SaveScreenInfoText
- call PlaceString
- coord hl, 12, 2
- ld de, wPlayerName
- call PlaceString
- coord hl, 17, 4
- call PrintNumBadges
- coord hl, 16, 6
- call PrintNumOwnedMons
- coord hl, 13, 8
- call PrintPlayTime
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld c, 30
- jp DelayFrames
-
-PrintNumBadges:
- push hl
- ld hl, wObtainedBadges
- ld b, $1
- call CountSetBits
- pop hl
- ld de, wNumSetBits
- lb bc, 1, 2
- jp PrintNumber
-
-PrintNumOwnedMons:
- push hl
- ld hl, wPokedexOwned
- ld b, wPokedexOwnedEnd - wPokedexOwned
- call CountSetBits
- pop hl
- ld de, wNumSetBits
- lb bc, 1, 3
- jp PrintNumber
-
-PrintPlayTime:
- ld de, wPlayTimeHours
- lb bc, 1, 3
- call PrintNumber
- ld [hl], $6d
- inc hl
- ld de, wPlayTimeMinutes
- lb bc, LEADING_ZEROES | 1, 2
- jp PrintNumber
-
-SaveScreenInfoText:
- db "PLAYER"
- next "BADGES "
- next "#DEX "
- next "TIME@"
-
-DisplayOptionMenu:
- coord hl, 0, 0
- ld b, 3
- ld c, 18
- call TextBoxBorder
- coord hl, 0, 5
- ld b, 3
- ld c, 18
- call TextBoxBorder
- coord hl, 0, 10
- ld b, 3
- ld c, 18
- call TextBoxBorder
- coord hl, 1, 1
- ld de, TextSpeedOptionText
- call PlaceString
- coord hl, 1, 6
- ld de, BattleAnimationOptionText
- call PlaceString
- coord hl, 1, 11
- ld de, BattleStyleOptionText
- call PlaceString
- coord hl, 2, 16
- ld de, OptionMenuCancelText
- call PlaceString
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- inc a
- ld [wLetterPrintingDelayFlags], a
- ld [wUnusedCD40], a
- ld a, 3 ; text speed cursor Y coordinate
- ld [wTopMenuItemY], a
- call SetCursorPositionsFromOptions
- ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
- ld [wTopMenuItemX], a
- ld a, $01
- ld [H_AUTOBGTRANSFERENABLED], a ; enable auto background transfer
- call Delay3
-.loop
- call PlaceMenuCursor
- call SetOptionsFromCursorPositions
-.getJoypadStateLoop
- call JoypadLowSensitivity
- ld a, [hJoy5]
- ld b, a
- and A_BUTTON | B_BUTTON | START | D_RIGHT | D_LEFT | D_UP | D_DOWN ; any key besides select pressed?
- jr z, .getJoypadStateLoop
- bit 1, b ; B button pressed?
- jr nz, .exitMenu
- bit 3, b ; Start button pressed?
- jr nz, .exitMenu
- bit 0, b ; A button pressed?
- jr z, .checkDirectionKeys
- ld a, [wTopMenuItemY]
- cp 16 ; is the cursor on Cancel?
- jr nz, .loop
-.exitMenu
- ld a, SFX_PRESS_AB
- call PlaySound
- ret
-.eraseOldMenuCursor
- ld [wTopMenuItemX], a
- call EraseMenuCursor
- jp .loop
-.checkDirectionKeys
- ld a, [wTopMenuItemY]
- bit 7, b ; Down pressed?
- jr nz, .downPressed
- bit 6, b ; Up pressed?
- jr nz, .upPressed
- cp 8 ; cursor in Battle Animation section?
- jr z, .cursorInBattleAnimation
- cp 13 ; cursor in Battle Style section?
- jr z, .cursorInBattleStyle
- cp 16 ; cursor on Cancel?
- jr z, .loop
-.cursorInTextSpeed
- bit 5, b ; Left pressed?
- jp nz, .pressedLeftInTextSpeed
- jp .pressedRightInTextSpeed
-.downPressed
- cp 16
- ld b, -13
- ld hl, wOptionsTextSpeedCursorX
- jr z, .updateMenuVariables
- ld b, 5
- cp 3
- inc hl
- jr z, .updateMenuVariables
- cp 8
- inc hl
- jr z, .updateMenuVariables
- ld b, 3
- inc hl
- jr .updateMenuVariables
-.upPressed
- cp 8
- ld b, -5
- ld hl, wOptionsTextSpeedCursorX
- jr z, .updateMenuVariables
- cp 13
- inc hl
- jr z, .updateMenuVariables
- cp 16
- ld b, -3
- inc hl
- jr z, .updateMenuVariables
- ld b, 13
- inc hl
-.updateMenuVariables
- add b
- ld [wTopMenuItemY], a
- ld a, [hl]
- ld [wTopMenuItemX], a
- call PlaceUnfilledArrowMenuCursor
- jp .loop
-.cursorInBattleAnimation
- ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate
- xor $0b ; toggle between 1 and 10
- ld [wOptionsBattleAnimCursorX], a
- jp .eraseOldMenuCursor
-.cursorInBattleStyle
- ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate
- xor $0b ; toggle between 1 and 10
- ld [wOptionsBattleStyleCursorX], a
- jp .eraseOldMenuCursor
-.pressedLeftInTextSpeed
- ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
- cp 1
- jr z, .updateTextSpeedXCoord
- cp 7
- jr nz, .fromSlowToMedium
- sub 6
- jr .updateTextSpeedXCoord
-.fromSlowToMedium
- sub 7
- jr .updateTextSpeedXCoord
-.pressedRightInTextSpeed
- ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
- cp 14
- jr z, .updateTextSpeedXCoord
- cp 7
- jr nz, .fromFastToMedium
- add 7
- jr .updateTextSpeedXCoord
-.fromFastToMedium
- add 6
-.updateTextSpeedXCoord
- ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate
- jp .eraseOldMenuCursor
-
-TextSpeedOptionText:
- db "TEXT SPEED"
- next " FAST MEDIUM SLOW@"
-
-BattleAnimationOptionText:
- db "BATTLE ANIMATION"
- next " ON OFF@"
-
-BattleStyleOptionText:
- db "BATTLE STYLE"
- next " SHIFT SET@"
-
-OptionMenuCancelText:
- db "CANCEL@"
-
-; sets the options variable according to the current placement of the menu cursors in the options menu
-SetOptionsFromCursorPositions:
- ld hl, TextSpeedOptionData
- ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate
- ld c, a
-.loop
- ld a, [hli]
- cp c
- jr z, .textSpeedMatchFound
- inc hl
- jr .loop
-.textSpeedMatchFound
- ld a, [hl]
- ld d, a
- ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate
- dec a
- jr z, .battleAnimationOn
-.battleAnimationOff
- set 7, d
- jr .checkBattleStyle
-.battleAnimationOn
- res 7, d
-.checkBattleStyle
- ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate
- dec a
- jr z, .battleStyleShift
-.battleStyleSet
- set 6, d
- jr .storeOptions
-.battleStyleShift
- res 6, d
-.storeOptions
- ld a, d
- ld [wOptions], a
- ret
-
-; reads the options variable and places menu cursors in the correct positions within the options menu
-SetCursorPositionsFromOptions:
- ld hl, TextSpeedOptionData + 1
- ld a, [wOptions]
- ld c, a
- and $3f
- push bc
- ld de, 2
- call IsInArray
- pop bc
- dec hl
- ld a, [hl]
- ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate
- coord hl, 0, 3
- call .placeUnfilledRightArrow
- sla c
- ld a, 1 ; On
- jr nc, .storeBattleAnimationCursorX
- ld a, 10 ; Off
-.storeBattleAnimationCursorX
- ld [wOptionsBattleAnimCursorX], a ; battle animation cursor X coordinate
- coord hl, 0, 8
- call .placeUnfilledRightArrow
- sla c
- ld a, 1
- jr nc, .storeBattleStyleCursorX
- ld a, 10
-.storeBattleStyleCursorX
- ld [wOptionsBattleStyleCursorX], a ; battle style cursor X coordinate
- coord hl, 0, 13
- call .placeUnfilledRightArrow
-; cursor in front of Cancel
- coord hl, 0, 16
- ld a, 1
-.placeUnfilledRightArrow
- ld e, a
- ld d, 0
- add hl, de
- ld [hl], $ec ; unfilled right arrow menu cursor
- ret
-
-; table that indicates how the 3 text speed options affect frame delays
-; Format:
-; 00: X coordinate of menu cursor
-; 01: delay after printing a letter (in frames)
-TextSpeedOptionData:
- db 14,5 ; Slow
- db 7,3 ; Medium
- db 1,1 ; Fast
- db 7 ; default X coordinate (Medium)
- db $ff ; terminator
-
-CheckForPlayerNameInSRAM:
-; Check if the player name data in SRAM has a string terminator character
-; (indicating that a name may have been saved there) and return whether it does
-; in carry.
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld b, NAME_LENGTH
- ld hl, sPlayerName
-.loop
- ld a, [hli]
- cp "@"
- jr z, .found
- dec b
- jr nz, .loop
-; not found
- xor a
- ld [MBC1SRamEnable], a
- ld [MBC1SRamBankingMode], a
- and a
- ret
-.found
- xor a
- ld [MBC1SRamEnable], a
- ld [MBC1SRamBankingMode], a
- scf
- ret
diff --git a/engine/menu/naming_screen.asm b/engine/menu/naming_screen.asm
deleted file mode 100755
index 64065c4d..00000000
--- a/engine/menu/naming_screen.asm
+++ /dev/null
@@ -1,512 +0,0 @@
-AskName:
- call SaveScreenTilesToBuffer1
- call GetPredefRegisters
- push hl
- ld a, [wIsInBattle]
- dec a
- coord hl, 0, 0
- ld b, 4
- ld c, 11
- call z, ClearScreenArea ; only if in wild battle
- ld a, [wcf91]
- ld [wd11e], a
- call GetMonName
- ld hl, DoYouWantToNicknameText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- pop hl
- ld a, [wCurrentMenuItem]
- and a
- jr nz, .declinedNickname
- ld a, [wUpdateSpritesEnabled]
- push af
- xor a
- ld [wUpdateSpritesEnabled], a
- push hl
- ld a, NAME_MON_SCREEN
- ld [wNamingScreenType], a
- call DisplayNamingScreen
- ld a, [wIsInBattle]
- and a
- jr nz, .inBattle
- call ReloadMapSpriteTilePatterns
-.inBattle
- call LoadScreenTilesFromBuffer1
- pop hl
- pop af
- ld [wUpdateSpritesEnabled], a
- ld a, [wcf4b]
- cp "@"
- ret nz
-.declinedNickname
- ld d, h
- ld e, l
- ld hl, wcd6d
- ld bc, NAME_LENGTH
- jp CopyData
-
-DoYouWantToNicknameText:
- TX_FAR _DoYouWantToNicknameText
- db "@"
-
-DisplayNameRaterScreen:
- ld hl, wBuffer
- xor a
- ld [wUpdateSpritesEnabled], a
- ld a, NAME_MON_SCREEN
- ld [wNamingScreenType], a
- call DisplayNamingScreen
- call GBPalWhiteOutWithDelay3
- call RestoreScreenTilesAndReloadTilePatterns
- call LoadGBPal
- ld a, [wcf4b]
- cp "@"
- jr z, .playerCancelled
- ld hl, wPartyMonNicks
- ld bc, NAME_LENGTH
- ld a, [wWhichPokemon]
- call AddNTimes
- ld e, l
- ld d, h
- ld hl, wBuffer
- ld bc, NAME_LENGTH
- call CopyData
- and a
- ret
-.playerCancelled
- scf
- ret
-
-DisplayNamingScreen:
- push hl
- ld hl, wd730
- set 6, [hl]
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call UpdateSprites
- ld b, SET_PAL_GENERIC
- call RunPaletteCommand
- call LoadHpBarAndStatusTilePatterns
- call LoadEDTile
- callba LoadMonPartySpriteGfx
- coord hl, 0, 4
- ld b, 9
- ld c, 18
- call TextBoxBorder
- call PrintNamingText
- ld a, 3
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
- ld [wLastMenuItem], a
- ld [wCurrentMenuItem], a
- ld a, $ff
- ld [wMenuWatchedKeys], a
- ld a, 7
- ld [wMaxMenuItem], a
- ld a, "@"
- ld [wcf4b], a
- xor a
- ld hl, wNamingScreenSubmitName
- ld [hli], a
- ld [hli], a
- ld [wAnimCounter], a
-.selectReturnPoint
- call PrintAlphabet
- call GBPalNormal
-.ABStartReturnPoint
- ld a, [wNamingScreenSubmitName]
- and a
- jr nz, .submitNickname
- call PrintNicknameAndUnderscores
-.dPadReturnPoint
- call PlaceMenuCursor
-.inputLoop
- ld a, [wCurrentMenuItem]
- push af
- callba AnimatePartyMon_ForceSpeed1
- pop af
- ld [wCurrentMenuItem], a
- call JoypadLowSensitivity
- ld a, [hJoyPressed]
- and a
- jr z, .inputLoop
- ld hl, .namingScreenButtonFunctions
-.checkForPressedButton
- sla a
- jr c, .foundPressedButton
- inc hl
- inc hl
- inc hl
- inc hl
- jr .checkForPressedButton
-.foundPressedButton
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- ld a, [hli]
- ld h, [hl]
- ld l, a
- push de
- jp hl
-
-.submitNickname
- pop de
- ld hl, wcf4b
- ld bc, NAME_LENGTH
- call CopyData
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call ClearSprites
- call RunDefaultPaletteCommand
- call GBPalNormal
- xor a
- ld [wAnimCounter], a
- ld hl, wd730
- res 6, [hl]
- ld a, [wIsInBattle]
- and a
- jp z, LoadTextBoxTilePatterns
- jpab LoadHudTilePatterns
-
-.namingScreenButtonFunctions
- dw .dPadReturnPoint
- dw .pressedDown
- dw .dPadReturnPoint
- dw .pressedUp
- dw .dPadReturnPoint
- dw .pressedLeft
- dw .dPadReturnPoint
- dw .pressedRight
- dw .ABStartReturnPoint
- dw .pressedStart
- dw .selectReturnPoint
- dw .pressedSelect
- dw .ABStartReturnPoint
- dw .pressedB
- dw .ABStartReturnPoint
- dw .pressedA
-
-.pressedA_changedCase
- pop de
- ld de, .selectReturnPoint
- push de
-.pressedSelect
- ld a, [wAlphabetCase]
- xor $1
- ld [wAlphabetCase], a
- ret
-
-.pressedStart
- ld a, 1
- ld [wNamingScreenSubmitName], a
- ret
-
-.pressedA
- ld a, [wCurrentMenuItem]
- cp $5 ; "ED" row
- jr nz, .didNotPressED
- ld a, [wTopMenuItemX]
- cp $11 ; "ED" column
- jr z, .pressedStart
-.didNotPressED
- ld a, [wCurrentMenuItem]
- cp $6 ; case switch row
- jr nz, .didNotPressCaseSwtich
- ld a, [wTopMenuItemX]
- cp $1 ; case switch column
- jr z, .pressedA_changedCase
-.didNotPressCaseSwtich
- ld hl, wMenuCursorLocation
- ld a, [hli]
- ld h, [hl]
- ld l, a
- inc hl
- ld a, [hl]
- ld [wNamingScreenLetter], a
- call CalcStringLength
- ld a, [wNamingScreenLetter]
- cp $e5
- ld de, Dakutens
- jr z, .dakutensAndHandakutens
- cp $e4
- ld de, Handakutens
- jr z, .dakutensAndHandakutens
- ld a, [wNamingScreenType]
- cp NAME_MON_SCREEN
- jr nc, .checkMonNameLength
- ld a, [wNamingScreenNameLength]
- cp $7 ; max length of player/rival names
- jr .checkNameLength
-.checkMonNameLength
- ld a, [wNamingScreenNameLength]
- cp $a ; max length of pokemon nicknames
-.checkNameLength
- jr c, .addLetter
- ret
-
-.dakutensAndHandakutens
- push hl
- call DakutensAndHandakutens
- pop hl
- ret nc
- dec hl
-.addLetter
- ld a, [wNamingScreenLetter]
- ld [hli], a
- ld [hl], "@"
- ld a, SFX_PRESS_AB
- call PlaySound
- ret
-.pressedB
- ld a, [wNamingScreenNameLength]
- and a
- ret z
- call CalcStringLength
- dec hl
- ld [hl], "@"
- ret
-.pressedRight
- ld a, [wCurrentMenuItem]
- cp $6
- ret z ; can't scroll right on bottom row
- ld a, [wTopMenuItemX]
- cp $11 ; max
- jp z, .wrapToFirstColumn
- inc a
- inc a
- jr .done
-.wrapToFirstColumn
- ld a, $1
- jr .done
-.pressedLeft
- ld a, [wCurrentMenuItem]
- cp $6
- ret z ; can't scroll right on bottom row
- ld a, [wTopMenuItemX]
- dec a
- jp z, .wrapToLastColumn
- dec a
- jr .done
-.wrapToLastColumn
- ld a, $11 ; max
- jr .done
-.pressedUp
- ld a, [wCurrentMenuItem]
- dec a
- ld [wCurrentMenuItem], a
- and a
- ret nz
- ld a, $6 ; wrap to bottom row
- ld [wCurrentMenuItem], a
- ld a, $1 ; force left column
- jr .done
-.pressedDown
- ld a, [wCurrentMenuItem]
- inc a
- ld [wCurrentMenuItem], a
- cp $7
- jr nz, .wrapToTopRow
- ld a, $1
- ld [wCurrentMenuItem], a
- jr .done
-.wrapToTopRow
- cp $6
- ret nz
- ld a, $1
-.done
- ld [wTopMenuItemX], a
- jp EraseMenuCursor
-
-LoadEDTile:
- ld de, ED_Tile
- ld hl, vFont + $700
- ld bc, (ED_TileEnd - ED_Tile) / $8
- ; to fix the graphical bug on poor emulators
- ;lb bc, BANK(ED_Tile), (ED_TileEnd - ED_Tile) / $8
- jp CopyVideoDataDouble
-
-ED_Tile:
- INCBIN "gfx/ED_tile.1bpp"
-ED_TileEnd:
-
-PrintAlphabet:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [wAlphabetCase]
- and a
- ld de, LowerCaseAlphabet
- jr nz, .lowercase
- ld de, UpperCaseAlphabet
-.lowercase
- coord hl, 2, 5
- lb bc, 5, 9 ; 5 rows, 9 columns
-.outerLoop
- push bc
-.innerLoop
- ld a, [de]
- ld [hli], a
- inc hl
- inc de
- dec c
- jr nz, .innerLoop
- ld bc, SCREEN_WIDTH + 2
- add hl, bc
- pop bc
- dec b
- jr nz, .outerLoop
- call PlaceString
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- jp Delay3
-
-LowerCaseAlphabet:
- db "abcdefghijklmnopqrstuvwxyz ×():;[]",$e1,$e2,"-?!♂♀/⠄,¥UPPER CASE@"
-
-UpperCaseAlphabet:
- db "ABCDEFGHIJKLMNOPQRSTUVWXYZ ×():;[]",$e1,$e2,"-?!♂♀/⠄,¥lower case@"
-
-PrintNicknameAndUnderscores:
- call CalcStringLength
- ld a, c
- ld [wNamingScreenNameLength], a
- coord hl, 10, 2
- lb bc, 1, 10
- call ClearScreenArea
- coord hl, 10, 2
- ld de, wcf4b
- call PlaceString
- coord hl, 10, 3
- ld a, [wNamingScreenType]
- cp NAME_MON_SCREEN
- jr nc, .pokemon1
- ld b, 7 ; player or rival max name length
- jr .playerOrRival1
-.pokemon1
- ld b, 10 ; pokemon max name length
-.playerOrRival1
- ld a, $76 ; underscore tile id
-.placeUnderscoreLoop
- ld [hli], a
- dec b
- jr nz, .placeUnderscoreLoop
- ld a, [wNamingScreenType]
- cp NAME_MON_SCREEN
- ld a, [wNamingScreenNameLength]
- jr nc, .pokemon2
- cp 7 ; player or rival max name length
- jr .playerOrRival2
-.pokemon2
- cp 10 ; pokemon max name length
-.playerOrRival2
- jr nz, .emptySpacesRemaining
- ; when all spaces are filled, force the cursor onto the ED tile
- call EraseMenuCursor
- ld a, $11 ; "ED" x coord
- ld [wTopMenuItemX], a
- ld a, $5 ; "ED" y coord
- ld [wCurrentMenuItem], a
- ld a, [wNamingScreenType]
- cp NAME_MON_SCREEN
- ld a, 9 ; keep the last underscore raised
- jr nc, .pokemon3
- ld a, 6 ; keep the last underscore raised
-.pokemon3
-.emptySpacesRemaining
- ld c, a
- ld b, $0
- coord hl, 10, 3
- add hl, bc
- ld [hl], $77 ; raised underscore tile id
- ret
-
-DakutensAndHandakutens:
- push de
- call CalcStringLength
- dec hl
- ld a, [hl]
- pop hl
- ld de, $2
- call IsInArray
- ret nc
- inc hl
- ld a, [hl]
- ld [wNamingScreenLetter], a
- ret
-
-Dakutens:
- db "かが", "きぎ", "くぐ", "けげ", "こご"
- db "さざ", "しじ", "すず", "せぜ", "そぞ"
- db "ただ", "ちぢ", "つづ", "てで", "とど"
- db "はば", "ひび", "ふぶ", "へべ", "ほぼ"
- db "カガ", "キギ", "クグ", "ケゲ", "コゴ"
- db "サザ", "シジ", "スズ", "セゼ", "ソゾ"
- db "タダ", "チヂ", "ツヅ", "テデ", "トド"
- db "ハバ", "ヒビ", "フブ", "へべ", "ホボ"
- db $ff
-
-Handakutens:
- db "はぱ", "ひぴ", "ふぷ", "へぺ", "ほぽ"
- db "ハパ", "ヒピ", "フプ", "へぺ", "ホポ"
- db $ff
-
-; calculates the length of the string at wcf4b and stores it in c
-CalcStringLength:
- ld hl, wcf4b
- ld c, $0
-.loop
- ld a, [hl]
- cp "@"
- ret z
- inc hl
- inc c
- jr .loop
-
-PrintNamingText:
- coord hl, 0, 1
- ld a, [wNamingScreenType]
- ld de, YourTextString
- and a
- jr z, .notNickname
- ld de, RivalsTextString
- dec a
- jr z, .notNickname
- ld a, [wcf91]
- ld [wMonPartySpriteSpecies], a
- push af
- callba WriteMonPartySpriteOAMBySpecies
- pop af
- ld [wd11e], a
- call GetMonName
- coord hl, 4, 1
- call PlaceString
- ld hl, $1
- add hl, bc
- ld [hl], $c9
- coord hl, 1, 3
- ld de, NicknameTextString
- jr .placeString
-.notNickname
- call PlaceString
- ld l, c
- ld h, b
- ld de, NameTextString
-.placeString
- jp PlaceString
-
-YourTextString:
- db "YOUR @"
-
-RivalsTextString:
- db "RIVAL's @"
-
-NameTextString:
- db "NAME?@"
-
-NicknameTextString:
- db "NICKNAME?@"
diff --git a/engine/menu/party_menu.asm b/engine/menu/party_menu.asm
deleted file mode 100755
index 8323d0eb..00000000
--- a/engine/menu/party_menu.asm
+++ /dev/null
@@ -1,325 +0,0 @@
-; [wPartyMenuTypeOrMessageID] = menu type / message ID
-; if less than $F0, it is a menu type
-; menu types:
-; 00: normal pokemon menu (e.g. Start menu)
-; 01: use healing item on pokemon menu
-; 02: in-battle switch pokemon menu
-; 03: learn TM/HM menu
-; 04: swap pokemon positions menu
-; 05: use evolution stone on pokemon menu
-; otherwise, it is a message ID
-; f0: poison healed
-; f1: burn healed
-; f2: freeze healed
-; f3: sleep healed
-; f4: paralysis healed
-; f5: HP healed
-; f6: health returned
-; f7: revitalized
-; f8: leveled up
-DrawPartyMenu_:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- call UpdateSprites
- callba LoadMonPartySpriteGfxWithLCDDisabled ; load pokemon icon graphics
-
-RedrawPartyMenu_:
- ld a, [wPartyMenuTypeOrMessageID]
- cp SWAP_MONS_PARTY_MENU
- jp z, .printMessage
- call ErasePartyMenuCursors
- callba InitPartyMenuBlkPacket
- coord hl, 3, 0
- ld de, wPartySpecies
- xor a
- ld c, a
- ld [hPartyMonIndex], a
- ld [wWhichPartyMenuHPBar], a
-.loop
- ld a, [de]
- cp $FF ; reached the terminator?
- jp z, .afterDrawingMonEntries
- push bc
- push de
- push hl
- ld a, c
- push hl
- ld hl, wPartyMonNicks
- call GetPartyMonName
- pop hl
- call PlaceString ; print the pokemon's name
- callba WriteMonPartySpriteOAMByPartyIndex ; place the appropriate pokemon icon
- ld a, [hPartyMonIndex]
- ld [wWhichPokemon], a
- inc a
- ld [hPartyMonIndex], a
- call LoadMonData
- pop hl
- push hl
- ld a, [wMenuItemToSwap]
- and a ; is the player swapping pokemon positions?
- jr z, .skipUnfilledRightArrow
-; if the player is swapping pokemon positions
- dec a
- ld b, a
- ld a, [wWhichPokemon]
- cp b ; is the player swapping the current pokemon in the list?
- jr nz, .skipUnfilledRightArrow
-; the player is swapping the current pokemon in the list
- dec hl
- dec hl
- dec hl
- ld a, "▷" ; unfilled right arrow menu cursor
- ld [hli], a ; place the cursor
- inc hl
- inc hl
-.skipUnfilledRightArrow
- ld a, [wPartyMenuTypeOrMessageID] ; menu type
- cp TMHM_PARTY_MENU
- jr z, .teachMoveMenu
- cp EVO_STONE_PARTY_MENU
- jr z, .evolutionStoneMenu
- push hl
- ld bc, 14 ; 14 columns to the right
- add hl, bc
- ld de, wLoadedMonStatus
- call PrintStatusCondition
- pop hl
- push hl
- ld bc, SCREEN_WIDTH + 1 ; down 1 row and right 1 column
- ld a, [hFlags_0xFFF6]
- set 0, a
- ld [hFlags_0xFFF6], a
- add hl, bc
- predef DrawHP2 ; draw HP bar and prints current / max HP
- ld a, [hFlags_0xFFF6]
- res 0, a
- ld [hFlags_0xFFF6], a
- call SetPartyMenuHPBarColor ; color the HP bar (on SGB)
- pop hl
- jr .printLevel
-.teachMoveMenu
- push hl
- predef CanLearnTM ; check if the pokemon can learn the move
- pop hl
- ld de, .ableToLearnMoveText
- ld a, c
- and a
- jr nz, .placeMoveLearnabilityString
- ld de, .notAbleToLearnMoveText
-.placeMoveLearnabilityString
- ld bc, 20 + 9 ; down 1 row and right 9 columns
- push hl
- add hl, bc
- call PlaceString
- pop hl
-.printLevel
- ld bc, 10 ; move 10 columns to the right
- add hl, bc
- call PrintLevel
- pop hl
- pop de
- inc de
- ld bc, 2 * 20
- add hl, bc
- pop bc
- inc c
- jp .loop
-.ableToLearnMoveText
- db "ABLE@"
-.notAbleToLearnMoveText
- db "NOT ABLE@"
-.evolutionStoneMenu
- push hl
- ld hl, EvosMovesPointerTable
- ld b, 0
- ld a, [wLoadedMonSpecies]
- dec a
- add a
- rl b
- ld c, a
- add hl, bc
- ld de, wEvosMoves
- ld a, BANK(EvosMovesPointerTable)
- ld bc, 2
- call FarCopyData
- ld hl, wEvosMoves
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, wEvosMoves
- ld a, BANK(EvosMovesPointerTable)
- ld bc, wEvosMoves.end - wEvosMoves
- call FarCopyData
- ld hl, wEvosMoves
- ld de, .notAbleToEvolveText
-; loop through the pokemon's evolution entries
-.checkEvolutionsLoop
- ld a, [hli]
- and a ; reached terminator?
- jr z, .placeEvolutionStoneString ; if so, place the "NOT ABLE" string
- inc hl
- inc hl
- cp EV_ITEM
- jr nz, .checkEvolutionsLoop
-; if it's a stone evolution entry
- dec hl
- dec hl
- ld b, [hl]
- ld a, [wEvoStoneItemID] ; the stone the player used
- inc hl
- inc hl
- inc hl
- cp b ; does the player's stone match this evolution entry's stone?
- jr nz, .checkEvolutionsLoop
-; if it does match
- ld de, .ableToEvolveText
-.placeEvolutionStoneString
- ld bc, 20 + 9 ; down 1 row and right 9 columns
- pop hl
- push hl
- add hl, bc
- call PlaceString
- pop hl
- jr .printLevel
-.ableToEvolveText
- db "ABLE@"
-.notAbleToEvolveText
- db "NOT ABLE@"
-.afterDrawingMonEntries
- ld b, SET_PAL_PARTY_MENU
- call RunPaletteCommand
-.printMessage
- ld hl, wd730
- ld a, [hl]
- push af
- push hl
- set 6, [hl] ; turn off letter printing delay
- ld a, [wPartyMenuTypeOrMessageID] ; message ID
- cp $F0
- jr nc, .printItemUseMessage
- add a
- ld hl, PartyMenuMessagePointers
- ld b, 0
- ld c, a
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- call PrintText
-.done
- pop hl
- pop af
- ld [hl], a
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- jp GBPalNormal
-.printItemUseMessage
- and $0F
- ld hl, PartyMenuItemUseMessagePointers
- add a
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- push hl
- ld a, [wUsedItemOnWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- pop hl
- call PrintText
- jr .done
-
-PartyMenuItemUseMessagePointers:
- dw AntidoteText
- dw BurnHealText
- dw IceHealText
- dw AwakeningText
- dw ParlyzHealText
- dw PotionText
- dw FullHealText
- dw ReviveText
- dw RareCandyText
-
-PartyMenuMessagePointers:
- dw PartyMenuNormalText
- dw PartyMenuItemUseText
- dw PartyMenuBattleText
- dw PartyMenuUseTMText
- dw PartyMenuSwapMonText
- dw PartyMenuItemUseText
-
-PartyMenuNormalText:
- TX_FAR _PartyMenuNormalText
- db "@"
-
-PartyMenuItemUseText:
- TX_FAR _PartyMenuItemUseText
- db "@"
-
-PartyMenuBattleText:
- TX_FAR _PartyMenuBattleText
- db "@"
-
-PartyMenuUseTMText:
- TX_FAR _PartyMenuUseTMText
- db "@"
-
-PartyMenuSwapMonText:
- TX_FAR _PartyMenuSwapMonText
- db "@"
-
-PotionText:
- TX_FAR _PotionText
- db "@"
-
-AntidoteText:
- TX_FAR _AntidoteText
- db "@"
-
-ParlyzHealText:
- TX_FAR _ParlyzHealText
- db "@"
-
-BurnHealText:
- TX_FAR _BurnHealText
- db "@"
-
-IceHealText:
- TX_FAR _IceHealText
- db "@"
-
-AwakeningText:
- TX_FAR _AwakeningText
- db "@"
-
-FullHealText:
- TX_FAR _FullHealText
- db "@"
-
-ReviveText:
- TX_FAR _ReviveText
- db "@"
-
-RareCandyText:
- TX_FAR _RareCandyText
- TX_SFX_ITEM_1 ; probably supposed to play SFX_LEVEL_UP but the wrong music bank is loaded
- TX_BLINK
- db "@"
-
-SetPartyMenuHPBarColor:
- ld hl, wPartyMenuHPBarColors
- ld a, [wWhichPartyMenuHPBar]
- ld c, a
- ld b, 0
- add hl, bc
- call GetHealthBarColor
- ld b, UPDATE_PARTY_MENU_BLK_PACKET
- call RunPaletteCommand
- ld hl, wWhichPartyMenuHPBar
- inc [hl]
- ret
diff --git a/engine/menu/players_pc.asm b/engine/menu/players_pc.asm
deleted file mode 100755
index bc2be4ef..00000000
--- a/engine/menu/players_pc.asm
+++ /dev/null
@@ -1,303 +0,0 @@
-PlayerPC:
- ld hl, wd730
- set 6, [hl]
- ld a, ITEM_NAME
- ld [wNameListType], a
- call SaveScreenTilesToBuffer1
- xor a
- ld [wBagSavedMenuItem], a
- ld [wParentMenuItem], a
- ld a, [wFlags_0xcd60]
- bit 3, a ; accessing player's PC through another PC?
- jr nz, PlayerPCMenu
-; accessing it directly
- ld a, SFX_TURN_ON_PC
- call PlaySound
- ld hl, TurnedOnPC2Text
- call PrintText
-
-PlayerPCMenu:
- ld a, [wParentMenuItem]
- ld [wCurrentMenuItem], a
- ld hl, wFlags_0xcd60
- set 5, [hl]
- call LoadScreenTilesFromBuffer2
- coord hl, 0, 0
- ld b, $8
- ld c, $e
- call TextBoxBorder
- call UpdateSprites
- coord hl, 2, 2
- ld de, PlayersPCMenuEntries
- call PlaceString
- ld hl, wTopMenuItemY
- ld a, 2
- ld [hli], a ; wTopMenuItemY
- dec a
- ld [hli], a ; wTopMenuItemX
- inc hl
- inc hl
- ld a, 3
- ld [hli], a ; wMaxMenuItem
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; wMenuWatchedKeys
- xor a
- ld [hl], a
- ld hl, wListScrollOffset
- ld [hli], a ; wListScrollOffset
- ld [hl], a ; wMenuWatchMovingOutOfBounds
- ld [wPlayerMonNumber], a
- ld hl, WhatDoYouWantText
- call PrintText
- call HandleMenuInput
- bit 1, a
- jp nz, ExitPlayerPC
- call PlaceUnfilledArrowMenuCursor
- ld a, [wCurrentMenuItem]
- ld [wParentMenuItem], a
- and a
- jp z, PlayerPCWithdraw
- dec a
- jp z, PlayerPCDeposit
- dec a
- jp z, PlayerPCToss
-
-ExitPlayerPC:
- ld a, [wFlags_0xcd60]
- bit 3, a ; accessing player's PC through another PC?
- jr nz, .next
-; accessing it directly
- ld a, SFX_TURN_OFF_PC
- call PlaySound
- call WaitForSoundToFinish
-.next
- ld hl, wFlags_0xcd60
- res 5, [hl]
- call LoadScreenTilesFromBuffer2
- xor a
- ld [wListScrollOffset], a
- ld [wBagSavedMenuItem], a
- ld hl, wd730
- res 6, [hl]
- xor a
- ld [wDoNotWaitForButtonPressAfterDisplayingText], a
- ret
-
-PlayerPCDeposit:
- xor a
- ld [wCurrentMenuItem], a
- ld [wListScrollOffset], a
- ld a, [wNumBagItems]
- and a
- jr nz, .loop
- ld hl, NothingToDepositText
- call PrintText
- jp PlayerPCMenu
-.loop
- ld hl, WhatToDepositText
- call PrintText
- ld hl, wNumBagItems
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wPrintItemPrices], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- call DisplayListMenuID
- jp c, PlayerPCMenu
- call IsKeyItem
- ld a, 1
- ld [wItemQuantity], a
- ld a, [wIsKeyItem]
- and a
- jr nz, .next
-; if it's not a key item, there can be more than one of the item
- ld hl, DepositHowManyText
- call PrintText
- call DisplayChooseQuantityMenu
- cp $ff
- jp z, .loop
-.next
- ld hl, wNumBoxItems
- call AddItemToInventory
- jr c, .roomAvailable
- ld hl, NoRoomToStoreText
- call PrintText
- jp .loop
-.roomAvailable
- ld hl, wNumBagItems
- call RemoveItemFromInventory
- call WaitForSoundToFinish
- ld a, SFX_WITHDRAW_DEPOSIT
- call PlaySound
- call WaitForSoundToFinish
- ld hl, ItemWasStoredText
- call PrintText
- jp .loop
-
-PlayerPCWithdraw:
- xor a
- ld [wCurrentMenuItem], a
- ld [wListScrollOffset], a
- ld a, [wNumBoxItems]
- and a
- jr nz, .loop
- ld hl, NothingStoredText
- call PrintText
- jp PlayerPCMenu
-.loop
- ld hl, WhatToWithdrawText
- call PrintText
- ld hl, wNumBoxItems
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wPrintItemPrices], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- call DisplayListMenuID
- jp c, PlayerPCMenu
- call IsKeyItem
- ld a, 1
- ld [wItemQuantity], a
- ld a, [wIsKeyItem]
- and a
- jr nz, .next
-; if it's not a key item, there can be more than one of the item
- ld hl, WithdrawHowManyText
- call PrintText
- call DisplayChooseQuantityMenu
- cp $ff
- jp z, .loop
-.next
- ld hl, wNumBagItems
- call AddItemToInventory
- jr c, .roomAvailable
- ld hl, CantCarryMoreText
- call PrintText
- jp .loop
-.roomAvailable
- ld hl, wNumBoxItems
- call RemoveItemFromInventory
- call WaitForSoundToFinish
- ld a, SFX_WITHDRAW_DEPOSIT
- call PlaySound
- call WaitForSoundToFinish
- ld hl, WithdrewItemText
- call PrintText
- jp .loop
-
-PlayerPCToss:
- xor a
- ld [wCurrentMenuItem], a
- ld [wListScrollOffset], a
- ld a, [wNumBoxItems]
- and a
- jr nz, .loop
- ld hl, NothingStoredText
- call PrintText
- jp PlayerPCMenu
-.loop
- ld hl, WhatToTossText
- call PrintText
- ld hl, wNumBoxItems
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wPrintItemPrices], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- push hl
- call DisplayListMenuID
- pop hl
- jp c, PlayerPCMenu
- push hl
- call IsKeyItem
- pop hl
- ld a, 1
- ld [wItemQuantity], a
- ld a, [wIsKeyItem]
- and a
- jr nz, .next
- ld a, [wcf91]
- call IsItemHM
- jr c, .next
-; if it's not a key item, there can be more than one of the item
- push hl
- ld hl, TossHowManyText
- call PrintText
- call DisplayChooseQuantityMenu
- pop hl
- cp $ff
- jp z, .loop
-.next
- call TossItem ; disallows tossing key items
- jp .loop
-
-PlayersPCMenuEntries:
- db "WITHDRAW ITEM"
- next "DEPOSIT ITEM"
- next "TOSS ITEM"
- next "LOG OFF@"
-
-TurnedOnPC2Text:
- TX_FAR _TurnedOnPC2Text
- db "@"
-
-WhatDoYouWantText:
- TX_FAR _WhatDoYouWantText
- db "@"
-
-WhatToDepositText:
- TX_FAR _WhatToDepositText
- db "@"
-
-DepositHowManyText:
- TX_FAR _DepositHowManyText
- db "@"
-
-ItemWasStoredText:
- TX_FAR _ItemWasStoredText
- db "@"
-
-NothingToDepositText:
- TX_FAR _NothingToDepositText
- db "@"
-
-NoRoomToStoreText:
- TX_FAR _NoRoomToStoreText
- db "@"
-
-WhatToWithdrawText:
- TX_FAR _WhatToWithdrawText
- db "@"
-
-WithdrawHowManyText:
- TX_FAR _WithdrawHowManyText
- db "@"
-
-WithdrewItemText:
- TX_FAR _WithdrewItemText
- db "@"
-
-NothingStoredText:
- TX_FAR _NothingStoredText
- db "@"
-
-CantCarryMoreText:
- TX_FAR _CantCarryMoreText
- db "@"
-
-WhatToTossText:
- TX_FAR _WhatToTossText
- db "@"
-
-TossHowManyText:
- TX_FAR _TossHowManyText
- db "@"
diff --git a/engine/menu/pokedex.asm b/engine/menu/pokedex.asm
deleted file mode 100755
index 8e1fd480..00000000
--- a/engine/menu/pokedex.asm
+++ /dev/null
@@ -1,665 +0,0 @@
-ShowPokedexMenu:
- call GBPalWhiteOut
- call ClearScreen
- call UpdateSprites
- ld a, [wListScrollOffset]
- push af
- xor a
- ld [wCurrentMenuItem], a
- ld [wListScrollOffset], a
- ld [wLastMenuItem], a
- inc a
- ld [wd11e], a
- ld [hJoy7], a
-.setUpGraphics
- ld b, SET_PAL_GENERIC
- call RunPaletteCommand
- callab LoadPokedexTilePatterns
-.doPokemonListMenu
- ld hl, wTopMenuItemY
- ld a, 3
- ld [hli], a ; top menu item Y
- xor a
- ld [hli], a ; top menu item X
- inc a
- ld [wMenuWatchMovingOutOfBounds], a
- inc hl
- inc hl
- ld a, 6
- ld [hli], a ; max menu item ID
- ld [hl], D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON
- call HandlePokedexListMenu
- jr c, .goToSideMenu ; if the player chose a pokemon from the list
-.exitPokedex
- xor a
- ld [wMenuWatchMovingOutOfBounds], a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [hJoy7], a
- ld [wWastedByteCD3A], a
- ld [wOverrideSimulatedJoypadStatesMask], a
- pop af
- ld [wListScrollOffset], a
- call GBPalWhiteOutWithDelay3
- call RunDefaultPaletteCommand
- jp ReloadMapData
-.goToSideMenu
- call HandlePokedexSideMenu
- dec b
- jr z, .exitPokedex ; if the player chose Quit
- dec b
- jr z, .doPokemonListMenu ; if pokemon not seen or player pressed B button
- jp .setUpGraphics ; if pokemon data or area was shown
-
-; handles the menu on the lower right in the pokedex screen
-; OUTPUT:
-; b = reason for exiting menu
-; 00: showed pokemon data or area
-; 01: the player chose Quit
-; 02: the pokemon has not been seen yet or the player pressed the B button
-HandlePokedexSideMenu:
- call PlaceUnfilledArrowMenuCursor
- ld a, [wCurrentMenuItem]
- push af
- ld b, a
- ld a, [wLastMenuItem]
- push af
- ld a, [wListScrollOffset]
- push af
- add b
- inc a
- ld [wd11e], a
- ld a, [wd11e]
- push af
- ld a, [wDexMaxSeenMon]
- push af ; this doesn't need to be preserved
- ld hl, wPokedexSeen
- call IsPokemonBitSet
- ld b, 2
- jr z, .exitSideMenu
- call PokedexToIndex
- ld hl, wTopMenuItemY
- ld a, 10
- ld [hli], a ; top menu item Y
- ld a, 15
- ld [hli], a ; top menu item X
- xor a
- ld [hli], a ; current menu item ID
- inc hl
- ld a, 3
- ld [hli], a ; max menu item ID
- ;ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; menu watched keys (A button and B button)
- xor a
- ld [hli], a ; old menu item ID
- ld [wMenuWatchMovingOutOfBounds], a
-.handleMenuInput
- call HandleMenuInput
- bit 1, a ; was the B button pressed?
- ld b, 2
- jr nz, .buttonBPressed
- ld a, [wCurrentMenuItem]
- and a
- jr z, .choseData
- dec a
- jr z, .choseCry
- dec a
- jr z, .choseArea
-.choseQuit
- ld b, 1
-.exitSideMenu
- pop af
- ld [wDexMaxSeenMon], a
- pop af
- ld [wd11e], a
- pop af
- ld [wListScrollOffset], a
- pop af
- ld [wLastMenuItem], a
- pop af
- ld [wCurrentMenuItem], a
- push bc
- coord hl, 0, 3
- ld de, 20
- lb bc, " ", 13
- call DrawTileLine ; cover up the menu cursor in the pokemon list
- pop bc
- ret
-
-.buttonBPressed
- push bc
- coord hl, 15, 10
- ld de, 20
- lb bc, " ", 7
- call DrawTileLine ; cover up the menu cursor in the side menu
- pop bc
- jr .exitSideMenu
-
-.choseData
- call ShowPokedexDataInternal
- ld b, 0
- jr .exitSideMenu
-
-; play pokemon cry
-.choseCry
- ld a, [wd11e]
- call GetCryData
- call PlaySound
- jr .handleMenuInput
-
-.choseArea
- predef LoadTownMap_Nest ; display pokemon areas
- ld b, 0
- jr .exitSideMenu
-
-; handles the list of pokemon on the left of the pokedex screen
-; sets carry flag if player presses A, unsets carry flag if player presses B
-HandlePokedexListMenu:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
-; draw the horizontal line separating the seen and owned amounts from the menu
- coord hl, 15, 8
- ld a, "─"
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hli], a
- coord hl, 14, 0
- ld [hl], $71 ; vertical line tile
- coord hl, 14, 1
- call DrawPokedexVerticalLine
- coord hl, 14, 9
- call DrawPokedexVerticalLine
- ld hl, wPokedexSeen
- ld b, wPokedexSeenEnd - wPokedexSeen
- call CountSetBits
- ld de, wNumSetBits
- coord hl, 16, 3
- lb bc, 1, 3
- call PrintNumber ; print number of seen pokemon
- ld hl, wPokedexOwned
- ld b, wPokedexOwnedEnd - wPokedexOwned
- call CountSetBits
- ld de, wNumSetBits
- coord hl, 16, 6
- lb bc, 1, 3
- call PrintNumber ; print number of owned pokemon
- coord hl, 16, 2
- ld de, PokedexSeenText
- call PlaceString
- coord hl, 16, 5
- ld de, PokedexOwnText
- call PlaceString
- coord hl, 1, 1
- ld de, PokedexContentsText
- call PlaceString
- coord hl, 16, 10
- ld de, PokedexMenuItemsText
- call PlaceString
-; find the highest pokedex number among the pokemon the player has seen
- ld hl, wPokedexSeenEnd - 1
- ld b, (wPokedexSeenEnd - wPokedexSeen) * 8 + 1
-.maxSeenPokemonLoop
- ld a, [hld]
- ld c, 8
-.maxSeenPokemonInnerLoop
- dec b
- sla a
- jr c, .storeMaxSeenPokemon
- dec c
- jr nz, .maxSeenPokemonInnerLoop
- jr .maxSeenPokemonLoop
-
-.storeMaxSeenPokemon
- ld a, b
- ld [wDexMaxSeenMon], a
-.loop
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 4, 2
- lb bc, 14, 10
- call ClearScreenArea
- coord hl, 1, 3
- ld a, [wListScrollOffset]
- ld [wd11e], a
- ld d, 7
- ld a, [wDexMaxSeenMon]
- cp 7
- jr nc, .printPokemonLoop
- ld d, a
- dec a
- ld [wMaxMenuItem], a
-; loop to print pokemon pokedex numbers and names
-; if the player has owned the pokemon, it puts a pokeball beside the name
-.printPokemonLoop
- ld a, [wd11e]
- inc a
- ld [wd11e], a
- push af
- push de
- push hl
- ld de, -SCREEN_WIDTH
- add hl, de
- ld de, wd11e
- lb bc, LEADING_ZEROES | 1, 3
- call PrintNumber ; print the pokedex number
- ld de, SCREEN_WIDTH
- add hl, de
- dec hl
- push hl
- ld hl, wPokedexOwned
- call IsPokemonBitSet
- pop hl
- ld a, " "
- jr z, .writeTile
- ld a, $72 ; pokeball tile
-.writeTile
- ld [hl], a ; put a pokeball next to pokemon that the player has owned
- push hl
- ld hl, wPokedexSeen
- call IsPokemonBitSet
- jr nz, .getPokemonName ; if the player has seen the pokemon
- ld de, .dashedLine ; print a dashed line in place of the name if the player hasn't seen the pokemon
- jr .skipGettingName
-.dashedLine ; for unseen pokemon in the list
- db "----------@"
-.getPokemonName
- call PokedexToIndex
- call GetMonName
-.skipGettingName
- pop hl
- inc hl
- call PlaceString
- pop hl
- ld bc, 2 * SCREEN_WIDTH
- add hl, bc
- pop de
- pop af
- ld [wd11e], a
- dec d
- jr nz, .printPokemonLoop
- ld a, 01
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- call GBPalNormal
- call HandleMenuInput
- bit 1, a ; was the B button pressed?
- jp nz, .buttonBPressed
-.checkIfUpPressed
- bit 6, a ; was Up pressed?
- jr z, .checkIfDownPressed
-.upPressed ; scroll up one row
- ld a, [wListScrollOffset]
- and a
- jp z, .loop
- dec a
- ld [wListScrollOffset], a
- jp .loop
-.checkIfDownPressed
- bit 7, a ; was Down pressed?
- jr z, .checkIfRightPressed
-.downPressed ; scroll down one row
- ld a, [wDexMaxSeenMon]
- cp 7
- jp c, .loop ; can't if the list is shorter than 7
- sub 7
- ld b, a
- ld a, [wListScrollOffset]
- cp b
- jp z, .loop
- inc a
- ld [wListScrollOffset], a
- jp .loop
-.checkIfRightPressed
- bit 4, a ; was Right pressed?
- jr z, .checkIfLeftPressed
-.rightPressed ; scroll down 7 rows
- ld a, [wDexMaxSeenMon]
- cp 7
- jp c, .loop ; can't if the list is shorter than 7
- sub 6
- ld b, a
- ld a, [wListScrollOffset]
- add 7
- ld [wListScrollOffset], a
- cp b
- jp c, .loop
- dec b
- ld a, b
- ld [wListScrollOffset], a
- jp .loop
-.checkIfLeftPressed ; scroll up 7 rows
- bit 5, a ; was Left pressed?
- jr z, .buttonAPressed
-.leftPressed
- ld a, [wListScrollOffset]
- sub 7
- ld [wListScrollOffset], a
- jp nc, .loop
- xor a
- ld [wListScrollOffset], a
- jp .loop
-.buttonAPressed
- scf
- ret
-.buttonBPressed
- and a
- ret
-
-DrawPokedexVerticalLine:
- ld c, 9 ; height of line
- ld de, SCREEN_WIDTH
- ld a, $71 ; vertical line tile
-.loop
- ld [hl], a
- add hl, de
- xor 1 ; toggle between vertical line tile and box tile
- dec c
- jr nz, .loop
- ret
-
-PokedexSeenText:
- db "SEEN@"
-
-PokedexOwnText:
- db "OWN@"
-
-PokedexContentsText:
- db "CONTENTS@"
-
-PokedexMenuItemsText:
- db "DATA"
- next "CRY"
- next "AREA"
- next "QUIT@"
-
-; tests if a pokemon's bit is set in the seen or owned pokemon bit fields
-; INPUT:
-; [wd11e] = pokedex number
-; hl = address of bit field
-IsPokemonBitSet:
- ld a, [wd11e]
- dec a
- ld c, a
- ld b, FLAG_TEST
- predef FlagActionPredef
- ld a, c
- and a
- ret
-
-; function to display pokedex data from outside the pokedex
-ShowPokedexData:
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call UpdateSprites
- callab LoadPokedexTilePatterns ; load pokedex tiles
-
-; function to display pokedex data from inside the pokedex
-ShowPokedexDataInternal:
- ld hl, wd72c
- set 1, [hl]
- ld a, $33 ; 3/7 volume
- ld [rNR50], a
- call GBPalWhiteOut ; zero all palettes
- call ClearScreen
- ld a, [wd11e] ; pokemon ID
- ld [wcf91], a
- push af
- ld b, SET_PAL_POKEDEX
- call RunPaletteCommand
- pop af
- ld [wd11e], a
- ld a, [hTilesetType]
- push af
- xor a
- ld [hTilesetType], a
-
- coord hl, 0, 0
- ld de, 1
- lb bc, $64, SCREEN_WIDTH
- call DrawTileLine ; draw top border
-
- coord hl, 0, 17
- ld b, $6f
- call DrawTileLine ; draw bottom border
-
- coord hl, 0, 1
- ld de, 20
- lb bc, $66, $10
- call DrawTileLine ; draw left border
-
- coord hl, 19, 1
- ld b, $67
- call DrawTileLine ; draw right border
-
- ld a, $63 ; upper left corner tile
- Coorda 0, 0
- ld a, $65 ; upper right corner tile
- Coorda 19, 0
- ld a, $6c ; lower left corner tile
- Coorda 0, 17
- ld a, $6e ; lower right corner tile
- Coorda 19, 17
-
- coord hl, 0, 9
- ld de, PokedexDataDividerLine
- call PlaceString ; draw horizontal divider line
-
- coord hl, 9, 6
- ld de, HeightWeightText
- call PlaceString
-
- call GetMonName
- coord hl, 9, 2
- call PlaceString
-
- ld hl, PokedexEntryPointers
- ld a, [wd11e]
- dec a
- ld e, a
- ld d, 0
- add hl, de
- add hl, de
- ld a, [hli]
- ld e, a
- ld d, [hl] ; de = address of pokedex entry
-
- coord hl, 9, 4
- call PlaceString ; print species name
-
- ld h, b
- ld l, c
- push de
- ld a, [wd11e]
- push af
- call IndexToPokedex
-
- coord hl, 2, 8
- ld a, "№"
- ld [hli], a
- ld a, "⠄"
- ld [hli], a
- ld de, wd11e
- lb bc, LEADING_ZEROES | 1, 3
- call PrintNumber ; print pokedex number
-
- ld hl, wPokedexOwned
- call IsPokemonBitSet
- pop af
- ld [wd11e], a
- ld a, [wcf91]
- ld [wd0b5], a
- pop de
-
- push af
- push bc
- push de
- push hl
-
- call Delay3
- call GBPalNormal
- call GetMonHeader ; load pokemon picture location
- coord hl, 1, 1
- call LoadFlippedFrontSpriteByMonIndex ; draw pokemon picture
- ld a, [wcf91]
- call PlayCry ; play pokemon cry
-
- pop hl
- pop de
- pop bc
- pop af
-
- ld a, c
- and a
- jp z, .waitForButtonPress ; if the pokemon has not been owned, don't print the height, weight, or description
- inc de ; de = address of feet (height)
- ld a, [de] ; reads feet, but a is overwritten without being used
- coord hl, 12, 6
- lb bc, 1, 2
- call PrintNumber ; print feet (height)
- ld a, $60 ; feet symbol tile (one tick)
- ld [hl], a
- inc de
- inc de ; de = address of inches (height)
- coord hl, 15, 6
- lb bc, LEADING_ZEROES | 1, 2
- call PrintNumber ; print inches (height)
- ld a, $61 ; inches symbol tile (two ticks)
- ld [hl], a
-; now print the weight (note that weight is stored in tenths of pounds internally)
- inc de
- inc de
- inc de ; de = address of upper byte of weight
- push de
-; put weight in big-endian order at hDexWeight
- ld hl, hDexWeight
- ld a, [hl] ; save existing value of [hDexWeight]
- push af
- ld a, [de] ; a = upper byte of weight
- ld [hli], a ; store upper byte of weight in [hDexWeight]
- ld a, [hl] ; save existing value of [hDexWeight + 1]
- push af
- dec de
- ld a, [de] ; a = lower byte of weight
- ld [hl], a ; store lower byte of weight in [hDexWeight + 1]
- ld de, hDexWeight
- coord hl, 11, 8
- lb bc, 2, 5 ; 2 bytes, 5 digits
- call PrintNumber ; print weight
- coord hl, 14, 8
- ld a, [hDexWeight + 1]
- sub 10
- ld a, [hDexWeight]
- sbc 0
- jr nc, .next
- ld [hl], "0" ; if the weight is less than 10, put a 0 before the decimal point
-.next
- inc hl
- ld a, [hli]
- ld [hld], a ; make space for the decimal point by moving the last digit forward one tile
- ld [hl], "⠄" ; decimal point tile
- pop af
- ld [hDexWeight + 1], a ; restore original value of [hDexWeight + 1]
- pop af
- ld [hDexWeight], a ; restore original value of [hDexWeight]
- pop hl
- inc hl ; hl = address of pokedex description text
- coord bc, 1, 11
- ld a, 2
- ld [$fff4], a
- call TextCommandProcessor ; print pokedex description text
- xor a
- ld [$fff4], a
-.waitForButtonPress
- call JoypadLowSensitivity
- ld a, [hJoy5]
- and A_BUTTON | B_BUTTON
- jr z, .waitForButtonPress
- pop af
- ld [hTilesetType], a
- call GBPalWhiteOut
- call ClearScreen
- call RunDefaultPaletteCommand
- call LoadTextBoxTilePatterns
- call GBPalNormal
- ld hl, wd72c
- res 1, [hl]
- ld a, $77 ; max volume
- ld [rNR50], a
- ret
-
-HeightWeightText:
- db "HT ?",$60,"??",$61
- next "WT ???lb@"
-
-; XXX does anything point to this?
-PokeText:
- db "#@"
-
-; horizontal line that divides the pokedex text description from the rest of the data
-PokedexDataDividerLine:
- db $68,$69,$6B,$69,$6B
- db $69,$6B,$69,$6B,$6B
- db $6B,$6B,$69,$6B,$69
- db $6B,$69,$6B,$69,$6A
- db "@"
-
-; draws a line of tiles
-; INPUT:
-; b = tile ID
-; c = number of tile ID's to write
-; de = amount to destination address after each tile (1 for horizontal, 20 for vertical)
-; hl = destination address
-DrawTileLine:
- push bc
- push de
-.loop
- ld [hl], b
- add hl, de
- dec c
- jr nz, .loop
- pop de
- pop bc
- ret
-
-INCLUDE "data/pokedex_entries.asm"
-
-PokedexToIndex:
- ; converts the Pokédex number at wd11e to an index
- push bc
- push hl
- ld a, [wd11e]
- ld b, a
- ld c, 0
- ld hl, PokedexOrder
-
-.loop ; go through the list until we find an entry with a matching dex number
- inc c
- ld a, [hli]
- cp b
- jr nz, .loop
-
- ld a, c
- ld [wd11e], a
- pop hl
- pop bc
- ret
-
-IndexToPokedex:
- ; converts the index number at wd11e to a Pokédex number
- push bc
- push hl
- ld a, [wd11e]
- dec a
- ld hl, PokedexOrder
- ld b, 0
- ld c, a
- add hl, bc
- ld a, [hl]
- ld [wd11e], a
- pop hl
- pop bc
- ret
-
-INCLUDE "data/pokedex_order.asm"
diff --git a/engine/menu/prize_menu.asm b/engine/menu/prize_menu.asm
deleted file mode 100755
index bcd0d4ea..00000000
--- a/engine/menu/prize_menu.asm
+++ /dev/null
@@ -1,306 +0,0 @@
-CeladonPrizeMenu:
- ld b, COIN_CASE
- call IsItemInBag
- jr nz, .havingCoinCase
- ld hl, RequireCoinCaseTextPtr
- jp PrintText
-.havingCoinCase
- ld hl, wd730
- set 6, [hl] ; disable letter-printing delay
- ld hl, ExchangeCoinsForPrizesTextPtr
- call PrintText
-; the following are the menu settings
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, $03
- ld [wMaxMenuItem], a
- ld a, $04
- ld [wTopMenuItemY], a
- ld a, $01
- ld [wTopMenuItemX], a
- call PrintPrizePrice
- coord hl, 0, 2
- ld b, 8
- ld c, 16
- call TextBoxBorder
- call GetPrizeMenuId
- call UpdateSprites
- ld hl, WhichPrizeTextPtr
- call PrintText
- call HandleMenuInput ; menu choice handler
- bit 1, a ; keypress = B (Cancel)
- jr nz, .noChoice
- ld a, [wCurrentMenuItem]
- cp 3 ; "NO,THANKS" choice
- jr z, .noChoice
- call HandlePrizeChoice
-.noChoice
- ld hl, wd730
- res 6, [hl]
- ret
-
-RequireCoinCaseTextPtr:
- TX_FAR _RequireCoinCaseText
- TX_WAIT
- db "@"
-
-ExchangeCoinsForPrizesTextPtr:
- TX_FAR _ExchangeCoinsForPrizesText
- db "@"
-
-WhichPrizeTextPtr:
- TX_FAR _WhichPrizeText
- db "@"
-
-GetPrizeMenuId:
-; determine which one among the three
-; prize-texts has been selected
-; using the text ID (stored in [hSpriteIndexOrTextID])
-; load the three prizes at wd13d-wd13f
-; load the three prices at wd141-wd146
-; display the three prizes' names
-; (distinguishing between Pokemon names
-; and Items (specifically TMs) names)
- ld a, [hSpriteIndexOrTextID]
- sub 3 ; prize-texts' id are 3, 4 and 5
- ld [wWhichPrizeWindow], a ; prize-texts' id (relative, i.e. 0, 1 or 2)
- add a
- add a
- ld d, 0
- ld e, a
- ld hl, PrizeDifferentMenuPtrs
- add hl, de
- ld a, [hli]
- ld d, [hl]
- ld e, a
- inc hl
- push hl
- ld hl, wPrize1
- call CopyString
- pop hl
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, wPrize1Price
- ld bc, 6
- call CopyData
- ld a, [wWhichPrizeWindow]
- cp 2 ;is TM_menu?
- jr nz, .putMonName
- ld a, [wPrize1]
- ld [wd11e], a
- call GetItemName
- coord hl, 2, 4
- call PlaceString
- ld a, [wPrize2]
- ld [wd11e], a
- call GetItemName
- coord hl, 2, 6
- call PlaceString
- ld a, [wPrize3]
- ld [wd11e], a
- call GetItemName
- coord hl, 2, 8
- call PlaceString
- jr .putNoThanksText
-.putMonName
- ld a, [wPrize1]
- ld [wd11e], a
- call GetMonName
- coord hl, 2, 4
- call PlaceString
- ld a, [wPrize2]
- ld [wd11e], a
- call GetMonName
- coord hl, 2, 6
- call PlaceString
- ld a, [wPrize3]
- ld [wd11e], a
- call GetMonName
- coord hl, 2, 8
- call PlaceString
-.putNoThanksText
- coord hl, 2, 10
- ld de, NoThanksText
- call PlaceString
-; put prices on the right side of the textbox
- ld de, wPrize1Price
- coord hl, 13, 5
-; reg. c:
-; [low nybble] number of bytes
-; [bit 765 = %100] space-padding (not zero-padding)
- ld c, (1 << 7 | 2)
-; Function $15CD displays BCD value (same routine
-; used by text-command $02)
- call PrintBCDNumber
- ld de, wPrize2Price
- coord hl, 13, 7
- ld c, (1 << 7 | 2)
- call PrintBCDNumber
- ld de, wPrize3Price
- coord hl, 13, 9
- ld c, (1 << 7 | 2)
- jp PrintBCDNumber
-
-INCLUDE "data/prizes.asm"
-
-PrintPrizePrice:
- coord hl, 11, 0
- ld b, 1
- ld c, 7
- call TextBoxBorder
- call UpdateSprites
- coord hl, 12, 0
- ld de, .CoinString
- call PlaceString
- coord hl, 13, 1
- ld de, .SixSpacesString
- call PlaceString
- coord hl, 13, 1
- ld de, wPlayerCoins
- ld c, %10000010
- call PrintBCDNumber
- ret
-
-.CoinString:
- db "COIN@"
-
-.SixSpacesString:
- db " @"
-
-LoadCoinsToSubtract:
- ld a, [wWhichPrize]
- add a
- ld d, 0
- ld e, a
- ld hl, wPrize1Price
- add hl, de ; get selected prize's price
- xor a
- ld [hUnusedCoinsByte], a
- ld a, [hli]
- ld [hCoins], a
- ld a, [hl]
- ld [hCoins + 1], a
- ret
-
-HandlePrizeChoice:
- ld a, [wCurrentMenuItem]
- ld [wWhichPrize], a
- ld d, 0
- ld e, a
- ld hl, wPrize1
- add hl, de
- ld a, [hl]
- ld [wd11e], a
- ld a, [wWhichPrizeWindow]
- cp 2 ; is prize a TM?
- jr nz, .getMonName
- call GetItemName
- jr .givePrize
-.getMonName
- call GetMonName
-.givePrize
- ld hl, SoYouWantPrizeTextPtr
- call PrintText
- call YesNoChoice
- ld a, [wCurrentMenuItem] ; yes/no answer (Y=0, N=1)
- and a
- jr nz, .printOhFineThen
- call LoadCoinsToSubtract
- call HasEnoughCoins
- jr c, .notEnoughCoins
- ld a, [wWhichPrizeWindow]
- cp $02
- jr nz, .giveMon
- ld a, [wd11e]
- ld b, a
- ld a, 1
- ld c, a
- call GiveItem
- jr nc, .bagFull
- jr .subtractCoins
-.giveMon
- ld a, [wd11e]
- ld [wcf91], a
- push af
- call GetPrizeMonLevel
- ld c, a
- pop af
- ld b, a
- call GivePokemon
-
-; If either the party or box was full, wait after displaying message.
- push af
- ld a, [wAddedToParty]
- and a
- call z, WaitForTextScrollButtonPress
- pop af
-
-; If the mon couldn't be given to the player (because both the party and box
-; were full), return without subtracting coins.
- ret nc
-
-.subtractCoins
- call LoadCoinsToSubtract
- ld hl, hCoins + 1
- ld de, wPlayerCoins + 1
- ld c, $02 ; how many bytes
- predef SubBCDPredef
- jp PrintPrizePrice
-.bagFull
- ld hl, PrizeRoomBagIsFullTextPtr
- jp PrintText
-.notEnoughCoins
- ld hl, SorryNeedMoreCoinsText
- jp PrintText
-.printOhFineThen
- ld hl, OhFineThenTextPtr
- jp PrintText
-
-UnknownPrizeData:
-; XXX what's this?
- db $00,$01,$00,$01,$00,$01,$00,$00,$01
-
-HereYouGoTextPtr:
- TX_FAR _HereYouGoText
- TX_WAIT
- db "@"
-
-SoYouWantPrizeTextPtr:
- TX_FAR _SoYouWantPrizeText
- db "@"
-
-SorryNeedMoreCoinsText:
- TX_FAR _SorryNeedMoreCoinsText
- TX_WAIT
- db "@"
-
-PrizeRoomBagIsFullTextPtr:
- TX_FAR _OopsYouDontHaveEnoughRoomText
- TX_WAIT
- db "@"
-
-OhFineThenTextPtr:
- TX_FAR _OhFineThenText
- TX_WAIT
- db "@"
-
-GetPrizeMonLevel:
- ld a, [wcf91]
- ld b, a
- ld hl, PrizeMonLevelDictionary
-.loop
- ld a, [hli]
- cp b
- jr z, .matchFound
- inc hl
- jr .loop
-.matchFound
- ld a, [hl]
- ld [wCurEnemyLVL], a
- ret
-
-INCLUDE "data/prize_mon_levels.asm"
diff --git a/engine/menu/start_sub_menus.asm b/engine/menu/start_sub_menus.asm
deleted file mode 100755
index 947837e3..00000000
--- a/engine/menu/start_sub_menus.asm
+++ /dev/null
@@ -1,854 +0,0 @@
-StartMenu_Pokedex:
- predef ShowPokedexMenu
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- call Delay3
- call LoadGBPal
- call UpdateSprites
- jp RedisplayStartMenu
-
-StartMenu_Pokemon:
- ld a, [wPartyCount]
- and a
- jp z, RedisplayStartMenu
- xor a
- ld [wMenuItemToSwap], a
- ld [wPartyMenuTypeOrMessageID], a
- ld [wUpdateSpritesEnabled], a
- call DisplayPartyMenu
- jr .checkIfPokemonChosen
-.loop
- xor a
- ld [wMenuItemToSwap], a
- ld [wPartyMenuTypeOrMessageID], a
- call GoBackToPartyMenu
-.checkIfPokemonChosen
- jr nc, .chosePokemon
-.exitMenu
- call GBPalWhiteOutWithDelay3
- call RestoreScreenTilesAndReloadTilePatterns
- call LoadGBPal
- jp RedisplayStartMenu
-.chosePokemon
- call SaveScreenTilesToBuffer1
- ld a, FIELD_MOVE_MON_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; display pokemon menu options
- ld hl, wFieldMoves
- lb bc, 2, 12 ; max menu item ID, top menu item Y
- ld e, 5
-.adjustMenuVariablesLoop
- dec e
- jr z, .storeMenuVariables
- ld a, [hli]
- and a ; end of field moves?
- jr z, .storeMenuVariables
- inc b
- dec c
- dec c
- jr .adjustMenuVariablesLoop
-.storeMenuVariables
- ld hl, wTopMenuItemY
- ld a, c
- ld [hli], a ; top menu item Y
- ld a, [hFieldMoveMonMenuTopMenuItemX]
- ld [hli], a ; top menu item X
- xor a
- ld [hli], a ; current menu item ID
- inc hl
- ld a, b
- ld [hli], a ; max menu item ID
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; menu watched keys
- xor a
- ld [hl], a
- call HandleMenuInput
- push af
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- pop af
- bit 1, a ; was the B button pressed?
- jp nz, .loop
-; if the B button wasn't pressed
- ld a, [wMaxMenuItem]
- ld b, a
- ld a, [wCurrentMenuItem] ; menu selection
- cp b
- jp z, .exitMenu ; if the player chose Cancel
- dec b
- cp b
- jr z, .choseSwitch
- dec b
- cp b
- jp z, .choseStats
- ld c, a
- ld b, 0
- ld hl, wFieldMoves
- add hl, bc
- jp .choseOutOfBattleMove
-.choseSwitch
- ld a, [wPartyCount]
- cp 2 ; is there more than one pokemon in the party?
- jp c, StartMenu_Pokemon ; if not, no switching
- call SwitchPartyMon_InitVarOrSwapData ; init [wMenuItemToSwap]
- ld a, SWAP_MONS_PARTY_MENU
- ld [wPartyMenuTypeOrMessageID], a
- call GoBackToPartyMenu
- jp .checkIfPokemonChosen
-.choseStats
- call ClearSprites
- xor a ; PLAYER_PARTY_DATA
- ld [wMonDataLocation], a
- predef StatusScreen
- predef StatusScreen2
- call ReloadMapData
- jp StartMenu_Pokemon
-.choseOutOfBattleMove
- push hl
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- pop hl
- ld a, [hl]
- dec a
- add a
- ld b, 0
- ld c, a
- ld hl, .outOfBattleMovePointers
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [wObtainedBadges] ; badges obtained
- jp hl
-.outOfBattleMovePointers
- dw .cut
- dw .fly
- dw .surf
- dw .surf
- dw .strength
- dw .flash
- dw .dig
- dw .teleport
- dw .softboiled
-.fly
- bit 2, a ; does the player have the Thunder Badge?
- jp z, .newBadgeRequired
- call CheckIfInOutsideMap
- jr z, .canFly
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- ld hl, .cannotFlyHereText
- call PrintText
- jp .loop
-.canFly
- call ChooseFlyDestination
- ld a, [wd732]
- bit 3, a ; did the player decide to fly?
- jp nz, .goBackToMap
- call LoadFontTilePatterns
- ld hl, wd72e
- set 1, [hl]
- jp StartMenu_Pokemon
-.cut
- bit 1, a ; does the player have the Cascade Badge?
- jp z, .newBadgeRequired
- predef UsedCut
- ld a, [wActionResultOrTookBattleTurn]
- and a
- jp z, .loop
- jp CloseTextDisplay
-.surf
- bit 4, a ; does the player have the Soul Badge?
- jp z, .newBadgeRequired
- callba IsSurfingAllowed
- ld hl, wd728
- bit 1, [hl]
- res 1, [hl]
- jp z, .loop
- ld a, SURFBOARD
- ld [wcf91], a
- ld [wPseudoItemID], a
- call UseItem
- ld a, [wActionResultOrTookBattleTurn]
- and a
- jp z, .loop
- call GBPalWhiteOutWithDelay3
- jp .goBackToMap
-.strength
- bit 3, a ; does the player have the Rainbow Badge?
- jp z, .newBadgeRequired
- predef PrintStrengthTxt
- call GBPalWhiteOutWithDelay3
- jp .goBackToMap
-.flash
- bit 0, a ; does the player have the Boulder Badge?
- jp z, .newBadgeRequired
- xor a
- ld [wMapPalOffset], a
- ld hl, .flashLightsAreaText
- call PrintText
- call GBPalWhiteOutWithDelay3
- jp .goBackToMap
-.flashLightsAreaText
- TX_FAR _FlashLightsAreaText
- db "@"
-.dig
- ld a, ESCAPE_ROPE
- ld [wcf91], a
- ld [wPseudoItemID], a
- call UseItem
- ld a, [wActionResultOrTookBattleTurn]
- and a
- jp z, .loop
- call GBPalWhiteOutWithDelay3
- jp .goBackToMap
-.teleport
- call CheckIfInOutsideMap
- jr z, .canTeleport
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- ld hl, .cannotUseTeleportNowText
- call PrintText
- jp .loop
-.canTeleport
- ld hl, .warpToLastPokemonCenterText
- call PrintText
- ld hl, wd732
- set 3, [hl]
- set 6, [hl]
- ld hl, wd72e
- set 1, [hl]
- res 4, [hl]
- ld c, 60
- call DelayFrames
- call GBPalWhiteOutWithDelay3
- jp .goBackToMap
-.warpToLastPokemonCenterText
- TX_FAR _WarpToLastPokemonCenterText
- db "@"
-.cannotUseTeleportNowText
- TX_FAR _CannotUseTeleportNowText
- db "@"
-.cannotFlyHereText
- TX_FAR _CannotFlyHereText
- db "@"
-.softboiled
- ld hl, wPartyMon1MaxHP
- ld a, [wWhichPokemon]
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld a, [hli]
- ld [H_DIVIDEND], a
- ld a, [hl]
- ld [H_DIVIDEND + 1], a
- ld a, 5
- ld [H_DIVISOR], a
- ld b, 2 ; number of bytes
- call Divide
- ld bc, wPartyMon1HP - wPartyMon1MaxHP
- add hl, bc
- ld a, [hld]
- ld b, a
- ld a, [H_QUOTIENT + 3]
- sub b
- ld b, [hl]
- ld a, [H_QUOTIENT + 2]
- sbc b
- jp nc, .notHealthyEnough
- ld a, [wPartyAndBillsPCSavedMenuItem]
- push af
- ld a, POTION
- ld [wcf91], a
- ld [wPseudoItemID], a
- call UseItem
- pop af
- ld [wPartyAndBillsPCSavedMenuItem], a
- jp .loop
-.notHealthyEnough ; if current HP is less than 1/5 of max HP
- ld hl, .notHealthyEnoughText
- call PrintText
- jp .loop
-.notHealthyEnoughText
- TX_FAR _NotHealthyEnoughText
- db "@"
-.goBackToMap
- call RestoreScreenTilesAndReloadTilePatterns
- jp CloseTextDisplay
-.newBadgeRequired
- ld hl, .newBadgeRequiredText
- call PrintText
- jp .loop
-.newBadgeRequiredText
- TX_FAR _NewBadgeRequiredText
- db "@"
-
-; writes a blank tile to all possible menu cursor positions on the party menu
-ErasePartyMenuCursors:
- coord hl, 0, 1
- ld bc, 2 * 20 ; menu cursor positions are 2 rows apart
- ld a, 6 ; 6 menu cursor positions
-.loop
- ld [hl], " "
- add hl, bc
- dec a
- jr nz, .loop
- ret
-
-ItemMenuLoop:
- call LoadScreenTilesFromBuffer2DisableBGTransfer ; restore saved screen
- call RunDefaultPaletteCommand
-
-StartMenu_Item:
- ld a, [wLinkState]
- dec a ; is the player in the Colosseum or Trade Centre?
- jr nz, .notInCableClubRoom
- ld hl, CannotUseItemsHereText
- call PrintText
- jr .exitMenu
-.notInCableClubRoom
- ld bc, wNumBagItems
- ld hl, wListPointer
- ld a, c
- ld [hli], a
- ld [hl], b ; store item bag pointer in wListPointer (for DisplayListMenuID)
- xor a
- ld [wPrintItemPrices], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- ld a, [wBagSavedMenuItem]
- ld [wCurrentMenuItem], a
- call DisplayListMenuID
- ld a, [wCurrentMenuItem]
- ld [wBagSavedMenuItem], a
- jr nc, .choseItem
-.exitMenu
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- call LoadTextBoxTilePatterns
- call UpdateSprites
- jp RedisplayStartMenu
-.choseItem
-; erase menu cursor (blank each tile in front of an item name)
- ld a, " "
- Coorda 5, 4
- Coorda 5, 6
- Coorda 5, 8
- Coorda 5, 10
- call PlaceUnfilledArrowMenuCursor
- xor a
- ld [wMenuItemToSwap], a
- ld a, [wcf91]
- cp BICYCLE
- jp z, .useOrTossItem
-.notBicycle1
- ld a, USE_TOSS_MENU_TEMPLATE
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld hl, wTopMenuItemY
- ld a, 11
- ld [hli], a ; top menu item Y
- ld a, 14
- ld [hli], a ; top menu item X
- xor a
- ld [hli], a ; current menu item ID
- inc hl
- inc a ; a = 1
- ld [hli], a ; max menu item ID
- ld a, A_BUTTON | B_BUTTON
- ld [hli], a ; menu watched keys
- xor a
- ld [hl], a ; old menu item id
- call HandleMenuInput
- call PlaceUnfilledArrowMenuCursor
- bit 1, a ; was the B button pressed?
- jr z, .useOrTossItem
- jp ItemMenuLoop
-.useOrTossItem ; if the player made the choice to use or toss the item
- ld a, [wcf91]
- ld [wd11e], a
- call GetItemName
- call CopyStringToCF4B ; copy name to wcf4b
- ld a, [wcf91]
- cp BICYCLE
- jr nz, .notBicycle2
- ld a, [wd732]
- bit 5, a
- jr z, .useItem_closeMenu
- ld hl, CannotGetOffHereText
- call PrintText
- jp ItemMenuLoop
-.notBicycle2
- ld a, [wCurrentMenuItem]
- and a
- jr nz, .tossItem
-; use item
- ld [wPseudoItemID], a ; a must be 0 due to above conditional jump
- ld a, [wcf91]
- cp HM_01
- jr nc, .useItem_partyMenu
- ld hl, UsableItems_CloseMenu
- ld de, 1
- call IsInArray
- jr c, .useItem_closeMenu
- ld a, [wcf91]
- ld hl, UsableItems_PartyMenu
- ld de, 1
- call IsInArray
- jr c, .useItem_partyMenu
- call UseItem
- jp ItemMenuLoop
-.useItem_closeMenu
- xor a
- ld [wPseudoItemID], a
- call UseItem
- ld a, [wActionResultOrTookBattleTurn]
- and a
- jp z, ItemMenuLoop
- jp CloseStartMenu
-.useItem_partyMenu
- ld a, [wUpdateSpritesEnabled]
- push af
- call UseItem
- ld a, [wActionResultOrTookBattleTurn]
- cp $02
- jp z, .partyMenuNotDisplayed
- call GBPalWhiteOutWithDelay3
- call RestoreScreenTilesAndReloadTilePatterns
- pop af
- ld [wUpdateSpritesEnabled], a
- jp StartMenu_Item
-.partyMenuNotDisplayed
- pop af
- ld [wUpdateSpritesEnabled], a
- jp ItemMenuLoop
-.tossItem
- call IsKeyItem
- ld a, [wIsKeyItem]
- and a
- jr nz, .skipAskingQuantity
- ld a, [wcf91]
- call IsItemHM
- jr c, .skipAskingQuantity
- call DisplayChooseQuantityMenu
- inc a
- jr z, .tossZeroItems
-.skipAskingQuantity
- ld hl, wNumBagItems
- call TossItem
-.tossZeroItems
- jp ItemMenuLoop
-
-CannotUseItemsHereText:
- TX_FAR _CannotUseItemsHereText
- db "@"
-
-CannotGetOffHereText:
- TX_FAR _CannotGetOffHereText
- db "@"
-
-; items which bring up the party menu when used
-UsableItems_PartyMenu:
- db MOON_STONE
- db ANTIDOTE
- db BURN_HEAL
- db ICE_HEAL
- db AWAKENING
- db PARLYZ_HEAL
- db FULL_RESTORE
- db MAX_POTION
- db HYPER_POTION
- db SUPER_POTION
- db POTION
- db FIRE_STONE
- db THUNDER_STONE
- db WATER_STONE
- db HP_UP
- db PROTEIN
- db IRON
- db CARBOS
- db CALCIUM
- db RARE_CANDY
- db LEAF_STONE
- db FULL_HEAL
- db REVIVE
- db MAX_REVIVE
- db FRESH_WATER
- db SODA_POP
- db LEMONADE
- db X_ATTACK
- db X_DEFEND
- db X_SPEED
- db X_SPECIAL
- db PP_UP
- db ETHER
- db MAX_ETHER
- db ELIXER
- db MAX_ELIXER
- db $ff
-
-; items which close the item menu when used
-UsableItems_CloseMenu:
- db ESCAPE_ROPE
- db ITEMFINDER
- db POKE_FLUTE
- db OLD_ROD
- db GOOD_ROD
- db SUPER_ROD
- db $ff
-
-StartMenu_TrainerInfo:
- call GBPalWhiteOut
- call ClearScreen
- call UpdateSprites
- ld a, [hTilesetType]
- push af
- xor a
- ld [hTilesetType], a
- call DrawTrainerInfo
- predef DrawBadges ; draw badges
- ld b, SET_PAL_TRAINER_CARD
- call RunPaletteCommand
- call GBPalNormal
- call WaitForTextScrollButtonPress ; wait for button press
- call GBPalWhiteOut
- call LoadFontTilePatterns
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- call RunDefaultPaletteCommand
- call ReloadMapData
- call LoadGBPal
- pop af
- ld [hTilesetType], a
- jp RedisplayStartMenu
-
-; loads tile patterns and draws everything except for gym leader faces / badges
-DrawTrainerInfo:
- ld de, RedPicFront
- lb bc, BANK(RedPicFront), $01
- predef DisplayPicCenteredOrUpperRight
- call DisableLCD
- coord hl, 0, 2
- ld a, " "
- call TrainerInfo_DrawVerticalLine
- coord hl, 1, 2
- call TrainerInfo_DrawVerticalLine
- ld hl, vChars2 + $70
- ld de, vChars2
- ld bc, $70 * 4
- call CopyData
- ld hl, TrainerInfoTextBoxTileGraphics ; trainer info text box tile patterns
- ld de, vChars2 + $770
- ld bc, $0080
- push bc
- call TrainerInfo_FarCopyData
- ld hl, BlankLeaderNames
- ld de, vChars2 + $600
- ld bc, $0170
- call TrainerInfo_FarCopyData
- pop bc
- ld hl, BadgeNumbersTileGraphics ; badge number tile patterns
- ld de, vChars1 + $580
- call TrainerInfo_FarCopyData
- ld hl, GymLeaderFaceAndBadgeTileGraphics ; gym leader face and badge tile patterns
- ld de, vChars2 + $200
- ld bc, $0400
- ld a, $03
- call FarCopyData2
- ld hl, TextBoxGraphics
- ld de, $00d0
- add hl, de ; hl = colon tile pattern
- ld de, vChars1 + $560
- ld bc, $0010
- ld a, $04
- push bc
- call FarCopyData2
- pop bc
- ld hl, TrainerInfoTextBoxTileGraphics + $80 ; background tile pattern
- ld de, vChars1 + $570
- call TrainerInfo_FarCopyData
- call EnableLCD
- ld hl, wTrainerInfoTextBoxWidthPlus1
- ld a, 18 + 1
- ld [hli], a
- dec a
- ld [hli], a
- ld [hl], 1
- coord hl, 0, 0
- call TrainerInfo_DrawTextBox
- ld hl, wTrainerInfoTextBoxWidthPlus1
- ld a, 16 + 1
- ld [hli], a
- dec a
- ld [hli], a
- ld [hl], 3
- coord hl, 1, 10
- call TrainerInfo_DrawTextBox
- coord hl, 0, 10
- ld a, $d7
- call TrainerInfo_DrawVerticalLine
- coord hl, 19, 10
- call TrainerInfo_DrawVerticalLine
- coord hl, 6, 9
- ld de, TrainerInfo_BadgesText
- call PlaceString
- coord hl, 2, 2
- ld de, TrainerInfo_NameMoneyTimeText
- call PlaceString
- coord hl, 7, 2
- ld de, wPlayerName
- call PlaceString
- coord hl, 8, 4
- ld de, wPlayerMoney
- ld c, $e3
- call PrintBCDNumber
- coord hl, 9, 6
- ld de, wPlayTimeHours ; hours
- lb bc, LEFT_ALIGN | 1, 3
- call PrintNumber
- ld [hl], $d6 ; colon tile ID
- inc hl
- ld de, wPlayTimeMinutes ; minutes
- lb bc, LEADING_ZEROES | 1, 2
- jp PrintNumber
-
-TrainerInfo_FarCopyData:
- ld a, BANK(TrainerInfoTextBoxTileGraphics)
- jp FarCopyData2
-
-TrainerInfo_NameMoneyTimeText:
- db "NAME/"
- next "MONEY/"
- next "TIME/@"
-
-; $76 is a circle tile
-TrainerInfo_BadgesText:
- db $76,"BADGES",$76,"@"
-
-; draws a text box on the trainer info screen
-; height is always 6
-; INPUT:
-; hl = destination address
-; [wTrainerInfoTextBoxWidthPlus1] = width
-; [wTrainerInfoTextBoxWidth] = width - 1
-; [wTrainerInfoTextBoxNextRowOffset] = distance from the end of a text box row to the start of the next
-TrainerInfo_DrawTextBox:
- ld a, $79 ; upper left corner tile ID
- lb de, $7a, $7b ; top edge and upper right corner tile ID's
- call TrainerInfo_DrawHorizontalEdge ; draw top edge
- call TrainerInfo_NextTextBoxRow
- ld a, [wTrainerInfoTextBoxWidthPlus1]
- ld e, a
- ld d, 0
- ld c, 6 ; height of the text box
-.loop
- ld [hl], $7c ; left edge tile ID
- add hl, de
- ld [hl], $78 ; right edge tile ID
- call TrainerInfo_NextTextBoxRow
- dec c
- jr nz, .loop
- ld a, $7d ; lower left corner tile ID
- lb de, $77, $7e ; bottom edge and lower right corner tile ID's
-
-TrainerInfo_DrawHorizontalEdge:
- ld [hli], a ; place left corner tile
- ld a, [wTrainerInfoTextBoxWidth]
- ld c, a
- ld a, d
-.loop
- ld [hli], a ; place edge tile
- dec c
- jr nz, .loop
- ld a, e
- ld [hl], a ; place right corner tile
- ret
-
-TrainerInfo_NextTextBoxRow:
- ld a, [wTrainerInfoTextBoxNextRowOffset] ; distance to the start of the next row
-.loop
- inc hl
- dec a
- jr nz, .loop
- ret
-
-; draws a vertical line
-; INPUT:
-; hl = address of top tile in the line
-; a = tile ID
-TrainerInfo_DrawVerticalLine:
- ld de, SCREEN_WIDTH
- ld c, 8
-.loop
- ld [hl], a
- add hl, de
- dec c
- jr nz, .loop
- ret
-
-StartMenu_SaveReset:
- ld a, [wd72e]
- bit 6, a ; is the player using the link feature?
- jp nz, Init
- predef SaveSAV ; save the game
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- jp HoldTextDisplayOpen
-
-StartMenu_Option:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- call UpdateSprites
- callab DisplayOptionMenu
- call LoadScreenTilesFromBuffer2 ; restore saved screen
- call LoadTextBoxTilePatterns
- call UpdateSprites
- jp RedisplayStartMenu
-
-SwitchPartyMon:
- call SwitchPartyMon_InitVarOrSwapData ; swap data
- ld a, [wSwappedMenuItem]
- call SwitchPartyMon_ClearGfx
- ld a, [wCurrentMenuItem]
- call SwitchPartyMon_ClearGfx
- jp RedrawPartyMenu_
-
-SwitchPartyMon_ClearGfx:
- push af
- coord hl, 0, 0
- ld bc, SCREEN_WIDTH * 2
- call AddNTimes
- ld c, SCREEN_WIDTH * 2
- ld a, " "
-.clearMonBGLoop ; clear the mon's row in the party menu
- ld [hli], a
- dec c
- jr nz, .clearMonBGLoop
- pop af
- ld hl, wOAMBuffer
- ld bc, $10
- call AddNTimes
- ld de, $4
- ld c, e
-.clearMonOAMLoop
- ld [hl], $a0
- add hl, de
- dec c
- jr nz, .clearMonOAMLoop
- call WaitForSoundToFinish
- ld a, SFX_SWAP
- jp PlaySound
-
-SwitchPartyMon_InitVarOrSwapData:
-; This is used to initialise [wMenuItemToSwap] and to actually swap the data.
- ld a, [wMenuItemToSwap]
- and a ; has [wMenuItemToSwap] been initialised yet?
- jr nz, .pickedMonsToSwap
-; If not, initialise [wMenuItemToSwap] so that it matches the current mon.
- ld a, [wWhichPokemon]
- inc a ; [wMenuItemToSwap] counts from 1
- ld [wMenuItemToSwap], a
- ret
-.pickedMonsToSwap
- xor a
- ld [wPartyMenuTypeOrMessageID], a
- ld a, [wMenuItemToSwap]
- dec a
- ld b, a
- ld a, [wCurrentMenuItem]
- ld [wSwappedMenuItem], a
- cp b ; swapping a mon with itself?
- jr nz, .swappingDifferentMons
-; can't swap a mon with itself
- xor a
- ld [wMenuItemToSwap], a
- ld [wPartyMenuTypeOrMessageID], a
- ret
-.swappingDifferentMons
- ld a, b
- ld [wMenuItemToSwap], a
- push hl
- push de
- ld hl, wPartySpecies
- ld d, h
- ld e, l
- ld a, [wCurrentMenuItem]
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [wMenuItemToSwap]
- add e
- ld e, a
- jr nc, .noCarry2
- inc d
-.noCarry2
- ld a, [hl]
- ld [hSwapTemp], a
- ld a, [de]
- ld [hl], a
- ld a, [hSwapTemp]
- ld [de], a
- ld hl, wPartyMons
- ld bc, wPartyMon2 - wPartyMon1
- ld a, [wCurrentMenuItem]
- call AddNTimes
- push hl
- ld de, wSwitchPartyMonTempBuffer
- ld bc, wPartyMon2 - wPartyMon1
- call CopyData
- ld hl, wPartyMons
- ld bc, wPartyMon2 - wPartyMon1
- ld a, [wMenuItemToSwap]
- call AddNTimes
- pop de
- push hl
- ld bc, wPartyMon2 - wPartyMon1
- call CopyData
- pop de
- ld hl, wSwitchPartyMonTempBuffer
- ld bc, wPartyMon2 - wPartyMon1
- call CopyData
- ld hl, wPartyMonOT
- ld a, [wCurrentMenuItem]
- call SkipFixedLengthTextEntries
- push hl
- ld de, wSwitchPartyMonTempBuffer
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wPartyMonOT
- ld a, [wMenuItemToSwap]
- call SkipFixedLengthTextEntries
- pop de
- push hl
- ld bc, NAME_LENGTH
- call CopyData
- pop de
- ld hl, wSwitchPartyMonTempBuffer
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wPartyMonNicks
- ld a, [wCurrentMenuItem]
- call SkipFixedLengthTextEntries
- push hl
- ld de, wSwitchPartyMonTempBuffer
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wPartyMonNicks
- ld a, [wMenuItemToSwap]
- call SkipFixedLengthTextEntries
- pop de
- push hl
- ld bc, NAME_LENGTH
- call CopyData
- pop de
- ld hl, wSwitchPartyMonTempBuffer
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wMenuItemToSwap]
- ld [wSwappedMenuItem], a
- xor a
- ld [wMenuItemToSwap], a
- ld [wPartyMenuTypeOrMessageID], a
- pop de
- pop hl
- ret
diff --git a/engine/menu/status_screen.asm b/engine/menu/status_screen.asm
deleted file mode 100755
index ef94f13c..00000000
--- a/engine/menu/status_screen.asm
+++ /dev/null
@@ -1,481 +0,0 @@
-DrawHP:
-; Draws the HP bar in the stats screen
- call GetPredefRegisters
- ld a, $1
- jr DrawHP_
-
-DrawHP2:
-; Draws the HP bar in the party screen
- call GetPredefRegisters
- ld a, $2
-
-DrawHP_:
- ld [wHPBarType], a
- push hl
- ld a, [wLoadedMonHP]
- ld b, a
- ld a, [wLoadedMonHP + 1]
- ld c, a
- or b
- jr nz, .nonzeroHP
- xor a
- ld c, a
- ld e, a
- ld a, $6
- ld d, a
- jp .drawHPBarAndPrintFraction
-.nonzeroHP
- ld a, [wLoadedMonMaxHP]
- ld d, a
- ld a, [wLoadedMonMaxHP + 1]
- ld e, a
- predef HPBarLength
- ld a, $6
- ld d, a
- ld c, a
-.drawHPBarAndPrintFraction
- pop hl
- push de
- push hl
- push hl
- call DrawHPBar
- pop hl
- ld a, [hFlags_0xFFF6]
- bit 0, a
- jr z, .printFractionBelowBar
- ld bc, $9 ; right of bar
- jr .printFraction
-.printFractionBelowBar
- ld bc, SCREEN_WIDTH + 1 ; below bar
-.printFraction
- add hl, bc
- ld de, wLoadedMonHP
- lb bc, 2, 3
- call PrintNumber
- ld a, "/"
- ld [hli], a
- ld de, wLoadedMonMaxHP
- lb bc, 2, 3
- call PrintNumber
- pop hl
- pop de
- ret
-
-
-; Predef 0x37
-StatusScreen:
- call LoadMonData
- ld a, [wMonDataLocation]
- cp BOX_DATA
- jr c, .DontRecalculate
-; mon is in a box or daycare
- ld a, [wLoadedMonBoxLevel]
- ld [wLoadedMonLevel], a
- ld [wCurEnemyLVL], a
- ld hl, wLoadedMonHPExp - 1
- ld de, wLoadedMonStats
- ld b, $1
- call CalcStats ; Recalculate stats
-.DontRecalculate
- ld hl, wd72c
- set 1, [hl]
- ld a, $33
- ld [rNR50], a ; Reduce the volume
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call UpdateSprites
- call LoadHpBarAndStatusTilePatterns
- ld de, BattleHudTiles1 ; source
- ld hl, vChars2 + $6d0 ; dest
- lb bc, BANK(BattleHudTiles1), $03
- call CopyVideoDataDouble ; ·│ :L and halfarrow line end
- ld de, BattleHudTiles2
- ld hl, vChars2 + $780
- lb bc, BANK(BattleHudTiles2), $01
- call CopyVideoDataDouble ; │
- ld de, BattleHudTiles3
- ld hl, vChars2 + $760
- lb bc, BANK(BattleHudTiles3), $02
- call CopyVideoDataDouble ; ─┘
- ld de, PTile
- ld hl, vChars2 + $720
- lb bc, BANK(PTile), (PTileEnd - PTile) / $8
- call CopyVideoDataDouble ; P (for PP), inline
- ld a, [hTilesetType]
- push af
- xor a
- ld [hTilesetType], a
- coord hl, 19, 1
- lb bc, 6, 10
- call DrawLineBox ; Draws the box around name, HP and status
- ld de, -6
- add hl, de
- ld [hl], "⠄" ; . after No ("." is a different one)
- dec hl
- ld [hl], "№"
- coord hl, 19, 9
- lb bc, 8, 6
- call DrawLineBox ; Draws the box around types, ID No. and OT
- coord hl, 10, 9
- ld de, Type1Text
- call PlaceString ; "TYPE1/"
- coord hl, 11, 3
- predef DrawHP
- ld hl, wStatusScreenHPBarColor
- call GetHealthBarColor
- ld b, SET_PAL_STATUS_SCREEN
- call RunPaletteCommand
- coord hl, 16, 6
- ld de, wLoadedMonStatus
- call PrintStatusCondition
- jr nz, .StatusWritten
- coord hl, 16, 6
- ld de, OKText
- call PlaceString ; "OK"
-.StatusWritten
- coord hl, 9, 6
- ld de, StatusText
- call PlaceString ; "STATUS/"
- coord hl, 14, 2
- call PrintLevel ; Pokémon level
- ld a, [wMonHIndex]
- ld [wd11e], a
- ld [wd0b5], a
- predef IndexToPokedex
- coord hl, 3, 7
- ld de, wd11e
- lb bc, LEADING_ZEROES | 1, 3
- call PrintNumber ; Pokémon no.
- coord hl, 11, 10
- predef PrintMonType
- ld hl, NamePointers2
- call .GetStringPointer
- ld d, h
- ld e, l
- coord hl, 9, 1
- call PlaceString ; Pokémon name
- ld hl, OTPointers
- call .GetStringPointer
- ld d, h
- ld e, l
- coord hl, 12, 16
- call PlaceString ; OT
- coord hl, 12, 14
- ld de, wLoadedMonOTID
- lb bc, LEADING_ZEROES | 2, 5
- call PrintNumber ; ID Number
- ld d, $0
- call PrintStatsBox
- call Delay3
- call GBPalNormal
- coord hl, 1, 0
- call LoadFlippedFrontSpriteByMonIndex ; draw Pokémon picture
- ld a, [wcf91]
- call PlayCry ; play Pokémon cry
- call WaitForTextScrollButtonPress ; wait for button
- pop af
- ld [hTilesetType], a
- ret
-
-.GetStringPointer
- ld a, [wMonDataLocation]
- add a
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [wMonDataLocation]
- cp DAYCARE_DATA
- ret z
- ld a, [wWhichPokemon]
- jp SkipFixedLengthTextEntries
-
-OTPointers:
- dw wPartyMonOT
- dw wEnemyMonOT
- dw wBoxMonOT
- dw wDayCareMonOT
-
-NamePointers2:
- dw wPartyMonNicks
- dw wEnemyMonNicks
- dw wBoxMonNicks
- dw wDayCareMonName
-
-Type1Text:
- db "TYPE1/", $4e
-
-Type2Text:
- db "TYPE2/", $4e
-
-IDNoText:
- db $73, "№/", $4e
-
-OTText:
- db "OT/"
- next "@"
-
-StatusText:
- db "STATUS/@"
-
-OKText:
- db "OK@"
-
-; Draws a line starting from hl high b and wide c
-DrawLineBox:
- ld de, SCREEN_WIDTH ; New line
-.PrintVerticalLine
- ld [hl], $78 ; │
- add hl, de
- dec b
- jr nz, .PrintVerticalLine
- ld [hl], $77 ; ┘
- dec hl
-.PrintHorizLine
- ld [hl], $76 ; ─
- dec hl
- dec c
- jr nz, .PrintHorizLine
- ld [hl], $6f ; ← (halfarrow ending)
- ret
-
-PTile: ; This is a single 1bpp "P" tile
- INCBIN "gfx/p_tile.1bpp"
-PTileEnd:
-
-PrintStatsBox:
- ld a, d
- and a ; a is 0 from the status screen
- jr nz, .DifferentBox
- coord hl, 0, 8
- ld b, 8
- ld c, 8
- call TextBoxBorder ; Draws the box
- coord hl, 1, 9 ; Start printing stats from here
- ld bc, $0019 ; Number offset
- jr .PrintStats
-.DifferentBox
- coord hl, 9, 2
- ld b, 8
- ld c, 9
- call TextBoxBorder
- coord hl, 11, 3
- ld bc, $0018
-.PrintStats
- push bc
- push hl
- ld de, StatsText
- call PlaceString
- pop hl
- pop bc
- add hl, bc
- ld de, wLoadedMonAttack
- lb bc, 2, 3
- call PrintStat
- ld de, wLoadedMonDefense
- call PrintStat
- ld de, wLoadedMonSpeed
- call PrintStat
- ld de, wLoadedMonSpecial
- jp PrintNumber
-PrintStat:
- push hl
- call PrintNumber
- pop hl
- ld de, SCREEN_WIDTH * 2
- add hl, de
- ret
-
-StatsText:
- db "ATTACK"
- next "DEFENSE"
- next "SPEED"
- next "SPECIAL@"
-
-StatusScreen2:
- ld a, [hTilesetType]
- push af
- xor a
- ld [hTilesetType], a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld bc, NUM_MOVES + 1
- ld hl, wMoves
- call FillMemory
- ld hl, wLoadedMonMoves
- ld de, wMoves
- ld bc, NUM_MOVES
- call CopyData
- callab FormatMovesString
- coord hl, 9, 2
- lb bc, 5, 10
- call ClearScreenArea ; Clear under name
- coord hl, 19, 3
- ld [hl], $78
- coord hl, 0, 8
- ld b, 8
- ld c, 18
- call TextBoxBorder ; Draw move container
- coord hl, 2, 9
- ld de, wMovesString
- call PlaceString ; Print moves
- ld a, [wNumMovesMinusOne]
- inc a
- ld c, a
- ld a, $4
- sub c
- ld b, a ; Number of moves ?
- coord hl, 11, 10
- ld de, SCREEN_WIDTH * 2
- ld a, $72 ; special P tile id
- call StatusScreen_PrintPP ; Print "PP"
- ld a, b
- and a
- jr z, .InitPP
- ld c, a
- ld a, "-"
- call StatusScreen_PrintPP ; Fill the rest with --
-.InitPP
- ld hl, wLoadedMonMoves
- coord de, 14, 10
- ld b, 0
-.PrintPP
- ld a, [hli]
- and a
- jr z, .PPDone
- push bc
- push hl
- push de
- ld hl, wCurrentMenuItem
- ld a, [hl]
- push af
- ld a, b
- ld [hl], a
- push hl
- callab GetMaxPP
- pop hl
- pop af
- ld [hl], a
- pop de
- pop hl
- push hl
- ld bc, wPartyMon1PP - wPartyMon1Moves - 1
- add hl, bc
- ld a, [hl]
- and $3f
- ld [wStatusScreenCurrentPP], a
- ld h, d
- ld l, e
- push hl
- ld de, wStatusScreenCurrentPP
- lb bc, 1, 2
- call PrintNumber
- ld a, "/"
- ld [hli], a
- ld de, wMaxPP
- lb bc, 1, 2
- call PrintNumber
- pop hl
- ld de, SCREEN_WIDTH * 2
- add hl, de
- ld d, h
- ld e, l
- pop hl
- pop bc
- inc b
- ld a, b
- cp $4
- jr nz, .PrintPP
-.PPDone
- coord hl, 9, 3
- ld de, StatusScreenExpText
- call PlaceString
- ld a, [wLoadedMonLevel]
- push af
- cp MAX_LEVEL
- jr z, .Level100
- inc a
- ld [wLoadedMonLevel], a ; Increase temporarily if not 100
-.Level100
- coord hl, 14, 6
- ld [hl], $70 ; 1-tile "to"
- inc hl
- inc hl
- call PrintLevel
- pop af
- ld [wLoadedMonLevel], a
- ld de, wLoadedMonExp
- coord hl, 12, 4
- lb bc, 3, 7
- call PrintNumber ; exp
- call CalcExpToLevelUp
- ld de, wLoadedMonExp
- coord hl, 7, 6
- lb bc, 3, 7
- call PrintNumber ; exp needed to level up
- coord hl, 9, 0
- call StatusScreen_ClearName
- coord hl, 9, 1
- call StatusScreen_ClearName
- ld a, [wMonHIndex]
- ld [wd11e], a
- call GetMonName
- coord hl, 9, 1
- call PlaceString
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- call WaitForTextScrollButtonPress ; wait for button
- pop af
- ld [hTilesetType], a
- ld hl, wd72c
- res 1, [hl]
- ld a, $77
- ld [rNR50], a
- call GBPalWhiteOut
- jp ClearScreen
-
-CalcExpToLevelUp:
- ld a, [wLoadedMonLevel]
- cp MAX_LEVEL
- jr z, .atMaxLevel
- inc a
- ld d, a
- callab CalcExperience
- ld hl, wLoadedMonExp + 2
- ld a, [hExperience + 2]
- sub [hl]
- ld [hld], a
- ld a, [hExperience + 1]
- sbc [hl]
- ld [hld], a
- ld a, [hExperience]
- sbc [hl]
- ld [hld], a
- ret
-.atMaxLevel
- ld hl, wLoadedMonExp
- xor a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ret
-
-StatusScreenExpText:
- db "EXP POINTS"
- next "LEVEL UP@"
-
-StatusScreen_ClearName:
- ld bc, 10
- ld a, " "
- jp FillMemory
-
-StatusScreen_PrintPP:
-; print PP or -- c times, going down two rows each time
- ld [hli], a
- ld [hld], a
- add hl, de
- dec c
- jr nz, StatusScreen_PrintPP
- ret
diff --git a/engine/menu/text_box.asm b/engine/menu/text_box.asm
deleted file mode 100644
index b9a36652..00000000
--- a/engine/menu/text_box.asm
+++ /dev/null
@@ -1,767 +0,0 @@
-; function to draw various text boxes
-DisplayTextBoxID_:
- ld a, [wTextBoxID]
- cp TWO_OPTION_MENU
- jp z, DisplayTwoOptionMenu
- ld c, a
- ld hl, TextBoxFunctionTable
- ld de, 3
- call SearchTextBoxTable
- jr c, .functionTableMatch
- ld hl, TextBoxCoordTable
- ld de, 5
- call SearchTextBoxTable
- jr c, .coordTableMatch
- ld hl, TextBoxTextAndCoordTable
- ld de, 9
- call SearchTextBoxTable
- jr c, .textAndCoordTableMatch
-.done
- ret
-.functionTableMatch
- ld a, [hli]
- ld h, [hl]
- ld l, a ; hl = address of function
- ld de, .done
- push de
- jp hl ; jump to the function
-.coordTableMatch
- call GetTextBoxIDCoords
- call GetAddressOfScreenCoords
- call TextBoxBorder
- ret
-.textAndCoordTableMatch
- call GetTextBoxIDCoords
- push hl
- call GetAddressOfScreenCoords
- call TextBoxBorder
- pop hl
- call GetTextBoxIDText
- ld a, [wd730]
- push af
- ld a, [wd730]
- set 6, a ; no pauses between printing each letter
- ld [wd730], a
- call PlaceString
- pop af
- ld [wd730], a
- call UpdateSprites
- ret
-
-; function to search a table terminated with $ff for a byte matching c in increments of de
-; sets carry flag if a match is found and clears carry flag if not
-SearchTextBoxTable:
- dec de
-.loop
- ld a, [hli]
- cp $ff
- jr z, .notFound
- cp c
- jr z, .found
- add hl, de
- jr .loop
-.found
- scf
-.notFound
- ret
-
-; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable
-; INPUT:
-; hl = address of coordinates
-; OUTPUT:
-; b = height
-; c = width
-; d = row of upper left corner
-; e = column of upper left corner
-GetTextBoxIDCoords:
- ld a, [hli] ; column of upper left corner
- ld e, a
- ld a, [hli] ; row of upper left corner
- ld d, a
- ld a, [hli] ; column of lower right corner
- sub e
- dec a
- ld c, a ; c = width
- ld a, [hli] ; row of lower right corner
- sub d
- dec a
- ld b, a ; b = height
- ret
-
-; function to load a text address and text coordinates from the TextBoxTextAndCoordTable
-GetTextBoxIDText:
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a ; de = address of text
- push de ; save text address
- ld a, [hli]
- ld e, a ; column of upper left corner of text
- ld a, [hl]
- ld d, a ; row of upper left corner of text
- call GetAddressOfScreenCoords
- pop de ; restore text address
- ret
-
-; function to point hl to the screen coordinates
-; INPUT:
-; d = row
-; e = column
-; OUTPUT:
-; hl = address of upper left corner of text box
-GetAddressOfScreenCoords:
- push bc
- coord hl, 0, 0
- ld bc, 20
-.loop ; loop to add d rows to the base address
- ld a, d
- and a
- jr z, .addedRows
- add hl, bc
- dec d
- jr .loop
-.addedRows
- pop bc
- add hl, de
- ret
-
-; Format:
-; 00: text box ID
-; 01-02: function address
-TextBoxFunctionTable:
- dbw MONEY_BOX, DisplayMoneyBox
- dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu
- dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu
- db $ff ; terminator
-
-; Format:
-; 00: text box ID
-; 01: column of upper left corner
-; 02: row of upper left corner
-; 03: column of lower right corner
-; 04: row of lower right corner
-TextBoxCoordTable:
- db MESSAGE_BOX, 0, 12, 19, 17
- db $03, 0, 0, 19, 14
- db $07, 0, 0, 11, 6
- db LIST_MENU_BOX, 4, 2, 19, 12
- db $10, 7, 0, 19, 17
- db MON_SPRITE_POPUP, 6, 4, 14, 13
- db $ff ; terminator
-
-; Format:
-; 00: text box ID
-; 01: column of upper left corner
-; 02: row of upper left corner
-; 03: column of lower right corner
-; 04: row of lower right corner
-; 05-06: address of text
-; 07: column of beginning of text
-; 08: row of beginning of text
-; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row]
-TextBoxTextAndCoordTable:
- db JP_MOCHIMONO_MENU_TEMPLATE
- db 0,0,14,17 ; text box coordinates
- dw JapaneseMochimonoText
- db 3,0 ; text coordinates
-
- db USE_TOSS_MENU_TEMPLATE
- db 13,10,19,14 ; text box coordinates
- dw UseTossText
- db 15,11 ; text coordinates
-
- db JP_SAVE_MESSAGE_MENU_TEMPLATE
- db 0,0,7,5 ; text box coordinates
- dw JapaneseSaveMessageText
- db 2,2 ; text coordinates
-
- db JP_SPEED_OPTIONS_MENU_TEMPLATE
- db 0,6,5,10 ; text box coordinates
- dw JapaneseSpeedOptionsText
- db 2,7 ; text coordinates
-
- db BATTLE_MENU_TEMPLATE
- db 8,12,19,17 ; text box coordinates
- dw BattleMenuText
- db 10,14 ; text coordinates
-
- db SAFARI_BATTLE_MENU_TEMPLATE
- db 0,12,19,17 ; text box coordinates
- dw SafariZoneBattleMenuText
- db 2,14 ; text coordinates
-
- db SWITCH_STATS_CANCEL_MENU_TEMPLATE
- db 11,11,19,17 ; text box coordinates
- dw SwitchStatsCancelText
- db 13,12 ; text coordinates
-
- db BUY_SELL_QUIT_MENU_TEMPLATE
- db 0,0,10,6 ; text box coordinates
- dw BuySellQuitText
- db 2,1 ; text coordinates
-
- db MONEY_BOX_TEMPLATE
- db 11,0,19,2 ; text box coordinates
- dw MoneyText
- db 13,0 ; text coordinates
-
- db JP_AH_MENU_TEMPLATE
- db 7,6,11,10 ; text box coordinates
- dw JapaneseAhText
- db 8,8 ; text coordinates
-
- db JP_POKEDEX_MENU_TEMPLATE
- db 11,8,19,17 ; text box coordinates
- dw JapanesePokedexMenu
- db 12,10 ; text coordinates
-
-; note that there is no terminator
-
-BuySellQuitText:
- db "BUY"
- next "SELL"
- next "QUIT@@"
-
-UseTossText:
- db "USE"
- next "TOSS@"
-
-JapaneseSaveMessageText:
- db "きろく"
- next "メッセージ@"
-
-JapaneseSpeedOptionsText:
- db "はやい"
- next "おそい@"
-
-MoneyText:
- db "MONEY@"
-
-JapaneseMochimonoText:
- db "もちもの@"
-
-JapaneseMainMenuText:
- db "つづきから"
- next "さいしょから@"
-
-BattleMenuText:
- db "FIGHT ",$E1,$E2
- next "ITEM RUN@"
-
-SafariZoneBattleMenuText:
- db "BALL× BAIT"
- next "THROW ROCK RUN@"
-
-SwitchStatsCancelText:
- db "SWITCH"
- next "STATS"
- next "CANCEL@"
-
-JapaneseAhText:
- db "アッ!@"
-
-JapanesePokedexMenu:
- db "データをみる"
- next "なきごえ"
- next "ぶんぷをみる"
- next "キャンセル@"
-
-DisplayMoneyBox:
- ld hl, wd730
- set 6, [hl]
- ld a, MONEY_BOX_TEMPLATE
- ld [wTextBoxID], a
- call DisplayTextBoxID
- coord hl, 13, 1
- ld b, 1
- ld c, 6
- call ClearScreenArea
- coord hl, 12, 1
- ld de, wPlayerMoney
- ld c, $a3
- call PrintBCDNumber
- ld hl, wd730
- res 6, [hl]
- ret
-
-CurrencyString:
- db " ¥@"
-
-DoBuySellQuitMenu:
- ld a, [wd730]
- set 6, a ; no printing delay
- ld [wd730], a
- xor a
- ld [wChosenMenuItem], a
- ld a, BUY_SELL_QUIT_MENU_TEMPLATE
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, $2
- ld [wMaxMenuItem], a
- ld a, $1
- ld [wTopMenuItemY], a
- ld a, $1
- ld [wTopMenuItemX], a
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [wMenuWatchMovingOutOfBounds], a
- ld a, [wd730]
- res 6, a ; turn on the printing delay
- ld [wd730], a
- call HandleMenuInput
- call PlaceUnfilledArrowMenuCursor
- bit 0, a ; was A pressed?
- jr nz, .pressedA
- bit 1, a ; was B pressed? (always true since only A/B are watched)
- jr z, .pressedA
- ld a, CANCELLED_MENU
- ld [wMenuExitMethod], a
- jr .quit
-.pressedA
- ld a, CHOSE_MENU_ITEM
- ld [wMenuExitMethod], a
- ld a, [wCurrentMenuItem]
- ld [wChosenMenuItem], a
- ld b, a
- ld a, [wMaxMenuItem]
- cp b
- jr z, .quit
- ret
-.quit
- ld a, CANCELLED_MENU
- ld [wMenuExitMethod], a
- ld a, [wCurrentMenuItem]
- ld [wChosenMenuItem], a
- scf
- ret
-
-; displays a menu with two options to choose from
-; b = Y of upper left corner of text region
-; c = X of upper left corner of text region
-; hl = address where the text box border should be drawn
-DisplayTwoOptionMenu:
- push hl
- ld a, [wd730]
- set 6, a ; no printing delay
- ld [wd730], a
-
-; pointless because both values are overwritten before they are read
- xor a
- ld [wChosenMenuItem], a
- ld [wMenuExitMethod], a
-
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, $1
- ld [wMaxMenuItem], a
- ld a, b
- ld [wTopMenuItemY], a
- ld a, c
- ld [wTopMenuItemX], a
- xor a
- ld [wLastMenuItem], a
- ld [wMenuWatchMovingOutOfBounds], a
- push hl
- ld hl, wTwoOptionMenuID
- bit 7, [hl] ; select second menu item by default?
- res 7, [hl]
- jr z, .storeCurrentMenuItem
- inc a
-.storeCurrentMenuItem
- ld [wCurrentMenuItem], a
- pop hl
- push hl
- push hl
- call TwoOptionMenu_SaveScreenTiles
- ld a, [wTwoOptionMenuID]
- ld hl, TwoOptionMenuStrings
- ld e, a
- ld d, $0
- ld a, $5
-.menuStringLoop
- add hl, de
- dec a
- jr nz, .menuStringLoop
- ld a, [hli]
- ld c, a
- ld a, [hli]
- ld b, a
- ld e, l
- ld d, h
- pop hl
- push de
- ld a, [wTwoOptionMenuID]
- cp TRADE_CANCEL_MENU
- jr nz, .notTradeCancelMenu
- call CableClub_TextBoxBorder
- jr .afterTextBoxBorder
-.notTradeCancelMenu
- call TextBoxBorder
-.afterTextBoxBorder
- call UpdateSprites
- pop hl
- ld a, [hli]
- and a ; put blank line before first menu item?
- ld bc, 20 + 2
- jr z, .noBlankLine
- ld bc, 2 * 20 + 2
-.noBlankLine
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- pop hl
- add hl, bc
- call PlaceString
- ld hl, wd730
- res 6, [hl] ; turn on the printing delay
- ld a, [wTwoOptionMenuID]
- cp NO_YES_MENU
- jr nz, .notNoYesMenu
-; No/Yes menu
-; this menu type ignores the B button
-; it only seems to be used when confirming the deletion of a save file
- xor a
- ld [wTwoOptionMenuID], a
- ld a, [wFlags_0xcd60]
- push af
- push hl
- ld hl, wFlags_0xcd60
- bit 5, [hl]
- set 5, [hl] ; don't play sound when A or B is pressed in menu
- pop hl
-.noYesMenuInputLoop
- call HandleMenuInput
- bit 1, a ; A button pressed?
- jr nz, .noYesMenuInputLoop ; try again if A was not pressed
- pop af
- pop hl
- ld [wFlags_0xcd60], a
- ld a, SFX_PRESS_AB
- call PlaySound
- jr .pressedAButton
-.notNoYesMenu
- xor a
- ld [wTwoOptionMenuID], a
- call HandleMenuInput
- pop hl
- bit 1, a ; A button pressed?
- jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed
-.pressedAButton
- ld a, [wCurrentMenuItem]
- ld [wChosenMenuItem], a
- and a
- jr nz, .choseSecondMenuItem
-; chose first menu item
- ld a, CHOSE_FIRST_ITEM
- ld [wMenuExitMethod], a
- ld c, 15
- call DelayFrames
- call TwoOptionMenu_RestoreScreenTiles
- and a
- ret
-.choseSecondMenuItem
- ld a, 1
- ld [wCurrentMenuItem], a
- ld [wChosenMenuItem], a
- ld a, CHOSE_SECOND_ITEM
- ld [wMenuExitMethod], a
- ld c, 15
- call DelayFrames
- call TwoOptionMenu_RestoreScreenTiles
- scf
- ret
-
-; Some of the wider/taller two option menus will not have the screen areas
-; they cover be fully saved/restored by the two functions below.
-; The bottom and right edges of the menu may remain after the function returns.
-
-TwoOptionMenu_SaveScreenTiles:
- ld de, wBuffer
- lb bc, 5, 6
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- dec c
- jr nz, .loop
- push bc
- ld bc, SCREEN_WIDTH - 6
- add hl, bc
- pop bc
- ld c, $6
- dec b
- jr nz, .loop
- ret
-
-TwoOptionMenu_RestoreScreenTiles:
- ld de, wBuffer
- lb bc, 5, 6
-.loop
- ld a, [de]
- inc de
- ld [hli], a
- dec c
- jr nz, .loop
- push bc
- ld bc, SCREEN_WIDTH - 6
- add hl, bc
- pop bc
- ld c, 6
- dec b
- jr nz, .loop
- call UpdateSprites
- ret
-
-; Format:
-; 00: byte width
-; 01: byte height
-; 02: byte put blank line before first menu item
-; 03: word text pointer
-TwoOptionMenuStrings:
- db 4,3,0
- dw .YesNoMenu
- db 6,3,0
- dw .NorthWestMenu
- db 6,3,0
- dw .SouthEastMenu
- db 6,3,0
- dw .YesNoMenu
- db 6,3,0
- dw .NorthEastMenu
- db 7,3,0
- dw .TradeCancelMenu
- db 7,4,1
- dw .HealCancelMenu
- db 4,3,0
- dw .NoYesMenu
-
-.NoYesMenu
- db "NO"
- next "YES@"
-.YesNoMenu
- db "YES"
- next "NO@"
-.NorthWestMenu
- db "NORTH"
- next "WEST@"
-.SouthEastMenu
- db "SOUTH"
- next "EAST@"
-.NorthEastMenu
- db "NORTH"
- next "EAST@"
-.TradeCancelMenu
- db "TRADE"
- next "CANCEL@"
-.HealCancelMenu
- db "HEAL"
- next "CANCEL@"
-
-DisplayFieldMoveMonMenu:
- xor a
- ld hl, wFieldMoves
- ld [hli], a ; wFieldMoves
- ld [hli], a ; wFieldMoves + 1
- ld [hli], a ; wFieldMoves + 2
- ld [hli], a ; wFieldMoves + 3
- ld [hli], a ; wNumFieldMoves
- ld [hl], 12 ; wFieldMovesLeftmostXCoord
- call GetMonFieldMoves
- ld a, [wNumFieldMoves]
- and a
- jr nz, .fieldMovesExist
-
-; no field moves
- coord hl, 11, 11
- ld b, 5
- ld c, 7
- call TextBoxBorder
- call UpdateSprites
- ld a, 12
- ld [hFieldMoveMonMenuTopMenuItemX], a
- coord hl, 13, 12
- ld de, PokemonMenuEntries
- jp PlaceString
-
-.fieldMovesExist
- push af
-
-; Calculate the text box position and dimensions based on the leftmost X coord
-; of the field move names before adjusting for the number of field moves.
- coord hl, 0, 11
- ld a, [wFieldMovesLeftmostXCoord]
- dec a
- ld e, a
- ld d, 0
- add hl, de
- ld b, 5
- ld a, 18
- sub e
- ld c, a
- pop af
-
-; For each field move, move the top of the text box up 2 rows while the leaving
-; the bottom of the text box at the bottom of the screen.
- ld de, -SCREEN_WIDTH * 2
-.textBoxHeightLoop
- add hl, de
- inc b
- inc b
- dec a
- jr nz, .textBoxHeightLoop
-
-; Make space for an extra blank row above the top field move.
- ld de, -SCREEN_WIDTH
- add hl, de
- inc b
-
- call TextBoxBorder
- call UpdateSprites
-
-; Calculate the position of the first field move name to print.
- coord hl, 0, 12
- ld a, [wFieldMovesLeftmostXCoord]
- inc a
- ld e, a
- ld d, 0
- add hl, de
- ld de, -SCREEN_WIDTH * 2
- ld a, [wNumFieldMoves]
-.calcFirstFieldMoveYLoop
- add hl, de
- dec a
- jr nz, .calcFirstFieldMoveYLoop
-
- xor a
- ld [wNumFieldMoves], a
- ld de, wFieldMoves
-.printNamesLoop
- push hl
- ld hl, FieldMoveNames
- ld a, [de]
- and a
- jr z, .donePrintingNames
- inc de
- ld b, a ; index of name
-.skipNamesLoop ; skip past names before the name we want
- dec b
- jr z, .reachedName
-.skipNameLoop ; skip past current name
- ld a, [hli]
- cp "@"
- jr nz, .skipNameLoop
- jr .skipNamesLoop
-.reachedName
- ld b, h
- ld c, l
- pop hl
- push de
- ld d, b
- ld e, c
- call PlaceString
- ld bc, SCREEN_WIDTH * 2
- add hl, bc
- pop de
- jr .printNamesLoop
-
-.donePrintingNames
- pop hl
- ld a, [wFieldMovesLeftmostXCoord]
- ld [hFieldMoveMonMenuTopMenuItemX], a
- coord hl, 0, 12
- ld a, [wFieldMovesLeftmostXCoord]
- inc a
- ld e, a
- ld d, 0
- add hl, de
- ld de, PokemonMenuEntries
- jp PlaceString
-
-FieldMoveNames:
- db "CUT@"
- db "FLY@"
- db "@"
- db "SURF@"
- db "STRENGTH@"
- db "FLASH@"
- db "DIG@"
- db "TELEPORT@"
- db "SOFTBOILED@"
-
-PokemonMenuEntries:
- db "STATS"
- next "SWITCH"
- next "CANCEL@"
-
-GetMonFieldMoves:
- ld a, [wWhichPokemon]
- ld hl, wPartyMon1Moves
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes
- ld d, h
- ld e, l
- ld c, NUM_MOVES + 1
- ld hl, wFieldMoves
-.loop
- push hl
-.nextMove
- dec c
- jr z, .done
- ld a, [de] ; move ID
- and a
- jr z, .done
- ld b, a
- inc de
- ld hl, FieldMoveDisplayData
-.fieldMoveLoop
- ld a, [hli]
- cp $ff
- jr z, .nextMove ; if the move is not a field move
- cp b
- jr z, .foundFieldMove
- inc hl
- inc hl
- jr .fieldMoveLoop
-.foundFieldMove
- ld a, b
- ld [wLastFieldMoveID], a
- ld a, [hli] ; field move name index
- ld b, [hl] ; field move leftmost X coordinate
- pop hl
- ld [hli], a ; store name index in wFieldMoves
- ld a, [wNumFieldMoves]
- inc a
- ld [wNumFieldMoves], a
- ld a, [wFieldMovesLeftmostXCoord]
- cp b
- jr c, .skipUpdatingLeftmostXCoord
- ld a, b
- ld [wFieldMovesLeftmostXCoord], a
-.skipUpdatingLeftmostXCoord
- ld a, [wLastFieldMoveID]
- ld b, a
- jr .loop
-.done
- pop hl
- ret
-
-; Format: [Move id], [name index], [leftmost tile]
-; Move id = id of move
-; Name index = index of name in FieldMoveNames
-; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed
-; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C
-FieldMoveDisplayData:
- db CUT, $01, $0C
- db FLY, $02, $0C
- db $B4, $03, $0C ; unused field move
- db SURF, $04, $0C
- db STRENGTH, $05, $0A
- db FLASH, $06, $0C
- db DIG, $07, $0C
- db TELEPORT, $08, $0A
- db SOFTBOILED, $09, $08
- db $ff ; list terminator
diff --git a/engine/menu/vending_machine.asm b/engine/menu/vending_machine.asm
deleted file mode 100755
index aab4adf4..00000000
--- a/engine/menu/vending_machine.asm
+++ /dev/null
@@ -1,139 +0,0 @@
-VendingMachineMenu:
- ld hl, VendingMachineText1
- call PrintText
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- call DisplayTextBoxID
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 3
- ld [wMaxMenuItem], a
- ld a, 5
- ld [wTopMenuItemY], a
- ld a, 1
- ld [wTopMenuItemX], a
- ld hl, wd730
- set 6, [hl]
- coord hl, 0, 3
- ld b, 8
- ld c, 12
- call TextBoxBorder
- call UpdateSprites
- coord hl, 2, 5
- ld de, DrinkText
- call PlaceString
- coord hl, 9, 6
- ld de, DrinkPriceText
- call PlaceString
- ld hl, wd730
- res 6, [hl]
- call HandleMenuInput
- bit 1, a ; pressed B?
- jr nz, .notThirsty
- ld a, [wCurrentMenuItem]
- cp 3 ; chose Cancel?
- jr z, .notThirsty
- xor a
- ld [hMoney], a
- ld [hMoney + 2], a
- ld a, $2
- ld [hMoney + 1], a
- call HasEnoughMoney
- jr nc, .enoughMoney
- ld hl, VendingMachineText4
- jp PrintText
-.enoughMoney
- call LoadVendingMachineItem
- ld a, [hVendingMachineItem]
- ld b, a
- ld c, 1
- call GiveItem
- jr nc, .BagFull
-
- ld b, 60 ; number of times to play the "brrrrr" sound
-.playDeliverySound
- ld c, 2
- call DelayFrames
- push bc
- ld a, SFX_PUSH_BOULDER
- call PlaySound
- pop bc
- dec b
- jr nz, .playDeliverySound
-
- ld hl, VendingMachineText5
- call PrintText
- ld hl, hVendingMachinePrice + 2
- ld de, wPlayerMoney + 2
- ld c, $3
- predef SubBCDPredef
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- jp DisplayTextBoxID
-.BagFull
- ld hl, VendingMachineText6
- jp PrintText
-.notThirsty
- ld hl, VendingMachineText7
- jp PrintText
-
-VendingMachineText1:
- TX_FAR _VendingMachineText1
- db "@"
-
-DrinkText:
- db "FRESH WATER"
- next "SODA POP"
- next "LEMONADE"
- next "CANCEL@"
-
-DrinkPriceText:
- db "¥200"
- next "¥300"
- next "¥350"
- next "@"
-
-VendingMachineText4:
- TX_FAR _VendingMachineText4
- db "@"
-
-VendingMachineText5:
- TX_FAR _VendingMachineText5
- db "@"
-
-VendingMachineText6:
- TX_FAR _VendingMachineText6
- db "@"
-
-VendingMachineText7:
- TX_FAR _VendingMachineText7
- db "@"
-
-LoadVendingMachineItem:
- ld hl, VendingPrices
- ld a, [wCurrentMenuItem]
- add a
- add a
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hli]
- ld [hVendingMachineItem], a
- ld a, [hli]
- ld [hVendingMachinePrice], a
- ld a, [hli]
- ld [hVendingMachinePrice + 1], a
- ld a, [hl]
- ld [hVendingMachinePrice + 2], a
- ret
-
-VendingPrices:
- db FRESH_WATER
- money 200
- db SODA_POP
- money 300
- db LEMONADE
- money 350
diff --git a/engine/oak_speech2.asm b/engine/oak_speech2.asm
deleted file mode 100755
index 1258c59b..00000000
--- a/engine/oak_speech2.asm
+++ /dev/null
@@ -1,272 +0,0 @@
-ChoosePlayerName:
- call OakSpeechSlidePicRight
- ld de, DefaultNamesPlayer
- call DisplayIntroNameTextBox
- ld a, [wCurrentMenuItem]
- and a
- jr z, .customName
- ld hl, DefaultNamesPlayerList
- call GetDefaultName
- ld de, wPlayerName
- call OakSpeechSlidePicLeft
- jr .done
-.customName
- ld hl, wPlayerName
- xor a ; NAME_PLAYER_SCREEN
- ld [wNamingScreenType], a
- call DisplayNamingScreen
- ld a, [wcf4b]
- cp "@"
- jr z, .customName
- call ClearScreen
- call Delay3
- ld de, RedPicFront
- ld b, BANK(RedPicFront)
- call IntroDisplayPicCenteredOrUpperRight
-.done
- ld hl, YourNameIsText
- jp PrintText
-
-YourNameIsText:
- TX_FAR _YourNameIsText
- db "@"
-
-ChooseRivalName:
- call OakSpeechSlidePicRight
- ld de, DefaultNamesRival
- call DisplayIntroNameTextBox
- ld a, [wCurrentMenuItem]
- and a
- jr z, .customName
- ld hl, DefaultNamesRivalList
- call GetDefaultName
- ld de, wRivalName
- call OakSpeechSlidePicLeft
- jr .done
-.customName
- ld hl, wRivalName
- ld a, NAME_RIVAL_SCREEN
- ld [wNamingScreenType], a
- call DisplayNamingScreen
- ld a, [wcf4b]
- cp "@"
- jr z, .customName
- call ClearScreen
- call Delay3
- ld de, Rival1Pic
- ld b, $13
- call IntroDisplayPicCenteredOrUpperRight
-.done
- ld hl, HisNameIsText
- jp PrintText
-
-HisNameIsText:
- TX_FAR _HisNameIsText
- db "@"
-
-OakSpeechSlidePicLeft:
- push de
- coord hl, 0, 0
- lb bc, 12, 11
- call ClearScreenArea ; clear the name list text box
- ld c, 10
- call DelayFrames
- pop de
- ld hl, wcd6d
- ld bc, NAME_LENGTH
- call CopyData
- call Delay3
- coord hl, 12, 4
- lb de, 6, 6 * SCREEN_WIDTH + 5
- ld a, $ff
- jr OakSpeechSlidePicCommon
-
-OakSpeechSlidePicRight:
- coord hl, 5, 4
- lb de, 6, 6 * SCREEN_WIDTH + 5
- xor a
-
-OakSpeechSlidePicCommon:
- push hl
- push de
- push bc
- ld [hSlideDirection], a
- ld a, d
- ld [hSlideAmount], a
- ld a, e
- ld [hSlidingRegionSize], a
- ld c, a
- ld a, [hSlideDirection]
- and a
- jr nz, .next
-; If sliding right, point hl to the end of the pic's tiles.
- ld d, 0
- add hl, de
-.next
- ld d, h
- ld e, l
-.loop
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [hSlideDirection]
- and a
- jr nz, .slideLeft
-; sliding right
- ld a, [hli]
- ld [hld], a
- dec hl
- jr .next2
-.slideLeft
- ld a, [hld]
- ld [hli], a
- inc hl
-.next2
- dec c
- jr nz, .loop
- ld a, [hSlideDirection]
- and a
- jr z, .next3
-; If sliding left, we need to zero the last tile in the pic (there is no need
-; to take a corresponding action when sliding right because hl initially points
-; to a 0 tile in that case).
- xor a
- dec hl
- ld [hl], a
-.next3
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- ld a, [hSlidingRegionSize]
- ld c, a
- ld h, d
- ld l, e
- ld a, [hSlideDirection]
- and a
- jr nz, .slideLeft2
- inc hl
- jr .next4
-.slideLeft2
- dec hl
-.next4
- ld d, h
- ld e, l
- ld a, [hSlideAmount]
- dec a
- ld [hSlideAmount], a
- jr nz, .loop
- pop bc
- pop de
- pop hl
- ret
-
-DisplayIntroNameTextBox:
- push de
- coord hl, 0, 0
- ld b, $a
- ld c, $9
- call TextBoxBorder
- coord hl, 3, 0
- ld de, .namestring
- call PlaceString
- pop de
- coord hl, 2, 2
- call PlaceString
- call UpdateSprites
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- inc a
- ld [wTopMenuItemX], a
- ld [wMenuWatchedKeys], a ; A_BUTTON
- inc a
- ld [wTopMenuItemY], a
- inc a
- ld [wMaxMenuItem], a
- jp HandleMenuInput
-
-.namestring
- db "NAME@"
-
-IF DEF(_RED)
-DefaultNamesPlayer:
- db "NEW NAME"
- next "RED"
- next "ASH"
- next "JACK"
- db "@"
-
-DefaultNamesRival:
- db "NEW NAME"
- next "BLUE"
- next "GARY"
- next "JOHN"
- db "@"
-ENDC
-
-IF DEF(_BLUE)
-DefaultNamesPlayer:
- db "NEW NAME"
- next "BLUE"
- next "GARY"
- next "JOHN"
- db "@"
-
-DefaultNamesRival:
- db "NEW NAME"
- next "RED"
- next "ASH"
- next "JACK"
- db "@"
-ENDC
-
-GetDefaultName:
-; a = name index
-; hl = name list
- ld b, a
- ld c, 0
-.loop
- ld d, h
- ld e, l
-.innerLoop
- ld a, [hli]
- cp "@"
- jr nz, .innerLoop
- ld a, b
- cp c
- jr z, .foundName
- inc c
- jr .loop
-.foundName
- ld h, d
- ld l, e
- ld de, wcd6d
- ld bc, $14
- jp CopyData
-
-IF DEF(_RED)
-DefaultNamesPlayerList:
- db "NEW NAME@"
- db "RED@"
- db "ASH@"
- db "JACK@"
-DefaultNamesRivalList:
- db "NEW NAME@"
- db "BLUE@"
- db "GARY@"
- db "JOHN@"
-ENDC
-IF DEF(_BLUE)
-DefaultNamesPlayerList:
- db "NEW NAME@"
- db "BLUE@"
- db "GARY@"
- db "JOHN@"
-DefaultNamesRivalList:
- db "NEW NAME@"
- db "RED@"
- db "ASH@"
- db "JACK@"
-ENDC
-
-TextTerminator_6b20:
- db "@"
diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm
deleted file mode 100644
index bbfbbc39..00000000
--- a/engine/overworld/movement.asm
+++ /dev/null
@@ -1,880 +0,0 @@
-UpdatePlayerSprite:
- ld a, [wSpriteStateData2]
- and a
- jr z, .checkIfTextBoxInFrontOfSprite
- cp $ff
- jr z, .disableSprite
- dec a
- ld [wSpriteStateData2], a
- jr .disableSprite
-; check if a text box is in front of the sprite by checking if the lower left
-; background tile the sprite is standing on is greater than $5F, which is
-; the maximum number for map tiles
-.checkIfTextBoxInFrontOfSprite
- aCoord 8, 9
- ld [hTilePlayerStandingOn], a
- cp $60
- jr c, .lowerLeftTileIsMapTile
-.disableSprite
- ld a, $ff
- ld [wSpriteStateData1 + 2], a
- ret
-.lowerLeftTileIsMapTile
- call DetectCollisionBetweenSprites
- ld h, wSpriteStateData1 / $100
- ld a, [wWalkCounter]
- and a
- jr nz, .moving
- ld a, [wPlayerMovingDirection]
-; check if down
- bit PLAYER_DIR_BIT_DOWN, a
- jr z, .checkIfUp
- xor a ; ld a, SPRITE_FACING_DOWN
- jr .next
-.checkIfUp
- bit PLAYER_DIR_BIT_UP, a
- jr z, .checkIfLeft
- ld a, SPRITE_FACING_UP
- jr .next
-.checkIfLeft
- bit PLAYER_DIR_BIT_LEFT, a
- jr z, .checkIfRight
- ld a, SPRITE_FACING_LEFT
- jr .next
-.checkIfRight
- bit PLAYER_DIR_BIT_RIGHT, a
- jr z, .notMoving
- ld a, SPRITE_FACING_RIGHT
- jr .next
-.notMoving
-; zero the animation counters
- xor a
- ld [wSpriteStateData1 + 7], a
- ld [wSpriteStateData1 + 8], a
- jr .calcImageIndex
-.next
- ld [wSpriteStateData1 + 9], a ; facing direction
- ld a, [wFontLoaded]
- bit 0, a
- jr nz, .notMoving
-.moving
- ld a, [wd736]
- bit 7, a ; is the player sprite spinning due to a spin tile?
- jr nz, .skipSpriteAnim
- ld a, [H_CURRENTSPRITEOFFSET]
- add $7
- ld l, a
- ld a, [hl]
- inc a
- ld [hl], a
- cp 4
- jr nz, .calcImageIndex
- xor a
- ld [hl], a
- inc hl
- ld a, [hl]
- inc a
- and $3
- ld [hl], a
-.calcImageIndex
- ld a, [wSpriteStateData1 + 8]
- ld b, a
- ld a, [wSpriteStateData1 + 9]
- add b
- ld [wSpriteStateData1 + 2], a
-.skipSpriteAnim
-; If the player is standing on a grass tile, make the player's sprite have
-; lower priority than the background so that it's partially obscured by the
-; grass. Only the lower half of the sprite is permitted to have the priority
-; bit set by later logic.
- ld a, [hTilePlayerStandingOn]
- ld c, a
- ld a, [wGrassTile]
- cp c
- ld a, $0
- jr nz, .next2
- ld a, $80
-.next2
- ld [wSpriteStateData2 + 7], a
- ret
-
-UnusedReadSpriteDataFunction:
- push bc
- push af
- ld a, [H_CURRENTSPRITEOFFSET]
- ld c, a
- pop af
- add c
- ld l, a
- pop bc
- ret
-
-UpdateNPCSprite:
- ld a, [H_CURRENTSPRITEOFFSET]
- swap a
- dec a
- add a
- ld hl, wMapSpriteData
- add l
- ld l, a
- ld a, [hl] ; read movement byte 2
- ld [wCurSpriteMovement2], a
- ld h, $c1
- ld a, [H_CURRENTSPRITEOFFSET]
- ld l, a
- inc l
- ld a, [hl] ; c1x1
- and a
- jp z, InitializeSpriteStatus
- call CheckSpriteAvailability
- ret c ; if sprite is invisible, on tile >=$60, in grass or player is currently walking
- ld h, $c1
- ld a, [H_CURRENTSPRITEOFFSET]
- ld l, a
- inc l
- ld a, [hl] ; c1x1
- bit 7, a ; is the face player flag set?
- jp nz, MakeNPCFacePlayer
- ld b, a
- ld a, [wFontLoaded]
- bit 0, a
- jp nz, notYetMoving
- ld a, b
- cp $2
- jp z, UpdateSpriteMovementDelay ; c1x1 == 2
- cp $3
- jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3
- ld a, [wWalkCounter]
- and a
- ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability)
- call InitializeSpriteScreenPosition
- ld h, $c2
- ld a, [H_CURRENTSPRITEOFFSET]
- add $6
- ld l, a
- ld a, [hl] ; c2x6: movement byte 1
- inc a
- jr z, .randomMovement ; value $FF
- inc a
- jr z, .randomMovement ; value $FE
-; scripted movement
- dec a
- ld [hl], a ; increment movement byte 1 (movement data index)
- dec a
- push hl
- ld hl, wNPCNumScriptedSteps
- dec [hl] ; decrement wNPCNumScriptedSteps
- pop hl
- ld de, wNPCMovementDirections
- call LoadDEPlusA ; a = [wNPCMovementDirections + movement byte 1]
- cp $e0
- jp z, ChangeFacingDirection
- cp STAY
- jr nz, .next
-; reached end of wNPCMovementDirections list
- ld [hl], a ; store $ff in movement byte 1, disabling scripted movement
- ld hl, wd730
- res 0, [hl]
- xor a
- ld [wSimulatedJoypadStatesIndex], a
- ld [wWastedByteCD3A], a
- ret
-.next
- cp WALK
- jr nz, .determineDirection
-; current NPC movement data is $fe. this seems buggy
- ld [hl], $1 ; set movement byte 1 to $1
- ld de, wNPCMovementDirections
- call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?)
- jr .determineDirection
-.randomMovement
- call GetTileSpriteStandsOn
- call Random
-.determineDirection
- ld b, a
- ld a, [wCurSpriteMovement2]
- cp $d0
- jr z, .moveDown ; movement byte 2 = $d0 forces down
- cp $d1
- jr z, .moveUp ; movement byte 2 = $d1 forces up
- cp $d2
- jr z, .moveLeft ; movement byte 2 = $d2 forces left
- cp $d3
- jr z, .moveRight ; movement byte 2 = $d3 forces right
- ld a, b
- cp $40 ; a < $40: down (or left)
- jr nc, .notDown
- ld a, [wCurSpriteMovement2]
- cp $2
- jr z, .moveLeft ; movement byte 2 = $2 only allows left or right
-.moveDown
- ld de, 2*SCREEN_WIDTH
- add hl, de ; move tile pointer two rows down
- lb de, 1, 0
- lb bc, 4, SPRITE_FACING_DOWN
- jr TryWalking
-.notDown
- cp $80 ; $40 <= a < $80: up (or right)
- jr nc, .notUp
- ld a, [wCurSpriteMovement2]
- cp $2
- jr z, .moveRight ; movement byte 2 = $2 only allows left or right
-.moveUp
- ld de, -2*SCREEN_WIDTH
- add hl, de ; move tile pointer two rows up
- lb de, -1, 0
- lb bc, 8, SPRITE_FACING_UP
- jr TryWalking
-.notUp
- cp $c0 ; $80 <= a < $c0: left (or up)
- jr nc, .notLeft
- ld a, [wCurSpriteMovement2]
- cp $1
- jr z, .moveUp ; movement byte 2 = $1 only allows up or down
-.moveLeft
- dec hl
- dec hl ; move tile pointer two columns left
- lb de, 0, -1
- lb bc, 2, SPRITE_FACING_LEFT
- jr TryWalking
-.notLeft ; $c0 <= a: right (or down)
- ld a, [wCurSpriteMovement2]
- cp $1
- jr z, .moveDown ; movement byte 2 = $1 only allows up or down
-.moveRight
- inc hl
- inc hl ; move tile pointer two columns right
- lb de, 0, 1
- lb bc, 1, SPRITE_FACING_RIGHT
- jr TryWalking
-
-; changes facing direction by zeroing the movement delta and calling TryWalking
-ChangeFacingDirection:
- ld de, $0
- ; fall through
-
-; b: direction (1,2,4 or 8)
-; c: new facing direction (0,4,8 or $c)
-; d: Y movement delta (-1, 0 or 1)
-; e: X movement delta (-1, 0 or 1)
-; hl: pointer to tile the sprite would walk onto
-; set carry on failure, clears carry on success
-TryWalking:
- push hl
- ld h, $c1
- ld a, [H_CURRENTSPRITEOFFSET]
- add $9
- ld l, a
- ld [hl], c ; c1x9 (update facing direction)
- ld a, [H_CURRENTSPRITEOFFSET]
- add $3
- ld l, a
- ld [hl], d ; c1x3 (update Y movement delta)
- inc l
- inc l
- ld [hl], e ; c1x5 (update X movement delta)
- pop hl
- push de
- ld c, [hl] ; read tile to walk onto
- call CanWalkOntoTile
- pop de
- ret c ; cannot walk there (reinitialization of delay values already done)
- ld h, $c2
- ld a, [H_CURRENTSPRITEOFFSET]
- add $4
- ld l, a
- ld a, [hl] ; c2x4: Y position
- add d
- ld [hli], a ; update Y position
- ld a, [hl] ; c2x5: X position
- add e
- ld [hl], a ; update X position
- ld a, [H_CURRENTSPRITEOFFSET]
- ld l, a
- ld [hl], $10 ; c2x0=16: walk animation counter
- dec h
- inc l
- ld [hl], $3 ; c1x1: set movement status to walking
- jp UpdateSpriteImage
-
-; update the walking animation parameters for a sprite that is currently walking
-UpdateSpriteInWalkingAnimation:
- ld a, [H_CURRENTSPRITEOFFSET]
- add $7
- ld l, a
- ld a, [hl] ; c1x7 (counter until next walk animation frame)
- inc a
- ld [hl], a ; c1x7 += 1
- cp $4
- jr nz, .noNextAnimationFrame
- xor a
- ld [hl], a ; c1x7 = 0
- inc l
- ld a, [hl] ; c1x8 (walk animation frame)
- inc a
- and $3
- ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step)
-.noNextAnimationFrame
- ld a, [H_CURRENTSPRITEOFFSET]
- add $3
- ld l, a
- ld a, [hli] ; c1x3 (movement Y delta)
- ld b, a
- ld a, [hl] ; c1x4 (screen Y position)
- add b
- ld [hli], a ; update screen Y position
- ld a, [hli] ; c1x5 (movement X delta)
- ld b, a
- ld a, [hl] ; c1x6 (screen X position)
- add b
- ld [hl], a ; update screen X position
- ld a, [H_CURRENTSPRITEOFFSET]
- ld l, a
- inc h
- ld a, [hl] ; c2x0 (walk animation counter)
- dec a
- ld [hl], a ; update walk animation counter
- ret nz
- ld a, $6 ; walking finished, update state
- add l
- ld l, a
- ld a, [hl] ; c2x6 (movement byte 1)
- cp $fe
- jr nc, .initNextMovementCounter ; values $fe and $ff
- ld a, [H_CURRENTSPRITEOFFSET]
- inc a
- ld l, a
- dec h
- ld [hl], $1 ; c1x1 = 1 (movement status ready)
- ret
-.initNextMovementCounter
- call Random
- ld a, [H_CURRENTSPRITEOFFSET]
- add $8
- ld l, a
- ld a, [hRandomAdd]
- and $7f
- ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f]
- dec h ; note that value 0 actually makes the delay $100 (bug?)
- ld a, [H_CURRENTSPRITEOFFSET]
- inc a
- ld l, a
- ld [hl], $2 ; c1x1 = 2 (movement status)
- inc l
- inc l
- xor a
- ld b, [hl] ; c1x3 (movement Y delta)
- ld [hli], a ; reset movement Y delta
- inc l
- ld c, [hl] ; c1x5 (movement X delta)
- ld [hl], a ; reset movement X delta
- ret
-
-; update delay value (c2x8) for sprites in the delayed state (c1x1)
-UpdateSpriteMovementDelay:
- ld h, $c2
- ld a, [H_CURRENTSPRITEOFFSET]
- add $6
- ld l, a
- ld a, [hl] ; c2x6: movement byte 1
- inc l
- inc l
- cp $fe
- jr nc, .tickMoveCounter ; values $fe or $ff
- ld [hl], $0
- jr .moving
-.tickMoveCounter
- dec [hl] ; c2x8: frame counter until next movement
- jr nz, notYetMoving
-.moving
- dec h
- ld a, [H_CURRENTSPRITEOFFSET]
- inc a
- ld l, a
- ld [hl], $1 ; c1x1 = 1 (mark as ready to move)
-notYetMoving:
- ld h, wSpriteStateData1 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $8
- ld l, a
- ld [hl], $0 ; c1x8 = 0 (walk animation frame)
- jp UpdateSpriteImage
-
-MakeNPCFacePlayer:
-; Make an NPC face the player if the player has spoken to him or her.
-
-; Check if the behaviour of the NPC facing the player when spoken to is
-; disabled. This is only done when rubbing the S.S. Anne captain's back.
- ld a, [wd72d]
- bit 5, a
- jr nz, notYetMoving
- res 7, [hl]
- ld a, [wPlayerDirection]
- bit PLAYER_DIR_BIT_UP, a
- jr z, .notFacingDown
- ld c, SPRITE_FACING_DOWN
- jr .facingDirectionDetermined
-.notFacingDown
- bit PLAYER_DIR_BIT_DOWN, a
- jr z, .notFacingUp
- ld c, SPRITE_FACING_UP
- jr .facingDirectionDetermined
-.notFacingUp
- bit PLAYER_DIR_BIT_LEFT, a
- jr z, .notFacingRight
- ld c, SPRITE_FACING_RIGHT
- jr .facingDirectionDetermined
-.notFacingRight
- ld c, SPRITE_FACING_LEFT
-.facingDirectionDetermined
- ld a, [H_CURRENTSPRITEOFFSET]
- add $9
- ld l, a
- ld [hl], c ; c1x9: set facing direction
- jr notYetMoving
-
-InitializeSpriteStatus:
- ld [hl], $1 ; $c1x1: set movement status to ready
- inc l
- ld [hl], $ff ; $c1x2: set sprite image to $ff (invisible/off screen)
- inc h
- ld a, [H_CURRENTSPRITEOFFSET]
- add $2
- ld l, a
- ld a, $8
- ld [hli], a ; $c2x2: set Y displacement to 8
- ld [hl], a ; $c2x3: set X displacement to 8
- ret
-
-; calculates the sprite's screen position form its map position and the player position
-InitializeSpriteScreenPosition:
- ld h, wSpriteStateData2 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $4
- ld l, a
- ld a, [wYCoord]
- ld b, a
- ld a, [hl] ; c2x4 (Y position + 4)
- sub b ; relative to player position
- swap a ; * 16
- sub $4 ; - 4
- dec h
- ld [hli], a ; c1x4 (screen Y position)
- inc h
- ld a, [wXCoord]
- ld b, a
- ld a, [hli] ; c2x6 (X position + 4)
- sub b ; relative to player position
- swap a ; * 16
- dec h
- ld [hl], a ; c1x6 (screen X position)
- ret
-
-; tests if sprite is off screen or otherwise unable to do anything
-CheckSpriteAvailability:
- predef IsObjectHidden
- ld a, [$ffe5]
- and a
- jp nz, .spriteInvisible
- ld h, wSpriteStateData2 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $6
- ld l, a
- ld a, [hl] ; c2x6: movement byte 1
- cp $fe
- jr c, .skipXVisibilityTest ; movement byte 1 < $fe (i.e. the sprite's movement is scripted)
- ld a, [H_CURRENTSPRITEOFFSET]
- add $4
- ld l, a
- ld b, [hl] ; c2x4: Y pos (+4)
- ld a, [wYCoord]
- cp b
- jr z, .skipYVisibilityTest
- jr nc, .spriteInvisible ; above screen region
- add $8 ; screen is 9 tiles high
- cp b
- jr c, .spriteInvisible ; below screen region
-.skipYVisibilityTest
- inc l
- ld b, [hl] ; c2x5: X pos (+4)
- ld a, [wXCoord]
- cp b
- jr z, .skipXVisibilityTest
- jr nc, .spriteInvisible ; left of screen region
- add $9 ; screen is 10 tiles wide
- cp b
- jr c, .spriteInvisible ; right of screen region
-.skipXVisibilityTest
-; make the sprite invisible if a text box is in front of it
-; $5F is the maximum number for map tiles
- call GetTileSpriteStandsOn
- ld d, $60
- ld a, [hli]
- cp d
- jr nc, .spriteInvisible ; standing on tile with ID >=$60 (bottom left tile)
- ld a, [hld]
- cp d
- jr nc, .spriteInvisible ; standing on tile with ID >=$60 (bottom right tile)
- ld bc, -20
- add hl, bc ; go back one row of tiles
- ld a, [hli]
- cp d
- jr nc, .spriteInvisible ; standing on tile with ID >=$60 (top left tile)
- ld a, [hl]
- cp d
- jr c, .spriteVisible ; standing on tile with ID >=$60 (top right tile)
-.spriteInvisible
- ld h, wSpriteStateData1 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $2
- ld l, a
- ld [hl], $ff ; c1x2
- scf
- jr .done
-.spriteVisible
- ld c, a
- ld a, [wWalkCounter]
- and a
- jr nz, .done ; if player is currently walking, we're done
- call UpdateSpriteImage
- inc h
- ld a, [H_CURRENTSPRITEOFFSET]
- add $7
- ld l, a
- ld a, [wGrassTile]
- cp c
- ld a, $0
- jr nz, .notInGrass
- ld a, $80
-.notInGrass
- ld [hl], a ; c2x7
- and a
-.done
- ret
-
-UpdateSpriteImage:
- ld h, $c1
- ld a, [H_CURRENTSPRITEOFFSET]
- add $8
- ld l, a
- ld a, [hli] ; c1x8: walk animation frame
- ld b, a
- ld a, [hl] ; c1x9: facing direction
- add b
- ld b, a
- ld a, [$ff93] ; current sprite offset
- add b
- ld b, a
- ld a, [H_CURRENTSPRITEOFFSET]
- add $2
- ld l, a
- ld [hl], b ; c1x2: sprite to display
- ret
-
-; tests if sprite can walk the specified direction
-; b: direction (1,2,4 or 8)
-; c: ID of tile the sprite would walk onto
-; d: Y movement delta (-1, 0 or 1)
-; e: X movement delta (-1, 0 or 1)
-; set carry on failure, clears carry on success
-CanWalkOntoTile:
- ld h, wSpriteStateData2 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $6
- ld l, a
- ld a, [hl] ; c2x6 (movement byte 1)
- cp $fe
- jr nc, .notScripted ; values $fe and $ff
-; always allow walking if the movement is scripted
- and a
- ret
-.notScripted
- ld a, [wTilesetCollisionPtr]
- ld l, a
- ld a, [wTilesetCollisionPtr+1]
- ld h, a
-.tilePassableLoop
- ld a, [hli]
- cp $ff
- jr z, .impassable
- cp c
- jr nz, .tilePassableLoop
- ld h, $c2
- ld a, [H_CURRENTSPRITEOFFSET]
- add $6
- ld l, a
- ld a, [hl] ; $c2x6 (movement byte 1)
- inc a
- jr z, .impassable ; if $ff, no movement allowed (however, changing direction is)
- ld h, wSpriteStateData1 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $4
- ld l, a
- ld a, [hli] ; c1x4 (screen Y pos)
- add $4 ; align to blocks (Y pos is always 4 pixels off)
- add d ; add Y delta
- cp $80 ; if value is >$80, the destination is off screen (either $81 or $FF underflow)
- jr nc, .impassable ; don't walk off screen
- inc l
- ld a, [hl] ; c1x6 (screen X pos)
- add e ; add X delta
- cp $90 ; if value is >$90, the destination is off screen (either $91 or $FF underflow)
- jr nc, .impassable ; don't walk off screen
- push de
- push bc
- call DetectCollisionBetweenSprites
- pop bc
- pop de
- ld h, wSpriteStateData1 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $c
- ld l, a
- ld a, [hl] ; c1xc (directions in which sprite collision would occur)
- and b ; check against chosen direction (1,2,4 or 8)
- jr nz, .impassable ; collision between sprites, don't go there
- ld h, wSpriteStateData2 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $2
- ld l, a
- ld a, [hli] ; c2x2 (sprite Y displacement, initialized at $8, keep track of where a sprite did go)
- bit 7, d ; check if going upwards (d=$ff)
- jr nz, .upwards
- add d
- cp $5
- jr c, .impassable ; if c2x2+d < 5, don't go ;bug: this tests probably were supposed to prevent sprites
- jr .checkHorizontal ; from walking out too far, but this line makes sprites get stuck
-.upwards ; whenever they walked upwards 5 steps
- sub $1 ; on the other hand, the amount a sprite can walk out to the
- jr c, .impassable ; if d2x2 == 0, don't go ; right of bottom is not limited (until the counter overflows)
-.checkHorizontal
- ld d, a
- ld a, [hl] ; c2x3 (sprite X displacement, initialized at $8, keep track of where a sprite did go)
- bit 7, e ; check if going left (e=$ff)
- jr nz, .left
- add e
- cp $5 ; compare, but no conditional jump like in the vertical check above (bug?)
- jr .passable
-.left
- sub $1
- jr c, .impassable ; if d2x3 == 0, don't go
-.passable
- ld [hld], a ; update c2x3
- ld [hl], d ; update c2x2
- and a ; clear carry (marking success)
- ret
-.impassable
- ld h, $c1
- ld a, [H_CURRENTSPRITEOFFSET]
- inc a
- ld l, a
- ld [hl], $2 ; c1x1 = 2 (set movement status to delayed)
- inc l
- inc l
- xor a
- ld [hli], a ; c1x3 = 0 (clear Y movement delta)
- inc l
- ld [hl], a ; c1x5 = 0 (clear X movement delta)
- inc h
- ld a, [H_CURRENTSPRITEOFFSET]
- add $8
- ld l, a
- call Random
- ld a, [hRandomAdd]
- and $7f
- ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f] (again with delay $100 if value is 0)
- scf ; set carry (marking failure to walk)
- ret
-
-; calculates the tile pointer pointing to the tile the current sprite stands on
-; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to
-; hl: output pointer
-GetTileSpriteStandsOn:
- ld h, wSpriteStateData1 / $100
- ld a, [H_CURRENTSPRITEOFFSET]
- add $4
- ld l, a
- ld a, [hli] ; c1x4: screen Y position
- add $4 ; align to 2*2 tile blocks (Y position is always off 4 pixels to the top)
- and $f0 ; in case object is currently moving
- srl a ; screen Y tile * 4
- ld c, a
- ld b, $0
- inc l
- ld a, [hl] ; c1x6: screen Y position
- srl a
- srl a
- srl a ; screen X tile
- add SCREEN_WIDTH ; screen X tile + 20
- ld d, $0
- ld e, a
- coord hl, 0, 0
- add hl, bc
- add hl, bc
- add hl, bc
- add hl, bc
- add hl, bc
- add hl, de ; wTileMap + 20*(screen Y tile + 1) + screen X tile
- ret
-
-; loads [de+a] into a
-LoadDEPlusA:
- add e
- ld e, a
- jr nc, .noCarry
- inc d
-.noCarry
- ld a, [de]
- ret
-
-DoScriptedNPCMovement:
-; This is an alternative method of scripting an NPC's movement and is only used
-; a few times in the game. It is used when the NPC and player must walk together
-; in sync, such as when the player is following the NPC somewhere. An NPC can't
-; be moved in sync with the player using the other method.
- ld a, [wd730]
- bit 7, a
- ret z
- ld hl, wd72e
- bit 7, [hl]
- set 7, [hl]
- jp z, InitScriptedNPCMovement
- ld hl, wNPCMovementDirections2
- ld a, [wNPCMovementDirections2Index]
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hl]
-; check if moving up
- cp NPC_MOVEMENT_UP
- jr nz, .checkIfMovingDown
- call GetSpriteScreenYPointer
- ld c, SPRITE_FACING_UP
- ld a, -2
- jr .move
-.checkIfMovingDown
- cp NPC_MOVEMENT_DOWN
- jr nz, .checkIfMovingLeft
- call GetSpriteScreenYPointer
- ld c, SPRITE_FACING_DOWN
- ld a, 2
- jr .move
-.checkIfMovingLeft
- cp NPC_MOVEMENT_LEFT
- jr nz, .checkIfMovingRight
- call GetSpriteScreenXPointer
- ld c, SPRITE_FACING_LEFT
- ld a, -2
- jr .move
-.checkIfMovingRight
- cp NPC_MOVEMENT_RIGHT
- jr nz, .noMatch
- call GetSpriteScreenXPointer
- ld c, SPRITE_FACING_RIGHT
- ld a, 2
- jr .move
-.noMatch
- cp $ff
- ret
-.move
- ld b, a
- ld a, [hl]
- add b
- ld [hl], a
- ld a, [H_CURRENTSPRITEOFFSET]
- add $9
- ld l, a
- ld a, c
- ld [hl], a ; facing direction
- call AnimScriptedNPCMovement
- ld hl, wScriptedNPCWalkCounter
- dec [hl]
- ret nz
- ld a, 8
- ld [wScriptedNPCWalkCounter], a
- ld hl, wNPCMovementDirections2Index
- inc [hl]
- ret
-
-InitScriptedNPCMovement:
- xor a
- ld [wNPCMovementDirections2Index], a
- ld a, 8
- ld [wScriptedNPCWalkCounter], a
- jp AnimScriptedNPCMovement
-
-GetSpriteScreenYPointer:
- ld a, $4
- ld b, a
- jr GetSpriteScreenXYPointerCommon
-
-GetSpriteScreenXPointer:
- ld a, $6
- ld b, a
-
-GetSpriteScreenXYPointerCommon:
- ld hl, wSpriteStateData1
- ld a, [H_CURRENTSPRITEOFFSET]
- add l
- add b
- ld l, a
- ret
-
-AnimScriptedNPCMovement:
- ld hl, wSpriteStateData2
- ld a, [H_CURRENTSPRITEOFFSET]
- add $e
- ld l, a
- ld a, [hl] ; VRAM slot
- dec a
- swap a
- ld b, a
- ld hl, wSpriteStateData1
- ld a, [H_CURRENTSPRITEOFFSET]
- add $9
- ld l, a
- ld a, [hl] ; facing direction
- cp SPRITE_FACING_DOWN
- jr z, .anim
- cp SPRITE_FACING_UP
- jr z, .anim
- cp SPRITE_FACING_LEFT
- jr z, .anim
- cp SPRITE_FACING_RIGHT
- jr z, .anim
- ret
-.anim
- add b
- ld b, a
- ld [hSpriteVRAMSlotAndFacing], a
- call AdvanceScriptedNPCAnimFrameCounter
- ld hl, wSpriteStateData1
- ld a, [H_CURRENTSPRITEOFFSET]
- add $2
- ld l, a
- ld a, [hSpriteVRAMSlotAndFacing]
- ld b, a
- ld a, [hSpriteAnimFrameCounter]
- add b
- ld [hl], a
- ret
-
-AdvanceScriptedNPCAnimFrameCounter:
- ld a, [H_CURRENTSPRITEOFFSET]
- add $7
- ld l, a
- ld a, [hl] ; intra-animation frame counter
- inc a
- ld [hl], a
- cp 4
- ret nz
- xor a
- ld [hl], a ; reset intra-animation frame counter
- inc l
- ld a, [hl] ; animation frame counter
- inc a
- and $3
- ld [hl], a
- ld [hSpriteAnimFrameCounter], a
- ret
diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm
deleted file mode 100755
index dc5b29b5..00000000
--- a/engine/overworld/pokemart.asm
+++ /dev/null
@@ -1,272 +0,0 @@
-DisplayPokemartDialogue_:
- ld a, [wListScrollOffset]
- ld [wSavedListScrollOffset], a
- call UpdateSprites
- xor a
- ld [wBoughtOrSoldItemInMart], a
-.loop
- xor a
- ld [wListScrollOffset], a
- ld [wCurrentMenuItem], a
- ld [wPlayerMonNumber], a
- inc a
- ld [wPrintItemPrices], a
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, BUY_SELL_QUIT_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
-
-; This code is useless. It copies the address of the pokemart's inventory to hl,
-; but the address is never used.
- ld hl, wItemListPointer
- ld a, [hli]
- ld l, [hl]
- ld h, a
-
- ld a, [wMenuExitMethod]
- cp CANCELLED_MENU
- jp z, .done
- ld a, [wChosenMenuItem]
- and a ; buying?
- jp z, .buyMenu
- dec a ; selling?
- jp z, .sellMenu
- dec a ; quitting?
- jp z, .done
-.sellMenu
-
-; the same variables are set again below, so this code has no effect
- xor a
- ld [wPrintItemPrices], a
- ld a, INIT_BAG_ITEM_LIST
- ld [wInitListType], a
- callab InitList
-
- ld a, [wNumBagItems]
- and a
- jp z, .bagEmpty
- ld hl, PokemonSellingGreetingText
- call PrintText
- call SaveScreenTilesToBuffer1 ; save screen
-.sellMenuLoop
- call LoadScreenTilesFromBuffer1 ; restore saved screen
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- call DisplayTextBoxID ; draw money text box
- ld hl, wNumBagItems
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wPrintItemPrices], a
- ld [wCurrentMenuItem], a
- ld a, ITEMLISTMENU
- ld [wListMenuID], a
- call DisplayListMenuID
- jp c, .returnToMainPokemartMenu ; if the player closed the menu
-.confirmItemSale ; if the player is trying to sell a specific item
- call IsKeyItem
- ld a, [wIsKeyItem]
- and a
- jr nz, .unsellableItem
- ld a, [wcf91]
- call IsItemHM
- jr c, .unsellableItem
- ld a, PRICEDITEMLISTMENU
- ld [wListMenuID], a
- ld [hHalveItemPrices], a ; halve prices when selling
- call DisplayChooseQuantityMenu
- inc a
- jr z, .sellMenuLoop ; if the player closed the choose quantity menu with the B button
- ld hl, PokemartTellSellPriceText
- lb bc, 14, 1 ; location that PrintText always prints to, this is useless
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wMenuExitMethod]
- cp CHOSE_SECOND_ITEM
- jr z, .sellMenuLoop ; if the player chose No or pressed the B button
-
-; The following code is supposed to check if the player chose No, but the above
-; check already catches it.
- ld a, [wChosenMenuItem]
- dec a
- jr z, .sellMenuLoop
-
-.sellItem
- ld a, [wBoughtOrSoldItemInMart]
- and a
- jr nz, .skipSettingFlag1
- inc a
- ld [wBoughtOrSoldItemInMart], a
-.skipSettingFlag1
- call AddAmountSoldToMoney
- ld hl, wNumBagItems
- call RemoveItemFromInventory
- jp .sellMenuLoop
-.unsellableItem
- ld hl, PokemartUnsellableItemText
- call PrintText
- jp .returnToMainPokemartMenu
-.bagEmpty
- ld hl, PokemartItemBagEmptyText
- call PrintText
- call SaveScreenTilesToBuffer1
- jp .returnToMainPokemartMenu
-.buyMenu
-
-; the same variables are set again below, so this code has no effect
- ld a, 1
- ld [wPrintItemPrices], a
- ld a, INIT_OTHER_ITEM_LIST
- ld [wInitListType], a
- callab InitList
-
- ld hl, PokemartBuyingGreetingText
- call PrintText
- call SaveScreenTilesToBuffer1
-.buyMenuLoop
- call LoadScreenTilesFromBuffer1
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld hl, wItemList
- ld a, l
- ld [wListPointer], a
- ld a, h
- ld [wListPointer + 1], a
- xor a
- ld [wCurrentMenuItem], a
- inc a
- ld [wPrintItemPrices], a
- inc a ; a = 2 (PRICEDITEMLISTMENU)
- ld [wListMenuID], a
- call DisplayListMenuID
- jr c, .returnToMainPokemartMenu ; if the player closed the menu
- ld a, 99
- ld [wMaxItemQuantity], a
- xor a
- ld [hHalveItemPrices], a ; don't halve item prices when buying
- call DisplayChooseQuantityMenu
- inc a
- jr z, .buyMenuLoop ; if the player closed the choose quantity menu with the B button
- ld a, [wcf91] ; item ID
- ld [wd11e], a ; store item ID for GetItemName
- call GetItemName
- call CopyStringToCF4B ; copy name to wcf4b
- ld hl, PokemartTellBuyPriceText
- call PrintText
- coord hl, 14, 7
- lb bc, 8, 15
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wMenuExitMethod]
- cp CHOSE_SECOND_ITEM
- jp z, .buyMenuLoop ; if the player chose No or pressed the B button
-
-; The following code is supposed to check if the player chose No, but the above
-; check already catches it.
- ld a, [wChosenMenuItem]
- dec a
- jr z, .buyMenuLoop
-
-.buyItem
- call .isThereEnoughMoney
- jr c, .notEnoughMoney
- ld hl, wNumBagItems
- call AddItemToInventory
- jr nc, .bagFull
- call SubtractAmountPaidFromMoney
- ld a, [wBoughtOrSoldItemInMart]
- and a
- jr nz, .skipSettingFlag2
- ld a, 1
- ld [wBoughtOrSoldItemInMart], a
-.skipSettingFlag2
- ld a, SFX_PURCHASE
- call PlaySoundWaitForCurrent
- call WaitForSoundToFinish
- ld hl, PokemartBoughtItemText
- call PrintText
- jp .buyMenuLoop
-.returnToMainPokemartMenu
- call LoadScreenTilesFromBuffer1
- ld a, MONEY_BOX
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld hl, PokemartAnythingElseText
- call PrintText
- jp .loop
-.isThereEnoughMoney
- ld de, wPlayerMoney
- ld hl, hMoney
- ld c, 3 ; length of money in bytes
- jp StringCmp
-.notEnoughMoney
- ld hl, PokemartNotEnoughMoneyText
- call PrintText
- jr .returnToMainPokemartMenu
-.bagFull
- ld hl, PokemartItemBagFullText
- call PrintText
- jr .returnToMainPokemartMenu
-.done
- ld hl, PokemartThankYouText
- call PrintText
- ld a, 1
- ld [wUpdateSpritesEnabled], a
- call UpdateSprites
- ld a, [wSavedListScrollOffset]
- ld [wListScrollOffset], a
- ret
-
-PokemartBuyingGreetingText:
- TX_FAR _PokemartBuyingGreetingText
- db "@"
-
-PokemartTellBuyPriceText:
- TX_FAR _PokemartTellBuyPriceText
- db "@"
-
-PokemartBoughtItemText:
- TX_FAR _PokemartBoughtItemText
- db "@"
-
-PokemartNotEnoughMoneyText:
- TX_FAR _PokemartNotEnoughMoneyText
- db "@"
-
-PokemartItemBagFullText:
- TX_FAR _PokemartItemBagFullText
- db "@"
-
-PokemonSellingGreetingText:
- TX_FAR _PokemonSellingGreetingText
- db "@"
-
-PokemartTellSellPriceText:
- TX_FAR _PokemartTellSellPriceText
- db "@"
-
-PokemartItemBagEmptyText:
- TX_FAR _PokemartItemBagEmptyText
- db "@"
-
-PokemartUnsellableItemText:
- TX_FAR _PokemartUnsellableItemText
- db "@"
-
-PokemartThankYouText:
- TX_FAR _PokemartThankYouText
- db "@"
-
-PokemartAnythingElseText:
- TX_FAR _PokemartAnythingElseText
- db "@"
diff --git a/engine/print_waiting_text.asm b/engine/print_waiting_text.asm
deleted file mode 100644
index 7a95da2a..00000000
--- a/engine/print_waiting_text.asm
+++ /dev/null
@@ -1,20 +0,0 @@
-PrintWaitingText:
- coord hl, 3, 10
- ld b, $1
- ld c, $b
- ld a, [wIsInBattle]
- and a
- jr z, .asm_4c17
- call TextBoxBorder
- jr .asm_4c1a
-.asm_4c17
- call CableClub_TextBoxBorder
-.asm_4c1a
- coord hl, 4, 11
- ld de, WaitingText
- call PlaceString
- ld c, 50
- jp DelayFrames
-
-WaitingText:
- db "Waiting...!@"
diff --git a/engine/save.asm b/engine/save.asm
deleted file mode 100755
index 97935dbb..00000000
--- a/engine/save.asm
+++ /dev/null
@@ -1,708 +0,0 @@
-LoadSAV:
-;(if carry -> write
-;"the file data is destroyed")
- call ClearScreen
- call LoadFontTilePatterns
- call LoadTextBoxTilePatterns
- call LoadSAV0
- jr c, .badsum
- call LoadSAV1
- jr c, .badsum
- call LoadSAV2
- jr c, .badsum
- ld a, $2 ; good checksum
- jr .goodsum
-.badsum
- ld hl, wd730
- push hl
- set 6, [hl]
- ld hl, FileDataDestroyedText
- call PrintText
- ld c, 100
- call DelayFrames
- pop hl
- res 6, [hl]
- ld a, $1 ; bad checksum
-.goodsum
- ld [wSaveFileStatus], a
- ret
-
-FileDataDestroyedText:
- TX_FAR _FileDataDestroyedText
- db "@"
-
-LoadSAV0:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, sPlayerName ; hero name located in SRAM
- ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV
- call SAVCheckSum
- ld c, a
- ld a, [sMainDataCheckSum] ; SAV's checksum
- cp c
- jp z, .checkSumsMatched
-
-; If the computed checksum didn't match the saved on, try again.
- ld hl, sPlayerName
- ld bc, sMainDataCheckSum - sPlayerName
- call SAVCheckSum
- ld c, a
- ld a, [sMainDataCheckSum] ; SAV's checksum
- cp c
- jp nz, SAVBadCheckSum
-
-.checkSumsMatched
- ld hl, sPlayerName
- ld de, wPlayerName
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, sMainData
- ld de, wMainDataStart
- ld bc, wMainDataEnd - wMainDataStart
- call CopyData
- ld hl, wCurMapTileset
- set 7, [hl]
- ld hl, sSpriteData
- ld de, wSpriteDataStart
- ld bc, wSpriteDataEnd - wSpriteDataStart
- call CopyData
- ld a, [sTilesetType]
- ld [hTilesetType], a
- ld hl, sCurBoxData
- ld de, wBoxDataStart
- ld bc, wBoxDataEnd - wBoxDataStart
- call CopyData
- and a
- jp SAVGoodChecksum
-
-LoadSAV1:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, sPlayerName ; hero name located in SRAM
- ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV
- call SAVCheckSum
- ld c, a
- ld a, [sMainDataCheckSum] ; SAV's checksum
- cp c
- jr nz, SAVBadCheckSum
- ld hl, sCurBoxData
- ld de, wBoxDataStart
- ld bc, wBoxDataEnd - wBoxDataStart
- call CopyData
- and a
- jp SAVGoodChecksum
-
-LoadSAV2:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, sPlayerName ; hero name located in SRAM
- ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV
- call SAVCheckSum
- ld c, a
- ld a, [sMainDataCheckSum] ; SAV's checksum
- cp c
- jp nz, SAVBadCheckSum
- ld hl, sPartyData
- ld de, wPartyDataStart
- ld bc, wPartyDataEnd - wPartyDataStart
- call CopyData
- ld hl, sMainData
- ld de, wPokedexOwned
- ld bc, wPokedexSeenEnd - wPokedexOwned
- call CopyData
- and a
- jp SAVGoodChecksum
-
-SAVBadCheckSum:
- scf
-
-SAVGoodChecksum:
- ld a, $0
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-LoadSAVIgnoreBadCheckSum:
-; unused function that loads save data and ignores bad checksums
- call LoadSAV0
- call LoadSAV1
- jp LoadSAV2
-
-SaveSAV:
- callba PrintSaveScreenText
- ld hl, WouldYouLikeToSaveText
- call SaveSAVConfirm
- and a ;|0 = Yes|1 = No|
- ret nz
- ld a, [wSaveFileStatus]
- dec a
- jr z, .save
- call SAVCheckRandomID
- jr z, .save
- ld hl, OlderFileWillBeErasedText
- call SaveSAVConfirm
- and a
- ret nz
-.save
- call SaveSAVtoSRAM
- coord hl, 1, 13
- lb bc, 4, 18
- call ClearScreenArea
- coord hl, 1, 14
- ld de, NowSavingString
- call PlaceString
- ld c, 120
- call DelayFrames
- ld hl, GameSavedText
- call PrintText
- ld a, SFX_SAVE
- call PlaySoundWaitForCurrent
- call WaitForSoundToFinish
- ld c, 30
- jp DelayFrames
-
-NowSavingString:
- db "Now saving...@"
-
-SaveSAVConfirm:
- call PrintText
- coord hl, 0, 7
- lb bc, 8, 1
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID ; yes/no menu
- ld a, [wCurrentMenuItem]
- ret
-
-WouldYouLikeToSaveText:
- TX_FAR _WouldYouLikeToSaveText
- db "@"
-
-GameSavedText:
- TX_FAR _GameSavedText
- db "@"
-
-OlderFileWillBeErasedText:
- TX_FAR _OlderFileWillBeErasedText
- db "@"
-
-SaveSAVtoSRAM0:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, wPlayerName
- ld de, sPlayerName
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wMainDataStart
- ld de, sMainData
- ld bc, wMainDataEnd - wMainDataStart
- call CopyData
- ld hl, wSpriteDataStart
- ld de, sSpriteData
- ld bc, wSpriteDataEnd - wSpriteDataStart
- call CopyData
- ld hl, wBoxDataStart
- ld de, sCurBoxData
- ld bc, wBoxDataEnd - wBoxDataStart
- call CopyData
- ld a, [hTilesetType]
- ld [sTilesetType], a
- ld hl, sPlayerName
- ld bc, sMainDataCheckSum - sPlayerName
- call SAVCheckSum
- ld [sMainDataCheckSum], a
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-SaveSAVtoSRAM1:
-; stored pokémon
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, wBoxDataStart
- ld de, sCurBoxData
- ld bc, wBoxDataEnd - wBoxDataStart
- call CopyData
- ld hl, sPlayerName
- ld bc, sMainDataCheckSum - sPlayerName
- call SAVCheckSum
- ld [sMainDataCheckSum], a
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-SaveSAVtoSRAM2:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld hl, wPartyDataStart
- ld de, sPartyData
- ld bc, wPartyDataEnd - wPartyDataStart
- call CopyData
- ld hl, wPokedexOwned ; pokédex only
- ld de, sMainData
- ld bc, wPokedexSeenEnd - wPokedexOwned
- call CopyData
- ld hl, sPlayerName
- ld bc, sMainDataCheckSum - sPlayerName
- call SAVCheckSum
- ld [sMainDataCheckSum], a
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-SaveSAVtoSRAM:
- ld a, $2
- ld [wSaveFileStatus], a
- call SaveSAVtoSRAM0
- call SaveSAVtoSRAM1
- jp SaveSAVtoSRAM2
-
-SAVCheckSum:
-;Check Sum (result[1 byte] is complemented)
- ld d, 0
-.loop
- ld a, [hli]
- add d
- ld d, a
- dec bc
- ld a, b
- or c
- jr nz, .loop
- ld a, d
- cpl
- ret
-
-CalcIndividualBoxCheckSums:
- ld hl, sBox1 ; sBox7
- ld de, sBank2IndividualBoxChecksums ; sBank3IndividualBoxChecksums
- ld b, NUM_BOXES / 2
-.loop
- push bc
- push de
- ld bc, wBoxDataEnd - wBoxDataStart
- call SAVCheckSum
- pop de
- ld [de], a
- inc de
- pop bc
- dec b
- jr nz, .loop
- ret
-
-GetBoxSRAMLocation:
-; in: a = box num
-; out: b = box SRAM bank, hl = pointer to start of box
- ld hl, BoxSRAMPointerTable
- ld a, [wCurrentBoxNum]
- and $7f
- cp NUM_BOXES / 2
- ld b, 2
- jr c, .next
- inc b
- sub NUM_BOXES / 2
-.next
- ld e, a
- ld d, 0
- add hl, de
- add hl, de
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ret
-
-BoxSRAMPointerTable:
- dw sBox1 ; sBox7
- dw sBox2 ; sBox8
- dw sBox3 ; sBox9
- dw sBox4 ; sBox10
- dw sBox5 ; sBox11
- dw sBox6 ; sBox12
-
-ChangeBox::
- ld hl, WhenYouChangeBoxText
- call PrintText
- call YesNoChoice
- ld a, [wCurrentMenuItem]
- and a
- ret nz ; return if No was chosen
- ld hl, wCurrentBoxNum
- bit 7, [hl] ; is it the first time player is changing the box?
- call z, EmptyAllSRAMBoxes ; if so, empty all boxes in SRAM
- call DisplayChangeBoxMenu
- call UpdateSprites
- ld hl, hFlags_0xFFF6
- set 1, [hl]
- call HandleMenuInput
- ld hl, hFlags_0xFFF6
- res 1, [hl]
- bit 1, a ; pressed b
- ret nz
- call GetBoxSRAMLocation
- ld e, l
- ld d, h
- ld hl, wBoxDataStart
- call CopyBoxToOrFromSRAM ; copy old box from WRAM to SRAM
- ld a, [wCurrentMenuItem]
- set 7, a
- ld [wCurrentBoxNum], a
- call GetBoxSRAMLocation
- ld de, wBoxDataStart
- call CopyBoxToOrFromSRAM ; copy new box from SRAM to WRAM
- ld hl, wMapTextPtr
- ld de, wChangeBoxSavedMapTextPointer
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- call RestoreMapTextPointer
- call SaveSAVtoSRAM
- ld hl, wChangeBoxSavedMapTextPointer
- call SetMapTextPointer
- ld a, SFX_SAVE
- call PlaySoundWaitForCurrent
- call WaitForSoundToFinish
- ret
-
-WhenYouChangeBoxText:
- TX_FAR _WhenYouChangeBoxText
- db "@"
-
-CopyBoxToOrFromSRAM:
-; copy an entire box from hl to de with b as the SRAM bank
- push hl
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld a, b
- ld [MBC1SRamBank], a
- ld bc, wBoxDataEnd - wBoxDataStart
- call CopyData
- pop hl
-
-; mark the memory that the box was copied from as am empty box
- xor a
- ld [hli], a
- dec a
- ld [hl], a
-
- ld hl, sBox1 ; sBox7
- ld bc, sBank2AllBoxesChecksum - sBox1
- call SAVCheckSum
- ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum
- call CalcIndividualBoxCheckSums
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-DisplayChangeBoxMenu:
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 11
- ld [wMaxMenuItem], a
- ld a, 1
- ld [wTopMenuItemY], a
- ld a, 12
- ld [wTopMenuItemX], a
- xor a
- ld [wMenuWatchMovingOutOfBounds], a
- ld a, [wCurrentBoxNum]
- and $7f
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- coord hl, 0, 0
- ld b, 2
- ld c, 9
- call TextBoxBorder
- ld hl, ChooseABoxText
- call PrintText
- coord hl, 11, 0
- ld b, 12
- ld c, 7
- call TextBoxBorder
- ld hl, hFlags_0xFFF6
- set 2, [hl]
- ld de, BoxNames
- coord hl, 13, 1
- call PlaceString
- ld hl, hFlags_0xFFF6
- res 2, [hl]
- ld a, [wCurrentBoxNum]
- and $7f
- cp 9
- jr c, .singleDigitBoxNum
- sub 9
- coord hl, 8, 2
- ld [hl], "1"
- add "0"
- jr .next
-.singleDigitBoxNum
- add "1"
-.next
- Coorda 9, 2
- coord hl, 1, 2
- ld de, BoxNoText
- call PlaceString
- call GetMonCountsForAllBoxes
- coord hl, 18, 1
- ld de, wBoxMonCounts
- ld bc, SCREEN_WIDTH
- ld a, $c
-.loop
- push af
- ld a, [de]
- and a ; is the box empty?
- jr z, .skipPlacingPokeball
- ld [hl], $78 ; place pokeball tile next to box name if box not empty
-.skipPlacingPokeball
- add hl, bc
- inc de
- pop af
- dec a
- jr nz, .loop
- ld a, 1
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-ChooseABoxText:
- TX_FAR _ChooseABoxText
- db "@"
-
-BoxNames:
- db "BOX 1"
- next "BOX 2"
- next "BOX 3"
- next "BOX 4"
- next "BOX 5"
- next "BOX 6"
- next "BOX 7"
- next "BOX 8"
- next "BOX 9"
- next "BOX10"
- next "BOX11"
- next "BOX12@"
-
-BoxNoText:
- db "BOX No.@"
-
-EmptyAllSRAMBoxes:
-; marks all boxes in SRAM as empty (initialisation for the first time the
-; player changes the box)
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld a, 2
- ld [MBC1SRamBank], a
- call EmptySRAMBoxesInBank
- ld a, 3
- ld [MBC1SRamBank], a
- call EmptySRAMBoxesInBank
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-EmptySRAMBoxesInBank:
-; marks every box in the current SRAM bank as empty
- ld hl, sBox1 ; sBox7
- call EmptySRAMBox
- ld hl, sBox2 ; sBox8
- call EmptySRAMBox
- ld hl, sBox3 ; sBox9
- call EmptySRAMBox
- ld hl, sBox4 ; sBox10
- call EmptySRAMBox
- ld hl, sBox5 ; sBox11
- call EmptySRAMBox
- ld hl, sBox6 ; sBox12
- call EmptySRAMBox
- ld hl, sBox1 ; sBox7
- ld bc, sBank2AllBoxesChecksum - sBox1
- call SAVCheckSum
- ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum
- call CalcIndividualBoxCheckSums
- ret
-
-EmptySRAMBox:
- xor a
- ld [hli], a
- dec a
- ld [hl], a
- ret
-
-GetMonCountsForAllBoxes:
- ld hl, wBoxMonCounts
- push hl
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- ld a, $2
- ld [MBC1SRamBank], a
- call GetMonCountsForBoxesInBank
- ld a, $3
- ld [MBC1SRamBank], a
- call GetMonCountsForBoxesInBank
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- pop hl
-
-; copy the count for the current box from WRAM
- ld a, [wCurrentBoxNum]
- and $7f
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [wNumInBox]
- ld [hl], a
-
- ret
-
-GetMonCountsForBoxesInBank:
- ld a, [sBox1] ; sBox7
- ld [hli], a
- ld a, [sBox2] ; sBox8
- ld [hli], a
- ld a, [sBox3] ; sBox9
- ld [hli], a
- ld a, [sBox4] ; sBox10
- ld [hli], a
- ld a, [sBox5] ; sBox11
- ld [hli], a
- ld a, [sBox6] ; sBox12
- ld [hli], a
- ret
-
-SAVCheckRandomID:
-;checks if Sav file is the same by checking player's name 1st letter ($a598)
-; and the two random numbers generated at game beginning
-;(which are stored at wPlayerID)s
- ld a, $0a
- ld [MBC1SRamEnable], a
- ld a, $01
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamBank], a
- ld a, [sPlayerName]
- and a
- jr z, .next
- ld hl, sPlayerName
- ld bc, sMainDataCheckSum - sPlayerName
- call SAVCheckSum
- ld c, a
- ld a, [sMainDataCheckSum]
- cp c
- jr nz, .next
- ld hl, sMainData + (wPlayerID - wMainDataStart) ; player ID
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, [wPlayerID]
- cp l
- jr nz, .next
- ld a, [wPlayerID + 1]
- cp h
-.next
- ld a, $00
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-SaveHallOfFameTeams:
- ld a, [wNumHoFTeams]
- dec a
- cp HOF_TEAM_CAPACITY
- jr nc, .shiftHOFTeams
- ld hl, sHallOfFame
- ld bc, HOF_TEAM
- call AddNTimes
- ld e, l
- ld d, h
- ld hl, wHallOfFame
- ld bc, HOF_TEAM
- jr HallOfFame_Copy
-
-.shiftHOFTeams
-; if the space designated for HOF teams is full, then shift all HOF teams to the next slot, making space for the new HOF team
-; this deletes the last HOF team though
- ld hl, sHallOfFame + HOF_TEAM
- ld de, sHallOfFame
- ld bc, HOF_TEAM * (HOF_TEAM_CAPACITY - 1)
- call HallOfFame_Copy
- ld hl, wHallOfFame
- ld de, sHallOfFame + HOF_TEAM * (HOF_TEAM_CAPACITY - 1)
- ld bc, HOF_TEAM
- jr HallOfFame_Copy
-
-LoadHallOfFameTeams:
- ld hl, sHallOfFame
- ld bc, HOF_TEAM
- ld a, [wHoFTeamIndex]
- call AddNTimes
- ld de, wHallOfFame
- ld bc, HOF_TEAM
- ; fallthrough
-
-HallOfFame_Copy:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- xor a
- ld [MBC1SRamBank], a
- call CopyData
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-ClearSAV:
- ld a, SRAM_ENABLE
- ld [MBC1SRamEnable], a
- ld a, $1
- ld [MBC1SRamBankingMode], a
- xor a
- call PadSRAM_FF
- ld a, $1
- call PadSRAM_FF
- ld a, $2
- call PadSRAM_FF
- ld a, $3
- call PadSRAM_FF
- xor a
- ld [MBC1SRamBankingMode], a
- ld [MBC1SRamEnable], a
- ret
-
-PadSRAM_FF:
- ld [MBC1SRamBank], a
- ld hl, $a000
- ld bc, $2000
- ld a, $ff
- jp FillMemory
diff --git a/engine/slot_machine.asm b/engine/slot_machine.asm
deleted file mode 100755
index 3a46687f..00000000
--- a/engine/slot_machine.asm
+++ /dev/null
@@ -1,892 +0,0 @@
-PromptUserToPlaySlots:
- call SaveScreenTilesToBuffer2
- ld a, BANK(DisplayTextIDInit)
- ld [wAutoTextBoxDrawingControl], a
- ld b, a
- ld hl, DisplayTextIDInit
- call Bankswitch
- ld hl, PlaySlotMachineText
- call PrintText
- call YesNoChoice
- ld a, [wCurrentMenuItem]
- and a
- jr nz, .done ; if player chose No
- dec a
- ld [wUpdateSpritesEnabled], a
- ld hl, wSlotMachineRerollCounter
- xor a
- ld [hli], a
- ld [hl], SMILE_BUBBLE
- predef EmotionBubble
- call GBPalWhiteOutWithDelay3
- call LoadSlotMachineTiles
- call LoadFontTilePatterns
- ld b, SET_PAL_SLOTS
- call RunPaletteCommand
- call GBPalNormal
- ld a, $e4
- ld [rOBP0], a
- ld hl, wd730
- set 6, [hl]
- xor a
- ld [wSlotMachineAllowMatchesCounter], a
- ld hl, wStoppingWhichSlotMachineWheel
- ld bc, $0014
- call FillMemory
- call MainSlotMachineLoop
- ld hl, wd730
- res 6, [hl]
- xor a
- ld [wSlotMachineAllowMatchesCounter], a
- call GBPalWhiteOutWithDelay3
- ld a, $1
- ld [wUpdateSpritesEnabled], a
- call RunDefaultPaletteCommand
- call ReloadMapSpriteTilePatterns
- call ReloadTilesetTilePatterns
-.done
- call LoadScreenTilesFromBuffer2
- call Delay3
- call GBPalNormal
- ld a, [wSlotMachineSavedROMBank]
- push af
- jp CloseTextDisplay
-
-PlaySlotMachineText:
- TX_FAR _PlaySlotMachineText
- db "@"
-
-MainSlotMachineLoop:
- call SlotMachine_PrintCreditCoins
- xor a
- ld hl, wPayoutCoins
- ld [hli], a
- ld [hl], a
- call SlotMachine_PrintPayoutCoins
- ld hl, BetHowManySlotMachineText
- call PrintText
- call SaveScreenTilesToBuffer1
-.loop
- ld a, A_BUTTON | B_BUTTON
- ld [wMenuWatchedKeys], a
- ld a, 2
- ld [wMaxMenuItem], a
- ld a, 12
- ld [wTopMenuItemY], a
- ld a, 15
- ld [wTopMenuItemX], a
- xor a
- ld [wCurrentMenuItem], a
- ld [wLastMenuItem], a
- ld [wMenuWatchMovingOutOfBounds], a
- coord hl, 14, 11
- ld b, 5
- ld c, 4
- call TextBoxBorder
- coord hl, 16, 12
- ld de, CoinMultiplierSlotMachineText
- call PlaceString
- call HandleMenuInput
- and B_BUTTON
- jp nz, LoadScreenTilesFromBuffer1
- ld a, [wCurrentMenuItem]
- ld b, a
- ld a, 3
- sub b
- ld [wSlotMachineBet], a
- ld hl, wPlayerCoins
- ld c, a
- ld a, [hli]
- and a
- jr nz, .skip1
- ld a, [hl]
- cp c
- jr nc, .skip1
- ld hl, NotEnoughCoinsSlotMachineText
- call PrintText
- jr .loop
-.skip1
- call LoadScreenTilesFromBuffer1
- call SlotMachine_SubtractBetFromPlayerCoins
- call SlotMachine_LightBalls
- call SlotMachine_SetFlags
- ld a, 4
- ld hl, wSlotMachineWheel1SlipCounter
- ld [hli], a
- ld [hli], a
- ld [hl], a
- call WaitForSoundToFinish
- ld a, SFX_SLOTS_NEW_SPIN
- call PlaySound
- ld hl, StartSlotMachineText
- call PrintText
- call SlotMachine_SpinWheels
- call SlotMachine_CheckForMatches
- ld hl, wPlayerCoins
- ld a, [hli]
- or [hl]
- jr nz, .skip2
- ld hl, OutOfCoinsSlotMachineText
- call PrintText
- ld c, 60
- jp DelayFrames
-.skip2
- ld hl, OneMoreGoSlotMachineText
- call PrintText
- coord hl, 14, 12
- lb bc, 13, 15
- xor a ; YES_NO_MENU
- ld [wTwoOptionMenuID], a
- ld a, TWO_OPTION_MENU
- ld [wTextBoxID], a
- call DisplayTextBoxID
- ld a, [wCurrentMenuItem]
- and a
- ret nz
- call SlotMachine_PutOutLitBalls
- jp MainSlotMachineLoop
-
-CoinMultiplierSlotMachineText:
- db "×3"
- next "×2"
- next "×1@"
-
-OutOfCoinsSlotMachineText:
- TX_FAR _OutOfCoinsSlotMachineText
- db "@"
-
-BetHowManySlotMachineText:
- TX_FAR _BetHowManySlotMachineText
- db "@"
-
-StartSlotMachineText:
- TX_FAR _StartSlotMachineText
- db "@"
-
-NotEnoughCoinsSlotMachineText:
- TX_FAR _NotEnoughCoinsSlotMachineText
- db "@"
-
-OneMoreGoSlotMachineText:
- TX_FAR _OneMoreGoSlotMachineText
- db "@"
-
-SlotMachine_SetFlags:
- ld hl, wSlotMachineFlags
- bit 7, [hl]
- ret nz
- ld a, [wSlotMachineAllowMatchesCounter]
- and a
- jr nz, .allowMatches
- call Random
- and a
- jr z, .setAllowMatchesCounter ; 1/256 (~0.4%) chance
- ld b, a
- ld a, [wSlotMachineSevenAndBarModeChance]
- cp b
- jr c, .allowSevenAndBarMatches
- ld a, 210
- cp b
- jr c, .allowMatches ; 55/256 (~21.5%) chance
- ld [hl], 0
- ret
-.allowMatches
- set 6, [hl]
- ret
-.setAllowMatchesCounter
- ld a, 60
- ld [wSlotMachineAllowMatchesCounter], a
- ret
-.allowSevenAndBarMatches
- set 7, [hl]
- ret
-
-SlotMachine_SpinWheels:
- ld c, 20
-.loop1
- push bc
- call SlotMachine_AnimWheel1
- call SlotMachine_AnimWheel2
- call SlotMachine_AnimWheel3
- ld c, 2
- call DelayFrames
- pop bc
- dec c
- jr nz, .loop1
- xor a
- ld [wStoppingWhichSlotMachineWheel], a
-.loop2
- call SlotMachine_HandleInputWhileWheelsSpin
- call SlotMachine_StopOrAnimWheel1
- call SlotMachine_StopOrAnimWheel2
- call SlotMachine_StopOrAnimWheel3
- ret c
- ld a, [wOnSGB]
- xor $1
- inc a
- ld c, a
- call DelayFrames
- jr .loop2
-
-; Note that the wheels can only stop when a symbol is centred in the wheel
-; and thus 3 full symbols rather than 2 full symbols and 2 half symbols are
-; visible. The 3 functions below ensure this by checking if the wheel offset
-; is even before stopping the wheel.
-
-SlotMachine_StopOrAnimWheel1:
- ld a, [wStoppingWhichSlotMachineWheel]
- cp 1
- jr c, .animWheel
- ld de, wSlotMachineWheel1Offset
- ld a, [de]
- rra
- jr nc, .animWheel ; check that a symbol is centred in the wheel
- ld hl, wSlotMachineWheel1SlipCounter
- ld a, [hl]
- and a
- ret z
- dec [hl]
- call SlotMachine_StopWheel1Early
- ret nz
-.animWheel
- jp SlotMachine_AnimWheel1
-
-SlotMachine_StopOrAnimWheel2:
- ld a, [wStoppingWhichSlotMachineWheel]
- cp 2
- jr c, .animWheel
- ld de, wSlotMachineWheel2Offset
- ld a, [de]
- rra
- jr nc, .animWheel ; check that a symbol is centred in the wheel
- ld hl, wSlotMachineWheel2SlipCounter
- ld a, [hl]
- and a
- ret z
- dec [hl]
- call SlotMachine_StopWheel2Early
- ret z
-.animWheel
- jp SlotMachine_AnimWheel2
-
-SlotMachine_StopOrAnimWheel3:
- ld a, [wStoppingWhichSlotMachineWheel]
- cp 3
- jr c, .animWheel
- ld de, wSlotMachineWheel3Offset
- ld a, [de]
- rra
- jr nc, .animWheel ; check that a symbol is centred in the wheel
-; wheel 3 stops as soon as possible
- scf
- ret
-.animWheel
- call SlotMachine_AnimWheel3
- and a
- ret
-
-SlotMachine_StopWheel1Early:
- call SlotMachine_GetWheel1Tiles
- ld hl, wSlotMachineWheel1BottomTile
- ld a, [wSlotMachineFlags]
- and $80
- jr nz, .sevenAndBarMode
-; Stop early if the middle symbol is not a cherry.
- inc hl
- ld a, [hl]
- cp SLOTSCHERRY >> 8
- jr nz, .stopWheel
- ret
-; It looks like this was intended to make the wheel stop when a 7 symbol was
-; visible, but it has a bug and so the wheel stops randomly.
-.sevenAndBarMode
- ld c, $3
-.loop
- ld a, [hli]
- cp SLOTS7 >> 8
- jr c, .stopWheel ; condition never true
- dec c
- jr nz, .loop
- ret
-.stopWheel
- inc a
- ld hl, wSlotMachineWheel1SlipCounter
- ld [hl], 0
- ret
-
-SlotMachine_StopWheel2Early:
- call SlotMachine_GetWheel2Tiles
- ld a, [wSlotMachineFlags]
- and $80
- jr nz, .sevenAndBarMode
-; Stop early if any symbols are lined up in the first two wheels.
- call SlotMachine_FindWheel1Wheel2Matches
- ret nz
- jr .stopWheel
-; Stop early if two 7 symbols or two bar symbols are lined up in the first two
-; wheels OR if no symbols are lined up and the bottom symbol in wheel 2 is a
-; 7 symbol or bar symbol. The second part could be a bug or a way to reduce the
-; player's odds.
-.sevenAndBarMode
- call SlotMachine_FindWheel1Wheel2Matches
- ld a, [de]
- cp (SLOTSBAR >> 8) + 1
- ret nc
-.stopWheel
- xor a
- ld [wSlotMachineWheel2SlipCounter], a
- ret
-
-SlotMachine_FindWheel1Wheel2Matches:
-; return whether wheel 1 and wheel 2's current positions allow a match (given
-; that wheel 3 stops in a good position) in Z
- ld hl, wSlotMachineWheel1BottomTile
- ld de, wSlotMachineWheel2BottomTile
- ld a, [de]
- cp [hl] ; wheel 1 bottom, wheel 2 bottom
- ret z
- inc de
- ld a, [de]
- cp [hl] ; wheel 1 bottom, wheel 2 middle
- ret z
- inc hl
- cp [hl] ; wheel 1 middle, wheel 2 middle
- ret z
- inc hl
- cp [hl] ; wheel 1 top, wheel 2 middle
- ret z
- inc de
- ld a, [de]
- cp [hl] ; wheel 1 top, wheel 2 top
- ret z
- dec de
- dec de
- ret
-
-SlotMachine_CheckForMatches:
- call SlotMachine_GetWheel3Tiles
- ld a, [wSlotMachineBet]
- cp 2
- jr z, .checkMatchesFor2CoinBet
- cp 1
- jr z, .checkMatchFor1CoinBet
-; 3 coin bet allows diagonal matches (plus the matches for 1/2 coin bets)
- ld hl, wSlotMachineWheel1BottomTile
- ld de, wSlotMachineWheel2MiddleTile
- ld bc, wSlotMachineWheel3TopTile
- call SlotMachine_CheckForMatch
- jp z, .foundMatch
- ld hl, wSlotMachineWheel1TopTile
- ld de, wSlotMachineWheel2MiddleTile
- ld bc, wSlotMachineWheel3BottomTile
- call SlotMachine_CheckForMatch
- jr z, .foundMatch
-; 2 coin bet allows top/bottom horizontal matches (plus the match for a 1 coin bet)
-.checkMatchesFor2CoinBet
- ld hl, wSlotMachineWheel1TopTile
- ld de, wSlotMachineWheel2TopTile
- ld bc, wSlotMachineWheel3TopTile
- call SlotMachine_CheckForMatch
- jr z, .foundMatch
- ld hl, wSlotMachineWheel1BottomTile
- ld de, wSlotMachineWheel2BottomTile
- ld bc, wSlotMachineWheel3BottomTile
- call SlotMachine_CheckForMatch
- jr z, .foundMatch
-; 1 coin bet only allows a middle horizontal match
-.checkMatchFor1CoinBet
- ld hl, wSlotMachineWheel1MiddleTile
- ld de, wSlotMachineWheel2MiddleTile
- ld bc, wSlotMachineWheel3MiddleTile
- call SlotMachine_CheckForMatch
- jr z, .foundMatch
- ld a, [wSlotMachineFlags]
- and $c0
- jr z, .noMatch
- ld hl, wSlotMachineRerollCounter
- dec [hl]
- jr nz, .rollWheel3DownByOneSymbol
-.noMatch
- ld hl, NotThisTimeText
- call PrintText
-.done
- xor a
- ld [wMuteAudioAndPauseMusic], a
- ret
-.rollWheel3DownByOneSymbol
- call SlotMachine_AnimWheel3
- call DelayFrame
- call SlotMachine_AnimWheel3
- call DelayFrame
- jp SlotMachine_CheckForMatches
-.foundMatch
- ld a, [wSlotMachineFlags]
- and $c0
- jr z, .rollWheel3DownByOneSymbol ; roll wheel if player isn't allowed to win
- and $80
- jr nz, .acceptMatch
-; if 7/bar matches aren't enabled and the match was a 7/bar symbol, roll wheel
- ld a, [hl]
- cp (SLOTSBAR >> 8) + 1
- jr c, .rollWheel3DownByOneSymbol
-.acceptMatch
- ld a, [hl]
- sub $2
- ld [wSlotMachineWinningSymbol], a
- ld hl, SlotRewardPointers
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- push de
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, wcf4b
- ld bc, 4
- call CopyData
- pop hl
- ld de, .flashScreenLoop
- push de
- jp hl
-
-.flashScreenLoop
- ld a, [rBGP]
- xor $40
- ld [rBGP], a
- ld c, 5
- call DelayFrames
- dec b
- jr nz, .flashScreenLoop
- ld hl, wPayoutCoins
- ld [hl], d
- inc hl
- ld [hl], e
- call SlotMachine_PrintPayoutCoins
- ld hl, SymbolLinedUpSlotMachineText
- call PrintText
- call WaitForTextScrollButtonPress
- call SlotMachine_PayCoinsToPlayer
- call SlotMachine_PrintPayoutCoins
- ld a, $e4
- ld [rOBP0], a
- jp .done
-
-SymbolLinedUpSlotMachineText:
- TX_ASM
- push bc
- call SlotMachine_PrintWinningSymbol
- ld hl, LinedUpText
- pop bc
- inc bc
- inc bc
- inc bc
- inc bc
- ret
-
-LinedUpText:
- TX_FAR _LinedUpText
- db "@"
-
-SlotRewardPointers:
- dw SlotReward300Func
- dw SlotReward300Text
- dw SlotReward100Func
- dw SlotReward100Text
- dw SlotReward8Func
- dw SlotReward8Text
- dw SlotReward15Func
- dw SlotReward15Text
- dw SlotReward15Func
- dw SlotReward15Text
- dw SlotReward15Func
- dw SlotReward15Text
-
-SlotReward300Text:
- db "300@"
-
-SlotReward100Text:
- db "100@"
-
-SlotReward8Text:
- db "8@"
-
-SlotReward15Text:
- db "15@"
-
-NotThisTimeText:
- TX_FAR _NotThisTimeText
- db "@"
-
-; compares the slot machine tiles at bc, de, and hl
-SlotMachine_CheckForMatch:
- ld a, [de]
- cp [hl]
- ret nz
- ld a, [bc]
- cp [hl]
- ret
-
-SlotMachine_GetWheel3Tiles:
- ld de, wSlotMachineWheel3BottomTile
- ld hl, SlotMachineWheel3
- ld a, [wSlotMachineWheel3Offset]
- call SlotMachine_GetWheelTiles
-
-SlotMachine_GetWheel2Tiles:
- ld de, wSlotMachineWheel2BottomTile
- ld hl, SlotMachineWheel2
- ld a, [wSlotMachineWheel2Offset]
- call SlotMachine_GetWheelTiles
-
-SlotMachine_GetWheel1Tiles:
- ld de, wSlotMachineWheel1BottomTile
- ld hl, SlotMachineWheel1
- ld a, [wSlotMachineWheel1Offset]
-
-SlotMachine_GetWheelTiles:
- ld c, a
- ld b, 0
- add hl, bc
- ld c, 3
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- inc hl
- dec c
- jr nz, .loop
- ret
-
-SlotReward8Func:
- ld hl, wSlotMachineAllowMatchesCounter
- ld a, [hl]
- and a
- jr z, .skip
- dec [hl]
-.skip
- ld b, $2
- ld de, 8
- ret
-
-SlotReward15Func:
- ld hl, wSlotMachineAllowMatchesCounter
- ld a, [hl]
- and a
- jr z, .skip
- dec [hl]
-.skip
- ld b, $4
- ld de, 15
- ret
-
-SlotReward100Func:
- ld a, SFX_GET_KEY_ITEM
- call PlaySound
- xor a
- ld [wSlotMachineFlags], a
- ld b, $8
- ld de, 100
- ret
-
-SlotReward300Func:
- ld hl, YeahText
- call PrintText
- ld a, SFX_GET_ITEM_2
- call PlaySound
- call Random
- cp $80
- ld a, $0
- jr c, .skip
- ld [wSlotMachineFlags], a
-.skip
- ld [wSlotMachineAllowMatchesCounter], a
- ld b, $14
- ld de, 300
- ret
-
-YeahText:
- TX_FAR _YeahText
- TX_DELAY
- db "@"
-
-SlotMachine_PrintWinningSymbol:
-; prints winning symbol and down arrow in text box
- coord hl, 2, 14
- ld a, [wSlotMachineWinningSymbol]
- add $25
- ld [hli], a
- inc a
- ld [hld], a
- inc a
- ld de, -SCREEN_WIDTH
- add hl, de
- ld [hli], a
- inc a
- ld [hl], a
- coord hl, 18, 16
- ld [hl], "▼"
- ret
-
-SlotMachine_SubtractBetFromPlayerCoins:
- ld hl, wTempCoins2 + 1
- ld a, [wSlotMachineBet]
- ld [hld], a
- xor a
- ld [hli], a
- ld de, wPlayerCoins + 1
- ld c, $2
- predef SubBCDPredef
-
-SlotMachine_PrintCreditCoins:
- coord hl, 5, 1
- ld de, wPlayerCoins
- ld c, $2
- jp PrintBCDNumber
-
-SlotMachine_PrintPayoutCoins:
- coord hl, 11, 1
- ld de, wPayoutCoins
- lb bc, LEADING_ZEROES | 2, 4 ; 2 bytes, 4 digits
- jp PrintNumber
-
-SlotMachine_PayCoinsToPlayer:
- ld a, $1
- ld [wMuteAudioAndPauseMusic], a
- call WaitForSoundToFinish
-
-; Put 1 in the temp coins variable. This value is added to the player's coins
-; repeatedly so the player can watch the value go up 1 coin at a time.
- ld hl, wTempCoins1
- xor a
- ld [hli], a
- inc a
- ld [hl], a
-
- ld a, 5
- ld [wAnimCounter], a
-
-; Subtract 1 from the payout amount and add 1 to the player's coins each
-; iteration until the payout amount reaches 0.
-.loop
- ld a, [wPayoutCoins + 1]
- ld l, a
- ld a, [wPayoutCoins]
- ld h, a
- or l
- ret z
- ld de, -1
- add hl, de
- ld a, l
- ld [wPayoutCoins + 1], a
- ld a, h
- ld [wPayoutCoins], a
- ld hl, wTempCoins1 + 1
- ld de, wPlayerCoins + 1
- ld c, $2
- predef AddBCDPredef
- call SlotMachine_PrintCreditCoins
- call SlotMachine_PrintPayoutCoins
- ld a, SFX_SLOTS_REWARD
- call PlaySound
- ld a, [wAnimCounter]
- dec a
- jr nz, .skip1
- ld a, [rOBP0]
- xor $40 ; make the slot wheel symbols flash
- ld [rOBP0], a
- ld a, 5
-.skip1
- ld [wAnimCounter], a
- ld a, [wSlotMachineWinningSymbol]
- cp (SLOTSBAR >> 8) + 1
- ld c, 8
- jr nc, .skip2
- srl c ; c = 4 (make the the coins transfer faster if the symbol was 7 or bar)
-.skip2
- call DelayFrames
- jr .loop
-
-SlotMachine_PutOutLitBalls:
- ld a, $23
- ld [wNewSlotMachineBallTile], a
- jr SlotMachine_UpdateThreeCoinBallTiles
-
-SlotMachine_LightBalls:
- ld a, $14
- ld [wNewSlotMachineBallTile], a
- ld a, [wSlotMachineBet]
- dec a
- jr z, SlotMachine_UpdateOneCoinBallTiles
- dec a
- jr z, SlotMachine_UpdateTwoCoinBallTiles
-
-SlotMachine_UpdateThreeCoinBallTiles:
- coord hl, 3, 2
- call SlotMachine_UpdateBallTiles
- coord hl, 3, 10
- call SlotMachine_UpdateBallTiles
-
-SlotMachine_UpdateTwoCoinBallTiles:
- coord hl, 3, 4
- call SlotMachine_UpdateBallTiles
- coord hl, 3, 8
- call SlotMachine_UpdateBallTiles
-
-SlotMachine_UpdateOneCoinBallTiles:
- coord hl, 3, 6
-
-SlotMachine_UpdateBallTiles:
- ld a, [wNewSlotMachineBallTile]
- ld [hl], a
- ld bc, 13
- add hl, bc
- ld [hl], a
- ld bc, 7
- add hl, bc
- inc a
- ld [hl], a
- ld bc, 13
- add hl, bc
- ld [hl], a
- ret
-
-SlotMachine_AnimWheel1:
- ld bc, SlotMachineWheel1
- ld de, wSlotMachineWheel1Offset
- ld hl, wOAMBuffer
- ld a, $30
- ld [wBaseCoordX], a
- jr SlotMachine_AnimWheel
-
-SlotMachine_AnimWheel2:
- ld bc, SlotMachineWheel2
- ld de, wSlotMachineWheel2Offset
- ld hl, wOAMBuffer + $30
- ld a, $50
- ld [wBaseCoordX], a
- jr SlotMachine_AnimWheel
-
-SlotMachine_AnimWheel3:
- ld bc, SlotMachineWheel3
- ld de, wSlotMachineWheel3Offset
- ld hl, wOAMBuffer + $60
- ld a, $70
- ld [wBaseCoordX], a
-
-SlotMachine_AnimWheel:
- ld a, $58
- ld [wBaseCoordY], a
- push de
- ld a, [de]
- ld d, b
- add c
- ld e, a
- jr nc, .loop
- inc d
-.loop
- ld a, [wBaseCoordY]
- ld [hli], a
- ld a, [wBaseCoordX]
- ld [hli], a
- ld a, [de]
- ld [hli], a
- ld a, $80
- ld [hli], a
- ld a, [wBaseCoordY]
- ld [hli], a
- ld a, [wBaseCoordX]
- add $8
- ld [hli], a
- ld a, [de]
- inc a
- ld [hli], a
- ld a, $80
- ld [hli], a
- inc de
- ld a, [wBaseCoordY]
- sub $8
- ld [wBaseCoordY], a
- cp $28
- jr nz, .loop
- pop de
- ld a, [de]
- inc a ; advance the offset so that the wheel animates
- cp 30
- jr nz, .skip
- xor a ; wrap around to 0 when the offset reaches 30
-.skip
- ld [de], a
- ret
-
-SlotMachine_HandleInputWhileWheelsSpin:
- call DelayFrame
- call JoypadLowSensitivity
- ld a, [hJoy5]
- and A_BUTTON
- ret z
- ld hl, wStoppingWhichSlotMachineWheel
- ld a, [hl]
- dec a
- ld de, wSlotMachineWheel1SlipCounter
- jr z, .skip
- dec a
- ld de, wSlotMachineWheel2SlipCounter
- jr z, .skip
-.loop
- inc [hl]
- ld a, SFX_SLOTS_STOP_WHEEL
- jp PlaySound
-.skip
- ld a, [de]
- and a
- ret nz
- jr .loop
-
-LoadSlotMachineTiles:
- call DisableLCD
- ld hl, SlotMachineTiles2
- ld de, vChars0
- ld bc, $1c0
- ld a, BANK(SlotMachineTiles2)
- call FarCopyData2
- ld hl, SlotMachineTiles1
- ld de, vChars2
- ld bc, $250
- ld a, BANK(SlotMachineTiles1)
- call FarCopyData2
- ld hl, SlotMachineTiles2
- ld de, vChars2 + $250
- ld bc, $1c0
- ld a, BANK(SlotMachineTiles2)
- call FarCopyData2
- ld hl, SlotMachineMap
- coord de, 0, 0
- ld bc, SlotMachineMapEnd - SlotMachineMap
- call CopyData
- call EnableLCD
- ld hl, wSlotMachineWheel1Offset
- ld a, $1c
- ld [hli], a
- ld [hli], a
- ld [hl], a
- call SlotMachine_AnimWheel1
- call SlotMachine_AnimWheel2
- jp SlotMachine_AnimWheel3
-
-SlotMachineMap:
- INCBIN "gfx/tilemaps/slotmachine.map"
-SlotMachineMapEnd:
-
-INCLUDE "data/slot_machine_wheels.asm"
-
-SlotMachineTiles1:
-IF DEF(_RED)
- INCBIN "gfx/red/slotmachine1.2bpp"
-ENDC
-IF DEF(_BLUE)
- INCBIN "gfx/blue/slotmachine1.2bpp"
-ENDC
diff --git a/engine/status_ailments.asm b/engine/status_ailments.asm
deleted file mode 100755
index 787533c4..00000000
--- a/engine/status_ailments.asm
+++ /dev/null
@@ -1,46 +0,0 @@
-PrintStatusAilment:
- ld a, [de]
- bit PSN, a
- jr nz, .psn
- bit BRN, a
- jr nz, .brn
- bit FRZ, a
- jr nz, .frz
- bit PAR, a
- jr nz, .par
- and SLP
- ret z
- ld a, "S"
- ld [hli], a
- ld a, "L"
- ld [hli], a
- ld [hl], "P"
- ret
-.psn
- ld a, "P"
- ld [hli], a
- ld a, "S"
- ld [hli], a
- ld [hl], "N"
- ret
-.brn
- ld a, "B"
- ld [hli], a
- ld a, "R"
- ld [hli], a
- ld [hl], "N"
- ret
-.frz
- ld a, "F"
- ld [hli], a
- ld a, "R"
- ld [hli], a
- ld [hl], "Z"
- ret
-.par
- ld a, "P"
- ld [hli], a
- ld a, "A"
- ld [hli], a
- ld [hl], "R"
- ret
diff --git a/engine/titlescreen.asm b/engine/titlescreen.asm
deleted file mode 100755
index 03a5832d..00000000
--- a/engine/titlescreen.asm
+++ /dev/null
@@ -1,403 +0,0 @@
-; copy text of fixed length NAME_LENGTH (like player name, rival name, mon names, ...)
-CopyFixedLengthText:
- ld bc, NAME_LENGTH
- jp CopyData
-
-SetDefaultNamesBeforeTitlescreen:
- ld hl, NintenText
- ld de, wPlayerName
- call CopyFixedLengthText
- ld hl, SonyText
- ld de, wRivalName
- call CopyFixedLengthText
- xor a
- ld [hWY], a
- ld [wLetterPrintingDelayFlags], a
- ld hl, wd732
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld a, BANK(Music_TitleScreen)
- ld [wAudioROMBank], a
- ld [wAudioSavedROMBank], a
-
-DisplayTitleScreen:
- call GBPalWhiteOut
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- xor a
- ld [hTilesetType], a
- ld [hSCX], a
- ld a, $40
- ld [hSCY], a
- ld a, $90
- ld [hWY], a
- call ClearScreen
- call DisableLCD
- call LoadFontTilePatterns
- ld hl, NintendoCopyrightLogoGraphics
- ld de, vTitleLogo2 + $100
- ld bc, $50
- ld a, BANK(NintendoCopyrightLogoGraphics)
- call FarCopyData2
- ld hl, GamefreakLogoGraphics
- ld de, vTitleLogo2 + $100 + $50
- ld bc, $90
- ld a, BANK(GamefreakLogoGraphics)
- call FarCopyData2
- ld hl, PokemonLogoGraphics
- ld de, vTitleLogo
- ld bc, $600
- ld a, BANK(PokemonLogoGraphics)
- call FarCopyData2 ; first chunk
- ld hl, PokemonLogoGraphics+$600
- ld de, vTitleLogo2
- ld bc, $100
- ld a, BANK(PokemonLogoGraphics)
- call FarCopyData2 ; second chunk
- ld hl, Version_GFX
- ld de, vChars2 + $600 - (Version_GFXEnd - Version_GFX - $50)
- ld bc, Version_GFXEnd - Version_GFX
- ld a, BANK(Version_GFX)
- call FarCopyDataDouble
- call ClearBothBGMaps
-
-; place tiles for pokemon logo (except for the last row)
- coord hl, 2, 1
- ld a, $80
- ld de, SCREEN_WIDTH
- ld c, 6
-.pokemonLogoTileLoop
- ld b, $10
- push hl
-.pokemonLogoTileRowLoop ; place tiles for one row
- ld [hli], a
- inc a
- dec b
- jr nz, .pokemonLogoTileRowLoop
- pop hl
- add hl, de
- dec c
- jr nz, .pokemonLogoTileLoop
-
-; place tiles for the last row of the pokemon logo
- coord hl, 2, 7
- ld a, $31
- ld b, $10
-.pokemonLogoLastTileRowLoop
- ld [hli], a
- inc a
- dec b
- jr nz, .pokemonLogoLastTileRowLoop
-
- call DrawPlayerCharacter
-
-; put a pokeball in the player's hand
- ld hl, wOAMBuffer + $28
- ld a, $74
- ld [hl], a
-
-; place tiles for title screen copyright
- coord hl, 2, 17
- ld de, .tileScreenCopyrightTiles
- ld b, $10
-.tileScreenCopyrightTilesLoop
- ld a, [de]
- ld [hli], a
- inc de
- dec b
- jr nz, .tileScreenCopyrightTilesLoop
-
- jr .next
-
-.tileScreenCopyrightTiles
- db $41,$42,$43,$42,$44,$42,$45,$46,$47,$48,$49,$4A,$4B,$4C,$4D,$4E ; ©'95.'96.'98 GAME FREAK inc.
-
-.next
- call SaveScreenTilesToBuffer2
- call LoadScreenTilesFromBuffer2
- call EnableLCD
-IF DEF(_RED)
- ld a, CHARMANDER ; which Pokemon to show first on the title screen
-ENDC
-IF DEF(_BLUE)
- ld a, SQUIRTLE ; which Pokemon to show first on the title screen
-ENDC
-
- ld [wTitleMonSpecies], a
- call LoadTitleMonSprite
- ld a, (vBGMap0 + $300) / $100
- call TitleScreenCopyTileMapToVRAM
- call SaveScreenTilesToBuffer1
- ld a, $40
- ld [hWY], a
- call LoadScreenTilesFromBuffer2
- ld a, vBGMap0 / $100
- call TitleScreenCopyTileMapToVRAM
- ld b, SET_PAL_TITLE_SCREEN
- call RunPaletteCommand
- call GBPalNormal
- ld a, %11100100
- ld [rOBP0], a
-
-; make pokemon logo bounce up and down
- ld bc, hSCY ; background scroll Y
- ld hl, .TitleScreenPokemonLogoYScrolls
-.bouncePokemonLogoLoop
- ld a, [hli]
- and a
- jr z, .finishedBouncingPokemonLogo
- ld d, a
- cp -3
- jr nz, .skipPlayingSound
- ld a, SFX_INTRO_CRASH
- call PlaySound
-.skipPlayingSound
- ld a, [hli]
- ld e, a
- call .ScrollTitleScreenPokemonLogo
- jr .bouncePokemonLogoLoop
-
-.TitleScreenPokemonLogoYScrolls:
-; Controls the bouncing effect of the Pokemon logo on the title screen
- db -4,16 ; y scroll amount, number of times to scroll
- db 3,4
- db -3,4
- db 2,2
- db -2,2
- db 1,2
- db -1,2
- db 0 ; terminate list with 0
-
-.ScrollTitleScreenPokemonLogo:
-; Scrolls the Pokemon logo on the title screen to create the bouncing effect
-; Scrolls d pixels e times
- call DelayFrame
- ld a, [bc] ; background scroll Y
- add d
- ld [bc], a
- dec e
- jr nz, .ScrollTitleScreenPokemonLogo
- ret
-
-.finishedBouncingPokemonLogo
- call LoadScreenTilesFromBuffer1
- ld c, 36
- call DelayFrames
- ld a, SFX_INTRO_WHOOSH
- call PlaySound
-
-; scroll game version in from the right
- call PrintGameVersionOnTitleScreen
- ld a, SCREEN_HEIGHT_PIXELS
- ld [hWY], a
- ld d, 144
-.scrollTitleScreenGameVersionLoop
- ld h, d
- ld l, 64
- call ScrollTitleScreenGameVersion
- ld h, 0
- ld l, 80
- call ScrollTitleScreenGameVersion
- ld a, d
- add 4
- ld d, a
- and a
- jr nz, .scrollTitleScreenGameVersionLoop
-
- ld a, vBGMap1 / $100
- call TitleScreenCopyTileMapToVRAM
- call LoadScreenTilesFromBuffer2
- call PrintGameVersionOnTitleScreen
- call Delay3
- call WaitForSoundToFinish
- ld a, MUSIC_TITLE_SCREEN
- ld [wNewSoundID], a
- call PlaySound
- xor a
- ld [wUnusedCC5B], a
-
-; Keep scrolling in new mons indefinitely until the user performs input.
-.awaitUserInterruptionLoop
- ld c, 200
- call CheckForUserInterruption
- jr c, .finishedWaiting
- call TitleScreenScrollInMon
- ld c, 1
- call CheckForUserInterruption
- jr c, .finishedWaiting
- callba TitleScreenAnimateBallIfStarterOut
- call TitleScreenPickNewMon
- jr .awaitUserInterruptionLoop
-
-.finishedWaiting
- ld a, [wTitleMonSpecies]
- call PlayCry
- call WaitForSoundToFinish
- call GBPalWhiteOutWithDelay3
- call ClearSprites
- xor a
- ld [hWY], a
- inc a
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- ld a, vBGMap0 / $100
- call TitleScreenCopyTileMapToVRAM
- ld a, vBGMap1 / $100
- call TitleScreenCopyTileMapToVRAM
- call Delay3
- call LoadGBPal
- ld a, [hJoyHeld]
- ld b, a
- and D_UP | SELECT | B_BUTTON
- cp D_UP | SELECT | B_BUTTON
- jp z, .doClearSaveDialogue
- jp MainMenu
-
-.doClearSaveDialogue
- jpba DoClearSaveDialogue
-
-TitleScreenPickNewMon:
- ld a, vBGMap0 / $100
- call TitleScreenCopyTileMapToVRAM
-
-.loop
-; Keep looping until a mon different from the current one is picked.
- call Random
- and $f
- ld c, a
- ld b, 0
- ld hl, TitleMons
- add hl, bc
- ld a, [hl]
- ld hl, wTitleMonSpecies
-
-; Can't be the same as before.
- cp [hl]
- jr z, .loop
-
- ld [hl], a
- call LoadTitleMonSprite
-
- ld a, $90
- ld [hWY], a
- ld d, 1 ; scroll out
- callba TitleScroll
- ret
-
-TitleScreenScrollInMon:
- ld d, 0 ; scroll in
- callba TitleScroll
- xor a
- ld [hWY], a
- ret
-
-ScrollTitleScreenGameVersion:
-.wait
- ld a, [rLY]
- cp l
- jr nz, .wait
-
- ld a, h
- ld [rSCX], a
-
-.wait2
- ld a, [rLY]
- cp h
- jr z, .wait2
- ret
-
-DrawPlayerCharacter:
- ld hl, PlayerCharacterTitleGraphics
- ld de, vSprites
- ld bc, PlayerCharacterTitleGraphicsEnd - PlayerCharacterTitleGraphics
- ld a, BANK(PlayerCharacterTitleGraphics)
- call FarCopyData2
- call ClearSprites
- xor a
- ld [wPlayerCharacterOAMTile], a
- ld hl, wOAMBuffer
- ld de, $605a
- ld b, 7
-.loop
- push de
- ld c, 5
-.innerLoop
- ld a, d
- ld [hli], a ; Y
- ld a, e
- ld [hli], a ; X
- add 8
- ld e, a
- ld a, [wPlayerCharacterOAMTile]
- ld [hli], a ; tile
- inc a
- ld [wPlayerCharacterOAMTile], a
- inc hl
- dec c
- jr nz, .innerLoop
- pop de
- ld a, 8
- add d
- ld d, a
- dec b
- jr nz, .loop
- ret
-
-ClearBothBGMaps:
- ld hl, vBGMap0
- ld bc, $400 * 2
- ld a, " "
- jp FillMemory
-
-LoadTitleMonSprite:
- ld [wcf91], a
- ld [wd0b5], a
- coord hl, 5, 10
- call GetMonHeader
- jp LoadFrontSpriteByMonIndex
-
-TitleScreenCopyTileMapToVRAM:
- ld [H_AUTOBGTRANSFERDEST + 1], a
- jp Delay3
-
-LoadCopyrightAndTextBoxTiles:
- xor a
- ld [hWY], a
- call ClearScreen
- call LoadTextBoxTilePatterns
-
-LoadCopyrightTiles:
- ld de, NintendoCopyrightLogoGraphics
- ld hl, vChars2 + $600
- lb bc, BANK(NintendoCopyrightLogoGraphics), (GamefreakLogoGraphicsEnd - NintendoCopyrightLogoGraphics) / $10
- call CopyVideoData
- coord hl, 2, 7
- ld de, CopyrightTextString
- jp PlaceString
-
-CopyrightTextString:
- db $60,$61,$62,$61,$63,$61,$64,$7F,$65,$66,$67,$68,$69,$6A ; ©'95.'96.'98 Nintendo
- next $60,$61,$62,$61,$63,$61,$64,$7F,$6B,$6C,$6D,$6E,$6F,$70,$71,$72 ; ©'95.'96.'98 Creatures inc.
- next $60,$61,$62,$61,$63,$61,$64,$7F,$73,$74,$75,$76,$77,$78,$79,$7A,$7B ; ©'95.'96.'98 GAME FREAK inc.
- db "@"
-
-INCLUDE "data/title_mons.asm"
-
-; prints version text (red, blue)
-PrintGameVersionOnTitleScreen:
- coord hl, 7, 8
- ld de, VersionOnTitleScreenText
- jp PlaceString
-
-; these point to special tiles specifically loaded for that purpose and are not usual text
-VersionOnTitleScreenText:
-IF DEF(_RED)
- db $60,$61,$7F,$65,$66,$67,$68,$69,"@" ; "Red Version"
-ENDC
-IF DEF(_BLUE)
- db $61,$62,$63,$64,$65,$66,$67,$68,"@" ; "Blue Version"
-ENDC
-
-NintenText: db "NINTEN@"
-SonyText: db "SONY@"
diff --git a/engine/town_map.asm b/engine/town_map.asm
deleted file mode 100755
index d417e0a3..00000000
--- a/engine/town_map.asm
+++ /dev/null
@@ -1,619 +0,0 @@
-DisplayTownMap:
- call LoadTownMap
- ld hl, wUpdateSpritesEnabled
- ld a, [hl]
- push af
- ld [hl], $ff
- push hl
- ld a, $1
- ld [hJoy7], a
- ld a, [wCurMap]
- push af
- ld b, $0
- call DrawPlayerOrBirdSprite ; player sprite
- coord hl, 1, 0
- ld de, wcd6d
- call PlaceString
- ld hl, wOAMBuffer
- ld de, wTileMapBackup
- ld bc, $10
- call CopyData
- ld hl, vSprites + $40
- ld de, TownMapCursor
- lb bc, BANK(TownMapCursor), (TownMapCursorEnd - TownMapCursor) / $8
- call CopyVideoDataDouble
- xor a
- ld [wWhichTownMapLocation], a
- pop af
- jr .enterLoop
-
-.townMapLoop
- coord hl, 0, 0
- lb bc, 1, 20
- call ClearScreenArea
- ld hl, TownMapOrder
- ld a, [wWhichTownMapLocation]
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
-.enterLoop
- ld de, wTownMapCoords
- call LoadTownMapEntry
- ld a, [de]
- push hl
- call TownMapCoordsToOAMCoords
- ld a, $4
- ld [wOAMBaseTile], a
- ld hl, wOAMBuffer + $10
- call WriteTownMapSpriteOAM ; town map cursor sprite
- pop hl
- ld de, wcd6d
-.copyMapName
- ld a, [hli]
- ld [de], a
- inc de
- cp $50
- jr nz, .copyMapName
- coord hl, 1, 0
- ld de, wcd6d
- call PlaceString
- ld hl, wOAMBuffer + $10
- ld de, wTileMapBackup + 16
- ld bc, $10
- call CopyData
-.inputLoop
- call TownMapSpriteBlinkingAnimation
- call JoypadLowSensitivity
- ld a, [hJoy5]
- ld b, a
- and A_BUTTON | B_BUTTON | D_UP | D_DOWN
- jr z, .inputLoop
- ld a, SFX_TINK
- call PlaySound
- bit 6, b
- jr nz, .pressedUp
- bit 7, b
- jr nz, .pressedDown
- xor a
- ld [wTownMapSpriteBlinkingEnabled], a
- ld [hJoy7], a
- ld [wAnimCounter], a
- call ExitTownMap
- pop hl
- pop af
- ld [hl], a
- ret
-.pressedUp
- ld a, [wWhichTownMapLocation]
- inc a
- cp TownMapOrderEnd - TownMapOrder ; number of list items + 1
- jr nz, .noOverflow
- xor a
-.noOverflow
- ld [wWhichTownMapLocation], a
- jp .townMapLoop
-.pressedDown
- ld a, [wWhichTownMapLocation]
- dec a
- cp -1
- jr nz, .noUnderflow
- ld a, TownMapOrderEnd - TownMapOrder - 1 ; number of list items
-.noUnderflow
- ld [wWhichTownMapLocation], a
- jp .townMapLoop
-
-INCLUDE "data/town_map_order.asm"
-
-TownMapCursor:
- INCBIN "gfx/town_map_cursor.1bpp"
-TownMapCursorEnd:
-
-LoadTownMap_Nest:
- call LoadTownMap
- ld hl, wUpdateSpritesEnabled
- ld a, [hl]
- push af
- ld [hl], $ff
- push hl
- call DisplayWildLocations
- call GetMonName
- coord hl, 1, 0
- call PlaceString
- ld h, b
- ld l, c
- ld de, MonsNestText
- call PlaceString
- call WaitForTextScrollButtonPress
- call ExitTownMap
- pop hl
- pop af
- ld [hl], a
- ret
-
-MonsNestText:
- db "'s NEST@"
-
-LoadTownMap_Fly:
- call ClearSprites
- call LoadTownMap
- call LoadPlayerSpriteGraphics
- call LoadFontTilePatterns
- ld de, BirdSprite
- ld hl, vSprites + $40
- lb bc, BANK(BirdSprite), $c
- call CopyVideoData
- ld de, TownMapUpArrow
- ld hl, vChars1 + $6d0
- lb bc, BANK(TownMapUpArrow), (TownMapUpArrowEnd - TownMapUpArrow) / $8
- call CopyVideoDataDouble
- call BuildFlyLocationsList
- ld hl, wUpdateSpritesEnabled
- ld a, [hl]
- push af
- ld [hl], $ff
- push hl
- coord hl, 0, 0
- ld de, ToText
- call PlaceString
- ld a, [wCurMap]
- ld b, $0
- call DrawPlayerOrBirdSprite
- ld hl, wFlyLocationsList
- coord de, 18, 0
-.townMapFlyLoop
- ld a, " "
- ld [de], a
- push hl
- push hl
- coord hl, 3, 0
- lb bc, 1, 15
- call ClearScreenArea
- pop hl
- ld a, [hl]
- ld b, $4
- call DrawPlayerOrBirdSprite ; draw bird sprite
- coord hl, 3, 0
- ld de, wcd6d
- call PlaceString
- ld c, 15
- call DelayFrames
- coord hl, 18, 0
- ld [hl], "▲"
- coord hl, 19, 0
- ld [hl], "▼"
- pop hl
-.inputLoop
- push hl
- call DelayFrame
- call JoypadLowSensitivity
- ld a, [hJoy5]
- ld b, a
- pop hl
- and A_BUTTON | B_BUTTON | D_UP | D_DOWN
- jr z, .inputLoop
- bit 0, b
- jr nz, .pressedA
- ld a, SFX_TINK
- call PlaySound
- bit 6, b
- jr nz, .pressedUp
- bit 7, b
- jr nz, .pressedDown
- jr .pressedB
-.pressedA
- ld a, SFX_HEAL_AILMENT
- call PlaySound
- ld a, [hl]
- ld [wDestinationMap], a
- ld hl, wd732
- set 3, [hl]
- inc hl
- set 7, [hl]
-.pressedB
- xor a
- ld [wTownMapSpriteBlinkingEnabled], a
- call GBPalWhiteOutWithDelay3
- pop hl
- pop af
- ld [hl], a
- ret
-.pressedUp
- coord de, 18, 0
- inc hl
- ld a, [hl]
- cp $ff
- jr z, .wrapToStartOfList
- cp $fe
- jr z, .pressedUp ; skip past unvisited towns
- jp .townMapFlyLoop
-.wrapToStartOfList
- ld hl, wFlyLocationsList
- jp .townMapFlyLoop
-.pressedDown
- coord de, 19, 0
- dec hl
- ld a, [hl]
- cp $ff
- jr z, .wrapToEndOfList
- cp $fe
- jr z, .pressedDown ; skip past unvisited towns
- jp .townMapFlyLoop
-.wrapToEndOfList
- ld hl, wFlyLocationsList + 11
- jr .pressedDown
-
-ToText:
- db "To@"
-
-BuildFlyLocationsList:
- ld hl, wFlyLocationsList - 1
- ld [hl], $ff
- inc hl
- ld a, [wTownVisitedFlag]
- ld e, a
- ld a, [wTownVisitedFlag + 1]
- ld d, a
- ld bc, SAFFRON_CITY + 1
-.loop
- srl d
- rr e
- ld a, $fe ; store $fe if the town hasn't been visited
- jr nc, .notVisited
- ld a, b ; store the map number of the town if it has been visited
-.notVisited
- ld [hl], a
- inc hl
- inc b
- dec c
- jr nz, .loop
- ld [hl], $ff
- ret
-
-TownMapUpArrow:
- INCBIN "gfx/up_arrow.1bpp"
-TownMapUpArrowEnd:
-
-LoadTownMap:
- call GBPalWhiteOutWithDelay3
- call ClearScreen
- call UpdateSprites
- coord hl, 0, 0
- ld b, $12
- ld c, $12
- call TextBoxBorder
- call DisableLCD
- ld hl, WorldMapTileGraphics
- ld de, vChars2 + $600
- ld bc, WorldMapTileGraphicsEnd - WorldMapTileGraphics
- ld a, BANK(WorldMapTileGraphics)
- call FarCopyData2
- ld hl, MonNestIcon
- ld de, vSprites + $40
- ld bc, MonNestIconEnd - MonNestIcon
- ld a, BANK(MonNestIcon)
- call FarCopyDataDouble
- coord hl, 0, 0
- ld de, CompressedMap
-.nextTile
- ld a, [de]
- and a
- jr z, .done
- ld b, a
- and $f
- ld c, a
- ld a, b
- swap a
- and $f
- add $60
-.writeRunLoop
- ld [hli], a
- dec c
- jr nz, .writeRunLoop
- inc de
- jr .nextTile
-.done
- call EnableLCD
- ld b, SET_PAL_TOWN_MAP
- call RunPaletteCommand
- call Delay3
- call GBPalNormal
- xor a
- ld [wAnimCounter], a
- inc a
- ld [wTownMapSpriteBlinkingEnabled], a
- ret
-
-CompressedMap:
-; you can decompress this file with the redrle program in the extras/ dir
- INCBIN "gfx/town_map.rle"
-
-ExitTownMap:
-; clear town map graphics data and load usual graphics data
- xor a
- ld [wTownMapSpriteBlinkingEnabled], a
- call GBPalWhiteOut
- call ClearScreen
- call ClearSprites
- call LoadPlayerSpriteGraphics
- call LoadFontTilePatterns
- call UpdateSprites
- jp RunDefaultPaletteCommand
-
-DrawPlayerOrBirdSprite:
-; a = map number
-; b = OAM base tile
- push af
- ld a, b
- ld [wOAMBaseTile], a
- pop af
- ld de, wTownMapCoords
- call LoadTownMapEntry
- ld a, [de]
- push hl
- call TownMapCoordsToOAMCoords
- call WritePlayerOrBirdSpriteOAM
- pop hl
- ld de, wcd6d
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- cp "@"
- jr nz, .loop
- ld hl, wOAMBuffer
- ld de, wTileMapBackup
- ld bc, $a0
- jp CopyData
-
-DisplayWildLocations:
- callba FindWildLocationsOfMon
- call ZeroOutDuplicatesInList
- ld hl, wOAMBuffer
- ld de, wTownMapCoords
-.loop
- ld a, [de]
- cp $ff
- jr z, .exitLoop
- and a
- jr z, .nextEntry
- push hl
- call LoadTownMapEntry
- pop hl
- ld a, [de]
- cp $19 ; Cerulean Cave's coordinates
- jr z, .nextEntry ; skip Cerulean Cave
- call TownMapCoordsToOAMCoords
- ld a, $4 ; nest icon tile no.
- ld [hli], a
- xor a
- ld [hli], a
-.nextEntry
- inc de
- jr .loop
-.exitLoop
- ld a, l
- and a ; were any OAM entries written?
- jr nz, .drawPlayerSprite
-; if no OAM entries were written, print area unknown text
- coord hl, 1, 7
- ld b, 2
- ld c, 15
- call TextBoxBorder
- coord hl, 2, 9
- ld de, AreaUnknownText
- call PlaceString
- jr .done
-.drawPlayerSprite
- ld a, [wCurMap]
- ld b, $0
- call DrawPlayerOrBirdSprite
-.done
- ld hl, wOAMBuffer
- ld de, wTileMapBackup
- ld bc, $a0
- jp CopyData
-
-AreaUnknownText:
- db " AREA UNKNOWN@"
-
-TownMapCoordsToOAMCoords:
-; in: lower nybble of a = x, upper nybble of a = y
-; out: b and [hl] = (y * 8) + 24, c and [hl+1] = (x * 8) + 24
- push af
- and $f0
- srl a
- add 24
- ld b, a
- ld [hli], a
- pop af
- and $f
- swap a
- srl a
- add 24
- ld c, a
- ld [hli], a
- ret
-
-WritePlayerOrBirdSpriteOAM:
- ld a, [wOAMBaseTile]
- and a
- ld hl, wOAMBuffer + $90 ; for player sprite
- jr z, WriteTownMapSpriteOAM
- ld hl, wOAMBuffer + $80 ; for bird sprite
-
-WriteTownMapSpriteOAM:
- push hl
-
-; Subtract 4 from c (X coord) and 4 from b (Y coord). However, the carry from c
-; is added to b, so the net result is that only 3 is subtracted from b.
- lb hl, -4, -4
- add hl, bc
-
- ld b, h
- ld c, l
- pop hl
-
-WriteAsymmetricMonPartySpriteOAM:
-; Writes 4 OAM blocks for a helix mon party sprite, since it does not have
-; a vertical line of symmetry.
- lb de, 2, 2
-.loop
- push de
- push bc
-.innerLoop
- ld a, b
- ld [hli], a
- ld a, c
- ld [hli], a
- ld a, [wOAMBaseTile]
- ld [hli], a
- inc a
- ld [wOAMBaseTile], a
- xor a
- ld [hli], a
- inc d
- ld a, 8
- add c
- ld c, a
- dec e
- jr nz, .innerLoop
- pop bc
- pop de
- ld a, 8
- add b
- ld b, a
- dec d
- jr nz, .loop
- ret
-
-WriteSymmetricMonPartySpriteOAM:
-; Writes 4 OAM blocks for a mon party sprite other than a helix. All the
-; sprites other than the helix one have a vertical line of symmetry which allows
-; the X-flip OAM bit to be used so that only 2 rather than 4 tile patterns are
-; needed.
- xor a
- ld [wSymmetricSpriteOAMAttributes], a
- lb de, 2, 2
-.loop
- push de
- push bc
-.innerLoop
- ld a, b
- ld [hli], a ; Y
- ld a, c
- ld [hli], a ; X
- ld a, [wOAMBaseTile]
- ld [hli], a ; tile
- ld a, [wSymmetricSpriteOAMAttributes]
- ld [hli], a ; attributes
- xor (1 << OAM_X_FLIP)
- ld [wSymmetricSpriteOAMAttributes], a
- inc d
- ld a, 8
- add c
- ld c, a
- dec e
- jr nz, .innerLoop
- pop bc
- pop de
- push hl
- ld hl, wOAMBaseTile
- inc [hl]
- inc [hl]
- pop hl
- ld a, 8
- add b
- ld b, a
- dec d
- jr nz, .loop
- ret
-
-ZeroOutDuplicatesInList:
-; replace duplicate bytes in the list of wild pokemon locations with 0
- ld de, wBuffer
-.loop
- ld a, [de]
- inc de
- cp $ff
- ret z
- ld c, a
- ld l, e
- ld h, d
-.zeroDuplicatesLoop
- ld a, [hl]
- cp $ff
- jr z, .loop
- cp c
- jr nz, .skipZeroing
- xor a
- ld [hl], a
-.skipZeroing
- inc hl
- jr .zeroDuplicatesLoop
-
-LoadTownMapEntry:
-; in: a = map number
-; out: lower nybble of [de] = x, upper nybble of [de] = y, hl = address of name
- cp REDS_HOUSE_1F
- jr c, .external
- ld bc, 4
- ld hl, InternalMapEntries
-.loop
- cp [hl]
- jr c, .foundEntry
- add hl, bc
- jr .loop
-.foundEntry
- inc hl
- jr .readEntry
-.external
- ld hl, ExternalMapEntries
- ld c, a
- ld b, 0
- add hl, bc
- add hl, bc
- add hl, bc
-.readEntry
- ld a, [hli]
- ld [de], a
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ret
-
-INCLUDE "data/town_map_entries.asm"
-
-INCLUDE "text/map_names.asm"
-
-MonNestIcon:
- INCBIN "gfx/mon_nest_icon.1bpp"
-MonNestIconEnd:
-
-TownMapSpriteBlinkingAnimation:
- ld a, [wAnimCounter]
- inc a
- cp 25
- jr z, .hideSprites
- cp 50
- jr nz, .done
-; show sprites when the counter reaches 50
- ld hl, wTileMapBackup
- ld de, wOAMBuffer
- ld bc, $90
- call CopyData
- xor a
- jr .done
-.hideSprites
- ld hl, wOAMBuffer
- ld b, $24
- ld de, $4
-.hideSpritesLoop
- ld [hl], $a0
- add hl, de
- dec b
- jr nz, .hideSpritesLoop
- ld a, 25
-.done
- ld [wAnimCounter], a
- jp DelayFrame
diff --git a/engine/trade.asm b/engine/trade.asm
deleted file mode 100755
index 8bc8e3bc..00000000
--- a/engine/trade.asm
+++ /dev/null
@@ -1,853 +0,0 @@
-InternalClockTradeAnim:
-; Do the trading animation with the player's gameboy on the left.
-; In-game trades and internally clocked link cable trades use this.
- ld a, [wTradedPlayerMonSpecies]
- ld [wLeftGBMonSpecies], a
- ld a, [wTradedEnemyMonSpecies]
- ld [wRightGBMonSpecies], a
- ld de, InternalClockTradeFuncSequence
- jr TradeAnimCommon
-
-ExternalClockTradeAnim:
-; Do the trading animation with the player's gameboy on the right.
-; Externally clocked link cable trades use this.
- ld a, [wTradedEnemyMonSpecies]
- ld [wLeftGBMonSpecies], a
- ld a, [wTradedPlayerMonSpecies]
- ld [wRightGBMonSpecies], a
- ld de, ExternalClockTradeFuncSequence
-
-TradeAnimCommon:
- ld a, [wOptions]
- push af
- ld a, [hSCY]
- push af
- ld a, [hSCX]
- push af
- xor a
- ld [wOptions], a
- ld [hSCY], a
- ld [hSCX], a
- push de
-.loop
- pop de
- ld a, [de]
- cp $ff
- jr z, .done
- inc de
- push de
- ld hl, TradeFuncPointerTable
- add a
- ld c, a
- ld b, $0
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld de, .loop
- push de
- jp hl ; call trade func, which will return to the top of the loop
-.done
- pop af
- ld [hSCX], a
- pop af
- ld [hSCY], a
- pop af
- ld [wOptions], a
- ret
-
-addtradefunc: MACRO
-\1TradeFunc::
- dw \1
- ENDM
-
-tradefunc: MACRO
- db (\1TradeFunc - TradeFuncPointerTable) / 2
- ENDM
-
-; The functions in the sequences below are executed in order by TradeFuncCommon.
-; They are from opposite perspectives. The external clock one makes use of
-; Trade_SwapNames to swap the player and enemy names for some functions.
-
-InternalClockTradeFuncSequence:
- tradefunc LoadTradingGFXAndMonNames
- tradefunc Trade_ShowPlayerMon
- tradefunc Trade_DrawOpenEndOfLinkCable
- tradefunc Trade_AnimateBallEnteringLinkCable
- tradefunc Trade_AnimLeftToRight
- tradefunc Trade_Delay100
- tradefunc Trade_ShowClearedWindow
- tradefunc PrintTradeWentToText
- tradefunc PrintTradeForSendsText
- tradefunc PrintTradeFarewellText
- tradefunc Trade_AnimRightToLeft
- tradefunc Trade_ShowClearedWindow
- tradefunc Trade_DrawOpenEndOfLinkCable
- tradefunc Trade_ShowEnemyMon
- tradefunc Trade_Delay100
- tradefunc Trade_Cleanup
- db $FF
-
-ExternalClockTradeFuncSequence:
- tradefunc LoadTradingGFXAndMonNames
- tradefunc Trade_ShowClearedWindow
- tradefunc PrintTradeWillTradeText
- tradefunc PrintTradeFarewellText
- tradefunc Trade_SwapNames
- tradefunc Trade_AnimLeftToRight
- tradefunc Trade_SwapNames
- tradefunc Trade_ShowClearedWindow
- tradefunc Trade_DrawOpenEndOfLinkCable
- tradefunc Trade_ShowEnemyMon
- tradefunc Trade_SlideTextBoxOffScreen
- tradefunc Trade_ShowPlayerMon
- tradefunc Trade_DrawOpenEndOfLinkCable
- tradefunc Trade_AnimateBallEnteringLinkCable
- tradefunc Trade_SwapNames
- tradefunc Trade_AnimRightToLeft
- tradefunc Trade_SwapNames
- tradefunc Trade_Delay100
- tradefunc Trade_ShowClearedWindow
- tradefunc PrintTradeWentToText
- tradefunc Trade_Cleanup
- db $FF
-
-TradeFuncPointerTable:
- addtradefunc LoadTradingGFXAndMonNames
- addtradefunc Trade_ShowPlayerMon
- addtradefunc Trade_DrawOpenEndOfLinkCable
- addtradefunc Trade_AnimateBallEnteringLinkCable
- addtradefunc Trade_ShowEnemyMon
- addtradefunc Trade_AnimLeftToRight
- addtradefunc Trade_AnimRightToLeft
- addtradefunc Trade_Delay100
- addtradefunc Trade_ShowClearedWindow
- addtradefunc PrintTradeWentToText
- addtradefunc PrintTradeForSendsText
- addtradefunc PrintTradeFarewellText
- addtradefunc PrintTradeTakeCareText
- addtradefunc PrintTradeWillTradeText
- addtradefunc Trade_Cleanup
- addtradefunc Trade_SlideTextBoxOffScreen
- addtradefunc Trade_SwapNames
-
-Trade_Delay100:
- ld c, 100
- jp DelayFrames
-
-Trade_CopyTileMapToVRAM:
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-Trade_Delay80:
- ld c, 80
- jp DelayFrames
-
-Trade_ClearTileMap:
- coord hl, 0, 0
- ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
- ld a, " "
- jp FillMemory
-
-LoadTradingGFXAndMonNames:
- call Trade_ClearTileMap
- call DisableLCD
- ld hl, TradingAnimationGraphics
- ld de, vChars2 + $310
- ld bc, TradingAnimationGraphicsEnd - TradingAnimationGraphics
- ld a, BANK(TradingAnimationGraphics)
- call FarCopyData2
- ld hl, TradingAnimationGraphics2
- ld de, vSprites + $7c0
- ld bc, TradingAnimationGraphics2End - TradingAnimationGraphics2
- ld a, BANK(TradingAnimationGraphics2)
- call FarCopyData2
- ld hl, vBGMap0
- ld bc, $800
- ld a, " "
- call FillMemory
- call ClearSprites
- ld a, $ff
- ld [wUpdateSpritesEnabled], a
- ld hl, wd730
- set 6, [hl] ; turn on instant text printing
- ld a, [wOnSGB]
- and a
- ld a, $e4 ; non-SGB OBP0
- jr z, .next
- ld a, $f0 ; SGB OBP0
-.next
- ld [rOBP0], a
- call EnableLCD
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [wTradedPlayerMonSpecies]
- ld [wd11e], a
- call GetMonName
- ld hl, wcd6d
- ld de, wcf4b
- ld bc, NAME_LENGTH
- call CopyData
- ld a, [wTradedEnemyMonSpecies]
- ld [wd11e], a
- jp GetMonName
-
-Trade_LoadMonPartySpriteGfx:
- ld a, %11010000
- ld [rOBP1], a
- jpba LoadMonPartySpriteGfx
-
-Trade_SwapNames:
- ld hl, wPlayerName
- ld de, wBuffer
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wLinkEnemyTrainerName
- ld de, wPlayerName
- ld bc, NAME_LENGTH
- call CopyData
- ld hl, wBuffer
- ld de, wLinkEnemyTrainerName
- ld bc, NAME_LENGTH
- jp CopyData
-
-Trade_Cleanup:
- xor a
- call LoadGBPal
- ld hl, wd730
- res 6, [hl] ; turn off instant text printing
- ret
-
-Trade_ShowPlayerMon:
- ld a, %10101011
- ld [rLCDC], a
- ld a, $50
- ld [hWY], a
- ld a, $86
- ld [rWX], a
- ld [hSCX], a
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- coord hl, 4, 0
- ld b, 6
- ld c, 10
- call TextBoxBorder
- call Trade_PrintPlayerMonInfoText
- ld b, vBGMap0 / $100
- call CopyScreenTileBufferToVRAM
- call ClearScreen
- ld a, [wTradedPlayerMonSpecies]
- call Trade_LoadMonSprite
- ld a, $7e
-.slideScreenLoop
- push af
- call DelayFrame
- pop af
- ld [rWX], a
- ld [hSCX], a
- dec a
- dec a
- and a
- jr nz, .slideScreenLoop
- call Trade_Delay80
- ld a, TRADE_BALL_POOF_ANIM
- call Trade_ShowAnimation
- ld a, TRADE_BALL_DROP_ANIM
- call Trade_ShowAnimation ; clears mon pic
- ld a, [wTradedPlayerMonSpecies]
- call PlayCry
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-Trade_DrawOpenEndOfLinkCable:
- call Trade_ClearTileMap
- ld b, vBGMap0 / $100
- call CopyScreenTileBufferToVRAM
- ld b, SET_PAL_GENERIC
- call RunPaletteCommand
-
-; This function call is pointless. It just copies blank tiles to VRAM that was
-; already filled with blank tiles.
- ld hl, vBGMap1 + $8c
- call Trade_CopyCableTilesOffScreen
-
- ld a, $a0
- ld [hSCX], a
- call DelayFrame
- ld a, %10001011
- ld [rLCDC], a
- coord hl, 6, 2
- ld b, $7 ; open end of link cable tile ID list index
- call CopyTileIDsFromList_ZeroBaseTileID
- call Trade_CopyTileMapToVRAM
- ld a, SFX_HEAL_HP
- call PlaySound
- ld c, 20
-.loop
- ld a, [hSCX]
- add 4
- ld [hSCX], a
- dec c
- jr nz, .loop
- ret
-
-Trade_AnimateBallEnteringLinkCable:
- ld a, TRADE_BALL_SHAKE_ANIM
- call Trade_ShowAnimation
- ld c, 10
- call DelayFrames
- ld a, %11100100
- ld [rOBP0], a
- xor a
- ld [wLinkCableAnimBulgeToggle], a
- lb bc, $20, $60
-.moveBallInsideLinkCableLoop
- push bc
- xor a
- ld de, Trade_BallInsideLinkCableOAM
- call WriteOAMBlock
- ld a, [wLinkCableAnimBulgeToggle]
- xor $1
- ld [wLinkCableAnimBulgeToggle], a
- add $7e
- ld hl, wOAMBuffer + $02
- ld de, 4
- ld c, e
-.cycleLinkCableBulgeTile
- ld [hl], a
- add hl, de
- dec c
- jr nz, .cycleLinkCableBulgeTile
- call Delay3
- pop bc
- ld a, c
- add $4
- ld c, a
- cp $a0
- jr nc, .ballSpriteReachedEdgeOfScreen
- ld a, SFX_TINK
- call PlaySound
- jr .moveBallInsideLinkCableLoop
-.ballSpriteReachedEdgeOfScreen
- call ClearSprites
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- ld b, $98
- call CopyScreenTileBufferToVRAM
- call Delay3
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-Trade_BallInsideLinkCableOAM:
- db $7E,$00,$7E,$20
- db $7E,$40,$7E,$60
-
-Trade_ShowEnemyMon:
- ld a, TRADE_BALL_TILT_ANIM
- call Trade_ShowAnimation
- call Trade_ShowClearedWindow
- coord hl, 4, 10
- ld b, 6
- ld c, 10
- call TextBoxBorder
- call Trade_PrintEnemyMonInfoText
- call Trade_CopyTileMapToVRAM
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [wTradedEnemyMonSpecies]
- call Trade_LoadMonSprite
- ld a, TRADE_BALL_POOF_ANIM
- call Trade_ShowAnimation
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld a, [wTradedEnemyMonSpecies]
- call PlayCry
- call Trade_Delay100
- coord hl, 4, 10
- lb bc, 8, 12
- call ClearScreenArea
- jp PrintTradeTakeCareText
-
-Trade_AnimLeftToRight:
-; Animates the mon moving from the left GB to the right one.
- call Trade_InitGameboyTransferGfx
- ld a, $1
- ld [wTradedMonMovingRight], a
- ld a, %11100100
- ld [rOBP0], a
- ld a, $54
- ld [wBaseCoordX], a
- ld a, $1c
- ld [wBaseCoordY], a
- ld a, [wLeftGBMonSpecies]
- ld [wMonPartySpriteSpecies], a
- call Trade_WriteCircledMonOAM
- call Trade_DrawLeftGameboy
- call Trade_CopyTileMapToVRAM
- call Trade_DrawCableAcrossScreen
- ld hl, vBGMap1 + $8c
- call Trade_CopyCableTilesOffScreen
- ld b, $6
- call Trade_AnimMonMoveHorizontal
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Trade_DrawCableAcrossScreen
- ld b, $4
- call Trade_AnimMonMoveHorizontal
- call Trade_DrawRightGameboy
- ld b, $6
- call Trade_AnimMonMoveHorizontal
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call Trade_AnimMonMoveVertical
- jp ClearSprites
-
-Trade_AnimRightToLeft:
-; Animates the mon moving from the right GB to the left one.
- call Trade_InitGameboyTransferGfx
- xor a
- ld [wTradedMonMovingRight], a
- ld a, $64
- ld [wBaseCoordX], a
- ld a, $44
- ld [wBaseCoordY], a
- ld a, [wRightGBMonSpecies]
- ld [wMonPartySpriteSpecies], a
- call Trade_WriteCircledMonOAM
- call Trade_DrawRightGameboy
- call Trade_CopyTileMapToVRAM
- call Trade_DrawCableAcrossScreen
- ld hl, vBGMap1 + $94
- call Trade_CopyCableTilesOffScreen
- call Trade_AnimMonMoveVertical
- ld b, $6
- call Trade_AnimMonMoveHorizontal
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Trade_DrawCableAcrossScreen
- ld b, $4
- call Trade_AnimMonMoveHorizontal
- call Trade_DrawLeftGameboy
- ld b, $6
- call Trade_AnimMonMoveHorizontal
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- jp ClearSprites
-
-Trade_InitGameboyTransferGfx:
-; Initialises the graphics for showing a mon moving between gameboys.
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- call Trade_LoadMonPartySpriteGfx
- call DelayFrame
- ld a, %10101011
- ld [rLCDC], a
- xor a
- ld [hSCX], a
- ld a, $90
- ld [hWY], a
- ret
-
-Trade_DrawLeftGameboy:
- call Trade_ClearTileMap
-
-; draw link cable
- coord hl, 11, 4
- ld a, $5d
- ld [hli], a
- ld a, $5e
- ld c, 8
-.loop
- ld [hli], a
- dec c
- jr nz, .loop
-
-; draw gameboy pic
- coord hl, 5, 3
- ld b, $6
- call CopyTileIDsFromList_ZeroBaseTileID
-
-; draw text box with player name below gameboy pic
- coord hl, 4, 12
- ld b, 2
- ld c, 7
- call TextBoxBorder
- coord hl, 5, 14
- ld de, wPlayerName
- call PlaceString
-
- jp DelayFrame
-
-Trade_DrawRightGameboy:
- call Trade_ClearTileMap
-
-; draw horizontal segment of link cable
- coord hl, 0, 4
- ld a, $5e
- ld c, $e
-.loop
- ld [hli], a
- dec c
- jr nz, .loop
-
-; draw vertical segment of link cable
- ld a, $5f
- ld [hl], a
- ld de, SCREEN_WIDTH
- add hl, de
- ld a, $61
- ld [hl], a
- add hl, de
- ld [hl], a
- add hl, de
- ld [hl], a
- add hl, de
- ld [hl], a
- add hl, de
- ld a, $60
- ld [hld], a
- ld a, $5d
- ld [hl], a
-
-; draw gameboy pic
- coord hl, 7, 8
- ld b, $6
- call CopyTileIDsFromList_ZeroBaseTileID
-
-; draw text box with enemy name above link cable
- coord hl, 6, 0
- ld b, 2
- ld c, 7
- call TextBoxBorder
- coord hl, 7, 2
- ld de, wLinkEnemyTrainerName
- call PlaceString
-
- jp DelayFrame
-
-Trade_DrawCableAcrossScreen:
-; Draws the link cable across the screen.
- call Trade_ClearTileMap
- coord hl, 0, 4
- ld a, $5e
- ld c, SCREEN_WIDTH
-.loop
- ld [hli], a
- dec c
- jr nz, .loop
- ret
-
-Trade_CopyCableTilesOffScreen:
-; This is used to copy the link cable tiles off screen so that the cable
-; continues when the screen is scrolled.
- push hl
- coord hl, 0, 4
- call CopyToRedrawRowOrColumnSrcTiles
- pop hl
- ld a, h
- ld [hRedrawRowOrColumnDest + 1], a
- ld a, l
- ld [hRedrawRowOrColumnDest], a
- ld a, REDRAW_ROW
- ld [hRedrawRowOrColumnMode], a
- ld c, 10
- jp DelayFrames
-
-Trade_AnimMonMoveHorizontal:
-; Animates the mon going through the link cable horizontally over a distance of
-; b 16-pixel units.
- ld a, [wTradedMonMovingRight]
- ld e, a
- ld d, $8
-.scrollLoop
- ld a, e
- dec a
- jr z, .movingRight
-; moving left
- ld a, [hSCX]
- sub $2
- jr .next
-.movingRight
- ld a, [hSCX]
- add $2
-.next
- ld [hSCX], a
- call DelayFrame
- dec d
- jr nz, .scrollLoop
- call Trade_AnimCircledMon
- dec b
- jr nz, Trade_AnimMonMoveHorizontal
- ret
-
-Trade_AnimCircledMon:
-; Cycles between the two animation frames of the mon party sprite, cycles
-; between a circle and an oval around the mon sprite, and makes the cable flash.
- push de
- push bc
- push hl
- ld a, [rBGP]
- xor $3c ; make link cable flash
- ld [rBGP], a
- ld hl, wOAMBuffer + $02
- ld de, $4
- ld c, $14
-.loop
- ld a, [hl]
- xor $40
- ld [hl], a
- add hl, de
- dec c
- jr nz, .loop
- pop hl
- pop bc
- pop de
- ret
-
-Trade_WriteCircledMonOAM:
- callba WriteMonPartySpriteOAMBySpecies
- call Trade_WriteCircleOAM
-
-Trade_AddOffsetsToOAMCoords:
- ld hl, wOAMBuffer
- ld c, $14
-.loop
- ld a, [wBaseCoordY]
- add [hl]
- ld [hli], a
- ld a, [wBaseCoordX]
- add [hl]
- ld [hli], a
- inc hl
- inc hl
- dec c
- jr nz, .loop
- ret
-
-Trade_AnimMonMoveVertical:
-; Animates the mon going through the link cable vertically as well as
-; horizontally for a bit. The last bit of horizontal movement (when moving
-; right) or the first bit of horizontal movement (when moving left) are done
-; here instead of Trade_AnimMonMoveHorizontal because this function moves the
-; sprite itself rather than scrolling the screen around the sprite. Moving the
-; sprite itself is necessary because the vertical segment of the link cable is
-; to the right of the screen position that the mon sprite has when
-; Trade_AnimMonMoveHorizontal is executing.
- ld a, [wTradedMonMovingRight]
- and a
- jr z, .movingLeft
-; moving right
- lb bc, 4, 0 ; move right
- call .doAnim
- lb bc, 0, 10 ; move down
- jr .doAnim
-.movingLeft
- lb bc, 0, -10 ; move up
- call .doAnim
- lb bc, -4, 0 ; move left
-.doAnim
- ld a, b
- ld [wBaseCoordX], a
- ld a, c
- ld [wBaseCoordY], a
- ld d, $4
-.loop
- call Trade_AddOffsetsToOAMCoords
- call Trade_AnimCircledMon
- ld c, 8
- call DelayFrames
- dec d
- jr nz, .loop
- ret
-
-Trade_WriteCircleOAM:
-; Writes the OAM blocks for the circle around the traded mon as it passes
-; the link cable.
- ld hl, Trade_CircleOAMPointers
- ld c, $4
- xor a
-.loop
- push bc
- ld e, [hl]
- inc hl
- ld d, [hl]
- inc hl
- ld c, [hl]
- inc hl
- ld b, [hl]
- inc hl
- push hl
- inc a
- push af
- call WriteOAMBlock
- pop af
- pop hl
- pop bc
- dec c
- jr nz, .loop
- ret
-
-Trade_CircleOAMPointers:
- dw Trade_CircleOAM0
- db $08,$08
- dw Trade_CircleOAM1
- db $18,$08
- dw Trade_CircleOAM2
- db $08,$18
- dw Trade_CircleOAM3
- db $18,$18
-
-Trade_CircleOAM0:
- db $38,$10,$39,$10
- db $3A,$10,$3B,$10
-
-Trade_CircleOAM1:
- db $39,$30,$38,$30
- db $3B,$30,$3A,$30
-
-Trade_CircleOAM2:
- db $3A,$50,$3B,$50
- db $38,$50,$39,$50
-
-Trade_CircleOAM3:
- db $3B,$70,$3A,$70
- db $39,$70,$38,$70
-
-; a = species
-Trade_LoadMonSprite:
- ld [wcf91], a
- ld [wd0b5], a
- ld [wWholeScreenPaletteMonSpecies], a
- ld b, SET_PAL_POKEMON_WHOLE_SCREEN
- ld c, 0
- call RunPaletteCommand
- ld a, [H_AUTOBGTRANSFERENABLED]
- xor $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call GetMonHeader
- coord hl, 7, 2
- call LoadFlippedFrontSpriteByMonIndex
- ld c, 10
- jp DelayFrames
-
-Trade_ShowClearedWindow:
-; clears the window and covers the BG entirely with the window
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call ClearScreen
- ld a, %11100011
- ld [rLCDC], a
- ld a, $7
- ld [rWX], a
- xor a
- ld [hWY], a
- ld a, $90
- ld [hSCX], a
- ret
-
-Trade_SlideTextBoxOffScreen:
-; Slides the window right until it's off screen. The window usually just has
-; a text box at the bottom when this is called. However, when this is called
-; after Trade_ShowEnemyMon in the external clock sequence, there is a mon pic
-; above the text box and it is also scrolled off the screen.
- ld c, 50
- call DelayFrames
-.loop
- call DelayFrame
- ld a, [rWX]
- inc a
- inc a
- ld [rWX], a
- cp $a1
- jr nz, .loop
- call Trade_ClearTileMap
- ld c, 10
- call DelayFrames
- ld a, $7
- ld [rWX], a
- ret
-
-PrintTradeWentToText:
- ld hl, TradeWentToText
- call PrintText
- ld c, 200
- call DelayFrames
- jp Trade_SlideTextBoxOffScreen
-
-TradeWentToText:
- TX_FAR _TradeWentToText
- db "@"
-
-PrintTradeForSendsText:
- ld hl, TradeForText
- call PrintText
- call Trade_Delay80
- ld hl, TradeSendsText
- call PrintText
- jp Trade_Delay80
-
-TradeForText:
- TX_FAR _TradeForText
- db "@"
-
-TradeSendsText:
- TX_FAR _TradeSendsText
- db "@"
-
-PrintTradeFarewellText:
- ld hl, TradeWavesFarewellText
- call PrintText
- call Trade_Delay80
- ld hl, TradeTransferredText
- call PrintText
- call Trade_Delay80
- jp Trade_SlideTextBoxOffScreen
-
-TradeWavesFarewellText:
- TX_FAR _TradeWavesFarewellText
- db "@"
-
-TradeTransferredText:
- TX_FAR _TradeTransferredText
- db "@"
-
-PrintTradeTakeCareText:
- ld hl, TradeTakeCareText
- call PrintText
- jp Trade_Delay80
-
-TradeTakeCareText:
- TX_FAR _TradeTakeCareText
- db "@"
-
-PrintTradeWillTradeText:
- ld hl, TradeWillTradeText
- call PrintText
- call Trade_Delay80
- ld hl, TradeforText
- call PrintText
- jp Trade_Delay80
-
-TradeWillTradeText:
- TX_FAR _TradeWillTradeText
- db "@"
-
-TradeforText:
- TX_FAR _TradeforText
- db "@"
-
-Trade_ShowAnimation:
- ld [wAnimationID], a
- xor a
- ld [wAnimationType], a
- predef_jump MoveAnimation