ソースを参照

Allow AIHooks for conversations

Reddo 5 年 前
コミット
d856402647
1 ファイル変更117 行追加2 行削除
  1. 117 2
      tools/dialogger/dialogger.js

+ 117 - 2
tools/dialogger/dialogger.js

@@ -388,7 +388,7 @@ joint.shapes.dialogue.StartNode = joint.shapes.devs.Model.extend(
 	(
 		{
 			type: 'dialogue.StartNode',
-			inPorts: ['input'],
+			inPorts: [],
 			outPorts: ['output'],
 			size: { width: 100, height: 30, },
 			value: 'DialogueNode.START',
@@ -518,6 +518,72 @@ joint.shapes.dialogue.SetView = joint.shapes.dialogue.BaseView.extend(
 	},
 });
 
+/**
+ *
+ * AI Hook
+ *
+ */
+joint.shapes.dialogue.AIHook = joint.shapes.devs.Model.extend(
+	{
+		defaults: joint.util.deepSupplement
+		(
+			{
+				type: 'dialogue.AIHook',
+				inPorts: [],
+				outPorts: [],
+				size: { width: 300, height: 124, },
+				value: '',
+			},
+			joint.shapes.dialogue.Base.prototype.defaults
+		),
+	});
+
+joint.shapes.dialogue.AIHookView = joint.shapes.dialogue.BaseView.extend(
+	{
+		template:
+			[
+				'<div class="node">',
+				'<span class="label"></span>',
+				'<button class="delete">x</button>',
+				'<input type="text" class="hooktype" placeholder="AskAbout/Circumstance/Informative/Critical" />',
+				'<input type="text" class="identifier" placeholder="Selection Text" />',
+				'<input type="text" class="conditions" placeholder="Conditions (greeter, answerer)" />',
+				'</div>',
+			].join(''),
+
+		initialize: function()
+		{
+			joint.shapes.dialogue.BaseView.prototype.initialize.apply(this, arguments);
+			this.$box.find('input.conditions').on('change', _.bind(function(evt)
+			{
+				this.model.set('conditions', $(evt.target).val());
+			}, this));
+			this.$box.find('input.hooktype').on('change', _.bind(function(evt)
+			{
+				this.model.set('hooktype', $(evt.target).val());
+			}, this));
+			this.$box.find('input.identifier').on('change', _.bind(function(evt)
+			{
+				this.model.set('identifier', $(evt.target).val());
+			}, this));
+		},
+
+		updateBox: function()
+		{
+			joint.shapes.dialogue.BaseView.prototype.updateBox.apply(this, arguments);
+			var field = this.$box.find('input.hooktype');
+			if (!field.is(':focus'))
+				field.val(this.model.get('hooktype'));
+			var field = this.$box.find('input.conditions');
+			if (!field.is(':focus'))
+				field.val(this.model.get('conditions'));
+			var field = this.$box.find('input.identifier');
+			if (!field.is(':focus'))
+				field.val(this.model.get('identifier'));
+		},
+	});
+
+
 // Functions
 
 var func = {};
@@ -626,6 +692,13 @@ func.optimized_data = function()
 				node.value = cell.value;
 				node.next = null;
 			}
+			else if (node.type === 'AIHook')
+			{
+				node.hooktype = cell.hooktype;
+				node.identifier = cell.identifier;
+				node.conditions = cell.conditions;
+				node.next = null;
+			}
 			else
 			{
 				node.name = cell.name;
@@ -661,7 +734,7 @@ func.optimized_data = function()
 					}
 					source.branches[value] = target ? target.id : null;
 				}
-				else if ((source.type === 'Text' || source.type === 'Node') && target && target.type === 'Choice')
+				else if ((source.type === 'Text' || source.type === 'Node' || source.type === 'StartNode') && target && target.type === 'Choice')
 				{
 					if (!source.choices)
 					{
@@ -894,6 +967,47 @@ func.ts_data = function(nodes, name) {
 			}
 			finalString += "tree.addNode(set);\n";
 			addDeclaration("let set : DialogueSet;\n");
+		} else if (node.type == "AIHook") {
+			// hooktype, identifier, conditions
+			// AskAbout/Circumstance/Informative/Critical
+			node.hooktype = node.hooktype != undefined ? node.hooktype : "";
+			node.identifier = node.identifier != undefined ? node.identifier : "";
+			node.conditions = node.conditions != undefined ? node.conditions : "";
+			let hookType = node.hooktype.toLowerCase().trim();
+			finalString += " AI." + (hookType == "askabout" ? "investigateRules" : "talktoRules") + ".createAndAddRule({\n" +
+				"    name : " + JSON.stringify("AIHook for " + name) + ",\n";
+			finalString += "    conditions : (runner : RulebookRunner<TalkingHeads>) => {\n" +
+				"        // @ts-ignore\n" +
+				"        let player = WorldState.player, greeter = runner.noun.greeter, answerer = runner.noun.answerer;\n" +
+				"\n" +
+				"        return (" + node.conditions + ");\n" +
+				"    },\n";
+
+			if (hookType == "critical" || hookType == "informative") {
+				finalString += "    priority : Rule.PRIORITY_HIGHEST,\n" +
+					"    firstPriority : Rule.PRIORITY_HIGHEST,\n";
+			} else {
+				finalString += "    priority : Rule.PRIORITY_MEDIUM,\n" +
+					"    firstPriority : Rule.PRIORITY_MEDIUM,\n"
+			}
+
+			if (hookType == "informative") {
+				finalString += "    code : (runner : RulebookRunner<TalkingHeads>) => {\n" +
+					"        runner.noun.runFirst.push(tree);\n" +
+					"    },\n";
+			} else if (hookType == "critical") {
+				finalString += "    code : (runner : RulebookRunner<TalkingHeads>) => {\n" +
+					"        runner.noun.runAndStop.push(tree);\n" +
+					"    },\n";
+			} else {
+				finalString += "    code : (runner : RulebookRunner<TalkingHeads>) => {\n" +
+					"        runner.noun.options.push({\n" +
+					"            tree: tree,\n" +
+					"            text : new Say(" + node.identifier + ")\n" +
+					"        })\n" +
+					"    },\n";
+			}
+			finalString += "});\n\n";
 		}
 	}
 	return declarations.join("") + finalString;
@@ -1035,6 +1149,7 @@ func.ts_data = function(nodes, name) {
 	state.menu.append(new nw.MenuItem({ label: 'Tree', click: func.add_node(joint.shapes.dialogue.Tree) }));
 	state.menu.append(new nw.MenuItem({ label: 'Label', click: func.add_node(joint.shapes.dialogue.Node) }));
 	state.menu.append(new nw.MenuItem({ label: 'Start Point', click: func.add_node(joint.shapes.dialogue.StartNode) }));
+	state.menu.append(new nw.MenuItem({ label: 'AI Hook', click: func.add_node(joint.shapes.dialogue.AIHook) }));
 	state.menu.append(new nw.MenuItem({ type: 'separator' }));
 	state.menu.append(new nw.MenuItem({ label: 'Save', click: func.save }));
 	state.menu.append(new nw.MenuItem({ label: 'Open', click: func.show_open_dialog }));