aboutsummaryrefslogtreecommitdiff
path: root/internal/game/act_effects.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-09 19:29:17 -0400
committerhistoria <[not public]>2026-07-09 19:29:17 -0400
commitb3d4c616f59ad2519f3a0b77e3b47d6571cd2486 (patch)
tree6f1f6a314e0550da68264a79381fc269db803312 /internal/game/act_effects.go
parent18c7af94b30c2767b6633d050324c1db34074ce2 (diff)
downloadthehouseoficarus-b3d4c616f59ad2519f3a0b77e3b47d6571cd2486.tar.gz
feat: message actions are now sequences of messages with settable delays
Diffstat (limited to 'internal/game/act_effects.go')
-rw-r--r--internal/game/act_effects.go38
1 files changed, 26 insertions, 12 deletions
diff --git a/internal/game/act_effects.go b/internal/game/act_effects.go
index 82d5022..9fce264 100644
--- a/internal/game/act_effects.go
+++ b/internal/game/act_effects.go
@@ -46,7 +46,7 @@ const (
// scopeGlobal ignores p entirely.
//
// The fixed effect order (matching the original executors, normalized):
-// 1. message (player/seq scopes — skipped for scopeGlobal)
+// 1. messages (player/seq scopes — skipped for scopeGlobal)
// 2. broadcast → all in room (seq/global scopes)
// 3. broadcast_global → all online (seq/global scopes)
// 4. set_global_flags (scopeGlobal only; player scopes handle globals in step 5
@@ -64,9 +64,8 @@ const (
// writePlayerMessage expands the message template (player name, flag value),
// colorizes inline {spec}text{/} tags under the caller's color mode, and writes
// it to sess. It is the single path used by every per-player message emission
-// in the interaction system (applyStepAction step 1, applyInteraction's
-// Interaction.Message, completeMove's on_traverse Message, and
-// advanceUseInteraction's d.Message) so color tags render consistently.
+// in the interaction system (applyStepAction step 1, the interaction sequencer,
+// and the advance handlers) so color tags render consistently.
func (g *Game) writePlayerMessage(sess *net.Session, msg string, playerName string, flagValue any) {
if sess == nil || msg == "" {
return
@@ -88,10 +87,14 @@ func (g *Game) applyStepAction(sess *net.Session, p *player.Player, step *behavi
playerName = p.Name
}
- // 1. message — direct to the triggering session. Skipped for scopeGlobal
- // (no per-player session is the target).
+ // 1. messages — direct to the triggering session. Skipped for scopeGlobal
+ // (no per-player session is the target). All Messages in the step emit in
+ // order; per-message delays are ignored here (they're honored by the
+ // interaction sequencer or handled as inter-step delays by on_enter/triggers).
if sc != scopeGlobal {
- g.writePlayerMessage(sess, step.Message, playerName, flagValue)
+ for _, msg := range step.Messages {
+ g.writePlayerMessage(sess, msg.Message, playerName, flagValue)
+ }
}
// 2 & 3. broadcast / broadcast_global — re-render color tags per recipient
@@ -238,9 +241,7 @@ func (g *Game) applyNodeAction(sess *net.Session, na *behavior.NodeAction) {
// applyInteraction fires the first matching entry in a list of conditional
// interactions (on_use, on_look, on_kill, exit traversal). Returns true when
// an entry matched and fired. The action runs at scopePlayer (or scopePlayerSeq
-// if allowSeq is set, for on_kill which may broadcast/spawn). The
-// interaction's Message is written to the player first (if non-empty), then
-// the Action fires via applyStepAction.
+// if allowSeq is set, for on_kill which may broadcast/spawn).
//
// itemMatch (optional) gates entries that carry an item_id: for on_look it
// requires the player to have the item in inventory; for on_kill it requires
@@ -260,9 +261,22 @@ func (g *Game) applyInteraction(sess *net.Session, p *player.Player, list []beha
if it.Condition != nil && !g.checkCondition(sess, it.Condition) {
continue
}
- g.writePlayerMessage(sess, it.Message, p.Name, nil)
- g.applyStepAction(sess, p, it.Action, roomID, sc, nil)
+ g.runInteraction(sess, p, it.Action, roomID, sc, nil)
return true
}
return false
+}
+
+// runInteraction fires a single interaction's Action. If the action carries
+// delayed Messages the player is locked for the duration (see the interaction
+// sequencer); otherwise the effects apply synchronously.
+func (g *Game) runInteraction(sess *net.Session, p *player.Player, step *behavior.StepAction, roomID int, sc effectScope, flagValue any) {
+ if step == nil {
+ return
+ }
+ if len(step.Messages) > 0 {
+ g.startInteractionSeq(sess, p, step, roomID, sc, flagValue)
+ return
+ }
+ g.applyStepAction(sess, p, step, roomID, sc, flagValue)
} \ No newline at end of file