Ports Bay's updated evacuation controller and bluespace jump. (#12445)

This commit is contained in:
Matt Atlas
2021-09-07 17:12:10 +02:00
committed by GitHub
parent 0b6631781a
commit b64224770c
59 changed files with 1137 additions and 597 deletions

View File

@@ -202,7 +202,7 @@
#include "code\controllers\subsystems\documents.dm"
#include "code\controllers\subsystems\economy.dm"
#include "code\controllers\subsystems\effects.dm"
#include "code\controllers\subsystems\emergency_shuttle.dm"
#include "code\controllers\subsystems\evac.dm"
#include "code\controllers\subsystems\event.dm"
#include "code\controllers\subsystems\explosives.dm"
#include "code\controllers\subsystems\fail2topic.dm"
@@ -247,6 +247,14 @@
#include "code\controllers\subsystems\virtual_reality.dm"
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\zcopy.dm"
#include "code\controllers\subsystems\evacuation\evacuation.dm"
#include "code\controllers\subsystems\evacuation\evacuation_eta.dm"
#include "code\controllers\subsystems\evacuation\evacuation_helpers.dm"
#include "code\controllers\subsystems\evacuation\evacuation_option.dm"
#include "code\controllers\subsystems\evacuation\evacuation_pods.dm"
#include "code\controllers\subsystems\evacuation\evacuation_predicate.dm"
#include "code\controllers\subsystems\evacuation\evacuation_shuttle.dm"
#include "code\controllers\subsystems\evacuation\~evac.dm"
#include "code\controllers\subsystems\initialization\atlas.dm"
#include "code\controllers\subsystems\initialization\atoms.dm"
#include "code\controllers\subsystems\initialization\holomap.dm"
@@ -314,6 +322,7 @@
#include "code\datums\looping_sounds\thermal_drill.dm"
#include "code\datums\observation\_debug.dm"
#include "code\datums\observation\destroyed.dm"
#include "code\datums\observation\dir_set.dm"
#include "code\datums\observation\entered.dm"
#include "code\datums\observation\equipped.dm"
#include "code\datums\observation\exited.dm"
@@ -533,6 +542,7 @@
#include "code\game\gamemodes\cult\structures\pylon.dm"
#include "code\game\gamemodes\cult\structures\structure.dm"
#include "code\game\gamemodes\endgame\endgame.dm"
#include "code\game\gamemodes\endgame\bluespace_jump\bluespace_jump.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\blob.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\universe.dm"

View File

@@ -71,6 +71,7 @@
//#define SS_PRIORITY_DEFAULT 50 // This is defined somewhere else.
#define SS_PRIORITY_PSYCHICS 30
#define SS_PRIORITY_ARRIVALS 30 // Centcomm arrivals shuttle auto-launch. Usually asleep.
#define SS_PRIORITY_EVAC 30 // Processes the evac controller.
#define SS_PRIORITY_EXPLOSIVES 20 // Explosion processor. Doesn't have much effect on explosion tick-checking.
#define SS_PRIORITY_DISPOSALS 20 // Disposal holder movement.
#define SS_PRIORITY_MODIFIER 10

View File

@@ -110,7 +110,7 @@
AI.ai_announcement()
/obj/screen/ai/call_shuttle
name = "Call Emergency Shuttle"
name = "Call Evacuation"
icon_state = "call_shuttle"
screen_loc = ui_ai_shuttle

View File

