mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-23 21:26:30 +01:00
Merge pull request #6826 from VOREStation/vplk-landmark-shuttles
Port Landmark Shuttles
This commit is contained in:
@@ -2,17 +2,17 @@
|
||||
name = "Jump a Shuttle"
|
||||
|
||||
/datum/admin_secret_item/admin_secret/jump_shuttle/can_execute(var/mob/user)
|
||||
if(!shuttle_controller) return 0
|
||||
if(!SSshuttles) return 0
|
||||
return ..()
|
||||
|
||||
/datum/admin_secret_item/admin_secret/jump_shuttle/execute(var/mob/user)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
|
||||
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
|
||||
if (!shuttle_tag) return
|
||||
|
||||
var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
|
||||
|
||||
var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
|
||||
if (!origin_area) return
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Launch a Shuttle"
|
||||
|
||||
/datum/admin_secret_item/admin_secret/launch_shuttle/can_execute(var/mob/user)
|
||||
if(!shuttle_controller) return 0
|
||||
if(!SSshuttles) return 0
|
||||
return ..()
|
||||
|
||||
/datum/admin_secret_item/admin_secret/launch_shuttle/execute(var/mob/user)
|
||||
@@ -10,15 +10,15 @@
|
||||
if(!.)
|
||||
return
|
||||
var/list/valid_shuttles = list()
|
||||
for (var/shuttle_tag in shuttle_controller.shuttles)
|
||||
if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
|
||||
for (var/shuttle_tag in SSshuttles.shuttles)
|
||||
if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
|
||||
valid_shuttles += shuttle_tag
|
||||
|
||||
var/shuttle_tag = input(user, "Which shuttle do you want to launch?") as null|anything in valid_shuttles
|
||||
if (!shuttle_tag)
|
||||
return
|
||||
|
||||
var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
|
||||
if (S.can_launch())
|
||||
S.launch(user)
|
||||
log_and_message_admins("launched the [shuttle_tag] shuttle", user)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Launch a Shuttle (Forced)"
|
||||
|
||||
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/can_execute(var/mob/user)
|
||||
if(!shuttle_controller) return 0
|
||||
if(!SSshuttles) return 0
|
||||
return ..()
|
||||
|
||||
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/execute(var/mob/user)
|
||||
@@ -10,15 +10,15 @@
|
||||
if(!.)
|
||||
return
|
||||
var/list/valid_shuttles = list()
|
||||
for (var/shuttle_tag in shuttle_controller.shuttles)
|
||||
if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
|
||||
for (var/shuttle_tag in SSshuttles.shuttles)
|
||||
if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
|
||||
valid_shuttles += shuttle_tag
|
||||
|
||||
var/shuttle_tag = input(user, "Which shuttle's launch do you want to force?") as null|anything in valid_shuttles
|
||||
if (!shuttle_tag)
|
||||
return
|
||||
|
||||
var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
|
||||
if (S.can_force())
|
||||
S.force_launch(user)
|
||||
log_and_message_admins("forced the [shuttle_tag] shuttle", user)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Move a Shuttle"
|
||||
|
||||
/datum/admin_secret_item/admin_secret/move_shuttle/can_execute(var/mob/user)
|
||||
if(!shuttle_controller) return 0
|
||||
if(!SSshuttles) return 0
|
||||
return ..()
|
||||
|
||||
/datum/admin_secret_item/admin_secret/move_shuttle/execute(var/mob/user)
|
||||
@@ -13,16 +13,15 @@
|
||||
if (confirm == "Cancel")
|
||||
return
|
||||
|
||||
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
|
||||
var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
|
||||
if (!shuttle_tag) return
|
||||
|
||||
var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
|
||||
|
||||
var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
|
||||
if (!origin_area) return
|
||||
var/destination_tag = input(user, "Which landmark do you want to jump to? (IF YOU GET THIS WRONG THINGS WILL BREAK)") as null|anything in SSshuttles.registered_shuttle_landmarks
|
||||
if (!destination_tag) return
|
||||
var/destination_location = SSshuttles.get_landmark(destination_tag)
|
||||
if (!destination_location) return
|
||||
|
||||
var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
|
||||
if (!destination_area) return
|
||||
|
||||
S.move(origin_area, destination_area)
|
||||
S.attempt_move(destination_location)
|
||||
log_and_message_admins("moved the [shuttle_tag] shuttle", user)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/turf/proc/lighting_clear_overlay()
|
||||
if(lighting_overlay)
|
||||
qdel(lighting_overlay)
|
||||
qdel(lighting_overlay, force = TRUE)
|
||||
|
||||
for(var/datum/lighting_corner/C in corners)
|
||||
C.update_active()
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
if (SSatoms.initialized == INITIALIZATION_INSSATOMS)
|
||||
return // let proper initialisation handle it later
|
||||
|
||||
var/prev_shuttle_queue_state = SSshuttles.block_init_queue
|
||||
SSshuttles.block_init_queue = TRUE
|
||||
|
||||
var/list/atom/atoms = list()
|
||||
var/list/area/areas = list()
|
||||
var/list/obj/structure/cable/cables = list()
|
||||
@@ -71,6 +74,9 @@
|
||||
var/area/A = I
|
||||
A.power_change()
|
||||
|
||||
SSshuttles.block_init_queue = prev_shuttle_queue_state
|
||||
SSshuttles.process_init_queues() // We will flush the queue unless there were other blockers, in which case they will do it.
|
||||
|
||||
admin_notice("<span class='danger'>Submap initializations finished.</span>", R_DEBUG)
|
||||
|
||||
/datum/map_template/proc/load_new_z(var/centered = FALSE, var/orientation = 0)
|
||||
|
||||
@@ -150,6 +150,9 @@
|
||||
var/turf/below = GetBelow(src)
|
||||
return !below || below.is_space()
|
||||
|
||||
/turf/simulated/open/is_solid_structure()
|
||||
return locate(/obj/structure/lattice, src) //counts as solid structure if it has a lattice (same as space)
|
||||
|
||||
/turf/simulated/open/is_safe_to_enter(mob/living/L)
|
||||
if(L.can_fall())
|
||||
for(var/obj/O in contents)
|
||||
|
||||
@@ -3,6 +3,57 @@
|
||||
//How far from the edge of overmap zlevel could randomly placed objects spawn
|
||||
#define OVERMAP_EDGE 7
|
||||
|
||||
|
||||
|
||||
//Dimension of overmap (squares 4 lyfe)
|
||||
var/global/list/map_sectors = list()
|
||||
|
||||
/area/overmap/
|
||||
name = "System Map"
|
||||
icon_state = "start"
|
||||
requires_power = 0
|
||||
base_turf = /turf/unsimulated/map
|
||||
|
||||
/turf/unsimulated/map
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "map"
|
||||
|
||||
/turf/unsimulated/map/edge
|
||||
opacity = 1
|
||||
density = 1
|
||||
|
||||
/turf/unsimulated/map/New()
|
||||
..()
|
||||
name = "[x]-[y]"
|
||||
var/list/numbers = list()
|
||||
|
||||
if(x == 1 || x == global.using_map.overmap_size)
|
||||
numbers += list("[round(y/10)]","[round(y%10)]")
|
||||
if(y == 1 || y == global.using_map.overmap_size)
|
||||
numbers += "-"
|
||||
if(y == 1 || y == global.using_map.overmap_size)
|
||||
numbers += list("[round(x/10)]","[round(x%10)]")
|
||||
|
||||
for(var/i = 1 to numbers.len)
|
||||
var/image/I = image('icons/effects/numbers.dmi',numbers[i])
|
||||
I.pixel_x = 5*i - 2
|
||||
I.pixel_y = world.icon_size/2 - 3
|
||||
if(y == 1)
|
||||
I.pixel_y = 3
|
||||
I.pixel_x = 5*i + 4
|
||||
if(y == global.using_map.overmap_size)
|
||||
I.pixel_y = world.icon_size - 9
|
||||
I.pixel_x = 5*i + 4
|
||||
if(x == 1)
|
||||
I.pixel_x = 5*i - 2
|
||||
if(x == global.using_map.overmap_size)
|
||||
I.pixel_x = 5*i + 2
|
||||
overlays += I
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//list used to track which zlevels are being 'moved' by the proc below
|
||||
var/list/moving_levels = list()
|
||||
//Proc to 'move' stars in spess
|
||||
@@ -35,6 +86,7 @@ proc/toggle_move_stars(zlevel, direction)
|
||||
AM.throw_at(get_step(T,reverse_direction(direction)), 5, 1)
|
||||
|
||||
|
||||
/*
|
||||
//list used to cache empty zlevels to avoid nedless map bloat
|
||||
var/list/cached_space = list()
|
||||
|
||||
@@ -99,3 +151,4 @@ proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A)
|
||||
testing("Catching [M] for future use")
|
||||
source.loc = null
|
||||
cached_space += source
|
||||
*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/obj/effect/overmap
|
||||
name = "map object"
|
||||
icon = 'icons/obj/overmap.dmi'
|
||||
icon_state = "object"
|
||||
|
||||
var/known = 1 //shows up on nav computers automatically
|
||||
var/scannable //if set to TRUE will show up on ship sensors for detailed scans
|
||||
|
||||
//Overlay of how this object should look on other skyboxes
|
||||
/obj/effect/overmap/proc/get_skybox_representation()
|
||||
return
|
||||
|
||||
/obj/effect/overmap/proc/get_scan_data(mob/user)
|
||||
return desc
|
||||
|
||||
/obj/effect/overmap/Initialize()
|
||||
. = ..()
|
||||
if(!global.using_map.use_overmap)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
if(known)
|
||||
//layer = ABOVE_LIGHTING_LAYER
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
// TODO - Leshana HELM
|
||||
// for(var/obj/machinery/computer/ship/helm/H in global.machines)
|
||||
// H.get_known_sectors()
|
||||
/*
|
||||
TODO - Leshana - No need for this, we don't have skyboxes
|
||||
/obj/effect/overmap/Crossed(var/obj/effect/overmap/visitable/other)
|
||||
if(istype(other))
|
||||
for(var/obj/effect/overmap/visitable/O in loc)
|
||||
SSskybox.rebuild_skyboxes(O.map_z)
|
||||
|
||||
/obj/effect/overmap/Uncrossed(var/obj/effect/overmap/visitable/other)
|
||||
if(istype(other))
|
||||
SSskybox.rebuild_skyboxes(other.map_z)
|
||||
for(var/obj/effect/overmap/visitable/O in loc)
|
||||
SSskybox.rebuild_skyboxes(O.map_z)
|
||||
*/
|
||||
+118
-106
@@ -1,124 +1,136 @@
|
||||
|
||||
//===================================================================================
|
||||
//Hook for building overmap
|
||||
//Overmap object representing zlevel(s)
|
||||
//===================================================================================
|
||||
var/global/list/map_sectors = list()
|
||||
|
||||
/hook/startup/proc/build_map()
|
||||
if(!config.use_overmap)
|
||||
return 1
|
||||
testing("Building overmap...")
|
||||
var/obj/effect/mapinfo/data
|
||||
for(var/level in 1 to world.maxz)
|
||||
data = locate("sector[level]")
|
||||
if (data)
|
||||
testing("Located sector \"[data.name]\" at [data.mapx],[data.mapy] corresponding to zlevel [level]")
|
||||
map_sectors["[level]"] = new data.obj_type(data)
|
||||
return 1
|
||||
|
||||
//===================================================================================
|
||||
//Metaobject for storing information about sector this zlevel is representing.
|
||||
//Should be placed only once on every zlevel.
|
||||
//===================================================================================
|
||||
/obj/effect/mapinfo/
|
||||
name = "map info metaobject"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x2"
|
||||
invisibility = 101
|
||||
var/obj_type //type of overmap object it spawns
|
||||
var/landing_area //type of area used as inbound shuttle landing, null if no shuttle landing area
|
||||
var/zlevel
|
||||
var/mapx //coordinates on the
|
||||
var/mapy //overmap zlevel
|
||||
var/known = 1
|
||||
|
||||
/obj/effect/mapinfo/New()
|
||||
tag = "sector[z]"
|
||||
zlevel = z
|
||||
loc = null
|
||||
|
||||
/obj/effect/mapinfo/sector
|
||||
name = "generic sector"
|
||||
obj_type = /obj/effect/map/sector
|
||||
|
||||
/obj/effect/mapinfo/ship
|
||||
name = "generic ship"
|
||||
obj_type = /obj/effect/map/ship
|
||||
|
||||
|
||||
//===================================================================================
|
||||
//Overmap object representing zlevel
|
||||
//===================================================================================
|
||||
|
||||
/obj/effect/map
|
||||
/obj/effect/overmap/visitable
|
||||
name = "map object"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "sheet-plasteel"
|
||||
var/map_z = 0
|
||||
var/area/shuttle/shuttle_landing
|
||||
var/always_known = 1
|
||||
scannable = TRUE
|
||||
|
||||
/obj/effect/map/New(var/obj/effect/mapinfo/data)
|
||||
map_z = data.zlevel
|
||||
name = data.name
|
||||
always_known = data.known
|
||||
if (data.icon != 'icons/mob/screen1.dmi')
|
||||
icon = data.icon
|
||||
icon_state = data.icon_state
|
||||
if(data.desc)
|
||||
desc = data.desc
|
||||
var/new_x = data.mapx ? data.mapx : rand(OVERMAP_EDGE, world.maxx - OVERMAP_EDGE)
|
||||
var/new_y = data.mapy ? data.mapy : rand(OVERMAP_EDGE, world.maxy - OVERMAP_EDGE)
|
||||
loc = locate(new_x, new_y, OVERMAP_ZLEVEL)
|
||||
var/list/map_z = list()
|
||||
|
||||
if(data.landing_area)
|
||||
shuttle_landing = locate(data.landing_area)
|
||||
var/list/initial_generic_waypoints //store landmark_tag of landmarks that should be added to the actual lists below on init.
|
||||
var/list/initial_restricted_waypoints //For use with non-automatic landmarks (automatic ones add themselves).
|
||||
|
||||
/obj/effect/map/CanPass(atom/movable/A)
|
||||
testing("[A] attempts to enter sector\"[name]\"")
|
||||
return 1
|
||||
var/list/generic_waypoints = list() //waypoints that any shuttle can use
|
||||
var/list/restricted_waypoints = list() //waypoints for specific shuttles
|
||||
var/docking_codes
|
||||
|
||||
/obj/effect/map/Crossed(atom/movable/A)
|
||||
testing("[A] has entered sector\"[name]\"")
|
||||
if (istype(A,/obj/effect/map/ship))
|
||||
var/obj/effect/map/ship/S = A
|
||||
S.current_sector = src
|
||||
var/start_x //Coordinates for self placing
|
||||
var/start_y //will use random values if unset
|
||||
|
||||
/obj/effect/map/Uncrossed(atom/movable/A)
|
||||
testing("[A] has left sector\"[name]\"")
|
||||
if (istype(A,/obj/effect/map/ship))
|
||||
var/obj/effect/map/ship/S = A
|
||||
S.current_sector = null
|
||||
var/base = 0 //starting sector, counts as station_levels
|
||||
var/in_space = 1 //can be accessed via lucky EVA
|
||||
|
||||
/obj/effect/map/sector
|
||||
var/hide_from_reports = FALSE
|
||||
|
||||
var/has_distress_beacon
|
||||
|
||||
/obj/effect/overmap/visitable/Initialize()
|
||||
. = ..()
|
||||
if(. == INITIALIZE_HINT_QDEL)
|
||||
return
|
||||
|
||||
find_z_levels() // This populates map_z and assigns z levels to the ship.
|
||||
register_z_levels() // This makes external calls to update global z level information.
|
||||
|
||||
if(!global.using_map.overmap_z)
|
||||
build_overmap()
|
||||
|
||||
start_x = start_x || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
start_y = start_y || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
|
||||
forceMove(locate(start_x, start_y, global.using_map.overmap_z))
|
||||
|
||||
docking_codes = "[ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))]"
|
||||
|
||||
testing("Located sector \"[name]\" at [start_x],[start_y], containing Z [english_list(map_z)]")
|
||||
|
||||
LAZYADD(SSshuttles.sectors_to_initialize, src) //Queued for further init. Will populate the waypoint lists; waypoints not spawned yet will be added in as they spawn.
|
||||
SSshuttles.process_init_queues()
|
||||
|
||||
//This is called later in the init order by SSshuttles to populate sector objects. Importantly for subtypes, shuttles will be created by then.
|
||||
/obj/effect/overmap/visitable/proc/populate_sector_objects()
|
||||
|
||||
// TODO - Leshana - Implement
|
||||
///obj/effect/overmap/visitable/proc/get_areas()
|
||||
// return get_filtered_areas(list(/proc/area_belongs_to_zlevels = map_z))
|
||||
|
||||
/obj/effect/overmap/visitable/proc/find_z_levels()
|
||||
map_z = GetConnectedZlevels(z)
|
||||
|
||||
/obj/effect/overmap/visitable/proc/register_z_levels()
|
||||
for(var/zlevel in map_z)
|
||||
map_sectors["[zlevel]"] = src
|
||||
|
||||
global.using_map.player_levels |= map_z
|
||||
if(!in_space)
|
||||
global.using_map.sealed_levels |= map_z
|
||||
if(base)
|
||||
global.using_map.station_levels |= map_z
|
||||
global.using_map.contact_levels |= map_z
|
||||
global.using_map.map_levels |= map_z
|
||||
|
||||
//Helper for init.
|
||||
/obj/effect/overmap/visitable/proc/check_ownership(obj/object)
|
||||
if((object.z in map_z) && !(get_area(object) in SSshuttles.shuttle_areas))
|
||||
return 1
|
||||
|
||||
//If shuttle_name is false, will add to generic waypoints; otherwise will add to restricted. Does not do checks.
|
||||
/obj/effect/overmap/visitable/proc/add_landmark(obj/effect/shuttle_landmark/landmark, shuttle_name)
|
||||
landmark.sector_set(src, shuttle_name)
|
||||
if(shuttle_name)
|
||||
LAZYADD(restricted_waypoints[shuttle_name], landmark)
|
||||
else
|
||||
generic_waypoints += landmark
|
||||
|
||||
/obj/effect/overmap/visitable/proc/remove_landmark(obj/effect/shuttle_landmark/landmark, shuttle_name)
|
||||
if(shuttle_name)
|
||||
var/list/shuttles = restricted_waypoints[shuttle_name]
|
||||
LAZYREMOVE(shuttles, landmark)
|
||||
else
|
||||
generic_waypoints -= landmark
|
||||
|
||||
/obj/effect/overmap/visitable/proc/get_waypoints(var/shuttle_name)
|
||||
. = list()
|
||||
for(var/obj/effect/overmap/visitable/contained in src)
|
||||
. += contained.get_waypoints(shuttle_name)
|
||||
for(var/thing in generic_waypoints)
|
||||
.[thing] = name
|
||||
if(shuttle_name in restricted_waypoints)
|
||||
for(var/thing in restricted_waypoints[shuttle_name])
|
||||
.[thing] = name
|
||||
|
||||
/obj/effect/overmap/visitable/proc/generate_skybox()
|
||||
return
|
||||
|
||||
/obj/effect/overmap/visitable/sector
|
||||
name = "generic sector"
|
||||
desc = "Sector with some stuff in it."
|
||||
icon_state = "sector"
|
||||
anchored = 1
|
||||
|
||||
//Space stragglers go here
|
||||
// Because of the way these are spawned, they will potentially have their invisibility adjusted by the turfs they are mapped on
|
||||
// prior to being moved to the overmap. This blocks that. Use set_invisibility to adjust invisibility as needed instead.
|
||||
/obj/effect/overmap/visitable/sector/hide()
|
||||
|
||||
/obj/effect/map/sector/temporary
|
||||
name = "Deep Space"
|
||||
icon_state = ""
|
||||
always_known = 0
|
||||
/proc/build_overmap()
|
||||
if(!global.using_map.use_overmap)
|
||||
return 1
|
||||
|
||||
/obj/effect/map/sector/temporary/New(var/nx, var/ny, var/nz)
|
||||
loc = locate(nx, ny, OVERMAP_ZLEVEL)
|
||||
map_z = nz
|
||||
map_sectors["[map_z]"] = src
|
||||
testing("Temporary sector at [x],[y] was created, corresponding zlevel is [map_z].")
|
||||
testing("Building overmap...")
|
||||
world.maxz++
|
||||
global.using_map.overmap_z = world.maxz
|
||||
|
||||
/obj/effect/map/sector/temporary/Destroy()
|
||||
map_sectors["[map_z]"] = null
|
||||
testing("Temporary sector at [x],[y] was deleted.")
|
||||
if (can_die())
|
||||
testing("Associated zlevel disappeared.")
|
||||
world.maxz--
|
||||
testing("Putting overmap on [global.using_map.overmap_z]")
|
||||
var/area/overmap/A = new
|
||||
for (var/square in block(locate(1,1,global.using_map.overmap_z), locate(global.using_map.overmap_size,global.using_map.overmap_size,global.using_map.overmap_z)))
|
||||
var/turf/T = square
|
||||
if(T.x == global.using_map.overmap_size || T.y == global.using_map.overmap_size)
|
||||
T = T.ChangeTurf(/turf/unsimulated/map/edge)
|
||||
else
|
||||
T = T.ChangeTurf(/turf/unsimulated/map)
|
||||
ChangeArea(T, A)
|
||||
|
||||
/obj/effect/map/sector/temporary/proc/can_die(var/mob/observer)
|
||||
testing("Checking if sector at [map_z] can die.")
|
||||
for(var/mob/M in player_list)
|
||||
if(M != observer && M.z == map_z)
|
||||
testing("There are people on it.")
|
||||
return 0
|
||||
global.using_map.sealed_levels |= global.using_map.overmap_z
|
||||
|
||||
testing("Overmap build complete.")
|
||||
return 1
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
//list used to cache empty zlevels to avoid nedless map bloat
|
||||
var/list/cached_space = list()
|
||||
|
||||
//Space stragglers go here
|
||||
|
||||
/obj/effect/overmap/visitable/sector/temporary
|
||||
name = "Deep Space"
|
||||
invisibility = 101
|
||||
known = 0
|
||||
|
||||
/obj/effect/overmap/visitable/sector/temporary/New(var/nx, var/ny, var/nz)
|
||||
loc = locate(nx, ny, global.using_map.overmap_z)
|
||||
x = nx
|
||||
y = ny
|
||||
map_z += nz
|
||||
map_sectors["[nz]"] = src
|
||||
testing("Temporary sector at [x],[y] was created, corresponding zlevel is [nz].")
|
||||
|
||||
/obj/effect/overmap/visitable/sector/temporary/Destroy()
|
||||
map_sectors["[map_z]"] = null
|
||||
testing("Temporary sector at [x],[y] was deleted.")
|
||||
|
||||
/obj/effect/overmap/visitable/sector/temporary/proc/can_die(var/mob/observer)
|
||||
testing("Checking if sector at [map_z[1]] can die.")
|
||||
for(var/mob/M in global.player_list)
|
||||
if(M != observer && (M.z in map_z))
|
||||
testing("There are people on it.")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
proc/get_deepspace(x,y)
|
||||
var/obj/effect/overmap/visitable/sector/temporary/res = locate(x,y,global.using_map.overmap_z)
|
||||
if(istype(res))
|
||||
return res
|
||||
else if(cached_space.len)
|
||||
res = cached_space[cached_space.len]
|
||||
cached_space -= res
|
||||
res.x = x
|
||||
res.y = y
|
||||
return res
|
||||
else
|
||||
return new /obj/effect/overmap/visitable/sector/temporary(x, y, global.using_map.get_empty_zlevel())
|
||||
|
||||
/atom/movable/proc/lost_in_space()
|
||||
for(var/atom/movable/AM in contents)
|
||||
if(!AM.lost_in_space())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/lost_in_space()
|
||||
return isnull(client)
|
||||
|
||||
/mob/living/carbon/human/lost_in_space()
|
||||
return isnull(client) && !key && stat == DEAD
|
||||
|
||||
proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A)
|
||||
if (!T || !A)
|
||||
return
|
||||
|
||||
var/obj/effect/overmap/visitable/M = map_sectors["[T.z]"]
|
||||
if (!M)
|
||||
return
|
||||
|
||||
if(A.lost_in_space())
|
||||
if(!QDELETED(A))
|
||||
qdel(A)
|
||||
return
|
||||
|
||||
var/nx = 1
|
||||
var/ny = 1
|
||||
var/nz = 1
|
||||
|
||||
if(T.x <= TRANSITIONEDGE)
|
||||
nx = world.maxx - TRANSITIONEDGE - 2
|
||||
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
|
||||
|
||||
else if (A.x >= (world.maxx - TRANSITIONEDGE - 1))
|
||||
nx = TRANSITIONEDGE + 2
|
||||
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
|
||||
|
||||
else if (T.y <= TRANSITIONEDGE)
|
||||
ny = world.maxy - TRANSITIONEDGE -2
|
||||
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
|
||||
|
||||
else if (A.y >= (world.maxy - TRANSITIONEDGE - 1))
|
||||
ny = TRANSITIONEDGE + 2
|
||||
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
|
||||
|
||||
testing("[A] spacemoving from [M] ([M.x], [M.y]).")
|
||||
|
||||
var/turf/map = locate(M.x,M.y,global.using_map.overmap_z)
|
||||
var/obj/effect/overmap/visitable/TM
|
||||
for(var/obj/effect/overmap/visitable/O in map)
|
||||
if(O != M && O.in_space && prob(50))
|
||||
TM = O
|
||||
break
|
||||
if(!TM)
|
||||
TM = get_deepspace(M.x,M.y)
|
||||
nz = pick(TM.map_z)
|
||||
|
||||
var/turf/dest = locate(nx,ny,nz)
|
||||
if(dest)
|
||||
A.forceMove(dest)
|
||||
if(ismob(A))
|
||||
var/mob/D = A
|
||||
if(D.pulling)
|
||||
D.pulling.forceMove(dest)
|
||||
|
||||
if(istype(M, /obj/effect/overmap/visitable/sector/temporary))
|
||||
var/obj/effect/overmap/visitable/sector/temporary/source = M
|
||||
if (source.can_die())
|
||||
testing("Caching [M] for future use")
|
||||
source.forceMove(null)
|
||||
cached_space += source
|
||||
@@ -1,4 +1,22 @@
|
||||
#define SHUTTLE_FLAGS_NONE 0
|
||||
#define SHUTTLE_FLAGS_PROCESS 1
|
||||
#define SHUTTLE_FLAGS_SUPPLY 2
|
||||
#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE)
|
||||
// Shuttle flags
|
||||
#define SHUTTLE_FLAGS_NONE 0
|
||||
#define SHUTTLE_FLAGS_PROCESS 1 // Should be processed by shuttle subsystem
|
||||
#define SHUTTLE_FLAGS_SUPPLY 2 // This is the supply shuttle. Why is this a tag?
|
||||
#define SHUTTLE_FLAGS_ZERO_G 4 // Shuttle has no internal gravity generation
|
||||
#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE)
|
||||
|
||||
// shuttle_landmark flags
|
||||
#define SLANDMARK_FLAG_AUTOSET 1 // If set, will set base area and turf type to same as where it was spawned at
|
||||
#define SLANDMARK_FLAG_ZERO_G 2 // Zero-G shuttles moved here will lose gravity unless the area has ambient gravity.
|
||||
|
||||
// Ferry shuttle location constants
|
||||
#define FERRY_LOCATION_STATION 0
|
||||
#define FERRY_LOCATION_OFFSITE 1
|
||||
#define FERRY_GOING_TO_STATION 0
|
||||
#define FERRY_GOING_TO_OFFSITE 1
|
||||
|
||||
#ifndef DEBUG_SHUTTLES
|
||||
#define log_shuttle(M)
|
||||
#else
|
||||
#define log_shuttle(M) log_debug("[M]")
|
||||
#endif
|
||||
|
||||
@@ -1,50 +1,55 @@
|
||||
/datum/shuttle/ferry/escape_pod
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod/arming_controller
|
||||
category = /datum/shuttle/ferry/escape_pod
|
||||
/datum/shuttle/autodock/ferry/escape_pod
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/arming_controller
|
||||
category = /datum/shuttle/autodock/ferry/escape_pod
|
||||
|
||||
/datum/shuttle/ferry/escape_pod/New()
|
||||
/datum/shuttle/autodock/ferry/escape_pod/New()
|
||||
move_time = move_time + rand(-30, 60)
|
||||
if(name in emergency_shuttle.escape_pods)
|
||||
CRASH("An escape pod with the name '[name]' has already been defined.")
|
||||
emergency_shuttle.escape_pods[name] = src
|
||||
|
||||
..()
|
||||
|
||||
/datum/shuttle/ferry/escape_pod/init_docking_controllers()
|
||||
..()
|
||||
arming_controller = locate(dock_target_station)
|
||||
//find the arming controller (berth) - If not configured directly, try to read it from current location landmark
|
||||
var/arming_controller_tag = arming_controller
|
||||
if(!arming_controller && active_docking_controller)
|
||||
arming_controller_tag = active_docking_controller.id_tag
|
||||
arming_controller = SSshuttles.docking_registry[arming_controller_tag]
|
||||
if(!istype(arming_controller))
|
||||
warning("warning: escape pod with station dock tag [dock_target_station] could not find it's dock target!")
|
||||
CRASH("Could not find arming controller for escape pod \"[name]\", tag was '[arming_controller_tag]'.")
|
||||
|
||||
if(docking_controller)
|
||||
var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/controller_master = docking_controller.master
|
||||
if(!istype(controller_master))
|
||||
warning("warning: escape pod with docking tag [docking_controller_tag] could not find it's controller master!")
|
||||
else
|
||||
controller_master.pod = src
|
||||
//find the pod's own controller
|
||||
var/datum/computer/file/embedded_program/docking/simple/prog = SSshuttles.docking_registry[docking_controller_tag]
|
||||
var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/controller_master = prog.master
|
||||
if(!istype(controller_master))
|
||||
CRASH("Escape pod \"[name]\" could not find it's controller master! docking_controller_tag=[docking_controller_tag]")
|
||||
controller_master.pod = src
|
||||
|
||||
/datum/shuttle/ferry/escape_pod/can_launch()
|
||||
/datum/shuttle/autodock/ferry/escape_pod/can_launch()
|
||||
if(arming_controller && !arming_controller.armed) //must be armed
|
||||
return 0
|
||||
if(location)
|
||||
return 0 //it's a one-way trip.
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/escape_pod/can_force()
|
||||
/datum/shuttle/autodock/ferry/escape_pod/can_force()
|
||||
if (arming_controller.eject_time && world.time < arming_controller.eject_time + 50)
|
||||
return 0 //dont allow force launching until 5 seconds after the arming controller has reached it's countdown
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/escape_pod/can_cancel()
|
||||
/datum/shuttle/autodock/ferry/escape_pod/can_cancel()
|
||||
return 0
|
||||
|
||||
|
||||
//This controller goes on the escape pod itself
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod
|
||||
name = "escape pod controller"
|
||||
var/datum/shuttle/ferry/escape_pod/pod
|
||||
program = /datum/computer/file/embedded_program/docking/simple
|
||||
var/datum/shuttle/autodock/ferry/escape_pod/pod
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
|
||||
|
||||
data = list(
|
||||
"docking_status" = docking_program.get_docking_status(),
|
||||
@@ -64,17 +69,18 @@
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if((. = ..()))
|
||||
return
|
||||
|
||||
if("manual_arm")
|
||||
pod.arming_controller.arm()
|
||||
return TOPIC_REFRESH
|
||||
if("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
|
||||
pod.launch(src)
|
||||
|
||||
return TOPIC_REFRESH
|
||||
return 0
|
||||
|
||||
|
||||
@@ -82,18 +88,15 @@
|
||||
//This controller is for the escape pod berth (station side)
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth
|
||||
name = "escape pod berth controller"
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/Initialize()
|
||||
. = ..()
|
||||
docking_program = new/datum/computer/file/embedded_program/docking/simple/escape_pod(src)
|
||||
program = docking_program
|
||||
program = /datum/computer/file/embedded_program/docking/simple/escape_pod_berth
|
||||
|
||||
/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
|
||||
|
||||
var/armed = null
|
||||
if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod))
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod/P = docking_program
|
||||
if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth))
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = docking_program
|
||||
armed = P.armed
|
||||
|
||||
data = list(
|
||||
@@ -114,44 +117,44 @@
|
||||
if (!emagged)
|
||||
to_chat(user, "<span class='notice'>You emag the [src], arming the escape pod!</span>")
|
||||
emagged = 1
|
||||
if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod))
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod/P = docking_program
|
||||
if (istype(program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth))
|
||||
var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = program
|
||||
if (!P.armed)
|
||||
P.arm()
|
||||
return 1
|
||||
|
||||
//A docking controller program for a simple door based docking port
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth
|
||||
var/armed = 0
|
||||
var/eject_delay = 10 //give latecomers some time to get out of the way if they don't make it onto the pod
|
||||
var/eject_time = null
|
||||
var/closing = 0
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/proc/arm()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/proc/arm()
|
||||
if(!armed)
|
||||
armed = 1
|
||||
open_door()
|
||||
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/receive_user_command(command)
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/receive_user_command(command)
|
||||
if (!armed)
|
||||
return
|
||||
..(command)
|
||||
return TRUE // Eat all commands.
|
||||
return ..(command)
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/process()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/process()
|
||||
..()
|
||||
if (eject_time && world.time >= eject_time && !closing)
|
||||
close_door()
|
||||
closing = 1
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/prepare_for_docking()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/prepare_for_docking()
|
||||
return
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/ready_for_docking()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/ready_for_docking()
|
||||
return 1
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/finish_docking()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/finish_docking()
|
||||
return //don't do anything - the doors only open when the pod is armed.
|
||||
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod/prepare_for_undocking()
|
||||
/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/prepare_for_undocking()
|
||||
eject_time = world.time + eject_delay*10
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
//making this separate from /obj/effect/landmark until that mess can be dealt with
|
||||
/obj/effect/shuttle_landmark
|
||||
name = "Nav Point"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "energynet"
|
||||
anchored = 1
|
||||
unacidable = 1
|
||||
simulated = 0
|
||||
invisibility = 101
|
||||
flags = SLANDMARK_FLAG_AUTOSET // We generally want to use current area/turf as base.
|
||||
|
||||
//ID of the landmark
|
||||
var/landmark_tag
|
||||
//ID of the controller on the dock side (intialize to id_tag, becomes reference)
|
||||
var/datum/computer/file/embedded_program/docking/docking_controller
|
||||
//Map of shuttle names to ID of controller used for this landmark for shuttles with multiple ones.
|
||||
var/list/special_dock_targets
|
||||
|
||||
//When the shuttle leaves this landmark, it will leave behind the base area
|
||||
//also used to determine if the shuttle can arrive here without obstruction
|
||||
var/area/base_area
|
||||
//Will also leave this type of turf behind if set.
|
||||
var/turf/base_turf
|
||||
//Name of the shuttle, null for generic waypoint
|
||||
var/shuttle_restricted
|
||||
|
||||
/obj/effect/shuttle_landmark/Initialize()
|
||||
. = ..()
|
||||
if(docking_controller)
|
||||
. = INITIALIZE_HINT_LATELOAD
|
||||
|
||||
// Even if this flag is set, hardcoded values take precedence.
|
||||
if(flags & SLANDMARK_FLAG_AUTOSET)
|
||||
if(ispath(base_area))
|
||||
var/area/A = locate(base_area)
|
||||
if(!istype(A))
|
||||
CRASH("Shuttle landmark \"[landmark_tag]\" couldn't locate area [base_area].")
|
||||
base_area = A
|
||||
else
|
||||
base_area = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && !base_turf)
|
||||
base_turf = T.type
|
||||
else
|
||||
base_area = locate(base_area || world.area)
|
||||
|
||||
name = (name + " ([x],[y])")
|
||||
SSshuttles.register_landmark(landmark_tag, src)
|
||||
|
||||
/obj/effect/shuttle_landmark/LateInitialize()
|
||||
if(!docking_controller)
|
||||
return
|
||||
var/docking_tag = docking_controller
|
||||
docking_controller = SSshuttles.docking_registry[docking_tag]
|
||||
if(!istype(docking_controller))
|
||||
log_error("Could not find docking controller for shuttle waypoint '[name]', docking tag was '[docking_tag]'.")
|
||||
if(using_map.use_overmap)
|
||||
var/obj/effect/overmap/visitable/location = map_sectors["[z]"]
|
||||
if(location && location.docking_codes)
|
||||
docking_controller.docking_codes = location.docking_codes
|
||||
|
||||
/obj/effect/shuttle_landmark/forceMove()
|
||||
var/obj/effect/overmap/visitable/map_origin = map_sectors["[z]"]
|
||||
. = ..()
|
||||
var/obj/effect/overmap/visitable/map_destination = map_sectors["[z]"]
|
||||
if(map_origin != map_destination)
|
||||
if(map_origin)
|
||||
map_origin.remove_landmark(src, shuttle_restricted)
|
||||
if(map_destination)
|
||||
map_destination.add_landmark(src, shuttle_restricted)
|
||||
|
||||
//Called when the landmark is added to an overmap sector.
|
||||
/obj/effect/shuttle_landmark/proc/sector_set(var/obj/effect/overmap/visitable/O, shuttle_name)
|
||||
shuttle_restricted = shuttle_name
|
||||
|
||||
/obj/effect/shuttle_landmark/proc/is_valid(var/datum/shuttle/shuttle)
|
||||
if(shuttle.current_location == src)
|
||||
return FALSE
|
||||
for(var/area/A in shuttle.shuttle_area)
|
||||
var/list/translation = get_turf_translation(get_turf(shuttle.current_location), get_turf(src), A.contents)
|
||||
if(check_collision(base_area, list_values(translation)))
|
||||
return FALSE
|
||||
var/conn = GetConnectedZlevels(z)
|
||||
for(var/w in (z - shuttle.multiz) to z)
|
||||
if(!(w in conn))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
// This creates a graphical warning to where the shuttle is about to land in approximately five seconds.
|
||||
/obj/effect/shuttle_landmark/proc/create_warning_effect(var/datum/shuttle/shuttle)
|
||||
if(shuttle.current_location == src)
|
||||
return // TOO LATE!
|
||||
for(var/area/A in shuttle.shuttle_area)
|
||||
var/list/translation = get_turf_translation(get_turf(shuttle.current_location), get_turf(src), A.contents)
|
||||
for(var/T in list_values(translation))
|
||||
new /obj/effect/temporary_effect/shuttle_landing(T) // It'll delete itself when needed.
|
||||
return
|
||||
|
||||
// Should return a readable description of why not if it can't depart.
|
||||
/obj/effect/shuttle_landmark/proc/cannot_depart(datum/shuttle/shuttle)
|
||||
return FALSE
|
||||
|
||||
/obj/effect/shuttle_landmark/proc/shuttle_departed(datum/shuttle/shuttle)
|
||||
return
|
||||
|
||||
/obj/effect/shuttle_landmark/proc/shuttle_arrived(datum/shuttle/shuttle)
|
||||
return
|
||||
|
||||
/proc/check_collision(area/target_area, list/target_turfs)
|
||||
for(var/target_turf in target_turfs)
|
||||
var/turf/target = target_turf
|
||||
if(!target)
|
||||
return TRUE //collides with edge of map
|
||||
if(target.loc != target_area)
|
||||
return TRUE //collides with another area
|
||||
if(target.density)
|
||||
return TRUE //dense turf
|
||||
return FALSE
|
||||
|
||||
//
|
||||
//Self-naming/numbering ones.
|
||||
//
|
||||
/obj/effect/shuttle_landmark/automatic
|
||||
name = "Navpoint"
|
||||
landmark_tag = "navpoint"
|
||||
flags = SLANDMARK_FLAG_AUTOSET
|
||||
|
||||
/obj/effect/shuttle_landmark/automatic/Initialize()
|
||||
landmark_tag += "-[x]-[y]-[z]-[random_id("landmarks",1,9999)]"
|
||||
return ..()
|
||||
|
||||
/obj/effect/shuttle_landmark/automatic/sector_set(var/obj/effect/overmap/visitable/O)
|
||||
..()
|
||||
name = ("[O.name] - [initial(name)] ([x],[y])")
|
||||
|
||||
//Subtype that calls explosion on init to clear space for shuttles
|
||||
/obj/effect/shuttle_landmark/automatic/clearing
|
||||
var/radius = 10
|
||||
|
||||
/obj/effect/shuttle_landmark/automatic/clearing/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/effect/shuttle_landmark/automatic/clearing/LateInitialize()
|
||||
..()
|
||||
for(var/turf/T in range(radius, src))
|
||||
if(T.density)
|
||||
T.ChangeTurf(get_base_turf_by_area(T))
|
||||
|
||||
|
||||
// Subtype that also queues a shuttle datum (for shuttles starting on maps loaded at runtime)
|
||||
/obj/effect/shuttle_landmark/shuttle_initializer
|
||||
var/datum/shuttle/shuttle_type
|
||||
|
||||
/obj/effect/shuttle_landmark/shuttle_initializer/Initialize()
|
||||
. = ..()
|
||||
LAZYADD(SSshuttles.shuttles_to_initialize, shuttle_type) // queue up for init.
|
||||
|
||||
//
|
||||
// Bluespace flare landmark beacon
|
||||
//
|
||||
/obj/item/device/spaceflare
|
||||
name = "bluespace flare"
|
||||
desc = "Burst transmitter used to broadcast all needed information for shuttle navigation systems. Has a flare attached for marking the spot where you probably shouldn't be standing."
|
||||
icon_state = "bluflare"
|
||||
light_color = "#3728ff"
|
||||
var/active
|
||||
|
||||
/obj/item/device/spaceflare/attack_self(var/mob/user)
|
||||
if(!active)
|
||||
visible_message("<span class='notice'>[user] pulls the cord, activating the [src].</span>")
|
||||
activate()
|
||||
|
||||
/obj/item/device/spaceflare/proc/activate()
|
||||
if(active)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/mob/M = loc
|
||||
if(istype(M) && !M.unEquip(src, T))
|
||||
return
|
||||
|
||||
active = 1
|
||||
anchored = 1
|
||||
|
||||
var/obj/effect/shuttle_landmark/automatic/mark = new(T)
|
||||
mark.name = ("Beacon signal ([T.x],[T.y])")
|
||||
T.hotspot_expose(1500, 5)
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/spaceflare/update_icon()
|
||||
. = ..()
|
||||
if(active)
|
||||
icon_state = "bluflare_on"
|
||||
set_light(0.3, 0.1, 6, 2, "85d1ff")
|
||||
+264
-140
@@ -1,6 +1,3 @@
|
||||
//These lists are populated in /datum/controller/subsystem/shuttles/proc/setup_shuttle_docks()
|
||||
//Shuttle subsystem is instantiated in shuttles.dm.
|
||||
|
||||
//shuttle moving state defines are in setup.dm
|
||||
|
||||
/datum/shuttle
|
||||
@@ -8,48 +5,78 @@
|
||||
var/warmup_time = 0
|
||||
var/moving_status = SHUTTLE_IDLE
|
||||
|
||||
var/docking_controller_tag //tag of the controller used to coordinate docking
|
||||
var/datum/computer/file/embedded_program/docking/docking_controller //the controller itself. (micro-controller, not game controller)
|
||||
var/list/shuttle_area // Initial value can be either a single area type or a list of area types
|
||||
var/obj/effect/shuttle_landmark/current_location //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
|
||||
|
||||
var/arrive_time = 0 //the time at which the shuttle arrives when long jumping
|
||||
var/depart_time = 0 //Similar to above, set when the shuttle leaves when long jumping, to compare against arrive time.
|
||||
var/flags = SHUTTLE_FLAGS_PROCESS
|
||||
var/tmp/arrive_time = 0 //the time at which the shuttle arrives when long jumping
|
||||
var/flags = SHUTTLE_FLAGS_NONE
|
||||
var/process_state = IDLE_STATE // Used with SHUTTLE_FLAGS_PROCESS, as well as to store current state.
|
||||
var/category = /datum/shuttle
|
||||
var/multiz = 0 //how many multiz levels, starts at 0 TODO Leshana - Are we porting this?
|
||||
|
||||
var/ceiling_type = /turf/unsimulated/floor/shuttle_ceiling
|
||||
var/ceiling_type // Type path of turf to roof over the shuttle when at multi-z landmarks. Ignored if null.
|
||||
|
||||
/datum/shuttle/New()
|
||||
var/sound_takeoff = 'sound/effects/shuttles/shuttle_takeoff.ogg'
|
||||
var/sound_landing = 'sound/effects/shuttles/shuttle_landing.ogg'
|
||||
|
||||
var/knockdown = 1 //whether shuttle downs non-buckled people when it moves
|
||||
|
||||
var/defer_initialisation = FALSE //If this this shuttle should be initialised automatically.
|
||||
//If set to true, you are responsible for initialzing the shuttle manually.
|
||||
//Useful for shuttles that are initialized by map_template loading, or shuttles that are created in-game or not used.
|
||||
|
||||
var/mothershuttle //tag of mothershuttle
|
||||
var/motherdock //tag of mothershuttle landmark, defaults to starting location
|
||||
|
||||
var/tmp/depart_time = 0 //Similar to above, set when the shuttle leaves when long jumping. Used for progress bars.
|
||||
|
||||
// Future Thoughts: Baystation put "docking" stuff in a subtype, leaving base type pure and free of docking stuff. Is this best?
|
||||
|
||||
/datum/shuttle/New(_name, var/obj/effect/shuttle_landmark/initial_location)
|
||||
..()
|
||||
if(src.name in shuttle_controller.shuttles)
|
||||
if(_name)
|
||||
src.name = _name
|
||||
|
||||
var/list/areas = list()
|
||||
if(!islist(shuttle_area))
|
||||
shuttle_area = list(shuttle_area)
|
||||
for(var/T in shuttle_area)
|
||||
var/area/A = locate(T)
|
||||
if(!istype(A))
|
||||
CRASH("Shuttle \"[name]\" couldn't locate area [T].")
|
||||
areas += A
|
||||
shuttle_area = areas
|
||||
|
||||
if(initial_location)
|
||||
current_location = initial_location
|
||||
else
|
||||
current_location = SSshuttles.get_landmark(current_location)
|
||||
if(!istype(current_location))
|
||||
log_debug("UM whoops, no initial? [src]")
|
||||
CRASH("Shuttle '[name]' could not find its starting location landmark [current_location].")
|
||||
|
||||
if(src.name in SSshuttles.shuttles)
|
||||
CRASH("A shuttle with the name '[name]' is already defined.")
|
||||
shuttle_controller.shuttles[src.name] = src
|
||||
SSshuttles.shuttles[src.name] = src
|
||||
if(flags & SHUTTLE_FLAGS_PROCESS)
|
||||
shuttle_controller.process_shuttles += src
|
||||
SSshuttles.process_shuttles += src
|
||||
if(flags & SHUTTLE_FLAGS_SUPPLY)
|
||||
if(supply_controller.shuttle)
|
||||
CRASH("A supply shuttle is already defined.")
|
||||
supply_controller.shuttle = src
|
||||
|
||||
/datum/shuttle/Destroy()
|
||||
shuttle_controller.shuttles -= src.name
|
||||
shuttle_controller.process_shuttles -= src
|
||||
current_location = null
|
||||
SSshuttles.shuttles -= src.name
|
||||
SSshuttles.process_shuttles -= src
|
||||
SSshuttles.shuttle_logs -= src
|
||||
if(supply_controller.shuttle == src)
|
||||
supply_controller.shuttle = null
|
||||
. = ..()
|
||||
|
||||
/datum/shuttle/process()
|
||||
return
|
||||
|
||||
/datum/shuttle/proc/init_docking_controllers()
|
||||
if(docking_controller_tag)
|
||||
docking_controller = locate(docking_controller_tag)
|
||||
if(!istype(docking_controller))
|
||||
to_world("<span class='danger'>warning: shuttle with docking tag [docking_controller_tag] could not find it's controller!</span>")
|
||||
|
||||
// This creates a graphical warning to where the shuttle is about to land, in approximately five seconds.
|
||||
/datum/shuttle/proc/create_warning_effect(area/landing_area)
|
||||
for(var/turf/T in landing_area)
|
||||
new /obj/effect/temporary_effect/shuttle_landing(T) // It'll delete itself when needed.
|
||||
/datum/shuttle/proc/create_warning_effect(var/obj/effect/shuttle_landmark/destination)
|
||||
destination.create_warning_effect(src)
|
||||
|
||||
// Return false to abort a jump, before the 'warmup' phase.
|
||||
/datum/shuttle/proc/pre_warmup_checks()
|
||||
@@ -60,194 +87,271 @@
|
||||
return TRUE
|
||||
|
||||
// If you need an event to occur when the shuttle jumps in short or long jump, override this.
|
||||
/datum/shuttle/proc/on_shuttle_departure(var/area/origin)
|
||||
origin.shuttle_departed()
|
||||
// Keep in mind that destination is the intended destination, the shuttle may or may not actually reach it.s
|
||||
/datum/shuttle/proc/on_shuttle_departure(var/obj/effect/shuttle_landmark/origin, var/obj/effect/shuttle_landmark/destination)
|
||||
return
|
||||
|
||||
// Similar to above, but when it finishes moving to the target. Short jump generally makes this occur immediately after the above proc.
|
||||
/datum/shuttle/proc/on_shuttle_arrival(var/area/destination)
|
||||
destination.shuttle_arrived()
|
||||
// Keep in mind we might not actually have gotten to destination. Check current_location to be sure where we ended up.
|
||||
/datum/shuttle/proc/on_shuttle_arrival(var/obj/effect/shuttle_landmark/origin, var/obj/effect/shuttle_landmark/destination)
|
||||
return
|
||||
|
||||
/datum/shuttle/proc/short_jump(var/area/origin,var/area/destination)
|
||||
/datum/shuttle/proc/short_jump(var/obj/effect/shuttle_landmark/destination)
|
||||
if(moving_status != SHUTTLE_IDLE)
|
||||
return
|
||||
|
||||
if(!pre_warmup_checks())
|
||||
return
|
||||
|
||||
var/obj/effect/shuttle_landmark/start_location = current_location
|
||||
// TODO - Figure out exactly when to play sounds. Before warmup_time delay? Should there be a sleep for waiting for sounds? or no?
|
||||
moving_status = SHUTTLE_WARMUP
|
||||
spawn(warmup_time*10)
|
||||
|
||||
make_sounds(origin, HYPERSPACE_WARMUP)
|
||||
make_sounds(HYPERSPACE_WARMUP)
|
||||
create_warning_effect(destination)
|
||||
sleep(5 SECONDS) // so the sound finishes.
|
||||
|
||||
if(!post_warmup_checks())
|
||||
moving_status = SHUTTLE_IDLE
|
||||
cancel_launch(null)
|
||||
|
||||
if(!fuel_check()) //fuel error (probably out of fuel) occured, so cancel the launch
|
||||
cancel_launch(null)
|
||||
|
||||
if (moving_status == SHUTTLE_IDLE)
|
||||
make_sounds(origin, HYPERSPACE_END)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
return //someone cancelled the launch
|
||||
|
||||
on_shuttle_departure(origin)
|
||||
|
||||
moving_status = SHUTTLE_INTRANSIT //shouldn't matter but just to be safe
|
||||
move(origin, destination)
|
||||
on_shuttle_departure(start_location, destination)
|
||||
|
||||
attempt_move(destination)
|
||||
|
||||
moving_status = SHUTTLE_IDLE
|
||||
on_shuttle_arrival(start_location, destination)
|
||||
|
||||
on_shuttle_arrival(destination)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
|
||||
make_sounds(destination, HYPERSPACE_END)
|
||||
|
||||
/datum/shuttle/proc/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction)
|
||||
//to_world("shuttle/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]")
|
||||
// TODO - Far Future - Would be great if this was driven by process too.
|
||||
/datum/shuttle/proc/long_jump(var/obj/effect/shuttle_landmark/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time)
|
||||
//to_world("shuttle/long_jump: current_location=[current_location], destination=[destination], interim=[interim], travel_time=[travel_time]")
|
||||
if(moving_status != SHUTTLE_IDLE)
|
||||
return
|
||||
|
||||
if(!pre_warmup_checks())
|
||||
return
|
||||
|
||||
//it would be cool to play a sound here
|
||||
var/obj/effect/shuttle_landmark/start_location = current_location
|
||||
// TODO - Figure out exactly when to play sounds. Before warmup_time delay? Should there be a sleep for waiting for sounds? or no?
|
||||
moving_status = SHUTTLE_WARMUP
|
||||
spawn(warmup_time*10)
|
||||
|
||||
make_sounds(departing, HYPERSPACE_WARMUP)
|
||||
make_sounds(HYPERSPACE_WARMUP)
|
||||
create_warning_effect(interim) // Really doubt someone is gonna get crushed in the interim area but for completeness's sake we'll make the warning.
|
||||
sleep(5 SECONDS) // so the sound finishes.
|
||||
|
||||
if(!post_warmup_checks())
|
||||
moving_status = SHUTTLE_IDLE
|
||||
cancel_launch(null)
|
||||
|
||||
if (moving_status == SHUTTLE_IDLE)
|
||||
make_sounds(departing, HYPERSPACE_END)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
return //someone cancelled the launch
|
||||
|
||||
arrive_time = world.time + travel_time*10
|
||||
|
||||
depart_time = world.time
|
||||
|
||||
moving_status = SHUTTLE_INTRANSIT
|
||||
on_shuttle_departure(start_location, destination)
|
||||
|
||||
on_shuttle_departure(departing)
|
||||
if(attempt_move(interim, TRUE))
|
||||
interim.shuttle_arrived()
|
||||
|
||||
move(departing, interim, direction)
|
||||
interim.shuttle_arrived()
|
||||
var/last_progress_sound = 0
|
||||
var/made_warning = FALSE
|
||||
while (world.time < arrive_time)
|
||||
// Make the shuttle make sounds every four seconds, since the sound file is five seconds.
|
||||
if(last_progress_sound + 4 SECONDS < world.time)
|
||||
make_sounds(HYPERSPACE_PROGRESS)
|
||||
last_progress_sound = world.time
|
||||
|
||||
var/last_progress_sound = 0
|
||||
var/made_warning = FALSE
|
||||
while (world.time < arrive_time)
|
||||
// Make the shuttle make sounds every four seconds, since the sound file is five seconds.
|
||||
if(last_progress_sound + 4 SECONDS < world.time)
|
||||
make_sounds(interim, HYPERSPACE_PROGRESS)
|
||||
last_progress_sound = world.time
|
||||
if(arrive_time - world.time <= 5 SECONDS && !made_warning)
|
||||
made_warning = TRUE
|
||||
create_warning_effect(destination)
|
||||
sleep(5)
|
||||
|
||||
if(arrive_time - world.time <= 5 SECONDS && !made_warning)
|
||||
made_warning = TRUE
|
||||
create_warning_effect(destination)
|
||||
sleep(5)
|
||||
if(!attempt_move(destination))
|
||||
attempt_move(start_location) //try to go back to where we started. If that fails, I guess we're stuck in the interim location
|
||||
|
||||
interim.shuttle_departed()
|
||||
move(interim, destination, direction)
|
||||
moving_status = SHUTTLE_IDLE
|
||||
on_shuttle_arrival(start_location, destination)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
|
||||
on_shuttle_arrival(destination)
|
||||
|
||||
make_sounds(destination, HYPERSPACE_END)
|
||||
//////////////////////////////
|
||||
// Forward declarations of public procs. They do nothing because this is not auto-dock.
|
||||
|
||||
/datum/shuttle/proc/fuel_check()
|
||||
return 1 //fuel check should always pass in non-overmap shuttles (they have magic engines)
|
||||
|
||||
/datum/shuttle/proc/cancel_launch(var/user)
|
||||
// If we are past warming up its too late to cancel.
|
||||
if (moving_status == SHUTTLE_WARMUP)
|
||||
moving_status = SHUTTLE_IDLE
|
||||
/*
|
||||
Docking stuff
|
||||
*/
|
||||
/datum/shuttle/proc/dock()
|
||||
if (!docking_controller)
|
||||
return
|
||||
|
||||
var/dock_target = current_dock_target()
|
||||
if (!dock_target)
|
||||
return
|
||||
|
||||
docking_controller.initiate_docking(dock_target)
|
||||
return
|
||||
|
||||
/datum/shuttle/proc/undock()
|
||||
if (!docking_controller)
|
||||
return
|
||||
docking_controller.initiate_undocking()
|
||||
return
|
||||
|
||||
/datum/shuttle/proc/current_dock_target()
|
||||
return null
|
||||
/datum/shuttle/proc/force_undock()
|
||||
return
|
||||
|
||||
/datum/shuttle/proc/skip_docking_checks()
|
||||
if (!docking_controller || !current_dock_target())
|
||||
return 1 //shuttles without docking controllers or at locations without docking ports act like old-style shuttles
|
||||
return 0
|
||||
// Check if we are docked (or never dock) and thus have properly arrived.
|
||||
/datum/shuttle/proc/check_docked()
|
||||
return TRUE
|
||||
|
||||
//just moves the shuttle from A to B, if it can be moved
|
||||
//A note to anyone overriding move in a subtype. move() must absolutely not, under any circumstances, fail to move the shuttle.
|
||||
// Check if we are undocked and thus probably ready to depart.
|
||||
/datum/shuttle/proc/check_undocked()
|
||||
return TRUE
|
||||
|
||||
/*****************
|
||||
* Shuttle Moved Handling * (Observer Pattern Implementation: Shuttle Moved)
|
||||
* Shuttle Pre Move Handling * (Observer Pattern Implementation: Shuttle Pre Move)
|
||||
*****************/
|
||||
|
||||
// Move the shuttle to destination if possible.
|
||||
// Returns TRUE if we actually moved, otherwise FALSE.
|
||||
/datum/shuttle/proc/attempt_move(var/obj/effect/shuttle_landmark/destination, var/interim = FALSE)
|
||||
if(current_location == destination)
|
||||
log_shuttle("Shuttle [src] attempted to move to [destination] but is already there!")
|
||||
return FALSE
|
||||
|
||||
if(!destination.is_valid(src))
|
||||
log_shuttle("Shuttle [src] aborting attempt_move() because destination=[destination] is not valid")
|
||||
return FALSE
|
||||
if(current_location.cannot_depart(src))
|
||||
log_shuttle("Shuttle [src] aborting attempt_move() because current_location=[current_location] refuses.")
|
||||
return FALSE
|
||||
|
||||
log_shuttle("[src] moving to [destination]. Areas are [english_list(shuttle_area)]")
|
||||
var/list/translation = list()
|
||||
for(var/area/A in shuttle_area)
|
||||
log_shuttle("Translating [A]")
|
||||
translation += get_turf_translation(get_turf(current_location), get_turf(destination), A.contents)
|
||||
var/old_location = current_location
|
||||
|
||||
// Observer pattern pre-move
|
||||
GLOB.shuttle_pre_move_event.raise_event(src, old_location, destination)
|
||||
current_location.shuttle_departed(src)
|
||||
|
||||
// Actually do it! (This never fails)
|
||||
perform_shuttle_move(destination, translation)
|
||||
|
||||
// Observer pattern post-move
|
||||
destination.shuttle_arrived(src)
|
||||
GLOB.shuttle_moved_event.raise_event(src, old_location, destination)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
//just moves the shuttle from A to B
|
||||
//A note to anyone overriding move in a subtype. perform_shuttle_move() must absolutely not, under any circumstances, fail to move the shuttle.
|
||||
//If you want to conditionally cancel shuttle launches, that logic must go in short_jump() or long_jump()
|
||||
/datum/shuttle/proc/move(var/area/origin, var/area/destination, var/direction=null)
|
||||
|
||||
/datum/shuttle/proc/perform_shuttle_move(var/obj/effect/shuttle_landmark/destination, var/list/turf_translation)
|
||||
log_shuttle("perform_shuttle_move() current=[current_location] destination=[destination]")
|
||||
//to_world("move_shuttle() called for [name] leaving [origin] en route to [destination].")
|
||||
|
||||
//to_world("area_coming_from: [origin]")
|
||||
//to_world("destination: [destination]")
|
||||
ASSERT(current_location != destination)
|
||||
|
||||
if(origin == destination)
|
||||
//to_world("cancelling move, shuttle will overlap.")
|
||||
return
|
||||
// If shuttle has no internal gravity, update our gravity with destination gravity
|
||||
if((flags & SHUTTLE_FLAGS_ZERO_G))
|
||||
var/new_grav = 1
|
||||
if(destination.flags & SLANDMARK_FLAG_ZERO_G)
|
||||
var/area/new_area = get_area(destination)
|
||||
new_grav = new_area.has_gravity
|
||||
for(var/area/our_area in shuttle_area)
|
||||
if(our_area.has_gravity != new_grav)
|
||||
our_area.gravitychange(new_grav)
|
||||
|
||||
if (docking_controller && !docking_controller.undocked())
|
||||
docking_controller.force_undock()
|
||||
// TODO - Old code used to throw stuff out of the way instead of squashing. Should we?
|
||||
|
||||
var/list/dstturfs = list()
|
||||
var/throwy = world.maxy
|
||||
|
||||
for(var/turf/T in destination)
|
||||
dstturfs += T
|
||||
if(T.y < throwy)
|
||||
throwy = T.y
|
||||
|
||||
for(var/turf/T in dstturfs)
|
||||
var/turf/D = locate(T.x, throwy - 1, T.z)
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.Move(D)
|
||||
|
||||
for(var/mob/living/carbon/bug in destination)
|
||||
bug.gib()
|
||||
|
||||
for(var/mob/living/simple_mob/pest in destination)
|
||||
pest.gib()
|
||||
|
||||
origin.move_contents_to(destination, direction=direction)
|
||||
|
||||
for(var/mob/M in destination)
|
||||
if(M.client)
|
||||
spawn(0)
|
||||
if(M.buckled)
|
||||
to_chat(M, "<font color='red'>Sudden acceleration presses you into \the [M.buckled]!</font>")
|
||||
shake_camera(M, 3, 1)
|
||||
// Move, gib, or delete everything in our way!
|
||||
for(var/turf/src_turf in turf_translation)
|
||||
var/turf/dst_turf = turf_translation[src_turf]
|
||||
if(src_turf.is_solid_structure()) // in case someone put a hole in the shuttle and you were lucky enough to be under it
|
||||
for(var/atom/movable/AM in dst_turf)
|
||||
//if(AM.movable_flags & MOVABLE_FLAG_DEL_SHUTTLE)
|
||||
// qdel(AM)
|
||||
// continue
|
||||
if(!AM.simulated)
|
||||
continue
|
||||
if(isliving(AM))
|
||||
var/mob/living/bug = AM
|
||||
bug.gib()
|
||||
else
|
||||
to_chat(M, "<font color='red'>The floor lurches beneath you!</font>")
|
||||
shake_camera(M, 10, 1)
|
||||
if(istype(M, /mob/living/carbon))
|
||||
if(!M.buckled)
|
||||
M.Weaken(3)
|
||||
qdel(AM) //it just gets atomized I guess? TODO throw it into space somewhere, prevents people from using shuttles as an atom-smasher
|
||||
|
||||
var/list/powernets = list()
|
||||
for(var/area/A in shuttle_area)
|
||||
// If there was a zlevel above our origin and we own the ceiling, erase our ceiling now we're leaving
|
||||
if(ceiling_type && HasAbove(current_location.z))
|
||||
for(var/turf/TO in A.contents)
|
||||
var/turf/TA = GetAbove(TO)
|
||||
if(istype(TA, ceiling_type))
|
||||
TA.ChangeTurf(get_base_turf_by_area(TA), 1, 1)
|
||||
if(knockdown)
|
||||
for(var/mob/living/M in A)
|
||||
spawn(0)
|
||||
if(M.buckled)
|
||||
to_chat(M, "<font color='red'>Sudden acceleration presses you into \the [M.buckled]!</font>")
|
||||
shake_camera(M, 3, 1)
|
||||
else
|
||||
to_chat(M, "<font color='red'>The floor lurches beneath you!</font>")
|
||||
shake_camera(M, 10, 1)
|
||||
// TODO - tossing?
|
||||
//M.visible_message("<span class='warning'>[M.name] is tossed around by the sudden acceleration!</span>")
|
||||
//M.throw_at_random(FALSE, 4, 1)
|
||||
if(istype(M, /mob/living/carbon))
|
||||
M.Weaken(3)
|
||||
// We only need to rebuild powernets for our cables. No need to check machines because they are on top of cables.
|
||||
for(var/obj/structure/cable/C in A)
|
||||
powernets |= C.powernet
|
||||
|
||||
// Actually do the movement of everything - This replaces origin.move_contents_to(destination)
|
||||
translate_turfs(turf_translation, current_location.base_area, current_location.base_turf)
|
||||
current_location = destination
|
||||
|
||||
// If there's a zlevel above our destination, paint in a ceiling on it so we retain our air
|
||||
if(ceiling_type && HasAbove(current_location.z))
|
||||
for(var/area/A in shuttle_area)
|
||||
for(var/turf/TD in A.contents)
|
||||
var/turf/TA = GetAbove(TD)
|
||||
if(istype(TA, get_base_turf_by_area(TA)) || isopenspace(TA))
|
||||
if(get_area(TA) in shuttle_area)
|
||||
continue
|
||||
TA.ChangeTurf(ceiling_type, TRUE, TRUE, TRUE)
|
||||
|
||||
// Power-related checks. If shuttle contains power related machinery, update powernets.
|
||||
var/update_power = 0
|
||||
for(var/obj/machinery/power/P in destination)
|
||||
update_power = 1
|
||||
break
|
||||
// Note: Old way was to rebuild ALL powernets: if(powernets.len) SSmachines.makepowernets()
|
||||
// New way only rebuilds the powernets we have to
|
||||
var/list/cables = list()
|
||||
for(var/datum/powernet/P in powernets)
|
||||
cables |= P.cables
|
||||
qdel(P)
|
||||
SSmachines.setup_powernets_for_cables(cables)
|
||||
|
||||
for(var/obj/structure/cable/C in destination)
|
||||
update_power = 1
|
||||
break
|
||||
|
||||
if(update_power)
|
||||
SSmachines.makepowernets()
|
||||
return
|
||||
|
||||
//returns 1 if the shuttle has a valid arrive time
|
||||
/datum/shuttle/proc/has_arrive_time()
|
||||
return (moving_status == SHUTTLE_INTRANSIT)
|
||||
|
||||
/datum/shuttle/proc/make_sounds(var/area/A, var/sound_type)
|
||||
/datum/shuttle/proc/make_sounds(var/sound_type)
|
||||
var/sound_to_play = null
|
||||
switch(sound_type)
|
||||
if(HYPERSPACE_WARMUP)
|
||||
@@ -256,9 +360,29 @@
|
||||
sound_to_play = 'sound/effects/shuttles/hyperspace_progress.ogg'
|
||||
if(HYPERSPACE_END)
|
||||
sound_to_play = 'sound/effects/shuttles/hyperspace_end.ogg'
|
||||
for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice
|
||||
playsound(E, sound_to_play, 50, FALSE)
|
||||
for(var/area/A in shuttle_area)
|
||||
for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice
|
||||
playsound(E, sound_to_play, 50, FALSE)
|
||||
|
||||
/datum/shuttle/proc/message_passengers(area/A, var/message)
|
||||
for(var/mob/M in A)
|
||||
M.show_message(message, 2)
|
||||
/datum/shuttle/proc/message_passengers(var/message)
|
||||
for(var/area/A in shuttle_area)
|
||||
for(var/mob/M in A)
|
||||
M.show_message(message, 2)
|
||||
|
||||
/datum/shuttle/proc/find_children()
|
||||
. = list()
|
||||
for(var/shuttle_name in SSshuttles.shuttles)
|
||||
var/datum/shuttle/shuttle = SSshuttles.shuttles[shuttle_name]
|
||||
if(shuttle.mothershuttle == name)
|
||||
. += shuttle
|
||||
|
||||
//Returns the areas in shuttle_area that are not actually child shuttles.
|
||||
/datum/shuttle/proc/find_childfree_areas()
|
||||
. = shuttle_area.Copy()
|
||||
for(var/datum/shuttle/child in find_children())
|
||||
. -= child.shuttle_area
|
||||
|
||||
/datum/shuttle/proc/get_location_name()
|
||||
if(moving_status == SHUTTLE_INTRANSIT)
|
||||
return "In transit"
|
||||
return current_location.name
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
// The new arrivals shuttle.
|
||||
/datum/shuttle/ferry/arrivals
|
||||
/datum/shuttle/autodock/ferry/arrivals
|
||||
category = /datum/shuttle/autodock/ferry/arrivals
|
||||
|
||||
name = "Arrivals"
|
||||
location = 1
|
||||
location = FERRY_LOCATION_OFFSITE
|
||||
warmup_time = 25 // Warmup takes 5 seconds, so 30 total.
|
||||
always_process = TRUE
|
||||
var/launch_delay = 3
|
||||
|
||||
area_offsite = /area/shuttle/arrival/pre_game // not really 'pre game' but this area is already defined and unused
|
||||
area_station = /area/shuttle/arrival/station
|
||||
docking_controller_tag = "arrivals_shuttle"
|
||||
dock_target_station = "arrivals_dock"
|
||||
// Maps must implement their own subtype for their arrivals shuttle, and define at least:
|
||||
// shuttle_area
|
||||
// landmark_station (Which should define its dock target)
|
||||
// landmark_offsite
|
||||
// docking_controller_tag
|
||||
|
||||
// For debugging.
|
||||
/obj/machinery/computer/shuttle_control/arrivals
|
||||
@@ -18,36 +21,42 @@
|
||||
shuttle_tag = "Arrivals"
|
||||
|
||||
// Unlike most shuttles, the arrivals shuttle is completely automated, so we need to put some additional code here.
|
||||
|
||||
// Process the arrivals shuttle even when idle.
|
||||
/obj/machinery/computer/shuttle_control/arrivals/process()
|
||||
var/datum/shuttle/autodock/ferry/arrivals/shuttle = SSshuttles.shuttles[shuttle_tag]
|
||||
if(shuttle && shuttle.process_state == IDLE_STATE)
|
||||
shuttle.process()
|
||||
..()
|
||||
|
||||
// This proc checks if anyone is on the shuttle.
|
||||
/datum/shuttle/ferry/arrivals/proc/check_for_passengers(area/A)
|
||||
for(var/mob/living/L in A)
|
||||
return TRUE
|
||||
/datum/shuttle/autodock/ferry/arrivals/proc/check_for_passengers()
|
||||
for(var/area/A in shuttle_area)
|
||||
for(var/mob/living/L in A)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// This is to stop the shuttle if someone tries to stow away when its leaving.
|
||||
/datum/shuttle/ferry/arrivals/post_warmup_checks()
|
||||
/datum/shuttle/autodock/ferry/arrivals/post_warmup_checks()
|
||||
if(!location) // If we're at station.
|
||||
if(check_for_passengers(area_station))
|
||||
if(check_for_passengers())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/shuttle/ferry/arrivals/process()
|
||||
/datum/shuttle/autodock/ferry/arrivals/process()
|
||||
if(process_state == IDLE_STATE)
|
||||
|
||||
if(location) // If we're off-station (space).
|
||||
if(check_for_passengers(area_offsite)) // No point arriving with an empty shuttle.
|
||||
if(check_for_passengers()) // No point arriving with an empty shuttle.
|
||||
warmup_time = initial(warmup_time)
|
||||
launch()
|
||||
message_passengers(area_offsite, "Arriving at [using_map.station_name] in thirty seconds...")
|
||||
message_passengers("Arriving at [using_map.station_name] in thirty seconds...")
|
||||
spawn(10 SECONDS)
|
||||
message_passengers(area_offsite, "Arriving at [using_map.station_name] in twenty seconds.")
|
||||
message_passengers("Arriving at [using_map.station_name] in twenty seconds.")
|
||||
spawn(10 SECONDS)
|
||||
message_passengers(area_offsite, "Arriving at [using_map.station_name] in ten seconds. Please buckle up.")
|
||||
message_passengers("Arriving at [using_map.station_name] in ten seconds. Please buckle up.")
|
||||
|
||||
else // We are at the station.
|
||||
if(!check_for_passengers(area_station)) // Don't leave with anyone.
|
||||
if(!check_for_passengers()) // Don't leave with anyone.
|
||||
if(launch_delay) // Give some time to get on the docks so people don't get trapped inbetween the dock airlocks.
|
||||
launch_delay--
|
||||
else
|
||||
@@ -58,7 +67,7 @@
|
||||
..() // Do everything else
|
||||
|
||||
/*
|
||||
/datum/shuttle/ferry/arrivals/current_dock_target()
|
||||
/datum/shuttle/autodock/ferry/arrivals/current_dock_target()
|
||||
if(location) // If we're off station.
|
||||
return null // Nothing to dock to in space.
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
#define DOCK_ATTEMPT_TIMEOUT 200 //how long in ticks we wait before assuming the docking controller is broken or blown up.
|
||||
|
||||
// Subtype of shuttle that handles docking with docking controllers
|
||||
// Consists of code pulled down from the old /datum/shuttle and up from /datum/shuttle/ferry
|
||||
// Note: Since all known shuttles extend this type, this really could just be built into /datum/shuttle
|
||||
// Why isn't it you ask? Eh, baystation did it this way and its convenient to keep the files smaller I guess.
|
||||
/datum/shuttle/autodock
|
||||
var/in_use = null // Tells the controller whether this shuttle needs processing, also attempts to prevent double-use
|
||||
var/last_dock_attempt_time = 0
|
||||
|
||||
var/docking_controller_tag = null // ID of the controller on the shuttle (If multiple, this is the default one)
|
||||
var/datum/computer/file/embedded_program/docking/shuttle_docking_controller // Controller on the shuttle (the one in use)
|
||||
var/docking_codes
|
||||
|
||||
var/tmp/obj/effect/shuttle_landmark/next_location //This is only used internally.
|
||||
var/datum/computer/file/embedded_program/docking/active_docking_controller // Controller we are docked with (or trying to)
|
||||
|
||||
var/obj/effect/shuttle_landmark/landmark_transition //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
|
||||
var/move_time = 240 //the time spent in the transition area
|
||||
|
||||
category = /datum/shuttle/autodock
|
||||
flags = SHUTTLE_FLAGS_PROCESS | SHUTTLE_FLAGS_ZERO_G
|
||||
|
||||
/datum/shuttle/autodock/New(var/_name, var/obj/effect/shuttle_landmark/start_waypoint)
|
||||
..(_name, start_waypoint)
|
||||
|
||||
//Initial dock
|
||||
active_docking_controller = current_location.docking_controller
|
||||
update_docking_target(current_location)
|
||||
if(active_docking_controller)
|
||||
set_docking_codes(active_docking_controller.docking_codes)
|
||||
else if(global.using_map.use_overmap)
|
||||
var/obj/effect/overmap/visitable/location = map_sectors["[current_location.z]"]
|
||||
if(location && location.docking_codes)
|
||||
set_docking_codes(location.docking_codes)
|
||||
dock()
|
||||
|
||||
//Optional transition area
|
||||
if(landmark_transition)
|
||||
landmark_transition = SSshuttles.get_landmark(landmark_transition)
|
||||
|
||||
/datum/shuttle/autodock/Destroy()
|
||||
in_use = null
|
||||
next_location = null
|
||||
active_docking_controller = null
|
||||
landmark_transition = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/autodock/proc/set_docking_codes(var/code)
|
||||
docking_codes = code
|
||||
if(shuttle_docking_controller)
|
||||
shuttle_docking_controller.docking_codes = code
|
||||
|
||||
/datum/shuttle/autodock/perform_shuttle_move()
|
||||
force_undock() //bye!
|
||||
..()
|
||||
|
||||
// Despite the name this actually updates the SHUTTLE docking conroller, not the active.
|
||||
/datum/shuttle/autodock/proc/update_docking_target(var/obj/effect/shuttle_landmark/location)
|
||||
var/current_dock_target
|
||||
if(location && location.special_dock_targets && location.special_dock_targets[name])
|
||||
current_dock_target = location.special_dock_targets[name]
|
||||
else
|
||||
current_dock_target = docking_controller_tag
|
||||
shuttle_docking_controller = SSshuttles.docking_registry[current_dock_target]
|
||||
if(current_dock_target && !shuttle_docking_controller)
|
||||
to_world("<span class='danger'>warning: shuttle [src] can't find its controller with tag [current_dock_target]!</span>")
|
||||
/*
|
||||
Docking stuff
|
||||
*/
|
||||
/datum/shuttle/autodock/dock()
|
||||
if(active_docking_controller && shuttle_docking_controller)
|
||||
shuttle_docking_controller.initiate_docking(active_docking_controller.id_tag)
|
||||
last_dock_attempt_time = world.time
|
||||
|
||||
/datum/shuttle/autodock/undock()
|
||||
if(shuttle_docking_controller)
|
||||
shuttle_docking_controller.initiate_undocking()
|
||||
|
||||
/datum/shuttle/autodock/force_undock()
|
||||
if(shuttle_docking_controller)
|
||||
shuttle_docking_controller.force_undock()
|
||||
|
||||
/datum/shuttle/autodock/check_docked()
|
||||
if(shuttle_docking_controller)
|
||||
return shuttle_docking_controller.docked()
|
||||
return TRUE
|
||||
|
||||
/datum/shuttle/autodock/check_undocked()
|
||||
if(shuttle_docking_controller)
|
||||
return shuttle_docking_controller.can_launch()
|
||||
return TRUE
|
||||
|
||||
// You also could just directly reference active_docking_controller
|
||||
/datum/shuttle/autodock/proc/current_dock_target()
|
||||
if(active_docking_controller)
|
||||
return active_docking_controller.id_tag
|
||||
return null
|
||||
|
||||
// These checks are built into the check_docked() and check_undocked() procs
|
||||
/datum/shuttle/autodock/proc/skip_docking_checks()
|
||||
if (!shuttle_docking_controller || !current_dock_target())
|
||||
return TRUE //shuttles without docking controllers or at locations without docking ports act like old-style shuttles
|
||||
return FALSE
|
||||
|
||||
|
||||
/*
|
||||
Please ensure that long_jump() and short_jump() are only called from here. This applies to subtypes as well.
|
||||
Doing so will ensure that multiple jumps cannot be initiated in parallel.
|
||||
*/
|
||||
/datum/shuttle/autodock/process()
|
||||
switch(process_state)
|
||||
if (WAIT_LAUNCH)
|
||||
if(check_undocked())
|
||||
//*** ready to go
|
||||
process_launch()
|
||||
|
||||
if (FORCE_LAUNCH)
|
||||
process_launch()
|
||||
|
||||
if (WAIT_ARRIVE)
|
||||
if (moving_status == SHUTTLE_IDLE)
|
||||
//*** we made it to the destination, update stuff
|
||||
process_arrived()
|
||||
process_state = WAIT_FINISH
|
||||
|
||||
if (WAIT_FINISH)
|
||||
if (world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT || check_docked())
|
||||
//*** all done here
|
||||
process_state = IDLE_STATE
|
||||
arrived()
|
||||
|
||||
//not to be confused with the arrived() proc
|
||||
/datum/shuttle/autodock/proc/process_arrived()
|
||||
active_docking_controller = next_location.docking_controller
|
||||
update_docking_target(next_location)
|
||||
dock()
|
||||
|
||||
next_location = null
|
||||
in_use = null //release lock
|
||||
|
||||
/datum/shuttle/autodock/proc/get_travel_time()
|
||||
return move_time
|
||||
|
||||
/datum/shuttle/autodock/proc/process_launch()
|
||||
if(!next_location || !next_location.is_valid(src) || current_location.cannot_depart(src))
|
||||
process_state = IDLE_STATE
|
||||
in_use = null
|
||||
return
|
||||
if (get_travel_time() && landmark_transition)
|
||||
. = long_jump(next_location, landmark_transition, get_travel_time())
|
||||
else
|
||||
. = short_jump(next_location)
|
||||
process_state = WAIT_ARRIVE
|
||||
|
||||
/*
|
||||
Guards - (These don't take docking status into account, just the state machine and move safety)
|
||||
*/
|
||||
/datum/shuttle/autodock/proc/can_launch()
|
||||
return (next_location && next_location.is_valid(src) && !current_location.cannot_depart(src) && moving_status == SHUTTLE_IDLE && !in_use)
|
||||
|
||||
/datum/shuttle/autodock/proc/can_force()
|
||||
return (next_location && next_location.is_valid(src) && !current_location.cannot_depart(src) && moving_status == SHUTTLE_IDLE && process_state == WAIT_LAUNCH)
|
||||
|
||||
/datum/shuttle/autodock/proc/can_cancel()
|
||||
return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH)
|
||||
|
||||
/*
|
||||
"Public" procs
|
||||
*/
|
||||
// Queue shuttle for undock and launch by shuttle subsystem.
|
||||
/datum/shuttle/autodock/proc/launch(var/user)
|
||||
if (!can_launch()) return
|
||||
|
||||
in_use = user //obtain an exclusive lock on the shuttle
|
||||
|
||||
process_state = WAIT_LAUNCH
|
||||
undock()
|
||||
|
||||
// Queue shuttle for forced undock and launch by shuttle subsystem.
|
||||
/datum/shuttle/autodock/proc/force_launch(var/user)
|
||||
if (!can_force()) return
|
||||
|
||||
in_use = user //obtain an exclusive lock on the shuttle
|
||||
|
||||
process_state = FORCE_LAUNCH
|
||||
|
||||
// Cancel queued launch.
|
||||
/datum/shuttle/autodock/cancel_launch(var/user)
|
||||
if (!can_cancel()) return
|
||||
|
||||
moving_status = SHUTTLE_IDLE
|
||||
process_state = WAIT_FINISH
|
||||
in_use = null
|
||||
|
||||
//whatever we were doing with docking: stop it, then redock
|
||||
force_undock()
|
||||
spawn(1 SECOND)
|
||||
dock()
|
||||
|
||||
//returns 1 if the shuttle is getting ready to move, but is not in transit yet
|
||||
/datum/shuttle/autodock/proc/is_launching()
|
||||
return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH)
|
||||
|
||||
// /datum/shuttle/autodock/get_location_name() defined in shuttle.dm
|
||||
|
||||
/datum/shuttle/autodock/proc/get_destination_name()
|
||||
if(!next_location)
|
||||
return "None"
|
||||
return next_location.name
|
||||
|
||||
//This gets called when the shuttle finishes arriving at it's destination
|
||||
//This can be used by subtypes to do things when the shuttle arrives.
|
||||
//Note that this is called when the shuttle leaves the WAIT_FINISHED state, the proc name is a little misleading
|
||||
/datum/shuttle/autodock/proc/arrived()
|
||||
return //do nothing for now
|
||||
|
||||
/obj/effect/shuttle_landmark/transit
|
||||
flags = SLANDMARK_FLAG_ZERO_G|SLANDMARK_FLAG_AUTOSET
|
||||
@@ -8,23 +8,20 @@
|
||||
var/shuttle_tag // Used to coordinate data in shuttle controller.
|
||||
var/hacked = 0 // Has been emagged, no access restrictions.
|
||||
|
||||
var/ui_template = "shuttle_control_console.tmpl"
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle_control/attack_hand(user as mob)
|
||||
if(..(user))
|
||||
return
|
||||
//src.add_fingerprint(user) //shouldn't need fingerprints just for looking at it.
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<font color='red'>Access Denied.</font>")
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return 1
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
if (!istype(shuttle))
|
||||
return
|
||||
|
||||
/obj/machinery/computer/shuttle_control/proc/get_ui_data(var/datum/shuttle/autodock/shuttle)
|
||||
var/shuttle_state
|
||||
switch(shuttle.moving_status)
|
||||
if(SHUTTLE_IDLE) shuttle_state = "idle"
|
||||
@@ -34,55 +31,100 @@
|
||||
var/shuttle_status
|
||||
switch (shuttle.process_state)
|
||||
if(IDLE_STATE)
|
||||
var/cannot_depart = shuttle.current_location.cannot_depart(shuttle)
|
||||
if (shuttle.in_use)
|
||||
shuttle_status = "Busy."
|
||||
else if (!shuttle.location)
|
||||
shuttle_status = "Standing-by at station."
|
||||
else if(cannot_depart)
|
||||
shuttle_status = cannot_depart
|
||||
else
|
||||
shuttle_status = "Standing-by at offsite location."
|
||||
shuttle_status = "Standing-by at \the [shuttle.get_location_name()]."
|
||||
|
||||
if(WAIT_LAUNCH, FORCE_LAUNCH)
|
||||
shuttle_status = "Shuttle has received command and will depart shortly."
|
||||
if(WAIT_ARRIVE)
|
||||
shuttle_status = "Proceeding to destination."
|
||||
shuttle_status = "Proceeding to \the [shuttle.get_destination_name()]."
|
||||
if(WAIT_FINISH)
|
||||
shuttle_status = "Arriving at destination now."
|
||||
|
||||
data = list(
|
||||
return list(
|
||||
"shuttle_status" = shuttle_status,
|
||||
"shuttle_state" = shuttle_state,
|
||||
"has_docking" = shuttle.docking_controller? 1 : 0,
|
||||
"docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null,
|
||||
"docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null,
|
||||
"has_docking" = shuttle.shuttle_docking_controller ? 1 : 0,
|
||||
"docking_status" = shuttle.shuttle_docking_controller?.get_docking_status(),
|
||||
"docking_override" = shuttle.shuttle_docking_controller?.override_enabled,
|
||||
"can_launch" = shuttle.can_launch(),
|
||||
"can_cancel" = shuttle.can_cancel(),
|
||||
"can_force" = shuttle.can_force(),
|
||||
"docking_codes" = shuttle.docking_codes
|
||||
)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "shuttle_control_console.tmpl", "[shuttle_tag] Shuttle Control", 470, 310)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
// This is a subset of the actual checks; contains those that give messages to the user.
|
||||
// This enables us to give nice error messages as well as not even bother proceeding if we can't.
|
||||
/obj/machinery/computer/shuttle_control/proc/can_move(var/datum/shuttle/autodock/shuttle, var/user)
|
||||
var/cannot_depart = shuttle.current_location.cannot_depart(shuttle)
|
||||
if(cannot_depart)
|
||||
to_chat(user, "<span class='warning'>[cannot_depart]</span>")
|
||||
log_shuttle("Shuttle [shuttle] cannot depart [shuttle.current_location] because: [cannot_depart].")
|
||||
return FALSE
|
||||
if(!shuttle.next_location.is_valid(shuttle))
|
||||
to_chat(user, "<span class='warning'>Destination zone is invalid or obstructed.</span>")
|
||||
log_shuttle("Shuttle [shuttle] destination [shuttle.next_location] is invalid.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/shuttle_control/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if((. = ..()))
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
if (!istype(shuttle))
|
||||
return
|
||||
var/datum/shuttle/autodock/shuttle = SSshuttles.shuttles[shuttle_tag]
|
||||
if(!shuttle)
|
||||
to_chat(usr, "<span class='warning'>Unable to establish link with the shuttle.</span>")
|
||||
return handle_topic_href(shuttle, href_list, usr)
|
||||
|
||||
/obj/machinery/computer/shuttle_control/proc/handle_topic_href(var/datum/shuttle/autodock/shuttle, var/list/href_list, var/user)
|
||||
if(!istype(shuttle))
|
||||
return TOPIC_NOACTION
|
||||
|
||||
if(href_list["move"])
|
||||
shuttle.launch(src)
|
||||
if(can_move(shuttle, user))
|
||||
shuttle.launch(src)
|
||||
return TOPIC_REFRESH
|
||||
return TOPIC_HANDLED
|
||||
|
||||
if(href_list["force"])
|
||||
shuttle.force_launch(src)
|
||||
else if(href_list["cancel"])
|
||||
if(can_move(shuttle, user))
|
||||
shuttle.force_launch(src)
|
||||
return TOPIC_REFRESH
|
||||
return TOPIC_HANDLED
|
||||
|
||||
if(href_list["cancel"])
|
||||
shuttle.cancel_launch(src)
|
||||
return TOPIC_REFRESH
|
||||
|
||||
if(href_list["set_codes"])
|
||||
var/newcode = input("Input new docking codes", "Docking codes", shuttle.docking_codes) as text|null
|
||||
if (newcode && CanInteract(usr, global.default_state))
|
||||
shuttle.set_docking_codes(uppertext(newcode))
|
||||
return TOPIC_REFRESH
|
||||
|
||||
// We delegate populating data to another proc to make it easier for overriding types to add their data.
|
||||
/obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/datum/shuttle/autodock/shuttle = SSshuttles.shuttles[shuttle_tag]
|
||||
if (!istype(shuttle))
|
||||
to_chat(user, "<span class='warning'>Unable to establish link with the shuttle.</span>")
|
||||
return
|
||||
|
||||
var/list/data = get_ui_data(shuttle)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, ui_template, "[shuttle_tag] Shuttle Control", 470, 310)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/computer/shuttle_control/emag_act(var/remaining_charges, var/mob/user)
|
||||
if (!hacked)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/obj/machinery/computer/shuttle_control/multi
|
||||
ui_template = "shuttle_control_console_multi.tmpl"
|
||||
|
||||
/obj/machinery/computer/shuttle_control/multi/get_ui_data(var/datum/shuttle/autodock/multi/shuttle)
|
||||
. = ..()
|
||||
if(istype(shuttle))
|
||||
. += list(
|
||||
"destination_name" = shuttle.next_location ? shuttle.next_location.name : "No destination set.",
|
||||
"can_pick" = shuttle.moving_status == SHUTTLE_IDLE,
|
||||
"can_cloak" = shuttle.can_cloak ? 1 : 0,
|
||||
"cloaked" = shuttle.cloaked ? 1 : 0,
|
||||
"legit" = shuttle.legit ? 1 : 0,
|
||||
// "engines_charging" = ((shuttle.last_move + (shuttle.cooldown SECONDS)) > world.time), // Replaced by longer warmup_time
|
||||
)
|
||||
|
||||
/obj/machinery/computer/shuttle_control/multi/handle_topic_href(var/datum/shuttle/autodock/multi/shuttle, var/list/href_list)
|
||||
if((. = ..()) != null)
|
||||
return
|
||||
|
||||
if(href_list["pick"])
|
||||
var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations()
|
||||
if(dest_key && CanInteract(usr, global.default_state))
|
||||
shuttle.set_destination(dest_key, usr)
|
||||
return TOPIC_REFRESH
|
||||
|
||||
if(href_list["toggle_cloaked"])
|
||||
if(!shuttle.can_cloak)
|
||||
return TOPIC_HANDLED
|
||||
shuttle.cloaked = !shuttle.cloaked
|
||||
if(shuttle.legit)
|
||||
to_chat(usr, "<span class='notice'>Ship ATC inhibitor systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be notified of our arrival.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Ship stealth systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.</span>")
|
||||
return TOPIC_REFRESH
|
||||
@@ -1,21 +1,22 @@
|
||||
/datum/shuttle/ferry/emergency
|
||||
category = /datum/shuttle/ferry/emergency
|
||||
// Formerly /datum/shuttle/ferry/emergency
|
||||
/datum/shuttle/autodock/ferry/emergency
|
||||
category = /datum/shuttle/autodock/ferry/emergency
|
||||
|
||||
/datum/shuttle/ferry/emergency/New()
|
||||
/datum/shuttle/autodock/ferry/emergency/New()
|
||||
..()
|
||||
if(emergency_shuttle.shuttle)
|
||||
CRASH("An emergency shuttle has already been defined.")
|
||||
emergency_shuttle.shuttle = src
|
||||
..()
|
||||
|
||||
/datum/shuttle/ferry/emergency/arrived()
|
||||
/datum/shuttle/autodock/ferry/emergency/arrived()
|
||||
. = ..()
|
||||
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()
|
||||
|
||||
/datum/shuttle/ferry/emergency/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction)
|
||||
//to_world("shuttle/ferry/emergency/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]")
|
||||
/datum/shuttle/autodock/ferry/emergency/long_jump(var/destination, var/interim, var/travel_time)
|
||||
if (!location)
|
||||
travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
else
|
||||
@@ -25,28 +26,28 @@
|
||||
move_time = travel_time
|
||||
emergency_shuttle.launch_time = world.time
|
||||
|
||||
..(destination, interim, travel_time, direction)
|
||||
|
||||
/datum/shuttle/autodock/ferry/emergency/perform_shuttle_move()
|
||||
if (current_location == landmark_station) //leaving the station
|
||||
spawn(0)
|
||||
emergency_shuttle.departed = 1
|
||||
var/estimated_time = round(emergency_shuttle.estimate_arrival_time()/60,1)
|
||||
|
||||
if (emergency_shuttle.evac)
|
||||
priority_announcement.Announce(replacetext(replacetext(using_map.emergency_shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"))
|
||||
else
|
||||
priority_announcement.Announce(replacetext(replacetext(using_map.shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"))
|
||||
..()
|
||||
|
||||
/datum/shuttle/ferry/emergency/move(var/area/origin,var/area/destination)
|
||||
..(origin, destination)
|
||||
|
||||
if (origin == area_station) //leaving the station
|
||||
emergency_shuttle.departed = 1
|
||||
var/estimated_time = round(emergency_shuttle.estimate_arrival_time()/60,1)
|
||||
|
||||
if (emergency_shuttle.evac)
|
||||
priority_announcement.Announce(replacetext(replacetext(using_map.emergency_shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"))
|
||||
else
|
||||
priority_announcement.Announce(replacetext(replacetext(using_map.shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"))
|
||||
|
||||
/datum/shuttle/ferry/emergency/can_launch(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/can_launch(var/user)
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency))
|
||||
var/obj/machinery/computer/shuttle_control/emergency/C = user
|
||||
if (!C.has_authorization())
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/emergency/can_force(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/can_force(var/user)
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency))
|
||||
var/obj/machinery/computer/shuttle_control/emergency/C = user
|
||||
|
||||
@@ -56,14 +57,14 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/emergency/can_cancel(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/can_cancel(var/user)
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency))
|
||||
var/obj/machinery/computer/shuttle_control/emergency/C = user
|
||||
if (!C.has_authorization())
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/emergency/launch(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/launch(var/user)
|
||||
if (!can_launch(user)) return
|
||||
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
|
||||
@@ -77,7 +78,7 @@
|
||||
|
||||
..(user)
|
||||
|
||||
/datum/shuttle/ferry/emergency/force_launch(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/force_launch(var/user)
|
||||
if (!can_force(user)) return
|
||||
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
|
||||
@@ -91,7 +92,7 @@
|
||||
|
||||
..(user)
|
||||
|
||||
/datum/shuttle/ferry/emergency/cancel_launch(var/user)
|
||||
/datum/shuttle/autodock/ferry/emergency/cancel_launch(var/user)
|
||||
if (!can_cancel(user)) return
|
||||
|
||||
if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console
|
||||
@@ -177,7 +178,7 @@
|
||||
|
||||
/obj/machinery/computer/shuttle_control/emergency/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/datum/shuttle/ferry/emergency/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/ferry/emergency/shuttle = SSshuttles.shuttles[shuttle_tag]
|
||||
if (!istype(shuttle))
|
||||
return
|
||||
|
||||
@@ -222,9 +223,9 @@
|
||||
data = list(
|
||||
"shuttle_status" = shuttle_status,
|
||||
"shuttle_state" = shuttle_state,
|
||||
"has_docking" = shuttle.docking_controller? 1 : 0,
|
||||
"docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null,
|
||||
"docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null,
|
||||
"has_docking" = shuttle.active_docking_controller? 1 : 0,
|
||||
"docking_status" = shuttle.active_docking_controller? shuttle.active_docking_controller.get_docking_status() : null,
|
||||
"docking_override" = shuttle.active_docking_controller? shuttle.active_docking_controller.override_enabled : null,
|
||||
"can_launch" = shuttle.can_launch(src),
|
||||
"can_cancel" = shuttle.can_cancel(src),
|
||||
"can_force" = shuttle.can_force(src),
|
||||
|
||||
@@ -1,177 +1,50 @@
|
||||
#define DOCK_ATTEMPT_TIMEOUT 200 //how long in ticks we wait before assuming the docking controller is broken or blown up.
|
||||
|
||||
/datum/shuttle/ferry
|
||||
var/location = 0 //0 = at area_station, 1 = at area_offsite
|
||||
var/direction = 0 //0 = going to station, 1 = going to offsite.
|
||||
var/process_state = IDLE_STATE
|
||||
var/always_process = FALSE
|
||||
/datum/shuttle/autodock/ferry
|
||||
var/location = FERRY_LOCATION_STATION //0 = at area_station, 1 = at area_offsite
|
||||
var/direction = FERRY_GOING_TO_STATION //0 = going to station, 1 = going to offsite.
|
||||
|
||||
var/in_use = null //tells the controller whether this shuttle needs processing
|
||||
var/always_process = FALSE // TODO -why should this exist?
|
||||
|
||||
var/area_transition
|
||||
var/move_time = 0 //the time spent in the transition area
|
||||
var/transit_direction = null //needed for area/move_contents_to() to properly handle shuttle corners - not exactly sure how it works.
|
||||
var/obj/effect/shuttle_landmark/landmark_station //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
|
||||
var/obj/effect/shuttle_landmark/landmark_offsite //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
|
||||
|
||||
var/area/area_station
|
||||
var/area/area_offsite
|
||||
//TODO: change location to a string and use a mapping for area and dock targets.
|
||||
var/dock_target_station
|
||||
var/dock_target_offsite
|
||||
category = /datum/shuttle/autodock/ferry
|
||||
|
||||
var/last_dock_attempt_time = 0
|
||||
category = /datum/shuttle/ferry
|
||||
/datum/shuttle/autodock/ferry/New(var/_name)
|
||||
if(landmark_station)
|
||||
landmark_station = SSshuttles.get_landmark(landmark_station)
|
||||
if(landmark_offsite)
|
||||
landmark_offsite = SSshuttles.get_landmark(landmark_offsite)
|
||||
|
||||
/datum/shuttle/ferry/New()
|
||||
area_offsite = locate(area_offsite)
|
||||
area_station = locate(area_station)
|
||||
if(area_transition)
|
||||
area_transition = locate(area_transition)
|
||||
..()
|
||||
..(_name, get_location_waypoint(location))
|
||||
|
||||
/datum/shuttle/ferry/short_jump(var/area/origin,var/area/destination)
|
||||
if(isnull(location))
|
||||
return
|
||||
next_location = get_location_waypoint(!location)
|
||||
|
||||
if(!destination)
|
||||
destination = get_location_area(!location)
|
||||
if(!origin)
|
||||
origin = get_location_area(location)
|
||||
|
||||
direction = !location
|
||||
..(origin, destination)
|
||||
|
||||
/datum/shuttle/ferry/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction)
|
||||
//to_world("shuttle/ferry/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]")
|
||||
if(isnull(location))
|
||||
return
|
||||
|
||||
if(!destination)
|
||||
destination = get_location_area(!location)
|
||||
if(!departing)
|
||||
departing = get_location_area(location)
|
||||
|
||||
direction = !location
|
||||
..(departing, destination, interim, travel_time, direction)
|
||||
|
||||
/datum/shuttle/ferry/move(var/area/origin,var/area/destination)
|
||||
..(origin, destination)
|
||||
|
||||
if (destination == area_station) location = 0
|
||||
if (destination == area_offsite) location = 1
|
||||
//if this is a long_jump retain the location we were last at until we get to the new one
|
||||
|
||||
/datum/shuttle/ferry/dock()
|
||||
..()
|
||||
last_dock_attempt_time = world.time
|
||||
|
||||
/datum/shuttle/ferry/proc/get_location_area(location_id = null)
|
||||
//Gets the shuttle landmark associated with the given location (defaults to current location)
|
||||
/datum/shuttle/autodock/ferry/proc/get_location_waypoint(location_id = null)
|
||||
if (isnull(location_id))
|
||||
location_id = location
|
||||
|
||||
if (!location_id)
|
||||
return area_station
|
||||
return area_offsite
|
||||
if (location_id == FERRY_LOCATION_STATION)
|
||||
return landmark_station
|
||||
return landmark_offsite
|
||||
|
||||
/*
|
||||
Please ensure that long_jump() and short_jump() are only called from here. This applies to subtypes as well.
|
||||
Doing so will ensure that multiple jumps cannot be initiated in parallel.
|
||||
*/
|
||||
/datum/shuttle/ferry/process()
|
||||
switch(process_state)
|
||||
if (WAIT_LAUNCH)
|
||||
if (skip_docking_checks() || docking_controller.can_launch())
|
||||
/datum/shuttle/autodock/ferry/short_jump(var/destination)
|
||||
direction = !location // Heading away from where we currently are
|
||||
. = ..()
|
||||
|
||||
//to_world("shuttle/ferry/process: area_transition=[area_transition], travel_time=[travel_time]")
|
||||
if (move_time && area_transition)
|
||||
long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction)
|
||||
else
|
||||
short_jump()
|
||||
/datum/shuttle/autodock/ferry/long_jump(var/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time)
|
||||
direction = !location // Heading away from where we currently are
|
||||
. = ..()
|
||||
|
||||
process_state = WAIT_ARRIVE
|
||||
|
||||
if (FORCE_LAUNCH)
|
||||
if (move_time && area_transition)
|
||||
long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction)
|
||||
else
|
||||
short_jump()
|
||||
|
||||
process_state = WAIT_ARRIVE
|
||||
|
||||
if (WAIT_ARRIVE)
|
||||
if (moving_status == SHUTTLE_IDLE)
|
||||
dock()
|
||||
in_use = null //release lock
|
||||
process_state = WAIT_FINISH
|
||||
|
||||
if (WAIT_FINISH)
|
||||
if (skip_docking_checks() || docking_controller.docked() || world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT)
|
||||
process_state = IDLE_STATE
|
||||
arrived()
|
||||
|
||||
/datum/shuttle/ferry/current_dock_target()
|
||||
var/dock_target
|
||||
if (!location) //station
|
||||
dock_target = dock_target_station
|
||||
else
|
||||
dock_target = dock_target_offsite
|
||||
return dock_target
|
||||
|
||||
|
||||
/datum/shuttle/ferry/proc/launch(var/user)
|
||||
if (!can_launch()) return
|
||||
|
||||
in_use = user //obtain an exclusive lock on the shuttle
|
||||
|
||||
process_state = WAIT_LAUNCH
|
||||
undock()
|
||||
|
||||
/datum/shuttle/ferry/proc/force_launch(var/user)
|
||||
if (!can_force()) return
|
||||
|
||||
in_use = user //obtain an exclusive lock on the shuttle
|
||||
|
||||
process_state = FORCE_LAUNCH
|
||||
|
||||
/datum/shuttle/ferry/proc/cancel_launch(var/user)
|
||||
if (!can_cancel()) return
|
||||
|
||||
moving_status = SHUTTLE_IDLE
|
||||
process_state = WAIT_FINISH
|
||||
in_use = null
|
||||
|
||||
if (docking_controller && !docking_controller.undocked())
|
||||
docking_controller.force_undock()
|
||||
|
||||
spawn(10)
|
||||
dock()
|
||||
|
||||
return
|
||||
|
||||
/datum/shuttle/ferry/proc/can_launch()
|
||||
if (moving_status != SHUTTLE_IDLE)
|
||||
return 0
|
||||
|
||||
if (in_use)
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/datum/shuttle/ferry/proc/can_force()
|
||||
if (moving_status == SHUTTLE_IDLE && process_state == WAIT_LAUNCH)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/shuttle/ferry/proc/can_cancel()
|
||||
if (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//returns 1 if the shuttle is getting ready to move, but is not in transit yet
|
||||
/datum/shuttle/ferry/proc/is_launching()
|
||||
return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH)
|
||||
|
||||
//This gets called when the shuttle finishes arriving at it's destination
|
||||
//This can be used by subtypes to do things when the shuttle arrives.
|
||||
/datum/shuttle/ferry/proc/arrived()
|
||||
return //do nothing for now
|
||||
/datum/shuttle/autodock/ferry/perform_shuttle_move()
|
||||
..()
|
||||
if (current_location == landmark_station) location = FERRY_LOCATION_STATION
|
||||
if (current_location == landmark_offsite) location = FERRY_LOCATION_OFFSITE
|
||||
|
||||
// Once we have arrived where we are going, plot a course back!
|
||||
/datum/shuttle/autodock/ferry/process_arrived()
|
||||
..()
|
||||
next_location = get_location_waypoint(!location)
|
||||
|
||||
@@ -4,39 +4,11 @@
|
||||
req_access = list(access_cent_specops)
|
||||
|
||||
/obj/machinery/computer/shuttle_control/specops/attack_ai(user as mob)
|
||||
to_chat(user, "<font color='red'>Access Denied.</font>")
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
return 1
|
||||
|
||||
//for shuttles that may use a different docking port at each location
|
||||
/datum/shuttle/ferry/multidock
|
||||
var/docking_controller_tag_station
|
||||
var/docking_controller_tag_offsite
|
||||
var/datum/computer/file/embedded_program/docking/docking_controller_station
|
||||
var/datum/computer/file/embedded_program/docking/docking_controller_offsite
|
||||
category = /datum/shuttle/ferry/multidock
|
||||
|
||||
/datum/shuttle/ferry/multidock/init_docking_controllers()
|
||||
if(docking_controller_tag_station)
|
||||
docking_controller_station = locate(docking_controller_tag_station)
|
||||
if(!istype(docking_controller_station))
|
||||
warning("warning: shuttle with docking tag [docking_controller_station] could not find it's controller!")
|
||||
if(docking_controller_tag_offsite)
|
||||
docking_controller_offsite = locate(docking_controller_tag_offsite)
|
||||
if(!istype(docking_controller_offsite))
|
||||
warning("warning: shuttle with docking tag [docking_controller_offsite] could not find it's controller!")
|
||||
if (!location)
|
||||
docking_controller = docking_controller_station
|
||||
else
|
||||
docking_controller = docking_controller_offsite
|
||||
|
||||
/datum/shuttle/ferry/multidock/move(var/area/origin,var/area/destination)
|
||||
..(origin, destination)
|
||||
if (!location)
|
||||
docking_controller = docking_controller_station
|
||||
else
|
||||
docking_controller = docking_controller_offsite
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops
|
||||
// Formerly /datum/shuttle/ferry/multidock/specops
|
||||
/datum/shuttle/autodock/ferry/specops
|
||||
var/specops_return_delay = 6000 //After moving, the amount of time that must pass before the shuttle may move again
|
||||
var/specops_countdown_time = 600 //Length of the countdown when moving the shuttle
|
||||
|
||||
@@ -44,19 +16,19 @@
|
||||
var/reset_time = 0 //the world.time at which the shuttle will be ready to move again.
|
||||
var/launch_prep = 0
|
||||
var/cancel_countdown = 0
|
||||
category = /datum/shuttle/ferry/multidock/specops
|
||||
category = /datum/shuttle/autodock/ferry/specops
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/New()
|
||||
/datum/shuttle/autodock/ferry/specops/New()
|
||||
..()
|
||||
announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
|
||||
announcer.config(list("Response Team" = 0))
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/proc/radio_announce(var/message)
|
||||
/datum/shuttle/autodock/ferry/specops/proc/radio_announce(var/message)
|
||||
if(announcer)
|
||||
announcer.autosay(message, "A.L.I.C.E.", "Response Team")
|
||||
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/launch(var/user)
|
||||
/datum/shuttle/autodock/ferry/specops/launch(var/user)
|
||||
if (!can_launch())
|
||||
return
|
||||
|
||||
@@ -64,14 +36,14 @@
|
||||
var/obj/machinery/computer/C = user
|
||||
|
||||
if(world.time <= reset_time)
|
||||
C.visible_message("<font color='blue'>[using_map.boss_name] will not allow the Special Operations shuttle to launch yet.</font>")
|
||||
C.visible_message("<span class='notice'>[global.using_map.boss_name] will not allow the Special Operations shuttle to launch yet.</span>")
|
||||
if (((world.time - reset_time)/10) > 60)
|
||||
C.visible_message("<font color='blue'>[-((world.time - reset_time)/10)/60] minutes remain!</font>")
|
||||
C.visible_message("<span class='notice'>[-((world.time - reset_time)/10)/60] minutes remain!</span>")
|
||||
else
|
||||
C.visible_message("<font color='blue'>[-(world.time - reset_time)/10] seconds remain!</font>")
|
||||
C.visible_message("<span class='notice'>[-(world.time - reset_time)/10] seconds remain!</span>")
|
||||
return
|
||||
|
||||
C.visible_message("<font color='blue'>The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.</font>")
|
||||
C.visible_message("<span class='notice'>The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.</span>")
|
||||
|
||||
if (location) //returning
|
||||
radio_announce("THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN")
|
||||
@@ -81,31 +53,31 @@
|
||||
sleep_until_launch()
|
||||
|
||||
if (location)
|
||||
var/obj/machinery/light/small/readylight/light = locate() in get_location_area()
|
||||
var/obj/machinery/light/small/readylight/light = locate() in shuttle_area
|
||||
if(light) light.set_state(0)
|
||||
|
||||
//launch
|
||||
radio_announce("ALERT: INITIATING LAUNCH SEQUENCE")
|
||||
..(user)
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/move(var/area/origin,var/area/destination)
|
||||
..(origin, destination)
|
||||
/datum/shuttle/autodock/ferry/specops/perform_shuttle_move()
|
||||
..()
|
||||
|
||||
spawn(20)
|
||||
spawn(2 SECONDS)
|
||||
if (!location) //just arrived home
|
||||
for(var/turf/T in get_area_turfs(destination))
|
||||
for(var/turf/T in get_area_turfs(shuttle_area))
|
||||
var/mob/M = locate(/mob) in T
|
||||
to_chat(M, "<span class='danger'>You have arrived at [using_map.boss_name]. Operation has ended!</span>")
|
||||
else //just left for the station
|
||||
launch_mauraders()
|
||||
for(var/turf/T in get_area_turfs(destination))
|
||||
for(var/turf/T in get_area_turfs(shuttle_area))
|
||||
var/mob/M = locate(/mob) in T
|
||||
to_chat(M, "<span class='danger'>You have arrived at [station_name()]. Commence operation!</span>")
|
||||
|
||||
var/obj/machinery/light/small/readylight/light = locate() in T
|
||||
if(light) light.set_state(1)
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/cancel_launch()
|
||||
/datum/shuttle/autodock/ferry/specops/cancel_launch()
|
||||
if (!can_cancel())
|
||||
return
|
||||
|
||||
@@ -113,27 +85,26 @@
|
||||
radio_announce("ALERT: LAUNCH SEQUENCE ABORTED")
|
||||
if (istype(in_use, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/C = in_use
|
||||
C.visible_message("<font color='red'>Launch sequence aborted.</font>")
|
||||
|
||||
C.visible_message("<span class='warning'>Launch sequence aborted.</span>")
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/can_launch()
|
||||
/datum/shuttle/autodock/ferry/specops/can_launch()
|
||||
if(launch_prep)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
//should be fine to allow forcing. process_state only becomes WAIT_LAUNCH after the countdown is over.
|
||||
///datum/shuttle/ferry/multidock/specops/can_force()
|
||||
///datum/shuttle/autodock/ferry/specops/can_force()
|
||||
// return 0
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/can_cancel()
|
||||
/datum/shuttle/autodock/ferry/specops/can_cancel()
|
||||
if(launch_prep)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/ferry/multidock/specops/proc/sleep_until_launch()
|
||||
/datum/shuttle/autodock/ferry/specops/proc/sleep_until_launch()
|
||||
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
|
||||
|
||||
var/launch_time = world.time + specops_countdown_time
|
||||
|
||||
@@ -1,82 +1,87 @@
|
||||
/datum/shuttle/ferry/supply
|
||||
var/away_location = 1 //the location to hide at while pretending to be in-transit
|
||||
// Formerly /datum/shuttle/ferry/supply
|
||||
/datum/shuttle/autodock/ferry/supply
|
||||
var/away_location = FERRY_LOCATION_OFFSITE //the location to hide at while pretending to be in-transit
|
||||
var/late_chance = 80
|
||||
var/max_late_time = 300
|
||||
category = /datum/shuttle/ferry/supply
|
||||
flags = SHUTTLE_FLAGS_PROCESS|SHUTTLE_FLAGS_SUPPLY
|
||||
category = /datum/shuttle/autodock/ferry/supply
|
||||
|
||||
/datum/shuttle/ferry/supply/short_jump(var/area/origin,var/area/destination)
|
||||
/datum/shuttle/autodock/ferry/supply/short_jump(var/obj/effect/shuttle_landmark/destination)
|
||||
if(moving_status != SHUTTLE_IDLE)
|
||||
return
|
||||
|
||||
if(isnull(location))
|
||||
return
|
||||
|
||||
if(!destination)
|
||||
destination = get_location_area(!location)
|
||||
if(!origin)
|
||||
origin = get_location_area(location)
|
||||
|
||||
//it would be cool to play a sound here
|
||||
moving_status = SHUTTLE_WARMUP
|
||||
spawn(warmup_time*10)
|
||||
|
||||
make_sounds(origin, HYPERSPACE_WARMUP)
|
||||
make_sounds(HYPERSPACE_WARMUP)
|
||||
sleep(5 SECONDS) // so the sound finishes.
|
||||
|
||||
if (moving_status == SHUTTLE_IDLE)
|
||||
make_sounds(origin, HYPERSPACE_END)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
return //someone cancelled the launch
|
||||
|
||||
if (at_station() && forbidden_atoms_check())
|
||||
//cancel the launch because of forbidden atoms. announce over supply channel?
|
||||
moving_status = SHUTTLE_IDLE
|
||||
make_sounds(origin, HYPERSPACE_END)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
return
|
||||
|
||||
if (!at_station()) //at centcom
|
||||
supply_controller.buy()
|
||||
|
||||
//We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period.
|
||||
var/area/away_area = get_location_area(away_location)
|
||||
var/obj/effect/shuttle_landmark/away_waypoint = get_location_waypoint(away_location)
|
||||
moving_status = SHUTTLE_INTRANSIT
|
||||
|
||||
//If we are at the away_area then we are just pretending to move, otherwise actually do the move
|
||||
if (origin != away_area)
|
||||
move(origin, away_area)
|
||||
//If we are at the away_landmark then we are just pretending to move, otherwise actually do the move
|
||||
if (next_location == away_waypoint)
|
||||
attempt_move(away_waypoint)
|
||||
|
||||
//wait ETA here.
|
||||
arrive_time = world.time + supply_controller.movetime
|
||||
while (world.time <= arrive_time)
|
||||
sleep(5)
|
||||
|
||||
if (destination != away_area)
|
||||
if (next_location != away_waypoint)
|
||||
//late
|
||||
if (prob(late_chance))
|
||||
sleep(rand(0,max_late_time))
|
||||
|
||||
move(away_area, destination)
|
||||
attempt_move(destination)
|
||||
|
||||
moving_status = SHUTTLE_IDLE
|
||||
make_sounds(destination, HYPERSPACE_END)
|
||||
make_sounds(HYPERSPACE_END)
|
||||
|
||||
if (!at_station()) //at centcom
|
||||
supply_controller.sell()
|
||||
|
||||
// returns 1 if the supply shuttle should be prevented from moving because it contains forbidden atoms
|
||||
/datum/shuttle/ferry/supply/proc/forbidden_atoms_check()
|
||||
/datum/shuttle/autodock/ferry/supply/proc/forbidden_atoms_check()
|
||||
if (!at_station())
|
||||
return 0 //if badmins want to send mobs or a nuke on the supply shuttle from centcom we don't care
|
||||
|
||||
return supply_controller.forbidden_atoms_check(get_location_area())
|
||||
for(var/area/A in shuttle_area)
|
||||
if(supply_controller.forbidden_atoms_check(A))
|
||||
return 1
|
||||
|
||||
/datum/shuttle/ferry/supply/proc/at_station()
|
||||
/datum/shuttle/autodock/ferry/supply/proc/at_station()
|
||||
return (!location)
|
||||
|
||||
//returns 1 if the shuttle is idle and we can still mess with the cargo shopping list
|
||||
/datum/shuttle/ferry/supply/proc/idle()
|
||||
/datum/shuttle/autodock/ferry/supply/proc/idle()
|
||||
return (moving_status == SHUTTLE_IDLE)
|
||||
|
||||
//returns the ETA in minutes
|
||||
/datum/shuttle/ferry/supply/proc/eta_minutes()
|
||||
/datum/shuttle/autodock/ferry/supply/proc/eta_minutes()
|
||||
var/ticksleft = arrive_time - world.time
|
||||
return round(ticksleft/600,1)
|
||||
|
||||
// Read the docking codes off of the target to make sure we can always dock.
|
||||
/datum/shuttle/autodock/ferry/supply/update_docking_target(var/obj/effect/shuttle_landmark/location)
|
||||
..()
|
||||
if(active_docking_controller && active_docking_controller.docking_codes)
|
||||
set_docking_codes(active_docking_controller.docking_codes)
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
//This is a holder for things like the Skipjack and Nuke shuttle.
|
||||
/datum/shuttle/multi_shuttle
|
||||
// Formerly /datum/shuttle/multi_shuttle
|
||||
/datum/shuttle/autodock/multi
|
||||
var/list/destination_tags
|
||||
var/list/destinations_cache = list()
|
||||
var/last_cache_rebuild_time = 0
|
||||
category = /datum/shuttle/autodock/multi
|
||||
|
||||
flags = SHUTTLE_FLAGS_NONE
|
||||
var/cloaked = FALSE
|
||||
var/can_cloak = FALSE
|
||||
|
||||
var/at_origin = 1
|
||||
var/returned_home = 0
|
||||
// var/move_time = 240
|
||||
var/move_time = 60
|
||||
var/cooldown = 20
|
||||
var/last_move = 0 //the time at which we last moved
|
||||
|
||||
@@ -15,238 +17,46 @@
|
||||
var/arrival_message
|
||||
var/departure_message
|
||||
|
||||
var/area/interim
|
||||
var/area/last_departed
|
||||
var/start_location
|
||||
var/last_location
|
||||
var/list/destinations
|
||||
var/list/destination_dock_controller_tags = list() //optional, in case the shuttle has multiple docking ports like the ERT shuttle (even though that isn't a multi_shuttle)
|
||||
var/list/destination_dock_controllers = list()
|
||||
var/list/destination_dock_targets = list()
|
||||
var/area/origin
|
||||
var/return_warning = 0
|
||||
category = /datum/shuttle/multi_shuttle
|
||||
var/legit = FALSE
|
||||
|
||||
/datum/shuttle/multi_shuttle/New()
|
||||
origin = locate(origin)
|
||||
interim = locate(interim)
|
||||
for(var/destination in destinations)
|
||||
destinations[destination] = locate(destinations[destination])
|
||||
/datum/shuttle/autodock/multi/New()
|
||||
..()
|
||||
start_location = current_location
|
||||
last_location = current_location
|
||||
|
||||
/datum/shuttle/multi_shuttle/init_docking_controllers()
|
||||
..()
|
||||
for(var/destination in destinations)
|
||||
var/controller_tag = destination_dock_controller_tags[destination]
|
||||
if(!controller_tag)
|
||||
destination_dock_controllers[destination] = docking_controller
|
||||
else
|
||||
var/datum/computer/file/embedded_program/docking/C = locate(controller_tag)
|
||||
/datum/shuttle/autodock/multi/proc/set_destination(var/destination_key, mob/user)
|
||||
if(moving_status != SHUTTLE_IDLE)
|
||||
return
|
||||
next_location = destinations_cache[destination_key]
|
||||
if(!next_location)
|
||||
warning("Shuttle [src] set to destination we can't find: [destination_key]")
|
||||
|
||||
if(!istype(C))
|
||||
warning("warning: shuttle with docking tag [controller_tag] could not find it's controller!")
|
||||
else
|
||||
destination_dock_controllers[destination] = C
|
||||
/datum/shuttle/autodock/multi/proc/get_destinations()
|
||||
if (last_cache_rebuild_time < SSshuttles.last_landmark_registration_time)
|
||||
build_destinations_cache()
|
||||
return destinations_cache
|
||||
|
||||
//might as well set this up here.
|
||||
if(origin) last_departed = origin
|
||||
last_location = start_location
|
||||
/datum/shuttle/autodock/multi/proc/build_destinations_cache()
|
||||
last_cache_rebuild_time = world.time
|
||||
destinations_cache.Cut()
|
||||
for(var/destination_tag in destination_tags)
|
||||
var/obj/effect/shuttle_landmark/landmark = SSshuttles.get_landmark(destination_tag)
|
||||
if (istype(landmark))
|
||||
destinations_cache["[landmark.name]"] = landmark
|
||||
|
||||
/datum/shuttle/multi_shuttle/current_dock_target()
|
||||
return destination_dock_targets[last_location]
|
||||
|
||||
/datum/shuttle/multi_shuttle/move(var/area/origin, var/area/destination)
|
||||
/datum/shuttle/autodock/multi/perform_shuttle_move()
|
||||
..()
|
||||
last_move = world.time
|
||||
if (destination == src.origin)
|
||||
returned_home = 1
|
||||
docking_controller = destination_dock_controllers[last_location]
|
||||
|
||||
/datum/shuttle/multi_shuttle/proc/announce_departure()
|
||||
|
||||
/datum/shuttle/autodock/multi/proc/announce_departure()
|
||||
if(cloaked || isnull(departure_message))
|
||||
return
|
||||
command_announcement.Announce(departure_message, (announcer ? announcer : "[using_map.boss_name]"))
|
||||
|
||||
command_announcement.Announce(departure_message,(announcer ? announcer : "[using_map.boss_name]"))
|
||||
|
||||
/datum/shuttle/multi_shuttle/proc/announce_arrival()
|
||||
|
||||
/datum/shuttle/autodock/multi/proc/announce_arrival()
|
||||
if(cloaked || isnull(arrival_message))
|
||||
return
|
||||
|
||||
command_announcement.Announce(arrival_message,(announcer ? announcer : "[using_map.boss_name]"))
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle_control/multi
|
||||
icon_keyboard = "syndie_key"
|
||||
icon_screen = "syndishuttle"
|
||||
|
||||
/obj/machinery/computer/shuttle_control/multi/attack_hand(user as mob)
|
||||
|
||||
if(..(user))
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
|
||||
var/datum/shuttle/multi_shuttle/MS = shuttle_controller.shuttles[shuttle_tag]
|
||||
if(!istype(MS)) return
|
||||
|
||||
var/dat
|
||||
dat = "<center>[shuttle_tag] Ship Control<hr>"
|
||||
|
||||
|
||||
if(MS.moving_status != SHUTTLE_IDLE)
|
||||
dat += "Location: <font color='red'>Moving</font> <br>"
|
||||
else
|
||||
var/area/areacheck = get_area(src)
|
||||
dat += "Location: [areacheck.name]<br>"
|
||||
|
||||
if((MS.last_move + MS.cooldown*10) > world.time)
|
||||
dat += "<font color='red'>Engines charging.</font><br>"
|
||||
else
|
||||
dat += "<font color='green'>Engines ready.</font><br>"
|
||||
|
||||
if(MS.can_cloak)
|
||||
dat += "<br><b><A href='?src=\ref[src];toggle_cloak=[1]'>Toggle cloaking field</A></b><br>"
|
||||
dat += "<b><A href='?src=\ref[src];move_multi=[1]'>Move ship</A></b><br>"
|
||||
dat += "<b><A href='?src=\ref[src];start=[1]'>Return to base</A></b></center>"
|
||||
|
||||
//Docking
|
||||
dat += "<center><br><br>"
|
||||
if(MS.skip_docking_checks())
|
||||
dat += "Docking Status: <font color='grey'>Not in use.</font>"
|
||||
else
|
||||
var/override_en = MS.docking_controller.override_enabled
|
||||
var/docking_status = MS.docking_controller.get_docking_status()
|
||||
|
||||
dat += "Docking Status: "
|
||||
switch(docking_status)
|
||||
if("undocked")
|
||||
dat += "<font color='[override_en? "red" : "grey"]'>Undocked</font>"
|
||||
if("docking")
|
||||
dat += "<font color='[override_en? "red" : "yellow"]'>Docking</font>"
|
||||
if("undocking")
|
||||
dat += "<font color='[override_en? "red" : "yellow"]'>Undocking</font>"
|
||||
if("docked")
|
||||
dat += "<font color='[override_en? "red" : "green"]'>Docked</font>"
|
||||
|
||||
if(override_en) dat += " <font color='red'>(Override Enabled)</font>"
|
||||
|
||||
dat += ". <A href='?src=\ref[src];refresh=[1]'>\[Refresh\]</A><br><br>"
|
||||
|
||||
switch(docking_status)
|
||||
if("undocked")
|
||||
dat += "<b><A href='?src=\ref[src];dock_command=[1]'>Dock</A></b>"
|
||||
if("docked")
|
||||
dat += "<b><A href='?src=\ref[src];undock_command=[1]'>Undock</A></b>"
|
||||
dat += "</center>"
|
||||
|
||||
user << browse("[dat]", "window=[shuttle_tag]shuttlecontrol;size=300x600")
|
||||
|
||||
//check if we're undocked, give option to force launch
|
||||
/obj/machinery/computer/shuttle_control/proc/check_docking(datum/shuttle/multi_shuttle/MS)
|
||||
if(MS.skip_docking_checks() || MS.docking_controller.can_launch())
|
||||
return 1
|
||||
|
||||
var/choice = alert("The shuttle is currently docked! Please undock before continuing.","Error","Cancel","Force Launch")
|
||||
if(choice == "Cancel")
|
||||
return 0
|
||||
|
||||
choice = alert("Forcing a shuttle launch while docked may result in severe injury, death and/or damage to property. Are you sure you wish to continue?", "Force Launch", "Force Launch", "Cancel")
|
||||
if(choice == "Cancel")
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/computer/shuttle_control/multi/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
var/datum/shuttle/multi_shuttle/MS = shuttle_controller.shuttles[shuttle_tag]
|
||||
if(!istype(MS)) return
|
||||
|
||||
//to_world("multi_shuttle: last_departed=[MS.last_departed], origin=[MS.origin], interim=[MS.interim], travel_time=[MS.move_time]")
|
||||
|
||||
if(href_list["refresh"])
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if (MS.moving_status != SHUTTLE_IDLE)
|
||||
to_chat(usr, "<font color='blue'>[shuttle_tag] vessel is moving.</font>")
|
||||
return
|
||||
|
||||
if(href_list["dock_command"])
|
||||
MS.dock()
|
||||
return
|
||||
|
||||
if(href_list["undock_command"])
|
||||
MS.undock()
|
||||
return
|
||||
|
||||
if(href_list["start"])
|
||||
if(MS.at_origin)
|
||||
to_chat(usr, "<font color='red'>You are already at the home base.</font>")
|
||||
return
|
||||
|
||||
if((MS.last_move + MS.cooldown*10) > world.time)
|
||||
to_chat(usr, "<font color='red'>The ship's drive is inoperable while the engines are charging.</font>")
|
||||
return
|
||||
|
||||
if(!check_docking(MS))
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
// No point giving a warning if it does literally nothing.
|
||||
// if(!MS.return_warning)
|
||||
// to_chat(usr, "<font color='red'>Returning to your home base will end your mission. If you are sure, press the button again.</font>")
|
||||
// //TODO: Actually end the mission.
|
||||
// MS.return_warning = 1
|
||||
// return
|
||||
|
||||
MS.long_jump(MS.last_departed, MS.origin, MS.interim, MS.move_time)
|
||||
MS.last_departed = MS.origin
|
||||
MS.last_location = MS.start_location
|
||||
MS.at_origin = 1
|
||||
|
||||
if(href_list["toggle_cloak"])
|
||||
if(!MS.can_cloak)
|
||||
return
|
||||
MS.cloaked = !MS.cloaked
|
||||
to_chat(usr, "<font color='red'>Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.</font>")
|
||||
|
||||
if(href_list["move_multi"])
|
||||
if((MS.last_move + MS.cooldown*10) > world.time)
|
||||
to_chat(usr, "<font color='red'>The ship's drive is inoperable while the engines are charging.</font>")
|
||||
return
|
||||
|
||||
if(!check_docking(MS))
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
var/choice = input("Select a destination.") as null|anything in MS.destinations
|
||||
if(!choice) return
|
||||
|
||||
to_chat(usr, "<font color='blue'>[shuttle_tag] main computer received message.</font>")
|
||||
|
||||
if(MS.at_origin)
|
||||
MS.announce_arrival()
|
||||
MS.last_departed = MS.origin
|
||||
MS.at_origin = 0
|
||||
|
||||
|
||||
MS.long_jump(MS.last_departed, MS.destinations[choice], MS.interim, MS.move_time)
|
||||
MS.last_departed = MS.destinations[choice]
|
||||
MS.last_location = choice
|
||||
return
|
||||
|
||||
else if(choice == MS.origin)
|
||||
|
||||
MS.announce_departure()
|
||||
|
||||
MS.short_jump(MS.last_departed, MS.destinations[choice])
|
||||
MS.last_departed = MS.destinations[choice]
|
||||
MS.last_location = choice
|
||||
|
||||
updateUsrDialog()
|
||||
command_announcement.Announce(arrival_message, (announcer ? announcer : "[using_map.boss_name]"))
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
//This shuttle traverses a "web" of route_datums to have a wider range of places to go and make flying feel like movement is actually occuring.
|
||||
/datum/shuttle/web_shuttle
|
||||
flags = SHUTTLE_FLAGS_NONE
|
||||
/datum/shuttle/autodock/web_shuttle
|
||||
flags = SHUTTLE_FLAGS_ZERO_G
|
||||
var/visible_name = null // The pretty name shown to people in announcements, since the regular name var is used internally for other things.
|
||||
var/cloaked = FALSE
|
||||
var/can_cloak = FALSE
|
||||
var/cooldown = 0
|
||||
var/last_move = 0 //the time at which we last moved
|
||||
var/area/current_area = null
|
||||
var/datum/shuttle_web_master/web_master = null
|
||||
var/web_master_type = null
|
||||
var/flight_time_modifier = 1.0
|
||||
@@ -15,15 +14,15 @@
|
||||
var/autopilot_delay = 60 // How many ticks to not do anything when not following an autopath. Should equal two minutes.
|
||||
var/autopilot_first_delay = null // If your want your shuttle to stay for a different amount of time for the first time, set this.
|
||||
var/can_rename = TRUE // Lets the pilot rename the shuttle. Only available once.
|
||||
category = /datum/shuttle/web_shuttle
|
||||
category = /datum/shuttle/autodock/web_shuttle
|
||||
var/list/obj/item/clothing/head/pilot/helmets
|
||||
|
||||
/datum/shuttle/web_shuttle/New()
|
||||
current_area = locate(current_area)
|
||||
/datum/shuttle/autodock/web_shuttle/New()
|
||||
web_master = new web_master_type(src)
|
||||
build_destinations()
|
||||
if(autopilot)
|
||||
flags |= SHUTTLE_FLAGS_PROCESS
|
||||
process_state = DO_AUTOPILOT
|
||||
if(autopilot_first_delay)
|
||||
autopilot_delay = autopilot_first_delay
|
||||
if(!visible_name)
|
||||
@@ -31,42 +30,45 @@
|
||||
helmets = list()
|
||||
..()
|
||||
|
||||
/datum/shuttle/web_shuttle/Destroy()
|
||||
qdel(web_master)
|
||||
/datum/shuttle/autodock/web_shuttle/Destroy()
|
||||
QDEL_NULL(web_master)
|
||||
helmets.Cut()
|
||||
return ..()
|
||||
|
||||
/datum/shuttle/autodock/web_shuttle/current_dock_target()
|
||||
// TODO - Probably don't even need to override this right? Debug testing code below will check!
|
||||
. = web_master?.get_current_destination()?.my_landmark?.docking_controller?.id_tag
|
||||
if (. != ..())
|
||||
warning("Web shuttle [src] had current_dock_target()=[.] but autodock.current_dock_target() = [..()]")
|
||||
|
||||
/datum/shuttle/web_shuttle/current_dock_target()
|
||||
if(web_master)
|
||||
return web_master.current_dock_target()
|
||||
|
||||
/datum/shuttle/web_shuttle/move(var/area/origin, var/area/destination)
|
||||
/datum/shuttle/autodock/web_shuttle/perform_shuttle_move()
|
||||
..()
|
||||
last_move = world.time
|
||||
|
||||
/datum/shuttle/web_shuttle/short_jump()
|
||||
/datum/shuttle/autodock/web_shuttle/short_jump()
|
||||
. = ..()
|
||||
update_helmets()
|
||||
|
||||
/datum/shuttle/web_shuttle/long_jump()
|
||||
/datum/shuttle/autodock/web_shuttle/long_jump()
|
||||
. = ..()
|
||||
update_helmets()
|
||||
|
||||
/datum/shuttle/web_shuttle/on_shuttle_departure()
|
||||
/datum/shuttle/autodock/web_shuttle/on_shuttle_departure()
|
||||
. = ..()
|
||||
web_master.on_shuttle_departure()
|
||||
update_helmets()
|
||||
|
||||
/datum/shuttle/web_shuttle/on_shuttle_arrival()
|
||||
/datum/shuttle/autodock/web_shuttle/on_shuttle_arrival()
|
||||
. = ..()
|
||||
active_docking_controller = current_location.docking_controller
|
||||
update_docking_target(current_location)
|
||||
web_master.on_shuttle_arrival()
|
||||
update_helmets()
|
||||
|
||||
/datum/shuttle/web_shuttle/proc/build_destinations()
|
||||
/datum/shuttle/autodock/web_shuttle/proc/build_destinations()
|
||||
return
|
||||
|
||||
/datum/shuttle/web_shuttle/process()
|
||||
/datum/shuttle/autodock/web_shuttle/process()
|
||||
update_helmets()
|
||||
|
||||
if(moving_status == SHUTTLE_IDLE)
|
||||
@@ -76,8 +78,8 @@
|
||||
|
||||
else // Otherwise we are about to start one or just finished one.
|
||||
if(autopilot_delay > 0) // Wait for awhile so people can get on and off.
|
||||
if(docking_controller && !skip_docking_checks()) // Dock to the destination if possible.
|
||||
var/docking_status = docking_controller.get_docking_status()
|
||||
if(active_docking_controller && shuttle_docking_controller) // Dock to the destination if possible.
|
||||
var/docking_status = shuttle_docking_controller.get_docking_status()
|
||||
if(docking_status == "undocked")
|
||||
dock()
|
||||
autopilot_say("Docking.")
|
||||
@@ -96,8 +98,8 @@
|
||||
autopilot_delay--
|
||||
|
||||
else // Time to go.
|
||||
if(docking_controller && !skip_docking_checks()) // Undock if possible.
|
||||
var/docking_status = docking_controller.get_docking_status()
|
||||
if(active_docking_controller && shuttle_docking_controller) // Undock if possible.
|
||||
var/docking_status = shuttle_docking_controller.get_docking_status()
|
||||
if(docking_status == "docked")
|
||||
undock()
|
||||
autopilot_say("Undocking.")
|
||||
@@ -109,13 +111,13 @@
|
||||
autopilot_say("Taking off.")
|
||||
web_master.process_autopath()
|
||||
|
||||
/datum/shuttle/web_shuttle/proc/update_helmets()
|
||||
/datum/shuttle/autodock/web_shuttle/proc/update_helmets()
|
||||
for(var/helm in helmets)
|
||||
if(!helm)
|
||||
helmets -= helm
|
||||
continue
|
||||
var/obj/item/clothing/head/pilot/H = helm
|
||||
if(!H.shuttle_comp || get_area(H.shuttle_comp) != get_area(H))
|
||||
if(QDELETED(H))
|
||||
helmets -= H
|
||||
continue
|
||||
if(!H.shuttle_comp || !(get_area(H) in shuttle_area))
|
||||
H.shuttle_comp = null
|
||||
H.audible_message("<span class='warning'>\The [H] pings as it loses it's connection with the ship.</span>")
|
||||
H.update_hud("discon")
|
||||
@@ -123,24 +125,28 @@
|
||||
else
|
||||
H.update_hud(moving_status)
|
||||
|
||||
/datum/shuttle/web_shuttle/proc/adjust_autopilot(on)
|
||||
/datum/shuttle/autodock/web_shuttle/proc/adjust_autopilot(on)
|
||||
if(on)
|
||||
if(autopilot)
|
||||
return
|
||||
autopilot = TRUE
|
||||
autopilot_delay = initial(autopilot_delay)
|
||||
shuttle_controller.process_shuttles += src
|
||||
shuttle_controller.process_shuttles |= src
|
||||
if(process_state == IDLE_STATE)
|
||||
process_state = DO_AUTOPILOT
|
||||
else
|
||||
if(!autopilot)
|
||||
return
|
||||
autopilot = FALSE
|
||||
shuttle_controller.process_shuttles -= src
|
||||
if (process_state == DO_AUTOPILOT)
|
||||
process_state = initial(process_state)
|
||||
|
||||
/datum/shuttle/web_shuttle/proc/autopilot_say(message) // Makes the autopilot 'talk' to the passengers.
|
||||
/datum/shuttle/autodock/web_shuttle/proc/autopilot_say(message) // Makes the autopilot 'talk' to the passengers.
|
||||
var/padded_message = "<span class='game say'><span class='name'>shuttle autopilot</span> states, \"[message]\"</span>"
|
||||
message_passengers(current_area, padded_message)
|
||||
message_passengers(padded_message)
|
||||
|
||||
/datum/shuttle/web_shuttle/proc/rename_shuttle(mob/user)
|
||||
/datum/shuttle/autodock/web_shuttle/proc/rename_shuttle(mob/user)
|
||||
if(!can_rename)
|
||||
to_chat(user, "<span class='warning'>You can't rename this vessel.</span>")
|
||||
return
|
||||
@@ -162,6 +168,8 @@
|
||||
var/list/my_doors //Should be list("id_tag" = "Pretty Door Name", ...)
|
||||
var/list/my_sensors //Should be list("id_tag" = "Pretty Sensor Name", ...)
|
||||
|
||||
// Note - Searching own area for doors/sensors is fine for legacy web shuttles as they are single-area.
|
||||
// However if this code is copied to future multi-area shuttles, should search in all shuttle areas
|
||||
/obj/machinery/computer/shuttle_control/web/Initialize()
|
||||
. = ..()
|
||||
var/area/my_area = get_area(src)
|
||||
@@ -186,7 +194,7 @@
|
||||
log_debug("[my_area] shuttle computer couldn't find [lost] sensor!")
|
||||
|
||||
/obj/machinery/computer/shuttle_control/web/attackby(obj/I, mob/user)
|
||||
var/datum/shuttle/web_shuttle/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/web_shuttle/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
if(shuttle && istype(I,/obj/item/clothing/head/pilot))
|
||||
var/obj/item/clothing/head/pilot/H = I
|
||||
H.shuttle_comp = src
|
||||
@@ -208,7 +216,7 @@
|
||||
|
||||
/*
|
||||
// If nanoUI falls over and you want a non-nanoUI UI, feel free to uncomment this section.
|
||||
var/datum/shuttle/web_shuttle/WS = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/web_shuttle/WS = shuttle_controller.shuttles[shuttle_tag]
|
||||
if(!istype(WS))
|
||||
message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.")
|
||||
return
|
||||
@@ -272,8 +280,9 @@
|
||||
/obj/machinery/computer/shuttle_control/web/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/list/routes[0]
|
||||
var/datum/shuttle/web_shuttle/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/web_shuttle/shuttle = SSshuttles.shuttles[shuttle_tag]
|
||||
if(!istype(shuttle))
|
||||
to_chat(user, "<span class='warning'>Unable to establish link with the shuttle.</span>")
|
||||
return
|
||||
|
||||
var/list/R = shuttle.web_master.get_available_routes()
|
||||
@@ -333,11 +342,11 @@
|
||||
"future_location" = future_location,
|
||||
"shuttle_state" = shuttle_state,
|
||||
"routes" = routes,
|
||||
"has_docking" = shuttle.docking_controller? 1 : 0,
|
||||
"has_docking" = shuttle.shuttle_docking_controller? 1 : 0,
|
||||
"skip_docking" = shuttle.skip_docking_checks(),
|
||||
"is_moving" = shuttle.moving_status != SHUTTLE_IDLE,
|
||||
"docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null,
|
||||
"docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null,
|
||||
"docking_status" = shuttle.shuttle_docking_controller? shuttle.shuttle_docking_controller.get_docking_status() : null,
|
||||
"docking_override" = shuttle.shuttle_docking_controller? shuttle.shuttle_docking_controller.override_enabled : null,
|
||||
"is_in_transit" = shuttle.has_arrive_time(),
|
||||
"travel_progress" = between(0, percent_finished, 100),
|
||||
"time_left" = round( (total_time - elapsed_time) / 10),
|
||||
@@ -360,13 +369,13 @@
|
||||
|
||||
|
||||
/obj/machinery/computer/shuttle_control/web/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if((. = ..()))
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
var/datum/shuttle/web_shuttle/WS = shuttle_controller.shuttles[shuttle_tag]
|
||||
var/datum/shuttle/autodock/web_shuttle/WS = SSshuttles.shuttles[shuttle_tag]
|
||||
if(!istype(WS))
|
||||
message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.")
|
||||
return
|
||||
@@ -436,19 +445,38 @@
|
||||
message_admins("ERROR: Shuttle computer was asked to travel to a nonexistant destination.")
|
||||
return
|
||||
|
||||
WS.next_location = target_destination.my_landmark
|
||||
if(!can_move(WS, usr))
|
||||
return
|
||||
|
||||
WS.web_master.future_destination = target_destination
|
||||
to_chat(usr, "<span class='notice'>[WS.visible_name] flight computer received command.</span>")
|
||||
WS.web_master.reset_autopath() // Deviating from the path will almost certainly confuse the autopilot, so lets just reset its memory.
|
||||
|
||||
var/travel_time = new_route.travel_time * WS.flight_time_modifier
|
||||
|
||||
// TODO - Leshana - Change this to use proccess stuff of autodock!
|
||||
if(new_route.interim && new_route.travel_time)
|
||||
WS.long_jump(WS.current_area, target_destination.my_area, new_route.interim, travel_time / 10)
|
||||
WS.long_jump(target_destination.my_landmark, new_route.interim, travel_time / 10)
|
||||
else
|
||||
WS.short_jump(WS.current_area, target_destination.my_area)
|
||||
WS.short_jump(target_destination.my_landmark)
|
||||
|
||||
ui_interact(usr)
|
||||
|
||||
//check if we're undocked, give option to force launch
|
||||
/obj/machinery/computer/shuttle_control/web/proc/check_docking(datum/shuttle/autodock/MS)
|
||||
if(MS.skip_docking_checks() || MS.check_undocked())
|
||||
return 1
|
||||
|
||||
var/choice = alert("The shuttle is currently docked! Please undock before continuing.","Error","Cancel","Force Launch")
|
||||
if(choice == "Cancel")
|
||||
return 0
|
||||
|
||||
choice = alert("Forcing a shuttle launch while docked may result in severe injury, death and/or damage to property. Are you sure you wish to continue?", "Force Launch", "Force Launch", "Cancel")
|
||||
if(choice == "Cancel")
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
// Props, for now.
|
||||
/obj/structure/flight_left
|
||||
name = "flight computer meters"
|
||||
@@ -474,11 +502,18 @@
|
||||
|
||||
/obj/shuttle_connector/Initialize()
|
||||
. = ..()
|
||||
SSshuttles.OnDocksInitialized(CALLBACK(src, .proc/setup_routes))
|
||||
GLOB.shuttle_added.register_global(src, .proc/setup_routes)
|
||||
|
||||
/obj/shuttle_connector/proc/setup_routes()
|
||||
if(destinations && shuttle_name)
|
||||
var/datum/shuttle/web_shuttle/ES = shuttle_controller.shuttles[shuttle_name]
|
||||
/obj/shuttle_connector/Destroy()
|
||||
GLOB.shuttle_added.unregister_global(src, .proc/setup_routes)
|
||||
. = ..()
|
||||
|
||||
// This is called whenever a shuttle is initialized. If its our shuttle, do our thing!
|
||||
/obj/shuttle_connector/proc/setup_routes(var/new_shuttle)
|
||||
var/datum/shuttle/autodock/web_shuttle/ES = shuttle_controller.shuttles[shuttle_name]
|
||||
if(ES != new_shuttle)
|
||||
return // Its not our shuttle! Ignore!
|
||||
if(destinations && istype(ES))
|
||||
var/datum/shuttle_web_master/WM = ES.web_master
|
||||
|
||||
for(var/new_dest in destinations)
|
||||
@@ -487,7 +522,9 @@
|
||||
|
||||
for(var/type_to_link in D.routes_to_make)
|
||||
var/travel_delay = D.routes_to_make[type_to_link]
|
||||
D.link_destinations(WM.get_destination_by_type(type_to_link), D.preferred_interim_area, travel_delay)
|
||||
D.link_destinations(WM.get_destination_by_type(type_to_link), D.preferred_interim_tag, travel_delay)
|
||||
else
|
||||
warning("[log_info_line()]'s shuttle [global.log_info_line(ES)] initialized but destinations:[destinations]")
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# "Landmark" Shuttles Conversion
|
||||
This guide helps with updating maps and shuttle datums from the old "area" based system to the "landmark" based system.
|
||||
|
||||
## Summary
|
||||
The old shuttle datum worked with areas (`/area`). You are probably familiar with every shuttle having a few cookie-cutter shaped areas it travels between.
|
||||
When the shuttle "moved" it was translated from its current area to the destination area. The areas had to be _exactly_ the same shape so
|
||||
that each turf in the origin area got translated to the equivalent place at the target.\
|
||||
Since _all possible_ destinations had to have a dedicated area (and areas in BYOND can't overlap) this means it is impossible for two shuttles to travel to the same spot, even at different times.
|
||||
|
||||
In the new system shuttle destinations are represented by "landmark" objects (`/obj/effect/shuttle_landmark`).
|
||||
When a shuttle is "moved" it is translated from its current landmark to the destination landmark, with each turf keeping its same position _relative_ to the landmarks.
|
||||
In other words, whatever a turf's x/y/z offsets are from the origin landmark, it will be moved to the same x/y/z offset from the destination landmark.
|
||||
|
||||
## Landmark Objects
|
||||
Shuttle destinations are represented by `/obj/effect/shuttle_landmark` objects on the map.
|
||||
|
||||
* `name` - Pretty name of the nav point, used on overmap and in messages and console UI.
|
||||
* `landmark_tag` - Globally unique ID, used by everything else to refer to this landmark.
|
||||
* `docking_controller` - ID of the controller on the dock side (initialize to id_tag, becomes reference). Leave null if not applicable.
|
||||
* `base_area` - Type path of the `/area` that should be here when a shuttle is *not* present.
|
||||
* `base_turf` - Type path of the `/turf` that should be here when a shuttle is *not* present.
|
||||
* `shuttle_restricted` - If not null, only the named shuttle is allowed to use this landmark. (TODO: Overmap functionality)
|
||||
* `flags` - Bitfield - defaults to `SLANDMARK_FLAG_AUTOSET`, can be any combination of:
|
||||
* `SLANDMARK_FLAG_AUTOSET` (1) - If set, will initialize base_area and base_turf to same as where it was spawned at.
|
||||
* `SLANDMARK_FLAG_ZERO_G` (2) - If set, Zero-G shuttles moved here will lose gravity unless the area has ambient gravity.
|
||||
* `special_dock_targets` - Used to configure shuttles with multiple docking controllers on the shuttle. Map of shuttle `name` -> `id_tag` of the docking controller it should use for this landmark. (Think of a shuttle with airlocks on both sides, each with their own controller. This would tell it which side to use.)
|
||||
|
||||
|
||||
## Shuttle Types
|
||||
|
||||
|
||||
### Ferry Shuttles
|
||||
These shuttles go back and forth between two locations (normally called "station" and "offsite").
|
||||
Examples: Mining shuttle, Arrivals Shuttle, etc.
|
||||
|
||||
Old Type Path: `/datum/shuttle/ferry`\
|
||||
New Type Path: `/datum/shuttle/autodock/ferry`
|
||||
|
||||
##### New Vars:
|
||||
|
||||
Name|Type|Required?|Info
|
||||
---|---|---|---
|
||||
shuttle_area |`/area` typepath(s)|Yes| Can be a single path or list of paths.
|
||||
|
||||
##### Replaced vars:
|
||||
|
||||
Old|New|Required?|Info
|
||||
:---:|:---:|:---:|---
|
||||
area_station |landmark_station |Yes|Tag of the landmark for the "station" location.
|
||||
area_offsite |landmark_offsite |Yes|Tag of the landmark for the "offsite" location.
|
||||
area_transition |landmark_transition |No|Tag of the landmark for the "transition" location used during long_jump()
|
||||
dock_target_station |On landmark |No|`id_tag` docking controller *on the dock* has been moved to the `docking_controller` var on the landmark_station landmark obj.
|
||||
dock_target_offsite |On landmark |No|`id_tag` docking controller *on the dock* has been moved to the `docking_controller` var on the landmark_offsite landmark obj.
|
||||
|
||||
|
||||
|
||||
|
||||
### Multi Shuttles
|
||||
These shuttles go between a list of configured locations, one of which is its starting location.
|
||||
Examples: Skipjack, Syndicate Shuttle
|
||||
|
||||
Old Type Path: `/datum/shuttle/multi_shuttle`\
|
||||
New Type Path: `/datum/shuttle/autodock/multi`
|
||||
|
||||
##### New Vars:
|
||||
|
||||
Name|Type|Required?|Info
|
||||
---|---|---|---
|
||||
shuttle_area |`/area` typepath(s)|Yes| Can be a single path or list of paths.
|
||||
|
||||
##### Replaced vars:
|
||||
|
||||
Old|New|Required?|Info
|
||||
:---:|:---:|:---:|---
|
||||
origin |current_location |Yes|Tag of the landmark where the shuttle is at startup.
|
||||
interim |landmark_transition |No|Tag of the landmark for the "transition" location used during long_jump()
|
||||
start_location |N/A |No|No longer necessary, automatically determined from the value of `origin`
|
||||
destinations |destination_tags |Yes|List of destinations the shuttle can travel to. Used to be associative list of *name* -> *area typepath*, now is normal list of landmark tag ids. Name is now read from the landmark obj.
|
||||
destination_dock_targets|On landmarks |No|Used to be associative list of *name* -> *id_tag* for which docking controller *on the dock* to use at each destination. This is now specified by the `docking_controller` var on each landmark obj.
|
||||
|
||||
|
||||
|
||||
### Web Shuttles
|
||||
These shuttles travel along a network of locations connected by routes. Instead of being able to travel to any of its destinations, it can only travel to destinations connected by a route to its current location. Added by Polaris as an upgrade to Multi Shuttles.
|
||||
Note: While cool, it is likely that the upcoming "overmap" shuttles will be even cooler, and may eventually replace some web shuttles.
|
||||
Examples: Southern Cross' Ninja Shuttle, Tether's Excursion Shuttle
|
||||
|
||||
Old Type Path: `/datum/shuttle/web_shuttle`\
|
||||
New Type Path: `/datum/shuttle/autodock/web_shuttle`
|
||||
|
||||
##### New Vars:
|
||||
|
||||
Name|Type|Required?|Info
|
||||
---|---|---|---
|
||||
shuttle_area |`/area` typepath(s)|Yes| Can be a single path or list of paths.
|
||||
|
||||
##### Replaced vars:
|
||||
|
||||
Old|New|Required?|Info
|
||||
:---:|:---:|:---:|---
|
||||
current_area |current_location |Yes|Tag of the landmark where the shuttle is at startup.
|
||||
|
||||
#### Web Destination Configuration (`/datum/shuttle_destination`)
|
||||
The network of routes for each web shuttle is configured by defining datums. These are mostly unchanged but use landmarks instead of areas now.
|
||||
|
||||
##### Replaced vars:
|
||||
|
||||
Old|New|Required?|Info
|
||||
:---:|:---:|:---:|---
|
||||
my_area |my_landmark |Yes|Tag of the landmark associated with this destination.
|
||||
preferred_interim_area |preferred_interim_tag |No|Tag of the landmark for the "transition" location used during long_jump()
|
||||
dock_target |On landmark |No|`id_tag` docking controller *on the dock* has been moved to the `docking_controller` var on the my_landmark landmark obj.
|
||||
|
||||
### Misc Shuttle Types
|
||||
Other shuttle types that are either unused or unchanged in particular.
|
||||
|
||||
#### Escape Pods
|
||||
Special case of ferry shuttles that use escape pod berth controllers.
|
||||
Type path changed from `/datum/shuttle/ferry/escape_pod` to `/datum/shuttle/autodock/ferry/escape_pod`
|
||||
Follow same instructions as for other ferry shuttles.
|
||||
|
||||
#### Multidock Ferry Shuttles
|
||||
`/datum/shuttle/ferry/multidock` was a variant of ferry shuttles that could use a different docking port at each location.
|
||||
Obsolete since is now natively supported by all dockable shuttles.
|
||||
@@ -8,7 +8,7 @@
|
||||
/datum/shuttle_route
|
||||
var/datum/shuttle_destination/start = null // One of the two sides of this route. Start just means it was the creator of this route.
|
||||
var/datum/shuttle_destination/end = null // The second side.
|
||||
var/area/interim = null // Where the shuttle sits during the movement. Make sure no other shuttle shares this or Very Bad Things will happen.
|
||||
var/var/obj/effect/shuttle_landmark/interim // Where the shuttle sits during the movement. Make sure no other shuttle shares this or Very Bad Things will happen.
|
||||
var/travel_time = 0 // How long it takes to move from start to end, or end to start. Set to 0 for instant travel.
|
||||
var/one_way = FALSE // If true, you can't travel from end to start.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
start = _start
|
||||
end = _end
|
||||
if(_interim)
|
||||
interim = locate(_interim)
|
||||
interim = SSshuttles.get_landmark(_interim)
|
||||
travel_time = _time
|
||||
one_way = _oneway
|
||||
|
||||
@@ -50,14 +50,12 @@
|
||||
// This is the second datum, and contains information on all the potential destinations for a specific shuttle.
|
||||
/datum/shuttle_destination
|
||||
var/name = "a place" // Name of the destination, used for the flight computer.
|
||||
var/area/my_area = null // Where the shuttle will move to when it actually arrives.
|
||||
var/obj/effect/shuttle_landmark/my_landmark = null // Where the shuttle will move to when it actually arrives.
|
||||
var/datum/shuttle_web_master/master = null // The datum that does the coordination with the actual shuttle datum.
|
||||
var/list/routes = list() // Routes that are connected to this destination.
|
||||
var/preferred_interim_area = null // When building a new route, use this interim area.
|
||||
var/preferred_interim_tag = null // When building a new route, use interim landmark with this tag.
|
||||
var/skip_me = FALSE // We will not autocreate this one. Some map must be doing it.
|
||||
|
||||
var/dock_target = null // The tag_id that the shuttle will use to try to dock to the destination, if able.
|
||||
|
||||
var/radio_announce = 0 // Whether it will make a station announcement (0) or a radio announcement (1).
|
||||
var/announcer = null // The name of the 'announcer' that will say the arrival/departure messages. Defaults to the map's boss name if blank.
|
||||
// var/arrival_message = null // Message said if the ship enters this destination. Not announced if the ship is cloaked.
|
||||
@@ -72,7 +70,9 @@
|
||||
var/list/routes_to_make = list()
|
||||
|
||||
/datum/shuttle_destination/New(var/new_master)
|
||||
my_area = locate(my_area)
|
||||
my_landmark = SSshuttles.get_landmark(my_landmark)
|
||||
if(!my_landmark)
|
||||
log_debug("Web shuttle destination '[name]' could not find its landmark '[my_landmark]'.")
|
||||
master = new_master
|
||||
|
||||
/datum/shuttle_destination/Destroy()
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
// Now link our new destination to us.
|
||||
var/travel_delay = destinations_to_create[type_to_make]
|
||||
link_destinations(new_dest, preferred_interim_area, travel_delay)
|
||||
link_destinations(new_dest, preferred_interim_tag, travel_delay)
|
||||
to_world("SHUTTLES: [name] has linked themselves to [new_dest.name]")
|
||||
|
||||
to_world("SHUTTLES: [name] has finished building destinations. already_made list is \[[english_list(already_made)]\].")
|
||||
@@ -135,14 +135,14 @@
|
||||
else
|
||||
global_announcer.autosay(get_arrival_message(),(announcer ? announcer : "[using_map.boss_name]"))
|
||||
|
||||
/datum/shuttle_destination/proc/link_destinations(var/datum/shuttle_destination/other_place, var/area/interim_area, var/travel_time = 0)
|
||||
/datum/shuttle_destination/proc/link_destinations(var/datum/shuttle_destination/other_place, var/interim_tag, var/travel_time = 0)
|
||||
// First, check to make sure this doesn't cause a duplicate route.
|
||||
for(var/datum/shuttle_route/R in routes)
|
||||
if(R.start == other_place || R.end == other_place)
|
||||
return
|
||||
|
||||
// Now we can connect them.
|
||||
var/datum/shuttle_route/new_route = new(src, other_place, interim_area, travel_time)
|
||||
var/datum/shuttle_route/new_route = new(src, other_place, interim_tag, travel_time)
|
||||
routes += new_route
|
||||
other_place.routes += new_route
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
// This is the third and final datum, which coordinates with the shuttle datum to tell it where it is, where it can go, and how long it will take.
|
||||
// It is also responsible for instancing all the destinations it has control over, and linking them together.
|
||||
/datum/shuttle_web_master
|
||||
var/datum/shuttle/web_shuttle/my_shuttle = null // Ref to the shuttle this datum is coordinating with.
|
||||
var/datum/shuttle/autodock/web_shuttle/my_shuttle = null // Ref to the shuttle this datum is coordinating with.
|
||||
var/datum/shuttle_destination/current_destination = null // Where the shuttle currently is. Bit of a misnomer.
|
||||
var/datum/shuttle_destination/future_destination = null // Where it will be in the near future.
|
||||
var/datum/shuttle_destination/starting_destination = null // Where the shuttle will start at, generally at the home base.
|
||||
@@ -204,7 +204,7 @@
|
||||
for(var/datum/shuttle_destination/D in destinations)
|
||||
for(var/type_to_link in D.routes_to_make)
|
||||
var/travel_delay = D.routes_to_make[type_to_link]
|
||||
D.link_destinations(get_destination_by_type(type_to_link), D.preferred_interim_area, travel_delay)
|
||||
D.link_destinations(get_destination_by_type(type_to_link), D.preferred_interim_tag, travel_delay)
|
||||
|
||||
/datum/shuttle_web_master/proc/on_shuttle_departure()
|
||||
current_destination.exit()
|
||||
@@ -214,11 +214,6 @@
|
||||
future_destination.enter()
|
||||
current_destination = future_destination
|
||||
future_destination = null
|
||||
my_shuttle.current_area = current_destination.my_area
|
||||
|
||||
/datum/shuttle_web_master/proc/current_dock_target()
|
||||
if(current_destination)
|
||||
return current_destination.dock_target
|
||||
|
||||
/datum/shuttle_web_master/proc/get_available_routes()
|
||||
if(current_destination)
|
||||
@@ -254,10 +249,11 @@
|
||||
future_destination = R.get_other_side(current_destination)
|
||||
|
||||
var/travel_time = R.travel_time * my_shuttle.flight_time_modifier * 2 // Autopilot is less efficent than having someone flying manually.
|
||||
// TODO - Leshana - Change this to use proccess stuff of autodock!
|
||||
if(R.interim && R.travel_time > 0)
|
||||
my_shuttle.long_jump(my_shuttle.current_area, future_destination.my_area, R.interim, travel_time / 10)
|
||||
my_shuttle.long_jump(future_destination.my_landmark, R.interim, travel_time / 10)
|
||||
else
|
||||
my_shuttle.short_jump(my_shuttle.current_area, future_destination.my_area)
|
||||
my_shuttle.short_jump(future_destination.my_landmark)
|
||||
return TRUE // Note this will return before the shuttle actually arrives.
|
||||
|
||||
/datum/shuttle_web_master/proc/process_autopath()
|
||||
|
||||
Reference in New Issue
Block a user