diff --git a/_maps/RandomZLevels/mothership_astrum.dmm b/_maps/RandomZLevels/mothership_astrum.dmm index 4c5fb971ddc..d1c10a6589d 100644 --- a/_maps/RandomZLevels/mothership_astrum.dmm +++ b/_maps/RandomZLevels/mothership_astrum.dmm @@ -683,7 +683,7 @@ /obj/structure/window/spawner/directional/north, /obj/structure/window/spawner/directional/east, /obj/structure/window/spawner/directional/west, -/obj/item/healthanalyzer/wound, +/obj/item/healthanalyzer/simple, /turf/open/floor/plating/abductor2, /area/awaymission/mothership_astrum/halls) "lV" = ( diff --git a/_maps/map_files/VoidRaptor/VoidRaptor.dmm b/_maps/map_files/VoidRaptor/VoidRaptor.dmm index d17e433b601..c0b4362213e 100644 --- a/_maps/map_files/VoidRaptor/VoidRaptor.dmm +++ b/_maps/map_files/VoidRaptor/VoidRaptor.dmm @@ -44810,12 +44810,6 @@ dir = 8 }, /area/station/engineering/lobby) -"mLT" = ( -/obj/effect/spawner/random/structure/crate, -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/engineering/vending_restock, -/turf/open/floor/iron/smooth, -/area/station/maintenance/starboard/lesser) "mMe" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/pod/dark, @@ -127033,7 +127027,7 @@ vTu owm aeN pMm -mLT +iGa rWS mdf onP diff --git a/code/datums/quirks/negative_quirks.dm b/code/datums/quirks/negative_quirks.dm index b827337030e..a6baee9d0da 100644 --- a/code/datums/quirks/negative_quirks.dm +++ b/code/datums/quirks/negative_quirks.dm @@ -946,7 +946,7 @@ var/datum/disease/chronic_illness/hms = new /datum/disease/chronic_illness() quirk_holder.ForceContractDisease(hms) give_item_to_holder(/obj/item/storage/pill_bottle/sansufentanyl, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK),flavour_text = "You've been provided with medication to help manage your condition. Take it regularly to avoid complications.") - give_item_to_holder(/obj/item/healthanalyzer/disease, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK)) + give_item_to_holder(/obj/item/healthanalyzer/simple/disease, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK)) /datum/quirk/unstable name = "Unstable" diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 18a0f947dc6..0d3347c1ca3 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -100,6 +100,11 @@ victim = null return ..() +// Applied into wounds when they're scanned with the wound analyzer, halves time to treat them manually. +#define TRAIT_WOUND_SCANNED "wound_scanned" +// I dunno lol +#define ANALYZER_TRAIT "analyzer_trait" + /** * apply_wound() is used once a wound type is instantiated to assign it to a bodypart, and actually come into play. * @@ -415,8 +420,16 @@ * * mob/user: The user examining the wound's owner, if that matters */ /datum/wound/proc/get_examine_description(mob/user) + . = get_wound_description(user) + if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + . += span_notice("\nThere is a holo-image next to the wound that seems to contain indications for treatment.") + + return . + +/datum/wound/proc/get_wound_description(mob/user) . = "[victim.p_their(TRUE)] [limb.plaintext_zone] [examine_desc]" . = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "[.]!" + return . /datum/wound/proc/get_scanner_description(mob/user) return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]" diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index b70a75bedc0..72c4e75fc1a 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -146,7 +146,7 @@ victim.add_splatter_floor(get_step(victim.loc, victim.dir)) -/datum/wound/blunt/get_examine_description(mob/user) +/datum/wound/blunt/get_wound_description(mob/user) if(!limb.current_gauze && !gelled && !taped) return ..() @@ -293,12 +293,17 @@ /datum/wound/blunt/moderate/treat(obj/item/I, mob/user) - if(victim == user) - victim.visible_message(span_danger("[user] begins resetting [victim.p_their()] [limb.plaintext_zone] with [I]."), span_warning("You begin resetting your [limb.plaintext_zone] with [I]...")) - else - user.visible_message(span_danger("[user] begins resetting [victim]'s [limb.plaintext_zone] with [I]."), span_notice("You begin resetting [victim]'s [limb.plaintext_zone] with [I]...")) + var/scanned = HAS_TRAIT(src, TRAIT_WOUND_SCANNED) + var/self_penalty_mult = user == victim ? 1.5 : 1 + var/scanned_mult = scanned ? 0.5 : 1 + var/treatment_delay = base_treat_time * self_penalty_mult * scanned_mult - if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) + if(victim == user) + victim.visible_message(span_danger("[user] begins [scanned ? "expertly" : ""] resetting [victim.p_their()] [limb.plaintext_zone] with [I]."), span_warning("You begin resetting your [limb.plaintext_zone] with [I][scanned ? ", keeping the holo-image's indications in mind" : ""]...")) + else + user.visible_message(span_danger("[user] begins [scanned ? "expertly" : ""] resetting [victim]'s [limb.plaintext_zone] with [I]."), span_notice("You begin resetting [victim]'s [limb.plaintext_zone] with [I][scanned ? ", keeping the holo-image's indications in mind" : ""]...")) + + if(!do_after(user, treatment_delay, target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) return if(victim == user) diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 3fc4e51f73a..fdcf3be67d9 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -130,7 +130,7 @@ var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone) victim.gain_trauma(sepsis) -/datum/wound/burn/get_examine_description(mob/user) +/datum/wound/burn/get_wound_description(mob/user) if(strikes_to_lose_limb <= 0) return span_deadsay("[victim.p_their(TRUE)] [limb.plaintext_zone] has locked up completely and is non-functional.") diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index be4180114bc..a18e66a3001 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -107,8 +107,15 @@ /// If someone is using a suture to close this puncture /datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user) var/self_penalty_mult = (user == victim ? 1.4 : 1) - user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) - if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + var/treatment_delay = base_treat_time * self_penalty_mult + + if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + treatment_delay *= 0.5 + user.visible_message(span_notice("[user] begins expertly stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image information in mind...")) + else + user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + + if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return var/bleeding_wording = (no_bleeding ? "holes" : "bleeding") user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"].")) @@ -124,11 +131,19 @@ /// If someone is using either a cautery tool or something with heat to cauterize this pierce /datum/wound/pierce/proc/tool_cauterize(obj/item/I, mob/user) + var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself - user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) - if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + var/treatment_delay = base_treat_time * self_penalty_mult * improv_penalty_mult + + if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + treatment_delay *= 0.5 + user.visible_message(span_danger("[user] begins expertly cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image indications in mind...")) + else + user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + + if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return var/bleeding_wording = (no_bleeding ? "holes" : "bleeding") diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 3b589159ae6..338c4046432 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -65,7 +65,7 @@ highest_scar.lazy_attach(limb) return ..() -/datum/wound/slash/get_examine_description(mob/user) +/datum/wound/slash/get_wound_description(mob/user) if(!limb.current_gauze) return ..() @@ -229,8 +229,15 @@ var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself - user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) - if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + var/treatment_delay = base_treat_time * self_penalty_mult * improv_penalty_mult + + if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + treatment_delay *= 0.5 + user.visible_message(span_danger("[user] begins expertly cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image indications in mind...")) + else + user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + + if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return var/bleeding_wording = (no_bleeding ? "cuts" : "bleeding") user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim].")) @@ -248,9 +255,15 @@ /// If someone is using a suture to close this cut /datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user) var/self_penalty_mult = (user == victim ? 1.4 : 1) - user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + var/treatment_delay = base_treat_time * self_penalty_mult - if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) + if(HAS_TRAIT(src, TRAIT_WOUND_SCANNED)) + treatment_delay *= 0.5 + user.visible_message(span_notice("[user] begins expertly stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I], keeping the holo-image information in mind...")) + else + user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) + + if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) return var/bleeding_wording = (no_bleeding ? "cuts" : "bleeding") user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"].")) diff --git a/code/game/objects/items/devices/scanners/firstaidanalyzer(1).dmi b/code/game/objects/items/devices/scanners/firstaidanalyzer(1).dmi new file mode 100644 index 00000000000..7dfcbf8422b Binary files /dev/null and b/code/game/objects/items/devices/scanners/firstaidanalyzer(1).dmi differ diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index ad71011c20e..52b28b3afc3 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -4,6 +4,8 @@ #define SCANMODE_COUNT 2 // Update this to be the number of scan modes if you add more #define SCANNER_CONDENSED 0 #define SCANNER_VERBOSE 1 +// Not updating above count because you're not meant to switch to this mode. +#define SCANNER_NO_MODE -1 /obj/item/healthanalyzer name = "health analyzer" @@ -72,6 +74,7 @@ user.visible_message(span_notice("[user] analyzes [M]'s vitals.")) balloon_alert(user, "analyzing vitals") + playsound(user.loc, 'sound/items/healthanalyzer.ogg', 50) switch (scanmode) if (SCANMODE_HEALTH) @@ -483,6 +486,9 @@ if(!user.can_perform_action(src, NEED_LITERACY|NEED_LIGHT) || user.is_blind()) return + if(mode == SCANNER_NO_MODE) + return + mode = !mode to_chat(user, mode == SCANNER_VERBOSE ? "The scanner now shows specific limb damage." : "The scanner no longer shows limb damage.") @@ -492,18 +498,29 @@ desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy." advanced = TRUE +#define AID_EMOTION_NEUTRAL "neutral" +#define AID_EMOTION_HAPPY "happy" +#define AID_EMOTION_WARN "cautious" +#define AID_EMOTION_ANGRY "angery" +#define AID_EMOTION_SAD "sad" + /// Displays wounds with extended information on their status vs medscanners -/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner) +/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/simple/scanner) if(!istype(patient) || user.incapacitated()) return var/render_list = "" - for(var/i in patient.get_wounded_bodyparts()) - var/obj/item/bodypart/wounded_part = i + var/advised + for(var/limb in patient.get_wounded_bodyparts()) + var/obj/item/bodypart/wounded_part = limb render_list += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]" - for(var/k in wounded_part.wounds) - var/datum/wound/W = k - render_list += "
[W.get_scanner_description()]
\n" + for(var/limb_wound in wounded_part.wounds) + var/datum/wound/current_wound = limb_wound + render_list += "
[current_wound.get_scanner_description()]
\n" + ADD_TRAIT(current_wound, TRAIT_WOUND_SCANNED, ANALYZER_TRAIT) + if(!advised) + to_chat(user, span_notice("You notice how bright holo-images appear over your [(length(wounded_part.wounds) || length(patient.get_wounded_bodyparts()) ) > 1 ? "various wounds" : "wound"]. They seem to be filled with helpful information, this should make treatment easier!")) + advised = TRUE render_list += "
" if(render_list == "") @@ -511,38 +528,57 @@ // Only emit the cheerful scanner message if this scan came from a scanner playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE) to_chat(user, span_notice("\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no wounds!")) + scanner.show_emotion(AID_EMOTION_HAPPY) else to_chat(user, "No wounds detected in subject.") else to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) + scanner.show_emotion(AID_EMOTION_WARN) + playsound(scanner, 'sound/machines/twobeep.ogg', 50, FALSE) -/obj/item/healthanalyzer/wound - name = "first aid analyzer" - icon_state = "adv_spectrometer" - desc = "A prototype MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds, but offers no further insight into the patient's health. You hope the final version is less annoying to read!" + +/obj/item/healthanalyzer/simple + name = "wound analyzer" + icon_state = "first_aid" + desc = "A helpful, child-proofed, and most importantly, extremely cheap MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds. While it might not sound very informative for it to be able to tell you if you have a gaping hole in your body or not, it applies a temporary holoimage near the wound with information that is guaranteed to double the efficacy and speed of treatment." + mode = SCANNER_NO_MODE + // Cooldown for when the analyzer will allow you to ask it for encouragement. Don't get greedy! var/next_encouragement - var/greedy + // The analyzer's current emotion. Affects the sprite overlays and if it's going to prick you for being greedy or not. + var/emotion = AID_EMOTION_NEUTRAL + // Encouragements to play when attack_selfing + var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \ + "reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins") + // How often one can ask for encouragement + var/patience = 10 SECONDS -/obj/item/healthanalyzer/wound/attack_self(mob/user) +/obj/item/healthanalyzer/simple/attack_self(mob/user) if(next_encouragement < world.time) playsound(src, 'sound/machines/ping.ogg', 50, FALSE) - var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \ - "reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins") to_chat(user, span_notice("\The [src] makes a happy ping and [pick(encouragements)]!")) next_encouragement = world.time + 10 SECONDS - greedy = FALSE - else if(!greedy) - to_chat(user, span_warning("\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.")) - greedy = TRUE + show_emotion(AID_EMOTION_HAPPY) + else if(emotion != AID_EMOTION_ANGRY) + greed_warning(user) else - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) - if(isliving(user)) - var/mob/living/L = user - to_chat(L, span_warning("\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!")) - L.adjustBruteLoss(4) - L.dropItemToGround(src) + violence(user) -/obj/item/healthanalyzer/wound/attack(mob/living/carbon/patient, mob/living/carbon/human/user) +/obj/item/healthanalyzer/simple/proc/greed_warning(mob/user) + to_chat(user, span_warning("\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.")) + show_emotion(AID_EMOTION_ANGRY) + +/obj/item/healthanalyzer/simple/proc/violence(mob/user) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + if(isliving(user)) + var/mob/living/L = user + to_chat(L, span_warning("\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!")) + flick(icon_state + "_pinprick", src) + L.adjustBruteLoss(4) + L.dropItemToGround(src) + show_emotion(AID_EMOTION_HAPPY) + + +/obj/item/healthanalyzer/simple/attack(mob/living/carbon/patient, mob/living/carbon/human/user) if(!user.can_read(src)) //SKYRAT EDIT: Blind People Can Analyze Again return @@ -551,23 +587,67 @@ if(!istype(patient)) playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) - to_chat(user, span_notice("\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].")) + to_chat(user, span_notice("\The [src] makes a sad buzz and briefly displays an unhappy face, indicating it can't scan [patient].")) + show_emotion(AI_EMOTION_SAD) return woundscan(user, patient, src) + flick(icon_state + "_pinprick", src) -/obj/item/healthanalyzer/disease +/obj/item/healthanalyzer/simple/update_overlays() + . = ..() + switch(emotion) + if(AID_EMOTION_HAPPY) + . += mutable_appearance(icon, "+no_wounds") + if(AID_EMOTION_WARN) + . += mutable_appearance(icon, "+wound_warn") + if(AID_EMOTION_ANGRY) + . += mutable_appearance(icon, "+angry") + if(AID_EMOTION_SAD) + . += mutable_appearance(icon, "+fail_scan") + +/// Sets a new emotion display on the scanner, and resets back to neutral in a moment +/obj/item/healthanalyzer/simple/proc/show_emotion(new_emotion) + emotion = new_emotion + update_appearance(UPDATE_OVERLAYS) + if (emotion != AID_EMOTION_NEUTRAL) + addtimer(CALLBACK(src, PROC_REF(reset_emotions), AID_EMOTION_NEUTRAL), 2 SECONDS) + +// Resets visible emotion back to neutral +/obj/item/healthanalyzer/simple/proc/reset_emotions() + emotion = AID_EMOTION_NEUTRAL + update_appearance(UPDATE_OVERLAYS) + +/obj/item/healthanalyzer/simple/miner + name = "mining wound analyzer" + icon_state = "miner_aid" + desc = "A helpful, child-proofed, and most importantly, extremely cheap MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds. While it might not sound very informative for it to be able to tell you if you have a gaping hole in your body or not, it applies a temporary holoimage near the wound with information that is guaranteed to double the efficacy and speed of treatment. This one has a cool aesthetic antenna that doesn't actually do anything!" + +/obj/item/healthanalyzer/simple/disease name = "disease state analyzer" - icon_state = "adv_spectrometer" - desc = "A disease status analyzer to determine the state of an infection to encourage responsible medication consumption." - -/obj/item/healthanalyzer/disease/attack_self(mob/user) - playsound(src, 'sound/machines/ping.ogg', 50, FALSE) - var/list/encouragements = list("encourages you to take your medication", "briefly displays a spinning cartoon heart", "reasures you about your condition", \ + desc = "Another of MeLo-Tech's dubiously useful medsci scanners, the disease analyzer is a pretty rare find these days - NT found out that giving their hospitals the lowest-common-denominator pandemic equipment resulted in too much financial loss of life to be profitable. There's rumours that the inbuilt AI is jealous of the first aid analyzer's success." + icon_state = "disease_aid" + mode = SCANNER_NO_MODE + encouragements = list("encourages you to take your medication", "briefly displays a spinning cartoon heart", "reasures you about your condition", \ "reminds you that everyone is doing their best", "displays a message wishing you well", "displays a message saying how proud it is that you're taking care of yourself", "formally absolves you of all your sins") - to_chat(user, span_notice("\The [src] makes a happy ping and [pick(encouragements)]!")) + patience = 20 SECONDS -/obj/item/healthanalyzer/disease/attack(mob/living/carbon/patient, mob/living/carbon/human/user) +/obj/item/healthanalyzer/simple/disease/greed_warning(mob/user) + to_chat(user, span_warning("\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.")) + show_emotion(AID_EMOTION_ANGRY) + +/obj/item/healthanalyzer/simple/disease/violence(mob/user) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + if(isliving(user)) + var/mob/living/L = user + to_chat(L, span_warning("\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!")) + flick(icon_state + "_pinprick", src) + L.adjustBruteLoss(1) + L.reagents.add_reagent(/datum/reagent/toxin, rand(1, 3)) + L.dropItemToGround(src) + show_emotion(AID_EMOTION_ANGRY) + +/obj/item/healthanalyzer/simple/disease/attack(mob/living/carbon/patient, mob/living/carbon/human/user) if(!user.can_read(src) || user.is_blind()) return @@ -577,11 +657,30 @@ if(!istype(user)) playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) to_chat(user, span_notice("\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].")) + emotion = AID_EMOTION_SAD + update_appearance(UPDATE_OVERLAYS) return - diseasescan(user, patient, src) + diseasescan(user, patient, src) // this updates emotion + update_appearance(UPDATE_OVERLAYS) + flick(icon_state + "_pinprick", src) + +/obj/item/healthanalyzer/simple/disease/update_overlays() + . = ..() + switch(emotion) + if(AID_EMOTION_HAPPY) + . += mutable_appearance(icon, "+not_infected") + if(AID_EMOTION_WARN) + . += mutable_appearance(icon, "+infected") + if(AID_EMOTION_ANGRY) + . += mutable_appearance(icon, "+rancurous") + if(AID_EMOTION_SAD) + . += mutable_appearance(icon, "+unknown_scan") + if(emotion != AID_EMOTION_NEUTRAL) + addtimer(CALLBACK(src, PROC_REF(reset_emotions)), 4 SECONDS) // longer on purpose + //Checks the individual for any diseases that are visible to the scanner, and displays the diseases in the attacked to the attacker. -/proc/diseasescan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner) +/proc/diseasescan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/simple/scanner) if(!istype(patient) || user.incapacitated()) return @@ -593,14 +692,23 @@ " if(!length(render)) - // Only emit the cheerful scanner message if this scan came from a scanner playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE) - to_chat(user, span_notice("The patient has no diseases.")) + to_chat(user, span_notice("\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no diseases!")) + scanner.emotion = AID_EMOTION_HAPPY else to_chat(user, span_notice(render.Join(""))) + scanner.emotion = AID_EMOTION_WARN + playsound(scanner, 'sound/machines/twobeep.ogg', 50, FALSE) #undef SCANMODE_HEALTH #undef SCANMODE_WOUND #undef SCANMODE_COUNT #undef SCANNER_CONDENSED #undef SCANNER_VERBOSE +#undef SCANNER_NO_MODE + +#undef AID_EMOTION_NEUTRAL +#undef AID_EMOTION_HAPPY +#undef AID_EMOTION_WARN +#undef AID_EMOTION_ANGRY +#undef AID_EMOTION_SAD diff --git a/code/game/objects/items/devices/scanners/sequence_scanner.dm b/code/game/objects/items/devices/scanners/sequence_scanner.dm index 7c42aa3c3b1..58f7459b7da 100644 --- a/code/game/objects/items/devices/scanners/sequence_scanner.dm +++ b/code/game/objects/items/devices/scanners/sequence_scanner.dm @@ -27,6 +27,7 @@ if (!HAS_TRAIT(target, TRAIT_GENELESS) && !HAS_TRAIT(target, TRAIT_BADDNA)) user.visible_message(span_notice("[user] analyzes [target]'s genetic sequence.")) balloon_alert(user, "sequence analyzed") + playsound(user.loc, 'sound/items/healthanalyzer.ogg', 50) // close enough gene_scan(target, user) else user.visible_message(span_notice("[user] fails to analyze [target]'s genetic sequence."), span_warning("[target] has no readable genetic sequence!")) diff --git a/code/game/objects/items/devices/scanners/slime_scanner.dm b/code/game/objects/items/devices/scanners/slime_scanner.dm index 8a293f3bf28..6dcf600cbad 100644 --- a/code/game/objects/items/devices/scanners/slime_scanner.dm +++ b/code/game/objects/items/devices/scanners/slime_scanner.dm @@ -2,7 +2,7 @@ name = "slime scanner" desc = "A device that analyzes a slime's internal composition and measures its stats." icon = 'icons/obj/device.dmi' - icon_state = "adv_spectrometer" + icon_state = "slime_scanner" inhand_icon_state = "analyzer" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 714c333d579..00f0a2e6c18 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -146,6 +146,9 @@ // gauze is only relevant for wounds, which are handled in the wounds themselves /obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent) + + var/treatment_delay = (user == patient ? self_delay : other_delay) + var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected)) if(!limb) patient.balloon_alert(user, "missing limb!") @@ -155,8 +158,9 @@ return var/gauzeable_wound = FALSE + var/datum/wound/woundies for(var/i in limb.wounds) - var/datum/wound/woundies = i + woundies = i if(woundies.wound_flags & ACCEPTS_GAUZE) gauzeable_wound = TRUE break @@ -167,7 +171,7 @@ //SKYRAT EDIT CHANGE BEGIN - MEDICAL /* if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 1.2 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row - patient.balloon_alert(user, "already bandaged!") + patient.balloon_alert(user, pick("already bandaged!", "bandage is clean!")) // good enough return */ if(limb.current_gauze) @@ -175,8 +179,16 @@ return //SKYRAT EDIT CHANGE END - user.visible_message(span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]...")) - if(!do_after(user, (user == patient ? self_delay : other_delay), target=patient)) + if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED)) + treatment_delay *= 0.5 + if(user == patient) + to_chat(user, span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin wrapping your wounds with [src].")) + else + user.visible_message(span_warning("[user] begins expertly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin quickly wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src], keeping the holo-image indications in mind...")) + else + user.visible_message(span_warning("[user] begins wrapping the wounds on [patient]'s [limb.plaintext_zone] with [src]..."), span_warning("You begin wrapping the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]...")) + + if(!do_after(user, treatment_delay, target = patient)) return user.visible_message("[user] applies [src] to [patient]'s [limb.plaintext_zone].", "You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].") diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm index eaf563de3c4..543f864f204 100644 --- a/code/game/objects/items/storage/boxes/job_boxes.dm +++ b/code/game/objects/items/storage/boxes/job_boxes.dm @@ -73,6 +73,7 @@ /obj/item/storage/box/survival/mining/PopulateContents() ..() new /obj/item/crowbar/red(src) + new /obj/item/healthanalyzer/simple/miner(src) // Engineer survival box /obj/item/storage/box/survival/engineer diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 46b7894c3dc..15eb4cfe54a 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -42,6 +42,7 @@ /obj/item/stack/medical/suture = 2, /obj/item/stack/medical/mesh = 2, /obj/item/reagent_containers/hypospray/medipen = 1, + /obj/item/healthanalyzer/simple = 1, ) generate_items_inside(items_inside,src) @@ -54,7 +55,7 @@ if(empty) return var/static/items_inside = list( - /obj/item/healthanalyzer/wound = 1, + /obj/item/healthanalyzer/simple = 1, /obj/item/stack/medical/gauze = 1, /obj/item/stack/medical/splint = 1, //SKYRAT EDIT ADDITION - MEDICAL /obj/item/stack/medical/suture/emergency = 1, @@ -200,10 +201,12 @@ if(empty) return var/static/items_inside = list( - /obj/item/storage/pill_bottle/multiver/less = 1, + /obj/item/storage/pill_bottle/multiver/less = 1, /obj/item/reagent_containers/syringe/syriniver = 3, /obj/item/storage/pill_bottle/potassiodide = 1, - /obj/item/reagent_containers/hypospray/medipen/penacid = 1) + /obj/item/reagent_containers/hypospray/medipen/penacid = 1, + /obj/item/healthanalyzer/simple/disease = 1, + ) generate_items_inside(items_inside,src) /obj/item/storage/medkit/o2 @@ -246,7 +249,9 @@ /obj/item/stack/medical/gauze = 1, /obj/item/stack/medical/splint = 1, //SKYRAT EDIT ADDITION - MEDICAL /obj/item/storage/pill_bottle/probital = 1, - /obj/item/reagent_containers/hypospray/medipen/salacid = 1) + /obj/item/reagent_containers/hypospray/medipen/salacid = 1, + /obj/item/healthanalyzer/simple = 1, + ) generate_items_inside(items_inside,src) /obj/item/storage/medkit/advanced diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 81df2da70ac..93c6803d55d 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -254,9 +254,12 @@ name = "surgical processor" desc = "A device for scanning and initiating surgeries from a disk or operating computer." icon = 'icons/obj/device.dmi' - icon_state = "spectrometer" + icon_state = "surgical_processor" item_flags = NOBLUDGEON + // List of surgeries downloaded into the device. var/list/loaded_surgeries = list() + // If a surgery has been downloaded in. Will cause the display to have a noticeable effect - helps to realize you forgot to load anything in. + var/downloaded = TRUE /obj/item/surgical_processor/Initialize(mapload) . = ..() @@ -304,8 +307,15 @@ var/obj/machinery/computer/operating/surgery_computer = design_holder loaded_surgeries |= surgery_computer.advanced_surgeries playsound(src, 'sound/machines/terminal_success.ogg', 25, TRUE) + downloaded = TRUE + update_appearance(UPDATE_OVERLAYS) return TRUE +/obj/item/surgical_processor/update_overlays() + . = ..() + if(downloaded) + . += mutable_appearance(src.icon, "+downloaded") + /obj/item/surgical_processor/proc/check_surgery(mob/user, datum/surgery/surgery, mob/patient) SIGNAL_HANDLER diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index ddfee8bd477..576cbb0b8b2 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -13,7 +13,7 @@ /obj/item/healthanalyzer = 4, /obj/item/wrench/medical = 1, /obj/item/stack/sticky_tape/surgical = 3, - /obj/item/healthanalyzer/wound = 4, + /obj/item/healthanalyzer/simple = 4, /obj/item/stack/medical/ointment = 2, /obj/item/stack/medical/suture = 2, /obj/item/stack/medical/bone_gel = 4, @@ -57,7 +57,7 @@ /obj/item/healthanalyzer = 0, /obj/item/wrench/medical = 0, /obj/item/stack/sticky_tape/surgical = 0, - /obj/item/healthanalyzer/wound = 0, + /obj/item/healthanalyzer/simple = 0, /obj/item/stack/medical/ointment = 0, /obj/item/stack/medical/suture = 1, /obj/item/stack/medical/bone_gel = 1, diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm index 9bdbd11ebc5..4fd120bdc48 100644 --- a/code/modules/vending/medical_wall.dm +++ b/code/modules/vending/medical_wall.dm @@ -13,7 +13,7 @@ /obj/item/reagent_containers/medigel/libital = 2, /obj/item/reagent_containers/medigel/aiuri = 2, /obj/item/reagent_containers/medigel/sterilizine = 1, - /obj/item/healthanalyzer/wound = 2, + /obj/item/healthanalyzer/simple = 2, /obj/item/stack/medical/bone_gel = 2, ) contraband = list( diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi index 8df1945d800..01c9fb635c2 100644 Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 5067052940d..526e378cbd2 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/sound/items/healthanalyzer.ogg b/sound/items/healthanalyzer.ogg new file mode 100644 index 00000000000..56fd762cdde Binary files /dev/null and b/sound/items/healthanalyzer.ogg differ diff --git a/tools/UpdatePaths/Scripts_Skyrat/22293_wound_scanner_to_simple_scanner.txt b/tools/UpdatePaths/Scripts_Skyrat/22293_wound_scanner_to_simple_scanner.txt new file mode 100644 index 00000000000..1030e966261 --- /dev/null +++ b/tools/UpdatePaths/Scripts_Skyrat/22293_wound_scanner_to_simple_scanner.txt @@ -0,0 +1 @@ +/obj/item/healthanalyzer/wound : /obj/item/healthanalyzer/simple{@OLD}