Getting down to brass tacks with the technology of telling a story
I am happy to say I spent last evening working on implementing the new NPC dialogue system; and using it to further a few of the quests we currently have in Revel Immortal.
It's going well, I can actually tell a story now...
We've always had some basic ideas of the stories we're planning to convey in Revel, but it's only been recently that we have been able to start implementing those stories to a greater degree.
Revel has several mechanics for story telling:
Quests - Named lists of descriptive objectives, by default quests are not started and may be started through various actions. Objectives may be evaluated and completed linearly or non-linearly; and each objective, and the quest itself, may fire other actions.
Dialogue - Conversation between the Player and NPCs in the form of player-chosen topics (qualified for visibility), with multiple NPC responses (qualified for validity, top-down), and (optional) user choosable Options (a player followup) for each response which can invoke actions.
Structures - Graphical elements in the world that can be activated by the player; activation may be qualified, and if qualification passes, associated actions are fired, making this a great construct for all manners of puzzles, traps, treasure chests, secrets, etc.
Story Flags - Named boolean values that exist in the world-space; ideal for retaining information that cant be naturally divined otherwise.
Actions & Qualifiers
You may have noticed I keep talking about Actions and Qualifiers; I've written a number of games that use general scripting to govern most mechanics of story telling; and in my experience this has ended up being very complicated, bug-prone and hard to keep consistent; especially with multiple designers.
...and of course completely uninteligable to those who don't program.
Revel uses a very simple architechture by comparison; at various points in the game data; certain objects contain collections of Actions, and or Qualifiers; they are assumed to be 'one-liners' of real code, designed to perform some end-effect on the game world; or ask a question; respectively.
//an example qualifier, where o is an 'environment context' return o.getQuestStarted("relicOfTheOldWorld");Using real code strikes a balance between full scripting, and a totally fixed-function system; or some sort of expression parser; and allows you to inline constant data where needed.
In general, a qualifier block is assumed to 'pass' when there are zero qualifiers that return false; (this means zero qualifiers means true); and action blocks are executed serially, top-down.
Noticable hotspots in the current setup...
After spending some time exploring the most recent changes to the system; hotspots or annoyances in the design tend to crop up, and are often good candidates for some refinement.
Recently as I delve deeper into implementing more complex quests, and as the data sizes grow I've found...
1. I really need quest-local story flags
There are many intermediate steps in completing some objectives; and often the only way to note that something has been done is to set a story flag; however story flags are global, which means there is huge potential for namespace polution (not in a code sense, but in a world data sense).
This leads to ad-hoc namespacing to make sure two designers wont accidentically collide flags.
In addition quest objectives are never directly /set/ to complete; objectives must have qualified completion (this is very important from a standpoint of emergent complexity); so you always need some way to express an objective should be complete, and often there is nothing to use but a one-off story flag.
So, I've decided that I will create quest-local 'quest flags' that require pre-defenition in the quest object, to provide a bit of auto-documentation.
2. Story Flags need pre-defenition
As I just mentioned about Quest-Flags; I really need to enforce pre-defenition of what story flags are in-play in the world; without that, it is impracticle to know what flags designers might be using, and collisions could occur. This aspect of self documentation is "a good thing" when developing a game this large.
3. Responses, not just options, need actions
At the moment, only quests, objectives, structures, dialogue options, and of course natural gameplay; can impart changes in the game world. This has left an obvious need for dialogue responses themselves to fire actions... take for example:
Some NPC: "I'll tell him you're looking for him."Based on this response, I would assume something in the world might change; but there is currently no ability to have a simple response effect such change. Only a follow-up option, which is user-optional (they can choose never to click it) could cause such change.
So, I will be adding an actions block to responses as well, so that on showing of a response, the designer can fire off actions.