From 88b6810a18984fa26966958e0a70e52a8e0323bd Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 28 Nov 2023 13:59:36 +0100 Subject: [PATCH] Implement talker events [commit 1] (#30) --- constants/script_constants.asm | 4 +- constants/trainer_data_constants.asm | 10 ++++ data/sprites/emotes.asm | 1 + engine/events/trainer_scripts.asm | 11 ++++- engine/overworld/events.asm | 14 ++++-- engine/overworld/player_object.asm | 4 +- engine/overworld/scripting.asm | 4 +- gfx/emotes.asm | 1 + gfx/emotes/talk.png | Bin 0 -> 250 bytes home/trainers.asm | 70 +++++++++++++++++++++------ macros/scripts/maps.asm | 12 ++++- maps/DebugLevel5_Map1.asm | 10 ++++ ram/wram.asm | 22 +++++++-- 13 files changed, 134 insertions(+), 29 deletions(-) create mode 100755 gfx/emotes/talk.png diff --git a/constants/script_constants.asm b/constants/script_constants.asm index 227dd8b93..78129593e 100644 --- a/constants/script_constants.asm +++ b/constants/script_constants.asm @@ -89,6 +89,7 @@ DEF RETVAR_EXECUTE EQU 2 << 6 const PLAYEREVENT_WHITEOUT const PLAYEREVENT_HATCH const PLAYEREVENT_JOYCHANGEFACING + const PLAYEREVENT_SEENBYTALKER DEF NUM_PLAYER_EVENTS EQU const_value ; PlayerMovementPointers indexes (see engine/overworld/events.asm) @@ -137,7 +138,7 @@ DEF NUM_BGEVENTS EQU const_value const OBJECTTYPE_SCRIPT const OBJECTTYPE_ITEMBALL const OBJECTTYPE_TRAINER - const OBJECTTYPE_3 + const OBJECTTYPE_TALKER const OBJECTTYPE_4 const OBJECTTYPE_5 const OBJECTTYPE_6 @@ -188,6 +189,7 @@ DEF NUM_FLOORS EQU const_value ; Emotes indexes (see data/sprites/emotes.asm) const_def const EMOTE_SHOCK + const EMOTE_TALK const EMOTE_QUESTION const EMOTE_HAPPY const EMOTE_SAD diff --git a/constants/trainer_data_constants.asm b/constants/trainer_data_constants.asm index 91a3bc81b..dda4fd451 100644 --- a/constants/trainer_data_constants.asm +++ b/constants/trainer_data_constants.asm @@ -45,3 +45,13 @@ DEF CONTEXT_USE EQU 1 << CONTEXT_USE_F const TRAINERTYPE_MOVES const TRAINERTYPE_ITEM const TRAINERTYPE_ITEM_MOVES + +; talker events (from talker macro and high bit of wTempTalkerType) +DEF TALKER_OPTIONAL EQU %0 +DEF TALKER_MANDATORY EQU %1 + +; talker types (from talker macro and low seven bits of wTempTalkerType) + const_def + const TALKERTYPE_TEXT + const TALKERTYPE_MODAL_TEXT + const TALKERTYPE_SCRIPT diff --git a/data/sprites/emotes.asm b/data/sprites/emotes.asm index ef4485bda..3a10869cc 100644 --- a/data/sprites/emotes.asm +++ b/data/sprites/emotes.asm @@ -9,6 +9,7 @@ Emotes: ; entries correspond to EMOTE_* constants table_width EMOTE_LENGTH, Emotes emote ShockEmote, 4, $f8 + emote TalkEmote, 4, $f8 emote QuestionEmote, 4, $f8 emote HappyEmote, 4, $f8 emote SadEmote, 4, $f8 diff --git a/engine/events/trainer_scripts.asm b/engine/events/trainer_scripts.asm index 8261065e8..030130fc5 100644 --- a/engine/events/trainer_scripts.asm +++ b/engine/events/trainer_scripts.asm @@ -11,7 +11,7 @@ SeenByTrainerScript:: waitsfx ; wait for any pending space-related sfx encountermusic showemote EMOTE_SHOCK, LAST_TALKED, 30 - callasm TrainerWalkToPlayer + callasm TrainerOrTalkerWalkToPlayer applymovementlasttalked wMovementBuffer writeobjectxy LAST_TALKED faceobject PLAYER, LAST_TALKED @@ -30,3 +30,12 @@ StartBattleWithMapTrainerScript: AlreadyBeatenTrainerScript: scripttalkafter + +SeenByTalkerScript:: + waitsfx ; wait for any pending space-related sfx + showemote EMOTE_TALK, LAST_TALKED, 20 + callasm TrainerOrTalkerWalkToPlayer + applymovementlasttalked wMovementBuffer + writeobjectxy LAST_TALKED + faceobject PLAYER, LAST_TALKED + end diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm index 628ed4ca4..b047f326c 100644 --- a/engine/overworld/events.asm +++ b/engine/overworld/events.asm @@ -285,7 +285,7 @@ PlayerEvents: call DisableSpaceEffects ; doesn't alter f jr c, .ok - call CheckTrainerEvent + call CheckTrainerOrTalkerEvent jr c, .ok call CheckTileEvent @@ -451,15 +451,20 @@ CheckBoardEvent: dw UnionSpaceScript ; COLL_UNION_SPACE assert_table_length NUM_COLL_SPACES -CheckTrainerEvent: +CheckTrainerOrTalkerEvent: ldh a, [hCurBoardEvent] cp BOARDEVENT_VIEW_MAP_MODE ret z - call CheckTrainerBattle + call CheckTrainerBattleOrTalkerPrompt jr nc, .nope + ld a, [wTrainerOrTalkerIsTalker] + and a ; cp FALSE ld a, PLAYEREVENT_SEENBYTRAINER + jr z, .done + ld a, PLAYEREVENT_SEENBYTALKER +.done scf ret @@ -748,7 +753,7 @@ ObjectEventTypeArray: dbw OBJECTTYPE_ITEMBALL, .itemball dbw OBJECTTYPE_TRAINER, .trainer ; the remaining four are dummy events - dbw OBJECTTYPE_3, .three + dbw OBJECTTYPE_TALKER, .three dbw OBJECTTYPE_4, .four dbw OBJECTTYPE_5, .five dbw OBJECTTYPE_6, .six @@ -1158,6 +1163,7 @@ PlayerEventScriptPointers: dba OverworldWhiteoutScript ; PLAYEREVENT_WHITEOUT dba HatchEggScript ; PLAYEREVENT_HATCH dba ChangeDirectionScript ; PLAYEREVENT_JOYCHANGEFACING + dba SeenByTalkerScript ; PLAYEREVENT_SEENBYTALKER dba InvalidEventScript ; (NUM_PLAYER_EVENTS) assert_table_length NUM_PLAYER_EVENTS + 1 diff --git a/engine/overworld/player_object.asm b/engine/overworld/player_object.asm index 698655e79..d7b9c16d5 100644 --- a/engine/overworld/player_object.asm +++ b/engine/overworld/player_object.asm @@ -514,12 +514,12 @@ CopyTempObjectToObjectStruct: ld [hl], a ret -TrainerWalkToPlayer: +TrainerOrTalkerWalkToPlayer: ldh a, [hLastTalked] call InitMovementBuffer ld a, movement_step_sleep call AppendToMovementBuffer - ld a, [wSeenTrainerDistance] + ld a, [wSeenTrainerOrTalkerDistance] dec a jr z, .TerminateStep ldh a, [hLastTalked] diff --git a/engine/overworld/scripting.asm b/engine/overworld/scripting.asm index e7a07fc09..bada8759e 100644 --- a/engine/overworld/scripting.asm +++ b/engine/overworld/scripting.asm @@ -671,7 +671,7 @@ Script_trainertext: ld a, [hli] ld h, [hl] ld l, a - ld a, [wSeenTrainerBank] + ld a, [wSeenTrainerOrTalkerBank] ld b, a call MapTextbox ret @@ -681,7 +681,7 @@ Script_scripttalkafter: ld a, [hli] ld h, [hl] ld l, a - ld a, [wSeenTrainerBank] + ld a, [wSeenTrainerOrTalkerBank] ld b, a jp ScriptJump diff --git a/gfx/emotes.asm b/gfx/emotes.asm index 1de06de2c..1e83ec27a 100644 --- a/gfx/emotes.asm +++ b/gfx/emotes.asm @@ -1,4 +1,5 @@ ShockEmote: INCBIN "gfx/emotes/shock.2bpp" +TalkEmote: INCBIN "gfx/emotes/talk.2bpp" QuestionEmote: INCBIN "gfx/emotes/question.2bpp" HappyEmote: INCBIN "gfx/emotes/happy.2bpp" SadEmote: INCBIN "gfx/emotes/sad.2bpp" diff --git a/gfx/emotes/talk.png b/gfx/emotes/talk.png new file mode 100755 index 0000000000000000000000000000000000000000..3f18ad7579efeebb70fc4aedd85f32cb60e14ee5 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBV85q}V~B7RL+y=IPHk1)d}r4KkM2{C{1Jhw1@GlgHF*auj{obKiYS1o2M8y(@rfk st^I|a8h>c2^}LyUf^%p0@w!;&oY^tqN(S2rpwk#UUHx3vIVCg!08>y}0{{R3 literal 0 HcmV?d00001 diff --git a/home/trainers.asm b/home/trainers.asm index ef55b0a18..bbfe25ed9 100644 --- a/home/trainers.asm +++ b/home/trainers.asm @@ -1,17 +1,17 @@ -CheckTrainerBattle:: +CheckTrainerBattleOrTalkerPrompt:: ldh a, [hROMBank] push af call SwitchToMapScriptsBank - call _CheckTrainerBattle + call _CheckTrainerBattleOrTalkerPrompt pop bc ld a, b rst Bankswitch ret -_CheckTrainerBattle:: -; Check if any trainer on the map sees the player and wants to battle. +_CheckTrainerBattleOrTalkerPrompt:: +; Check if any trainer or talker on the map sees the player and wants to battle or talk. ; Skip the player object. ld a, 1 @@ -30,14 +30,25 @@ _CheckTrainerBattle:: and a jr z, .next -; Is a trainer +; Is a trainer or a talker ld hl, MAPOBJECT_TYPE add hl, de ld a, [hl] and MAPOBJECT_TYPE_MASK cp OBJECTTYPE_TRAINER + jr z, .is_trainer + cp OBJECTTYPE_TALKER jr nz, .next +; also set wTrainerOrTalkerIsTalker accordingly (flag is only relevant if there's actually an event) +;.is_talker + ld a, TRUE + ld [wTrainerOrTalkerIsTalker], a + jr .go +.is_trainer + xor a ; FALSE + ld [wTrainerOrTalkerIsTalker], a +.go ; Is visible on the map ld hl, MAPOBJECT_OBJECT_STRUCT_ID add hl, de @@ -57,7 +68,38 @@ _CheckTrainerBattle:: cp b jr c, .next -; And hasn't already been beaten + ld a, [wTrainerOrTalkerIsTalker] + and a ; TRUE? + jr z, .trainer_battle + +;.talker_prompt + pop de + pop af + ldh [hLastTalked], a + ld a, b + ld [wSeenTrainerOrTalkerDistance], a + ld a, c + ld [wSeenTrainerOrTalkerDirection], a + call GetMapScriptsBank + ld [wSeenTrainerOrTalkerBank], a + + ldh a, [hLastTalked] + call GetMapObject + + ld hl, MAPOBJECT_SCRIPT_POINTER + add hl, bc + ld a, [wSeenTrainerOrTalkerBank] + call GetFarWord + ld de, wTempTalker + ld bc, wTempTalkerEnd - wTempTalker + ld a, [wSeenTrainerOrTalkerBank] + call FarCopyBytes + + scf + ret + +.trainer_battle +; And hasn't already been beaten if it's a trainer push bc push de ld hl, MAPOBJECT_SCRIPT_POINTER @@ -86,7 +128,7 @@ _CheckTrainerBattle:: pop af inc a cp NUM_OBJECTS - jr nz, .loop + jp nz, .loop xor a ret @@ -95,31 +137,31 @@ _CheckTrainerBattle:: pop af ldh [hLastTalked], a ld a, b - ld [wSeenTrainerDistance], a + ld [wSeenTrainerOrTalkerDistance], a ld a, c - ld [wSeenTrainerDirection], a + ld [wSeenTrainerOrTalkerDirection], a jr LoadTrainer_continue TalkToTrainer:: ld a, 1 - ld [wSeenTrainerDistance], a + ld [wSeenTrainerOrTalkerDistance], a ld a, -1 - ld [wSeenTrainerDirection], a + ld [wSeenTrainerOrTalkerDirection], a LoadTrainer_continue:: call GetMapScriptsBank - ld [wSeenTrainerBank], a + ld [wSeenTrainerOrTalkerBank], a ldh a, [hLastTalked] call GetMapObject ld hl, MAPOBJECT_SCRIPT_POINTER add hl, bc - ld a, [wSeenTrainerBank] + ld a, [wSeenTrainerOrTalkerBank] call GetFarWord ld de, wTempTrainer ld bc, wTempTrainerEnd - wTempTrainer - ld a, [wSeenTrainerBank] + ld a, [wSeenTrainerOrTalkerBank] call FarCopyBytes xor a ld [wRunningTrainerBattleScript], a diff --git a/macros/scripts/maps.asm b/macros/scripts/maps.asm index ecaa8349f..2438e661a 100644 --- a/macros/scripts/maps.asm +++ b/macros/scripts/maps.asm @@ -232,7 +232,7 @@ ENDM MACRO trainer ;\1: trainer group ;\2: trainer id -;\3: flag: an EVENT_BEAT_* constant +;\3: flag: an EVENT_* constant ;\4: seen text ;\5: win text ;\6: loss text @@ -242,6 +242,16 @@ MACRO trainer dw \4, \5, \6, \7 ENDM +MACRO talker +;\1: flag: an EVENT_* constant +;\2: OPTIONAL or MANDATORY +;\3: talker type: TEXT, MODAL_TEXT, SCRIPT +;\4: pointer to talker data + dw \1 + db \2 | \3 + dw \4 +ENDM + MACRO itemball ;\1: item: from constants/item_constants.asm ;\2: quantity: default 1 diff --git a/maps/DebugLevel5_Map1.asm b/maps/DebugLevel5_Map1.asm index 04c86bbe1..f50a1ee47 100755 --- a/maps/DebugLevel5_Map1.asm +++ b/maps/DebugLevel5_Map1.asm @@ -28,6 +28,16 @@ DebugLevel5_Map1_MapEvents: .DebugLevel5_Map1TrainerYoungsterMikey2: trainer YOUNGSTER, MIKEY, EVENT_LEVEL_SCOPED_2, .YoungsterMikeySeenText, .YoungsterMikeyBeatenText, 0, .Script +; talker EVENT_STEP_SCOPED_*, OPTIONAL/MANDATORY | TEXT/MODAL_TEXT/SCRIPT, .Data +; .Data: ; Text +; db .Text +; .Data: ; Modal text +; dw EVENT_*, .Text1 +; dw EVENT_*, .Text2 +; dw DEFAULT_TEXT, .DefaultText +; .Data: ; Script +; end + .Script: endifjustbattled opentext diff --git a/ram/wram.asm b/ram/wram.asm index 002fd26c8..619423540 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1550,10 +1550,15 @@ SECTION UNION "Miscellaneous WRAM 1", WRAMX ds 60 UNION +; trainer and talker data +wTrainerOrTalkerIsTalker:: db ; TRUE means talker; FALSE means trainer +wSeenTrainerOrTalkerBank:: db +wSeenTrainerOrTalkerDistance:: db +wSeenTrainerOrTalkerDirection:: db + +NEXTU ; trainer data -wSeenTrainerBank:: db -wSeenTrainerDistance:: db -wSeenTrainerDirection:: db + ds 4 wTempTrainer:: wTempTrainerEventFlag:: dw wTempTrainerClass:: db @@ -1565,6 +1570,15 @@ wScriptAfterPointer:: dw wRunningTrainerBattleScript:: db wTempTrainerEnd:: +NEXTU +; talker data + ds 4 +wTempTalker:: +wTempTalkerEventFlag:: dw +wTempTalkerType:: db +wTempTalkerDataPointer:: dw +wTempTalkerEnd:: + NEXTU ; menu items list wMenuItemsList:: ds 16 @@ -1642,7 +1656,7 @@ wFacingDirection:: db wWalkingX:: db wWalkingY:: db wWalkingTile:: db - ds 6 + ds 7 wPlayerTurningDirection:: db NEXTU