Files
Aurora.3/code/datums/components/armor/_armor.dm
T
FenodyreeAvandGitHub be17521156 Fixes armour checks, rubbers checking siemens and pain interrupting t… (#23023)
**_- bugfix: "Fixes all rubber bullets dealing damage twice."_**
Rubber bullets were dealing their pain damage twice, while checking if
they should shake your screen or not.

_**- bugfix: "Fixes all attacks that dealt pain damage checking siemens
coefficient. This makes everything but hardsuits and voidsuits stronger
against rubber bullets. Insulated gloves are also no longer immune to
rubber bullets."**_

Hardsuits has siemens 0.1, meaning they took 10% damage from all stuns.
Now rubber bullets check their melee armor. Hardsuits are now weaker, or
the same against stuns.

Regular armor all has siemens 0.5, they took a flat 50% reduction.
Security armour is slightly weaker to rubbers, ablative and ballistic
are much weaker. Combat armour is roughly the same, or slightly better.
Riot armour is a lot better.

Voidsuits all had better siemens than armour, all voidsuits are now
weaker against stuns.

Finally, all jumpsuits had 0.75 siemens, but no (or nearly no) armor.
Combined with the fix of them hitting twice this means that rubber
bullets previously dealt 50% more damage against people in jumpsuits
than they do now.

**_- bugfix: "Fixes pain failing to make your blurt out whatever you
were typing. Now getting shot will cause you to say whatever was in the
typing window when you were hit and close the window immediately,
allowing you to move."_**

No more getting stuck in the typing window when you're getting sprayed
down by an STS!
 

_**- bugfix: "Fixes all attacks that had manually set armour checks,
previously they ignored the armour they were meant to check and decided
what armour affected them based only on their damage type."**_

Weapons that were set to specifically target armour types, such as
explosive projectiles (rockets, etc) were instead defaulting to the
damage type they dealt. So a rocket to the head was checking your melee
armour, not your bomb armour.

---------

Signed-off-by: FenodyreeAv <fenodyree.av@gmail.com>
2026-08-16 16:13:03 +00:00

141 lines
5.2 KiB
Plaintext

/datum/component/armor
var/list/armor_values
var/full_block_message = "Your armor absorbs the blow!"
var/partial_block_message = "Your armor softens the blow!"
/// If this armour component should be hidden on examine.
var/hidden = FALSE
/// This controls how some armor types such as mech armor work.
var/armor_flags = ARMOR_TYPE_STANDARD
/// Armor 'works' for damages in range from 0 to [armor_range_mult * armor].
/// The lower the damage, the harder it gets blocked, tapering to 0 mitigation at [armor_range_mult * armor]
var/armor_range_mult = 2
/// [under_armor_mult] multiplies how strongly damage that is <= armor value is blocked.
/// E.g. setting it to 0 will flat out block all damage below armor
var/under_armor_mult = 0.7
/// [over_armor_mult] multiplies how strongly damage that is > armor value is blocked.
/// E.g. setting it to more than 1 will make mitigation drop off faster, effectively reducing the range of damage mitigation
var/over_armor_mult = 1
/// Used with ARMOR_TYPE_RIG.
var/sealed = FALSE
/datum/component/armor/Initialize(list/armor, armor_type, hidden)
..()
if(armor)
armor_values = armor.Copy()
if(armor_type)
armor_flags = armor_type
if(hidden)
hidden = TRUE
/**
* Takes in incoming damage value
* Applies state changes to self, holder, and whatever else caused by damage mitigation
* Returns modified damage, a list to allow for flag modification or damage conversion, in the same format as the arguments.
*/
/datum/component/armor/proc/apply_damage_modifications(damage, damage_type, damage_flags, mob/living/victim, armor_pen, silent = FALSE, check_armor)
if(armor_flags & ARMOR_TYPE_EXOSUIT)
if(prob(get_blocked(damage_type, damage_flags, armor_pen) * 100)) //extra removal of sharp and edge on account of us being big robots
damage_flags &= ~(DAMAGE_FLAG_SHARP | DAMAGE_FLAG_EDGE)
if(damage <= 0)
return args.Copy()
var/blocked = get_blocked(damage_type, damage_flags, armor_pen, damage, check_armor)
on_blocking(damage, damage_type, damage_flags, armor_pen, blocked)
// Blocking values that mean the damage was under armor, so all dangerous flags are removed (edge/sharp)
var/armor_border_blocking = 1 - (under_armor_mult * 1/armor_range_mult)
if(blocked >= armor_border_blocking)
if(damage_flags & DAMAGE_FLAG_LASER)
damage *= FLUIDLOSS_CONC_BURN/FLUIDLOSS_WIDE_BURN
damage_flags &= ~(DAMAGE_FLAG_SHARP | DAMAGE_FLAG_EDGE | DAMAGE_FLAG_LASER)
if(damage_type == DAMAGE_RADIATION)
damage = max(0, damage - 100 * blocked)
silent = TRUE
damage *= 1 - blocked
if(!silent)
if(blocked > 0.7)
to_chat(victim, SPAN_NOTICE(full_block_message))
else if(blocked > 0.2)
to_chat(victim, SPAN_NOTICE(partial_block_message))
return args.Copy()
/datum/component/armor/proc/on_blocking(damage, damage_type, damage_flags, armor_pen, blocked)
/**
* A simpler proc used as a helper for above but can also be used externally. Does not modify state.
* Returns a value between 0 and 1, representing the percentage of damage blocked by this armor component.
* armor_pen is subtracted from the armor value before calculating the percentage blocked.
* armor_range_mult is used to determine the range of damage that is mitigated by this armor
* under_armor_mult is used to determine how much damage is mitigated when the incoming damage is less than or equal to the armor value
* over_armor_mult is used to determine how much damage is mitigated when the incoming damage is greater than the armor value
*/
/datum/component/armor/proc/get_blocked(damage_type, damage_flags, armor_pen = 0, damage = 5, check_armor)
var/key = check_armor
if(!key)
key = get_armor_key(damage_type, damage_flags)
if(!key)
return 0
var/armor = max(0, get_value(key) - armor_pen)
if(!armor)
return 0
var/efficiency = min(damage / (armor_range_mult * armor), 1)
var/coef = damage <= armor ? under_armor_mult : over_armor_mult
return max(1 - coef * efficiency, 0)
/datum/component/armor/proc/get_value(key)
if(isnull(armor_values[key]))
return 0
if(armor_flags & ARMOR_TYPE_RIG)
if(key == BIO && sealed)
return 100
return min(armor_values[key], 100)
/datum/component/armor/proc/set_value(key, newval)
armor_values[key] = clamp(newval, 0, 100)
// There is a disconnect between legacy damage and armor code. This here helps bridge the gap.
/proc/get_armor_key(damage_type, damage_flags)
var/key
switch(damage_type)
if(DAMAGE_BRUTE)
if(damage_flags & DAMAGE_FLAG_BULLET)
key = BULLET
else if(damage_flags & DAMAGE_FLAG_EXPLODE)
key = BOMB
else
key = MELEE
if(DAMAGE_BURN)
if(damage_flags & DAMAGE_FLAG_LASER)
key = LASER
else if(damage_flags & DAMAGE_FLAG_EXPLODE)
key = BOMB
else
key = ENERGY
if (DAMAGE_TOXIN)
if(damage_flags & DAMAGE_FLAG_BIO)
key = BIO // Otherwise just not blocked by default.
if (DAMAGE_RADIATION)
key = RAD
return key
// Used for natural armor for species.
/datum/component/armor/natural
full_block_message = "Your natural armor blocks the blow!"
partial_block_message = "Your natural armor softens the blow!"
/datum/component/armor/toggle
var/active = TRUE
/datum/component/armor/toggle/proc/toggle(new_state)
active = new_state
/datum/component/armor/toggle/get_value(key)
return active ? ..() : 0