aboutsummaryrefslogtreecommitdiff
path: root/internal/game/act_talk.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/act_talk.go')
-rw-r--r--internal/game/act_talk.go47
1 files changed, 31 insertions, 16 deletions
diff --git a/internal/game/act_talk.go b/internal/game/act_talk.go
index ef3c6e5..9ae9959 100644
--- a/internal/game/act_talk.go
+++ b/internal/game/act_talk.go
@@ -55,8 +55,8 @@ func (g *Game) startTalk(sess *net.Session, p *player.Player, obj *object.Object
}
}
-func (g *Game) handleNodeAction(sess *net.Session, na *behavior.Step) (intercepted bool) {
- g.applyTalkStep(sess, na)
+func (g *Game) handleNodeAction(sess *net.Session, na *behavior.Step) (intercepted bool, applied bool) {
+ applied = g.applyTalkStep(sess, na)
if v, ok := g.GlobalFlags.Get("guard_hostile"); ok && v != nil {
g.GlobalFlags.Delete("guard_hostile")
@@ -70,11 +70,11 @@ func (g *Game) handleNodeAction(sess *net.Session, na *behavior.Step) (intercept
guardMob.Protected = false
g.startCombat(sess, p, guardMob)
}
- return true
+ return true, applied
}
}
}
- return false
+ return false, applied
}
func (g *Game) showTalkNode(sess *net.Session, node behavior.TalkNode) {
@@ -90,12 +90,19 @@ func (g *Game) showTalkNode(sess *net.Session, node behavior.TalkNode) {
for {
if node.Condition == nil || g.checkCondition(sess, node.Condition) {
- if len(node.Messages) > 0 {
- if node.Action != nil {
- if g.handleNodeAction(sess, node.Action) {
- return
- }
+ // Apply the node's action first. A failed preflight (missing item,
+ // full inventory, unaffordable cost) applies nothing, so skip the
+ // node's success messages rather than narrating a trade that did
+ // not happen; the player still gets the node's options.
+ actionApplied := true
+ if node.Action != nil {
+ intercepted, applied := g.handleNodeAction(sess, node.Action)
+ if intercepted {
+ return
}
+ actionApplied = applied
+ }
+ if actionApplied && len(node.Messages) > 0 {
td.SeqIndex = 0
msg := node.Messages[0]
if msg != "" {
@@ -107,12 +114,6 @@ func (g *Game) showTalkNode(sess *net.Session, node behavior.TalkNode) {
sess.Write(g.colorize(sess, "dialog_options", "[enter to continue]\n"))
return
}
- } else {
- if node.Action != nil {
- if g.handleNodeAction(sess, node.Action) {
- return
- }
- }
}
visible := g.visibleOptions(sess, node.Options)
if len(visible) > 0 {
@@ -313,7 +314,21 @@ func (g *Game) advanceTalk(sess *net.Session, p *player.Player) {
td.PendingChoice = ""
td.PendingAction = nil
if action != nil {
- if g.handleNodeAction(sess, action) {
+ intercepted, applied := g.handleNodeAction(sess, action)
+ if intercepted {
+ return
+ }
+ if !applied {
+ // The option's cost could not be met and no effect was applied.
+ // Re-show the current node's options instead of advancing to the
+ // success node and its misleading success text.
+ if node, ok := td.Cfg.Nodes[td.Node]; ok {
+ g.finishSequence(sess, node)
+ } else {
+ g.cancelAction(p)
+ sess.SetState(net.StateGame)
+ g.writePrompt(sess)
+ }
return
}
}