From 16ba25346c2bee8e47fc44650bfaf124c7f18f7c Mon Sep 17 00:00:00 2001 From: xCrystal Date: Thu, 28 Dec 2023 19:53:34 +0100 Subject: [PATCH] Implement Rock Smash technique (#34) --- constants/map_object_constants.asm | 5 ++ constants/script_constants.asm | 2 +- constants/technique_constants.asm | 8 +-- data/events/special_pointers.asm | 1 + engine/events/overworld.asm | 11 +++- engine/overworld/events.asm | 85 +++++++++++++++++++++++++++++- engine/overworld/map_objects.asm | 15 ++++++ engine/overworld/map_objects_2.asm | 4 +- engine/overworld/scripting.asm | 12 ++--- home/map.asm | 2 +- maps/DebugLevel2_Map1.asm | 2 + 11 files changed, 131 insertions(+), 16 deletions(-) diff --git a/constants/map_object_constants.asm b/constants/map_object_constants.asm index adce3e52d..85fd72351 100644 --- a/constants/map_object_constants.asm +++ b/constants/map_object_constants.asm @@ -124,6 +124,11 @@ DEF PLAYER_OBJECT EQU 0 DEF MAPOBJECT_PALETTE_MASK EQU %11110000 DEF MAPOBJECT_TYPE_MASK EQU %00001111 +; special MAPOBJECT_EVENT_FLAG values +DEF ALWAYS_HIDDEN EQU $ff00 ; anything between $ff00 and $fffe +DEF ALWAYS_SHOWN EQU $ffff +assert HIGH(ALWAYS_HIDDEN) == HIGH(ALWAYS_SHOWN) + ; number of entries in MapObjectsBackups. ; this sets a limit to the maximum number of different maps that can be reentered during a level. ; map groups with more than NUM_MAP_OBJECTS_BACKUPS maps are only ok if no more than diff --git a/constants/script_constants.asm b/constants/script_constants.asm index 660312528..a76c851bb 100644 --- a/constants/script_constants.asm +++ b/constants/script_constants.asm @@ -144,7 +144,7 @@ DEF NUM_BGEVENTS EQU const_value const OBJECTTYPE_ITEMBALL const OBJECTTYPE_TRAINER const OBJECTTYPE_TALKER - const OBJECTTYPE_4 + const OBJECTTYPE_ROCK const OBJECTTYPE_5 const OBJECTTYPE_6 DEF NUM_OBJECT_TYPES EQU const_value diff --git a/constants/technique_constants.asm b/constants/technique_constants.asm index 47e049a84..5a014f926 100755 --- a/constants/technique_constants.asm +++ b/constants/technique_constants.asm @@ -3,8 +3,10 @@ const TECHNIQUE_CUT_F const TECHNIQUE_FLASH_F const TECHNIQUE_SURF_F + const TECHNIQUE_ROCK_SMASH_F DEF NUM_TECHNIQUES EQU const_value -DEF TECHNIQUE_CUT EQU 1 << TECHNIQUE_CUT_F -DEF TECHNIQUE_FLASH EQU 1 << TECHNIQUE_FLASH_F -DEF TECHNIQUE_SURF EQU 1 << TECHNIQUE_SURF_F +DEF TECHNIQUE_CUT EQU 1 << TECHNIQUE_CUT_F +DEF TECHNIQUE_FLASH EQU 1 << TECHNIQUE_FLASH_F +DEF TECHNIQUE_SURF EQU 1 << TECHNIQUE_SURF_F +DEF TECHNIQUE_ROCK_SMASH EQU 1 << TECHNIQUE_ROCK_SMASH_F diff --git a/data/events/special_pointers.asm b/data/events/special_pointers.asm index a26971633..c8dfce0d0 100644 --- a/data/events/special_pointers.asm +++ b/data/events/special_pointers.asm @@ -115,6 +115,7 @@ SpecialsPointers:: add_special PrintDiploma add_special PrintGainCoins add_special PrintLoseCoins + add_special SetObjectToRemainHidden ; Crystal only add_special Reset ; bank 0 diff --git a/engine/events/overworld.asm b/engine/events/overworld.asm index 93f6f36ca..b67ea6c3d 100644 --- a/engine/events/overworld.asm +++ b/engine/events/overworld.asm @@ -1358,7 +1358,7 @@ RockSmashScript: playsound SFX_STRENGTH earthquake 84 applymovementlasttalked MovementData_RockSmash - disappear -2 + disappear LAST_TALKED callasm RockMonEncounter readmem wTempWildMonSpecies @@ -1369,6 +1369,15 @@ RockSmashScript: .done end +RockSmashAutoScript:: + special WaitSFX + playsound SFX_STRENGTH + earthquake 84 + applymovementlasttalked MovementData_RockSmash + disappear LAST_TALKED + special SetObjectToRemainHidden + end + MovementData_RockSmash: rock_smash 10 step_end diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm index a7c3d2e61..33cd42b67 100644 --- a/engine/overworld/events.asm +++ b/engine/overworld/events.asm @@ -360,6 +360,9 @@ PlayerEvents: call DisableTileEvents ; preserves f jr c, .ok + call CheckFacingTileEvent + jr c, .ok + call RunMemScript jr c, .ok @@ -637,6 +640,86 @@ SetMinTwoStepWildEncounterCooldown: ; unreferenced ld [wWildEncounterCooldown], a ret +CheckFacingTileEvent: + ldh a, [hCurBoardEvent] + cp BOARDEVENT_VIEW_MAP_MODE + jr z, .NoAction + + call .TryObjectEvent + jr c, .Action + ; fallthrough + +.NoAction: + xor a + ret + +.Action: + push af + farcall StopPlayerForEvent + pop af + scf + ret + +.TryObjectEvent: + farcall CheckFacingObject + jr c, .IsObject + xor a + ret + +.IsObject: + ldh a, [hObjectStructIndex] + call GetObjectStruct + ld hl, OBJECT_MAP_OBJECT_INDEX + add hl, bc + ld a, [hl] + ldh [hLastTalked], a + + ldh a, [hLastTalked] + call GetMapObject + ld hl, MAPOBJECT_TYPE + add hl, bc + ld a, [hl] + and MAPOBJECT_TYPE_MASK + + push bc + ld de, 3 + ld hl, .ObjectEventTypeArray + call IsInArray + pop bc + jr nc, .nope + + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.nope + xor a + ret + +.ObjectEventTypeArray: + table_width 3, .ObjectEventTypeArray + dbw OBJECTTYPE_SCRIPT, .none + dbw OBJECTTYPE_ITEMBALL, .none + dbw OBJECTTYPE_TRAINER, .none + dbw OBJECTTYPE_TALKER, .none + dbw OBJECTTYPE_ROCK, .rock_smash + dbw OBJECTTYPE_5, .none + dbw OBJECTTYPE_6, .none + assert_table_length NUM_OBJECT_TYPES + db -1 ; end + +.none + xor a + ret ; nc + +.rock_smash + ld a, BANK(RockSmashAutoScript) + ld hl, RockSmashAutoScript + call CallScript + ret ; c + RunSceneScript: ldh a, [hCurBoardEvent] cp BOARDEVENT_VIEW_MAP_MODE @@ -824,7 +907,7 @@ ObjectEventTypeArray: dbw OBJECTTYPE_TRAINER, .trainer ; the remaining four are dummy events dbw OBJECTTYPE_TALKER, .three - dbw OBJECTTYPE_4, .four + dbw OBJECTTYPE_ROCK, .four dbw OBJECTTYPE_5, .five dbw OBJECTTYPE_6, .six assert_table_length NUM_OBJECT_TYPES diff --git a/engine/overworld/map_objects.asm b/engine/overworld/map_objects.asm index 840ec7d65..fd7d119d1 100644 --- a/engine/overworld/map_objects.asm +++ b/engine/overworld/map_objects.asm @@ -2750,6 +2750,21 @@ ResetObject: db SPRITEMOVEDATA_STANDING_LEFT db SPRITEMOVEDATA_STANDING_RIGHT +; Used to make the last talked object remain hidden. +; This is done by setting its event flag to special value ALWAYS_HIDDEN. +; Otherwise when data is read from wMapObjectsBackups after entering the map, +; it would appear by default even if it had been made disappear. +SetObjectToRemainHidden: + ldh a, [hLastTalked] + call GetMapObject + ld hl, MAPOBJECT_EVENT_FLAG + add hl, bc + ld de, ALWAYS_HIDDEN + ld [hl], e + inc hl + ld [hl], d + ret + _UpdateActiveSpritesAfterOffset:: ld a, [wVramState] bit 0, a diff --git a/engine/overworld/map_objects_2.asm b/engine/overworld/map_objects_2.asm index d89d95fc0..b2db408bb 100644 --- a/engine/overworld/map_objects_2.asm +++ b/engine/overworld/map_objects_2.asm @@ -41,10 +41,10 @@ CheckObjectFlag: ld e, a ld a, [hl] ld d, a - cp -1 + cp HIGH(ALWAYS_SHOWN) ; HIGH(ALWAYS_HIDDEN) jr nz, .check ld a, e - cp -1 + cp LOW(ALWAYS_SHOWN) jr z, .unmasked jr .masked .check diff --git a/engine/overworld/scripting.asm b/engine/overworld/scripting.asm index 72250e964..0d8f595d2 100644 --- a/engine/overworld/scripting.asm +++ b/engine/overworld/scripting.asm @@ -1007,16 +1007,14 @@ ApplyEventActionAppearDisappear: ld e, [hl] inc hl ld d, [hl] - ld a, -1 - cp e - jr nz, .okay + ld a, HIGH(ALWAYS_SHOWN) ; HIGH(ALWAYS_HIDDEN) cp d - jr nz, .okay - xor a - ret -.okay + jr z, .not_a_flag call EventFlagAction ret +.not_a_flag + xor a + ret Script_follow: call GetScriptByte diff --git a/home/map.asm b/home/map.asm index 4d2cefb84..c8fa358b2 100644 --- a/home/map.asm +++ b/home/map.asm @@ -1110,7 +1110,7 @@ LoadMapStatus:: ret CallScript:: -; Call a script at a:hl. +; Call a script at a:hl and return carry. ld [wScriptBank], a ld a, l diff --git a/maps/DebugLevel2_Map1.asm b/maps/DebugLevel2_Map1.asm index 4bb0234d3..3bb82027f 100755 --- a/maps/DebugLevel2_Map1.asm +++ b/maps/DebugLevel2_Map1.asm @@ -26,6 +26,8 @@ DebugLevel2_Map1_MapEvents: def_bg_events def_object_events + object_event 6, 13, SPRITE_ROCK, SPRITEMOVEDATA_SMASHABLE_ROCK, 0, 0, -1, -1, 0, OBJECTTYPE_ROCK, 0, ObjectEvent, -1 + object_event 5, 12, SPRITE_ROCK, SPRITEMOVEDATA_SMASHABLE_ROCK, 0, 0, -1, -1, 0, OBJECTTYPE_ROCK, 0, ObjectEvent, -1 DebugLevel2_Map1_MapSpaces: space 6, 16, $0, 1 ; 0