Some more armor tweaks (#30398)

* summary

* (required)

* undef

* oh this is unused, nice

* ok but.. why

* a tiny bit more

* Update human_defense.dm

* Update mass_hallucination.dm
This commit is contained in:
kyunkyunkyun
2025-09-19 20:43:42 +05:00
committed by GitHub
parent b52f6cc6c0
commit 83509c3967
32 changed files with 155 additions and 142 deletions
+1 -1
View File
@@ -376,7 +376,7 @@ RESTRICT_TYPE(/mob/living/basic)
visible_message("<span class='warning'>[src] looks unharmed.</span>")
return FALSE
else
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
apply_damage(damage, damagetype, null, getarmor(armor_type = armorcheck))
return TRUE
@@ -305,7 +305,7 @@
var/atom/throw_target = get_edge_target_turf(L, get_dir(src, get_step_away(L, src)))
L.throw_at(throw_target, 4, 4)
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
var/armor = L.run_armor_check(def_zone = limb_to_hit, attack_flag = MELEE, armor_penetration_percentage = 50)
var/armor = L.run_armor_check(def_zone = limb_to_hit, armor_type = MELEE, armor_penetration_percentage = 50)
L.apply_damage(40, BRUTE, limb_to_hit, armor)
// Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms.
@@ -75,7 +75,7 @@
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
if(ishuman(L))
var/mob/living/carbon/human/H = L
H.apply_effect(10 SECONDS, KNOCKDOWN, H.run_armor_check(null, MELEE))
H.apply_effect(10 SECONDS, KNOCKDOWN, H.run_armor_check(armor_type = MELEE))
H.apply_damage(40, STAMINA)
else
L.Weaken(5 SECONDS)
@@ -160,39 +160,37 @@ emp_act
affecting.droplimb(FALSE, damtype)
/mob/living/carbon/human/getarmor(def_zone, type)
var/armorval = 0
var/organnum = 0
/// This proc calculates armor value for humans.
/// If null is passed for def_zone, then this will return something appropriate for all zones (e.g. area effect damage)
/mob/living/carbon/human/getarmor(def_zone, armor_type)
// If a specific bodypart is targetted, check if it exists, how that bodypart is protected and return the value
if(def_zone)
if(is_external_organ(def_zone))
return getarmor_organ(def_zone, type)
var/obj/item/organ/external/affecting = get_organ(def_zone)
return __getarmor_bodypart(def_zone, armor_type)
var/affecting = get_organ(def_zone)
if(affecting)
return getarmor_organ(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
return __getarmor_bodypart(affecting, armor_type)
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/obj/item/organ/external/organ in bodyparts)
armorval += getarmor_organ(organ, type)
organnum++
// If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
var/armor
var/mob_bodyparts
for(var/obj/item/organ/external/part as anything in bodyparts)
armor += __getarmor_bodypart(part, armor_type)
mob_bodyparts++
return (armorval/max(organnum, 1))
return armor / mob_bodyparts
/// This is an internal proc, returns the armor value for a particular bodypart [/obj/item/organ/external].
/// Use `getarmor()` instead
/mob/living/carbon/human/proc/__getarmor_bodypart(obj/item/organ/external/def_zone, armor_type)
// Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
var/list/obj/item/worn_items = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, l_ear, r_ear, wear_id, neck)
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(obj/item/organ/external/def_zone, type)
if(!type || !def_zone) return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, l_ear, r_ear, wear_id, neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
for(var/bp in body_parts)
if(!bp) continue
if(bp && isclothing(bp))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor.getRating(type)
protection += physiology.armor.getRating(type)
return protection
for(var/obj/item/thing in worn_items)
if(thing?.body_parts_covered & def_zone.body_part)
. += thing.armor.getRating(armor_type)
. += physiology.armor.getRating(armor_type)
//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ.
/mob/living/carbon/human/proc/get_siemens_coefficient_organ(obj/item/organ/external/def_zone)
@@ -208,17 +206,6 @@ emp_act
return siemens_coefficient
/mob/living/carbon/human/proc/check_head_coverage()
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
for(var/bp in body_parts)
if(!bp) continue
if(bp && isclothing(bp))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & HEAD)
return 1
return 0
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance var of the object
if(wear_suit && isitem(wear_suit))
var/obj/item/I = wear_suit
@@ -485,7 +472,14 @@ emp_act
if(!I.force)
return //item force is zero
var/armor = run_armor_check(affecting, MELEE, "<span class='warning'>Your armour has protected your [hit_area].</span>", "<span class='warning'>Your armour has softened hit to your [hit_area].</span>", armor_penetration_flat = I.armor_penetration_flat, armor_penetration_percentage = I.armor_penetration_percentage)
var/armor = run_armor_check(
def_zone = affecting,
armor_type = MELEE,
absorb_text = "Your armor has protected your [hit_area].",
soften_text = "Your armor has softened hit to your [hit_area].",
armor_penetration_flat = I.armor_penetration_flat,
armor_penetration_percentage = I.armor_penetration_percentage,
)
if(armor == INFINITY)
return
@@ -667,8 +661,7 @@ emp_act
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/organ/external/affecting = get_organ(ran_zone(L.zone_selected))
var/armor_block = run_armor_check(affecting, MELEE)
apply_damage(damage, BRUTE, affecting, armor_block)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, MELEE))
updatehealth("larva attack")
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
@@ -274,7 +274,7 @@
var/brute_loss = 0
var/burn_loss = 0
var/bomb_armor = ARMOUR_VALUE_TO_PERCENTAGE(getarmor(null, BOMB))
var/bomb_armor = ARMOUR_VALUE_TO_PERCENTAGE(getarmor(armor_type = BOMB))
var/list/valid_limbs = list("l_arm", "l_leg", "r_arm", "r_leg")
var/limbs_amount = 1
var/limb_loss_chance = 50
+1 -1
View File
@@ -1123,7 +1123,7 @@
amount -= RAD_BACKGROUND_RADIATION // This will always be at least 1 because of how skin protection is calculated
var/blocked = getarmor(null, RAD)
var/blocked = getarmor(armor_type = RAD)
if(blocked == INFINITY) // Full protection, go no further.
return
if(amount > RAD_BURN_THRESHOLD)
+39 -27
View File
@@ -1,38 +1,43 @@
/*
run_armor_check(a,b)
args
a:def_zone - What part is getting hit, if null will check entire body
b:attack_flag - What type of attack, bullet, laser, energy, melee
Returns
0 - no block
1 - halfblock
2 - fullblock
/**
* Returns final, affected by `armor_penetration_flat` and `armor_penetration_percentage`, armor value of specific armor type
*
* * def_zone - What part is getting hit, if not set will check armor of entire body
* * armor_type - What type of armor is used. MELEE, BULLET, MAGIC etc.
* * absorb_text - Text displayed when your armor makes you immune (armor is INFINITY)
* * soften_text - Text displayed when 0 < armor < INFINITY. So armor protected us from some damage
* * penetrated_text - Text displayed when armor penetration decreases non 0 armor to 0. So it's completely penetrated
* * armor_penetration_percentage - % of armor value that is penetrated. Does nothing if armor <= 0. Happens before flat AP
* * armor_penetration_flat - armor value that is penetrated. Does nothing if armor <= 0. Occurs after percentage AP
*/
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = MELEE, absorb_text = "Your armor absorbs the blow!", soften_text = "Your armor softens the blow!", armor_penetration_flat = 0, penetrated_text = "Your armor was penetrated!", armor_penetration_percentage = 0)
var/armor = getarmor(def_zone, attack_flag)
/mob/living/proc/run_armor_check(
def_zone,
armor_type = MELEE,
absorb_text = "Your armor absorbs the blow!",
soften_text = "Your armor softens the blow!",
penetrated_text = "Your armor was penetrated!",
armor_penetration_flat,
armor_penetration_percentage,
)
. = getarmor(def_zone, armor_type)
if(armor == INFINITY)
if(. == INFINITY)
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
return armor
if(armor <= 0)
return armor
return
if(. <= 0)
return
if(!armor_penetration_flat && !armor_penetration_percentage)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
return armor
return
var/armor_original = armor
armor = max(0, (armor * ((100 - armor_penetration_percentage) / 100)) - armor_penetration_flat)
if(armor_original <= armor)
. = max(0, . * (100 - armor_penetration_percentage) / 100 - armor_penetration_flat)
if(.)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
else
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
return armor
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
/mob/living/proc/getarmor(def_zone, type)
/// Returns armor value of our mob.
/// As u can see, mobs have no armor by default so we override this proc on mob subtypes if we add them any armor
/mob/living/proc/getarmor(def_zone, armor_type)
return 0
/mob/living/proc/is_mouth_covered(head_only = FALSE, mask_only = FALSE)
@@ -124,7 +129,7 @@
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
if(isitem(AM))
var/obj/item/thrown_item = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
var/nosell_hit = SEND_SIGNAL(thrown_item, COMSIG_MOVABLE_IMPACT_ZONE, src, zone, throwingdatum) // TODO: find a better way to handle hitpush and skipcatch for humans
if(nosell_hit)
skipcatch = TRUE
@@ -140,7 +145,14 @@
visible_message("<span class='danger'>[src] is hit by [thrown_item]!</span>", "<span class='userdanger'>You're hit by [thrown_item]!</span>")
if(!thrown_item.throwforce)
return
var/armor = run_armor_check(zone, MELEE, "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", thrown_item.armor_penetration_flat, armor_penetration_percentage = thrown_item.armor_penetration_percentage)
var/armor = run_armor_check(
def_zone = zone,
armor_type = MELEE,
absorb_text = "Your armor has protected your [parse_zone(zone)].",
soften_text = "Your armor has softened hit to your [parse_zone(zone)].",
armor_penetration_flat = thrown_item.armor_penetration_flat,
armor_penetration_percentage = thrown_item.armor_penetration_percentage,
)
apply_damage(thrown_item.throwforce, thrown_item.damtype, zone, armor, thrown_item.sharp, thrown_item)
if(QDELETED(src)) //Damage can delete the mob.
return
@@ -80,7 +80,7 @@
visible_message("<span class='warning'>[src] looks unharmed.</span>")
return FALSE
else
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
apply_damage(damage, damagetype, null, getarmor(armor_type = armorcheck))
return TRUE
/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
@@ -94,7 +94,7 @@
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
var/bomb_armor = getarmor(null, BOMB)
var/bomb_armor = getarmor(armor_type = BOMB)
switch(severity)
if(1)
if(prob(bomb_armor))
@@ -738,16 +738,13 @@
"<span class='userdanger'>[src] drives over you!</span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
var/damage = rand(5,15)
H.apply_damage(2*damage, BRUTE, "head", run_armor_check("head", MELEE))
H.apply_damage(2*damage, BRUTE, "chest", run_armor_check("chest", MELEE))
H.apply_damage(0.5*damage, BRUTE, "l_leg", run_armor_check("l_leg", MELEE))
H.apply_damage(0.5*damage, BRUTE, "r_leg", run_armor_check("r_leg", MELEE))
H.apply_damage(0.5*damage, BRUTE, "l_arm", run_armor_check("l_arm", MELEE))
H.apply_damage(0.5*damage, BRUTE, "r_arm", run_armor_check("r_arm", MELEE))
var/damage = rand(5, 15)
H.apply_damage(2 * damage, BRUTE, BODY_ZONE_HEAD, run_armor_check(BODY_ZONE_HEAD, MELEE))
H.apply_damage(2 * damage, BRUTE, BODY_ZONE_CHEST, run_armor_check(BODY_ZONE_CHEST, MELEE))
H.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_LEG, run_armor_check(BODY_ZONE_L_LEG, MELEE))
H.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_LEG, run_armor_check(BODY_ZONE_R_LEG, MELEE))
H.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_ARM, run_armor_check(BODY_ZONE_L_ARM, MELEE))
H.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_ARM, run_armor_check(BODY_ZONE_R_ARM, MELEE))
if(NO_BLOOD in H.dna.species.species_traits)//Does the run over mob have blood?
return//If it doesn't it shouldn't bleed (Though a check should be made eventually for things with liquid in them, like slime people.)
@@ -166,22 +166,22 @@
update_corgi_fluff()
regenerate_icons()
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, type)
/mob/living/simple_animal/pet/dog/corgi/getarmor(def_zone, armor_type)
var/armorval = 0
if(def_zone)
if(def_zone == "head")
if(inventory_head)
armorval = inventory_head.armor.getRating(type)
armorval = inventory_head.armor.getRating(armor_type)
else
if(inventory_back)
armorval = inventory_back.armor.getRating(type)
armorval = inventory_back.armor.getRating(armor_type)
return armorval
else
if(inventory_head)
armorval += inventory_head.armor.getRating(type)
armorval += inventory_head.armor.getRating(armor_type)
if(inventory_back)
armorval += inventory_back.armor.getRating(type)
armorval += inventory_back.armor.getRating(armor_type)
return armorval * 0.5
/mob/living/simple_animal/pet/dog/corgi/item_interaction(mob/living/user, obj/item/O, list/modifiers)
@@ -338,7 +338,7 @@ Difficulty: Hard
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] tramples you into the ground!</span>")
forceMove(get_turf(L))
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armor_penetration_flat, armor_penetration_percentage))
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, armor_penetration_flat = armor_penetration_flat, armor_penetration_percentage = armor_penetration_percentage))
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE)
shake_camera(L, 4, 3)
shake_camera(src, 2, 3)
@@ -321,7 +321,7 @@ Difficulty: Hard
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
playsound(T, attack_sound, 100, TRUE, -1)
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
L.apply_damage(second_life ? 20 : 10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armor_penetration_flat, armor_penetration_percentage))
L.apply_damage(second_life ? 20 : 10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, armor_penetration_flat = armor_penetration_flat, armor_penetration_percentage = armor_penetration_percentage))
SLEEP_CHECK_DEATH(3)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T, handedness)
@@ -357,8 +357,8 @@ Difficulty: Very Hard
loot += pick_n_take(choices)
/obj/item/projectile/colossus
name ="death bolt"
icon_state= "chronobolt"
name = "death bolt"
icon_state = "chronobolt"
damage = 25
armor_penetration_percentage = 100
speed = 2
@@ -762,7 +762,7 @@ Difficulty: Hard
playsound(target,'sound/weapons/sear.ogg', 50, TRUE, -4)
to_chat(target, "<span class='userdanger'>You're struck by \a [name]!</span>")
var/limb_to_hit = target.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
var/armor = target.run_armor_check(limb_to_hit, MELEE, "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
var/armor = target.run_armor_check(limb_to_hit, MELEE, "Your armor absorbs [src]!", "Your armor blocks part of [src]!", "Your armor was penetrated by [src]!", 50)
target.apply_damage(damage, BURN, limb_to_hit, armor)
if(ishostile(target))
var/mob/living/simple_animal/hostile/H = target //mobs find and damage you...
@@ -30,7 +30,7 @@
else
// Target prioritization by spider type. BRUTE spiders prioritize lower armor values, POISON spiders prioritize poisonable targets
if(ai_target_method == TS_DAMAGE_BRUTE)
var/theirarmor = C.getarmor(type = MELEE)
var/theirarmor = C.getarmor(armor_type = MELEE)
// Example values: Assistant: 2, Engineer w/ Hardsuit: 10, Sec Officer with armor: 19, HoS: 48, Deathsquad: 80
if(theirarmor < 10)
targets1 += C
+1 -1
View File
@@ -403,7 +403,7 @@
var/obj/item/clothing/hat = attacker.head
if(istype(hat))
damage += hat.force * 3
affecting.apply_damage(damage*rand(90, 110)/100, BRUTE, "head", affected.run_armor_check(affecting, MELEE))
affecting.apply_damage(damage * rand(90, 110) / 100, BRUTE, BODY_ZONE_HEAD, affected.run_armor_check(affecting, MELEE))
playsound(assailant.loc, "swing_hit", 25, TRUE, -1)
add_attack_logs(assailant, affecting, "Headbutted")
return