Quest Syntax Plus is a Power Quest extension that provides an easy way to extend Quest Script Editor with advanced syntax features.
Installation
- Download PQQuestSyntaxPlus.unitypackage
- Add it to your project via Assets > Import Package > Custom Package...
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