mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-18 21:53:22 +00:00
Fixes critical plane masters improperly not being readded in show_to (#72604) ## About The Pull Request [Adds support for pulling z offset context from an atom's plane](9f215c5316) This is needed to fix paper bins, since the object we plane set there isn't actually on a z level. Useful elsewhere too! [Fixes compiler errors that came from asserting that plane spokesmen had a plane var](b830002443) [Ensures lighting backdrops ALWAYS exist for each lighting plane.](0e931169f7) They can't float becuase we can see more then one plane at once yaknow? [Fixes parallax going to shit if a mob moved zs without having a client](244b2b25ba) Issue lies with how is_outside_bounds just blocked any plane readding It's possible for a client to not be connected during z moves, so we need to account for them rejoining in show_to, instead of just blocking any of our edge cases. Fixing this involved having parallax override blocks for show_plane and anything with the right critical flags ensuring mobs have JUST the right PMs and relays. It's duped logic but I'm unsure of how else to handle it and frankly this stuff is just kinda depressing. Might refactor later [show_to can be called twice successfully with no hide_from call.](092581a5c0) Ensures no runtimes off the registers from this ## Why It's Good For The Game Fixes #72543 Fixes lighting looking batshit on multiz. None reported this I cry into the night. ## Changelog 🆑 fix: Fixes parallax showing up ABOVE the game if you moved z levels while disconnected /🆑 --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: Time-Green <timkoster1@hotmail.com>
402 lines
15 KiB
Plaintext
402 lines
15 KiB
Plaintext
/obj/machinery/computer/camera_advanced/shuttle_docker
|
|
name = "navigation computer"
|
|
desc = "Used to designate a precise transit location for a spacecraft."
|
|
jump_action = null
|
|
should_supress_view_changes = FALSE
|
|
|
|
// Docking cameras should only interact with their current z-level.
|
|
move_up_action = null
|
|
move_down_action = null
|
|
|
|
var/shuttleId = ""
|
|
var/shuttlePortId = ""
|
|
var/shuttlePortName = "custom location"
|
|
/// Hashset of ports to jump to and ignore for collision purposes
|
|
var/list/jump_to_ports = list()
|
|
/// The custom docking port placed by this console
|
|
var/obj/docking_port/stationary/my_port
|
|
/// The mobile docking port of the connected shuttle
|
|
var/obj/docking_port/mobile/shuttle_port
|
|
// Traits forbided for custom docking
|
|
var/list/locked_traits = list(ZTRAIT_RESERVED, ZTRAIT_CENTCOM, ZTRAIT_AWAY)
|
|
var/view_range = 0
|
|
var/x_offset = 0
|
|
var/y_offset = 0
|
|
var/list/whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava, /turf/open/openspace)
|
|
var/see_hidden = FALSE
|
|
var/designate_time = 0
|
|
var/turf/designating_target_loc
|
|
var/jammed = FALSE
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/Initialize(mapload)
|
|
. = ..()
|
|
GLOB.navigation_computers += src
|
|
actions += new /datum/action/innate/shuttledocker_rotate(src)
|
|
actions += new /datum/action/innate/shuttledocker_place(src)
|
|
|
|
set_init_ports()
|
|
|
|
if(connect_to_shuttle(mapload, SSshuttle.get_containing_shuttle(src)))
|
|
for(var/obj/docking_port/stationary/port as anything in SSshuttle.stationary_docking_ports)
|
|
if(port.shuttle_id == shuttleId)
|
|
add_jumpable_port(port.shuttle_id)
|
|
|
|
for(var/obj/docking_port/stationary/port as anything in SSshuttle.stationary_docking_ports)
|
|
if(!port)
|
|
continue
|
|
if(jump_to_ports[port.shuttle_id])
|
|
z_lock |= port.z
|
|
whitelist_turfs = typecacheof(whitelist_turfs)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/Destroy()
|
|
. = ..()
|
|
GLOB.navigation_computers -= src
|
|
|
|
if(my_port?.get_docked())
|
|
my_port.delete_after = TRUE
|
|
my_port.shuttle_id = null
|
|
my_port.name = "Old [my_port.name]"
|
|
my_port = null
|
|
else
|
|
QDEL_NULL(my_port)
|
|
|
|
/// "Initializes" any default port ids we have, done so add_jumpable_port can be a proper setter
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/set_init_ports()
|
|
var/list/init_ports = jump_to_ports.Copy()
|
|
jump_to_ports = list() //Reset it so we don't get dupes
|
|
for(var/port_id in init_ports)
|
|
add_jumpable_port(port_id)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/add_jumpable_port(port_id)
|
|
if(!length(jump_to_ports))
|
|
actions += new /datum/action/innate/camera_jump/shuttle_docker(src)
|
|
jump_to_ports[port_id] = TRUE
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/remove_jumpable_port(port_id)
|
|
jump_to_ports -= port_id
|
|
if(!length(jump_to_ports))
|
|
var/datum/action/to_remove = locate(/datum/action/innate/camera_jump/shuttle_docker) in actions
|
|
actions -= to_remove
|
|
qdel(to_remove)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/attack_hand(mob/user, list/modifiers)
|
|
if(jammed)
|
|
to_chat(user, span_warning("The Syndicate is jamming the console!"))
|
|
return
|
|
if(!shuttle_port && !SSshuttle.getShuttle(shuttleId))
|
|
to_chat(user,span_warning("Warning: Shuttle connection severed!"))
|
|
return
|
|
return ..()
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/CreateEye()
|
|
shuttle_port = SSshuttle.getShuttle(shuttleId)
|
|
if(QDELETED(shuttle_port))
|
|
shuttle_port = null
|
|
return
|
|
|
|
eyeobj = new /mob/camera/ai_eye/remote/shuttle_docker(null, src)
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
the_eye.setDir(shuttle_port.dir)
|
|
var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z)
|
|
for(var/V in shuttle_port.shuttle_areas)
|
|
var/area/A = V
|
|
for(var/turf/T in A)
|
|
if(T.z != origin.z)
|
|
continue
|
|
var/image/I = image('icons/effects/alphacolors.dmi', origin, "red")
|
|
var/x_off = T.x - origin.x
|
|
var/y_off = T.y - origin.y
|
|
I.loc = locate(origin.x + x_off, origin.y + y_off, origin.z) //we have to set this after creating the image because it might be null, and images created in nullspace are immutable.
|
|
I.layer = ABOVE_NORMAL_TURF_LAYER
|
|
SET_PLANE(I, ABOVE_GAME_PLANE, T)
|
|
I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
the_eye.placement_images[I] = list(x_off, y_off)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user)
|
|
..()
|
|
if(!QDELETED(user) && user.client)
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
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.view_size.setTo(view_range)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
|
|
..()
|
|
if(!QDELETED(user) && user.client)
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
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.view_size.resetToDefault()
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot()
|
|
if(designating_target_loc || !current_user)
|
|
return
|
|
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
var/landing_clear = checkLandingSpot()
|
|
if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED))
|
|
to_chat(current_user, span_warning("Targeting transit location, please wait [DisplayTimeText(designate_time)]..."))
|
|
designating_target_loc = the_eye.loc
|
|
var/wait_completed = do_after(current_user, designate_time, designating_target_loc, timed_action_flags = IGNORE_HELD_ITEM, extra_checks = CALLBACK(src, TYPE_PROC_REF(/obj/machinery/computer/camera_advanced/shuttle_docker, canDesignateTarget)))
|
|
designating_target_loc = null
|
|
if(!current_user)
|
|
return
|
|
if(!wait_completed)
|
|
to_chat(current_user, span_warning("Operation aborted."))
|
|
return
|
|
landing_clear = checkLandingSpot()
|
|
|
|
if(landing_clear != SHUTTLE_DOCKER_LANDING_CLEAR)
|
|
switch(landing_clear)
|
|
if(SHUTTLE_DOCKER_BLOCKED)
|
|
to_chat(current_user, span_warning("Invalid transit location."))
|
|
if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
|
|
to_chat(current_user, span_warning("Unknown object detected in landing zone. Please designate another location."))
|
|
return
|
|
|
|
///Make one use port that deleted after fly off, to don't lose info that need on to properly fly off.
|
|
if(my_port?.get_docked())
|
|
my_port.unregister()
|
|
my_port.delete_after = TRUE
|
|
my_port.shuttle_id = null
|
|
my_port.name = "Old [my_port.name]"
|
|
my_port = null
|
|
|
|
if(!my_port)
|
|
my_port = new()
|
|
my_port.unregister()
|
|
my_port.name = shuttlePortName
|
|
my_port.shuttle_id = shuttlePortId
|
|
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.register(TRUE)
|
|
my_port.setDir(the_eye.dir)
|
|
my_port.forceMove(locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z))
|
|
|
|
if(current_user.client)
|
|
current_user.client.images -= the_eye.placed_images
|
|
|
|
QDEL_LIST(the_eye.placed_images)
|
|
|
|
for(var/image/place_spots as anything in the_eye.placement_images)
|
|
var/image/newI = image('icons/effects/alphacolors.dmi', the_eye.loc, "blue")
|
|
newI.loc = place_spots.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry.
|
|
newI.layer = NAVIGATION_EYE_LAYER
|
|
SET_PLANE_EXPLICIT(newI, ABOVE_GAME_PLANE, place_spots)
|
|
newI.mouse_opacity = 0
|
|
the_eye.placed_images += newI
|
|
|
|
if(current_user.client)
|
|
current_user.client.images += the_eye.placed_images
|
|
to_chat(current_user, span_notice("Transit location designated."))
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/canDesignateTarget()
|
|
if(!designating_target_loc || !current_user || (eyeobj.loc != designating_target_loc) || (machine_stat & (NOPOWER|BROKEN)) )
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot()
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
var/list/image_cache = the_eye.placement_images
|
|
the_eye.setDir(turn(the_eye.dir, -90))
|
|
for(var/i in 1 to image_cache.len)
|
|
var/image/pic = image_cache[i]
|
|
var/list/coords = image_cache[pic]
|
|
var/Tmp = coords[1]
|
|
coords[1] = coords[2]
|
|
coords[2] = -Tmp
|
|
pic.loc = locate(the_eye.x + coords[1], the_eye.y + coords[2], the_eye.z)
|
|
var/Tmp = x_offset
|
|
x_offset = y_offset
|
|
y_offset = -Tmp
|
|
checkLandingSpot()
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot()
|
|
var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj
|
|
var/turf/eyeturf = get_turf(the_eye)
|
|
if(!eyeturf)
|
|
return SHUTTLE_DOCKER_BLOCKED
|
|
if(!eyeturf.z || SSmapping.level_has_any_trait(eyeturf.z, locked_traits))
|
|
return SHUTTLE_DOCKER_BLOCKED
|
|
|
|
. = 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)
|
|
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
|
|
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 <= 10 || T.y <= 10 || T.x >= world.maxx - 10 || T.y >= world.maxy - 10)
|
|
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 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(length(whitelist_turfs))
|
|
var/turf_type = hidden_turf_info ? hidden_turf_info[2] : T.type
|
|
if(!is_type_in_typecache(turf_type, whitelist_turfs))
|
|
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]"])
|
|
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?.client)
|
|
current_user.client.images -= remove_images
|
|
current_user.client.images += add_images
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
|
if(!mapload)
|
|
return FALSE
|
|
if(port)
|
|
shuttleId = port.shuttle_id
|
|
shuttlePortId = "[port.shuttle_id]_custom"
|
|
if(dock)
|
|
add_jumpable_port(dock.shuttle_id)
|
|
return TRUE
|
|
|
|
/mob/camera/ai_eye/remote/shuttle_docker
|
|
visible_icon = FALSE
|
|
use_static = FALSE
|
|
var/list/placement_images = list()
|
|
var/list/placed_images = list()
|
|
|
|
/mob/camera/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin)
|
|
src.origin = origin
|
|
return ..()
|
|
|
|
/mob/camera/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE)
|
|
. = ..()
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin
|
|
console.checkLandingSpot()
|
|
|
|
/mob/camera/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user)
|
|
user.set_sight(BLIND|SEE_TURFS)
|
|
user.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
|
user.sync_lighting_plane_alpha()
|
|
return TRUE
|
|
|
|
/datum/action/innate/shuttledocker_rotate
|
|
name = "Rotate"
|
|
button_icon = 'icons/mob/actions/actions_mecha.dmi'
|
|
button_icon_state = "mech_cycle_equip_off"
|
|
|
|
/datum/action/innate/shuttledocker_rotate/Activate()
|
|
if(QDELETED(owner) || !isliving(owner))
|
|
return
|
|
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
|
origin.rotateLandingSpot()
|
|
|
|
/datum/action/innate/shuttledocker_place
|
|
name = "Place"
|
|
button_icon = 'icons/mob/actions/actions_mecha.dmi'
|
|
button_icon_state = "mech_zoom_off"
|
|
|
|
/datum/action/innate/shuttledocker_place/Activate()
|
|
if(QDELETED(owner) || !isliving(owner))
|
|
return
|
|
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
|
origin.placeLandingSpot(owner)
|
|
|
|
/datum/action/innate/camera_jump/shuttle_docker
|
|
name = "Jump to Location"
|
|
button_icon_state = "camera_jump"
|
|
|
|
/datum/action/innate/camera_jump/shuttle_docker/Activate()
|
|
if(QDELETED(owner) || !isliving(owner))
|
|
return
|
|
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin
|
|
|
|
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
|
|
|
var/list/L = list()
|
|
for(var/V in SSshuttle.stationary_docking_ports)
|
|
if(!V)
|
|
stack_trace("SSshuttle.stationary_docking_ports have null entry!")
|
|
continue
|
|
var/obj/docking_port/stationary/S = V
|
|
if(console.z_lock.len && !(S.z in console.z_lock))
|
|
continue
|
|
if(console.jump_to_ports[S.shuttle_id])
|
|
L["([L.len])[S.name]"] = S
|
|
|
|
for(var/V in SSshuttle.beacon_list)
|
|
if(!V)
|
|
stack_trace("SSshuttle.beacon_list have null entry!")
|
|
continue
|
|
var/obj/machinery/spaceship_navigation_beacon/nav_beacon = V
|
|
if(!nav_beacon.z || SSmapping.level_has_any_trait(nav_beacon.z, console.locked_traits))
|
|
break
|
|
if(!nav_beacon.locked)
|
|
L["([L.len]) [nav_beacon.name] located: [nav_beacon.x] [nav_beacon.y] [nav_beacon.z]"] = nav_beacon
|
|
else
|
|
L["([L.len]) [nav_beacon.name] locked"] = null
|
|
|
|
playsound(console, 'sound/machines/terminal_prompt.ogg', 25, FALSE)
|
|
var/selected = tgui_input_list(usr, "Choose location to jump to", "Locations", sort_list(L))
|
|
if(isnull(selected))
|
|
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
|
return
|
|
if(QDELETED(src) || QDELETED(owner) || !isliving(owner))
|
|
return
|
|
playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
|
|
var/turf/T = get_turf(L[selected])
|
|
if(isnull(T))
|
|
return
|
|
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
|
remote_eye.setLoc(T)
|
|
to_chat(owner, span_notice("Jumped to [selected]."))
|
|
owner.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
|
owner.clear_fullscreen("flash", 3)
|