Add "Dialogue Tree" extension by @blurymind (experimental) (#1112)

This commit is contained in:
Todor Imreorov
2019-08-04 22:45:04 +01:00
committed by Florian Rival
parent bd273055cb
commit 933e5426bc
11 changed files with 1462 additions and 0 deletions

View File

@@ -0,0 +1,512 @@
/**
* This is a declaration of an extension for GDevelop 5.
*
* Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change
* to this extension file or to any other *.js file that you reference inside.
*
* The file must be named "JsExtension.js", otherwise GDevelop won't load it.
* ⚠️ If you make a change and the extension is not loaded, open the developer console
* and search for any errors.
*
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
*/
module.exports = {
createExtension: function(_, gd) {
const extension = new gd.PlatformExtension();
extension
.setExtensionInformation(
'DialogueTree',
_('Dialogue Tree (Experimental)'),
_('Start dialogue trees, made using Yarn, powered by Bondage.js. Experimental extension that can change in the future.'),
'Todor Imreorov',
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/dialogue-tree');
extension
.addAction(
'LoadDialogueFromSceneVariable',
_('Load dialogue Tree from a Scene Variable'),
_('Load a dialogue data object - Yarn json format, stored in a scene variable. Use this command to load all the Dialogue data at the beginning of the game.'),
_('Load dialogue data from Scene variable _PARAM1_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('scenevar', _('Scene variable that holds the Yarn Json data'))
.getCodeExtraInformation()
.setIncludeFile('Extensions/DialogueTree/dialoguetools.js')
.addIncludeFile('Extensions/DialogueTree/bondage.min.js')
.setFunctionName('gdjs.dialogueTree.loadFromSceneVariable');
extension
.addAction(
'LoadDialogueFromJsonFile',
_('Load dialogue Tree from a Json File'),
_('Load a dialogue data object - Yarn json format, stored in a Json file. Use this command to load all the Dialogue data at the beginning of the game.'),
_('Load dialogue data from json file _PARAM1_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addCodeOnlyParameter('currentScene', '')
.addParameter('jsonResource', _('Json file that holds the Yarn Json data'))
.getCodeExtraInformation()
.setIncludeFile('Extensions/DialogueTree/dialoguetools.js')
.addIncludeFile('Extensions/DialogueTree/bondage.min.js')
.setFunctionName('gdjs.dialogueTree.loadFromJsonFile');
extension
.addAction(
'StarDialogueFromBranch',
_('Start dialogue from branch'),
_('Start dialogue from branch. Use this to initiate the dialogue from a specified branch.'),
_('Start dialogue from branch _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Dialogue branch'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.startFrom');
extension
.addAction(
'GoToNextLine',
_('Go to the next dialogue line'),
_('Go to the next dialogue line. Use this to advance to the next dialogue line when the player presses a button.'),
_('Go to the next dialogue line'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.goToNextDialogueLine');
extension
.addAction(
'ConfirmSelectOption',
_('Confirm selected Option'),
_('Set the selected option as confirmed, which will validate it and go forward to the next node. Use other actions to select options (see "select next option" and "Select previous option").'),
_('Confirm selected Option'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.confirmSelectOption');
extension
.addAction(
'SelectNextOption',
_('Select next Option'),
_('Select next Option (add 1 to selected option number). Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'),
_('Select next Option'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectNextOption');
extension
.addAction(
'SelectPreviousOption',
_('Select previous Option'),
_('Select previous Option (subtract 1 from selected option number). Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'),
_('Select previous Option'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectPreviousOption');
extension
.addAction(
'SelectOption',
_('Select option by number'),
_('Select option by number. Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'),
_('Select option by number'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Option index number'))
.setDefaultValue('0')
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectPreviousOption');
extension
.addAction(
'ScrollClippedText',
_('Scroll clipped text'),
_('Scroll clipped text. Use this with a timer and "get clipped text" when you want to create a typewriter effect. Every time the action runs, a new character appears from the text.'),
_('Scroll clipped text'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.scrollClippedText');
extension
.addAction(
'SetVariable',
_('Set dialogue state variable'),
_('Set dialogue state variable. Use this to set a variable that the dialogue data is using.'),
_('Set dialogue state variable _PARAM0_ to _PARAM1_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('State Variable Name'))
.addParameter('expression', _('Variable Value'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.setVariable');
extension
.addAction(
'SaveState',
_('Save dialogue state'),
_('Save dialogue state. Use this to store the dialogue state into a variable, which can later be used for saving the game. That way player choices can become part of the game save.'),
_('Save dialogue state to _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('globalvar', _('Global Variable'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.saveState');
extension
.addAction(
'LoadState',
_('Load dialogue state'),
_('Load dialogue state. Use this to restore dialogue state, if you have stored in a variable before with the "Save state" action.'),
_('Load dialogue state from _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('globalvar', _('Global Variable'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.loadState');
extension
.addStrExpression(
'LineText',
_('Get the current dialogue line text'),
_('Returns the current dialogue line text'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineText');
extension
.addExpression(
'OptionsCount',
_('Get the number of options in an options line type'),
_('Get the number of options in an options line type'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineOptionsCount');
extension
.addStrExpression(
'Option',
_('Get the text of an option from an Options line type'),
_('Get the text of an option from an Options line type, using the option\'s Number. The numbers start from 0.'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Option Index Number'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineOption');
extension
.addExpression(
'SelectedOptionIndex',
_('Get the number of the currently selected option'),
_('Get the number of the currently selected option. Use this to help you render the option selection marker at the right place.'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getSelectedOption');
extension
.addStrExpression(
'ClippedLineText',
_('Get dialogue line text clipped'),
_('Get dialogue line text clipped by the typewriter effect. Use the ScrollClippedText action to control the typewriter effect.'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getClippedLineText');
extension
.addStrExpression(
'BranchTitle',
_('Get the title of the current branch of running dialogue'),
_('Get the title of the current branch of running dialogue'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTitle');
extension
.addStrExpression(
'BranchTags',
_('Get the tags of the current branch of running dialogue'),
_('Get the tags of the current branch of running dialogue'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTags');
extension
.addStrExpression(
'BranchTag',
_('Get a tag of the current branch of running dialogue via number'),
_('Get a tag of the current branch of running dialogue via number'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Tag Index Number'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTag');
extension
.addStrExpression(
'CommandParameter',
_('Get the parameters of a command call'),
_('Get the parameters of a command call - <<command withParameter anotherParameter>>'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('parameter Index Number'), '', true)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getCommandParameter');
extension
.addExpression(
'CommandParametersCount',
_('Get the number of parameters in the currently passed command'),
_('Get the number of parameters in the currently passed command'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.commandParametersCount');
extension
.addStrExpression(
'TagParameter',
_('Get parameter from a Tag found by the branch contains tag condition'),
_('Get parameter from a Tag found by the branch contains tag condition'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('parameter Index Number'), '', true)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getTagParameter');
extension
.addStrExpression(
'VisitedBranchTitles',
_('Get a list of all visited branches'),
_('Get a list of all visited branches'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getVisitedBranchTitles');
extension
.addStrExpression(
'BranchText',
_('Get the raw text of the current branch'),
_('Get the full raw text of the current branch'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchText');
extension
.addExpression(
'Variable',
_('Get dialogue state value'),
_('Get dialogue state value'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Variable Name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getVariable');
extension
.addCondition(
'Is command called',
_('Command is called'),
_('Check if a specific Command is called. If it is a <<command withParameter>>, you can even get the parameter with the CommandParameter expression.'),
_('Command <<_PARAM0_>> is called'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Command String'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isCommandCalled');
extension
.addCondition(
'IsDialogueLineType',
_('The dialogue line type is'),
_('Check if the the current dialogue line line is one of the three existing types. Use this to set what logic is executed for each type.\nThe three types are as follows:\n- text: when displaying dialogue text.\n- options: when displaying [[branching/options]] for dialogue choices.\n-command: when <<commands>> are triggered by the dialogue data.'),
_('The dialogue line is _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('stringWithSelector', _('type'), '["text", "options", "command"]', false)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isDialogueLineType');
extension
.addCondition(
'Is running',
_('Is running'),
_('Check if the dialogue is running. Use this to for things like locking the player movement while speaking with a non player character.'),
_('Is running'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isRunning');
extension
.addCondition(
'HasBranch',
_('Dialogue has branch'),
_('Check if the dialogue has a branch with specified name. Use this to check if a dialogue branch exists in the loaded dialogue data.'),
_('Dialogue has a branch named _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Branch name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasDialogueBranch');
extension
.addCondition(
'HasSelectedOptionChanged',
_('Has selected option changed'),
_('Check if a selected option has changed when the current dialogue line type is options. Use this to detect when the player has selected another option, so you can re-draw where the selection arrow is.'),
_('Has selected option changed'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasSelectedOptionChanged');
extension
.addCondition(
'Current branch title is',
_('Current dialogue branch title is'),
_('Check if the current dialogue branch title is equal to a string. Use this to trigger game events when the player has visited a specific dialogue branch.'),
_('The current dialogue branch title is _PARAM0_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('title name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchTitleIs');
extension
.addCondition(
'Current branch contains Tag',
_('Current dialogue branch contains a tag'),
_('Check if the current dialogue branch contains a specific tag. Tags are an alternative useful way to <<commands>> to drive game logic with the dialogue data.'),
_('The current dialogue branch contains a _PARAM0_ tag'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('tag name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchContainsTag');
extension
.addCondition(
'Branch has been visited before',
_('Branch title has been visited before'),
_('Check if the current branch has been visited before'),
_('Branch title _PARAM0_ has been visited before'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('branch title'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchTitleHasBeenVisited');
extension
.addCondition(
'Compare dialogue state variable',
_('Compare dialogue state variable'),
_('Compare dialogue state variable. Use this to trigger game events via dialogue variables.'),
_('Dialogue state variable _PARAM0_ is equal to _PARAM1_'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('State variable'))
.addParameter('string', _('Equal to'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.compareVariable');
extension
.addCondition(
'HasClippedTextScrollingCompleted',
_('Has clipped text scrolling completed'),
_('Check if the clipped text scrolling has completed. Use this to prevent the player from going to the next dialogue line before the typing effect has revealed the entire text.'),
_('Has clipped text scrolling completed'),
_('Dialogue Tree'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasClippedScrollingCompleted');
return extension;
},
runExtensionSanityTests: function(gd, extension) {
return [];
},
};

11
Extensions/DialogueTree/bondage.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,609 @@
/**
* @memberof gdjs
* @class dialogueTree
* @static
* @private
*/
gdjs.dialogueTree = {};
gdjs.dialogueTree.runner = new bondage.Runner();
/**
* Load the Dialogue Tree data of the game. Initialize The Dialogue Tree, so as it can be used in the game.
* @param {gdjs.Variable} sceneVar The variable to load the Dialogue tree data from. The data is a JSON string, created by Yarn.
* @param {string} startDialogueNode The Dialogue Branch to start the Dialogue Tree from. If left empty, the data will only be loaded, but can later be initialized via another action
*/
gdjs.dialogueTree.loadFromSceneVariable = function(
sceneVar,
startDialogueNode
) {
this.runner = gdjs.dialogueTree.runner;
try {
this.yarnData = JSON.parse(sceneVar.getAsString());
this.runner.load(this.yarnData);
if (startDialogueNode && startDialogueNode.length > 0) {
gdjs.dialogueTree.startFrom(startDialogueNode);
}
} catch (e) {
console.error(e);
}
};
/**
* Load the Dialogue Tree data from a JSON resource.
*
* @param {gdjs.RuntimeScene} runtimeScene The scene where the dialogue is running.
* @param {string} jsonResourceName The JSON resource where to load the Dialogue Tree data from. The data is a JSON string usually created with [Yarn Dialogue Editor](https://github.com/InfiniteAmmoInc/Yarn).
* @param {string} startDialogueNode The Dialogue Branch to start the Dialogue Tree from. If left empty, the data will only be loaded, but can later be initialized via another action
*/
gdjs.dialogueTree.loadFromJsonFile = function(
runtimeScene,
jsonResourceName,
startDialogueNode
) {
runtimeScene
.getGame()
.getJsonManager()
.loadJson(jsonResourceName, function(error, content) {
if (error) {
console.error("An error happened while loading JSON resource:", error);
} else {
if (!content) return;
gdjs.dialogueTree.yarnData = content;
gdjs.dialogueTree.runner.load(gdjs.dialogueTree.yarnData);
if (startDialogueNode && startDialogueNode.length > 0) {
gdjs.dialogueTree.startFrom(startDialogueNode);
}
}
});
};
/**
* Check if the Dialogue Tree is currently parsing data.
* For example, you can do things like disabling player movement while talking to a NPC.
*/
gdjs.dialogueTree.isRunning = function() {
return this.dialogueIsRunning;
};
/**
* Scroll the clipped text. This can be combined with a timer and user input to control how fast the dialogue line text is scrolling.
*/
gdjs.dialogueTree.scrollClippedText = function() {
if (this.pauseScrolling || !this.dialogueIsRunning) return;
if (this.dialogueText) {
this.clipTextEnd += 1;
}
};
/**
* Check if text scrolling has completed.
* Useful to prevent the user from skipping to next line before the current one has been printed fully.
*/
gdjs.dialogueTree.hasClippedScrollingCompleted = function() {
if (this.dialogueData && this.dialogueText.length) {
return this.clipTextEnd >= this.dialogueText.length;
}
return false;
};
/**
* Get the current dialogue line with a scrolling effect (recommended).
* Used with the scrollClippedText to achieve a classic scrolling text, as well as any <<wait>> effects to pause scrolling.
*/
gdjs.dialogueTree.getClippedLineText = function() {
return this.dialogueText.length
? this.dialogueText.substring(0, this.clipTextEnd)
: "";
};
/**
* Get the current complete dialogue line without using any scrolling effects.
* Note that using this instead getClippedLineText will skip any <<wait>> commands entirely.
*/
gdjs.dialogueTree.getLineText = function() {
this.clipTextEnd = this.dialogueText.length;
return this.dialogueText.length ? this.dialogueText : "";
};
/**
* Get the number of command parameters in a command with parameters that has been caught by a isCommandCalled condition
*/
gdjs.dialogueTree.commandParametersCount = function() {
if (this.commandParameters && this.commandParameters.length > 1) {
return this.commandParameters.length - 1;
}
return 0;
};
/**
* Get a command parameter in any command with parameters that has been caught by a isCommandCalled condition
* @param {number} paramIndex The index of the parameter to get.
*/
gdjs.dialogueTree.getCommandParameter = function(paramIndex) {
if (
this.commandParameters &&
this.commandParameters.length >= paramIndex + 1
) {
var returnedParam = this.commandParameters[paramIndex + 1];
return returnedParam ? returnedParam : "";
}
return "";
};
/**
* Catch <<commands>> and <<commands with parameters>> from the current Dialogue Line.
* You can trigger custom logic that relate to the story you are telling during the dialogue.
*
* @param {string} command The command you want to check for being called. Write it without the `<<>>`.
*/
gdjs.dialogueTree.isCommandCalled = function(command) {
var commandCalls = gdjs.dialogueTree.commandCalls;
var clipTextEnd = gdjs.dialogueTree.clipTextEnd;
var dialogueText = gdjs.dialogueTree.dialogueText;
if (this.pauseScrolling || !commandCalls) return false;
return this.commandCalls.some(function(call, index) {
if (clipTextEnd < call.time) return false;
if (call.cmd === "wait" && clipTextEnd !== dialogueText.length) {
gdjs.dialogueTree.pauseScrolling = true;
setTimeout(function() {
gdjs.dialogueTree.pauseScrolling = false;
commandCalls.splice(index, 1);
}, parseInt(call.params[1], 10));
}
if (call.cmd === command) {
gdjs.dialogueTree.commandParameters = call.params;
commandCalls.splice(index, 1);
return true;
}
});
};
/**
* Internal method to allow for capping option selection.
* @private
*/
gdjs.dialogueTree._normalizedOptionIndex = function(optionIndex) {
if (optionIndex >= this.options.length) optionIndex = this.options.length - 1;
if (optionIndex < 0) optionIndex = 0;
return optionIndex;
};
/**
* Internal method to allow for cycling option selection.
* @private
*/
gdjs.dialogueTree._cycledOptionIndex = function(optionIndex) {
if (optionIndex >= this.options.length) optionIndex = 0;
if (optionIndex < 0) optionIndex = this.options.length - 1;
return optionIndex;
};
/**
* Get the text of an option the player can select.
* Used with getLineOptionsCount to render options for the player when a line of the Options type is parsed
* @param {number} optionIndex The index of the option you want to get
*/
gdjs.dialogueTree.getLineOption = function(optionIndex) {
if (!this.options.length) return [];
optionIndex = gdjs.dialogueTree._normalizedOptionIndex(optionIndex);
return this.options[optionIndex];
};
/**
* Get the number of options that are presented to the player, during the parsing of an Options type line.
* @returns {number} The number of options
*/
gdjs.dialogueTree.getLineOptionsCount = function() {
if (this.options.length) {
return this.optionsCount;
}
return 0;
};
/**
* Confirm the currently selected option, during the parsing of an Options type line.
*
* This will advance the dialogue tree to the dialogue branch was selected by the player.
*/
gdjs.dialogueTree.confirmSelectOption = function() {
if (
this.dialogueData.select &&
!this.selectedOptionUpdated &&
this.selectedOption !== -1
) {
this.commandCalls = [];
this.dialogueData.select(this.selectedOption);
this.dialogueData = this.dialogue.next().value;
gdjs.dialogueTree.goToNextDialogueLine();
}
};
/**
* Select next option during Options type line parsing. Hook this to your game input.
*/
gdjs.dialogueTree.selectNextOption = function() {
if (this.dialogueData.select) {
this.selectedOption += 1;
this.selectedOption = gdjs.dialogueTree._cycledOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Select previous option during Options type line parsing. Hook this to your game input.
*/
gdjs.dialogueTree.selectPreviousOption = function() {
if (this.dialogueData.select) {
this.selectedOption -= 1;
this.selectedOption = gdjs.dialogueTree._cycledOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Select option by index during Options type line parsing.
* @param {number} optionIndex The index of the option to select
*/
gdjs.dialogueTree.selectOption = function(optionIndex) {
if (this.dialogueData.select) {
this.selectedOption = gdjs.dialogueTree._normalizedOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Get the currently selected option
* @returns {number} The index of the currently selected option
*/
gdjs.dialogueTree.getSelectedOption = function() {
if (this.dialogueData.select) {
return this.selectedOption;
}
return 0;
};
/**
* Check when the player has changed option selection since the last call to this function.
*
* Can be used to re-render your displayed dialogue options when needed.
*
* @returns {boolean} true if the selected option was updated since the last call to this function
*/
gdjs.dialogueTree.hasSelectedOptionChanged = function() {
if (this.selectedOptionUpdated) {
this.selectedOptionUpdated = false;
if (this.selectedOption === -1) this.selectedOption = 0;
return true;
}
return false;
};
/**
* Check the type of the Dialogue Line that is being displayed to the player at the moment.
*
* There are three types:
* - text - regular dialogue text is being parsed at the moment
* - options - the player has reached a branching choise moment where they must select one of multiple options
* - command - a <<command>> was called in the background, that can be used to trigger game events, but will not be displayed in the dialogue box.
*
* @param {string} type The type you want to check for ( one of the three above )
*/
gdjs.dialogueTree.isDialogueLineType = function(type) {
if (
this.commandCalls &&
this.commandCalls.some(function(call) {
return gdjs.dialogueTree.clipTextEnd > call.time;
})
) {
return true;
}
return this.dialogueIsRunning ? this.dialogueDataType === type : false;
};
/**
* Check if a branch exists. It is also used internaly whenever you use the start from action.
* @param {string} branchName The Dialogue Branch name you want to check.
*/
gdjs.dialogueTree.hasDialogueBranch = function(branchName) {
return (
this.runner &&
this.runner.yarnNodes &&
Object.keys(this.runner.yarnNodes).some(function(node) {
return node === branchName;
})
);
};
/**
* Start parsing dialogue from a specified Dialogue tree branch.
* Can be used if you want to store multiple dialogues inside a single Dialogue tree data set.
* @param {string} startDialogueNode The Dialogue Branch name you want to start parsing from.
*/
gdjs.dialogueTree.startFrom = function(startDialogueNode) {
this.runner = gdjs.dialogueTree.runner;
if (!this.hasDialogueBranch(startDialogueNode)) return;
this.optionsCount = 0;
this.options = [];
this.dialogueBranchTitle = "";
this.dialogueBranchBody = "";
this.dialogueBranchTags = [];
this.tagParameters = [];
this.dialogue = this.runner.run(startDialogueNode);
this.dialogueData = null;
this.dialogueDataType = "";
this.dialogueText = "";
this.commandCalls = [];
this.commandParameters = [];
this.pauseScrolling = false;
this.dialogueData = this.dialogue.next().value;
this.dialogueIsRunning = true;
gdjs.dialogueTree.goToNextDialogueLine();
};
/**
* Internal methods to check the type of a Dialogue Line
*/
gdjs.dialogueTree._isLineTypeText = function() {
return this.dialogueData instanceof bondage.TextResult;
};
gdjs.dialogueTree._isLineTypeOptions = function() {
return this.dialogueData instanceof bondage.OptionsResult;
};
gdjs.dialogueTree._isLineTypeCommand = function() {
return this.dialogueData instanceof bondage.CommandResult;
};
/**
* This is the main lifecycle function.It runs once only when the user is advancing the dialogue to the next line.
* Progress Dialogue to the next line. Hook it to your game input.
* Note that this action can be influenced by any <<wait>> commands, but they work only if you have at least one isCommandCalled condition.
*/
gdjs.dialogueTree.goToNextDialogueLine = function() {
if (this.pauseScrolling || !this.dialogueIsRunning) return;
this.optionsCount = 0;
this.selectedOption = -1;
this.selectedOptionUpdated = false;
if (gdjs.dialogueTree._isLineTypeText()) {
if (
this.dialogueDataType === "options" ||
this.dialogueDataType === "text" ||
!this.dialogueDataType
) {
this.clipTextEnd = 0;
this.dialogueText = this.dialogueData.text;
this.commandCalls = [];
} else {
this.dialogueText += this.dialogueData.text;
}
this.dialogueDataType = "text";
this.dialogueBranchTags = this.dialogueData.data.tags;
this.dialogueBranchTitle = this.dialogueData.data.title;
this.dialogueBranchBody = this.dialogueData.data.body;
this.dialogueData = this.dialogue.next().value;
} else if (gdjs.dialogueTree._isLineTypeOptions()) {
this.dialogueDataType = "options";
this.optionsCount = this.dialogueData.options.length;
this.options = this.dialogueData.options;
this.selectedOptionUpdated = true;
} else if (gdjs.dialogueTree._isLineTypeCommand()) {
this.dialogueDataType = "command";
var command = this.dialogueData.text.split(" ");
// If last command was to wait, increase time by one
var offsetTime =
this.commandCalls.length &&
this.commandCalls[this.commandCalls.length - 1].cmd === "wait"
? 1
: 0;
this.commandCalls.push({
cmd: command[0],
params: command,
time: this.dialogueText.length + offsetTime
});
this.dialogueData = this.dialogue.next().value;
gdjs.dialogueTree.goToNextDialogueLine();
} else {
this.dialogueDataType = "unknown";
}
if (gdjs.dialogueTree._isLineTypeCommand()) {
this.dialogueDataType = "command";
gdjs.dialogueTree.goToNextDialogueLine();
}
// Dialogue has finished
if (!this.dialogueData) {
this.dialogueIsRunning = false;
}
};
/**
* Get the current Dialogue Tree branch title.
* @returns {string} The current branch title.
*/
gdjs.dialogueTree.getBranchTitle = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchTitle;
}
return "";
};
/**
* Check if the currently parsed Dialogue branch title is a query.
* @param {string} title The Dialogue Branch name you want to check for.
*/
gdjs.dialogueTree.branchTitleIs = function(title) {
if (this.dialogueIsRunning) {
return this.dialogueBranchTitle === title;
}
return false;
};
/**
* Get all the branch tags from the current Dialogue branch as a string. Useful for debugging.
* @returns {string} The current branch tags, separated by a comma.
*/
gdjs.dialogueTree.getBranchTags = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchTags.join(",");
}
return "";
};
/**
* Get one of the current Dialogue branch tags via index.
* @param {number} index The index of the Dialogue Branch tag you want to get.
* @returns {string} The branch tag at the specified index, or an empty string if not found.
*/
gdjs.dialogueTree.getBranchTag = function(index) {
if (this.dialogueIsRunning && this.dialogueBranchTags.length) {
if (index > this.dialogueBranchTags.length - 1)
index = this.dialogueBranchTags.length - 1;
return this.dialogueBranchTags[index];
}
return "";
};
/**
* Check if the current Dialogue branch contains a specific tag.
* @param {string} query The name of the Dialogue Branch tag you want to check.
*/
gdjs.dialogueTree.branchContainsTag = function(query) {
this.tagParameters = [];
if (this.dialogueIsRunning && this.dialogueBranchTags.length) {
return this.dialogueBranchTags.some(function(tag) {
var splitTag = tag.match(/([^\(]+)\(([^\)]+)\)/i);
gdjs.dialogueTree.tagParameters = splitTag ? splitTag[2].split(",") : [];
return splitTag ? splitTag[1] === query : tag === query;
});
}
return false;
};
/**
* Get any tag(parameter,anotherParameter) from a tag captured by the branchContainsTag Condition
* @param {number} paramIndex The index of the tag parameter you want to get.
* Leaving this empty will result in retrieving the first parameter.
*/
gdjs.dialogueTree.getTagParameter = function(paramIndex) {
if (this.dialogueIsRunning && this.tagParameters.length >= paramIndex) {
var returnedParam = this.tagParameters[paramIndex];
return returnedParam ? returnedParam : "";
}
return "";
};
/**
* Get a list of all the titles of visited by the player Branches. Useful for debugging.
*/
gdjs.dialogueTree.getVisitedBranchTitles = function() {
if (this.dialogueIsRunning) {
return Object.keys(this.runner.visited).join(",");
}
return "";
};
/**
* Check if a player has visited a Dialogue Branch in the past.
* @param {string} title The title of the branch to check for.
* Leaving this empty will check if the current branch title has been visited in the past.
*/
gdjs.dialogueTree.branchTitleHasBeenVisited = function(title) {
if (!title) title = this.dialogueBranchTitle;
return (
Object.keys(this.runner.visited).includes(title) &&
this.runner.visited[title]
);
};
/**
* Get the entire unparsed text of the current Dialogue Branch
*/
gdjs.dialogueTree.getBranchText = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchBody;
}
return "";
};
/**
* Get the value of a variable that was created by the Dialogue parses.
* @param {string} key The name of the variable you want to get the value of
*/
gdjs.dialogueTree.getVariable = function(key) {
if (this.dialogueIsRunning && key in this.runner.variables.data) {
return this.runner.variables.data[key];
}
return "";
};
/**
* Check if a specific variable created by the Dialogue parses exists and is equal to a specific value.
* @param {string} key The name of the variable you want to check the value of
* @param {string} value The value you want to check against
*/
gdjs.dialogueTree.compareVariable = function(key, value) {
if (this.dialogueIsRunning && key in this.runner.variables.data) {
return this.runner.variables.data[key].toString() === value;
}
return false;
};
/**
* Set a specific variable created by the Dialogue parser to a specific value.
* @param {string} key The name of the variable you want to set the value of
* @param {string} value The value you want to set
*/
gdjs.dialogueTree.setVariable = function(key, value) {
if (this.dialogueIsRunning && this.runner.variables.data) {
this.runner.variables.data[key] = value;
}
};
/**
* Store the current State of the Dialogue Parser in a specified variable.
* Can be used to implement persistence in dialogue through your game's Load/Save function.
* That way you can later load all the dialogue choices the player has made.
* @param {gdjs.Variable} outputVariable The variable where to store the State
*/
gdjs.dialogueTree.saveState = function(outputVariable) {
const dialogueState = {
variables: gdjs.dialogueTree.runner.variables.data,
visited: gdjs.dialogueTree.runner.visited
};
gdjs.evtTools.network._objectToVariable(dialogueState, outputVariable);
};
/**
* Load the current State of the Dialogue Parser from a specified variable.
* Can be used to implement persistence in dialogue through your game's Load/Save function.
* That way you can later load all the dialogue choices the player has made.
* @param {gdjs.Variable} inputVariable The variable where to load the State from.
*/
gdjs.dialogueTree.loadState = function(inputVariable) {
const jsonData = gdjs.evtTools.network.variableStructureToJSON(inputVariable);
try {
const loadedState = JSON.parse(
gdjs.evtTools.network.variableStructureToJSON(inputVariable)
);
gdjs.dialogueTree.runner.visited = loadedState.visited;
gdjs.dialogueTree.runner.variables.data = loadedState.variables;
} catch (e) {
console.error(e);
}
};

View File

@@ -0,0 +1,81 @@
[
{
"title": "Numeric",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = -123.4>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},{
"title": "NumericExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = (1 + 2) * -3 + 4.3>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "String",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = \"Variable String\">>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "StringExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = \"Variable String\" + \" Appended\">>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Boolean",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = true>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BooleanExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = (true || false) && (false || !false)>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Variable",
"tags": "Tag",
"body": "Test Line\n<<set $firstvar = \"First variable string\">><<set $secondvar = $firstvar>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VariableExpression",
"tags": "Tag",
"body": "Test Line\n<<set $firstvar = 100>><<set $secondvar = -4.3 + $firstvar>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,52 @@
[
{
"title": "BasicCommands",
"tags": "Tag",
"body": "<<command>>text in between commands<<command with space>> <<callFunction()>> <<callFunctionWithParam(\"test\",true,1,12.5,[2,3])>>",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "StopCommand",
"tags": "Tag",
"body": "First line\n<<stop>>\nThis shouldn't show",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "FunctionConditional",
"tags": "Tag",
"body": "First line\n<<if testfunc(\"firstarg\")>>This shouldn't show<<elseif testfunc(\"firstarg\", \"secondarg\")>>This should show<<endif>>After both",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VisitedFunction",
"tags": "Tag",
"body": "<<if visited(\"VisitedFunctionStart\")>>you have visited VisitedFunctionStart!<<endif>><<if visited(\"SomeOtherNode\")>>You have not visited SomeOtherNode!<<endif>>",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VisitedFunctionStart",
"tags": "Tag",
"body": "Hello[[VisitedFunction]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,93 @@
[
{
"title": "Start",
"tags": "Tag",
"body": "What are you?\n-> A troll\n <<set $troll to true >>\n-> A nice person\n <<set $troll to false >>\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective",
"tags": "Tag",
"body": "<<if $repeat >= 3>>\nBye...\n<<else>>\nIs your objective clear?\n[[Yes|Objective.Yes]]\n[[No|Objective.No]]\n<<if $troll == true>>\n[[Maybe|Objective.Maybe]]\n<<endif>>\n<<endif>>\n",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.No",
"tags": "Tag",
"body": "Blah blah blah blah\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.Yes",
"tags": "Tag",
"body": "Good let's start the mission.",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.Maybe",
"tags": "Tag",
"body": "Are you trolling me?\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIf",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 321>>Inside if<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElse",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<else>>Inside else<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElseIf",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<elseif $testvar == 321>>Inside elseif<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElseIfElse",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<elseif $testvar == 1>>Inside elseif<<else>>Inside else<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,72 @@
[
{
"title": "OneNode",
"tags": "Tag",
"body": "This is a test line",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "ThreeNodes",
"tags": "",
"body": "This is a test line\nThis is another test line[[Option1]]\n[[Option2]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Option1",
"tags": "",
"body": "This is Option1's test line",
"position": {
"x": 770,
"y": 84
},
"colorID": 0
},
{
"title": "Option2",
"tags": "",
"body": "This is Option2's test line",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "NamedLink",
"tags": "",
"body": "This is a test line\nThis is another test line\n[[First choice|Option1]]\n[[Second choice|Option2]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "OneLinkPassthrough",
"tags": "",
"body": "First test line\n[[Option1]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "LinkAfterShortcuts",
"tags": "",
"body": "First test line\n-> Shortcut 1\n\tThis is the first shortcut\n-> Shortcut 2\n\tThis is the second shortcut\n[[First link|Option1]][[Second link|Option2]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
}
]

View File

@@ -0,0 +1,32 @@
[
{
"title": "NonNested",
"tags": "Tag",
"body": "This is a test line\n-> Option 1\n\tThis is the first option\n-> Option 2\n\tThis is the second option\nThis is after both options",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Nested",
"tags": "Tag",
"body": "text\n-> shortcut1\n\tText1\n\t-> nestedshortcut1\n\t\tNestedText1\n\t-> nestedshortcut2\n\t\tNestedText2\n-> shortcut2\n\tText2\nmore text",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Conditional",
"tags": "Tag",
"body": "This is a test line\n-> Option 1\n\tThis is the first option\n-> Option 2 <<if 1 == 0>>\n\tThis is the second option\n-> Option 3\n\tThis is the third option\nThis is after both options",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB