Hi, dungeon-crawling Fans!
The year is coming to an end, but the work on Monomyth continues – a good opportunity for another update! This month we will focus more on the technical side of things, so, let’s get started…
Current Progress
You may remember, in the last update, I mentioned that I’d do some coding for the first two weeks of December. I wanted to improve some of the game’s systems and make it easier to include additional immersive features (work I would have otherwise done during January).
After the first two weeks, I saw that with a little bit more time I could turn the refactoring into a major code rework, which would immensely simplify future development and potentially save me a lot of time in debugging. So, I decided to take the chance and I dedicated another two weeks to coding.
Alongside the removal of several conceptual problems with the AI, two major results came out of this process:
- Improved Character State Machines
- Improved Inventory System
These improvements allowed me to introduce a series of features, most of which were either requested during the Kickstarter demo or part of the “Expanded Immersive Simulation” stretch goal. In this update, we will deal with the inner workings of the improvements as well as their effects on the game design. It will be a bit more technical this time but don’t worry, we will talk more about level design (and – as promised – dungeon rooms) in next month’s update!
Refactoring & Game Design
To recap a bit, refactoring means the rework and improvement of code and code architecture. Much of the Kickstarter demo’s code has been written quite some time ago, and while it is maintainable, cleaning it up here and there is always a good idea. Failing to do so may not ruin a project (even though, there certainly are projects that have become victims of their own spaghetti code), but with increasing complexity, the time spent on fixing bugs and introducing new features increases drastically. Lately, people started referring to this additional work as so-called “technical debt” or rather the “interests” of technical debt – a term originally coined by Ward Cunningham in 1992. It’s a common problem in many engineering fields and game programming is no exception. A cleaned-up architecture helps to keep the code maintain- and extendable, mostly by preventing side effects of both major and minor code changes. I refactored a few systems this month. The most significant ones were the character state machine, as well as the inventory system. So let us take a look at these.
As for the character state machine, we must first clarify: “What even is a state machine?”. A state machine (or FSM, standing for “finite state machine”), is actually a very simple concept. It’s a depiction of possible states a certain object (e.g., a person, a machine, a piece of software, etc.) can be in. It further depicts how the state of an object can change (i.e., what triggers the transition between states). To give you an example:
Imagine yourself. You can either be “awake” or “asleep”. To be awake you have to “wake up”. To be asleep you have to “fall asleep”. This can be depicted in a simple state machine (I won’t bother you with default states for the moment)[…]
Being awake (normally) allows you certain activities. For example, you could play video games! Usually, that shouldn’t affect your awake state, so the activity could be expressed as a self-transition (alternatively “playing” could be a sub-state of “awake”, but I won’t bother you with that either – for more information, look up “Hierarchical State Machines”)[…]
You can probably already see how this concept can help organize the activities of a character within a video game. It is also very easy to add further complexity to these constructs while keeping the programming effort relatively low. That is if you follow a proper design pattern and know how to implement it in the engine you are using.
There are numerous ways to use FSMs in a game’s code, from NPC behavior to the lock of a simple door. Among other things, Monomyth uses FSMs to document a character’s current state and restrict possible inputs for both the player and the AI[…]
Originally, Monomyth used an old-fashioned enum-based state machine for its player controller class. Characters mostly used ad-hoc structures to restrict their inputs (e.g., gates, checks, etc). This worked for the most part, but using a well-defined design pattern instead helps avoid a vast variety of potential bugs and unexpected runtime behavior (especially with regards to AI).
Now let’s come to something that had a more immediate effect on the game design. The refactoring of the inventory system opened up a few possibilities in terms of newly implemented features. But first, what exactly was wrong with the original implementation you saw in the Kickstarter demo?
The original implementation of the inventory system used a static approach towards object handling. That essentially means that items were not really passed between the game world and the player inventory. Instead, what was passed was an identifier, from which items were constructed in the inventory once the player picked up their representation in the game world. There are various reasons to implement inventories like that, but in the case of Monomyth it was mostly premature optimization, as well as vaguely defined requirements, both of which are big no-nos in any software project. From the player’s perspective, it would mean that items had – for the lack of a better description – no “object permanence”. Custom properties, that would change on an item throughout the game, could not be carried over from the world to the player inventory. This restricted various planned features. Among others, blacksmithing, which is directly connected to weapon improvements and item durability. But let’s go through these things in detail…
Blacksmithing
Blacksmithing was one of the features planned for the “Expanded Immersive Simulation” stretch goal, and while we slipped slightly under that goal in the final funding, I still intend to implement a good bit of its feature catalog. The feature itself is always a difficult topic in games, because a) you don’t want it to be a time sink and b) you don’t want it to feel like just another menu slapped on the GUI. In Monomyth the players should really swing the hammer, and when they do that they should do it for a useful purpose (no “creating 100 iron daggers to push a number in the character menu”). Blacksmithing will focus on repairing items, improving items, and creating special equipment. The earlier two require the aforementioned custom properties introduced during the refactoring, while the latter is more of a special questline for the right ingredients. Improving items can take many forms, from creating a classic “Longsword +1” to instilling a holy essence in a lance. Repairing items on the other hand is a more straightforward process, that only really makes sense when there is item durability.
Item Durability
I can already hear some people groan, but don’t worry! Item durability is a logical conclusion of previously introduced features (not only blacksmithing) and I will try to handle it in the most balanced way possible. I remember having a discussion on the topic a few years ago and people generally felt lukewarm about it. I expressed my concern that there was very little to prevent players from destroying all doors in the game, other than the fact that it may attract hostile NPCs (which is essentially just a problem for stealth-focused characters). In the demo, this was balanced out by using indestructible metal doors in numerous places. It was a more or less subtle solution to the problem, but what it really did was nullify a feature of the game. With item durability, on the other hand, there is an explicit trade-off attached to destroying doors. Now the question is, how to balance this feature properly.
In a lot of games, item durability comes in one of three flavors: Neglectable, annoying, or stressful. Neglectable item durability is the one that you never really notice. You go through the entire game finding lots of new equipment so item durability never really takes effect. The feature is more of a formality than part of the actual design. Annoying item durability is the exact opposite. All your weapons break all the time and you have to go and repair them constantly. Here, the feature is more or less a time sink. Stressful item durability essentially works like the annoying kind, except all broken weapons vanish from your inventory forever. In many games, this approach disturbs clean item progression and the sense of finding a real treasure because everything is essentially fleeting.
Ultima Underworld on the other hand had a relatively balanced approach towards item durability. While most weapons could be entirely destroyed, you could pick up weapons from enemies. This balanced item durability and gave the early game a bit of a survival element.
I do not intend to implement full item destruction in Monomyth, however, I would like to scale item durability with ongoing item progression. This means earlier in the game item durability will be more important, while later it will take a backseat. This way, Monomyth might develop a survival aspect in its early game, similar to its inspiration. And of course, that means another thing…
Picking up weapons from dead NPCs
During the Kickstarter demo multiple players wanted to pick up weapons dropped by enemies. Not being able to do so was considered immersion breaking, illogical, etc. The same was true for the “loot orbs” (the floating blue orbs that would appear on an NPC’s corpse). With the introduction of the new character state machine, the new inventory system, as well as item durability, these problems could be addressed. Players can now directly loot items from a character’s body. Given that the character is in the right state (dead) the new code directly accesses that character’s individual inventory. The same approach could be used for a pickpocketing feature (which was originally included in the “Advanced Playstyles” stretch goal), but given the schedule, unfortunately, I can’t make any promises concerning that right now. Weapons dropped by NPCs are now regular (damaged) items the players can pick up. Item durability is supposed to balance this new feature as well. Talking about picking up stuff from the ground: I implemented one last feature after the inventory system refactoring…
Inventory Tetris
Maybe one of the most popular inventory management features from the late 90s/early 2000s. Since the existing inventory system from the Kickstarter demo was just a specialization (with all items occupying only one space in the inventory) it seemed natural to prepare this approach while I was already working on the inventory code. What happened in the background was a switch from a simple item array, to a vector map of items and the addition of dimensions to item data. From there on the implementation was relatively straight forward and most of the work went into the functionality of the GUI (which now features drag and drop interaction).
Testing will show how much of an impact this feature has on the game design. My guess is, that the deciding factor of inventory space management will still be item scarcity, whereas item dimensions should add a further possibility to balance the issue.
In conclusion, I believe that the refactoring was definitely worth it. Newly introduced features, as well as implemented feature requests, look promising so far. I still have to adapt a few systems to the new codebase (persistence, item combinations, etc). I hope these follow-up tasks won’t interrupt the planned schedule too much. All in all, I’m confident that the lion’s share of the necessary work is done and smaller features will fall into place nicely due to the improved architecture. During January I will mostly create narrative assets and do more level, respectively character design. I’ll probably throw in a day of programming here and there and update you about the progress. Until then!
Best wishes and a happy new year!
Michael