Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows you to attach air tanks to operating tables for eaiser application of Anesthesia (or pain) (Also converts Op Computer to TSX) #361

Merged
merged 7 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions code/game/machinery/computer/operating_computer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OperatingComputer", name)
ui = new(user, src, "_OperatingComputer", name) // NON-MODULE CHANGE
ui.open()

/obj/machinery/computer/operating/ui_data(mob/user)
Expand All @@ -97,7 +97,7 @@
data["patient"] = null
return data

data["table"] = table
data["table"] = !!table // NON-MODULE CHANGE
data["patient"] = list()
if(!table.patient)
return data
Expand Down Expand Up @@ -164,9 +164,10 @@
switch(action)
if("sync")
sync_surgeries()
return TRUE // NON-MODULE CHANGE
if("open_experiments")
experiment_handler.ui_interact(usr)
return TRUE
return TRUE // NON-MODULE CHANGE

#undef MENU_OPERATION
#undef MENU_SURGERIES
1 change: 1 addition & 0 deletions maplestation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -5413,6 +5413,7 @@
#include "maplestation_modules\code\game\objects\spawners\random\contraband.dm"
#include "maplestation_modules\code\game\objects\structures\item_dispensers.dm"
#include "maplestation_modules\code\game\objects\structures\static_plaques.dm"
#include "maplestation_modules\code\game\objects\structures\surgery_table.dm"
#include "maplestation_modules\code\game\objects\structures\crate_lockers\crates.dm"
#include "maplestation_modules\code\game\objects\structures\crate_lockers\closets\secure\asset_protection.dm"
#include "maplestation_modules\code\game\objects\structures\crate_lockers\closets\secure\bridge_officer.dm"
Expand Down
247 changes: 247 additions & 0 deletions maplestation_modules/code/game/objects/structures/surgery_table.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/obj/structure/table/optable
/// Internals tank clamped onto the table.
/// Allows an operating computer to easily attach it to the mob and use it for anesthesia.
VAR_FINAL/obj/item/tank/internals/attached_tank
/// World time when the patient was set onto the tank
VAR_FINAL/patient_set_at = -1
/// Time after which the anesthesia will be automatically disabled
/// Can be set to INFINITY to never auto-disable
var/failsafe_time = 6 MINUTES

/obj/structure/table/optable/Initialize(mapload)
. = ..()
update_appearance(UPDATE_OVERLAYS)

/obj/structure/table/optable/examine(mob/user)
. = ..()
if(isnull(attached_tank))
. += span_notice("It has a clamp on the side for attaching a breath tank.")
else
. += span_notice("It has \a [attached_tank] attached to it.")

/obj/structure/table/optable/update_overlays()
. = ..()
if(!isnull(attached_tank))
. += mutable_appearance(
icon = 'maplestation_modules/icons/obj/surgery_table_overlay.dmi',
icon_state = "surgery_[attached_tank.icon_state]",
alpha = src.alpha,
)

. += mutable_appearance(
icon = 'maplestation_modules/icons/obj/surgery_table_overlay.dmi',
icon_state = "patient_light_[patient ? "on" : "off"]",
alpha = src.alpha,
)

. += mutable_appearance(
icon = 'maplestation_modules/icons/obj/surgery_table_overlay.dmi',
icon_state = "anesthesia_light_[patient_set_at == -1 ? "off" : "on"]",
alpha = src.alpha,
)

. += emissive_appearance(
icon = 'maplestation_modules/icons/obj/surgery_table_overlay.dmi',
icon_state = "emissive",
offset_spokesman = src,
alpha = src.alpha,
)

/obj/structure/table/optable/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
. = ..()

if(isnull(attached_tank))
if(istype(held_item, /obj/item/tank/internals))
context[SCREENTIP_CONTEXT_LMB] = "Attach tank"
. = CONTEXTUAL_SCREENTIP_SET
else
if(isnull(held_item))
context[SCREENTIP_CONTEXT_RMB] = "Remove tank"
. = CONTEXTUAL_SCREENTIP_SET


/obj/structure/table/optable/deconstruct(disassembled, wrench_disassembly)
attached_tank.forceMove(drop_location())
return ..()

/obj/structure/table/optable/Exited(atom/movable/gone, direction)
. = ..()
if(gone == attached_tank)
disable_anesthesia(patient)
attached_tank = null
if(!QDELING(src))
update_appearance(UPDATE_OVERLAYS)

/obj/structure/table/optable/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/tank/internals))
if(isnull(attached_tank))
if(user.transferItemToLoc(I, src))
attached_tank = I
update_appearance(UPDATE_OVERLAYS)
balloon_alert_to_viewers("tank attached")
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
else
balloon_alert(user, "can't attach tank!")
else
balloon_alert(user, "already has a tank!")
return TRUE

return ..()

/obj/structure/table/optable/attack_hand_secondary(mob/user, list/modifiers)
. = ..()
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return .
if(isnull(attached_tank))
return .

user.put_in_hands(attached_tank)
balloon_alert(user, "tank removed")
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN

/obj/structure/table/optable/recheck_patient(mob/living/carbon/potential_patient)
var/mob/living/carbon/old_patient = patient
. = ..()
update_appearance(UPDATE_OVERLAYS)
if(patient == potential_patient && patient != old_patient)
START_PROCESSING(SSobj, src)
return

STOP_PROCESSING(SSobj, src)
if(old_patient == potential_patient)
disable_anesthesia(old_patient)

/obj/structure/table/optable/process(seconds_per_tick)
if(isnull(patient))
return PROCESS_KILL
if(isnull(attached_tank))
return
if(!can_have_tank_opened(patient))
disable_anesthesia(patient)
return
if(computer?.is_operational && patient_set_at + failsafe_time < world.time)
safety_disable()
return

/// Checks if the passed mob is in a valid state to start breathing out of the attached tank.
/obj/structure/table/optable/proc/can_have_tank_opened(mob/living/carbon/who)
if(!isnull(who.external) && who.external != attached_tank)
return FALSE
if(who.internal)
return FALSE
if(!istype(who.wear_mask) || !(who.wear_mask.clothing_flags & MASKINTERNALS))
return FALSE
if(!who.is_mouth_covered())
return FALSE // Must have an internals mask + mouth covered
return TRUE

/// Called when the safety triggers and attempts to unhook the patient from the tank.
/obj/structure/table/optable/proc/safety_disable()
if(isnull(attached_tank) || patient.external != attached_tank)
return
if(computer?.obj_flags & EMAGGED)
return
disable_anesthesia(patient)
balloon_alert_to_viewers("anesthesia safety activated")
playsound(src, 'sound/machines/cryo_warning.ogg', 50, vary = TRUE, frequency = 0.75)
playsound(src, 'sound/machines/doorclick.ogg', 50, vary = FALSE)

/// Enables the patient to start breathing out of the attached tank.
/obj/structure/table/optable/proc/enable_anesthesia(mob/living/carbon/new_patient)
PRIVATE_PROC(TRUE)
if(isnull(attached_tank) || !can_have_tank_opened(new_patient))
return

new_patient.open_internals(attached_tank, TRUE)
patient_set_at = world.time
update_appearance(UPDATE_OVERLAYS)

/// Disables the patient from breathing out of the attached tank.
/obj/structure/table/optable/proc/disable_anesthesia(mob/living/carbon/old_patient)
PRIVATE_PROC(TRUE)
if(isnull(attached_tank) || old_patient?.external != attached_tank)
return

old_patient.close_externals()
patient_set_at = -1
update_appearance(UPDATE_OVERLAYS)

/// Toggles the tank on and off, playing a sound as well.
/obj/structure/table/optable/proc/toggle_anesthesia()
if(isnull(patient) || isnull(attached_tank))
return

if(patient.external == attached_tank)
disable_anesthesia(patient)
playsound(src, 'sound/machines/doorclick.ogg', 50, vary = FALSE)

else if(isnull(patient.external))
enable_anesthesia(patient)
playsound(src, 'sound/machines/doorclick.ogg', 50, vary = FALSE)
playsound(src, 'sound/machines/hiss.ogg', 25, vary = TRUE, frequency = 1.5)

/obj/machinery/computer/operating

/obj/machinery/computer/operating/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
if(obj_flags & EMAGGED)
return
if(!is_operational)
return

obj_flags |= EMAGGED
balloon_alert(user, "safeties overridden")
playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE, SHORT_RANGE_SOUND_EXTRARANGE)
playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)

/obj/machinery/computer/operating/on_set_is_operational(old_value)
if(is_operational)
return
// Losing power / getting broken will auto disable anesthesia
table.safety_disable()

/obj/machinery/computer/operating/ui_data(mob/user)
var/list/data = ..()
if(isnull(table))
return data

var/tank_exists = !isnull(table.attached_tank)
data["anesthesia"] = list(
"has_tank" = tank_exists,
"open" = tank_exists && table.patient?.external == table.attached_tank,
"can_open_tank" = tank_exists && table.can_have_tank_opened(table.patient),
"failsafe" = table.failsafe_time == INFINITY ? -1 : (table.failsafe_time / 10),
)

if(isnull(table.patient))
return data

var/obj/item/organ/patient_brain = table.patient.get_organ_slot(ORGAN_SLOT_BRAIN)
data["patient"]["brain"] = isnull(patient_brain) ? 100 : ((patient_brain.damage / patient_brain.maxHealth) * 100)
// We can also show pain and stuff here if we want.

return data

/obj/machinery/computer/operating/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(. || isnull(table))
return

switch(action)
if("toggle_anesthesia")
if(iscarbon(usr))
var/mob/living/carbon/toggler = usr
if(toggler == table.patient && table.patient_set_at == -1 && table.failsafe_time >= 5 MINUTES)
to_chat(toggler, span_warning("You feel as if you know better than to do that."))
return FALSE

table.toggle_anesthesia()
return TRUE

if("set_failsafe")
table.failsafe_time = clamp(text2num(params["new_failsafe_time"]) * 10, 5 SECONDS, 10 MINUTES)
return TRUE

if("disable_failsafe")
table.failsafe_time = INFINITY
return TRUE
Binary file not shown.
Loading
Loading