game skeleton

This commit is contained in:
2026-08-29 19:07:32 +02:00
parent a04a61ddd0
commit 0d8918e6f5
39 changed files with 2540 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
package dialog
import (
inkwell "git.teletypegames.org/engines/inkwell"
"realworld/internal/names"
)
// dexTalk is the standing conversation with Dex. Its branches are gated on
// story flags, so the same entry point stays useful as the game progresses.
func dexTalk() inkwell.Dialogue {
return inkwell.Dialogue{
Name: names.DlgDex,
Start: "root",
Nodes: []inkwell.DialogueNode{{
Name: "root",
Lines: []inkwell.DialogueLine{{Speaker: names.Dex, Text: "Talk."}},
Choices: []inkwell.DialogueChoice{
{
Text: "What am I doing here, Dex?",
Actions: []inkwell.Action{
inkwell.Say(names.Dex, "You got a letter from a man you hadn't seen in twenty years. And you came. That says more about you than it does about him."),
inkwell.GotoNode("root"),
},
},
{
Text: "What do you know about Noodle?",
Show: inkwell.Not(inkwell.Flag(names.FlagHasTape)),
Actions: []inkwell.Action{
inkwell.Say(names.Dex, "He traded cracked Armillas. That isn't charity, Paul, that's a business. The kind they take you in for."),
inkwell.GotoNode("root"),
},
},
{
Text: "What do you make of this tape?",
Show: inkwell.Flag(names.FlagHasTape),
Actions: []inkwell.Action{
inkwell.Say(names.Dex, "I make of it that you found a password-locked tape in a gap between two bins, on a tip from a government office. Count how many times that has ended well."),
inkwell.GotoNode("root"),
},
},
{
Text: "I miss you.",
Once: true,
Actions: []inkwell.Action{
inkwell.Say(names.Dex, "I'm four kilobytes of a dead man. Don't do this to yourself."),
inkwell.GotoNode("root"),
},
},
{
Text: "Nothing. Forget it.",
Actions: []inkwell.Action{inkwell.EndDialogue()},
},
},
}},
}
}
+26
View File
@@ -0,0 +1,26 @@
// Package dialog registers the game's dialogue trees.
//
// Talking to a tape carries the same weight as talking to a human NPC — the
// wiki states this explicitly. Tapes are dialogue partners, not menus.
//
// A note on DialogueChoice.Once: inkwell HIDES a spent choice. The wireframe
// deck wanted it struck through but still visible, so the list becomes a
// memory of what you already tried. That is still open — see README, "Known
// gaps".
package dialog
import (
inkwell "git.teletypegames.org/engines/inkwell"
"realworld/internal/world"
)
// Register adds every dialogue to the game.
func Register(w *world.World) {
for _, d := range []inkwell.Dialogue{
dexTalk(),
mysteryTapeSilent(),
} {
w.G.DialogueManager.Register(d)
}
}
@@ -0,0 +1,34 @@
package dialog
import (
inkwell "git.teletypegames.org/engines/inkwell"
"realworld/internal/names"
)
// mysteryTapeSilent covers the stretch before the club trigger (beat 6), while
// the tape is still mute. Talking to it is really Dex talking about it — the
// tape itself says nothing.
func mysteryTapeSilent() inkwell.Dialogue {
return inkwell.Dialogue{
Name: names.DlgMysteryTape,
Start: "root",
Nodes: []inkwell.DialogueNode{{
Name: "root",
Lines: []inkwell.DialogueLine{{Speaker: names.Dex, Text: "Nothing. Warm, spinning, and silent."}},
Choices: []inkwell.DialogueChoice{
{
Text: "Are you sure it works?",
Actions: []inkwell.Action{
inkwell.Say(names.Dex, "It works. It just isn't talking to you. That is not the same as silence."),
inkwell.GotoNode("root"),
},
},
{
Text: "Fine. It'll speak when it speaks.",
Actions: []inkwell.Action{inkwell.EndDialogue()},
},
},
}},
}
}