Recently I was sidetracked from my main project to prototyping some sort of singleplayer RPG with elements of hardcore survival. And while doing so I realised that I have to make some quests and dialogues for it to classify as RPG so I started to dig in that direction. Eventually I came up with an conception of node-based dialogue editor though I yet have to find some time to implement it.
Realistically I will not manage to start coding this thing in near future so I’d like to ask what do you use when it comes to dialogue or quest building? Not UI part but model part consisting from text, states and transitions. Plain text files? XML? Some form of spreadsheet? Already existing visual editor with it’s own data format?
Goal of this thread is not to just get answer - it’s to discuss and refine knowledge about various approaches to this problem. And, ideally, as result we could end up with concept good enough to be contributed to JME if it ever to be implemented in code.
And to kick up this discussion, here is what I already came up with:
idea of node-based editor, much like shader node editor but with some differences
every node could contain some data and be freely linked to other nodes
node could be of two types - “request” and “response”, corresponding to what system tells to user and to what user could answer to system. For example, main menu of a game could be described as “request” and all menu buttons could be described as “responses”.
link from a request A to a response B means that response B could be given by user as answer to request A.
link from a response B to a request C means that response B leads to request C to be provided to user next.
node always have single input with unlimited inbound links and some used-defined outputs with one outbound link per output
node outputs could contain some filters or other expressions to be evaluated to choose if link from this output should be available based on current state.
so request node could have filters on outputs to block some responses from being available until some condition is met
and response node could have filters on outputs (actually it should have filters for more than one output to work) to lead user to different request from the same response, based on some conditions.
nodes could have some metadata and other stuff stored inside, not just limited to a plain text, so the same model could be loaded and used ingame with different display logic.
for interaction between model logic and game logic there could be something like “virtual cursor” or “state” pointing to current active request, if any and providing interface to sync data or dispatch events
there could be many “virtual cursors” on the same model simultaneously, allowing multiple players or situations when the same player participates in multiple dialogues at the same time (though multiple simultaneous quests for one player may be represented by just data instead and I think it’s more clean approach than having one “cursor” per quest per player).
“virtual cursor” always snaps to request and is capable to provide available responses, with or without evaluating filters on response outputs (so based on this data your game could, for example, provide player with all possible responses but grey out ones not available for player in current state)
“virtual cursor” could be provided with a response to current active request, effectively making it to move to corresponding next request, always evaluating filters on response outputs, if any.
“virtual cursor” could be forcefully moved to any request, ignoring links and filters
I know, it’s long, a bit messy and not very clear, but hope someone will manage to break trough it and participate in discussion :chimpanzee_winktongue:
I have done it like this:
There is an entity (an NPC) in the game world that contains a quest.
The quest contains a reward, the needed reputation of the player, a position needed to complete (if any) and some other small things.
I can then add this quest to a list of quests the player has. It gets set to the state “active”.
The completion is done over the eventbus, which seemed to be the easiest solution for me. E.g. if you have a quest “pick up item xy” then the quest listens on the eventbus for an event of the type QuestEvent which contains a string that could say “picked_up_item_ID”.
The quest is then set to “completed” and the rewards are applied.
The quests are created in a constructor as they all appear within entities which are created anyway.
I don’t know if it’s clear what I did or if it’s good, but it works for me and I hope I could help you.
Soon I will probably be publishing a dialog management layer… it even handles networking. It will have support for a simple groovy-based DSL for configuring standard dialogs (or pretty much any text + options based interaction you could need.)
Having modded a lot of games in the past, a dialog creation GUI is so annoying when all I want to do is type a lot of stuff. It’s no wonder that 90% of the ‘text game’ creators out there these days work directly from a text file style scripting language.
Advice: keep the handling of presentation and option display + selection separate from whatever structure you use to manage the dialogs themselves. a) it’s cleaner, b) you are likely to find that whatever structure you come up with doesn’t handle some case… and it’s nice to be able to fall back on the callbacks of the real layer.
Sounds interesting, @pspeed , I will look forward for it. Though, will not abandon my own idea as well - to have something to compare against.
Well, I hate all existing tools for dialog creation I know as well, that’s why I did non use any.
Maybe I should be a bit more clear about what architecture I have in mind for it:
Lowest layer contains raw data consisting from nodes, links and metadata in nodes, this layer is used mainly for storage as it even don’t recognize if a node is request or response
On top of that layer there is more advanced layer, understanding types of nodes and some restrictions like “one link per node output”, it’s used mainly for model editing as it already knows what could be put where and what could not. This layer is good in giving out all model or parts of it at once as well.
For ingame usage there is data access layer, based on iterator-like structure that I call “virtual cursor”. It’s not actual iterator as it moves not to next element in collection but rather to element linked trough specified element. And on top of that sits a version of “cursor” capable to store metadata provided by game logic and to evaluate expressions in filters against this metadata (it should really be a part of game logic actually, so it may be abandoned as I start coding things, leaving only traversing version of “cursor” capable to move along links and give out current node and nodes behind outgoing links).
Final display layer is completely up to game/editor logic. GUI dialogue editor will not even use data access layer here most of the time.
And to think about it - I don’t like supporting some crazy stuff like polymorphic quests capable to change data model on the go so read only mode it is. Only two exceptions are debug mode identical to free edit mode and dynamical dialogues generation system, capable to add or remove entire dialogues on fly, but not to edit them I think.
Oh, one final thing is localization - my plan leaves actual display to game logic so it could be used independently from whether metadata contains plain text or localization keys for game logic to replace with real text. But when it comes to real code chances are that I’ll include some optional localization system in it for my own usage.
Did not think about networking, though - there may be some unexpected trash involved.
Sorry for bumping this but I found the coolest related thing today called Yarn. It appears to be a tool with which you can visually build conversations that export into .json .xml and something called .twee. The only thing left is to load it into java yourself.
And it’s under the MIT license I don’t think it gets any better than this.
Nothing wrong in bumping this thread, it’s meant to be bumped for additional discussion.
Yarn looks like a nice tool but I don’t like it. It makes you to write every transition in text meaning that you have to give unique name to every node. And there are too many actions needed if one “just wants to write down tons of text” - create node, open it, write down this part of text, exit node, or you go and write json stuff directly, completely defeating purpose of editor. So it don’t suit both types of people - ones who prefer writing small portions of text here and there to link them later visually and ones who prefer to type a lot and get result in one go.
The way I prefer it to be in editor looks like this:
User enters text without any special markup - just raw chunks of text separated by something simple like double empty line. It may be a file or input window, it may contain some display markup for future use in game or be a plain text - for editor it does not matter.
Raw text then will be converted to nodes, every chunk goes to a separate node.
After finishing writing down a text user starts to mark nodes as inputs or outputs and defines links between them. There is no logic at this stage, just all possible transitions defined and nodes properly marked as input or output.
And only then user starts to refine nodes structure he have - adding metadata required by game or conditions to transitions or conditions to make transition available or whatever. This could be done by different person, not one responsible for writing the “story” and linking nodes.
At any time additional nodes could be imported from raw text and added to node tree without creating them one by one manually.
For localization needs it should be possible to automatically generate localization keys for every node and manually edit them if necessary or to export all texts as key-value pairs or to replace current texts by localized ones from file containing key-value pairs.
Comments everywhere - it should be possible to place comments to nodes, to groups of nodes, without nodes, inside nodes and even to transition arrows.
Do you still think it can’t get better than Yarn and Twine?
And I have even more cool feature in mind - something I call “story flow input mode”:
User writes down single thread of story as it goes, without thinking about branches and it translates to already connected chain of nodes.
User selects any node and starts writing down more text - new nodes will be linked to one currently selected as a new chain. Alternatively new nodes could be all connected directly to selected one if corresponding mode is enabled.
User could drag any existing node to input window and text from that node will appear in input window, effectively including that node in new node chain without breaking existing transitions. Alternatively node could be dragged with Shift key pressed and text will be copied instead of making link to it, resulting in creation of new node instead of adding transitions to existing one. Alternatively “story flow input mode” could change controls, turning double click on node into a way to take it to input window instead of opening node details.
User could select node chain and take them all to input window in one go, to rewrite said chain or to make full copy of it with some changes.