After a couple of attempts to do some medical redesigns, one major part of this always results in my projects failures: The application of damage handling.
The major problem with damage handling is that it has a ton of different implementations, spread out across the entire codebase.

Here I am proposing a technical redesign for the application of damage, which will standardise the ways damage is dealt, making it easier to refactor, in turn making medical redesigns more feasable without shooting ourselves in the foot by attempting to build upon an already rocky foundation.

Targets:

  • Standardise the application of damage
  • Make a system that allows for easy modification and refactoring
  • Allow this to be able to replace all current use cases of damage application
  • Standardise things like armour penetration (The majority of damage applications entirely ignore armour at the moment)

Method:

  • Have an intermediary interface between the damage sources and damage targets.

Analysis of current damage application needs

Physical damage sources:

  • Items: Damage dealt directly from items being used to attack someone. Contains force, damage type, armour penetration, sharpness and attack weight.
  • Mobs:
    • Species:
    • Mob directly:

Abstract damage sources:

  • Viruses
  • Chemicals
  • Explosions
  • Blob damage (This one is the weirdest since the damage is applied through reagents??)
    These above abstract damage sources can be handled by creating a damage_source in the proc dealing the damage, applying the damage and then letting the created damage_source go out of scope where it will be GC'd.

Note that there are quite a few cases of unique damage application that needs to be taken into account. For example, kicking someone in the nuts requires a special damage application datum to be created for this unique attack, applied and then that can be handled by GC. It should be noted that the majority of these would be able to use the item's damage application proc instead, and won't need a new one to be created on the fly.
References should be carefully considered, so that these can pop out of existance at any time if they are created and used locally within a proc.

Damage source datum

Handling the target bodyzone

Damage sources often need to apply their damage to a specific target body zone. For this, we could directly pass in the bodyzone that we want to target within the proc that applies the damage, however this doesn't allow for easy expandability and refactoring in the future, since if we want to add something that is only sometimes used, we will need to refactor the damage application proc and add on our new functionality.

The best way to handle this would be to introduce another datum that can store information about how damage should be applied. This datum will be stored on the mob

Handling varying damage from the same damage sources
In order to account for damage sources that can vary from usage to usage (See CQC for an example, some attacks do 15 and some do 10, but are ultimately all coming from the same damage source), we need 2 procs.

//Set the force of the damage source to 15, temporarilly.
damage_source.set_force(15)
//Apply the damage source to the target
damage_source.apply(target)
//Set the force of the damage source back to the damage it had during creation.
//In New() we need to keep track of the initial damage value, so that we can change it back.
damage_source.reset_force()

If anything else changes on a whim, then it can use a new damage source. For example, while each CQC attack varies in damage, it will always have the same armour penetration and attack type, since that is the species damage source.

Unique situations with damtype
A unique case that comes to mind would be the rainbow knife. Every time you attack with the rainbow knife, the damage type changes. For this, the damage type of the damage_source can be modified directly.

damage_source.damtype = pick(BURN, BRUTE, ...)

Since these are unique situations, we don't need the robustness of being able to temporarilly set it and reset it like we do for source, which changes extremely commonly.

Hard-deletion handling:

  • Damage sources shouldn't be destroyed from code. In cases where they are no longer being used, byond GC will automatically collect them (if they are made temporarilly). As such, the damage_source should be self contained and shouldn't be passed on into the mob when damage is applied to the mob.