3
\$\begingroup\$

I'm currently working on a scriptable questing system. As for scripting, I will probably use JavaScript, but I'd appreciate some help with the design of the system. My first attempt essentially resulted in something which was way too complicated to script, and wasn't plausible at all.

My objectives for the system are as follows:

  • Branchable (probably not a real word) - So there can be multiple different outcomes for the same objective depending on what the player chooses, and their choices will affect which quests they move onto next.
  • Not ridiculously complicated.

Obviously, I'm not here to be given a list of everything I need to do. Ideally, I'd like some tips on how to store progression and a basic idea of how branching would work.

Some details: I'm writing in Java, and I ideally want there to be many options in terms of types of objectives. I can implement these easily enough - my problem is more the structure of a quest. I'm writing the quest system on top of an already existing game - said game uses LWJGL and does it's own engine-stuff, it doesn't use an engine.

\$\endgroup\$
  • \$\begingroup\$ What language/engine/middleware/etc. are you using? \$\endgroup\$ – Selali Adobor Aug 12 '14 at 11:38
  • \$\begingroup\$ What specifically in Java are you using to make the game? \$\endgroup\$ – Selali Adobor Aug 12 '14 at 11:43
  • \$\begingroup\$ Added language to the question and tried to make it a little more specific with the last part - Java. \$\endgroup\$ – DziNeIT Aug 12 '14 at 11:43
  • \$\begingroup\$ It would be helpful when you would elaborate about how your first attempt worked and what flaws you recognized. That way we would have a better idea what you are actually looking for. \$\endgroup\$ – Philipp Aug 12 '14 at 15:19
5
\$\begingroup\$

A common way to implement states and branching in a quest is through quest variables. I have witnessed this technique in many RPG titles from companies like Bioware or Bethesda. This is also what I am doing in my current project, and so far it works really well.

Just add a script binding which allows scripts to store values in variables and later retrieve them. Also allow events in the game to set these variables (entering an area, killing a specific enemy etc).

This already allows you to do some nice things. In javascript, this could look like this:

function talkToDragonQuestGiver(user) {
     var dragonQuestState = user.getVar("DragonQuest")
     switch (dragonQuestState) {

         case null:
             say("Go, slay the dragon and I will reward you.");
             user.setVar("DragonQuest", "active");
             break;
         case "active":
             say("What are you doing here? You have a dragon to slay!");
             break;
         case "dragonDead":                 
             say("You have slain the dragon. Here, have this bragging rights reward.");
             user.giveItem("Sword of Awesomeness +10");
             user.setVar("DragonQuest", "over");
             user.setVar("isKiller", true);
             break;
         case "dragonHugged":
             say("You were supposed to slay the dragon, not hug it. Have this piece of junk.");
             user.giveItem("Headband of the lame Hippie +5");
             user.setVar("DragonQuest", "over");
             user.setVar("isHippie", true);
             break;
         case "over":
             if (user.getVar("isKiller")) {
                 say("Because you like killing things, I have another thing for you to kill...");
                 /* ... */
             }
             if (user.getVar("isHippie")) {
                 say("Because you hate violence so much, I have another peaceful task for you...");
                 /* ... */
             }
             break;
     }
}
\$\endgroup\$
3
\$\begingroup\$

