/obj/machinery/bodyscanner name = "body scanner" desc = "A sophisticated device which reports most internal and external injuries." icon = 'icons/obj/cryogenic2.dmi' icon_state = "bodyscanner-open" density = TRUE dir = WEST anchored = TRUE idle_power_consumption = 1250 active_power_consumption = 2500 light_color = "#00FF00" var/mob/living/carbon/human/occupant ///What is the level of the stock parts in the body scanner. A scan_level of one detects organs of stealth_level 1 or below, while a scan level of 4 would detect 4 or below. var/scan_level = 1 var/known_implants = list(/obj/item/bio_chip/chem, /obj/item/bio_chip/death_alarm, /obj/item/bio_chip/mindshield, /obj/item/bio_chip/tracking) /obj/machinery/bodyscanner/examine(mob/user) . = ..() if(occupant) if(occupant.stat == DEAD) . += "You see [occupant.name] inside. [occupant.p_they(TRUE)] [occupant.p_are()] dead!" else . += "You see [occupant.name] inside." if(Adjacent(user)) . += "You can Alt-Click to eject the current occupant. Click-drag someone to the scanner to place them inside." /obj/machinery/bodyscanner/Destroy() go_out() return ..() /obj/machinery/bodyscanner/power_change() if(!..()) return if(!(stat & (BROKEN|NOPOWER))) set_light(2) else set_light(0) /obj/machinery/bodyscanner/process() for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp if(M == occupant) continue else M.forceMove(loc) /obj/machinery/bodyscanner/Initialize(mapload) . = ..() component_parts = list() component_parts += new /obj/item/circuitboard/bodyscanner(null) component_parts += new /obj/item/stock_parts/scanning_module(null) component_parts += new /obj/item/stack/sheet/glass(null) component_parts += new /obj/item/stack/sheet/glass(null) component_parts += new /obj/item/stack/cable_coil(null, 2) RefreshParts() /obj/machinery/bodyscanner/RefreshParts() for(var/obj/item/stock_parts/scanning_module/S in component_parts) scan_level = S.rating /obj/machinery/bodyscanner/update_icon_state() if(occupant) icon_state = "bodyscanner" else icon_state = "bodyscanner-open" /obj/machinery/bodyscanner/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/grab)) var/obj/item/grab/TYPECAST_YOUR_SHIT = I if(panel_open) to_chat(user, "Close the maintenance panel first.") return if(!ishuman(TYPECAST_YOUR_SHIT.affecting)) return if(occupant) to_chat(user, "The scanner is already occupied!") return if(TYPECAST_YOUR_SHIT.affecting.has_buckled_mobs()) //mob attached to us to_chat(user, "[TYPECAST_YOUR_SHIT.affecting] will not fit into [src] because [TYPECAST_YOUR_SHIT.affecting.p_they()] [TYPECAST_YOUR_SHIT.affecting.p_have()] a fucking slime latched onto [TYPECAST_YOUR_SHIT.affecting.p_their()] head.") return var/mob/living/carbon/human/M = TYPECAST_YOUR_SHIT.affecting if(M.abiotic()) to_chat(user, "Subject may not hold anything in their hands.") return M.forceMove(src) occupant = M playsound(src, 'sound/machines/podclose.ogg', 5) update_icon(UPDATE_ICON_STATE) add_fingerprint(user) qdel(TYPECAST_YOUR_SHIT) SStgui.update_uis(src) return return ..() /obj/machinery/bodyscanner/crowbar_act(mob/user, obj/item/I) if(default_deconstruction_crowbar(user, I)) return TRUE /obj/machinery/bodyscanner/screwdriver_act(mob/user, obj/item/I) if(default_deconstruction_screwdriver(user, "bodyscanner-o", "bodyscanner-open", I)) return TRUE /obj/machinery/bodyscanner/wrench_act(mob/user, obj/item/I) . = TRUE if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return if(occupant) to_chat(user, "The scanner is occupied.") return if(panel_open) to_chat(user, "Close the maintenance panel first.") return setDir(turn(dir, -90)) /obj/machinery/bodyscanner/MouseDrop_T(mob/living/carbon/human/H, mob/user) if(!istype(H)) return FALSE //not human if(user.incapacitated()) return FALSE //user shouldn't be doing things if(H.anchored) return FALSE //mob is anchored??? if(get_dist(user, src) > 1 || get_dist(user, H) > 1) return FALSE //doesn't use adjacent() to allow for non-cardinal (fuck my life) if(!ishuman(user) && !isrobot(user)) return FALSE //not a borg or human if(panel_open) to_chat(user, "Close the maintenance panel first.") return TRUE //panel open if(occupant) to_chat(user, "[src] is already occupied.") return TRUE //occupied if(H.buckled) return FALSE if(H.abiotic()) to_chat(user, "Subject may not hold anything in their hands.") return TRUE if(H.has_buckled_mobs()) //mob attached to us to_chat(user, "[H] will not fit into [src] because [H.p_they()] [H.p_have()] a slime latched onto [H.p_their()] head.") return TRUE if(H == user) visible_message("[user] climbs into [src].") else visible_message("[user] puts [H] into the body scanner.") QDEL_LIST_CONTENTS(H.grabbed_by) H.forceMove(src) occupant = H playsound(src, 'sound/machines/podclose.ogg', 5) update_icon(UPDATE_ICON_STATE) add_fingerprint(user) SStgui.update_uis(src) return TRUE /obj/machinery/bodyscanner/attack_ai(user) return attack_hand(user) /obj/machinery/bodyscanner/attack_ghost(user) ui_interact(user) /obj/machinery/bodyscanner/attack_hand(user) if(stat & (NOPOWER|BROKEN)) return if(occupant == user) return // you cant reach that if(panel_open) to_chat(user, "Close the maintenance panel first.") return ui_interact(user) /obj/machinery/bodyscanner/relaymove(mob/user) if(user.incapacitated()) return FALSE //maybe they should be able to get out with cuffs, but whatever go_out() /obj/machinery/bodyscanner/AltClick(mob/user) if(issilicon(user)) eject() return if(!Adjacent(user) || !ishuman(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) return eject() /obj/machinery/bodyscanner/proc/eject(mob/user) go_out() add_fingerprint(user) /obj/machinery/bodyscanner/proc/go_out() if(!occupant) return occupant.forceMove(loc) occupant = null playsound(src, 'sound/machines/podopen.ogg', 5) update_icon(UPDATE_ICON_STATE) // eject trash the occupant dropped for(var/atom/movable/A in contents - component_parts) A.forceMove(loc) SStgui.update_uis(src) /obj/machinery/bodyscanner/force_eject_occupant(mob/target) go_out() /obj/machinery/bodyscanner/ex_act(severity) if(occupant) occupant.ex_act(severity) ..() /obj/machinery/bodyscanner/handle_atom_del(atom/A) ..() if(A == occupant) occupant = null update_icon(UPDATE_ICON_STATE) /obj/machinery/bodyscanner/narsie_act() go_out() new /obj/effect/gibspawner/generic(get_turf(loc)) //I REPLACE YOUR TECHNOLOGY WITH FLESH! qdel(src) /obj/machinery/bodyscanner/ui_state(mob/user) return GLOB.default_state /obj/machinery/bodyscanner/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "BodyScanner") ui.open() /obj/machinery/bodyscanner/ui_data(mob/user) var/list/data = list() data["occupied"] = occupant ? TRUE : FALSE var/occupantData[0] if(occupant) occupantData["name"] = occupant.name occupantData["stat"] = HAS_TRAIT(occupant, TRAIT_FAKEDEATH) ? DEAD : occupant.stat occupantData["health"] = occupant.health occupantData["maxHealth"] = occupant.maxHealth var/found_disease = FALSE for(var/thing in occupant.viruses) var/datum/disease/D = thing if(D.visibility_flags & HIDDEN_SCANNER || D.visibility_flags & HIDDEN_PANDEMIC) continue if(istype(D, /datum/disease/critical)) continue found_disease = TRUE break occupantData["hasVirus"] = found_disease occupantData["bruteLoss"] = occupant.getBruteLoss() occupantData["oxyLoss"] = occupant.getOxyLoss() occupantData["toxLoss"] = occupant.getToxLoss() occupantData["fireLoss"] = occupant.getFireLoss() occupantData["radLoss"] = occupant.radiation occupantData["cloneLoss"] = occupant.getCloneLoss() occupantData["brainLoss"] = occupant.getBrainLoss() occupantData["drunkenness"] = (occupant.get_drunkenness() / 10) occupantData["bodyTempC"] = occupant.bodytemperature-T0C occupantData["bodyTempF"] = (((occupant.bodytemperature-T0C) * 1.8) + 32) var/bloodData[0] bloodData["hasBlood"] = FALSE if(!(NO_BLOOD in occupant.dna.species.species_traits)) bloodData["hasBlood"] = TRUE bloodData["volume"] = occupant.blood_volume bloodData["percent"] = round(((occupant.blood_volume / BLOOD_VOLUME_NORMAL)*100)) bloodData["pulse"] = occupant.get_pulse() bloodData["bloodLevel"] = occupant.blood_volume bloodData["bloodMax"] = occupant.max_blood occupantData["blood"] = bloodData var/implantData[0] for(var/obj/item/bio_chip/I in occupant) if(I.implanted && is_type_in_list(I, known_implants)) var/implantSubData[0] implantSubData["name"] = sanitize(I.name) implantData.Add(list(implantSubData)) occupantData["implant"] = implantData occupantData["implant_len"] = length(implantData) var/extOrganData[0] for(var/obj/item/organ/external/E in occupant.bodyparts) var/organData[0] organData["name"] = E.name organData["open"] = E.open organData["germ_level"] = E.germ_level organData["bruteLoss"] = E.brute_dam organData["fireLoss"] = E.burn_dam organData["totalLoss"] = E.brute_dam + E.burn_dam organData["maxHealth"] = E.max_damage organData["bruised"] = E.min_bruised_damage organData["broken"] = E.min_broken_damage var/shrapnelData[0] for(var/obj/I in E.embedded_objects) var/shrapnelSubData[0] shrapnelSubData["name"] = I.name shrapnelData.Add(list(shrapnelSubData)) organData["shrapnel"] = shrapnelData organData["shrapnel_len"] = length(shrapnelData) var/organStatus[0] if(E.status & ORGAN_BROKEN) if(!E.broken_description) organStatus["broken"] = "Broken" else organStatus["broken"] = E.broken_description if(E.is_robotic()) organStatus["robotic"] = TRUE if(E.status & ORGAN_SPLINTED) organStatus["splinted"] = TRUE if(E.status & ORGAN_DEAD) organStatus["dead"] = TRUE organData["status"] = organStatus if(istype(E, /obj/item/organ/external/chest) && occupant.is_lung_ruptured()) organData["lungRuptured"] = TRUE if(E.status & ORGAN_INT_BLEEDING) organData["internalBleeding"] = TRUE if(E.status & ORGAN_BURNT) organData["burnWound"] = TRUE extOrganData.Add(list(organData)) occupantData["extOrgan"] = extOrganData var/intOrganData[0] for(var/obj/item/organ/internal/I in occupant.internal_organs) if(I.stealth_level > scan_level) continue var/organData[0] organData["name"] = I.name organData["desc"] = I.desc organData["germ_level"] = I.germ_level organData["damage"] = I.damage organData["maxHealth"] = I.max_damage organData["bruised"] = I.min_bruised_damage organData["broken"] = I.min_broken_damage organData["robotic"] = I.is_robotic() organData["dead"] = (I.status & ORGAN_DEAD) intOrganData.Add(list(organData)) occupantData["intOrgan"] = intOrganData occupantData["blind"] = HAS_TRAIT(occupant, TRAIT_BLIND) occupantData["colourblind"] = HAS_TRAIT(occupant, TRAIT_COLORBLIND) occupantData["nearsighted"] = HAS_TRAIT(occupant, TRAIT_NEARSIGHT) data["occupant"] = occupantData return data /obj/machinery/bodyscanner/ui_act(action, params) if(..()) return if(stat & (NOPOWER|BROKEN)) return . = TRUE switch(action) if("ejectify") eject() if("print_p") visible_message("[src] rattles and prints out a sheet of paper.") var/obj/item/paper/P = new /obj/item/paper(loc) playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE) var/name = occupant ? occupant.name : "Unknown" P.info = "
| Body Part | " dat += "Burn Damage | " dat += "Brute Damage | " dat += "Injuries | " dat += "
|---|---|---|---|
| [e.name] | " dat += "[e.burn_dam] | " dat += "[e.brute_dam] | " dat += "[jointext(ailments, " ")] | "
dat += "
| Organ | " dat += "Damage | " dat += "Injuries | " dat += "
|---|---|---|
| [I.name] | " dat += "[I.damage] | " dat += "[jointext(ailments, " ")] | "
dat += "