@@ -1,308 +0,0 @@
var/datum/controller/subsystem/emergency_shuttle/emergency_shuttle
/datum/controller/subsystem/emergency_shuttle
name = "Emergency Shuttle"
flags = SS_NO_TICK_CHECK | SS_NO_INIT
var/datum/shuttle/autodock/ferry/emergency/shuttle
var/launch_time //the time at which the shuttle will be launched
var/force_time //the time at which the shuttle will be forced
var/auto_recall = 0 //if set, the shuttle will be auto-recalled
var/auto_recall_time //the time at which the shuttle will be auto-recalled
var/evac = 0 //1 = emergency evacuation, 0 = crew transfer
var/wait_for_launch = 0 //if the shuttle is waiting to launch
var/wait_for_force = 0 //if the shuttle is waiting to be forced
var/autopilot = 1 //set to 0 to disable the shuttle automatically launching
var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called
var/departed = 0 //if the shuttle has left the station at least once
/datum/controller/subsystem/emergency_shuttle/Recover()
// Just copy all the stuff over.
src.shuttle = emergency_shuttle.shuttle
src.launch_time = emergency_shuttle.launch_time
src.auto_recall = emergency_shuttle.auto_recall
src.auto_recall_time = emergency_shuttle.auto_recall_time
src.evac = emergency_shuttle.evac
src.wait_for_launch = emergency_shuttle.wait_for_launch
src.autopilot = emergency_shuttle.autopilot
src.deny_shuttle = emergency_shuttle.deny_shuttle
/datum/controller/subsystem/emergency_shuttle/New()
NEW_SS_GLOBAL(emergency_shuttle)
/datum/controller/subsystem/emergency_shuttle/fire()
if(!shuttle)
return
if (wait_for_launch)
if (evac && auto_recall && world.time >= auto_recall_time)
recall()
if (world.time >= launch_time) //time to launch the shuttle
stop_launch_countdown()
if (!shuttle.location) //leaving from the station
//launch the pods!
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (!pod.arming_controller || pod.arming_controller.armed)
pod.launch(src)
if (autopilot)
shuttle.launch(src)
if (wait_for_force)
if (world.time > force_time)
stop_force_countdown()
if(waiting_to_leave())
shuttle.launch(src)
shuttle.force_launch(src)
/datum/controller/subsystem/emergency_shuttle/proc/shuttle_arrived()
if (!shuttle.location) //at station
if (autopilot)
set_launch_countdown(SHUTTLE_LEAVETIME) //get ready to return
if (evac)
set_force_countdown(SHUTTLE_FORCETIME)
priority_announcement.Announce(replacetext(current_map.emergency_shuttle_docked_message, "%ETD%", round(estimate_launch_time()/60,1)), new_sound = 'sound/AI/emergencyshuttledock.ogg')
else
set_force_countdown(SHUTTLE_LEAVETIME)
var/list/fields = list(
"%ETA%" = round(emergency_shuttle.estimate_launch_time()/60,1),
"%dock%" = current_map.dock_name
)
priority_announcement.Announce(replacemany(current_map.shuttle_docked_message, fields), new_sound = 'sound/AI/shuttledock.ogg')
//arm the escape pods
if (evac)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
//begins the launch countdown and sets the amount of time left until launch
/datum/controller/subsystem/emergency_shuttle/proc/set_launch_countdown(var/seconds)
wait_for_launch = 1
launch_time = world.time + seconds*10
//begins the launch countdown and sets the amount of time left until launch
/datum/controller/subsystem/emergency_shuttle/proc/set_force_countdown(var/seconds)
if(!wait_for_force)
wait_for_force = 1
force_time = world.time + seconds*10
/datum/controller/subsystem/emergency_shuttle/proc/stop_launch_countdown()
wait_for_launch = 0
/datum/controller/subsystem/emergency_shuttle/proc/stop_force_countdown()
wait_for_force = 0
//calls the shuttle for an emergency evacuation
/datum/controller/subsystem/emergency_shuttle/proc/call_evac()
if(!can_call()) return
//set the launch timer
autopilot = 1
set_launch_countdown(get_shuttle_prep_time())
auto_recall_time = rand(world.time + 300, launch_time - 300)
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
evac = 1
priority_announcement.Announce(replacetext(current_map.emergency_shuttle_called_message, "%ETA%", round(estimate_arrival_time()/60)), new_sound = 'sound/AI/emergencyshuttlecalled.ogg')
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyalert()
//calls the shuttle for a routine crew transfer
/datum/controller/subsystem/emergency_shuttle/proc/call_transfer()
if(!can_call()) return
//set the launch timer
autopilot = 1
set_launch_countdown(get_shuttle_prep_time())
auto_recall_time = rand(world.time + 300, launch_time - 300)
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
var/list/replacements = list(
"%ETA%" = round(estimate_arrival_time()/60),
"%dock%" = current_map.dock_name
)
priority_announcement.Announce(replacemany(current_map.shuttle_called_message, replacements), new_sound = 'sound/AI/shuttlecalled.ogg')
//recalls the shuttle
/datum/controller/subsystem/emergency_shuttle/proc/recall()
if (!can_recall()) return
wait_for_launch = 0
shuttle.cancel_launch(src)
if (evac)
priority_announcement.Announce(current_map.emergency_shuttle_recall_message, new_sound = 'sound/AI/emergencyshuttlerecalled.ogg')
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyreset()
evac = 0
else
priority_announcement.Announce(current_map.shuttle_recall_message, new_sound = 'sound/AI/shuttlerecalled.ogg')
/datum/controller/subsystem/emergency_shuttle/proc/can_call()
if (!universe.OnShuttleCall(null))
return 0
if (deny_shuttle)
return 0
if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom
return 0
if (wait_for_launch) //already launching
return 0
return 1
//this only returns 0 if it would absolutely make no sense to recall
//e.g. the shuttle is already at the station or wasn't called to begin with
//other reasons for the shuttle not being recallable should be handled elsewhere
/datum/controller/subsystem/emergency_shuttle/proc/can_recall()
if (shuttle.moving_status == SHUTTLE_INTRANSIT) //if the shuttle is already in transit then it's too late
return 0
if (!shuttle.location) //already at the station.
return 0
if (!wait_for_launch) //we weren't going anywhere, anyways...
return 0
return 1
/datum/controller/subsystem/emergency_shuttle/proc/get_shuttle_prep_time()
// During mutiny rounds, the shuttle takes twice as long.
if(SSticker.mode)
return SHUTTLE_PREPTIME * SSticker.mode.shuttle_delay
return SHUTTLE_PREPTIME
/*
These procs are not really used by the controller itself, but are for other parts of the
game whose logic depends on the emergency shuttle.
*/
//returns 1 if the shuttle is docked at the station and waiting to leave
/datum/controller/subsystem/emergency_shuttle/proc/waiting_to_leave()
if(!shuttle)
return
if (shuttle.location)
return 0 //not at station
return (wait_for_launch || shuttle.moving_status != SHUTTLE_INTRANSIT)
//so we don't have emergency_shuttle.shuttle.location everywhere
/datum/controller/subsystem/emergency_shuttle/proc/location()
if (!shuttle)
return 1 //if we dont have a shuttle datum, just act like it's at centcom
return shuttle.location
//returns the time left until the shuttle arrives at it's destination, in seconds
/datum/controller/subsystem/emergency_shuttle/proc/estimate_arrival_time()
var/eta
if (shuttle.has_arrive_time())
//we are in transition and can get an accurate ETA
eta = shuttle.arrive_time
else
//otherwise we need to estimate the arrival time using the scheduled launch time
eta = launch_time + shuttle.move_time*10 + shuttle.warmup_time*10
return (eta - world.time)/10
//returns the time left until the shuttle launches, in seconds
/datum/controller/subsystem/emergency_shuttle/proc/estimate_launch_time()
return (launch_time - world.time)/10
/datum/controller/subsystem/emergency_shuttle/proc/has_eta()
if(!shuttle)
return
return (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
//returns 1 if the shuttle has gone to the station and come back at least once,
//used for game completion checking purposes
/datum/controller/subsystem/emergency_shuttle/proc/returned()
return (departed && shuttle.moving_status == SHUTTLE_IDLE && shuttle.location) //we've gone to the station at least once, no longer in transit and are idle back at centcom
//returns 1 if the shuttle is not idle at centcom
/datum/controller/subsystem/emergency_shuttle/proc/online()
if (isnull(shuttle))
return FALSE
if (!shuttle.location) //not at centcom
return TRUE
if (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
return TRUE
return FALSE
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
/datum/controller/subsystem/emergency_shuttle/proc/going_to_station()
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
/datum/controller/subsystem/emergency_shuttle/proc/going_to_centcom()
return (shuttle && shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
/datum/controller/subsystem/emergency_shuttle/proc/get_status_panel_eta()
if (online())
if (shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
return "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
if (waiting_to_leave())
if (shuttle.moving_status == SHUTTLE_WARMUP)
return "Departing..."
var/timeleft = emergency_shuttle.estimate_launch_time()
return "ETD-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
return ""
/*
Some slapped-together star effects for maximum spess immershuns. Basically consists of a
spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction
until they reach a starender.
*/
/obj/effect/bgstar
name = "star"
var/speed = 10
var/direction = SOUTH
layer = 2 // TURF_LAYER
/obj/effect/bgstar/New()
..()
pixel_x += rand(-2,30)
pixel_y += rand(-2,30)
var/starnum = pick("1", "1", "1", "2", "3", "4")
icon_state = "star"+starnum
speed = rand(2, 5)
/obj/effect/bgstar/proc/startmove()
while(src)
sleep(speed)
step(src, direction)
for(var/obj/effect/starender/E in loc)
qdel(src)
return
/obj/effect/starender
invisibility = 101
/obj/effect/starspawner
invisibility = 101
var/spawndir = SOUTH
var/spawning = 0
/obj/effect/starspawner/West
spawndir = WEST
/obj/effect/starspawner/proc/startspawn()
spawning = 1
while(spawning)
sleep(rand(2, 30))
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
S.direction = spawndir
spawn()
S.startmove()

View File

@@ -0,0 +1,17 @@
var/datum/controller/subsystem/evac/SSevac
/datum/controller/subsystem/evac
name = "Evacuation"
priority = SS_PRIORITY_EVAC
//Initializes at default time
flags = SS_NO_TICK_CHECK|SS_BACKGROUND
wait = 2 SECONDS
/datum/controller/subsystem/evac/Initialize()
. = ..()
if(!evacuation_controller)
evacuation_controller = new current_map.evac_controller_type ()
evacuation_controller.set_up()
/datum/controller/subsystem/evac/fire()
evacuation_controller.process()

View File

@@ -0,0 +1,183 @@
#define EVAC_IDLE 0
#define EVAC_PREPPING 1
#define EVAC_LAUNCHING 2
#define EVAC_IN_TRANSIT 3
#define EVAC_COOLDOWN 4
#define EVAC_COMPLETE 5
var/datum/evacuation_controller/evacuation_controller
/datum/evacuation_controller
var/name = "generic evac controller"
var/state = EVAC_IDLE
var/deny
var/recall
var/auto_recall_time
var/emergency_evacuation
var/evac_prep_delay = 10 MINUTES
var/evac_launch_delay = 3 MINUTES
var/evac_transit_delay = 2 MINUTES
var/autotransfer_prep_additional_delay = 0 MINUTES
var/emergency_prep_additional_delay = 0 MINUTES
var/transfer_prep_additional_delay = 0 MINUTES
var/force_time = 0 MINUTES
var/wait_for_force = FALSE //If the evac is waiting to be forced
var/evac_cooldown_time
var/evac_called_at
var/evac_no_return
var/evac_ready_time
var/evac_launch_time
var/evac_arrival_time
var/list/evacuation_predicates = list()
var/list/evacuation_options = list()
var/datum/announcement/priority/evac_waiting = new(0)
var/datum/announcement/priority/evac_called = new(0)
var/datum/announcement/priority/evac_recalled = new(0)
/datum/evacuation_controller/proc/auto_recall(var/_recall)
recall = _recall
/datum/evacuation_controller/proc/set_up()
set waitfor=0
set background=1
/datum/evacuation_controller/proc/get_cooldown_message()
return "An evacuation cannot be called at this time. Please wait another [round((evac_cooldown_time-world.time)/600)] minute\s before trying again."
/datum/evacuation_controller/proc/add_can_call_predicate(var/datum/evacuation_predicate/esp)
if(esp in evacuation_predicates)
CRASH("[esp] has already been added as an evacuation predicate")
evacuation_predicates += esp
/datum/evacuation_controller/proc/call_evacuation(var/mob/user, var/_emergency_evac, var/forced, var/skip_announce, var/autotransfer)
if(state != EVAC_IDLE)
return FALSE
if(!can_evacuate(user, forced))
return FALSE
emergency_evacuation = _emergency_evac
var/evac_prep_delay_multiplier = 1
if(SSticker.mode)
evac_prep_delay_multiplier = SSticker.mode.shuttle_delay
var/additional_delay
if(_emergency_evac)
additional_delay = emergency_prep_additional_delay
else if(autotransfer)
additional_delay = autotransfer_prep_additional_delay
else
additional_delay = transfer_prep_additional_delay
evac_called_at = world.time
evac_no_return = evac_called_at + round(evac_prep_delay/2) + additional_delay
evac_ready_time = evac_called_at + (evac_prep_delay*evac_prep_delay_multiplier) + additional_delay
evac_launch_time = evac_ready_time + evac_launch_delay
evac_arrival_time = evac_launch_time + evac_transit_delay
var/evac_range = round((evac_launch_time - evac_called_at)/3)
auto_recall_time = rand(evac_called_at + evac_range, evac_launch_time - evac_range)
state = EVAC_PREPPING
if(emergency_evacuation)
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyalert()
if(!skip_announce)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_called_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"), new_sound = 'sound/AI/emergencyshuttlecalled.ogg')
else
if(!skip_announce)
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_called_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"), new_sound = 'sound/AI/shuttlecalled.ogg')
return TRUE
/datum/evacuation_controller/proc/cancel_evacuation()
if(!can_cancel())
return FALSE
evac_cooldown_time = world.time + (world.time - evac_called_at)
state = EVAC_COOLDOWN
evac_ready_time = null
evac_arrival_time = null
evac_no_return = null
evac_called_at = null
evac_launch_time = null
auto_recall_time = null
if(emergency_evacuation)
evac_recalled.Announce(current_map.emergency_shuttle_recall_message)
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyreset()
emergency_evacuation = 0
else
priority_announcement.Announce(current_map.shuttle_recall_message)
return TRUE
/datum/evacuation_controller/proc/finish_preparing_evac()
state = EVAC_LAUNCHING
var/estimated_time = round(get_eta()/60,1)
if (emergency_evacuation)
evac_waiting.Announce(replacetext(current_map.emergency_shuttle_docked_message, "%ETA%", "[estimated_time] minute\s"), new_sound = sound('sound/AI/emergencyshuttledock.ogg'))
else
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_docked_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"), new_sound = sound('sound/AI/shuttledock.ogg'))
/datum/evacuation_controller/proc/launch_evacuation()
if(waiting_to_leave())
return
state = EVAC_IN_TRANSIT
if (emergency_evacuation)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
else
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_leaving_dock, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
return TRUE
/datum/evacuation_controller/proc/finish_evacuation()
state = EVAC_COMPLETE
/datum/evacuation_controller/process()
if(state == EVAC_PREPPING && recall && world.time >= auto_recall_time)
cancel_evacuation()
return
if(state == EVAC_PREPPING)
if(world.time >= evac_ready_time)
finish_preparing_evac()
else if(state == EVAC_LAUNCHING)
if(world.time >= evac_launch_time)
launch_evacuation()
else if(state == EVAC_IN_TRANSIT)
if(world.time >= evac_arrival_time)
finish_evacuation()
else if(state == EVAC_COOLDOWN)
if(world.time >= evac_cooldown_time)
state = EVAC_IDLE
/datum/evacuation_controller/proc/available_evac_options()
return list()
/datum/evacuation_controller/proc/handle_evac_option(var/option_target, var/mob/user)
var/datum/evacuation_option/selected = evacuation_options[option_target]
if (!isnull(selected) && istype(selected))
selected.execute(user)
/datum/evacuation_controller/proc/get_evac_option(var/option_target)
return null
/datum/evacuation_controller/proc/should_call_autotransfer_vote()
return (state == EVAC_IDLE)

View File

@@ -0,0 +1,22 @@
/datum/evacuation_controller/proc/get_status_panel_eta()
if(waiting_to_leave())
return "Delayed"
var/timeleft = get_eta()
if(timeleft < 0)
return ""
return "[is_on_cooldown() ? "Returning" : (is_arriving() ? "ETA" : "ETD")] [add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/datum/evacuation_controller/proc/has_eta()
return (state == EVAC_PREPPING || state == EVAC_LAUNCHING || state == EVAC_IN_TRANSIT || state == EVAC_COOLDOWN)
/datum/evacuation_controller/proc/get_eta()
if(state == EVAC_PREPPING)
return (evac_ready_time ? (evac_ready_time - world.time)/10 : -1)
else if(state == EVAC_LAUNCHING)
return (evac_launch_time ? (evac_launch_time - world.time)/10 : -1)
else if(state == EVAC_IN_TRANSIT)
return (evac_arrival_time ? (evac_arrival_time - world.time)/10 : -1)
else if(state == EVAC_COOLDOWN)
return (evac_cooldown_time ? (evac_cooldown_time - world.time)/10 : -1)
return -1

View File

@@ -0,0 +1,68 @@
/datum/evacuation_controller/proc/set_launch_time(var/val)
evac_launch_time = val
/datum/evacuation_controller/proc/set_arrival_time(var/val)
evac_arrival_time = val
/datum/evacuation_controller/proc/is_prepared()
return (state == EVAC_LAUNCHING)
/datum/evacuation_controller/proc/is_in_transit()
return (state == EVAC_IN_TRANSIT)
/datum/evacuation_controller/proc/is_idle()
return (state == EVAC_IDLE)
/datum/evacuation_controller/proc/has_evacuated()
return (!isnull(evac_launch_time) && world.time > evac_launch_time)
/datum/evacuation_controller/proc/round_over()
return state == EVAC_COMPLETE
/datum/evacuation_controller/proc/is_on_cooldown()
return state == EVAC_COOLDOWN
/datum/evacuation_controller/proc/is_evacuating()
return state != EVAC_IDLE
/datum/evacuation_controller/proc/can_evacuate(var/mob/user, var/forced)
if(!isnull(evac_called_at))
return FALSE
if (!universe.OnShuttleCall(null))
return FALSE
if(!forced)
for(var/predicate in evacuation_predicates)
var/datum/evacuation_predicate/esp = predicate
if(!esp.is_valid())
evacuation_predicates -= esp
qdel(esp)
else
if(!esp.can_call(user))
return FALSE
return TRUE
/datum/evacuation_controller/proc/waiting_to_leave()
return FALSE
/datum/evacuation_controller/proc/can_cancel()
// Are we evacuating?
if(isnull(evac_called_at))
return FALSE
// Have we already launched?
if(state != EVAC_PREPPING)
return FALSE
// Are we already committed?
if(world.time > evac_no_return)
return FALSE
return TRUE
/datum/evacuation_controller/proc/is_arriving()
if(state == EVAC_LAUNCHING)
return FALSE
return has_eta()
/datum/evacuation_controller/proc/is_departing()
if(state == EVAC_LAUNCHING)
return TRUE

View File

@@ -0,0 +1,28 @@
#define EVAC_OPT_ABANDON_SHIP "abandon_ship"
#define EVAC_OPT_CANCEL_ABANDON_SHIP "cancel_abandon_ship"
/datum/evacuation_controller/lifepods
name = "escape pod controller"
evac_prep_delay = 7 MINUTES
evac_launch_delay = 0
evac_transit_delay = 2 MINUTES
evacuation_options = list(
EVAC_OPT_ABANDON_SHIP = new /datum/evacuation_option/abandon_ship(),
EVAC_OPT_CANCEL_ABANDON_SHIP = new /datum/evacuation_option/cancel_abandon_ship(),
)
/datum/evacuation_controller/lifepods/launch_evacuation()
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
/datum/evacuation_controller/lifepods/available_evac_options()
if (is_on_cooldown())
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_ABANDON_SHIP])
if (is_evacuating())
return list(evacuation_options[EVAC_OPT_CANCEL_ABANDON_SHIP])
#undef EVAC_OPT_ABANDON_SHIP
#undef EVAC_OPT_CANCEL_ABANDON_SHIP

View File

@@ -0,0 +1,10 @@
/datum/evacuation_option
var/option_text = "Generic evac option"
var/option_desc = "do something that should never be seen"
var/option_target = "generic"
var/needs_syscontrol = FALSE
var/silicon_allowed = TRUE
var/abandon_ship = FALSE
/datum/evacuation_option/proc/execute(var/mob/user)
return

View File

@@ -0,0 +1,145 @@
#define EVAC_OPT_ABANDON_SHIP "abandon_ship"
#define EVAC_OPT_BLUESPACE_JUMP "bluespace_jump"
#define EVAC_OPT_CANCEL_ABANDON_SHIP "cancel_abandon_ship"
#define EVAC_OPT_CANCEL_BLUESPACE_JUMP "cancel_bluespace_jump"
// Apparently, emergency_evacuation --> "abandon ship" and !emergency_evacuation --> "bluespace jump"
// That stuff should be moved to the evacuation option datums but someone can do that later
/datum/evacuation_controller/starship
name = "escape pod controller"
evac_prep_delay = 5 MINUTES
evac_launch_delay = 3 MINUTES
evac_transit_delay = 2 MINUTES
transfer_prep_additional_delay = 5 MINUTES
autotransfer_prep_additional_delay = 5 MINUTES
emergency_prep_additional_delay = 0 MINUTES
evacuation_options = list(
EVAC_OPT_ABANDON_SHIP = new /datum/evacuation_option/abandon_ship(),
EVAC_OPT_BLUESPACE_JUMP = new /datum/evacuation_option/bluespace_jump(),
EVAC_OPT_CANCEL_ABANDON_SHIP = new /datum/evacuation_option/cancel_abandon_ship(),
EVAC_OPT_CANCEL_BLUESPACE_JUMP = new /datum/evacuation_option/cancel_bluespace_jump()
)
/datum/evacuation_controller/starship/finish_preparing_evac()
. = ..()
// Arm the escape pods.
if (emergency_evacuation)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
/datum/evacuation_controller/starship/launch_evacuation()
state = EVAC_IN_TRANSIT
if (emergency_evacuation)
// Abondon Ship
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods) // Launch the pods!
if (!pod.arming_controller || pod.arming_controller.armed)
pod.move_time = (evac_transit_delay/10)
pod.launch(src)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
else
// Bluespace Jump
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
SetUniversalState(/datum/universal_state/bluespace_jump, arguments=list(current_map.station_levels))
/datum/evacuation_controller/starship/finish_evacuation()
..()
if(!emergency_evacuation) //bluespace jump
SetUniversalState(/datum/universal_state) //clear jump state
/datum/evacuation_controller/starship/available_evac_options()
if (is_on_cooldown())
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_BLUESPACE_JUMP], evacuation_options[EVAC_OPT_ABANDON_SHIP])
if (is_evacuating())
if (emergency_evacuation)
return list(evacuation_options[EVAC_OPT_CANCEL_ABANDON_SHIP])
else
return list(evacuation_options[EVAC_OPT_CANCEL_BLUESPACE_JUMP])
/datum/evacuation_option/abandon_ship
option_text = "Abandon spacecraft"
option_desc = "abandon the spacecraft"
option_target = EVAC_OPT_ABANDON_SHIP
needs_syscontrol = TRUE
silicon_allowed = TRUE
abandon_ship = TRUE
/datum/evacuation_option/abandon_ship/execute(mob/user)
if (!evacuation_controller)
return
if (evacuation_controller.deny)
to_chat(user, "Unable to initiate escape procedures.")
return
if (evacuation_controller.is_on_cooldown())
to_chat(user, evacuation_controller.get_cooldown_message())
return
if (evacuation_controller.is_evacuating())
to_chat(user, "Escape procedures already in progress.")
return
if (evacuation_controller.call_evacuation(user, 1))
log_and_message_admins("[user? key_name(user) : "Autotransfer"] has initiated abandonment of the spacecraft.")
/datum/evacuation_option/bluespace_jump
option_text = "Initiate bluespace jump"
option_desc = "initiate a bluespace jump"
option_target = EVAC_OPT_BLUESPACE_JUMP
needs_syscontrol = TRUE
silicon_allowed = TRUE
/datum/evacuation_option/bluespace_jump/execute(mob/user)
if (!evacuation_controller)
return
if (evacuation_controller.deny)
to_chat(user, "Unable to initiate jump preparation.")
return
if (evacuation_controller.is_on_cooldown())
to_chat(user, evacuation_controller.get_cooldown_message())
return
if (evacuation_controller.is_evacuating())
to_chat(user, "Jump preparation already in progress.")
return
if (evacuation_controller.call_evacuation(user, 0))
log_and_message_admins("[user? key_name(user) : "Autotransfer"] has initiated bluespace jump preparation.")
/datum/evacuation_option/cancel_abandon_ship
option_text = "Cancel abandonment"
option_desc = "cancel abandonment of the spacecraft"
option_target = EVAC_OPT_CANCEL_ABANDON_SHIP
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/cancel_abandon_ship/execute(mob/user)
if (evacuation_controller && evacuation_controller.cancel_evacuation())
log_and_message_admins("[key_name(user)] has cancelled abandonment of the spacecraft.")
/datum/evacuation_option/cancel_bluespace_jump
option_text = "Cancel bluespace jump"
option_desc = "cancel the jump preparation"
option_target = EVAC_OPT_CANCEL_BLUESPACE_JUMP
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/cancel_bluespace_jump/execute(mob/user)
if (evacuation_controller && evacuation_controller.cancel_evacuation())
log_and_message_admins("[key_name(user)] has cancelled the bluespace jump.")
/obj/screen/fullscreen/bluespace_overlay
icon = 'icons/effects/effects.dmi'
icon_state = "mfoam"
screen_loc = "WEST,SOUTH to EAST,NORTH"
color = "#ff9900"
blend_mode = BLEND_SUBTRACT
layer = SCREEN_LAYER
#undef EVAC_OPT_ABANDON_SHIP
#undef EVAC_OPT_BLUESPACE_JUMP
#undef EVAC_OPT_CANCEL_ABANDON_SHIP
#undef EVAC_OPT_CANCEL_BLUESPACE_JUMP

