Files
2020-02-19 19:48:29 -08:00

364 lines
13 KiB
Plaintext

// Controls the emergency shuttle
#define SHUTTLE_TRANSIT 1
// these define the time taken for the shuttle to get to SS13
// and the time before it leaves again
#define SHUTTLEARRIVETIME 360 // 6 minutes = 360 seconds
#define SHUTTLELEAVETIME 120 // 2 minutes = 120 seconds
#define SHUTTLETRANSITTIME 120 // 2 minutes = 120 seconds
var/global/datum/shuttle_controller/emergency_shuttle/emergency_shuttle
datum/shuttle_controller
var/location = 0 //0 = somewhere far away, 1 = at SS13, 2 = returned from SS13
var/online = 0
var/direction = 1 //-1 = going back to central command, 1 = going back to SS13
var/disabled = 0 //Block shuttle calling if it's disabled.
var/callcount = 0 //Number of shuttle calls required to break through interference (wizard mode)
var/endtime // round_elapsed_ticks that shuttle arrives
var/announcement_done = 0
var/can_recall = 1 // set to 0 in the admin call thing to make it not recallable
var/list/airbridges = list()
var/map_turf = /turf/space //Set in New() by map settings
var/transit_turf = /turf/space/no_replace //Not currently modified
var/centcom_turf = /turf/unsimulated/outdoors/grass //Not currently modified
// call the shuttle
// if not called before, set the endtime to T+600 seconds
// otherwise if outgoing, switch to incoming
proc/incall()
if (online)
if(direction == -1)
setdirection(1)
else
settimeleft(SHUTTLEARRIVETIME)
online = 1
ircbot.event("shuttlecall", src.timeleft())
proc/recall()
if (online && direction == 1)
setdirection(-1)
ircbot.event("shuttlerecall", src.timeleft())
// returns the time (in seconds) before shuttle arrival
// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME
proc/timeleft()
if(online)
var/timeleft = round((endtime - ticker.round_elapsed_ticks)/10 ,1)
if(direction == 1)
return timeleft
else
return SHUTTLEARRIVETIME-timeleft
else
return SHUTTLEARRIVETIME
// sets the time left to a given delay (in seconds)
proc/settimeleft(var/delay)
endtime = ticker.round_elapsed_ticks + delay * 10
// sets the shuttle direction
// 1 = towards SS13, -1 = back to centcom
proc/setdirection(var/dirn)
if(direction == dirn)
return
direction = dirn
// if changing direction, flip the timeleft by SHUTTLEARRIVETIME
var/ticksleft = endtime - ticker.round_elapsed_ticks
endtime = ticker.round_elapsed_ticks + (SHUTTLEARRIVETIME*10 - ticksleft)
return
proc/process()
emergency_shuttle
New()
..()
for (var/obj/machinery/computer/airbr/S in machines)
if (S.emergency && !(S in src.airbridges))
src.airbridges += S
map_turf = map_settings.shuttle_map_turf
process()
if (!online)
return
var/timeleft = timeleft()
if (timeleft > 1e5 || timeleft <= 0) // midnight rollover protection
timeleft = 0
switch (location)
if (SHUTTLE_LOC_CENTCOM)
if (timeleft>SHUTTLEARRIVETIME)
online = 0
direction = 1
endtime = null
return 0
else if (timeleft <= 0)
location = SHUTTLE_LOC_STATION
if (ticker && ticker.mode)
if (ticker.mode.shuttle_available == 0)
command_alert("CentCom has received reports of unusual activity on the station. The shuttle has been returned to base as a precaution, and will not be usable.");
online = 0
direction = 1
endtime = null
return 0
if (ticker.mode.shuttle_available == 2 && (ticker.round_elapsed_ticks < max(0, ticker.mode.shuttle_available_threshold)) && callcount < 1)
callcount++
command_alert("CentCom reports that the emergency shuttle has veered off course due to unknown interference. The next shuttle will be equipped with electronic countermeasures to break through.");
online = 0
direction = 1
location = SHUTTLE_LOC_CENTCOM
endtime = null
return 0
processScheduler.disableProcess("Fluid_Turfs")
var/area/start_location = locate(map_settings ? map_settings.escape_centcom : /area/shuttle/escape/centcom)
var/area/end_location = locate(map_settings ? map_settings.escape_station : /area/shuttle/escape/station)
var/list/dstturfs = list()
var/northBound = 1
var/southBound = world.maxy
var/westBound = world.maxx
var/eastBound = 1
for (var/atom/A as obj|mob in end_location)
SPAWN_DBG(0)
A.ex_act(1)
for (var/turf/P in start_location)
if (istype(P, centcom_turf))
new map_turf(P)
end_location.color = null //Remove the colored shuttle!
for (var/turf/T in end_location)
dstturfs += T
if (T.y > northBound) northBound = T.y
if (T.y < southBound) southBound = T.y
if (T.x < westBound) westBound = T.x
if (T.x > eastBound) eastBound = T.x
// hey you, get out of the way!
var/shuttle_dir = map_settings ? map_settings.escape_dir : EAST // default to cog2 direction because EH
for (var/turf/T in dstturfs)
// find the turf to move things to
var/turf/D = locate(shuttle_dir == EAST ? eastBound + 1 : T.x, // X
shuttle_dir == NORTH ? northBound + 1 : shuttle_dir == EAST ? T.y : southBound - 1, // Y
1) // Z
for (var/atom/movable/AM as mob|obj in T)
if (isobserver(AM))
continue // skip ghosties
AM.set_loc(D)
// NOTE: Commenting this out to avoid recreating mass driver glitch
/*
SPAWN_DBG(0)
AM.throw_at(E, 1, 1)
return
*/
if (istype(T, /turf/simulated))
T.ReplaceWithSpace()
start_location.move_contents_to(end_location, centcom_turf)
settimeleft(SHUTTLELEAVETIME)
#ifdef UNDERWATER_MAP
end_location.force_fullbright = 1
end_location.update_fullbright()
#endif
if (src.airbridges.len)
for (var/obj/machinery/computer/airbr/S in src.airbridges)
S.establish_bridge()
boutput(world, "<B>The Emergency Shuttle has docked with the station! You have [timeleft()/60] minutes to board the Emergency Shuttle.</B>")
ircbot.event("shuttledock")
world << csound("sound/misc/shuttle_arrive1.ogg")
processScheduler.enableProcess("Fluid_Turfs")
return 1
#ifdef SHUTTLE_TRANSIT // shuttle spends some time in transit to centcom before arriving
if (SHUTTLE_LOC_STATION)
if (!announcement_done && timeleft <= 60)
var/display_time = round(timeleft()/60)
//if (display_time <= 0) // The Emergency Shuttle will be entering the wormhole to CentCom in 0 minutes!
//display_time = 1 // fuckofffffffffff
boutput(world, "<B>The Emergency Shuttle will be entering the wormhole to CentCom in [display_time] minute[s_es(display_time)]! Please prepare for wormhole traversal.</B>")
announcement_done = 1
else if (announcement_done < 2 && timeleft < 30)
var/area/sound_location = locate(/area/shuttle_sound_spawn)
playsound(sound_location, 'sound/effects/ship_charge.ogg', 100)
announcement_done = 2
else if (announcement_done < 3 && timeleft < 4)
var/area/sound_location = locate(/area/shuttle_sound_spawn)
playsound(sound_location, 'sound/effects/ship_engage.ogg', 100)
announcement_done = 3
else if (announcement_done < 4 && timeleft < 1)
var/area/sound_location = locate(/area/shuttle_sound_spawn)
playsound(sound_location, 'sound/effects/explosion_new4.ogg', 75)
playsound(sound_location, 'sound/effects/flameswoosh.ogg', 75)
announcement_done = 4
if (src.airbridges.len)
for (var/obj/machinery/computer/airbr/S in src.airbridges)
S.remove_bridge()
else if (timeleft > 0)
return 0
else
location = SHUTTLE_LOC_TRANSIT
var/area/start_location = locate(map_settings ? map_settings.escape_station : /area/shuttle/escape/station)
var/area/end_location = locate(map_settings ? map_settings.escape_transit : /area/shuttle/escape/transit)
var/door_type = map_settings ? map_settings.ext_airlocks : /obj/machinery/door/airlock/external
for (var/obj/machinery/door/D in start_location)
if (istype(D, door_type))
D.set_density(1)
D.locked = 1
D.update_icon()
for (var/atom/A in start_location)
if(istype( A, /obj/stool ))
var/obj/stool/O = A
if( !O.anchored )
var/atom/target = get_edge_target_turf(O, pick(alldirs))
if( O.buckled_guy )
boutput( O.buckled_guy, "<span style='color:red'>The [O] shoots off due to being unsecured!</span>" )
O.unbuckle()
if( target )
SPAWN_DBG(0)
O.throw_at( target, 25, 1 )//dear god I am sorry in advance for doing this
else if(istype( A, /mob ))
var/mob/M = A
shake_camera(M, 32, 4)
M.addOverlayComposition(/datum/overlayComposition/shuttle_warp)
if (!isturf(M.loc) || !isliving(M) || isintangible(M))
continue
SPAWN_DBG(1 DECI SECOND)
var/bonus_stun = 0
if (ishuman(M))
var/mob/living/carbon/human/H = M
bonus_stun = (H && H.buckled && H.on_chair)
//DEBUG_MESSAGE("[M] is human and bonus_stun is [bonus_stun]")
if (!M.buckled || bonus_stun)
M.changeStatus("stunned", 2 SECONDS)
M.changeStatus("weakened", 2 SECONDS)
if (prob(50) || bonus_stun)
var/atom/target = get_edge_target_turf(M, pick(alldirs))
SPAWN_DBG(0)
if (target)
if (M.buckled) M.buckled.unbuckle()
M.throw_at(target, 25, 1)
if (bonus_stun)
M.changeStatus("paralysis", 60)
M.playsound_local(target, 'sound/impact_sounds/Flesh_Break_1.ogg', 50, 1)
M.show_text("You are thrown off the chair! [prob(50) ? "Standing on that during takeoff was a terrible idea!" : null]", "red")
if (!bonus_stun)
M.show_text("You are thrown about as the shuttle launches due to not being securely buckled in!", "red")
for (var/turf/O in start_location)
if (istype(O, map_turf))
new transit_turf(O)
var/area/shuttle_particle_spawn/particle_spawn = locate(/area/shuttle_particle_spawn) in world
if (particle_spawn)
particle_spawn.start_particles()
#ifdef UNDERWATER_MAP
end_location.force_fullbright = 1
end_location.update_fullbright()
#endif
SPAWN_DBG(0)
var/shuttle_dir = map_settings ? map_settings.escape_dir : EAST // default to cog2 direction because EH
for (var/obj/landmark/L in escape_pod_success)
if (L.dir != shuttle_dir)
escape_pod_success -= L //leave behind only landmarks that match our dir
DEBUG_MESSAGE("Now moving shuttle!")
start_location.move_contents_to(end_location, map_turf)
DEBUG_MESSAGE("Done moving shuttle!")
settimeleft(SHUTTLETRANSITTIME)
boutput(world, "<B>The Emergency Shuttle has left for CentCom! It will arrive in [timeleft()/60] minute[s_es(timeleft()/60)]!</B>")
world << csound("sound/misc/shuttle_enroute.ogg")
//online = 0
return 1
if (SHUTTLE_LOC_TRANSIT)
if (timeleft>0)
return 0
else
var/area/start_location = locate(map_settings ? map_settings.escape_transit : /area/shuttle/escape/transit)
var/area/end_location = locate(map_settings ? map_settings.escape_centcom : /area/shuttle/escape/centcom)
for (var/mob/M in start_location)
M.removeOverlayComposition(/datum/overlayComposition/shuttle_warp)
M.removeOverlayComposition(/datum/overlayComposition/shuttle_warp/ew)
var/door_type = map_settings ? map_settings.ext_airlocks : /obj/machinery/door/airlock/external
for (var/obj/machinery/door/D in start_location)
if (istype(D, door_type))
D.set_density(0)
D.locked = 0
D.update_icon()
for (var/turf/G in start_location)
if (istype(G, transit_turf))
new centcom_turf(G)
start_location.move_contents_to(end_location, transit_turf)
boutput(world, "<B>The Emergency Shuttle has arrived at CentCom!")
world << csound("sound/misc/shuttle_centcom.ogg")
logTheThing("station", null, null, "The emergency shuttle has arrived at Centcom.")
online = 0
#ifdef UNDERWATER_MAP
end_location.force_fullbright = 1
end_location.update_fullbright()
#endif
location = SHUTTLE_LOC_RETURNED
return 1
else
return 1
#else // standard shuttle departure - immediately arrives at centcom
if (SHUTTLE_LOC_STATION)
if (timeleft>0)
return 0
else
location = SHUTTLE_LOC_RETURNED
var/area/start_location = locate(map_settings ? map_settings.escape_station : /area/shuttle/escape/station)
var/area/end_location = locate(map_settings ? map_settings.escape_centcom : /area/shuttle/escape/centcom)
for (var/turf/O in start_location)
if (istype(O, transit_turf))
new centcom_turf(O)
start_location.move_contents_to(end_location, map_turf)
boutput(world, "<B>The Emergency Shuttle has arrived at CentCom!")
logTheThing("station", null, null, "The emergency shuttle has arrived at Centcom.")
online = 0
#ifdef UNDERWATER_MAP
end_location.force_fullbright = 1
end_location.update_fullbright()
#endif
return 1
else
return 1
#endif