mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-01-28 18:32:04 +00:00
* Wound datumization * Rejuv additions * Fixes * Adds `get_wound()` proc * Ruptured lungs get fixed now * Apply suggestions from code review Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Fix this * Potentially fix an issue, might remove the proc later * Many fixes * Fuck --------- Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
284 lines
10 KiB
Plaintext
284 lines
10 KiB
Plaintext
/obj/item/bodyanalyzer
|
|
name = "handheld body analyzer"
|
|
desc = "A handheld scanner capable of deep-scanning an entire body."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "bodyanalyzer_0"
|
|
worn_icon_state = "healthanalyzer"
|
|
inhand_icon_state = "healthanalyzer"
|
|
slot_flags = ITEM_SLOT_BELT
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
throw_speed = 5
|
|
throw_range = 10
|
|
origin_tech = "magnets=6;biotech=6"
|
|
var/obj/item/stock_parts/cell/cell
|
|
var/cell_type = /obj/item/stock_parts/cell/high
|
|
var/ready = TRUE // Ready to scan
|
|
var/printing = FALSE
|
|
var/time_to_use = 0 // How much time remaining before next scan is available.
|
|
var/usecharge = 750
|
|
var/scan_time = 5 SECONDS //how long does it take to scan
|
|
var/scan_cd = 30 SECONDS //how long before we can scan again
|
|
|
|
/obj/item/bodyanalyzer/get_cell()
|
|
return cell
|
|
|
|
/obj/item/bodyanalyzer/advanced
|
|
cell_type = /obj/item/stock_parts/cell/super // twice the charge!
|
|
|
|
/obj/item/bodyanalyzer/borg
|
|
name = "cyborg body analyzer"
|
|
desc = "Scan an entire body to prepare for field surgery. Consumes power for each scan."
|
|
|
|
/obj/item/bodyanalyzer/borg/syndicate
|
|
scan_cd = 20 SECONDS
|
|
|
|
/obj/item/bodyanalyzer/New()
|
|
..()
|
|
cell = new cell_type(src)
|
|
cell.give(cell.maxcharge)
|
|
update_icon()
|
|
|
|
/obj/item/bodyanalyzer/proc/setReady()
|
|
ready = TRUE
|
|
playsound(src, 'sound/machines/defib_saftyon.ogg', 50, 0)
|
|
update_icon()
|
|
|
|
/obj/item/bodyanalyzer/update_icon_state()
|
|
if(!cell)
|
|
icon_state = "bodyanalyzer_0"
|
|
return
|
|
if(ready)
|
|
icon_state = "bodyanalyzer_1"
|
|
else
|
|
icon_state = "bodyanalyzer_2"
|
|
|
|
/obj/item/bodyanalyzer/update_overlays()
|
|
. = ..()
|
|
var/percent = cell.percent()
|
|
var/overlayid = round(percent / 10)
|
|
. += "bodyanalyzer_charge[overlayid]"
|
|
if(printing)
|
|
. += "bodyanalyzer_printing"
|
|
|
|
/obj/item/bodyanalyzer/attack__legacy__attackchain(mob/living/M, mob/living/carbon/human/user)
|
|
if(user.incapacitated() || !user.Adjacent(M))
|
|
return
|
|
|
|
if(!ready)
|
|
to_chat(user, SPAN_NOTICE("The scanner beeps angrily at you! It's currently recharging - [round((time_to_use - world.time) * 0.1)] seconds remaining."))
|
|
playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
|
|
return
|
|
|
|
if(cell.charge >= usecharge)
|
|
mobScan(M, user)
|
|
else
|
|
to_chat(user, SPAN_NOTICE("The scanner beeps angrily at you! It's out of charge!"))
|
|
playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
|
|
|
|
/obj/item/bodyanalyzer/borg/attack__legacy__attackchain(mob/living/M, mob/living/silicon/robot/user)
|
|
if(user.incapacitated() || !user.Adjacent(M))
|
|
return
|
|
|
|
if(!ready)
|
|
to_chat(user, SPAN_NOTICE("[src] is currently recharging - [round((time_to_use - world.time) * 0.1)] seconds remaining."))
|
|
return
|
|
|
|
if(user.cell.charge >= usecharge)
|
|
mobScan(M, user)
|
|
else
|
|
to_chat(user, SPAN_NOTICE("You need to recharge before you can use [src]"))
|
|
|
|
/obj/item/bodyanalyzer/proc/mobScan(mob/living/M, mob/user)
|
|
if(ishuman(M))
|
|
var/report = generate_printing_text(M, user)
|
|
user.visible_message("[user] begins scanning [M] with [src].", "You begin scanning [M].")
|
|
if(do_after(user, scan_time, target = M))
|
|
var/obj/item/paper/printout = new
|
|
printout.info = report
|
|
printout.name = "Scan report - [M.name]"
|
|
playsound(user.loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
|
user.put_in_hands(printout)
|
|
time_to_use = world.time + scan_cd
|
|
if(isrobot(user))
|
|
var/mob/living/silicon/robot/R = user
|
|
R.cell.use(usecharge)
|
|
else
|
|
cell.use(usecharge)
|
|
ready = FALSE
|
|
printing = TRUE
|
|
update_icon()
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/bodyanalyzer, setReady)), scan_cd)
|
|
addtimer(VARSET_CALLBACK(src, printing, FALSE), 1.4 SECONDS)
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon), UPDATE_OVERLAYS), 1.5 SECONDS)
|
|
else if(iscorgi(M) && M.stat == DEAD)
|
|
to_chat(user, SPAN_NOTICE("You wonder if [M.p_they()] was a good dog. <b>[src] tells you they were the best...</b>")) // :'(
|
|
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
|
|
ready = FALSE
|
|
update_icon(UPDATE_ICON_STATE)
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/bodyanalyzer, setReady)), scan_cd)
|
|
time_to_use = world.time + scan_cd
|
|
else
|
|
to_chat(user, SPAN_NOTICE("Scanning error detected. Invalid specimen."))
|
|
|
|
//Unashamedly ripped from adv_med.dm
|
|
/obj/item/bodyanalyzer/proc/generate_printing_text(mob/living/M, mob/user)
|
|
var/dat = ""
|
|
var/mob/living/carbon/human/target = M
|
|
|
|
dat = "<font color='blue'><b>Target Statistics:</b></font><br>"
|
|
var/t1
|
|
switch(target.stat) // obvious, see what their status is
|
|
if(CONSCIOUS)
|
|
t1 = "Conscious"
|
|
if(UNCONSCIOUS)
|
|
t1 = "Unconscious"
|
|
else
|
|
t1 = "*dead*"
|
|
dat += "[target.health > 50 ? "<font color='blue'>" : "<font color='red'>"]\tHealth %: [target.health], ([t1])</font><br>"
|
|
|
|
var/found_disease = FALSE
|
|
for(var/thing in target.viruses)
|
|
var/datum/disease/D = thing
|
|
if(D.visibility_flags) //If any visibility flags are on.
|
|
continue
|
|
found_disease = TRUE
|
|
break
|
|
if(found_disease)
|
|
dat += "<font color='red'>Disease detected in target.</font><BR>"
|
|
|
|
var/extra_font = null
|
|
extra_font = (target.getBruteLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\t-Brute Damage %: [target.getBruteLoss()]</font><br>"
|
|
|
|
extra_font = (target.getOxyLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\t-Respiratory Damage %: [target.getOxyLoss()]</font><br>"
|
|
|
|
extra_font = (target.getToxLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\t-Toxin Content %: [target.getToxLoss()]</font><br>"
|
|
|
|
extra_font = (target.getFireLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\t-Burn Severity %: [target.getFireLoss()]</font><br>"
|
|
|
|
extra_font = (target.radiation < 10 ?"<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tRadiation Level %: [target.radiation]</font><br>"
|
|
|
|
extra_font = (target.getCloneLoss() < 1 ?"<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tGenetic Tissue Damage %: [target.getCloneLoss()]<br>"
|
|
|
|
extra_font = (target.getBrainLoss() < 1 ?"<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tApprox. Brain Damage %: [target.getBrainLoss()]<br>"
|
|
|
|
dat += "Paralysis Summary %: [target.IsParalyzed()] ([round(target.AmountParalyzed() / 10)] seconds left!)<br>"
|
|
dat += "Body Temperature: [target.bodytemperature-T0C]°C ([target.bodytemperature*1.8-459.67]°F)<br>"
|
|
|
|
dat += "<hr>"
|
|
|
|
var/blood_percent = round((target.blood_volume / BLOOD_VOLUME_NORMAL))
|
|
blood_percent *= 100
|
|
|
|
extra_font = (target.blood_volume > 448 ? "<font color='blue'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tBlood Level %: [blood_percent] ([target.blood_volume] units)</font><br>"
|
|
|
|
if(target.reagents)
|
|
dat += "Epinephrine units: [target.reagents.get_reagent_amount("Epinephrine")] units<BR>"
|
|
dat += "Ether: [target.reagents.get_reagent_amount("ether")] units<BR>"
|
|
|
|
extra_font = (target.reagents.get_reagent_amount("silver_sulfadiazine") < 30 ? "<font color='black'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tSilver Sulfadiazine: [target.reagents.get_reagent_amount("silver_sulfadiazine")]</font><br>"
|
|
|
|
extra_font = (target.reagents.get_reagent_amount("styptic_powder") < 30 ? "<font color='black'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tStyptic Powder: [target.reagents.get_reagent_amount("styptic_powder")] units<BR>"
|
|
|
|
extra_font = (target.reagents.get_reagent_amount("salbutamol") < 30 ? "<font color='black'>" : "<font color='red'>")
|
|
dat += "[extra_font]\tSalbutamol: [target.reagents.get_reagent_amount("salbutamol")] units<BR>"
|
|
|
|
dat += "<hr><table border='1'>"
|
|
dat += "<tr>"
|
|
dat += "<th>Organ</th>"
|
|
dat += "<th>Burn Damage</th>"
|
|
dat += "<th>Brute Damage</th>"
|
|
dat += "<th>Other Wounds</th>"
|
|
dat += "</tr>"
|
|
|
|
for(var/obj/item/organ/external/e in target.bodyparts)
|
|
dat += "<tr>"
|
|
var/AN = ""
|
|
var/open = ""
|
|
var/infected = ""
|
|
var/robot = ""
|
|
var/imp = ""
|
|
var/bled = ""
|
|
var/splint = ""
|
|
var/internal_bleeding = ""
|
|
var/lung_ruptured = ""
|
|
if(e.status & ORGAN_INT_BLEEDING)
|
|
internal_bleeding = "<br>Internal bleeding"
|
|
if(istype(e, /obj/item/organ/external/chest) && target.is_lung_ruptured())
|
|
lung_ruptured = "Lung ruptured:"
|
|
if(e.status & ORGAN_SPLINTED)
|
|
splint = "Splinted:"
|
|
if(e.status & ORGAN_BROKEN)
|
|
var/datum/wound/fracture = e.get_wound(/datum/wound/fracture)
|
|
AN = "[fracture.name]:"
|
|
if(e.is_robotic())
|
|
robot = "Robotic:"
|
|
if(e.open)
|
|
open = "Open:"
|
|
switch(e.germ_level)
|
|
if(INFECTION_LEVEL_ONE to INFECTION_LEVEL_ONE + 200)
|
|
infected = "Mild Infection:"
|
|
if(INFECTION_LEVEL_ONE + 200 to INFECTION_LEVEL_ONE + 300)
|
|
infected = "Mild Infection+:"
|
|
if(INFECTION_LEVEL_ONE + 300 to INFECTION_LEVEL_ONE + 400)
|
|
infected = "Mild Infection++:"
|
|
if(INFECTION_LEVEL_TWO to INFECTION_LEVEL_TWO + 200)
|
|
infected = "Acute Infection:"
|
|
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
|
|
infected = "Acute Infection+:"
|
|
if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 400)
|
|
infected = "Acute Infection++:"
|
|
if(INFECTION_LEVEL_THREE to INFINITY)
|
|
infected = "Septic:"
|
|
|
|
var/unknown_body = 0
|
|
for(var/I in e.embedded_objects)
|
|
unknown_body++
|
|
|
|
if(unknown_body || e.hidden)
|
|
imp += "Unknown body present:"
|
|
if(!AN && !open && !infected && !imp)
|
|
AN = "None:"
|
|
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]</td>"
|
|
dat += "</tr>"
|
|
for(var/obj/item/organ/internal/i in target.internal_organs)
|
|
var/mech = i.desc
|
|
var/infection = "None"
|
|
switch(i.germ_level)
|
|
if(1 to INFECTION_LEVEL_ONE + 200)
|
|
infection = "Mild Infection:"
|
|
if(INFECTION_LEVEL_ONE + 200 to INFECTION_LEVEL_ONE + 300)
|
|
infection = "Mild Infection+:"
|
|
if(INFECTION_LEVEL_ONE + 300 to INFECTION_LEVEL_ONE + 400)
|
|
infection = "Mild Infection++:"
|
|
if(INFECTION_LEVEL_TWO to INFECTION_LEVEL_TWO + 200)
|
|
infection = "Acute Infection:"
|
|
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
|
|
infection = "Acute Infection+:"
|
|
if(INFECTION_LEVEL_TWO + 300 to INFINITY)
|
|
infection = "Acute Infection++:"
|
|
|
|
dat += "<tr>"
|
|
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech]</td><td></td>"
|
|
dat += "</tr>"
|
|
dat += "</table>"
|
|
if(HAS_TRAIT(target, TRAIT_BLIND))
|
|
dat += "<font color='red'>Cataracts detected.</font><BR>"
|
|
if(HAS_TRAIT(target, TRAIT_COLORBLIND))
|
|
dat += "<font color='red'>Photoreceptor abnormalities detected.</font><BR>"
|
|
if(HAS_TRAIT(target, TRAIT_NEARSIGHT))
|
|
dat += "<font color='red'>Retinal misalignment detected.</font><BR>"
|
|
if(HAS_TRAIT(target, TRAIT_PARAPLEGIC))
|
|
dat += "<font color='red'>Lumbar nerves damaged.</font><BR>"
|
|
|
|
return dat
|