DialogueTree.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /// <reference path="../Save/StoredVariable.ts" />
  2. class DialogueTree {
  3. public id : string;
  4. private nodes : {[id : string] : DialogueNode} = {};
  5. public startNode : DialogueNode = undefined;
  6. private repeatChoices : boolean = true;
  7. private lastPrintedChoice : Array<HTMLElement>;
  8. private executedCount : StoredVariable<number>;
  9. public static ReturnValue : any = undefined; // Use this to mimic a return value if using a dialogue tree to find a value.
  10. public constructor (id : string) {
  11. this.id = id;
  12. this.executedCount = new StoredVariable({id: "DialogueTree " + id, value : 0});
  13. }
  14. public hasRan () {
  15. return this.executedCount.value > 0;
  16. }
  17. public ranTimes () {
  18. return this.executedCount.value;
  19. }
  20. public incrementRanCount () {
  21. this.executedCount.value = (this.ranTimes() + 1);
  22. }
  23. public addNode (node : DialogueNode) {
  24. this.nodes[node.id] = node;
  25. if (node.type == NodeType.Node) {
  26. this.nodes[node.name] = node; // This is a label!
  27. }
  28. }
  29. public addStartNode (node : DialogueNode) {
  30. this.addNode(node);
  31. this.startNode = node;
  32. }
  33. public getNode (id : string) {
  34. return this.nodes[id];
  35. }
  36. public getNext (node : DialogueNode) {
  37. let next = node.getNext();
  38. if (next != undefined) {
  39. return this.getNode(next);
  40. }
  41. }
  42. public setRepeatChoices (doIt : boolean) {
  43. this.repeatChoices = doIt;
  44. }
  45. public async execute (startId? : string) {
  46. this.incrementRanCount();
  47. console.debug(Rulebook.getIndentation() + "[DialogueTree] Running " + this.id);
  48. Rulebook.increaseIndentation(this);
  49. DialogueTree.ReturnValue = undefined;
  50. let node : DialogueNode;
  51. if (startId == undefined) {
  52. node = this.startNode;
  53. } else {
  54. node = this.getNode(startId);
  55. }
  56. if (node == undefined) {
  57. Elements.CurrentTurnHandler.printAsError("Unable to start dialogue " + this.id + ": A starting node could not be found.");
  58. return;
  59. }
  60. let previousNode : DialogueNode;
  61. while (node != undefined) {
  62. let nextNode = await this.processNode(node, previousNode);
  63. previousNode = node;
  64. node = nextNode;
  65. }
  66. Rulebook.decreaseIndentation();
  67. return (DialogueTree.ReturnValue);
  68. }
  69. public async processNode (node : DialogueNode, previousNode : DialogueNode) {
  70. console.debug(Rulebook.getIndentation() + "[" + node.type + "] " + node.id);
  71. Rulebook.increaseIndentation(node);
  72. let doChoices = node.hasChoices();
  73. if (node.type == NodeType.Tree) {
  74. await (<DialogueNodeTree> node).tree().execute();
  75. } else if (node.type == NodeType.Text) {
  76. let say = (<DialogueText> node).getSay();
  77. Elements.CurrentTurnHandler.printAsContent(say);
  78. } else if (node.type == NodeType.Set) {
  79. let runningSet = (<DialogueSet> node).run();
  80. if (runningSet instanceof Promise) {
  81. await runningSet;
  82. }
  83. }
  84. if (doChoices) {
  85. // Next node is decided by the choices
  86. let branchingDialogue = new BranchingDialogue();
  87. let choices = node.choices;
  88. let options = [];
  89. for (let i = 0; i < choices.length; i++) {
  90. let choice = <DialogueChoice> this.getNode(choices[i]);
  91. let branchingOption = new BranchingOption(choice.getSay(), choice.isAvailable());
  92. options.push(branchingOption);
  93. branchingDialogue.addOptions(branchingOption);
  94. }
  95. let chosenOption : BranchingOption = await branchingDialogue.getChosenOption();
  96. let chosenNodeId = choices[options.indexOf(chosenOption)];
  97. let chosenNode = <DialogueChoice> this.getNode(chosenNodeId);
  98. if (this.repeatChoices) {
  99. let say = new Say(new SayBold(" > ", chosenNode.getSay()));
  100. this.lastPrintedChoice = await Elements.CurrentTurnHandler.getSayElementsAsContent(say);
  101. await Elements.CurrentTurnHandler.print(...this.lastPrintedChoice);
  102. }
  103. console.debug(Rulebook.getIndentation() + "[Choice] Picked " + chosenNodeId);
  104. console.debug(Rulebook.getIndentation() + "[Choice] Going to " + chosenNode.getNext());
  105. Rulebook.increaseIndentation(chosenNodeId);
  106. Rulebook.decreaseIndentation();
  107. Rulebook.decreaseIndentation();
  108. return this.getNext(chosenNode);
  109. } else {
  110. Rulebook.decreaseIndentation();
  111. return this.getNext(node);
  112. }
  113. }
  114. public unprintLastChoice () {
  115. Elements.CurrentTurnHandler.unprint(...this.lastPrintedChoice);
  116. }
  117. }