Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

PowerQuest

A Nifty 2D Adventure Toolkit for Unity · By Powerhoof

Extension: Quest Syntax Plus

A topic by 13px created 27 days ago Views: 62
Viewing posts 1 to 1
(2 edits) (+1)

Quest Syntax Plus

Quest Syntax Plus is a Power Quest extension that provides an easy way to extend Quest Script Editor with advanced syntax features.

Installation

Pre-made Features:

Shuffled Options

A feature recently introduced in Power Quest lets you easily create randomized responses using E.FirstOption() and E.NextOption:

if ( E.FirstOption(3) ) 
    Display: Can't do that 
else if ( E.NextOption )
    Display: Won't work 
else if ( E.NextOption ) 
    Display: Nope

QS+ lets you use a syntax like this:

?~~~
Display: Can't do that
?~
Display: Won't work
?~
Display: Nope
?~~~

This syntax is:

  • Much more compact and fast to type
  • Doesn't require manually  passing the options count to FirstOption. Just add or remove options as much as you want!

You can still use string keys to have shuffled reactions to events in different places in code. Where you'd type E.FirstOption(..., "wrong-click"), just add the key string to the header like this:

?~~~wrong-click
Display: Can't do that
?~
Display: Won't work
?~
Display: Nope
?~~~

Reaction Loops

⚠️ NB: you need at least C# 9.0 to use this (it uses tuple pattern matching with relational patterns)
If you're using an older version, consider switching to the later one (they have a lot of fun stuff!) or disable Reaction Loops feature by commenting out the [QuestSyntaxFeature] attribute of QuestSyntaxFeatureReactionLoops class. Or you can just delete QuestSyntaxFeatureReactionLoops.cs altogether. You'll still have the Shuffled Options!

Consider a situation common in any adventure game: you click a hotspot, and a character responds with different lines each time. After a while he runs out of new things to say and starts repeating the last few lines over and over again.

Something like this requires writing a piece of code that is very simple, but surprisingly long, awkward and a headache to modify. The simplest case could look something like this:

switch (prop.UseCount % 3) {
    case 0: 
        Vampire: What? Garlic? I hate garlic!
        break;
    case 1: 
        Vampire: Get this thing away from me! 
        break;
    case 2:
        Vampire: I said no!
        break;
}

All this just to get a loop of three reactions. This is frustrating because:

  • Adventure games need this behaviour all the time
  • Too much boilerplate code
  • Again, we need to keep the case count in sync with a value manually
  • What if we wanted the Vampire to say the first line only once and then loop the rest? 
    if UseCount == 0 say line 1 else switch ((UseCount – 1) % 2)...
    Simple enough, but even longer and starts being error-prone.
  • Editing this is a major, major headache

Introducing QS+ way of writing the same thing:

~~~prop.UseCount
~
Vampire: What? Garlic? I hate garlic!
~
Vampire: Get this thing away from me! 
~
Vampire: I said no!
~~~

Add or remove cases as you like, no need to count them and update a value!
Each case starts with a ~ header. If you need one or several first cases to repeat only once before the loop kicks in, mark them with ~* instead like this:

~~~prop.UseCount
~*
Vampire: I will only say this once: I hate garlic!
~*
Vampire: Get this thing away from me! 
~
C.Vampire.PlayAnimationBG("hiss");
Vampire: H-s-s-s-s-s!
~~~

This way, the vampire will use words the first two times and rely on endless hissing after that.

You can combine this with Shuffled Options from before!

~~~prop.UseCount
~*
Vampire: I will only say this once: I hate garlic!
~*
Vampire: Get this thing away from me! 
~
?~~~
Vampire: H-s-s-s-s-s!
?~
Vampire: Ugh!
?~
Vampire: A-a-a-ah!
?~~~
~~~

Extensibility

The extension can be easily extended!

If you know some Regex-fu and are feeling adventurous, you can write your own syntax feature. To do that:

  • Create a class in an Editor folder, under namespace PowerTools.Quest.QuestSyntaxFeatures 
  • Make the class implement the IQuestSyntaxFeature interface
  • Write logic for the two methods, ProcessOnLoad and ProcessOnSave
  • Add the [QuestSyntaxFeature] attribute to your class

The attribute will automatically add your feature to the editor. If you ever want to disable it, just comment out the attribute.

Creating syntax features isn't the hardest task out there, but there are pitfalls, you a lot of testing might be required. Please use version control, it's very easy to mess up your code.

Example of a simpler syntax feature

A very simple syntax feature I'm using in my PQ games is a shorthand for declaring enum flags. Instead of writing, say,

public enum weekday_state { Sun, Mon, Tue, Wed, Thu, Fri, Sat }
public weekday_state weekday = weekday_state.Thu; 

I can type just this:

flag>> weekday Sun > Mon > Tue > Wed > Thu! > Fri > Sat

With a ! marking the starting state if for some reason it's not the first one.
This combined with some simple replacements for integer and boolean flags makes numerous flag definitions extra easy to read and modify.
It's adapted to conventions in my games, but you can grab it here and modify it to your needs.

Notes

  • The extension "uses up" the partial functions of QuestScriptEditor, PostprocessOnLoadEx and PostprocessOnSaveEx. You cannot have two implementations of a partial function. If you still need to use postprocess functions for your own purposes, use the new ones from the extension: PostprocessOnLoadExEx and PostprocessOnSaveExEx.
  • The code created by advanced features contains auxiliary comments used for recognizing the patterns and translating them into the quest editor syntax. 
  • This is probably not the best code in the universe, but it's also not production code, and it seems to work!

Support

Reach out to me in PQ Discord (@13px or @13x666) with any questions or requests