mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-01-07 12:11:37 +01:00
Added support for different types of item requirements in conversation replies. For example, requiring the player to wear a specific item instead of just having it in inventory. git-svn-id: https://andors-trail.googlecode.com/svn/trunk@216 08aca716-68be-ccc6-4d58-36f5abd142ac
320 lines
9.0 KiB
JavaScript
320 lines
9.0 KiB
JavaScript
|
|
|
|
function createConversationEditor(obj) {
|
|
var div = $( "#templates #editDialogue" ).clone(true);
|
|
|
|
var treeDiv = $ ( "#dialogueTree", div );
|
|
treeDiv.dynatree({
|
|
title: "Conversation flow"
|
|
,imagePath: 'img'
|
|
});
|
|
var tree = treeDiv.dynatree("getTree");
|
|
|
|
var rootNode = treeDiv.dynatree("getRoot");
|
|
updatePhraseTreeNodesBelow(tree, rootNode, obj);
|
|
|
|
treeDiv.dynatree({
|
|
onActivate: function(node) {
|
|
onConversationPhraseSelected(div, node.data.model, tree);
|
|
}
|
|
});
|
|
|
|
tree.activateKey(obj.id);
|
|
|
|
return div;
|
|
}
|
|
|
|
function getPhraseByPhraseID(phraseID) {
|
|
if (!phraseID) return;
|
|
return model.dialogue.findById(phraseID);
|
|
}
|
|
|
|
function onConversationPhraseSelected(div, obj, tree) {
|
|
var dialoguePhrase = $( "#dialoguePhrase", div );
|
|
var dialogueReply = $( "#dialogueReply", div );
|
|
var dialoguePhraseReplies = $( "#dialoguePhraseReplies", div );
|
|
dialogueReply.hide();
|
|
dialoguePhrase.hide();
|
|
dialoguePhraseReplies.hide();
|
|
if (!obj) return;
|
|
|
|
var treeNodeKey = getTreeNodeKey(obj);
|
|
var treeNode = tree.getNodeByKey(treeNodeKey);
|
|
if (!treeNode) {
|
|
treeNode = updatePhraseTreeNodesBelow(tree, tree.getRoot(), obj, true);
|
|
}
|
|
|
|
treeNode.activateSilently();
|
|
|
|
applyCommonEditorBindings(div, obj, model.dialogue);
|
|
|
|
if (obj.isPhrase) {
|
|
buildEditorForPhrase(div, obj, tree, treeNode);
|
|
} else {
|
|
buildEditorForReply(div, obj, tree, treeNode);
|
|
}
|
|
}
|
|
|
|
// ========================================================
|
|
// Set up editor for NPC phrases
|
|
|
|
function buildEditorForPhrase(div, phrase, tree, treeNode) {
|
|
var dialoguePhrase = $( "#dialoguePhrase", div );
|
|
var dialoguePhraseReplies = $( "#dialoguePhraseReplies", div );
|
|
|
|
checkboxHidesElement( $( '#hasRewards', dialoguePhrase ), $( '#hasRewardsDisplay', dialoguePhrase ), phrase.rewards);
|
|
|
|
var rebuildChildNodes = function() {
|
|
updatePhraseReplyTreeNodesBelow(tree, treeNode, phrase);
|
|
}
|
|
var reloadReplyTable = function() {
|
|
applyTableEditor({
|
|
table: $( "#replies", dialoguePhraseReplies ),
|
|
array: phrase.replies,
|
|
templateFunction: function() { return createReplyForPhrase(phrase); },
|
|
onItemSelected: function(obj) {
|
|
onConversationPhraseSelected(div, obj, tree);
|
|
},
|
|
onItemAdded: function(addedObject) {
|
|
rebuildChildNodes();
|
|
}
|
|
});
|
|
}
|
|
reloadReplyTable();
|
|
|
|
var hasOnlyNextReply = $( '#hasOnlyNextReply', dialoguePhraseReplies );
|
|
checkboxHidesElement( hasOnlyNextReply, $( '#hasOnlyNextReplyDisplay', dialoguePhraseReplies ), phrase.hasOnlyNextReply);
|
|
checkboxShowsElement( hasOnlyNextReply, $( '#hasRepliesDisplay', dialoguePhraseReplies ), !phrase.hasOnlyNextReply);
|
|
|
|
hasOnlyNextReply.change(function() {
|
|
if ( $(this).attr("checked") ) {
|
|
var nextReply = createReplyForPhrase(phrase);
|
|
nextReply.text = 'N';
|
|
phrase.replies = [ nextReply ];
|
|
} else {
|
|
phrase.replies = [ ];
|
|
reloadReplyTable();
|
|
}
|
|
rebuildChildNodes();
|
|
});
|
|
|
|
var nextPhraseID = $( "#nextPhraseID", dialoguePhraseReplies );
|
|
nextPhraseID.unbind("change").change(function() {
|
|
phrase.replies[0].nextPhraseID = $( this ).val();
|
|
rebuildChildNodes();
|
|
});
|
|
if (phrase.hasOnlyNextReply) {
|
|
nextPhraseID.val(phrase.replies[0].nextPhraseID);
|
|
}
|
|
|
|
var phraseID = $( "#id", dialoguePhrase );
|
|
phraseID.change(function() {
|
|
treeNode.data.key = phrase.id;
|
|
rebuildChildNodes();
|
|
});
|
|
|
|
$( "#followNextReply", dialoguePhraseReplies ).button().unbind('click').click(function() {
|
|
openNextPhrase(nextPhraseID.val(), div, phrase.replies[0], tree);
|
|
});
|
|
|
|
$( '#message', dialoguePhrase ).change(function() { treeNode.setTitle( getPhraseNodeText(phrase) ); });
|
|
|
|
var createNewReward = function() { return { rewardType: 0 }; }
|
|
var setupEditor = function(div) { }
|
|
if (!phrase.rewards) phrase.rewards = [];
|
|
applyTableEditor({
|
|
table: $( '#rewards', dialoguePhrase ),
|
|
dialog: phraseRewardDialog,
|
|
array: phrase.rewards,
|
|
templateFunction: createNewReward,
|
|
editorSetup: setupEditor
|
|
});
|
|
|
|
dialoguePhrase.show();
|
|
dialoguePhraseReplies.show();
|
|
}
|
|
|
|
function createReplyForPhrase(phrase) {
|
|
return {
|
|
id: phrase.id,
|
|
isPhrase: false,
|
|
phrase: phrase
|
|
};
|
|
}
|
|
|
|
function openNextPhrase(nextPhraseID, div, reply, tree) {
|
|
var createNewPhrase = true;
|
|
var phrase;
|
|
if (nextPhraseID) {
|
|
phrase = getPhraseByPhraseID(nextPhraseID);
|
|
if (phrase) {
|
|
createNewPhrase = false;
|
|
}
|
|
} else {
|
|
nextPhraseID = generatePhraseID(reply.phrase.id);
|
|
}
|
|
|
|
if (createNewPhrase) {
|
|
phrase = { id: nextPhraseID, isPhrase: true };
|
|
model.dialogue.add(phrase);
|
|
}
|
|
reply.nextPhraseID = nextPhraseID;
|
|
|
|
var treeNodeKey = getTreeNodeKey(reply.phrase);
|
|
var treeNode = tree.getNodeByKey(treeNodeKey);
|
|
updatePhraseReplyTreeNodesBelow(tree, treeNode, reply.phrase);
|
|
//alert("followNextReply: " + nextPhraseID);
|
|
onConversationPhraseSelected(div, phrase, tree);
|
|
}
|
|
|
|
function generatePhraseID(previousPhraseID) {
|
|
var suffix;
|
|
var n = 1;
|
|
|
|
var match = (/^(.*\D)(\d+)$/g).exec(previousPhraseID);
|
|
if (match) {
|
|
suffix = match[1];
|
|
n = parseInt(match[2]) + 1;
|
|
} else {
|
|
suffix = previousPhraseID + "_";
|
|
}
|
|
|
|
for (var i = n; i < 1000; ++i) {
|
|
var phraseID = suffix + i;
|
|
if (!getPhraseByPhraseID(phraseID)) return phraseID;
|
|
}
|
|
}
|
|
|
|
// ========================================================
|
|
// Set up editor for replies
|
|
|
|
function buildEditorForReply(div, reply, tree, treeNode) {
|
|
var dialogueReply = $( "#dialogueReply", div );
|
|
|
|
checkboxHidesElement( $( '#requiresItems', dialogueReply ), $( '#requiresItemsDisplay', dialogueReply ), reply.requires_itemID);
|
|
checkboxHidesElement( $( '#requiresQuest', dialogueReply ), $( '#requiresQuestDisplay', dialogueReply ), reply.requires_Progress);
|
|
bindFieldToDataStore( $( "#requires_itemID", dialogueReply ), model.items);
|
|
bindFieldToDataStore( $( "#requires_Progress", dialogueReply ), model.quests);
|
|
|
|
var replyLeadsTo = $( "#replyLeadsTo", dialogueReply );
|
|
replyLeadsTo.val(reply.nextPhraseID);
|
|
if (!replyLeadsTo.val()) { replyLeadsTo.val(""); }
|
|
replyLeadsTo.change(function() { nextPhraseID.val( $(this).val() ).change(); });
|
|
changeHidesElement(replyLeadsTo, $( "#nextPhraseIDDisplay", dialogueReply ) , function() { return replyLeadsTo.val() == ''; } );
|
|
|
|
var nextPhraseID = $( "#nextPhraseID", dialogueReply );
|
|
nextPhraseID.change(function() {
|
|
updatePhraseTreeNodesBelow(tree, treeNode, getPhraseByPhraseID(reply.nextPhraseID) );
|
|
});
|
|
|
|
$( "#followReply", dialogueReply ).button().unbind('click').click(function() {
|
|
openNextPhrase(nextPhraseID.val(), div, reply, tree);
|
|
});
|
|
|
|
$( '#text', dialogueReply ).change(function() { treeNode.setTitle( getReplyNodeText(reply) ); });
|
|
|
|
dialogueReply.show();
|
|
}
|
|
|
|
|
|
// ========================================================
|
|
// Tree node key generators
|
|
|
|
function getTreeNodeKey(obj) {
|
|
if (!obj) return "";
|
|
if (obj.isPhrase) return obj.id;
|
|
return getTreeNodeReplyKey(obj);
|
|
}
|
|
|
|
function getTreeNodeReplyKey(obj) {
|
|
var idx = 0;
|
|
for (var i = 0; i < obj.phrase.replies.length; ++i) {
|
|
if (obj.phrase.replies[i] == obj) {
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
return getTreeNodeReplyKeyIndex(obj, idx);
|
|
}
|
|
|
|
function getTreeNodeReplyKeyIndex(obj, idx) {
|
|
return getTreeNodeKey(obj.phrase) + "__reply_" + idx;
|
|
}
|
|
|
|
|
|
// ========================================================
|
|
// Tree node title generators
|
|
|
|
function getPhraseNodeText(phrase) {
|
|
return phrase.message ? shortenString(phrase.message, 30) : "(no phrase text)";
|
|
}
|
|
|
|
function getReplyNodeText(reply) {
|
|
return reply.text ? shortenString(reply.text, 30) : "(no reply text)";
|
|
}
|
|
|
|
// ========================================================
|
|
// Tree-building functions
|
|
|
|
// (re)Build a NPC phrase node
|
|
function updatePhraseTreeNodesBelow(tree, parent, phrase, keepExisting) {
|
|
if (!keepExisting) { parent.removeChildren(); }
|
|
|
|
if (!phrase) return;
|
|
|
|
phrase.isPhrase = true;
|
|
var key = getTreeNodeKey(phrase);
|
|
|
|
if (tree.getNodeByKey(key)) {
|
|
parent.addChild({
|
|
title: '(conversation loop)'
|
|
,model: phrase
|
|
});
|
|
return;
|
|
}
|
|
|
|
var phraseNode = parent.addChild({
|
|
title: getPhraseNodeText(phrase)
|
|
,key: key
|
|
,model: phrase
|
|
,icon: 'phrase.png'
|
|
});
|
|
|
|
if (!phrase.replies) phrase.replies = [];
|
|
updatePhraseReplyTreeNodesBelow(tree, phraseNode, phrase, phrase.replies);
|
|
|
|
phraseNode.expand(true);
|
|
return phraseNode;
|
|
}
|
|
|
|
// (re)Build all nodes below a NPC phrase (i.e. rebuild all reply nodes)
|
|
function updatePhraseReplyTreeNodesBelow(tree, phraseNode, phrase) {
|
|
phraseNode.removeChildren();
|
|
|
|
if (!phrase.replies) phrase.replies = [];
|
|
|
|
if (phrase.replies.length == 1) {
|
|
var singleReply = phrase.replies[0];
|
|
if (singleReply.text == 'N') {
|
|
phrase.hasOnlyNextReply = true;
|
|
updatePhraseTreeNodesBelow(tree, phraseNode, getPhraseByPhraseID(singleReply.nextPhraseID) );
|
|
return;
|
|
}
|
|
}
|
|
|
|
phrase.replies.forEach(function(reply, idx) {
|
|
jQuery.extend(reply, createReplyForPhrase(phrase));
|
|
var key = getTreeNodeReplyKeyIndex(reply, idx);
|
|
var replyNode = phraseNode.addChild({
|
|
title: getReplyNodeText(reply)
|
|
,key: key
|
|
,model: reply
|
|
,icon: 'reply.png'
|
|
});
|
|
if (reply.nextPhraseID) {
|
|
updatePhraseTreeNodesBelow(tree, replyNode, getPhraseByPhraseID(reply.nextPhraseID) );
|
|
}
|
|
replyNode.expand(true);
|
|
});
|
|
}
|