From 303deca959e6b1267e3c45c89ff64fdac7fce53e Mon Sep 17 00:00:00 2001 From: xCrystal Date: Fri, 29 Dec 2023 13:34:37 +0100 Subject: [PATCH] Implement Cut technique, making cut trees use objects (#34) --- charmap.asm | 1 + constants/map_object_constants.asm | 1 + constants/script_constants.asm | 2 +- constants/sprite_constants.asm | 1 + data/maps/outdoor_sprites.asm | 6 +- data/sprites/map_objects.asm | 8 ++ data/sprites/sprites.asm | 1 + engine/board/menu.asm | 1 + engine/events/field_moves.asm | 134 +++++++++++++++++++++++++++++ engine/events/overworld.asm | 14 ++- engine/overworld/events.asm | 22 +++-- gfx/sprites.asm | 1 + gfx/sprites/cut_tree.png | Bin 0 -> 293 bytes maps/DebugLevel5_Map1.asm | 2 + ram/wram.asm | 1 + 15 files changed, 186 insertions(+), 9 deletions(-) create mode 100755 gfx/sprites/cut_tree.png diff --git a/charmap.asm b/charmap.asm index 874edea76..7cbf2bc49 100644 --- a/charmap.asm +++ b/charmap.asm @@ -198,6 +198,7 @@ DEF SECONDARY_SPRITES_FIRST_TILE EQU $20 DEF BOARD_MENU_OAM_FIRST_TILE EQU SECONDARY_SPRITES_FIRST_TILE DEF DIE_ROLL_OAM_FIRST_TILE EQU BOARD_MENU_OAM_FIRST_TILE + 45 ; max(BOARD_MENU_ITEM_SIZE * NUM_BOARD_MENU_ITEMS, DIE_SIZE * 10) DEF DIE_NUMBERS_OAM_FIRST_TILE EQU BOARD_MENU_OAM_FIRST_TILE +DEF CUT_TREE_OAM_FIRST_TILE EQU DIE_NUMBERS_OAM_FIRST_TILE + 40 ; DIE_NUMBER_SIZE * 10 ; Branch space DEF BRANCH_ARROWS_OAM_FIRST_TILE EQU DIE_NUMBERS_OAM_FIRST_TILE + 40 ; DIE_NUMBER_SIZE * 10 diff --git a/constants/map_object_constants.asm b/constants/map_object_constants.asm index 85fd72351..cf49e8dda 100644 --- a/constants/map_object_constants.asm +++ b/constants/map_object_constants.asm @@ -187,6 +187,7 @@ DEF MAPOBJECT_SCREEN_HEIGHT EQU (SCREEN_HEIGHT / 2) + 2 const SPRITEMOVEDATA_BOULDERDUST ; 22 const SPRITEMOVEDATA_GRASS ; 23 const SPRITEMOVEDATA_SWIM_WANDER ; 24 + const SPRITEMOVEDATA_CUTTABLE_TREE ; 25 DEF NUM_SPRITEMOVEDATA EQU const_value ; StepFunction_FromMovement.Pointers indexes (see engine/overworld/map_objects.asm) diff --git a/constants/script_constants.asm b/constants/script_constants.asm index a76c851bb..7827d1475 100644 --- a/constants/script_constants.asm +++ b/constants/script_constants.asm @@ -145,7 +145,7 @@ DEF NUM_BGEVENTS EQU const_value const OBJECTTYPE_TRAINER const OBJECTTYPE_TALKER const OBJECTTYPE_ROCK - const OBJECTTYPE_5 + const OBJECTTYPE_TREE const OBJECTTYPE_6 DEF NUM_OBJECT_TYPES EQU const_value diff --git a/constants/sprite_constants.asm b/constants/sprite_constants.asm index 11812856a..6ffb6322b 100644 --- a/constants/sprite_constants.asm +++ b/constants/sprite_constants.asm @@ -104,6 +104,7 @@ const SPRITE_ENTEI ; 64 const SPRITE_RAIKOU ; 65 const SPRITE_STANDING_YOUNGSTER ; 66 + const SPRITE_CUT_TREE ; 67 DEF NUM_OVERWORLD_SPRITES EQU const_value - 1 ; SpriteMons indexes (see data/sprites/sprite_mons.asm) diff --git a/data/maps/outdoor_sprites.asm b/data/maps/outdoor_sprites.asm index 0f6a89830..5cb18e674 100644 --- a/data/maps/outdoor_sprites.asm +++ b/data/maps/outdoor_sprites.asm @@ -29,7 +29,8 @@ Level1GroupSprites: db SPRITE_POKE_BALL db SPRITE_FRUIT_TREE db SPRITE_ROCK - ; max 3 of 10 still sprites + db SPRITE_CUT_TREE + ; max 4 of 10 still sprites db 0 ; end ; Level2GroupSprites: @@ -54,6 +55,7 @@ DebugLevel5GroupSprites: db SPRITE_POKE_BALL db SPRITE_FRUIT_TREE db SPRITE_ROCK - ; max 3 of 10 still sprites + db SPRITE_CUT_TREE + ; max 4 of 10 still sprites db 0 ; end endc diff --git a/data/sprites/map_objects.asm b/data/sprites/map_objects.asm index 5bc0e0eb6..d111bf90d 100644 --- a/data/sprites/map_objects.asm +++ b/data/sprites/map_objects.asm @@ -298,6 +298,14 @@ SpriteMovementData:: db 0 ; flags2 db SWIMMING ; palette flags +; SPRITEMOVEDATA_CUTTABLE_TREE + db SPRITEMOVEFN_STANDING ; movement function + db DOWN ; facing + db OBJECT_ACTION_STAND ; action + db WONT_DELETE | FIXED_FACING | SLIDING | MOVE_ANYWHERE ; flags1 + db 0 ; flags2 + db 0 ; palette flags + assert_table_length NUM_SPRITEMOVEDATA ; unused diff --git a/data/sprites/sprites.asm b/data/sprites/sprites.asm index 0d02109b9..7cac6b2db 100644 --- a/data/sprites/sprites.asm +++ b/data/sprites/sprites.asm @@ -109,4 +109,5 @@ OverworldSprites: overworld_sprite EnteiSpriteGFX, 4, STILL_SPRITE, PAL_OW_RED overworld_sprite RaikouSpriteGFX, 4, STILL_SPRITE, PAL_OW_RED overworld_sprite StandingYoungsterSpriteGFX, 12, STANDING_SPRITE, PAL_OW_BLUE + overworld_sprite CutTreeSpriteGFX, 4, STILL_SPRITE, PAL_OW_TREE assert_table_length NUM_OVERWORLD_SPRITES diff --git a/engine/board/menu.asm b/engine/board/menu.asm index fe3b93a3f..d89b241a5 100755 --- a/engine/board/menu.asm +++ b/engine/board/menu.asm @@ -409,6 +409,7 @@ BoardMenu_BreakDieAnimation: .done ld hl, wVramState res 2, [hl] + farcall ClearSpriteAnims ld hl, wDisplaySecondarySprites set SECONDARYSPRITES_SPACES_LEFT_F, [hl] ld a, [wDieRoll] diff --git a/engine/events/field_moves.asm b/engine/events/field_moves.asm index c636da9c1..825804b6d 100644 --- a/engine/events/field_moves.asm +++ b/engine/events/field_moves.asm @@ -109,6 +109,140 @@ TreeRelativeLocationTable: dwcoord 8 - 2, 8 ; DOWN dwcoord 8 + 2, 8 ; UP +OWCutAnimation_WithCutTreeAsObject: + ld a, $a0 + ld [wCutTreeOAMAddr], a + ld de, CutTreeGFX + ld hl, vTiles0 tile CUT_TREE_OAM_FIRST_TILE + lb bc, BANK(CutTreeGFX), 4 + call Request2bpp + call WaitSFX + ld de, SFX_PLACE_PUZZLE_PIECE_DOWN + call PlaySFX + xor a + ld [wJumptableIndex], a +.loop + ld a, [wJumptableIndex] + bit 7, a + jr nz, .finish + call .FindCutTreeOAMAddr + ld a, 36 * SPRITEOAMSTRUCT_LENGTH + jr nc, .got_oam_addr + ld a, l +.got_oam_addr + ld [wCurSpriteOAMAddr], a + ld [wCutTreeOAMAddr], a + ld hl, wVramState + set 2, [hl] ; do not clear wShadowOAM during DoNextFrameForAllSprites + callfar DoNextFrameForAllSprites + ld hl, wVramState + res 2, [hl] + call .OWCutJumptable + call DelayFrame + jr .loop + +.finish + farcall ClearSpriteAnims + ret + +; find the sprite in wShadowOAM with coordinates that match exactly the tile facing the player. +; if found, return in l its location within wShadowOAM and return carry. +; if it has already been found during this animation and thus copied into wCutTreeOAMAddr, return that value instead. +; otherwise return nc. +.FindCutTreeOAMAddr: + ld a, [wCutTreeOAMAddr] + cp $a0 + ld l, a + scf + ret nz ; c + call .GetPixelFacing + ; .GetPixelFacing returns the coordinates of the bottom right object. + ; convert them to the top left object. + ld a, d + sub TILE_WIDTH + ld d, a + ld a, e + sub TILE_WIDTH + ld e, a + ld hl, wShadowOAM + ld bc, 4 * SPRITEOAMSTRUCT_LENGTH +.sprite_loop + ld a, [hl] + cp d + jr nz, .next_sprite + inc hl + ld a, [hld] + cp e + scf + ret z ; c +.next_sprite + add hl, bc + ld a, l + cp LOW(wShadowOAMEnd) + ret nc + jr .sprite_loop + +.OWCutJumptable: + jumptable .dw, wJumptableIndex + +.dw + dw .Cut_SpawnAnimateTree + dw .Cut_StartWaiting + dw .Cut_WaitAnimSFX + +.Cut_SpawnAnimateTree: + call .GetPixelFacing + ld a, SPRITE_ANIM_OBJ_CUT_TREE + call InitSpriteAnimStruct + ld hl, SPRITEANIMSTRUCT_TILE_ID + add hl, bc + ld [hl], CUT_TREE_OAM_FIRST_TILE + ld a, 32 + ld [wFrameCounter], a +; .Cut_StartWaiting + ld hl, wJumptableIndex + inc [hl] + ret + +.GetPixelFacing: + ld a, [wPlayerDirection] + and %00001100 + srl a + ld e, a + ld d, 0 + ld hl, .Coords + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ret + +.Coords: + dbpixel 10, 12, 0, 4 + dbpixel 10, 8, 0, 4 + dbpixel 8, 10, 0, 4 + dbpixel 12, 10, 0, 4 + +.Cut_StartWaiting: + ld a, 1 + ldh [hBGMapMode], a +; .Cut_WaitAnimSFX + ld hl, wJumptableIndex + inc [hl] + +.Cut_WaitAnimSFX: + ld hl, wFrameCounter + ld a, [hl] + and a + jr z, .finished + dec [hl] + ret + +.finished + ld hl, wJumptableIndex + set 7, [hl] + ret + OWCutAnimation: ; Animation index in e ; 0: Split tree in half diff --git a/engine/events/overworld.asm b/engine/events/overworld.asm index b67ea6c3d..7af698b57 100644 --- a/engine/events/overworld.asm +++ b/engine/events/overworld.asm @@ -233,6 +233,18 @@ CutDownTreeOrGrass: call LoadStandardFont ret +Script_CutAuto:: + refreshscreen + callasm CutDownTreeObject + disappear LAST_TALKED + special SetObjectToRemainHidden + reloadmappart + end + +CutDownTreeObject: + farcall OWCutAnimation_WithCutTreeAsObject + ret + CheckOverworldTileArrays: ; Input: c contains the tile you're facing ; Output: Replacement tile in b and effect on wild encounters in c, plus carry set. @@ -1370,7 +1382,7 @@ RockSmashScript: end RockSmashAutoScript:: - special WaitSFX + waitsfx playsound SFX_STRENGTH earthquake 84 applymovementlasttalked MovementData_RockSmash diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm index 33cd42b67..e25f6e20b 100644 --- a/engine/overworld/events.asm +++ b/engine/overworld/events.asm @@ -647,6 +647,8 @@ CheckFacingTileEvent: call .TryObjectEvent jr c, .Action + call .TryTileCollisionEvent + jr c, .Action ; fallthrough .NoAction: @@ -704,8 +706,8 @@ CheckFacingTileEvent: dbw OBJECTTYPE_ITEMBALL, .none dbw OBJECTTYPE_TRAINER, .none dbw OBJECTTYPE_TALKER, .none - dbw OBJECTTYPE_ROCK, .rock_smash - dbw OBJECTTYPE_5, .none + dbw OBJECTTYPE_ROCK, .rock + dbw OBJECTTYPE_TREE, .tree dbw OBJECTTYPE_6, .none assert_table_length NUM_OBJECT_TYPES db -1 ; end @@ -714,12 +716,22 @@ CheckFacingTileEvent: xor a ret ; nc -.rock_smash +.rock ld a, BANK(RockSmashAutoScript) ld hl, RockSmashAutoScript call CallScript ret ; c +.tree + ld a, BANK(Script_CutAuto) + ld hl, Script_CutAuto + call CallScript + ret ; c + +.TryTileCollisionEvent: + xor a + ret ; nc + RunSceneScript: ldh a, [hCurBoardEvent] cp BOARDEVENT_VIEW_MAP_MODE @@ -908,7 +920,7 @@ ObjectEventTypeArray: ; the remaining four are dummy events dbw OBJECTTYPE_TALKER, .three dbw OBJECTTYPE_ROCK, .four - dbw OBJECTTYPE_5, .five + dbw OBJECTTYPE_TREE, .five dbw OBJECTTYPE_6, .six assert_table_length NUM_OBJECT_TYPES db -1 ; end @@ -1456,7 +1468,7 @@ TryTileCollisionEvent:: .done call PlayClickSFX - ld a, $ff + ld a, PLAYEREVENT_MAPSCRIPT scf ret diff --git a/gfx/sprites.asm b/gfx/sprites.asm index 212c0b259..8d4357423 100644 --- a/gfx/sprites.asm +++ b/gfx/sprites.asm @@ -106,3 +106,4 @@ SuicuneSpriteGFX:: INCBIN "gfx/sprites/suicune.2bpp" EnteiSpriteGFX:: INCBIN "gfx/sprites/entei.2bpp" RaikouSpriteGFX:: INCBIN "gfx/sprites/raikou.2bpp" StandingYoungsterSpriteGFX:: INCBIN "gfx/sprites/standing_youngster.2bpp" +CutTreeSpriteGFX:: INCBIN "gfx/sprites/cut_tree.2bpp" diff --git a/gfx/sprites/cut_tree.png b/gfx/sprites/cut_tree.png new file mode 100755 index 0000000000000000000000000000000000000000..244a0d87501887e9771bb5bce587f11c895c83b6 GIT binary patch literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85o30K$!7fntTONaF?fxV~B-+?_@^476l%bhyPaex42i`ZFAH} zn$w~)rA)W$r_m+$qH~@rHU7-nw`kF03$@lfhk`pIB3GkgkEUGeD~K!z>iD=~)5Sw6 zZvI<-EmdAv^KHAVL6QvX?DZ!fYb^cpbI1Cf(k9cF&e+Oh((kt64)eJj&vh5h%S60u zoD{N#>4vEFs|TFhGHQ=6pZ&wj_|=C`E%W-c%=X#L;5l|=V+8Z#j7@JFp6oa#Ay@zW nvrX(zp|BTON7tEa{$&)LTY2l(bUQPkFBm*s{an^LB{Ts5M&oyy literal 0 HcmV?d00001 diff --git a/maps/DebugLevel5_Map1.asm b/maps/DebugLevel5_Map1.asm index e7f3fc043..891cb3b54 100755 --- a/maps/DebugLevel5_Map1.asm +++ b/maps/DebugLevel5_Map1.asm @@ -21,6 +21,8 @@ DebugLevel5_Map1_MapEvents: def_object_events object_event 10, 2, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_BLUE, OBJECTTYPE_TRAINER, 2, .DebugLevel5_Map1TrainerYoungsterMikey1, -1 object_event 9, 2, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_BLUE, OBJECTTYPE_TALKER, 2, .DebugLevel5_Map1Talker1, -1 + object_event 6, 1, SPRITE_CUT_TREE, SPRITEMOVEDATA_CUTTABLE_TREE, 0, 0, -1, -1, PAL_NPC_TREE, OBJECTTYPE_TREE, 0, ObjectEvent, -1 + object_event 9, 4, SPRITE_CUT_TREE, SPRITEMOVEDATA_CUTTABLE_TREE, 0, 0, -1, -1, PAL_NPC_TREE, OBJECTTYPE_TREE, 0, ObjectEvent, -1 .DebugLevel5_Map1TrainerYoungsterMikey1: trainer YOUNGSTER, MIKEY, EVENT_LEVEL_SCOPED_1, .YoungsterMikeySeenText, .YoungsterMikeyBeatenText, 0, .Script diff --git a/ram/wram.asm b/ram/wram.asm index c9b3ce1c3..a0ef3e426 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -205,6 +205,7 @@ wSpriteAnimationStructsEnd:: wSpriteAnimCount:: db wCurSpriteOAMAddr:: db +wCutTreeOAMAddr:: wCurIcon:: db wCurIconTile:: db