The Ebonheim Chronicle

Development Blog for Chronicles IV: Ebonheim

Today is June 28th which means that two years ago today I decided to try to #gamedev again and made my first commit to a new repo for a new engine attempting (for the fourth time) to make a game with the title “Chronicles IV: Ebonheim

Past Attempts

I thought it might be fun to talk about some pre-2022 project history and show some never-before-seen development gifs!

sEGA

Back in 2015, I started a new game engine with the constraints of being

  • 100% pure C
  • low-dependency
  • emulating EGA graphics cards

In the end I think the most powerful result of that endeavor was reshaping my brain around C. It forced me to learn so much about how code actually works and what is going on and completely revolutionized my coding style and ability.

The EGA emulation came as an idea of trying to create a cool arbitrary limitation on the graphical capabilities because old EGA games is some of the first games I ever played as a kid.

You can access that old engine here!

sEGA Games

The original idea for the engine was a point-and-click adventure title called Borrowed Time (BT) in the repo. I have nothing to show for this except for some scattered design documents but the general premise involved using a pocket watch to traverse over a clockwork Majora's Mask -style slice of time and solve a murder (still waiting for my check from the Obra Dinn devs).

By the time the engine was up and running and the graphics all worked I had “shifted” my idea to a turn-based tactical RPG called Shift which involved going on runs by diving into other planes of existence via D&D-style color pools. This project didn't get a lot further but it was influenced a lot by me being into DotA at the time and attempting to come up with new ways to accomplish complex deterministic combat resolution which was a constant pain point in BladeQuest.

BOMBILLAS.BAS

I used sEGA a little later to make a clone of the old QBASIC game GORILLAS.BAS for the Giant Bomb Game Jam!

You can download and play it here and see it being played by the Giant Bomb staff here!!

Chronicles IV (1)

After taking a break, moving apartments, losing a lot of weight, and getting exceptionally into a tabletop game called Burning Wheel, I had the idea of using sEGA to try and make some kind of Burning Wheel, Morrowind, Ultima, completely unrealistic game.

A big part of the pitch was that the whole game world would have (hundreds of) years worth of history mapped out in scripts. You create a starting character whose background would determine their age and starting location. You would then pick and poke and interact with the world to try and cause the course of history to change to accomplish your goals. It was this incredibly ambitious idea of having an RPG character who could literally grow too old and die of natural causes, where learning new skills took months or years of training.

Despite this idea never really coming together or having much hope of turning into anything, it's something I tinkered and played with for three years. It had no ImGui or in-engine edit UI but I still wanted to do all asset editing in-engine. This lead to creating a Lua console and building the map editor into the running instance. It had very tight lua integration for all of the actors. It's honestly wild to me just how much stuff this tech demo did in the end.

Here's some gifs from that project!

Thank you!

To everyone who has been following this project, it has been a joy to share my game's development with you!

Here's to a great third year!!

| 🌐 | 🙋‍ | @britown@blog.brianna.town

I've been actively developing this game for two years as of this month and have enjoyed keeping a tightly-curated blog of development progress and technical write-ups. But, as that body of work has grown, I've felt less and less easy about having that horse hitched to a platform I can't control or export from.

So now welcome to The Ebonheim Chronicle! All posts and their content from the last two years have been migrated manually here to a laptop in my office at home running Writefreely, a great minimal blog app that also has activitypub federation!

I've added a line of links to the signature of every post with how to access the RSS feed or follow the blog on mastodon or your federated feed of choice!

| 🌐 | 🙋‍ | @britown@blog.brianna.town

Spent this week building the art and UI around items and equipment. Items are the key to progression in the game! I can't wait to have them actually start affecting combat in meaningful ways 😁

#gamedev #chron4 #pixelart

| 🌐 | 🙋‍ | @britown@blog.brianna.town

In the combat demo, I had created a system called “Dodge Locking” described by the game's instruction screen as


The idea went something like this:

  • If you go before someone in the turn order you can always just move away from an incoming melee attack, dodging it.
  • Going first should be an advantage but there should still be a cost associated with disengaging from melee range
  • So rather than taking the hits, one or more lockers causes a 1-damage “dodge cost” for disengaging

Here's an example of disengaging from two lockers:

