We’ve decided to spice things up a bit! From time to time we would like to take a closer look at certain team members and showcase something cool they are working on. This week, Camille, one of our programmers extraordinaire is going to talk about how she is introducing journal entries into the game :)
Observant fans might’ve noticed that one of the icons in the player menu has been disabled for quite some time. That’s about to change, as we’ll be introducing the journal along with more encounters that make use of it in order to introduce a bit more feedback and interactivity about the player’s actions.
The journal serves two basic purposes: keeping a written record of progress made, and tracking goals to be fulfilled in order to achieve that progress. This will come as no surprise to any moderately seasoned game player, so instead of talking about the basics of the journal screen, I’d like to describe some of the considerations and challenges behind the scenes.
Few things are more frustrating in a game than having your progression break because of a mission or quest being stuck in an invalid state. While playing the released version of a game I’d previously worked on, an important NPC simply vanished and no amount of reloading the save would bring him back. I ended up losing a good eight hours of progression and gave up on the game, vowing to never create a system that would allow irreconcilable issues like this.
Unfortunately, it’s not as simple as that! Stability and flexibility are a tradeoff. The more control given to designers, the more powerful the system can be... But the easier it is to make mistakes that bring the whole thing down. I’ve therefore taken some time to study what we’ll need in our quest system and put together a series of tools to make sure that system is both solid and flexible.
Distilled to its very essence, a game quest is simply a series of goals that connect to each other. Some are optional, some are parallel, but ultimately completing them all leads to success... Whereas failing one objective means the quest is over and failed. Most likely we’ll want to update the journal to reflect on the result of this success or failure. All of those things can be abstracted out so it’s not necessary to manually handle an objective, its overarching quest as well as the journal text or objective tracking.
Creating a quest is very simple thanks to Unreal Engine 4’s blueprint system. One simply creates a new Quest blueprint and all the logic for objectives and prerequisites comes with it for free. For instance, I can type in the text that should appear in the journal when the objectives are updated:
Linking objectives together is similarly simple and makes sure to restrict selection to a dropdown menu of existing objectives in order to prevent issues like a typo in the objective name:
Likewise, a very common kind of objective is gathering one or more items from the world. This is also automated through pickup counter objectives:
Now, while this defines the data of a quest, it doesn’t say how that quest will progress within the world. Again, there is the chance of a tradeoff here where something too automated will limit designer freedom but something too freeform will be error prone. Therefore, there are different levels of automation and control available.
At the very basic level, you have the most manual level of control through script functions for UE4’s Blueprint system:
These functions can be used anywhere in script, whether when crossing an area as is the case here, when killing an NPC, when picking up an item, when interacting with an object, etc. The engine’s scripting functionality is incredibly powerful and all it requires on my end is to add a keyword to existing quest management logic in order to make it available to script.
This is fine and dandy, but if that were everything, there’d still be a lot of manual work involved in managing related states. For instance, if an important NPC is only supposed to show during certain parts of a quest, our designers would have to manually watch the status of that quest and toggle the visibility of the NPC as needed. With lots of quests big and small, this can get tedious very fast.
Enter the quest conditional component:
By simply adding this component on a quest-related actor, the designers can simply choose whatever quest that actor should be linked to and let the component automatically drive it. For instance, the component above was added to the Bobby in the An Odd End pawn shop scenario in order to make him go away once the scenario is cleared (i.e.: “Until Finished”).
Furthermore, should simple toggling of visibility not be enough functionality, the component itself has scripting logic of its own. For instance, if I wanted to do something if the player has a cricket bat equipped when an objective is activated:
The vast majority of objectives and quests won’t require this functionality, but it was so easy to include said functionality that it would’ve been a shame not to do it!
That said, there’s still lots of work still remaining in order for the quest system to be fully featured. Namely, I will need to revisit the HUD to make sure clear and proper feedback is provided whenever quests are updated. Not to mention being able to display all of these things on the map with minimal effort so that players can easily get oriented in our vast generated world.
In the meantime, the current pieces of the puzzle are falling into place with a satisfactory first pass:
With all of these tools in place, our designers and writer will now have a lot of work ahead of them filling that journal with lots of interesting encounters, quests and story text.
If you enjoyed this kind of spotlight, please let us know and if so, what other aspect of development would you be interested in reading about :)
Discuss this post here