Adds stasis beds

This commit is contained in:
Artur
2022-04-06 15:38:05 +03:00
parent 4c3fa08cdf
commit c36019bf56
15 changed files with 257 additions and 20 deletions

View File

@@ -1120,9 +1120,7 @@
/obj/structure/window{
dir = 8
},
/obj/machinery/sleeper{
dir = 1
},
/obj/machinery/stasis,
/turf/open/floor/holofloor{
icon_state = "white"
},
@@ -1134,9 +1132,7 @@
},
/area/holodeck/rec_center/medical)
"dd" = (
/obj/machinery/sleeper{
dir = 1
},
/obj/machinery/stasis,
/turf/open/floor/holofloor{
icon_state = "white"
},

View File

@@ -153,3 +153,6 @@
/////////////
#define STASIS_ASCENSION_EFFECT "heretic_ascension"
/// If the incapacitated status effect will ignore a mob in stasis (stasis beds)
#define IGNORE_STASIS (1<<1)

View File

@@ -70,6 +70,10 @@
#define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE)
//mob traits
/// Prevents voluntary movement.
#define TRAIT_IMMOBILIZED "immobilized"
/// Prevents usage of manipulation appendages (picking, holding or using items, manipulating storage).
#define TRAIT_HANDS_BLOCKED "handsblocked"
#define TRAIT_BLIND "blind"
#define TRAIT_MUTE "mute"
#define TRAIT_EMOTEMUTE "emotemute"

View File

@@ -484,3 +484,5 @@ GLOBAL_LIST_EMPTY(species_datums)
//check if the person is dead, not sure where to put this
#define IS_DEAD_OR_INCAP(source) (source.incapacitated() || source.stat)
#define IS_IN_STASIS(mob) (mob.has_status_effect(/datum/status_effect/grouped/stasis))

View File

@@ -75,10 +75,8 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
/proc/daysSince(realtimev)
return round((world.realtime - realtimev) / (24 HOURS))
/proc/worldtime2text()
return gameTimestamp("hh:mm:ss", world.time)
/proc/worldtime2text(wtime = world.timeofday)
return gameTimestamp("hh:mm:ss", wtime)
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
if(!wtime)
wtime = world.time
/proc/gameTimestamp(format = "hh:mm:ss", wtime=world.time)
return time2text(wtime - GLOB.timezoneOffset, format)

View File

@@ -107,7 +107,7 @@ SUBSYSTEM_DEF(traumas)
/obj/item/clothing/under/rank/medical/doctor/nurse, /obj/item/clothing/under/rank/medical/chief_medical_officer,
/obj/item/reagent_containers/syringe, /obj/item/reagent_containers/pill/, /obj/item/reagent_containers/hypospray,
/obj/item/storage/firstaid, /obj/item/storage/pill_bottle, /obj/item/healthanalyzer,
/obj/structure/sign/departments/medbay, /obj/machinery/door/airlock/medical, /obj/machinery/sleeper,
/obj/structure/sign/departments/medbay, /obj/machinery/door/airlock/medical, /obj/machinery/sleeper, /obj/machinery/stasis,
/obj/machinery/dna_scannernew, /obj/machinery/atmospherics/components/unary/cryo_cell, /obj/item/surgical_drapes,
/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw,
/obj/item/clothing/suit/bio_suit/plaguedoctorsuit, /obj/item/clothing/head/plaguedoctorhat, /obj/item/clothing/mask/gas/plaguedoctor)),

View File

