///
class DialogueTree {
public id : string;
private nodes : {[id : string] : DialogueNode} = {};
public startNode : DialogueNode = undefined;
private repeatChoices : boolean = true;
private lastPrintedChoice : Array;
private executedCount : StoredVariable;
public static ReturnValue : any = undefined; // Use this to mimic a return value if using a dialogue tree to find a value.
public constructor (id : string) {
this.id = id;
this.executedCount = new StoredVariable({id: "DialogueTree " + id, value : 0});
}
public hasRan () {
return this.executedCount.value > 0;
}
public ranTimes () {
return this.executedCount.value;
}
public incrementRanCount () {
this.executedCount.value = (this.ranTimes() + 1);
}
public addNode (node : DialogueNode) {
this.nodes[node.id] = node;
if (node.type == NodeType.Node) {
this.nodes[node.name] = node; // This is a label!
}
}
public addStartNode (node : DialogueNode) {
this.addNode(node);
this.startNode = node;
}
public getNode (id : string) {
return this.nodes[id];
}
public getNext (node : DialogueNode) {
let next = node.getNext();
if (next != undefined) {
return this.getNode(next);
}
}
public setRepeatChoices (doIt : boolean) {
this.repeatChoices = doIt;
}
public async execute (startId? : string) {
this.incrementRanCount();
console.debug(Rulebook.getIndentation() + "[DialogueTree] Running " + this.id);
Rulebook.increaseIndentation(this);
DialogueTree.ReturnValue = undefined;
let node : DialogueNode;
if (startId == undefined) {
node = this.startNode;
} else {
node = this.getNode(startId);
}
if (node == undefined) {
Elements.CurrentTurnHandler.printAsError("Unable to start dialogue " + this.id + ": A starting node could not be found.");
return;
}
let previousNode : DialogueNode;
while (node != undefined) {
let nextNode = await this.processNode(node, previousNode);
previousNode = node;
node = nextNode;
}
Rulebook.decreaseIndentation();
return (DialogueTree.ReturnValue);
}
public async processNode (node : DialogueNode, previousNode : DialogueNode) {
console.debug(Rulebook.getIndentation() + "[" + node.type + "] " + node.id);
Rulebook.increaseIndentation(node);
let doChoices = node.hasChoices();
if (node.type == NodeType.Tree) {
await ( node).tree().execute();
} else if (node.type == NodeType.Text) {
let say = ( node).getSay();
Elements.CurrentTurnHandler.printAsContent(say);
} else if (node.type == NodeType.Set) {
let runningSet = ( node).run();
if (runningSet instanceof Promise) {
await runningSet;
}
}
if (doChoices) {
// Next node is decided by the choices
let branchingDialogue = new BranchingDialogue();
let choices = node.choices;
let options = [];
for (let i = 0; i < choices.length; i++) {
let choice = this.getNode(choices[i]);
let branchingOption = new BranchingOption(choice.getSay(), choice.isAvailable());
options.push(branchingOption);
branchingDialogue.addOptions(branchingOption);
}
let chosenOption : BranchingOption = await branchingDialogue.getChosenOption();
let chosenNodeId = choices[options.indexOf(chosenOption)];
let chosenNode = this.getNode(chosenNodeId);
if (this.repeatChoices) {
let say = new Say(new SayBold(" > ", chosenNode.getSay()));
this.lastPrintedChoice = await Elements.CurrentTurnHandler.getSayElementsAsContent(say);
await Elements.CurrentTurnHandler.print(...this.lastPrintedChoice);
}
console.debug(Rulebook.getIndentation() + "[Choice] Picked " + chosenNodeId);
console.debug(Rulebook.getIndentation() + "[Choice] Going to " + chosenNode.getNext());
Rulebook.increaseIndentation(chosenNodeId);
Rulebook.decreaseIndentation();
Rulebook.decreaseIndentation();
return this.getNext(chosenNode);
} else {
Rulebook.decreaseIndentation();
return this.getNext(node);
}
}
public unprintLastChoice () {
Elements.CurrentTurnHandler.unprint(...this.lastPrintedChoice);
}
}