1
\$\begingroup\$

I'm writing a game where deliveries are made to specific people. These people act in different ways depending on what the delivery is. At times one character might ask the player to make a delivery to a difference character.

I'm having a hard time figuring out a healthy architecture for this. Currently I have a story manager singleton class, a quest class (which has subclasses like letter, package etc) which keeps track of the character sending/receiving the delivery and its' contents, and a character class that handles the behavior upon receiving a quest.

This works for the small version of the game that I'm working on at the moment since the order of interactions is fairly simple, so if x gets a package from y we have a switch statement handling this in y, but it doesn't feel scalable whatsoever - what if x sends y multiple packages throughout the story? Also, this mean I would have to manually mark the quest as complete from the character class and it feels wrong.

Of course I could give each quest an ID but it also doesn't feel great to do, since many IDs are difficult to read and expand upon. I don't necessarily want to end up with a giant switch statement that's just numbers (or enum), especially since that would have to be done for each character and it sounds like a nightmare.

Are there any design patterns applicable here? Do you have any advice? I'm working in gdscript at the moment but it doesn't seem like a language-specific problem.

Thanks!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Are those delivery quests all the same except for what needs to be delivered to where, or do some of them contain any unique logic? \$\endgroup\$
    – Philipp
    Commented May 11, 2023 at 9:37

1 Answer 1

1
\$\begingroup\$

Games with lots of quests often use some kind of domain-specific language (DSL) to define quests. That means that the quests are created in a text format that is interpreted by the game at runtime. In simple cases, the DSL can be based on a standard data markup format like JSON or XML. This has the advantage that you can make the implementation much easier by using a library to parse those formats. Here is an example how a simple fetch-quest could look in a DSL based on JSON:

{ "quest_type": "delivery",
  "min_level" : 5,
  "time_limit": 1200,
  "steps": [
         { "npc":"Alice",
           "text":"I got a job for you. Can you bring this small package to Bob?",
           "item_received":"small_package_A" 
         },
         { "npc":"Bob",
           "text":"Sorry, but that's not for me, it's for Charlie. Alice always keeps mixing us up." 
         },
         { "npc":"Charlie",
           "text":"Thank you for the package. Can you bring this thank-you letter back to Alice?" ,
           "item_lost": "small_package_A" ,
           "item_received":"letter_C" 
         },
         { "npc":"Alice",
           "text":"How nice of Charlie to send me this letter. Here is your payment.", 
           "item_lost": "letter_C",
           "reward_money": 1000,
           "reward_exp": 500
         }
    ]
}

You would store this as a text file so your quest system can read it at startup, convert it into the appropriate data-structure and reference that data-structure during gameplay.

When there is a requirement to add some custom logic and mechanics to quests, then such a DSL can be more than just a linear data format. It can be a full-fledged scripting language supporting variables, loops, conditions, math and everything else you would expect from a programming language. Some games invent their own scripting language, but to keep development time reasonable it's often far wiser to just use an existing one with an existing implementation for your technology stack. But even this is something you should really think hard about if you really need it. It's easy to get carried away and turn your scripting engine into an inner platform that isn't any less complex than the platform you are already working with. So in the end you might end up with a scripting language that is even less convenient to work in than just hardcoding the quests in GDScript. So consider carefully what logic should be described in the scripting engine and what logic would be better to do with a call to GDScript that hides the nitty-gritty technical details of the quest scripts.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .