2022 Year in Review

Legend is now entering its fourth year of development. It took the first two years to build the foundation. Systems were stood up, then overhauled once, twice, or even three times in some cases. In 2022, rework dropped significantly (evidence that systems were stabilizing and meeting design needs), enabling me to focus on refinement and content in preparation for a public release. The release didn’t happen due to the unplanned Map Generation 2.0 work, but the game is much, much closer to this goal.

UI/UX Improvements

With the focus on getting a playable version out to the public, UI/UX received a lot of attention. 

  • Quick equipment switching. Melee weapons, ranged weapons, ranged weapon ammo, and light sources can be quickly changed using slots next to the hotbar.
  • New inventory screen with separate equipment slots, stats, and inventory items.
  • Visual indicators for the cell the mouse is hovering over and the default action that will be performed by clicking on the cell.
  • Improved inspect panel now displays each tile and entity in the cell and actions that can be performed on those.  
  • Status effect icons shown for player and enemies.
  • Improved Select Class screen.
  • Stamina and magic bars.
  • Added a loading screen.
  • Changed the main font to Merriweather. Not sure if I’ll keep it, but it’s preferable to the low resolution, fixed-width font I was previously using because it’s more compact and looks less retro.
Updated UI
Loading screen
Status effect icons
Select Class screen

Visibility

Using the Smart Lighting 2d Unity asset, dynamic lighting, shadows, ambient lighting, and entity light sources were added. In addition to giving dungeons more ambience, the new lighting creates some interesting gameplay. Players should proceed with caution because who knows what could be lurking in the shadows… Lighting example.

One of the trickier features implemented this year was partial wall hiding. This was needed because walls between rooms occupy a single cell. The player shouldn’t be able to see the wall in the other room. Partial wall hiding solves this problem by only drawing the portion of a wall cell that is visible to the player. Partial wall hiding example.

New Content

The slowdown in systems development, and maturation of those systems, made it possible to create a lot of new content. Dozens of new enemies, items, and objects were added. Abilities were finally added to the game as well.

Examples:

Crystals | Torches | Vampire | Eggs | Resurrect Ability | Mass Fear Ability | Summon Giant Rat Swarm Ability | Destroy Undead Ability | Warding Glyph Ability | Kill Touch and Charm Animals Abilities

Map Generation 2.0

At the beginning of November I realized that my map generator was too limited to achieve the game’s vision and that it needed to be replaced. Map Generation 2.0 had four objectives:

  1. New structuring methodology – layout of walls and floors in rooms, corridors, caverns, and other shapes
  2. Sections – map partitioned into separate areas with discrete structures, themes, and content 
  3. Data-driven stocking – replace the existing hardcoded dungeon stocking with a data-driven implementation
  4. Node pattern-based stocking – identify the best locations on the map to place specific types of content using node patterns on the map graph

All four objectives were completed. Much of the code from original map generation was still usable, but had to be repackaged. Some code, such as the BSP code, was scrapped. The new generator is much cleaner and, most importantly, is capable of producing the kinds of maps I originally envisioned (with some more fine-tuning).

New multi-section map structure and map graph visualization improvements

Unity Assets

I acquired some fantastic Unity assets in 2022:

  • Odin Inspector and Serializer – I can’t recommend this asset enough; it’s a must-have for Unity developers. It can greatly increase your productivity when using the Unity inspector. It’s very easy to learn and start using.
  • History Inspector – super handy. It lists recently viewed assets and allows you to go to those assets with a single mouse click. I was spending a lot of time going back and forth between assets and finding assets before I got this.
  • All in 1 Sprite Shader – I used this to make grayscale and frozen versions of sprites. 
  • 3552 RPG Icons Pixel Art – using for ability icons. I doubt I’ll keep these in the final version because I want all the art to be custom.
  • Pro Sound Collection and Ultimate Sound FX Bundle – added to my stock sound effects collection.

I didn’t end up using:

  • Recently Used Assets – this wasn’t useful because it just tracked assets that changed. History Inspector (see above) is what I was actually looking for.
  • Behavior Designer – this seems like a great tool, but after I bought it I realized I was trying to solve the wrong problem. Legend’s AI meets present requirements, and doesn’t require the sophistication of behavior trees. But, if more complex AI is required in the future I will reconsider this asset.

