From ac204e7749a7b1c73af9faa31c2b23bfb1671e84 Mon Sep 17 00:00:00 2001 From: Casey Date: Fri, 29 Jul 2022 16:48:00 -0400 Subject: [PATCH] Replaces some old code w/ IsAdvancedToolUser and fixes twohanded weapons for simple_mobs --- code/game/objects/items.dm | 4 + .../objects/items/devices/scanners/gas.dm | 2 +- .../objects/items/devices/scanners/health.dm | 330 ++++++++++++++++++ .../devices/scanners/mass_spectrometer.dm | 2 +- code/game/objects/items/stacks/medical.dm | 5 +- code/game/objects/items/weapons/weaponry.dm | 2 +- code/modules/mining/mine_turfs.dm | 2 +- 7 files changed, 340 insertions(+), 7 deletions(-) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d3d63650dc..0ccf26230c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -161,6 +161,10 @@ var/obj/item/organ/external/hand = H.organs_by_name[check_hand] if(istype(hand) && hand.is_usable()) return TRUE + var/mob/living/simple_mob/S = M + if(istype(S) && S.has_hands) //Are they a mob? And do they have hands? + return TRUE + return FALSE diff --git a/code/game/objects/items/devices/scanners/gas.dm b/code/game/objects/items/devices/scanners/gas.dm index ca35911448..9fbc319d6d 100644 --- a/code/game/objects/items/devices/scanners/gas.dm +++ b/code/game/objects/items/devices/scanners/gas.dm @@ -23,7 +23,7 @@ /obj/item/device/analyzer/attack_self(mob/user as mob) if (user.stat) return - if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") + if (!user.IsAdvancedToolUser()) to_chat(usr, "You don't have the dexterity to do this!") return diff --git a/code/game/objects/items/devices/scanners/health.dm b/code/game/objects/items/devices/scanners/health.dm index ae2683ede0..96380c68b1 100644 --- a/code/game/objects/items/devices/scanners/health.dm +++ b/code/game/objects/items/devices/scanners/health.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD #define DEFIB_TIME_LIMIT (10 MINUTES) //VOREStation addition- past this many seconds, defib is useless. /obj/item/device/healthanalyzer @@ -325,3 +326,332 @@ icon_state = "health3" #undef DEFIB_TIME_LIMIT //VOREStation addition +======= +#define DEFIB_TIME_LIMIT (10 MINUTES) //VOREStation addition- past this many seconds, defib is useless. + +/obj/item/device/healthanalyzer + name = "health analyzer" + desc = "A hand-held body scanner able to distinguish vital signs of the subject." + icon_state = "health" + item_state = "healthanalyzer" + slot_flags = SLOT_BELT + throwforce = 3 + w_class = ITEMSIZE_SMALL + throw_speed = 5 + throw_range = 10 + matter = list(MAT_STEEL = 200) + origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 1) + var/mode = 1; + var/advscan = 0 + var/showadvscan = 1 + +/obj/item/device/healthanalyzer/New() + if(advscan >= 1) + verbs += /obj/item/device/healthanalyzer/proc/toggle_adv + ..() + +/obj/item/device/healthanalyzer/do_surgery(mob/living/M, mob/living/user) + if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool + return ..() + scan_mob(M, user) //default surgery behaviour is just to scan as usual + return 1 + +/obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/user) + scan_mob(M, user) + +/obj/item/device/healthanalyzer/proc/scan_mob(mob/living/M, mob/living/user) + var/dat = "" + if ((CLUMSY in user.mutations) && prob(50)) + user.visible_message("\The [user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!") + dat += "Analyzing Results for the floor:
" + dat += "Overall Status: Healthy
" + dat += "\tDamage Specifics: 0-0-0-0
" + dat += "Key: Suffocation/Toxin/Burns/Brute
" + dat += "Body Temperature: ???" + user.show_message("[dat]", 1) + return + if (!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return + + flick("[icon_state]-scan", src) //makes it so that it plays the scan animation on a succesful scan + user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.") + + if (!ishuman(M) || M.isSynthetic()) + //these sensors are designed for organic life + dat += "Analyzing Results for ERROR:\n\tOverall Status: ERROR
" + dat += "\tKey: Suffocation/Toxin/Burns/Brute
" + dat += "\tDamage Specifics: ? - ? - ? - ?
" + dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)