But there were issues with this when playtesting:

  • Few testers understood this mechanic, the closest being individuals asking if it's like Attack of Opportunity in D&D
  • There's already a problem with that demo where kiting enemies to get stamina back is overpowered
  • The dodge cost isn't high enough to make much impact

I worry because I think as a game designer you should trust your weird ideas most of the time and should try to never change something for the purpose of “Will people understand that” Sometimes teaching someone to understand your weird thing can be very impactful! But I did also feel like this system wasn't going to work out in the long run.

So I thought why not just turn it into Attacks of Opportunity! Essentially, if you're locked by an attack or ability, that attack will play out normally in reaction to you moving away. Here it is working:

I believe that this is an overall improvement for a few reasons:

  • Taking the attack that was declared as a cost to moving away makes disengaging much harder and makes melee much more dangerous
  • There's still room to modify this system via passive abilities that can modify the damage, create dodging effects, or adding counters
  • Adding locking to powerful ranged abilities is on the table now too with the same UI messaging

Finally, I am so proud that making this change was just a few lines of code! The combat execution is so modular and structured so nicely that making this enormous change was trivial and automatically works with enemy behavior and preview UI!

#gamedev #chron4

| 🌐 | 🙋‍ | @britown@blog.brianna.town

I've always wanted to nick this design ever since playing Divinity Original Sin 2.

Tiles that accept surface elements can now be made wet, frozen, shrouded, oiled, or burning. Applying elements interact with the existing status in a (mostly) intuitive way: Fire melts ice, water puts fires out, oil burns, etc. etc.

Since pushing is a big part of the game's combat, pushing an enemy through fire can be an extremely powerful tool. And anyone moving or getting pushed onto an ice tile will cause them to slide until they hit something!

Burning tiles also emit light and smoke from doused fires blocks vision for a few turns before dissipating.

The great thing about the enemy behavior system is that it has a very generic function for calculating value and cost from resultant game states. So the high-value things like getting close to an enemy or avoiding damage automatically incorporate the tile hazards and I'm already seeing enemies be smart about ice sliding usage.

There's so much to be done with all of this, I can't wait to start using it all with some encounter design and create synergies with different abilities ♥

#gamedev #chron4

| 🌐 | 🙋‍ | @britown@blog.brianna.town

Light and Vision are critical components for Chronicles with the dark areas of the world requiring torches to light your way.

Additionally, your character will remember tiles you've seen which appear on the screen like a map when they're not currently visible.

This knowledge persists between runs! It's an iterative effort from dozens of runs to map the world 😄

| 🌐 | 🙋‍ | @britown@blog.brianna.town

Chronicles uses 2D tiles like other RPG's but organizes the world into an arbitrary tree of map layers. In the end, every position in the entire game is in the same world coordinate system with all exteriors and interiors existing on the same continuous map.


To make this work performantly, the tiles are chunked and then stored in a QuadTree. Temporary static rendering takes place at higher zoom levels to allow you to fully explore and edit tiles even at a 10k x 10k scale while maintaining 60fps.

Buildings and towns and caves and dungeons and lakes and islands can all be separated into individual layers whose children will then be located relative to them. In the video I move a town to a different island layer and then move it around, which in turn moves around the town's child layer which is the buildings. I then add an event for a player origin so that when the game actually starts, it spawns a player-controlled actor at that point in the world. Moving the town would move this origin as well automatically!

The effect of all of this is new content can be created arbitrarily using the asset system. It's simple to mod in a new town or a new island on top of the existing geography and everything stacks up together.

A critical feature to this is that layers can be conditional based on the world state, allowing the world to change between runs. Towns can be destroyed, rivers flooded, bridges built, and all just by conditionally loading the correct layers when a run starts.

Querying the content of an individual tile in this massive world map is lightning-fast in this structure and allows a ton of freedom for creating content. Really proud of how all of this has come together!

#gamedev #chron4

| 🌐 | 🙋‍ | @britown@blog.brianna.town

There's some relevant game design talk going around today, and I kind of shy away from some of my not-implemented and not-playtested design ideas waiting to be poured into my game, not because they're secret but just because I'd rather show it all actually working instead of just talking about it.

But I feel like it for this so here we go!


When it comes to the larger run-based structure of Chronicles, I've talked a lot before about how the world isn't procedural but that it changes between runs. This is inspired by the notion of “Faction Turns” which I first heard about from Stars Without Number, and then also used to great effect running a modded 5e campaign through the Caverns of Thracia.

I believe Blades in the Dark does something similar to this but I haven't played it! Essentially, after enough time has passed, the world's factions get to “play a turn” wherein time passes in the larger world and macro-scale events take place including wars, changes of territory ownership, travel of key characters, etc. etc.

For Chronicles, the idea is that when your character falls in battle, the world will tick forward in time which will affect any of a very large list of possible variables. This can be as simple as shuffling around the enemy placement within a dungeon or as complicated as the defeat and razing of a population center. The world map system I'm working on uses a concept of “tile layering” to be able to phase in different states of the world piecemeal based on flags and counters that change from run to run.

This has a huge influence on how the player interfaces with the scale of the world. The only “fast travel” during one run is picking a starting point in the world from those you have unlocked. After that, it is a combination of just-plain-walking along with morrowind-style public transportation routes.

This is on my mind with the Dragon's Dogma Fast Travel quote going around today because the goal in my game is to create an environment where you aren't being forced to manually travel distances to create difficulty or friction, but rather that you get to traverse these distances because they'll be changing in subtle or not-so-subtle ways regularly!

Whether or not this actually works in practice or is achievable by a single creator remains to be seen, but I am fairly confident in my approach, primarily optimizing for how quick and easy it is to add new conditions and throw together a variety of layers. The next milestone should show off this working on a smaller scale :eggbug:

Edit: Here's a Masto post from last year talking about the new map system a bit!

From a commenter:

This is really cool and actually was the thing that caught my attention when I first read about Chronicles. I think no matter how successful you are with the execution, it's bound to produce something interesting!

If you're looking for inspo within video games, Unexplored 2: The Wayfarer's Legacy does something similar to this! Not quite the same and the implementation sounds very different than yours, but there are various factions in the game (ranging from clans and empires to “giant spider monster”) that act when your character dies, with imperial forces that are hunting you down spreading out on the map and the giant spider moving between caves to nest in (they're still updating the game so this might be somewhat outdated).

In theory it works great – every time you die the game world can become harder to traverse, but you do have allied factions and if you power them up they can beat back the imperial forces so you're encouraged to help these factions instead of beelining towards the main quest. In practice though, at least when I last played the game, dying wasn't a super common occurrence if you were careful and the actions during a tick weren't very drastic so it felt out of sync with the rest of the gameplay (I think they might have actually updated it to happen more than just on deaths now but it's been a while since I've given it a go).

I guess all that to say, maybe some questions to think about as you're building this out, if they're not already on your mind:

  • What happens to someone who's really good at the game and will not die a lot? Will they miss part of the intended experience with this?
  • What happens if someone sucks at the game and dies a lot? Does playing poorly always lead to a worse map state? Could that lead to snowballing failures? (Not always a bad thing!)
  • How much variation can this system provide? If someone dies a bunch, will they end up in the same scenarios quickly?
  • Can there be a set of conditions that make the map unplayable? Or just not fun to play?
  • Could a large gap of time between deaths make the faction turns seem inconsequential, or in the opposite case, overwhelming? Should the amount of time since the last death factor into how many actions are taken between turns? Would it make sense within the story you're trying to tell?

I was already looking forward to the next milestone after playing the combat demo, but now I'm real excited for it!

Thank you for the very thorough response!! I will have to look into Unexplored 2, that sounds really interesting!

To address some of your questions, I have a few philosophical rules for faction turn consequences that should try to alleviate most of the obvious pitfalls.

1) Death is expected. Never or rarely dying on a blind playthrough would be highly unexpected partly due to a component of the difficulty being knowledge-based instead of only skill/tactical. Death isn't something that's generally punished with a worse game state, subscribing to the notion of “failing forward” where the progression of time may produce complications or variations, but avoid the snowball of everything getting harder. There's a lot of checks and balances needed to make this work.

2) Changes to the world have scope and can be heavily localized; being reactive to what areas were visited or where enemies were defeated or where the death took place. Series of events set in motion may not be strictly tied to a global clock, only beginning when the player has encountered it. A key trick here is to show evidence of things happening over the course of multiple runs to hint at progress being made or something having only recently happened. An example is a tunnel being dug where lanterns and pickaxes and miners are present and the passage widens or lengthens as time progresses.

3) Macro-scale changes driven by factions and larger timelines should be created with the goal of being able to be observed and interrupted. I want to avoid hidden timers that cut you off from content and I want the game to be completable with 0 or 10 thousand deaths. That being said, noticing something major in the world that took place is a great motivation to attempt to circumvent it or explore interactions with it on subsequent playthroughs!

#gamedev #chron4

| 🌐 | 🙋‍ | @britown@blog.brianna.town

I've had my project manager hat on for the last month+ trying to figure out the next standalone milestone that gets me closer to the full game. Originally, I assumed that I would just focus on creating the early game experience more or less as it would appear in the final product. Upon further thinking, if the combat mechanics milestone was designed around getting a bunch of mechanics and systems put together and working, then the next milestone should aim to do the same, just with a new set of systems.

So Milestone 2 is going to be: The Mid-Game Dungeon

Here's some major highlights for this milestone to get excited about:

  • A large, sprawling handcrafted dungeon to crawl through
  • Line-of-Sight, Fog-of-War, and Dynamic Lighting
  • Inventory and Equipment: Your strength comes from your loot
  • Sneaking
  • Enemy awareness: Baddies can see and hear you and hunt you down
  • Death is permanent and time progresses between runs
  • Some of your loot can be salvaged if you fall, the rest may be dispersed
  • A selection of abilities for both combat and exploration: experiment with different builds
  • Combat Mechanics cut from the last demo: Tile Hazards, Sigils, Stuns, Roots

I really want the next playtest to be more of what someone might expect to experience roughly halfway through a campaign.

I've spend the last week working on a complete overhaul of the map system to be able to support the new interconnected world, and it's probably onto lighting and sight from there! I really feel like the work required for this is a lot less intense that everything that has come before it so I hope this one will come together rather quickly!

#gamedev #chron4

| 🌐 | 🙋‍ | @britown@blog.brianna.town

It's been a really wonderful week of getting my combat system into the hands of interested parties! I want to take some time to pontificate on the last 14 months as well as talk about the future.


Slow and Steady

I had largely given up on personal game development over the last few years. It really just demanded so much of my time and never ended in anything but disappointment. I also now have far more commitments throughout the week than I ever have before so it really started to feel like there was just no room for it anymore.

So when I was bit with the bug of this game, it was time to employ some new strategies.

This biggest difference between this project and every other attempt at making games in my life has been a fairly tight budget for time to work on it. There's a lot of life that's been happening and so I can't just go and dump 80 hour weeks into it. I've had to learn how to cope with the knowledge that large systems are going to potentially take weeks and that there's going to be fairly big gaps where I don't really get to touch it.

Once I began to make my peace with it, I found a much healthier relationship with my side project. I always coded and designed with the expectation that something might not come together for a while, and optimized for prioritizing systems that I immediately need rather than dumping large times into theoretical architecture. I also haven't, so far, burned completely out on the immense feature list by burning the candle on both ends week after week.

The fact that I could take a few months off and play Dwarf Fortress or get distracted with Tears of the Kingdom and still just come back and keep going with it is a testament to a better relationship with the work.

The Combat System Milestone

Early into the project, I identified that the scope was just enormous and had so many ideas going on. I knew it was too much for a single person to accomplish in any reasonable timeframe but also I knew that this was largely a hobby project for my own curiosity; something to tinker with in the evenings.

As I became more excited about the overall design that was brewing, I decided to break it into completable chunks to make progress somewhat realistic to track. Knowing at the time that I was prone to abandoning projects and could very well never see this dream completed, I wanted to design standalone games that would have ~80% overlap with the final vision. If I never completed the game, at least I'd have something to show for it.

At the heart of Chronicles' design is the tile-based combat. The initial elevator pitch was “Nethack, except with Disgaea-like tactics abilities, and Into-the-Breach's perfect turn information.” I also employed the health and stamina system that I had designed for a previous unseen real-time dungeon crawling project which fit perfectly into the gridded turn-based environment.

Regardless of how big the world is or how the character progression works out, the central heart of the game's success to me was making the combat fun. I hate kiting enemies into hallways in roguelikes and wanted something better. So if I couldn't make that elevator pitch work, there wasn't much use in continuing the project.

And so I wrote out the essential pieces necessary for making a standalone “Combat-Puzzles” game where each level you had to use your abilities to defeat the enemy formation. I forbade myself from thinking about shops, and world maps, and faction turns, and equipment, and instead focused on an asset-defined combat actions system for creating complex abilities, UI for turn result messaging, and creative enemy AI.

By far the biggest success of this way of doing a milestone is that I had to make an actual game around the combat so splash screen, menus, tooltips, and audio. I had to do a ton of shell architecture to actually present the combat to players so being forced to do that this early in the process was extremely beneficial!

Playtesting

I wanted to get feedback on whether or not the combat was fun from people without needing the larger structure to be defined. I was really self-conscious about the demo just coming off as a weekend game-jam game and I wanted to clearly denote that it's building toward a larger goal. I tried to call it a mechanics playtest more often than calling it a demo because felt weird to solicit feedback from something that is only tangentially related to the final product.

To help get feedback in this specific context, I solicited volunteers to playtest via a google form and then I chose to publish to a password-protected itch page, only sending out access to people who volunteered to help test. To me this encouraged participation from people who have been following this blog or otherwise have a personal interest in the project. This helped me with feeling anxious about people not understanding the goal of the release and it helped me organize and track feedback and issues.

I wanted to create a direct line of communication to people, so that I could address their individual needs and encourage sharing any thoughts. A big thing that helped a ton in this respect was to provide a list of feedback concerns and questions on the itch page. Nearly everyone who responded with feedback directly addressed those points! It was extremely effective to include those prompts!

I'm so incredibly thankful to the wonderful people I've gotten to meet and interact with this week!

Replays

I've designed my game with functional determinism in-mind and one of the big gets out of that is that it's easy to record user inputs in a game session and then simply replay them on my own copy of the executable.

The replay files are a compressed format including mouse movement and semantically-named game inputs all attached to frame-counts. By running the same version of the game with the same asset stack, I can replay those inputs and watch the player's session seamlessly. And since it's running the actual game I can

  • Hit break points in the code to track down bugs
  • Rewind to previous game states
  • Live-hotpatch the running code with Live++
  • Start playing myself from any point

This is enormous not just for focus testing but also for fixing bugs. I can see a bug in a replay and implement a fix for it all without restarting the program!

The final piece that made this perfect is including OpenSSL and DropBox's API to automatically upload the .chrep files to my DropBox for review. Naturally, I made sure to include a disclaimer at the top of the demo allowing the player to opt-out of the automatic upload. This system worked like a dream with replays from playtesters popping up on my DropBox within hours of sending out copies!

Often, by the time a tester had sent me their feedback email I already watched their session and could directly tie their experience to their feedback as though I had been standing behind them.

Cross-Platform

I recently posted about using Zig's build system to create cross-compilation targets for other platforms. This cost me nearly two weeks in mid-October but it wound up being a huge success! Although I could never get the auto-upload to work on those platforms, plenty of volunteer testers from Mac and Linux reached out to me manually sending me their replays.

I now have a simple batch file in my repo for building Windows, Mac, and Linux game versions all from Windows! M1 Macs coming soon!!

What's Next?

In between responding to testers and writing down notes and fixes, I've been doing a lot thinking about what my next actual development session even looks like.

As I crept closer to the combat demo being finished, I started to taste some of that forbidden fruit thinking about the larger game structure. I'm calling the next milestone “The Early-Game Demo” and is meant to be fairly representative (~80%) of the final product.

As opposed to the combat demo's level structure, this will have the run-based rogue-lite elements and be a showcase for the persistent world. I'm hoping that the full final 1.0 game release someday down the line will essentially consist of the Early Game Demo just with a ton more stuff!

Right now I'm putting my Project Manager hat on to try and build out a roadmap and prioritize all of the systems that need to get built. It's starting to sound like the first major task is replacing the current map system with a world-map grid. More on that another time!

Thank you!

To everyone who has followed my little side-project or gotten anything out of these blog posts! Whether you helped playtest, left a kind comment once, or just smashed that fave button, I really get so much joy sharing this thing with these little corners of internet!

Have a great day! :eggbug:

#gamedev #chron4 #longpost

| 🌐 | 🙋‍ | @britown@blog.brianna.town