View File

@@ -0,0 +1,13 @@
/datum/evacuation_predicate/New()
return
/datum/evacuation_predicate/Destroy(forced)
if(forced)
return ..()
return QDEL_HINT_LETMELIVE
/datum/evacuation_predicate/proc/is_valid()
return FALSE
/datum/evacuation_predicate/proc/can_call(var/user)
return TRUE

View File

@@ -0,0 +1,149 @@
#define EVAC_OPT_CALL_SHUTTLE "call_shuttle"
#define EVAC_OPT_RECALL_SHUTTLE "recall_shuttle"
/datum/evacuation_controller/shuttle
name = "escape shuttle controller"
evac_waiting = new(0, new_sound = sound('sound/AI/shuttledock.ogg'))
evac_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg'))
evac_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg'))
emergency_prep_additional_delay = 0 MINUTES
transfer_prep_additional_delay = 0 MINUTES
evacuation_options = list(
EVAC_OPT_CALL_SHUTTLE = new /datum/evacuation_option/call_shuttle(),
EVAC_OPT_RECALL_SHUTTLE = new /datum/evacuation_option/recall_shuttle()
)
var/departed = 0
var/autopilot = 1
var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm
var/shuttle_launch_time
/datum/evacuation_controller/shuttle/has_evacuated()
return departed
/datum/evacuation_controller/shuttle/waiting_to_leave()
return (!autopilot || (shuttle && shuttle.is_launching()))
/datum/evacuation_controller/shuttle/launch_evacuation()
if(waiting_to_leave())
return
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (!pod.arming_controller || pod.arming_controller.armed)
pod.move_time = evac_transit_delay
pod.launch(src)
if(autopilot && shuttle.moving_status == SHUTTLE_IDLE)
evac_arrival_time = world.time + (shuttle.move_time*10) + (shuttle.warmup_time*10)
shuttle.launch(src)
// Announcements, state changes and such are handled by the shuttle itself to prevent desync.
/datum/evacuation_controller/shuttle/finish_preparing_evac()
departed = 1
evac_launch_time = world.time + evac_launch_delay
set_force_countdown(SHUTTLE_FORCETIME)
. = ..()
// Arm the escape pods.
if (emergency_evacuation)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
/datum/evacuation_controller/shuttle/call_evacuation(var/mob/user, var/_emergency_evac, var/forced, var/skip_announce, var/autotransfer)
if(..())
autopilot = 1
shuttle_launch_time = evac_no_return
evac_ready_time += shuttle.warmup_time*10
return 1
return 0
/datum/evacuation_controller/shuttle/cancel_evacuation()
if(..() && shuttle.moving_status != SHUTTLE_INTRANSIT)
shuttle_launch_time = null
shuttle.cancel_launch(src)
return 1
return 0
/datum/evacuation_controller/shuttle/get_eta()
if (shuttle && shuttle.has_arrive_time())
return (shuttle.arrive_time-world.time)/10
return ..()
/datum/evacuation_controller/shuttle/get_status_panel_eta()
if(has_eta() && waiting_to_leave())
return "Launching..."
return ..()
// This is largely handled by the emergency shuttle datum.
/datum/evacuation_controller/shuttle/process()
if(state == EVAC_PREPPING)
if(!isnull(shuttle_launch_time) && world.time > shuttle_launch_time && shuttle.moving_status == SHUTTLE_IDLE)
shuttle.launch()
shuttle_launch_time = null
return
else if(state == EVAC_IN_TRANSIT)
return
return ..()
/datum/evacuation_controller/shuttle/can_cancel()
return (shuttle.moving_status == SHUTTLE_IDLE && shuttle.location && ..())
/datum/evacuation_controller/shuttle/proc/shuttle_leaving()
state = EVAC_IN_TRANSIT
/datum/evacuation_controller/shuttle/proc/shuttle_evacuated()
state = EVAC_COMPLETE
/datum/evacuation_controller/shuttle/proc/shuttle_preparing()
state = EVAC_PREPPING
/datum/evacuation_controller/shuttle/proc/get_long_jump_time()
if (shuttle.location)
return round(evac_prep_delay/10)/2
else
return round(evac_transit_delay/10)
//begins the launch countdown and sets the amount of time left until launch
/datum/evacuation_controller/proc/set_force_countdown(var/seconds)
if(!wait_for_force)
wait_for_force = TRUE
force_time = world.time + seconds*10
/datum/evacuation_controller/proc/stop_force_countdown()
wait_for_force = TRUE
/datum/evacuation_controller/shuttle/available_evac_options()
if (!shuttle.location)
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_CALL_SHUTTLE])
else
return list(evacuation_options[EVAC_OPT_RECALL_SHUTTLE])
/datum/evacuation_option/call_shuttle
option_text = "Call emergency shuttle"
option_desc = "call the emergency shuttle"
option_target = EVAC_OPT_CALL_SHUTTLE
needs_syscontrol = TRUE
silicon_allowed = TRUE
/datum/evacuation_option/call_shuttle/execute(mob/user)
call_shuttle_proc(user)
/datum/evacuation_option/recall_shuttle
option_text = "Cancel shuttle call"
option_desc = "recall the emergency shuttle"
option_target = EVAC_OPT_RECALL_SHUTTLE
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/recall_shuttle/execute(mob/user)
cancel_call_proc(user)
#undef EVAC_OPT_CALL_SHUTTLE
#undef EVAC_OPT_RECALL_SHUTTLE