I want to say, one of the other answers at the time of writing are suggesting "hard-coding" these events in your language. An alternative approach that can be pretty powerful is using an external format like XML, or a DSL (this is somewhat similar to the script binding approach) to define these events. Then you can easily an editor that outputs it. An example (this example would probably have a matching XSD document, but for simplicity it's left out):

Define a quest in the editor, and it saves something like:

<quest name="FirstQuest">
    <unlocks condition="dragonSlayed">
        <newquest name="SecondQuest"/>
        <item name="Good Sword" quantity=1/>
    </unlocks>
    <unlocks condition="goodGuySlayed">
        <newquest name="OtherQuest"/>
        <item name="Evil Sword" quantity=1/>
    </unlocks>
</quest>

Define a dialogue sequence and it saves something like:

<dialogue name="Bystander Dialogue">
  <messagetree condition="dragonSlayed">
     <event type="Message">Thanks for the help!</message>
     <event type="Message">You have a good sword!</message>
     <event type="AddKarma">100</event>
  </messagetree>
  <messagetree condition="goodGuySlayed">
     <event type="Message">What have you done?</message>
     <event type="Message">You have a good evil!</message>
     <event type="AddKarma">-100</event>
  </messagetree>
</dialogue>

The benefits of something like this is that you can make changes outside of your programming language, but I'd still recommend a simple editor to validate something like this.

\$\endgroup\$
  • \$\begingroup\$ I'd +1 this if I had enough reputation. I was actually considering the possibility of something like XML / YML, so this is interesting to me. \$\endgroup\$ – DziNeIT Aug 13 '14 at 10:43
-1
\$\begingroup\$

I'm not exactly sure if this would fit in with JavaScript, I'm always on C++ so there will be differences.

Since it's a quest system then I'll just assume it's a RPG and give an answer with that theme.

quest: "press A or B"

Rewards: A-100 gold; B- 200 gold

The scenario now has 2 outcomes, pressing A get's you into branch 1 while pressing B get's you into branch 2.

I'm not that familiar with javascript so I can't give you a sample code from that language.

I usually make a boolean, let's name is alpha and beta, and let's make another one namely, check.

Oh we also have an integer to act as the storage of gold.

I suppose you're already familiar as too how reading inputs would work.

if(input press for A from the keboard && !checked)
{
alpha = true;
checked = true;
gold += 100;
}

else if(input press for B && !checked)
{
beta = true;
checked = true;
gold += 100;
}

Let's start discussion with alpha, to get alpha to become "true", there are 2 pre-requisites. One is to press "A" on the keyboard while the other is to have checked = false.

checked = false;

is the most important part, if you don't have that then the program won't understant if the player has already the other button, thus, making a glitch and allowing the player to press the button again and again while reaping the rewards.

Now, you have the basics. You can further branch this off by using booleans or by nesting the branches inside the original branch, though I would recommend using some sort of boolean, int, etc. to make the script more organized.

if(input press for A from the keboard && !checked)
{
alpha = true;
checked = true;
gold += 100;
second = true;
}

As you can see, there is another bool there named "second".

if(second) //will only start if second == true
//you can now fill in the events here
\$\endgroup\$
  • \$\begingroup\$ I'd personally say that a solution like this would become very unruly very quickly. There are better layers of abstraction than directly tying in each quest with input, in-game values, and every other quest. \$\endgroup\$ – Selali Adobor Aug 13 '14 at 0:31
  • \$\begingroup\$ I was actually having trouble trying to make another user, who's using a different language, understand this. Basing on the question, you could get an idea that this person might not be someone familiar with these stuff, that's why my example was just a basic type. I actually prefer making and using primitive quest engines rather than fill in inputs one by one, that way, you could minimize typing and make the code easier on the eyes. \$\endgroup\$ – kdyz Aug 13 '14 at 8:23
  • \$\begingroup\$ Even for a simplified approach I find this approach to be very impractical. If someone tries to implement a quest system this way, no matter how advanced or basic their skills, this is approach is unsustainable. The only way something like this could be used is within snippets for a scripting engine of some sort, but even then the concept of a "quest" would still need to be better defined. And the skills needed to implement a scripting engine wouldn't be trivial either. \$\endgroup\$ – Selali Adobor Aug 13 '14 at 8:53
  • \$\begingroup\$ Okay, okay. I'll give in, it was wrong of me, in the first place, to actually try to respond to a question that originates from a language I don't use. I can't really compete with a person who uses that language. But to say that this approach is unsustainable? it actually is another version of the switch statement, it would be highly sustainable enough given that you know how to handle memory leaks that could occur from destroyed textures or objects recalled from within, the negative side would be the increased complexity from when a complex scenario arises, which I don't fore come. \$\endgroup\$ – kdyz Aug 13 '14 at 11:23
-1
\$\begingroup\$

Actually I think your question is first too broad, so is hard to provide any valuable feedback, and second primarily opinion based. Still, I will pitch my ball.

Are you familiar with Formal Grammars in the context of computer science? If you organize terminal symbols as missions or objectives, non-terminal symbols as decisions and production rules as outcomes, I think you can create a system able to procedurally create quests in a minimal coherent sense.

Sorry for not being too specific, broad questions make for broad answers.

EDIT: A little background to elaborate.

Formal Grammars describe how to form words in a language based on rules. For instance you have a language formed by the letters 'a' and 'b', and a set of rules describe how to form valid words in that language. The key point is that at an abstract level this is a very powerful concept.

In you case your symbols are steps in a quest, and the 'words' are complete quests. For instance if symbol 'a' means 'kill monster x' and b means 'get item y', the word 'abb' would mean 'first kill monster x, then get items y and z'.

By using production rules you can generate meaningful quests comprised of individual steps. With rules you can control that the steps are performed in an order that makes sense, and by choosing what rules to apply randomly, you make sure that you always get different variations on the quest. Also by using some more advance concepts such as contextual grammars, you can make a quest system that actually accounts for the outcomes of the steps and diverges based on that, but maybe you won't need to go that far.

\$\endgroup\$
  • \$\begingroup\$ I'm not too familiar with that concept, but I can understand your description to a decent degree anyway. Thanks. \$\endgroup\$ – DziNeIT Aug 12 '14 at 11:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.