diff options
author | mid-kid <esteve.varela@gmail.com> | 2018-03-13 13:07:16 +0100 |
---|---|---|
committer | mid-kid <esteve.varela@gmail.com> | 2018-03-13 13:21:40 +0100 |
commit | baa0dc5a963a79843b37888bcfe1d2dfe833ade9 (patch) | |
tree | 968c86105bd67a3121d8f3f20018bfc59191f4c9 /engine/overworld | |
parent | 12070ca50067d3abe36a730190f88ee43f2cace9 (diff) |
Organize the engine/ directory
This is an informed attempt at reorganizing the engine/ directory by
creating categorized subdirectories, in order to make it easier to
navigate and find things.
The directories created are as follows:
* engine/game: Contains all "minigames", things like the unown puzzle
and slot machine.
* engine/gfx: Contains all handling of graphics. From loading palettes
to playing animations.
* engine/link: Contains all multiplayer functionality.
* engine/menu: Contains all generic/misc. menus and menu code.
Other, more specialized menus are in their own subdirectories (pokedex,
pokegear, party menu, etc).
* engine/overworld: Contains all handling of the overworld. From loading
and connecting maps to wild encounters and the scripting engine.
* engine/pokegear: In the same vein as engine/pokedex, except it could
use some more splitting up.
* engine/pokemon: Contains everything related to manipulating pokemon
data. From the pokemon storage system to evolution and mail.
* engine/printer: Contains everything related to printing things as well
as the printer communication.
* engine/title: Contains intro sequences, title screens and credits.
Diffstat (limited to 'engine/overworld')
23 files changed, 16424 insertions, 0 deletions
diff --git a/engine/overworld/decorations.asm b/engine/overworld/decorations.asm new file mode 100755 index 000000000..33d0ca0cd --- /dev/null +++ b/engine/overworld/decorations.asm @@ -0,0 +1,1303 @@ +InitDecorations: ; 26751 (9:6751) + ld a, DECO_FEATHERY_BED + ld [wDecoBed], a + ld a, DECO_TOWN_MAP + ld [wDecoPoster], a + ret + +_PlayerDecorationMenu: ; 0x2675c + ld a, [wWhichIndexSet] + push af + ld hl, .MenuHeader + call LoadMenuHeader + xor a + ld [wBuffer5], a + ld a, $1 + ld [wBuffer6], a +.top_loop + ld a, [wBuffer6] + ld [wMenuCursorBuffer], a + call .FindCategoriesWithOwnedDecos + call DoNthMenu + ld a, [wMenuCursorY] + ld [wBuffer6], a + jr c, .exit_menu + ld a, [wMenuSelection] + ld hl, .pointers + call MenuJumptable + jr nc, .top_loop + +.exit_menu + call ExitMenu + pop af + ld [wWhichIndexSet], a + ld a, [wBuffer5] + ld c, a + ret +; 0x2679a + +.MenuHeader: ; 0x2679a + db MENU_BACKUP_TILES ; flags + menu_coords 5, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw .MenuData + db 1 ; default option +; 0x267a2 + +.MenuData: ; 0x267a2 + db STATICMENU_CURSOR | STATICMENU_WRAP ; flags + db 0 ; items + dw wd002 + dw PlaceNthMenuStrings + dw .pointers +; 0x267aa + +.pointers ; 267aa + dw DecoBedMenu, .bed + dw DecoCarpetMenu, .carpet + dw DecoPlantMenu, .plant + dw DecoPosterMenu, .poster + dw DecoConsoleMenu, .game + dw DecoOrnamentMenu, .ornament + dw DecoBigDollMenu, .big_doll + dw DecoExitMenu, .exit + +.bed db "BED@" +.carpet db "CARPET@" +.plant db "PLANT@" +.poster db "POSTER@" +.game db "GAME CONSOLE@" +.ornament db "ORNAMENT@" +.big_doll db "BIG DOLL@" +.exit db "EXIT@" +; 26806 + +.FindCategoriesWithOwnedDecos: ; 26806 + xor a + ld [wWhichIndexSet], a + call .ClearStringBuffer2 + call .FindOwndDecos + ld a, 7 + call .AppendToStringBuffer2 + ld hl, wStringBuffer2 + ld de, wd002 + ld bc, ITEM_NAME_LENGTH + call CopyBytes + ret + +.ClearStringBuffer2: ; 26822 (9:6822) + ld hl, wStringBuffer2 + xor a + ld [hli], a + ld bc, ITEM_NAME_LENGTH - 1 + ld a, -1 + call ByteFill + ret + +.AppendToStringBuffer2: ; 26830 (9:6830) + ld hl, wStringBuffer2 + inc [hl] + ld e, [hl] + ld d, 0 + add hl, de + ld [hl], a + ret + +.FindOwndDecos: ; 2683a (9:683a) + ld hl, .dw +.loop + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + or e + jr z, .done + push hl + call _de_ + pop hl + jr nc, .next + ld a, [hl] + push hl + call .AppendToStringBuffer2 + pop hl +.next + inc hl + jr .loop +.done + ret +; 26855 (9:6855) + +.dw ; 26855 + dwb FindOwnedBeds, 0 ; bed + dwb FindOwnedCarpets, 1 ; carpet + dwb FindOwnedPlants, 2 ; plant + dwb FindOwnedPosters, 3 ; poster + dwb FindOwnedConsoles, 4 ; game console + dwb FindOwnedOrnaments, 5 ; ornament + dwb FindOwnedBigDolls, 6 ; big doll + dw 0 ; end +; 2686c + +Deco_FillTempWithMinusOne: ; 2686c + xor a + ld hl, wd002 + ld [hli], a + ld a, -1 + ld bc, $10 + call ByteFill + ret +; 2687a + +CheckAllDecorationFlags: ; 2687a +.loop + ld a, [hli] + cp -1 + jr z, .done + push hl + push af + ld b, CHECK_FLAG + call DecorationFlagAction + ld a, c + and a + pop bc + ld a, b + call nz, AppendDecoIndex + pop hl + jr .loop + +.done + ret +; 26891 + +AppendDecoIndex: ; 26891 + ld hl, wd002 + inc [hl] + ld e, [hl] + ld d, $0 + add hl, de + ld [hl], a + ret +; 2689b + +FindOwnedDecosInCategory: ; 2689b + push bc + push hl + call Deco_FillTempWithMinusOne + pop hl + call CheckAllDecorationFlags + pop bc + ld a, [wd002] + and a + ret z + + ld a, c + call AppendDecoIndex + ld a, 0 + call AppendDecoIndex + scf + ret +; 268b5 + +DecoBedMenu: ; 268b5 + call FindOwnedBeds + call PopulateDecoCategoryMenu + xor a + ret +; 268bd + +FindOwnedBeds: ; 268bd + ld hl, .beds + ld c, BEDS + jp FindOwnedDecosInCategory +; 268c5 + +.beds ; 268c5 + db DECO_FEATHERY_BED ; 2 + db DECO_PINK_BED ; 3 + db DECO_POLKADOT_BED ; 4 + db DECO_PIKACHU_BED ; 5 + db -1 +; 268ca + +DecoCarpetMenu: ; 268ca + call FindOwnedCarpets + call PopulateDecoCategoryMenu + xor a + ret +; 268d2 + +FindOwnedCarpets: ; 268d2 + ld hl, .carpets + ld c, CARPETS + jp FindOwnedDecosInCategory +; 268da + +.carpets ; 268da + db DECO_RED_CARPET ; 7 + db DECO_BLUE_CARPET ; 8 + db DECO_YELLOW_CARPET ; 9 + db DECO_GREEN_CARPET ; a + db -1 +; 268df + +DecoPlantMenu: ; 268df + call FindOwnedPlants + call PopulateDecoCategoryMenu + xor a + ret +; 268e7 + +FindOwnedPlants: ; 268e7 + ld hl, .plants + ld c, PLANTS + jp FindOwnedDecosInCategory +; 268ef + +.plants ; 268ef + db DECO_MAGNAPLANT ; c + db DECO_TROPICPLANT ; d + db DECO_JUMBOPLANT ; e + db -1 +; 268f3 + +DecoPosterMenu: ; 268f3 + call FindOwnedPosters + call PopulateDecoCategoryMenu + xor a + ret +; 268fb + +FindOwnedPosters: ; 268fb + ld hl, .posters + ld c, POSTERS + jp FindOwnedDecosInCategory +; 26903 + +.posters ; 26903 + db DECO_TOWN_MAP ; 10 + db DECO_PIKACHU_POSTER ; 11 + db DECO_CLEFAIRY_POSTER ; 12 + db DECO_JIGGLYPUFF_POSTER ; 13 + db -1 +; 26908 + +DecoConsoleMenu: ; 26908 + call FindOwnedConsoles + call PopulateDecoCategoryMenu + xor a + ret +; 26910 + +FindOwnedConsoles: ; 26910 + ld hl, .consoles + ld c, CONSOLES + jp FindOwnedDecosInCategory +; 26918 + +.consoles ; 26918 + db DECO_FAMICOM ; 15 + db DECO_SNES ; 16 + db DECO_N64 ; 17 + db DECO_VIRTUAL_BOY ; 18 + db -1 +; 2691d + +DecoOrnamentMenu: ; 2691d + call FindOwnedOrnaments + call PopulateDecoCategoryMenu + xor a + ret +; 26925 + +FindOwnedOrnaments: ; 26925 + ld hl, .ornaments + ld c, DOLLS + jp FindOwnedDecosInCategory +; 2692d + +.ornaments ; 2692d + db DECO_PIKACHU_DOLL ; 1e + db DECO_SURF_PIKACHU_DOLL ; 1f + db DECO_CLEFAIRY_DOLL ; 20 + db DECO_JIGGLYPUFF_DOLL ; 21 + db DECO_BULBASAUR_DOLL ; 22 + db DECO_CHARMANDER_DOLL ; 23 + db DECO_SQUIRTLE_DOLL ; 24 + db DECO_POLIWAG_DOLL ; 25 + db DECO_DIGLETT_DOLL ; 26 + db DECO_STARMIE_DOLL ; 27 + db DECO_MAGIKARP_DOLL ; 28 + db DECO_ODDISH_DOLL ; 29 + db DECO_GENGAR_DOLL ; 2a + db DECO_SHELLDER_DOLL ; 2b + db DECO_GRIMER_DOLL ; 2c + db DECO_VOLTORB_DOLL ; 2d + db DECO_WEEDLE_DOLL ; 2e + db DECO_UNOWN_DOLL ; 2f + db DECO_GEODUDE_DOLL ; 30 + db DECO_MACHOP_DOLL ; 31 + db DECO_TENTACOOL_DOLL ; 32 + db DECO_GOLD_TROPHY_DOLL ; 33 + db DECO_SILVER_TROPHY_DOLL ; 34 + db -1 +; 26945 + +DecoBigDollMenu: ; 26945 + call FindOwnedBigDolls + call PopulateDecoCategoryMenu + xor a + ret +; 2694d + +FindOwnedBigDolls: ; 2694d + ld hl, .big_dolls + ld c, BIG_DOLLS + jp FindOwnedDecosInCategory +; 26955 + +.big_dolls ; 26955 + db DECO_BIG_SNORLAX_DOLL ; 1a + db DECO_BIG_ONIX_DOLL ; 1b + db DECO_BIG_LAPRAS_DOLL ; 1c + db -1 +; 26959 + +DecoExitMenu: ; 26959 + scf + ret +; 2695b + +PopulateDecoCategoryMenu: ; 2695b + ld a, [wd002] + and a + jr z, .empty + cp 8 + jr nc, .beyond_eight + xor a + ld [wWhichIndexSet], a + ld hl, .NonscrollingMenuHeader + call LoadMenuHeader + call DoNthMenu + jr c, .no_action_1 + call DoDecorationAction2 + +.no_action_1 + call ExitMenu + ret + +.beyond_eight + ld hl, wd002 + ld e, [hl] + dec [hl] + ld d, 0 + add hl, de + ld [hl], -1 + call LoadStandardMenuHeader + ld hl, .ScrollingMenuHeader + call CopyMenuHeader + xor a + ld [hBGMapMode], a + call InitScrollingMenu + xor a + ld [wMenuScrollPosition], a + call ScrollingMenu + ld a, [wMenuJoypad] + cp 2 + jr z, .no_action_2 + call DoDecorationAction2 + +.no_action_2 + call ExitMenu + ret + +.empty + ld hl, .Text_nothing_to_choose + call MenuTextBoxBackup + ret +; 269b0 + +.Text_nothing_to_choose: ; 0x269b0 + ; There's nothing to choose. + text_jump UnknownText_0x1bc471 + db "@" +; 0x269b5 + +.NonscrollingMenuHeader: ; 0x269b5 + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 + dw .NonscrollingMenuData + db 1 ; default option +; 0x269bd + +.NonscrollingMenuData: ; 0x269bd + db STATICMENU_CURSOR | STATICMENU_WRAP ; flags + db 0 ; items + dw wd002 + dw DecorationMenuFunction + dw DecorationAttributes +; 0x269c5 + +.ScrollingMenuHeader: ; 0x269c5 + db MENU_BACKUP_TILES ; flags + menu_coords 1, 1, SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2 + dw .ScrollingMenuData + db 1 ; default option +; 0x269cd + +.ScrollingMenuData: ; 0x269cd + db SCROLLINGMENU_DISPLAY_ARROWS ; flags + db 8, 0 ; rows, columns + db 1 ; horizontal spacing + dbw 0, wd002 ; text pointer + dba DecorationMenuFunction + dbw 0, 0 + dbw 0, 0 +; 269dd + + +GetDecorationData: ; 269dd + ld hl, DecorationAttributes + ld bc, 6 + call AddNTimes + ret +; 269e7 + +GetDecorationName: ; 269e7 + push hl + call GetDecorationData + call GetDecoName + pop hl + call CopyName2 + ret +; 269f3 + +DecorationMenuFunction: ; 269f3 + ld a, [wMenuSelection] + push de + call GetDecorationData + call GetDecoName + pop hl + call PlaceString + ret +; 26a02 + +DoDecorationAction2: ; 26a02 + ld a, [wMenuSelection] + call GetDecorationData + ld de, 2 ; function 2 + add hl, de + ld a, [hl] + ld hl, .DecoActions + rst JumpTable + ret +; 26a12 + +.DecoActions: ; 26a12 + dw DecoAction_nothing + dw DecoAction_setupbed + dw DecoAction_putawaybed + dw DecoAction_setupcarpet + dw DecoAction_putawaycarpet + dw DecoAction_setupplant + dw DecoAction_putawayplant + dw DecoAction_setupposter + dw DecoAction_putawayposter + dw DecoAction_setupconsole + dw DecoAction_putawayconsole + dw DecoAction_setupbigdoll + dw DecoAction_putawaybigdoll + dw DecoAction_setupornament + dw DecoAction_putawayornament +; 26a30 + + +GetDecorationFlag: ; 26a30 + call GetDecorationData + ld de, 3 ; event flag + add hl, de + ld a, [hli] + ld d, [hl] + ld e, a + ret +; 26a3b + +DecorationFlagAction: ; 26a3b + push bc + call GetDecorationFlag + pop bc + call EventFlagAction + ret +; 26a44 + +GetDecorationSprite: ; 26a44 + ld a, c + call GetDecorationData + ld de, 5 ; sprite + add hl, de + ld a, [hl] + ld c, a + ret +; 26a4f + +INCLUDE "data/decorations/attributes.asm" + +INCLUDE "data/decorations/names.asm" + +GetDecoName: ; 26c72 + ld a, [hli] + ld e, [hl] + ld bc, wStringBuffer2 + push bc + ld hl, .NameFunctions + rst JumpTable + pop de + ret +; 26c7e + +.NameFunctions: ; 26c7e + dw .invalid + dw .plant + dw .bed + dw .carpet + dw .poster + dw .doll + dw .bigdoll +; 26c8c + + +.invalid ; 26c8c + ret +; 26c8d + +.plant ; 26c8d + ld a, e + jr .getdeconame + +.bed ; 26c90 + call .plant + ld a, _BED + jr .getdeconame + +.carpet ; 26c97 + call .plant + ld a, _CARPET + jr .getdeconame + +.poster ; 26c9e + ld a, e + call .getpokename + ld a, _POSTER + jr .getdeconame + +.doll ; 26ca6 + ld a, e + call .getpokename + ld a, _DOLL + jr .getdeconame + +.bigdoll ; 26cae + push de + ld a, BIG_ + call .getdeconame + pop de + ld a, e + jr .getpokename + +.unused ; 26cb8 + push de + call .getdeconame + pop de + ld a, e + jr .getdeconame + +.getpokename ; 26cc0 + push bc + ld [wd265], a + call GetPokemonName + pop bc + jr .copy + +.getdeconame ; 26cca + call ._getdeconame + jr .copy + +._getdeconame ; 26ccf + push bc + ld hl, DecorationNames + call GetNthString + ld d, h + ld e, l + pop bc + ret + +.copy ; 26cda + ld h, b + ld l, c + call CopyName2 + dec hl + ld b, h + ld c, l + ret +; 26ce3 + +DecoAction_nothing: ; 26ce3 + scf + ret +; 26ce5 + +DecoAction_setupbed: ; 26ce5 + ld hl, wDecoBed + jp DecoAction_TrySetItUp +; 26ceb + +DecoAction_putawaybed: ; 26ceb + ld hl, wDecoBed + jp DecoAction_TryPutItAway +; 26cf1 + +DecoAction_setupcarpet: ; 26cf1 + ld hl, wDecoCarpet + jp DecoAction_TrySetItUp +; 26cf7 + +DecoAction_putawaycarpet: ; 26cf7 + ld hl, wDecoCarpet + jp DecoAction_TryPutItAway +; 26cfd + +DecoAction_setupplant: ; 26cfd + ld hl, wDecoPlant + jp DecoAction_TrySetItUp +; 26d03 + +DecoAction_putawayplant: ; 26d03 + ld hl, wDecoPlant + jp DecoAction_TryPutItAway +; 26d09 + +DecoAction_setupposter: ; 26d09 + ld hl, wDecoPoster + jp DecoAction_TrySetItUp +; 26d0f + +DecoAction_putawayposter: ; 26d0f + ld hl, wDecoPoster + jp DecoAction_TryPutItAway +; 26d15 + +DecoAction_setupconsole: ; 26d15 + ld hl, wDecoConsole + jp DecoAction_TrySetItUp +; 26d1b + +DecoAction_putawayconsole: ; 26d1b + ld hl, wDecoConsole + jp DecoAction_TryPutItAway +; 26d21 + +DecoAction_setupbigdoll: ; 26d21 + ld hl, wDecoBigDoll + jp DecoAction_TrySetItUp +; 26d27 + +DecoAction_putawaybigdoll: ; 26d27 + ld hl, wDecoBigDoll + jp DecoAction_TryPutItAway +; 26d2d + +DecoAction_TrySetItUp: ; 26d2d + ld a, [hl] + ld [wBuffer1], a + push hl + call DecoAction_SetItUp + jr c, .failed + ld a, 1 + ld [wBuffer5], a + pop hl + ld a, [wMenuSelection] + ld [hl], a + xor a + ret + +.failed + pop hl + xor a + ret +; 26d46 + +DecoAction_SetItUp: ; 26d46 +; See if there's anything of the same type already out + ld a, [wBuffer1] + and a + jr z, .nothingthere +; See if that item is already out + ld b, a + ld a, [wMenuSelection] + cp b + jr z, .alreadythere +; Put away the item that's already out, and set up the new one + ld a, [wMenuSelection] + ld hl, wStringBuffer4 + call GetDecorationName + ld a, [wBuffer1] + ld hl, wStringBuffer3 + call GetDecorationName + ld hl, DecoText_PutAwayAndSetUp + call MenuTextBoxBackup + xor a + ret + +.nothingthere + ld a, [wMenuSelection] + ld hl, wStringBuffer3 + call GetDecorationName + ld hl, DecoText_SetUpTheDeco + call MenuTextBoxBackup + xor a + ret + +.alreadythere + ld hl, DecoText_AlreadySetUp + call MenuTextBoxBackup + scf + ret +; 26d86 + +DecoAction_TryPutItAway: ; 26d86 +; If there is no item of that type already set, there is nothing to put away. + ld a, [hl] + ld [wBuffer1], a + xor a + ld [hl], a + ld a, [wBuffer1] + and a + jr z, .nothingthere +; Put it away. + ld a, $1 + ld [wBuffer5], a + ld a, [wBuffer1] + ld [wMenuSelection], a + ld hl, wStringBuffer3 + call GetDecorationName + ld hl, DecoText_PutAwayTheDeco + call MenuTextBoxBackup + xor a + ret + +.nothingthere + ld hl, DecoText_NothingToPutAway + call MenuTextBoxBackup + xor a + ret +; 26db3 + +DecoAction_setupornament: ; 26db3 + ld hl, UnknownText_0x26e41 + call DecoAction_AskWhichSide + jr c, .cancel + call DecoAction_SetItUp_Ornament + jr c, .cancel + ld a, $1 + ld [wBuffer5], a + jr DecoAction_FinishUp_Ornament + +.cancel + xor a + ret + +DecoAction_putawayornament: ; 26dc9 + ld hl, DecoText_WhichSide + call DecoAction_AskWhichSide + jr nc, .incave + xor a + ret + +.incave + call DecoAction_PutItAway_Ornament + +DecoAction_FinishUp_Ornament: ; 26dd6 + call QueryWhichSide + ld a, [wSelectedDecoration] + ld [hl], a + ld a, [wOtherDecoration] + ld [de], a + xor a + ret +; 26de3 + +DecoAction_SetItUp_Ornament: ; 26de3 + ld a, [wSelectedDecoration] + and a + jr z, .nothingthere + ld b, a + ld a, [wMenuSelection] + cp b + jr z, .failed + ld a, b + ld hl, wStringBuffer3 + call GetDecorationName + ld a, [wMenuSelection] + ld hl, wStringBuffer4 + call GetDecorationName + ld a, [wMenuSelection] + ld [wSelectedDecoration], a + call .getwhichside + ld hl, DecoText_PutAwayAndSetUp + call MenuTextBoxBackup + xor a + ret + +.nothingthere + ld a, [wMenuSelection] + ld [wSelectedDecoration], a + call .getwhichside + ld a, [wMenuSelection] + ld hl, wStringBuffer3 + call GetDecorationName + ld hl, DecoText_SetUpTheDeco + call MenuTextBoxBackup + xor a + ret + +.failed + ld hl, DecoText_AlreadySetUp + call MenuTextBoxBackup + scf + ret +; 26e33 + +.getwhichside ; 26e33 + ld a, [wMenuSelection] + ld b, a + ld a, [wOtherDecoration] + cp b + ret nz + xor a + ld [wOtherDecoration], a + ret +; 26e41 + +UnknownText_0x26e41: ; 0x26e41 + ; Which side do you want to put it on? + text_jump UnknownText_0x1bc48c + db "@" +; 0x26e46 + +DecoAction_PutItAway_Ornament: ; 26e46 + ld a, [wSelectedDecoration] + and a + jr z, .nothingthere + ld hl, wStringBuffer3 + call GetDecorationName + ld a, $1 + ld [wBuffer5], a + xor a + ld [wSelectedDecoration], a + ld hl, DecoText_PutAwayTheDeco + call MenuTextBoxBackup + xor a + ret + +.nothingthere + ld hl, DecoText_NothingToPutAway + call MenuTextBoxBackup + xor a + ret +; 26e6b + +DecoText_WhichSide: ; 0x26e6b + ; Which side do you want to put away? + text_jump UnknownText_0x1bc4b2 + db "@" +; 0x26e70 + +DecoAction_AskWhichSide: ; 26e70 + call MenuTextBox + ld hl, MenuHeader_0x26eab + call GetMenu2 + call ExitMenu + call CopyMenuData + jr c, .nope + ld a, [wMenuCursorY] + cp 3 + jr z, .nope + ld [wBuffer2], a + call QueryWhichSide + ld a, [hl] + ld [wSelectedDecoration], a + ld a, [de] + ld [wOtherDecoration], a + xor a + ret + +.nope + scf + ret +; 26e9a + +QueryWhichSide: ; 26e9a + ld hl, wDecoRightOrnament + ld de, wDecoLeftOrnament + ld a, [wBuffer2] + cp 1 + ret z + push hl + ld h, d + ld l, e + pop de + ret +; 26eab + +MenuHeader_0x26eab: ; 0x26eab + db MENU_BACKUP_TILES ; flags + menu_coords 0, 0, 13, 7 + dw MenuData_0x26eb3 + db 1 ; default option +; 0x26eb3 + +MenuData_0x26eb3: ; 0x26eb3 + db STATICMENU_CURSOR ; flags + db 3 ; items + db "RIGHT SIDE@" + db "LEFT SIDE@" + db "CANCEL@" +; 0x26ed1 + +DecoText_PutAwayTheDeco: ; 0x26ed1 + ; Put away the @ . + text_jump UnknownText_0x1bc4d7 + db "@" +; 0x26ed6 + +DecoText_NothingToPutAway: ; 0x26ed6 + ; There's nothing to put away. + text_jump UnknownText_0x1bc4ec + db "@" +; 0x26edb + +DecoText_SetUpTheDeco: ; 0x26edb + ; Set up the @ . + text_jump UnknownText_0x1bc509 + db "@" +; 0x26ee0 + +DecoText_PutAwayAndSetUp: ; 0x26ee0 + ; Put away the @ and set up the @ . + text_jump UnknownText_0x1bc51c + db "@" +; 0x26ee5 + +DecoText_AlreadySetUp: ; 0x26ee5 + ; That's already set up. + text_jump UnknownText_0x1bc546 + db "@" +; 0x26eea + +GetDecorationName_c_de: ; 26eea + ld a, c + ld h, d + ld l, e + call GetDecorationName + ret +; 26ef1 + +DecorationFlagAction_c: ; 26ef1 + ld a, c + jp DecorationFlagAction +; 26ef5 + + +GetDecorationName_c: ; 26ef5 (9:6ef5) + ld a, c + call GetDecorationID + ld hl, wStringBuffer1 + push hl + call GetDecorationName + pop de + ret + + +SetSpecificDecorationFlag: ; 26f02 + ld a, c + call GetDecorationID + ld b, SET_FLAG + call DecorationFlagAction + ret +; 26f0c + +GetDecorationID: ; 26f0c + push hl + push de + ld e, a + ld d, 0 + ld hl, DecorationIDs + add hl, de + ld a, [hl] + pop de + pop hl + ret +; 26f19 + +SetAllDecorationFlags: ; 26f19 + ld hl, DecorationIDs +.loop + ld a, [hli] + cp -1 + jr z, .done + push hl + ld b, SET_FLAG + call DecorationFlagAction + pop hl + jr .loop + +.done + ret +; 26f2b + +INCLUDE "data/decorations/decorations.asm" + +DescribeDecoration:: ; 26f59 + ld a, b + ld hl, .JumpTable + rst JumpTable + ret +; 26f5f + +.JumpTable: ; 26f5f +; entries correspond to DECODESC_* constants + dw DecorationDesc_Poster + dw DecorationDesc_LeftOrnament + dw DecorationDesc_RightOrnament + dw DecorationDesc_GiantOrnament + dw DecorationDesc_Console +; 26f69 + +DecorationDesc_Poster: ; 26f69 + ld a, [wDecoPoster] + ld hl, DecorationDesc_PosterPointers + ld de, 3 + call IsInArray + jr c, .nope + ld de, DecorationDesc_NullPoster + ld b, BANK(DecorationDesc_NullPoster) + ret + +.nope + ld b, BANK(DecorationDesc_TownMapPoster) + inc hl + ld a, [hli] + ld d, [hl] + ld e, a + ret +; 26f84 + +DecorationDesc_PosterPointers: ; 26f84 + dbw DECO_TOWN_MAP, DecorationDesc_TownMapPoster + dbw DECO_PIKACHU_POSTER, DecorationDesc_PikachuPoster + dbw DECO_CLEFAIRY_POSTER, DecorationDesc_ClefairyPoster + dbw DECO_JIGGLYPUFF_POSTER, DecorationDesc_JigglypuffPoster + db -1 +; 26f91 + +DecorationDesc_TownMapPoster: ; 0x26f91 + opentext + writetext .TownMapText + waitbutton + special OverworldTownMap + closetext + end +; 0x26f9b + +.TownMapText: ; 0x26f9b + ; It's the TOWN MAP. + text_jump UnknownText_0x1bc55d + db "@" +; 0x26fa0 + +DecorationDesc_PikachuPoster: ; 0x26fa0 + jumptext .PikaPosterText +; 0x26fa3 + +.PikaPosterText: ; 0x26fa3 + ; It's a poster of a cute PIKACHU. + text_jump UnknownText_0x1bc570 + db "@" +; 0x26fa8 + +DecorationDesc_ClefairyPoster: ; 0x26fa8 + jumptext .ClefairyPosterText +; 0x26fab + +.ClefairyPosterText: ; 0x26fab + ; It's a poster of a cute CLEFAIRY. + text_jump UnknownText_0x1bc591 + db "@" +; 0x26fb0 + +DecorationDesc_JigglypuffPoster: ; 0x26fb0 + jumptext .JigglypuffPosterText +; 0x26fb3 + +.JigglypuffPosterText: ; 0x26fb3 + ; It's a poster of a cute JIGGLYPUFF. + text_jump UnknownText_0x1bc5b3 + db "@" +; 0x26fb8 + +DecorationDesc_NullPoster: ; 26fb8 + end +; 26fb9 + +DecorationDesc_LeftOrnament: ; 26fb9 + ld a, [wDecoLeftOrnament] + jr DecorationDesc_OrnamentOrConsole + +DecorationDesc_RightOrnament: ; 26fbe + ld a, [wDecoRightOrnament] + jr DecorationDesc_OrnamentOrConsole + +DecorationDesc_Console: ; 26fc3 + ld a, [wDecoConsole] + jr DecorationDesc_OrnamentOrConsole + +DecorationDesc_OrnamentOrConsole: ; 26fc8 + ld c, a + ld de, wStringBuffer3 + call GetDecorationName_c_de + ld b, BANK(.OrnamentConsoleScript) + ld de, .OrnamentConsoleScript + ret +; 26fd5 + +.OrnamentConsoleScript: ; 26fd5 + jumptext .OrnamentConsoleText +; 26fd8 + +.OrnamentConsoleText: ; 0x26fd8 + ; It's an adorable @ . + text_jump UnknownText_0x1bc5d7 + db "@" +; 0x26fdd + +DecorationDesc_GiantOrnament: ; 26fdd + ld b, BANK(.BigDollScript) + ld de, .BigDollScript + ret +; 26fe3 + +.BigDollScript: ; 26fe3 + jumptext .BigDollText +; 26fe6 + +.BigDollText: ; 0x26fe6 + ; A giant doll! It's fluffy and cuddly. + text_jump UnknownText_0x1bc5ef + db "@" +; 0x26feb + +ToggleMaptileDecorations: ; 26feb + lb de, 0, 4 + ld a, [wDecoBed] + call SetDecorationTile + lb de, 7, 4 + ld a, [wDecoPlant] + call SetDecorationTile + lb de, 6, 0 + ld a, [wDecoPoster] + call SetDecorationTile + call SetPosterVisibility + lb de, 0, 0 + call PadCoords_de + ld a, [wDecoCarpet] + and a + ret z + call _GetDecorationSprite + ld [hl], a + push af + lb de, 0, 2 + call PadCoords_de + pop af + inc a + ld [hli], a + inc a + ld [hli], a + dec a + ld [hl], a + ret +; 27027 + +SetPosterVisibility: ; 27027 + ld b, SET_FLAG + ld a, [wDecoPoster] + and a + jr nz, .ok + ld b, RESET_FLAG + +.ok + ld de, EVENT_PLAYERS_ROOM_POSTER + jp EventFlagAction +; 27037 + +SetDecorationTile: ; 27037 + push af + call PadCoords_de + pop af + and a + ret z + call _GetDecorationSprite + ld [hl], a + ret +; 27043 + +ToggleDecorationsVisibility: ; 27043 + ld de, EVENT_PLAYERS_HOUSE_2F_CONSOLE + ld hl, wVariableSprites + SPRITE_CONSOLE - SPRITE_VARS + ld a, [wDecoConsole] + call ToggleDecorationVisibility + ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_1 + ld hl, wVariableSprites + SPRITE_DOLL_1 - SPRITE_VARS + ld a, [wDecoLeftOrnament] + call ToggleDecorationVisibility + ld de, EVENT_PLAYERS_HOUSE_2F_DOLL_2 + ld hl, wVariableSprites + SPRITE_DOLL_2 - SPRITE_VARS + ld a, [wDecoRightOrnament] + call ToggleDecorationVisibility + ld de, EVENT_PLAYERS_HOUSE_2F_BIG_DOLL + ld hl, wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS + ld a, [wDecoBigDoll] + call ToggleDecorationVisibility + ret +; 27074 + +ToggleDecorationVisibility: ; 27074 + and a + jr z, .hide + call _GetDecorationSprite + ld [hl], a + ld b, RESET_FLAG + jp EventFlagAction + +.hide + ld b, SET_FLAG + jp EventFlagAction +; 27085 + +_GetDecorationSprite: ; 27085 + ld c, a + push de + push hl + farcall GetDecorationSprite + pop hl + pop de + ld a, c + ret +; 27092 + +PadCoords_de: ; 27092 + ld a, d + add 4 + ld d, a + ld a, e + add 4 + ld e, a + call GetBlockLocation + ret diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm new file mode 100644 index 000000000..cc2c8c574 --- /dev/null +++ b/engine/overworld/events.asm @@ -0,0 +1,1111 @@ +INCLUDE "constants.asm" + + +SECTION "Events", ROMX + +OverworldLoop:: ; 966b0 + xor a + ld [wMapStatus], a +.loop + ld a, [wMapStatus] + ld hl, .jumps + rst JumpTable + ld a, [wMapStatus] + cp 3 ; done + jr nz, .loop +.done + ret + +.jumps + dw StartMap + dw EnterMap + dw HandleMap + dw .done +; 966cb + +DisableEvents: ; 966cb + xor a + ld [wScriptFlags3], a + ret +; 966d0 + +EnableEvents:: ; 966d0 + ld a, $ff + ld [wScriptFlags3], a + ret +; 966d6 + +CheckBit5_ScriptFlags3: ; 966d6 + ld hl, wScriptFlags3 + bit 5, [hl] + ret +; 966dc + +DisableWarpsConnxns: ; 966dc + ld hl, wScriptFlags3 + res 2, [hl] + ret +; 966e2 + +DisableCoordEvents: ; 966e2 + ld hl, wScriptFlags3 + res 1, [hl] + ret +; 966e8 + +DisableStepCount: ; 966e8 + ld hl, wScriptFlags3 + res 0, [hl] + ret +; 966ee + +DisableWildEncounters: ; 966ee + ld hl, wScriptFlags3 + res 4, [hl] + ret +; 966f4 + +EnableWarpsConnxns: ; 966f4 + ld hl, wScriptFlags3 + set 2, [hl] + ret +; 966fa + +EnableCoordEvents: ; 966fa + ld hl, wScriptFlags3 + set 1, [hl] + ret +; 96700 + +EnableStepCount: ; 96700 + ld hl, wScriptFlags3 + set 0, [hl] + ret +; 96706 + +EnableWildEncounters: ; 96706 + ld hl, wScriptFlags3 + set 4, [hl] + ret +; 9670c + +CheckWarpConnxnScriptFlag: ; 9670c + ld hl, wScriptFlags3 + bit 2, [hl] + ret +; 96712 + +CheckCoordEventScriptFlag: ; 96712 + ld hl, wScriptFlags3 + bit 1, [hl] + ret +; 96718 + +CheckStepCountScriptFlag: ; 96718 + ld hl, wScriptFlags3 + bit 0, [hl] + ret +; 9671e + +CheckWildEncountersScriptFlag: ; 9671e + ld hl, wScriptFlags3 + bit 4, [hl] + ret +; 96724 + +StartMap: ; 96724 + xor a + ld [wScriptVar], a + xor a + ld [wScriptRunning], a + ld hl, wMapStatus + ld bc, wMapStatusEnd - wMapStatus + call ByteFill + farcall InitCallReceiveDelay + call ClearJoypad +EnterMap: ; 9673e + xor a + ld [wXYComparePointer], a + ld [wXYComparePointer + 1], a + call SetUpFiveStepWildEncounterCooldown + farcall RunMapSetupScript + call DisableEvents + + ld a, [hMapEntryMethod] + cp MAPSETUP_CONNECTION + jr nz, .dont_enable + call EnableEvents +.dont_enable + + ld a, [hMapEntryMethod] + cp MAPSETUP_RELOADMAP + jr nz, .dontresetpoison + xor a + ld [wPoisonStepCount], a +.dontresetpoison + + xor a ; end map entry + ld [hMapEntryMethod], a + ld a, 2 ; HandleMap + ld [wMapStatus], a + ret +; 9676d + +UnusedWait30Frames: ; 9676d + ld c, 30 + call DelayFrames + ret +; 96773 + +HandleMap: ; 96773 + call ResetOverworldDelay + call HandleMapTimeAndJoypad + farcall HandleCmdQueue ; no need to farcall + call MapEvents + +; Not immediately entering a connected map will cause problems. + ld a, [wMapStatus] + cp 2 ; HandleMap + ret nz + + call HandleMapObjects + call NextOverworldFrame + call HandleMapBackground + call CheckPlayerState + ret +; 96795 + +MapEvents: ; 96795 + ld a, [wMapEventStatus] + ld hl, .jumps + rst JumpTable + ret + +.jumps + dw .events + dw .no_events +; 967a1 + +.events ; 967a1 + call PlayerEvents + call DisableEvents + farcall ScriptEvents + ret +; 967ae + +.no_events ; 967ae + ret +; 967af + +MaxOverworldDelay: ; 967af + db 2 +; 967b0 + +ResetOverworldDelay: ; 967b0 + ld a, [MaxOverworldDelay] + ld [wOverworldDelay], a + ret +; 967b7 + +NextOverworldFrame: ; 967b7 + ld a, [wOverworldDelay] + and a + ret z + ld c, a + call DelayFrames + ret +; 967c1 + +HandleMapTimeAndJoypad: ; 967c1 + ld a, [wMapEventStatus] + cp 1 ; no events + ret z + + call UpdateTime + call GetJoypad + call TimeOfDayPals + ret +; 967d1 + +HandleMapObjects: ; 967d1 + farcall HandleNPCStep ; engine/map_objects.asm + farcall _HandlePlayerStep + call _CheckObjectEnteringVisibleRange + ret +; 967e1 + +HandleMapBackground: ; 967e1 + farcall _UpdateSprites + farcall ScrollScreen + farcall PlaceMapNameSign + ret +; 967f4 + +CheckPlayerState: ; 967f4 + ld a, [wPlayerStepFlags] + bit 5, a ; in the middle of step + jr z, .events + bit 6, a ; stopping step + jr z, .noevents + bit 4, a ; in midair + jr nz, .noevents + call EnableEvents +.events + ld a, 0 ; events + ld [wMapEventStatus], a + ret + +.noevents + ld a, 1 ; no events + ld [wMapEventStatus], a + ret +; 96812 + +_CheckObjectEnteringVisibleRange: ; 96812 + ld hl, wPlayerStepFlags + bit 6, [hl] + ret z + farcall CheckObjectEnteringVisibleRange + ret +; 9681f + +PlayerEvents: ; 9681f + xor a +; If there's already a player event, don't interrupt it. + ld a, [wScriptRunning] + and a + ret nz + + call Dummy_CheckScriptFlags3Bit5 ; This is a waste of time + + call CheckTrainerBattle3 + jr c, .ok + + call CheckTileEvent + jr c, .ok + + call RunMemScript + jr c, .ok + + call RunSceneScript + jr c, .ok + + call CheckTimeEvents + jr c, .ok + + call OWPlayerInput + jr c, .ok + + xor a + ret + +.ok + push af + farcall EnableScriptMode + pop af + + ld [wScriptRunning], a + call DoPlayerEvent + ld a, [wScriptRunning] + cp PLAYEREVENT_CONNECTION + jr z, .ok2 + cp PLAYEREVENT_JOYCHANGEFACING + jr z, .ok2 + + xor a + ld [wLandmarkSignTimer], a + +.ok2 + scf + ret +; 96867 + +CheckTrainerBattle3: ; 96867 + nop + nop + call CheckTrainerBattle2 + jr nc, .nope + + ld a, PLAYEREVENT_SEENBYTRAINER + scf + ret + +.nope + xor a + ret +; 96874 + +CheckTileEvent: ; 96874 +; Check for warps, coord events, or wild battles. + + call CheckWarpConnxnScriptFlag + jr z, .connections_disabled + + farcall CheckMovingOffEdgeOfMap + jr c, .map_connection + + call CheckWarpTile + jr c, .warp_tile + +.connections_disabled + call CheckCoordEventScriptFlag + jr z, .coord_events_disabled + + call CheckCurrentMapCoordEvents + jr c, .coord_event + +.coord_events_disabled + call CheckStepCountScriptFlag + jr z, .step_count_disabled + + call CountStep + ret c + +.step_count_disabled + call CheckWildEncountersScriptFlag + jr z, .ok + + call RandomEncounter + ret c + jr .ok ; pointless + +.ok + xor a + ret + +.map_connection + ld a, PLAYEREVENT_CONNECTION + scf + ret + +.warp_tile + ld a, [wPlayerStandingTile] + call CheckPitTile + jr nz, .not_pit + ld a, PLAYEREVENT_FALL + scf + ret + +.not_pit + ld a, PLAYEREVENT_WARP + scf + ret + +.coord_event + ld hl, wCurCoordEventScriptAddr + ld a, [hli] + ld h, [hl] + ld l, a + call GetMapScriptsBank + call CallScript + ret +; 968c7 + +CheckWildEncounterCooldown:: ; 968c7 + ld hl, wWildEncounterCooldown + ld a, [hl] + and a + ret z + dec [hl] + ret z + scf + ret +; 968d1 + +SetUpFiveStepWildEncounterCooldown: ; 968d1 + ld a, 5 + ld [wWildEncounterCooldown], a + ret +; 968d7 + +ret_968d7: ; 968d7 + ret +;968d8 + +SetMinTwoStepWildEncounterCooldown: ; 968d8 + ld a, [wWildEncounterCooldown] + cp 2 + ret nc + ld a, 2 + ld [wWildEncounterCooldown], a + ret +; 968e4 + +Dummy_CheckScriptFlags3Bit5: ; 968e4 + call CheckBit5_ScriptFlags3 + ret z + call ret_2f3e + ret +; 968ec + +RunSceneScript: ; 968ec + ld a, [wCurrMapSceneScriptCount] + and a + jr z, .nope + + ld c, a + call CheckScenes + cp c + jr nc, .nope + + ld e, a + ld d, 0 + ld hl, wCurrMapSceneScriptsPointer + ld a, [hli] + ld h, [hl] + ld l, a +rept 4 + add hl, de +endr + + call GetMapScriptsBank + call GetFarHalfword + call GetMapScriptsBank + call CallScript + + ld hl, wScriptFlags + res 3, [hl] + + farcall EnableScriptMode + farcall ScriptEvents + + ld hl, wScriptFlags + bit 3, [hl] + jr z, .nope + + ld hl, wPriorityScriptAddr + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wPriorityScriptBank] + call CallScript + scf + ret + +.nope + xor a + ret +; 9693a + +CheckTimeEvents: ; 9693a + ld a, [wLinkMode] + and a + jr nz, .nothing + + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + jr z, .do_daily + + farcall CheckBugContestTimer + jr c, .end_bug_contest + xor a + ret + +.do_daily + farcall CheckDailyResetTimer + farcall CheckPokerusTick + farcall CheckPhoneCall + ret c + +.nothing + xor a + ret + +.end_bug_contest + ld a, BANK(BugCatchingContestOverScript) + ld hl, BugCatchingContestOverScript + call CallScript + scf + ret +; 96970 + +.unused ; 96970 + ld a, 8 + scf + ret +; 96974 + +OWPlayerInput: ; 96974 + + call PlayerMovement + ret c + and a + jr nz, .NoAction + +; Can't perform button actions while sliding on ice. + farcall CheckStandingOnIce + jr c, .NoAction + + call CheckAPressOW + jr c, .Action + + call CheckMenuOW + jr c, .Action + +.NoAction: + xor a + ret + +.Action: + push af + farcall StopPlayerForEvent + pop af + scf + ret +; 96999 + +CheckAPressOW: ; 96999 + ld a, [hJoyPressed] + and A_BUTTON + ret z + call TryObjectEvent + ret c + call TryBGEvent + ret c + call TryTileCollisionEvent + ret c + xor a + ret +; 969ac + +PlayTalkObject: ; 969ac + push de + ld de, SFX_READ_TEXT_2 + call PlaySFX + pop de + ret +; 969b5 + +TryObjectEvent: ; 969b5 + farcall CheckFacingObject + jr c, .IsObject + xor a + ret + +.IsObject: + call PlayTalkObject + ld a, [hObjectStructIndexBuffer] + call GetObjectStruct + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + ld [hLastTalked], a + + ld a, [hLastTalked] + call GetMapObject + ld hl, MAPOBJECT_COLOR + add hl, bc + ld a, [hl] + and %00001111 + +; Bug: If IsInArray returns nc, data at bc will be executed as code. + push bc + ld de, 3 + ld hl, .pointers + call IsInArray + jr nc, .nope_bugged + pop bc + + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.nope_bugged + ; pop bc + xor a + ret + +.pointers + dbw OBJECTTYPE_SCRIPT, .script + dbw OBJECTTYPE_ITEMBALL, .itemball + dbw OBJECTTYPE_TRAINER, .trainer + ; the remaining four are dummy events + dbw OBJECTTYPE_3, .three + dbw OBJECTTYPE_4, .four + dbw OBJECTTYPE_5, .five + dbw OBJECTTYPE_6, .six + db -1 +; 96a04 + +.script ; 96a04 + ld hl, MAPOBJECT_SCRIPT_POINTER + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call GetMapScriptsBank + call CallScript + ret +; 96a12 + +.itemball ; 96a12 + ld hl, MAPOBJECT_SCRIPT_POINTER + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call GetMapScriptsBank + ld de, wEngineBuffer1 + ld bc, 2 + call FarCopyBytes + ld a, PLAYEREVENT_ITEMBALL + scf + ret +; 96a29 + +.trainer ; 96a29 + call TalkToTrainer + ld a, PLAYEREVENT_TALKTOTRAINER + scf + ret +; 96a30 + +.three ; 96a30 + xor a + ret +; 96a32 + +.four ; 96a32 + xor a + ret +; 96a34 + +.five ; 96a34 + xor a + ret +; 96a36 + +.six ; 96a36 + xor a + ret +; 96a38 + +TryBGEvent: ; 96a38 + call CheckFacingBGEvent + jr c, .is_bg_event + xor a + ret + +.is_bg_event: + ld a, [wEngineBuffer3] + ld hl, .bg_events + rst JumpTable + ret + +.bg_events + dw .read + dw .up + dw .down + dw .right + dw .left + dw .ifset + dw .ifnotset + dw .itemifset + dw .copy +; 96a59 + +.up + ld b, OW_UP + jr .checkdir +.down + ld b, OW_DOWN + jr .checkdir +.right + ld b, OW_RIGHT + jr .checkdir +.left + ld b, OW_LEFT + jr .checkdir + +.checkdir + ld a, [wPlayerDirection] + and %1100 + cp b + jp nz, .dontread + +.read + call PlayTalkObject + ld hl, wEngineBuffer4 + ld a, [hli] + ld h, [hl] + ld l, a + call GetMapScriptsBank + call CallScript + scf + ret + +.itemifset + call CheckBGEventFlag + jp nz, .dontread + call PlayTalkObject + call GetMapScriptsBank + ld de, wEngineBuffer1 + ld bc, 3 + call FarCopyBytes + ld a, BANK(HiddenItemScript) + ld hl, HiddenItemScript + call CallScript + scf + ret + +.copy + call CheckBGEventFlag + jr nz, .dontread + call GetMapScriptsBank + ld de, wEngineBuffer1 + ld bc, 3 + call FarCopyBytes + jr .dontread + +.ifset + call CheckBGEventFlag + jr z, .dontread + jr .thenread + +.ifnotset + call CheckBGEventFlag + jr nz, .dontread + +.thenread + push hl + call PlayTalkObject + pop hl + inc hl + inc hl + call GetMapScriptsBank + call GetFarHalfword + call GetMapScriptsBank + call CallScript + scf + ret + +.dontread + xor a + ret +; 96ad8 + +CheckBGEventFlag: ; 96ad8 + ld hl, wEngineBuffer4 + ld a, [hli] + ld h, [hl] + ld l, a + push hl + call GetMapScriptsBank + call GetFarHalfword + ld e, l + ld d, h + ld b, CHECK_FLAG + call EventFlagAction + ld a, c + and a + pop hl + ret +; 96af0 + +PlayerMovement: ; 96af0 + farcall DoPlayerMovement + ld a, c + ld hl, .pointers + rst JumpTable + ld a, c + ret +; 96afd + +.pointers + dw .zero + dw .one + dw .two + dw .three + dw .four + dw .five + dw .six + dw .seven + +.zero +.four ; 96b0d + xor a + ld c, a + ret +; 96b10 + +.seven ; 96b10 + call ret_968d7 ; mobile + xor a + ld c, a + ret +; 96b16 + +.one ; 96b16 + ld a, 5 + ld c, a + scf + ret +; 96b1b + +.two ; 96b1b + ld a, 9 + ld c, a + scf + ret +; 96b20 + +.three ; 96b20 +; force the player to move in some direction + ld a, BANK(Script_ForcedMovement) + ld hl, Script_ForcedMovement + call CallScript +; ld a, -1 + ld c, a + scf + ret +; 96b2b + +.five +.six ; 96b2b + ld a, -1 + ld c, a + and a + ret +; 96b30 + +CheckMenuOW: ; 96b30 + xor a + ld [hMenuReturn], a + ld [hMenuReturn + 1], a + ld a, [hJoyPressed] + + bit SELECT_F, a + jr nz, .Select + + bit START_F, a + jr z, .NoMenu + + ld a, BANK(StartMenuScript) + ld hl, StartMenuScript + call CallScript + scf + ret + +.NoMenu: + xor a + ret + +.Select: + call PlayTalkObject + ld a, BANK(SelectMenuScript) + ld hl, SelectMenuScript + call CallScript + scf + ret +; 96b58 + +StartMenuScript: ; 96b58 + callasm StartMenu + jump StartMenuCallback +; 96b5f + +SelectMenuScript: ; 96b5f + callasm SelectMenu + jump SelectMenuCallback +; 96b66 + +StartMenuCallback: +SelectMenuCallback: ; 96b66 + copybytetovar hMenuReturn + ifequal HMENURETURN_SCRIPT, .Script + ifequal HMENURETURN_ASM, .Asm + end +; 96b72 + +.Script: ; 96b72 + ptjump wQueuedScriptBank +; 96b75 + +.Asm: ; 96b75 + ptcallasm wQueuedScriptBank + end +; 96b79 + +CountStep: ; 96b79 + ; Don't count steps in link communication rooms. + ld a, [wLinkMode] + and a + jr nz, .done + + ; If there is a special phone call, don't count the step. + farcall CheckSpecialPhoneCall + jr c, .doscript + + ; If Repel wore off, don't count the step. + call DoRepelStep + jr c, .doscript + + ; Count the step for poison and total steps + ld hl, wPoisonStepCount + inc [hl] + ld hl, wStepCount + inc [hl] + ; Every 256 steps, increase the happiness of all your Pokemon. + jr nz, .skip_happiness + + farcall StepHappiness + +.skip_happiness + ; Every 256 steps, offset from the happiness incrementor by 128 steps, + ; decrease the hatch counter of all your eggs until you reach the first + ; one that is ready to hatch. + ld a, [wStepCount] + cp $80 + jr nz, .skip_egg + + farcall DoEggStep + jr nz, .hatch + +.skip_egg + ; Increase the EXP of (both) DayCare Pokemon by 1. + farcall DayCareStep + + ; Every four steps, deal damage to all Poisoned Pokemon + ld hl, wPoisonStepCount + ld a, [hl] + cp 4 + jr c, .skip_poison + ld [hl], 0 + + farcall DoPoisonStep + jr c, .doscript + +.skip_poison + farcall DoBikeStep + +.done + xor a + ret + +.doscript + ld a, -1 + scf + ret + +.hatch + ld a, 8 + scf + ret +; 96bd3 + +; unused +.unreferenced ; 96bd3 + ld a, 7 + scf + ret +; 96bd7 + +DoRepelStep: ; 96bd7 + ld a, [wRepelEffect] + and a + ret z + + dec a + ld [wRepelEffect], a + ret nz + + ld a, BANK(RepelWoreOffScript) + ld hl, RepelWoreOffScript + call CallScript + scf + ret +; 96beb + +DoPlayerEvent: ; 96beb + ld a, [wScriptRunning] + and a + ret z + + cp PLAYEREVENT_MAPSCRIPT ; run script + ret z + + cp NUM_PLAYER_EVENTS + ret nc + + ld c, a + ld b, 0 + ld hl, PlayerEventScriptPointers + add hl, bc + add hl, bc + add hl, bc + ld a, [hli] + ld [wScriptBank], a + ld a, [hli] + ld [wScriptPos], a + ld a, [hl] + ld [wScriptPos + 1], a + ret +; 96c0c + +PlayerEventScriptPointers: ; 96c0c + dba Invalid_0x96c2d ; 0 + dba SeenByTrainerScript ; 1 + dba TalkToTrainerScript ; 2 + dba FindItemInBallScript ; 3 + dba EdgeWarpScript ; 4 + dba WarpToNewMapScript ; 5 + dba FallIntoMapScript ; 6 + dba Script_OverworldWhiteout ; 7 + dba HatchEggScript ; 8 + dba ChangeDirectionScript ; 9 + dba Invalid_0x96c2d ; 10 +; 96c2d + +Invalid_0x96c2d: ; 96c2d + end +; 96c2e + +; unused + end +; 96c2f + +HatchEggScript: ; 96c2f + callasm OverworldHatchEgg + end +; 96c34 + +WarpToNewMapScript: ; 96c34 + warpsound + newloadmap MAPSETUP_DOOR + end +; 96c38 + +FallIntoMapScript: ; 96c38 + newloadmap MAPSETUP_FALL + playsound SFX_KINESIS + applymovement PLAYER, MovementData_0x96c48 + playsound SFX_STRENGTH + scall LandAfterPitfallScript + end +; 96c48 + +MovementData_0x96c48: ; 96c48 + skyfall + step_end +; 96c4a + +LandAfterPitfallScript: ; 96c4a + earthquake 16 + end +; 96c4d + +EdgeWarpScript: ; 4 + reloadandreturn MAPSETUP_CONNECTION +; 96c4f + +ChangeDirectionScript: ; 9 + deactivatefacing 3 + callasm EnableWildEncounters + end +; 96c56 + +INCLUDE "engine/overworld/scripting.asm" + +INCLUDE "engine/overworld/events_2.asm" diff --git a/engine/overworld/events_2.asm b/engine/overworld/events_2.asm new file mode 100644 index 000000000..6e106541a --- /dev/null +++ b/engine/overworld/events_2.asm @@ -0,0 +1,650 @@ +; More overworld event handling. + + +WarpToSpawnPoint:: ; 97c28 + ld hl, wStatusFlags2 + res STATUSFLAGS2_SAFARI_GAME_F, [hl] + res STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + ret +; 97c30 + +RunMemScript:: ; 97c30 +; If there is no script here, we don't need to be here. + ld a, [wMapReentryScriptQueueFlag] + and a + ret z +; Execute the script at (wMapReentryScriptBank):(wMapReentryScriptAddress). + ld hl, wMapReentryScriptAddress + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wMapReentryScriptBank] + call CallScript + scf +; Clear the buffer for the next script. + push af + xor a + ld hl, wMapReentryScriptQueueFlag + ld bc, 8 + call ByteFill + pop af + ret +; 97c4f + +LoadScriptBDE:: ; 97c4f +; If there's already a script here, don't overwrite. + ld hl, wMapReentryScriptQueueFlag + ld a, [hl] + and a + ret nz +; Set the flag + ld [hl], 1 + inc hl +; Load the script pointer b:de into (wMapReentryScriptBank):(wMapReentryScriptAddress) + ld [hl], b + inc hl + ld [hl], e + inc hl + ld [hl], d + scf + ret +; 97c5f + +TryTileCollisionEvent:: ; 97c5f + call GetFacingTileCoord + ld [wEngineBuffer1], a + ld c, a + farcall CheckFacingTileForStdScript + jr c, .done + + call CheckCutTreeTile + jr nz, .whirlpool + farcall TryCutOW + jr .done + +.whirlpool + ld a, [wEngineBuffer1] + call CheckWhirlpoolTile + jr nz, .waterfall + farcall TryWhirlpoolOW + jr .done + +.waterfall + ld a, [wEngineBuffer1] + call CheckWaterfallTile + jr nz, .headbutt + farcall TryWaterfallOW + jr .done + +.headbutt + ld a, [wEngineBuffer1] + call CheckHeadbuttTreeTile + jr nz, .surf + farcall TryHeadbuttOW + jr c, .done + jr .noevent + +.surf + farcall TrySurfOW + jr nc, .noevent + jr .done + +.noevent + xor a + ret + +.done + call PlayClickSFX + ld a, $ff + scf + ret +; 97cc0 + + +RandomEncounter:: ; 97cc0 +; Random encounter + + call CheckWildEncounterCooldown + jr c, .nope + call CanUseSweetScent + jr nc, .nope + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BUG_CONTEST_TIMER_F, [hl] + jr nz, .bug_contest + farcall TryWildEncounter + jr nz, .nope + jr .ok + +.bug_contest + call _TryWildEncounter_BugContest + jr nc, .nope + jr .ok_bug_contest + +.nope + ld a, 1 + and a + ret + +.ok + ld a, BANK(WildBattleScript) + ld hl, WildBattleScript + jr .done + +.ok_bug_contest + ld a, BANK(BugCatchingContestBattleScript) + ld hl, BugCatchingContestBattleScript + jr .done + +.done + call CallScript + scf + ret +; 97cf9 + +WildBattleScript: ; 97cf9 + randomwildmon + startbattle + reloadmapafterbattle + end +; 97cfd + +CanUseSweetScent:: ; 97cfd + ld hl, wStatusFlags + bit STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl] + jr nz, .no + ld a, [wEnvironment] + cp CAVE + jr z, .ice_check + cp DUNGEON + jr z, .ice_check + farcall CheckGrassCollision + jr nc, .no + +.ice_check + ld a, [wPlayerStandingTile] + call CheckIceTile + jr z, .no + scf + ret + +.no + and a + ret +; 97d23 + +_TryWildEncounter_BugContest: ; 97d23 + call TryWildEncounter_BugContest + ret nc + call ChooseWildEncounter_BugContest + farcall CheckRepelEffect + ret +; 97d31 + +ChooseWildEncounter_BugContest:: ; 97d31 +; Pick a random mon out of ContestMons. + +.loop + call Random + cp 100 << 1 + jr nc, .loop + srl a + + ld hl, ContestMons + ld de, 4 +.CheckMon: + sub [hl] + jr c, .GotMon + add hl, de + jr .CheckMon + +.GotMon: + inc hl + +; Species + ld a, [hli] + ld [wTempWildMonSpecies], a + +; Min level + ld a, [hli] + ld d, a + +; Max level + ld a, [hl] + + sub d + jr nz, .RandomLevel + +; If min and max are the same. + ld a, d + jr .GotLevel + +.RandomLevel: +; Get a random level between the min and max. + ld c, a + inc c + call Random + ld a, [hRandomAdd] + call SimpleDivide + add d + +.GotLevel: + ld [wCurPartyLevel], a + + xor a + ret +; 97d64 + +TryWildEncounter_BugContest: ; 97d64 + ld a, [wPlayerStandingTile] + call CheckSuperTallGrassTile + ld b, 40 percent + jr z, .ok + ld b, 20 percent + +.ok + farcall ApplyMusicEffectOnEncounterRate + farcall ApplyCleanseTagEffectOnEncounterRate + call Random + ld a, [hRandomAdd] + cp b + ret c + ld a, 1 + and a + ret +; 97d87 + + +INCLUDE "data/wild/bug_contest_mons.asm" + + +DoBikeStep:: ; 97db3 + nop + nop + ; If the bike shop owner doesn't have our number, or + ; if we've already gotten the call, we don't have to + ; be here. + ld hl, wStatusFlags2 + bit STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl] + jr z, .NoCall + + ; If we're not on the bike, we don't have to be here. + ld a, [wPlayerState] + cp PLAYER_BIKE + jr nz, .NoCall + + ; If we're not in an area of phone service, we don't + ; have to be here. + call GetMapPhoneService + and a + jr nz, .NoCall + + ; Check the bike step count and check whether we've + ; taken 65536 of them yet. + ld hl, wBikeStep + ld a, [hli] + ld d, a + ld e, [hl] + cp 255 + jr nz, .increment + ld a, e + cp 255 + jr z, .dont_increment + +.increment + inc de + ld [hl], e + dec hl + ld [hl], d + +.dont_increment + ; If we've taken at least 1024 steps, have the bike + ; shop owner try to call us. + ld a, d + cp HIGH(1024) + jr c, .NoCall + + ; If a call has already been queued, don't overwrite + ; that call. + ld a, [wSpecialPhoneCallID] + and a + jr nz, .NoCall + + ; Queue the call. + ld a, SPECIALCALL_BIKESHOP + ld [wSpecialPhoneCallID], a + xor a + ld [wSpecialPhoneCallID + 1], a + ld hl, wStatusFlags2 + res STATUSFLAGS2_BIKE_SHOP_CALL_F, [hl] + scf + ret + +.NoCall: + xor a + ret +; 97df9 + +ClearCmdQueue:: ; 97df9 + ld hl, wCmdQueue + ld de, 6 + ld c, 4 + xor a +.loop + ld [hl], a + add hl, de + dec c + jr nz, .loop + ret +; 97e08 + +HandleCmdQueue:: ; 97e08 + ld hl, wCmdQueue + xor a +.loop + ld [hMapObjectIndexBuffer], a + ld a, [hl] + and a + jr z, .skip + push hl + ld b, h + ld c, l + call HandleQueuedCommand + pop hl + +.skip + ld de, CMDQUEUE_ENTRY_SIZE + add hl, de + ld a, [hMapObjectIndexBuffer] + inc a + cp CMDQUEUE_CAPACITY + jr nz, .loop + ret +; 97e25 + +Unreferenced_GetNthCmdQueueEntry: ; 97e25 + ld hl, wCmdQueue + ld bc, CMDQUEUE_ENTRY_SIZE + call AddNTimes + ld b, h + ld c, l + ret +; 97e31 + +WriteCmdQueue:: ; 97e31 + push bc + push de + call .GetNextEmptyEntry + ld d, h + ld e, l + pop hl + pop bc + ret c + ld a, b + ld bc, CMDQUEUE_ENTRY_SIZE - 1 + call FarCopyBytes + xor a + ld [hl], a + ret +; 97e45 + +.GetNextEmptyEntry: ; 97e45 + ld hl, wCmdQueue + ld de, CMDQUEUE_ENTRY_SIZE + ld c, CMDQUEUE_CAPACITY +.loop + ld a, [hl] + and a + jr z, .done + add hl, de + dec c + jr nz, .loop + scf + ret + +.done + ld a, CMDQUEUE_CAPACITY + sub c + and a + ret +; 97e5c + +DelCmdQueue:: ; 97e5c + ld hl, wCmdQueue + ld de, CMDQUEUE_ENTRY_SIZE + ld c, CMDQUEUE_CAPACITY +.loop + ld a, [hl] + cp b + jr z, .done + add hl, de + dec c + jr nz, .loop + and a + ret + +.done + xor a + ld [hl], a + scf + ret +; 97e72 + +_DelCmdQueue: ; 97e72 + ld hl, CMDQUEUE_TYPE + add hl, bc + ld [hl], 0 + ret +; 97e79 + +HandleQueuedCommand: ; 97e79 + ld hl, CMDQUEUE_TYPE + add hl, bc + ld a, [hl] + cp 5 + jr c, .okay + xor a + +.okay + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + add hl, de + ld a, [hli] + push af + ld a, [hli] + ld h, [hl] + ld l, a + pop af + rst FarCall + ret +; 97e94 + +.Jumptable: ; 97e94 + dba CmdQueue_Null + dba CmdQueue_Null2 + dba CmdQueue_StoneTable + dba CmdQueue_Type3 + dba CmdQueue_Type4 +; 97ea3 + +CmdQueueAnonymousJumptable: ; 97ea3 + ld hl, CMDQUEUE_05 + add hl, bc + ld a, [hl] + pop hl + rst JumpTable + ret +; 97eab + +CmdQueueAnonJT_Increment: ; 97eab + ld hl, CMDQUEUE_05 + add hl, bc + inc [hl] + ret +; 97eb1 + +CmdQueueAnonJT_Decrement: ; 97eb1 + ld hl, CMDQUEUE_05 + add hl, bc + dec [hl] + ret +; 97eb7 + +CmdQueue_Null: ; 97eb7 + ret +; 97eb8 + +CmdQueue_Null2: ; 97eb8 + call ret_2f3e + ret +; 97ebc + +CmdQueue_Type4: ; 97ebc + call CmdQueueAnonymousJumptable + ; anonymous dw + dw .zero + dw .one +; 97ec3 + +.zero ; 97ec3 + ld a, [hSCY] + ld hl, 4 + add hl, bc + ld [hl], a + call CmdQueueAnonJT_Increment +.one ; 97ecd + ld hl, 1 + add hl, bc + ld a, [hl] + dec a + ld [hl], a + jr z, .finish + and $1 + jr z, .add + ld hl, 2 + add hl, bc + ld a, [hSCY] + sub [hl] + ld [hSCY], a + ret + +.add + ld hl, 2 + add hl, bc + ld a, [hSCY] + add [hl] + ld [hSCY], a + ret + +.finish + ld hl, 4 + add hl, bc + ld a, [hl] + ld [hSCY], a + call _DelCmdQueue + ret +; 97ef9 + +CmdQueue_Type3: ; 97ef9 + call CmdQueueAnonymousJumptable + ; anonymous dw + dw .zero + dw .one + dw .two +; 97f02 + +.zero ; 97f02 + call .IsPlayerFacingDown + jr z, .PlayerNotFacingDown + call CmdQueueAnonJT_Increment +.one ; 97f0a + call .IsPlayerFacingDown + jr z, .PlayerNotFacingDown + call CmdQueueAnonJT_Increment + + ld hl, 2 + add hl, bc + ld a, [hl] + ld [wd173], a + ret +; 97f1b + +.two ; 97f1b + call .IsPlayerFacingDown + jr z, .PlayerNotFacingDown + call CmdQueueAnonJT_Decrement + + ld hl, 3 + add hl, bc + ld a, [hl] + ld [wd173], a + ret +; 97f2c + +.PlayerNotFacingDown: ; 97f2c + ld a, $7f + ld [wd173], a + ld hl, 5 + add hl, bc + ld [hl], 0 + ret +; 97f38 + +.IsPlayerFacingDown: ; 97f38 + push bc + ld bc, wPlayerStruct + call GetSpriteDirection + and a + pop bc + ret +; 97f42 + +CmdQueue_StoneTable: ; 97f42 + ld de, wPlayerStruct + ld a, NUM_OBJECT_STRUCTS +.loop + push af + + ld hl, OBJECT_SPRITE + add hl, de + ld a, [hl] + and a + jr z, .next + + ld hl, OBJECT_MOVEMENTTYPE + add hl, de + ld a, [hl] + cp SPRITEMOVEDATA_STRENGTH_BOULDER + jr nz, .next + + ld hl, OBJECT_NEXT_TILE + add hl, de + ld a, [hl] + call CheckPitTile + jr nz, .next + + ld hl, OBJECT_DIRECTION_WALKING + add hl, de + ld a, [hl] + cp STANDING + jr nz, .next + call HandleStoneQueue + jr c, .fall_down_hole + +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, de + ld d, h + ld e, l + + pop af + dec a + jr nz, .loop + ret + +.fall_down_hole + pop af + ret +; 97f7e diff --git a/engine/overworld/init_map.asm b/engine/overworld/init_map.asm new file mode 100644 index 000000000..2eb4998a6 --- /dev/null +++ b/engine/overworld/init_map.asm @@ -0,0 +1,103 @@ +ReanchorBGMap_NoOAMUpdate:: ; 6454 + call DelayFrame + ld a, [hOAMUpdate] + push af + + ld a, $1 + ld [hOAMUpdate], a + ld a, [hBGMapMode] + push af + xor a + ld [hBGMapMode], a + + call .ReanchorBGMap + + pop af + ld [hBGMapMode], a + pop af + ld [hOAMUpdate], a + ld hl, wVramState + set 6, [hl] + ret + +.ReanchorBGMap: + xor a + ld [hLCDCPointer], a + ld [hBGMapMode], a + ld a, $90 + ld [hWY], a + call OverworldTextModeSwitch + ld a, HIGH(vBGMap1) + call .LoadBGMapAddrIntoHRAM + call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap + farcall LoadOW_BGPal7 + farcall ApplyPals + ld a, $1 + ld [hCGBPalUpdate], a + xor a + ld [hBGMapMode], a + ld [hWY], a + farcall HDMATransfer_FillBGMap0WithBlack ; no need to farcall + ld a, HIGH(vBGMap0) + call .LoadBGMapAddrIntoHRAM + xor a ; LOW(vBGMap0) + ld [wBGMapAnchor], a + ld a, HIGH(vBGMap0) + ld [wBGMapAnchor + 1], a + xor a + ld [hSCX], a + ld [hSCY], a + call ApplyBGMapAnchorToObjects + ret + +.LoadBGMapAddrIntoHRAM: ; 64b9 + ld [hBGMapAddress + 1], a + xor a + ld [hBGMapAddress], a + ret + +LoadFonts_NoOAMUpdate:: ; 64bf + ld a, [hOAMUpdate] + push af + ld a, $1 + ld [hOAMUpdate], a + + call .LoadGFX + + pop af + ld [hOAMUpdate], a + ret + +.LoadGFX: + call LoadFontsExtra + ld a, $90 + ld [hWY], a + call SafeUpdateSprites + call LoadStandardFont + ret + +HDMATransfer_FillBGMap0WithBlack: ; 64db + ld a, [rSVBK] + push af + ld a, BANK(wDecompressScratch) + ld [rSVBK], a + + ld a, "■" + ld hl, wDecompressScratch + ld bc, wScratchAttrMap - wDecompressScratch + call ByteFill + ld a, HIGH(wDecompressScratch) + ld [rHDMA1], a + ld a, LOW(wDecompressScratch) + ld [rHDMA2], a + ld a, HIGH(vBGMap0 % $8000) + ld [rHDMA3], a + ld a, LOW(vBGMap0 % $8000) + ld [rHDMA4], a + ld a, $3f + ld [hDMATransfer], a + call DelayFrame + + pop af + ld [rSVBK], a + ret diff --git a/engine/overworld/landmarks.asm b/engine/overworld/landmarks.asm new file mode 100644 index 000000000..f16f48e67 --- /dev/null +++ b/engine/overworld/landmarks.asm @@ -0,0 +1,87 @@ +GetLandmarkCoords: ; 0x1ca896 +; Return coordinates (d, e) of landmark e. + push hl + ld l, e + ld h, 0 + add hl, hl + add hl, hl + ld de, Landmarks + add hl, de + ld a, [hli] + ld e, a + ld d, [hl] + pop hl + ret +; 0x1ca8a5 + + +GetLandmarkName:: ; 0x1ca8a5 +; Copy the name of landmark e to wStringBuffer1. + push hl + push de + push bc + + ld l, e + ld h, 0 + add hl, hl + add hl, hl + ld de, Landmarks + 2 + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + + ld de, wStringBuffer1 + ld c, 18 +.copy + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copy + + pop bc + pop de + pop hl + ret +; 0x1ca8c3 + + +INCLUDE "data/maps/landmarks.asm" + + +RegionCheck: ; 0x1caea1 +; Checks if the player is in Kanto or Johto. +; If in Johto, returns 0 in e. +; If in Kanto, returns 1 in e. + ld a, [wMapGroup] + ld b, a + ld a, [wMapNumber] + ld c, a + call GetWorldMapLocation + cp FAST_SHIP ; S.S. Aqua + jr z, .johto + cp SPECIAL_MAP + jr nz, .checkagain + +; In a special map, get the backup map group / map id + ld a, [wBackupMapGroup] + ld b, a + ld a, [wBackupMapNumber] + ld c, a + call GetWorldMapLocation + +.checkagain + cp KANTO_LANDMARK + jr c, .johto + +; Victory Road area is considered to be Johto. + cp VICTORY_ROAD + jr c, .kanto + +.johto + ld e, JOHTO_REGION + ret +.kanto + ld e, KANTO_REGION + ret diff --git a/engine/overworld/map_object_action.asm b/engine/overworld/map_object_action.asm new file mode 100755 index 000000000..c82cd80a2 --- /dev/null +++ b/engine/overworld/map_object_action.asm @@ -0,0 +1,313 @@ +ObjectActionPairPointers: ; 445f +; entries correspond to OBJECT_ACTION_* constants + dw SetFacingStanding, SetFacingStanding + dw SetFacingStandAction, SetFacingCurrent + dw SetFacingStepAction, SetFacingCurrent + dw SetFacingBumpAction, SetFacingCurrent + dw SetFacingCounterclockwiseSpin, SetFacingCurrent + dw SetFacingCounterclockwiseSpin2, SetFacingStanding + dw SetFacingFish, SetFacingFish + dw SetFacingShadow, SetFacingStanding + dw SetFacingEmote, SetFacingEmote + dw SetFacingBigDollSym, SetFacingBigDollSym + dw SetFacingBounce, SetFacingFreezeBounce + dw SetFacingWeirdTree, SetFacingCurrent + dw SetFacingBigDollAsym, SetFacingBigDollAsym + dw SetFacingBigDoll, SetFacingBigDoll + dw SetFacingBoulderDust, SetFacingStanding + dw SetFacingGrassShake, SetFacingStanding + dw SetFacingSkyfall, SetFacingCurrent +; 44a3 + +SetFacingStanding: ; 44a3 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], STANDING + ret +; 44aa + +SetFacingCurrent: ; 44aa + call GetSpriteDirection + or FACING_STEP_DOWN_0 ; useless + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 44b5 + +SetFacingStandAction: ; 44b5 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld a, [hl] + and 1 + jr nz, SetFacingStepAction + jp SetFacingCurrent +; 44c1 + +SetFacingStepAction: ; 44c1 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit SLIDING, [hl] + jp nz, SetFacingCurrent + + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + inc a + and %00001111 + ld [hl], a + + rrca + rrca + and %00000011 + ld d, a + + call GetSpriteDirection + or FACING_STEP_DOWN_0 ; useless + or d + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 44e4 + +SetFacingSkyfall: ; 44e4 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit SLIDING, [hl] + jp nz, SetFacingCurrent + + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + add 2 + and %00001111 + ld [hl], a + + rrca + rrca + and %00000011 + ld d, a + + call GetSpriteDirection + or FACING_STEP_DOWN_0 ; useless + or d + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 4508 + +SetFacingBumpAction: ; 4508 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit SLIDING, [hl] + jp nz, SetFacingCurrent + + ld hl, OBJECT_STEP_FRAME + add hl, bc + inc [hl] + + ld a, [hl] + rrca + rrca + rrca + and %00000011 + ld d, a + + call GetSpriteDirection + or FACING_STEP_DOWN_0 ; useless + or d + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 4529 + +SetFacingCounterclockwiseSpin: ; 4529 + call CounterclockwiseSpinAction + ld hl, OBJECT_FACING + add hl, bc + ld a, [hl] + or FACING_STEP_DOWN_0 ; useless + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 4539 + +SetFacingCounterclockwiseSpin2: ; 4539 + call CounterclockwiseSpinAction + jp SetFacingStanding +; 453f + +CounterclockwiseSpinAction: ; 453f +; Here, OBJECT_STEP_FRAME consists of two 2-bit components, +; using only bits 0,1 and 4,5. +; bits 0,1 is a timer (4 overworld frames) +; bits 4,5 determines the facing - the direction is counterclockwise. + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + and %11110000 + ld e, a + + ld a, [hl] + inc a + and %00001111 + ld d, a + cp 4 + jr c, .ok + + ld d, 0 + ld a, e + add $10 + and %00110000 + ld e, a + +.ok + ld a, d + or e + ld [hl], a + + swap e + ld d, 0 + ld hl, .Directions + add hl, de + ld a, [hl] + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a + ret +; 456a + +.Directions: ; 456a + db OW_DOWN, OW_RIGHT, OW_UP, OW_LEFT +; 456e + +SetFacingFish: ; 456e + call GetSpriteDirection + rrca + rrca + add FACING_FISH_DOWN + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 457b + +SetFacingShadow: ; 457b + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_SHADOW + ret +; 4582 + +SetFacingEmote: ; 4582 emote + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_EMOTE + ret +; 4589 + +SetFacingBigDollSym: ; 4589 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_BIG_DOLL_SYM + ret +; 4590 + +SetFacingBounce: ; 4590 + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + inc a + and %00001111 + ld [hl], a + and %00001000 + jr z, SetFacingFreezeBounce + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_STEP_UP_0 + ret +; 45a4 + +SetFacingFreezeBounce: ; 45a4 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_STEP_DOWN_0 + ret +; 45ab + +SetFacingWeirdTree: ; 45ab + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + inc a + ld [hl], a + and %00001100 + rrca + rrca + add FACING_WEIRD_TREE_0 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], a + ret +; 45be + +SetFacingBigDollAsym: ; 45be + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], FACING_BIG_DOLL_ASYM + ret +; 45c5 + +SetFacingBigDoll: ; 45c5 + ld a, [wVariableSprites + SPRITE_BIG_DOLL - SPRITE_VARS] + ld d, FACING_BIG_DOLL_SYM ; symmetric + cp SPRITE_BIG_SNORLAX + jr z, .ok + cp SPRITE_BIG_LAPRAS + jr z, .ok + ld d, FACING_BIG_DOLL_ASYM ; asymmetric + +.ok + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], d + ret +; 45da + +SetFacingBoulderDust: ; 45da + ld hl, OBJECT_STEP_FRAME + add hl, bc + inc [hl] + ld a, [hl] + + ld hl, OBJECT_FACING_STEP + add hl, bc + and 2 + ld a, FACING_BOULDER_DUST_1 + jr z, .ok + inc a ; FACING_BOULDER_DUST_2 +.ok + ld [hl], a + ret +; 45ed + +SetFacingGrassShake: ; 45ed + ld hl, OBJECT_STEP_FRAME + add hl, bc + inc [hl] + ld a, [hl] + ld hl, OBJECT_FACING_STEP + add hl, bc + and 4 + ld a, FACING_GRASS_1 + jr z, .ok + inc a ; FACING_GRASS_2 + +.ok + ld [hl], a + ret +; 4600 diff --git a/engine/overworld/map_objects.asm b/engine/overworld/map_objects.asm new file mode 100644 index 000000000..8d6f4082f --- /dev/null +++ b/engine/overworld/map_objects.asm @@ -0,0 +1,3123 @@ +INCLUDE "data/sprites/facings.asm" + +INCLUDE "data/sprites/map_objects.asm" + + +; 4357 +DeleteMapObject:: ; 4357 + push bc + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + push af + ld h, b + ld l, c + ld bc, OBJECT_STRUCT_LENGTH + xor a + call ByteFill + pop af + cp -1 + jr z, .ok + bit 7, a + jr nz, .ok + call GetMapObject + ld hl, OBJECT_SPRITE + add hl, bc + ld [hl], -1 +.ok + pop bc + ret +; 437b + +Function437b: ; 437b + call .CheckObjectStillVisible + ret c + call .HandleStepType + call .HandleObjectAction + ret + +.CheckObjectStillVisible: + ld hl, OBJECT_FLAGS2 + add hl, bc + res 6, [hl] + ld a, [wXCoord] + ld e, a + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .ok + cp MAPOBJECT_SCREEN_WIDTH + jr nc, .ok + ld a, [wYCoord] + ld e, a + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .ok + cp MAPOBJECT_SCREEN_HEIGHT + jr nc, .ok + jr .yes + +.ok + ld hl, OBJECT_FLAGS2 + add hl, bc + set 6, [hl] + ld a, [wXCoord] + ld e, a + ld hl, OBJECT_INIT_X + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .ok2 + cp MAPOBJECT_SCREEN_WIDTH + jr nc, .ok2 + ld a, [wYCoord] + ld e, a + ld hl, OBJECT_INIT_Y + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .ok2 + cp MAPOBJECT_SCREEN_HEIGHT + jr nc, .ok2 +.yes + and a + ret + +.ok2 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit 1, [hl] + jr nz, .yes2 + call DeleteMapObject + scf + ret + +.yes2 + ld hl, OBJECT_FLAGS2 + add hl, bc + set 6, [hl] + and a + ret + +.HandleStepType: + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld a, [hl] + and a + jr z, .zero + ld hl, OBJECT_FLAGS2 + add hl, bc + bit 5, [hl] + jr nz, .bit5 + cp STEP_TYPE_SLEEP + jr z, .one + jr .ok3 + +.zero + call ObjectMovementReset + ld hl, OBJECT_FLAGS2 + add hl, bc + bit 5, [hl] + jr nz, .bit5 +.one + call MapObjectMovementPattern + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld a, [hl] + and a + ret z + cp STEP_TYPE_SLEEP + ret z +.ok3 + ld hl, StepTypesJumptable + rst JumpTable + ret + +.bit5 + ret + +.HandleObjectAction: + ld hl, OBJECT_FLAGS1 + add hl, bc + bit INVISIBLE, [hl] + jr nz, SetFacingStanding + ld hl, OBJECT_FLAGS2 + add hl, bc + bit 6, [hl] + jr nz, SetFacingStanding + bit 5, [hl] + jr nz, asm_4448 + ld de, ObjectActionPairPointers ; use first column + jr _HandleObjectAction +; 4440 + +Function4440: ; 4440 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit INVISIBLE, [hl] + jr nz, SetFacingStanding +asm_4448 + ld de, ObjectActionPairPointers + 2 ; use second column + jr _HandleObjectAction +; 444d + +_HandleObjectAction +; call [4 * wObjectStructs[ObjInd, OBJECT_ACTION] + de] + ld hl, OBJECT_ACTION + add hl, bc + ld a, [hl] + ld l, a + ld h, 0 + add hl, hl + add hl, hl + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call _hl_ + ret +; 445f + +INCLUDE "engine/overworld/map_object_action.asm" + +CopyNextCoordsTileToStandingCoordsTile: ; 4600 + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_MAP_X + add hl, bc + ld [hl], a + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [hl] + ld hl, OBJECT_MAP_Y + add hl, bc + ld [hl], a + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + ld hl, OBJECT_STANDING_TILE + add hl, bc + ld [hl], a + call SetTallGrassFlags + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call UselessAndA + ret +; 462a + +Function462a: ; 462a + ld hl, OBJECT_MAP_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld [hl], a + ld hl, OBJECT_MAP_Y + add hl, bc + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld [hl], a + ret +; 463f + +UpdateTallGrassFlags: ; 463f + ld hl, OBJECT_FLAGS2 + add hl, bc + bit OVERHEAD, [hl] + jr z, .ok + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call SetTallGrassFlags +.ok + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call UselessAndA + ret c ; never happens + ld hl, OBJECT_STANDING_TILE + add hl, bc + ld a, [hl] + call UselessAndA + ret +; 4661 + +SetTallGrassFlags: ; 4661 + call CheckSuperTallGrassTile + jr z, .set + call CheckGrassTile + jr c, .reset +.set + ld hl, OBJECT_FLAGS2 + add hl, bc + set OVERHEAD, [hl] + ret + +.reset + ld hl, OBJECT_FLAGS2 + add hl, bc + res OVERHEAD, [hl] + ret +; 4679 + +UselessAndA: ; 4679 + and a + ret +; 467b + +EndSpriteMovement: ; 467b + xor a + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], a + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a ; OBJECT_1E + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 4690 + +InitStep: ; 4690 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], a + ld hl, OBJECT_FLAGS1 + add hl, bc + bit FIXED_FACING, [hl] + jr nz, GetNextTile + add a + add a + and %00001100 + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a +GetNextTile: ; 46a6 + call GetStepVector + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld a, d + call GetStepVectorSign + ld hl, OBJECT_MAP_X + add hl, bc + add [hl] + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld [hl], a + ld d, a + ld a, e + call GetStepVectorSign + ld hl, OBJECT_MAP_Y + add hl, bc + add [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld [hl], a + ld e, a + push bc + call GetCoordTile + pop bc + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld [hl], a + ret +; 46d7 + +AddStepVector: ; 46d7 + call GetStepVector + ld hl, OBJECT_SPRITE_X + add hl, bc + ld a, [hl] + add d + ld [hl], a + ld hl, OBJECT_SPRITE_Y + add hl, bc + ld a, [hl] + add e + ld [hl], a + ret +; 46e9 + +GetStepVector: ; 46e9 +; Return (x, y, duration, speed) in (d, e, a, h). + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + and %00001111 + add a + add a + ld l, a + ld h, 0 + ld de, StepVectors + add hl, de + ld d, [hl] + inc hl + ld e, [hl] + inc hl + ld a, [hli] + ld h, [hl] + ret +; 4700 + +StepVectors: ; 4700 +; x, y, duration, speed + ; slow + db 0, 1, 16, 1 + db 0, -1, 16, 1 + db -1, 0, 16, 1 + db 1, 0, 16, 1 + ; normal + db 0, 2, 8, 2 + db 0, -2, 8, 2 + db -2, 0, 8, 2 + db 2, 0, 8, 2 + ; fast + db 0, 4, 4, 4 + db 0, -4, 4, 4 + db -4, 0, 4, 4 + db 4, 0, 4, 4 +; 4730 + +GetStepVectorSign: ; 4730 + add a + ret z ; 0 or 128 + ld a, 1 + ret nc ; 1 - 127 + ld a, -1 + ret ; 129 - 255 +; 4738 + +UpdatePlayerStep: ; 4738 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + and %00000011 + ld [wPlayerStepDirection], a + call AddStepVector + ld a, [wPlayerStepVectorX] + add d + ld [wPlayerStepVectorX], a + ld a, [wPlayerStepVectorY] + add e + ld [wPlayerStepVectorY], a + ld hl, wPlayerStepFlags + set 5, [hl] + ret +; 4759 + +Unreferenced_Function4759: ; 4759 + push bc + ld e, a + ld d, 0 + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + call GetMapObject + add hl, de + ld a, [hl] + pop bc + ret +; 4769 + +RestoreDefaultMovement: ; 4769 + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + cp -1 + jr z, .ok + push bc + call GetMapObject + ld hl, MAPOBJECT_MOVEMENT + add hl, bc + ld a, [hl] + pop bc + ret + +.ok + ld a, SPRITEMOVEFN_STANDING + ret +; 4780 + +ClearObjectMovementByteIndex: ; 4780 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld [hl], 0 + ret +; 4787 + +IncrementObjectMovementByteIndex: ; 4787 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + inc [hl] + ret +; 478d + +DecrementObjectMovementByteIndex: ; 478d + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + dec [hl] + ret +; 4793 + +MovementAnonymousJumptable: ; 4793 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld a, [hl] + pop hl + rst JumpTable + ret +; 479b + +ClearObjectStructField1c: ; 479b + ld hl, OBJECT_1C + add hl, bc + ld [hl], 0 + ret +; 47a2 + +IncrementObjectStructField1c: ; 47a2 + ld hl, OBJECT_1C + add hl, bc + inc [hl] + ret +; 47a8 + +Field1cAnonymousJumptable: ; 47a8 + ld hl, OBJECT_1C + add hl, bc + ld a, [hl] + pop hl + rst JumpTable + ret +; 47b0 + +GetValueObjectStructField1c: ; 47b0 + ld hl, OBJECT_1C + add hl, bc + ld a, [hl] + ret +; 47b6 + +SetValueObjectStructField1c: ; 47b6 + ld hl, OBJECT_1C + add hl, bc + ld [hl], a + ret +; 47bc + +ObjectMovementReset: ; 47bc + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + push bc + call GetCoordTile + pop bc + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld [hl], a + call CopyNextCoordsTileToStandingCoordsTile + call EndSpriteMovement + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 47dd + +MapObjectMovementPattern: ; 47dd + call ClearObjectStructField1c + call GetSpriteMovementFunction + ld a, [hl] + ld hl, .Pointers + rst JumpTable + ret + +.Pointers: ; 47e9 +; entries correspond to SPRITEMOVEFN_* constants + dw .Null_00 ; 00 + dw .RandomWalkY ; 01 + dw .RandomWalkX ; 02 + dw .RandomWalkXY ; 03 + dw .RandomSpin1 ; 04 + dw .RandomSpin2 ; 05 + dw .Standing ; 06 + dw .ObeyDPad ; 07 + dw .Movement08 ; 08 + dw .Movement09 ; 09 + dw .Movement0a ; 0a + dw .Movement0b ; 0b + dw .Movement0c ; 0c + dw .Movement0d ; 0d + dw .Movement0e ; 0e + dw .Follow ; 0f + dw .Script ; 10 + dw .Strength ; 11 + dw .FollowNotExact ; 12 + dw .MovementShadow ; 13 + dw .MovementEmote ; 14 + dw .MovementBigStanding ; 15 + dw .MovementBouncing ; 16 + dw .MovementScreenShake ; 17 + dw .MovementSpinClockwise ; 18 + dw .MovementSpinCounterclockwise ; 19 + dw .MovementBoulderDust ; 1a + dw .MovementShakingGrass ; 1b + +.Null_00: + ret + +.RandomWalkY: + call Random + ld a, [hRandomAdd] + and %00000001 + jp .RandomWalkContinue + +.RandomWalkX: + call Random + ld a, [hRandomAdd] + and %00000001 + or %00000010 + jp .RandomWalkContinue + +.RandomWalkXY: + call Random + ld a, [hRandomAdd] + and %00000011 + jp .RandomWalkContinue + +.RandomSpin1: + call Random + ld a, [hRandomAdd] + and %00001100 + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a + jp RandomStepDuration_Slow + +.RandomSpin2: + ld hl, OBJECT_FACING + add hl, bc + ld a, [hl] + and %00001100 + ld d, a + call Random + ld a, [hRandomAdd] + and %00001100 + cp d + jr nz, .keep + xor %00001100 +.keep + ld [hl], a + jp RandomStepDuration_Fast + +.Standing: + call Function462a + call EndSpriteMovement + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_05 + ret + +.ObeyDPad: + ld hl, Function5000 + jp HandleMovementData + +.Movement08: + ld hl, Function5015 + jp HandleMovementData + +.Movement09: + ld hl, Function5026 + jp HandleMovementData + +.Movement0a: + jp _GetMovementObject + +.Movement0b: + jp _GetMovementObject + +.Movement0c: + jp _GetMovementObject + +.Movement0d: + ld hl, Function5000 + jp HandleMovementData + +.Movement0e: + jp _GetMovementObject + +.Follow: + ld hl, GetFollowerNextMovementByte + jp HandleMovementData + +.Script: + ld hl, GetMovementByte + jp HandleMovementData + +.Strength: + call MovementAnonymousJumptable + dw .Strength_Start + dw .Strength_Stop + +.Strength_Start: + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call CheckPitTile + jr z, .on_pit + ld hl, OBJECT_FLAGS2 + add hl, bc + bit 2, [hl] + res 2, [hl] + jr z, .ok + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + and %00000011 + or 0 + call InitStep + call Function6ec1 + jr c, .ok2 + ld de, SFX_STRENGTH + call PlaySFX + call SpawnStrengthBoulderDust + call UpdateTallGrassFlags + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_0F + ret + +.ok2 + call Function462a +.ok + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret + +.on_pit + call IncrementObjectMovementByteIndex +.Strength_Stop: + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret + +.FollowNotExact: + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + push bc + call GetObjectStruct + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + cp STANDING + jr z, .standing + ld hl, OBJECT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr z, .equal + jr c, .less + ld a, 3 + jr .done + +.less + ld a, 2 + jr .done + +.equal + ld hl, OBJECT_MAP_Y + add hl, bc + ld a, [hl] + cp e + jr z, .standing + jr c, .less2 + ld a, 0 + jr .done + +.less2 + ld a, 1 +.done + ld d, a + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + and %00001100 + or d + pop bc + jp NormalStep + +.standing + pop bc + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + ret + +.MovementBigStanding: + call EndSpriteMovement + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_BIG_DOLL_SYM + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_04 + ret + +.MovementBouncing: + call EndSpriteMovement + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_BOUNCE + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_04 + ret + +.MovementSpinCounterclockwise: + call MovementAnonymousJumptable + dw .MovementSpinInit + dw .MovementSpinRepeat + dw .MovementSpinTurnLeft + +.MovementSpinClockwise: + call MovementAnonymousJumptable + dw .MovementSpinInit + dw .MovementSpinRepeat + dw .MovementSpinTurnRight + +.MovementSpinInit: + call EndSpriteMovement + call IncrementObjectMovementByteIndex +.MovementSpinRepeat: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + ld a, $10 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + call IncrementObjectMovementByteIndex + ret + +.MovementSpinTurnLeft: + ld de, .DirectionData_Counterclockwise + call .MovementSpinNextFacing + jr .MovementSpinCounterclockwise + +.DirectionData_Counterclockwise: ; 49c0 + db OW_RIGHT, OW_LEFT, OW_DOWN, OW_UP + +.MovementSpinTurnRight: + ld de, .DirectionData_Clockwise + call .MovementSpinNextFacing + jr .MovementSpinClockwise + +.DirectionData_Clockwise: ; 49cc + db OW_LEFT, OW_RIGHT, OW_UP, OW_DOWN + +.MovementSpinNextFacing: + ld hl, OBJECT_FACING + add hl, bc + ld a, [hl] + and %00001100 + rrca + rrca + push hl + ld l, a + ld h, 0 + add hl, de + ld a, [hl] + pop hl + ld [hl], a + call DecrementObjectMovementByteIndex + ret + +.MovementShadow: + call ._MovementShadow_Grass_Emote_BoulderDust + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SHADOW + ld hl, OBJECT_STEP_DURATION + add hl, de + ld a, [hl] + inc a + add a + add 0 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_DIRECTION_WALKING + add hl, de + ld a, [hl] + maskbits NUM_DIRECTIONS + ld d, 1 * 8 + 6 + cp DOWN + jr z, .ok_13 + cp UP + jr z, .ok_13 + ld d, 1 * 8 + 4 +.ok_13 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], d + ld hl, OBJECT_SPRITE_X_OFFSET + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TRACKING_OBJECT + ret + +.MovementEmote: + call EndSpriteMovement + call ._MovementShadow_Grass_Emote_BoulderDust + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_EMOTE + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 0 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], -2 * 8 + ld hl, OBJECT_SPRITE_X_OFFSET + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TRACKING_OBJECT + ret + +.MovementBoulderDust: + call EndSpriteMovement + call ._MovementShadow_Grass_Emote_BoulderDust + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_BOULDER_DUST + ld hl, OBJECT_STEP_DURATION + add hl, de + ld a, [hl] + inc a + add a + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_DIRECTION_WALKING + add hl, de + ld a, [hl] + and %00000011 + ld e, a + ld d, 0 + ld hl, .data_4a81 + add hl, de + add hl, de + ld d, [hl] + inc hl + ld e, [hl] + ld hl, OBJECT_SPRITE_X_OFFSET + add hl, bc + ld [hl], d + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], e + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TRACKING_OBJECT + ret + +.data_4a81 ; 4a81 + ; x, y + db 0, -4 + db 0, 8 + db 6, 2 + db -6, 2 + +.MovementShakingGrass: + call EndSpriteMovement + call ._MovementShadow_Grass_Emote_BoulderDust + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_GRASS_SHAKE + ld hl, OBJECT_STEP_DURATION + add hl, de + ld a, [hl] + add -1 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TRACKING_OBJECT + ret + +._MovementShadow_Grass_Emote_BoulderDust: + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + push bc + call GetObjectStruct + ld d, b + ld e, c + pop bc + ld hl, OBJECT_1D + add hl, bc + ld [hl], e + inc hl + ld [hl], d + ret + +.MovementScreenShake: + call EndSpriteMovement + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_00 + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + call ._MovementScreenShake + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], e + ld hl, OBJECT_1E + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_15 + ret + +._MovementScreenShake: + ld d, a + and %00111111 + ld e, a + ld a, d + rlca + rlca + and %00000011 + ld d, a + inc d + ld a, 1 +.loop + dec d + ret z + add a + jr .loop + +.RandomWalkContinue: + call InitStep + call Function6ec1 ; check whether the object can move in that direction + jr c, .NewDuration + call UpdateTallGrassFlags + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STEP + ld hl, wCenteredObject + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr z, .load_6 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_07 + ret + +.load_6 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_PLAYER_WALK + ret + +.NewDuration: + call EndSpriteMovement + call Function462a +RandomStepDuration_Slow: ; 4b1d + call Random + ld a, [hRandomAdd] + and %01111111 + jr SetRandomStepDuration +; 4b26 + +RandomStepDuration_Fast: ; 4b26 + call Random + ld a, [hRandomAdd] + and %00011111 +SetRandomStepDuration: ; 4b2d + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + ret +; 4b45 + +StepTypesJumptable: ; 4b45 +; entries correspond to STEP_TYPE_* constants + dw ObjectMovementReset ; 00 + dw MapObjectMovementPattern ; 01 + dw NPCStep ; 02 + dw StepType03 ; 03 + dw StepType04 ; 04 + dw StepType05 ; 05 + dw PlayerStep ; 06 + dw StepType07 ; 07 + dw NPCJump ; 08 + dw PlayerJump ; 09 + dw PlayerOrNPCTurnStep ; 0a + dw StepTypeBump ; 0b + dw TeleportFrom ; 0c + dw TeleportTo ; 0d + dw Skyfall ; 0e + dw StepType0f ; 0f + dw GotBiteStep ; 10 + dw RockSmashStep ; 11 + dw ReturnDigStep ; 12 + dw StepTypeTrackingObject ; 13 + dw StepType14 ; 14 + dw StepType15 ; 15 + dw StepType16 ; 16 + dw StepType17 ; 17 + dw StepType18 ; 18 + dw SkyfallTop ; 19 +; 4b79 + +WaitStep_InPlace: ; 4b79 + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4b86 + +NPCJump: ; 4b86 + call Field1cAnonymousJumptable +; anonymous dw + dw .Jump + dw .Land + +.Jump: + call AddStepVector + call UpdateJumpPosition + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call CopyNextCoordsTileToStandingCoordsTile + call GetNextTile + ld hl, OBJECT_FLAGS2 + add hl, bc + res 3, [hl] + call IncrementObjectStructField1c + ret + +.Land: + call AddStepVector + call UpdateJumpPosition + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4bbf + +PlayerJump: ; 4bbf + call Field1cAnonymousJumptable +; anonymous dw + dw .initjump + dw .stepjump + dw .initland + dw .stepland + +.initjump + ld hl, wPlayerStepFlags + set 7, [hl] + call IncrementObjectStructField1c +.stepjump + call UpdateJumpPosition + call UpdatePlayerStep + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_FLAGS2 + add hl, bc + res 3, [hl] + ld hl, wPlayerStepFlags + set 6, [hl] + set 4, [hl] + call IncrementObjectStructField1c + ret + +.initland + call GetNextTile + ld hl, wPlayerStepFlags + set 7, [hl] + call IncrementObjectStructField1c +.stepland + call UpdateJumpPosition + call UpdatePlayerStep + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, wPlayerStepFlags + set 6, [hl] + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4c18 + +TeleportFrom: ; 4c18 + call Field1cAnonymousJumptable +; anonymous dw + dw .InitSpin + dw .DoSpin + dw .InitSpinRise + dw .DoSpinRise +; 4c23 + +.InitSpin: + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c +.DoSpin: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call IncrementObjectStructField1c + ret + +.InitSpinRise: + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_1F + add hl, bc + ld [hl], $10 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + ld hl, OBJECT_FLAGS2 + add hl, bc + res 3, [hl] + call IncrementObjectStructField1c +.DoSpinRise: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + ld hl, OBJECT_1F + add hl, bc + inc [hl] + ld a, [hl] + ld d, $60 + call Sine + ld a, h + sub $60 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4c89 + +TeleportTo: ; 4c89 + call Field1cAnonymousJumptable +; anonymous dw + dw .InitWait + dw .DoWait + dw .InitDescent + dw .DoDescent + dw .InitFinalSpin + dw .DoFinalSpin + dw .FinishStep +; 4c9a + +.InitWait: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_00 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c + ret +; 4caa + +.DoWait: + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call IncrementObjectStructField1c +.InitDescent: + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_1F + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c + ret +; 4cc9 + +.DoDescent: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + ld hl, OBJECT_1F + add hl, bc + inc [hl] + ld a, [hl] + ld d, $60 + call Sine + ld a, h + sub $60 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call IncrementObjectStructField1c +.InitFinalSpin: + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c + ret +; 4cf5 + +.DoFinalSpin: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz +.FinishStep: + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4d14 + +Skyfall: ; 4d14 + call Field1cAnonymousJumptable +; anonymous dw + dw .Init + dw .Step + dw .Fall + dw .Finish +; 4d1f + +.Init: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_00 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c +.Step: + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STEP + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_1F + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c +.Fall: + ld hl, OBJECT_1F + add hl, bc + inc [hl] + ld a, [hl] + ld d, $60 + call Sine + ld a, h + sub $60 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call IncrementObjectStructField1c +.Finish: + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4d7e + +GotBiteStep: ; 4d7e + call Field1cAnonymousJumptable +; anonymous dw + dw .Init + dw .Run +; 4d85 + +.Init: + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 8 + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], 0 + call IncrementObjectStructField1c +.Run: + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld a, [hl] + xor 1 + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4daf + +RockSmashStep: ; 4daf + call .Step + jp WaitStep_InPlace +; 4db5 + +.Step: + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld a, [hl] + and %00000001 + ld a, OBJECT_ACTION_STAND + jr z, .yes + ld a, OBJECT_ACTION_00 +.yes + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], a + ret +; 4dc8 + +ReturnDigStep: ; 4dc8 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld a, [hl] + and %00000001 + ld a, OBJECT_ACTION_SPIN + jr z, .yes + ld a, OBJECT_ACTION_SPIN_FLICKER +.yes + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], a + jp WaitStep_InPlace +; 4ddd + +StepType03: ; 4ddd + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4df0 + +StepType18: ; 4df0 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + jp DeleteMapObject +; 4dff + +StepTypeBump: ; 4dff + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4e0c + +StepType05: ; 4e0c + call Field1cAnonymousJumptable +; anonymous dw + dw .Reset + dw StepType04 + +.Reset: + call RestoreDefaultMovement + call GetInitialFacing + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a + call IncrementObjectStructField1c +StepType04: ; 4e21 + call Stubbed_Function4fb2 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 4e2b + +NPCStep: ; 4e2b + call Stubbed_Function4fb2 + call AddStepVector + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4e47 + +StepType07: ; 4e47 + call AddStepVector + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call CopyNextCoordsTileToStandingCoordsTile + jp RandomStepDuration_Slow +; 4e56 + +PlayerStep: ; 4e56 +; AnimateStep? + call Field1cAnonymousJumptable +; anonymous dw + dw .init + dw .step + +.init + ld hl, wPlayerStepFlags + set 7, [hl] + call IncrementObjectStructField1c +.step + call UpdatePlayerStep + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, wPlayerStepFlags + set 6, [hl] + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4e83 + +PlayerOrNPCTurnStep: ; 4e83 + call Field1cAnonymousJumptable +; anonymous dw + dw .init1 + dw .step1 + dw .init2 + dw .step2 + +.init1 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld a, [hl] + ld [hl], 2 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 2 + call IncrementObjectStructField1c +.step1 + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + call IncrementObjectStructField1c +.init2 + ld hl, OBJECT_1D ; new facing + add hl, bc + ld a, [hl] + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 2 + call IncrementObjectStructField1c +.step2 + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4ecd + +StepType0f: ; 4ecd + call AddStepVector + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + push bc + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + ld b, a + farcall CopyDECoordsToMapObject + pop bc + ld hl, OBJECT_FLAGS2 + add hl, bc + res 2, [hl] + call CopyNextCoordsTileToStandingCoordsTile + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4f04 + +StepTypeTrackingObject: ; 4f04 + ld hl, OBJECT_1D + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + ld hl, OBJECT_SPRITE + add hl, de + ld a, [hl] + and a + jr z, .nope + ld hl, OBJECT_SPRITE_X + add hl, de + ld a, [hl] + ld hl, OBJECT_SPRITE_X + add hl, bc + ld [hl], a + ld hl, OBJECT_SPRITE_Y + add hl, de + ld a, [hl] + ld hl, OBJECT_SPRITE_Y + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld a, [hl] + and a + ret z + dec [hl] + ret nz +.nope + jp DeleteMapObject +; 4f33 + +StepType14: ; 4f33 +StepType15: ; 4f33 + call Field1cAnonymousJumptable +; anonymous dw + dw .Init + dw .Run + +.Init: + xor a + ld hl, OBJECT_1D + add hl, bc + ld [hl], a + call IncrementObjectStructField1c +.Run: + ld hl, OBJECT_1D + add hl, bc + ld d, [hl] + ld a, [wPlayerStepVectorY] + sub d + ld [wPlayerStepVectorY], a + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + jr z, .ok + ld a, [hl] + call .GetSign + ld hl, OBJECT_1D + add hl, bc + ld [hl], a + ld d, a + ld a, [wPlayerStepVectorY] + add d + ld [wPlayerStepVectorY], a + ret + +.ok + call DeleteMapObject + ret + +.GetSign: + ld hl, OBJECT_1E + add hl, bc + and 1 + ld a, [hl] + ret z + cpl + inc a + ret +; 4f77 + +StepType16: ; 4f77 + call Field1cAnonymousJumptable ; ???? +; 4f7a +StepType17: ; 4f7a + call Field1cAnonymousJumptable +; anonymous dw + dw .null + dw .null + dw .null +.null +; 4f83 + +SkyfallTop: ; 4f83 + call Field1cAnonymousJumptable +; anonymous dw + dw .Init + dw .Run + +.Init: + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SKYFALL + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], 16 + call IncrementObjectStructField1c + +.Run: + ld hl, OBJECT_STEP_DURATION + add hl, bc + dec [hl] + ret nz + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], $60 + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], 0 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 4fb2 + +Stubbed_Function4fb2: + ret + ld hl, OBJECT_1D + add hl, bc + inc [hl] + ld a, [hl] + srl a + srl a + and %00000111 + ld l, a + ld h, 0 + ld de, .y + add hl, de + ld a, [hl] + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], a + ret + +.y ; 4fcd + db 0, -1, -2, -3, -4, -3, -2, -1 +; 4fd5 +UpdateJumpPosition: ; 4fd5 + call GetStepVector + ld a, h + ld hl, OBJECT_1F + add hl, bc + ld e, [hl] + add e + ld [hl], a + nop + srl e + ld d, 0 + ld hl, .y + add hl, de + ld a, [hl] + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld [hl], a + ret + +.y ; 4ff0 + db -4, -6, -8, -10, -11, -12, -12, -12 + db -11, -10, -9, -8, -6, -4, 0, 0 +; 5000 +Function5000: ; unscripted? +; copy [wPlayerNextMovement] to [wPlayerMovement] + ld a, [wPlayerNextMovement] + ld hl, wPlayerMovement + ld [hl], a +; load [wPlayerNextMovement] with movement_step_sleep + ld a, movement_step_sleep + ld [wPlayerNextMovement], a +; recover the previous value of [wPlayerNextMovement] + ld a, [hl] + ret +; 500e + +GetMovementByte: + ld hl, wMovementDataPointer + call _GetMovementByte + ret +; 5015 + +Function5015: ; 5015 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld e, [hl] + inc [hl] + ld d, 0 + ld hl, wc2e2 + ld a, [hli] + ld h, [hl] + ld l, a + add hl, de + ld a, [hl] + ret +; 5026 + +Function5026: ; 5026 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld e, [hl] + inc [hl] + ld d, 0 + ld hl, wc2e6 + ld a, [hli] + ld h, [hl] + ld l, a + add hl, de + ld a, [hl] + ret +; 5037 + +_GetMovementObject: ; 5037 + ld hl, GetMovementObject + jp HandleMovementData +; 503d + +GetMovementObject: ; 503d + ld a, [wMovementObject] + ret +; 5041 + +HandleMovementData: ; 5041 + call .StorePointer +.loop + xor a + ld [wMovementByteWasControlSwitch], a + call JumpMovementPointer + call DoMovementFunction + ld a, [wMovementByteWasControlSwitch] + and a + jr nz, .loop + ret + +.StorePointer: + ld a, l + ld [wMovementPointer], a + ld a, h + ld [wMovementPointer + 1], a + ret +; 505e + +JumpMovementPointer: ; 505e + ld hl, wMovementPointer + ld a, [hli] + ld h, [hl] + ld l, a + jp hl +; 5065 + +ContinueReadingMovement: ; 5065 + ld a, 1 + ld [wMovementByteWasControlSwitch], a + ret +; 506b + +DoMovementFunction: ; 506b + push af + call ApplyMovementToFollower + pop af + ld hl, MovementPointers + rst JumpTable + ret +; 5075 + +INCLUDE "engine/overworld/movement.asm" +; 54b8 + +ApplyMovementToFollower: ; 54b8 + ld e, a + ld a, [wObjectFollow_Follower] + cp -1 + ret z + ld a, [wObjectFollow_Leader] + ld d, a + ld a, [hMapObjectIndexBuffer] + cp d + ret nz + ld a, e + cp movement_step_sleep + ret z + cp movement_step_end + ret z + cp movement_step_4b + ret z + cp movement_step_bump + ret z + cp movement_slow_step + ret c + push af + ld hl, wFollowerMovementQueueLength + inc [hl] + ld e, [hl] + ld d, 0 + ld hl, wFollowMovementQueue + add hl, de + pop af + ld [hl], a + ret +; 54e6 + +GetFollowerNextMovementByte: ; 54e6 + ld hl, wFollowerMovementQueueLength + ld a, [hl] + and a + jr z, .done + cp -1 + jr z, .done + dec [hl] + ld e, a + ld d, 0 + ld hl, wFollowMovementQueue + add hl, de + inc e + ld a, -1 +.loop + ld d, [hl] + ld [hld], a + ld a, d + dec e + jr nz, .loop + ret + +.done + call .CancelFollowIfLeaderMissing + ret c + ld a, movement_step_sleep + ret + +.CancelFollowIfLeaderMissing: + ld a, [wObjectFollow_Leader] + cp -1 + jr z, .nope + push bc + call GetObjectStruct + ld hl, OBJECT_SPRITE + add hl, bc + ld a, [hl] + pop bc + and a + jr z, .nope + and a + ret + +.nope + ld a, -1 + ld [wObjectFollow_Follower], a + ld a, movement_step_end + scf + ret +; 5529 + +SpawnShadow: ; 5529 + push bc + ld de, .ShadowObject + call CopyTempObjectData + call InitTempObject + pop bc + ret + +.ShadowObject: + ; vtile, palette, movement + db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SHADOW +; 5538 + +SpawnStrengthBoulderDust: ; 5538 + push bc + ld de, .BoulderDustObject + call CopyTempObjectData + call InitTempObject + pop bc + ret + +.BoulderDustObject: + db $00, PAL_OW_SILVER, SPRITEMOVEDATA_BOULDERDUST +; 5547 + +SpawnEmote: ; 5547 + push bc + ld de, .EmoteObject + call CopyTempObjectData + call InitTempObject + pop bc + ret + +.EmoteObject: + db $00, PAL_OW_SILVER, SPRITEMOVEDATA_EMOTE +; 5556 + +ShakeGrass: ; 5556 + push bc + ld de, .data_5562 + call CopyTempObjectData + call InitTempObject + pop bc + ret + +.data_5562 + db $00, PAL_OW_TREE, SPRITEMOVEDATA_GRASS +; 5565 + +ShakeScreen: ; 5565 + push bc + push af + ld de, .ScreenShakeObject + call CopyTempObjectData + pop af + ld [wTempObjectCopyRange], a + call InitTempObject + pop bc + ret + +.ScreenShakeObject: + db $00, PAL_OW_SILVER, SPRITEMOVEDATA_SCREENSHAKE +; 5579 +DespawnEmote: ; 5579 + push bc + ld a, [hMapObjectIndexBuffer] + ld c, a + call .DeleteEmote + pop bc + ret + +.DeleteEmote: + ld de, wObjectStructs + ld a, NUM_OBJECT_STRUCTS +.loop + push af + ld hl, OBJECT_FLAGS1 + add hl, de + bit EMOTE_OBJECT, [hl] + jr z, .next + ld hl, OBJECT_SPRITE + add hl, de + ld a, [hl] + and a + jr z, .next + push bc + xor a + ld bc, OBJECT_STRUCT_LENGTH + call ByteFill + pop bc +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, de + ld d, h + ld e, l + pop af + dec a + jr nz, .loop + ret +; 55ac + +InitTempObject: ; 55ac + call FindFirstEmptyObjectStruct + ret nc + ld d, h + ld e, l + farcall CopyTempObjectToObjectStruct + ret +; 55b9 + +CopyTempObjectData: ; 55b9 +; load into wTempObjectCopy: +; -1, -1, [de], [de + 1], [de + 2], [hMapObjectIndexBuffer], [NextMapX], [NextMapY], -1 +; This spawns the object at the same place as whichever object is loaded into bc. + ld hl, wTempObjectCopyMapObjectIndex + ld [hl], -1 + inc hl + ld [hl], -1 + inc hl + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + ld a, [de] + ld [hli], a + ld a, [hMapObjectIndexBuffer] + ld [hli], a + push hl + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + pop hl + ld [hl], d + inc hl + ld [hl], e + inc hl + ld [hl], -1 + ret +; 55e0 + +Function55e0:: ; 55e0 + ld a, [wVramState] + bit 0, a + ret z + ld bc, wObjectStructs + xor a +.loop + ld [hMapObjectIndexBuffer], a + call DoesObjectHaveASprite + jr z, .ok + call Function565c +.ok + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + ret +; 5602 + +Function5602: ; 5602, called at battle start + call Function5645 ; clear sprites + ld a, PLAYER + call Function5629 ; respawn player + ld a, [wBattleScriptFlags] + bit 7, a + jr z, .ok + ld a, [hLastTalked] + and a + jr z, .ok + call Function5629 ; respawn opponent +.ok + call _UpdateSprites + ret +; 561d + +Function561d: ; 561d + call Function5645 ; clear sprites + ld a, PLAYER + call Function5629 ; respawn player + call _UpdateSprites + ret +; 5629 + +Function5629: ; 5629 + cp NUM_OBJECTS + ret nc + call GetMapObject + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp -1 + ret z + cp NUM_OBJECT_STRUCTS + ret nc + call GetObjectStruct + call DoesObjectHaveASprite + ret z + call Function5673 + ret +; 5645 + +Function5645: ; 5645 + xor a + ld bc, wObjectStructs +.loop + ld [hMapObjectIndexBuffer], a + call SetFacing_Standing + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + ret +; 565c + +Function565c: ; 565c + push bc + call Function56cd + pop bc + jr c, SetFacing_Standing + call Function56a3 + jr c, SetFacing_Standing + call Function5688 + farcall Function4440 + xor a + ret +; 5673 + +Function5673: ; 5673 + call Function56a3 + jr c, SetFacing_Standing + farcall Function4440 ; no need to farcall + xor a + ret +; 5680 + +SetFacing_Standing: ; 5680 + ld hl, OBJECT_FACING_STEP + add hl, bc + ld [hl], STANDING + scf + ret +; 5688 + +Function5688: ; 5688 + push bc + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + call GetCoordTile + pop bc + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld [hl], a + farcall UpdateTallGrassFlags ; no need to farcall + ret +; 56a3 + +Function56a3: ; 56a3 + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + inc d + inc e + ld a, [wXCoord] + cp d + jr z, .equal_x + jr nc, .nope + add MAPOBJECT_SCREEN_WIDTH - 1 + cp d + jr c, .nope +.equal_x + ld a, [wYCoord] + cp e + jr z, .equal_y + jr nc, .nope + add MAPOBJECT_SCREEN_HEIGHT - 1 + cp e + jr c, .nope +.equal_y + xor a + ret + +.nope + scf + ret +; 56cd + +Function56cd: ; 56cd + ld a, [wPlayerBGMapOffsetX] + ld d, a + ld hl, OBJECT_SPRITE_X_OFFSET + add hl, bc + ld a, [hl] + ld hl, OBJECT_SPRITE_X + add hl, bc + add [hl] + add d + cp $f0 + jr nc, .ok1 + cp $a0 + jp nc, .nope +.ok1 + and %00000111 + ld d, 2 + cp 4 + jr c, .ok2 + ld d, 3 +.ok2 + ld a, [hl] + srl a + srl a + srl a + cp SCREEN_WIDTH + jr c, .ok3 + sub BG_MAP_WIDTH +.ok3 + ld [hUsedSpriteIndex], a + ld a, [wPlayerBGMapOffsetY] + ld e, a + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + ld a, [hl] + ld hl, OBJECT_SPRITE_Y + add hl, bc + add [hl] + add e + cp $f0 + jr nc, .ok4 + cp $90 + jr nc, .nope +.ok4 + and %00000111 + ld e, 2 + cp 4 + jr c, .ok5 + ld e, 3 +.ok5 + ld a, [hl] + srl a + srl a + srl a + cp SCREEN_HEIGHT + jr c, .ok6 + sub BG_MAP_HEIGHT +.ok6 + ld [hUsedSpriteTile], a + ld hl, OBJECT_PALETTE + add hl, bc + bit 7, [hl] + jr z, .ok7 + ld a, d + add 2 + ld d, a + ld a, e + add 2 + ld e, a +.ok7 + ld a, d + ld [hFFBF], a +.loop + ld a, [hFFBF] + ld d, a + ld a, [hUsedSpriteTile] + add e + dec a + cp SCREEN_HEIGHT + jr nc, .ok9 + ld b, a +.next + ld a, [hUsedSpriteIndex] + add d + dec a + cp SCREEN_WIDTH + jr nc, .ok8 + ld c, a + push bc + call Coord2Tile + pop bc +; NPCs disappear if standing on tile $60-$7f (or $e0-$ff), +; since those IDs are for text characters and textbox frames. + ld a, [hl] + cp FIRST_REGULAR_TEXT_CHAR + jr nc, .nope +.ok8 + dec d + jr nz, .next +.ok9 + dec e + jr nz, .loop + and a + ret + +.nope + scf + ret +; 576a + +HandleNPCStep:: ; 576a + call .ResetStepVector + call .DoStepsForAllObjects + ret + +.ResetStepVector: + xor a + ld [wPlayerStepVectorX], a + ld [wPlayerStepVectorY], a + ld [wPlayerStepFlags], a + ld a, -1 + ld [wPlayerStepDirection], a + ret + +.DoStepsForAllObjects: + ld bc, wObjectStructs + xor a +.loop + ld [hMapObjectIndexBuffer], a + call DoesObjectHaveASprite + jr z, .next + call Function437b +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + ret +; 579d + +RefreshPlayerSprite: ; 579d + ld a, movement_step_sleep + ld [wPlayerNextMovement], a + ld [wPlayerMovement], a + xor a + ld [wPlayerTurningDirection], a + ld [wPlayerObjectStepFrame], a + call .TryResetPlayerAction + farcall CheckWarpFacingDown + call c, SpawnInFacingDown + call .SpawnInCustomFacing + ret +; 57bc + +.TryResetPlayerAction: ; 57bc + ld hl, wPlayerSpriteSetupFlags + bit PLAYERSPRITESETUP_RESET_ACTION_F, [hl] + jr nz, .ok + ret + +.ok + ld a, OBJECT_ACTION_00 + ld [wPlayerAction], a + ret +; 57ca + +.SpawnInCustomFacing: ; 57ca + ld hl, wPlayerSpriteSetupFlags + bit PLAYERSPRITESETUP_CUSTOM_FACING_F, [hl] + ret z + ld a, [wPlayerSpriteSetupFlags] + and PLAYERSPRITESETUP_FACING_MASK + add a + add a + jr ContinueSpawnFacing +; 57d9 + +SpawnInFacingDown: ; 57d9 + ld a, 0 +ContinueSpawnFacing: ; 57db + ld bc, wPlayerStruct + call SetSpriteDirection + ret +; 57e2 + +_SetPlayerPalette: ; 57e2 + ld a, d + and %10000000 + ret z + ld bc, 0 ; debug? + ld hl, OBJECT_FACING + add hl, bc + ld a, [hl] + or d + ld [hl], a + ld a, d + swap a + and %00000111 + ld d, a + ld bc, wPlayerStruct + ld hl, OBJECT_PALETTE + add hl, bc + ld a, [hl] + and %11111000 + or d + ld [hl], a + ret +; 5803 + +StartFollow:: ; 5803 + push bc + ld a, b + call SetLeaderIfVisible + pop bc + ret c + ld a, c + call SetFollowerIfVisible + farcall QueueFollowerFirstStep + ret +; 5815 + +SetLeaderIfVisible: ; 5815 + call CheckObjectVisibility + ret c + ld a, [hObjectStructIndexBuffer] + ld [wObjectFollow_Leader], a + ret +; 581f + +StopFollow:: ; 581f + call ResetLeader + call ResetFollower + ret +; 5826 + +ResetLeader: ; 5826 + ld a, -1 + ld [wObjectFollow_Leader], a + ret +; 582c + +SetFollowerIfVisible: ; 582c + push af + call ResetFollower + pop af + call CheckObjectVisibility + ret c + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld [hl], SPRITEMOVEDATA_FOLLOWING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_00 + ld a, [hObjectStructIndexBuffer] + ld [wObjectFollow_Follower], a + ret +; 5847 + +ResetFollower: ; 5847 + ld a, [wObjectFollow_Follower] + cp -1 + ret z + call GetObjectStruct + farcall Function58e3 ; no need to bankswitch + ld a, -1 + ld [wObjectFollow_Follower], a + ret +; 585c + +SetFlagsForMovement_1:: ; 585c + ld a, c + call CheckObjectVisibility + ret c + push bc + call Function587a + pop bc + ld hl, OBJECT_FLAGS2 + add hl, bc + res 5, [hl] + xor a + ret +; 586e + +Function586e: ; 586e + call CheckObjectVisibility + ret c + ld hl, OBJECT_FLAGS2 + add hl, bc + set 5, [hl] + xor a + ret +; 587a + +Function587a: ; 587a + ld bc, wObjectStructs + xor a +.loop + push af + call DoesObjectHaveASprite + jr z, .next + ld hl, OBJECT_FLAGS2 + add hl, bc + set 5, [hl] +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + pop af + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + ret +; 5897 + +_SetFlagsForMovement_2:: ; 5897 + ld a, [wObjectFollow_Leader] + cp -1 + ret z + push bc + call GetObjectStruct + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + pop bc + cp c + ret nz + ld a, [wObjectFollow_Follower] + cp -1 + ret z + call GetObjectStruct + ld hl, OBJECT_FLAGS2 + add hl, bc + res 5, [hl] + ret +; 58b9 + +Function58b9:: ; 58b9 + push bc + ld bc, wObjectStructs + xor a +.loop + push af + call DoesObjectHaveASprite + jr z, .next + ld hl, OBJECT_FLAGS2 + add hl, bc + res 5, [hl] +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + pop af + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + pop bc + ret +; 58d8 + +Function58d8: ; 58d8 + call CheckObjectVisibility + ret c + ld hl, OBJECT_FLAGS2 + add hl, bc + res 5, [hl] + ret +; 58e3 + +Function58e3: ; 58e3 + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + cp -1 + jp z, Function5903 ; a jr would have been appropriate here + push bc + call GetMapObject + ld hl, MAPOBJECT_MOVEMENT + add hl, bc + ld a, [hl] + pop bc + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_00 + ret +; 5903 + +Function5903: ; 5903 + call GetSpriteDirection + rrca + rrca + ld e, a + ld d, 0 + ld hl, .standing_movefns + add hl, de + ld a, [hl] + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_00 + ret + +.standing_movefns + db SPRITEMOVEDATA_STANDING_DOWN + db SPRITEMOVEDATA_STANDING_UP + db SPRITEMOVEDATA_STANDING_LEFT + db SPRITEMOVEDATA_STANDING_RIGHT +; 5920 + +_UpdateSprites:: ; 5920 + ld a, [wVramState] + bit 0, a + ret z + xor a + ld [hUsedSpriteIndex], a + ld a, [hOAMUpdate] + push af + ld a, 1 + ld [hOAMUpdate], a + call InitSprites + call .fill + pop af + ld [hOAMUpdate], a + ret + +.fill + ld a, [wVramState] + bit 1, a + ld b, LOW(wVirtualOAMEnd) + jr z, .ok + ld b, 28 * SPRITEOAMSTRUCT_LENGTH +.ok + ld a, [hUsedSpriteIndex] + cp b + ret nc + ld l, a + ld h, HIGH(wVirtualOAM) + ld de, SPRITEOAMSTRUCT_LENGTH + ld a, b + ld c, SCREEN_HEIGHT_PX + 2 * TILE_WIDTH +.loop + ld [hl], c ; y + add hl, de + cp l + jr nz, .loop + ret +; 5958 + +ApplyBGMapAnchorToObjects: ; 5958 + push hl + push de + push bc + ld a, [wPlayerBGMapOffsetX] + ld d, a + ld a, [wPlayerBGMapOffsetY] + ld e, a + ld bc, wObjectStructs + ld a, NUM_OBJECT_STRUCTS +.loop + push af + call DoesObjectHaveASprite + jr z, .skip + ld hl, OBJECT_SPRITE_X + add hl, bc + ld a, [hl] + add d + ld [hl], a + ld hl, OBJECT_SPRITE_Y + add hl, bc + ld a, [hl] + add e + ld [hl], a +.skip + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + pop af + dec a + jr nz, .loop + xor a + ld [wPlayerBGMapOffsetX], a + ld [wPlayerBGMapOffsetY], a + pop bc + pop de + pop hl + ret +; 5991 + + +PRIORITY_LOW EQU $10 +PRIORITY_NORM EQU $20 +PRIORITY_HIGH EQU $30 + +InitSprites: ; 5991 + call .DeterminePriorities + ld c, PRIORITY_HIGH + call .InitSpritesByPriority + ld c, PRIORITY_NORM + call .InitSpritesByPriority + ld c, PRIORITY_LOW + call .InitSpritesByPriority + ret + +.DeterminePriorities: + xor a + ld hl, wMovementPointer + ld bc, NUM_OBJECT_STRUCTS + call ByteFill + ld d, 0 + ld bc, wObjectStructs + ld hl, wMovementPointer +.loop + push hl + call DoesObjectHaveASprite + jr z, .skip + ld hl, OBJECT_FACING_STEP + add hl, bc + ld a, [hl] + cp STANDING + jr z, .skip +; Define the sprite priority. + ld e, PRIORITY_LOW + ld hl, OBJECT_FLAGS2 + add hl, bc + bit LOW_PRIORITY, [hl] + jr nz, .add + ld e, PRIORITY_NORM + bit HIGH_PRIORITY, [hl] + jr z, .add + ld e, PRIORITY_HIGH + jr .add + +.skip + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + pop hl + jr .next + +.add + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + pop hl + ld a, d + or e + ld [hli], a +.next + inc d + ld a, d + cp NUM_OBJECT_STRUCTS + jr nz, .loop + ret + +.InitSpritesByPriority: + ld hl, wMovementPointer +.next_sprite + ld a, [hli] + ld d, a + and $f0 + ret z + cp c + jr nz, .next_sprite + push bc + push hl + ld a, d + and $f + call .GetObjectStructPointer + call .InitSprite + pop hl + pop bc + jr .next_sprite + +.InitSprite: + ld hl, OBJECT_SPRITE_TILE + add hl, bc + ld a, [hl] + and %01111111 + ld [hFFC1], a + xor a + bit 7, [hl] + jr nz, .skip1 + or %00001000 +.skip1 + ld hl, OBJECT_FLAGS2 + add hl, bc + ld e, [hl] + bit 7, e + jr z, .skip2 + or %10000000 +.skip2 + bit 4, e + jr z, .skip3 + or %00010000 +.skip3 + ld hl, OBJECT_PALETTE + add hl, bc + ld d, a + ld a, [hl] + and %00000111 + or d + ld d, a + xor a + bit 3, e + jr z, .skip4 + or %10000000 +.skip4 + ld [hFFC2], a + ld hl, OBJECT_SPRITE_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_SPRITE_X_OFFSET + add hl, bc + add [hl] + add 8 + ld e, a + ld a, [wPlayerBGMapOffsetX] + add e + ld [hFFBF], a + ld hl, OBJECT_SPRITE_Y + add hl, bc + ld a, [hl] + ld hl, OBJECT_SPRITE_Y_OFFSET + add hl, bc + add [hl] + add 12 + ld e, a + ld a, [wPlayerBGMapOffsetY] + add e + ld [hFFC0], a + ld hl, OBJECT_FACING_STEP + add hl, bc + ld a, [hl] + cp STANDING + jp z, .done + cp NUM_FACINGS + jp nc, .done + ld l, a + ld h, 0 + add hl, hl + ld bc, Facings + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hUsedSpriteIndex] + ld c, a + ld b, HIGH(wVirtualOAM) + ld a, [hli] + ld [hUsedSpriteTile], a + add c + cp LOW(wVirtualOAMEnd) + jr nc, .full +.addsprite + ld a, [hFFC0] + add [hl] + inc hl + ld [bc], a ; y + inc c + ld a, [hFFBF] + add [hl] + inc hl + ld [bc], a ; x + inc c + ld e, [hl] + inc hl + ld a, [hFFC1] + bit 2, e + jr z, .nope1 + xor a +.nope1 + add [hl] + inc hl + ld [bc], a ; tile id + inc c + ld a, e + bit 1, a + jr z, .nope2 + ld a, [hFFC2] + or e +.nope2 + and OBP_NUM | X_FLIP | Y_FLIP | PRIORITY + or d + ld [bc], a ; attributes + inc c + ld a, [hUsedSpriteTile] + dec a + ld [hUsedSpriteTile], a + jr nz, .addsprite + ld a, c + ld [hUsedSpriteIndex], a +.done + xor a + ret + +.full + scf + ret + +.GetObjectStructPointer: + ld c, a + ld b, 0 + ld hl, .Addresses + add hl, bc + add hl, bc + ld c, [hl] + inc hl + ld b, [hl] + ret + +.Addresses: ; 5ace + dw wPlayerStruct + dw wObject1Struct + dw wObject2Struct + dw wObject3Struct + dw wObject4Struct + dw wObject5Struct + dw wObject6Struct + dw wObject7Struct + dw wObject8Struct + dw wObject9Struct + dw wObject10Struct + dw wObject11Struct + dw wObject12Struct +; 5ae8 diff --git a/engine/overworld/map_objects_2.asm b/engine/overworld/map_objects_2.asm new file mode 100644 index 000000000..038e2b49b --- /dev/null +++ b/engine/overworld/map_objects_2.asm @@ -0,0 +1,70 @@ +LoadObjectMasks: ; 2454f + ld hl, wObjectMasks + xor a + ld bc, NUM_OBJECTS + call ByteFill + nop + ld bc, wMapObjects + ld de, wObjectMasks + xor a +.loop + push af + push bc + push de + call GetObjectTimeMask + jr c, .next + call CheckObjectFlag +.next + pop de + ld [de], a + inc de + pop bc + ld hl, OBJECT_LENGTH + add hl, bc + ld b, h + ld c, l + pop af + inc a + cp NUM_OBJECTS + jr nz, .loop + ret + +CheckObjectFlag: ; 2457d (9:457d) + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + and a + jr z, .masked + ld hl, MAPOBJECT_EVENT_FLAG + add hl, bc + ld a, [hli] + ld e, a + ld a, [hl] + ld d, a + cp -1 + jr nz, .check + ld a, e + cp -1 + jr z, .unmasked + jr .masked +.check + ld b, CHECK_FLAG + call EventFlagAction + ld a, c + and a + jr nz, .masked +.unmasked + xor a + ret + +.masked + ld a, -1 + scf + ret + +GetObjectTimeMask: ; 245a7 (9:45a7) + call CheckObjectTime + ld a, -1 + ret c + xor a + ret diff --git a/engine/overworld/map_setup.asm b/engine/overworld/map_setup.asm new file mode 100644 index 000000000..268574de0 --- /dev/null +++ b/engine/overworld/map_setup.asm @@ -0,0 +1,260 @@ +RunMapSetupScript:: ; 15363 + ld a, [hMapEntryMethod] + and $f + dec a + ld c, a + ld b, 0 + ld hl, MapSetupScripts + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call ReadMapSetupScript + ret +; 15377 + +INCLUDE "data/maps/setup_scripts.asm" + +ReadMapSetupScript: ; 1541d +.loop + ld a, [hli] + cp -1 + ret z + + push hl + + ld c, a + ld b, 0 + ld hl, MapSetupCommands + add hl, bc + add hl, bc + add hl, bc + + ; bank + ld b, [hl] + inc hl + + ; address + ld a, [hli] + ld h, [hl] + ld l, a + + ; Bit 7 of the bank indicates a parameter. + ; This is left unused. + bit 7, b + jr z, .go + + pop de + ld a, [de] + ld c, a + inc de + push de + +.go + ld a, b + and $7f + rst FarCall + + pop hl + jr .loop +; 15440 + +MapSetupCommands: ; 15440 +; entries correspond to command indexes in constants/map_setup_constants.asm + dba EnableLCD ; 00 + dba DisableLCD ; 01 + dba MapSetup_Sound_Off ; 02 + dba PlayMapMusic ; 03 + dba RestartMapMusic ; 04 + dba FadeToMapMusic ; 05 + dba RotatePalettesRightMapAndMusic ; 06 + dba EnterMapMusic ; 07 + dba ForceMapMusic ; 08 + dba FadeInMusic ; 09 + dba LoadBlockData ; 0a (callback 1) + dba LoadNeighboringBlockData ; 0b + dba SaveScreen ; 0c + dba BufferScreen ; 0d + dba LoadGraphics ; 0e + dba LoadTileset ; 0f + dba LoadMapTimeOfDay ; 10 + dba LoadMapPalettes ; 11 + dba LoadWildMonData ; 12 + dba RefreshMapSprites ; 13 + dba HandleNewMap ; 14 + dba InitCommandQueue ; 15 + dba LoadObjectsRunCallback_02 ; 16 + dba LoadSpawnPoint ; 17 + dba EnterMapConnection ; 18 + dba LoadWarpData ; 19 + dba LoadMapAttributes ; 1a + dba LoadMapAttributes_SkipPeople ; 1b + dba ClearBGPalettes ; 1c + dba FadeOutPalettes ; 1d + dba FadeInPalettes ; 1e + dba GetCoordOfUpperLeftCorner ; 1f + dba RestoreFacingAfterWarp ; 20 + dba SpawnInFacingDown ; 21 + dba SpawnPlayer ; 22 + dba RefreshPlayerCoords ; 23 + dba DelayClearingOldSprites ; 24 + dba DelayLoadingNewSprites ; 25 + dba UpdateRoamMons ; 26 + dba JumpRoamMons ; 27 + dba FadeOldMapMusic ; 28 + dba ActivateMapAnims ; 29 + dba SuspendMapAnims ; 2a + dba RetainOldPalettes ; 2b + dba DontScrollText ; 2c + dba ReturnFromMapSetupScript ; 2d +; 154ca + + +DontScrollText: ; 154ca + xor a + ld [wDisableTextAcceleration], a + ret +; 154cf + +ActivateMapAnims: ; 154cf + ld a, $1 + ld [hMapAnims], a + ret +; 154d3 + +SuspendMapAnims: ; 154d3 + xor a + ld [hMapAnims], a + ret +; 154d7 + +LoadObjectsRunCallback_02: ; 154d7 + ld a, MAPCALLBACK_OBJECTS + call RunMapCallback + farcall LoadObjectMasks + farcall InitializeVisibleSprites + ret +; 154ea (5:54ea) + +; unused + ret +; 154eb + +DelayClearingOldSprites: ; 154eb + ld hl, wPlayerSpriteSetupFlags + set PLAYERSPRITESETUP_RESET_ACTION_F, [hl] + ret +; 154f1 + +DelayLoadingNewSprites: ; 154f1 + ld hl, wPlayerSpriteSetupFlags + set PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl] + ret + +CheckReplaceKrisSprite: ; 154f7 + nop + call .CheckBiking + jr c, .ok + call .CheckSurfing + jr c, .ok + call .CheckSurfing2 + jr c, .ok + ret + +.ok + call ReplaceKrisSprite + ret + +.CheckBiking: ; 1550c (5:550c) + and a + ld hl, wBikeFlags + bit BIKEFLAGS_ALWAYS_ON_BIKE_F, [hl] + ret z + ld a, PLAYER_BIKE + ld [wPlayerState], a + scf + ret + +.CheckSurfing2: ; 1551a (5:551a) + ld a, [wPlayerState] + cp PLAYER_NORMAL + jr z, .nope + cp PLAYER_SKATE + jr z, .nope + cp PLAYER_SURF + jr z, .surfing + cp PLAYER_SURF_PIKA + jr z, .surfing + call GetMapEnvironment + cp INDOOR + jr z, .checkbiking + cp ENVIRONMENT_5 + jr z, .checkbiking + cp DUNGEON + jr z, .checkbiking + jr .nope +.checkbiking + ld a, [wPlayerState] + cp PLAYER_BIKE + jr nz, .nope +.surfing + ld a, PLAYER_NORMAL + ld [wPlayerState], a + scf + ret + +.nope + and a + ret + +.CheckSurfing: ; 1554e (5:554e) + call CheckOnWater + jr nz, .ret_nc + ld a, [wPlayerState] + cp PLAYER_SURF + jr z, ._surfing + cp PLAYER_SURF_PIKA + jr z, ._surfing + ld a, PLAYER_SURF + ld [wPlayerState], a +._surfing + scf + ret +.ret_nc + and a + ret +; 15567 + +FadeOldMapMusic: ; 15567 + ld a, 6 + call SkipMusic + ret +; 1556d + +RetainOldPalettes: ; 1556d + farcall _UpdateTimePals + ret + +RotatePalettesRightMapAndMusic: ; 15574 + ld e, 0 + ld a, [wMusicFadeID] + ld d, 0 + ld a, [wMusicFadeID + 1] + ld a, $4 + ld [wMusicFade], a + call RotateThreePalettesRight + ret +; 15587 + +ForceMapMusic: ; 15587 + ld a, [wPlayerState] + cp PLAYER_BIKE + jr nz, .notbiking + call VolumeOff + ld a, $88 + ld [wMusicFade], a +.notbiking + call TryRestartMapMusic + ret +; 1559a diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm new file mode 100644 index 000000000..3dbb0b83a --- /dev/null +++ b/engine/overworld/movement.asm @@ -0,0 +1,864 @@ +MovementPointers: ; 5075 +; entries correspond to macros/scripts/movement.asm enumeration + dw Movement_turn_head_down ; 00 + dw Movement_turn_head_up ; 01 + dw Movement_turn_head_left ; 02 + dw Movement_turn_head_right ; 03 + dw Movement_turn_step_down ; 04 + dw Movement_turn_step_up ; 05 + dw Movement_turn_step_left ; 06 + dw Movement_turn_step_right ; 07 + dw Movement_slow_step_down ; 08 + dw Movement_slow_step_up ; 09 + dw Movement_slow_step_left ; 0a + dw Movement_slow_step_right ; 0b + dw Movement_step_down ; 0c + dw Movement_step_up ; 0d + dw Movement_step_left ; 0e + dw Movement_step_right ; 0f + dw Movement_big_step_down ; 10 + dw Movement_big_step_up ; 11 + dw Movement_big_step_left ; 12 + dw Movement_big_step_right ; 13 + dw Movement_slow_slide_step_down ; 14 + dw Movement_slow_slide_step_up ; 15 + dw Movement_slow_slide_step_left ; 16 + dw Movement_slow_slide_step_right ; 17 + dw Movement_slide_step_down ; 18 + dw Movement_slide_step_up ; 19 + dw Movement_slide_step_left ; 1a + dw Movement_slide_step_right ; 1b + dw Movement_fast_slide_step_down ; 1c + dw Movement_fast_slide_step_up ; 1d + dw Movement_fast_slide_step_left ; 1e + dw Movement_fast_slide_step_right ; 1f + dw Movement_turn_away_down ; 20 + dw Movement_turn_away_up ; 21 + dw Movement_turn_away_left ; 22 + dw Movement_turn_away_right ; 23 + dw Movement_turn_in_down ; 24 + dw Movement_turn_in_up ; 25 + dw Movement_turn_in_left ; 26 + dw Movement_turn_in_right ; 27 + dw Movement_turn_waterfall_down ; 28 + dw Movement_turn_waterfall_up ; 29 + dw Movement_turn_waterfall_left ; 2a + dw Movement_turn_waterfall_right ; 2b + dw Movement_slow_jump_step_down ; 2c + dw Movement_slow_jump_step_up ; 2d + dw Movement_slow_jump_step_left ; 2e + dw Movement_slow_jump_step_right ; 2f + dw Movement_jump_step_down ; 30 + dw Movement_jump_step_up ; 31 + dw Movement_jump_step_left ; 32 + dw Movement_jump_step_right ; 33 + dw Movement_fast_jump_step_down ; 34 + dw Movement_fast_jump_step_up ; 35 + dw Movement_fast_jump_step_left ; 36 + dw Movement_fast_jump_step_right ; 37 + dw Movement_remove_sliding ; 38 + dw Movement_set_sliding ; 39 + dw Movement_remove_fixed_facing ; 3a + dw Movement_fix_facing ; 3b + dw Movement_show_object ; 3c + dw Movement_hide_object ; 3d + dw Movement_step_sleep_1 ; 3e + dw Movement_step_sleep_2 ; 3f + dw Movement_step_sleep_3 ; 40 + dw Movement_step_sleep_4 ; 41 + dw Movement_step_sleep_5 ; 42 + dw Movement_step_sleep_6 ; 43 + dw Movement_step_sleep_7 ; 44 + dw Movement_step_sleep_8 ; 45 + dw Movement_step_sleep ; 46 + dw Movement_step_end ; 47 + dw Movement_48 ; 48 + dw Movement_remove_object ; 49 + dw Movement_step_loop ; 4a + dw Movement_4b ; 4b + dw Movement_teleport_from ; 4c + dw Movement_teleport_to ; 4d + dw Movement_skyfall ; 4e + dw Movement_step_dig ; 4f + dw Movement_step_bump ; 50 + dw Movement_fish_got_bite ; 51 + dw Movement_fish_cast_rod ; 52 + dw Movement_hide_emote ; 53 + dw Movement_show_emote ; 54 + dw Movement_step_shake ; 55 + dw Movement_tree_shake ; 56 + dw Movement_rock_smash ; 57 + dw Movement_return_dig ; 58 + dw Movement_skyfall_top ; 59 +; 5129 + + +Movement_teleport_from: ; 5129 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TELEPORT_FROM + ret +; 5130 + +Movement_teleport_to: ; 5130 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_TELEPORT_TO + ret +; 5137 + +Movement_skyfall: ; 5137 + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SKYFALL + ret +; 513e + +Movement_skyfall_top: ; 513e + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SKYFALL_TOP + ret +; 5145 + +Movement_step_dig: ; 5145 + call GetSpriteDirection + rlca + rlca + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], a + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + call JumpMovementPointer + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 516a + +Movement_return_dig: ; 516a + call GetSpriteDirection + rlca + rlca + ld hl, OBJECT_STEP_FRAME + add hl, bc + ld [hl], a + call JumpMovementPointer + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_RETURN_DIG + ret +; 5189 + +Movement_fish_got_bite: ; 5189 + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_FISHING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_GOT_BITE + ret +; 5196 + +Movement_rock_smash: ; 5196 + call JumpMovementPointer + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_ROCK_SMASH + ret +; 51ab + +Movement_fish_cast_rod: ; 51ab + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_FISHING + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 51b8 + +Movement_step_loop: ; 51b8 + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld [hl], $0 + jp ContinueReadingMovement +; 51c1 + +Movement_step_end: ; 51c1 + call RestoreDefaultMovement + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld [hl], a + + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld [hl], $0 + + ld hl, wVramState + res 7, [hl] + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_SLEEP + ret +; 51db + +Movement_48: ; 51db + call RestoreDefaultMovement + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld [hl], a + + ld hl, OBJECT_MOVEMENT_BYTE_INDEX + add hl, bc + ld [hl], $0 + + call JumpMovementPointer + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + + ld hl, wVramState + res 7, [hl] + ret +; 51fd + +Movement_remove_object: ; 51fd + call DeleteMapObject + ld hl, wObjectFollow_Leader + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr nz, .not_leading + ld [hl], -1 + +.not_leading + ld hl, wVramState + res 7, [hl] + ret +; 5210 + +Movement_4b: ; 5210 + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_04 + + ld hl, wVramState + res 7, [hl] + ret +; 5222 + +Movement_step_sleep_1: ; 5222 + ld a, 1 + jr Movement_step_sleep_common + +Movement_step_sleep_2: ; 5226 + ld a, 2 + jr Movement_step_sleep_common + +Movement_step_sleep_3: ; 522a + ld a, 3 + jr Movement_step_sleep_common + +Movement_step_sleep_4: ; 522e + ld a, 4 + jr Movement_step_sleep_common + +Movement_step_sleep_5: ; 5232 + ld a, 5 + jr Movement_step_sleep_common + +Movement_step_sleep_6: ; 5236 + ld a, 6 + jr Movement_step_sleep_common + +Movement_step_sleep_7: ; 523a + ld a, 7 + jr Movement_step_sleep_common + +Movement_step_sleep_8: ; 523e + ld a, 8 + jr Movement_step_sleep_common + +Movement_step_sleep: ; 5242 +; parameters: +; duration (DecimalParam) + + call JumpMovementPointer + jr Movement_step_sleep_common + +Movement_step_sleep_common: ; 5247 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 525f + +Movement_step_bump: ; 525f + ld a, 1 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_BUMP + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_BUMP + + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 5279 + +Movement_tree_shake: ; 5279 + ld a, 24 + ld hl, OBJECT_STEP_DURATION + add hl, bc + ld [hl], a + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_03 + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_WEIRD_TREE + + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 5293 + +Movement_remove_sliding: ; 5293 + ld hl, OBJECT_FLAGS1 + add hl, bc + res SLIDING, [hl] + jp ContinueReadingMovement +; 529c + +Movement_set_sliding: ; 529c + ld hl, OBJECT_FLAGS1 + add hl, bc + set SLIDING, [hl] + jp ContinueReadingMovement +; 52a5 + +Movement_remove_fixed_facing: ; 52a5 + ld hl, OBJECT_FLAGS1 + add hl, bc + res FIXED_FACING, [hl] + jp ContinueReadingMovement +; 52ae + +Movement_fix_facing: ; 52ae + ld hl, OBJECT_FLAGS1 + add hl, bc + set FIXED_FACING, [hl] + jp ContinueReadingMovement +; 52b7 + +Movement_show_object: ; 52b7 + ld hl, OBJECT_FLAGS1 + add hl, bc + res INVISIBLE, [hl] + jp ContinueReadingMovement +; 52c0 + +Movement_hide_object: ; 52c0 + ld hl, OBJECT_FLAGS1 + add hl, bc + set INVISIBLE, [hl] + jp ContinueReadingMovement +; 52c9 + +Movement_hide_emote: ; 52c9 + call DespawnEmote + jp ContinueReadingMovement +; 52cf + +Movement_show_emote: ; 52cf + call SpawnEmote + jp ContinueReadingMovement +; 52d5 + +Movement_step_shake: ; 52d5 +; parameters: +; displacement (DecimalParam) + + call JumpMovementPointer + call ShakeScreen + jp ContinueReadingMovement +; 52de + +Movement_turn_head_down: ; 52de + ld a, OW_DOWN + jr TurnHead + +Movement_turn_head_up: ; 52e2 + ld a, OW_UP + jr TurnHead + +Movement_turn_head_left: ; 52e6 + ld a, OW_LEFT + jr TurnHead + +Movement_turn_head_right: ; 52ea + ld a, OW_RIGHT + jr TurnHead + +TurnHead: ; 52ee + ld hl, OBJECT_FACING + add hl, bc + ld [hl], a + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld [hl], STANDING + ret +; 5300 + +Movement_slow_step_down: ; 5300 + ld a, STEP_SLOW << 2 | DOWN + jp NormalStep +; 5305 + +Movement_slow_step_up: ; 5305 + ld a, STEP_SLOW << 2 | UP + jp NormalStep +; 530a + +Movement_slow_step_left: ; 530a + ld a, STEP_SLOW << 2 | LEFT + jp NormalStep +; 530f + +Movement_slow_step_right: ; 530f + ld a, STEP_SLOW << 2 | RIGHT + jp NormalStep +; 5314 + +Movement_step_down: ; 5314 + ld a, STEP_WALK << 2 | DOWN + jp NormalStep +; 5319 + +Movement_step_up: ; 5319 + ld a, STEP_WALK << 2 | UP + jp NormalStep +; 531e + +Movement_step_left: ; 531e + ld a, STEP_WALK << 2 | LEFT + jp NormalStep +; 5323 + +Movement_step_right: ; 5323 + ld a, STEP_WALK << 2 | RIGHT + jp NormalStep +; 5328 + +Movement_big_step_down: ; 5328 + ld a, STEP_BIKE << 2 | DOWN + jp NormalStep +; 532d + +Movement_big_step_up: ; 532d + ld a, STEP_BIKE << 2 | UP + jp NormalStep +; 5332 + +Movement_big_step_left: ; 5332 + ld a, STEP_BIKE << 2 | LEFT + jp NormalStep +; 5337 + +Movement_big_step_right: ; 5337 + ld a, STEP_BIKE << 2 | RIGHT + jp NormalStep +; 533c + + +Movement_turn_away_down: ; 533c + ld a, STEP_SLOW << 2 | DOWN + jp TurningStep +; 5341 + +Movement_turn_away_up: ; 5341 + ld a, STEP_SLOW << 2 | UP + jp TurningStep +; 5346 + +Movement_turn_away_left: ; 5346 + ld a, STEP_SLOW << 2 | LEFT + jp TurningStep +; 534b + +Movement_turn_away_right: ; 534b + ld a, STEP_SLOW << 2 | RIGHT + jp TurningStep +; 5350 + +Movement_turn_in_down: ; 5350 + ld a, STEP_WALK << 2 | DOWN + jp TurningStep +; 5355 + +Movement_turn_in_up: ; 5355 + ld a, STEP_WALK << 2 | UP + jp TurningStep +; 535a + +Movement_turn_in_left: ; 535a + ld a, STEP_WALK << 2 | LEFT + jp TurningStep +; 535f + +Movement_turn_in_right: ; 535f + ld a, STEP_WALK << 2 | RIGHT + jp TurningStep +; 5364 + +Movement_turn_waterfall_down: ; 5364 + ld a, STEP_BIKE << 2 | DOWN + jp TurningStep +; 5369 + +Movement_turn_waterfall_up: ; 5369 + ld a, STEP_BIKE << 2 | UP + jp TurningStep +; 536e + +Movement_turn_waterfall_left: ; 536e + ld a, STEP_BIKE << 2 | LEFT + jp TurningStep +; 5373 + +Movement_turn_waterfall_right: ; 5373 + ld a, STEP_BIKE << 2 | RIGHT + jp TurningStep +; 5378 + + +Movement_slow_slide_step_down: ; 5378 + ld a, STEP_SLOW << 2 | DOWN + jp SlideStep +; 537d + +Movement_slow_slide_step_up: ; 537d + ld a, STEP_SLOW << 2 | UP + jp SlideStep +; 5382 + +Movement_slow_slide_step_left: ; 5382 + ld a, STEP_SLOW << 2 | LEFT + jp SlideStep +; 5387 + +Movement_slow_slide_step_right: ; 5387 + ld a, STEP_SLOW << 2 | RIGHT + jp SlideStep +; 538c + +Movement_slide_step_down: ; 538c + ld a, STEP_WALK << 2 | DOWN + jp SlideStep +; 5391 + +Movement_slide_step_up: ; 5391 + ld a, STEP_WALK << 2 | UP + jp SlideStep +; 5396 + +Movement_slide_step_left: ; 5396 + ld a, STEP_WALK << 2 | LEFT + jp SlideStep +; 539b + +Movement_slide_step_right: ; 539b + ld a, STEP_WALK << 2 | RIGHT + jp SlideStep +; 53a0 + +Movement_fast_slide_step_down: ; 53a0 + ld a, STEP_BIKE << 2 | DOWN + jp SlideStep +; 53a5 + +Movement_fast_slide_step_up: ; 53a5 + ld a, STEP_BIKE << 2 | UP + jp SlideStep +; 53aa + +Movement_fast_slide_step_left: ; 53aa + ld a, STEP_BIKE << 2 | LEFT + jp SlideStep +; 53af + +Movement_fast_slide_step_right: ; 53af + ld a, STEP_BIKE << 2 | RIGHT + jp SlideStep +; 53b4 + + +Movement_slow_jump_step_down: ; 53b4 + ld a, STEP_SLOW << 2 | DOWN + jp JumpStep +; 53b9 + +Movement_slow_jump_step_up: ; 53b9 + ld a, STEP_SLOW << 2 | UP + jp JumpStep +; 53be + +Movement_slow_jump_step_left: ; 53be + ld a, STEP_SLOW << 2 | LEFT + jp JumpStep +; 53c3 + +Movement_slow_jump_step_right: ; 53c3 + ld a, STEP_SLOW << 2 | RIGHT + jp JumpStep +; 53c8 + +Movement_jump_step_down: ; 53c8 + ld a, STEP_WALK << 2 | DOWN + jp JumpStep +; 53cd + +Movement_jump_step_up: ; 53cd + ld a, STEP_WALK << 2 | UP + jp JumpStep +; 53d2 + +Movement_jump_step_left: ; 53d2 + ld a, STEP_WALK << 2 | LEFT + jp JumpStep +; 53d7 + +Movement_jump_step_right: ; 53d7 + ld a, STEP_WALK << 2 | RIGHT + jp JumpStep +; 53dc + +Movement_fast_jump_step_down: ; 53dc + ld a, STEP_BIKE << 2 | DOWN + jp JumpStep +; 53e1 + +Movement_fast_jump_step_up: ; 53e1 + ld a, STEP_BIKE << 2 | UP + jp JumpStep +; 53e6 + +Movement_fast_jump_step_left: ; 53e6 + ld a, STEP_BIKE << 2 | LEFT + jp JumpStep +; 53eb + +Movement_fast_jump_step_right: ; 53eb + ld a, STEP_BIKE << 2 | RIGHT + jp JumpStep +; 53f0 + + +Movement_turn_step_down: ; 53f0 + ld a, OW_DOWN + jr TurnStep + +Movement_turn_step_up: ; 53f4 + ld a, OW_UP + jr TurnStep + +Movement_turn_step_left: ; 53f8 + ld a, OW_LEFT + jr TurnStep + +Movement_turn_step_right: ; 53fc + ld a, OW_RIGHT + jr TurnStep + +TurnStep: ; 5400 + ld hl, OBJECT_1D ; new facing + add hl, bc + ld [hl], a + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STEP + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_HALF_STEP + ret +; 5412 + +NormalStep: ; 5412 + call InitStep + call UpdateTallGrassFlags + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STEP + + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call CheckSuperTallGrassTile + jr z, .shake_grass + + call CheckGrassTile + jr c, .skip_grass + +.shake_grass + call ShakeGrass + +.skip_grass + ld hl, wCenteredObject + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr z, .player + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_NPC_WALK + ret + +.player + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_PLAYER_WALK + ret +; 5446 + +TurningStep: ; 5446 + call InitStep + call UpdateTallGrassFlags + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_SPIN + + ld hl, wCenteredObject + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr z, .player + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_NPC_WALK + ret + +.player + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_PLAYER_WALK + ret +; 5468 + + +SlideStep: ; 5468 + call InitStep + call UpdateTallGrassFlags + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STAND + + ld hl, wCenteredObject + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr z, .player + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_NPC_WALK + ret + +.player + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_PLAYER_WALK + ret +; 548a + + +JumpStep: ; 548a + call InitStep + ld hl, OBJECT_1F + add hl, bc + ld [hl], $0 + + ld hl, OBJECT_FLAGS2 + add hl, bc + res OVERHEAD, [hl] + + ld hl, OBJECT_ACTION + add hl, bc + ld [hl], OBJECT_ACTION_STEP + + call SpawnShadow + + ld hl, wCenteredObject + ld a, [hMapObjectIndexBuffer] + cp [hl] + jr z, .player + + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_NPC_JUMP + ret + +.player + ld hl, OBJECT_STEP_TYPE + add hl, bc + ld [hl], STEP_TYPE_PLAYER_JUMP + ret +; 54b8 diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm new file mode 100755 index 000000000..5670935e8 --- /dev/null +++ b/engine/overworld/npc_movement.asm @@ -0,0 +1,573 @@ +Function6ec1: ; 6ec1 + + ld hl, OBJECT_PALETTE + add hl, bc + bit 5, [hl] + jr z, .not_bit_5 + + ld hl, OBJECT_FLAGS1 + add hl, bc + bit 4, [hl] ; lost, uncomment next line to fix +; jr nz, .resume + push hl + push bc + call Function6f2c + pop bc + pop hl + ret c + jr .resume + +.not_bit_5 + ld hl, OBJECT_FLAGS1 + add hl, bc + bit 4, [hl] + jr nz, .resume + push hl + push bc + call Function6f07 + pop bc + pop hl + ret c + +.resume + bit 6, [hl] + jr nz, .bit_6 + + push hl + push bc + call WillObjectBumpIntoSomeoneElse + pop bc + pop hl + ret c + +.bit_6 + bit 5, [hl] + jr nz, .bit_5 + push hl + call HasObjectReachedMovementLimit + pop hl + ret c + + push hl + call IsObjectMovingOffEdgeOfScreen + pop hl + ret c + +.bit_5 + and a + ret +; 6f07 + + +Function6f07: ; 6f07 + call Function6f5f + ret c + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + ld hl, OBJECT_PALETTE + add hl, bc + bit OAM_PRIORITY, [hl] + jp nz, Function6fa1 + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + ld d, a + call GetTileCollision + and a ; LANDTILE + jr z, Function6f3e + scf + ret +; 6f2c + +Function6f2c: ; 6f2c + call Function6f5f + ret c + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call GetTileCollision + cp WATERTILE + jr z, Function6f3e + scf + ret +; 6f3e + +Function6f3e: ; 6f3e + ld hl, OBJECT_NEXT_TILE + add hl, bc + ld a, [hl] + call Function6f7f + ret nc + push af + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + maskbits NUM_DIRECTIONS + ld e, a + ld d, 0 + ld hl, .data_6f5b + add hl, de + pop af + and [hl] + ret z + scf + ret +; 6f5b + +.data_6f5b + db DOWN_MASK, UP_MASK, RIGHT_MASK, LEFT_MASK +; 6f5f + +Function6f5f: ; 6f5f + ld hl, OBJECT_STANDING_TILE + add hl, bc + ld a, [hl] + call Function6f7f + ret nc + push af + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + maskbits NUM_DIRECTIONS + ld e, a + ld d, 0 + ld hl, .data_6f7b + add hl, de + pop af + and [hl] + ret z + scf + ret +; 6f7b + +.data_6f7b + db UP_MASK, DOWN_MASK, LEFT_MASK, RIGHT_MASK +; 6f7f + +Function6f7f: ; 6f7f + ld d, a + and $f0 + cp $b0 + jr z, .done + cp $c0 + jr z, .done + xor a + ret + +.done + ld a, d + and 7 + ld e, a + ld d, 0 + ld hl, .data_6f99 + add hl, de + ld a, [hl] + scf + ret +; 6f99 + +.data_6f99 + db 8, 4, 1, 2 + db 10, 6, 9, 5 +; 6fa1 + +Function6fa1: ; 6fa1 + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + maskbits NUM_DIRECTIONS + jr z, .down + dec a + jr z, .up + dec a + jr z, .left + jr .right + +.down + inc e + push de + inc d + jr .continue + +.up + push de + inc d + jr .continue + +.left + push de + inc e + jr .continue + +.right + inc d + push de + inc e + +.continue + call GetCoordTile + call GetTileCollision + pop de + and a ; LANDTILE + jr nz, .not_land + call GetCoordTile + call GetTileCollision + and a ; LANDTILE + jr nz, .not_land + xor a + ret + +.not_land + scf + ret +; 6fd9 + + + +CheckFacingObject:: ; 6fd9 + + call GetFacingTileCoord + +; Double the distance for counter tiles. + call CheckCounterTile + jr nz, .asm_6ff1 + + ld a, [wPlayerStandingMapX] + sub d + cpl + inc a + add d + ld d, a + + ld a, [wPlayerStandingMapY] + sub e + cpl + inc a + add e + ld e, a + +.asm_6ff1 + ld bc, wObjectStructs ; redundant + ld a, 0 + ld [hMapObjectIndexBuffer], a + call IsNPCAtCoord + ret nc + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + cp STANDING + jr z, .standing + xor a + ret + +.standing + scf + ret +; 7009 + + +WillObjectBumpIntoSomeoneElse: ; 7009 + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + jr IsNPCAtCoord +; 7015 + +Unreferenced_Function7015: + ld a, [hMapObjectIndexBuffer] + call GetObjectStruct + call .CheckWillBeFacingNPC + call IsNPCAtCoord + ret + +.CheckWillBeFacingNPC: ; 7021 + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + call GetSpriteDirection + and a + jr z, .down + cp OW_UP + jr z, .up + cp OW_LEFT + jr z, .left + inc d + ret + +.down + inc e + ret + +.up + dec e + ret + +.left + dec d + ret +; 7041 + +IsNPCAtCoord: ; 7041 + ld bc, wObjectStructs + xor a +.loop + ld [hObjectStructIndexBuffer], a + call DoesObjectHaveASprite + jr z, .next + + ld hl, OBJECT_FLAGS1 + add hl, bc + bit 7, [hl] + jr nz, .next + + ld hl, OBJECT_PALETTE + add hl, bc + bit 7, [hl] + jr z, .got + + call Function7171 + jr nc, .ok + jr .ok2 + +.got + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr nz, .ok + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [hl] + cp e + jr nz, .ok + +.ok2 + ld a, [hMapObjectIndexBuffer] + ld l, a + ld a, [hObjectStructIndexBuffer] + cp l + jr nz, .setcarry + +.ok + ld hl, OBJECT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr nz, .next + ld hl, OBJECT_MAP_Y + add hl, bc + ld a, [hl] + cp e + jr nz, .next + ld a, [hMapObjectIndexBuffer] + ld l, a + ld a, [hObjectStructIndexBuffer] + cp l + jr nz, .setcarry + +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hObjectStructIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + and a + ret + +.setcarry + scf + ret +; 70a4 + +HasObjectReachedMovementLimit: ; 70a4 + ld hl, OBJECT_RADIUS + add hl, bc + ld a, [hl] + and a + jr z, .nope + and $f + jr z, .check_y + ld e, a + ld d, a + ld hl, OBJECT_INIT_X + add hl, bc + ld a, [hl] + sub d + ld d, a + ld a, [hl] + add e + ld e, a + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr z, .yes + cp e + jr z, .yes + +.check_y + ld hl, OBJECT_RADIUS + add hl, bc + ld a, [hl] + swap a + and $f + jr z, .nope + ld e, a + ld d, a + ld hl, OBJECT_INIT_Y + add hl, bc + ld a, [hl] + sub d + ld d, a + ld a, [hl] + add e + ld e, a + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [hl] + cp d + jr z, .yes + cp e + jr z, .yes + +.nope + xor a + ret + +.yes + scf + ret +; 70ed + +IsObjectMovingOffEdgeOfScreen: ; 70ed + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [wXCoord] + cp [hl] + jr z, .check_y + jr nc, .yes + add $9 + cp [hl] + jr c, .yes + +.check_y + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [wYCoord] + cp [hl] + jr z, .nope + jr nc, .yes + add $8 + cp [hl] + jr c, .yes + +.nope + and a + ret + +.yes + scf + ret +; 7113 + +Unreferenced_Function7113: + ld a, [wPlayerStandingMapX] + ld d, a + ld a, [wPlayerStandingMapY] + ld e, a + ld bc, wObjectStructs + xor a +.loop + ld [hObjectStructIndexBuffer], a + call DoesObjectHaveASprite + jr z, .next + ld hl, OBJECT_MOVEMENTTYPE + add hl, bc + ld a, [hl] + cp SPRITEMOVEDATA_BIGDOLLSYM + jr nz, .not_snorlax + call Function7171 + jr c, .yes + jr .next + +.not_snorlax + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, [hl] + cp e + jr nz, .check_current_coords + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr nz, .check_current_coords + ld a, [hObjectStructIndexBuffer] + cp $0 + jr z, .next + jr .yes + +.check_current_coords + ld hl, OBJECT_MAP_Y + add hl, bc + ld a, [hl] + cp e + jr nz, .next + ld hl, OBJECT_MAP_X + add hl, bc + ld a, [hl] + cp d + jr nz, .next + jr .yes + +.next + ld hl, OBJECT_STRUCT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hObjectStructIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + xor a + ret + +.yes + scf + ret +; 7171 + + +Function7171: ; 7171 + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, d + sub [hl] + jr c, .nope + cp $2 + jr nc, .nope + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, e + sub [hl] + jr c, .nope + cp $2 + jr nc, .nope + scf + ret + +.nope + and a + ret +; 718d diff --git a/engine/overworld/overworld.asm b/engine/overworld/overworld.asm new file mode 100755 index 000000000..381c2d89f --- /dev/null +++ b/engine/overworld/overworld.asm @@ -0,0 +1,715 @@ +GetEmote2bpp: ; 1412a + ld a, $1 + ld [rVBK], a + call Get2bpp + xor a + ld [rVBK], a + ret +; 14135 + +_ReplaceKrisSprite:: ; 14135 + call GetPlayerSprite + ld a, [wUsedSprites] + ld [hUsedSpriteIndex], a + ld a, [wUsedSprites + 1] + ld [hUsedSpriteTile], a + call GetUsedSprite + ret +; 14146 + +Function14146: ; mobile + ld hl, wSpriteFlags + ld a, [hl] + push af + res 7, [hl] + set 6, [hl] + call LoadUsedSpritesGFX + pop af + ld [wSpriteFlags], a + ret +; 14157 + +Function14157: ; mobile + ld hl, wSpriteFlags + ld a, [hl] + push af + set 7, [hl] + res 6, [hl] + call LoadUsedSpritesGFX + pop af + ld [wSpriteFlags], a + ret +; 14168 + +RefreshSprites:: ; 14168 + call .Refresh + call LoadUsedSpritesGFX + ret +; 1416f + +.Refresh: ; 1416f + xor a + ld bc, wUsedSpritesEnd - wUsedSprites + ld hl, wUsedSprites + call ByteFill + call GetPlayerSprite + call AddMapSprites + call LoadAndSortSprites + ret +; 14183 + +GetPlayerSprite: ; 14183 +; Get Chris or Kris's sprite. + ld hl, ChrisStateSprites + ld a, [wPlayerSpriteSetupFlags] + bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a + jr nz, .go + ld a, [wPlayerGender] + bit PLAYERGENDER_FEMALE_F, a + jr z, .go + ld hl, KrisStateSprites + +.go + ld a, [wPlayerState] + ld c, a +.loop + ld a, [hli] + cp c + jr z, .good + inc hl + cp -1 + jr nz, .loop + +; Any player state not in the array defaults to Chris's sprite. + xor a ; ld a, PLAYER_NORMAL + ld [wPlayerState], a + ld a, SPRITE_CHRIS + jr .finish + +.good + ld a, [hl] + +.finish + ld [wUsedSprites + 0], a + ld [wPlayerSprite], a + ld [wPlayerObjectSprite], a + ret + +INCLUDE "data/sprites/player_sprites.asm" + + +AddMapSprites: ; 141c9 + call GetMapEnvironment + call CheckOutdoorMap + jr z, .outdoor + call AddIndoorSprites + ret + +.outdoor + call AddOutdoorSprites + ret +; 141d9 + + +AddIndoorSprites: ; 141d9 + ld hl, wMap1ObjectSprite + ld a, 1 +.loop + push af + ld a, [hl] + call AddSpriteGFX + ld de, OBJECT_LENGTH + add hl, de + pop af + inc a + cp NUM_OBJECTS + jr nz, .loop + ret +; 141ee + + +AddOutdoorSprites: ; 141ee + ld a, [wMapGroup] + dec a + ld c, a + ld b, 0 + ld hl, OutdoorSprites + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld c, MAX_OUTDOOR_SPRITES +.loop + push bc + ld a, [hli] + call AddSpriteGFX + pop bc + dec c + jr nz, .loop + ret +; 14209 + + +LoadUsedSpritesGFX: ; 14209 + ld a, MAPCALLBACK_SPRITES + call RunMapCallback + call GetUsedSprites + call .LoadMiscTiles + ret +; 14215 + +.LoadMiscTiles: ; 14215 + ld a, [wSpriteFlags] + bit 6, a + ret nz + + ld c, EMOTE_SHADOW + farcall LoadEmote + call GetMapEnvironment + call CheckOutdoorMap + ld c, EMOTE_GRASS_RUSTLE + jr z, .outdoor + ld c, EMOTE_BOULDER_DUST +.outdoor + farcall LoadEmote + ret +; 14236 + + + +SafeGetSprite: ; 14236 + push hl + call GetSprite + pop hl + ret +; 1423c + +GetSprite: ; 1423c + call GetMonSprite + ret c + + ld hl, OverworldSprites + SPRITEDATA_ADDR + dec a + ld c, a + ld b, 0 + ld a, NUM_SPRITEDATA_FIELDS + call AddNTimes + ; load the address into de + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ; load the length into c + ld a, [hli] + swap a + ld c, a + ; load the sprite bank into both b and h + ld b, [hl] + ld a, [hli] + ; load the sprite type into l + ld l, [hl] + ld h, a + ret +; 14259 + + +GetMonSprite: ; 14259 +; Return carry if a monster sprite was loaded. + + cp SPRITE_POKEMON + jr c, .Normal + cp SPRITE_DAY_CARE_MON_1 + jr z, .BreedMon1 + cp SPRITE_DAY_CARE_MON_2 + jr z, .BreedMon2 + cp SPRITE_VARS + jr nc, .Variable + jr .Icon + +.Normal: + and a + ret + +.Icon: + sub SPRITE_POKEMON + ld e, a + ld d, 0 + ld hl, SpriteMons + add hl, de + ld a, [hl] + jr .Mon + +.BreedMon1 + ld a, [wBreedMon1Species] + jr .Mon + +.BreedMon2 + ld a, [wBreedMon2Species] + +.Mon: + ld e, a + and a + jr z, .NoBreedmon + + farcall LoadOverworldMonIcon + + ld l, 1 + ld h, 0 + scf + ret + +.Variable: + sub SPRITE_VARS + ld e, a + ld d, 0 + ld hl, wVariableSprites + add hl, de + ld a, [hl] + and a + jp nz, GetMonSprite + +.NoBreedmon: + ld a, 1 + ld l, 1 + ld h, 0 + and a + ret +; 142a7 + + +_DoesSpriteHaveFacings:: ; 142a7 +; Checks to see whether we can apply a facing to a sprite. +; Returns carry unless the sprite is a Pokemon or a Still Sprite. + cp SPRITE_POKEMON + jr nc, .only_down + + push hl + push bc + ld hl, OverworldSprites + SPRITEDATA_TYPE + dec a + ld c, a + ld b, 0 + ld a, NUM_SPRITEDATA_FIELDS + call AddNTimes + ld a, [hl] + pop bc + pop hl + cp STILL_SPRITE + jr nz, .only_down + scf + ret + +.only_down + and a + ret +; 142c4 + + +_GetSpritePalette:: ; 142c4 + ld a, c + call GetMonSprite + jr c, .is_pokemon + + ld hl, OverworldSprites + SPRITEDATA_PALETTE + dec a + ld c, a + ld b, 0 + ld a, NUM_SPRITEDATA_FIELDS + call AddNTimes + ld c, [hl] + ret + +.is_pokemon + xor a + ld c, a + ret +; 142db + + +LoadAndSortSprites: ; 142db + call LoadSpriteGFX + call SortUsedSprites + call ArrangeUsedSprites + ret +; 142e5 + + +AddSpriteGFX: ; 142e5 +; Add any new sprite ids to a list of graphics to be loaded. +; Return carry if the list is full. + + push hl + push bc + ld b, a + ld hl, wUsedSprites + 2 + ld c, SPRITE_GFX_LIST_CAPACITY - 1 +.loop + ld a, [hl] + cp b + jr z, .exists + and a + jr z, .new + inc hl + inc hl + dec c + jr nz, .loop + + pop bc + pop hl + scf + ret + +.exists + pop bc + pop hl + and a + ret + +.new + ld [hl], b + pop bc + pop hl + and a + ret +; 14306 + + +LoadSpriteGFX: ; 14306 +; Bug: b is not preserved, so it's useless as a next count. +; Uncomment the lines below to fix. + + ld hl, wUsedSprites + ld b, SPRITE_GFX_LIST_CAPACITY +.loop + ld a, [hli] + and a + jr z, .done + push hl + call .LoadSprite + pop hl + ld [hli], a + dec b + jr nz, .loop + +.done + ret + +.LoadSprite: + ; push bc + call GetSprite + ; pop bc + ld a, l + ret +; 1431e + + +SortUsedSprites: ; 1431e +; Bubble-sort sprites by type. + +; Run backwards through wUsedSprites to find the last one. + + ld c, SPRITE_GFX_LIST_CAPACITY + ld de, wUsedSprites + (SPRITE_GFX_LIST_CAPACITY - 1) * 2 +.FindLastSprite: + ld a, [de] + and a + jr nz, .FoundLastSprite + dec de + dec de + dec c + jr nz, .FindLastSprite +.FoundLastSprite: + dec c + jr z, .quit + +; If the length of the current sprite is +; higher than a later one, swap them. + + inc de + ld hl, wUsedSprites + 1 + +.CheckSprite: + push bc + push de + push hl + +.CheckFollowing: + ld a, [de] + cp [hl] + jr nc, .loop + +; Swap the two sprites. + + ld b, a + ld a, [hl] + ld [hl], b + ld [de], a + dec de + dec hl + ld a, [de] + ld b, a + ld a, [hl] + ld [hl], b + ld [de], a + inc de + inc hl + +; Keep doing this until everything's in order. + +.loop + dec de + dec de + dec c + jr nz, .CheckFollowing + + pop hl + inc hl + inc hl + pop de + pop bc + dec c + jr nz, .CheckSprite + +.quit + ret +; 14355 + + +ArrangeUsedSprites: ; 14355 +; Get the length of each sprite and space them out in VRAM. +; Crystal introduces a second table in VRAM bank 0. + + ld hl, wUsedSprites + ld c, SPRITE_GFX_LIST_CAPACITY + ld b, 0 +.FirstTableLength: +; Keep going until the end of the list. + ld a, [hli] + and a + jr z, .quit + + ld a, [hl] + call GetSpriteLength + +; Spill over into the second table after $80 tiles. + add b + cp $80 + jr z, .loop + jr nc, .SecondTable + +.loop + ld [hl], b + inc hl + ld b, a + +; Assumes the next table will be reached before c hits 0. + dec c + jr nz, .FirstTableLength + +.SecondTable: +; The second tile table starts at tile $80. + ld b, $80 + dec hl +.SecondTableLength: +; Keep going until the end of the list. + ld a, [hli] + and a + jr z, .quit + + ld a, [hl] + call GetSpriteLength + +; There are only two tables, so don't go any further than that. + add b + jr c, .quit + + ld [hl], b + ld b, a + inc hl + + dec c + jr nz, .SecondTableLength + +.quit + ret +; 14386 + + +GetSpriteLength: ; 14386 +; Return the length of sprite type a in tiles. + + cp WALKING_SPRITE + jr z, .AnyDirection + cp STANDING_SPRITE + jr z, .AnyDirection + cp STILL_SPRITE + jr z, .OneDirection + + ld a, 12 + ret + +.AnyDirection: + ld a, 12 + ret + +.OneDirection: + ld a, 4 + ret +; 1439b + + +GetUsedSprites: ; 1439b + ld hl, wUsedSprites + ld c, SPRITE_GFX_LIST_CAPACITY + +.loop + ld a, [wSpriteFlags] + res 5, a + ld [wSpriteFlags], a + + ld a, [hli] + and a + jr z, .done + ld [hUsedSpriteIndex], a + + ld a, [hli] + ld [hUsedSpriteTile], a + + bit 7, a + jr z, .dont_set + + ld a, [wSpriteFlags] + set 5, a ; load VBank0 + ld [wSpriteFlags], a + +.dont_set + push bc + push hl + call GetUsedSprite + pop hl + pop bc + dec c + jr nz, .loop + +.done + ret +; 143c8 + +GetUsedSprite: ; 143c8 + ld a, [hUsedSpriteIndex] + call SafeGetSprite + ld a, [hUsedSpriteTile] + call .GetTileAddr + push hl + push de + push bc + ld a, [wSpriteFlags] + bit 7, a + jr nz, .skip + call .CopyToVram + +.skip + pop bc + ld l, c + ld h, $0 +rept 4 + add hl, hl +endr + pop de + add hl, de + ld d, h + ld e, l + pop hl + + ld a, [wSpriteFlags] + bit 5, a + jr nz, .done + bit 6, a + jr nz, .done + + ld a, [hUsedSpriteIndex] + call _DoesSpriteHaveFacings + jr c, .done + + ld a, h + add $8 + ld h, a + call .CopyToVram + +.done + ret +; 14406 + +.GetTileAddr: ; 14406 +; Return the address of tile (a) in (hl). + and $7f + ld l, a + ld h, 0 +rept 4 + add hl, hl +endr + ld a, l + add LOW(vTiles0) + ld l, a + ld a, h + adc HIGH(vTiles0) + ld h, a + ret +; 14418 + +.CopyToVram: ; 14418 + ld a, [rVBK] + push af + ld a, [wSpriteFlags] + bit 5, a + ld a, $1 + jr z, .bankswitch + ld a, $0 + +.bankswitch + ld [rVBK], a + call Get2bpp + pop af + ld [rVBK], a + ret +; 1442f + +LoadEmote:: ; 1442f +; Get the address of the pointer to emote c. + ld a, c + ld bc, 6 ; sizeof(emote) + ld hl, Emotes + call AddNTimes +; Load the emote address into de + ld e, [hl] + inc hl + ld d, [hl] +; load the length of the emote (in tiles) into c + inc hl + ld c, [hl] + swap c +; load the emote pointer bank into b + inc hl + ld b, [hl] +; load the VRAM destination into hl + inc hl + ld a, [hli] + ld h, [hl] + ld l, a +; if the emote has a length of 0, do not proceed (error handling) + ld a, c + and a + ret z + call GetEmote2bpp + ret +; 1444d + + +INCLUDE "data/sprites/emotes.asm" + +INCLUDE "data/sprites/sprite_mons.asm" + +INCLUDE "data/maps/outdoor_sprites.asm" + +INCLUDE "data/sprites/sprites.asm" diff --git a/engine/overworld/player_movement.asm b/engine/overworld/player_movement.asm new file mode 100755 index 000000000..ef9afc7ad --- /dev/null +++ b/engine/overworld/player_movement.asm @@ -0,0 +1,851 @@ +DoPlayerMovement:: ; 80000 + + call .GetDPad + ld a, movement_step_sleep + ld [wMovementAnimation], a + xor a + ld [wd041], a + call .TranslateIntoMovement + ld c, a + ld a, [wMovementAnimation] + ld [wPlayerNextMovement], a + ret + +.GetDPad: + + ld a, [hJoyDown] + ld [wCurInput], a + +; Standing downhill instead moves down. + + ld hl, wBikeFlags + bit BIKEFLAGS_DOWNHILL_F, [hl] + ret z + + ld c, a + and D_PAD + ret nz + + ld a, c + or D_DOWN + ld [wCurInput], a + ret +; 8002d + +.TranslateIntoMovement: + ld a, [wPlayerState] + cp PLAYER_NORMAL + jr z, .Normal + cp PLAYER_SURF + jr z, .Surf + cp PLAYER_SURF_PIKA + jr z, .Surf + cp PLAYER_BIKE + jr z, .Normal + cp PLAYER_SKATE + jr z, .Ice + +.Normal: + call .CheckForced + call .GetAction + call .CheckTile + ret c + call .CheckTurning + ret c + call .TryStep + ret c + call .TryJump + ret c + call .CheckWarp + ret c + jr .NotMoving + +.Surf: + call .CheckForced + call .GetAction + call .CheckTile + ret c + call .CheckTurning + ret c + call .TrySurf + ret c + jr .NotMoving + +.Ice: + call .CheckForced + call .GetAction + call .CheckTile + ret c + call .CheckTurning + ret c + call .TryStep + ret c + call .TryJump + ret c + call .CheckWarp + ret c + ld a, [wWalkingDirection] + cp STANDING + jr z, .HitWall + call .BumpSound +.HitWall: + call .StandInPlace + xor a + ret + +.NotMoving: + ld a, [wWalkingDirection] + cp STANDING + jr z, .Standing + +; Walking into an edge warp won't bump. + ld a, [wEngineBuffer4] + and a + jr nz, .CantMove + call .BumpSound +.CantMove: + call ._WalkInPlace + xor a + ret + +.Standing: + call .StandInPlace + xor a + ret +; 800b7 + +.CheckTile: ; 800b7 +; Tiles such as waterfalls and warps move the player +; in a given direction, overriding input. + + ld a, [wPlayerStandingTile] + ld c, a + call CheckWhirlpoolTile + jr c, .not_whirlpool + ld a, 3 + scf + ret + +.not_whirlpool + and $f0 + cp HI_NYBBLE_CURRENT + jr z, .water + cp HI_NYBBLE_WALK + jr z, .land1 + cp HI_NYBBLE_WALK_ALT + jr z, .land2 + cp HI_NYBBLE_WARPS + jr z, .warps + jr .no_walk + +.water + ld a, c + maskbits NUM_DIRECTIONS + ld c, a + ld b, 0 + ld hl, .water_table + add hl, bc + ld a, [hl] + ld [wWalkingDirection], a + jr .continue_walk + +.water_table + db RIGHT ; COLL_WATERFALL_RIGHT + db LEFT ; COLL_WATERFALL_LEFT + db UP ; COLL_WATERFALL_UP + db DOWN ; COLL_WATERFALL + +.land1 + ld a, c + and 7 + ld c, a + ld b, 0 + ld hl, .land1_table + add hl, bc + ld a, [hl] + cp STANDING + jr z, .no_walk + ld [wWalkingDirection], a + jr .continue_walk + +.land1_table + db STANDING ; COLL_BRAKE + db RIGHT ; COLL_WALK_RIGHT + db LEFT ; COLL_WALK_LEFT + db UP ; COLL_WALK_UP + db DOWN ; COLL_WALK_DOWN + db STANDING ; COLL_BRAKE_45 + db STANDING ; COLL_BRAKE_46 + db STANDING ; COLL_BRAKE_47 + +.land2 + ld a, c + and 7 + ld c, a + ld b, 0 + ld hl, .land2_table + add hl, bc + ld a, [hl] + cp STANDING + jr z, .no_walk + ld [wWalkingDirection], a + jr .continue_walk + +.land2_table + db RIGHT ; COLL_WALK_RIGHT_ALT + db LEFT ; COLL_WALK_LEFT_ALT + db UP ; COLL_WALK_UP_ALT + db DOWN ; COLL_WALK_DOWN_ALT + db STANDING ; COLL_BRAKE_ALT + db STANDING ; COLL_BRAKE_55 + db STANDING ; COLL_BRAKE_56 + db STANDING ; COLL_BRAKE_57 + +.warps + ld a, c + cp COLL_DOOR + jr z, .down + cp COLL_DOOR_79 + jr z, .down + cp COLL_STAIRCASE + jr z, .down + cp COLL_CAVE + jr nz, .no_walk + +.down + ld a, DOWN + ld [wWalkingDirection], a + jr .continue_walk + +.no_walk + xor a + ret + +.continue_walk + ld a, STEP_WALK + call .DoStep + ld a, 5 + scf + ret +; 80147 + +.CheckTurning: ; 80147 +; If the player is turning, change direction first. This also lets +; the player change facing without moving by tapping a direction. + + ld a, [wPlayerTurningDirection] + cp 0 + jr nz, .not_turning + ld a, [wWalkingDirection] + cp STANDING + jr z, .not_turning + + ld e, a + ld a, [wPlayerDirection] + rrca + rrca + maskbits NUM_DIRECTIONS + cp e + jr z, .not_turning + + ld a, STEP_TURN + call .DoStep + ld a, 2 + scf + ret + +.not_turning + xor a + ret +; 8016b + +.TryStep: ; 8016b + +; Surfing actually calls .TrySurf directly instead of passing through here. + ld a, [wPlayerState] + cp PLAYER_SURF + jr z, .TrySurf + cp PLAYER_SURF_PIKA + jr z, .TrySurf + + call .CheckLandPerms + jr c, .bump + + call .CheckNPC + and a + jr z, .bump + cp 2 + jr z, .bump + + ld a, [wPlayerStandingTile] + call CheckIceTile + jr nc, .ice + +; Downhill riding is slower when not moving down. + call .BikeCheck + jr nz, .walk + + ld hl, wBikeFlags + bit BIKEFLAGS_DOWNHILL_F, [hl] + jr z, .fast + + ld a, [wWalkingDirection] + cp DOWN + jr z, .fast + + ld a, STEP_WALK + call .DoStep + scf + ret + +.fast + ld a, STEP_BIKE + call .DoStep + scf + ret + +.walk + ld a, STEP_WALK + call .DoStep + scf + ret + +.ice + ld a, STEP_ICE + call .DoStep + scf + ret + +; unused + xor a + ret + +.bump + xor a + ret +; 801c0 + +.TrySurf: ; 801c0 + + call .CheckSurfPerms + ld [wd040], a + jr c, .surf_bump + + call .CheckNPC + ld [wd03f], a + and a + jr z, .surf_bump + cp 2 + jr z, .surf_bump + + ld a, [wd040] + and a + jr nz, .ExitWater + + ld a, STEP_WALK + call .DoStep + scf + ret + +.ExitWater: + call .GetOutOfWater + call PlayMapMusic + ld a, STEP_WALK + call .DoStep + ld a, 6 + scf + ret + +.surf_bump + xor a + ret +; 801f3 + +.TryJump: ; 801f3 + ld a, [wPlayerStandingTile] + ld e, a + and $f0 + cp HI_NYBBLE_LEDGES + jr nz, .DontJump + + ld a, e + and 7 + ld e, a + ld d, 0 + ld hl, .data_8021e + add hl, de + ld a, [wFacingDirection] + and [hl] + jr z, .DontJump + + ld de, SFX_JUMP_OVER_LEDGE + call PlaySFX + ld a, STEP_LEDGE + call .DoStep + ld a, 7 + scf + ret + +.DontJump: + xor a + ret + +.data_8021e + db FACE_RIGHT ; COLL_HOP_RIGHT + db FACE_LEFT ; COLL_HOP_LEFT + db FACE_UP ; COLL_HOP_UP + db FACE_DOWN ; COLL_HOP_DOWN + db FACE_RIGHT | FACE_DOWN ; COLL_HOP_DOWN_RIGHT + db FACE_DOWN | FACE_LEFT ; COLL_HOP_DOWN_LEFT + db FACE_UP | FACE_RIGHT ; COLL_HOP_UP_RIGHT + db FACE_UP | FACE_LEFT ; COLL_HOP_UP_LEFT +; 80226 + +.CheckWarp: ; 80226 + +; Bug: Since no case is made for STANDING here, it will check +; [.edgewarps + $ff]. This resolves to $3e at $8035a. +; This causes wd041 to be nonzero when standing on tile $3e, +; making bumps silent. + + ld a, [wWalkingDirection] + ; cp STANDING + ; jr z, .not_warp + ld e, a + ld d, 0 + ld hl, .EdgeWarps + add hl, de + ld a, [wPlayerStandingTile] + cp [hl] + jr nz, .not_warp + + ld a, 1 + ld [wd041], a + ld a, [wWalkingDirection] + ; This is in the wrong place. + cp STANDING + jr z, .not_warp + + ld e, a + ld a, [wPlayerDirection] + rrca + rrca + maskbits NUM_DIRECTIONS + cp e + jr nz, .not_warp + call WarpCheck + jr nc, .not_warp + + call .StandInPlace + scf + ld a, 1 + ret + +.not_warp + xor a + ret + +.EdgeWarps: + db COLL_WARP_CARPET_DOWN + db COLL_WARP_CARPET_UP + db COLL_WARP_CARPET_LEFT + db COLL_WARP_CARPET_RIGHT +; 8025f + +.DoStep: + ld e, a + ld d, 0 + ld hl, .Steps + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + + ld a, [wWalkingDirection] + ld e, a + cp STANDING + jp z, .StandInPlace + + add hl, de + ld a, [hl] + ld [wMovementAnimation], a + + ld hl, .FinishFacing + add hl, de + ld a, [hl] + ld [wPlayerTurningDirection], a + + ld a, 4 + ret + +.Steps: + dw .SlowStep + dw .NormalStep + dw .FastStep + dw .JumpStep + dw .SlideStep + dw .TurningStep + dw .BackJumpStep + dw .FinishFacing + +.SlowStep: + slow_step DOWN + slow_step UP + slow_step LEFT + slow_step RIGHT +.NormalStep: + step DOWN + step UP + step LEFT + step RIGHT +.FastStep: + big_step DOWN + big_step UP + big_step LEFT + big_step RIGHT +.JumpStep: + jump_step DOWN + jump_step UP + jump_step LEFT + jump_step RIGHT +.SlideStep: + fast_slide_step DOWN + fast_slide_step UP + fast_slide_step LEFT + fast_slide_step RIGHT +.BackJumpStep: + jump_step UP + jump_step DOWN + jump_step RIGHT + jump_step LEFT +.TurningStep: + turn_step DOWN + turn_step UP + turn_step LEFT + turn_step RIGHT +.FinishFacing: + db $80 + DOWN + db $80 + UP + db $80 + LEFT + db $80 + RIGHT +; 802b3 + +.StandInPlace: ; 802b3 + ld a, 0 + ld [wPlayerTurningDirection], a + ld a, movement_step_sleep + ld [wMovementAnimation], a + xor a + ret +; 802bf + +._WalkInPlace: ; 802bf + ld a, 0 + ld [wPlayerTurningDirection], a + ld a, movement_step_bump + ld [wMovementAnimation], a + xor a + ret +; 802cb + +.CheckForced: ; 802cb +; When sliding on ice, input is forced to remain in the same direction. + + call CheckStandingOnIce + ret nc + + ld a, [wPlayerTurningDirection] + cp 0 + ret z + + maskbits NUM_DIRECTIONS + ld e, a + ld d, 0 + ld hl, .forced_dpad + add hl, de + ld a, [wCurInput] + and BUTTONS + or [hl] + ld [wCurInput], a + ret + +.forced_dpad + db D_DOWN, D_UP, D_LEFT, D_RIGHT +; 802ec + +.GetAction: ; 802ec +; Poll player input and update movement info. + + ld hl, .table + ld de, .table2 - .table1 + ld a, [wCurInput] + bit D_DOWN_F, a + jr nz, .d_down + bit D_UP_F, a + jr nz, .d_up + bit D_LEFT_F, a + jr nz, .d_left + bit D_RIGHT_F, a + jr nz, .d_right +; Standing + jr .update + +.d_down add hl, de +.d_up add hl, de +.d_left add hl, de +.d_right add hl, de + +.update + ld a, [hli] + ld [wWalkingDirection], a + ld a, [hli] + ld [wFacingDirection], a + ld a, [hli] + ld [wWalkingX], a + ld a, [hli] + ld [wWalkingY], a + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hl] + ld [wWalkingTile], a + ret + +.table +; struct: +; walk direction +; facing +; x movement +; y movement +; tile collision pointer +.table1 + db STANDING, FACE_CURRENT, 0, 0 + dw wPlayerStandingTile +.table2 + db RIGHT, FACE_RIGHT, 1, 0 + dw wTileRight + db LEFT, FACE_LEFT, -1, 0 + dw wTileLeft + db UP, FACE_UP, 0, -1 + dw wTileUp + db DOWN, FACE_DOWN, 0, 1 + dw wTileDown +; 80341 + +.CheckNPC: ; 80341 +; Returns 0 if there is an NPC in front that you can't move +; Returns 1 if there is no NPC in front +; Returns 2 if there is a movable NPC in front + ld a, 0 + ld [hMapObjectIndexBuffer], a +; Load the next X coordinate into d + ld a, [wPlayerStandingMapX] + ld d, a + ld a, [wWalkingX] + add d + ld d, a +; Load the next Y coordinate into e + ld a, [wPlayerStandingMapY] + ld e, a + ld a, [wWalkingY] + add e + ld e, a +; Find an object struct with coordinates equal to d,e + ld bc, wObjectStructs ; redundant + farcall IsNPCAtCoord + jr nc, .is_npc + call .CheckStrengthBoulder + jr c, .no_bump + + xor a + ret + +.is_npc + ld a, 1 + ret + +.no_bump + ld a, 2 + ret +; 8036f + +.CheckStrengthBoulder: ; 8036f + + ld hl, wBikeFlags + bit BIKEFLAGS_STRENGTH_ACTIVE_F, [hl] + jr z, .not_boulder + + ld hl, OBJECT_DIRECTION_WALKING + add hl, bc + ld a, [hl] + cp STANDING + jr nz, .not_boulder + + ld hl, OBJECT_PALETTE + add hl, bc + bit 6, [hl] + jr z, .not_boulder + + ld hl, OBJECT_FLAGS2 + add hl, bc + set 2, [hl] + + ld a, [wWalkingDirection] + ld d, a + ld hl, OBJECT_RANGE + add hl, bc + ld a, [hl] + and $fc + or d + ld [hl], a + + scf + ret + +.not_boulder + xor a + ret +; 8039e + +.CheckLandPerms: ; 8039e +; Return 0 if walking onto land and tile permissions allow it. +; Otherwise, return carry. + + ld a, [wTilePermissions] + ld d, a + ld a, [wFacingDirection] + and d + jr nz, .NotWalkable + + ld a, [wWalkingTile] + call .CheckWalkable + jr c, .NotWalkable + + xor a + ret + +.NotWalkable: + scf + ret +; 803b4 + +.CheckSurfPerms: ; 803b4 +; Return 0 if moving in water, or 1 if moving onto land. +; Otherwise, return carry. + + ld a, [wTilePermissions] + ld d, a + ld a, [wFacingDirection] + and d + jr nz, .NotSurfable + + ld a, [wWalkingTile] + call .CheckSurfable + jr c, .NotSurfable + + and a + ret + +.NotSurfable: + scf + ret +; 803ca + +.BikeCheck: ; 803ca + ld a, [wPlayerState] + cp PLAYER_BIKE + ret z + cp PLAYER_SKATE + ret +; 803d3 + +.CheckWalkable: ; 803d3 +; Return 0 if tile a is land. Otherwise, return carry. + + call GetTileCollision + and a ; LANDTILE? + ret z + scf + ret +; 803da + +.CheckSurfable: ; 803da +; Return 0 if tile a is water, or 1 if land. +; Otherwise, return carry. + + call GetTileCollision + cp WATERTILE + jr z, .Water + +; Can walk back onto land from water. + and a ; LANDTILE? + jr z, .Land + + jr .Neither + +.Water: + xor a + ret + +.Land: + ld a, 1 + and a + ret + +.Neither: + scf + ret +; 803ee + +.BumpSound: ; 803ee + + call CheckSFX + ret c + ld de, SFX_BUMP + call PlaySFX + ret +; 803f9 + +.GetOutOfWater: ; 803f9 + push bc + ld a, PLAYER_NORMAL + ld [wPlayerState], a + call ReplaceKrisSprite ; UpdateSprites + pop bc + ret +; 80404 + +CheckStandingOnIce:: ; 80404 + ld a, [wPlayerTurningDirection] + cp 0 + jr z, .not_ice + cp $f0 + jr z, .not_ice + ld a, [wPlayerStandingTile] + call CheckIceTile + jr nc, .yep + ld a, [wPlayerState] + cp PLAYER_SKATE + jr nz, .not_ice + +.yep + scf + ret + +.not_ice + and a + ret +; 80422 + +StopPlayerForEvent:: ; 80422 + ld hl, wPlayerNextMovement + ld a, movement_step_sleep + cp [hl] + ret z + + ld [hl], a + ld a, 0 + ld [wPlayerTurningDirection], a + ret +; 80430 diff --git a/engine/overworld/player_object.asm b/engine/overworld/player_object.asm new file mode 100755 index 000000000..7d287dedb --- /dev/null +++ b/engine/overworld/player_object.asm @@ -0,0 +1,856 @@ +BlankScreen: ; 8000 + call DisableSpriteUpdates + xor a + ld [hBGMapMode], a + call ClearBGPalettes + call ClearSprites + hlcoord 0, 0 + ld bc, wTileMapEnd - wTileMap + ld a, " " + call ByteFill + hlcoord 0, 0, wAttrMap + ld bc, wAttrMapEnd - wAttrMap + ld a, $7 + call ByteFill + call WaitBGMap2 + call SetPalettes + ret + +SpawnPlayer: ; 8029 + ld a, -1 + ld [wObjectFollow_Leader], a + ld [wObjectFollow_Follower], a + ld a, $0 + ld hl, PlayerObjectTemplate + call CopyPlayerObjectTemplate + ld b, $0 + call PlayerSpawn_ConvertCoords + ld a, PLAYER_OBJECT + call GetMapObject + ld hl, MAPOBJECT_COLOR + add hl, bc + ln e, PAL_NPC_RED, OBJECTTYPE_SCRIPT + ld a, [wPlayerSpriteSetupFlags] + bit PLAYERSPRITESETUP_FEMALE_TO_MALE_F, a + jr nz, .ok + ld a, [wPlayerGender] + bit PLAYERGENDER_FEMALE_F, a + jr z, .ok + ln e, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT + +.ok + ld [hl], e + ld a, PLAYER_OBJECT + ld [hMapObjectIndexBuffer], a + ld bc, wMapObjects + ld a, PLAYER_OBJECT + ld [hObjectStructIndexBuffer], a + ld de, wObjectStructs + call CopyMapObjectToObjectStruct + ld a, PLAYER + ld [wCenteredObject], a + ret + +PlayerObjectTemplate: ; 8071 +; A dummy map object used to initialize the player object. +; Shorter than the actual amount copied by two bytes. +; Said bytes seem to be unused. + object_event -4, -4, SPRITE_CHRIS, SPRITEMOVEDATA_PLAYER, 15, 15, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, 0, -1 + +CopyDECoordsToMapObject:: ; 807e + push de + ld a, b + call GetMapObject + pop de + ld hl, MAPOBJECT_X_COORD + add hl, bc + ld [hl], d + ld hl, MAPOBJECT_Y_COORD + add hl, bc + ld [hl], e + ret + +PlayerSpawn_ConvertCoords: ; 808f + push bc + ld a, [wXCoord] + add 4 + ld d, a + ld a, [wYCoord] + add 4 + ld e, a + pop bc + call CopyDECoordsToMapObject + ret + +WriteObjectXY:: ; 80a1 + ld a, b + call CheckObjectVisibility + ret c + + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + ld a, [hMapObjectIndexBuffer] + ld b, a + call CopyDECoordsToMapObject + and a + ret + +RefreshPlayerCoords: ; 80b8 + ld a, [wXCoord] + add 4 + ld d, a + ld hl, wPlayerStandingMapX + sub [hl] + ld [hl], d + ld hl, wMapObjects + MAPOBJECT_X_COORD + ld [hl], d + ld hl, wPlayerLastMapX + ld [hl], d + ld d, a + ld a, [wYCoord] + add 4 + ld e, a + ld hl, wPlayerStandingMapY + sub [hl] + ld [hl], e + ld hl, wMapObjects + MAPOBJECT_Y_COORD + ld [hl], e + ld hl, wPlayerLastMapY + ld [hl], e + ld e, a + ld a, [wObjectFollow_Leader] + cp $0 + ret nz ; wtf + ret + +CopyObjectStruct:: ; 80e7 + call CheckObjectMask + and a + ret nz ; masked + + ld hl, wObjectStructs + OBJECT_STRUCT_LENGTH * 1 + ld a, 1 + ld de, OBJECT_STRUCT_LENGTH +.loop + ld [hObjectStructIndexBuffer], a + ld a, [hl] + and a + jr z, .done + add hl, de + ld a, [hObjectStructIndexBuffer] + inc a + cp NUM_OBJECT_STRUCTS + jr nz, .loop + scf + ret ; overflow + +.done + ld d, h + ld e, l + call CopyMapObjectToObjectStruct + ld hl, wVramState + bit 7, [hl] + ret z + + ld hl, OBJECT_FLAGS2 + add hl, de + set 5, [hl] + ret + +CopyMapObjectToObjectStruct: ; 8116 + call .CopyMapObjectToTempObject + call CopyTempObjectToObjectStruct + ret + +.CopyMapObjectToTempObject: ; 811d + ld a, [hObjectStructIndexBuffer] + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld [hl], a + + ld a, [hMapObjectIndexBuffer] + ld [wTempObjectCopyMapObjectIndex], a + + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + ld [wTempObjectCopySprite], a + + call GetSpriteVTile + ld [wTempObjectCopySpriteVTile], a + + ld a, [hl] + call GetSpritePalette + ld [wTempObjectCopyPalette], a + + ld hl, MAPOBJECT_COLOR + add hl, bc + ld a, [hl] + and $f0 + jr z, .skip_color_override + swap a + and PALETTE_MASK + ld [wTempObjectCopyPalette], a + +.skip_color_override + ld hl, MAPOBJECT_MOVEMENT + add hl, bc + ld a, [hl] + ld [wTempObjectCopyMovement], a + + ld hl, MAPOBJECT_RANGE + add hl, bc + ld a, [hl] + ld [wTempObjectCopyRange], a + + ld hl, MAPOBJECT_X_COORD + add hl, bc + ld a, [hl] + ld [wTempObjectCopyX], a + + ld hl, MAPOBJECT_Y_COORD + add hl, bc + ld a, [hl] + ld [wTempObjectCopyY], a + + ld hl, MAPOBJECT_RADIUS + add hl, bc + ld a, [hl] + ld [wTempObjectCopyRadius], a + ret + +InitializeVisibleSprites: ; 8177 + ld bc, wMapObjects + OBJECT_LENGTH + ld a, 1 +.loop + ld [hMapObjectIndexBuffer], a + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + and a + jr z, .next + + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp -1 + jr nz, .next + + ld a, [wXCoord] + ld d, a + ld a, [wYCoord] + ld e, a + + ld hl, MAPOBJECT_X_COORD + add hl, bc + ld a, [hl] + add 1 + sub d + jr c, .next + + cp MAPOBJECT_SCREEN_WIDTH + jr nc, .next + + ld hl, MAPOBJECT_Y_COORD + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .next + + cp MAPOBJECT_SCREEN_HEIGHT + jr nc, .next + + push bc + call CopyObjectStruct + pop bc + jp c, .ret + +.next + ld hl, OBJECT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECTS + jr nz, .loop + ret + +.ret ; 81c9 + ret + +CheckObjectEnteringVisibleRange:: ; 81ca + nop + ld a, [wPlayerStepDirection] + cp STANDING + ret z + ld hl, .dw + rst JumpTable + ret + +.dw ; 81d6 + dw .Down + dw .Up + dw .Left + dw .Right + +.Up: ; 81de + ld a, [wYCoord] + sub 1 + jr .Vertical + +.Down: ; 81e5 + ld a, [wYCoord] + add 9 +.Vertical: ; 81ea + ld d, a + ld a, [wXCoord] + ld e, a + ld bc, wMapObjects + OBJECT_LENGTH + ld a, 1 +.loop_v + ld [hMapObjectIndexBuffer], a + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + and a + jr z, .next_v + ld hl, MAPOBJECT_Y_COORD + add hl, bc + ld a, d + cp [hl] + jr nz, .next_v + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp -1 + jr nz, .next_v + ld hl, MAPOBJECT_X_COORD + add hl, bc + ld a, [hl] + add 1 + sub e + jr c, .next_v + cp MAPOBJECT_SCREEN_WIDTH + jr nc, .next_v + push de + push bc + call CopyObjectStruct + pop bc + pop de + +.next_v + ld hl, OBJECT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECTS + jr nz, .loop_v + ret + +.Left: ; 8232 + ld a, [wXCoord] + sub 1 + jr .Horizontal + +.Right: ; 8239 + ld a, [wXCoord] + add 10 +.Horizontal: ; 823e + ld e, a + ld a, [wYCoord] + ld d, a + ld bc, wMapObjects + OBJECT_LENGTH + ld a, 1 +.loop_h + ld [hMapObjectIndexBuffer], a + ld hl, MAPOBJECT_SPRITE + add hl, bc + ld a, [hl] + and a + jr z, .next_h + ld hl, MAPOBJECT_X_COORD + add hl, bc + ld a, e + cp [hl] + jr nz, .next_h + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp -1 + jr nz, .next_h + ld hl, MAPOBJECT_Y_COORD + add hl, bc + ld a, [hl] + add 1 + sub d + jr c, .next_h + cp MAPOBJECT_SCREEN_HEIGHT + jr nc, .next_h + push de + push bc + call CopyObjectStruct + pop bc + pop de + +.next_h + ld hl, OBJECT_LENGTH + add hl, bc + ld b, h + ld c, l + ld a, [hMapObjectIndexBuffer] + inc a + cp NUM_OBJECTS + jr nz, .loop_h + ret + +CopyTempObjectToObjectStruct: ; 8286 + ld a, [wTempObjectCopyMapObjectIndex] + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, de + ld [hl], a + + ld a, [wTempObjectCopyMovement] + call CopySpriteMovementData + + ld a, [wTempObjectCopyPalette] + ld hl, OBJECT_PALETTE + add hl, de + or [hl] + ld [hl], a + + ld a, [wTempObjectCopyY] + call .InitYCoord + + ld a, [wTempObjectCopyX] + call .InitXCoord + + ld a, [wTempObjectCopySprite] + ld hl, OBJECT_SPRITE + add hl, de + ld [hl], a + + ld a, [wTempObjectCopySpriteVTile] + ld hl, OBJECT_SPRITE_TILE + add hl, de + ld [hl], a + + ld hl, OBJECT_STEP_TYPE + add hl, de + ld [hl], STEP_TYPE_00 + + ld hl, OBJECT_FACING_STEP + add hl, de + ld [hl], STANDING + + ld a, [wTempObjectCopyRadius] + call .InitRadius + + ld a, [wTempObjectCopyRange] + ld hl, OBJECT_RANGE + add hl, de + ld [hl], a + + and a + ret + +.InitYCoord: ; 82d5 + ld hl, OBJECT_INIT_Y + add hl, de + ld [hl], a + + ld hl, OBJECT_NEXT_MAP_Y + add hl, de + ld [hl], a + + ld hl, wYCoord + sub [hl] + and $f + swap a + ld hl, wPlayerBGMapOffsetY + sub [hl] + ld hl, OBJECT_SPRITE_Y + add hl, de + ld [hl], a + ret + +.InitXCoord: ; 82f1 + ld hl, OBJECT_INIT_X + add hl, de + ld [hl], a + ld hl, OBJECT_NEXT_MAP_X + add hl, de + ld [hl], a + ld hl, wXCoord + sub [hl] + and $f + swap a + ld hl, wPlayerBGMapOffsetX + sub [hl] + ld hl, OBJECT_SPRITE_X + add hl, de + ld [hl], a + ret + +.InitRadius: ; 830d + ld h, a + inc a + and $f + ld l, a + ld a, h + add $10 + and $f0 + or l + ld hl, OBJECT_RADIUS + add hl, de + ld [hl], a + ret + +TrainerWalkToPlayer: ; 831e + ld a, [hLastTalked] + call InitMovementBuffer + ld a, movement_step_sleep + call AppendToMovementBuffer + ld a, [wd03f] + dec a + jr z, .TerminateStep + ld a, [hLastTalked] + ld b, a + ld c, PLAYER + ld d, 1 + call .GetPathToPlayer + call DecrementMovementBufferCount + +.TerminateStep: + ld a, movement_step_end + call AppendToMovementBuffer + ret + +.GetPathToPlayer: ; 8341 + push de + push bc +; get player object struct, load to de + ld a, c + call GetMapObject + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + call GetObjectStruct + ld d, b + ld e, c + +; get last talked object struct, load to bc + pop bc + ld a, b + call GetMapObject + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + call GetObjectStruct + +; get last talked coords, load to bc + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld c, [hl] + ld b, a + +; get player coords, load to de + ld hl, OBJECT_NEXT_MAP_X + add hl, de + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, de + ld e, [hl] + ld d, a + + pop af + call ComputePathToWalkToPlayer + ret + +SurfStartStep: ; 8379 + call InitMovementBuffer + call .GetMovementData + call AppendToMovementBuffer + ld a, movement_step_end + call AppendToMovementBuffer + ret + +.GetMovementData: ; 8388 + ld a, [wPlayerDirection] + srl a + srl a + maskbits NUM_DIRECTIONS + ld e, a + ld d, 0 + ld hl, .movement_data + add hl, de + ld a, [hl] + ret + +.movement_data + slow_step DOWN + slow_step UP + slow_step LEFT + slow_step RIGHT + +FollowNotExact:: ; 839e + push bc + ld a, c + call CheckObjectVisibility + ld d, b + ld e, c + pop bc + ret c + + ld a, b + call CheckObjectVisibility + ret c + +; object 2 is now in bc, object 1 is now in de + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld c, [hl] + ld b, a + + ld hl, OBJECT_NEXT_MAP_X + add hl, de + ld a, [hl] + cp b + jr z, .same_x + jr c, .to_the_left + inc b + jr .continue + +.to_the_left + dec b + jr .continue + +.same_x + ld hl, OBJECT_NEXT_MAP_Y + add hl, de + ld a, [hl] + cp c + jr z, .continue + jr c, .below + inc c + jr .continue + +.below + dec c + +.continue + ld hl, OBJECT_NEXT_MAP_X + add hl, de + ld [hl], b + ld a, b + ld hl, wXCoord + sub [hl] + and $f + swap a + ld hl, wPlayerBGMapOffsetX + sub [hl] + ld hl, OBJECT_SPRITE_X + add hl, de + ld [hl], a + ld hl, OBJECT_NEXT_MAP_Y + add hl, de + ld [hl], c + ld a, c + ld hl, wYCoord + sub [hl] + and $f + swap a + ld hl, wPlayerBGMapOffsetY + sub [hl] + ld hl, OBJECT_SPRITE_Y + add hl, de + ld [hl], a + ld a, [hObjectStructIndexBuffer] + ld hl, OBJECT_RANGE + add hl, de + ld [hl], a + ld hl, OBJECT_MOVEMENTTYPE + add hl, de + ld [hl], SPRITEMOVEDATA_FOLLOWNOTEXACT + ld hl, OBJECT_STEP_TYPE + add hl, de + ld [hl], STEP_TYPE_00 + ret + +GetRelativeFacing:: ; 8417 +; Determines which way map object e would have to turn to face map object d. Returns carry if it's impossible for whatever reason. + ld a, d + call GetMapObject + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp NUM_OBJECT_STRUCTS + jr nc, .carry + ld d, a + ld a, e + call GetMapObject + ld hl, MAPOBJECT_OBJECT_STRUCT_ID + add hl, bc + ld a, [hl] + cp NUM_OBJECT_STRUCTS + jr nc, .carry + ld e, a + call .GetFacing_e_relativeto_d + ret + +.carry + scf + ret + +.GetFacing_e_relativeto_d: ; 8439 +; Determines which way object e would have to turn to face object d. Returns carry if it's impossible. +; load the coordinates of object d into bc + ld a, d + call GetObjectStruct + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld c, [hl] + ld b, a + push bc +; load the coordinates of object e into de + ld a, e + call GetObjectStruct + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + pop bc +; |x1 - x2| + ld a, b + sub d + jr z, .same_x_1 + jr nc, .b_right_of_d_1 + cpl + inc a + +.b_right_of_d_1 +; |y1 - y2| + ld h, a + ld a, c + sub e + jr z, .same_y_1 + jr nc, .c_below_e_1 + cpl + inc a + +.c_below_e_1 +; |y1 - y2| - |x1 - x2| + sub h + jr c, .same_y_1 + +.same_x_1 +; compare the y coordinates + ld a, c + cp e + jr z, .same_x_and_y + jr c, .c_directly_below_e +; c directly above e + ld d, DOWN + and a + ret + +.c_directly_below_e + ld d, UP + and a + ret + +.same_y_1 + ld a, b + cp d + jr z, .same_x_and_y + jr c, .b_directly_right_of_d +; b directly left of d + ld d, RIGHT + and a + ret + +.b_directly_right_of_d + ld d, LEFT + and a + ret + +.same_x_and_y + scf + ret + +QueueFollowerFirstStep: ; 848a + call .QueueFirstStep + jr c, .same + ld [wFollowMovementQueue], a + xor a + ld [wFollowerMovementQueueLength], a + ret + +.same + ld a, -1 + ld [wFollowerMovementQueueLength], a + ret + +.QueueFirstStep: + ld a, [wObjectFollow_Leader] + call GetObjectStruct + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld d, [hl] + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld e, [hl] + ld a, [wObjectFollow_Follower] + call GetObjectStruct + ld hl, OBJECT_NEXT_MAP_X + add hl, bc + ld a, d + cp [hl] + jr z, .check_y + jr c, .left + and a + ld a, movement_step + RIGHT + ret + +.left + and a + ld a, movement_step + LEFT + ret + +.check_y + ld hl, OBJECT_NEXT_MAP_Y + add hl, bc + ld a, e + cp [hl] + jr z, .same_xy + jr c, .up + and a + ld a, movement_step + DOWN + ret + +.up + and a + ld a, movement_step + UP + ret + +.same_xy + scf + ret diff --git a/engine/overworld/player_step.asm b/engine/overworld/player_step.asm new file mode 100755 index 000000000..675c6553b --- /dev/null +++ b/engine/overworld/player_step.asm @@ -0,0 +1,270 @@ +_HandlePlayerStep:: ; d497 (3:5497) + ld a, [wPlayerStepFlags] + and a + ret z + bit 7, a ; starting step + jr nz, .update_overworld_map + bit 6, a ; finishing step + jr nz, .update_player_coords + bit 5, a ; ongoing step + jr nz, .finish + ret + +.update_overworld_map + ld a, 4 + ld [wHandlePlayerStep], a + call UpdateOverworldMap + jr .finish + +.update_player_coords + call UpdatePlayerCoords + jr .finish + +.finish + call HandlePlayerStep + ld a, [wPlayerStepVectorX] + ld d, a + ld a, [wPlayerStepVectorY] + ld e, a + ld a, [wPlayerBGMapOffsetX] + sub d + ld [wPlayerBGMapOffsetX], a + ld a, [wPlayerBGMapOffsetY] + sub e + ld [wPlayerBGMapOffsetY], a + ret + +ScrollScreen:: ; d4d2 (3:54d2) + ld a, [wPlayerStepVectorX] + ld d, a + ld a, [wPlayerStepVectorY] + ld e, a + ld a, [hSCX] + add d + ld [hSCX], a + ld a, [hSCY] + add e + ld [hSCY], a + ret + +HandlePlayerStep: ; d4e5 (3:54e5) + ld hl, wHandlePlayerStep + ld a, [hl] + and a + ret z + dec [hl] + ld a, [hl] + ld hl, .Jumptable + rst JumpTable + ret + +.Jumptable: ; d4f2 (3:54f2) + dw GetMovementPermissions + dw BufferScreen + dw .mobile + dw .fail2 +; The rest are never used. Ever. + dw .fail1 + dw .fail1 + dw .fail1 + dw .fail1 + dw .fail1 + dw .fail1 + dw .fail1 + +.fail1 ; d508 (3:5508) + ret + +.mobile ; d509 (3:5509) + farcall StubbedTrainerRankings_StepCount + ret + +.fail2 ; d510 (3:5510) + ret + +UpdatePlayerCoords: ; d511 (3:5511) + ld a, [wPlayerStepDirection] + and a + jr nz, .check_step_down + ld hl, wYCoord + inc [hl] + ret + +.check_step_down + cp UP + jr nz, .check_step_left + ld hl, wYCoord + dec [hl] + ret + +.check_step_left + cp LEFT + jr nz, .check_step_right + ld hl, wXCoord + dec [hl] + ret + +.check_step_right + cp RIGHT + ret nz + ld hl, wXCoord + inc [hl] + ret + +UpdateOverworldMap: ; d536 (3:5536) + ld a, [wPlayerStepDirection] + and a + jr z, .step_down + cp UP + jr z, .step_up + cp LEFT + jr z, .step_left + cp RIGHT + jr z, .step_right + ret + +.step_down + call .ScrollOverworldMapDown + call LoadMapPart + call ScrollMapUp + ret + +.step_up + call .ScrollOverworldMapUp + call LoadMapPart + call ScrollMapDown + ret + +.step_left + call .ScrollOverworldMapLeft + call LoadMapPart + call ScrollMapRight + ret + +.step_right + call .ScrollOverworldMapRight + call LoadMapPart + call ScrollMapLeft + ret + +.ScrollOverworldMapDown: ; d571 (3:5571) + ld a, [wBGMapAnchor] + add 2 * BG_MAP_WIDTH + ld [wBGMapAnchor], a + jr nc, .not_overflowed + ld a, [wBGMapAnchor + 1] + inc a + and %11 + or HIGH(vBGMap0) + ld [wBGMapAnchor + 1], a +.not_overflowed + ld hl, wMetatileStandingY + inc [hl] + ld a, [hl] + cp 2 ; was 1 + jr nz, .done_down + ld [hl], 0 + call .Add6ToOverworldMapAnchor +.done_down + ret + +.Add6ToOverworldMapAnchor: ; d595 (3:5595) + ld hl, wOverworldMapAnchor + ld a, [wMapWidth] + add 6 + add [hl] + ld [hli], a + ret nc + inc [hl] + ret + +.ScrollOverworldMapUp: ; d5a2 (3:55a2) + ld a, [wBGMapAnchor] + sub 2 * BG_MAP_WIDTH + ld [wBGMapAnchor], a + jr nc, .not_underflowed + ld a, [wBGMapAnchor + 1] + dec a + and %11 + or HIGH(vBGMap0) + ld [wBGMapAnchor + 1], a +.not_underflowed + ld hl, wMetatileStandingY + dec [hl] + ld a, [hl] + cp -1 ; was 0 + jr nz, .done_up + ld [hl], $1 + call .Sub6FromOverworldMapAnchor +.done_up + ret + +.Sub6FromOverworldMapAnchor: ; d5c6 (3:55c6) + ld hl, wOverworldMapAnchor + ld a, [wMapWidth] + add 6 + ld b, a + ld a, [hl] + sub b + ld [hli], a + ret nc + dec [hl] + ret + +.ScrollOverworldMapLeft: ; d5d5 (3:55d5) + ld a, [wBGMapAnchor] + ld e, a + and $e0 + ld d, a + ld a, e + sub $2 + and $1f + or d + ld [wBGMapAnchor], a + ld hl, wMetatileStandingX + dec [hl] + ld a, [hl] + cp -1 + jr nz, .done_left + ld [hl], 1 + call .DecrementwOverworldMapAnchor +.done_left + ret + +.DecrementwOverworldMapAnchor: ; d5f4 (3:55f4) + ld hl, wOverworldMapAnchor + ld a, [hl] + sub 1 + ld [hli], a + ret nc + dec [hl] + ret + +.ScrollOverworldMapRight: ; d5fe (3:55fe) + ld a, [wBGMapAnchor] + ld e, a + and $e0 + ld d, a + ld a, e + add $2 + and $1f + or d + ld [wBGMapAnchor], a + ld hl, wMetatileStandingX + inc [hl] + ld a, [hl] + cp 2 + jr nz, .done_right + ld [hl], 0 + call .IncrementwOverworldMapAnchor +.done_right + ret + +.IncrementwOverworldMapAnchor: ; d61d (3:561d) + ld hl, wOverworldMapAnchor + ld a, [hl] + add 1 + ld [hli], a + ret nc + inc [hl] + ret diff --git a/engine/overworld/scripting.asm b/engine/overworld/scripting.asm new file mode 100644 index 000000000..f65f2f9c0 --- /dev/null +++ b/engine/overworld/scripting.asm @@ -0,0 +1,2857 @@ +; Event scripting commands. + + +EnableScriptMode:: + push af + ld a, SCRIPT_READ + ld [wScriptMode], a + pop af + ret + +ScriptEvents:: + call StartScript +.loop + ld a, [wScriptMode] + ld hl, .modes + rst JumpTable + call CheckScript + jr nz, .loop + ret + +.modes + dw EndScript + dw RunScriptCommand + dw WaitScriptMovement + dw WaitScript + +EndScript: + call StopScript + ret + +WaitScript: + call StopScript + + ld hl, wScriptDelay + dec [hl] + ret nz + + farcall Function58b9 + + ld a, SCRIPT_READ + ld [wScriptMode], a + call StartScript + ret + +WaitScriptMovement: + call StopScript + + ld hl, wVramState + bit 7, [hl] + ret nz + + farcall Function58b9 + + ld a, SCRIPT_READ + ld [wScriptMode], a + call StartScript + ret + +RunScriptCommand: + call GetScriptByte + ld hl, ScriptCommandTable + rst JumpTable + ret + + +ScriptCommandTable: +; entries correspond to macros/scripts/events.asm enumeration + dw Script_scall ; 00 + dw Script_farscall ; 01 + dw Script_ptcall ; 02 + dw Script_jump ; 03 + dw Script_farjump ; 04 + dw Script_ptjump ; 05 + dw Script_ifequal ; 06 + dw Script_ifnotequal ; 07 + dw Script_iffalse ; 08 + dw Script_iftrue ; 09 + dw Script_ifgreater ; 0a + dw Script_ifless ; 0b + dw Script_jumpstd ; 0c + dw Script_callstd ; 0d + dw Script_callasm ; 0e + dw Script_special ; 0f + dw Script_ptcallasm ; 10 + dw Script_checkmapscene ; 11 + dw Script_setmapscene ; 12 + dw Script_checkscene ; 13 + dw Script_setscene ; 14 + dw Script_writebyte ; 15 + dw Script_addvar ; 16 + dw Script_random ; 17 + dw Script_checkver ; 18 + dw Script_copybytetovar ; 19 + dw Script_copyvartobyte ; 1a + dw Script_loadvar ; 1b + dw Script_checkcode ; 1c + dw Script_writevarcode ; 1d + dw Script_writecode ; 1e + dw Script_giveitem ; 1f + dw Script_takeitem ; 20 + dw Script_checkitem ; 21 + dw Script_givemoney ; 22 + dw Script_takemoney ; 23 + dw Script_checkmoney ; 24 + dw Script_givecoins ; 25 + dw Script_takecoins ; 26 + dw Script_checkcoins ; 27 + dw Script_addcellnum ; 28 + dw Script_delcellnum ; 29 + dw Script_checkcellnum ; 2a + dw Script_checktime ; 2b + dw Script_checkpoke ; 2c + dw Script_givepoke ; 2d + dw Script_giveegg ; 2e + dw Script_givepokeitem ; 2f + dw Script_checkpokeitem ; 30 + dw Script_checkevent ; 31 + dw Script_clearevent ; 32 + dw Script_setevent ; 33 + dw Script_checkflag ; 34 + dw Script_clearflag ; 35 + dw Script_setflag ; 36 + dw Script_wildon ; 37 + dw Script_wildoff ; 38 + dw Script_xycompare ; 39 + dw Script_warpmod ; 3a + dw Script_blackoutmod ; 3b + dw Script_warp ; 3c + dw Script_readmoney ; 3d + dw Script_readcoins ; 3e + dw Script_vartomem ; 3f + dw Script_pokenamemem ; 40 + dw Script_itemtotext ; 41 + dw Script_mapnametotext ; 42 + dw Script_trainertotext ; 43 + dw Script_stringtotext ; 44 + dw Script_itemnotify ; 45 + dw Script_pocketisfull ; 46 + dw Script_opentext ; 47 + dw Script_refreshscreen ; 48 + dw Script_closetext ; 49 + dw Script_loadbytec2cf ; 4a + dw Script_farwritetext ; 4b + dw Script_writetext ; 4c + dw Script_repeattext ; 4d + dw Script_yesorno ; 4e + dw Script_loadmenu ; 4f + dw Script_closewindow ; 50 + dw Script_jumptextfaceplayer ; 51 +if _CRYSTAL + dw Script_farjumptext ; 52 +endc + dw Script_jumptext ; 53 + dw Script_waitbutton ; 54 + dw Script_buttonsound ; 55 + dw Script_pokepic ; 56 + dw Script_closepokepic ; 57 + dw Script__2dmenu ; 58 + dw Script_verticalmenu ; 59 + dw Script_loadpikachudata ; 5a + dw Script_randomwildmon ; 5b + dw Script_loadmemtrainer ; 5c + dw Script_loadwildmon ; 5d + dw Script_loadtrainer ; 5e + dw Script_startbattle ; 5f + dw Script_reloadmapafterbattle ; 60 + dw Script_catchtutorial ; 61 + dw Script_trainertext ; 62 + dw Script_trainerflagaction ; 63 + dw Script_winlosstext ; 64 + dw Script_scripttalkafter ; 65 + dw Script_endifjustbattled ; 66 + dw Script_checkjustbattled ; 67 + dw Script_setlasttalked ; 68 + dw Script_applymovement ; 69 + dw Script_applymovement2 ; 6a + dw Script_faceplayer ; 6b + dw Script_faceobject ; 6c + dw Script_variablesprite ; 6d + dw Script_disappear ; 6e + dw Script_appear ; 6f + dw Script_follow ; 70 + dw Script_stopfollow ; 71 + dw Script_moveobject ; 72 + dw Script_writeobjectxy ; 73 + dw Script_loademote ; 74 + dw Script_showemote ; 75 + dw Script_turnobject ; 76 + dw Script_follownotexact ; 77 + dw Script_earthquake ; 78 + dw Script_changemap ; 79 + dw Script_changeblock ; 7a + dw Script_reloadmap ; 7b + dw Script_reloadmappart ; 7c + dw Script_writecmdqueue ; 7d + dw Script_delcmdqueue ; 7e + dw Script_playmusic ; 7f + dw Script_encountermusic ; 80 + dw Script_musicfadeout ; 81 + dw Script_playmapmusic ; 82 + dw Script_dontrestartmapmusic ; 83 + dw Script_cry ; 84 + dw Script_playsound ; 85 + dw Script_waitsfx ; 86 + dw Script_warpsound ; 87 + dw Script_specialsound ; 88 + dw Script_passtoengine ; 89 + dw Script_newloadmap ; 8a + dw Script_pause ; 8b + dw Script_deactivatefacing ; 8c + dw Script_priorityjump ; 8d + dw Script_warpcheck ; 8e + dw Script_ptpriorityjump ; 8f + dw Script_return ; 90 + dw Script_end ; 91 + dw Script_reloadandreturn ; 92 + dw Script_endall ; 93 + dw Script_pokemart ; 94 + dw Script_elevator ; 95 + dw Script_trade ; 96 + dw Script_askforphonenumber ; 97 + dw Script_phonecall ; 98 + dw Script_hangup ; 99 + dw Script_describedecoration ; 9a + dw Script_fruittree ; 9b + dw Script_specialphonecall ; 9c + dw Script_checkphonecall ; 9d + dw Script_verbosegiveitem ; 9e + dw Script_verbosegiveitem2 ; 9f + dw Script_swarm ; a0 + dw Script_halloffame ; a1 + dw Script_credits ; a2 + dw Script_warpfacing ; a3 + dw Script_battletowertext ; a4 + dw Script_landmarktotext ; a5 + dw Script_trainerclassname ; a6 + dw Script_name ; a7 + dw Script_wait ; a8 + dw Script_checksave ; a9 + +StartScript: + ld hl, wScriptFlags + set SCRIPT_RUNNING, [hl] + ret + +CheckScript: + ld hl, wScriptFlags + bit SCRIPT_RUNNING, [hl] + ret + +StopScript: + ld hl, wScriptFlags + res SCRIPT_RUNNING, [hl] + ret + +Script_callasm: +; script command 0xe +; parameters: asm + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, b + rst FarCall + ret + +Script_special: +; script command 0xf +; parameters: predefined_script + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + farcall Special + ret + +Script_ptcallasm: +; script command 0x10 +; parameters: asm + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + ld a, b + rst FarCall + ret + +Script_jumptextfaceplayer: +; script command 0x51 +; parameters: text_pointer + + ld a, [wScriptBank] + ld [wScriptTextBank], a + call GetScriptByte + ld [wScriptTextAddr], a + call GetScriptByte + ld [wScriptTextAddr + 1], a + ld b, BANK(JumpTextFacePlayerScript) + ld hl, JumpTextFacePlayerScript + jp ScriptJump + +Script_jumptext: +; script command 0x53 +; parameters: text_pointer + + ld a, [wScriptBank] + ld [wScriptTextBank], a + call GetScriptByte + ld [wScriptTextAddr], a + call GetScriptByte + ld [wScriptTextAddr + 1], a + ld b, BANK(JumpTextScript) + ld hl, JumpTextScript + jp ScriptJump + +JumpTextFacePlayerScript: + faceplayer +JumpTextScript: + opentext + repeattext -1, -1 + waitbutton + closetext + end + + +if _CRYSTAL + +Script_farjumptext: +; script command 0x52 +; parameters: text_pointer + + call GetScriptByte + ld [wScriptTextBank], a + call GetScriptByte + ld [wScriptTextAddr], a + call GetScriptByte + ld [wScriptTextAddr + 1], a + ld b, BANK(JumpTextScript) + ld hl, JumpTextScript + jp ScriptJump + +endc + + +Script_writetext: +; script command 0x4c +; parameters: text_pointer + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [wScriptBank] + ld b, a + call MapTextbox + ret + +Script_farwritetext: +; script command 0x4b +; parameters: text_pointer + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + call MapTextbox + ret + +Script_repeattext: +; script command 0x4d +; parameters: byte, byte + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + cp -1 + jr nz, .done + ld a, l + cp -1 + jr nz, .done + ld hl, wScriptTextBank + ld a, [hli] + ld b, a + ld a, [hli] + ld h, [hl] + ld l, a + call MapTextbox + ret + +.done + ret + +Script_waitbutton: +; script command 0x54 + + jp WaitButton + +Script_buttonsound: +; script command 0x55 + + ld a, [hOAMUpdate] + push af + ld a, $1 + ld [hOAMUpdate], a + call WaitBGMap + call ButtonSound + pop af + ld [hOAMUpdate], a + ret + +Script_yesorno: +; script command 0x4e + + call YesNoBox + ld a, FALSE + jr c, .no + ld a, TRUE +.no + ld [wScriptVar], a + ret + +Script_loadmenu: +; script command 0x4f +; parameters: menu_header + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld de, LoadMenuHeader + ld a, [wScriptBank] + call Call_a_de + call UpdateSprites + ret + +Script_closewindow: +; script command 0x50 + + call CloseWindow + call UpdateSprites + ret + +Script_pokepic: +; script command 0x56 +; parameters: pokemon + + call GetScriptByte + and a + jr nz, .ok + ld a, [wScriptVar] +.ok + ld [wCurPartySpecies], a + farcall Pokepic + ret + +Script_closepokepic: +; script command 0x57 + + farcall ClosePokepic + ret + +Script_verticalmenu: +; script command 0x59 + + ld a, [wScriptBank] + ld hl, VerticalMenu + rst FarCall + ld a, [wMenuCursorY] + jr nc, .ok + xor a +.ok + ld [wScriptVar], a + ret + +Script__2dmenu: +; script command 0x58 + + ld a, [wScriptBank] + ld hl, _2DMenu + rst FarCall + ld a, [wMenuCursorBuffer] + jr nc, .ok + xor a +.ok + ld [wScriptVar], a + ret + +Script_battletowertext: +; script command 0xa4 +; parameters: pointer, memory + + call SetUpTextBox + call GetScriptByte + ld c, a + farcall BattleTowerText + ret + +Script_verbosegiveitem: +; script command 0x9e +; parameters: item, quantity + + call Script_giveitem + call CurItemName + ld de, wStringBuffer1 + ld a, 1 + call CopyConvertedText + ld b, BANK(GiveItemScript) + ld de, GiveItemScript + jp ScriptCall + + +ret_96f76: + ret + +GiveItemScript: + callasm ret_96f76 + writetext ReceivedItemText + iffalse .Full + waitsfx + specialsound + waitbutton + itemnotify + end + +.Full: + buttonsound + pocketisfull + end + +ReceivedItemText: + text_jump UnknownText_0x1c4719 + db "@" + + +Script_verbosegiveitem2: +; script command 0x9f +; parameters: item, var + + call GetScriptByte + cp -1 + jr nz, .ok + ld a, [wScriptVar] +.ok + ld [wCurItem], a + call GetScriptByte + call GetVarAction + ld a, [de] + ld [wItemQuantityChangeBuffer], a + ld hl, wNumItems + call ReceiveItem + ld a, TRUE + jr c, .ok2 + xor a +.ok2 + ld [wScriptVar], a + call CurItemName + ld de, wStringBuffer1 + ld a, 1 + call CopyConvertedText + ld b, BANK(GiveItemScript) + ld de, GiveItemScript + jp ScriptCall + +Script_itemnotify: +; script command 0x45 + + call GetPocketName + call CurItemName + ld b, BANK(PutItemInPocketText) + ld hl, PutItemInPocketText + call MapTextbox + ret + +Script_pocketisfull: +; script command 0x46 + + call GetPocketName + call CurItemName + ld b, BANK(PocketIsFullText) + ld hl, PocketIsFullText + call MapTextbox + ret + +Script_specialsound: +; script command 0x88 + + farcall CheckItemPocket + ld a, [wItemAttributeParamBuffer] + cp TM_HM + ld de, SFX_GET_TM + jr z, .play + ld de, SFX_ITEM +.play + call PlaySFX + call WaitSFX + ret + + +GetPocketName: + farcall CheckItemPocket + ld a, [wItemAttributeParamBuffer] + dec a + ld hl, .Pockets + maskbits NUM_POCKETS + add a + ld e, a + ld d, 0 + add hl, de + ld a, [hli] + ld d, [hl] + ld e, a + ld hl, wStringBuffer3 + call CopyName2 + ret + +.Pockets: + dw .Item + dw .Key + dw .Ball + dw .TM + +.Item: + db "ITEM POCKET@" +.Key: + db "KEY POCKET@" +.Ball: + db "BALL POCKET@" +.TM: + db "TM POCKET@" + +CurItemName: + ld a, [wCurItem] + ld [wd265], a + call GetItemName + ret + + +PutItemInPocketText: + text_jump UnknownText_0x1c472c + db "@" + +PocketIsFullText: + text_jump UnknownText_0x1c474b + db "@" + + +Script_pokemart: +; script command 0x94 +; parameters: dialog_id, mart_id + + call GetScriptByte + ld c, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld b, a + farcall OpenMartDialog + ret + +Script_elevator: +; script command 0x95 +; parameters: floor_list_pointer + + xor a + ld [wScriptVar], a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld b, a + farcall Elevator + ret c + ld a, TRUE + ld [wScriptVar], a + ret + +Script_trade: +; script command 0x96 +; parameters: trade_id + + call GetScriptByte + ld e, a + farcall NPCTrade + ret + +Script_phonecall: +; script command 0x98 +; parameters: caller_name + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld b, a + farcall PhoneCall + ret + +Script_hangup: +; script command 0x99 + + farcall HangUp + ret + +Script_askforphonenumber: +; script command 0x97 +; parameters: number + + call YesNoBox + jr c, .refused + call GetScriptByte + ld c, a + farcall AddPhoneNumber + jr c, .phonefull + xor a ; PHONE_CONTACT_GOT + jr .done +.phonefull + ld a, PHONE_CONTACTS_FULL + jr .done +.refused + call GetScriptByte + ld a, PHONE_CONTACT_REFUSED +.done + ld [wScriptVar], a + ret + +Script_describedecoration: +; script command 0x9a +; parameters: byte + + call GetScriptByte + ld b, a + farcall DescribeDecoration + ld h, d + ld l, e + jp ScriptJump + +Script_fruittree: +; script command 0x9b +; parameters: tree_id + + call GetScriptByte + ld [wCurFruitTree], a + ld b, BANK(FruitTreeScript) + ld hl, FruitTreeScript + jp ScriptJump + +Script_swarm: +; script command 0xa0 +; parameters: flag, map_group, map_id + + call GetScriptByte + ld c, a + call GetScriptByte + ld d, a + call GetScriptByte + ld e, a + farcall StoreSwarmMapIndices + ret + +Script_trainertext: +; script command 0x62 +; parameters: which_text + + call GetScriptByte + ld c, a + ld b, 0 + ld hl, wWalkingX + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wEngineBuffer1] + ld b, a + call MapTextbox + ret + +Script_scripttalkafter: +; script command 0x65 + + ld hl, wScriptAfterPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wEngineBuffer1] + ld b, a + jp ScriptJump + +Script_trainerflagaction: +; script command 0x63 +; parameters: action + + xor a + ld [wScriptVar], a + ld hl, wd041 + ld e, [hl] + inc hl + ld d, [hl] + call GetScriptByte + ld b, a + call EventFlagAction + ld a, c + and a + ret z + ld a, TRUE + ld [wScriptVar], a + ret + +Script_winlosstext: +; script command 0x64 +; parameters: win_text_pointer, loss_text_pointer + + ld hl, wWinTextPointer + call GetScriptByte + ld [hli], a + call GetScriptByte + ld [hli], a + ld hl, wLossTextPointer + call GetScriptByte + ld [hli], a + call GetScriptByte + ld [hli], a + ret + +Script_endifjustbattled: +; script command 0x66 + + ld a, [wRunningTrainerBattleScript] + and a + ret z + jp Script_end + +Script_checkjustbattled: +; script command 0x67 + + ld a, TRUE + ld [wScriptVar], a + ld a, [wRunningTrainerBattleScript] + and a + ret nz + xor a + ld [wScriptVar], a + ret + +Script_encountermusic: +; script command 0x80 + + ld a, [wOtherTrainerClass] + ld e, a + farcall PlayTrainerEncounterMusic + ret + +Script_playmapmusic: +; script command 0x82 + + call PlayMapMusic + ret + +Script_playmusic: +; script command 0x7f +; parameters: music_pointer + + ld de, MUSIC_NONE + call PlayMusic + xor a + ld [wMusicFade], a + call MaxVolume + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + call PlayMusic + ret + +Script_musicfadeout: +; script command 0x81 +; parameters: music, fadetime + + call GetScriptByte + ld [wMusicFadeID], a + call GetScriptByte + ld [wMusicFadeID + 1], a + call GetScriptByte + and $ff ^ (1 << MUSIC_FADE_IN_F) + ld [wMusicFade], a + ret + +Script_playsound: +; script command 0x85 +; parameters: sound_pointer + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + call PlaySFX + ret + +Script_waitsfx: +; script command 0x86 + + call WaitSFX + ret + +Script_warpsound: +; script command 0x87 + + farcall GetWarpSFX + call PlaySFX + ret + +Script_cry: +; script command 0x84 +; parameters: cry_id + + call GetScriptByte + push af + call GetScriptByte + pop af + and a + jr nz, .ok + ld a, [wScriptVar] +.ok + call PlayMonCry + ret + +GetScriptObject: + and a ; PLAYER? + ret z + cp LAST_TALKED + ret z + dec a + ret + +Script_setlasttalked: +; script command 0x68 +; parameters: object_id + + call GetScriptByte + call GetScriptObject + ld [hLastTalked], a + ret + +Script_applymovement: +; script command 0x69 +; parameters: object_id, data + + call GetScriptByte + call GetScriptObject + ld c, a + +ApplyMovement: + push bc + ld a, c + farcall SetFlagsForMovement_1 + pop bc + + push bc + call SetFlagsForMovement_2 + pop bc + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [wScriptBank] + ld b, a + call GetMovementData + ret c + + ld a, SCRIPT_WAIT_MOVEMENT + ld [wScriptMode], a + call StopScript + ret + +SetFlagsForMovement_2: + farcall _SetFlagsForMovement_2 + ret + +Script_applymovement2: +; script command 0x6a +; parameters: data +; apply movement to last talked + + ld a, [hLastTalked] + ld c, a + jp ApplyMovement + +Script_faceplayer: +; script command 0x6b + + ld a, [hLastTalked] + and a + ret z + ld d, $0 + ld a, [hLastTalked] + ld e, a + farcall GetRelativeFacing + ld a, d + add a + add a + ld e, a + ld a, [hLastTalked] + ld d, a + call ApplyObjectFacing + ret + +Script_faceobject: +; script command 0x6c +; parameters: object1, object2 + + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr c, .ok + ld a, [hLastTalked] +.ok + ld e, a + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr nz, .ok2 + ld a, [hLastTalked] +.ok2 + ld d, a + push de + farcall GetRelativeFacing + pop bc + ret c + ld a, d + add a + add a + ld e, a + ld d, c + call ApplyObjectFacing + ret + +Script_turnobject: +; script command 0x76 +; parameters: object_id, facing + + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr nz, .ok + ld a, [hLastTalked] +.ok + ld d, a + call GetScriptByte + add a + add a + ld e, a + call ApplyObjectFacing + ret + +ApplyObjectFacing: + ld a, d + push de + call CheckObjectVisibility + jr c, .not_visible + ld hl, OBJECT_SPRITE + add hl, bc + ld a, [hl] + push bc + call DoesSpriteHaveFacings + pop bc + jr c, .not_visible ; STILL_SPRITE + ld hl, OBJECT_FLAGS1 + add hl, bc + bit FIXED_FACING, [hl] + jr nz, .not_visible + pop de + ld a, e + call SetSpriteDirection + ld hl, wVramState + bit 6, [hl] + jr nz, .text_state + call .DisableTextTiles +.text_state + call UpdateSprites + ret + +.not_visible + pop de + scf + ret + +.DisableTextTiles: + call LoadMapPart + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT +.loop + res 7, [hl] + inc hl + dec bc + ld a, b + or c + jr nz, .loop + ret + +Script_variablesprite: +; script command 0x6d +; parameters: byte, sprite + + call GetScriptByte + ld e, a + ld d, $0 + ld hl, wVariableSprites + add hl, de + call GetScriptByte + ld [hl], a + ret + +Script_appear: +; script command 0x6f +; parameters: object_id + + call GetScriptByte + call GetScriptObject + call _CopyObjectStruct + ld a, [hMapObjectIndexBuffer] + ld b, 0 ; clear + call ApplyEventActionAppearDisappear + ret + +Script_disappear: +; script command 0x6e +; parameters: object_id + + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr nz, .ok + ld a, [hLastTalked] +.ok + call DeleteObjectStruct + ld a, [hMapObjectIndexBuffer] + ld b, 1 ; set + call ApplyEventActionAppearDisappear + farcall _UpdateSprites + ret + +ApplyEventActionAppearDisappear: + push bc + call GetMapObject + ld hl, MAPOBJECT_EVENT_FLAG + add hl, bc + pop bc + ld e, [hl] + inc hl + ld d, [hl] + ld a, -1 + cp e + jr nz, .okay + cp d + jr nz, .okay + xor a + ret +.okay + call EventFlagAction + ret + +Script_follow: +; script command 0x70 +; parameters: object2, object1 + + call GetScriptByte + call GetScriptObject + ld b, a + call GetScriptByte + call GetScriptObject + ld c, a + farcall StartFollow + ret + +Script_stopfollow: +; script command 0x71 + + farcall StopFollow + ret + +Script_moveobject: +; script command 0x72 +; parameters: object id, x, y + + call GetScriptByte + call GetScriptObject + ld b, a + call GetScriptByte + add 4 + ld d, a + call GetScriptByte + add 4 + ld e, a + farcall CopyDECoordsToMapObject + ret + +Script_writeobjectxy: +; script command 0x73 +; parameters: object_id + + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr nz, .ok + ld a, [hLastTalked] +.ok + ld b, a + farcall WriteObjectXY + ret + +Script_follownotexact: +; script command 0x77 +; parameters: object2, object1 + + call GetScriptByte + call GetScriptObject + ld b, a + call GetScriptByte + call GetScriptObject + ld c, a + farcall FollowNotExact + ret + +Script_loademote: +; script command 0x74 +; parameters: bubble + + call GetScriptByte + cp -1 + jr nz, .not_var_emote + ld a, [wScriptVar] +.not_var_emote + ld c, a + farcall LoadEmote + ret + +Script_showemote: +; script command 0x75 +; parameters: bubble, object_id, time + + call GetScriptByte + ld [wScriptVar], a + call GetScriptByte + call GetScriptObject + cp LAST_TALKED + jr z, .ok + ld [hLastTalked], a +.ok + call GetScriptByte + ld [wScriptDelay], a + ld b, BANK(ShowEmoteScript) + ld de, ShowEmoteScript + jp ScriptCall + +ShowEmoteScript: + loademote EMOTE_MEM + applymovement2 .Show + pause 0 + applymovement2 .Hide + end + +.Show: + show_emote + step_sleep 1 + step_end + +.Hide: + hide_emote + step_sleep 1 + step_end + + +Script_earthquake: +; script command 0x78 +; parameters: param + + ld hl, EarthquakeMovement + ld de, wEarthquakeMovementDataBuffer + ld bc, EarthquakeMovement.End - EarthquakeMovement + call CopyBytes + call GetScriptByte + ld [wEarthquakeMovementDataBuffer + 1], a + and %00111111 + ld [wEarthquakeMovementDataBuffer + 3], a + ld b, BANK(.script) + ld de, .script + jp ScriptCall + +.script + applymovement PLAYER, wEarthquakeMovementDataBuffer + end + +EarthquakeMovement: + step_shake 16 ; the 16 gets overwritten with the script byte + step_sleep 16 ; the 16 gets overwritten with the lower 6 bits of the script byte + step_end +.End + + +Script_loadpikachudata: +; script command 0x5a + + ld a, PIKACHU + ld [wTempWildMonSpecies], a + ld a, 5 + ld [wCurPartyLevel], a + ret + +Script_randomwildmon: +; script command 0x5b + + xor a + ld [wBattleScriptFlags], a + ret + +Script_loadmemtrainer: +; script command 0x5c + + ld a, (1 << 7) | 1 + ld [wBattleScriptFlags], a + ld a, [wTempTrainerClass] + ld [wOtherTrainerClass], a + ld a, [wTempTrainerID] + ld [wOtherTrainerID], a + ret + +Script_loadwildmon: +; script command 0x5d +; parameters: pokemon, level + + ld a, (1 << 7) + ld [wBattleScriptFlags], a + call GetScriptByte + ld [wTempWildMonSpecies], a + call GetScriptByte + ld [wCurPartyLevel], a + ret + +Script_loadtrainer: +; script command 0x5e +; parameters: trainer_group, trainer_id + + ld a, (1 << 7) | 1 + ld [wBattleScriptFlags], a + call GetScriptByte + ld [wOtherTrainerClass], a + call GetScriptByte + ld [wOtherTrainerID], a + ret + +Script_startbattle: +; script command 0x5f + + call BufferScreen + predef StartBattle + ld a, [wBattleResult] + and $3f + ld [wScriptVar], a + ret + +Script_catchtutorial: +; script command 0x61 +; parameters: byte + + call GetScriptByte + ld [wBattleType], a + call BufferScreen + farcall CatchTutorial + jp Script_reloadmap + +Script_reloadmapafterbattle: +; script command 0x60 + + ld hl, wBattleScriptFlags + ld d, [hl] + ld [hl], $0 + ld a, [wBattleResult] + and $3f + cp $1 + jr nz, .notblackedout + ld b, BANK(Script_BattleWhiteout) + ld hl, Script_BattleWhiteout + jp ScriptJump + +.notblackedout + bit 0, d + jr z, .was_wild + farcall MomTriesToBuySomething + jr .done + +.was_wild + ld a, [wBattleResult] + bit 7, a + jr z, .done + ld b, BANK(Script_SpecialBillCall) + ld de, Script_SpecialBillCall + farcall LoadScriptBDE +.done + jp Script_reloadmap + +Script_reloadmap: +; script command 0x7b + + xor a + ld [wBattleScriptFlags], a + ld a, MAPSETUP_RELOADMAP + ld [hMapEntryMethod], a + ld a, $1 + call LoadMapStatus + call StopScript + ret + +Script_scall: +; script command 0x0 +; parameters: pointer + + ld a, [wScriptBank] + ld b, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + jr ScriptCall + +Script_farscall: +; script command 0x1 +; parameters: pointer + + call GetScriptByte + ld b, a + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + jr ScriptCall + +Script_ptcall: +; script command 0x2 +; parameters: pointer + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld e, [hl] + inc hl + ld d, [hl] + ; fallthrough + +ScriptCall: +; Bug: The script stack has a capacity of 5 scripts, yet there is +; nothing to stop you from pushing a sixth script. The high part +; of the script address can then be overwritten by modifications +; to wScriptDelay, causing the script to return to the rst/interrupt +; space. + + push de + ld hl, wScriptStackSize + ld e, [hl] + inc [hl] + ld d, $0 + ld hl, wScriptStack + add hl, de + add hl, de + add hl, de + pop de + ld a, [wScriptBank] + ld [hli], a + ld a, [wScriptPos] + ld [hli], a + ld a, [wScriptPos + 1] + ld [hl], a + ld a, b + ld [wScriptBank], a + ld a, e + ld [wScriptPos], a + ld a, d + ld [wScriptPos + 1], a + ret + +CallCallback:: + ld a, [wScriptBank] + or $80 + ld [wScriptBank], a + jp ScriptCall + +Script_jump: +; script command 0x3 +; parameters: pointer + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [wScriptBank] + ld b, a + jp ScriptJump + +Script_farjump: +; script command 0x4 +; parameters: pointer + + call GetScriptByte + ld b, a + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + jp ScriptJump + +Script_ptjump: +; script command 0x5 +; parameters: pointer + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld b, [hl] + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp ScriptJump + +Script_iffalse: +; script command 0x8 +; parameters: pointer + + ld a, [wScriptVar] + and a + jp nz, SkipTwoScriptBytes + jp Script_jump + +Script_iftrue: +; script command 0x9 +; parameters: pointer + + ld a, [wScriptVar] + and a + jp nz, Script_jump + jp SkipTwoScriptBytes + +Script_ifequal: +; script command 0x6 +; parameters: byte, pointer + + call GetScriptByte + ld hl, wScriptVar + cp [hl] + jr z, Script_jump + jr SkipTwoScriptBytes + +Script_ifnotequal: +; script command 0x7 +; parameters: byte, pointer + + call GetScriptByte + ld hl, wScriptVar + cp [hl] + jr nz, Script_jump + jr SkipTwoScriptBytes + +Script_ifgreater: +; script command 0xa +; parameters: byte, pointer + + ld a, [wScriptVar] + ld b, a + call GetScriptByte + cp b + jr c, Script_jump + jr SkipTwoScriptBytes + +Script_ifless: +; script command 0xb +; parameters: byte, pointer + + call GetScriptByte + ld b, a + ld a, [wScriptVar] + cp b + jr c, Script_jump + jr SkipTwoScriptBytes + +Script_jumpstd: +; script command 0xc +; parameters: predefined_script + + call StdScript + jr ScriptJump + +Script_callstd: +; script command 0xd +; parameters: predefined_script + + call StdScript + ld d, h + ld e, l + jp ScriptCall + +StdScript: + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld hl, StdScripts + add hl, de + add hl, de + add hl, de + ld a, BANK(StdScripts) + call GetFarByte + ld b, a + inc hl + ld a, BANK(StdScripts) + call GetFarHalfword + ret + +SkipTwoScriptBytes: + call GetScriptByte + call GetScriptByte + ret + +ScriptJump: + ld a, b + ld [wScriptBank], a + ld a, l + ld [wScriptPos], a + ld a, h + ld [wScriptPos + 1], a + ret + +Script_priorityjump: +; script command 0x8d +; parameters: pointer + + ld a, [wScriptBank] + ld [wPriorityScriptBank], a + call GetScriptByte + ld [wPriorityScriptAddr], a + call GetScriptByte + ld [wPriorityScriptAddr + 1], a + ld hl, wScriptFlags + set 3, [hl] + ret + +Script_checkscene: +; script command 0x13 + + call CheckScenes + jr z, .no_scene + ld [wScriptVar], a + ret + +.no_scene + ld a, $ff + ld [wScriptVar], a + ret + +Script_checkmapscene: +; script command 0x11 +; parameters: map_group, map_id + + call GetScriptByte + ld b, a + call GetScriptByte + ld c, a + call GetMapSceneID + ld a, d + or e + jr z, .no_scene + ld a, [de] + ld [wScriptVar], a + ret + +.no_scene + ld a, $ff + ld [wScriptVar], a + ret + +Script_setscene: +; script command 0x14 +; parameters: scene_id + + ld a, [wMapGroup] + ld b, a + ld a, [wMapNumber] + ld c, a + jr DoScene + +Script_setmapscene: +; script command 0x12 +; parameters: map_group, map_id, scene_id + + call GetScriptByte + ld b, a + call GetScriptByte + ld c, a +DoScene: + call GetMapSceneID + ld a, d + or e + jr z, .no_scene + call GetScriptByte + ld [de], a +.no_scene + ret + +Script_copybytetovar: +; script command 0x19 +; parameters: address + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [hl] + ld [wScriptVar], a + ret + +Script_copyvartobyte: +; script command 0x1a +; parameters: address + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [wScriptVar] + ld [hl], a + ret + +Script_loadvar: +; script command 0x1b +; parameters: address, value + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + call GetScriptByte + ld [hl], a + ret + +Script_writebyte: +; script command 0x15 +; parameters: value + + call GetScriptByte + ld [wScriptVar], a + ret + +Script_addvar: +; script command 0x16 +; parameters: value + + call GetScriptByte + ld hl, wScriptVar + add [hl] + ld [hl], a + ret + +Script_random: +; script command 0x17 +; parameters: input + + call GetScriptByte + ld [wScriptVar], a + and a + ret z + + ld c, a + call .Divide256byC + and a + jr z, .no_restriction ; 256 % b == 0 + ld b, a + xor a + sub b + ld b, a +.loop + push bc + call Random + pop bc + ld a, [hRandomAdd] + cp b + jr nc, .loop + jr .finish + +.no_restriction + push bc + call Random + pop bc + ld a, [hRandomAdd] + +.finish + push af + ld a, [wScriptVar] + ld c, a + pop af + call SimpleDivide + ld [wScriptVar], a + ret + +.Divide256byC: + xor a + ld b, a + sub c +.mod_loop + inc b + sub c + jr nc, .mod_loop + dec b + add c + ret + +Script_checkcode: +; script command 0x1c +; parameters: variable_id + + call GetScriptByte + call GetVarAction + ld a, [de] + ld [wScriptVar], a + ret + +Script_writevarcode: +; script command 0x1d +; parameters: variable_id + + call GetScriptByte + call GetVarAction + ld a, [wScriptVar] + ld [de], a + ret + +Script_writecode: +; script command 0x1e +; parameters: variable_id, value + + call GetScriptByte + call GetVarAction + call GetScriptByte + ld [de], a + ret + +GetVarAction: + ld c, a + farcall _GetVarAction + ret + +Script_checkver: +; script command 0x18 + + ld a, [.gs_version] + ld [wScriptVar], a + ret + +.gs_version: + db GS_VERSION + +Script_pokenamemem: +; script command 0x40 +; parameters: pokemon (0 aka USE_SCRIPT_VAR to use wScriptVar), memory + + call GetScriptByte + and a + jr nz, .gotit + ld a, [wScriptVar] +.gotit + ld [wd265], a + call GetPokemonName + ld de, wStringBuffer1 + +ConvertMemToText: + call GetScriptByte + cp NUM_MEM_BUFFERS + jr c, .ok + xor a +.ok + +CopyConvertedText: + ld hl, wStringBuffer3 + ld bc, wStringBuffer4 - wStringBuffer3 + call AddNTimes + call CopyName2 + ret + +Script_itemtotext: +; script command 0x41 +; parameters: item (0 aka USE_SCRIPT_VAR to use wScriptVar), memory + + call GetScriptByte + and a ; USE_SCRIPT_VAR + jr nz, .ok + ld a, [wScriptVar] +.ok + ld [wd265], a + call GetItemName + ld de, wStringBuffer1 + jr ConvertMemToText + +Script_mapnametotext: +; script command 0x42 +; parameters: memory + + ld a, [wMapGroup] + ld b, a + ld a, [wMapNumber] + ld c, a + call GetWorldMapLocation + +ConvertLandmarkToText: + ld e, a + farcall GetLandmarkName + ld de, wStringBuffer1 + jp ConvertMemToText + +Script_landmarktotext: +; script command 0xa5 +; parameters: id, memory + + call GetScriptByte + jr ConvertLandmarkToText + +Script_trainertotext: +; script command 0x43 +; parameters: trainer_id, trainer_group, memory + + call GetScriptByte + ld c, a + call GetScriptByte + ld b, a + farcall GetTrainerName + jr ConvertMemToText + +Script_name: +; script command 0xa7 +; parameters: type, id, memory + + call GetScriptByte + ld [wNamedObjectTypeBuffer], a + +ContinueToGetName: + call GetScriptByte + ld [wCurSpecies], a + call GetName + ld de, wStringBuffer1 + jp ConvertMemToText + +Script_trainerclassname: +; script command 0xa6 +; parameters: id, memory + + ld a, TRAINER_NAME + ld [wNamedObjectTypeBuffer], a + jr ContinueToGetName + +Script_readmoney: +; script command 0x3d +; parameters: account, memory + + call ResetStringBuffer1 + call GetMoneyAccount + ld hl, wStringBuffer1 + lb bc, PRINTNUM_RIGHTALIGN | 3, 6 + call PrintNum + ld de, wStringBuffer1 + jp ConvertMemToText + +Script_readcoins: +; script command 0x3e +; parameters: memory + + call ResetStringBuffer1 + ld hl, wStringBuffer1 + ld de, wCoins + lb bc, PRINTNUM_RIGHTALIGN | 2, 6 + call PrintNum + ld de, wStringBuffer1 + jp ConvertMemToText + +Script_vartomem: +; script command 0x3f +; parameters: memory + + call ResetStringBuffer1 + ld de, wScriptVar + ld hl, wStringBuffer1 + lb bc, PRINTNUM_RIGHTALIGN | 1, 3 + call PrintNum + ld de, wStringBuffer1 + jp ConvertMemToText + +ResetStringBuffer1: + ld hl, wStringBuffer1 + ld bc, NAME_LENGTH + ld a, "@" + call ByteFill + ret + +Script_stringtotext: +; script command 0x44 +; parameters: text_pointer, memory + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld hl, CopyName1 + rst FarCall + ld de, wStringBuffer2 + jp ConvertMemToText + +Script_givepokeitem: +; script command 0x2f +; parameters: pointer + + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + ld a, [wScriptBank] + call GetFarByte + ld b, a + push bc + inc hl + ld bc, MAIL_MSG_LENGTH + ld de, wd002 + ld a, [wScriptBank] + call FarCopyBytes + pop bc + farcall GivePokeItem + ret + +Script_checkpokeitem: +; script command 0x30 +; parameters: pointer + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld b, a + farcall CheckPokeItem + ret + +Script_giveitem: +; script command 0x1f +; parameters: item, quantity + + call GetScriptByte + cp ITEM_FROM_MEM + jr nz, .ok + ld a, [wScriptVar] +.ok + ld [wCurItem], a + call GetScriptByte + ld [wItemQuantityChangeBuffer], a + ld hl, wNumItems + call ReceiveItem + jr nc, .full + ld a, TRUE + ld [wScriptVar], a + ret +.full + xor a + ld [wScriptVar], a + ret + +Script_takeitem: +; script command 0x20 +; parameters: item, quantity + + xor a + ld [wScriptVar], a + call GetScriptByte + ld [wCurItem], a + call GetScriptByte + ld [wItemQuantityChangeBuffer], a + ld a, -1 + ld [wCurItemQuantity], a + ld hl, wNumItems + call TossItem + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_checkitem: +; script command 0x21 +; parameters: item + + xor a + ld [wScriptVar], a + call GetScriptByte + ld [wCurItem], a + ld hl, wNumItems + call CheckItem + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_givemoney: +; script command 0x22 +; parameters: account, money + + call GetMoneyAccount + call LoadMoneyAmountToMem + farcall GiveMoney + ret + +Script_takemoney: +; script command 0x23 +; parameters: account, money + + call GetMoneyAccount + call LoadMoneyAmountToMem + farcall TakeMoney + ret + +Script_checkmoney: +; script command 0x24 +; parameters: account, money + + call GetMoneyAccount + call LoadMoneyAmountToMem + farcall CompareMoney + +CompareMoneyAction: + jr c, .less + jr z, .exact + ld a, HAVE_MORE + jr .done +.exact + ld a, HAVE_AMOUNT + jr .done +.less + ld a, HAVE_LESS +.done + ld [wScriptVar], a + ret + +GetMoneyAccount: + call GetScriptByte + and a + ld de, wMoney ; YOUR_MONEY + ret z + ld de, wMomsMoney ; MOMS_MONEY + ret + +LoadMoneyAmountToMem: + ld bc, hMoneyTemp + push bc + call GetScriptByte + ld [bc], a + inc bc + call GetScriptByte + ld [bc], a + inc bc + call GetScriptByte + ld [bc], a + pop bc + ret + +Script_givecoins: +; script command 0x25 +; parameters: coins + + call LoadCoinAmountToMem + farcall GiveCoins + ret + +Script_takecoins: +; script command 0x26 +; parameters: coins + + call LoadCoinAmountToMem + farcall TakeCoins + ret + +Script_checkcoins: +; script command 0x27 +; parameters: coins + + call LoadCoinAmountToMem + farcall CheckCoins + jr CompareMoneyAction + +LoadCoinAmountToMem: + call GetScriptByte + ld [hMoneyTemp + 1], a + call GetScriptByte + ld [hMoneyTemp], a + ld bc, hMoneyTemp + ret + +Script_checktime: +; script command 0x2b +; parameters: time + + xor a + ld [wScriptVar], a + farcall CheckTime + call GetScriptByte + and c + ret z + ld a, TRUE + ld [wScriptVar], a + ret + +Script_checkpoke: +; script command 0x2c +; parameters: pokemon + + xor a + ld [wScriptVar], a + call GetScriptByte + ld hl, wPartySpecies + ld de, 1 + call IsInArray + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_addcellnum: +; script command 0x28 +; parameters: person + + xor a + ld [wScriptVar], a + call GetScriptByte + ld c, a + farcall AddPhoneNumber + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_delcellnum: +; script command 0x29 +; parameters: person + + xor a + ld [wScriptVar], a + call GetScriptByte + ld c, a + farcall DelCellNum + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_checkcellnum: +; script command 0x2a +; parameters: person +; returns false if the cell number is not in your phone + + xor a + ld [wScriptVar], a + call GetScriptByte + ld c, a + farcall CheckCellNum + ret nc + ld a, TRUE + ld [wScriptVar], a + ret + +Script_specialphonecall: +; script command 0x9c +; parameters: call_id + + call GetScriptByte + ld [wSpecialPhoneCallID], a + call GetScriptByte + ld [wSpecialPhoneCallID + 1], a + ret + +Script_checkphonecall: +; script command 0x9d +; returns false if no special phone call is stored + + ld a, [wSpecialPhoneCallID] + and a + jr z, .ok + ld a, TRUE +.ok + ld [wScriptVar], a + ret + +Script_givepoke: +; script command 0x2d +; parameters: pokemon, level, item, trainer, trainer_name_pointer, pkmn_nickname + + call GetScriptByte + ld [wCurPartySpecies], a + call GetScriptByte + ld [wCurPartyLevel], a + call GetScriptByte + ld [wCurItem], a + call GetScriptByte + and a + ld b, a + jr z, .ok + ld hl, wScriptPos + ld e, [hl] + inc hl + ld d, [hl] + call GetScriptByte + call GetScriptByte + call GetScriptByte + call GetScriptByte +.ok + farcall GivePoke + ld a, b + ld [wScriptVar], a + ret + +Script_giveegg: +; script command 0x2e +; parameters: pokemon, level +; if no room in the party, return 0 in wScriptVar; else, return 2 + + xor a ; PARTYMON + ld [wScriptVar], a + ld [wMonType], a + call GetScriptByte + ld [wCurPartySpecies], a + call GetScriptByte + ld [wCurPartyLevel], a + farcall GiveEgg + ret nc + ld a, 2 + ld [wScriptVar], a + ret + +Script_setevent: +; script command 0x33 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, SET_FLAG + call EventFlagAction + ret + +Script_clearevent: +; script command 0x32 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, RESET_FLAG + call EventFlagAction + ret + +Script_checkevent: +; script command 0x31 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, CHECK_FLAG + call EventFlagAction + ld a, c + and a + jr z, .false + ld a, TRUE +.false + ld [wScriptVar], a + ret + +Script_setflag: +; script command 0x36 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, SET_FLAG + call _EngineFlagAction + ret + +Script_clearflag: +; script command 0x35 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, RESET_FLAG + call _EngineFlagAction + ret + +Script_checkflag: +; script command 0x34 +; parameters: bit_number + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld b, CHECK_FLAG + call _EngineFlagAction + ld a, c + and a + jr z, .false + ld a, TRUE +.false + ld [wScriptVar], a + ret + +_EngineFlagAction: + farcall EngineFlagAction + ret + +Script_wildoff: +; script command 0x38 + + ld hl, wStatusFlags + set STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl] + ret + +Script_wildon: +; script command 0x37 + + ld hl, wStatusFlags + res STATUSFLAGS_NO_WILD_ENCOUNTERS_F, [hl] + ret + +Script_xycompare: +; script command 0x39 +; parameters: pointer + + call GetScriptByte + ld [wXYComparePointer], a + call GetScriptByte + ld [wXYComparePointer + 1], a + ret + +Script_warpfacing: +; script command 0xa3 +; parameters: facing, map_group, map_id, x, y + + call GetScriptByte + maskbits NUM_DIRECTIONS + ld c, a + ld a, [wPlayerSpriteSetupFlags] + set PLAYERSPRITESETUP_CUSTOM_FACING_F, a + or c + ld [wPlayerSpriteSetupFlags], a +; fall through + +Script_warp: +; script command 0x3c +; parameters: map_group, map_id, x, y + +; This seems to be some sort of error handling case. + call GetScriptByte + and a + jr z, .not_ok + ld [wMapGroup], a + call GetScriptByte + ld [wMapNumber], a + call GetScriptByte + ld [wXCoord], a + call GetScriptByte + ld [wYCoord], a + ld a, -1 + ld [wDefaultSpawnpoint], a + ld a, MAPSETUP_WARP + ld [hMapEntryMethod], a + ld a, 1 + call LoadMapStatus + call StopScript + ret + +.not_ok + call GetScriptByte + call GetScriptByte + call GetScriptByte + ld a, -1 + ld [wDefaultSpawnpoint], a + ld a, MAPSETUP_BADWARP + ld [hMapEntryMethod], a + ld a, 1 + call LoadMapStatus + call StopScript + ret + +Script_warpmod: +; script command 0x3a +; parameters: warp_id, map_group, map_id + + call GetScriptByte + ld [wBackupWarpNumber], a + call GetScriptByte + ld [wBackupMapGroup], a + call GetScriptByte + ld [wBackupMapNumber], a + ret + +Script_blackoutmod: +; script command 0x3b +; parameters: map_group, map_id + + call GetScriptByte + ld [wLastSpawnMapGroup], a + call GetScriptByte + ld [wLastSpawnMapNumber], a + ret + +Script_dontrestartmapmusic: +; script command 0x83 + + ld a, 1 + ld [wDontPlayMapMusicOnReload], a + ret + +Script_writecmdqueue: +; script command 0x7d +; parameters: queue_pointer + + call GetScriptByte + ld e, a + call GetScriptByte + ld d, a + ld a, [wScriptBank] + ld b, a + farcall WriteCmdQueue ; no need to farcall + ret + +Script_delcmdqueue: +; script command 0x7e +; parameters: byte + + xor a + ld [wScriptVar], a + call GetScriptByte + ld b, a + farcall DelCmdQueue ; no need to farcall + ret c + ld a, 1 + ld [wScriptVar], a + ret + +Script_changemap: +; script command 0x79 +; parameters: map_data_pointer + + call GetScriptByte + ld [wMapBlocksBank], a + call GetScriptByte + ld [wMapBlocksPointer], a + call GetScriptByte + ld [wMapBlocksPointer + 1], a + call ChangeMap + call BufferScreen + ret + +Script_changeblock: +; script command 0x7a +; parameters: x, y, block + + call GetScriptByte + add 4 + ld d, a + call GetScriptByte + add 4 + ld e, a + call GetBlockLocation + call GetScriptByte + ld [hl], a + call BufferScreen + ret + +Script_reloadmappart:: +; script command 0x7c + + xor a + ld [hBGMapMode], a + call OverworldTextModeSwitch + call GetMovementPermissions + farcall ReloadMapPart + call UpdateSprites + ret + +Script_warpcheck: +; script command 0x8e + + call WarpCheck + ret nc + farcall EnableEvents + ret + +Script_enableevents: +; unused + farcall EnableEvents + ret + +Script_newloadmap: +; script command 0x8a +; parameters: which_method + + call GetScriptByte + ld [hMapEntryMethod], a + ld a, 1 + call LoadMapStatus + call StopScript + ret + +Script_reloadandreturn: +; script command 0x92 + + call Script_newloadmap + jp Script_end + +Script_opentext: +; script command 0x47 + + call OpenText + ret + +Script_refreshscreen: +; script command 0x48 +; parameters: dummy + + call RefreshScreen + call GetScriptByte + ret + +Script_loadbytec2cf: +; script command 0x4a +; parameters: byte + + call GetScriptByte + ld [wc2cf], a + ret + + db closetext_command ; unused + +Script_closetext: +; script command 0x49 + + call _OpenAndCloseMenu_HDMATransferTileMapAndAttrMap + call CloseText + ret + + +Script_passtoengine: +; script command 0x89 +; parameters: data_pointer + + call GetScriptByte + push af + call GetScriptByte + ld l, a + call GetScriptByte + ld h, a + pop af + call StartAutoInput + ret + +Script_pause: +; script command 0x8b +; parameters: length + + call GetScriptByte + and a + jr z, .loop + ld [wScriptDelay], a +.loop + ld c, 2 + call DelayFrames + ld hl, wScriptDelay + dec [hl] + jr nz, .loop + ret + +Script_deactivatefacing: +; script command 0x8c +; parameters: time + + call GetScriptByte + and a + jr z, .no_time + ld [wScriptDelay], a +.no_time + ld a, SCRIPT_WAIT + ld [wScriptMode], a + call StopScript + ret + +Script_ptpriorityjump: +; script command 0x8f +; parameters: pointer + + call StopScript + jp Script_jump + +Script_end: +; script command 0x91 + + call ExitScriptSubroutine + jr c, .resume + ret + +.resume + xor a + ld [wScriptRunning], a + ld a, SCRIPT_OFF + ld [wScriptMode], a + ld hl, wScriptFlags + res 0, [hl] + call StopScript + ret + +Script_return: +; script command 0x90 + + call ExitScriptSubroutine + jr c, .dummy +.dummy + ld hl, wScriptFlags + res 0, [hl] + call StopScript + ret + +ExitScriptSubroutine: +; Return carry if there's no parent to return to. + + ld hl, wScriptStackSize + ld a, [hl] + and a + jr z, .done + dec [hl] + ld e, [hl] + ld d, $0 + ld hl, wScriptStack + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld b, a + and " " + ld [wScriptBank], a + ld a, [hli] + ld e, a + ld [wScriptPos], a + ld a, [hl] + ld d, a + ld [wScriptPos + 1], a + and a + ret +.done + scf + ret + +Script_endall: +; script command 0x93 + + xor a + ld [wScriptStackSize], a + ld [wScriptRunning], a + ld a, SCRIPT_OFF + ld [wScriptMode], a + ld hl, wScriptFlags + res 0, [hl] + call StopScript + ret + +Script_halloffame: +; script command 0xa1 + + ld hl, wGameTimerPause + res GAMETIMERPAUSE_TIMER_PAUSED_F, [hl] + farcall StubbedTrainerRankings_HallOfFame + farcall StubbedTrainerRankings_HallOfFame2 + farcall HallOfFame + ld hl, wGameTimerPause + set GAMETIMERPAUSE_TIMER_PAUSED_F, [hl] + jr ReturnFromCredits + +Script_credits: +; script command 0xa2 + + farcall RedCredits +ReturnFromCredits: + call Script_endall + ld a, $3 + call LoadMapStatus + call StopScript + ret + +Script_wait: +; script command 0xa8 +; parameters: unknown + + push bc + call GetScriptByte +.loop + push af + ld c, 6 + call DelayFrames + pop af + dec a + jr nz, .loop + pop bc + ret + +Script_checksave: +; script command 0xa9 + + farcall CheckSave + ld a, c + ld [wScriptVar], a + ret + + +; unused + ld a, [.byte] + ld [wScriptVar], a + ret + +.byte + db 0 diff --git a/engine/overworld/select_menu.asm b/engine/overworld/select_menu.asm new file mode 100755 index 000000000..9898afda2 --- /dev/null +++ b/engine/overworld/select_menu.asm @@ -0,0 +1,191 @@ +SelectMenu:: ; 13327 + + call CheckRegisteredItem + jr c, .NotRegistered + jp UseRegisteredItem + +.NotRegistered: + call OpenText + ld b, BANK(ItemMayBeRegisteredText) + ld hl, ItemMayBeRegisteredText + call MapTextbox + call WaitButton + jp CloseText +; 13340 + + +ItemMayBeRegisteredText: ; 13340 + text_jump UnknownText_0x1c1cf3 + db "@" +; 13345 + + +CheckRegisteredItem: ; 13345 + + ld a, [wWhichRegisteredItem] + and a + jr z, .NoRegisteredItem + and REGISTERED_POCKET + rlca + rlca + ld hl, .Pockets + rst JumpTable + ret + +.Pockets: +; entries correspond to *_POCKET constants + dw .CheckItem + dw .CheckBall + dw .CheckKeyItem + dw .CheckTMHM + +.CheckItem: + ld hl, wNumItems + call .CheckRegisteredNo + jr c, .NoRegisteredItem + inc hl + ld e, a + ld d, 0 + add hl, de + add hl, de + call .IsSameItem + jr c, .NoRegisteredItem + and a + ret + +.CheckKeyItem: + ld a, [wRegisteredItem] + ld hl, wKeyItems + ld de, 1 + call IsInArray + jr nc, .NoRegisteredItem + ld a, [wRegisteredItem] + ld [wCurItem], a + and a + ret + +.CheckBall: + ld hl, wNumBalls + call .CheckRegisteredNo + jr nc, .NoRegisteredItem + inc hl + ld e, a + ld d, 0 + add hl, de + add hl, de + call .IsSameItem + jr c, .NoRegisteredItem + ret + +.CheckTMHM: + jr .NoRegisteredItem + +.NoRegisteredItem: + xor a + ld [wWhichRegisteredItem], a + ld [wRegisteredItem], a + scf + ret +; 133a6 + + +.CheckRegisteredNo: ; 133a6 + ld a, [wWhichRegisteredItem] + and REGISTERED_NUMBER + dec a + cp [hl] + jr nc, .NotEnoughItems + ld [wCurItemQuantity], a + and a + ret + +.NotEnoughItems: + scf + ret +; 133b6 + + +.IsSameItem: ; 133b6 + ld a, [wRegisteredItem] + cp [hl] + jr nz, .NotSameItem + ld [wCurItem], a + and a + ret + +.NotSameItem: + scf + ret +; 133c3 + + +UseRegisteredItem: ; 133c3 + + farcall CheckItemMenu + ld a, [wItemAttributeParamBuffer] + ld hl, .SwitchTo + rst JumpTable + ret + +.SwitchTo: +; entries correspond to ITEMMENU_* constants + dw .CantUse + dw .NoFunction + dw .NoFunction + dw .NoFunction + dw .Current + dw .Party + dw .Overworld +; 133df + +.NoFunction: ; 133df + call OpenText + call CantUseItem + call CloseText + and a + ret +; 133ea + +.Current: ; 133ea + call OpenText + call DoItemEffect + call CloseText + and a + ret +; 133f5 + +.Party: ; 133f5 + call RefreshScreen + call FadeToMenu + call DoItemEffect + call CloseSubmenu + call CloseText + and a + ret +; 13406 + +.Overworld: ; 13406 + call RefreshScreen + ld a, 1 + ld [wUsingItemWithSelect], a + call DoItemEffect + xor a + ld [wUsingItemWithSelect], a + ld a, [wItemEffectSucceeded] + cp 1 + jr nz, ._cantuse + scf + ld a, HMENURETURN_SCRIPT + ld [hMenuReturn], a + ret +; 13422 + +.CantUse: ; 13422 + call RefreshScreen + +._cantuse + call CantUseItem + call CloseText + and a + ret +; 1342d diff --git a/engine/overworld/spawn_points.asm b/engine/overworld/spawn_points.asm new file mode 100644 index 000000000..1a3d12441 --- /dev/null +++ b/engine/overworld/spawn_points.asm @@ -0,0 +1,62 @@ +INCLUDE "data/maps/spawn_points.asm" + + +LoadSpawnPoint: ; 1531f + ; loads the spawn point in wDefaultSpawnpoint + push hl + push de + ld a, [wDefaultSpawnpoint] + cp SPAWN_N_A + jr z, .spawn_n_a + ld l, a + ld h, 0 + add hl, hl + add hl, hl + ld de, SpawnPoints + add hl, de + ld a, [hli] + ld [wMapGroup], a + ld a, [hli] + ld [wMapNumber], a + ld a, [hli] + ld [wXCoord], a + ld a, [hli] + ld [wYCoord], a +.spawn_n_a + pop de + pop hl + ret +; 15344 + + +IsSpawnPoint: ; 15344 +; Checks if the map loaded in de is a spawn point. Returns carry if it's a spawn point. + ld hl, SpawnPoints + ld c, 0 +.loop + ld a, [hl] + cp SPAWN_N_A + jr z, .nope + cp d + jr nz, .next + inc hl + ld a, [hld] + cp e + jr z, .yes + +.next + push bc + ld bc, 4 ; length of a spawn table entry + add hl, bc + pop bc + inc c + jr .loop + +.nope + and a + ret + +.yes + scf + ret +; 15363 diff --git a/engine/overworld/tile_events.asm b/engine/overworld/tile_events.asm new file mode 100755 index 000000000..705c0e427 --- /dev/null +++ b/engine/overworld/tile_events.asm @@ -0,0 +1,110 @@ +CheckWarpCollision:: ; 1499a +; Is this tile a warp? + ld a, [wPlayerStandingTile] + cp COLL_PIT + jr z, .warp + cp COLL_PIT_68 + jr z, .warp + and $f0 + cp HI_NYBBLE_WARPS + jr z, .warp + and a + ret + +.warp + scf + ret +; 149af + +CheckDirectionalWarp:: ; 149af +; If this is a directional warp, clear carry (press the designated button to warp). +; Else, set carry (immediate warp). + ld a, [wPlayerStandingTile] + cp COLL_WARP_CARPET_DOWN + jr z, .directional + cp COLL_WARP_CARPET_LEFT + jr z, .directional + cp COLL_WARP_CARPET_UP + jr z, .directional + cp COLL_WARP_CARPET_RIGHT + jr z, .directional + scf + ret + +.directional + xor a + ret +; 149c6 + +CheckWarpFacingDown: ; 149c6 + ld de, 1 + ld hl, .blocks + ld a, [wPlayerStandingTile] + call IsInArray + ret +; 149d3 + +.blocks ; 149d3 + db COLL_DOOR + db COLL_DOOR_79 + db COLL_STAIRCASE + db COLL_STAIRCASE_73 + db COLL_CAVE + db COLL_CAVE_74 + db COLL_WARP_PANEL + db COLL_DOOR_75 + db COLL_DOOR_7D + db -1 +; 149dd + +CheckGrassCollision:: ; 149dd + ld a, [wPlayerStandingTile] + ld hl, .blocks + ld de, 1 + call IsInArray + ret +; 149ea + +.blocks ; 149ea + db COLL_CUT_08 + db COLL_TALL_GRASS + db COLL_LONG_GRASS + db COLL_CUT_28 + db COLL_WATER + db COLL_GRASS_48 + db COLL_GRASS_49 + db COLL_GRASS_4A + db COLL_GRASS_4B + db COLL_GRASS_4C + db -1 +; 149f5 + +CheckCutCollision: ; 149f5 + ld a, c + ld hl, .blocks + ld de, 1 + call IsInArray + ret +; 14a00 + +.blocks ; 14a00 + db COLL_CUT_TREE + db COLL_CUT_TREE_1A + db COLL_TALL_GRASS_10 + db COLL_TALL_GRASS + db COLL_LONG_GRASS + db COLL_LONG_GRASS_1C + db -1 +; 14a07 + +GetWarpSFX:: ; 14a07 + ld a, [wPlayerStandingTile] + ld de, SFX_ENTER_DOOR + cp COLL_DOOR + ret z + ld de, SFX_WARP_TO + cp COLL_WARP_PANEL + ret z + ld de, SFX_EXIT_BUILDING + ret +; 14a1a diff --git a/engine/overworld/time.asm b/engine/overworld/time.asm new file mode 100755 index 000000000..0f83447cc --- /dev/null +++ b/engine/overworld/time.asm @@ -0,0 +1,465 @@ +_InitializeStartDay: ; 113d6 + call InitializeStartDay + ret +; 113da + +ClearDailyTimers: ; 113da + xor a + ld [wLuckyNumberDayBuffer], a + ld [wUnusedTwoDayTimer], a + ld [wDailyResetTimer], a + ret +; 113e5 + +InitCallReceiveDelay:: ; 113e5 + xor a + ld [wTimeCyclesSinceLastCall], a + +NextCallReceiveDelay: ; 113e9 + ld a, [wTimeCyclesSinceLastCall] + cp 3 + jr c, .okay + ld a, 3 + +.okay + ld e, a + ld d, 0 + ld hl, .ReceiveCallDelays + add hl, de + ld a, [hl] + jp RestartReceiveCallDelay +; 113fd + +.ReceiveCallDelays: + db 20, 10, 5, 3 +; 11401 + +CheckReceiveCallTimer: ; 11401 + call CheckReceiveCallDelay ; check timer + ret nc + ld hl, wTimeCyclesSinceLastCall + ld a, [hl] + cp 3 + jr nc, .ok + inc [hl] + +.ok + call NextCallReceiveDelay ; restart timer + scf + ret +; 11413 + +InitOneDayCountdown: ; 11413 + ld a, 1 + +InitNDaysCountdown: ; 11415 + ld [hl], a + push hl + call UpdateTime + pop hl + inc hl + call CopyDayToHL + ret +; 11420 + +CheckDayDependentEventHL: ; 11420 + inc hl + push hl + call CalcDaysSince + call GetDaysSince + pop hl + dec hl + call UpdateTimeRemaining + ret +; 1142e + +RestartReceiveCallDelay: ; 1142e + ld hl, wReceiveCallDelay_MinsRemaining + ld [hl], a + call UpdateTime + ld hl, wReceiveCallDelay_StartTime + call CopyDayHourMinToHL + ret +; 1143c + +CheckReceiveCallDelay: ; 1143c + ld hl, wReceiveCallDelay_StartTime + call CalcMinsHoursDaysSince + call GetMinutesSinceIfLessThan60 + ld hl, wReceiveCallDelay_MinsRemaining + call UpdateTimeRemaining + ret +; 1144c + +RestartDailyResetTimer: ; 1144c + ld hl, wDailyResetTimer + jp InitOneDayCountdown +; 11452 + +CheckDailyResetTimer:: ; 11452 + ld hl, wDailyResetTimer + call CheckDayDependentEventHL + ret nc + xor a + ld hl, wDailyFlags + ld [hli], a ; wDailyFlags + ld [hli], a ; wWeeklyFlags + ld [hli], a ; wSwarmFlags + ld [hl], a ; wSwarmFlags + 1 + ld hl, wDailyRematchFlags +rept 4 + ld [hli], a +endr + ld hl, wDailyPhoneItemFlags +rept 4 + ld [hli], a +endr + ld hl, wDailyPhoneTimeOfDayFlags +rept 4 + ld [hli], a +endr + ld hl, wKenjiBreakTimer + ld a, [hl] + and a + jr z, .RestartKenjiBreakCountdown + dec [hl] + jr nz, .DontRestartKenjiBreakCountdown +.RestartKenjiBreakCountdown: + call SampleKenjiBreakCountdown +.DontRestartKenjiBreakCountdown: + jr RestartDailyResetTimer +; 11485 + +SampleKenjiBreakCountdown: ; 11485 +; Generate a random number between 3 and 6 + call Random + and %11 + add 3 + ld [wKenjiBreakTimer], a + ret +; 11490 + +StartBugContestTimer: ; 11490 + ld a, BUG_CONTEST_MINUTES + ld [wBugContestMinsRemaining], a + ld a, BUG_CONTEST_SECONDS + ld [wBugContestSecsRemaining], a + call UpdateTime + ld hl, wBugContestStartTime + call CopyDayHourMinSecToHL + ret +; 114a4 + + +CheckBugContestTimer:: ; 114a4 (4:54a4) + ld hl, wBugContestStartTime + call CalcSecsMinsHoursDaysSince + ld a, [wDaysSince] + and a + jr nz, .timed_out + ld a, [wHoursSince] + and a + jr nz, .timed_out + ld a, [wSecondsSince] + ld b, a + ld a, [wBugContestSecsRemaining] + sub b + jr nc, .okay + add 60 + +.okay + ld [wBugContestSecsRemaining], a + ld a, [wMinutesSince] + ld b, a + ld a, [wBugContestMinsRemaining] + sbc b + ld [wBugContestMinsRemaining], a + jr c, .timed_out + and a + ret + +.timed_out + xor a + ld [wBugContestMinsRemaining], a + ld [wBugContestSecsRemaining], a + scf + ret + + +InitializeStartDay: ; 114dd + call UpdateTime + ld hl, wTimerEventStartDay + call CopyDayToHL + ret +; 114e7 + +CheckPokerusTick:: ; 114e7 + ld hl, wTimerEventStartDay + call CalcDaysSince + call GetDaysSince + and a + jr z, .done ; not even a day has passed since game start + ld b, a + farcall ApplyPokerusTick +.done + xor a + ret +; 114fc + +SetUnusedTwoDayTimer: ; 114fc + ld a, 2 + ld hl, wUnusedTwoDayTimer + ld [hl], a + call UpdateTime + ld hl, wUnusedTwoDayTimerStartDate + call CopyDayToHL + ret +; 1150c + +CheckUnusedTwoDayTimer: ; 1150c + ld hl, wUnusedTwoDayTimerStartDate + call CalcDaysSince + call GetDaysSince + ld hl, wUnusedTwoDayTimer + call UpdateTimeRemaining + ret +; 1151c + +; unused + ld hl, wDailyFlags + set DAILYFLAGS_FISH_SWARM_F, [hl] + ret +; 11522 + +; unused + and a + ld hl, wDailyFlags + bit DAILYFLAGS_FISH_SWARM_F, [hl] + ret nz + scf + ret +; 1152b + +RestartLuckyNumberCountdown: ; 1152b + call .GetDaysUntilNextFriday + ld hl, wLuckyNumberDayBuffer + jp InitNDaysCountdown +; 11534 + +.GetDaysUntilNextFriday: ; 11534 + call GetWeekday + ld c, a + ld a, FRIDAY + sub c + jr z, .friday_saturday + jr nc, .earlier ; could have done "ret nc" + +.friday_saturday + add 7 + +.earlier + ret +; 11542 + +_CheckLuckyNumberShowFlag: ; 11542 + ld hl, wLuckyNumberDayBuffer + jp CheckDayDependentEventHL +; 11548 + +DoMysteryGiftIfDayHasPassed: ; 11548 + ld a, BANK(sMysteryGiftTimer) + call GetSRAMBank + ld hl, sMysteryGiftTimer + ld a, [hli] + ld [wBuffer1], a + ld a, [hl] + ld [wBuffer2], a + call CloseSRAM + + ld hl, wBuffer1 + call CheckDayDependentEventHL + jr nc, .not_timed_out + ld hl, wBuffer1 + call InitOneDayCountdown + call CloseSRAM + farcall Function1050c8 + +.not_timed_out + ld a, BANK(sMysteryGiftTimer) + call GetSRAMBank + ld hl, wBuffer1 + ld a, [hli] + ld [sMysteryGiftTimer], a + ld a, [hl] + ld [sMysteryGiftTimer + 1], a + call CloseSRAM + ret +; 11586 + +UpdateTimeRemaining: ; 11586 +; If the amount of time elapsed exceeds the capacity of its +; unit, skip this part. + cp -1 + jr z, .set_carry + ld c, a + ld a, [hl] ; time remaining + sub c + jr nc, .ok + xor a + +.ok + ld [hl], a + jr z, .set_carry + xor a + ret + +.set_carry + xor a + ld [hl], a + scf + ret +; 11599 + +GetSecondsSinceIfLessThan60: ; 11599 + ld a, [wDaysSince] + and a + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wHoursSince] + and a + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wMinutesSince] + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wSecondsSince] + ret +; 115ae + +GetMinutesSinceIfLessThan60: ; 115ae + ld a, [wDaysSince] + and a + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wHoursSince] + and a + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wMinutesSince] + ret +; 115be + +GetHoursSinceIfLessThan24: ; 115be + ld a, [wDaysSince] + and a + jr nz, GetTimeElapsed_ExceedsUnitLimit + ld a, [wHoursSince] + ret +; 115c8 + +GetDaysSince: ; 115c8 + ld a, [wDaysSince] + ret +; 115cc + +GetTimeElapsed_ExceedsUnitLimit: ; 115cc + ld a, -1 + ret +; 115cf + +CalcDaysSince: ; 115cf + xor a + jr _CalcDaysSince +; 115d2 + +CalcHoursDaysSince: ; 115d2 + inc hl + xor a + jr _CalcHoursDaysSince +; 115d6 + +CalcMinsHoursDaysSince: ; 115d6 + inc hl + inc hl + xor a + jr _CalcMinsHoursDaysSince +; 115db + +CalcSecsMinsHoursDaysSince: ; 115db + inc hl + inc hl + inc hl + ld a, [hSeconds] + ld c, a + sub [hl] + jr nc, .skip + add 60 +.skip + ld [hl], c ; current seconds + dec hl + ld [wSecondsSince], a ; seconds since + +_CalcMinsHoursDaysSince: ; 115eb + ld a, [hMinutes] + ld c, a + sbc [hl] + jr nc, .skip + add 60 +.skip + ld [hl], c ; current minutes + dec hl + ld [wMinutesSince], a ; minutes since + +_CalcHoursDaysSince: ; 115f8 + ld a, [hHours] + ld c, a + sbc [hl] + jr nc, .skip + add 24 +.skip + ld [hl], c ; current hours + dec hl + ld [wHoursSince], a ; hours since + +_CalcDaysSince: + ld a, [wCurDay] + ld c, a + sbc [hl] + jr nc, .skip + add 20 * 7 +.skip + ld [hl], c ; current days + ld [wDaysSince], a ; days since + ret +; 11613 + +CopyDayHourMinSecToHL: ; 11613 + ld a, [wCurDay] + ld [hli], a + ld a, [hHours] + ld [hli], a + ld a, [hMinutes] + ld [hli], a + ld a, [hSeconds] + ld [hli], a + ret +; 11621 + +CopyDayToHL: ; 11621 + ld a, [wCurDay] + ld [hl], a + ret +; 11626 + +CopyDayHourToHL: ; 11626 + ld a, [wCurDay] + ld [hli], a + ld a, [hHours] + ld [hli], a + ret +; 1162e + +CopyDayHourMinToHL: ; 1162e + ld a, [wCurDay] + ld [hli], a + ld a, [hHours] + ld [hli], a + ld a, [hMinutes] + ld [hli], a + ret +; 11639 diff --git a/engine/overworld/variables.asm b/engine/overworld/variables.asm new file mode 100755 index 000000000..89026fdba --- /dev/null +++ b/engine/overworld/variables.asm @@ -0,0 +1,151 @@ +_GetVarAction:: ; 80648 (20:4648) + ld a, c + cp NUM_VARS + jr c, .valid + xor a +.valid + ld c, a + ld b, 0 + ld hl, .VarActionTable + add hl, bc + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld b, [hl] + ld a, b + and RETVAR_EXECUTE + jr nz, .call + ld a, b + and RETVAR_ADDR_DE + ret nz + ld a, [de] + jr .loadstringbuffer2 + +.call + call _de_ + ret + +.loadstringbuffer2 ; 8066c (20:466c) + ld de, wStringBuffer2 + ld [de], a + ret +; 80671 (20:4671) + +.VarActionTable: ; 80671 +; entries correspond to VAR_* constants + ; RETVAR_STRBUF2: copy [de] to wStringBuffer2 + ; RETVAR_ADDR_DE: return address in de + ; RETVAR_EXECUTE: call function + dwb wStringBuffer2, RETVAR_STRBUF2 + dwb wPartyCount, RETVAR_STRBUF2 + dwb .BattleResult, RETVAR_EXECUTE + dwb wBattleType, RETVAR_ADDR_DE + dwb wTimeOfDay, RETVAR_STRBUF2 + dwb .CountCaughtMons, RETVAR_EXECUTE + dwb .CountSeenMons, RETVAR_EXECUTE + dwb .CountBadges, RETVAR_EXECUTE + dwb wPlayerState, RETVAR_ADDR_DE + dwb .PlayerFacing, RETVAR_EXECUTE + dwb hHours, RETVAR_STRBUF2 + dwb .DayOfWeek, RETVAR_EXECUTE + dwb wMapGroup, RETVAR_STRBUF2 + dwb wMapNumber, RETVAR_STRBUF2 + dwb .UnownCaught, RETVAR_EXECUTE + dwb wEnvironment, RETVAR_STRBUF2 + dwb .BoxFreeSpace, RETVAR_EXECUTE + dwb wBugContestMinsRemaining, RETVAR_STRBUF2 + dwb wXCoord, RETVAR_STRBUF2 + dwb wYCoord, RETVAR_STRBUF2 + dwb wSpecialPhoneCallID, RETVAR_STRBUF2 + dwb wNrOfBeatenBattleTowerTrainers, RETVAR_STRBUF2 + dwb wKurtApricornQuantity, RETVAR_STRBUF2 + dwb wCurrentCaller, RETVAR_ADDR_DE + dwb wBlueCardBalance, RETVAR_ADDR_DE + dwb wBuenasPassword, RETVAR_ADDR_DE + dwb wKenjiBreakTimer, RETVAR_STRBUF2 + dwb NULL, RETVAR_STRBUF2 +; 806c5 + +.CountCaughtMons: ; 806c5 +; Caught mons. + ld hl, wPokedexCaught + ld b, wEndPokedexCaught - wPokedexCaught + call CountSetBits + ld a, [wd265] + jp .loadstringbuffer2 +; 806d3 + +.CountSeenMons: ; 806d3 +; Seen mons. + ld hl, wPokedexSeen + ld b, wEndPokedexSeen - wPokedexSeen + call CountSetBits + ld a, [wd265] + jp .loadstringbuffer2 +; 806e1 + +.CountBadges: ; 806e1 +; Number of owned badges. + ld hl, wBadges + ld b, 2 + call CountSetBits + ld a, [wd265] + jp .loadstringbuffer2 +; 806ef + +.PlayerFacing: ; 806ef +; The direction the player is facing. + ld a, [wPlayerDirection] + and $c + rrca + rrca + jp .loadstringbuffer2 +; 806f9 + +.DayOfWeek: ; 806f9 +; The day of the week. + call GetWeekday + jp .loadstringbuffer2 +; 806ff + +.UnownCaught: ; 806ff +; Number of unique Unown caught. + call .count + ld a, b + jp .loadstringbuffer2 + +.count + ld hl, wUnownDex + ld b, 0 +.loop + ld a, [hli] + and a + ret z + inc b + ld a, b + cp NUM_UNOWN + jr c, .loop + ret +; 80715 + +.BoxFreeSpace: ; 80715 +; Remaining slots in the current box. + ld a, BANK(sBoxCount) + call GetSRAMBank + ld hl, sBoxCount + ld a, MONS_PER_BOX + sub [hl] + ld b, a + call CloseSRAM + ld a, b + jp .loadstringbuffer2 +; 80728 + +.BattleResult: ; 80728 + ld a, [wBattleResult] + and $3f + jp .loadstringbuffer2 +; 80730 diff --git a/engine/overworld/warp_connection.asm b/engine/overworld/warp_connection.asm new file mode 100755 index 000000000..069b72234 --- /dev/null +++ b/engine/overworld/warp_connection.asm @@ -0,0 +1,439 @@ + +HandleNewMap: ; 1045b0 + call Clearwc7e8 + call ResetMapBufferEventFlags + call ResetFlashIfOutOfCave + call GetCurrentMapSceneID + call ResetBikeFlags + ld a, MAPCALLBACK_NEWMAP + call RunMapCallback +InitCommandQueue: ; 1045c4 + farcall ClearCmdQueue + ld a, MAPCALLBACK_CMDQUEUE + call RunMapCallback + call GetMapTimeOfDay + ld [wMapTimeOfDay], a + ret + + +EnterMapConnection: ; 1045d6 +; Return carry if a connection has been entered. + ld a, [wPlayerStepDirection] + and a + jp z, .south + cp UP + jp z, .north + cp LEFT + jp z, .west + cp RIGHT + jp z, .east + ret + +.west + ld a, [wWestConnectedMapGroup] + ld [wMapGroup], a + ld a, [wWestConnectedMapNumber] + ld [wMapNumber], a + ld a, [wWestConnectionStripXOffset] + ld [wXCoord], a + ld a, [wWestConnectionStripYOffset] + ld hl, wYCoord + add [hl] + ld [hl], a + ld c, a + ld hl, wWestConnectionWindow + ld a, [hli] + ld h, [hl] + ld l, a + srl c + jr z, .skip_to_load + ld a, [wWestConnectedMapWidth] + add 6 + ld e, a + ld d, 0 + +.loop + add hl, de + dec c + jr nz, .loop + +.skip_to_load + ld a, l + ld [wOverworldMapAnchor], a + ld a, h + ld [wOverworldMapAnchor + 1], a + jp .done + +.east + ld a, [wEastConnectedMapGroup] + ld [wMapGroup], a + ld a, [wEastConnectedMapNumber] + ld [wMapNumber], a + ld a, [wEastConnectionStripXOffset] + ld [wXCoord], a + ld a, [wEastConnectionStripYOffset] + ld hl, wYCoord + add [hl] + ld [hl], a + ld c, a + ld hl, wEastConnectionWindow + ld a, [hli] + ld h, [hl] + ld l, a + srl c + jr z, .skip_to_load2 + ld a, [wEastConnectedMapWidth] + add 6 + ld e, a + ld d, 0 + +.loop2 + add hl, de + dec c + jr nz, .loop2 + +.skip_to_load2 + ld a, l + ld [wOverworldMapAnchor], a + ld a, h + ld [wOverworldMapAnchor + 1], a + jp .done + +.north + ld a, [wNorthConnectedMapGroup] + ld [wMapGroup], a + ld a, [wNorthConnectedMapNumber] + ld [wMapNumber], a + ld a, [wNorthConnectionStripYOffset] + ld [wYCoord], a + ld a, [wNorthConnectionStripXOffset] + ld hl, wXCoord + add [hl] + ld [hl], a + ld c, a + ld hl, wNorthConnectionWindow + ld a, [hli] + ld h, [hl] + ld l, a + ld b, 0 + srl c + add hl, bc + ld a, l + ld [wOverworldMapAnchor], a + ld a, h + ld [wOverworldMapAnchor + 1], a + jp .done + +.south + ld a, [wSouthConnectedMapGroup] + ld [wMapGroup], a + ld a, [wSouthConnectedMapNumber] + ld [wMapNumber], a + ld a, [wSouthConnectionStripYOffset] + ld [wYCoord], a + ld a, [wSouthConnectionStripXOffset] + ld hl, wXCoord + add [hl] + ld [hl], a + ld c, a + ld hl, wSouthConnectionWindow + ld a, [hli] + ld h, [hl] + ld l, a + ld b, 0 + srl c + add hl, bc + ld a, l + ld [wOverworldMapAnchor], a + ld a, h + ld [wOverworldMapAnchor + 1], a +.done + scf + ret +; 1046c6 + +LoadWarpData: ; 1046c6 + call .SaveDigWarp + call .SetSpawn + ld a, [wNextWarp] + ld [wWarpNumber], a + ld a, [wNextMapGroup] + ld [wMapGroup], a + ld a, [wNextMapNumber] + ld [wMapNumber], a + ret + +.SaveDigWarp: ; 1046df (41:46df) + call GetMapEnvironment + call CheckOutdoorMap + ret nz + ld a, [wNextMapGroup] + ld b, a + ld a, [wNextMapNumber] + ld c, a + call GetAnyMapEnvironment + call CheckIndoorMap + ret nz + +; MOUNT_MOON_SQUARE and TIN_TOWER_ROOF are outdoor maps within indoor maps. +; Dig and Escape Rope should not take you to them. + ld a, [wPrevMapGroup] + cp GROUP_MOUNT_MOON_SQUARE ; GROUP_TIN_TOWER_ROOF + jr nz, .not_mt_moon_or_tin_tower + ld a, [wPrevMapNumber] + cp MAP_MOUNT_MOON_SQUARE + ret z + cp MAP_TIN_TOWER_ROOF + ret z +.not_mt_moon_or_tin_tower + + ld a, [wPrevWarp] + ld [wDigWarpNumber], a + ld a, [wPrevMapGroup] + ld [wDigMapGroup], a + ld a, [wPrevMapNumber] + ld [wDigMapNumber], a + ret + +.SetSpawn: ; 104718 (41:4718) + call GetMapEnvironment + call CheckOutdoorMap + ret nz + ld a, [wNextMapGroup] + ld b, a + ld a, [wNextMapNumber] + ld c, a + call GetAnyMapEnvironment + call CheckIndoorMap + ret nz + ld a, [wNextMapGroup] + ld b, a + ld a, [wNextMapNumber] + ld c, a + +; Respawn in Pokémon Centers. + call GetAnyMapTileset + ld a, c + cp TILESET_POKECENTER + jr z, .pokecenter_pokecom + cp TILESET_POKECOM_CENTER + jr z, .pokecenter_pokecom + ret +.pokecenter_pokecom + + ld a, [wPrevMapGroup] + ld [wLastSpawnMapGroup], a + ld a, [wPrevMapNumber] + ld [wLastSpawnMapNumber], a + ret + +LoadMapTimeOfDay: ; 104750 + ld hl, wVramState + res 6, [hl] + ld a, $1 + ld [wSpriteUpdatesEnabled], a + farcall ReplaceTimeOfDayPals + farcall UpdateTimeOfDayPal + call OverworldTextModeSwitch + call .ClearBGMap + call .PushAttrMap + ret + +.ClearBGMap: ; 104770 (41:4770) + ld a, HIGH(vBGMap0) + ld [wBGMapAnchor + 1], a + xor a ; LOW(vBGMap0) + ld [wBGMapAnchor], a + ld [hSCY], a + ld [hSCX], a + farcall ApplyBGMapAnchorToObjects + + ld a, [rVBK] + push af + ld a, $1 + ld [rVBK], a + + xor a + ld bc, vBGMap1 - vBGMap0 + hlbgcoord 0, 0 + call ByteFill + + pop af + ld [rVBK], a + + ld a, "■" + ld bc, vBGMap1 - vBGMap0 + hlbgcoord 0, 0 + call ByteFill + ret + +.PushAttrMap: ; 1047a3 (41:47a3) + decoord 0, 0 + call .copy + ld a, [hCGB] + and a + ret z + + decoord 0, 0, wAttrMap + ld a, $1 + ld [rVBK], a +.copy + hlbgcoord 0, 0 + ld c, SCREEN_WIDTH + ld b, SCREEN_HEIGHT +.row + push bc +.column + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .column + ld bc, BG_MAP_WIDTH - SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .row + ld a, $0 + ld [rVBK], a + ret + +LoadGraphics: ; 1047cf + call LoadTileset + call LoadTilesetGFX + xor a + ld [hMapAnims], a + xor a + ld [hTileAnimFrame], a + farcall RefreshSprites + call LoadFontsExtra + farcall LoadOverworldFont + ret + +LoadMapPalettes: ; 1047eb + ld b, SCGB_MAPPALS + jp GetSGBLayout +; 1047f0 + +RefreshMapSprites: ; 1047f0 + call ClearSprites + farcall ReturnFromMapSetupScript + call GetMovementPermissions + farcall RefreshPlayerSprite + farcall CheckReplaceKrisSprite + ld hl, wPlayerSpriteSetupFlags + bit PLAYERSPRITESETUP_SKIP_RELOAD_GFX_F, [hl] + jr nz, .skip + ld hl, wVramState + set 0, [hl] + call SafeUpdateSprites +.skip + ld a, [wPlayerSpriteSetupFlags] + and %00011100 + ld [wPlayerSpriteSetupFlags], a + ret + +CheckMovingOffEdgeOfMap:: ; 104820 (41:4820) + ld a, [wPlayerStepDirection] + cp STANDING + ret z + and a ; DOWN + jr z, .down + cp UP + jr z, .up + cp LEFT + jr z, .left + cp RIGHT + jr z, .right + and a + ret + +.down + ld a, [wPlayerStandingMapY] + sub 4 + ld b, a + ld a, [wMapHeight] + add a + cp b + jr z, .ok + and a + ret + +.up + ld a, [wPlayerStandingMapY] + sub 4 + cp -1 + jr z, .ok + and a + ret + +.left + ld a, [wPlayerStandingMapX] + sub 4 + cp -1 + jr z, .ok + and a + ret + +.right + ld a, [wPlayerStandingMapX] + sub 4 + ld b, a + ld a, [wMapWidth] + add a + cp b + jr z, .ok + and a + ret + +.ok + scf + ret + + +GetCoordOfUpperLeftCorner:: ; 10486d + ld hl, wOverworldMap + ld a, [wXCoord] + bit 0, a + jr nz, .increment_then_halve1 + srl a + add $1 + jr .resume + +.increment_then_halve1 + add $1 + srl a + +.resume + ld c, a + ld b, $0 + add hl, bc + ld a, [wMapWidth] + add $6 + ld c, a + ld b, $0 + ld a, [wYCoord] + bit 0, a + jr nz, .increment_then_halve2 + srl a + add $1 + jr .resume2 + +.increment_then_halve2 + add $1 + srl a + +.resume2 + call AddNTimes + ld a, l + ld [wOverworldMapAnchor], a + ld a, h + ld [wOverworldMapAnchor + 1], a + ld a, [wYCoord] + and $1 + ld [wMetatileStandingY], a + ld a, [wXCoord] + and $1 + ld [wMetatileStandingX], a + ret +; 1048ba diff --git a/engine/overworld/wildmons.asm b/engine/overworld/wildmons.asm new file mode 100755 index 000000000..494e8d2a4 --- /dev/null +++ b/engine/overworld/wildmons.asm @@ -0,0 +1,1000 @@ +LoadWildMonData: ; 29ff8 + call _GrassWildmonLookup + jr c, .copy + ld hl, wMornEncounterRate + xor a + ld [hli], a + ld [hli], a + ld [hl], a + jr .done_copy + +.copy + inc hl + inc hl + ld de, wMornEncounterRate + ld bc, 3 + call CopyBytes +.done_copy + call _WaterWildmonLookup + ld a, 0 + jr nc, .no_copy + inc hl + inc hl + ld a, [hl] +.no_copy + ld [wWaterEncounterRate], a + ret + +FindNest: ; 2a01f +; Parameters: +; e: 0 = Johto, 1 = Kanto +; wNamedObjectIndexBuffer: species + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + xor a + call ByteFill + ld a, e + and a + jr nz, .kanto + decoord 0, 0 + ld hl, JohtoGrassWildMons + call .FindGrass + ld hl, JohtoWaterWildMons + call .FindWater + call .RoamMon1 + call .RoamMon2 + ret + +.kanto + decoord 0, 0 + ld hl, KantoGrassWildMons + call .FindGrass + ld hl, KantoWaterWildMons + jp .FindWater +; 2a052 + +.FindGrass: ; 2a052 + ld a, [hl] + cp -1 + ret z + push hl + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a + inc hl + inc hl + inc hl + ld a, NUM_GRASSMON * 3 + call .SearchMapForMon + jr nc, .next_grass + ld [de], a + inc de + +.next_grass + pop hl + ld bc, GRASS_WILDDATA_LENGTH + add hl, bc + jr .FindGrass +; 2a06e + +.FindWater: ; 2a06e + ld a, [hl] + cp -1 + ret z + push hl + ld a, [hli] + ld b, a + ld a, [hli] + ld c, a + inc hl + ld a, 3 + call .SearchMapForMon + jr nc, .next_water + ld [de], a + inc de + +.next_water + pop hl + ld bc, 3 * 3 + add hl, bc + jr .FindWater +; 2a088 + +.SearchMapForMon: ; 2a088 + inc hl +.ScanMapLoop: + push af + ld a, [wNamedObjectIndexBuffer] + cp [hl] + jr z, .found + inc hl + inc hl + pop af + dec a + jr nz, .ScanMapLoop + and a + ret + +.found + pop af + jp .AppendNest +; 2a09c + +.AppendNest: ; 2a09c + push de + call GetWorldMapLocation + ld c, a + hlcoord 0, 0 + ld de, SCREEN_WIDTH * SCREEN_HEIGHT +.AppendNestLoop: + ld a, [hli] + cp c + jr z, .found_nest + dec de + ld a, e + or d + jr nz, .AppendNestLoop + ld a, c + pop de + scf + ret + +.found_nest + pop de + and a + ret +; 2a0b7 + +.RoamMon1: ; 2a0b7 + ld a, [wRoamMon1Species] + ld b, a + ld a, [wNamedObjectIndexBuffer] + cp b + ret nz + ld a, [wRoamMon1MapGroup] + ld b, a + ld a, [wRoamMon1MapNumber] + ld c, a + call .AppendNest + ret nc + ld [de], a + inc de + ret +; 2a0cf + +.RoamMon2: ; 2a0cf + ld a, [wRoamMon2Species] + ld b, a + ld a, [wNamedObjectIndexBuffer] + cp b + ret nz + ld a, [wRoamMon2MapGroup] + ld b, a + ld a, [wRoamMon2MapNumber] + ld c, a + call .AppendNest + ret nc + ld [de], a + inc de + ret +; 2a0e7 + +TryWildEncounter:: ; 2a0e7 +; Try to trigger a wild encounter. + call .EncounterRate + jr nc, .no_battle + call ChooseWildEncounter + jr nz, .no_battle + call CheckRepelEffect + jr nc, .no_battle + xor a + ret + +.no_battle + xor a ; BATTLETYPE_NORMAL + ld [wTempWildMonSpecies], a + ld [wBattleType], a + ld a, 1 + and a + ret +; 2a103 + +.EncounterRate: ; 2a103 + call GetMapEncounterRate + call ApplyMusicEffectOnEncounterRate + call ApplyCleanseTagEffectOnEncounterRate + call Random + cp b + ret +; 2a111 + +GetMapEncounterRate: ; 2a111 + ld hl, wMornEncounterRate + call CheckOnWater + ld a, wWaterEncounterRate - wMornEncounterRate + jr z, .ok + ld a, [wTimeOfDay] +.ok + ld c, a + ld b, 0 + add hl, bc + ld b, [hl] + ret +; 2a124 + +ApplyMusicEffectOnEncounterRate:: ; 2a124 +; Pokemon March and Ruins of Alph signal double encounter rate. +; Pokemon Lullaby halves encounter rate. + ld a, [wMapMusic] + cp MUSIC_POKEMON_MARCH + jr z, .double + cp MUSIC_RUINS_OF_ALPH_RADIO + jr z, .double + cp MUSIC_POKEMON_LULLABY + ret nz + srl b + ret + +.double + sla b + ret +; 2a138 + +ApplyCleanseTagEffectOnEncounterRate:: ; 2a138 +; Cleanse Tag halves encounter rate. + ld hl, wPartyMon1Item + ld de, PARTYMON_STRUCT_LENGTH + ld a, [wPartyCount] + ld c, a +.loop + ld a, [hl] + cp CLEANSE_TAG + jr z, .cleansetag + add hl, de + dec c + jr nz, .loop + ret + +.cleansetag + srl b + ret +; 2a14f + +ChooseWildEncounter: ; 2a14f + call LoadWildMonDataPointer + jp nc, .nowildbattle + call CheckEncounterRoamMon + jp c, .startwildbattle + + inc hl + inc hl + inc hl + call CheckOnWater + ld de, WaterMonProbTable + jr z, .watermon + inc hl + inc hl + ld a, [wTimeOfDay] + ld bc, $e + call AddNTimes + ld de, GrassMonProbTable + +.watermon +; hl contains the pointer to the wild mon data, let's save that to the stack + push hl +.randomloop + call Random + cp 100 + jr nc, .randomloop + inc a ; 1 <= a <= 100 + ld b, a + ld h, d + ld l, e +; This next loop chooses which mon to load up. +.prob_bracket_loop + ld a, [hli] + cp b + jr nc, .got_it + inc hl + jr .prob_bracket_loop + +.got_it + ld c, [hl] + ld b, 0 + pop hl + add hl, bc ; this selects our mon + ld a, [hli] + ld b, a +; If the Pokemon is encountered by surfing, we need to give the levels some variety. + call CheckOnWater + jr nz, .ok +; Check if we buff the wild mon, and by how much. + call Random + cp 35 percent + jr c, .ok + inc b + cp 65 percent + jr c, .ok + inc b + cp 85 percent + jr c, .ok + inc b + cp 95 percent + jr c, .ok + inc b +; Store the level +.ok + ld a, b + ld [wCurPartyLevel], a + ld b, [hl] + ; ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + ld a, b ; This is in the wrong place. + cp UNOWN + jr nz, .done + + ld a, [wUnlockedUnowns] + and a + jr z, .nowildbattle + +.done + jr .loadwildmon + +.nowildbattle + ld a, 1 + and a + ret + +.loadwildmon + ld a, b + ld [wTempWildMonSpecies], a + +.startwildbattle + xor a + ret +; 2a1cb + +INCLUDE "data/wild/probabilities.asm" + +CheckRepelEffect:: ; 2a1df +; If there is no active Repel, there's no need to be here. + ld a, [wRepelEffect] + and a + jr z, .encounter +; Get the first Pokemon in your party that isn't fainted. + ld hl, wPartyMon1HP + ld bc, PARTYMON_STRUCT_LENGTH - 1 +.loop + ld a, [hli] + or [hl] + jr nz, .ok + add hl, bc + jr .loop + +.ok +; to PartyMonLevel +rept 4 + dec hl +endr + + ld a, [wCurPartyLevel] + cp [hl] + jr nc, .encounter + and a + ret + +.encounter + scf + ret +; 2a200 + +LoadWildMonDataPointer: ; 2a200 + call CheckOnWater + jr z, _WaterWildmonLookup + +_GrassWildmonLookup: ; 2a205 + ld hl, SwarmGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call _SwarmWildmonCheck + ret c + ld hl, JohtoGrassWildMons + ld de, KantoGrassWildMons + call _JohtoWildmonCheck + ld bc, GRASS_WILDDATA_LENGTH + jr _NormalWildmonOK + +_WaterWildmonLookup: ; 2a21d + ld hl, SwarmWaterWildMons + ld bc, WATER_WILDDATA_LENGTH + call _SwarmWildmonCheck + ret c + ld hl, JohtoWaterWildMons + ld de, KantoWaterWildMons + call _JohtoWildmonCheck + ld bc, WATER_WILDDATA_LENGTH + jr _NormalWildmonOK + +_JohtoWildmonCheck + call IsInJohto + and a + ret z + ld h, d + ld l, e + ret + +_SwarmWildmonCheck + call CopyCurrMapDE + push hl + ld hl, wSwarmFlags + bit SWARMFLAGS_DUNSPARCE_SWARM_F, [hl] + pop hl + jr z, .CheckYanma + ld a, [wDunsparceMapGroup] + cp d + jr nz, .CheckYanma + ld a, [wDunsparceMapNumber] + cp e + jr nz, .CheckYanma + call LookUpWildmonsForMapDE + jr nc, _NoSwarmWildmon + scf + ret + +.CheckYanma: + push hl + ld hl, wSwarmFlags + bit SWARMFLAGS_YANMA_SWARM_F, [hl] + pop hl + jr z, _NoSwarmWildmon + ld a, [wYanmaMapGroup] + cp d + jr nz, _NoSwarmWildmon + ld a, [wYanmaMapNumber] + cp e + jr nz, _NoSwarmWildmon + call LookUpWildmonsForMapDE + jr nc, _NoSwarmWildmon + scf + ret + +_NoSwarmWildmon + and a + ret + +_NormalWildmonOK + call CopyCurrMapDE + jr LookUpWildmonsForMapDE +; 2a27f + +CopyCurrMapDE: ; 2a27f + ld a, [wMapGroup] + ld d, a + ld a, [wMapNumber] + ld e, a + ret +; 2a288 + +LookUpWildmonsForMapDE: ; 2a288 +.loop + push hl + ld a, [hl] + inc a + jr z, .nope + ld a, d + cp [hl] + jr nz, .next + inc hl + ld a, e + cp [hl] + jr z, .yup + +.next + pop hl + add hl, bc + jr .loop + +.nope + pop hl + and a + ret + +.yup + pop hl + scf + ret +; 2a2a0 + + +InitRoamMons: ; 2a2a0 +; initialize wRoamMon structs + +; species + ld a, RAIKOU + ld [wRoamMon1Species], a + ld a, ENTEI + ld [wRoamMon2Species], a + +; level + ld a, 40 + ld [wRoamMon1Level], a + ld [wRoamMon2Level], a + +; raikou starting map + ld a, GROUP_ROUTE_42 + ld [wRoamMon1MapGroup], a + ld a, MAP_ROUTE_42 + ld [wRoamMon1MapNumber], a + +; entei starting map + ld a, GROUP_ROUTE_37 + ld [wRoamMon2MapGroup], a + ld a, MAP_ROUTE_37 + ld [wRoamMon2MapNumber], a + +; hp + xor a ; generate new stats + ld [wRoamMon1HP], a + ld [wRoamMon2HP], a + + ret +; 2a2ce + + +CheckEncounterRoamMon: ; 2a2ce + push hl +; Don't trigger an encounter if we're on water. + call CheckOnWater + jr z, .DontEncounterRoamMon +; Load the current map group and number to de + call CopyCurrMapDE +; Randomly select a beast. + call Random + cp 100 ; 25/64 chance + jr nc, .DontEncounterRoamMon + and %00000011 ; Of that, a 3/4 chance. Running total: 75/256, or around 29.3%. + jr z, .DontEncounterRoamMon + dec a ; 1/3 chance that it's Entei, 1/3 chance that it's Raikou +; Compare its current location with yours + ld hl, wRoamMon1MapGroup + ld c, a + ld b, 0 + ld a, 7 ; length of the roam_struct + call AddNTimes + ld a, d + cp [hl] + jr nz, .DontEncounterRoamMon + inc hl + ld a, e + cp [hl] + jr nz, .DontEncounterRoamMon +; We've decided to take on a beast, so stage its information for battle. + dec hl + dec hl + dec hl + ld a, [hli] + ld [wTempWildMonSpecies], a + ld a, [hl] + ld [wCurPartyLevel], a + ld a, BATTLETYPE_ROAMING + ld [wBattleType], a + + pop hl + scf + ret + +.DontEncounterRoamMon: + pop hl + and a + ret +; 2a30d + + +UpdateRoamMons: ; 2a30d + ld a, [wRoamMon1MapGroup] + cp GROUP_N_A + jr z, .SkipRaikou + ld b, a + ld a, [wRoamMon1MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon1MapGroup], a + ld a, c + ld [wRoamMon1MapNumber], a + +.SkipRaikou: + ld a, [wRoamMon2MapGroup] + cp GROUP_N_A + jr z, .SkipEntei + ld b, a + ld a, [wRoamMon2MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon2MapGroup], a + ld a, c + ld [wRoamMon2MapNumber], a + +.SkipEntei: + ld a, [wRoamMon3MapGroup] + cp GROUP_N_A + jr z, .Finished + ld b, a + ld a, [wRoamMon3MapNumber] + ld c, a + call .Update + ld a, b + ld [wRoamMon3MapGroup], a + ld a, c + ld [wRoamMon3MapNumber], a + +.Finished: + jp _BackUpMapIndices +; 2a355 + + +.Update: ; 2a355 + ld hl, RoamMaps +.loop +; Are we at the end of the table? + ld a, [hl] + cp -1 + ret z +; Is this the correct entry? + ld a, b + cp [hl] + jr nz, .next + inc hl + ld a, c + cp [hl] + jr z, .yes +; We don't have the correct entry yet, so let's continue. A 0 terminates each entry. +.next + ld a, [hli] + and a + jr nz, .next + jr .loop + +; We have the correct entry now, so let's choose a random map from it. +.yes + inc hl + ld d, h + ld e, l +.update_loop + ld h, d + ld l, e +; Choose which map to warp to. + call Random + and %00011111 ; 1/8n chance it moves to a completely random map, where n is the number of roaming connections from the current map. + jr z, JumpRoamMon + and %11 + cp [hl] + jr nc, .update_loop ; invalid index, try again + inc hl + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld a, [wRoamMons_LastMapGroup] + cp [hl] + jr nz, .done + inc hl + ld a, [wRoamMons_LastMapNumber] + cp [hl] + jr z, .update_loop + dec hl + +.done + ld a, [hli] + ld b, a + ld c, [hl] + ret + +JumpRoamMons: ; 2a394 + ld a, [wRoamMon1MapGroup] + cp GROUP_N_A + jr z, .SkipRaikou + call JumpRoamMon + ld a, b + ld [wRoamMon1MapGroup], a + ld a, c + ld [wRoamMon1MapNumber], a + +.SkipRaikou: + ld a, [wRoamMon2MapGroup] + cp GROUP_N_A + jr z, .SkipEntei + call JumpRoamMon + ld a, b + ld [wRoamMon2MapGroup], a + ld a, c + ld [wRoamMon2MapNumber], a + +.SkipEntei: + ld a, [wRoamMon3MapGroup] + cp GROUP_N_A + jr z, .Finished + call JumpRoamMon + ld a, b + ld [wRoamMon3MapGroup], a + ld a, c + ld [wRoamMon3MapNumber], a + +.Finished: + jp _BackUpMapIndices + +JumpRoamMon: ; 2a3cd +.loop + ld hl, RoamMaps +.innerloop1 ; This loop happens to be unnecessary. + call Random ; Choose a random number. + maskbits NUM_ROAMMON_MAPS ; Mask the number to limit it between 0 and 15. + cp NUM_ROAMMON_MAPS ; If the number is not less than 16, try again. + jr nc, .innerloop1 ; I'm sure you can guess why this check is bogus. + inc a + ld b, a +.innerloop2 ; Loop to get hl to the address of the chosen roam map. + dec b + jr z, .ok +.innerloop3 ; Loop to skip the current roam map, which is terminated by a 0. + ld a, [hli] + and a + jr nz, .innerloop3 + jr .innerloop2 +; Check to see if the selected map is the one the player is currently in. If so, try again. +.ok + ld a, [wMapGroup] + cp [hl] + jr nz, .done + inc hl + ld a, [wMapNumber] + cp [hl] + jr z, .loop + dec hl +; Return the map group and number in bc. +.done + ld a, [hli] + ld b, a + ld c, [hl] + ret +; 2a3f6 + +_BackUpMapIndices: ; 2a3f6 + ld a, [wRoamMons_CurrentMapNumber] + ld [wRoamMons_LastMapNumber], a + ld a, [wRoamMons_CurrentMapGroup] + ld [wRoamMons_LastMapGroup], a + ld a, [wMapNumber] + ld [wRoamMons_CurrentMapNumber], a + ld a, [wMapGroup] + ld [wRoamMons_CurrentMapGroup], a + ret +; 2a40f + + +INCLUDE "data/wild/roammon_maps.asm" + + +ValidateTempWildMonSpecies: ; 2a4a0 +; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a. + and a + jr z, .nowildmon ; = 0 + cp NUM_POKEMON + 1 ; 252 + jr nc, .nowildmon ; >= 252 + and a ; 1 <= Species <= 251 + ret + +.nowildmon + scf + ret +; 2a4ab + +; Finds a rare wild Pokemon in the route of the trainer calling, then checks if it's been Seen already. +; The trainer will then tell you about the Pokemon if you haven't seen it. +RandomUnseenWildMon: ; 2a4ab + farcall GetCallerLocation + ld d, b + ld e, c + ld hl, JohtoGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call LookUpWildmonsForMapDE + jr c, .GetGrassmon + ld hl, KantoGrassWildMons + call LookUpWildmonsForMapDE + jr nc, .done + +.GetGrassmon: + push hl + ld bc, 5 + 4 * 2 ; Location of the level of the 5th wild Pokemon in that map + add hl, bc + ld a, [wTimeOfDay] + ld bc, NUM_GRASSMON * 2 + call AddNTimes +.randloop1 + call Random + and %11 + jr z, .randloop1 + dec a + ld c, a + ld b, $0 + add hl, bc + add hl, bc +; We now have the pointer to one of the last (rarest) three wild Pokemon found in that area. + inc hl + ld c, [hl] ; Contains the species index of this rare Pokemon + pop hl + ld de, 5 + 0 * 2 + add hl, de + inc hl ; Species index of the most common Pokemon on that route + ld b, 4 +.loop2 + ld a, [hli] + cp c ; Compare this most common Pokemon with the rare one stored in c. + jr z, .done + inc hl + dec b + jr nz, .loop2 +; This Pokemon truly is rare. + push bc + dec c + ld a, c + call CheckSeenMon + pop bc + jr nz, .done +; Since we haven't seen it, have the caller tell us about it. + ld de, wStringBuffer1 + call CopyName1 + ld a, c + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, .SawRareMonText + call PrintText + xor a + ld [wScriptVar], a + ret + +.done + ld a, $1 + ld [wScriptVar], a + ret + +.SawRareMonText: + ; I just saw some rare @ in @ . I'll call you if I see another rare #MON, OK? + text_jump UnknownText_0x1bd34b + db "@" +; 0x2a51f + +RandomPhoneWildMon: ; 2a51f + farcall GetCallerLocation + ld d, b + ld e, c + ld hl, JohtoGrassWildMons + ld bc, GRASS_WILDDATA_LENGTH + call LookUpWildmonsForMapDE + jr c, .ok + ld hl, KantoGrassWildMons + call LookUpWildmonsForMapDE + +.ok + ld bc, 5 + 0 * 2 + add hl, bc + ld a, [wTimeOfDay] + inc a + ld bc, NUM_GRASSMON * 2 +.loop + dec a + jr z, .done + add hl, bc + jr .loop + +.done + call Random + and %11 + ld c, a + ld b, $0 + add hl, bc + add hl, bc + inc hl + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, wStringBuffer1 + ld de, wStringBuffer4 + ld bc, MON_NAME_LENGTH + jp CopyBytes +; 2a567 + +RandomPhoneMon: ; 2a567 +; Get a random monster owned by the trainer who's calling. + farcall GetCallerLocation + ld hl, TrainerGroups + ld a, d + dec a + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld a, BANK(TrainerGroups) + call GetFarHalfword + +.skip_trainer + dec e + jr z, .skipped +.skip + ld a, BANK(Trainers) + call GetFarByte + inc hl + cp -1 + jr nz, .skip + jr .skip_trainer +.skipped + +.skip_name + ld a, BANK(Trainers) + call GetFarByte + inc hl + cp "@" + jr nz, .skip_name + + ld a, BANK(Trainers) + call GetFarByte + inc hl + ld bc, 2 ; level, species + cp TRAINERTYPE_NORMAL + jr z, .got_mon_length + ld bc, 2 + NUM_MOVES ; level, species, moves + cp TRAINERTYPE_MOVES + jr z, .got_mon_length + ld bc, 2 + 1 ; level, species, item + cp TRAINERTYPE_ITEM + jr z, .got_mon_length + ; TRAINERTYPE_ITEM_MOVES + ld bc, 2 + 1 + NUM_MOVES ; level, species, item, moves +.got_mon_length + + ld e, 0 + push hl +.count_mon + inc e + add hl, bc + ld a, BANK(Trainers) + call GetFarByte + cp -1 + jr nz, .count_mon + pop hl + +.rand + call Random + maskbits PARTY_LENGTH + cp e + jr nc, .rand + + inc a +.get_mon + dec a + jr z, .got_mon + add hl, bc + jr .get_mon +.got_mon + + inc hl ; species + ld a, BANK(Trainers) + call GetFarByte + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, wStringBuffer1 + ld de, wStringBuffer4 + ld bc, MON_NAME_LENGTH + jp CopyBytes +; 2a5e9 + + +INCLUDE "data/wild/johto_grass.asm" +INCLUDE "data/wild/johto_water.asm" +INCLUDE "data/wild/kanto_grass.asm" +INCLUDE "data/wild/kanto_water.asm" +INCLUDE "data/wild/swarm_grass.asm" +INCLUDE "data/wild/swarm_water.asm" |