@@ -7,10 +7,12 @@ SUBSYSTEM_DEF(vis_overlays)
var/list/vis_overlay_cache
var/list/unique_vis_overlays
var/list/currentrun
var/datum/callback/rotate_cb
/datum/controller/subsystem/vis_overlays/Initialize()
vis_overlay_cache = list()
unique_vis_overlays = list()
rotate_cb = CALLBACK(src, .proc/rotate_vis_overlay)
return ..()
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
@@ -55,6 +57,7 @@ SUBSYSTEM_DEF(vis_overlays)
if(!thing.managed_vis_overlays)
thing.managed_vis_overlays = list(overlay)
RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, rotate_cb)
else
thing.managed_vis_overlays += overlay
return overlay
@@ -78,3 +81,18 @@ SUBSYSTEM_DEF(vis_overlays)
thing.managed_vis_overlays -= overlays
if(!length(thing.managed_vis_overlays))
thing.managed_vis_overlays = null
UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE)
/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir)
if(old_dir == new_dir)
return
var/rotation = dir2angle(old_dir) - dir2angle(new_dir)
var/list/overlays_to_remove = list()
for(var/i in thing.managed_vis_overlays - unique_vis_overlays)
var/obj/effect/overlay/vis/overlay = i
add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags)
overlays_to_remove += overlay
for(var/i in thing.managed_vis_overlays & unique_vis_overlays)
var/obj/effect/overlay/vis/overlay = i
overlay.dir = turn(overlay.dir, rotation)
remove_vis_overlay(thing, overlays_to_remove)

View File

@@ -127,13 +127,61 @@
desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are."
icon_state = "asleep"
/datum/status_effect/grouped/stasis
id = "stasis"
duration = -1
tick_interval = 10
alert_type = /atom/movable/screen/alert/status_effect/stasis
var/last_dead_time
/datum/status_effect/grouped/stasis/proc/update_time_of_death()
if(last_dead_time)
var/delta = world.time - last_dead_time
var/new_timeofdeath = owner.timeofdeath + delta
owner.timeofdeath = new_timeofdeath
owner.tod = gameTimestamp(wtime=new_timeofdeath)
last_dead_time = null
if(owner.stat == DEAD)
last_dead_time = world.time
/datum/status_effect/grouped/stasis/on_creation(mob/living/new_owner, set_duration)
. = ..()
if(.)
update_time_of_death()
owner.reagents?.end_metabolization(owner, FALSE)
/datum/status_effect/grouped/stasis/on_apply()
. = ..()
if(!.)
return
owner.mobility_flags &= ~MOBILITY_USE
owner.mobility_flags &= ~MOBILITY_PICKUP
owner.mobility_flags &= ~MOBILITY_PULL
owner.mobility_flags &= ~MOBILITY_HOLD
owner.update_mobility()
owner.add_filter("stasis_status_ripple", 2, list("type" = "ripple", "flags" = WAVE_BOUNDED, "radius" = 0, "size" = 2))
var/filter = owner.get_filter("stasis_status_ripple")
animate(filter, radius = 32, time = 15, size = 0, loop = -1)
/datum/status_effect/grouped/stasis/tick()
update_time_of_death()
/datum/status_effect/grouped/stasis/on_remove()
owner.mobility_flags |= MOBILITY_USE
owner.mobility_flags |= MOBILITY_PICKUP
owner.mobility_flags |= MOBILITY_PULL
owner.mobility_flags |= MOBILITY_HOLD
owner.update_mobility()
owner.remove_filter("stasis_status_ripple")
update_time_of_death()
return ..()
/atom/movable/screen/alert/status_effect/stasis
name = "Stasis"
desc = "Your biological functions have halted. You could live forever this way, but it's pretty boring."
icon_state = "stasis"
/datum/status_effect/robotic_emp
id = "emp_no_combat_mode"

View File

