Refactoring Effects and Status

Freezing and burning effects

Quite a bit of refactoring this week, and some bug fixing as well. Net results: level-scalable effects and more/better status effects.

Effects now are level-scalable, and they also include a source entity. Basically, I have this Effect class everywhere in the gameplay code, which previously was just a generic Effect.Execute( Entity target). While super-general, it’s also super-problematic when I want to have more info. Long story short, I realised that changing that to Effect.Execute( Entity target, Entity source, float effectLevel) is absolutely great and useful for anywhere effects are used in the codebase. So, I can have a damage effect that scales with level, e.g. 5-30 damage at level 3, and add 1-6 to the min/max for each level thereafter. Example: instead of having a lot of healing potion variations, I could even get away with just a single healing potion with level scaling. There can be still weak/strong potion variations by changing the constant/scaling values (if a weak potion cures 1d8+2d4level, a strong potion could cure 2d8+4d4level). Level scaling is optional, so many effects are of course not scaled like that. By knowing who the source is, it’s easy to track the source entity to award XP on death, among other uses. This can/should chain, for example if a player creates a trap that applies a burning effect to a creature, that dies after 3 turns of being burnt, the user should get the XP.

Status effects got a big update, to support more complex things. I’ve added burning and freezing to test a few things:

  • Can now attach visual effects to the entity with that status, e.g. a freezing entity will appear blueish, whereas a burning entity will be surrounding in flames.
  • Can now attach effects, permanent or temporary, to status effects. For example burning has a permanent effect where, for a few turns, we repeatedly apply a permanent hit points modification (fire damage), so basically damage over time. Freezing has a temporary effect where it reduces the total speed by 50% for its duration. Status effects can optionally stack, so if I decide later to have a status effect, such as poison, that can stack, then getting poisoned twice might be twice as bad. Status effects can be associated to verbal, somatic or visual components, where as active abilities might require any combination of verbal (e.g. spell/warcry), somatic (anything that requires body movement) or visual (anything that requires a clear view of a target) component.
  • I’m not going to go the route of status effects cancelling each other and changing to other things (e.g. burning + frozen cancelling each other out, etc). If necessary, it can be explained anyway as your feet are burning while your arms are encased in ice πŸ™‚

Secret things are uncovered only when they are in view, and only uncover them by the player.

I also fixed a bug with passing StructuredBuffers to Unity shaders. Unity did not want to send a compute buffer to gpu correctly when in the shader I use StructuredBuffer and in Unity I specify the buffer with a size of 4,6,8 uints and a few more. Yes, totally reasonable, but it should warn me maybe that shader and ComputeBuffer do not match?? Ugh, spent 2-3 hours on that at least.

Entity effects & more

Entity effects: boss aura and an early prototype of a burning effect

Several “random” bits of work again this week, as my TODO list is a hydra. Solve one entry, and poof more appear. Not as bugs, but more like a dependency tree where you try to resolve a node and the fog of war dissipates and reveals more things that are not in place πŸ˜€

  • Framework for rendering “entity effects”, graphical effects attached to (and dependent on) a particular entity. Two examples are shown in the video above: a boss aura like Dungeonmans, and an early version of a burning effect.
  • Some debugging GUI for increasing attributes/skills
  • Added potions and tomes that increase attributes and skills
  • Allow per-creature blood spatters (on injury) and blood pools (on death). So that skeletons, ghosts and oozes don’t bleed.
  • Refactoring my configuration database to not have dependencies at all, as it got cyclic. So, I have for example the configuration for a creature race that depends on the configuration for an effect. The moment I started adding more effects, one of the effect types might depend on a creature configuration, so the dependency chain got cyclic, so I had to get rid of that. Now I’m doing a two-pass approach: first I load all the configurations in their most basic form and register their name (“allocate” them so to speak). Then in the second pass, I read everything normally, and order does not matter as I’ve allocated all the configurations by name in advance.
  • Machinery/planning for how a creature gets to learn active abilities (spells, active skills, special attack moves, etc):
    • Monsters have a mapping of ability-to-level-requirement. E.g. a monster wizard of level 3 would know firebolt, same creature level 7 would know fireball.
    • Equipping particular weapon categories might allow for special moves. E.g. equipping polearms would give a skill (that costs energy) which attacks from 2 tiles away
    • Progression in mastery levels in particular skills can unlock some active abilities.
    • Consumable items (e.g. book)
    • (tbd) Special dungeon objects
    • (tbd) Shops/trainers/people in cities
  • Try to be a bit more gamey and less simulationist with items and effects. Equipment will not have on-use effects, whereas potions should generally have different effects than, say, scrolls or items that can be used (wands? etc). Potions and scrolls should be different, beyond “this can get wet” for example

Refactoring abilities & input

Player getting blasted by AI’s ice AoE spell, then obliterating them with a multi-fireball. Yes, terrible and over the top, but it’s useful for testing πŸ™‚

Mainly refactoring work this week, with the purpose of unifying the handling of abilities by the player or the AI. Concrete outcomes of this refactoring process:

  • New WIP ability, usable by both player and AI: fireball.
    • We need to select a target position
    • It has an area of effect
    • It’s effect is “fire damage”
    • It spawns a particle system, initialised with the positions of affected tiles
    • Fireball itself is a projectile, so if it hits an obstacle, it will stop (and explode)
    • We can setup the skill to be able to shoot multiple ones, homing ones, or both
  • AI can use the fireball skill too, by evaluating the “score” of each possible tile, determined by the possibility to hit ourselves (-5 score), allies (-2 score each) and enemies (1 score each). A score greater than 1 means “good enough”
  • AI applies a recency-based weight when choosing a skill to execute. So, a no-cooldown skill that was just executed will have 75% weighting which goes back to 100% after several standard actions. This is to avoid repetition of maximally scoring abilities, and make the AI hopefully feel less robotic.
  • New WIP ability: magic missile.
    • Like fireball, but does damage to a single tile
    • Number of projectiles can be greater than one, and for each projectile we can select a different target. Homing missiles still need a clear path to a destination
  • Reworked item transfer interface a bit, so that when transferring items between player/container or player/ground, we can select a number of items from container, a number of items from the player, and then click a button to make the transaction. So that with a standard action we can move e.g. 2 items to the container and pick 3 items up.
  • Cleared up input/keys a bit (still far, far from final though). Now we have the following categories of actions:
    • Ability-based: Fireball, melee attack, ranged attack, use item, etc. These typically need to be configured with some gui (which item? which direction? etc). Most of these would not appear in an input configuration file, as we have just too many. Instead, they’ll be mapped to…
    • Hotkeys: so that I can map any ability-based actions to hotkeys. Whereas the essential actions are limited (move in a direction, primary action, etc), most abilities have to be mapped via hotkeys.
    • Actions that do not require a gui, e.g. quicksave, quickload, teleport, look.
    • Press-and-hold actions, e.g. highlighting of creatures or objects, minimap view