Ergonomics

I replaced my keyboard with a Logitech MX Keys Mini keyboard and mouse with a Logitech MX Vertical mouse after experiencing pain in my forearms, wrists, and hands. I haven’t had any pain since!

Time Tracking

I wanted to understand how many hours I was working on Legend and what that time was spent doing. In April, I started tracking my time using Clockify.me. Since Clockify integrates with Trello, the tool I use to track my work, the overhead added by time tracking was negligible. 

In 2022, I spent 538 hours working on Legend, averaging 10.3 hours per week. 

Hours per week from April – December

Over half of this time was spent on enhancements (new features, feature improvements). 25% of my time went to testing and bug fixing. While I didn’t track time in prior years, I suspect the refactoring time was much higher in those years compare to the 8.7% in 2022 because I was doing a lot more rework.

Time spent by category

2023 Outlook

I’m confident that more people than me and my kids will play this game in 2023. There’s some work to do to get a public release out, and it will be far from finished (and will very likely still contain the Oryx stock art rather than original art). That work includes:

Improved Dungeon Stocking 

Dungeon stocking using Map Elements is currently done on a per-room basis. I want to add multi-room and multi-level Map Elements to provide more cohesion across levels and the dungeon as a whole. An example is placing a locked door and key in different map locations.

Improved Performance

Playing the game doesn’t feel great currently. It’s clunky and unresponsive at times, especially when there are multiple enemies on the screen. A big issue is the way turns are handled. Actor actions are animated sequentially, so the player has to wait for every other visible actor to move before moving again.

Content Creation

Much more content is needed, primarily objects, Map Elements, and map section types, to ensure that maps are varied enough. Some more enemies and items are needed too.

Balancing

Balancing improved in 2022 but still has a ways to go.

Once these tasks are completed, I’ll distribute the game to a small group of people who are interested in trying out Legend and providing feedback. After incorporating that feedback, I’ll create a Steam page and publish an early access version.

Thanks for reading and Happy New Year everyone!.

Weekly Update – October 22, 2022

I was short on time this week due to a family health issue. 

  • Acquired gold and kill tracking. The amount of gold the player acquires and the number of enemies the player kills is now tracked. These stats are displayed when the run ends.
  • Tester player class. It’s been a few weeks since I’ve run the automated tests. When I ran them this week, every one of them failed. Yikes! Most of the tests failed because of the recent changes I made to the starting classes, specifically removing items and abilities that the classes shouldn’t have at the start of the game. The automated tests assumed these items and abilities were available. I added a new player class (Tester) that has all abilities, and made that the class used by the automated tests. For obvious reasons, the Tester won’t be available to the player. 
  • Bug fixes. Resuming automated testing exposed some issues. Fortunately, none of the issues were caused by code defects; they were caused by objects that weren’t properly configured after the Stat Modifier enhancements implemented a few weeks ago.
  • Contextual map generation brainstorming. I put a lot of thought into how to arrange map rooms and elements in a more logical fashion. I already have many pages of notes on this topic. I’ve worked through a variety of concepts including procedural history generation, rules for the types of rooms that can be placed next to each other, tying stories to structure, and story hierarchies that span the entire dungeon. A concrete implementation is slowly being pieced together. It’s been helpful to list examples of dungeon levels that the generation would ideally be able to produce, such as a level divided into two sections occupied by opposing factions.    

Next week, an initial, though likely rudimentary, contextual map generation implementation is the main goal. I can’t spend much more time on this if I want to complete the demo release by year-end. I also need to complete combat / progression balancing, which is a dependency for finalizing actor and item stats.

Weekly Update – October 7, 2022

Between unexpected issues at work and a lot of thinking and spreadsheeting rather than coding, it didn’t feel like I got much done this week. My brain is getting fried working out how various numbers will change over the course of a run – HP, damage, damage reduction, stat ratios between no/light/medium/heavy armor, net stats from different equipment combinations (this has especially been a headache; I’m tempted to have a single equipment slot for armor rather than body/head/hands/feet), early vs. late game ratios (to control difficulty), etc. It’s been challenging figuring out where to start because there are so many relationships between stats. My starting point is determining what should be the typical number of hits to kill the player according to their armor category and working backwards from these numbers to determine the stat values. It’s also been helpful to write out different combat scenarios like “how many hits should it take a bandit with a short sword to kill a player wearing light armor.” The model is coming together, but there are still many numbers to plug in. After the model is finished, I’ll create a simple simulator to efficiently test it, and do play testing. 

Aside from all the fun with spreadsheets, I completed a couple of items on the 2022 goal list: finalizing the Select Class Screen and Passive Abilities.  

  • Updated Select Class Screen. Locked classes are now shown as a silhouette of the sprite, with a lock icon (I’d prefer a padlock but grabbed the closest thing I had, which was from the Oryx sprites). Class attributes are now shown in a grid view with the attribute names.
Updated Select Class screen
  • Passive Abilities. Passive Abilities were previously 25% completed. They could be assigned to classes in the designer, but didn’t appear on the Abilities Panel, didn’t have sprites, and didn’t have any effect in the game. These items have now been implemented. Passive Abilities are currently only used to dictate the weapons and armor that a class can use. Passive Abilities that provide other types of benefits will be added in the future.
Passive Abilities
  • Finalized the starting classes. Three classes will be unlocked when the game is installed: Knight, Ranger, and Wizard. Just this week I replaced the Rogue with the Ranger. I wanted the starting classes to be the most straightforward classes to play, representing the core combat styles of melee, ranged, and magic. Additionally, the Rogue’s abilities, and map features to use those abilities, won’t be ready by year-end.
  • Common Ability Group. I decided that all classes should have the Run ability. I added a new ability group called “Common” to contain abilities that are available to all classes. I don’t have any other abilities in mind currently that fit into this category, but I expect there will be some in the future. 
  • Q4 plan. I set goals for the remaining weeks of the year. I don’t usually get this granular with planning, but it is necessary to keep me on track and reach my goal of a playable version by the end of 2022. I’ve set goals by month as well, which are:
    • October: remaining functionality
    • November: remaining content
    • December. testing and polish

Next week, I must finish the initial progression/balancing model. I also plan to finalize the item, ability, and enemy list for the demo release. I’ll also review all of the systems and identify the major improvements/fixes that are needed for the demo release.

Weekly Update – September 30, 2022

This week’s activities were all over the map.

  • New Abilities
    • Kill Touch and Charm Animals. Kill Touch instantly kills an adjacent target. I need to put some limits on this, such as resistance for stronger enemies. Charm Animals charms all animals in a 5×5 square
    • Warding Glyph. Places a glyph on the ground, visible only to the caster, that harms the first actor to walk on it.
    • Destroy Undead. Destroys all undead enemies in a 5×5 square.
    • Cure. Cures poison.
Kill Touch and Charm Animals
Warding Glyph
Destroy Undead
  • New Item: Poison Arrow. Poison Arrows inflict poison on their target. 
  • New Map Element: Poisoned Fountain. The water in this fountain is poisoned, giving it a green hue. Drinking from the fountain causes a Poisoned status effect. The fountain will have additional future uses (when the functionality is built): pouring a Cure Poison potion into the fountain purifies the fountain, an empty vial can be dipped into the fountain to create a Poison Potion, and a weapon can be dipped into the fountain to give it a temporary Poison effect. 
  • New sound effects. Cauldron bubbling, fountain trickling, egg cracking and hatching
  • Particle effect for conjuration. It’s a slightly modified version of one of the particle effects from the Pixel Arsenal particle effects package.
