Created
October 7, 2018 06:34
-
-
Save thetooth/0a5fdaea13f0006cdb7886c0ccd3def6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dialog | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"github.com/gen2brain/raylib-go/raylib" | |
"github.com/sirupsen/logrus" | |
) | |
// NewConversation returns a dialog tree | |
func NewConversation(fileName string) *Conversation { | |
c := &Conversation{ | |
Nodes: make(map[string]*Node), | |
Variables: make(map[string]string), | |
} | |
b, err := ioutil.ReadFile(fileName) | |
if err != nil { | |
logrus.Error(err) | |
} | |
nodes := []*Node{} | |
if err := json.Unmarshal(b, &nodes); err != nil { | |
logrus.Error(err) | |
} | |
for _, node := range nodes { | |
c.Nodes[node.ID] = node | |
} | |
logrus.Info("Loaded ", len(c.Nodes), " nodes") | |
return c | |
} | |
// Node stores each tree node and it's possible values | |
type Node struct { | |
ID string | |
Type string | |
Actor string | |
Name string | |
Next string | |
Branches map[string]string | |
Choices []string | |
Variable string | |
Value string | |
} | |
// Conversation stores the dialog tree, branch variables and currently active node for immediate mode | |
type Conversation struct { | |
Nodes map[string]*Node | |
Variables map[string]string | |
CurrentNode *Node | |
} | |
// Next advances through the tree until either a Text or Choice node is encountered. | |
// We return on these two types for drawing and interaction. | |
func (c *Conversation) Next(node *Node) *Node { | |
logrus.Info("Execute ", node.Type, " ", node.Actor) | |
c.CurrentNode = node | |
next := "" | |
switch node.Type { | |
case "Node": | |
next = node.Next | |
case "Text": | |
return node | |
case "Choice": | |
return node | |
case "Branch": | |
if v, ok := c.Variables[node.Variable]; ok { | |
if nextBranch, ok := node.Branches[v]; ok { | |
next = nextBranch | |
} else { | |
next = node.Branches["_default"] | |
} | |
} else { | |
logrus.Warn("Variable '", node.Variable, "' not present, will default") | |
next = node.Branches["_default"] | |
} | |
case "Set": | |
c.Set(node.Variable, node.Value) | |
next = node.Next | |
} | |
if next != "" { | |
return c.Next(c.Nodes[next]) | |
} | |
return nil | |
} | |
// Talk finds the start of dialog for a given actor returning the first text node. | |
func (c *Conversation) Talk(actor string) *Node { | |
for _, node := range c.Nodes { | |
if node.Type == "Node" && node.Actor == actor && node.Name == "start" { | |
c.CurrentNode = node | |
return c.Next(node) | |
} | |
} | |
return nil | |
} | |
// Bye clears the current node so it won't be drawn. | |
func (c *Conversation) Bye() { | |
c.CurrentNode = nil | |
} | |
// Choose an option or just advance the text | |
func (c *Conversation) Choose(choice int) { | |
if c.CurrentNode == nil { | |
return | |
} | |
if c.CurrentNode.Type == "Text" { | |
choices := c.CurrentNode.Choices | |
if len(choices) > 0 { | |
c.Next(c.Nodes[choices[choice]]) | |
} else if c.CurrentNode.Next != "" { | |
c.Next(c.Nodes[c.CurrentNode.Next]) | |
} else { | |
c.Bye() | |
} | |
} else if c.CurrentNode.Type == "Choice" { | |
c.Next(c.Nodes[c.CurrentNode.Next]) | |
} | |
} | |
// Set variable to value (is this even needed?) | |
func (c *Conversation) Set(variable, value string) { | |
logrus.Info(variable, " = ", value) | |
c.Variables[variable] = value | |
} | |
// Draw currently active dialog | |
func (c *Conversation) Draw(x, y int32) { | |
if c.CurrentNode == nil { | |
return | |
} | |
text := "" | |
if c.CurrentNode.Type == "Choice" { | |
text += fmt.Sprintf("(You):\n\n%v", c.CurrentNode.Name) | |
} else { | |
text += fmt.Sprintf("%v:\n\n%v\n", c.CurrentNode.Actor, c.CurrentNode.Name) | |
for _, choice := range c.CurrentNode.Choices { | |
text += fmt.Sprintf("[ %v ] ", c.Nodes[choice].Name) | |
} | |
} | |
raylib.DrawText(text, x, y, 8, raylib.White) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment