Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Savior Maker (Tech Demo)

A sexy, old-school dungeon crawler tech demo. Help Serena get to the bottom of the haunted house! · By bbsoftworks

Devblog 11/3

A topic by bbsoftworks created Nov 03, 2024 Views: 42
Viewing posts 1 to 1
Developer

BB-DungeonCrawl is coded from scratch in Godot.

As of 11/3: ~2200 lines of code (it's certainly growing!)

So this is another bit of a lengthy post that I'm going to try and keep short, but there's only so much I can do while trying to summarize what I did during October! For this post, I'm going to write down some thoughts on general game design, my growing pains with building the game and things like that. Further down, you can find a more organized structure for key changes, bug fixes and what I plan on working on next.

October was tough in the sense that a lot of the systems were in place, at least in a very primitive manner. So equipment for the player, including stat bonuses (boni?), is available - however, there's no pictures to go with the armor, there's no damage to it or ArmorPoints, and no interactivity. Effects are in (see the previous devblog where I talk about Commands)  - however, you can attack, double damage attack and heal, which seems limited for a game with 1-on-1 high-stakes combat. Environments were in and it's possible to navigate the "map" - but there's no way for me to lock a connection, or any coding for something like a traproom, and 90% of my "map" content is empty rooms.

So, even though I promised myself I was going to focus on content with the goal of releasing the functional tech demo at the end of October, I ended up not working as much on content as I did on improving old systems.

Environment Processor

The environment processor was a big undertaking and a massive leap forward in terms of functionality. Data is now added to the environment custom resources such as the sound the player hears when they enter this room, whether this room has been explored or not, and what other environment_resources are linked to this room (ie, exits, where does this room lead to). The environment_processor keeps a copy of all the rooms and is able to reference the data while the movement buttons are being generated, and therefore can change an exit name to ????? if the room hasn't been explored yet. Defining exits at the individual resource level also allows me to fine-tune how different rooms link together. Here's an example from the game:

First of all, remember this is a "virtual" map; there's no physicality to the rooms themselves or to the exits, only an arrangement defined by me; what I mean by this is that, if I wanted to, I could connect the basement to the moon because there's no actual distance between the two. Behind House is a room in the outside of the house. This room can be accessed from the Pathway to the House (aka the starting room), as well as from the second floor Balcony, and also from the Living Room. These are all meant to be plausible exits by the way, so I want them to make sense. Conceptually, you would have Pathway -> Behind House which is just walking (cue gravel sound and call it a day). You would also have Balcony -> Behind House, and this one's trickier because you can't climb from the yard to the second floor, but you can certainly jump from the second floor to the garden (now there's an HP cost to traversing this way). Finally, if you're inside, you should be able to open the living room door and simply walk to the garden - but if you were in the garden and trying to walk inside the house, you might find the living room door locked from the inside.

Each of these situations requires a different approach. The code needs to be simple enough to allow me to connect rooms easily and without having to define all these little variables if I don't need them. But, when I do need them, I need to be able to tell the game that jumping down from the Balcony costs 5 HP and, by the way, if the player can't afford it, make sure to stop them. A door might be locked, but is it locked from every direction that you enter it from? The Living Room is locked if you're coming in from the garden, but it wouldn't make sense for the Living Room to also be locked if you're entering from the Kitchen.

That level of granularity made the environment_processor into a significant challenge but also elevated the navigation to a new level, where the map itself can be a part of the survival aspect (rather than just speed-clicking the rooms in a straight line to the exit, which you could do before). There's additional functionality to change sounds depending on the particular exit (so, gravel sound if walking from pathway to garden, but falling sound and THUMP if going from Balcony to garden). To signal the player about these environmental challlenges, the env__processor also displays a "locked" icon if an entrance is unavailable, or a "danger" icon if there's an HP cost to the player. And, as I mentioned before, simply leaving all the details blank tells the script not to worry about it and leaves all the defaults on. For me, it's a huge win.

Effects

In case you missed the previous post, Effects are my version of entity-agnostic, modular objects which can be attached to the player or the enemy to cause something like damage, or healing, or buffing/debuffing, etc. They essentially started as a proof of concept kind of thing ("would it be possible to use the same damage object for both the player and the enemy to save me work?") and evolved to be an integral part of how combat is currently managed, what with being able to queue up actions, cancel them, process them, etc.

From one point of view, it was all about growth for effects. Started out with DamageEffect and expanded into Heal, StrongDamage, ArmorPierce, Buff/Debuff, and so on. Having different tactical options for different situations seemed like a natural fit for my kind of game, where combat is meant to be deadly and unforgiving and ignoring the enemy's defense on a critical round may be the difference between walking away with low HP or none at all.

However, there were other changes to the Effects system which ended up needing reworks at the combat_processor, which is the node that handles all combat logic. One of these changes is the action_circle_cost, aka how many actions does an Effect require to be queued. I had already added action_circles (ie, actions within a turn, depending on your speed) to the game and did a lot of coding around that early version - for instance, when using the cancel action button, your last queued action is removed and you are given a single action_circle back so you can queue up something else. But now, with different effects having different action_circle_costs, the code has to be rewritten in a way that identifies how many action_circles to return to the player. Before, enemy actions were deleted 1-to-1 with the player's, but now the code has to behave differently because player and enemy actions are not necessarily matched 1-to-1. All of these little things require constant revision and rework (and it would all be much better if I just designed everything perfectly from the beginning), but the "final" version is always satisfying to see in motion.

Armor Points

Before yesterday last week, Armor Points didn't even exist. This is meant to be an HP system for armors/clothing which absorbs damage for the player and, when damaged enough, come apart to become more powerful, less defensive and more interesting to look at :). Conceptually, all armor has 4 "states" of damage (think undamaged, low damage, high damage, broken) and every state has its own Armor Points to absorb damage with. So, for example, if the Psychic Robe has 3 AP, it has 3 AP for every of the 4 total states, which means 12 AP total. Every time you cross one of the 3 AP thresholds, a little bit of the robe comes off.

Compared to prior to this rework, where all damage goes directly to HP, a lot of the logic has to change! The player's take_damage formula hahd to be rewritten so that AP is damaged before HP is, which means keeping track of the current state of each specific armor and its AP. And what happens if an enemy hits for 5 damage, but there's only 3 AP left? Should the rest of the damage just fizzle out? No, I want that excess damage to hit the player's HP instead. Oh, and don't forget to call the function to break the armor when that happens! 

In the future, I plan to add bonuses to the armors depending on their state. So, for the Psychic Robe, "undamaged" state might provide +1 ATK, and "broken" might give you the ability to use the DoubleDamage attack, but leave you open to attacks because you have no AP left. I think it can add an interesting nuance to combat and how resources are managed, which should be challenging, which is the direction I see the game going.


NEW STUFF:

  • Armor Points added, armor will now absorb damage and break.
  • New effects added including buff/debuff stats and Armor Piercing damage.
  • Attacks can now use mana as a resource, or cost more than one action per turn, or both.
  • File structure reorganization, matters only to me.
  • 3 armors with pictures added (Psychic Robe, Shirt + Skirt, Domina).
  • Basic, if tardy functionality, such as an Escape Battle button.
  • Enemies can now drop items if defeated in battle and the player doesn't have the item.
  • Placeholder game over screen that allows player to restart the game instead of having to reopen the game.
  • Max mana is now determined based on the armor being worn, making decisions around armor more significant.


MAJOR BUG FIXES:

  • Buff stats can be used to buff stats infinitely (unfixed, but found :P)
  • Armor states not being tracked separately by armor (ie, damage to one armor was affecting all armor).
  • Custom resource data not being saved along with character save data.
  • Text window / combat log overflowing, there should be no occurrences of lines being hidden unless I screw up again and add a newline where I'm not supposed to.
  • release_effect (code used to delete an effect and return all affected stats to normal, such as in the case of buffing) now differentiates between effects being used vs canceled so, for example, mana is returned when queueing an attack and canceling it.


PLANNED ADDITIONS:

  • Encounter bar rework. Once a threshold is reached (x amount of encounters? x amount of levelups? x amount of rooms explored?), enemies receive bonuses.
  • Finish Armor rework to provide bonuses per state.
  • Make all equipment significant, the way armor currently is: each armor has stats for how much mana you can have, how much AP it provides, stat boni, etc, which means that choosing one armor over another should be something to think about. I'd like for weapons and accessories to be similarly important: for example, weapons might give you a specific skill that's unique to that weapon. Or they might have customizable slots which the player can add different boni to (kinda like a Materia system).
  • UI improvements so that shit isn't in the wrong place, the wrong size, or unaligned (ugh!).
  • Rebalancing enemies to account for the new Armor system.