Summon particle effect
  • Enemies can open doors. Gone are the days in which the player could flee from enemies simply by passing through a doorway. Enemies can now open doors to continue their pursuit. Whether a particular enemy can open a door is governed by the actions it can perform. Some enemies, such as giant rats, are too unintelligent and/or physically incapable of opening doors.
  • Combat balancing. Several hours went into fine-tuning the damage formula and damage progression in a spreadsheet. My naive original damage formula was [Damage caused by the attacker] – [Damage reduced by the defender]. I liked the simplicity and intuitiveness of this calculation but it didn’t work in practice. I did a bit of research on damage formulas used in RPG’s (in hindsight, something I should have done before any spreadsheet work or coding, because designers have already figured this stuff out) and found some alternative formulas. A common formula is [Damage] = [Attack] * C / ([Defense] + C), where Attack is the damage caused by an attack before applying damage reduction, Defense is a  C is a Constant, usually 100, and Damage is the resulting damage after damage is applied.
  • Assumptions and constraints:
    • Max HP never changes.
    • Max HP only slightly varies between different classes.
    • Each class fits into one of the following armor categories: none, light, medium, heavy.
    • Each armor category has a target number of hits before dying (none:2, light:3, medium:7, heavy: 12). The damage formula and item stats are all designed around these numbers.
  • Tooltips for stats. Tooltips are now displayed when hovering over player stats.
  • New automated tests. Cell area utilities.
  • Fixed AI bugs.
    • Actors don’t track the player’s last seen location in some scenarios
    • Actors sometimes choose to respond to the wrong observation because observation weighting isn’t taking player regard (friendly or hostile) into consideration
    • Player allies sometimes follow the player instead of attacking enemies of the player
  • Fixed other bugs.
    • Inanimate objects, such as stairs, barrels, and doors, are subject to charming. It doesn’t make sense for entities without brains (and some with brains) to be charmed, so they’re now excluded. That said, this bug may inspire a future spell where inanimate objects are brought to life.
    • The Run ability allows the player to run past an enemy.
  • Changing levels and saving/loading working again. The reinstantiation of a previously visited level breaks more often than any other functionality in the game. So many changes break it. Most recently, adding theme-specific sprites for certain objects caused it to fail. 

With the last quarter of 2022 starting this weekend, I’m putting together a plan to get the first playable version done by year-end. Next week’s goals will be determined by that plan.

Weekly Update – August 26, 2022

After literally years of research, brainstorming, analysis, and procrastination, the types of resources consumed by abilities have been determined. This decision has been drawn out by many dependent questions regarding Legend’s underlying resource management design: are resources finite or infinite? Is there a hunger clock? Do health, magic, etc. regenerate? Not all of the questions have been answered. I aspired to find the perfect solution, but the model is too complex to assemble, and I no longer believe a perfect solution exists anyway. I increasingly aim for solutions that are good enough, solutions that don’t offer complete flexibility, but are flexible enough. I embrace the resulting constraints, for they shrink the answer space, and foster creativity. And thus, at the end of the ability resource design journey, I arrived not at revelation but convention, with the health/stamina/magic trinity, a staple of the PC RPG.

  • Ability resource consumption design. Abilities may consume stamina, magic, health, and/or items. Magic fuels spells, stamina powers physical feats, and items are needed for specific skills such as picking locks. Like health, stamina and magic are represented in points. The quantities of resources consumed by each ability will be fine-tuned during balancing.
  • Player magic and stamina meters. Stamina and magic meters now join the Health meter. I reduced the dimensions of the meters so that they cover up a smaller screen area.