View File

@@ -0,0 +1,5 @@
#undef EVAC_IDLE
#undef EVAC_PREPPING
#undef EVAC_IN_TRANSIT
#undef EVAC_COOLDOWN
#undef EVAC_COMPLETE

View File

@@ -351,7 +351,7 @@
SearchVar(SScargo)
SearchVar(SSeconomy)
SearchVar(SSeffects)
SearchVar(emergency_shuttle)
SearchVar(evacuation_controller)
SearchVar(SSevents)
SearchVar(SSexplosives)
SearchVar(SSgarbage)

View File

@@ -168,10 +168,10 @@ var/datum/controller/subsystem/ticker/SSticker
game_finished = TRUE
mode_finished = TRUE
else if(config.continous_rounds)
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
game_finished = (evacuation_controller.round_over() || mode.station_was_nuked)
mode_finished = (!post_game && mode.check_finished())
else
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended
game_finished = (mode.check_finished() || (evacuation_controller.round_over() && evacuation_controller.emergency_evacuation)) || universe_has_ended
mode_finished = game_finished
if(!mode.explosion_in_progress && game_finished && (mode_finished || post_game))
@@ -243,7 +243,7 @@ var/datum/controller/subsystem/ticker/SSticker
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD)
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(evacuation_controller.round_over() && evacuation_controller.emergency_evacuation)
if(isNotAdminLevel(playerTurf.z))
to_chat(Player, "<span class='notice'><b>You managed to survive, but were marooned on [station_name()] as [Player.real_name]...</b></span>")
else

View File

@@ -109,7 +109,7 @@ var/list/global_webhooks = list()
emb["description"] += data["antags"]
if(data["survivours"] > 0)
emb["description"] += "There [data["survivours"]>1 ? "were **[data["survivours"]] survivors**" : "was **one survivor**"]"
emb["description"] += " ([data["escaped"]>0 ? data["escaped"] : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]) and **[data["ghosts"]] ghosts**."
emb["description"] += " ([data["escaped"]>0 ? data["escaped"] : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]) and **[data["ghosts"]] ghosts**."
else
emb["description"] += "There were **no survivors** ([data["ghosts"]] ghosts)."
OutData["embeds"] = list(emb)

View File

@@ -61,11 +61,11 @@
data["character_name"] = user.client.prefs.real_name
var/shuttle_status = ""
if(emergency_shuttle) //In case Nanotrasen decides to reposess CentComm's shuttles.
if(emergency_shuttle.going_to_centcom()) //Shuttle is going to centcomm, not recalled
if(evacuation_controller) //In case Nanotrasen decides to reposess CentComm's shuttles.
if(evacuation_controller.has_evacuated()) //Shuttle is going to centcomm, not recalled
shuttle_status = "post-evac"
if(emergency_shuttle.online())
if (emergency_shuttle.evac) // Emergency shuttle is past the point of no recall
if(evacuation_controller.is_evacuating())
if (evacuation_controller.emergency_evacuation) // Emergency shuttle is past the point of no recall
shuttle_status = "evac"
else // Crew transfer initiated
shuttle_status = "transfer"

View File

@@ -0,0 +1,41 @@
// Observer Pattern Implementation: Direction Set
// Registration type: /atom
//
// Raised when: An /atom changes dir using the set_dir() proc.
//
// Arguments that the called proc should expect:
// /atom/dir_changer: The instance that changed direction
// /old_dir: The dir before the change.
// /new_dir: The dir after the change.
var/datum/observ/dir_set/dir_set_event = new()
/datum/observ/dir_set
name = "Direction Set"
expected_type = /atom
/datum/observ/dir_set/register(var/atom/dir_changer, var/datum/listener, var/proc_call)
. = ..()
// Listen to the parent if possible.
if(. && istype(dir_changer.loc, /atom/movable)) // We don't care about registering to turfs.
register(dir_changer.loc, dir_changer, /atom/proc/recursive_dir_set)
/*********************
* Direction Handling *
*********************/
/atom/set_dir()
var/old_dir = dir
UNLINT(. = ..())
if(old_dir != dir)
dir_set_event.raise_event(src, old_dir, dir)
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
. = ..()
if(dir_set_event.has_listeners(am))
dir_set_event.register(src, am, /atom/proc/recursive_dir_set)
/atom/movable/Exited(var/atom/movable/am, atom/new_loc)
. = ..()
dir_set_event.unregister(src, am, /atom/proc/recursive_dir_set)

View File

@@ -11,4 +11,11 @@
/atom/movable/proc/move_to_loc_or_null(var/atom/movable/am, var/old_loc, var/new_loc)
if(new_loc != loc)
forceMove(new_loc)
forceMove(new_loc)
/atom/proc/recursive_dir_set(var/atom/a, var/old_dir, var/new_dir)
set_dir(new_dir)
// Sometimes you just want to end yourself
/datum/proc/qdel_self()
qdel(src)

View File

@@ -232,6 +232,9 @@
if(anchored)
return
if(!universe.OnTouchMapEdge(src))
return
if(current_map.use_overmap)
overmap_spacetravel(get_turf(src), src)

View File

@@ -56,9 +56,9 @@ var/global/list/narsie_list = list()
narsie_cometh = 1
spawn(10 SECONDS)
if(emergency_shuttle)
emergency_shuttle.call_evac()
emergency_shuttle.launch_time = 0 // Cannot recall
if(evacuation_controller)
evacuation_controller.call_evacuation(null, TRUE, 1)
evacuation_controller.evac_no_return = 0 // Cannot recall
/obj/singularity/narsie/process()
eat()

View File

@@ -0,0 +1,148 @@
/datum/universal_state/bluespace_jump
name = "Bluespace Jump"
var/list/bluespaced = list()
var/list/bluegoasts = list()
var/list/affected_levels
var/list/old_accessible_z_levels
/datum/universal_state/bluespace_jump/New(var/list/zlevels)
affected_levels = zlevels
/datum/universal_state/bluespace_jump/OnEnter()
var/space_zlevel = current_map.get_empty_zlevel() //get a place for stragglers
for(var/mob/living/M in mob_list)
if(M.z in affected_levels)
var/area/A = get_area(M)
if(istype(A,/area/space)) //straggler
var/turf/T = locate(M.x, M.y, space_zlevel)
if(T)
M.forceMove(T)
else
apply_bluespaced(M)
for(var/mob/abstract/observer/goast in player_list)
goast.mouse_opacity = 0 //can't let you click that Dave
goast.invisibility = SEE_INVISIBLE_LIVING
goast.alpha = 255
old_accessible_z_levels = current_map.accessible_z_levels.Copy()
for(var/z in affected_levels)
current_map.accessible_z_levels -= "[z]" //not accessible during the jump
/datum/universal_state/bluespace_jump/OnExit()
for(var/mob/M in bluespaced)
if(!QDELETED(M))
clear_bluespaced(M)
bluespaced.Cut()
current_map.accessible_z_levels = old_accessible_z_levels
old_accessible_z_levels = null
/datum/universal_state/bluespace_jump/OnPlayerLatejoin(var/mob/living/M)
if(M.z in affected_levels)
apply_bluespaced(M)
/datum/universal_state/bluespace_jump/OnTouchMapEdge(var/atom/A)
if((A.z in affected_levels) && (A in bluespaced))
if(ismob(A))
to_chat(A,"<span class='warning'>You drift away into the shifting expanse, never to be seen again.</span>")
qdel(A) //lost in bluespace
return FALSE
return TRUE
/datum/universal_state/bluespace_jump/proc/apply_bluespaced(var/mob/living/M)
bluespaced += M
if(M.client)
to_chat(M,"<span class='notice'>You feel oddly light, and somewhat disoriented as everything around you shimmers and warps ever so slightly.</span>")
M.overlay_fullscreen("bluespace", /obj/screen/fullscreen/bluespace_overlay)
M.confused = 20
bluegoasts += new/obj/effect/bluegoast/(get_turf(M),M)
/datum/universal_state/bluespace_jump/proc/clear_bluespaced(var/mob/living/M)
if(M.client)
to_chat(M,"<span class='notice'>You feel rooted in material world again.</span>")
M.clear_fullscreen("bluespace")
M.confused = 0
for(var/mob/abstract/observer/goast in player_list)
goast.mouse_opacity = initial(goast.mouse_opacity)
goast.invisibility = goast.invisibility
goast.alpha = initial(goast.alpha)
for(var/G in bluegoasts)
qdel(G)
bluegoasts.Cut()
/obj/effect/bluegoast
name = "bluespace echo"
desc = "It's not going to punch you, is it?"
var/mob/living/carbon/human/daddy
anchored = TRUE
var/reality = 0
simulated = FALSE
/obj/effect/bluegoast/New(nloc, ndaddy)
..(nloc)
if(!ndaddy)
qdel(src)
return
daddy = ndaddy
set_dir(daddy.dir)
appearance = daddy.appearance
moved_event.register(daddy, src, /obj/effect/bluegoast/proc/mirror)
dir_set_event.register(daddy, src, /obj/effect/bluegoast/proc/mirror_dir)
destroyed_event.register(daddy, src, /datum/proc/qdel_self)
/obj/effect/bluegoast/Destroy()
destroyed_event.unregister(daddy, src)
dir_set_event.unregister(daddy, src)
moved_event.unregister(daddy, src)
daddy = null
. = ..()
/obj/effect/bluegoast/proc/mirror(var/atom/movable/am, var/old_loc, var/new_loc)
var/ndir = get_dir(new_loc,old_loc)
appearance = daddy.appearance
var/nloc = get_step(src, ndir)
if(nloc)
forceMove(nloc)
if(nloc == new_loc)
reality++
if(reality > 5)
to_chat(daddy, "<span class='notice'>Yep, it's certainly the other one. Your existance was a glitch, and it's finally being mended...</span>")
blueswitch()
else if(reality > 3)
to_chat(daddy, "<span class='danger'>Something is definitely wrong. Why do you think YOU are the original?</span>")
else
to_chat(daddy, "<span class='warning'>You feel a bit less real. Which one of you two was original again?..</span>")
/obj/effect/bluegoast/proc/mirror_dir(var/atom/movable/am, var/old_dir, var/new_dir)
set_dir(reverse_dir[new_dir])
/obj/effect/bluegoast/examine()
return daddy?.examine(arglist(args))
/obj/effect/bluegoast/proc/blueswitch()
var/mob/living/carbon/human/H
if(ishuman(daddy))
H = new(get_turf(src), daddy.species.name)
H.dna = daddy.dna.Clone()
H.sync_organ_dna()
H.UpdateAppearance()
for(var/obj/item/entry in daddy.get_equipped_items(TRUE))
daddy.remove_from_mob(entry) //steals instead of copies so we don't end up with duplicates
H.equip_to_appropriate_slot(entry)
else
H = new daddy.type(get_turf(src))
H.appearance = daddy.appearance
H.real_name = daddy.real_name
H.flavor_text = daddy.flavor_text
daddy.dust()
qdel(src)
/obj/screen/fullscreen/bluespace_overlay
icon = 'icons/effects/effects.dmi'
icon_state = "mfoam"
screen_loc = "WEST,SOUTH to EAST,NORTH"
color = "#ff9900"
alpha = 100
blend_mode = BLEND_SUBTRACT
layer = SCREEN_LAYER

