diff options
Diffstat (limited to 'internal/game/act_effects.go')
| -rw-r--r-- | internal/game/act_effects.go | 38 |
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 |
