diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index 007fffd634..82243073f3 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -8108,6 +8108,7 @@
name = "syndicate infiltrator";
port_direction = 1;
roundstart_move = "syndicate_away";
+ hidden = 1;
width = 18
},
/obj/structure/fans/tiny,
diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm
index 26b166fd8c..b961c9bd44 100644
--- a/code/__DEFINES/shuttles.dm
+++ b/code/__DEFINES/shuttles.dm
@@ -70,4 +70,8 @@
//Rotation params
#define ROTATE_DIR 1
#define ROTATE_SMOOTH 2
-#define ROTATE_OFFSET 4
\ No newline at end of file
+#define ROTATE_OFFSET 4
+
+#define SHUTTLE_DOCKER_LANDING_CLEAR 1
+#define SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT 2
+#define SHUTTLE_DOCKER_BLOCKED 3
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 4800f35b65..d3b62b67af 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -359,7 +359,7 @@ Proc for attack log creation, because really why not
if(!user)
return 0
var/atom/Tloc = null
- if(target)
+ if(target && !isturf(target))
Tloc = target.loc
var/atom/Uloc = user.loc
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 12173b21b7..ad295167cf 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -4,6 +4,7 @@ GLOBAL_LIST_EMPTY(airlocks) //list of all airlocks
GLOBAL_LIST_EMPTY(mechas_list) //list of all mechs. Used by hostile mobs target tracking.
GLOBAL_LIST_EMPTY(shuttle_caller_list) //list of all communication consoles and AIs, for automatic shuttle calls when there are none.
GLOBAL_LIST_EMPTY(machines) //NOTE: this is a list of ALL machines now. The processing machines list is SSmachine.processing !
+GLOBAL_LIST_EMPTY(navigation_computers) //list of all /obj/machinery/computer/camera_advanced/shuttle_docker
GLOBAL_LIST_EMPTY(syndicate_shuttle_boards) //important to keep track of for managing nukeops war declarations.
GLOBAL_LIST_EMPTY(navbeacons) //list of all bot nagivation beacons, used for patrolling.
GLOBAL_LIST_EMPTY(teleportbeacons) //list of all tracking beacons used by teleporters
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 75111a2017..c80bc17047 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -44,6 +44,9 @@ SUBSYSTEM_DEF(shuttle)
var/list/requestlist = list()
var/list/orderhistory = list()
+ var/list/hidden_shuttle_turfs = list() //all turfs hidden from navigation computers associated with a list containing the image hiding them and the type of the turf they are pretending to be
+ var/list/hidden_shuttle_turf_images = list() //only the images from the above list
+
var/datum/round_event/shuttle_loan/shuttle_loan
var/shuttle_purchased = FALSE //If the station has purchased a replacement escape shuttle this round
@@ -648,4 +651,40 @@ SUBSYSTEM_DEF(shuttle)
var/list/xs = overlap[1]
var/list/ys = overlap[2]
if(xs.len && ys.len)
- .[port] = overlap
\ No newline at end of file
+ .[port] = overlap
+
+/datum/controller/subsystem/shuttle/proc/update_hidden_docking_ports(list/remove_turfs, list/add_turfs)
+ var/list/remove_images = list()
+ var/list/add_images = list()
+
+ if(remove_turfs)
+ for(var/T in remove_turfs)
+ var/list/L = hidden_shuttle_turfs[T]
+ if(L)
+ remove_images += L[1]
+ hidden_shuttle_turfs -= remove_turfs
+
+ if(add_turfs)
+ for(var/V in add_turfs)
+ var/turf/T = V
+ var/image/I
+ if(remove_images.len)
+ //we can just reuse any images we are about to delete instead of making new ones
+ I = remove_images[1]
+ remove_images.Cut(1, 2)
+ I.loc = T
+ else
+ I = image(loc = T)
+ add_images += I
+ I.appearance = T.appearance
+ I.override = TRUE
+ hidden_shuttle_turfs[T] = list(I, T.type)
+
+ hidden_shuttle_turf_images -= remove_images
+ hidden_shuttle_turf_images += add_images
+
+ for(var/V in GLOB.navigation_computers)
+ var/obj/machinery/computer/camera_advanced/shuttle_docker/C = V
+ C.update_hidden_docking_ports(remove_images, add_images)
+
+ QDEL_LIST(remove_images)
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index e1e605526d..0668ec63fb 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -204,6 +204,7 @@
shuttlePortName = "custom location"
x_offset = 9
y_offset = 0
+ see_hidden = FALSE
/obj/docking_port/mobile/pirate
name = "pirate shuttle"
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index cedebc8edb..65636aa528 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -14,6 +14,17 @@
var/x_offset = 0
var/y_offset = 0
var/space_turfs_only = TRUE
+ var/see_hidden = FALSE
+ var/designate_time = 0
+ var/turf/designating_target_loc
+
+/obj/machinery/computer/camera_advanced/shuttle_docker/Initialize()
+ . = ..()
+ GLOB.navigation_computers += src
+
+/obj/machinery/computer/camera_advanced/shuttle_docker/Destroy()
+ . = ..()
+ GLOB.navigation_computers -= src
/obj/machinery/computer/camera_advanced/shuttle_docker/GrantActions(mob/living/user)
if(jumpto_ports.len)
@@ -59,51 +70,87 @@
..()
if(!QDELETED(user) && user.client)
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
- user.client.images += the_eye.placement_images
- user.client.images += the_eye.placed_images
+ var/list/to_add = list()
+ to_add += the_eye.placement_images
+ to_add += the_eye.placed_images
+ if(!see_hidden)
+ to_add += SSshuttle.hidden_shuttle_turf_images
+
+ user.client.images += to_add
user.client.change_view(view_range)
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
..()
if(!QDELETED(user) && user.client)
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
- user.client.images -= the_eye.placement_images
- user.client.images -= the_eye.placed_images
+ var/list/to_remove = list()
+ to_remove += the_eye.placement_images
+ to_remove += the_eye.placed_images
+ if(!see_hidden)
+ to_remove += SSshuttle.hidden_shuttle_turf_images
+
+ user.client.images -= to_remove
user.client.change_view(CONFIG_GET(string/default_view))
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot()
- if(!checkLandingSpot())
- return FALSE
+ if(designating_target_loc || !current_user)
+ return
+
var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj
+ var/landing_clear = checkLandingSpot()
+ if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED))
+ to_chat(current_user, "Targeting transit location, please wait [designate_time/10] seconds...")
+ designating_target_loc = the_eye.loc
+ var/wait_completed = do_after(current_user, designate_time, FALSE, designating_target_loc, TRUE, CALLBACK(src, /obj/machinery/computer/camera_advanced/shuttle_docker/proc/canDesignateTarget))
+ designating_target_loc = null
+ if(!current_user)
+ return
+ if(!wait_completed)
+ to_chat(current_user, "Operation aborted.")
+ return
+ landing_clear = checkLandingSpot()
+
+ if(landing_clear != SHUTTLE_DOCKER_LANDING_CLEAR)
+ switch(landing_clear)
+ if(SHUTTLE_DOCKER_BLOCKED)
+ to_chat(current_user, "Invalid transit location")
+ if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
+ to_chat(current_user, "Unknown object detected in landing zone. Please designate another location.")
+ return
+
if(!my_port)
my_port = new /obj/docking_port/stationary()
my_port.name = shuttlePortName
my_port.id = shuttlePortId
- var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
- my_port.height = M.height
- my_port.width = M.width
- my_port.dheight = M.dheight
- my_port.dwidth = M.dwidth
+ my_port.height = shuttle_port.height
+ my_port.width = shuttle_port.width
+ my_port.dheight = shuttle_port.dheight
+ my_port.dwidth = shuttle_port.dwidth
+ my_port.hidden = shuttle_port.hidden
my_port.dir = the_eye.dir
my_port.loc = locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z)
- if(current_user && current_user.client)
+ if(current_user.client)
current_user.client.images -= the_eye.placed_images
- for(var/V in the_eye.placed_images)
- qdel(V)
- the_eye.placed_images = list()
+ QDEL_LIST(the_eye.placed_images)
for(var/V in the_eye.placement_images)
var/image/I = V
var/image/newI = image('icons/effects/alphacolors.dmi', the_eye.loc, "blue")
- newI.loc = I.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry
+ newI.loc = I.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry.
newI.layer = ABOVE_OPEN_TURF_LAYER
newI.plane = 0
newI.mouse_opacity = 0
the_eye.placed_images += newI
- if(current_user && current_user.client)
+ if(current_user.client)
current_user.client.images += the_eye.placed_images
+ to_chat(current_user, "Transit location designated")
+ return
+
+/obj/machinery/computer/camera_advanced/shuttle_docker/proc/canDesignateTarget()
+ if(!designating_target_loc || !current_user || (eyeobj.loc != designating_target_loc) || (stat & (NOPOWER|BROKEN)) )
+ return FALSE
return TRUE
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot()
@@ -127,41 +174,65 @@
var/turf/eyeturf = get_turf(the_eye)
if(!eyeturf)
return
+ . = SHUTTLE_DOCKER_LANDING_CLEAR
var/list/bounds = shuttle_port.return_coords(the_eye.x - x_offset, the_eye.y - y_offset, the_eye.dir)
var/list/overlappers = SSshuttle.get_dock_overlap(bounds[1], bounds[2], bounds[3], bounds[4], the_eye.z)
- . = TRUE
var/list/image_cache = the_eye.placement_images
for(var/i in 1 to image_cache.len)
var/image/I = image_cache[i]
var/list/coords = image_cache[I]
var/turf/T = locate(eyeturf.x + coords[1], eyeturf.y + coords[2], eyeturf.z)
I.loc = T
- if(checkLandingTurf(T, overlappers))
- I.icon_state = "green"
- else
- I.icon_state = "red"
- . = FALSE
+ switch(checkLandingTurf(T, overlappers))
+ if(SHUTTLE_DOCKER_LANDING_CLEAR)
+ I.icon_state = "green"
+ if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
+ I.icon_state = "green"
+ if(. == SHUTTLE_DOCKER_LANDING_CLEAR)
+ . = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
+ else
+ I.icon_state = "red"
+ . = SHUTTLE_DOCKER_BLOCKED
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingTurf(turf/T, list/overlappers)
// Too close to the map edge is never allowed
if(!T || T.x == 1 || T.y == 1 || T.x == world.maxx || T.y == world.maxy)
- return FALSE
+ return SHUTTLE_DOCKER_BLOCKED
// If it's one of our shuttle areas assume it's ok to be there
if(shuttle_port.shuttle_areas[T.loc])
- return TRUE
+ return SHUTTLE_DOCKER_LANDING_CLEAR
+ . = SHUTTLE_DOCKER_LANDING_CLEAR
+ // See if the turf is hidden from us
+ var/list/hidden_turf_info
+ if(!see_hidden)
+ hidden_turf_info = SSshuttle.hidden_shuttle_turfs[T]
+ if(hidden_turf_info)
+ . = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
+
+ if(space_turfs_only)
+ var/turf_type = hidden_turf_info ? hidden_turf_info[2] : T.type
+ if(!ispath(turf_type, /turf/open/space))
+ return SHUTTLE_DOCKER_BLOCKED
+
// Checking for overlapping dock boundaries
for(var/i in 1 to overlappers.len)
var/obj/docking_port/port = overlappers[i]
if(port == my_port)
continue
+ var/port_hidden = !see_hidden && port.hidden
var/list/overlap = overlappers[port]
var/list/xs = overlap[1]
var/list/ys = overlap[2]
if(xs["[T.x]"] && ys["[T.y]"])
- return FALSE
- if(space_turfs_only && !isspaceturf(T))
- return FALSE
- return TRUE
+ if(port_hidden)
+ . = SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT
+ else
+ return SHUTTLE_DOCKER_BLOCKED
+
+/obj/machinery/computer/camera_advanced/shuttle_docker/proc/update_hidden_docking_ports(list/remove_images, list/add_images)
+ if(!see_hidden && current_user && current_user.client)
+ current_user.client.images -= remove_images
+ current_user.client.images += add_images
/mob/camera/aiEye/remote/shuttle_docker
visible_icon = FALSE
@@ -204,10 +275,7 @@
var/mob/living/C = target
var/mob/camera/aiEye/remote/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
- if(origin.placeLandingSpot())
- to_chat(target, "Transit location designated")
- else
- to_chat(target, "Invalid transit location")
+ origin.placeLandingSpot(target)
/datum/action/innate/camera_jump/shuttle_docker
name = "Jump to Location"
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 2e0248b2cd..6b32a8ad21 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -24,6 +24,7 @@
var/area_type
var/turf_type
var/baseturf_type
+ var/hidden = FALSE //are we invisible to shuttle navigation computers?
//these objects are indestructible
/obj/docking_port/Destroy(force)
@@ -304,6 +305,7 @@
var/current_engines = 0 //current engine power
var/initial_engines = 0 //initial engine power
var/can_move_docking_ports = FALSE //if this shuttle can move docking ports other than the one it is docked at
+ var/list/hidden_turfs = list()
/obj/docking_port/mobile/proc/register()
SSshuttle.mobile += src
@@ -539,7 +541,7 @@
// The baseturf that the gets assigned to the turf_type above
var/underlying_baseturf_type = /turf/open/space
-
+
// The area that gets placed under where the shuttle moved from
var/underlying_area_type = /area/space
@@ -591,7 +593,7 @@
CHECK_TICK
/****************************************All beforeShuttleMove procs*****************************************/
-
+
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
@@ -619,6 +621,17 @@
old_turfs[oldT] = move_mode
+ /*******************************************Hiding turfs if necessary******************************************/
+
+ var/list/new_hidden_turfs
+ if(hidden)
+ new_hidden_turfs = list()
+ for(var/i in 1 to old_turfs.len)
+ var/turf/oldT = old_turfs[i]
+ if(old_turfs[oldT] & MOVE_TURF)
+ new_hidden_turfs += new_turfs[i]
+ SSshuttle.update_hidden_docking_ports(null, new_hidden_turfs)
+
/*******************************************All onShuttleMove procs******************************************/
for(var/i in 1 to old_turfs.len)
@@ -632,10 +645,10 @@
continue
moving_atom.onShuttleMove(newT, oldT, movement_force, movement_direction, old_dock, src) //atoms
moved_atoms[moving_atom] = oldT
-
+
if(move_mode & MOVE_TURF)
oldT.onShuttleMove(newT, movement_force, movement_direction) //turfs
-
+
if(move_mode & MOVE_AREA)
var/area/shuttle_area = oldT.loc
shuttle_area.onShuttleMove(oldT, newT, underlying_old_area) //areas
@@ -682,6 +695,12 @@
newT.blocks_air = initial(newT.blocks_air)
newT.air_update_turf(TRUE)
+ /*******************************************Unhiding turfs if necessary******************************************/
+
+ if(new_hidden_turfs)
+ SSshuttle.update_hidden_docking_ports(hidden_turfs, null)
+ hidden_turfs = new_hidden_turfs
+
check_poddoors()
new_dock.last_dock_time = world.time
setDir(new_dock.dir)
diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm
index 4574e62bd1..283ac0f35c 100644
--- a/code/modules/shuttle/syndicate.dm
+++ b/code/modules/shuttle/syndicate.dm
@@ -58,5 +58,6 @@
view_range = 13
x_offset = -4
y_offset = -2
+ see_hidden = TRUE
#undef SYNDICATE_CHALLENGE_TIMER
\ No newline at end of file
diff --git a/code/modules/shuttle/white_ship.dm b/code/modules/shuttle/white_ship.dm
index b6775fea82..507fef54a8 100644
--- a/code/modules/shuttle/white_ship.dm
+++ b/code/modules/shuttle/white_ship.dm
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
/obj/machinery/computer/shuttle/white_ship
name = "White Ship Console"
desc = "Used to control the White Ship."
@@ -16,3 +17,25 @@
view_range = 20
x_offset = -6
y_offset = -10
+=======
+/obj/machinery/computer/shuttle/white_ship
+ name = "White Ship Console"
+ desc = "Used to control the White Ship."
+ circuit = /obj/item/circuitboard/computer/white_ship
+ shuttleId = "whiteship"
+ possible_destinations = "whiteship_away;whiteship_home;whiteship_z4;whiteship_lavaland;whiteship_custom"
+
+/obj/machinery/computer/camera_advanced/shuttle_docker/whiteship
+ name = "White Ship Navigation Computer"
+ desc = "Used to designate a precise transit location for the White Ship."
+ shuttleId = "whiteship"
+ station_lock_override = TRUE
+ shuttlePortId = "whiteship_custom"
+ shuttlePortName = "Custom Location"
+ jumpto_ports = list("whiteship_away" = 1, "whiteship_home" = 1, "whiteship_z4" = 1)
+ view_range = 18
+ x_offset = -6
+ y_offset = -10
+ designate_time = 100
+
+>>>>>>> 05d7402... Allowed shuttle docking ports to be hidden from some shuttle docking computers (#33148)