View File

@@ -63,10 +63,19 @@
/datum/universal_state/proc/OverlayAndAmbientSet()
return
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1)
/datum/universal_state/proc/OnPlayerLatejoin(var/mob/living/M)
return
/datum/universal_state/proc/OnTouchMapEdge(var/atom/A)
return TRUE //return FALSE to cancel map edge handling
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1, list/arguments=null)
if(on_exit)
universe.OnExit()
universe = new newstate
if(arguments)
universe = new newstate(arglist(arguments))
else
universe = new newstate
if(on_enter)
universe.OnEnter()

View File

@@ -45,9 +45,8 @@ var/global/universe_has_ended = 0
for(var/mob/M in player_list)
M.flash_eyes()
if(emergency_shuttle.can_recall())
priority_announcement.Announce("The emergency shuttle has returned due to bluespace distortion.")
emergency_shuttle.recall()
if(evacuation_controller.cancel_evacuation())
priority_announcement.Announce("The evacuation has been aborted due to bluespace distortion.")
AreaSet()
MiscSet()

View File

@@ -284,8 +284,8 @@ var/global/list/additional_antag_types = list()
if(!(antag.flags & ANTAG_NO_ROUNDSTART_SPAWN))
antag.finalize_spawn() //actually spawn antags
if(emergency_shuttle && auto_recall_shuttle)
emergency_shuttle.auto_recall = 1
if(evacuation_controller && auto_recall_shuttle)
evacuation_controller.auto_recall(1)
feedback_set_details("round_start","[time2text(world.realtime)]")
if(SSticker.mode)
@@ -335,14 +335,14 @@ var/global/list/additional_antag_types = list()
command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission")
/datum/game_mode/proc/check_finished()
if(emergency_shuttle.returned() || station_was_nuked)
if(evacuation_controller.round_over() || station_was_nuked)
return 1
if(end_on_antag_death && antag_templates && antag_templates.len)
for(var/datum/antagonist/antag in antag_templates)
if(!antag.antags_are_dead())
return 0
if(config.continous_rounds)
emergency_shuttle.auto_recall = 0
evacuation_controller.auto_recall(1)
return 0
return 1
return 0
@@ -421,10 +421,10 @@ var/global/list/additional_antag_types = list()
var/text = ""
if(surviving_total > 0)
text += "<br>There [surviving_total>1 ? "were <b>[surviving_total] survivors</b>" : "was <b>one survivor</b>"]"
text += " (<b>[escaped_total>0 ? escaped_total : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]</b>) and <b>[ghosts] ghosts</b>.<br>"
text += " (<b>[escaped_total>0 ? escaped_total : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]</b>) and <b>[ghosts] ghosts</b>.<br>"
discord_text += "There [surviving_total>1 ? "were **[surviving_total] survivors**" : "was **one survivor**"]"
discord_text += " ([escaped_total>0 ? escaped_total : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]) and **[ghosts] ghosts**."
discord_text += " ([escaped_total>0 ? escaped_total : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]) and **[ghosts] ghosts**."
else
text += "There were <b>no survivors</b> (<b>[ghosts] ghosts</b>)."

View File

@@ -6,7 +6,7 @@
///process()
///Called by the gameticker
/datum/game_mode/process()
if(round_autoantag && world.time >= next_spawn && !emergency_shuttle.departed)
if(round_autoantag && world.time >= next_spawn && !evacuation_controller.round_over())
process_autoantag()
// Process loop for objectives like the brig one.
@@ -21,7 +21,7 @@
/datum/game_mode/proc/process_autoantag()
message_admins("[uppertext(name)]: Attempting autospawn.")
if(emergency_shuttle.online())
if(evacuation_controller.is_evacuating())
message_admins("[uppertext(name)]: An evac or transfer shuttle is on the way. Aborted.")
next_spawn = world.time + min_autotraitor_delay
return

View File

@@ -267,7 +267,7 @@ datum
explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the Centcom station alive. We'll handle the rest from there."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(target.current.stat == 2)
return 0
@@ -313,7 +313,7 @@ datum
explanation_text = "[target.current.real_name], the [target.assigned_role] is a [pick("relative of a","friend of a","") + pick("high ranking","important","well-liked")] mercenary [pick("Leader","Officer","Agent","sympathiser")]. Make sure they get off the station safely, while minimizing intervention."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(target.current.stat == 2)
@@ -477,7 +477,7 @@ datum
explanation_text = "Hijack the emergency shuttle by escaping alone."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat == 2)
@@ -512,7 +512,7 @@ datum
explanation_text = "Escape on the shuttle alive, without being arrested."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat ==2)
@@ -1230,7 +1230,7 @@ datum
check_completion()
if(!istype(owner.current, /mob/living/silicon))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current)
return 0
@@ -1455,7 +1455,7 @@ datum/objective/silence
explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
var/area/shuttle = locate(/area/shuttle/escape/centcom)

View File

@@ -42,7 +42,7 @@ var/list/nuke_disks = list()
if(!is_type_in_list(disk_area, centcom_areas))
disk_rescued = 0
break
var/crew_evacuated = (emergency_shuttle.returned())
var/crew_evacuated = (evacuation_controller.round_over())
if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
feedback_set_details("round_end_result","win - syndicate nuke")

View File

@@ -230,7 +230,7 @@ datum/objective/hijack
check_completion()
if(!owner.current || owner.current.stat)
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(issilicon(owner.current))
return 0
@@ -252,7 +252,7 @@ datum/objective/block
check_completion()
if(!istype(owner.current, /mob/living/silicon))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current)
return 0
@@ -270,7 +270,7 @@ datum/objective/silence
explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
for(var/mob/living/player in player_list)
@@ -295,7 +295,7 @@ datum/objective/escape
return 0
if(isbrain(owner.current))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat ==2)
return 0

View File

@@ -13,5 +13,5 @@
/datum/game_mode/sandbox/post_setup()
..()
if(emergency_shuttle)
emergency_shuttle.auto_recall = 1
if(evacuation_controller)
evacuation_controller.auto_recall(1)

View File

@@ -10,8 +10,17 @@
attackby(var/obj/item/card/W as obj, var/mob/user as mob)
if(stat & (BROKEN|NOPOWER)) return
if ((!( istype(W, /obj/item/card) ) || !(ROUND_IS_STARTED) || emergency_shuttle.location() || !( user ))) return
if(stat & (BROKEN|NOPOWER))
return
var/datum/evacuation_controller/shuttle/evac_control = evacuation_controller
if(!istype(evac_control))
to_chat(user, SPAN_DANGER("This console should not in use on this map. Please report this to a developer."))
return
if ((!( istype(W, /obj/item/card) ) || !( SSticker ) || evacuation_controller.has_evacuated() || !( user )))
return
if (W.GetID())
var/obj/item/card/id/id = W
@@ -29,7 +38,7 @@
return 0
var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort")
if(emergency_shuttle.location() && user.get_active_hand() != id)
if(evacuation_controller.is_prepared() && user.get_active_hand() != id)
return 0
switch(choice)
if("Authorize")
@@ -43,7 +52,7 @@
message_admins("[key_name_admin(user)] has launched the shuttle")
log_game("[key_name(user)] has launched the shuttle early",ckey=key_name(user))
to_world("<span class='notice'><b>Alert: Shuttle launch time shortened to 10 seconds!</b></span>")
emergency_shuttle.set_launch_countdown(10)
evacuation_controller.set_launch_time(world.time+100)
//src.authorized = null
qdel(src.authorized)
src.authorized = list( )
@@ -60,11 +69,11 @@
else if (istype(W, /obj/item/card/emag) && !emagged)
var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel")
if(!emagged && !emergency_shuttle.location() && user.get_active_hand() == W)
if(!emagged && !evacuation_controller.is_prepared() && user.get_active_hand() == W)
switch(choice)
if("Launch")
to_world("<span class='notice'><b>Alert: Shuttle launch time shortened to 10 seconds!</b></span>")
emergency_shuttle.set_launch_countdown(10)
evacuation_controller.set_launch_time(world.time+100)
emagged = 1
if("Cancel")
return

View File

