diff --git a/tgui/packages/voidcrew_tgui/interfaces/VoidcrewManagement.js b/tgui/packages/voidcrew_tgui/interfaces/VoidcrewManagement.js
new file mode 100644
index 00000000000..f28e126627d
--- /dev/null
+++ b/tgui/packages/voidcrew_tgui/interfaces/VoidcrewManagement.js
@@ -0,0 +1,197 @@
+import { map } from '../../common/collections';
+import { useBackend, useLocalState } from '../../tgui/backend';
+import {Box, Button, Divider, Section, Table, Tabs } from '../../tgui/components';
+import { Window } from '../../tgui/layouts';
+
+export const VoidcrewManagement = (props, context) => {
+ const [tab, setTab] = useLocalState(context, 'tab', 1);
+ return (
+
+
+
+ setTab(1)}>
+ Ships
+
+ setTab(2)}>
+ Planets
+
+
+ {tab === 1 && }
+ {tab === 2 && }
+
+
+ );
+};
+
+export const VoidcrewManagementShips = (props, context) => {
+ const { act, data } = useBackend(context);
+ const ships = data.ships || [];
+ return (
+
+
+ {ships.map((ship) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {ship.name}
+ {ship.short_name}
+ {ship.status}
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export const VoidcrewManagementPlanets = (props, context) => {
+ const { act, data } = useBackend(context);
+ const planets = data.planets || [];
+ return (
+
+
+ {planets.map((planet) => (
+
+
+
+ act('jump_to', {
+ type: 'planet',
+ ref: planet.ref,
+ })
+ }
+ />
+
+
+
+ act('vv', {
+ ref: planet.ref,
+ })
+ }
+ />
+
+
+
+ act('load_unload', {
+ type: 'planet',
+ ref: planet.ref,
+ })
+ }
+ />
+
+
+
+ act('preserve', {
+ type: 'planet',
+ ref: planet.ref,
+ })
+ }
+ />
+
+ {planet.name}
+ {planet.loaded ? "Loaded" : "Unloaded"}
+ {planet.preserved ? "Preserved" : "Unpreserved"}
+
+ ))}
+
+
+
+
+ act('spawn', {
+ type: 'planet',
+ })
+ }
+ />
+
+
+ );
+};
+
diff --git a/voidcrew/modules/overmap/code/controllers/subsystem/overmap.dm b/voidcrew/modules/overmap/code/controllers/subsystem/overmap.dm
index 840b2b187ba..21d6c4cd115 100644
--- a/voidcrew/modules/overmap/code/controllers/subsystem/overmap.dm
+++ b/voidcrew/modules/overmap/code/controllers/subsystem/overmap.dm
@@ -24,6 +24,8 @@ SUBSYSTEM_DEF(overmap)
var/list/turf/radius_tiles = list()
/// List of all events
var/list/events = list()
+ /// List of all dynamic overmap objects
+ var/list/dynamic_objects = list()
var/size = OVERMAP_SIZE
@@ -235,6 +237,7 @@ SUBSYSTEM_DEF(overmap)
planet_to_spawn.color = planet_info.color
qdel(planet_info)
+/datum/controller/subsystem/overmap/proc/spawn_planet()
// TODO - MULTI-Z VLEVELS
/datum/controller/subsystem/overmap/proc/calculate_turf_above(turf/T)
return
diff --git a/voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm b/voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm
index 3b8085942c9..05105c8f096 100644
--- a/voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm
+++ b/voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm
@@ -41,7 +41,8 @@
/client/proc/initiate_jump,
/client/proc/cancel_jump,
/client/proc/team_panel,
- /client/proc/togglepurchasing
+ /client/proc/togglepurchasing,
+ /client/proc/manage_ships
))
/client/remove_admin_verbs()
@@ -53,6 +54,7 @@
/client/proc/cancel_jump,
/client/proc/team_panel,
/client/proc/togglepurchasing,
+ /client/proc/manage_ships
))
#define RESPAWN_FORCE "Force Respawn"
@@ -83,6 +85,19 @@
var/obj/structure/overmap/ship/spawned = SSshuttle.create_ship(choices[ship_to_spawn])
mob.client?.admin_follow(spawned.shuttle)
+/client/proc/spawn_specific_planet()
+ var/static/list/choices
+ if(!choices)
+ choices = list()
+ for(var/planet in subtypesof(/obj/structure/overmap/planet))
+ var/obj/structure/overmap/planet/V = planet
+ choices[initial(V.name)] = V
+ var/planet_to_spawn = tgui_input_list(usr, "Which planet do you want to spawn?", "Spawn Specific Planet", choices)
+ if(!planet_to_spawn)
+ return
+ var/final_planet = choices[planet_to_spawn]
+ new final_planet(SSovermap.get_unused_overmap_square())
+
/client/proc/initiate_jump()
set name = "Initiate Jump"
set category = "Overmap.Jump"
@@ -141,5 +156,142 @@
world.update_status()
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Ship Purchasing", "[GLOB.ship_buying ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/client/proc/manage_ships()
+ set category = "Overmap.Ships"
+ set desc="Ship Management Console"
+ set name="Ship/Planet Management"
+ if(!check_rights(R_ADMIN))
+ return
+ new /datum/ship_management(usr)//create the datum
+
+/datum/ship_management
+ var/client/holder //client of whoever is using this datum
+
+/datum/ship_management/New(user) //user can either be a client or a mob
+ if (istype(user,/client))
+ var/client/user_client = user
+ holder = user_client //if its a client, assign it to holder
+ else
+ var/mob/user_mob = user
+ holder = user_mob.client //if its a mob, assign the mob's client to holder
+ ui_interact(holder.mob)
+
+/datum/ship_management/ui_state(mob/user)
+ return GLOB.admin_state
+
+/datum/ship_management/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ // Open UI
+ ui = new(user, src, "VoidcrewManagement")
+ ui.open()
+
+/datum/ship_management/ui_data(mob/user)
+ var/list/data = list()
+ data["ships"] = list()
+ for(var/i in SSovermap.simulated_ships)
+ var/obj/structure/overmap/ship/M = i
+ var/list/L = list()
+ L["name"] = M.name
+ L["id"] = M.shuttle.shuttle_id
+ L["ref"] = REF(M)
+ L["short_name"] = M.source_template.short_name
+ L["status"] = M.state
+ L["docked"] = M.docked
+ L["locked"] = M.helm_locked
+ data["ships"] += list(L)
+ data["planets"] = list()
+ for(var/i in SSovermap.dynamic_objects)
+ var/obj/structure/overmap/planet/M = i
+ var/list/L = list()
+ L["name"] = M.name
+ L["ref"] = REF(M)
+ L["loaded"] = FALSE
+ L["preserved"] = M.preserve_level
+ if(M.mapzone)
+ L["loaded"] = TRUE
+ data["planets"] += list(L)
+ return data
+
+/datum/ship_management/ui_act(action, params)
+ . = ..()
+ if(.)
+ return
+ var/mob/user = usr
+ var/obj/docking_port/mobile/mobile_dock
+ var/obj/structure/overmap/planet/planet
+ var/obj/structure/overmap/ship/ship
+ if(params["id"])
+ for(var/i in SSshuttle.mobile_docking_ports)
+ mobile_dock = i
+ if(mobile_dock.shuttle_id == params["id"])
+ break
+ if(params["ref"])
+ var/located = locate(params["ref"])
+ if(istype(located, /obj/structure/overmap/ship))
+ ship = located
+ if(istype(located, /obj/structure/overmap/planet))
+ planet = located
+
+ switch(action)
+ if("jump_to")
+ if(params["type"] == "mobile")
+ user.forceMove(get_turf(mobile_dock))
+ return TRUE
+ else
+ if(planet.reserve_dock)
+ user.forceMove(get_turf(planet.reserve_dock))
+ return TRUE
+ else
+ user.forceMove(planet.loc)
+ return TRUE
+ if("spawn")
+ if(params["type"] == "ship")
+ user.client.spawn_specific_ship()
+ if(params["type"] == "planet")
+ user.client.spawn_specific_planet()
+ if("toggle_ship_purchases")
+ user.client.togglepurchasing()
+ if("recalc")
+ mobile_dock.recalculate_bounds()
+ if("load_unload")
+ if(!planet.mapzone)
+ planet.load_level()
+ else
+ if(!planet.unload_level())
+ if(tgui_alert(usr, "A ship or alive mobs have been detected, do you want to force an unload?","LIFESIGNS DETECTED", list("Yes", "No")) == "Yes")
+ planet.unload_level(TRUE)
+ if("preserve")
+ planet.preserve_level = !planet.preserve_level
+ if("dock")
+ if(!ship.docked)
+ var/available_overmap_planets = list()
+ for(var/obj/structure/overmap/planet/planets as anything in SSovermap.dynamic_objects)
+ available_overmap_planets["[planets.name] X:[planets.x] Y:[planets.y]"] = planets
+ var/obj/structure/overmap/planet/option = available_overmap_planets[tgui_input_list(usr, "Select dock type", "Dock Type Selection", available_overmap_planets)]
+ if(!option)
+ return
+ option.ship_act(usr, ship)
+ else
+ ship.undock()
+ if("vv")
+ if(ship)
+ user.client.debug_variables(ship)
+ if(planet)
+ user.client.debug_variables(planet)
+ if("lock")
+ ship.helm_locked = !ship.helm_locked
+ if("control")
+ if(ship.helms[1])
+ var/obj/machinery/computer/helm/helm_console = ship.helms[1]
+ helm_console.ui_interact(usr)
+
+
+
+
+
+
+
+
diff --git a/voidcrew/modules/overmap/code/modules/overmap/dynamic_object_defines.dm b/voidcrew/modules/overmap/code/modules/overmap/dynamic_object_defines.dm
index d5218f02b97..acd2630c6df 100644
--- a/voidcrew/modules/overmap/code/modules/overmap/dynamic_object_defines.dm
+++ b/voidcrew/modules/overmap/code/modules/overmap/dynamic_object_defines.dm
@@ -27,6 +27,7 @@
/obj/structure/overmap/planet/Initialize(mapload)
. = ..()
+ SSovermap.dynamic_objects += src
if(planet)
var/datum/overmap/planet/planet_info = new planet
name = planet_info.name
@@ -35,31 +36,44 @@
color = planet_info.color
qdel(planet_info)
+/obj/structure/overmap/planet/Destroy()
+ . = ..()
+ SSovermap.dynamic_objects -= src
+
/obj/structure/overmap/planet/lava
+ name = "strange lava planet"
planet = /datum/overmap/planet/lava
/obj/structure/overmap/planet/ice
+ name = "strange ice planet"
planet = /datum/overmap/planet/ice
/obj/structure/overmap/planet/beach
+ name = "strange beach planet"
planet = /datum/overmap/planet/beach
/obj/structure/overmap/planet/jungle
+ name = "strange jungle planet"
planet = /datum/overmap/planet/jungle
/obj/structure/overmap/planet/reebe
+ name = "???"
planet = /datum/overmap/planet/reebe
/obj/structure/overmap/planet/asteroid
+ name = "large asteroid"
planet = /datum/overmap/planet/asteroid
/obj/structure/overmap/planet/energy_signal
+ name = "weak energy signal"
planet = /datum/overmap/planet/space
/obj/structure/overmap/planet/wasteland
+ name = "strange apocalyptic planet"
planet = /datum/overmap/planet/wasteland
/obj/structure/overmap/planet/empty
+ name = "Empty Space"
planet = /datum/overmap/planet/empty
/obj/structure/overmap/planet/empty/unload_level()
diff --git a/voidcrew/modules/overmap/code/modules/overmap/planet.dm b/voidcrew/modules/overmap/code/modules/overmap/planet.dm
index 9199d7edcc2..cd715a1892a 100644
--- a/voidcrew/modules/overmap/code/modules/overmap/planet.dm
+++ b/voidcrew/modules/overmap/code/modules/overmap/planet.dm
@@ -141,15 +141,15 @@
/**
* Unloads the reserve, deletes the linked docking port, and moves to a random location if there's no client-having, alive mobs.
*/
-/obj/structure/overmap/planet/proc/unload_level()
- if(preserve_level || concerned || !mapzone)
- return
+/obj/structure/overmap/planet/proc/unload_level(force)
+ if((preserve_level || concerned || !mapzone) && !force)
+ return FALSE
- if(first_dock_taken || second_dock_taken)
- return
+ if((first_dock_taken || second_dock_taken) && !force)
+ return FALSE
- if(length(mapzone.get_mind_mobs()))
- return //Dont fuck over stranded people? tbh this shouldn't be called on this condition, instead of bandaiding it inside
+ if(length(mapzone.get_mind_mobs()) && !force)
+ return FALSE //Dont fuck over stranded people? tbh this shouldn't be called on this condition, instead of bandaiding it inside
concerned = TRUE //Prevent someone to act with this while it reloads
@@ -164,6 +164,7 @@
*/
forceMove(SSovermap.get_unused_overmap_square())
concerned = FALSE //Now it can be raided again
+ return TRUE
/obj/structure/overmap/planet/proc/remove_mapzone()
diff --git a/voidcrew/modules/overmap/code/modules/overmap/ship.dm b/voidcrew/modules/overmap/code/modules/overmap/ship.dm
index 2edd89544f1..a409c52e7eb 100644
--- a/voidcrew/modules/overmap/code/modules/overmap/ship.dm
+++ b/voidcrew/modules/overmap/code/modules/overmap/ship.dm
@@ -62,6 +62,10 @@
var/list/manifest = list()
///Assoc list of remaining open job slots (job = remaining slots)
var/list/job_slots
+ /// All helms connected to this ship
+ var/list/obj/machinery/computer/helm/helms = list()
+ /// Is helm access for this ship locked
+ var/helm_locked = FALSE
/**
* Movement stuff
diff --git a/voidcrew/modules/shuttle/helm/_helm.dm b/voidcrew/modules/shuttle/helm/_helm.dm
index a85132dd3da..0853f84a801 100644
--- a/voidcrew/modules/shuttle/helm/_helm.dm
+++ b/voidcrew/modules/shuttle/helm/_helm.dm
@@ -49,6 +49,9 @@
current_ship.update_screen()
if(!ui)
+ if(current_ship.helm_locked && !check_rights(R_ADMIN, FALSE))
+ say("ACCESS DENIED: The helm console has been disabled by your system administrator.")
+ return FALSE
current_ship.cam_screen.display_to(user)
user.client.register_map_obj(current_ship.cam_screen)
user.client.register_map_obj(current_ship.cam_background)
@@ -199,6 +202,7 @@
if(!istype(port))
return
current_ship = port.current_ship
+ current_ship.helms |= src
/**
* This proc manually rechecks that the helm computer is connected to a proper ship
@@ -215,6 +219,7 @@
stack_trace("Failed to connect a helm to its ship, this is almost certainly a bug!")
current_ship = port?.current_ship
+ current_ship.helms |= src
return !!current_ship
/**
@@ -224,6 +229,7 @@
var/obj/docking_port/mobile/voidcrew/port = SSshuttle.get_containing_shuttle(src)
if(port?.current_ship)
current_ship = port.current_ship
+ current_ship.helms |= src
return TRUE
/obj/machinery/computer/helm/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)