mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-30 00:21:11 +01:00
Operating Tables Refactor (#18340)
* sadf * sdf * adeste fideles * sadf
This commit is contained in:
@@ -570,6 +570,7 @@
|
||||
#include "code\game\area\ai_monitored.dm"
|
||||
#include "code\game\area\area_power.dm"
|
||||
#include "code\game\area\areas.dm"
|
||||
#include "code\game\atom\_atom.dm"
|
||||
#include "code\game\atom\atoms_initializing_EXPENSIVE.dm"
|
||||
#include "code\game\dna\dna2.dm"
|
||||
#include "code\game\dna\dna2_domutcheck.dm"
|
||||
|
||||
@@ -7,3 +7,12 @@
|
||||
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success"
|
||||
//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization and has a loc
|
||||
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON "atom_init_success_on"
|
||||
///from base of atom/Entered(): (atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered"
|
||||
/// Sent from the atom that just Entered src. From base of atom/Entered(): (/atom/destination, atom/old_loc, list/atom/old_locs)
|
||||
#define COMSIG_ATOM_ENTERING "atom_entering"
|
||||
///from base of atom/Exit(): (/atom/movable/leaving, direction)
|
||||
#define COMSIG_ATOM_EXIT "atom_exit"
|
||||
#define COMPONENT_ATOM_BLOCK_EXIT (1<<0)
|
||||
///from base of atom/Exited(): (atom/movable/gone, direction)
|
||||
#define COMSIG_ATOM_EXITED "atom_exited"
|
||||
|
||||
@@ -14,11 +14,3 @@ GLOBAL_DATUM_INIT(entered_event, /singleton/observ/entered, new)
|
||||
/singleton/observ/entered
|
||||
name = "Entered"
|
||||
expected_type = /atom
|
||||
|
||||
/*******************
|
||||
* Entered Handling *
|
||||
*******************/
|
||||
|
||||
/atom/Entered(atom/movable/enterer, atom/old_loc)
|
||||
..()
|
||||
GLOB.entered_event.raise_event(src, enterer, old_loc)
|
||||
|
||||
@@ -14,11 +14,3 @@ GLOBAL_DATUM_INIT(exited_event, /singleton/observ/exited, new)
|
||||
/singleton/observ/exited
|
||||
name = "Exited"
|
||||
expected_type = /atom
|
||||
|
||||
/******************
|
||||
* Exited Handling *
|
||||
******************/
|
||||
|
||||
/atom/Exited(atom/movable/exitee, atom/new_loc)
|
||||
. = ..()
|
||||
GLOB.exited_event.raise_event(src, exitee, new_loc)
|
||||
|
||||
@@ -44,10 +44,6 @@ GLOBAL_DATUM_INIT(moved_event, /singleton/observ/moved, new)
|
||||
/atom/movable/proc/recursive_move(var/atom/movable/am, var/old_loc, var/new_loc)
|
||||
GLOB.moved_event.raise_event(src, old_loc, new_loc)
|
||||
|
||||
/atom/Entered(var/atom/movable/am, atom/old_loc)
|
||||
..()
|
||||
GLOB.moved_event.raise_event(am, old_loc, am.loc)
|
||||
|
||||
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
|
||||
..()
|
||||
if(GLOB.moved_event.has_listeners(am) && !GLOB.moved_event.is_listening(src, am))
|
||||
|
||||
@@ -43,7 +43,11 @@
|
||||
oneoff_light = 0
|
||||
oneoff_environ = 0
|
||||
|
||||
// Don't call this unless you know what you're doing. See use_power_oneoff below.
|
||||
/**
|
||||
* Don't call this unless you know what you're doing
|
||||
*
|
||||
* See use_power_oneoff below
|
||||
*/
|
||||
/area/proc/use_power(var/amount, var/chan)
|
||||
switch(chan)
|
||||
if(EQUIP)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* The base type for nearly all physical objects in SS13
|
||||
|
||||
* Lots and lots of functionality lives here, although in general we are striving to move
|
||||
* as much as possible to the components/elements system
|
||||
*/
|
||||
|
||||
/**
|
||||
* An atom has entered this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_ENTERED]
|
||||
*
|
||||
* Aurora note: old_locs is not populated currently, and will always be null
|
||||
*/
|
||||
/atom/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, arrived, old_loc, old_locs)
|
||||
SEND_SIGNAL(arrived, COMSIG_ATOM_ENTERING, src, old_loc, old_locs)
|
||||
|
||||
//Observables event, Aurora snowflake code
|
||||
GLOB.entered_event.raise_event(src, arrived, old_loc)
|
||||
GLOB.moved_event.raise_event(arrived, old_loc, arrived.loc)
|
||||
|
||||
/**
|
||||
* An atom is attempting to exit this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_EXIT]
|
||||
*/
|
||||
/atom/Exit(atom/movable/leaving, direction)
|
||||
// Don't call `..()` here, otherwise `Uncross()` gets called.
|
||||
// See the doc comment on `Uncross()` to learn why this is bad.
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, leaving, direction) & COMPONENT_ATOM_BLOCK_EXIT)
|
||||
return FALSE
|
||||
|
||||
//Observables event, Aurora snowflake code
|
||||
GLOB.exited_event.raise_event(src, leaving, get_step_towards(src, direction))
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* An atom has exited this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_EXITED]
|
||||
*/
|
||||
/atom/Exited(atom/movable/gone, direction)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, gone, direction)
|
||||
+217
-106
@@ -4,7 +4,6 @@
|
||||
desc_info = "Click your target with Grab intent, then click on the table with an empty hand, to place them on it."
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "table2-idle"
|
||||
var/modify_state = "table2"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
use_power = POWER_USE_IDLE
|
||||
@@ -15,39 +14,110 @@
|
||||
/obj/item/stock_parts/scanning_module = 1
|
||||
)
|
||||
|
||||
var/mob/living/carbon/human/occupant = null
|
||||
///The base icon state that will be modified
|
||||
var/modify_state = "table2"
|
||||
|
||||
///The person occupying the table, a weakref to a `/mob/living/carbon/human`
|
||||
var/datum/weakref/occupant = null
|
||||
|
||||
///If the table is currently suppressing, aka active
|
||||
var/suppressing = FALSE
|
||||
|
||||
///The connected surgery computer
|
||||
var/obj/machinery/computer/operating/computer = null
|
||||
|
||||
var/list/allowed_species = list(
|
||||
SPECIES_HUMAN,
|
||||
SPECIES_HUMAN_OFFWORLD,
|
||||
SPECIES_SKRELL,
|
||||
SPECIES_SKRELL_AXIORI,
|
||||
SPECIES_UNATHI,
|
||||
SPECIES_TAJARA,
|
||||
SPECIES_TAJARA_MSAI,
|
||||
SPECIES_TAJARA_ZHAN,
|
||||
SPECIES_VAURCA_WORKER,
|
||||
SPECIES_VAURCA_WARRIOR,
|
||||
SPECIES_VAURCA_BREEDER,
|
||||
SPECIES_VAURCA_BULWARK,
|
||||
SPECIES_DIONA,
|
||||
SPECIES_DIONA_COEUS,
|
||||
SPECIES_MONKEY
|
||||
)
|
||||
|
||||
/obj/machinery/optable/Initialize()
|
||||
. = ..()
|
||||
..()
|
||||
|
||||
LAZYADD(can_buckle, /mob/living)
|
||||
buckle_delay = 30
|
||||
for(dir in GLOB.cardinal)
|
||||
computer = locate(/obj/machinery/computer/operating, get_step(src, dir))
|
||||
if(computer)
|
||||
computer.table = src
|
||||
|
||||
RegisterSignal(loc, COMSIG_ATOM_ENTERED, PROC_REF(mark_patient))
|
||||
RegisterSignal(loc, COMSIG_ATOM_EXITED, PROC_REF(unmark_patient))
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/optable/LateInitialize()
|
||||
. = ..()
|
||||
|
||||
//Search for an operating computer and ask it to hook us up
|
||||
for(var/obj/machinery/computer/operating/candidate_computer in orange(src, 1))
|
||||
if(candidate_computer.hook_table(src))
|
||||
break
|
||||
|
||||
/obj/machinery/optable/Destroy()
|
||||
STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF)
|
||||
UnregisterSignal(loc, COMSIG_ATOM_ENTERED)
|
||||
UnregisterSignal(loc, COMSIG_ATOM_EXITED)
|
||||
|
||||
//If we have a computer, ask it to unhook us, clear the reference anyways just to be sure
|
||||
if(computer)
|
||||
computer.unhook_table(src)
|
||||
computer = null
|
||||
|
||||
//If there's an occupant, ensure to release the view before dropping the weakref
|
||||
var/occupant_resolved = occupant?.resolve()
|
||||
if(occupant_resolved)
|
||||
release_view(occupant_resolved)
|
||||
occupant = null
|
||||
|
||||
. = ..()
|
||||
|
||||
/// Any mob that enters our tile will awaken our processing as it's a potential patient
|
||||
/obj/machinery/optable/proc/mark_patient(datum/source, mob/living/carbon/potential_patient)
|
||||
SIGNAL_HANDLER
|
||||
if(!istype(potential_patient))
|
||||
return
|
||||
START_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF)
|
||||
refresh_icon_state()
|
||||
|
||||
/// Unmark the potential patient
|
||||
/obj/machinery/optable/proc/unmark_patient(datum/source, mob/living/carbon/potential_patient)
|
||||
SIGNAL_HANDLER
|
||||
if(!istype(potential_patient))
|
||||
return
|
||||
|
||||
//Stop processing only if it's not the occupant, or the occupant doesn't exist
|
||||
var/occupant_resolved = occupant?.resolve()
|
||||
if(isnull(occupant_resolved) || potential_patient == occupant_resolved)
|
||||
STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF)
|
||||
|
||||
//If it was the occupant, clear the var and give him back the view, and turn off the suppressor
|
||||
if(potential_patient == occupant_resolved)
|
||||
suppressing = FALSE
|
||||
occupant = null //Null the weakref
|
||||
release_view(potential_patient)
|
||||
|
||||
//Reprocess the icon state at the end
|
||||
refresh_icon_state()
|
||||
|
||||
/obj/machinery/optable/process(seconds_per_tick)
|
||||
//We just call the check_occupant for all the processing
|
||||
check_occupant(seconds_per_tick)
|
||||
|
||||
/**
|
||||
* Acquires the view of the patient so that it's locked on the table, instead of eg. remote viewing a camera
|
||||
*/
|
||||
/obj/machinery/optable/proc/acquire_view(mob/living/carbon/patient)
|
||||
//No point if there's no client
|
||||
if(!patient.client)
|
||||
return
|
||||
|
||||
//Perspective according to the eye
|
||||
patient.client.perspective = EYE_PERSPECTIVE
|
||||
patient.client.eye = src
|
||||
|
||||
/**
|
||||
* Releases the view of the patient back to the mob
|
||||
*/
|
||||
/obj/machinery/optable/proc/release_view(mob/living/carbon/patient)
|
||||
//No point if there's no client
|
||||
if(!patient.client)
|
||||
return
|
||||
|
||||
patient.reset_view(null)
|
||||
|
||||
/obj/machinery/optable/examine(var/mob/user)
|
||||
. = ..()
|
||||
to_chat(user, SPAN_NOTICE("The neural suppressors are switched [suppressing ? "on" : "off"]."))
|
||||
@@ -73,18 +143,19 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(!occupant)
|
||||
var/mob/living/carbon/human/occupant_resolved = occupant?.resolve()
|
||||
if(!occupant_resolved)
|
||||
to_chat(user, SPAN_WARNING("There is nobody on \the [src]. It would be pointless to turn the suppressor on."))
|
||||
return TRUE
|
||||
|
||||
if((user.a_intent != I_HELP) && buckled)
|
||||
user_unbuckle(user)
|
||||
return
|
||||
if(user != occupant && !use_check_and_message(user)) // Skip checks if you're doing it to yourself or turning it off, this is an anti-griefing mechanic more than anything.
|
||||
if(user != occupant_resolved && !use_check_and_message(user)) // Skip checks if you're doing it to yourself or turning it off, this is an anti-griefing mechanic more than anything.
|
||||
user.visible_message(SPAN_WARNING("\The [user] begins switching [suppressing ? "off" : "on"] \the [src]'s neural suppressor."))
|
||||
if(!do_after(user, 3 SECONDS, src, DO_UNIQUE))
|
||||
return
|
||||
if(!occupant)
|
||||
if(!occupant_resolved)
|
||||
to_chat(user, SPAN_WARNING("There is nobody on \the [src]. It would be pointless to turn the suppressor on."))
|
||||
|
||||
suppressing = !suppressing
|
||||
@@ -102,87 +173,145 @@
|
||||
user.drop_from_inventory(O,get_turf(src))
|
||||
..()
|
||||
|
||||
/obj/machinery/optable/proc/check_occupant()
|
||||
if(!occupant || !occupant.lying || occupant.loc != loc)
|
||||
suppressing = FALSE
|
||||
occupant = null
|
||||
var/mob/living/carbon/human/H = locate() in loc
|
||||
if(istype(H))
|
||||
if(H.lying)
|
||||
icon_state = H.pulse() ? "[modify_state]-active" : "[modify_state]-idle"
|
||||
occupant = H
|
||||
if(occupant && !occupant.isSynthetic())
|
||||
if(suppressing && occupant.sleeping < 7)
|
||||
occupant.Sleeping(7 - occupant.sleeping)
|
||||
occupant.willfully_sleeping = FALSE
|
||||
if(occupant.eye_blurry < 7)
|
||||
occupant.eye_blurry = (7 - occupant.eye_blurry)
|
||||
icon_state = occupant.pulse() ? "[modify_state]-active" : "[modify_state]-idle"
|
||||
if(occupant.stat == DEAD || occupant.is_asystole() || occupant.status_flags & FAKEDEATH)
|
||||
icon_state = "[modify_state]-critical"
|
||||
return TRUE
|
||||
icon_state = "[modify_state]-idle"
|
||||
return FALSE
|
||||
/**
|
||||
* Refreshes the icon state based on the table status
|
||||
*/
|
||||
/obj/machinery/optable/proc/refresh_icon_state()
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
/obj/machinery/optable/process()
|
||||
check_occupant()
|
||||
var/mob/living/carbon/human/human_occupant = occupant?.resolve()
|
||||
|
||||
/obj/machinery/optable/proc/take_occupant(mob/living/carbon/C, mob/living/carbon/user)
|
||||
if(C == user)
|
||||
user.visible_message("\The [user] climbs on \the [src].", "You climb on \the [src].")
|
||||
else
|
||||
visible_message(SPAN_NOTICE("\The [C] has been laid on \the [src] by \the [user]."))
|
||||
if(C.client)
|
||||
C.client.perspective = EYE_PERSPECTIVE
|
||||
C.client.eye = src
|
||||
C.resting = TRUE
|
||||
C.forceMove(loc)
|
||||
add_fingerprint(user)
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
occupant = H
|
||||
icon_state = H.pulse() ? "[modify_state]-active" : "[modify_state]-idle"
|
||||
if(H.stat == DEAD || H.is_asystole() || H.status_flags & FAKEDEATH)
|
||||
if(istype(human_occupant) && human_occupant.lying && !(human_occupant.isSynthetic()))
|
||||
//If there's a bad condition, set the critical table icon
|
||||
if(human_occupant.stat == DEAD || human_occupant.is_asystole() || (human_occupant.status_flags & FAKEDEATH) || !human_occupant.pulse())
|
||||
icon_state = "[modify_state]-critical"
|
||||
//Otherwise, as far as we can tell, the patient is alive; set the active table icon
|
||||
else
|
||||
icon_state = "[modify_state]-active"
|
||||
|
||||
//Noone on the table or a synthetic, idle status
|
||||
else
|
||||
icon_state = "[modify_state]-idle"
|
||||
|
||||
/obj/machinery/optable/MouseDrop_T(mob/target, mob/user)
|
||||
var/mob/living/M = user
|
||||
if(user.stat || user.restrained() || !iscarbon(target))
|
||||
|
||||
/obj/machinery/optable/proc/check_occupant(seconds_per_tick)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
refresh_icon_state()
|
||||
var/mob/living/carbon/human/occupant_resolved = occupant?.resolve()
|
||||
|
||||
//If the occupant is not set
|
||||
if(!occupant_resolved)
|
||||
//Reset suppression
|
||||
suppressing = FALSE
|
||||
|
||||
//Try to find a patient, if you have one, set it as occupant
|
||||
//does not mean it's suppressed, just that it's occupying the table
|
||||
var/mob/living/carbon/human/new_occupant = locate() in loc
|
||||
if(istype(new_occupant))
|
||||
if(new_occupant.lying)
|
||||
//Set the occupant weakref and get his view
|
||||
occupant = WEAKREF(new_occupant)
|
||||
acquire_view(new_occupant)
|
||||
|
||||
//We have a patient, and it's not synthetic
|
||||
else if(!occupant_resolved.isSynthetic())
|
||||
//If the table is on and suppressing
|
||||
if(suppressing)
|
||||
if(stat & NOPOWER)
|
||||
return FALSE
|
||||
|
||||
src.use_power_oneoff(2 KILOWATTS)
|
||||
|
||||
//Set it to unwillful sleep
|
||||
occupant_resolved.Sleeping(3.5*seconds_per_tick)
|
||||
occupant_resolved.willfully_sleeping = FALSE
|
||||
|
||||
//Blur the vision
|
||||
occupant_resolved.eye_blurry = max((3.5*seconds_per_tick), occupant_resolved.eye_blurry)
|
||||
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* To handle the 30 snowflake ways to get a mob on the table
|
||||
*
|
||||
* * patient - The (will be) occupant
|
||||
* * giver - The person that is occupant the `patient` on the table
|
||||
*
|
||||
* Returns `TRUE` if the patient was taken, `FALSE` otherwise
|
||||
*/
|
||||
/obj/machinery/optable/proc/take_occupant(mob/living/carbon/patient, mob/living/carbon/giver)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
//No point if there's no patient
|
||||
if(!istype(patient))
|
||||
return FALSE
|
||||
|
||||
//Someone is already on the table
|
||||
var/mob/living/carbon/human/occupant_resolved = occupant?.resolve()
|
||||
if(occupant_resolved)
|
||||
return FALSE
|
||||
|
||||
if(patient == giver) //Putting yourself on the table
|
||||
giver.visible_message("\The [giver] climbs on \the [src].", "You climb on \the [src].")
|
||||
else //Putting someone else on the table, or noone
|
||||
visible_message(SPAN_NOTICE("\The [patient] has been laid on \the [src] by \the [giver]."))
|
||||
|
||||
//Add the fingerprints and fibers of both the giver and the patient
|
||||
add_fingerprint(giver)
|
||||
add_fibers(giver)
|
||||
add_fingerprint(patient)
|
||||
add_fibers(patient)
|
||||
|
||||
patient.resting = TRUE
|
||||
patient.forceMove(loc)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/optable/MouseDrop_T(atom/dropping, mob/user)
|
||||
var/mob/living/carbon/patient = dropping
|
||||
//No point if it's not a possible patient
|
||||
if(!istype(patient))
|
||||
return
|
||||
if(istype(M) && (get_turf(target) != get_turf(src)))
|
||||
var/mob/living/L = target
|
||||
var/bucklestatus = L.bucklecheck(user)
|
||||
|
||||
//If the user is not able, stop
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
|
||||
//It's already occupied, spessbro
|
||||
var/mob/living/carbon/human/occupant_resolved = occupant?.resolve()
|
||||
if(occupant_resolved)
|
||||
to_chat(usr, SPAN_NOTICE(SPAN_BOLD("\The [src] is already occupied!")))
|
||||
return
|
||||
|
||||
if((get_turf(patient) != get_turf(src)))
|
||||
var/bucklestatus = patient.bucklecheck(user)
|
||||
if(!bucklestatus)
|
||||
return
|
||||
|
||||
if(L == user)
|
||||
if(patient == user)
|
||||
user.visible_message(SPAN_NOTICE("\The [user] starts climbing onto \the [src]."), SPAN_NOTICE("You start climbing onto \the [src]."), range = 3)
|
||||
else
|
||||
user.visible_message(SPAN_NOTICE("\The [user] starts putting [L] onto \the [src]."), SPAN_NOTICE("You start putting \the [L] onto \the [src]."), range = 3)
|
||||
if(do_mob(user, L, 10, needhand = FALSE))
|
||||
user.visible_message(SPAN_NOTICE("\The [user] starts putting \the [patient] onto \the [src]."), SPAN_NOTICE("You start putting \the [patient] onto \the [src]."), range = 3)
|
||||
|
||||
//Move the patient on the table after a short delay and buckle him
|
||||
if(do_mob(user, patient, 1 SECOND, needhand = FALSE))
|
||||
//If he's already buckled to something, unbuckle him first
|
||||
if(bucklestatus == 2)
|
||||
var/obj/structure/LB = L.buckled_to
|
||||
var/obj/structure/LB = patient.buckled_to
|
||||
LB.user_unbuckle(user)
|
||||
take_occupant(target,user)
|
||||
take_occupant(patient, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/optable/verb/climb_on()
|
||||
set name = "Climb On Table"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(usr.stat || !ishuman(usr) || usr.restrained() )
|
||||
return
|
||||
|
||||
take_occupant(usr,usr)
|
||||
|
||||
/obj/machinery/optable/attackby(obj/item/W, mob/living/carbon/user)
|
||||
if(istype(W, /obj/item/grab))
|
||||
var/obj/item/grab/G = W
|
||||
if(occupant)
|
||||
|
||||
var/mob/living/carbon/human/occupant_resolved = occupant?.resolve()
|
||||
if(occupant_resolved)
|
||||
to_chat(usr, SPAN_NOTICE(SPAN_BOLD("\The [src] is already occupied!")))
|
||||
return TRUE
|
||||
|
||||
@@ -205,21 +334,3 @@
|
||||
return TRUE
|
||||
if(default_part_replacement(user, W))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/optable/proc/check_table(mob/living/carbon/patient)
|
||||
check_occupant()
|
||||
if(occupant?.lying && get_turf(occupant) == get_turf(src))
|
||||
to_chat(usr, SPAN_WARNING("\The [src] is already occupied!"))
|
||||
return FALSE
|
||||
if(patient.buckled_to)
|
||||
to_chat(usr, SPAN_NOTICE("Unbuckle \the [patient] first!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/optable/proc/check_species()
|
||||
if (!occupant || !ishuman(occupant))
|
||||
return TRUE
|
||||
var/mob/living/carbon/human/O = occupant
|
||||
if (!O)
|
||||
return TRUE
|
||||
return !(O.get_species() in allowed_species)
|
||||
|
||||
@@ -886,7 +886,12 @@
|
||||
|
||||
/obj/machinery/body_scanconsole/embedded/get_occupant()
|
||||
if(monitor_console?.table)
|
||||
return monitor_console.table.occupant
|
||||
|
||||
if(istype(monitor_console.table.occupant, /datum/weakref))
|
||||
return monitor_console.table.occupant.resolve()
|
||||
else
|
||||
return monitor_console.table.occupant
|
||||
|
||||
return null
|
||||
|
||||
// if our primer has a scan target, that means it was validated by a bodyscanner
|
||||
|
||||
@@ -10,24 +10,79 @@
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
circuit = /obj/item/circuitboard/operating
|
||||
|
||||
///The operating table we are hooked into
|
||||
var/obj/machinery/optable/table
|
||||
|
||||
///The paper with the scan of the patient
|
||||
var/obj/item/paper/medscan/primer
|
||||
|
||||
var/obj/machinery/body_scanconsole/embedded/embedded_scanner
|
||||
|
||||
/obj/machinery/computer/operating/Initialize()
|
||||
. = ..()
|
||||
..()
|
||||
|
||||
embedded_scanner = new /obj/machinery/body_scanconsole/embedded(src, 0, TRUE, TRUE)
|
||||
for(var/obj/machinery/optable/T in orange(1,src))
|
||||
table = T
|
||||
if (table)
|
||||
table.computer = src
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/operating/LateInitialize()
|
||||
. = ..()
|
||||
|
||||
for(var/obj/machinery/optable/T in orange(1, src))
|
||||
var/successfully_hooked = hook_table(T)
|
||||
if(successfully_hooked)
|
||||
break
|
||||
|
||||
/obj/machinery/computer/operating/Destroy()
|
||||
QDEL_NULL(embedded_scanner)
|
||||
QDEL_NULL(primer)
|
||||
|
||||
//Clear the operating table
|
||||
if(table)
|
||||
unhook_table(table)
|
||||
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* Used to connect (hook) the computer to the operating table
|
||||
*
|
||||
* Returns `TRUE` on successful hook, `FALSE` otherwise
|
||||
*
|
||||
* * table_to_hook - An `/obj/machinery/optable` to hook to
|
||||
*/
|
||||
/obj/machinery/computer/operating/proc/hook_table(obj/machinery/optable/table_to_hook)
|
||||
if(table)
|
||||
return FALSE
|
||||
|
||||
if(QDELETED(table_to_hook))
|
||||
crash_with("Trying to hook a QDELETED optable!")
|
||||
return FALSE
|
||||
|
||||
if(!istype(table_to_hook))
|
||||
crash_with("Trying to hook a table that is not of the correct type!")
|
||||
return FALSE
|
||||
|
||||
table = table_to_hook
|
||||
table.computer = src
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Used to disconnect (unhook) the computer to the operating table
|
||||
*
|
||||
* Returns `TRUE` on successful unhook, `FALSE` otherwise
|
||||
*
|
||||
* * table_to_unhook - An `/obj/machinery/optable` to hook to
|
||||
*/
|
||||
/obj/machinery/computer/operating/proc/unhook_table(obj/machinery/optable/table_to_unhook)
|
||||
if(table_to_unhook != table)
|
||||
crash_with("Trying to unhook a table that is not hooked!")
|
||||
return FALSE
|
||||
|
||||
table.computer = null
|
||||
table = null
|
||||
return ..()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/item, mob/user)
|
||||
if(istype(item, /obj/item/paper/medscan))
|
||||
|
||||
@@ -115,7 +115,10 @@ Class Procs:
|
||||
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
|
||||
var/printing = 0 // Is this machine currently printing anything?
|
||||
var/list/processing_parts // Component parts queued for processing by the machine. Expected type: `/obj/item/stock_parts` Unused currently
|
||||
var/processing_flags // Bitflag. What is being processed. One of `MACHINERY_PROCESS_*`.
|
||||
|
||||
/// Bitflag. What is being processed. One of `MACHINERY_PROCESS_*`.
|
||||
var/processing_flags
|
||||
|
||||
var/clicksound //played sound on usage
|
||||
var/clickvol = 40 //volume
|
||||
var/obj/item/device/assembly/signaler/signaler // signaller attached to the machine
|
||||
|
||||
@@ -395,18 +395,51 @@
|
||||
Weaken(FLOOR(stun_duration/2))
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Adds an amount of a chemical effect to the mob
|
||||
*
|
||||
* * effect - A string indicative of the effect, as per `CE_*` defines in `code\__DEFINES\chemistry.dm`
|
||||
* * magnitude - The magnitude/quantity/amount of the effect to add
|
||||
*/
|
||||
/mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
if(effect in chem_effects)
|
||||
chem_effects[effect] += magnitude
|
||||
else
|
||||
chem_effects[effect] = magnitude
|
||||
|
||||
/**
|
||||
* Adds _up to_ an amount of a chemical effect to the mob
|
||||
*
|
||||
* Makes a chemical effect have _at least_ the specified `magnitude`
|
||||
*
|
||||
* * effect - A string indicative of the effect, as per `CE_*` defines in `code\__DEFINES\chemistry.dm`
|
||||
* * magnitude - The magnitude/quantity/amount of the effect to reach, if lacking
|
||||
*/
|
||||
/mob/living/carbon/proc/add_up_to_chemical_effect(var/effect, var/magnitude = 1)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
if(effect in chem_effects)
|
||||
chem_effects[effect] = max(magnitude, chem_effects[effect])
|
||||
else
|
||||
chem_effects[effect] = magnitude
|
||||
|
||||
/**
|
||||
* Removes an amount of a chemical effect from the mob
|
||||
*
|
||||
* Prevents the magnitude to go negative
|
||||
*
|
||||
* * effect - A string indicative of the effect, as per `CE_*` defines in `code\__DEFINES\chemistry.dm`
|
||||
* * magnitude - The magnitude/quantity/amount of the effect to remove
|
||||
*/
|
||||
/mob/living/carbon/proc/remove_chemical_effect(var/effect, var/magnitude = 1)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
if(effect in chem_effects)
|
||||
chem_effects[effect] -= max(magnitude, chem_effects[effect])
|
||||
|
||||
|
||||
/mob/living/carbon/get_default_language()
|
||||
if(default_language)
|
||||
return default_language
|
||||
|
||||
@@ -55,7 +55,14 @@ This is /obj/machinery level code to properly manage power usage from the area.
|
||||
else
|
||||
return 0
|
||||
|
||||
// This will have this machine have its area eat this much power next tick, and not afterwards. Do not use for continued power draw.
|
||||
/**
|
||||
* This will have this machine have its area eat this much power next tick, and not afterwards
|
||||
*
|
||||
* Do not use for continued power draw.
|
||||
*
|
||||
* * amount - The amount of power to consume
|
||||
* * chan - The channel to consume it from, see `code\__DEFINES\machinery.dm`
|
||||
*/
|
||||
/obj/machinery/proc/use_power_oneoff(var/amount, var/chan = POWER_CHAN)
|
||||
var/area/A = get_area(src) // make sure it's in an area
|
||||
if(!A)
|
||||
|
||||
@@ -43,9 +43,6 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE)
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/soil/invisible,
|
||||
|
||||
// Requires an operating table
|
||||
/obj/machinery/computer/operating,
|
||||
|
||||
// Requires to pick an output at init
|
||||
/obj/machinery/appliance/mixer/,
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
################################
|
||||
# Example Changelog File
|
||||
#
|
||||
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
|
||||
#
|
||||
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
|
||||
# When it is, any changes listed below will disappear.
|
||||
#
|
||||
# Valid Prefixes:
|
||||
# bugfix
|
||||
# wip (For works in progress)
|
||||
# tweak
|
||||
# soundadd
|
||||
# sounddel
|
||||
# rscadd (general adding of nice things)
|
||||
# rscdel (general deleting of nice things)
|
||||
# imageadd
|
||||
# imagedel
|
||||
# maptweak
|
||||
# spellcheck (typo fixes)
|
||||
# experiment
|
||||
# balance
|
||||
# admin
|
||||
# backend
|
||||
# security
|
||||
# refactor
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: FluffyGhost
|
||||
|
||||
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
|
||||
delete-after: True
|
||||
|
||||
# Any changes you've made. See valid prefix list above.
|
||||
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
|
||||
# SCREW THIS UP AND IT WON'T WORK.
|
||||
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- backend: "Implemented COMSIG_ATOM_ENTERED, COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED and COMSIG_ATOM_EXITING."
|
||||
- backend: "Unified atom's Entered, Entering and Exited in a single proc."
|
||||
- backend: "Added remove_chemical_effect proc to remove chemical effect quantities (currently unused)."
|
||||
- backend: "DMDocs, some SDMM proc markings."
|
||||
- refactor: "Refactored optable beds."
|
||||
- rscadd: "Optable beds now use power to suppress the patient's brain."
|
||||
- bugfix: "The camera getting stuck on optable beds should now be fixed."
|
||||
- refactor: "Refactored operating computer in how it connects and disconnects with the surgery table."
|
||||
- backend: "Adjusted integrated bodyscanner to account for tables using weakrefs on patients."
|
||||
- rscadd: "It should now be possible to reliably build operating tables and consoles and have them hook with each other."
|
||||
- backend: "Operating tables and operating computers should now delete cleanly."
|
||||
Reference in New Issue
Block a user