mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-28 18:41:37 +00:00
* Shuttle tweak and fix (#54395) Fix lavaland podding Make lavaland pod destinations hidden Removed unused variables from connect_to_shuttle() proc Shuttle consoles remove old custom port id from possible destinations when connects to new shuttle Custom ports keeps clear from unwanted numbers. Now shuttle machinery property connects to additional loaded shuttles. Add some docking_port register logging and safety. * Shuttle tweak and fix Co-authored-by: Dennok <Deneles@yandex.ru>
391 lines
14 KiB
Plaintext
391 lines
14 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
|
|
var/datum/action/innate/shuttledocker_rotate/rotate_action = new
|
|
var/datum/action/innate/shuttledocker_place/place_action = new
|
|
var/shuttleId = ""
|
|
var/shuttlePortId = ""
|
|
var/shuttlePortName = "custom location"
|
|
var/list/jumpto_ports = list() //hashset of ports to jump to and ignore for collision purposes
|
|
var/obj/docking_port/stationary/my_port //the custom docking port placed by this console
|
|
var/obj/docking_port/mobile/shuttle_port //the mobile docking port of the connected shuttle
|
|
var/list/locked_traits = list(ZTRAIT_RESERVED, ZTRAIT_CENTCOM, ZTRAIT_AWAY) //traits forbided for custom docking
|
|
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)
|
|
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
|
|
|
|
if(!mapload)
|
|
connect_to_shuttle(SSshuttle.get_containing_shuttle(src))
|
|
|
|
for(var/port_id in SSshuttle.stationary)
|
|
var/obj/docking_port/stationary/S = SSshuttle.stationary[port_id]
|
|
if(S.id == shuttleId)
|
|
jumpto_ports[S.id] = TRUE
|
|
|
|
for(var/V in SSshuttle.stationary)
|
|
if(!V)
|
|
continue
|
|
var/obj/docking_port/stationary/S = V
|
|
if(jumpto_ports[S.id])
|
|
z_lock |= S.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.id = null
|
|
my_port.name = "Old [my_port.name]"
|
|
my_port = null
|
|
else
|
|
QDEL_NULL(my_port)
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/attack_hand(mob/user)
|
|
if(jammed)
|
|
to_chat(user, "<span class='warning'>The Syndicate is jamming the console!</span>")
|
|
return
|
|
if(!shuttle_port && !SSshuttle.getShuttle(shuttleId))
|
|
to_chat(user,"<span class='warning'>Warning: Shuttle connection severed!</span>")
|
|
return
|
|
return ..()
|
|
|
|
/obj/machinery/computer/camera_advanced/shuttle_docker/GrantActions(mob/living/user)
|
|
if(jumpto_ports.len)
|
|
jump_action = new /datum/action/innate/camera_jump/shuttle_docker
|
|
..()
|
|
|
|
if(rotate_action)
|
|
rotate_action.target = user
|
|
rotate_action.Grant(user)
|
|
actions += rotate_action
|
|
|
|
if(place_action)
|
|
place_action.target = user
|
|
place_action.Grant(user)
|
|
actions += place_action
|
|
|
|
/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
|
|
I.plane = 0
|
|
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 class='warning'>Targeting transit location, please wait [DisplayTimeText(designate_time)]...</span>")
|
|
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, "<span class='warning'>Operation aborted.</span>")
|
|
return
|
|
landing_clear = checkLandingSpot()
|
|
|
|
if(landing_clear != SHUTTLE_DOCKER_LANDING_CLEAR)
|
|
switch(landing_clear)
|
|
if(SHUTTLE_DOCKER_BLOCKED)
|
|
to_chat(current_user, "<span class='warning'>Invalid transit location.</span>")
|
|
if(SHUTTLE_DOCKER_BLOCKED_BY_HIDDEN_PORT)
|
|
to_chat(current_user, "<span class='warning'>Unknown object detected in landing zone. Please designate another location.</span>")
|
|
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.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.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/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.layer = ABOVE_OPEN_TURF_LAYER
|
|
newI.plane = 0
|
|
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 class='notice'>Transit location designated.</span>")
|
|
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(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
|
if(port)
|
|
shuttleId = port.id
|
|
shuttlePortId = "[port.id]_custom"
|
|
if(dock)
|
|
jumpto_ports[dock.id] = TRUE
|
|
|
|
/mob/camera/ai_eye/remote/shuttle_docker
|
|
visible_icon = FALSE
|
|
use_static = USE_STATIC_NONE
|
|
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(T)
|
|
..()
|
|
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.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"
|
|
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
|
|
button_icon_state = "mech_cycle_equip_off"
|
|
|
|
/datum/action/innate/shuttledocker_rotate/Activate()
|
|
if(QDELETED(target) || !isliving(target))
|
|
return
|
|
var/mob/living/C = target
|
|
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
|
origin.rotateLandingSpot()
|
|
|
|
/datum/action/innate/shuttledocker_place
|
|
name = "Place"
|
|
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
|
|
button_icon_state = "mech_zoom_off"
|
|
|
|
/datum/action/innate/shuttledocker_place/Activate()
|
|
if(QDELETED(target) || !isliving(target))
|
|
return
|
|
var/mob/living/C = target
|
|
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
|
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
|
origin.placeLandingSpot(target)
|
|
|
|
/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(target) || !isliving(target))
|
|
return
|
|
var/mob/living/C = target
|
|
var/mob/camera/ai_eye/remote/remote_eye = C.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)
|
|
if(!V)
|
|
stack_trace("SSshuttle.stationary 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.jumpto_ports[S.id])
|
|
L["([L.len])[S.name]"] = S
|
|
|
|
for(var/V in SSshuttle.beacons)
|
|
if(!V)
|
|
stack_trace("SSshuttle.beacons 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 = input("Choose location to jump to", "Locations", null) as null|anything in sortList(L)
|
|
if(QDELETED(src) || QDELETED(target) || !isliving(target))
|
|
return
|
|
playsound(src, "terminal_type", 25, FALSE)
|
|
if(selected)
|
|
var/turf/T = get_turf(L[selected])
|
|
if(T)
|
|
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
|
remote_eye.setLoc(T)
|
|
to_chat(target, "<span class='notice'>Jumped to [selected].</span>")
|
|
C.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
|
|
C.clear_fullscreen("flash", 3)
|
|
else
|
|
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|