@@ -86,22 +86,23 @@
if(STATUS_DISPLAY_BLANK) //blank
return 1
if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer
if(emergency_shuttle.waiting_to_leave())
message1 = "-ETD-"
if (emergency_shuttle.shuttle.is_launching())
message2 = "Launch"
else
message2 = get_shuttle_timer_departure()
if(evacuation_controller)
if(evacuation_controller.is_prepared())
message1 = "-ETD-"
if (evacuation_controller.waiting_to_leave())
message2 = "Launch"
else
message2 = get_shuttle_timer()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
else if(evacuation_controller.has_eta())
message1 = "-ETA-"
message2 = get_shuttle_timer()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
else if(emergency_shuttle.has_eta())
message1 = "-ETA-"
message2 = get_shuttle_timer_arrival()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
return 1
update_display(message1, message2)
return 1
if(STATUS_DISPLAY_MESSAGE) //custom messages
var/line1
var/line2
@@ -165,14 +166,8 @@
if(maptext != new_text)
maptext = new_text
/obj/machinery/status_display/proc/get_shuttle_timer_arrival()
var/timeleft = emergency_shuttle.estimate_arrival_time()
if(timeleft < 0)
return ""
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/obj/machinery/status_display/proc/get_shuttle_timer_departure()
var/timeleft = emergency_shuttle.estimate_launch_time()
/obj/machinery/status_display/proc/get_shuttle_timer()
var/timeleft = evacuation_controller.get_eta()
if(timeleft < 0)
return ""
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"

View File

@@ -3,22 +3,15 @@
var/dat = ""
dat += "Current Game Mode: <b>[SSticker.mode.name]</b><br>"
dat += "Round Duration: [get_round_duration_formatted()]<br>"
dat += "<b>Emergency Shuttle</b><br>"
if (!emergency_shuttle.online())
dat += "<vui-button :params=\"{ call_shuttle: 1 }\">Call Shuttle</vui-button><br>"
dat += "<b>Evacuation</b><br>"
if (evacuation_controller.is_idle())
dat += "<vui-button :params=\"{ call_shuttle: 1 }\">Call Evacuation</vui-button><br>"
else
if (emergency_shuttle.wait_for_launch)
var/timeleft = emergency_shuttle.estimate_launch_time()
dat += "ETL: <vui-button :params=\"{ edit_shuttle_time: 1 }\">[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</vui-button><br>"
else if (emergency_shuttle.shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
dat += "ETA: <vui-button :params=\"{ edit_shuttle_time: 1 }\">[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</vui-button><br>"
var/timeleft = evacuation_controller.get_eta()
if (evacuation_controller.waiting_to_leave())
dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]<BR>"
dat += "<a href='?src=\ref[src];call_shuttle=2'>Send Back</a><br>"
if (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP)
dat += "Launching now...<br>"
dat += "<vui-button :params=\"{ delay_round_end: 1 }\">[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]</vui-button><br>"
dat += "<hr>"
for(var/antag_type in all_antag_types)

View File

@@ -112,53 +112,19 @@
else if(href_list["call_shuttle"])
if(!check_rights(R_ADMIN)) return
if( SSticker.mode.name == "blob" )
alert("You can't call the shuttle during blob!")
return
switch(href_list["call_shuttle"])
if("1")
if ((!( ROUND_IS_STARTED ) || !emergency_shuttle.location()))
return
if (emergency_shuttle.can_call())
emergency_shuttle.call_evac()
log_admin("[key_name(usr)] called the Emergency Shuttle",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>", 1)
if (evacuation_controller.call_evacuation(usr, TRUE))
log_admin("[key_name(usr)] called an evacuation.")
message_admins("[key_name_admin(usr)] called an evacuation.", 1)
if("2")
if (!( ROUND_IS_STARTED ) || !emergency_shuttle.location())
return
if (emergency_shuttle.can_call())
emergency_shuttle.call_evac()
log_admin("[key_name(usr)] called the Emergency Shuttle",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>", 1)
else if (emergency_shuttle.can_recall())
emergency_shuttle.recall()
log_admin("[key_name(usr)] sent the Emergency Shuttle back",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] sent the Emergency Shuttle back</span>", 1)
href_list["secretsadmin"] = "check_antagonist"
else if(href_list["edit_shuttle_time"])
if(!check_rights(R_SERVER)) return
if (emergency_shuttle.wait_for_launch)
var/new_time_left = input("Enter new shuttle launch countdown (seconds):","Edit Shuttle Launch Time", emergency_shuttle.estimate_launch_time() ) as num
emergency_shuttle.launch_time = world.time + new_time_left*10
log_admin("[key_name(usr)] edited the Emergency Shuttle's launch time to [new_time_left]",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] edited the Emergency Shuttle's launch time to [new_time_left*10]</span>", 1)
else if (emergency_shuttle.shuttle.has_arrive_time())
var/new_time_left = input("Enter new shuttle arrival time (seconds):","Edit Shuttle Arrival Time", emergency_shuttle.estimate_arrival_time() ) as num
emergency_shuttle.shuttle.arrive_time = world.time + new_time_left*10
log_admin("[key_name(usr)] edited the Emergency Shuttle's arrival time to [new_time_left]",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] edited the Emergency Shuttle's arrival time to [new_time_left*10]</span>", 1)
else
alert("The shuttle is neither counting down to launch nor is it in transit. Please try again when it is.")
if (evacuation_controller.call_evacuation(usr, TRUE))
log_admin("[key_name(usr)] called an evacuation.")
message_admins("[key_name_admin(usr)] called an evacuation.", 1)
else if (evacuation_controller.cancel_evacuation())
log_admin("[key_name(usr)] cancelled an evacuation.")
message_admins("[key_name_admin(usr)] cancelled an evacuation.", 1)
href_list["secretsadmin"] = "check_antagonist"

View File

@@ -888,67 +888,62 @@ Traitors and the like can also be revived with the previous role mostly intact.
/client/proc/admin_call_shuttle()
set category = "Admin"
set name = "Call Shuttle"
set name = "Call Evacuation"
if ((!( ROUND_IS_STARTED ) || !emergency_shuttle.location()))
if ((!( ROUND_IS_STARTED ) || !evacuation_controller))
return
if(!check_rights(R_ADMIN)) return
if(!check_rights(R_ADMIN))
return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
if(alert(src, "Are you sure?", "Confirm", "Yes", "No") != "Yes")
return
var/choice
if(SSticker.mode.auto_recall_shuttle)
choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel")
if(choice == "Confirm")
emergency_shuttle.auto_recall = 1 //enable auto-recall
else
if(input("The evacuation will just be cancelled if you call it. Call anyway?") in list("Confirm", "Cancel") != "Confirm")
return
choice = input("Is this an emergency evacuation or a crew transfer?") in list("Emergency", "Crew Transfer")
if (choice == "Emergency")
emergency_shuttle.call_evac()
else
emergency_shuttle.call_transfer()
var/choice = input("Is this an emergency evacuation or a crew transfer?") in list("Emergency", "Crew Transfer")
evacuation_controller.call_evacuation(usr, (choice == "Emergency"))
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-called the emergency shuttle.</span>", 1)
log_admin("[key_name(usr)] admin-called an evacuation.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-called an evacuation</span>", 1)
return
/client/proc/admin_cancel_shuttle()
set category = "Admin"
set name = "Cancel Shuttle"
set name = "Cancel Evacuation"
if(!check_rights(R_ADMIN)) return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
if(!ROUND_IS_STARTED || !emergency_shuttle.can_recall())
if(!ROUND_IS_STARTED || !evacuation_controller)
return
emergency_shuttle.recall()
evacuation_controller.cancel_evacuation()
feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-recalled the emergency shuttle.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-recalled the emergency shuttle.</span>", 1)
log_admin("[key_name(usr)] admin-cancelled the evacuation.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-cancelled the evacuation.</span>", 1)
return
/client/proc/admin_deny_shuttle()
set category = "Admin"
set name = "Toggle Deny Shuttle"
set name = "Toggle Deny Evacuation"
if (!ROUND_IS_STARTED)
return
if(!check_rights(R_ADMIN)) return
if(!check_rights(R_ADMIN))
return
emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle
evacuation_controller.deny = !evacuation_controller.deny
log_admin("[key_name(src)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.",admin_key=key_name(usr))
message_admins("[key_name_admin(usr)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.")
log_admin("[key_name(src)] has [evacuation_controller.deny ? "denied" : "allowed"] the evacuation to be called.",admin_key=key_name(usr))
message_admins("[key_name_admin(usr)] has [evacuation_controller.deny ? "denied" : "allowed"] the evacuation to be called.")
/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list)
set category = "Special Verbs"

View File

@@ -52,8 +52,8 @@
if(wired && screwed)
to_chat(usr, "You check your watch, spotting a digital collection of numbers reading '[worldtime2text()]'. Today's date is '[time2text(world.time, "Month DD")]. [game_year]'.")
if (emergency_shuttle.get_status_panel_eta())
to_chat(usr, SPAN_WARNING("The shuttle's status is reported as: [emergency_shuttle.get_status_panel_eta()]."))
if (evacuation_controller.get_status_panel_eta())
to_chat(usr, SPAN_WARNING("The shuttle's status is reported as: [evacuation_controller.get_status_panel_eta()]."))
else if(wired && !screwed)
to_chat(usr, "You check your watch, realising it's still open.")
else

View File

@@ -172,6 +172,7 @@
disable()
if(welcome_message)
to_chat(user, SPAN_NOTICE(welcome_message))
universe.OnPlayerLatejoin(user)
return TRUE
//Proc to check if a specific user can edit this spawner (open/close/...)

View File

@@ -177,7 +177,7 @@
if(start_location.landmark_tag != "nav_emergency_start")
return TRUE
if(emergency_shuttle.evac)
if(evacuation_controller.emergency_evacuation)
if(get_security_level() != "green" )
var/datum/wifi/sender/door/wifi_sender = new("odin_arrivals_lockdown", SSghostroles)
wifi_sender.activate("close")

View File

@@ -279,6 +279,7 @@ INITIALIZE_IMMEDIATE(/mob/abstract/new_player)
character.buckled_to.set_dir(character.dir)
SSticker.mode.handle_latejoin(character)
universe.OnPlayerLatejoin(character)
if(SSjobs.ShouldCreateRecords(character.mind))
if(character.mind.assigned_role != "Cyborg")
SSrecords.generate_record(character)

View File

@@ -266,8 +266,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/abstract/observer/Stat()
..()
if(statpanel("Status"))
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)

View File

@@ -185,8 +185,8 @@
if(statpanel("Status"))
stat("Intent:", "[a_intent]")
stat("Move Mode:", "[m_intent]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if(is_diona() && DS)

View File

@@ -429,12 +429,12 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/ai_call_shuttle()
set category = "AI Commands"
set name = "Call Emergency Shuttle"
set name = "Call Evacuation"
if(check_unable(AI_CHECK_WIRELESS))
return
var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No")
var/confirm = alert("Are you sure you want to call the evacuation?", "Confirm Evacuation", "Yes", "No")
if(check_unable(AI_CHECK_WIRELESS))
return
@@ -442,17 +442,16 @@ var/list/ai_verbs_default = list(
if(confirm == "Yes")
call_shuttle_proc(src)
if(emergency_shuttle.online())
post_display_status("shuttle")
post_display_status("shuttle")
/mob/living/silicon/ai/proc/ai_recall_shuttle()
set category = "AI Commands"
set name = "Recall Emergency Shuttle"
set name = "Cancel Evacuation"
if(check_unable(AI_CHECK_WIRELESS))
return
var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No")
var/confirm = alert("Are you sure you want to cancel the evacuation?", "Confirm Cancel", "Yes", "No")
if(check_unable(AI_CHECK_WIRELESS))
return

View File

@@ -176,8 +176,8 @@
// this function displays the shuttles ETA in the status panel if the shuttle has been called
/mob/living/silicon/proc/show_emergency_shuttle_eta()
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)

View File

@@ -102,8 +102,8 @@
..()
statpanel("Status")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)

