From 6c5369b69bc850192050649e48fba5d83182da6d Mon Sep 17 00:00:00 2001 From: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Date: Wed, 11 Sep 2024 03:33:33 -0700 Subject: [PATCH] Improved suit sensor repair (#86525) ## About The Pull Request Adds suit sensor repair to the cable coil attack chain, allowing you to fix your suit sensors by hitting yourself with cable coil. (Previously you'd have to use it on the uniform) Broken suit sensor is visible when examining the mob. ## Why It's Good For The Game Makes repairing your suit sensors more intuitive by responding similarly as applying mesh, sutures and other products. ## Changelog :cl: LT3 qol: Quick repair suit sensors by hitting yourself with cable coil qol: Improved feedback for broken suit sensors /:cl: --- code/modules/clothing/under/_under.dm | 111 +++++++++++++++------- code/modules/mob/living/carbon/examine.dm | 5 + code/modules/power/cable.dm | 4 + 3 files changed, 86 insertions(+), 34 deletions(-) diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 4482af81f02c0..226346fc81235 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -107,11 +107,7 @@ . += accessory_overlay /obj/item/clothing/under/attackby(obj/item/attacking_item, mob/user, params) - if(has_sensor == BROKEN_SENSORS && istype(attacking_item, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/cabling = attacking_item - to_chat(user, span_notice("You repair the suit sensors on [src] with [cabling].")) - cabling.use(1) - has_sensor = HAS_SENSORS + if(repair_sensors(attacking_item, user)) return TRUE if(istype(attacking_item, /obj/item/clothing/accessory)) @@ -130,35 +126,11 @@ /obj/item/clothing/under/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) . = ..() if(damaged_state == CLOTHING_SHREDDED && has_sensor > NO_SENSORS) - has_sensor = BROKEN_SENSORS + break_sensors() else if(damaged_state == CLOTHING_PRISTINE && has_sensor == BROKEN_SENSORS) - has_sensor = HAS_SENSORS + repair_sensors(cable_required = FALSE) update_appearance() -/obj/item/clothing/under/emp_act(severity) - . = ..() - if(. & EMP_PROTECT_SELF) - return - if(has_sensor == NO_SENSORS || has_sensor == BROKEN_SENSORS) - return - - if(severity <= EMP_HEAVY) - has_sensor = BROKEN_SENSORS - if(ismob(loc)) - var/mob/M = loc - to_chat(M,span_warning("[src]'s sensors short out!")) - - else - sensor_mode = pick(SENSOR_OFF, SENSOR_OFF, SENSOR_OFF, SENSOR_LIVING, SENSOR_LIVING, SENSOR_VITALS, SENSOR_VITALS, SENSOR_COORDS) - if(ismob(loc)) - var/mob/M = loc - to_chat(M,span_warning("The sensors on the [src] change rapidly!")) - - if(ishuman(loc)) - var/mob/living/carbon/human/ooman = loc - if(ooman.w_uniform == src) - ooman.update_suit_sensors() - /obj/item/clothing/under/visual_equipped(mob/user, slot) . = ..() if(adjusted == ALT_STYLE) @@ -176,13 +148,67 @@ freshly_laundered = FALSE user.add_mood_event("fresh_laundry", /datum/mood_event/fresh_laundry) +// Start suit sensor handling + +/// Change the suit sensor state to broken and update the mob's status on the global sensor list +/obj/item/clothing/under/proc/break_sensors() + if(has_sensor == BROKEN_SENSORS || has_sensor == NO_SENSORS) + return + + visible_message(span_warning("[src]'s medical sensors short out!"), blind_message = span_warning("The [src] makes an electronic sizzling sound!"), vision_distance = COMBAT_MESSAGE_RANGE) + has_sensor = BROKEN_SENSORS + sensor_malfunction() + update_wearer_status() + +/** + * Repair the suit sensors and update the mob's status on the global sensor list. + * Can be called either through player action such as repairing with coil, or as part of a general fixing proc + * + * Arguments: + * * attacking_item - the item being used for the repair, if any + * * user - mob that's doing the repair + * * cable_required - set to FALSE to bypass consuming cable coil + */ +/obj/item/clothing/under/proc/repair_sensors(obj/item/attacking_item, mob/user, cable_required = TRUE) + if(has_sensor != BROKEN_SENSORS) + return + + if(cable_required) + if(!istype(attacking_item, /obj/item/stack/cable_coil)) + return + var/obj/item/stack/cable_coil/cabling = attacking_item + if(!cabling.use(1)) + return + cabling.visible_message(span_notice("[user] repairs the suit sensors on [src] with [cabling].")) + + playsound(source = src, soundin = 'sound/effects/sparks4.ogg', vol = 100, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE) + has_sensor = HAS_SENSORS + update_wearer_status() + + return TRUE + +/// If the item is being worn, a gentle reminder every 3-5 minutes that the sensors are broken +/obj/item/clothing/under/proc/sensor_malfunction() + if(!QDELETED(src) && has_sensor == BROKEN_SENSORS && ishuman(loc)) + do_sparks(number = 2, cardinal_only = FALSE, source = src) + addtimer(CALLBACK(src, PROC_REF(sensor_malfunction)), rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX * 0.5), TIMER_UNIQUE | TIMER_NO_HASH_WAIT) + +/// If the item is being worn, update the mob's status on the global sensor list +/obj/item/clothing/under/proc/update_wearer_status() + if(!ishuman(loc)) + return + + var/mob/living/carbon/human/ooman = loc + ooman.update_suit_sensors() + /mob/living/carbon/human/update_suit_sensors() . = ..() update_sensor_list() +/// Adds or removes a mob from the global suit sensors list based on sensor status and mode /mob/living/carbon/human/proc/update_sensor_list() - var/obj/item/clothing/under/U = w_uniform - if(istype(U) && U.has_sensor > NO_SENSORS && U.sensor_mode) + var/obj/item/clothing/under/uniform = w_uniform + if(istype(uniform) && uniform.has_sensor > NO_SENSORS && uniform.sensor_mode) GLOB.suit_sensors_list |= src else GLOB.suit_sensors_list -= src @@ -190,6 +216,23 @@ /mob/living/carbon/human/dummy/update_sensor_list() return +/obj/item/clothing/under/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + if(has_sensor == NO_SENSORS || has_sensor == BROKEN_SENSORS) + return + + if(severity <= EMP_HEAVY) + break_sensors() + + else + sensor_mode = pick(SENSOR_OFF, SENSOR_OFF, SENSOR_OFF, SENSOR_LIVING, SENSOR_LIVING, SENSOR_VITALS, SENSOR_VITALS, SENSOR_COORDS) + playsound(source = src, soundin = 'sound/effects/sparks3.ogg', vol = 75, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE, ignore_walls = FALSE) + visible_message(span_warning("The [src]'s medical sensors flash and change rapidly!"), blind_message = span_warning("The [src] makes an electronic sizzling sound!"), vision_distance = COMBAT_MESSAGE_RANGE) + + update_wearer_status() + // End suit sensor handling /// Attach the passed accessory to the clothing item @@ -285,7 +328,7 @@ if(can_adjust) . += "Alt-click on [src] to wear it [adjusted == ALT_STYLE ? "normally" : "casually"]." if(has_sensor == BROKEN_SENSORS) - . += "Its sensors appear to be shorted out. You could repair it with some cabling." + . += span_warning("The medical sensors appear to be shorted out. You could repair it with some cabling.") else if(has_sensor > NO_SENSORS) switch(sensor_mode) if(SENSOR_OFF) diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index cb0f7f50bb669..dc03dce8541fb 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -563,4 +563,9 @@ age_text = "withering away" . += list(span_notice("[p_They()] appear[p_s()] to be [age_text].")) + if(istype(w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/undershirt = w_uniform + if(undershirt.has_sensor == BROKEN_SENSORS) + . += list(span_notice("The [undershirt]'s medical sensors are sparking.")) + #undef ADD_NEWLINE_IF_NECESSARY diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index f68319f4205fb..5c68bb8f4c8b0 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -577,6 +577,10 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri /obj/item/stack/cable_coil/proc/try_heal_loop(atom/interacting_with, mob/living/user, repeating = FALSE) var/mob/living/carbon/human/attacked_humanoid = interacting_with + var/obj/item/clothing/under/uniform = attacked_humanoid.w_uniform + if(uniform.repair_sensors(src, user)) + return ITEM_INTERACT_SUCCESS + var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected)) if(isnull(affecting) || !IS_ROBOTIC_LIMB(affecting)) return NONE