Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] Adds docking beacons #288

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions code/controllers/subsystems/shuttle.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SUBSYSTEM_DEF(shuttle)
var/list/shuttle_logs = list() //Keeps records of shuttle movement, format is list(datum/shuttle = datum/shuttle_log)
var/list/shuttle_areas = list() //All the areas of all shuttles.
var/list/docking_registry = list() //Docking controller tag -> docking controller program, mostly for init purposes.
var/list/docking_beacons = list() //Magnetic docking beacons, used for free-form landing in secure areas.

var/list/landmarks_awaiting_sector = list() //Stores automatic landmarks that are waiting for a sector to finish loading.
var/list/landmarks_still_needed = list() //Stores landmark_tags that need to be assigned to the sector (landmark_tag = sector) when registered.
Expand Down Expand Up @@ -156,5 +157,13 @@ SUBSYSTEM_DEF(shuttle)
if (ship.type == type)
return ship

/datum/controller/subsystem/shuttle/proc/docking_beacons_by_z(z_levels)
. = list()
if(!islist(z_levels))
z_levels = list(z_levels)
for(var/obj/machinery/docking_beacon/beacon in docking_beacons)
if(beacon.z in z_levels)
. |= beacon

/datum/controller/subsystem/shuttle/stat_entry()
..("Shuttles:[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/obj/item/stock_parts/circuitboard/docking_beacon
name = T_BOARD("magnetic docking beacon")
board_type = "machine"
build_path = /obj/machinery/docking_beacon
origin_tech = "{'magnets':3}"
req_components = list(
/obj/item/stock_parts/capacitor = 1,
/obj/item/stock_parts/micro_laser = 1)
additional_spawn_components = list(
/obj/item/stock_parts/console_screen = 1,
/obj/item/stock_parts/keyboard = 1,
/obj/item/stock_parts/power/apc/buildable = 1
)
Original file line number Diff line number Diff line change
Expand Up @@ -447,4 +447,7 @@
path = /obj/item/stock_parts/circuitboard/relay

/datum/fabricator_recipe/imprinter/circuit/inertial_damper
path = /obj/item/stock_parts/circuitboard/inertial_damper
path = /obj/item/stock_parts/circuitboard/inertial_damper

/datum/fabricator_recipe/imprinter/circuit/docking_beacon
path = /obj/item/stock_parts/circuitboard/docking_beacon
38 changes: 33 additions & 5 deletions code/modules/mob/observer/eye/landing_eye.dm
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
desc = "A visual projection used to assist in the landing of a shuttle."
name_sufix = "Landing Eye"
var/datum/shuttle/autodock/shuttle
var/obj/effect/overmap/visitable/target_sector
var/list/landing_images = list()
var/list/docking_images = list()
var/list/docking_turfs = list() // Turfs where it is okay to land, even if its within a restricted area.

/mob/observer/eye/landing/Initialize(var/mapload, var/shuttle_tag)
/mob/observer/eye/landing/Initialize(var/mapload, var/shuttle_tag, var/obj/effect/overmap/visitable/sector)
shuttle = SSshuttle.shuttles[shuttle_tag]
target_sector = sector
// Generates the overlay of the shuttle on turfs.
var/turf/origin = get_turf(src)
for(var/area/A in shuttle.shuttle_area)
Expand All @@ -21,13 +25,29 @@
I.loc = locate(origin.x + x_off, origin.y + y_off, origin.z)
I.plane = OBSERVER_PLANE
landing_images[I] = list(x_off, y_off)


// Find the docking beacons in the z-level(s) we're landing in.
var/list/docking_beacons = SSshuttle.docking_beacons_by_z(target_sector.map_z)
for(var/obj/machinery/docking_beacon/beacon in docking_beacons)
// If the beacon permits us, we'll generate the images for the area where we can land.
if(beacon.check_permission(shuttle.name, shuttle.docking_codes))
docking_turfs += beacon.get_area()

for(var/turf/T in docking_turfs)
var/image/I = image('icons/effects/alphacolors.dmi', T, "blue")

I.plane = OBSERVER_PLANE
docking_images += I

. = ..(mapload)

/mob/observer/eye/landing/Destroy()
. = ..()
shuttle = null
target_sector = null
landing_images.Cut()
docking_images.Cut()
docking_turfs.Cut()

/mob/observer/eye/landing/setLoc(var/turf/T)
T = get_turf(T)
Expand All @@ -46,7 +66,9 @@

var/turf/origin = get_turf(src)
var/turf/T = locate(origin.x + coords[1], origin.y + coords[2], origin.z)
var/area/A = T?.loc

var/ra = target_sector.restricted_area

img.loc = T

img.icon_state = "green"
Expand All @@ -58,16 +80,22 @@
. = FALSE // Cannot land past the normal world boundaries.
else if(check_collision(origin.loc, list(T))) // Checking for density or multi-area overlap.
. = FALSE
else if(!istype(A, /area/space) && !istype(A, /area/exoplanet)) // Can only land in space or outside.
. = FALSE
else if((T.x > (world.maxx - ra)/2 && T.x < (world.maxx + ra)/2) && (T.y > (world.maxy - ra)/2 && T.y < (world.maxy + ra)/2))
if(!(T in docking_turfs))
. = FALSE // Cannot land within the restricted area *unless* there is a valid docking beacon in the same location.
if(!.)
img.icon_state = "red" // Visual indicator the spot is invalid.

// Checks if the landing location is secure, and therefore the shuttle will move with whatever sector its landed in.
/mob/observer/eye/landing/proc/check_secure_landing()
return ((target_sector.sector_flags & (~OVERMAP_SECTOR_IN_SPACE)) || (get_turf(src) in docking_turfs))

/mob/observer/eye/landing/possess(var/mob/user)
. = ..()
if(owner && owner.client)
owner.client.view = LANDING_VIEW
owner.client.images += landing_images
owner.client.images += docking_images

/mob/observer/eye/landing/release(var/mob/user)
if(owner && owner.client && owner == user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
filename = "docking"
filedesc = "Docking Control"
required_access = access_bridge
nanomodule_path = /datum/nano_module/docking
nanomodule_path = /datum/nano_module/program/docking
program_icon_state = "supply"
program_key_state = "rd_key"
program_menu_icon = "triangle-2-e-w"
extended_desc = "A management tool that lets you see the status of the docking ports."
extended_desc = "A management tool that lets you see the status of the docking ports and beacons."
size = 10
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
available_on_network = 1
Expand All @@ -16,19 +16,21 @@
/datum/computer_file/program/docking/on_startup()
. = ..()
if(NM)
var/datum/nano_module/docking/NMD = NM
var/datum/nano_module/program/docking/NMD = NM
NMD.refresh_docks()

/datum/nano_module/docking
/datum/nano_module/program/docking
name = "Docking Control program"
var/list/docking_controllers = list() //list of tags
var/list/docking_beacons = list() //list of magnetic docking beacon tags

/datum/nano_module/docking/New(var/datum/host, var/topic_manager)
/datum/nano_module/program/docking/New(var/datum/host, var/topic_manager)
..()
refresh_docks()

/datum/nano_module/docking/proc/refresh_docks()
/datum/nano_module/program/docking/proc/refresh_docks()
docking_controllers.Cut()
docking_beacons.Cut()
var/list/zlevels = GetConnectedZlevels(get_host_z())
for(var/obj/machinery/embedded_controller/radio/airlock/docking_port/D in SSmachines.machinery)
if(D.z in zlevels)
Expand All @@ -39,53 +41,88 @@
if(S.shuttle_docking_controller.id_tag == D.program.id_tag)
shuttleside = 1
break
if(shuttleside)
if(shuttleside)
continue
docking_controllers += D.program.id_tag

/datum/nano_module/docking/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, state = GLOB.default_state)

// Add magnetic docking beacons.
var/datum/computer_network/network = get_network()
if(network)
docking_beacons |= network.get_tags_by_type(/obj/machinery/docking_beacon)

/datum/nano_module/program/docking/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, state = GLOB.default_state)
var/list/data = host.initial_data()
var/list/docks = list()
var/list/beacons = list()
var/datum/computer_network/network = get_network()