Redesigned health/stamina/magic meters
  • New Action Step: Consume Resources. Luckily, I didn’t have to implement a new system to handle resource consumption; it fits nicely into the Action Step framework, becoming another building block for constructing actions. This was the most logical solution, since abilities essentially just invoke actions.    
  • Added Action Source to Actions. Actions are defined using the following structure: [Actor] do [Action Type] with [Item(s)] on [Target] in [Context]. For the Consume Resources Action Step to work, it needs the source of the action (the ability that invoked the action), so that it knows which resources, and how much of each resource, to consume. The action source has been added to the actor structure, making the structure now: [Actor] do [Action Type] from [Source] with [Items] on [Target] in [Context]. This required a lot of changes in the code, but was done quickly using global search and replace (which is surely an architecture smell).
  • New items
    • Magic and Stamina Potions. Self explanatory.
  • New abilities
    • Health to Magic. Recover magic at the cost of health. No class with healing abilities will be able to use this, since it would be possible to have unlimited health and magic.
    • Magic to Stamina. Recover stamina at the cost of magic.
  • Visual effects. While looking for a way to modify sprite colors at runtime (I need to display grayscale versions of sprites and make sprites appear frozen when they are hit with an Ice spell), I came across a Unity Asset, All in 1 Sprite Shader. It does far more than I need (at least currently), but it was very popular and highly rated (and on sale) so I bought it. Of all the Unity assets I’ve installed, this asset is probably the easiest to learn; simply add the component to a gameobject and, using the component’s UI, select the visual effects you want to apply. However, I don’t think I’m using it in the intended way. I didn’t want to add the component to the dozens of actor and item prefabs because I didn’t want the visual effect to be always on, and I didn’t want to maintain an extra component for actors and items. So, I just used it to make materials, and I’m applying the effects at runtime by changing the sprite material.
  • Improved random Map Element selection. Previously, all Map Elements were assigned a rarity level, which served as the weight in a weighted randomizer. The problem with this is that the rarity distribution changes depending on the number of Map Elements of each rarity level. I’ve now split the selection into two steps. The first step selects the rarity level using a fixed set of probabilities. The second step selects a Map Element from the list of Map Elements of the selected rarity level. This ensures that Map Elements are correctly chosen based on the rarity distribution.
  • Bug fixes
    • Quick Switch and Hotbar slots still interactive after the player dies
    • The action indicator cursor still appears after the player dies
    • Enemies stop moving when the player moves out of sight
  • Minor improvements
    • The Escape key now cancels the Select Cell prompt. My goal is for the game to be completely playable using a keyboard and/or mouse.
    • Ability resource consumption support
      • Preventing abilities from being used if there are insufficient resources
      • Dimming slots containing abilities that can’t be used due to lack of resources
      • Tooltips indicate why ability slots are dimmed

Next week, the major task is reassigning sound effects. I’ve purchased several collections from the Unity asset store, but I recently pulled the files out of the Unity project because they were making project snapshots huge. Now, I need to bring only the sound effects that the game is using back into the project. Beyond that, there will be more play-testing and tightening things up. 

Weekly Update – August 12, 2022

Adding a new ability to summon a swarm of giant rats nearly derailed my plans for this week (and potentially the next few months) when I tried out the ability and, to my surprise, the rats started attacking each other. I realized that there was no way of indicating that the rats were both allies of the player and each other; I needed to be able to specify relationships between actors. Factions were the first thing that came to my mind. They’re overkill for this single use case, but I’ve always intended to have factions in the game and reasoned that I could use them to solve the rat problem. As I’ve done with other aspects of the game design, I start with a flurry of research and brainstorming. I read up on factions in game design and roguelikes specifically, including a FAQ Friday on the topic, and wrote down all of the ideas and details I could think of. And, as I always do in this situation, I got lost in the subject and created a conceptual design that far exceeded what I likely needed and what I had time to build. That’s not a bad thing, as long as you can quickly pull yourself back into reality and reduce a grandiose design to something practical. I was able to do that in this case. My solution was to add an actor attribute indicating whether the actor is friendly, neutral, or hostile to the player. It’s a compromise, and there’s a good chance it will be thrown away in the future when I add a true faction system, but it’s the right solution right now, because it was extremely simple to implement and I don’t have a clear vision for how factions will work.

