diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index ca76b715c4..f1c901ab9a 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -232,3 +232,24 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, if(round(num) != num) return round(num--) else return num + +//proc/get_overlap() +// Returns a list where [1] is all x values and [2] is all y values that overlap between the given pair of rectangles +/proc/get_overlap(x1, y1, x2, y2, x3, y3, x4, y4) + var/list/region_x1 = list() + var/list/region_y1 = list() + var/list/region_x2 = list() + var/list/region_y2 = list() + + // These loops create loops filled with x/y values that the boundaries inhabit + // ex: list(5, 6, 7, 8, 9) + for(var/i in min(x1, x2) to max(x1, x2)) + region_x1["[i]"] = TRUE + for(var/i in min(y1, y2) to max(y1, y2)) + region_y1["[i]"] = TRUE + for(var/i in min(x3, x4) to max(x3, x4)) + region_x2["[i]"] = TRUE + for(var/i in min(y3, y4) to max(y3, y4)) + region_y2["[i]"] = TRUE + + return list(region_x1 & region_x2, region_y1 & region_y2) \ No newline at end of file diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 00730fc1aa..75111a2017 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -622,6 +622,30 @@ SUBSYSTEM_DEF(shuttle) return TRUE /datum/controller/subsystem/shuttle/proc/get_containing_shuttle(atom/A) - for(var/obj/docking_port/mobile/M in mobile) - if(M.is_in_shuttle_bounds(A)) - return M + var/list/mobile_cache = mobile + for(var/i in 1 to mobile_cache.len) + var/obj/docking_port/port = mobile_cache[i] + if(port.is_in_shuttle_bounds(A)) + return port + +/datum/controller/subsystem/shuttle/proc/get_containing_dock(atom/A) + . = list() + var/list/stationary_cache = stationary + for(var/i in 1 to stationary_cache.len) + var/obj/docking_port/port = stationary_cache[i] + if(port.is_in_shuttle_bounds(A)) + . += port + +/datum/controller/subsystem/shuttle/proc/get_dock_overlap(x0, y0, x1, y1, z) + . = list() + var/list/stationary_cache = stationary + for(var/i in 1 to stationary_cache.len) + var/obj/docking_port/port = stationary_cache[i] + if(!port || port.z != z) + continue + var/list/bounds = port.return_coords() + var/list/overlap = get_overlap(x0, y0, x1, y1, bounds[1], bounds[2], bounds[3], bounds[4]) + var/list/xs = overlap[1] + var/list/ys = overlap[2] + if(xs.len && ys.len) + .[port] = overlap \ No newline at end of file diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index 7f99829843..27ef7eec33 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -8,7 +8,6 @@ var/shuttlePortId = "" var/shuttlePortName = "" var/list/jumpto_ports = list() //hashset of ports to jump to and ignore for collision purposes - var/list/blacklisted_turfs //turfs we cannot go on, by default, any turf covered by a docking port that we did not place and cannot jump to 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/view_range = 7 @@ -56,7 +55,6 @@ I.pixel_x = x_off * 32 I.pixel_y = y_off * 32 the_eye.placement_images[I] = list(x_off, y_off) - generateBlacklistedTurfs() /obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user) ..() @@ -110,54 +108,61 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot() var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj + var/list/image_cache = the_eye.placement_images the_eye.dir = turn(the_eye.dir, -90) - for(var/V in the_eye.placement_images) - var/image/I = V - var/list/coords = the_eye.placement_images[V] + 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 - - I.pixel_x = coords[1] * 32 - I.pixel_y = coords[2] * 32 + pic.pixel_x = coords[1] * 32 + pic.pixel_y = coords[2] * 32 var/Tmp = x_offset x_offset = y_offset y_offset = -Tmp checkLandingSpot() -/obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingTurf(turf/T) - return T && (shuttle_port.shuttle_areas[T.loc] || (!blacklisted_turfs || !blacklisted_turfs[T]) && (!space_turfs_only || isspaceturf(T)) ) && (T.x > 1 && T.y > 1 && T.x < world.maxx && T.y < world.maxy) - -/obj/machinery/computer/camera_advanced/shuttle_docker/proc/generateBlacklistedTurfs() - blacklisted_turfs = list() - for(var/V in SSshuttle.stationary) - if(!V) - continue - var/obj/docking_port/stationary/S = V - if(z_lock.len && !(S.z in z_lock)) - continue - if((S.id == shuttlePortId) || jumpto_ports[S.id]) - continue - for(var/T in S.return_turfs()) - blacklisted_turfs[T] = TRUE - /obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot() var/mob/camera/aiEye/remote/shuttle_docker/the_eye = eyeobj var/turf/eyeturf = get_turf(the_eye) if(!eyeturf) return - var/landing_spot_clear = TRUE - for(var/V in the_eye.placement_images) - var/image/I = V + 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] I.loc = eyeturf - var/list/coords = the_eye.placement_images[V] + var/list/coords = image_cache[I] var/turf/T = locate(eyeturf.x + coords[1], eyeturf.y + coords[2], eyeturf.z) - if(checkLandingTurf(T)) + if(checkLandingTurf(T, overlappers)) I.icon_state = "green" else I.icon_state = "red" - landing_spot_clear = FALSE - return landing_spot_clear + . = FALSE + +/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 + // If it's one of our shuttle areas assume it's ok to be there + if(shuttle_port.shuttle_areas[T.loc]) + return TRUE + // 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/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 /mob/camera/aiEye/remote/shuttle_docker visible_icon = FALSE diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 642037bdf1..2f0fb711bd 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -182,6 +182,25 @@ if(P) return P.id +/obj/docking_port/proc/is_in_shuttle_bounds(atom/A) + var/turf/T = get_turf(A) + if(T.z != z) + return FALSE + var/list/bounds = return_coords() + var/x0 = bounds[1] + var/y0 = bounds[2] + var/x1 = bounds[3] + var/y1 = bounds[4] + if(x0 <= x1 && !IsInRange(T.x, x0, x1)) + return FALSE + else if(!IsInRange(T.x, x1, x0)) + return FALSE + if(y0 <= y1 && !IsInRange(T.y, y0, y1)) + return FALSE + else if(!IsInRange(T.y, y1, y0)) + return FALSE + return TRUE + /obj/docking_port/stationary name = "dock" @@ -855,17 +874,6 @@ for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice playsound(E, s, 100, FALSE, max(width, height) - world.view) -/obj/docking_port/mobile/proc/is_in_shuttle_bounds(atom/A) - var/turf/T = get_turf(A) - if(T.z != z) - return FALSE - var/list/bounds= return_coords() - var/turf/T0 = locate(bounds[1],bounds[2],z) - var/turf/T1 = locate(bounds[3],bounds[4],z) - if(T in block(T0,T1)) - return TRUE - return FALSE - // Losing all initial engines should get you 2 // Adding another set of engines at 0.5 time /obj/docking_port/mobile/proc/alter_engines(mod)