" + dat += "Warning: Blood Level ERROR: --% --cl. Type: ERROR
" + dat += "Subject's pulse: -- bpm." + user.show_message(dat, 1) + return + + var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss()))) + var/OX = M.getOxyLoss() > 50 ? "[M.getOxyLoss()]" : M.getOxyLoss() + var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss() + var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss() + var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss() + if(M.status_flags & FAKEDEATH) + OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy + dat += "Analyzing Results for [M]:
" + dat += "Overall Status: dead
" + else + dat += "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]
" + dat += "\tKey: Suffocation/Toxin/Burns/Brute
" + dat += "\tDamage Specifics: [OX] - [TX] - [BU] - [BR]
" + dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)

" + //VOREStation edit/addition starts + if(M.timeofdeath && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) + dat += "Time of Death: [worldtime2stationtime(M.timeofdeath)]
" + var/tdelta = round(world.time - M.timeofdeath) + if(tdelta < (DEFIB_TIME_LIMIT * 10)) + dat += "Subject died [DisplayTimeText(tdelta)] ago - resuscitation may be possible!
" + //VOREStation edit/addition ends + if(istype(M, /mob/living/carbon/human) && mode == 1) + var/mob/living/carbon/human/H = M + var/list/damaged = H.get_damaged_organs(1,1) + dat += "Localized Damage, Brute/Burn:
" + if(length(damaged)>0) + for(var/obj/item/organ/external/org in damaged) + if(org.robotic >= ORGAN_ROBOT) + continue + else + dat += " [capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : 0]" + dat += "[(org.status & ORGAN_BLEEDING)?"\[Bleeding\]":""] - " + dat += "[(org.burn_dam > 0) ? "[org.burn_dam]" : 0]
" + else + dat += " Limbs are OK.
" + + OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" + TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal" + BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K" + BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K" + if(M.status_flags & FAKEDEATH) + OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" + dat += "[OX] | [TX] | [BU] | [BR]
" + if(M.radiation) + if(advscan >= 2 && showadvscan == 1) + var/severity = "" + if(M.radiation >= 75) + severity = "Critical" + else if(M.radiation >= 50) + severity = "Severe" + else if(M.radiation >= 25) + severity = "Moderate" + else if(M.radiation >= 1) + severity = "Low" + dat += "[severity] levels of radiation detected. [(severity == "Critical") ? " Immediate treatment advised." : ""]
" + else + dat += "Radiation detected.
" + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(C.reagents.total_volume) + var/unknown = 0 + var/reagentdata[0] + var/unknownreagents[0] + for(var/datum/reagent/R as anything in C.reagents.reagent_list) + if(R.scannable) + reagentdata["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - Overdose" : ""]
" + else + unknown++ + unknownreagents["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - Overdose" : ""]
" + if(reagentdata.len) + dat += "Beneficial reagents detected in subject's blood:
" + for(var/d in reagentdata) + dat += reagentdata[d] + if(unknown) + if(advscan >= 3 && showadvscan == 1) + dat += "Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:
" + for(var/d in unknownreagents) + dat += unknownreagents[d] + else + dat += "Warning: Unknown substance[(unknown>1)?"s":""] detected in subject's blood.
" + if(C.ingested && C.ingested.total_volume) + var/unknown = 0 + var/stomachreagentdata[0] + var/stomachunknownreagents[0] + for(var/datum/reagent/R as anything in C.ingested.reagent_list) + if(R.scannable) + stomachreagentdata["[R.id]"] = "\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - Overdose" : ""]
" + if (advscan == 0 || showadvscan == 0) + dat += "[R.name] found in subject's stomach.
" + else + ++unknown + stomachunknownreagents["[R.id]"] = "\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - Overdose" : ""]
" + if(advscan >= 1 && showadvscan == 1) + dat += "Beneficial reagents detected in subject's stomach:
" + for(var/d in stomachreagentdata) + dat += stomachreagentdata[d] + if(unknown) + if(advscan >= 3 && showadvscan == 1) + dat += "Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:
" + for(var/d in stomachunknownreagents) + dat += stomachunknownreagents[d] + else + dat += "Unknown substance[(unknown > 1)?"s":""] found in subject's stomach.
" + if(C.touching && C.touching.total_volume) + var/unknown = 0 + var/touchreagentdata[0] + var/touchunknownreagents[0] + for(var/datum/reagent/R as anything in C.touching.reagent_list) + if(R.scannable) + touchreagentdata["[R.id]"] = "\t[round(C.touching.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.can_overdose_touch && R.volume > R.overdose) ? " - Overdose" : ""]
" + if (advscan == 0 || showadvscan == 0) + dat += "[R.name] found in subject's dermis.
" + else + ++unknown + touchunknownreagents["[R.id]"] = "\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.can_overdose_touch && R.volume > R.overdose) ? " - Overdose" : ""]
" + if(advscan >= 1 && showadvscan == 1) + dat += "Beneficial reagents detected in subject's dermis:
" + for(var/d in touchreagentdata) + dat += touchreagentdata[d] + if(unknown) + if(advscan >= 3 && showadvscan == 1) + dat += "Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's dermis:
" + for(var/d in touchunknownreagents) + dat += touchunknownreagents[d] + else + dat += "Unknown substance[(unknown > 1)?"s":""] found in subject's dermis.
" + if(C.virus2.len) + for (var/ID in C.virus2) + if (ID in virusDB) + var/datum/data/record/V = virusDB[ID] + dat += "Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]
" + else + dat += "Warning: Unknown pathogen detected in subject's blood.
" + if (M.getCloneLoss()) + dat += "Subject appears to have been imperfectly cloned.
" +// if (M.reagents && M.reagents.get_reagent_amount("inaprovaline")) +// user.show_message("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.") + if (M.has_brain_worms()) + dat += "Subject suffering from aberrant brain activity. Recommend further scanning.
" + else if (M.getBrainLoss() >= 60 || !M.has_brain()) + dat += "Subject is brain dead.
" + else if (M.getBrainLoss() >= 25) + dat += "Severe brain damage detected. Subject likely to have a traumatic brain injury.
" + else if (M.getBrainLoss() >= 10) + dat += "Significant brain damage detected. Subject may have had a concussion.
" + else if (M.getBrainLoss() >= 1 && advscan >= 2 && showadvscan == 1) + dat += "Minor brain damage detected.
" + if(ishuman(M)) + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/internal/appendix/a in H.internal_organs) + var/severity = "" + if(a.inflamed > 3) + severity = "Severe" + else if(a.inflamed > 2) + severity = "Moderate" + else if(a.inflamed >= 1) + severity = "Mild" + if(severity) + dat += "[severity] inflammation detected in subject [a.name].
" + // Infections, fractures, and IB + var/basic_fracture = 0 // If it's a basic scanner + var/basic_ib = 0 // If it's a basic scanner + var/fracture_dat = "" // All the fractures + var/infection_dat = "" // All the infections + var/ib_dat = "" // All the IB + for(var/obj/item/organ/external/e in H.organs) + if(!e) + continue + // Broken limbs + if(e.status & ORGAN_BROKEN) + if((e.name in list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG, BP_HEAD, BP_TORSO, BP_GROIN)) && (!e.splinted)) + fracture_dat += "Unsecured fracture in subject [e.name]. Splinting recommended for transport.
" + else if(advscan >= 1 && showadvscan == 1) + fracture_dat += "Bone fractures detected in subject [e.name].
" + else + basic_fracture = 1 + // Infections + if(e.has_infected_wound()) + dat += "Infected wound detected in subject [e.name]. Disinfection recommended.
" + // IB + for(var/datum/wound/W in e.wounds) + if(W.internal) + if(advscan >= 1 && showadvscan == 1) + ib_dat += "Internal bleeding detected in subject [e.name].
" + else + basic_ib = 1 + if(basic_fracture) + fracture_dat += "Bone fractures detected. Advanced scanner required for location.
" + if(basic_ib) + ib_dat += "Internal bleeding detected. Advanced scanner required for location.
" + dat += fracture_dat + dat += infection_dat + dat += ib_dat + + // Blood level + if(M:vessel) + var/blood_volume = H.vessel.get_reagent_amount("blood") + var/blood_percent = round((blood_volume / H.species.blood_volume)*100) + var/blood_type = H.dna.b_type + if(blood_volume <= H.species.blood_volume*H.species.blood_level_danger) + dat += "Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" + else if(blood_volume <= H.species.blood_volume*H.species.blood_level_warning) + dat += "Warning: Blood Level VERY LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" + else if(blood_volume <= H.species.blood_volume*H.species.blood_level_safe) + dat += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" + else + dat += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" + dat += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.
" // VORE Edit: Missed a linebreak here. + if(istype(H.species, /datum/species/xenochimera)) // VOREStation Edit Start: Visible feedback for medmains on Xenochimera. + if(H.stat == DEAD && H.revive_ready == REVIVING_READY && !H.hasnutriment()) + dat += "WARNING: Protein levels low. Subject incapable of reconstitution." + else if(H.revive_ready == REVIVING_NOW) + dat += "Subject is undergoing form reconstruction. Estimated time to finish is in: [round((H.revive_finished - world.time) / 10)] seconds." + else if(H.revive_ready == REVIVING_DONE) + dat += "Subject is ready to hatch. Transfer to dark room for holding with food available." + else if(H.stat == DEAD) + dat+= "WARNING: Defib will cause extreme pain and set subject feral. Sedation recommended prior to defibrillation." + else // If they bop them and they're not dead or reviving, give 'em a little notice. + dat += "Subject is a Xenochimera. Treat accordingly." + // VOREStation Edit End + user.show_message(dat, 1) + +/obj/item/device/healthanalyzer/verb/toggle_mode() + set name = "Switch Verbosity" + set category = "Object" + + mode = !mode + switch (mode) + if(1) + to_chat(usr, "The scanner now shows specific limb damage.") + if(0) + to_chat(usr, "The scanner no longer shows limb damage.") + +/obj/item/device/healthanalyzer/proc/toggle_adv() + set name = "Toggle Advanced Scan" + set category = "Object" + + showadvscan = !showadvscan + switch (showadvscan) + if(1) + to_chat(usr, "The scanner will now perform an advanced analysis.") + if(0) + to_chat(usr, "The scanner will now perform a basic analysis.") + +/obj/item/device/healthanalyzer/improved //reports bone fractures, IB, quantity of beneficial reagents in stomach; also regular health analyzer stuff + name = "improved health analyzer" + desc = "A miracle of medical technology, this handheld scanner can produce an accurate and specific report of a patient's biosigns." + advscan = 1 + origin_tech = list(TECH_MAGNET = 5, TECH_BIO = 6) + icon_state = "health1" + +/obj/item/device/healthanalyzer/advanced //reports all of the above, as well as radiation severity and minor brain damage + name = "advanced health analyzer" + desc = "An even more advanced handheld health scanner, complete with a full biosign monitor and on-board radiation and neurological analysis suites." + advscan = 2 + origin_tech = list(TECH_MAGNET = 6, TECH_BIO = 7) + icon_state = "health2" + +/obj/item/device/healthanalyzer/phasic //reports all of the above, as well as name and quantity of nonmed reagents in stomach + name = "phasic health analyzer" + desc = "Possibly the most advanced health analyzer to ever have existed, utilising bluespace technology to determine almost everything worth knowing about a patient." + advscan = 3 + origin_tech = list(TECH_MAGNET = 7, TECH_BIO = 8) + icon_state = "health3" + +#undef DEFIB_TIME_LIMIT //VOREStation addition +>>>>>>> 23efe5e67d... Merge pull request #13392 from Cameron653/scug_fix diff --git a/code/game/objects/items/devices/scanners/mass_spectrometer.dm b/code/game/objects/items/devices/scanners/mass_spectrometer.dm index fee41eb880..5c044fc535 100644 --- a/code/game/objects/items/devices/scanners/mass_spectrometer.dm +++ b/code/game/objects/items/devices/scanners/mass_spectrometer.dm @@ -30,7 +30,7 @@ /obj/item/device/mass_spectrometer/attack_self(mob/user as mob) if (user.stat) return - if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") + if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return if(reagents.total_volume) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index f065ec3ea1..9676919792 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -20,8 +20,7 @@ to_chat(user, "\The [src] cannot be applied to [M]!") return 1 - if ( ! (istype(user, /mob/living/carbon/human) || \ - istype(user, /mob/living/silicon)) ) + if (!M.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return 1 @@ -129,7 +128,7 @@ if(used >= available) to_chat(user, "You run out of [src]!") break - + if (W.current_stage <= W.max_bleeding_stage) user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \ "You bandage \a [W.desc] on [M]'s [affecting.name]." ) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 02c25c736d..26f3200242 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -19,7 +19,7 @@ user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) - if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 396325a97a..632781992e 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -361,7 +361,7 @@ var/list/mining_overlay_cache = list() //Not even going to touch this pile of spaghetti /turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return