for(var/docktag in docking_controllers)
var/datum/computer/file/embedded_program/docking/P = SSshuttle.docking_registry[docktag]
if(P)
var/docking_attempt = P.tag_target && !P.dock_state
var/docked = P.tag_target && (P.dock_state == STATE_DOCKED)
docks.Add(list(list(
"tag"=P.id_tag,
"tag" = P.id_tag,
"location" = P.get_name(),
"status" = capitalize(P.get_docking_status()),
"docking_attempt" = docking_attempt,
"docked" = docked,
"codes" = P.docking_codes ? P.docking_codes : "Unset"
)))

for(var/beacontag in docking_beacons)
var/datum/extension/network_device/D = network.get_device_by_tag(beacontag)
var/obj/machinery/docking_beacon/beacon = D.holder
if(istype(beacon))
beacons.Add(list(list(
"size" = "[beacon.docking_width], [beacon.docking_height]",
"name" = beacon.display_name,
"locked" = beacon.locked,
"network_tag" = D.network_tag,
"code_docking" = beacon.docking_by_codes,
)))
else
docking_beacons -= beacontag
data["docks"] = docks
data["docking_beacons"] = beacons
ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "docking.tmpl", name, 600, 450, state = state)
ui.set_auto_update(1)
ui.set_initial_data(data)
ui.open()

