mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 17:14:47 +01:00
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
291 lines
10 KiB
Plaintext
291 lines
10 KiB
Plaintext
#define MENU_OPERATION 1
|
|
#define MENU_SURGERIES 2
|
|
|
|
/obj/machinery/computer/operating
|
|
name = "operating computer"
|
|
desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures. Automatically syncs to operating tables within its line of sight for surgical tech advancement."
|
|
icon_screen = "crew"
|
|
icon_keyboard = "med_key"
|
|
circuit = /obj/item/circuitboard/computer/operating
|
|
interaction_flags_machine = parent_type::interaction_flags_machine | INTERACT_MACHINE_REQUIRES_STANDING
|
|
|
|
light_color = LIGHT_COLOR_GREEN
|
|
|
|
/// Linked operating table, if any
|
|
var/obj/structure/table/optable/table
|
|
/// List if surgery typepaths available on this computer
|
|
var/list/advanced_surgeries = list()
|
|
/// Techweb linked to this operating computer
|
|
var/datum/techweb/linked_techweb
|
|
/// Currently selected body zone for surgery
|
|
var/target_zone = BODY_ZONE_CHEST
|
|
/// Experiment handler component reference
|
|
var/datum/component/experiment_handler/experiment_handler
|
|
/// Lazyassoclist of mob weakrefs to the zone they had selected when opening the UI
|
|
/// When closing the UI we try to revert their zone selector to that zone
|
|
var/list/datum/weakref/zone_on_open
|
|
|
|
/obj/machinery/computer/operating/Initialize(mapload)
|
|
. = ..()
|
|
find_table()
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/machinery/computer/operating/post_machine_initialize()
|
|
. = ..()
|
|
if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
|
|
CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
|
|
|
|
if(linked_techweb)
|
|
RegisterSignal(linked_techweb, COMSIG_TECHWEB_ADD_DESIGN, PROC_REF(on_techweb_research))
|
|
RegisterSignal(linked_techweb, COMSIG_TECHWEB_REMOVE_DESIGN, PROC_REF(on_techweb_unresearch))
|
|
RegisterSignal(linked_techweb, COMSIG_TECHWEB_EXPERIMENT_COMPLETED, PROC_REF(update_static_data_batched))
|
|
|
|
for(var/datum/design/surgery/design in linked_techweb.get_researched_design_datums())
|
|
advanced_surgeries |= design.surgery
|
|
|
|
var/list/operating_signals = list(
|
|
COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_autopsy_experiment),
|
|
)
|
|
experiment_handler = AddComponent(
|
|
/datum/component/experiment_handler, \
|
|
allowed_experiments = list(/datum/experiment/autopsy), \
|
|
config_flags = EXPERIMENT_CONFIG_ALWAYS_ACTIVE, \
|
|
config_mode = EXPERIMENT_CONFIG_ALTCLICK, \
|
|
experiment_signals = operating_signals, \
|
|
)
|
|
|
|
/obj/machinery/computer/operating/Destroy()
|
|
for(var/direction in GLOB.alldirs)
|
|
table = locate(/obj/structure/table/optable) in get_step(src, direction)
|
|
if(table && table.computer == src)
|
|
table.computer = null
|
|
QDEL_NULL(experiment_handler)
|
|
return ..()
|
|
|
|
/obj/machinery/computer/operating/multitool_act(mob/living/user, obj/item/multitool/tool)
|
|
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
|
|
linked_techweb = tool.buffer
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/operating/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
if(istype(tool, /obj/item/disk/surgery))
|
|
user.visible_message(
|
|
span_notice("[user] begins to load [tool] in [src]..."),
|
|
span_notice("You begin to load a surgery protocol from [tool]..."),
|
|
span_hear("You hear the chatter of a floppy drive."),
|
|
)
|
|
var/obj/item/disk/surgery/disky = tool
|
|
if(!do_after(user, 1 SECONDS, src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
advanced_surgeries |= disky.surgeries
|
|
update_static_data_for_all_viewers()
|
|
playsound(src, 'sound/machines/compiler/compiler-stage2.ogg', 50, FALSE, SILENCED_SOUND_EXTRARANGE)
|
|
balloon_alert(user, "surgeries loaded")
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if((tool.item_flags & SURGICAL_TOOL) && !user.combat_mode)
|
|
ui_interact(user)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
return NONE
|
|
|
|
/obj/machinery/computer/operating/on_set_is_operational(old_value)
|
|
update_static_data_for_all_viewers()
|
|
|
|
/obj/machinery/computer/operating/proc/find_table()
|
|
for(var/direction in GLOB.alldirs)
|
|
table = locate(/obj/structure/table/optable) in get_step(src, direction)
|
|
if(table)
|
|
table.computer = src
|
|
break
|
|
|
|
/obj/machinery/computer/operating/ui_status(mob/user, datum/ui_state/state)
|
|
. = ..()
|
|
if(isliving(user) && !issilicon(user))
|
|
. = min(., ui_check(user))
|
|
|
|
/// Checks for special ui state conditions
|
|
/obj/machinery/computer/operating/proc/ui_check(mob/living/user)
|
|
// lower states should be checked first
|
|
|
|
// normally machines revert to "disabled" when non-operational,
|
|
// but here we outright close it so people can't gleam extra info
|
|
if(!is_operational)
|
|
return UI_CLOSE
|
|
// if you're knocked out, ie anesthetic... definitely a no-go
|
|
if(user.stat >= UNCONSCIOUS || HAS_TRAIT(user, TRAIT_KNOCKEDOUT))
|
|
return UI_CLOSE
|
|
// the patient itself should be blocked from viewing the computer
|
|
if(user.body_position == LYING_DOWN)
|
|
return (user.loc == table?.loc) ? UI_CLOSE : UI_DISABLED
|
|
// we have a tight range check so people can't spy on surgeries from across the room
|
|
// likewise it'd be pretty lame if you could see what was going on while incapacitated
|
|
if(get_dist(user, src) > 2 || user.incapacitated)
|
|
return UI_DISABLED
|
|
|
|
return UI_INTERACTIVE
|
|
|
|
/obj/machinery/computer/operating/ui_interact(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(ui)
|
|
return
|
|
|
|
if(ishuman(user))
|
|
// if you are the first human to open the ui, it changes to your active zone
|
|
if(!LAZYLEN(zone_on_open))
|
|
target_zone = user.zone_selected
|
|
// then we record what you were looking at for when you close it
|
|
LAZYSET(zone_on_open, WEAKREF(user), user.zone_selected)
|
|
|
|
ui = new(user, src, "OperatingComputer", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/computer/operating/ui_close(mob/user)
|
|
. = ..()
|
|
// reverts zone to whatever you had going into it, typically chest, so you don't have to mess around with it
|
|
var/zone_found = LAZYACCESS(zone_on_open, WEAKREF(user))
|
|
if(!zone_found)
|
|
return
|
|
|
|
var/atom/movable/screen/zone_sel/selector = user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]
|
|
selector?.set_selected_zone(zone_found, user, FALSE)
|
|
LAZYREMOVE(zone_on_open, WEAKREF(user))
|
|
if(!LAZYLEN(zone_on_open))
|
|
zone_on_open = initial(zone_on_open)
|
|
|
|
/obj/machinery/computer/operating/ui_assets(mob/user)
|
|
. = ..()
|
|
. += get_asset_datum(/datum/asset/simple/body_zones)
|
|
|
|
/obj/machinery/computer/operating/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["has_table"] = !!table
|
|
data["target_zone"] = target_zone
|
|
if(isnull(table?.patient))
|
|
return data
|
|
|
|
data["patient"] = list()
|
|
var/mob/living/patient = table.patient
|
|
|
|
switch(patient.stat)
|
|
if(CONSCIOUS)
|
|
data["patient"]["stat"] = "Conscious"
|
|
data["patient"]["statstate"] = "good"
|
|
if(SOFT_CRIT)
|
|
data["patient"]["stat"] = "Critical Condition"
|
|
data["patient"]["statstate"] = "average"
|
|
if(UNCONSCIOUS, HARD_CRIT)
|
|
data["patient"]["stat"] = "Unconscious"
|
|
data["patient"]["statstate"] = "average"
|
|
if(DEAD)
|
|
data["patient"]["stat"] = "Dead"
|
|
data["patient"]["statstate"] = "bad"
|
|
data["patient"]["health"] = patient.health
|
|
data["patient"]["blood_type"] = patient.get_bloodtype()?.name || "UNKNOWN"
|
|
data["patient"]["maxHealth"] = patient.maxHealth
|
|
data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD
|
|
data["patient"]["bruteLoss"] = patient.get_brute_loss()
|
|
data["patient"]["fireLoss"] = patient.get_fire_loss()
|
|
data["patient"]["toxLoss"] = patient.get_tox_loss()
|
|
data["patient"]["oxyLoss"] = patient.get_oxy_loss()
|
|
data["patient"]["blood_level"] = patient.blood_volume
|
|
data["patient"]["standard_blood_level"] = BLOOD_VOLUME_NORMAL
|
|
data["patient"]["surgery_state"] = patient.get_surgery_state_as_list(deprecise_zone(target_zone))
|
|
return data
|
|
|
|
/obj/machinery/computer/operating/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
data["experiments"] = list()
|
|
data["techwebs"] = list()
|
|
data["surgeries"] = list()
|
|
if(!is_operational)
|
|
return data
|
|
|
|
if(linked_techweb)
|
|
data["techwebs"] += list(list(
|
|
"web_id" = linked_techweb.id,
|
|
"web_org" = linked_techweb.organization,
|
|
"selected" = TRUE,
|
|
"ref" = REF(linked_techweb),
|
|
"all_servers" = linked_techweb.techweb_servers,
|
|
))
|
|
|
|
for(var/datum/experiment/experiment as anything in linked_techweb.available_experiments)
|
|
if(istype(experiment, /datum/experiment/autopsy))
|
|
data["experiments"] += list(experiment.to_ui_data())
|
|
|
|
var/list/operations = GLOB.operations.get_instances_from(GLOB.operations.unlocked | advanced_surgeries)
|
|
var/any_recommended = FALSE
|
|
for(var/datum/surgery_operation/operation as anything in operations)
|
|
var/recommend = FALSE
|
|
if(table?.patient && operation.show_as_next_step(table.patient, target_zone))
|
|
recommend = TRUE
|
|
any_recommended = TRUE
|
|
|
|
data["surgeries"] += list(list(
|
|
"name" = operation.rnd_name || operation.name,
|
|
"desc" = operation.rnd_desc || operation.desc,
|
|
"tool_rec" = operation.get_recommended_tool() || "error",
|
|
"requirements" = operation.get_requirements(),
|
|
"show_as_next" = recommend,
|
|
"show_in_list" = TRUE,
|
|
"priority" = operation.operation_flags & OPERATION_PRIORITY_NEXT_STEP,
|
|
"mechanic" = operation.operation_flags & OPERATION_MECHANIC,
|
|
))
|
|
|
|
if(!any_recommended && table?.patient && !HAS_TRAIT(table.patient, TRAIT_READY_TO_OPERATE))
|
|
data["surgeries"] += list(list(
|
|
"name" = "Prepare for surgery",
|
|
"desc" = "Begin surgery by applying surgical drapes to the patient or by buckling the patient to the surgical table.",
|
|
"tool_rec" = /obj/item/surgical_drapes::name,
|
|
"show_as_next" = TRUE,
|
|
"show_in_list" = FALSE,
|
|
))
|
|
|
|
return data
|
|
|
|
/obj/machinery/computer/operating/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
switch(action)
|
|
if("open_experiments")
|
|
experiment_handler.ui_interact(usr)
|
|
if("change_zone")
|
|
if(params["new_zone"] in (GLOB.all_body_zones + GLOB.all_precise_body_zones))
|
|
target_zone = params["new_zone"]
|
|
var/atom/movable/screen/zone_sel/selector = ui.user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]
|
|
selector?.set_selected_zone(params["new_zone"], ui.user, FALSE)
|
|
update_static_data_for_all_viewers()
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/operating/proc/on_techweb_research(datum/source, datum/design/surgery/design)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(design))
|
|
return
|
|
|
|
advanced_surgeries |= design.surgery
|
|
update_static_data_batched()
|
|
|
|
/obj/machinery/computer/operating/proc/on_techweb_unresearch(datum/source, datum/design/surgery/design)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(design))
|
|
return
|
|
|
|
advanced_surgeries -= design.surgery
|
|
update_static_data_batched()
|
|
|
|
/// Updates static data for all viewers after a miniscule delay (to batch multiple updates together)
|
|
/obj/machinery/computer/operating/proc/update_static_data_batched(...)
|
|
SIGNAL_HANDLER
|
|
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, update_static_data_for_all_viewers)), 0.1 SECONDS, TIMER_UNIQUE)
|
|
|
|
#undef MENU_OPERATION
|
|
#undef MENU_SURGERIES
|