View File

@@ -353,7 +353,7 @@ mob/living/simple_animal/hostile/hitby(atom/movable/AM as mob|obj,var/speed = TH
/mob/living/simple_animal/hostile/proc/check_horde()
if(emergency_shuttle.shuttle.location)
if(evacuation_controller.is_prepared())
if(!enroute && !target_mob) //The shuttle docked, all monsters rush for the escape hallway
if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick
shuttletarget = pick(escape_list) //Pick a shuttle target

View File

@@ -92,14 +92,18 @@
if(current_viewing_message)
data["message_current"] = current_viewing_message
if(emergency_shuttle.location())
data["have_shuttle"] = TRUE
if(emergency_shuttle.online())
data["have_shuttle_called"] = TRUE
else
data["have_shuttle_called"] = FALSE
else
data["have_shuttle"] = FALSE
var/list/processed_evac_options = list()
if(!isnull(evacuation_controller))
for (var/datum/evacuation_option/EO in evacuation_controller.available_evac_options())
if(EO.abandon_ship)
continue
var/list/option = list()
option["option_text"] = EO.option_text
option["option_target"] = EO.option_target
option["needs_syscontrol"] = EO.needs_syscontrol
option["silicon_allowed"] = EO.silicon_allowed
processed_evac_options[++processed_evac_options.len] = option
data["evac_options"] = processed_evac_options
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
@@ -206,16 +210,18 @@
log_say("[key_name(usr)] has sent a message to [current_map.boss_short]: [input]", ckey = key_name(usr))
centcomm_message_cooldown = TRUE
addtimer(CALLBACK(src, .proc/set_centcomm_message_cooldown, FALSE), 300) // thirty second cooldown
if("shuttle")
if(is_authenticated(user) && ntn_cont && can_call_shuttle())
if(href_list["target"] == "call")
var/confirm = alert("Are you sure you want to call the shuttle?", name, "No", "Yes")
if(confirm == "Yes" && can_still_topic())
call_shuttle_proc(usr)
if(href_list["target"] == "cancel" && !issilicon(usr))
var/confirm = alert("Are you sure you want to cancel the shuttle?", name, "No", "Yes")
if(confirm == "Yes" && can_still_topic())
cancel_call_proc(usr)
if("evac")
if(is_authenticated(user))
var/datum/evacuation_option/selected_evac_option = evacuation_controller.evacuation_options[href_list["target"]]
if (isnull(selected_evac_option) || !istype(selected_evac_option))
return
if (!selected_evac_option.silicon_allowed && issilicon(user))
return
if (selected_evac_option.needs_syscontrol && !ntn_cont)
return
var/confirm = alert("Are you sure you want to [selected_evac_option.option_desc]?", name, "No", "Yes")
if (confirm == "Yes" && can_still_topic())
evacuation_controller.handle_evac_option(selected_evac_option.option_target, user)
if("setstatus")
if(is_authenticated(user) && ntn_cont)
switch(href_list["target"])
@@ -358,15 +364,13 @@ Command action procs
//Returns 1 if recalled 0 if not
/proc/cancel_call_proc(var/mob/user)
if(!(ROUND_IS_STARTED) || !emergency_shuttle.can_recall())
if(!(ROUND_IS_STARTED) || !evacuation_controller)
return FALSE
if((SSticker.mode.name == "blob")||(SSticker.mode.name == "Meteor"))
if(SSticker.mode.name == "Meteor")
return FALSE
if(!emergency_shuttle.going_to_centcom()) //check that shuttle isn't already heading to centcomm
emergency_shuttle.recall()
log_game("[key_name(user)] has recalled the shuttle.", key_name(user))
message_admins("[key_name_admin(user)] has recalled the shuttle.", 1)
if(evacuation_controller.cancel_evacuation())
log_and_message_admins("has cancelled the evacuation.", user)
return TRUE
return FALSE
@@ -379,77 +383,46 @@ Command action procs
//Returns 1 if called 0 if not
/proc/call_shuttle_proc(var/mob/user)
if((!(ROUND_IS_STARTED) || !emergency_shuttle.location()))
if((!(ROUND_IS_STARTED) || !evacuation_controller))
return FALSE
if(!universe.OnShuttleCall(usr))
to_chat(user, SPAN_WARNING("Cannot establish a bluespace connection."))
to_chat(user, SPAN_WARNING("A bluespace connection cannot be established! Please check the user manual for more information."))
return FALSE
if(emergency_shuttle.deny_shuttle)
to_chat(user, SPAN_WARNING("The emergency shuttle cannot be sent at this time. Please try again later."))
if(evacuation_controller.deny)
to_chat(user, SPAN_WARNING("An evacuation cannot be sent at this time. Please try again later."))
return FALSE
if(world.time < config.time_to_call_emergency_shuttle)
to_chat(user, SPAN_WARNING("The emergency shuttle is refueling. Please wait another [round((config.time_to_call_emergency_shuttle-world.time)/600)] minute\s before trying again."))
to_chat(user, SPAN_WARNING("An evacuation cannot be sent at this time. Please wait another [round((config.time_to_call_emergency_shuttle-world.time)/600)] minute\s before trying again."))
return FALSE
if(emergency_shuttle.going_to_centcom())
to_chat(user, SPAN_WARNING("The emergency shuttle cannot be called while returning to [current_map.boss_short]."))
return FALSE
if(evacuation_controller.is_on_cooldown()) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE
to_chat(user, evacuation_controller.get_cooldown_message())
if(emergency_shuttle.online())
to_chat(user, SPAN_WARNING("The emergency shuttle is already on its way."))
return FALSE
if(evacuation_controller.is_evacuating())
to_chat(user, "An evacuation is already underway.")
return
if(SSticker.mode.name == "blob")
to_chat(user, SPAN_WARNING("Under directive 7-10, [station_name()] is quarantined until further notice."))
return FALSE
emergency_shuttle.call_evac()
log_game("[key_name(user)] has called the shuttle.",ckey=key_name(user))
message_admins("[key_name_admin(user)] has called the shuttle.", 1)
if(evacuation_controller.call_evacuation(user))
log_and_message_admins("[user? key_name(user) : "Autotransfer"] has called the shuttle.")
return TRUE
/proc/init_shift_change(var/mob/user, var/force = FALSE)
if ((!(ROUND_IS_STARTED) || !emergency_shuttle.location()))
if ((!(ROUND_IS_STARTED) || !evacuation_controller))
return
if(emergency_shuttle.going_to_centcom())
to_chat(user, SPAN_WARNING("The shuttle cannot be called while returning to [current_map.boss_short]."))
if (!evacuation_controller)
return
if(emergency_shuttle.online())
to_chat(user, SPAN_WARNING("The shuttle is already on its way."))
return
// if force is 0, some things may stop the shuttle call
if(!force)
if(emergency_shuttle.deny_shuttle)
to_chat(user, SPAN_WARNING("[current_map.boss_short] does not currently have a shuttle available in your sector. Please try again later."))
return
if(world.time < 54000) // 30 minute grace period to let the game get going
to_chat(user, SPAN_WARNING("The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again."))
return
if(SSticker.mode.auto_recall_shuttle)
//New version pretends to call the shuttle but cause the shuttle to return after a random duration.
emergency_shuttle.auto_recall = TRUE
if(SSticker.mode.name == "blob" || SSticker.mode.name == "epidemic")
to_chat(user, SPAN_WARNING("Under directive 7-10, [station_name()] is quarantined until further notice."))
return
emergency_shuttle.call_transfer()
. = evacuation_controller.call_evacuation(null, _emergency_evac = FALSE, autotransfer = TRUE)
//delay events in case of an autotransfer
if(!user)
if(.)
SSevents.delay_events(EVENT_LEVEL_MODERATE, 10200) //17 minutes
SSevents.delay_events(EVENT_LEVEL_MAJOR, 10200)
log_game("[user? key_name(user) : "Autotransfer"] has called the shuttle.")
message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1)
return
message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1)

View File

@@ -82,8 +82,8 @@
return FALSE
to_chat(owner, SPAN_NOTICE("Hello [user], it is currently: '[worldtime2text()]'. Today's date is '[time2text(world.time, "Month DD")]. [game_year]'. Have a lovely day."))
if (emergency_shuttle.get_status_panel_eta())
to_chat(owner, SPAN_WARNING("Notice: You have one (1) scheduled flight, ETA: [emergency_shuttle.get_status_panel_eta()]."))
if (evacuation_controller.get_status_panel_eta())
to_chat(owner, SPAN_WARNING("Notice: You have one (1) scheduled flight, ETA: [evacuation_controller.get_status_panel_eta()]."))
/obj/item/organ/internal/augment/tool
name = "retractable widget"

View File