@@ -0,0 +1,141 @@
#define STASIS_TOGGLE_COOLDOWN 50
/obj/machinery/stasis
name = "Lifeform Stasis Unit"
desc = "A not so comfortable looking bed with some nozzles at the top and bottom. It will keep someone in stasis."
icon = 'icons/obj/machines/stasis.dmi'
icon_state = "stasis"
density = FALSE
can_buckle = TRUE
buckle_lying = 90
circuit = /obj/item/circuitboard/machine/stasis
idle_power_usage = 40
active_power_usage = 340
fair_market_price = 10
payment_department = ACCOUNT_MED
var/stasis_enabled = TRUE
var/last_stasis_sound = FALSE
var/stasis_can_toggle = 0
var/mattress_state = "stasis_on"
var/obj/effect/overlay/vis/mattress_on
/obj/machinery/stasis/examine(mob/user)
..()
var/turn_on_or_off = stasis_enabled ? "turn off" : "turn on"
to_chat(user, "<span class='notice'>Alt-click to [turn_on_or_off] the machine.</span>")
/obj/machinery/stasis/proc/play_power_sound()
var/_running = stasis_running()
if(last_stasis_sound != _running)
var/sound_freq = rand(5120, 8800)
if(_running)
playsound(src, 'sound/machines/synth_yes.ogg', 50, TRUE, frequency = sound_freq)
else
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, frequency = sound_freq)
last_stasis_sound = _running
/obj/machinery/stasis/AltClick(mob/user)
if(world.time >= stasis_can_toggle && user.canUseTopic(src))
stasis_enabled = !stasis_enabled
stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN
playsound(src, 'sound/machines/click.ogg', 60, TRUE)
play_power_sound()
update_icon()
/obj/machinery/stasis/Exited(atom/movable/AM, atom/newloc)
if(AM == occupant)
var/mob/living/L = AM
if(L.IsInStasis())
thaw_them(L)
. = ..()
/obj/machinery/stasis/proc/stasis_running()
return stasis_enabled && is_operational()
/obj/machinery/stasis/update_icon()
. = ..()
var/_running = stasis_running()
var/list/overlays_to_remove = managed_vis_overlays
if(mattress_state)
if(!mattress_on || !managed_vis_overlays)
mattress_on = SSvis_overlays.add_vis_overlay(src, icon, mattress_state, layer, plane, dir, alpha = 0, unique = TRUE)
if(mattress_on.alpha ? !_running : _running) //check the inverse of _running compared to truthy alpha, to see if they differ
var/new_alpha = _running ? 255 : 0
var/easing_direction = _running ? EASE_OUT : EASE_IN
animate(mattress_on, alpha = new_alpha, time = 50, easing = CUBIC_EASING|easing_direction)
overlays_to_remove = managed_vis_overlays - mattress_on
SSvis_overlays.remove_vis_overlay(src, overlays_to_remove)
if(occupant)
SSvis_overlays.add_vis_overlay(src, 'icons/obj/machines/stasis.dmi', "tubes", LYING_MOB_LAYER + 0.1, plane, dir) //using vis_overlays instead of normal overlays for mouse_opacity here
if(stat & BROKEN)
icon_state = "stasis_broken"
return
if(panel_open || stat & MAINT)
icon_state = "stasis_maintenance"
return
icon_state = "stasis"
/obj/machinery/stasis/obj_break(damage_flag)
. = ..()
play_power_sound()
update_icon()
/obj/machinery/stasis/power_change()
. = ..()
play_power_sound()
update_icon()
/obj/machinery/stasis/proc/chill_out(mob/living/target)
if(target != occupant)
return
var/freq = rand(24750, 26550)
playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 2, frequency = freq)
target.SetStasis(TRUE)
target.ExtinguishMob()
use_power = ACTIVE_POWER_USE
/obj/machinery/stasis/proc/thaw_them(mob/living/target)
target.SetStasis(FALSE)
if(target == occupant)
use_power = IDLE_POWER_USE
/obj/machinery/stasis/post_buckle_mob(mob/living/L)
if(!can_be_occupant(L))
return
occupant = L
if(stasis_running() && check_nap_violations())
chill_out(L)
update_icon()
/obj/machinery/stasis/post_unbuckle_mob(mob/living/L)
thaw_them(L)
if(L == occupant)
occupant = null
update_icon()
/obj/machinery/stasis/process()
if( !( occupant && isliving(occupant) && check_nap_violations() ) )
use_power = IDLE_POWER_USE
return
var/mob/living/L_occupant = occupant
if(stasis_running())
if(!L_occupant.IsInStasis())
chill_out(L_occupant)
else if(L_occupant.IsInStasis())
thaw_them(L_occupant)
/obj/machinery/stasis/screwdriver_act(mob/living/user, obj/item/I)
. = default_deconstruction_screwdriver(user, "stasis_maintenance", "stasis", I)
update_icon()
/obj/machinery/stasis/crowbar_act(mob/living/user, obj/item/I)
return default_deconstruction_crowbar(I)
/obj/machinery/stasis/nap_violation(mob/violator)
unbuckle_mob(violator, TRUE)
#undef STASIS_TOGGLE_COOLDOWN

