4
\$\begingroup\$

This question in very similar to this question, however I am still confused about how one would implement a story and quests in a finite state automaton RPG.

This is my first game that I am making (my background is in computational science not games) and it is similar to this game. At every frame in my game you are in a state. Examples of states might be Shops, Worlds, Battle state, Inns, Player Stats screen, etc. Each state has a next and previous state that allows one to progress (or back out) to one state after the other. For example if you are currently in the World state, upon moving to the door of an inn the state changes from World to Inn. After clicking to leave the inn the state then reverts back to the World state. All of this appears to be what is described in the this question.

However, quests and story don't seem to fit all that well here and I am confused about what data structures to use for quests and how they should be implemented in the game. One problem with quests is that they cross states and time. For example, you might get a quest from the inn keeper (in state Inn) and then have to go back into the world and perform some action to complete the quest (World state). Maybe you then have to turn in the quest to the potion shop keeper (Potion Shop state). All of this crosses multiple states and knowing when to post dialogue to the screen is time and state dependent.

The easiest solution seems to just create a quest dictionary and make it global. This way all states can see all the quests and data in the quest dictionary (e.g. different flags etc) can be modified at will. The downside here is that a) we are using globals, a generally frowned upon idea by most programmers, b) this quest dictionary could easily become quite large and cumbersome, and c) this idea is hardly OOP. Another idea I had was to create a class called Quest and each quest would just be an instance of a this class. I would then pass these instances to whatever states need them. This is also pretty cumbersome though. Having to pass quests around to different states (and basically hard coding different quests to all the states that need access to them) seems like a bad idea. I could also implement the quests directly into the states. For example the Inn state has methods and flags to deal with quest 1, quest 2, ... etc. This isnt very OOP though because what if I want more then one inn? The quests associated with my first inn would be different from those associated with my second inn (different inn keepers after all!!). I would have to write two different versions of my Inn state class.

I suspect I am missing something obvious here given that my background is not in game design. I understand the finite state automaton at least in terms of moving from location to location within my game, but I am failing to grasp how to do something similar for quests and story. Should I have a global quest data structure? Hopefully this isn't marked as duplicate. Thanks for any help you can give in clarifying this for me.

\$\endgroup\$
3
\$\begingroup\$

As far as I see it the Shop class (for example) needs dependencies on at least two classes:

  • The current status of the player-character (things like available money, inventory and what quests they are currently on)
  • The current status of the shop the player is visiting (things like shop inventory, prices and available quests)

These dependencies must be injected when transitioning to the Shop state.

But where do these statuses come from?

Pretty much every state will need the player-status in one way or another, so it should simply be mandatory to pass it on with every state transition.

The status of individual shops is a bit more tricky. But when the player is on a World, then that World should know the status of each facility in it, so state-changes from facility to facility should be managed by the World-class.

When you have the status of the player and the status of the World(s), you have the whole progress of the game. That's what you need to save in a savegame, by the way.

How to do quests depends on what you actually mean by "quest". When you want a sandbox-style game with mostly procedurally generated cookie-cutter quests like "Kill monster X", "Speak to X", "Bring X items to person Y", then it seems like a good idea to implement each quest-type as a separate class inheriting from an abstract base-class Quest and then add a list of Quests to the player-character representing the currently active quests. But when you want a more narrative style with a pre-written storyline, then a dictionary of quest-flags would be more appropriate.

\$\endgroup\$
1
\$\begingroup\$

Model the flow of data

Working with desktop computer apps and web for a while, I learned to love the notion of unidirectional data flow. (1df)

Without 1DF, the quests state lies somewhere, can be mutated by any objects that have access to it (if it's a global variable, this means every object), and reasoning about where and how to change them becomes quite hard.

1DF proposes a different approach. There's a state dispatcher which notifies subscribers about state changes. The state objects adhere to value type semantics, i.e. even if you changed the state in the "shop" screen, the "menu" screen's data would not be affected. Everyone gets a copy, essentially.

Now changes are performed through events which a state store processes. The store uses reducers (in reactive/Flux lingo) to apply the event to the current state and reports back a modified version. This new version of the state will replace the old in the store. The store will then make the dispatcher do its job and tell all subscribers. And there you go.

The flow is unidirectional because state changes are only performed by reducers, commanded by the store, and updates are pushed from a central place to subscribers.

This is a model of information flow or process. Your state machine musings relate to the structure of the app into modules which can issue transitions about which one is active.

Handling quests state

Now if your quests are in a state object, a collection of active Quest objects say, each with a unique ID the game can understand, then you can have a quest log menu screen obtain the new state upon being displayed. If the quests change in a background thread, the quest log will receive updates and can re-display itself.

Quests affect dialogue. So you have to model NPC interactions to take this into account. Showing text on screen is easy. But the game has to have conditions that display some text if a quest is completed and another while it isn't. To write dialogue scripts it pays off to use some sort of scripting language. (Can be LUA, can be home-cooked.)

  • I found a sketch of quest reprentation as JSON with C# interface code. Good to represent quests data.
  • I myself used a simple GOTO-heavy scripting language for which I wrote my own parser. (Sample script.) There I set and checked "flags" for their value.

So now you have quests, dialogue branches depending on quest conditions that are best expressed through scripts, and the framework to push state changes to active objects in your app.

\$\endgroup\$

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.