mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 13:10:02 +01:00
[MIRROR] Ports Cryopods (#4880)
* Ports Cryopods (#58025) Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com> Co-authored-by: Kokonut <38844529+maxymax13@ users.noreply.github.com> Co-authored-by: Aleksej Komarov <stylemistake@ gmail.com> * Ports Cryopods * aaaa * Update cryopod.dm Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com> Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com> Co-authored-by: Kokonut <38844529+maxymax13@ users.noreply.github.com> Co-authored-by: Aleksej Komarov <stylemistake@ gmail.com> Co-authored-by: Gandalf <jzo123@hotmail.com>
This commit is contained in:
co-authored by
Mothblocks
Kokonut
Aleksej Komarov
Jeremiah
Gandalf
parent
da714da60e
commit
ef50ca23cb
@@ -145,6 +145,14 @@ SUBSYSTEM_DEF(job)
|
||||
JobDebug("AR has failed, Player: [player], Rank: [rank]")
|
||||
return FALSE
|
||||
|
||||
/datum/controller/subsystem/job/proc/FreeRole(rank)
|
||||
if(!rank)
|
||||
return
|
||||
JobDebug("Freeing role: [rank]")
|
||||
var/datum/job/job = GetJob(rank)
|
||||
if(!job)
|
||||
return FALSE
|
||||
job.current_positions = max(0, job.current_positions - 1)
|
||||
|
||||
/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level, flag)
|
||||
JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
var/assigned_role
|
||||
var/special_role
|
||||
var/list/restricted_roles = list()
|
||||
var/list/datum/objective/objectives = list()
|
||||
|
||||
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
|
||||
|
||||
|
||||
@@ -608,6 +608,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "Recreation Area"
|
||||
icon_state = "rec"
|
||||
|
||||
/area/commons/cryopods
|
||||
name = "Cryopod Room"
|
||||
icon_state = "cryopod"
|
||||
|
||||
// Commons - Vacant Rooms
|
||||
|
||||
/area/commons/vacant_room
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
|
||||
GLOBAL_LIST_EMPTY(objectives)
|
||||
|
||||
/datum/objective
|
||||
var/datum/mind/owner //The primary owner of the objective. !!SOMEWHAT DEPRECATED!! Prefer using 'team' for new code.
|
||||
@@ -14,6 +15,7 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list
|
||||
var/martyr_compatible = FALSE //If the objective is compatible with martyr objective, i.e. if you can still do it while dead.
|
||||
|
||||
/datum/objective/New(text)
|
||||
GLOB.objectives += src
|
||||
if(text)
|
||||
explanation_text = text
|
||||
|
||||
|
||||
@@ -83,12 +83,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
message = CompileText(arrival, user, rank)
|
||||
else if(message_type == "NEWHEAD" && newheadToggle)
|
||||
message = CompileText(newhead, user, rank)
|
||||
else if(message_type == "CRYOSTORAGE")
|
||||
message = "[user][rank ? ", [rank]" : ""] has been moved to cryo storage."
|
||||
else if(message_type == "ARRIVALS_BROKEN")
|
||||
message = "The arrivals shuttle has been damaged. Docking for repairs..."
|
||||
//SKYRAT EDIT ADDITION BEGIN - CRYOSLEEP
|
||||
else if(message_type == "CRYOSTORAGE")
|
||||
message = CompileText("%PERSON, %RANK has been moved to cryo storage.", user, rank)
|
||||
//SKYRAT EDIT ADDITION END
|
||||
|
||||
broadcast(message, channels)
|
||||
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Cryogenic refrigeration unit. Basically a despawner.
|
||||
* Stealing a lot of concepts/code from sleepers due to massive laziness.
|
||||
* The despawn tick will only fire if it's been more than time_till_despawned ticks
|
||||
* since time_entered, which is world.time when the occupant moves in.
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
GLOBAL_LIST_EMPTY(cryopod_computers)
|
||||
|
||||
//Main cryopod console.
|
||||
|
||||
/obj/machinery/computer/cryopod
|
||||
name = "cryogenic oversight console"
|
||||
desc = "An interface between crew and the cryogenic storage oversight systems."
|
||||
icon = 'modular_skyrat/modules/cryosleep/icons/cryogenics.dmi' //SKYRAT EDIT CHANGE - ORIGINAL: 'icons/obj/machines/cryopod.dmi'
|
||||
icon_state = "cellconsole_1"
|
||||
// circuit = /obj/item/circuitboard/cryopodcontrol
|
||||
density = FALSE
|
||||
interaction_flags_machine = INTERACT_MACHINE_OFFLINE
|
||||
req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) // Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with.
|
||||
var/mode = null
|
||||
|
||||
// Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/list/frozen_crew = list()
|
||||
var/list/frozen_items = list()
|
||||
|
||||
var/storage_type = "crewmembers"
|
||||
var/storage_name = "Cryogenic Oversight Control"
|
||||
var/allow_items = TRUE
|
||||
|
||||
/obj/machinery/computer/cryopod/Initialize()
|
||||
. = ..()
|
||||
GLOB.cryopod_computers += src
|
||||
|
||||
/obj/machinery/computer/cryopod/Destroy()
|
||||
GLOB.cryopod_computers -= src
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/cryopod/update_icon_state()
|
||||
if(machine_stat & (NOPOWER|BROKEN))
|
||||
icon_state = "cellconsole"
|
||||
return ..()
|
||||
icon_state = "cellconsole_1"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/cryopod/ui_interact(mob/user, datum/tgui/ui)
|
||||
if(machine_stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "CryopodConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/cryopod/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["allow_items"] = allow_items
|
||||
data["frozen_crew"] = frozen_crew
|
||||
data["frozen_items"] = list()
|
||||
|
||||
if(allow_items)
|
||||
data["frozen_items"] = frozen_items
|
||||
|
||||
var/obj/item/card/id/id_card
|
||||
var/datum/bank_account/current_user
|
||||
if(isliving(user))
|
||||
var/mob/living/person = user
|
||||
id_card = person.get_idcard()
|
||||
if(id_card?.registered_account)
|
||||
current_user = id_card.registered_account
|
||||
if(current_user)
|
||||
data["account_name"] = current_user.account_holder
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/cryopod/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
switch(action)
|
||||
if("one_item")
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
|
||||
if(!allow_items) return
|
||||
|
||||
if(!params["item"])
|
||||
return
|
||||
|
||||
var/obj/item/item = frozen_items[text2num(params["item"])]
|
||||
if(!item)
|
||||
to_chat(user, "<span class='notice'>[item] is no longer in storage.</span>")
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>[src] beeps happily as it disgorges [item].</span>")
|
||||
item.forceMove(get_turf(src))
|
||||
frozen_items -= item
|
||||
|
||||
if("all_items")
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return
|
||||
|
||||
if(!allow_items) return
|
||||
|
||||
visible_message("<span class='notice'>[src] beeps happily as it disgorges the desired objects.</span>")
|
||||
|
||||
for(var/obj/item/item in frozen_items)
|
||||
item.forceMove(get_turf(src))
|
||||
frozen_items -= item
|
||||
|
||||
return TRUE
|
||||
|
||||
// Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "cryogenic freezer"
|
||||
desc = "Suited for Cyborgs and Humanoids, the pod is a safe place for personnel affected by the Space Sleep Disorder to get some rest."
|
||||
icon = 'icons/obj/machines/cryopod.dmi'
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
state_open = TRUE
|
||||
|
||||
var/on_store_message = "has entered long-term storage."
|
||||
var/on_store_name = "Cryogenic Oversight"
|
||||
|
||||
// 3 minutes-ish safe period before being despawned.
|
||||
var/time_till_despawn = 3 MINUTES // This is reduced to 30 seconds if a player manually enters cryo
|
||||
var/fast_despawn = 30 SECONDS
|
||||
var/despawn_world_time = null // Used to keep track of the safe period.
|
||||
|
||||
var/obj/machinery/computer/cryopod/control_computer
|
||||
COOLDOWN_DECLARE(last_no_computer_message)
|
||||
|
||||
/obj/machinery/cryopod/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD //Gotta populate the cryopod computer GLOB first
|
||||
|
||||
/obj/machinery/cryopod/LateInitialize()
|
||||
update_icon()
|
||||
find_control_computer()
|
||||
|
||||
// This is not a good situation
|
||||
/obj/machinery/cryopod/Destroy()
|
||||
control_computer = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/cryopod/proc/find_control_computer(urgent = FALSE)
|
||||
|
||||
for(var/cryo_console as anything in GLOB.cryopod_computers)
|
||||
var/obj/machinery/computer/cryopod/console = cryo_console
|
||||
if(get_area(console) == get_area(src))
|
||||
control_computer = console
|
||||
break
|
||||
|
||||
// Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged
|
||||
if(!control_computer && urgent && COOLDOWN_FINISHED(src, last_no_computer_message))
|
||||
COOLDOWN_START(src, last_no_computer_message, 5 MINUTES)
|
||||
log_admin("Cryopod in [get_area(src)] could not find control computer!")
|
||||
message_admins("Cryopod in [get_area(src)] could not find control computer!")
|
||||
last_no_computer_message = world.time
|
||||
|
||||
return control_computer != null
|
||||
|
||||
/obj/machinery/cryopod/close_machine(mob/user)
|
||||
if(!control_computer)
|
||||
find_control_computer(TRUE)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
if(mob_occupant.client || !mob_occupant.key) // Self cryos and SSD
|
||||
despawn_world_time = world.time + (fast_despawn) // This gives them 30 seconds
|
||||
else
|
||||
despawn_world_time = world.time + time_till_despawn
|
||||
icon_state = "cryopod"
|
||||
|
||||
/obj/machinery/cryopod/open_machine()
|
||||
..()
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/container_resist_act(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/cryopod/relaymove(mob/user)
|
||||
container_resist_act(user)
|
||||
|
||||
/obj/machinery/cryopod/process()
|
||||
if(!occupant)
|
||||
return
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
// Eject dead people
|
||||
if(mob_occupant.stat == DEAD)
|
||||
open_machine()
|
||||
|
||||
if(world.time <= despawn_world_time)
|
||||
return
|
||||
|
||||
if(!mob_occupant.client && mob_occupant.stat <= SOFT_CRIT) // Occupant is living and has no client.
|
||||
if(!control_computer)
|
||||
find_control_computer(urgent = TRUE) // better hope you found it this time
|
||||
|
||||
despawn_occupant()
|
||||
|
||||
/obj/machinery/cryopod/proc/handle_objectives()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
// Update any existing objectives involving this mob.
|
||||
for(var/datum/objective/objective in GLOB.objectives)
|
||||
// We don't want revs to get objectives that aren't for heads of staff. Letting
|
||||
// them win or lose based on cryo is silly so we remove the objective.
|
||||
if(istype(objective,/datum/objective/mutiny) && objective.target == mob_occupant.mind)
|
||||
objective.team.objectives -= objective
|
||||
qdel(objective)
|
||||
for(var/datum/mind/mind in objective.team.members)
|
||||
to_chat(mind.current, "<BR><span class='userdanger'>Your target is no longer within reach. Objective removed!</span>")
|
||||
mind.announce_objectives()
|
||||
else if(objective.target && istype(objective.target, /datum/mind))
|
||||
if(objective.target == mob_occupant.mind)
|
||||
var/old_target = objective.target
|
||||
objective.target = null
|
||||
if(!objective)
|
||||
return
|
||||
objective.find_target()
|
||||
if(!objective.target && objective.owner)
|
||||
to_chat(objective.owner.current, "<BR><span class='userdanger'>Your target is no longer within reach. Objective removed!</span>")
|
||||
for(var/datum/antagonist/antag in objective.owner.antag_datums)
|
||||
antag.objectives -= objective
|
||||
if (!objective.team)
|
||||
objective.update_explanation_text()
|
||||
objective.owner.announce_objectives()
|
||||
to_chat(objective.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
else
|
||||
var/list/objectivestoupdate
|
||||
for(var/datum/mind/objective_owner in objective.get_owners())
|
||||
to_chat(objective_owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
for(var/datum/objective/update_target_objective in objective_owner.get_all_objectives())
|
||||
LAZYADD(objectivestoupdate, update_target_objective)
|
||||
objectivestoupdate += objective.team.objectives
|
||||
for(var/datum/objective/update_objective in objectivestoupdate)
|
||||
if(update_objective.target != old_target || !istype(update_objective,objective.type))
|
||||
continue
|
||||
update_objective.target = objective.target
|
||||
update_objective.update_explanation_text()
|
||||
to_chat(objective.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
update_objective.owner.announce_objectives()
|
||||
qdel(objective)
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/item)
|
||||
for(var/datum/objective_item/steal/possible_item in GLOB.possible_items)
|
||||
if(istype(item, possible_item.targetitem))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
/obj/machinery/cryopod/proc/despawn_occupant()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/crew_member = list()
|
||||
|
||||
crew_member["name"] = mob_occupant.real_name
|
||||
|
||||
if(mob_occupant.mind && mob_occupant.mind.assigned_role)
|
||||
// Handle job slot/tater cleanup.
|
||||
var/job = mob_occupant.mind.assigned_role
|
||||
crew_member["job"] = job
|
||||
SSjob.FreeRole(job)
|
||||
if(LAZYLEN(mob_occupant.mind.objectives))
|
||||
mob_occupant.mind.objectives.Cut()
|
||||
mob_occupant.mind.special_role = null
|
||||
//SKYRAT EDIT ADDITION
|
||||
if(SSticker.mode.name == "assaultops")
|
||||
if(is_assaultops_target(mob_occupant.mind))
|
||||
remove_assaultops_target(mob_occupant.mind) //Remove them from the list of targets for the assops.
|
||||
//SKYRAT EDIT END
|
||||
else
|
||||
crew_member["job"] = "N/A"
|
||||
// Delete them from datacore.
|
||||
var/announce_rank = null
|
||||
for(var/datum/data/record/medical_record in GLOB.data_core.medical)
|
||||
if(medical_record.fields["name"] == mob_occupant.real_name)
|
||||
qdel(medical_record)
|
||||
for(var/datum/data/record/security_record in GLOB.data_core.security)
|
||||
if(security_record.fields["name"] == mob_occupant.real_name)
|
||||
qdel(security_record)
|
||||
for(var/datum/data/record/general_record in GLOB.data_core.general)
|
||||
if(general_record.fields["name"] == mob_occupant.real_name)
|
||||
announce_rank = general_record.fields["rank"]
|
||||
qdel(general_record)
|
||||
|
||||
control_computer?.frozen_crew += list(crew_member)
|
||||
|
||||
// Make an announcement and log the person entering storage.
|
||||
if(GLOB.announcement_systems.len)
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("CRYOSTORAGE", mob_occupant.real_name, announce_rank, list())
|
||||
|
||||
visible_message("<span class='notice'>[src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
|
||||
|
||||
for(var/obj/item/item in mob_occupant.GetAllContents())
|
||||
if(item.loc.loc && (item.loc.loc == loc || item.loc.loc == control_computer))
|
||||
continue // means we already moved whatever this thing was in
|
||||
// I'm a professional, okay
|
||||
|
||||
if(!should_preserve_item(item))
|
||||
continue
|
||||
|
||||
if(control_computer && control_computer.allow_items)
|
||||
control_computer.frozen_items += item
|
||||
mob_occupant.transferItemToLoc(item, control_computer, TRUE)
|
||||
else
|
||||
mob_occupant.transferItemToLoc(item, loc, TRUE)
|
||||
|
||||
var/list/contents = mob_occupant.GetAllContents()
|
||||
QDEL_LIST(contents)
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(TRUE))
|
||||
if(world.time < 15 MINUTES) // before the 15 minute mark
|
||||
mob_occupant.ghostize(FALSE) // Players despawned too early may not re-enter the game
|
||||
else
|
||||
mob_occupant.ghostize(TRUE)
|
||||
handle_objectives()
|
||||
QDEL_NULL(occupant)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || !can_interact(user) || !target.Adjacent(user) || !ismob(target) || isanimal(target) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='notice'>[src] is already occupied!</span>")
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>Dead people can not be put into cryo.</span>")
|
||||
return
|
||||
|
||||
if(target.client && user != target)
|
||||
if(iscyborg(target))
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. [target.p_theyre(capitalized = TRUE)] online.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. [target.p_theyre(capitalized = TRUE)] conscious.</span>")
|
||||
return
|
||||
else if(target.client)
|
||||
if(alert(target,"Would you like to enter cryosleep?",,"Yes","No") == "No")
|
||||
return
|
||||
|
||||
var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!"
|
||||
|
||||
if(target == user && COOLDOWN_FINISHED(target.client, cryo_warned))
|
||||
var/caught = FALSE
|
||||
var/datum/antagonist/antag = target.mind.has_antag_datum(/datum/antagonist)
|
||||
var/datum/job/target_job = SSjob.GetJob(target.mind.assigned_role)
|
||||
if(target_job.req_admin_notify)
|
||||
alert("You're an important role![generic_plsnoleave_message]")
|
||||
caught = TRUE
|
||||
if(antag)
|
||||
alert("You're \a [antag.name]![generic_plsnoleave_message]")
|
||||
caught = TRUE
|
||||
if(caught)
|
||||
COOLDOWN_START(target.client, cryo_warned, 5 MINUTES)
|
||||
return
|
||||
|
||||
if(!istype(target) || !can_interact(user) || !target.Adjacent(user) || !ismob(target) || isanimal(target) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
// rerun the checks in case of shenanigans
|
||||
|
||||
if(target == user)
|
||||
visible_message("[user] starts climbing into the cryo pod.")
|
||||
else
|
||||
visible_message("[user] starts putting [target] into the cryo pod.")
|
||||
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='notice'>[src] is in use.</span>")
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
to_chat(target, "<span class='boldnotice'>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</span>")
|
||||
name = "[name] ([occupant.name])"
|
||||
log_admin("[key_name(target)] entered a stasis pod.")
|
||||
message_admins("[key_name_admin(target)] entered a stasis pod. [ADMIN_JMP(src)]")
|
||||
add_fingerprint(target)
|
||||
|
||||
// Attacks/effects.
|
||||
/obj/machinery/cryopod/blob_act()
|
||||
return // Sorta gamey, but we don't really want these to be destroyed.
|
||||
@@ -283,23 +283,31 @@
|
||||
|
||||
/datum/team/cult/proc/ascend(cultist)
|
||||
if(ishuman(cultist))
|
||||
var/mob/living/carbon/human/H = cultist
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
|
||||
var/mob/living/carbon/human/human = cultist
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(human), human.dir)
|
||||
var/istate = pick("halo1","halo2","halo3","halo4","halo5","halo6")
|
||||
var/mutable_appearance/new_halo_overlay = mutable_appearance('icons/effects/32x64.dmi', istate, -HALO_LAYER)
|
||||
H.overlays_standing[HALO_LAYER] = new_halo_overlay
|
||||
H.apply_overlay(HALO_LAYER)
|
||||
human.overlays_standing[HALO_LAYER] = new_halo_overlay
|
||||
human.apply_overlay(HALO_LAYER)
|
||||
|
||||
/datum/team/cult/proc/setup_objectives()
|
||||
//SAC OBJECTIVE , todo: move this to objective internals
|
||||
/datum/team/cult/proc/make_image(datum/objective/sacrifice/sac_objective)
|
||||
var/datum/job/job_of_sacrifice = SSjob.GetJob(sac_objective.target.assigned_role)
|
||||
var/datum/preferences/prefs_of_sacrifice = sac_objective.target.current.client.prefs
|
||||
var/icon/reshape = get_flat_human_icon(null, job_of_sacrifice, prefs_of_sacrifice, list(SOUTH))
|
||||
reshape.Shift(SOUTH, 4)
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
sac_objective.sac_image = reshape
|
||||
|
||||
/datum/objective/sacrifice/find_target(dupe_search_range)
|
||||
if(!istype(team, /datum/team/cult))
|
||||
return
|
||||
var/datum/team/cult/cult = team
|
||||
var/list/target_candidates = list()
|
||||
var/datum/objective/sacrifice/sac_objective = new
|
||||
sac_objective.team = src
|
||||
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && !is_convertable_to_cult(player) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
|
||||
if(target_candidates.len == 0)
|
||||
message_admins("Cult Sacrifice: Could not find unconvertible target, checking for convertible target.")
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
@@ -307,30 +315,26 @@
|
||||
target_candidates += player.mind
|
||||
listclearnulls(target_candidates)
|
||||
if(LAZYLEN(target_candidates))
|
||||
sac_objective.target = pick(target_candidates)
|
||||
sac_objective.update_explanation_text()
|
||||
|
||||
var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role)
|
||||
var/datum/preferences/sacface = sac_objective.target.current.client.prefs
|
||||
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface, list(SOUTH))
|
||||
reshape.Shift(SOUTH, 4)
|
||||
reshape.Shift(EAST, 1)
|
||||
reshape.Crop(7,4,26,31)
|
||||
reshape.Crop(-5,-3,26,30)
|
||||
sac_objective.sac_image = reshape
|
||||
|
||||
objectives += sac_objective
|
||||
target = pick(target_candidates)
|
||||
update_explanation_text()
|
||||
else
|
||||
message_admins("Cult Sacrifice: Could not find unconvertible or convertible target. WELP!")
|
||||
cult.make_image(src)
|
||||
for(var/datum/mind/mind in cult.members)
|
||||
if(mind.current)
|
||||
mind.current.clear_alert("bloodsense")
|
||||
mind.current.throw_alert("bloodsense", /atom/movable/screen/alert/bloodsense)
|
||||
|
||||
/datum/team/cult/proc/setup_objectives()
|
||||
var/datum/objective/sacrifice/sacrifice_objective = new
|
||||
sacrifice_objective.team = src
|
||||
sacrifice_objective.find_target()
|
||||
objectives += sacrifice_objective
|
||||
|
||||
//SUMMON OBJECTIVE
|
||||
|
||||
var/datum/objective/eldergod/summon_objective = new()
|
||||
var/datum/objective/eldergod/summon_objective = new
|
||||
summon_objective.team = src
|
||||
objectives += summon_objective
|
||||
|
||||
|
||||
/datum/objective/sacrifice
|
||||
var/sacced = FALSE
|
||||
var/sac_image
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
var/total_count_reset = 0
|
||||
///Internal counter for clients sending external (IRC/Discord) relay messages via ahelp to prevent spamming. Set to a number every time an admin reply is sent, decremented for every client send.
|
||||
var/externalreplyamount = 0
|
||||
|
||||
///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
|
||||
COOLDOWN_DECLARE(cryo_warned)
|
||||
/////////
|
||||
//OTHER//
|
||||
/////////
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -1,493 +0,0 @@
|
||||
/client
|
||||
var/cryo_warned = 0
|
||||
|
||||
/*
|
||||
* Cryogenic refrigeration unit. Basically a despawner.
|
||||
* Stealing a lot of concepts/code from sleepers due to massive laziness.
|
||||
* The despawn tick will only fire if it's been more than time_till_despawned ticks
|
||||
* since time_entered, which is world.time when the occupant moves in.
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
|
||||
//Main cryopod console.
|
||||
|
||||
/obj/machinery/computer/cryopod
|
||||
name = "cryogenic oversight console"
|
||||
desc = "An interface between crew and the cryogenic storage oversight systems."
|
||||
icon = 'modular_skyrat/modules/cryosleep/icons/cryogenics.dmi'
|
||||
icon_state = "cellconsole_1"
|
||||
circuit = /obj/item/circuitboard/cryopodcontrol
|
||||
density = FALSE
|
||||
interaction_flags_machine = INTERACT_MACHINE_OFFLINE
|
||||
req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) //Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with.
|
||||
|
||||
var/menu = 1 //Which menu screen to display
|
||||
|
||||
//Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/list/frozen_crew = list()
|
||||
var/list/frozen_items = list()
|
||||
|
||||
// Used for containing rare items traitors need to steal, so it's not
|
||||
// game-over if they get iced
|
||||
var/list/objective_items = list()
|
||||
// A cache of theft datums so you don't have to re-create them for
|
||||
// each item check
|
||||
var/list/theft_cache = list()
|
||||
|
||||
var/allow_items = TRUE
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_ai()
|
||||
attack_hand()
|
||||
|
||||
/obj/machinery/computer/cryopod/ui_interact(mob/user = usr)
|
||||
. = ..()
|
||||
user.set_machine(src)
|
||||
add_fingerprint(user)
|
||||
|
||||
var/dat = ""
|
||||
|
||||
dat += "<h2>Welcome, [user.real_name].</h2><hr/>"
|
||||
dat += "<br><br>"
|
||||
|
||||
switch(src.menu)
|
||||
if(1)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=2'>View crew storage log</a><br><br>"
|
||||
if(allow_items)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=3'>View objects storage log</a><br><br>"
|
||||
dat += "<a href='byond://?src=[REF(src)];item=1'>Recover object</a><br><br>"
|
||||
dat += "<a href='byond://?src=[REF(src)];allitems=1'>Recover all objects</a><br>"
|
||||
if(2)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored Crew</h3><br/><hr/><br/>"
|
||||
if(!frozen_crew.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/person in frozen_crew)
|
||||
dat += "[person]<br/>"
|
||||
dat += "<hr/>"
|
||||
if(3)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored objects</h3><br/><hr/><br/>"
|
||||
if(!frozen_items.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/obj/item/I in frozen_items)
|
||||
dat += "[I.name]<br/>"
|
||||
dat += "<hr/>"
|
||||
|
||||
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cryopod/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(href_list["item"])
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!I)
|
||||
return
|
||||
|
||||
if(!(I in frozen_items))
|
||||
to_chat(user, "<span class='notice'>\The [I] is no longer in storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges \the [I].</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
I.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(I)
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["allitems"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges the desired objects.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
for(var/obj/item/I in frozen_items)
|
||||
I.forceMove(drop_location())
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
updateUsrDialog()
|
||||
|
||||
ui_interact(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/circuitboard/cryopodcontrol
|
||||
name = "Circuit board (Cryogenic Oversight Console)"
|
||||
build_path = "/obj/machinery/computer/cryopod"
|
||||
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return
|
||||
|
||||
//Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "cryogenic freezer"
|
||||
desc = "Suited for Cyborgs and Humanoids, the pod is a safe place for personnel affected by the Space Sleep Disorder to get some rest."
|
||||
icon = 'modular_skyrat/modules/cryosleep/icons/cryogenics.dmi'
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
state_open = TRUE
|
||||
|
||||
var/on_store_message = "has entered long-term storage."
|
||||
var/on_store_name = "Cryogenic Oversight"
|
||||
|
||||
// 15 minutes-ish safe period before being despawned.
|
||||
var/time_till_despawn = 15 * 600 // This is reduced by 90% if a player manually enters cryo
|
||||
var/despawn_world_time // Used to keep track of the safe period.
|
||||
|
||||
var/obj/machinery/computer/cryopod/control_computer
|
||||
var/last_no_computer_message = 0
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/static/list/preserve_items = typecacheof(list(
|
||||
/obj/item/hand_tele,
|
||||
/obj/item/card/id/advanced/gold/captains_spare,
|
||||
/obj/item/aicard,
|
||||
/obj/item/mmi,
|
||||
/obj/item/paicard,
|
||||
/obj/item/gun,
|
||||
/obj/item/pinpointer,
|
||||
/obj/item/clothing/shoes/magboots,
|
||||
/obj/item/areaeditor/blueprints,
|
||||
/obj/item/clothing/head/helmet/space,
|
||||
/obj/item/clothing/suit/space,
|
||||
/obj/item/clothing/suit/armor,
|
||||
/obj/item/defibrillator/compact,
|
||||
/obj/item/reagent_containers/hypospray/cmo,
|
||||
/obj/item/clothing/accessory/medal/gold/captain,
|
||||
/obj/item/clothing/gloves/krav_maga,
|
||||
/obj/item/nullrod,
|
||||
/obj/item/tank/jetpack,
|
||||
/obj/item/documents,
|
||||
/obj/item/nuke_core_container
|
||||
))
|
||||
// These items will NOT be preserved
|
||||
var/static/list/do_not_preserve_items = typecacheof(list(
|
||||
/obj/item/mmi/posibrain,
|
||||
/obj/item/gun/energy/laser/mounted,
|
||||
/obj/item/gun/energy/e_gun/advtaser/mounted,
|
||||
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/gun/energy/e_gun/advtaser/cyborg,
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
))
|
||||
|
||||
/obj/machinery/cryopod/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
find_control_computer(mapload)
|
||||
|
||||
/obj/machinery/cryopod/proc/find_control_computer(urgent = FALSE)
|
||||
for(var/obj/machinery/computer/cryopod/C in get_area(src))
|
||||
control_computer = C
|
||||
if(C)
|
||||
return C
|
||||
break
|
||||
|
||||
// Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged
|
||||
if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time)
|
||||
log_admin("Cryopod in [get_area(src)] could not find control computer!")
|
||||
message_admins("Cryopod in [get_area(src)] could not find control computer!")
|
||||
last_no_computer_message = world.time
|
||||
|
||||
return control_computer != null
|
||||
|
||||
/obj/machinery/cryopod/close_machine(mob/user)
|
||||
if(!control_computer)
|
||||
find_control_computer(TRUE)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
if(mob_occupant.client)//if they're logged in
|
||||
despawn_world_time = world.time + (time_till_despawn * 0.1)
|
||||
else
|
||||
despawn_world_time = world.time + time_till_despawn
|
||||
icon_state = "cryopod"
|
||||
|
||||
/obj/machinery/cryopod/open_machine()
|
||||
..()
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/container_resist_act(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/cryopod/relaymove(mob/user)
|
||||
container_resist_act(user)
|
||||
|
||||
/obj/machinery/cryopod/process()
|
||||
if(!occupant)
|
||||
return
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
// Eject dead people
|
||||
if(mob_occupant.stat == DEAD)
|
||||
open_machine()
|
||||
|
||||
if(!(world.time > despawn_world_time + 100))//+ 10 seconds
|
||||
return
|
||||
|
||||
if(!mob_occupant.client && mob_occupant.stat < 2) //Occupant is living and has no client.
|
||||
if(!control_computer)
|
||||
find_control_computer(urgent = TRUE)//better hope you found it this time
|
||||
|
||||
despawn_occupant()
|
||||
|
||||
#define CRYO_DESTROY 0
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
#define CRYO_IGNORE 3
|
||||
#define CRYO_DESTROY_LATER 4
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
if(istype(I, T.targetitem) && T.check_special_completion(I))
|
||||
return CRYO_OBJECTIVE
|
||||
if(preserve_items[I] && !do_not_preserve_items[I])
|
||||
return CRYO_PRESERVE
|
||||
return CRYO_DESTROY
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
/obj/machinery/cryopod/proc/despawn_occupant()
|
||||
if(!control_computer)
|
||||
find_control_computer()
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
//Handle Borg stuff first
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
if(R.mmi?.brain)
|
||||
cryo_items[R.mmi] = CRYO_DESTROY_LATER
|
||||
cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER
|
||||
for(var/obj/item/I in R.model) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
R.model.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER)
|
||||
continue
|
||||
cryo_items[I] = should_preserve_item(I)
|
||||
mob_occupant.transferItemToLoc(I, src, TRUE)
|
||||
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
|
||||
if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
continue
|
||||
for(var/obj/item/O in I.contents)
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
|
||||
for(var/A in cryo_items)
|
||||
var/obj/item/I = A
|
||||
if(QDELETED(I)) //edge cases and DROPDEL.
|
||||
continue
|
||||
var/preserve = cryo_items[I]
|
||||
if(preserve == CRYO_DESTROY_LATER)
|
||||
continue
|
||||
if(preserve != CRYO_IGNORE)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.moveToNullspace()
|
||||
else
|
||||
I.forceMove(loc)
|
||||
cryo_items -= I
|
||||
|
||||
/*
|
||||
//Update any existing objectives involving this mob.
|
||||
for(var/datum/objective/O in GLOB.objectives)
|
||||
// We don't want revs to get objectives that aren't for heads of staff. Letting
|
||||
// them win or lose based on cryo is silly so we remove the objective.
|
||||
if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind)
|
||||
qdel(O)
|
||||
else if(O.target && istype(O.target, /datum/mind))
|
||||
if(O.target == mob_occupant.mind)
|
||||
if(O.owner && O.owner.current)
|
||||
to_chat(O.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
O.target = null
|
||||
spawn(10) //This should ideally fire after the occupant is deleted.
|
||||
if(!O)
|
||||
return
|
||||
O.find_target()
|
||||
O.update_explanation_text()
|
||||
if(!(O.target))
|
||||
qdel(O)*/
|
||||
|
||||
if(mob_occupant.mind)
|
||||
//Handle job slot/tater cleanup.
|
||||
if(mob_occupant.mind.assigned_role)
|
||||
SSjob.FreeRole(mob_occupant.mind.assigned_role)
|
||||
mob_occupant.mind.special_role = null
|
||||
if(SSticker.mode.name == "assaultops")
|
||||
if(is_assaultops_target(mob_occupant.mind))
|
||||
remove_assaultops_target(mob_occupant.mind) //Remove them from the list of targets for the assops.
|
||||
|
||||
// Delete them from datacore.
|
||||
|
||||
var/announce_rank = null
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
if((R.fields["name"] == mob_occupant.real_name))
|
||||
qdel(R)
|
||||
break
|
||||
for(var/datum/data/record/T in GLOB.data_core.security)
|
||||
if((T.fields["name"] == mob_occupant.real_name))
|
||||
qdel(T)
|
||||
break
|
||||
for(var/datum/data/record/G in GLOB.data_core.general)
|
||||
if((G.fields["name"] == mob_occupant.real_name))
|
||||
announce_rank = G.fields["rank"]
|
||||
qdel(G)
|
||||
break
|
||||
|
||||
//Make an announcement and log the person entering storage.
|
||||
if(control_computer)
|
||||
control_computer.frozen_crew += "[mob_occupant.real_name]"
|
||||
|
||||
if(GLOB.announcement_systems.len)
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("CRYOSTORAGE", mob_occupant.real_name, announce_rank, list())
|
||||
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(TRUE))
|
||||
mob_occupant.ghostize(FALSE)
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
|
||||
var/atom/A = I
|
||||
if(!QDELETED(A))
|
||||
qdel(A)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
#undef CRYO_DESTROY
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
#undef CRYO_IGNORE
|
||||
#undef CRYO_DESTROY_LATER
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>The cryo pod is already occupied!</span>")
|
||||
return
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>Dead people can not be put into cryo.</span>")
|
||||
return
|
||||
if(target.client && user != target)
|
||||
if(iscyborg(target))
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're online.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're conscious.</span>")
|
||||
return
|
||||
else if(target.client)
|
||||
if(alert(target,"Would you like to enter cryosleep?",,"Yes","No") == "No")
|
||||
return
|
||||
if (user != target && round(((world.time - target.lastclienttime) / (1 MINUTES)),1) <= CONFIG_GET(number/cryo_min_ssd_time))
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They might wake up soon.</span>")
|
||||
return
|
||||
var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!"
|
||||
if(target == user && world.time - target.client.cryo_warned > 5 MINUTES)//if we haven't warned them in the last 5 minutes
|
||||
var/list/caught_string
|
||||
var/addendum = ""
|
||||
if(target.mind.assigned_role in GLOB.command_positions)
|
||||
LAZYADD(caught_string, "Head of Staff")
|
||||
addendum = " Be sure to put your locker items back into your locker!"
|
||||
if(iscultist(target))
|
||||
LAZYADD(caught_string, "Cultist")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/gang))
|
||||
LAZYADD(caught_string, "Gangster")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head))
|
||||
LAZYADD(caught_string, "Head Revolutionary")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
LAZYADD(caught_string, "Revolutionary")
|
||||
if(caught_string)
|
||||
alert(target, "You're a [english_list(caught_string)]![generic_plsnoleave_message][addendum]")
|
||||
target.client.cryo_warned = world.time
|
||||
return
|
||||
if(!target || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
//rerun the checks in case of shenanigans
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>\The [src] is in use.</span>")
|
||||
return
|
||||
if(target == user)
|
||||
visible_message("<span class='notice'>[user] starts climbing into the cryo pod.</span>")
|
||||
else
|
||||
visible_message("<span class='notice'>[user] starts putting [target] into the cryo pod.</span>")
|
||||
if(do_after(user, 3 SECONDS, target = target))
|
||||
if(occupant)
|
||||
return
|
||||
close_machine(target)
|
||||
to_chat(target, "<span class='boldnotice'>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</span>")
|
||||
name = "[name] ([occupant.name])"
|
||||
if(target == user)
|
||||
log_admin("<span class='notice'>[key_name(target)] entered a stasis pod.</span>")
|
||||
message_admins("[key_name_admin(target)] entered a stasis pod. (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
else
|
||||
log_admin("<span class='notice'>[key_name(user)] put [key_name(target)] inside a stasis pod.</span>")
|
||||
message_admins("[key_name_admin(user)] put [key_name_admin(target)] inside a stasis pod. (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
add_fingerprint(target)
|
||||
|
||||
//Attacks/effects.
|
||||
/obj/machinery/cryopod/blob_act()
|
||||
return //Sorta gamey, but we don't really want these to be destroyed.
|
||||
@@ -1,7 +0,0 @@
|
||||
/datum/controller/subsystem/job/proc/FreeRole(rank)
|
||||
if(!rank)
|
||||
return
|
||||
var/datum/job/job = GetJob(rank)
|
||||
if(!job)
|
||||
return FALSE
|
||||
job.current_positions = max(0, job.current_positions - 1)
|
||||
+1
-2
@@ -929,6 +929,7 @@
|
||||
#include "code\game\machinery\cell_charger.dm"
|
||||
#include "code\game\machinery\civilian_bounties.dm"
|
||||
#include "code\game\machinery\constructable_frame.dm"
|
||||
#include "code\game\machinery\cryopod.dm"
|
||||
#include "code\game\machinery\dance_machine.dm"
|
||||
#include "code\game\machinery\defibrillator_mount.dm"
|
||||
#include "code\game\machinery\deployable.dm"
|
||||
@@ -3747,8 +3748,6 @@
|
||||
#include "modular_skyrat\modules\cryosleep\code\ai.dm"
|
||||
#include "modular_skyrat\modules\cryosleep\code\area.dm"
|
||||
#include "modular_skyrat\modules\cryosleep\code\config.dm"
|
||||
#include "modular_skyrat\modules\cryosleep\code\cryopod.dm"
|
||||
#include "modular_skyrat\modules\cryosleep\code\job.dm"
|
||||
#include "modular_skyrat\modules\cum\jerkoff_verb.dm"
|
||||
#include "modular_skyrat\modules\cum\seaofmen_keg.dm"
|
||||
#include "modular_skyrat\modules\cum\chemistry\reagents\cum_reagent.dm"
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Stack, Button, Section, NoticeBox, LabeledList, Collapsible } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const CryopodConsole = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const { account_name, allow_items } = data;
|
||||
|
||||
const welcomeTitle = `Hello, ${account_name || '[REDACTED]'}!`;
|
||||
|
||||
return (
|
||||
<Window title="Cryopod Console" width={400} height={480}>
|
||||
<Window.Content>
|
||||
<Stack vertical>
|
||||
<Section title={welcomeTitle}>
|
||||
This automated cryogenic freezing unit will safely store your
|
||||
corporeal form until your next assignment.
|
||||
</Section>
|
||||
<CrewList />
|
||||
{!!allow_items && <ItemList />}
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const CrewList = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const { frozen_crew } = data;
|
||||
|
||||
return (
|
||||
<Collapsible title="Stored Crew">
|
||||
{!frozen_crew.length ? (
|
||||
<NoticeBox>No stored crew!</NoticeBox>
|
||||
) : (
|
||||
<Section height={10} fill scrollable>
|
||||
<LabeledList>
|
||||
{frozen_crew.map((person) => (
|
||||
<LabeledList.Item key={person} label={person.name}>
|
||||
{person.job}
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
)}
|
||||
</Collapsible>
|
||||
);
|
||||
};
|
||||
|
||||
const ItemList = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { frozen_items } = data;
|
||||
|
||||
const replaceItemName = (item) => {
|
||||
let itemName = item.toString();
|
||||
if (itemName.startsWith('the')) {
|
||||
itemName = itemName.slice(4, itemName.length);
|
||||
}
|
||||
return itemName.replace(/^\w/, (c) => c.toUpperCase());
|
||||
};
|
||||
|
||||
return (
|
||||
<Collapsible title="Stored Items">
|
||||
{!frozen_items.length ? (
|
||||
<NoticeBox>No stored items!</NoticeBox>
|
||||
) : (
|
||||
<>
|
||||
<Section height={12} fill scrollable>
|
||||
<LabeledList>
|
||||
{frozen_items.map((item, index) => (
|
||||
<LabeledList.Item
|
||||
key={item}
|
||||
label={replaceItemName(item)}
|
||||
buttons={
|
||||
<Button
|
||||
icon="arrow-down"
|
||||
content="Drop"
|
||||
mr={1}
|
||||
onClick={() => act('one_item', { item: index + 1 })}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Button
|
||||
content="Drop All Items"
|
||||
color="red"
|
||||
onClick={() => act('all_items')}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Collapsible>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user