View File

@@ -1482,3 +1482,11 @@
icon_state = "engineering"
build_path = /obj/machinery/research/explosive_compressor
req_components = list(/obj/item/stock_parts/matter_bin = 3)
/obj/item/circuitboard/machine/stasis
name = "Lifeform Stasis Unit (Machine Board)"
build_path = /obj/machinery/stasis
req_components = list(
/obj/item/stack/cable_coil = 3,
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/capacitor = 1)

View File

@@ -162,6 +162,26 @@
if(!state_open)
. += "sleeper_cover"
//Lifeform Stasis Unit
/obj/machinery/stasis/survival_pod
icon = 'icons/obj/lavaland/survival_pod.dmi'
icon_state = "sleeper"
mattress_state = null
buckle_lying = 270
/obj/machinery/stasis/survival_pod/play_power_sound()
return
/obj/machinery/stasis/survival_pod/update_icon()
return
//NanoMed
/obj/machinery/vending/wallmed/survival_pod
name = "survival pod medical supply"
desc = "Wall-mounted Medical Equipment dispenser. This one seems just a tiny bit smaller."
refill_canister = null
onstation = FALSE
//Computer
/obj/item/gps/computer
name = "pod computer"

View File

@@ -6,11 +6,12 @@
SHOULD_NOT_SLEEP(TRUE)
if(mob_transforming)
return
handle_traits() // eye, ear, brain damages
handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc
. = SEND_SIGNAL(src, COMSIG_LIVING_LIFE, seconds, times_fired)
if(!(. & COMPONENT_INTERRUPT_LIFE_PHYSICAL))
PhysicalLife(seconds, times_fired)
if(!(. & COMPONENT_INTERRUPT_LIFE_BIOLOGICAL))
if(!(. & COMPONENT_INTERRUPT_LIFE_BIOLOGICAL) && !IS_IN_STASIS())
BiologicalLife(seconds, times_fired)
// CODE BELOW SHOULD ONLY BE THINGS THAT SHOULD HAPPEN NO MATTER WHAT AND CAN NOT BE SUSPENDED!
@@ -69,9 +70,6 @@
handle_block_parry(seconds)
// These two MIGHT need to be moved to base Life() if we get any in the future that's a "physical" effect that needs to fire even while in stasis.
handle_traits() // eye, ear, brain damages
handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc
return TRUE
/**

View File

@@ -433,8 +433,8 @@
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
death()
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, check_immobilized = FALSE)
if(stat || IsUnconscious() || IsStun() || IsParalyzed() || (combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (check_immobilized && IsImmobilized()) || (!ignore_restraints && restrained(ignore_grab)))
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, check_immobilized = FALSE, ignore_stasis = FALSE)
if(stat || IsUnconscious() || IsStun() || IsParalyzed() || (combat_flags & COMBAT_FLAG_HARD_STAMCRIT) || (check_immobilized && IsImmobilized()) || (!ignore_restraints && restrained(ignore_grab)) || (!ignore_stasis && IS_IN_STASIS()))
return TRUE
/mob/living/canUseStorage()

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -912,6 +912,7 @@
#include "code\game\machinery\Sleeper.dm"
#include "code\game\machinery\slotmachine.dm"
#include "code\game\machinery\spaceheater.dm"
#include "code\game\machinery\stasis.dm"
#include "code\game\machinery\status_display.dm"
#include "code\game\machinery\suit_storage_unit.dm"
#include "code\game\machinery\syndicatebeacon.dm"