@@ -1,4 +1,5 @@
var/list/escape_pods = list()
var/list/escape_pods_by_name = list()
/datum/shuttle/autodock/ferry/escape_pod
var/datum/computer/file/embedded_program/docking/simple/escape_pod/arming_controller
@@ -13,6 +14,8 @@ var/list/escape_pods = list()
CRASH("Could not find arming controller for escape pod \"[name]\", tag was '[arming_controller_tag]'.")
escape_pods += src
escape_pods_by_name[name] = src
move_time = evacuation_controller.evac_transit_delay + rand(-30, 60)
if(dock_target)
var/datum/computer/file/embedded_program/docking/simple/own_target = SSshuttle.docking_registry[dock_target]
if(own_target)
@@ -48,7 +51,7 @@ var/list/escape_pods = list()
"override_enabled" = docking_program.override_enabled,
"door_state" = docking_program.memory["door_status"]["state"],
"door_lock" = docking_program.memory["door_status"]["lock"],
"can_force" = pod.can_force() || (emergency_shuttle.departed && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves
"can_force" = pod.can_force() || (evacuation_controller.has_evacuated() && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves
"is_armed" = pod.arming_controller.armed
)
@@ -69,7 +72,7 @@ var/list/escape_pods = list()
if(href_list["force_launch"])
if (pod.can_force())
pod.force_launch(src)
else if (emergency_shuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves
else if (evacuation_controller.has_evacuated() && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves
pod.launch(src)
return 0

View File

@@ -1,39 +1,37 @@
/datum/shuttle/autodock/ferry/emergency
//pass
category = /datum/shuttle/autodock/ferry/emergency
move_time = 10 MINUTES
var/datum/evacuation_controller/shuttle/emergency_controller
/datum/shuttle/autodock/ferry/emergency/New()
..()
if(emergency_shuttle.shuttle)
emergency_controller = evacuation_controller
if(!istype(emergency_controller))
CRASH("Escape shuttle created without the appropriate controller type.")
if(emergency_controller.shuttle)
CRASH("An emergency shuttle has already been created.")
emergency_shuttle.shuttle = src
emergency_controller.shuttle = src
/datum/shuttle/autodock/ferry/emergency/arrived()
. = ..()
if(!emergency_controller.has_evacuated())
emergency_controller.finish_preparing_evac()
if (istype(in_use, /obj/machinery/computer/shuttle_control/emergency))
var/obj/machinery/computer/shuttle_control/emergency/C = in_use
C.reset_authorization()
emergency_shuttle.shuttle_arrived()
if((current_location == waypoint_offsite) && emergency_controller.has_evacuated())
emergency_controller.shuttle_evacuated()
/datum/shuttle/autodock/ferry/emergency/long_jump(var/obj/effect/shuttle_landmark/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time)
var/time_to_go = SHUTTLE_TRANSIT_DURATION
if(destination == waypoint_offsite)
time_to_go = SHUTTLE_TRANSIT_DURATION_RETURN
..(destination, interim, time_to_go)
emergency_shuttle.launch_time = world.time
..(destination, interim, emergency_controller.get_long_jump_time(), direction)
/datum/shuttle/autodock/ferry/emergency/shuttle_moved()
if (!emergency_shuttle.departed && next_location != waypoint_station) //leaving the station
var/list/replacements = list(
"%ETA%" = round(emergency_shuttle.estimate_arrival_time()/60,1),
"%dock%" = current_map.dock_name
)
if (emergency_shuttle.evac)
priority_announcement.Announce(replacemany(current_map.emergency_shuttle_leaving_dock, replacements))
else
priority_announcement.Announce(replacemany(current_map.shuttle_leaving_dock, replacements))
emergency_shuttle.departed = TRUE
if(next_location != waypoint_station)
emergency_controller.shuttle_leaving() // This is a hell of a line. v
priority_announcement.Announce(replacetext(replacetext((emergency_controller.emergency_evacuation ? current_map.emergency_shuttle_leaving_dock : current_map.shuttle_leaving_dock), "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(emergency_controller.get_eta()/60,1)] minute\s"))
..()
/datum/shuttle/autodock/ferry/emergency/can_launch(var/user)
@@ -54,6 +52,8 @@
return ..()
/datum/shuttle/autodock/ferry/emergency/can_cancel(var/user)
if(emergency_controller.has_evacuated())
return 0
//If we try to cancel it via the shuttle computer
if (istype(user, /obj/machinery/computer/shuttle_control/emergency))
var/obj/machinery/computer/shuttle_control/emergency/C = user
@@ -62,8 +62,8 @@
return 0
// If the emergency shuttle is waiting to leave the station and the world time exceeded the force time
if(emergency_shuttle.waiting_to_leave() && (world.time > emergency_shuttle.force_time))
return 0
if(evacuation_controller.is_prepared() && (world.time > emergency_controller.force_time))
return 0
return ..()
@@ -72,8 +72,8 @@
return
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
if (emergency_controller.autopilot)
emergency_controller.autopilot = FALSE
to_world("<span class='notice'><b>Alert: The shuttle autopilot has been overridden. Launch sequence initiated!</b></span>")
if(usr)
@@ -87,8 +87,8 @@
return
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
if (emergency_controller.autopilot)
emergency_controller.autopilot = FALSE
to_world("<span class='notice'><b>Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!</b></span>")
if(usr)
@@ -102,8 +102,8 @@
return
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
if (emergency_shuttle.autopilot)
emergency_shuttle.autopilot = 0
if (emergency_controller.autopilot)
emergency_controller.autopilot = FALSE
to_world("<span class='notice'><b>Alert: The shuttle autopilot has been overridden. Launch sequence aborted!</b></span>")
if(usr)

View File

@@ -17,7 +17,7 @@
s["roundduration"] = get_round_duration_formatted()
s["gameid"] = game_id
s["game_state"] = SSticker ? 0 : SSticker.current_state
s["transferring"] = !!(emergency_shuttle?.online())
s["transferring"] = !!(evacuation_controller.is_evacuating())
s["players"] = clients.len
s["staff"] = staff.len

View File

@@ -0,0 +1,41 @@
################################
# 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: MattAtlas
# 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:
- experiment: "Ported Baystation's evacuation controller for eventual usage in the NBT. There may be some evacuation or transfer shuttle weirdness. Make sure to report it on GitHub."

View File

@@ -50,6 +50,8 @@
var/emergency_shuttle_recall_message
var/emergency_shuttle_called_message
var/evac_controller_type = /datum/evacuation_controller
var/list/station_networks = list() // Camera networks that will show up on the console.
var/list/holodeck_programs = list() // map of string ids to /datum/holodeck_program instances

View File

@@ -58,14 +58,16 @@
NETWORK_SUPPLY
)
shuttle_docked_message = "The scheduled crew transfer shuttle to %dock% has docked with the station. It will depart in approximately %ETA% minutes."
shuttle_leaving_dock = "The crew transfer shuttle has left the station. Estimate %ETA% minutes until the shuttle docks at %dock%."
shuttle_called_message = "A crew transfer to %dock% has been scheduled. The shuttle has been called. It will arrive in approximately %ETA% minutes."
shuttle_docked_message = "The scheduled crew transfer shuttle to %dock% has docked with the station. It will depart in approximately %ETA%."
shuttle_leaving_dock = "The crew transfer shuttle has left the station. Estimate %ETA% until the shuttle docks at %dock%."
shuttle_called_message = "A crew transfer to %dock% has been scheduled. The shuttle has been called. It will arrive in approximately %ETA%."
shuttle_recall_message = "The scheduled crew transfer has been cancelled."
emergency_shuttle_docked_message = "The emergency shuttle has docked with the station. You have approximately %ETD% minutes to board the emergency shuttle."
emergency_shuttle_leaving_dock = "The emergency shuttle has left the station. Estimate %ETA% minutes until the shuttle docks at %dock%."
emergency_shuttle_recall_message = "The emergency shuttle has been recalled."
emergency_shuttle_called_message = "An emergency evacuation shuttle has been called. It will arrive in approximately %ETA% minutes."
emergency_shuttle_called_message = "An emergency evacuation shuttle has been called. It will arrive in approximately %ETA%."
evac_controller_type = /datum/evacuation_controller/shuttle
map_shuttles = list(
/datum/shuttle/autodock/ferry/escape_pod/pod/escape_pod1,

View File

@@ -50,7 +50,6 @@ AURORA_ESCAPE_POD(3)
/datum/shuttle/autodock/ferry/emergency/aurora
name = "Escape Shuttle"
location = 1
move_time = 20
warmup_time = 10
shuttle_area = /area/shuttle/escape
dock_target = "escape_shuttle"

View File

@@ -42,6 +42,8 @@
emergency_shuttle_recall_message = "The emergency shuttle has been recalled."
emergency_shuttle_called_message = "An emergency evacuation shuttle has been called. It will arrive in approximately %ETA% minutes."
evac_controller_type = /datum/evacuation_controller/shuttle
station_levels = list(1)
admin_levels = list(2)
contact_levels = list(1, 5)

View File

@@ -1,6 +1,6 @@
/datum/map/runtime
name = "Runtime Station"
full_name = "Runtime Debugging Station"
name = "Runtime Ship"
full_name = "Runtime Debugging Ship"
path = "runtime"
lobby_icons = list('icons/misc/titlescreens/runtime/developers.dmi')
lobby_transitions = 10 SECONDS
@@ -11,7 +11,7 @@
player_levels = list(1, 2, 3)
accessible_z_levels = list(1, 2, 3)
station_name = "NSS Runtime"
station_name = "NSV Runtime"
station_short = "Runtime"
dock_name = "singulo"
boss_name = "#code_dungeon"
@@ -21,6 +21,13 @@
use_overmap = TRUE
shuttle_docked_message = "Attention all hands: Jump preparation complete. The bluespace drive is now spooling up, secure all stations for departure. Time to jump: approximately %ETD%."
shuttle_leaving_dock = "Attention all hands: Jump initiated, exiting bluespace in %ETA%."
shuttle_called_message = "Attention all hands: Jump sequence initiated. Transit procedures are now in effect. Jump in %ETA%."
shuttle_recall_message = "Attention all hands: Jump sequence aborted, return to normal operating conditions."
evac_controller_type = /datum/evacuation_controller/starship
station_networks = list(
NETWORK_CIVILIAN_MAIN,
NETWORK_COMMAND,

View File

@@ -8,11 +8,13 @@
{{/if}} </div>
<div class=item>{{:helper.link('Change alert level', null, {'action' : 'sw_menu', 'target' : 5}, data.isAI || !data.net_syscont || !data.net_comms ? 'disabled' : null)}} </div>
{{if data.can_call_shuttle}}
<div class=item>{{if data.have_shuttle && data.have_shuttle_called}}
{{:helper.link('Cancel Shuttle Call', null, {'action' : 'shuttle', 'target' : 'cancel'}, data.isAI || !data.net_syscont ? 'disabled' : null)}}
{{else data.have_shuttle && !data.have_shuttle_called}}
{{:helper.link('Call Emergency Shuttle', null, {'action' : 'shuttle', 'target' : 'call'}, !data.net_syscont ? 'disabled' : null)}}
{{/if}} </div>
{{for data.evac_options}}
<div class="item">
{{:helper.link(value.option_text, null, {'action' : 'evac', 'target' : value.option_target}, ((value.needs_syscontrol && !data.net_syscont) || (!value.silicon_allowed && data.isAI)) ? 'disabled' : null, 'redButton')}}
</div>
{{empty}}
<div class=bad>No further options currently available.</div>
{{/for}}
{{/if}}
{{if data.current_maint_all_access}}
<div class=item>{{:helper.link('Disable Emergency Maintenance Access', null, {'action' : 'emergencymaint'}, data.isAI ? 'disabled' : null)}}</div>
@@ -45,7 +47,7 @@
Set status displays:
<div class=item>{{:helper.link('Clear', null, {'action' : 'setstatus', 'target' : 'blank'})}} </div>
<div class=item>{{:helper.link('Station Time', null, {'action' : 'setstatus', 'target' : 'time'})}} </div>
<div class=item>{{:helper.link('Shuttle ETA', null, {'action' : 'setstatus', 'target' : 'shuttle'})}} </div>
<div class=item>{{:helper.link('Evacuation ETA', null, {'action' : 'setstatus', 'target' : 'shuttle'})}} </div>
<div class=item>{{:helper.link('Message', null, {'action' : 'setstatus', 'target' : 'message'})}}
<ul>
<li><div class=item>Line 1: {{:helper.link(data.message_line1 ? data.message_line1 : '(none)', null, {'action' : 'setstatus', 'target' : 'line1'})}}</div></li>

Binary file not shown.