/datum/nano_module/docking/Topic(href, href_list, state)
/datum/nano_module/program/docking/Topic(href, href_list, state)
if(..())
return 1
if(istext(href_list["edit_code"]))
var/datum/computer/file/embedded_program/docking/P = SSshuttle.docking_registry[href_list["edit_code"]]
return TOPIC_HANDLED

if(istext(href_list["edit_docking_codes"]))
var/datum/computer/file/embedded_program/docking/P = SSshuttle.docking_registry[href_list["edit_docking_codes"]]
if(P)
var/newcode = input("Input new docking codes", "Docking codes", P.docking_codes) as text|null
if(!CanInteract(usr,state))
return
if (newcode)
if(newcode)
P.docking_codes = uppertext(newcode)
return 1
return TOPIC_HANDLED

if(istext(href_list["dock"]))
var/datum/computer/file/embedded_program/docking/P = SSshuttle.docking_registry[href_list["dock"]]
if(P)
P.receive_user_command("dock")
return 1
return TOPIC_HANDLED

if(istext(href_list["undock"]))
var/datum/computer/file/embedded_program/docking/P = SSshuttle.docking_registry[href_list["undock"]]
if(P)
P.receive_user_command("undock")
return 1
return TOPIC_HANDLED

if(istext(href_list["beacon"]))
var/datum/computer_network/network = get_network()
var/datum/extension/network_device/device = network.get_device_by_tag(href_list["beacon"])
var/obj/machinery/docking_beacon/beacon = device.holder
if(istype(beacon))
var/datum/topic_state/remote/R = new(src, beacon)
beacon.ui_interact(usr, state = R)
return TOPIC_REFRESH
8 changes: 8 additions & 0 deletions code/modules/modular_computers/networking/_network.dm
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,11 @@
results += device.holder
return results

/datum/computer_network/proc/get_tags_by_type(var/type)
var/list/results = list()
for(var/tag in devices_by_tag)
var/datum/extension/network_device/device = devices_by_tag[tag]
if(istype(device.holder, type))
results |= tag
return results

7 changes: 6 additions & 1 deletion code/modules/overmap/sectors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
var/hide_from_reports = FALSE

var/has_distress_beacon
var/free_landing = FALSE //whether or not shuttles can land in arbitrary places within the sector's z-levels.
var/free_landing = TRUE // Whether or not shuttles can land in arbitrary places within the sector's z-levels.
var/restricted_area = 0 // Regardless of if free_landing is set to TRUE, this square area (centered on the z level) will be restricted from free shuttle landing unless permitted by a docking becaon.

var/list/map_z = list()
var/list/consoles