Mass Fear spell
  • New Ability: Summon Giant Rat Swarm. Summons a swarm of giant rats to fight on the player’s behalf. 
  • New Item: Fire Sword. Sets enemies and objects it strikes on fire. It’s overpowered at the moment, but I haven’t decided how to nerf it.
  • Chests and corpse item access. The items contained in chests and corpses can now be viewed and taken from the Inspect Panel. A “Take All” button lets all items in the container be taken at once.
  • Inventory Panel is automatically displayed when inspecting a container. When viewing a container, such as a chest, the player inventory is now displayed automatically. This allows items to be dragged from the container into inventory and vice versa.
  • Weighted observation selection. One of the configurable AI components is the ObservationDecider. This component examines the actor’s observations since the last turn and chooses an observation to react to. There are two implementations of this component, one that selects the first observation involving a tracked actor, and another that randomly selects an observation (used by the Fear status effect). These implementations are primitive. They don’t work well when there’s more than one suitable observation to respond to. To address this, I modified the ObservationDeciders to weight each observation and select the highest weighted observation. 
  • New automated tests: Eggs. I’ve repeatedly broken the functionality of eggs, so this was a great automated test to add. The unique behavior of eggs (turning into a cracked egg upon detecting the player, waiting 10 turns to hatch, hatching a creature at the end of waiting) tests a number of systems.
  • Installed History Inspector from the Unity Asset store. My project asset list has gotten enormous. ScriptableObjects are used extensively, and many of these ScriptableObjects reference other ScriptableObjects. I often have to follow a trail of ScriptableObject references to fully understand how something is working, or go back to the previous asset I was viewing. The time spent scrolling through the asset tree, and the effect of navigating the structure on cognitive load, is impacting my productivity. I looked for a built-in Inspector history viewer in Unity but couldn’t find one. So, I turned to the Unity Asset Store and found the History Inspector asset. It’s already become an indispensable tool that’s saving me a lot of time.

Next week, I’m play-testing combat and overall level difficulty. I’ll adjust and fix based on what I find. The overarching goal for the year remains getting to a version of the game that I can distribute to others.

Weekly Update – April 22, 2022

This week, I started on the next milestone, abilities. Abilities include special attacks, spells, utility skills, and passive effects. I have a list of around 90 abilities currently and expect the final count to be between 120 and 150. Each actor (player classes, NPC’s, enemies) will start with zero or more abilities. Players can gain more abilities over the course of the game. I haven’t worked out all the details, but the ability acquisition will be integrated into gameplay (i.e. they can be found like items, or learned from an NPC) as opposed to a skill tree. Like items, the abilities placed on the map get stronger the deeper the player goes. The abilities available to the player depend on the player’s class. Each class has a set of attributes and a maximum proficiency level for each attribute (basic, intermediate, advanced). Each attribute proficiency level is associated with a set of abilities. A class is able to use the abilities defined for each of its attributes, at or below the proficiency level defined for that attribute. For example, a Ranger has a Weapons (Intermediate) attribute that allows use of the abilities associated with the basic and intermediate proficiency levels of the Weapons attribute.

  • Reworked abilities and attribute classes. Basic ability and attribute functionality was already in place to display attributes on the class selection screen and display abilities available to the player. To fully support the ability system, the underlying code had to be extensively reworked. Most of this week’s time went into this rework. Active and passive abilities were split into separate classes inheriting from a common base class. Relationships between attributes, attribute proficiency levels, and abilities were rewired. Attribute ScriptableObject assets were condensed from one asset per combination of attribute and proficiency level to one asset per attribute to directly group abilities for each proficiency level (this is useful because classes have access to abilities for a maximum proficiency level and all proficiency levels below the maximum).
  • Improved Abilities Panel. The Abilities Panel previously displayed all available abilities in a single grid. Now the panel has a tab for each Actor Attribute and the abilities for the selected attribute are grouped by proficiency level.
  • Miscellaneous ability-related enhancements
    • Starting abilities automatically added to the hotbar.
    • Abilities can be inspected like entities and cells.
  • Contemplated replacing abilities with items. This is more of a side note than an update, but midweek I stopped development and seriously considered implementing abilities as items. The origin of the thought was my struggle to determine how resource consumption will work with abilities (I still haven’t figured this out, by the way). One option was to simplify and consolidate resource management to inventory. Players would find items that did the same things that abilities would do – a scroll to cast a spell, lockpicks to pick a lock, etc. This idea appealed to me because clever use of what you find is key to success in the game, and it avoids using time as a resource (waiting to regenerate mana/stamina). But, there are drawbacks: 1) the desired player behavior is to frequently use abilities, but having a finite number of uses and uncertainty about how many future uses the player will have encourages hoarding 2) it’s difficult to allot uses of large quantities of items over the course of the game. Because of the drawbacks, I rejected the idea and resumed work on abilities as planned.

Next week, now that the abilities system is complete, work will begin on the abilities themselves. The big challenge here is implementing many abilities in a scalable manner. I want to avoid creating a separate class for every ability, and I want to leverage existing objects like actions and effects as much as possible.