Implement talker events [commit 2] (#30)

This commit is contained in:
xCrystal 2023-11-28 18:02:00 +01:00
parent 88b6810a18
commit 933fca3b4b
12 changed files with 111 additions and 44 deletions

View File

@ -2,6 +2,7 @@
const_def
;; The first eight flags are reset upon reloading the map
const EVENT_TEMPORARY_UNTIL_MAP_RELOAD_1
const EVENT_TEMPORARY_UNTIL_MAP_RELOAD_2
@ -17,6 +18,7 @@ const_value = const_value + 8 - (const_value % 8)
endc
EVENT_TEMPORARY_UNTIL_MAP_RELOAD_FLAGS_END EQU const_value
;; The next flags are reset upon entering a new level (for e.g. trainers)
EVENT_LEVEL_SCOPED_FLAGS_START EQU EVENT_TEMPORARY_UNTIL_MAP_RELOAD_FLAGS_END
@ -46,8 +48,39 @@ const_value = const_value + 8 - (const_value % 8)
endc
EVENT_LEVEL_SCOPED_FLAGS_END EQU const_value
;; The next flags are reset upon taking a step (for e.g. talker)
EVENT_TURN_SCOPED_FLAGS_START EQU EVENT_LEVEL_SCOPED_FLAGS_END
const EVENT_TURN_SCOPED_1
const EVENT_TURN_SCOPED_2
const EVENT_TURN_SCOPED_3
const EVENT_TURN_SCOPED_4
const EVENT_TURN_SCOPED_5
const EVENT_TURN_SCOPED_6
const EVENT_TURN_SCOPED_7
const EVENT_TURN_SCOPED_8
const EVENT_TURN_SCOPED_9
const EVENT_TURN_SCOPED_10
const EVENT_TURN_SCOPED_11
const EVENT_TURN_SCOPED_12
const EVENT_TURN_SCOPED_13
const EVENT_TURN_SCOPED_14
const EVENT_TURN_SCOPED_15
const EVENT_TURN_SCOPED_16
const EVENT_TURN_SCOPED_17
const EVENT_TURN_SCOPED_18
const EVENT_TURN_SCOPED_19
const EVENT_TURN_SCOPED_20
if (const_value % 8) != 0
const_value = const_value + 8 - (const_value % 8)
endc
EVENT_TURN_SCOPED_FLAGS_END EQU const_value
;; The remaining flags are only reset explicitly
EVENT_REGULAR_FLAGS_START EQU EVENT_LEVEL_SCOPED_FLAGS_END
EVENT_REGULAR_FLAGS_START EQU EVENT_TURN_SCOPED_FLAGS_END
const EVENT_INITIALIZED_EVENTS

View File

@ -47,10 +47,12 @@ DEF CONTEXT_USE EQU 1 << CONTEXT_USE_F
const TRAINERTYPE_ITEM_MOVES
; talker events (from talker macro and high bit of wTempTalkerType)
DEF TALKER_OPTIONAL EQU %0
DEF TALKER_MANDATORY EQU %1
DEF TALKEREVENTTYPE_MASK EQU %10000000
DEF TALKEREVENTTYPE_OPTIONAL EQU %0
DEF TALKEREVENTTYPE_MANDATORY EQU %1
; talker types (from talker macro and low seven bits of wTempTalkerType)
DEF TALKERTYPE_MASK EQU %01111111
const_def
const TALKERTYPE_TEXT
const TALKERTYPE_MODAL_TEXT

View File

@ -342,7 +342,7 @@ If <code><i>item_id</i></code> = `USE_SCRIPT_VAR`, then it uses `[hScriptVar]` i
## `$62`: <code>trainertext <i>text_id</i></code>
## `$63`: <code>trainerflagaction <i>action</i></code>
## `$63`: <code>trainerortalkerflagaction <i>action</i></code>
## `$64`: <code>winlosstext <i>win_text_pointer</i>, <i>loss_text_pointer</i></code>

View File

@ -20,12 +20,22 @@ BoardMenuScript::
; save after opentext to reanchor map first
; save before processing variables like wCurTurn due to BoardMenuScript reentry after game reset
farcall AutoSaveGameInOverworld
; reset turn-scoped variables (wDieRoll, wSpacesLeft) and update wCurTurn
ld hl, wTurnData
ld bc, wTurnDataEnd - wTurnData
xor a
call ByteFill
ld hl, wCurTurn
inc [hl]
; reset turn-scoped event flags
ld hl, wEventFlags + EVENT_LEVEL_SCOPED_FLAGS_START / 8
ld c, (EVENT_LEVEL_SCOPED_FLAGS_END / 8) - (EVENT_LEVEL_SCOPED_FLAGS_START / 8)
xor a
.loop
ld [hli], a
dec c
jr nz, .loop
; load the data for the current space to wCurSpaceStruct
jp LoadCurSpaceData
.Die:

View File

@ -1,6 +1,6 @@
TalkToTrainerScript::
faceplayer
trainerflagaction CHECK_FLAG
trainerortalkerflagaction CHECK_FLAG
iftrue AlreadyBeatenTrainerScript
loadtemptrainer
encountermusic
@ -25,7 +25,7 @@ StartBattleWithMapTrainerScript:
loadtemptrainer
startbattle
reloadmapafterbattle
trainerflagaction SET_FLAG
trainerortalkerflagaction SET_FLAG
loadmem wRunningTrainerBattleScript, -1
AlreadyBeatenTrainerScript:
@ -34,8 +34,30 @@ AlreadyBeatenTrainerScript:
SeenByTalkerScript::
waitsfx ; wait for any pending space-related sfx
showemote EMOTE_TALK, LAST_TALKED, 20
callasm .TalkOrSkipTalker
iffalse .skipped
callasm TrainerOrTalkerWalkToPlayer
applymovementlasttalked wMovementBuffer
writeobjectxy LAST_TALKED
faceobject PLAYER, LAST_TALKED
.skipped
end
.TalkOrSkipTalker:
ld a, [wTempTalkerType]
and %1
cp TALKEREVENTTYPE_MANDATORY
jr z, .skip
call WaitButton
call PlayClickSFX
call WaitSFX
ldh a, [hJoyPressed]
bit A_BUTTON_F, a
jr z, .skip ; jump if b was pressed
ld a, TRUE
jr .done
.skip
xor a ; FALSE
.done
ld [hScriptVar], a
ret

View File

@ -459,7 +459,7 @@ CheckTrainerOrTalkerEvent:
call CheckTrainerBattleOrTalkerPrompt
jr nc, .nope
ld a, [wTrainerOrTalkerIsTalker]
ld a, [wSeenTrainerOrTalkerIsTalker]
and a ; cp FALSE
ld a, PLAYEREVENT_SEENBYTRAINER
jr z, .done

View File

@ -163,7 +163,7 @@ ScriptCommandTable:
dw Script_reloadmapafterbattle ; 60
dw Script_catchtutorial ; 61
dw Script_trainertext ; 62
dw Script_trainerflagaction ; 63
dw Script_trainerortalkerflagaction ; 63
dw Script_winlosstext ; 64
dw Script_scripttalkafter ; 65
dw Script_endifjustbattled ; 66
@ -685,10 +685,10 @@ Script_scripttalkafter:
ld b, a
jp ScriptJump
Script_trainerflagaction:
Script_trainerortalkerflagaction:
xor a
ldh [hScriptVar], a
ld hl, wTempTrainerEventFlag
ld hl, wTempTrainerEventFlag ; wTempTalkerEventFlag
ld e, [hl]
inc hl
ld d, [hl]

View File

@ -39,14 +39,14 @@ _CheckTrainerBattleOrTalkerPrompt::
jr z, .is_trainer
cp OBJECTTYPE_TALKER
jr nz, .next
; also set wTrainerOrTalkerIsTalker accordingly (flag is only relevant if there's actually an event)
; also set wSeenTrainerOrTalkerIsTalker accordingly (flag is only relevant if there's actually an event)
;.is_talker
ld a, TRUE
ld [wTrainerOrTalkerIsTalker], a
ld [wSeenTrainerOrTalkerIsTalker], a
jr .go
.is_trainer
xor a ; FALSE
ld [wTrainerOrTalkerIsTalker], a
ld [wSeenTrainerOrTalkerIsTalker], a
.go
; Is visible on the map
@ -68,11 +68,31 @@ _CheckTrainerBattleOrTalkerPrompt::
cp b
jr c, .next
ld a, [wTrainerOrTalkerIsTalker]
and a ; TRUE?
jr z, .trainer_battle
; And hasn't already been beaten if it's a trainer, or talked to if it's a talker,
; according to the scope of the flag of the trainer or talker event.
push bc
push de
ld hl, MAPOBJECT_SCRIPT_POINTER
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
ld e, [hl]
inc hl
ld d, [hl] ; de = wTempTrainerEventFlag = wTempTalkerEventFlag
ld b, CHECK_FLAG
call EventFlagAction
ld a, c
pop de
pop bc
and a
jr nz, .next
;.talker_prompt
ld a, [wSeenTrainerOrTalkerIsTalker]
and a ; cp FALSE
jr z, .prepare_trainer_battle
;.prepare_talker_prompt
pop de
pop af
ldh [hLastTalked], a
@ -98,26 +118,6 @@ _CheckTrainerBattleOrTalkerPrompt::
scf
ret
.trainer_battle
; And hasn't already been beaten if it's a trainer
push bc
push de
ld hl, MAPOBJECT_SCRIPT_POINTER
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
ld e, [hl]
inc hl
ld d, [hl]
ld b, CHECK_FLAG
call EventFlagAction
ld a, c
pop de
pop bc
and a
jr z, .startbattle
.next
pop de
ld hl, MAPOBJECT_LENGTH
@ -132,7 +132,7 @@ _CheckTrainerBattleOrTalkerPrompt::
xor a
ret
.startbattle
.prepare_trainer_battle
pop de
pop af
ldh [hLastTalked], a

View File

@ -206,7 +206,7 @@ DEF battlecheck EQUS "randomwildmon"
DEF loadtrainerdata EQUS "loadtemptrainer"
DEF loadpokedata EQUS "loadwildmon"
DEF returnafterbattle EQUS "reloadmapafterbattle"
DEF trainerstatus EQUS "trainerflagaction"
DEF trainerstatus EQUS "trainerortalkerflagaction"
DEF talkaftercancel EQUS "endifjustbattled"
DEF talkaftercheck EQUS "checkjustbattled"
DEF playrammusic EQUS "encountermusic"

View File

@ -632,9 +632,9 @@ MACRO trainertext
db \1 ; text_id
ENDM
const trainerflagaction_command ; $63
MACRO trainerflagaction
db trainerflagaction_command
const trainerortalkerflagaction_command ; $63
MACRO trainerortalkerflagaction
db trainerortalkerflagaction_command
db \1 ; action
ENDM

View File

@ -28,7 +28,7 @@ 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
; talker EVENT_TURN_SCOPED_*, OPTIONAL/MANDATORY | TEXT/MODAL_TEXT/SCRIPT, .Data
; .Data: ; Text
; db .Text
; .Data: ; Modal text

View File

@ -1551,7 +1551,7 @@ SECTION UNION "Miscellaneous WRAM 1", WRAMX
UNION
; trainer and talker data
wTrainerOrTalkerIsTalker:: db ; TRUE means talker; FALSE means trainer
wSeenTrainerOrTalkerIsTalker:: db ; TRUE means talker; FALSE means trainer
wSeenTrainerOrTalkerBank:: db
wSeenTrainerOrTalkerDistance:: db
wSeenTrainerOrTalkerDirection:: db