Expand Down Expand Up @@ -135,6 +137,9 @@
testing("Overmap build complete.")
return 1

/obj/effect/overmap/visitable/proc/allow_free_landing(var/datum/shuttle/landing_shuttle)
return free_landing

/obj/effect/overmap/visitable/handle_overmap_pixel_movement()
..()
for(var/obj/machinery/computer/ship/machine in consoles)
Expand Down
8 changes: 4 additions & 4 deletions code/modules/overmap/ships/computers/shuttle.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

var/list/available_sectors = list()
for(var/obj/effect/overmap/visitable/S in range(get_turf(current_sector), shuttle.range))
if(S.free_landing)
if(S.allow_free_landing(shuttle))
available_sectors += S

if(LAZYLEN(available_sectors))
Expand All @@ -84,7 +84,7 @@
return

var/turf/eye_turf = locate(world.maxx/2, world.maxy/2, target_sector.map_z[target_sector.map_z.len]) // Center of the top z-level of the target sector.
if(landing_eye.look(user, list(shuttle_tag), eye_turf)) // Placement of the eye was successful
if(landing_eye.look(user, list(shuttle_tag, target_sector))) // Placement of the eye was successful
landing_eye.extension_eye.forceMove(eye_turf)
return

Expand All @@ -101,13 +101,13 @@
var/turf/lz_turf = eye_extension.get_eye_turf()

var/obj/effect/overmap/visitable/sector = map_sectors["[lz_turf.z]"]
if(!sector.free_landing) // Additional safety check to ensure the sector permits landing.
if(!sector.allow_free_landing()) // Additional safety check to ensure the sector permits landing.
to_chat(user, SPAN_WARNING("Invalid landing zone!"))
return
var/datum/shuttle/autodock/overmap/shuttle = SSshuttle.shuttles[shuttle_tag]

if(landing_eye.check_landing()) // Make sure the landmark is in a valid location.
var/obj/effect/shuttle_landmark/temporary/lz = new(lz_turf)
var/obj/effect/shuttle_landmark/temporary/lz = new(lz_turf, landing_eye.check_secure_landing())
if(lz.is_valid(shuttle)) // Make sure the shuttle fits.
to_chat(user, SPAN_NOTICE("Landing zone set!"))
shuttle.set_destination(lz)
Expand Down
14 changes: 13 additions & 1 deletion code/modules/overmap/ships/landable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,26 @@
if(get_area(object) in areas)
return 1

/obj/effect/overmap/visitable/ship/landable/allow_free_landing(var/datum/shuttle/landing_shuttle)
var/datum/shuttle/autodock/overmap/child_shuttle = SSshuttle.shuttles[shuttle]
if(child_shuttle == landing_shuttle)
return FALSE // Use the main landmark.
if(child_shuttle.current_location != landmark)
return FALSE // Cannot encounter a shuttle while it is landed elsewhere.
. = ..()

/obj/effect/overmap/visitable/ship/landable/Process()
. = ..()
var/datum/shuttle/autodock/overmap/child_shuttle = SSshuttle.shuttles[shuttle]
if(!child_shuttle || !istype(child_shuttle))
return
if(child_shuttle.current_location.flags & SLANDMARK_FLAG_DISCONNECTED) // Keep an eye on the distance between the shuttle and the sector if we aren't fully docked.
if(get_dist(src, map_sectors["[child_shuttle.current_location.z]"]) > min(child_shuttle.range, 1)) // Some leeway so 0 range shuttles are still able to chase.
var/obj/effect/overmap/visitable/ship/landable/encounter = map_sectors["[child_shuttle.current_location.z]"]
if((get_dist(src, encounter) > min(child_shuttle.range, 1))) // Some leeway so 0 range shuttles are still able to chase.
child_shuttle.attempt_force_move(landmark)
if(istype(encounter))
if(encounter.status != SHIP_STATUS_OVERMAP) // Check if the encountered sector has moved out of space and landed elsewhere.
child_shuttle.attempt_force_move(landmark)

// We autobuild our z levels.
/obj/effect/overmap/visitable/ship/landable/find_z_levels()
Expand Down
Loading