From ddb6f3c316d51851bf829e76cab3905eec3d80a4 Mon Sep 17 00:00:00 2001 From: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Date: Sun, 11 Aug 2024 18:54:46 -0400 Subject: [PATCH] Wounds Atomization: repairing clothes (#10782) * finished, basically * 515 * fix broken overlays --- code/__DEFINES/obj_flags.dm | 8 +- code/__HELPERS/type2type.dm | 16 ++ code/_onclick/item_attack.dm | 41 +-- code/datums/traits/negative_quirk.dm | 2 +- code/game/objects/obj_defense.dm | 1 + code/modules/clothing/clothing.dm | 241 ++++++++++++++---- code/modules/clothing/glasses/_glasses.dm | 2 +- code/modules/clothing/gloves/_gloves.dm | 12 +- code/modules/clothing/head/_head.dm | 2 +- code/modules/clothing/masks/_masks.dm | 2 +- code/modules/clothing/shoes/_shoes.dm | 2 +- .../clothing/spacesuits/_spacesuits.dm | 5 +- code/modules/clothing/suits/_suits.dm | 2 +- code/modules/clothing/under/_under.dm | 8 +- .../mob/living/carbon/human/human_defense.dm | 13 + code/modules/ninja/suit/gloves.dm | 2 +- 16 files changed, 274 insertions(+), 85 deletions(-) diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index c5d69146da015..ccb1c97b78797 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -50,7 +50,13 @@ #define SCAN_BOOZEPOWER (1<<12) //! Allows helmets and glasses to scan reagents. #define MASKEXTENDRANGE (1<<13) //! For masks, allows you to breathe from internals on adjecent tiles #define NOTCONSUMABLE (1<<14) //! Moths cannot eat clothing with that flag -#define HEADINTERNALS (1<<15) //! Headgear/helmet allows internals +/// Headgear/helmet allows internals +#define HEADINTERNALS (1<<18) + +/// Integrity defines for clothing (not flags but close enough) +#define CLOTHING_PRISTINE 0 // We have no damage on the clothing +#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped +#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first /// Flags for the organ_flags var on /obj/item/organ diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 17d0f18859353..9e97d2b6c031e 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -175,6 +175,22 @@ . = "NONE" return . +/// For finding out what body parts a body zone covers, the inverse of the below basically +/proc/body_zone2cover_flags(def_zone) + switch(def_zone) + if(BODY_ZONE_CHEST) + return CHEST|GROIN + if(BODY_ZONE_HEAD) + return HEAD + if(BODY_ZONE_L_ARM) + return ARM_LEFT|HAND_LEFT + if(BODY_ZONE_R_ARM) + return ARM_RIGHT|HAND_RIGHT + if(BODY_ZONE_L_LEG) + return LEG_LEFT|FOOT_LEFT + if(BODY_ZONE_R_LEG) + return LEG_RIGHT|FOOT_RIGHT + /// Converts an RGB color to an HSL color /proc/rgb2hsl(red, green, blue) red /= 255;green /= 255;blue /= 255; diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index bebe1933939a6..86011abca63a6 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -81,20 +81,21 @@ return I.attack(src, user) /** - * Called from [/mob/living/attackby] - * - * Arguments: - * * mob/living/M - The mob being hit by this item - * * mob/living/user - The mob hitting with this item - */ -/obj/item/proc/attack(mob/living/M, mob/living/user) - var/signal_return = SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) + * Called from [/mob/living/proc/attackby] + * + * Arguments: + * * mob/living/target_mob - The mob being hit by this item + * * mob/living/user - The mob hitting with this item + * * params - Click params of this attack + */ +/obj/item/proc/attack(mob/living/M, mob/living/user, params) + var/signal_return = SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user, params) if(signal_return & COMPONENT_CANCEL_ATTACK_CHAIN) return TRUE if(signal_return & COMPONENT_SKIP_ATTACK) return - SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user, params) SEND_SIGNAL(M, COMSIG_MOB_ITEM_ATTACKBY, user, src) var/nonharmfulhit = FALSE @@ -165,17 +166,17 @@ /mob/living/attacked_by(obj/item/I, mob/living/user) send_item_attack_message(I, user) - if(I.force) - var/armour_block = run_armor_check(null, MELEE, armour_penetration = I.armour_penetration) - apply_damage(I.force, I.damtype, blocked = armour_block) - if(I.damtype == BRUTE) - if(prob(33)) - I.add_mob_blood(src) - var/turf/location = get_turf(src) - add_splatter_floor(location) - if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood - user.add_mob_blood(src) - return TRUE //successful attack + if(!I.force) + return FALSE + var/armour_block = run_armor_check(null, MELEE, armour_penetration = I.armour_penetration) + apply_damage(I.force, I.damtype, blocked = armour_block) + if(I.damtype == BRUTE && prob(33)) + I.add_mob_blood(src) + var/turf/location = get_turf(src) + add_splatter_floor(location) + if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood + user.add_mob_blood(src) + return TRUE //successful attack /mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user, nonharmfulhit = FALSE) if(I.force < force_threshold || I.damtype == STAMINA || nonharmfulhit) diff --git a/code/datums/traits/negative_quirk.dm b/code/datums/traits/negative_quirk.dm index d20380451137a..561f23594f8cf 100644 --- a/code/datums/traits/negative_quirk.dm +++ b/code/datums/traits/negative_quirk.dm @@ -141,7 +141,7 @@ var/mob/living/carbon/human/H = quirk_target var/obj/item/heirloom_type - if(is_species(H, /datum/species/moth) && prob(50)) + if((ismoth(H)) && prob(50)) heirloom_type = /obj/item/flashlight/lantern/heirloom_moth else switch(quirk_holder.assigned_role) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 0aef759471a2a..3aeaa50a71511 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -296,6 +296,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e //what happens when the obj's integrity reaches zero. /obj/proc/obj_destruction(damage_flag) + if(damage_flag == ACID) acid_melt() else if(damage_flag == FIRE) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 747308300863a..723509ef40772 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -11,7 +11,7 @@ resistance_flags = FLAMMABLE max_integrity = 200 integrity_failure = 0.4 - var/damaged_clothes = 0 //similar to machine's BROKEN stat and structure's broken var + var/damaged_clothes = CLOTHING_PRISTINE //similar to machine's BROKEN stat and structure's broken var var/flash_protect = 0 //What level of bright light protection item has. 1 = Flashers, Flashes, & Flashbangs | 2 = Welding | -1 = OH GOD WELDING BURNT OUT MY RETINAS var/bang_protect = 0 //what level of sound protection the item has. 1 is the level of a normal bowman. var/tint = 0 //Sets the item's level of visual impairment tint, normally set to the same as flash_protect @@ -31,6 +31,9 @@ var/clothing_flags = NONE + /// What items can be consumed to repair this clothing (must by an /obj/item/stack) + var/repairable_by = /obj/item/stack/sheet/cotton/cloth + var/can_be_bloody = TRUE //Var modification - PLEASE be careful with this I know who you are and where you live @@ -51,6 +54,13 @@ var/high_pressure_multiplier = 1 var/static/list/high_pressure_multiplier_types = list(MELEE, BULLET, LASER, ENERGY, BOMB) + /// How much clothing damage has been dealt to each of the limbs of the clothing, assuming it covers more than one limb + var/list/damage_by_parts + /// How much integrity is in a specific limb before that limb is disabled (for use in [/obj/item/clothing/proc/take_damage_zone], and only if we cover multiple zones.) Set to 0 to disable shredding. + var/limb_integrity = 0 + /// How many zones (body parts, not precise) we have disabled so far, for naming purposes + var/zones_disabled + /// A lazily initiated "food" version of the clothing for moths var/obj/item/food/clothing/moth_snack @@ -113,26 +123,127 @@ else qdel(src) -/obj/item/clothing/attack(mob/attacker, mob/user, def_zone) - if(user.a_intent != INTENT_HARM && (ismoth(attacker) || ispsyphoza(attacker)) && !(clothing_flags & NOTCONSUMABLE) && !(resistance_flags & INDESTRUCTIBLE) && (armor.getRating(MELEE) == 0)) - if (isnull(moth_snack)) - moth_snack = new - moth_snack.name = name - moth_snack.clothing = WEAKREF(src) - moth_snack.attack(attacker, user, def_zone) - else - return ..() +/obj/item/clothing/attack(mob/attacker, mob/user, params) + if(user.a_intent == INTENT_HARM) + return //Harm intent does not eat + //if(!ismoth(attacker) || !ispsyphoza(attacker)) + // return ..() //Not a clotheater species? No Clotheating! + //if((clothing_flags & NOTCONSUMABLE) && (resistance_flags & INDESTRUCTIBLE) && (armor.getRating(MELEE) != 0)) + // return ..() //Any remaining flags that make eating it impossible? + + if (isnull(moth_snack)) + moth_snack = new + moth_snack.name = name + moth_snack.clothing = WEAKREF(src) + moth_snack.attack(attacker, user, params) /obj/item/clothing/attackby(obj/item/W, mob/user, params) - if(damaged_clothes && istype(W, /obj/item/stack/sheet/cotton/cloth)) - var/obj/item/stack/sheet/cotton/cloth/C = W - C.use(1) - update_clothes_damaged_state(FALSE) - obj_integrity = max_integrity - to_chat(user, "You fix the damage on [src] with [C].") - return 1 + if(!istype(W, repairable_by)) + return ..() + + switch(damaged_clothes) + if(CLOTHING_PRISTINE) + return..() + if(CLOTHING_DAMAGED) + var/obj/item/stack/cloth_repair = W + cloth_repair.use(1) + repair(user, params) + return TRUE + if(CLOTHING_SHREDDED) + var/obj/item/stack/cloth_repair = W + if(cloth_repair.amount < 3) + to_chat(user, "You require 3 [cloth_repair.name] to repair [src].") + return TRUE + to_chat(user, "You begin fixing the damage to [src] with [cloth_repair]...") + if(!do_after(user, 6 SECONDS, src) || !cloth_repair.use(3)) + return TRUE + repair(user, params) + return TRUE + return ..() +/// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up +/obj/item/clothing/proc/repair(mob/user, params) + update_clothes_damaged_state(CLOTHING_PRISTINE) + obj_integrity = max_integrity + name = initial(name) // remove "tattered" or "shredded" if there's a prefix + body_parts_covered = initial(body_parts_covered) + slot_flags = initial(slot_flags) + damage_by_parts = null + if(user) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + to_chat(user, "You fix the damage on [src].") + update_appearance() + +/** + * take_damage_zone() is used for dealing damage to specific bodyparts on a worn piece of clothing, meant to be called from [/obj/item/bodypart/proc/check_woundings_mods()] + * + * This proc only matters when a bodypart that this clothing is covering is harmed by a direct attack (being on fire or in space need not apply), and only if this clothing covers + * more than one bodypart to begin with. No point in tracking damage by zone for a hat, and I'm not cruel enough to let you fully break them in a few shots. + * Also if limb_integrity is 0, then this clothing doesn't have bodypart damage enabled so skip it. + * + * Arguments: + * * def_zone: The bodypart zone in question + * * damage_amount: Incoming damage + * * damage_type: BRUTE or BURN + * * armour_penetration: If the attack had armour_penetration + */ +/obj/item/clothing/proc/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration) + if(!def_zone || !limb_integrity || (initial(body_parts_covered) in GLOB.bitflags)) // the second check sees if we only cover one bodypart anyway and don't need to bother with this + return + var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered) // what do we actually cover? + if(!(def_zone in covered_limbs)) + return + + var/damage_dealt = take_damage(damage_amount * 0.1, damage_type, armour_penetration, FALSE) * 10 // only deal 10% of the damage to the general integrity damage, then multiply it by 10 so we know how much to deal to limb + LAZYINITLIST(damage_by_parts) + damage_by_parts[def_zone] += damage_dealt + if(damage_by_parts[def_zone] > limb_integrity) + disable_zone(def_zone, damage_type) + +/** + * disable_zone() is used to disable a given bodypart's protection on our clothing item, mainly from [/obj/item/clothing/proc/take_damage_zone()] + * + * This proc disables all protection on the specified bodypart for this piece of clothing: it'll be as if it doesn't cover it at all anymore (because it won't!) + * If every possible bodypart has been disabled on the clothing, we put it out of commission entirely and mark it as shredded, whereby it will have to be repaired in + * order to equip it again. Also note we only consider it damaged if there's more than one bodypart disabled. + * + * Arguments: + * * def_zone: The bodypart zone we're disabling + * * damage_type: Only really relevant for the verb for describing the breaking, and maybe obj_destruction() + */ +/obj/item/clothing/proc/disable_zone(def_zone, damage_type) + var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered) + if(!(def_zone in covered_limbs)) + return + + var/zone_name = parse_zone(def_zone) + var/break_verb = ((damage_type == BRUTE) ? "torn" : "burned") + + if(iscarbon(loc)) + var/mob/living/carbon/C = loc + C.visible_message("The [zone_name] on [C]'s [src.name] is [break_verb] away!", "The [zone_name] on your [src.name] is [break_verb] away!", vision_distance = COMBAT_MESSAGE_RANGE) + RegisterSignal(C, COMSIG_MOVABLE_MOVED, PROC_REF(bristle)) + + zones_disabled++ + for(var/i in body_zone2cover_flags(def_zone)) + body_parts_covered &= ~i + + if(body_parts_covered == NONE) // if there are no more parts to break then the whole thing is kaput + obj_destruction((damage_type == BRUTE ? "melee" : "laser")) // melee/laser is good enough since this only procs from direct attacks anyway and not from fire/bombs + return + + switch(zones_disabled) + if(1) + name = "damaged [initial(name)]" + if(2) + name = "mangy [initial(name)]" + if(3 to INFINITY) // take better care of your shit, dude + name = "tattered [initial(name)]" + + update_clothes_damaged_state(CLOTHING_DAMAGED) + update_appearance() + /obj/item/clothing/Destroy() user_vars_remembered = null //Oh god somebody put REFERENCES in here? not to worry, we'll clean it up QDEL_NULL(moth_snack) @@ -142,6 +253,8 @@ ..() if(!istype(user)) return + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + if(LAZYLEN(user_vars_remembered)) for(var/variable in user_vars_remembered) if(variable in user.vars) @@ -154,7 +267,10 @@ if (!istype(user)) return if(slot_flags & slot) //Was equipped to a valid slot for this item? - if (LAZYLEN(user_vars_to_edit)) + if(iscarbon(user) && LAZYLEN(zones_disabled)) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(bristle)) + + if(LAZYLEN(user_vars_to_edit)) for(var/variable in user_vars_to_edit) if(variable in user.vars) LAZYSET(user_vars_remembered, variable, user.vars[variable]) @@ -162,6 +278,10 @@ /obj/item/clothing/examine(mob/user) . = ..() + if(damaged_clothes == CLOTHING_SHREDDED) + . += "[p_theyre(TRUE)] completely shredded and require[p_s()] mending before [p_they()] can be worn again!" + return + switch (max_heat_protection_temperature) if (400 to 1000) . += "[src] offers the wearer limited protection from fire." @@ -169,22 +289,17 @@ . += "[src] offers the wearer some protection from fire." if (1601 to 35000) . += "[src] offers the wearer robust protection from fire." - if(damaged_clothes) - . += "It looks damaged!" - /* Bodypart wounds-related shit for when we eventually port https://github.com/tgstation/tgstation/pull/50558 - * for(var/zone in damage_by_parts) var/pct_damage_part = damage_by_parts[zone] / limb_integrity * 100 var/zone_name = parse_zone(zone) switch(pct_damage_part) if(100 to INFINITY) - . += span_warning("The [zone_name] is useless and requires mending!") + . += "The [zone_name] is useless and requires mending!" if(60 to 99) - . += span_warning("The [zone_name] is heavily shredded!") + . += "The [zone_name] is heavily shredded!" if(30 to 59) - . += span_danger("The [zone_name] is partially shredded.") - */ + . += "The [zone_name] is partially shredded." var/datum/component/storage/pockets = GetComponent(/datum/component/storage) if(pockets) @@ -276,32 +391,31 @@ /obj/item/clothing/obj_break(damage_flag) . = ..() - if(!damaged_clothes) - update_clothes_damaged_state(TRUE) - if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it - var/mob/M = loc - to_chat(M, "Your [name] starts to fall apart!") + update_clothes_damaged_state(CLOTHING_DAMAGED) + + if(isliving(loc)) //It's not important enough to warrant a message if it's not on someone + var/mob/living/M = loc + if(src in M.get_equipped_items(FALSE)) + to_chat(M, "Your [name] start[p_s()] to fall apart!") + else + to_chat(M, "[src] start[p_s()] to fall apart!") //This mostly exists so subtypes can call appriopriate update icon calls on the wearer. -/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE) - if(damaging) - damaged_clothes = 1 - else - damaged_clothes = 0 +/obj/item/clothing/proc/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) + damaged_clothes = damaged_state /obj/item/clothing/update_overlays() . = ..() if(!damaged_clothes) return - var/initial_icon = initial(icon) - var/index = "[REF(initial_icon)]-[initial(icon_state)]" + var/index = "[REF(icon)]-[icon_state]" var/static/list/damaged_clothes_icons = list() var/icon/damaged_clothes_icon = damaged_clothes_icons[index] if(!damaged_clothes_icon) - damaged_clothes_icon = icon(icon, icon_state, null, 1) - damaged_clothes_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) + damaged_clothes_icon = icon(icon, icon_state, , 1) + damaged_clothes_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon) damaged_clothes_icons[index] = damaged_clothes_icon @@ -314,15 +428,15 @@ SEE_MOBS // can see all mobs, no matter what SEE_OBJS // can see all objs, no matter what SEE_TURFS // can see all turfs (and areas), no matter what SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are - // in a lit area (via pixel_x,y or smooth movement), can see those pixels + // in a lit area (via pixel_x,y or smooth movement), can see those pixels BLIND // can't see anything */ /proc/generate_female_clothing(index,t_color,icon,type) - var/icon/female_clothing_icon = icon("icon"=icon, "icon_state"=t_color) + var/icon/female_clothing_icon = icon("icon"=icon, "icon_state"=t_color) var/icon/female_s = icon("icon"='icons/mob/clothing/under/masking_helpers.dmi', "icon_state"="[(type == FEMALE_UNIFORM_FULL) ? "female_full" : "female_top"]") female_clothing_icon.Blend(female_s, ICON_MULTIPLY) - female_clothing_icon = fcopy_rsc(female_clothing_icon) + female_clothing_icon = fcopy_rsc(female_clothing_icon) GLOB.female_clothing_icons[index] = female_clothing_icon /obj/item/clothing/under/proc/set_sensors(mob/user) @@ -436,11 +550,19 @@ BLIND // can't see anything fitted = NO_FEMALE_UNIFORM if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted body_parts_covered &= ~CHEST + body_parts_covered &= ~ARMS else fitted = initial(fitted) envirosealed = initial(envirosealed) if(!alt_covers_chest) body_parts_covered |= CHEST + body_parts_covered |= ARMS + if(!LAZYLEN(damage_by_parts)) + return adjusted + for(var/zone in list(BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) // ugly check to make sure we don't reenable protection on a disabled part + if(damage_by_parts[zone] > limb_integrity) + for(var/part in body_zone2cover_flags(zone)) + body_parts_covered &= part return adjusted /obj/item/clothing/proc/weldingvisortoggle(mob/user) //proc to toggle welding visors on helmets, masks, goggles, etc. @@ -484,12 +606,13 @@ BLIND // can't see anything return 1 return 0 +/obj/item/clothing/proc/_spawn_shreds() + new /obj/effect/decal/cleanable/shreds(get_turf(src), name) + /obj/item/clothing/obj_destruction(damage_flag) - if(damage_flag == BOMB || damage_flag == MELEE) - var/turf/T = get_turf(src) - spawn(1) //so the shred survives potential turf change from the explosion. - var/obj/effect/decal/cleanable/shreds/Shreds = new(T) - Shreds.desc = "The sad remains of what used to be [name]." + if(damage_flag == BOMB) + //so the shred survives potential turf change from the explosion. + addtimer(CALLBACK(src, PROC_REF(_spawn_shreds)), 1) deconstruct(FALSE) if(damage_flag == CONSUME) //This allows for moths to fully consume clothing, rather than damaging it like other sources like brute var/turf/current_position = get_turf(src) @@ -498,9 +621,31 @@ BLIND // can't see anything var/mob/living/possessing_mob = loc possessing_mob.visible_message("[src] is consumed until naught but shreds remains!", "[src] falls apart into little bits!") deconstruct(FALSE) + else if(!(damage_flag in list(ACID, FIRE))) + body_parts_covered = NONE + slot_flags = NONE + update_clothes_damaged_state(CLOTHING_SHREDDED) + if(isliving(loc)) + var/mob/living/M = loc + if(src in M.get_equipped_items(FALSE)) //make sure they were wearing it and not attacking the item in their hands + M.visible_message("[M]'s [src.name] fall[p_s()] off, [p_theyre()] completely shredded!", "Your [src.name] fall[p_s()] off, [p_theyre()] completely shredded!", vision_distance = COMBAT_MESSAGE_RANGE) + M.dropItemToGround(src) + else + M.visible_message("[src] fall[p_s()] apart, completely shredded!", vision_distance = COMBAT_MESSAGE_RANGE) + name = "shredded [initial(name)]" // change the name -after- the message, not before. + update_appearance() else ..() +/// If we're a clothing with at least 1 shredded/disabled zone, give the wearer a periodic heads up letting them know their clothes are damaged +/obj/item/clothing/proc/bristle(mob/living/L) + SIGNAL_HANDLER + + if(!istype(L)) + return + if(prob(0.2)) + to_chat(L, "The damaged threads on your [src.name] chafe!") + /obj/item/clothing/get_armor_rating(d_type, mob/wearer) . = ..() if(high_pressure_multiplier == 1) diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 1c81e72e5dffe..7eb20bdca3c0c 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -31,7 +31,7 @@ /obj/item/clothing/glasses/examine(mob/user) . = ..() if(glass_colour_type && ishuman(user)) - . += "Alt-click to toggle its colors." + . += "Alt-click to toggle [p_their()] colors." /obj/item/clothing/glasses/update_overlays() . = ..() diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 1dbe7fdaab4e1..7c601c0c419f4 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -31,12 +31,14 @@ /obj/item/clothing/gloves/worn_overlays(mutable_appearance/standing, isinhands = FALSE, icon_file, item_layer, atom/origin) . = list() if(!isinhands) - if(damaged_clothes) - . += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves", item_layer) - if(HAS_BLOOD_DNA(src)) - . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", item_layer) + return + + if(damaged_clothes) + . += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves", item_layer) + if(HAS_BLOOD_DNA(src)) + . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", item_layer) -/obj/item/clothing/gloves/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/gloves/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index 464766aff8062..48d68753eecb8 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -143,7 +143,7 @@ if(HAS_BLOOD_DNA(src)) . += mutable_appearance('icons/effects/blood.dmi', "helmetblood", item_layer) -/obj/item/clothing/head/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/head/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 9540fed92cca0..e25003b96afd4 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -47,7 +47,7 @@ if(HAS_BLOOD_DNA(src)) . += mutable_appearance('icons/effects/blood.dmi', "maskblood", item_layer) -/obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/mask/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 6c5e6d1a16b43..7470dc01e32df 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -61,7 +61,7 @@ if(offset && equipped_before_drop) restore_offsets(user) -/obj/item/clothing/shoes/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/shoes/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index f753d1e455d3e..10f1173c51507 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -38,7 +38,10 @@ permeability_coefficient = 0.02 clothing_flags = NOTCONSUMABLE | STOPSPRESSUREDAMAGE | THICKMATERIAL body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - allowed = list(/obj/item/flashlight, /obj/item/tank/internals) + allowed = list( + /obj/item/flashlight, + /obj/item/tank/internals, + ) slowdown = 1 armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 50, FIRE = 80, ACID = 70, STAMINA = 10, BLEED = 50) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 3ddbb1945e747..a2411a769ca29 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -37,7 +37,7 @@ if(A.above_suit) . += U.accessory_overlay -/obj/item/clothing/suit/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/suit/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 2b1d78cfd6b5f..fbbe7af58d8dd 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -42,14 +42,16 @@ if(!attach_accessory(I, user)) return ..() -/obj/item/clothing/under/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/under/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) ..() if(ismob(loc)) var/mob/M = loc M.update_inv_w_uniform() - if(has_sensor > NO_SENSORS) + if(damaged_state == CLOTHING_SHREDDED && has_sensor > NO_SENSORS) has_sensor = BROKEN_SENSORS - update_sensors(NO_SENSORS) + else if(damaged_state == CLOTHING_PRISTINE && has_sensor == BROKEN_SENSORS) + has_sensor = HAS_SENSORS + update_sensors(NO_SENSORS) /obj/item/clothing/under/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 701172cac1662..ff02f8efca6fb 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -47,6 +47,19 @@ protection *= 1 - CLAMP01(physiology.armor.getRating(d_type) / 100) return (1 - protection) * 100 +///Get all the clothing on a specific body part +/mob/living/carbon/human/proc/clothingonpart(obj/item/bodypart/def_zone) + var/list/covering_part = list() + var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_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 && istype(bp , /obj/item/clothing)) + var/obj/item/clothing/C = bp + if(C.body_parts_covered & def_zone.body_part) + covering_part += C + return covering_part + /mob/living/carbon/human/on_hit(obj/projectile/P) if(dna?.species) dna.species.on_hit(P, src) diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm index 4f5669b3dcfe6..4925002d6a842 100644 --- a/code/modules/ninja/suit/gloves.dm +++ b/code/modules/ninja/suit/gloves.dm @@ -78,4 +78,4 @@ /obj/item/clothing/gloves/space_ninja/examine(mob/user) . = ..() if(HAS_TRAIT_FROM(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)) - . += "The energy drain mechanism is [candrain?"active":"inactive"]." + . += "[p_their(TRUE)] energy drain mechanism is [candrain?"active":"inactive"]."