From 45e9ab6513bdef25ad8d445e5ea7dd7d442ffdf1 Mon Sep 17 00:00:00 2001 From: Zandario Date: Wed, 19 Aug 2020 19:02:19 -0500 Subject: [PATCH] Checkpoint --- code/__DEFINES/_lists.dm | 2 +- .../subsystems/emergency_shuttle.dm | 4 + code/controllers/subsystems/shuttles.dm | 38 +- code/controllers/subsystems/supply.dm | 6 +- code/controllers/subsystems/ticker.dm | 2 +- code/datums/observation/shuttle_added.dm | 2 +- code/game/atoms_movable.dm | 2 +- .../airlock_controllers.dm | 2 +- .../airlock_docking_controller_multi.dm | 32 +- .../embedded_controller/airlock_program.dm | 83 ++-- .../embedded_controller/docking_program.dm | 115 ++--- .../embedded_controller_base.dm | 51 ++- .../embedded_program_base.dm | 9 +- .../simple_docking_controller.dm | 48 +- code/game/machinery/status_display.dm | 32 +- code/game/machinery/supply_display.dm | 2 +- code/game/objects/items/devices/PDA/cart.dm | 22 +- .../items/devices/communicator/helper.dm | 34 +- code/game/turfs/simulated/floor_types.dm | 64 +-- code/game/turfs/space/space.dm | 9 +- code/game/turfs/turf.dm | 44 +- .../secrets/admin_secrets/launch_shuttle.dm | 4 +- .../admin_secrets/launch_shuttle_forced.dm | 4 +- .../secrets/admin_secrets/move_shuttle.dm | 10 +- code/modules/lighting/lighting_turf.dm | 26 +- code/modules/maps/tg/map_template.dm | 70 +-- code/modules/media/mediamanager.dm | 2 +- code/modules/multiz/turf.dm | 31 +- code/modules/overmap/_defines.dm | 65 ++- code/modules/overmap/helpers.dm | 5 + code/modules/overmap/overmap_object.dm | 38 ++ code/modules/overmap/sectors.dm | 223 +++++----- code/modules/overmap/spacetravel.dm | 114 +++++ code/modules/rogueminer_vr/zone_console.dm | 46 +- code/modules/rogueminer_vr/zonemaster.dm | 118 ++--- code/modules/shuttles/_defines.dm | 26 +- code/modules/shuttles/crashes.dm | 48 +- code/modules/shuttles/escape_pods.dm | 103 ++--- code/modules/shuttles/landmarks.dm | 187 ++++++++ code/modules/shuttles/shuttle.dm | 413 ++++++++++++------ code/modules/shuttles/shuttle_autodock.dm | 220 ++++++++++ code/modules/shuttles/shuttle_console.dm | 108 +++-- .../modules/shuttles/shuttle_console_multi.dm | 34 ++ code/modules/shuttles/shuttle_emergency.dm | 87 ++-- code/modules/shuttles/shuttle_ferry.dm | 196 ++------- code/modules/shuttles/shuttle_specops.dm | 130 +++--- code/modules/shuttles/shuttle_supply.dm | 71 ++- code/modules/shuttles/shuttles_multi.dm | 295 ++----------- code/modules/shuttles/shuttles_web.dm | 184 ++++---- code/modules/shuttles/web_datums.dm | 44 +- code/unit_tests/zas_tests.dm | 10 +- icons/effects/numbers.dmi | Bin 0 -> 296 bytes icons/obj/overmap.dmi | Bin 0 -> 10656 bytes maps/~map_system/maps.dm | 100 ++--- .../shuttle_control_console_multi.tmpl | 84 ++++ sound/effects/shuttles/shuttle_landing.ogg | Bin 0 -> 115520 bytes sound/effects/shuttles/shuttle_takeoff.ogg | Bin 0 -> 116582 bytes vorestation.dme | 9 + 58 files changed, 2184 insertions(+), 1524 deletions(-) create mode 100644 code/modules/overmap/helpers.dm create mode 100644 code/modules/overmap/overmap_object.dm create mode 100644 code/modules/overmap/spacetravel.dm create mode 100644 code/modules/shuttles/landmarks.dm create mode 100644 code/modules/shuttles/shuttle_autodock.dm create mode 100644 code/modules/shuttles/shuttle_console_multi.dm create mode 100644 icons/effects/numbers.dmi create mode 100644 icons/obj/overmap.dmi create mode 100644 nano/templates/shuttle_control_console_multi.tmpl create mode 100644 sound/effects/shuttles/shuttle_landing.ogg create mode 100644 sound/effects/shuttles/shuttle_takeoff.ogg diff --git a/code/__DEFINES/_lists.dm b/code/__DEFINES/_lists.dm index 6d38e6193b4..065376803ba 100644 --- a/code/__DEFINES/_lists.dm +++ b/code/__DEFINES/_lists.dm @@ -12,7 +12,7 @@ // Adds I to L, initalizing I if necessary #define LAZYADD(L, I) if(!L) { L = list(); } L += I; // Adds I to L, initalizing L if necessary, if I is not already in L -#define LAZYDISTINCTADDSTINCTADD(L, I) if(!L) { L = list(); } L |= I; +#define LAZYDISTINCTADD(L, I) if(!L) { L = list(); } L |= I; #define LAZYFIND(L, V) (L ? L.Find(V) : 0) // Reads I from L safely - Works with both associative and traditional lists. #define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null) diff --git a/code/controllers/subsystems/emergency_shuttle.dm b/code/controllers/subsystems/emergency_shuttle.dm index 86f7992fe29..463279427cd 100644 --- a/code/controllers/subsystems/emergency_shuttle.dm +++ b/code/controllers/subsystems/emergency_shuttle.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(emergencyshuttle) wait = 20 var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm TODO - is it really? + var/list/escape_pods var/launch_time //the time at which the shuttle will be launched var/auto_recall = 0 //if set, the shuttle will be auto-recalled @@ -18,6 +19,9 @@ SUBSYSTEM_DEF(emergencyshuttle) var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg')) var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg')) +/datum/emergency_shuttle_controller/New() + escape_pods = list() + ..() /datum/controller/subsystem/emergencyshuttle/fire() if (wait_for_launch) if (evac && auto_recall && world.time >= auto_recall_time) diff --git a/code/controllers/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm index c3dfb0b8af3..49533cf8e63 100644 --- a/code/controllers/subsystems/shuttles.dm +++ b/code/controllers/subsystems/shuttles.dm @@ -1,5 +1,5 @@ // -// SSshuttles subsystem - Handles initialization and processing of shuttles. +// SSshuttle subsystem - Handles initialization and processing of shuttles. // // Also handles initialization and processing of overmap sectors. // For... some reason... // @@ -33,17 +33,14 @@ SUBSYSTEM_DEF(shuttle) var/tmp/list/current_run // Shuttles remaining to process this fire() tick -/datum/controller/subsystem/shuttles/PreInit() - global.shuttle_controller = src // TODO - Remove this! Change everything to point at SSshuttles intead - /datum/controller/subsystem/shuttle/Initialize(timeofday) last_landmark_registration_time = world.time // Find all declared shuttle datums and initailize them. (Okay, queue them for initialization a few lines further down) - for(var/shuttle_type in subtypesof(/datum/shuttle)) // This accounts for most shuttles, though away maps can queue up more. + for(var/shuttle_type in subtypesof(/datum/shuttle)) // This accounts for most shuttles, though away maps can queue up more. var/datum/shuttle/shuttle = shuttle_type if(initial(shuttle.category) == shuttle_type) - continue // Its an "abstract class" datum, not for a real shuttle. - if(!initial(shuttle.defer_initialisation)) // Skip if it asks not to be initialized at startup. + continue // Its an "abstract class" datum, not for a real shuttle. + if(!initial(shuttle.defer_initialisation)) // Skip if it asks not to be initialized at startup. LAZYDISTINCTADD(shuttles_to_initialize, shuttle_type) block_init_queue = FALSE process_init_queues() @@ -58,25 +55,24 @@ SUBSYSTEM_DEF(shuttle) var/datum/shuttle/S = working_shuttles[working_shuttles.len] working_shuttles.len-- if(!istype(S) || QDELETED(S)) - error("Bad entry in SSshuttles.process_shuttles - [log_info_line(S)] ") + log_debug("Bad entry in SSshuttle.process_shuttles - [log_info_line(S)] ") process_shuttles -= S continue // NOTE - In old system, /datum/shuttle/ferry was processed only if (F.process_state || F.always_process) if(S.process_state && (S.process(wait, times_fired, src) == PROCESS_KILL)) - else process_shuttles -= S if(MC_TICK_CHECK) return -/datum/controller/subsystem/shuttles/proc/process_init_queues() +/datum/controller/subsystem/shuttle/proc/process_init_queues() if(block_init_queue) return initialize_shuttles() initialize_sectors() // Initializes all shuttles in shuttles_to_initialize -/datum/controller/subsystem/shuttles/proc/initialize_shuttles() +/datum/controller/subsystem/shuttle/proc/initialize_shuttles() var/list/shuttles_made = list() for(var/shuttle_type in shuttles_to_initialize) var/shuttle = initialize_shuttle(shuttle_type) @@ -85,12 +81,12 @@ SUBSYSTEM_DEF(shuttle) hook_up_motherships(shuttles_made) shuttles_to_initialize = null -/datum/controller/subsystem/shuttles/proc/initialize_sectors() +/datum/controller/subsystem/shuttle/proc/initialize_sectors() for(var/sector in sectors_to_initialize) initialize_sector(sector) sectors_to_initialize = null -/datum/controller/subsystem/shuttles/proc/register_landmark(shuttle_landmark_tag, obj/effect/shuttle_landmark/shuttle_landmark) +/datum/controller/subsystem/shuttle/proc/register_landmark(shuttle_landmark_tag, obj/effect/shuttle_landmark/shuttle_landmark) if (registered_shuttle_landmarks[shuttle_landmark_tag]) CRASH("Attempted to register shuttle landmark with tag [shuttle_landmark_tag], but it is already registered!") if (istype(shuttle_landmark)) @@ -106,12 +102,12 @@ SUBSYSTEM_DEF(shuttle) // O = map_sectors["[shuttle_landmark.z]"] // O ? O.add_landmark(shuttle_landmark, shuttle_landmark.shuttle_restricted) : (landmarks_awaiting_sector += shuttle_landmark) -/datum/controller/subsystem/shuttles/proc/get_landmark(var/shuttle_landmark_tag) +/datum/controller/subsystem/shuttle/proc/get_landmark(var/shuttle_landmark_tag) return registered_shuttle_landmarks[shuttle_landmark_tag] // Checks if the given sector's landmarks have initialized; if so, registers them with the sector, if not, marks them for assignment after they come in. // Also adds automatic landmarks that were waiting on their sector to spawn. -/datum/controller/subsystem/shuttles/proc/initialize_sector(obj/effect/overmap/visitable/given_sector) +/datum/controller/subsystem/shuttle/proc/initialize_sector(obj/effect/overmap/visitable/given_sector) return // TODO - Uncomment once overmap sectors are ported // given_sector.populate_sector_objects() // This is a late init operation that sets up the sector's map_z and does non-overmap-related init tasks. @@ -133,7 +129,7 @@ SUBSYSTEM_DEF(shuttle) // TODO - Uncomment once overmap sectors are ported //// Attempts to add a landmark instance with a sector (returns false if landmark isn't registered yet) -///datum/controller/subsystem/shuttles/proc/try_add_landmark_tag(landmark_tag, obj/effect/overmap/visitable/given_sector) +///datum/controller/subsystem/shuttle/proc/try_add_landmark_tag(landmark_tag, obj/effect/overmap/visitable/given_sector) // var/obj/effect/shuttle_landmark/landmark = get_landmark(landmark_tag) // if(!landmark) // return @@ -146,7 +142,7 @@ SUBSYSTEM_DEF(shuttle) // given_sector.add_landmark(landmark, shuttle_name) // . = 1 -/datum/controller/subsystem/shuttles/proc/initialize_shuttle(var/shuttle_type) +/datum/controller/subsystem/shuttle/proc/initialize_shuttle(var/shuttle_type) var/datum/shuttle/shuttle = shuttle_type if(initial(shuttle.category) != shuttle_type) // Skip if its an "abstract class" datum shuttle = new shuttle() @@ -157,7 +153,7 @@ SUBSYSTEM_DEF(shuttle) // and shuttles fetch refs in New(). Shuttles also dock() themselves in new if they want. // TODO - Leshana to hook up more of this when overmap is ported. -/datum/controller/subsystem/shuttles/proc/hook_up_motherships(shuttles_list) +/datum/controller/subsystem/shuttle/proc/hook_up_motherships(shuttles_list) for(var/datum/shuttle/S in shuttles_list) if(S.mothershuttle && !S.motherdock) var/datum/shuttle/mothership = shuttles[S.mothershuttle] @@ -165,10 +161,10 @@ SUBSYSTEM_DEF(shuttle) S.motherdock = S.current_location.landmark_tag mothership.shuttle_area |= S.shuttle_area else - error("Shuttle [S] was unable to find mothership [mothership]!") + log_debug("Shuttle [S] was unable to find mothership [mothership]!") // Admin command to halt/resume overmap -// /datum/controller/subsystem/shuttles/proc/toggle_overmap(new_setting) +// /datum/controller/subsystem/shuttle/proc/toggle_overmap(new_setting) // if(overmap_halted == new_setting) // return // overmap_halted = !overmap_halted @@ -176,5 +172,5 @@ SUBSYSTEM_DEF(shuttle) // var/obj/effect/overmap/visitable/ship/ship_effect = ship // overmap_halted ? ship_effect.halt() : ship_effect.unhalt() -/datum/controller/subsystem/shuttles/stat_entry() +/datum/controller/subsystem/shuttle/stat_entry() ..("Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]") diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm index 7bb0f502f82..039c0a6b8e0 100644 --- a/code/controllers/subsystems/supply.dm +++ b/code/controllers/subsystems/supply.dm @@ -111,8 +111,8 @@ SUBSYSTEM_DEF(supply) ) // Sell manifests - if(find_slip && istype(A,/obj/item/weapon/paper/manifest)) - var/obj/item/weapon/paper/manifest/slip = A + if(find_slip && istype(A,/obj/item/paper/manifest)) + var/obj/item/paper/manifest/slip = A if(!slip.is_copy && slip.stamped && slip.stamped.len) // Yes, the clown stamp will work. clown is the highest authority on the station, it makes sense, trust me guys points += points_per_slip EC.contents[EC.contents.len]["value"] = points_per_slip @@ -128,7 +128,7 @@ SUBSYSTEM_DEF(supply) EC.value += EC.contents[EC.contents.len]["value"] // Sell spacebucks - if(istype(A, /obj/item/weapon/spacecash)) + if(istype(A, /obj/item/spacecash)) var/obj/item/weapon/spacecash/cashmoney = A EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money EC.contents[EC.contents.len]["quantity"] = cashmoney.worth diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 8d299f09e8a..1e40b5e9c75 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -226,7 +226,7 @@ SUBSYSTEM_DEF(ticker) callHook("roundstart") - // TODO - Leshana - Dear God Fix This. Fix all of this. Not just this line, this entire proc. This entire file! + // TODO Dear God Fix This. Fix all of this. Not just this line, this entire proc. This entire file! spawn(0)//Forking here so we dont have to wait for this to finish mode.post_setup() //Cleanup some stuff diff --git a/code/datums/observation/shuttle_added.dm b/code/datums/observation/shuttle_added.dm index 8b82ebd8ff5..8db95c4041e 100644 --- a/code/datums/observation/shuttle_added.dm +++ b/code/datums/observation/shuttle_added.dm @@ -16,7 +16,7 @@ GLOBAL_DATUM_INIT(shuttle_added, /decl/observ/shuttle_added, new) * Shuttle Added Handling * *****************************/ -/datum/controller/subsystem/shuttles/initialize_shuttle() +/datum/controller/subsystem/shuttle/initialize_shuttle() . = ..() if(.) GLOB.shuttle_added.raise_event(.) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index c9af6d86b25..cce1795839c 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -226,7 +226,7 @@ if(z in GLOB.using_map.sealed_levels) return - if(using_map.use_overmap) + if(GLOB.using_map.use_overmap) overmap_spacetravel(get_turf(src), src) return diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index 6e83b86b9e7..d207776fc83 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -16,7 +16,7 @@ var/cycle_to_external_air = 0 /obj/machinery/embedded_controller/radio/airlock/Destroy() - // TODO - Leshana - Implement dummy terminals + // TODO Implement dummy terminals //for(var/thing in dummy_terminals) // var/obj/machinery/dummy_airlock_controller/dummy = thing // dummy.master_controller = null diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm index 734d0ba6346..09d5ed22486 100644 --- a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm +++ b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm @@ -1,18 +1,15 @@ -//a controller for a docking port with multiple independent airlocks -//this is the master controller, that things will try to dock with. +// A controller for a docking port with multiple independent airlocks +// This is the master controller, that things will try to dock with. /obj/machinery/embedded_controller/radio/docking_port_multi name = "docking port controller" + program = /datum/computer/file/embedded_program/docking/multi var/child_tags_txt var/child_names_txt var/list/child_names = list() - var/datum/computer/file/embedded_program/docking/multi/docking_program - /obj/machinery/embedded_controller/radio/docking_port_multi/Initialize() . = ..() - docking_program = new/datum/computer/file/embedded_program/docking/multi(src) - program = docking_program var/list/names = splittext(child_names_txt, ";") var/list/tags = splittext(child_tags_txt, ";") @@ -24,6 +21,7 @@ /obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] + var/datum/computer/file/embedded_program/docking/multi/docking_program = program // Cast to proper type var/list/airlocks[child_names.len] var/i = 1 @@ -44,24 +42,21 @@ ui.set_auto_update(1) /obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list) - return + return 1 // Apparently we swallow all input (this is corrected legacy code) -//a docking port based on an airlock +// A docking port based on an airlock +// This is the actual controller that will be commanded by the master defined above /obj/machinery/embedded_controller/radio/airlock/docking_port_multi name = "docking port controller" - var/master_tag //for mapping - var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program + program = /datum/computer/file/embedded_program/airlock/multi_docking + var/master_tag // For mapping tag_secure = 1 -/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Initialize() - . = ..() - airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src) - program = airlock_program - /obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] + var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program // Cast to proper type data = list( "chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]), @@ -82,14 +77,11 @@ ui.set_auto_update(1) /obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list) - if(..()) + if((. = ..())) return - usr.set_machine(src) - src.add_fingerprint(usr) - var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks + switch(href_list["command"]) // Anti-HTML-hacking checks if("cycle_ext") clean = 1 if("cycle_int") diff --git a/code/game/machinery/embedded_controller/airlock_program.dm b/code/game/machinery/embedded_controller/airlock_program.dm index 5ebbac93aeb..d848e1d372b 100644 --- a/code/game/machinery/embedded_controller/airlock_program.dm +++ b/code/game/machinery/embedded_controller/airlock_program.dm @@ -1,4 +1,4 @@ -//Handles the control of airlocks +// Handles the control of airlocks #define STATE_IDLE 0 #define STATE_PREPARE 1 @@ -9,8 +9,8 @@ #define TARGET_INOPEN -1 #define TARGET_OUTOPEN -2 -#define MIN_TARGET_PRESSURE (ONE_ATMOSPHERE * 0.05) // Never try to pump to pure vacuum, its not happening. -#define SKIPCYCLE_MARGIN 1 // Skip cycling airlock (just open the doors) if pressures are within this range. +#define MIN_TARGET_PRESSURE (ONE_ATMOSPHERE * 0.05) // Never try to pump to pure vacuum, its not happening. +#define SKIPCYCLE_MARGIN 1 // Skip cycling airlock (just open the doors) if pressures are within this range. /datum/computer/file/embedded_program/airlock var/tag_exterior_door @@ -33,16 +33,16 @@ ..(M) memory["chamber_sensor_pressure"] = ONE_ATMOSPHERE - memory["external_sensor_pressure"] = 0 //assume vacuum for simple airlock controller + memory["external_sensor_pressure"] = 0 // Assume vacuum for simple airlock controller memory["internal_sensor_pressure"] = ONE_ATMOSPHERE - memory["exterior_status"] = list(state = "closed", lock = "locked") //assume closed and locked in case the doors dont report in + memory["exterior_status"] = list(state = "closed", lock = "locked") // Assume closed and locked in case the doors dont report in memory["interior_status"] = list(state = "closed", lock = "locked") memory["pump_status"] = "unknown" memory["target_pressure"] = ONE_ATMOSPHERE memory["purge"] = 0 memory["secure"] = 0 - if (istype(M, /obj/machinery/embedded_controller/radio/airlock)) //if our controller is an airlock controller than we can auto-init our tags + if (istype(M, /obj/machinery/embedded_controller/radio/airlock)) // If our controller is an airlock controller than we can auto-init our tags var/obj/machinery/embedded_controller/radio/airlock/controller = M cycle_to_external_air = controller.cycle_to_external_air if(cycle_to_external_air) @@ -52,14 +52,14 @@ tag_interior_door = controller.tag_interior_door? controller.tag_interior_door : "[id_tag]_inner" tag_airpump = controller.tag_airpump? controller.tag_airpump : "[id_tag]_pump" tag_chamber_sensor = controller.tag_chamber_sensor? controller.tag_chamber_sensor : "[id_tag]_sensor" - tag_exterior_sensor = controller.tag_exterior_sensor - tag_interior_sensor = controller.tag_interior_sensor + tag_exterior_sensor = controller.tag_exterior_sensor || "[id_tag]_exterior_sensor" + tag_interior_sensor = controller.tag_interior_sensor || "[id_tag]_interior_sensor" tag_airlock_mech_sensor = controller.tag_airlock_mech_sensor? controller.tag_airlock_mech_sensor : "[id_tag]_airlock_mech" tag_shuttle_mech_sensor = controller.tag_shuttle_mech_sensor? controller.tag_shuttle_mech_sensor : "[id_tag]_shuttle_mech" memory["secure"] = controller.tag_secure spawn(10) - signalDoor(tag_exterior_door, "update") //signals connected doors to update their status + signalDoor(tag_exterior_door, "update") // Signals connected doors to update their status signalDoor(tag_interior_door, "update") /datum/computer/file/embedded_program/airlock/receive_signal(datum/signal/signal, receive_method, receive_param) @@ -98,7 +98,7 @@ if("cycle_interior") receive_user_command("cycle_int_door") if("cycle") - if(memory["interior_status"]["state"] == "open") //handle backwards compatibility + if(memory["interior_status"]["state"] == "open") // Handle backwards compatibility receive_user_command("cycle_ext") else receive_user_command("cycle_int") @@ -109,7 +109,7 @@ if("cycle_interior") receive_user_command("cycle_int") if("cycle") - if(memory["interior_status"]["state"] == "open") //handle backwards compatibility + if(memory["interior_status"]["state"] == "open") // Handle backwards compatibility receive_user_command("cycle_ext") else receive_user_command("cycle_int") @@ -117,13 +117,14 @@ /datum/computer/file/embedded_program/airlock/receive_user_command(command) var/shutdown_pump = 0 + . = TRUE switch(command) if("cycle_ext") - //If airlock is already cycled in this direction, just toggle the doors. + // If airlock is already cycled in this direction, just toggle the doors. if(!memory["purge"] && abs(memory["external_sensor_pressure"] - memory["chamber_sensor_pressure"]) <= SKIPCYCLE_MARGIN) toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "toggle") - //only respond to these commands if the airlock isn't already doing something - //prevents the controller from getting confused and doing strange things + // Only respond to these commands if the airlock isn't already doing something + // Prevents the controller from getting confused and doing strange things else if(state == target_state) begin_cycle_out() @@ -163,9 +164,11 @@ else signalDoor(tag_interior_door, "unlock") signalDoor(tag_exterior_door, "unlock") + else + . = FALSE if(shutdown_pump) - signalPump(tag_airpump, 0) //send a signal to stop pressurizing + signalPump(tag_airpump, 0) // Send a signal to stop pressurizing if(cycle_to_external_air) signalPump(tag_pump_out_internal, 0) signalPump(tag_pump_out_external, 0) @@ -173,7 +176,7 @@ /datum/computer/file/embedded_program/airlock/process() - if(!state) //Idle + if(!state) // Idle if(target_state) switch(target_state) if(TARGET_INOPEN) @@ -181,20 +184,20 @@ if(TARGET_OUTOPEN) memory["target_pressure"] = memory["external_sensor_pressure"] - //lock down the airlock before activating pumps + // Lock down the airlock before activating pumps close_doors() state = STATE_PREPARE else - //make sure to return to a sane idle state - if(memory["pump_status"] != "off") //send a signal to stop pumping + // Make sure to return to a sane idle state + if(memory["pump_status"] != "off") // Send a signal to stop pumping signalPump(tag_airpump, 0) if(cycle_to_external_air) signalPump(tag_pump_out_internal, 0) signalPump(tag_pump_out_external, 0) if ((state == STATE_PRESSURIZE || state == STATE_DEPRESSURIZE) && !check_doors_secured()) - //the airlock will not allow itself to continue to cycle when any of the doors are forced open. + // The airlock will not allow itself to continue to cycle when any of the doors are forced open. stop_cycling() switch(state) @@ -204,37 +207,37 @@ var/target_pressure = memory["target_pressure"] if(memory["purge"]) - //purge apparently means clearing the airlock chamber to vacuum (then refilling, handled later) + // Purge apparently means clearing the airlock chamber to vacuum (then refilling, handled later) target_pressure = 0 state = STATE_DEPRESSURIZE - if(!cycle_to_external_air || target_state == TARGET_OUTOPEN) // if going outside, pump internal air into air tank - signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing + if(!cycle_to_external_air || target_state == TARGET_OUTOPEN) // If going outside, pump internal air into air tank + signalPump(tag_airpump, 1, 0, target_pressure) // Send a signal to start depressurizing else - signalPump(tag_pump_out_internal, 1, 0, target_pressure) // if going inside, pump external air out of the airlock - signalPump(tag_pump_out_external, 1, 1, 15000) // make sure the air is actually going outside + signalPump(tag_pump_out_internal, 1, 0, target_pressure) // If going inside, pump external air out of the airlock + signalPump(tag_pump_out_external, 1, 1, 15000) // Make sure the air is actually going outside else if(chamber_pressure <= target_pressure) state = STATE_PRESSURIZE - if(!cycle_to_external_air || target_state == TARGET_INOPEN) // if going inside, pump air into airlock - signalPump(tag_airpump, 1, 1, target_pressure) //send a signal to start pressurizing + if(!cycle_to_external_air || target_state == TARGET_INOPEN) // If going inside, pump air into airlock + signalPump(tag_airpump, 1, 1, target_pressure) // Send a signal to start pressurizing else - signalPump(tag_pump_out_internal, 1, 1, target_pressure) // if going outside, fill airlock with external air + signalPump(tag_pump_out_internal, 1, 1, target_pressure) // If going outside, fill airlock with external air signalPump(tag_pump_out_external, 1, 0, 0) else if(chamber_pressure > target_pressure) if(!cycle_to_external_air) state = STATE_DEPRESSURIZE - signalPump(tag_airpump, 1, 0, target_pressure) //send a signal to start depressurizing + signalPump(tag_airpump, 1, 0, target_pressure) // Send a signal to start depressurizing else - memory["purge"] = 1 // should always purge first if using external air, chamber pressure should never be higher than target pressure here - //Make sure the airlock isn't aiming for pure vacuum - an impossibility + memory["purge"] = 1 // Should always purge first if using external air, chamber pressure should never be higher than target pressure here + // Make sure the airlock isn't aiming for pure vacuum - an impossibility memory["target_pressure"] = max(target_pressure, MIN_TARGET_PRESSURE) if(STATE_PRESSURIZE) if(memory["chamber_sensor_pressure"] >= memory["target_pressure"] * 0.95) - //not done until the pump has reported that it's off + // Not done until the pump has reported that it's off if(memory["pump_status"] != "off") - signalPump(tag_airpump, 0) //send a signal to stop pumping + signalPump(tag_airpump, 0) //Send a signal to stop pumping if(cycle_to_external_air) signalPump(tag_pump_out_internal, 0) signalPump(tag_pump_out_external, 0) @@ -255,7 +258,7 @@ memory["purge"] = 0 memory["target_pressure"] = (target_state == TARGET_INOPEN ? memory["internal_sensor_pressure"] : memory["external_sensor_pressure"]) if (memory["target_pressure"] > SKIPCYCLE_MARGIN) - state = STATE_PREPARE // Skip pressurizing if target pressure is already close enough. + state = STATE_PREPARE // Skip pressurizing if target pressure is already close enough. else cycleDoors(target_state) state = STATE_IDLE @@ -266,13 +269,17 @@ return 1 -//these are here so that other types don't have to make so many assuptions about our implementation +// These are here so that other types don't have to make so many assuptions about our implementation /datum/computer/file/embedded_program/airlock/proc/begin_cycle_in() state = STATE_IDLE target_state = TARGET_INOPEN memory["purge"] = cycle_to_external_air +/datum/computer/file/embedded_program/airlock/proc/begin_dock_cycle() + state = STATE_IDLE + target_state = TARGET_INOPEN + /datum/computer/file/embedded_program/airlock/proc/begin_cycle_out() state = STATE_IDLE target_state = TARGET_OUTOPEN @@ -289,7 +296,7 @@ /datum/computer/file/embedded_program/airlock/proc/done_cycling() return (state == STATE_IDLE && target_state == TARGET_NONE) -//are the doors closed and locked? +// Are the doors closed and locked? /datum/computer/file/embedded_program/airlock/proc/check_exterior_door_secured() return (memory["exterior_status"]["state"] == "closed" && memory["exterior_status"]["lock"] == "locked") @@ -318,7 +325,7 @@ ) post_signal(signal) -//this is called to set the appropriate door state at the end of a cycling process, or for the exterior buttons +// This is called to set the appropriate door state at the end of a cycling process, or for the exterior buttons /datum/computer/file/embedded_program/airlock/proc/cycleDoors(var/target) switch(target) if(TARGET_OUTOPEN) @@ -410,4 +417,4 @@ send an additional command to open the door again. #undef TARGET_NONE #undef TARGET_INOPEN -#undef TARGET_OUTOPEN \ No newline at end of file +#undef TARGET_OUTOPEN diff --git a/code/game/machinery/embedded_controller/docking_program.dm b/code/game/machinery/embedded_controller/docking_program.dm index 95acededb3c..8e1b9b24ffd 100644 --- a/code/game/machinery/embedded_controller/docking_program.dm +++ b/code/game/machinery/embedded_controller/docking_program.dm @@ -6,25 +6,25 @@ #define MODE_NONE 0 #define MODE_SERVER 1 -#define MODE_CLIENT 2 //The one who initiated the docking, and who can initiate the undocking. The server cannot initiate undocking, and is the one responsible for deciding to accept a docking request and signals when docking and undocking is complete. (Think server == station, client == shuttle) +#define MODE_CLIENT 2 // The one who initiated the docking, and who can initiate the undocking. The server cannot initiate undocking, and is the one responsible for deciding to accept a docking request and signals when docking and undocking is complete. (Think server == station, client == shuttle) -#define MESSAGE_RESEND_TIME 5 //how long (in seconds) do we wait before resending a message +#define MESSAGE_RESEND_TIME 5 // How long (in seconds) do we wait before resending a message /* *** STATE TABLE *** - MODE_CLIENT|STATE_UNDOCKED sent a request for docking and now waiting for a reply. - MODE_CLIENT|STATE_DOCKING server told us they are OK to dock, waiting for our docking port to be ready. - MODE_CLIENT|STATE_DOCKED idle - docked as client. - MODE_CLIENT|STATE_UNDOCKING we are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking. + MODE_CLIENT|STATE_UNDOCKED Sent a request for docking and now waiting for a reply. + MODE_CLIENT|STATE_DOCKING Server told us they are OK to dock, waiting for our docking port to be ready. + MODE_CLIENT|STATE_DOCKED Idle - docked as client. + MODE_CLIENT|STATE_UNDOCKING We are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking. - MODE_SERVER|STATE_UNDOCKED should never happen. - MODE_SERVER|STATE_DOCKING someone requested docking, we are waiting for our docking port to be ready. - MODE_SERVER|STATE_DOCKED idle - docked as server - MODE_SERVER|STATE_UNDOCKING client requested undocking, we are waiting for our docking port to be ready. + MODE_SERVER|STATE_UNDOCKED Should never happen. + MODE_SERVER|STATE_DOCKING Someone requested docking, we are waiting for our docking port to be ready. + MODE_SERVER|STATE_DOCKED Idle - docked as server + MODE_SERVER|STATE_UNDOCKING Client requested undocking, we are waiting for our docking port to be ready. - MODE_NONE|STATE_UNDOCKED idle - not docked. - MODE_NONE|anything else should never happen. + MODE_NONE|STATE_UNDOCKED Idle - not docked. + MODE_NONE|anything else Should never happen. *** Docking Signals *** @@ -62,31 +62,36 @@ /datum/computer/file/embedded_program/docking - var/tag_target //the tag of the docking controller that we are trying to dock with + var/tag_target // The tag of the docking controller that we are trying to dock with var/dock_state = STATE_UNDOCKED var/control_mode = MODE_NONE - var/response_sent = 0 //so we don't spam confirmation messages - var/resend_counter = 0 //for periodically resending confirmation messages in case they are missed + var/response_sent = 0 // So we don't spam confirmation messages + var/resend_counter = 0 // For periodically resending confirmation messages in case they are missed - var/override_enabled = 0 //when enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually - var/received_confirm = 0 //for undocking, whether the server has recieved a confirmation from the client + var/override_enabled = 0 // When enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually + var/received_confirm = 0 // For undocking, whether the server has recieved a confirmation from the client + + var/docking_codes // Would only allow docking when receiving signal with these, if set + var/display_name // Override the name shown on docking monitoring program; defaults to area name + coordinates if unset /datum/computer/file/embedded_program/docking/New() ..() - var/datum/existing = locate(id_tag) //in case a datum already exists with our tag - if(existing) - existing.tag = null //take it from them - - tag = id_tag //Greatly simplifies shuttle initialization + if(id_tag) + if(SSshuttle.docking_registry[id_tag]) + crash_with("Docking controller tag [id_tag] had multiple associated programs.") + SSshuttle.docking_registry[id_tag] = src +/datum/computer/file/embedded_program/docking/Destroy() + SSshuttle.docking_registry -= id_tag + return ..() /datum/computer/file/embedded_program/docking/receive_signal(datum/signal/signal, receive_method, receive_param) - var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id + var/receive_tag = signal.data["tag"] // For docking signals, this is the sender id var/command = signal.data["command"] - var/recipient = signal.data["recipient"] //the intended recipient of the docking signal + var/recipient = signal.data["recipient"] // The intended recipient of the docking signal if (recipient != id_tag) - return //this signal is not for us + return // This signal is not for us switch (command) if ("confirm_dock") @@ -100,28 +105,35 @@ dock_state = STATE_DOCKED broadcast_docking_status() if (!override_enabled) - finish_docking() //client done docking! + finish_docking() // Client done docking! response_sent = 0 - else if (control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) //client just sent us the confirmation back, we're done with the docking process + else if (control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) // Client just sent us the confirmation back, we're done with the docking process received_confirm = 1 if ("request_dock") if (control_mode == MODE_NONE && dock_state == STATE_UNDOCKED) - control_mode = MODE_SERVER + tag_target = receive_tag + + if(docking_codes) + var/code = signal.data["code"] + if(code != docking_codes) + testing("Controller [id_tag] got request_dock but code:[code] != docking_codes:[docking_codes]") + return + + control_mode = MODE_SERVER dock_state = STATE_DOCKING broadcast_docking_status() - tag_target = receive_tag if (!override_enabled) prepare_for_docking() - send_docking_command(tag_target, "confirm_dock") //acknowledge the request + send_docking_command(tag_target, "confirm_dock") // Acknowledge the request if ("confirm_undock") if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKING && receive_tag == tag_target) if (!override_enabled) finish_undocking() - reset() //client is done undocking! + reset() // Client is done undocking! else if (control_mode == MODE_SERVER && dock_state == STATE_UNDOCKING && receive_tag == tag_target) received_confirm = 1 @@ -139,21 +151,21 @@ /datum/computer/file/embedded_program/docking/process() switch(dock_state) - if (STATE_DOCKING) //waiting for our docking port to be ready for docking + if (STATE_DOCKING) // Waiting for our docking port to be ready for docking if (ready_for_docking()) if (control_mode == MODE_CLIENT) if (!response_sent) - send_docking_command(tag_target, "confirm_dock") //tell the server we're ready + send_docking_command(tag_target, "confirm_dock") // Tell the server we're ready response_sent = 1 else if (control_mode == MODE_SERVER && received_confirm) - send_docking_command(tag_target, "confirm_dock") //tell the client we are done docking. + send_docking_command(tag_target, "confirm_dock") // Tell the client we are done docking. dock_state = STATE_DOCKED broadcast_docking_status() if (!override_enabled) - finish_docking() //server done docking! + finish_docking() // Server done docking! response_sent = 0 received_confirm = 0 @@ -161,14 +173,14 @@ if (ready_for_undocking()) if (control_mode == MODE_CLIENT) if (!response_sent) - send_docking_command(tag_target, "confirm_undock") //tell the server we are OK to undock. + send_docking_command(tag_target, "confirm_undock") // Tell the server we are OK to undock. response_sent = 1 else if (control_mode == MODE_SERVER && received_confirm) - send_docking_command(tag_target, "confirm_undock") //tell the client we are done undocking. + send_docking_command(tag_target, "confirm_undock") // Tell the client we are done undocking. if (!override_enabled) finish_undocking() - reset() //server is done undocking! + reset() // Server is done undocking! if (response_sent || resend_counter > 0) resend_counter++ @@ -177,7 +189,7 @@ response_sent = 0 resend_counter = 0 - //handle invalid states + // Handle invalid states if (control_mode == MODE_NONE && dock_state != STATE_UNDOCKED) if (tag_target) send_docking_command(tag_target, "dock_error") @@ -187,7 +199,7 @@ /datum/computer/file/embedded_program/docking/proc/initiate_docking(var/target) - if (dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) //must be undocked and not serving another request to begin a new docking handshake + if (dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) // Must be undocked and not serving another request to begin a new docking handshake return tag_target = target @@ -196,7 +208,7 @@ send_docking_command(tag_target, "request_dock") /datum/computer/file/embedded_program/docking/proc/initiate_undocking() - if (dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) //must be docked and must be client to start undocking + if (dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) // Must be docked and must be client to start undocking return dock_state = STATE_UNDOCKING @@ -207,27 +219,27 @@ send_docking_command(tag_target, "request_undock") -//tell the docking port to start getting ready for docking - e.g. pressurize +// Tell the docking port to start getting ready for docking - e.g. pressurize /datum/computer/file/embedded_program/docking/proc/prepare_for_docking() return -//are we ready for docking? +// Are we ready for docking? /datum/computer/file/embedded_program/docking/proc/ready_for_docking() return 1 -//we are docked, open the doors or whatever. +// We are docked, open the doors or whatever. /datum/computer/file/embedded_program/docking/proc/finish_docking() return -//tell the docking port to start getting ready for undocking - e.g. close those doors. +// Tell the docking port to start getting ready for undocking - e.g. close those doors. /datum/computer/file/embedded_program/docking/proc/prepare_for_undocking() return -//we are docked, open the doors or whatever. +// We are docked, open the doors or whatever. /datum/computer/file/embedded_program/docking/proc/finish_undocking() return -//are we ready for undocking? +// Are we ready for undocking? /datum/computer/file/embedded_program/docking/proc/ready_for_undocking() return 1 @@ -258,7 +270,7 @@ /datum/computer/file/embedded_program/docking/proc/undocked() return (dock_state == STATE_UNDOCKED) -//returns 1 if we are saftely undocked (and the shuttle can leave) +// Returns 1 if we are saftely undocked (and the shuttle can leave) /datum/computer/file/embedded_program/docking/proc/can_launch() return undocked() @@ -267,6 +279,7 @@ signal.data["tag"] = id_tag signal.data["command"] = command signal.data["recipient"] = recipient + signal.data["code"] = docking_codes post_signal(signal) /datum/computer/file/embedded_program/docking/proc/broadcast_docking_status() @@ -275,7 +288,7 @@ signal.data["dock_status"] = get_docking_status() post_signal(signal) -//this is mostly for NanoUI +// This is mostly for NanoUI /datum/computer/file/embedded_program/docking/proc/get_docking_status() switch (dock_state) if (STATE_UNDOCKED) return "undocked" @@ -283,6 +296,8 @@ if (STATE_UNDOCKING) return "undocking" if (STATE_DOCKED) return "docked" +/datum/computer/file/embedded_program/docking/proc/get_name() + return display_name ? display_name : "[get_area(master)] ([master.x], [master.y])" #undef STATE_UNDOCKED #undef STATE_DOCKING @@ -291,4 +306,4 @@ #undef MODE_NONE #undef MODE_SERVER -#undef MODE_CLIENT \ No newline at end of file +#undef MODE_CLIENT diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 32b8839f212..a624389afaf 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -1,18 +1,20 @@ /obj/machinery/embedded_controller - var/datum/computer/file/embedded_program/program //the currently executing program - name = "Embedded Controller" anchored = 1 - use_power = USE_POWER_IDLE idle_power_usage = 10 - + var/datum/computer/file/embedded_program/program // The currently executing program var/on = 1 -obj/machinery/embedded_controller/radio/Destroy() - if(radio_controller) - radio_controller.remove_object(src,frequency) - ..() +/obj/machinery/embedded_controller/Initialize() + if(ispath(program)) + program = new program(src) + return ..() + +/obj/machinery/embedded_controller/Destroy() + if(istype(program)) + qdel(program) // The program will clear the ref in its Destroy + return ..() /obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) return 0 @@ -22,7 +24,18 @@ obj/machinery/embedded_controller/radio/Destroy() if(program) program.receive_signal(signal, receive_method, receive_param) - //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0 + //spawn(5) program.process() // No, program.process sends some signals and machines respond and we here again and we lag -rastaf0 + +/obj/machinery/embedded_controller/Topic(href, href_list) + if((. = ..())) + return + if(usr) + usr.set_machine(src) + src.add_fingerprint(usr) + // We would now pass it to the program, except that some of our embedded controller types want to block certain commands. + // Until/unless that is refactored differently, we rely on subtypes to pass it on. + //if(program) + // return program.receive_user_command(href_list["command"]) /obj/machinery/embedded_controller/process() if(program) @@ -40,26 +53,32 @@ obj/machinery/embedded_controller/radio/Destroy() src.ui_interact(user) -/obj/machinery/embedded_controller/ui_interact() - return +// +// Embedded controller with a radio! (Most things (All things?) use this) +// /obj/machinery/embedded_controller/radio icon = 'icons/obj/airlock_machines.dmi' icon_state = "airlock_control_standby" power_channel = ENVIRON density = 0 + unacidable = 1 var/id_tag - //var/radio_power_use = 50 //power used to xmit signals + //var/radio_power_use = 50 // Power used to xmit signals var/frequency = 1379 var/radio_filter = null var/datum/radio_frequency/radio_connection - unacidable = 1 /obj/machinery/embedded_controller/radio/Initialize() + set_frequency(frequency) // Set it before parent instantiates program . = ..() - set_frequency(frequency) + +/obj/machinery/embedded_controller/radio/Destroy() + if(radio_controller) + radio_controller.remove_object(src,frequency) + ..() /obj/machinery/embedded_controller/radio/update_icon() if(on && program) @@ -73,7 +92,7 @@ obj/machinery/embedded_controller/radio/Destroy() /obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal, var/radio_filter = null) signal.transmission_method = TRANSMISSION_RADIO if(radio_connection) - //use_power(radio_power_use) //neat idea, but causes way too much lag. + //use_power(radio_power_use) // Neat idea, but causes way too much lag. return radio_connection.post_signal(src, signal, radio_filter) else qdel(signal) @@ -81,4 +100,4 @@ obj/machinery/embedded_controller/radio/Destroy() /obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency) radio_controller.remove_object(src, frequency) frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, radio_filter) \ No newline at end of file + radio_connection = radio_controller.add_object(src, frequency, radio_filter) diff --git a/code/game/machinery/embedded_controller/embedded_program_base.dm b/code/game/machinery/embedded_controller/embedded_program_base.dm index 56a605759d0..f61e2e1cddb 100644 --- a/code/game/machinery/embedded_controller/embedded_program_base.dm +++ b/code/game/machinery/embedded_controller/embedded_program_base.dm @@ -11,8 +11,15 @@ var/obj/machinery/embedded_controller/radio/R = M id_tag = R.id_tag +/datum/computer/file/embedded_program/Destroy() + if(master) + master.program = null + master = null + return ..() + +// Return TRUE if was a command for us, otherwise return FALSE (so controllers with multiple programs can try each in turn until one accepts) /datum/computer/file/embedded_program/proc/receive_user_command(command) - return + return FALSE /datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param) return diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm index 14b27b2512e..4b98d28c77e 100644 --- a/code/game/machinery/embedded_controller/simple_docking_controller.dm +++ b/code/game/machinery/embedded_controller/simple_docking_controller.dm @@ -1,16 +1,12 @@ -//a docking port that uses a single door +// A docking port that uses a single door /obj/machinery/embedded_controller/radio/simple_docking_controller name = "docking hatch controller" + program = /datum/computer/file/embedded_program/docking/simple var/tag_door - var/datum/computer/file/embedded_program/docking/simple/docking_program - -/obj/machinery/embedded_controller/radio/simple_docking_controller/Initialize() - . = ..() - docking_program = new/datum/computer/file/embedded_program/docking/simple(src) - program = docking_program /obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] + var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type data = list( "docking_status" = docking_program.get_docking_status(), @@ -28,14 +24,11 @@ ui.set_auto_update(1) /obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list) - if(..()) - return 1 - - usr.set_machine(src) - src.add_fingerprint(usr) + if((. = ..())) + return var/clean = 0 - switch(href_list["command"]) //anti-HTML-hacking checks + switch(href_list["command"]) // Anti-HTML-hacking checks if("force_door") clean = 1 if("toggle_override") @@ -44,16 +37,15 @@ if(clean) program.receive_user_command(href_list["command"]) - return 0 + return - -//A docking controller program for a simple door based docking port +// A docking controller program for a simple door based docking port /datum/computer/file/embedded_program/docking/simple var/tag_door /datum/computer/file/embedded_program/docking/simple/New(var/obj/machinery/embedded_controller/M) ..(M) - memory["door_status"] = list(state = "closed", lock = "locked") //assume closed and locked in case the doors dont report in + memory["door_status"] = list(state = "closed", lock = "locked") // Assume closed and locked in case the doors dont report in if (istype(M, /obj/machinery/embedded_controller/radio/simple_docking_controller)) var/obj/machinery/embedded_controller/radio/simple_docking_controller/controller = M @@ -61,7 +53,7 @@ tag_door = controller.tag_door? controller.tag_door : "[id_tag]_hatch" spawn(10) - signal_door("update") //signals connected doors to update their status + signal_door("update") // Signals connected doors to update their status /datum/computer/file/embedded_program/docking/simple/receive_signal(datum/signal/signal, receive_method, receive_param) @@ -76,6 +68,7 @@ ..(signal, receive_method, receive_param) /datum/computer/file/embedded_program/docking/simple/receive_user_command(command) + . = TRUE switch(command) if("force_door") if (override_enabled) @@ -88,7 +81,8 @@ disable_override() else enable_override() - + else + . = FALSE /datum/computer/file/embedded_program/docking/simple/proc/signal_door(var/command) var/datum/signal/signal = new @@ -114,23 +108,23 @@ else if(memory["door_status"]["lock"] == "unlocked") signal_door("lock") -//tell the docking port to start getting ready for docking - e.g. pressurize +// Tell the docking port to start getting ready for docking - e.g. pressurize /datum/computer/file/embedded_program/docking/simple/prepare_for_docking() - return //don't need to do anything + return // Don't need to do anything -//are we ready for docking? +// Are we ready for docking? /datum/computer/file/embedded_program/docking/simple/ready_for_docking() - return 1 //don't need to do anything + return 1 // Don't need to do anything -//we are docked, open the doors or whatever. +// We are docked, open the doors or whatever. /datum/computer/file/embedded_program/docking/simple/finish_docking() open_door() -//tell the docking port to start getting ready for undocking - e.g. close those doors. +// Tell the docking port to start getting ready for undocking - e.g. close those doors. /datum/computer/file/embedded_program/docking/simple/prepare_for_undocking() close_door() -//are we ready for undocking? +// Are we ready for undocking? /datum/computer/file/embedded_program/docking/simple/ready_for_undocking() return (memory["door_status"]["state"] == "closed" && memory["door_status"]["lock"] == "locked") @@ -161,4 +155,4 @@ set src in view(1) src.program:initiate_undocking() -*/ \ No newline at end of file +*/ diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index d23c3ffdc11..de904977f31 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -19,23 +19,23 @@ density = 0 use_power = USE_POWER_IDLE idle_power_usage = 10 - circuit = /obj/item/circuitboard/status_display + circuit = /obj/item/circuitboard/status_display var/mode = 1 // 0 = Blank // 1 = Shuttle timer // 2 = Arbitrary message(s) - // 3 = alert picture + // 3 = Alert picture // 4 = Supply shuttle timer - var/picture_state // icon_state of alert picture - var/message1 = "" // message line 1 - var/message2 = "" // message line 2 - var/index1 // display index for scrolling messages or 0 if non-scrolling + var/picture_state // Icon_state of alert picture + var/message1 = "" // Message line 1 + var/message2 = "" // Message line 2 + var/index1 // Display index for scrolling messages or 0 if non-scrolling var/index2 var/picture = null - var/frequency = 1435 // radio frequency + var/frequency = 1435 // Radio frequency - var/friendc = 0 // track if Friend Computer mode + var/friendc = 0 // Track if Friend Computer mode var/ignore_friendc = 0 maptext_height = 26 @@ -63,13 +63,13 @@ attack_hand(user) return -// register for radio system +// Register for radio system /obj/machinery/status_display/Initialize() . = ..() if(radio_controller) radio_controller.add_object(src, frequency) -// timed process +// Timed process /obj/machinery/status_display/process() if(stat & NOPOWER) remove_display() @@ -83,7 +83,7 @@ set_picture("ai_bsod") ..(severity) -// set what is displayed +// Set what is displayed /obj/machinery/status_display/proc/update() remove_display() if(friendc && !ignore_friendc) @@ -91,12 +91,12 @@ return 1 switch(mode) - if(STATUS_DISPLAY_BLANK) //blank + if(STATUS_DISPLAY_BLANK) // Blank return 1 - if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer + if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) // Emergency shuttle timer if(!SSemergencyshuttle) message1 = "-ETA-" - message2 = "Never" // You're here forever. + message2 = "Never" // You're here forever. return 1 if(SSemergencyshuttle.waiting_to_leave()) message1 = "-ETD-" @@ -114,7 +114,7 @@ message2 = "Error" update_display(message1, message2) return 1 - if(STATUS_DISPLAY_MESSAGE) //custom messages + if(STATUS_DISPLAY_MESSAGE) // Custom messages var/line1 var/line2 @@ -210,7 +210,7 @@ return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" /obj/machinery/status_display/proc/get_supply_shuttle_timer() - var/datum/shuttle/ferry/supply/shuttle = SSsupply.shuttle + var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle if(!shuttle) return "Error" diff --git a/code/game/machinery/supply_display.dm b/code/game/machinery/supply_display.dm index 5c111c129f8..5a5c9750b6a 100644 --- a/code/game/machinery/supply_display.dm +++ b/code/game/machinery/supply_display.dm @@ -6,7 +6,7 @@ message1 = "CARGO" message2 = "" - var/datum/shuttle/ferry/supply/shuttle = SSsupply.shuttle + var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle if(!shuttle) message2 = "Error" else if(shuttle.has_arrive_time()) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index aebbd17f29e..bfab65e15ba 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -6,7 +6,7 @@ var/list/command_cartridges = list( /obj/item/cartridge/rd, /obj/item/cartridge/cmo, /obj/item/cartridge/head, - /obj/item/cartridge/lawyer // Internal Affaris, + /obj/item/cartridge/lawyer // Internal Affaris, ) var/list/security_cartridges = list( @@ -33,7 +33,7 @@ var/list/research_cartridges = list( ) var/list/cargo_cartridges = list( - /obj/item/cartridge/quartermaster, // This also covers cargo-techs, apparently, + /obj/item/cartridge/quartermaster, // This also covers cargo-techs, apparently, for some reason /obj/item/cartridge/miner, /obj/item/cartridge/hop ) @@ -62,7 +62,7 @@ var/list/civilian_cartridges = list( var/access_janitor = 0 // var/access_flora = 0 var/access_reagent_scanner = 0 - var/access_remote_door = 0 // Control some blast doors remotely!! + var/access_remote_door = 0 // Control some blast doors remotely!! var/remote_door_id = "" var/access_status_display = 0 var/access_quartermaster = 0 @@ -71,11 +71,11 @@ var/list/civilian_cartridges = list( var/charges = 0 var/mode = null var/menu - var/datum/data/record/active1 = null //General - var/datum/data/record/active2 = null //Medical - var/datum/data/record/active3 = null //Security - var/selected_sensor = null // Power Sensor - var/message1 // used for status_displays + var/datum/data/record/active1 = null // General + var/datum/data/record/active2 = null // Medical + var/datum/data/record/active3 = null // Security + var/selected_sensor = null // Power Sensor + var/message1 // Used for status_displays var/message2 var/list/stored_data = list() @@ -246,7 +246,7 @@ var/list/civilian_cartridges = list( icon_state = "cart" access_remote_door = 1 access_detonate_pda = 1 - remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. + remote_door_id = "smindicate" // Make sure this matches the syndicate shuttle's shield/door id!! // Don't ask about the name, testing. charges = 4 /obj/item/cartridge/proc/post_status(var/command, var/data1, var/data2) @@ -425,7 +425,7 @@ var/list/civilian_cartridges = list( if(mode==47) var/supplyData[0] - var/datum/shuttle/ferry/supply/shuttle = SSsupply.shuttle + var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle if (shuttle) supplyData["shuttle_moving"] = shuttle.has_arrive_time() supplyData["shuttle_eta"] = shuttle.eta_minutes() @@ -462,7 +462,7 @@ var/list/civilian_cartridges = list( - /* Janitor Supplies Locator (Mode: 49) */ + /* Janitor Supplies Locator (Mode: 49) */ if(mode==49) var/JaniData[0] var/turf/cl = get_turf(src) diff --git a/code/game/objects/items/devices/communicator/helper.dm b/code/game/objects/items/devices/communicator/helper.dm index 078bd65b446..128e9616c2c 100644 --- a/code/game/objects/items/devices/communicator/helper.dm +++ b/code/game/objects/items/devices/communicator/helper.dm @@ -226,8 +226,8 @@ if(T) var/list/levels = GLOB.using_map.get_map_levels(T.z, FALSE) for(var/obj/machinery/power/sensor/S in machines) - if((S.long_range) || (S.loc.z in levels) || (S.loc.z == T.z)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels. - if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen! + if((S.long_range) || (S.loc.z in levels) || (S.loc.z == T.z)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels. + if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen! warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z") else grid_sensors += S @@ -299,7 +299,7 @@ janidata[++janidata.len] = list("field" = "Current Location", "val" = "[userloc.x], [userloc.y], [GLOB.using_map.get_zlevel_name(userloc.z)]") else janidata[++janidata.len] = list("field" = "Current Location", "val" = "Unknown") - return janidata // If the user isn't on a valid turf, then it shouldn't be able to find anything anyways + return janidata // If the user isn't on a valid turf, then it shouldn't be able to find anything anyways // Mops, mop buckets, janitorial carts. for(var/obj/C in cleaningList) @@ -332,23 +332,23 @@ // The contents of the three lists are inherently related, so separating them into different procs would be largely redundant /obj/item/commcard/proc/get_GPS_lists() // GPS Access - var/intgps[0] // Gps devices within the commcard -- Allow tag edits, turning on/off, etc - var/extgps[0] // Gps devices not inside the commcard -- Print locations if a gps is on - var/stagps[0] // Gps net status, location, whether it's on, if it's got long range + var/intgps[0] // Gps devices within the commcard -- Allow tag edits, turning on/off, etc + var/extgps[0] // Gps devices not inside the commcard -- Print locations if a gps is on + var/stagps[0] // Gps net status, location, whether it's on, if it's got long range var/obj/item/gps/cumulative = new(src) cumulative.tracking = FALSE - cumulative.local_mode = TRUE // Won't detect long-range signals automatically + cumulative.local_mode = TRUE // Won't detect long-range signals automatically cumulative.long_range = FALSE - var/list/toggled_gps = list() // List of GPS units that are turned off before display_list() is called + var/list/toggled_gps = list() // List of GPS units that are turned off before display_list() is called for(var/obj/item/gps/G in internal_devices) var/gpsdata[0] if(G.tracking && !G.emped) - cumulative.tracking = TRUE // Turn it on + cumulative.tracking = TRUE // Turn it on if(G.long_range) - cumulative.long_range = TRUE // It can detect long-range + cumulative.long_range = TRUE // It can detect long-range if(!G.local_mode) - cumulative.local_mode = FALSE // It is detecting long-range + cumulative.local_mode = FALSE // It is detecting long-range gpsdata["ref"] = "\ref[G]" gpsdata["tag"] = G.gps_tag @@ -358,15 +358,15 @@ gpsdata["hide_signal"] = G.hide_signal gpsdata["can_hide"] = G.can_hide_signal - intgps[++intgps.len] = gpsdata // Add it to the list + intgps[++intgps.len] = gpsdata // Add it to the list if(G.tracking) - G.tracking = FALSE // Disable the internal gps units so they don't show up in the report + G.tracking = FALSE // Disable the internal gps units so they don't show up in the report toggled_gps += G var/list/remote_gps = cumulative.display_list() // Fetch information for all units except the ones inside of this device - for(var/obj/item/gps/G in toggled_gps) // Reenable any internal GPS units + for(var/obj/item/gps/G in toggled_gps) // Reenable any internal GPS units G.tracking = TRUE stagps["enabled"] = cumulative.tracking @@ -393,7 +393,7 @@ // code\game\machinery\computer\supply.dm, starting at line 55 /obj/item/commcard/proc/get_supply_shuttle_status() var/shuttle_status[0] - var/datum/shuttle/ferry/supply/shuttle = SSsupply.shuttle + var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle if(shuttle) if(shuttle.has_arrive_time()) shuttle_status["location"] = "In transit" @@ -403,8 +403,8 @@ else shuttle_status["time"] = 0 if(shuttle.at_station()) - if(shuttle.docking_controller) - switch(shuttle.docking_controller.get_docking_status()) + if(shuttle.shuttle_docking_controller) + switch(shuttle.shuttle_docking_controller.get_docking_status()) if("docked") shuttle_status["location"] = "Docked" shuttle_status["mode"] = SUP_SHUTTLE_DOCKED diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 9bcb2bcc28d..ce3d3382031 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -5,7 +5,7 @@ /turf/simulated/floor/diona/attackby() return -//Shuttle Floors +// Shuttle Floors /obj/landed_holder name = "landed turf holder" desc = "holds all the info about the turf this turf 'landed on'" @@ -19,7 +19,7 @@ my_turf = turf /obj/landed_holder/proc/land_on(var/turf/T) - //Gather destination information + // Gather destination information var/obj/landed_holder/new_holder = new(null) new_holder.turf_type = T.type new_holder.dir = T.dir @@ -29,7 +29,7 @@ new_holder.underlays = T.underlays.Copy() new_holder.decals = T.decals ? T.decals.Copy() : null - //Set the destination to be like us + // Set the destination to be like us T.Destroy() var/turf/simulated/shuttle/new_dest = T.ChangeTurf(my_turf.type,,1) new_dest.setDir(my_turf.dir) @@ -38,7 +38,7 @@ new_dest.copy_overlays(my_turf, TRUE) new_dest.underlays = my_turf.underlays new_dest.decals = my_turf.decals - //Shuttle specific stuff + // Shuttle specific stuff new_dest.interior_corner = my_turf.interior_corner new_dest.takes_underlays = my_turf.takes_underlays new_dest.under_turf = my_turf.under_turf @@ -49,15 +49,15 @@ new_holder.my_turf = new_dest new_dest.landed_holder = new_holder - //Update underlays if necessary (interior corners won't have changed). + // Update underlays if necessary (interior corners won't have changed). if(new_dest.takes_underlays && !new_dest.interior_corner) new_dest.underlay_update() return new_dest -/obj/landed_holder/proc/leave_turf() +/obj/landed_holder/proc/leave_turf(var/turf/base_turf = null) var/turf/new_source - //Change our source to whatever it was before + // Change our source to whatever it was before if(turf_type) new_source = my_turf.ChangeTurf(turf_type,,1) new_source.setDir(dir) @@ -67,7 +67,7 @@ new_source.underlays = underlays new_source.decals = decals else - new_source = my_turf.ChangeTurf(get_base_turf_by_area(my_turf),,1) + new_source = my_turf.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(my_turf),,1) return new_source @@ -80,9 +80,9 @@ var/obj/landed_holder/landed_holder var/interior_corner = 0 var/takes_underlays = 0 - var/turf/under_turf //Underlay override turf path. - var/join_flags = 0 //Bitstring to represent adjacency of joining walls - var/join_group = "shuttle" //A tag for what other walls to join with. Null if you don't want them to. + var/turf/under_turf // Underlay override turf path. + var/join_flags = 0 // Bitstring to represent adjacency of joining walls + var/join_group = "shuttle" // A tag for what other walls to join with. Null if you don't want them to. /turf/simulated/shuttle/Destroy() landed_holder = null @@ -90,22 +90,22 @@ /turf/simulated/shuttle/proc/underlay_update() if(!takes_underlays) - //Basically, if it's not forced, and we don't care, don't do it. + // Basically, if it's not forced, and we don't care, don't do it. return 0 - var/turf/under //May be a path or a turf - var/mutable_appearance/us = new(src) //We'll use this for changes later + var/turf/under // May be a path or a turf + var/mutable_appearance/us = new(src) // We'll use this for changes later us.underlays.Cut() - //Mapper wanted something specific + // Mapper wanted something specific if(under_turf) under = under_turf - //Well if this isn't our first rodeo, we know EXACTLY what we landed on, and it looks like this. + // Well if this isn't our first rodeo, we know EXACTLY what we landed on, and it looks like this. if(landed_holder && !interior_corner) var/mutable_appearance/landed_on = new(landed_holder) - landed_on.layer = FLOAT_LAYER //Not turf - landed_on.plane = FLOAT_PLANE //Not turf + landed_on.layer = FLOAT_LAYER // Not turf + landed_on.plane = FLOAT_PLANE // Not turf us.underlays = list(landed_on) appearance = us return @@ -115,9 +115,9 @@ var/turf/T2 var/turf/T3 - T1 = get_step(src, turn(join_flags,135)) // 45 degrees before opposite - T2 = get_step(src, turn(join_flags,225)) // 45 degrees beyond opposite - T3 = get_step(src, turn(join_flags,180)) // Opposite from the diagonal + T1 = get_step(src, turn(join_flags,135)) // 45 degrees before opposite + T2 = get_step(src, turn(join_flags,225)) // 45 degrees beyond opposite + T3 = get_step(src, turn(join_flags,180)) // Opposite from the diagonal if(isfloor(T1) && ((T1.type == T2.type) || (T1.type == T3.type))) under = T1 @@ -129,21 +129,21 @@ under = get_base_turf_by_area(src) if(istype(under,/turf/simulated/shuttle)) - interior_corner = 1 //Prevents us from 'landing on grass' and having interior corners update. + interior_corner = 1 // Prevents us from 'landing on grass' and having interior corners update. var/mutable_appearance/under_ma - if(ispath(under)) //It's just a mapper-specified path + if(ispath(under)) // It's just a mapper-specified path under_ma = new() under_ma.icon = initial(under.icon) under_ma.icon_state = initial(under.icon_state) under_ma.color = initial(under.color) - else //It's a real turf + else // It's a real turf under_ma = new(under) if(under_ma) - if(ispath(under,/turf/space)) //Scramble space turfs + if(ispath(under,/turf/space)) // Scramble space turfs under_ma.icon_state = "[rand(1,25)]" us.underlays = list(under_ma) @@ -182,7 +182,7 @@ icon_state = "alienpod1" light_range = 3 light_power = 0.6 - light_color = "#66ffff" // Bright cyan. + light_color = "#66ffff" // Bright cyan. block_tele = TRUE /turf/simulated/shuttle/floor/alien/Initialize() @@ -193,7 +193,7 @@ icon_state = "alienplating" block_tele = TRUE -/turf/simulated/shuttle/floor/alienplating/external // For the outer rim of the UFO, to avoid active edges. +/turf/simulated/shuttle/floor/alienplating/external // For the outer rim of the UFO, to avoid active edges. // The actual temperature adjustment is defined if the SC or other future map is compiled. /turf/simulated/shuttle/plating @@ -204,13 +204,13 @@ /turf/simulated/shuttle/plating/airless initial_gas_mix = GAS_STRING_VACUUM -//For 'carrying' otherwise empty turfs or stuff in space turfs with you or having holes in the floor or whatever. +// For 'carrying' otherwise empty turfs or stuff in space turfs with you or having holes in the floor or whatever. /turf/simulated/shuttle/plating/carry name = "carry turf" icon = 'icons/turf/shuttle_parts.dmi' icon_state = "carry" takes_underlays = 1 - blocks_air = 1 //I'd make these unsimulated but it just fucks with so much stuff so many other places. + blocks_air = 1 // I'd make these unsimulated but it just fucks with so much stuff so many other places. /turf/simulated/shuttle/plating/carry/Initialize() . = ..() @@ -227,10 +227,10 @@ . = ..() icon_state = "carry_ingame" -/turf/simulated/shuttle/plating/skipjack //Skipjack plating +/turf/simulated/shuttle/plating/skipjack // Skipjack plating initial_gas_mix = GAS_STRING_STP_NITROGEN -/turf/simulated/shuttle/floor/skipjack //Skipjack floors +/turf/simulated/shuttle/floor/skipjack // Skipjack floors name = "skipjack floor" icon_state = "floor_dred" initial_gas_mix = GAS_STRING_STP_NITROGEN @@ -247,7 +247,7 @@ name = "voidcraft tiles" icon_state = "void_light" -/turf/simulated/shuttle/floor/voidcraft/external // For avoiding active edges. +/turf/simulated/shuttle/floor/voidcraft/external // For avoiding active edges. // The actual temperature adjustment is defined if the SC or other future map is compiled. /turf/simulated/shuttle/floor/voidcraft/external/dark diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index a0a8b15a7e0..f46453fcfbc 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -19,11 +19,14 @@ /turf/space/is_space() return 1 -// override for space turfs, since they should never hide anything +// Override for space turfs, since they should never hide anything /turf/space/levelupdate() for(var/obj/O in src) O.hide(0) +/turf/space/is_solid_structure() + return locate(/obj/structure/lattice, src) // Counts as solid structure if it has a lattice + /turf/space/proc/update_starlight() if(!config_legacy.starlight) return @@ -66,7 +69,7 @@ // Patch holes in the ceiling if(T) if(istype(T, /turf/simulated/open) || istype(T, /turf/space)) - // Must be build adjacent to an existing floor/wall, no floating floors + // Must be build adjacent to an existing floor/wall, no floating floors var/turf/simulated/A = locate(/turf/simulated/floor) in T.CardinalTurfs() if(!A) A = locate(/turf/simulated/wall) in T.CardinalTurfs() @@ -74,7 +77,7 @@ to_chat(user, "There's nothing to attach the ceiling to!") return - if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating + if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating T.ReplaceWithLattice() T.ChangeTurf(/turf/simulated/floor) playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 3ddf60b8a3c..00e5673480f 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -10,35 +10,35 @@ var/initial_gas_mix = GAS_STRING_TURF_DEFAULT // End - //Properties for airtight tiles (/wall) + // Properties for airtight tiles (/wall) var/thermal_conductivity = 0.05 var/heat_capacity = 1 - //Properties for both - var/temperature = T20C // Initial turf temperature. - var/blocks_air = 0 // Does this turf contain air/let air through? + // Properties for both + var/temperature = T20C // Initial turf temperature. + var/blocks_air = 0 // Does this turf contain air/let air through? // General properties. var/icon_old = null - var/pathweight = 1 // How much does it cost to pathfind over this turf? - var/blessed = 0 // Has the turf been blessed? + var/pathweight = 1 // How much does it cost to pathfind over this turf? + var/blessed = 0 // Has the turf been blessed? var/list/decals - var/movement_cost = 0 // How much the turf slows down movement, if any. + var/movement_cost = 0 // How much the turf slows down movement, if any. var/list/footstep_sounds = null - var/block_tele = FALSE // If true, most forms of teleporting to or from this turf tile will fail. + var/block_tele = FALSE // If true, most forms of teleporting to or from this turf tile will fail. var/can_build_into_floor = FALSE // Used for things like RCDs (and maybe lattices/floor tiles in the future), to see if a floor should replace it. - var/list/dangerous_objects // List of 'dangerous' objs that the turf holds that can cause something bad to happen when stepped on, used for AI mobs. + var/list/dangerous_objects // List of 'dangerous' objs that the turf holds that can cause something bad to happen when stepped on, used for AI mobs. /turf/Initialize(mapload) if(flags & INITIALIZED) stack_trace("Warning: [src]([type]) initialized multiple times!") flags |= INITIALIZED - // by default, vis_contents is inherited from the turf that was here before + // By default, vis_contents is inherited from the turf that was here before vis_contents.Cut() if(color) @@ -88,14 +88,12 @@ ComponentInitialize() - // VORESTATION EDIT - if(movement_cost && pathweight == 1) // This updates pathweight automatically. + if(movement_cost && pathweight == 1) // This updates pathweight automatically. pathweight = movement_cost if(dynamic_lighting) luminosity = 0 else luminosity = 1 - // VORE/POLARIS EDIT END return INITIALIZE_HINT_NORMAL @@ -117,7 +115,7 @@ */ if(force) ..() - //this will completely wipe turf state + // This will completely wipe turf state var/turf/B = new world.turf(src) for(var/A in B.contents) qdel(A) @@ -144,6 +142,10 @@ /turf/proc/is_intact() return 0 +// Used by shuttle code to check if this turf is empty enough to not crush want it lands on. +/turf/proc/is_solid_structure() + return 1 + /turf/attack_hand(mob/user) . = ..() user.move_pulled_towards(src) @@ -161,14 +163,14 @@ return FALSE var/list/viable_targets = list() - var/success = FALSE // Hitting something makes this true. If its still false, the miss sound is played. + var/success = FALSE // Hitting something makes this true. If its still false, the miss sound is played. for(var/mob/living/L in contents) - if(L == user) // Don't hit ourselves. + if(L == user) // Don't hit ourselves. continue viable_targets += L - if(!viable_targets.len) // No valid targets on this tile. + if(!viable_targets.len) // No valid targets on this tile. if(W.can_cleave) success = W.cleave(user, src) else @@ -178,7 +180,7 @@ user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src, no_attack_icons = TRUE) - if(!success) // Nothing got hit. + if(!success) // Nothing got hit. user.visible_message("\The [user] swipes \the [W] over \the [src].") playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1) return success @@ -259,7 +261,7 @@ return 1 return 0 -//expects an atom containing the reagents used to clean the turf +// Expects an atom containing the reagents used to clean the turf /turf/proc/clean(atom/source, mob/user) if(source.reagents.has_reagent("water", 1) || source.reagents.has_reagent("cleaner", 1)) clean_blood() @@ -271,7 +273,7 @@ qdel(O) else to_chat(user, "\The [source] is too dry to wash that.") - source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. + source.reagents.trans_to_turf(src, 1, 10) // 10 is the multiplier for the reaction effect. probably needed to wet the floor properly. /turf/proc/update_blood_overlays() return @@ -309,7 +311,7 @@ if(!istype(O)) return FALSE LAZYREMOVE(dangerous_objects, O) - UNSETEMPTY(dangerous_objects) // This nulls the list var if it's empty. + UNSETEMPTY(dangerous_objects) // This nulls the list var if it's empty. // color = "#00FF00" // This is all the way up here since its the common ancestor for things that need to get replaced with a floor when an RCD is used on them. diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm index 9c659eb9417..c7b76063c39 100644 --- a/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm +++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm @@ -11,14 +11,14 @@ return var/list/valid_shuttles = list() for (var/shuttle_tag in SSshuttle.shuttles) - if (istype(SSshuttle.shuttles[shuttle_tag], /datum/shuttle/ferry)) + if (istype(SSshuttle.shuttles[shuttle_tag], /datum/shuttle/autodock)) valid_shuttles += shuttle_tag var/shuttle_tag = input(user, "Which shuttle do you want to launch?") as null|anything in valid_shuttles if (!shuttle_tag) return - var/datum/shuttle/ferry/S = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/S = SSshuttle.shuttles[shuttle_tag] if (S.can_launch()) S.launch(user) log_and_message_admins("launched the [shuttle_tag] shuttle", user) diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm index cb2f8ce3fc3..7d82541876f 100644 --- a/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm +++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm @@ -11,14 +11,14 @@ return var/list/valid_shuttles = list() for (var/shuttle_tag in SSshuttle.shuttles) - if (istype(SSshuttle.shuttles[shuttle_tag], /datum/shuttle/ferry)) + if (istype(SSshuttle.shuttles[shuttle_tag], /datum/shuttle/autodock)) valid_shuttles += shuttle_tag var/shuttle_tag = input(user, "Which shuttle's launch do you want to force?") as null|anything in valid_shuttles if (!shuttle_tag) return - var/datum/shuttle/ferry/S = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/S = SSshuttle.shuttles[shuttle_tag] if (S.can_force()) S.force_launch(user) log_and_message_admins("forced the [shuttle_tag] shuttle", user) diff --git a/code/modules/admin/secrets/admin_secrets/move_shuttle.dm b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm index 8b18ff3d6af..b02a108cd64 100644 --- a/code/modules/admin/secrets/admin_secrets/move_shuttle.dm +++ b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm @@ -18,11 +18,11 @@ var/datum/shuttle/S = SSshuttle.shuttles[shuttle_tag] - var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!origin_area) return + var/destination_tag = input(user, "Which landmark do you want to jump to? (IF YOU GET THIS WRONG THINGS WILL BREAK)") as null|anything in SSshuttle.registered_shuttle_landmarks + if (!destination_tag) return - var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!destination_area) return + var/destination_location = SSshuttle.get_landmark(destination_tag) + if (!destination_location) return - S.move(origin_area, destination_area) + S.attempt_move(destination_location) log_and_message_admins("moved the [shuttle_tag] shuttle", user) diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index d82d31598b2..51c91de2363 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,13 +1,13 @@ /turf - var/dynamic_lighting = TRUE // Does the turf use dynamic lighting? - luminosity = 1 + var/dynamic_lighting = TRUE // Does the turf use dynamic lighting? + luminosity = 1 var/tmp/lighting_corners_initialised = FALSE - var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf. - var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay. + var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf. + var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay. var/tmp/list/datum/lighting_corner/corners - var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. + var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() @@ -16,7 +16,7 @@ /turf/proc/lighting_clear_overlay() if(lighting_overlay) - qdel(lighting_overlay) + qdel(lighting_overlay, force = TRUE) for(var/datum/lighting_corner/C in corners) C.update_active() @@ -34,7 +34,7 @@ new /atom/movable/lighting_overlay(src) for(var/datum/lighting_corner/C in corners) - if(!C.active) // We would activate the corner, calculate the lighting for it. + if(!C.active) // We would activate the corner, calculate the lighting for it. for(var/L in C.affecting) var/datum/light_source/S = L S.recalc_corner(C) @@ -50,7 +50,7 @@ for(var/datum/lighting_corner/L in corners) totallums += max(L.lum_r, L.lum_g, L.lum_b) - totallums /= 4 // 4 corners, max channel selected, return the average + totallums /= 4 // 4 corners, max channel selected, return the average totallums =(totallums - minlum) /(maxlum - minlum) @@ -59,7 +59,7 @@ // Can't think of a good name, this proc will recalculate the has_opaque_atom variable. /turf/proc/recalc_atom_opacity() has_opaque_atom = FALSE - for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...) + for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...) if(A.opacity) has_opaque_atom = TRUE @@ -68,19 +68,19 @@ ..() if(Obj && Obj.opacity) - has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. + has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. reconsider_lights() /turf/Exited(var/atom/movable/Obj, var/atom/newloc) ..() if(Obj && Obj.opacity) - recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates. + recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates. reconsider_lights() /turf/proc/get_corners() if(has_opaque_atom) - return null // Since this proc gets used in a for loop, null won't be looped though. + return null // Since this proc gets used in a for loop, null won't be looped though. return corners @@ -90,7 +90,7 @@ corners = list(null, null, null, null) for(var/i = 1 to 4) - if(corners[i]) // Already have a corner on this direction. + if(corners[i]) // Already have a corner on this direction. continue corners[i] = new /datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i]) diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 491bc06dd3f..b87a3c4233d 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -4,7 +4,7 @@ var/list/global/map_templates = list() /proc/load_map_templates() for(var/T in subtypesof(/datum/map_template)) var/datum/map_template/template = T - if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence. + if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence. continue template = new T() map_templates[template.name] = template @@ -13,22 +13,22 @@ var/list/global/map_templates = list() /datum/map_template var/name = "Default Template Name" var/desc = "Some text should go here. Maybe." - var/template_group = null // If this is set, no more than one template in the same group will be spawned, per submap seeding. + var/template_group = null // If this is set, no more than one template in the same group will be spawned, per submap seeding. var/width = 0 var/height = 0 var/mappath = null - var/loaded = 0 // Times loaded this round - var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. + var/loaded = 0 // Times loaded this round + var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. - var/cost = null // The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until \ + var/cost = null // The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until \ it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. \ Set to -1 to force the submap to always be made. - var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. - var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use. + var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. + var/discard_prob = 0 // If non-zero, there is a chance that the map seeding algorithm will skip this template when selecting potential templates to use. var/static/dmm_suite/maploader = new - var/fixed_orientation = FALSE //for ruins + var/fixed_orientation = FALSE // For ruins /// Zlevel traits var/list/ztraits @@ -49,13 +49,16 @@ var/list/global/map_templates = list() width = bounds[MAP_MAXY] height = bounds[MAP_MAXX] else - width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1 + width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1 height = bounds[MAP_MAXY] return bounds /datum/map_template/proc/initTemplateBounds(var/list/bounds) if (SSatoms.subsystem_initialized == INITIALIZATION_INSSATOMS) - return // let proper initialisation handle it later + return // Let proper initialisation handle it later + + var/prev_shuttle_queue_state = SSshuttle.block_init_queue + SSshuttle.block_init_queue = TRUE var/list/atom/atoms = list() var/list/area/areas = list() @@ -89,6 +92,9 @@ var/list/global/map_templates = list() var/area/A = I A.power_change() + SSshuttle.block_init_queue = prev_shuttle_queue_state + SSshuttle.process_init_queues() // We will flush the queue unless there were other blockers, in which case they will do it. + admin_notice("Submap initializations finished.", R_DEBUG) /datum/map_template/proc/load_new_z(var/centered = FALSE, var/orientation = SOUTH, list/traits = src.ztraits || list(ZTRAIT_AWAY = TRUE)) @@ -106,10 +112,10 @@ var/list/global/map_templates = list() // repopulate_sorted_areas() - //initialize things that are normally initialized after map load + // Initialize things that are normally initialized after map load initTemplateBounds(bounds) log_game("Z-level [name] loaded at at [x],[y],[world.maxz]") - on_map_loaded(world.maxz) //VOREStation Edit + on_map_loaded(world.maxz) return TRUE /datum/map_template/proc/load(turf/T, centered = FALSE, orientation = SOUTH) @@ -130,10 +136,10 @@ var/list/global/map_templates = list() if(!bounds) return -// if(!SSmapping.loading_ruins) //Will be done manually during mapping ss init +// if(!SSmapping.loading_ruins) // Will be done manually during mapping ss init // repopulate_sorted_areas() - //initialize things that are normally initialized after map load + // Initialize things that are normally initialized after map load initTemplateBounds(bounds) log_game("[name] loaded at at [T.x],[T.y],[T.z]") @@ -160,8 +166,8 @@ var/list/global/map_templates = list() admin_notice("Annihilated [deleted_atoms] objects.", R_DEBUG) -//for your ever biggening badminnery kevinz000 -//❤ - Cyberboss +// For your ever biggening badminnery kevinz000 +// ❤ - Cyberboss /proc/load_new_z_level(var/file, var/name, var/orientation = SOUTH) var/datum/map_template/template = new(file, name) template.load_new_z(orientation) @@ -180,20 +186,20 @@ var/list/global/map_templates = list() admin_notice("Z level [zl] does not exist - Not generating submaps", R_DEBUG) return - var/overall_sanity = 100 // If the proc fails to place a submap more than this, the whole thing aborts. - var/list/potential_submaps = list() // Submaps we may or may not place. - var/list/priority_submaps = list() // Submaps that will always be placed. + var/overall_sanity = 100 // If the proc fails to place a submap more than this, the whole thing aborts. + var/list/potential_submaps = list() // Submaps we may or may not place. + var/list/priority_submaps = list() // Submaps that will always be placed. // Lets go find some submaps to make. for(var/map in map_templates) var/datum/map_template/MT = map_templates[map] - if(!MT.allow_duplicates && MT.loaded > 0) // This probably won't be an issue but we might as well. + if(!MT.allow_duplicates && MT.loaded > 0) // This probably won't be an issue but we might as well. continue - if(!istype(MT, desired_map_template_type)) // Not the type wanted. + if(!istype(MT, desired_map_template_type)) // Not the type wanted. continue if(MT.discard_prob && prob(MT.discard_prob)) continue - if(MT.cost && MT.cost < 0) // Negative costs always get spawned. + if(MT.cost && MT.cost < 0) // Negative costs always get spawned. priority_submaps += MT else potential_submaps += MT @@ -201,7 +207,7 @@ var/list/global/map_templates = list() CHECK_TICK var/list/loaded_submap_names = list() - var/list/template_groups_used = list() // Used to avoid spawning three seperate versions of the same PoI. + var/list/template_groups_used = list() // Used to avoid spawning three seperate versions of the same PoI. // Now lets start choosing some. while(budget > 0 && overall_sanity > 0) @@ -209,12 +215,12 @@ var/list/global/map_templates = list() var/datum/map_template/chosen_template = null if(potential_submaps.len) - if(priority_submaps.len) // Do these first. + if(priority_submaps.len) // Do these first. chosen_template = pick(priority_submaps) else chosen_template = pick(potential_submaps) - else // We're out of submaps. + else // We're out of submaps. admin_notice("Submap loader had no submaps to pick from with [budget] left to spend.", R_DEBUG) break @@ -233,7 +239,7 @@ var/list/global/map_templates = list() continue // If so, try to place it. - var/specific_sanity = 100 // A hundred chances to place the chosen submap. + var/specific_sanity = 100 // A hundred chances to place the chosen submap. while(specific_sanity > 0) specific_sanity-- var/orientation = pick(cardinal) @@ -247,8 +253,8 @@ var/list/global/map_templates = list() for(var/turf/check in chosen_template.get_affected_turfs(T,TRUE,orientation)) var/area/new_area = get_area(check) if(!(istype(new_area, whitelist))) - valid = FALSE // Probably overlapping something important. - // world << "Invalid due to overlapping with area [new_area.type] at ([check.x], [check.y], [check.z]), when attempting to place at ([T.x], [T.y], [T.z])." + valid = FALSE // Probably overlapping something important. + // world << "Invalid due to overlapping with area [new_area.type] at ([check.x], [check.y], [check.z]), when attempting to place at ([T.x], [T.y], [T.z])." break CHECK_TICK @@ -260,7 +266,7 @@ var/list/global/map_templates = list() admin_notice("Submap \"[chosen_template.name]\" placed at ([T.x], [T.y], [T.z])\n", R_DEBUG) // Do loading here. - chosen_template.load(T, centered = TRUE, orientation=orientation) // This is run before the main map's initialization routine, so that can initilize our submaps for us instead. + chosen_template.load(T, centered = TRUE, orientation=orientation) // This is run before the main map's initialization routine, so that can initilize our submaps for us instead. CHECK_TICK @@ -279,12 +285,12 @@ var/list/global/map_templates = list() budget -= chosen_template.cost // Remove the submap from our options. - if(chosen_template in priority_submaps) // Always remove priority submaps. + if(chosen_template in priority_submaps) // Always remove priority submaps. priority_submaps -= chosen_template else if(!chosen_template.allow_duplicates) potential_submaps -= chosen_template - break // Load the next submap. + break // Load the next submap. var/list/pretty_submap_list = list() for(var/submap_name in loaded_submap_names) @@ -298,4 +304,4 @@ var/list/global/map_templates = list() admin_notice("Submap loader gave up with [budget] left to spend.", R_DEBUG) else admin_notice("Submaps loaded.", R_DEBUG) - admin_notice("Loaded: [english_list(pretty_submap_list)]", R_DEBUG) \ No newline at end of file + admin_notice("Loaded: [english_list(pretty_submap_list)]", R_DEBUG) diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index 3d24b0b6604..480d9b67f20 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -31,7 +31,7 @@ if(M && M.client) M.stop_all_music() // SHITTY HACK TO AVOID RACE CONDITION WITH SERVER REBOOT. - sleep(10) // TODO - Leshana - see if this is needed + sleep(10) // TODO see if this is needed // Update when moving between areas. // TODO - While this direct override might technically be faster, probably better code to use observer or hooks ~Leshana diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 148a181cfd2..6bbd29441f4 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -1,11 +1,11 @@ /turf/proc/CanZPass(atom/A, direction) - if(z == A.z) //moving FROM this turf - return direction == UP //can't go below + if(z == A.z) // Moving FROM this turf + return direction == UP //Can't go below else - if(direction == UP) //on a turf below, trying to enter + if(direction == UP) // On a turf below, trying to enter return 0 - if(direction == DOWN) //on a turf above, trying to enter - return !density && isopenspace(GetAbove(src)) // VOREStation Edit + if(direction == DOWN) // On a turf above, trying to enter + return !density && isopenspace(GetAbove(src)) /turf/simulated/open/CanZPass(atom, direction) return 1 @@ -24,8 +24,8 @@ desc = "\..." density = 0 plane = OPENSPACE_PLANE_START - pathweight = 100000 //Seriously, don't try and path over this one numbnuts - dynamic_lighting = 0 // Someday lets do proper lighting z-transfer. Until then we are leaving this off so it looks nicer. + pathweight = 100000 // Seriously, don't try and path over this one numbnuts + dynamic_lighting = 0 // Someday lets do proper lighting z-transfer. Until then we are leaving this off so it looks nicer. can_build_into_floor = TRUE var/turf/below @@ -55,13 +55,13 @@ below = GetBelow(src) GLOB.turf_changed_event.register(below, src, /atom/proc/update_icon) levelupdate() - below.update_icon() // So the 'ceiling-less' overlay gets added. + below.update_icon() // So the 'ceiling-less' overlay gets added. for(var/atom/movable/A in src) if(A.movement_type & GROUND) A.fall() SSopenspace.add_turf(src, 1) -// override to make sure nothing is hidden +// Override to make sure nothing is hidden /turf/simulated/open/levelupdate() for(var/obj/O in src) O.hide(0) @@ -92,11 +92,11 @@ underlays = list(bottom_turf) copy_overlays(below) - // get objects (not mobs, they are handled by /obj/zshadow) + // Get objects (not mobs, they are handled by /obj/zshadow) var/list/o_img = list() for(var/obj/O in below) - if(O.invisibility) continue // Ignore objects that have any form of invisibility - if(O.loc != below) continue // Ignore multi-turf objects not directly below + if(O.invisibility) continue // Ignore objects that have any form of invisibility + if(O.loc != below) continue // Ignore multi-turf objects not directly below var/image/temp2 = image(O, dir = O.dir, layer = O.layer) temp2.plane = src.plane temp2.color = O.color @@ -144,14 +144,14 @@ else to_chat(user, "The plating is going to need some support.") - //To lay cable. + // To lay cable. if(istype(C, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = C coil.turf_place(src, user) return return -//Most things use is_plating to test if there is a cover tile on top (like regular floors) +// Most things use is_plating to test if there is a cover tile on top (like regular floors) /turf/simulated/open/is_plating() return TRUE @@ -159,6 +159,9 @@ var/turf/below = GetBelow(src) return !below || below.is_space() +/turf/simulated/open/is_solid_structure() + return locate(/obj/structure/lattice, src) // Counts as solid structure if it has a lattice (same as space) + /turf/simulated/open/is_safe_to_enter(mob/living/L) if(L.can_fall()) if(!locate(/obj/structure/stairs) in GetBelow(src)) diff --git a/code/modules/overmap/_defines.dm b/code/modules/overmap/_defines.dm index 6d17d8e3981..53f97bd2bef 100644 --- a/code/modules/overmap/_defines.dm +++ b/code/modules/overmap/_defines.dm @@ -1,13 +1,64 @@ -//Zlevel where overmap objects should be +// Zlevel where overmap objects should be #define OVERMAP_ZLEVEL 1 -//How far from the edge of overmap zlevel could randomly placed objects spawn +// How far from the edge of overmap zlevel could randomly placed objects spawn #define OVERMAP_EDGE 7 -//list used to track which zlevels are being 'moved' by the proc below + + +// Dimension of overmap (squares 4 lyfe) +var/global/list/map_sectors = list() + +/area/overmap/ + name = "System Map" + icon_state = "start" + requires_power = 0 + base_turf = /turf/unsimulated/map + +/turf/unsimulated/map + icon = 'icons/turf/space.dmi' + icon_state = "map" + +/turf/unsimulated/map/edge + opacity = 1 + density = 1 + +/turf/unsimulated/map/New() + ..() + name = "[x]-[y]" + var/list/numbers = list() + + if(x == 1 || x == global.using_map.overmap_size) + numbers += list("[round(y/10)]","[round(y%10)]") + if(y == 1 || y == global.using_map.overmap_size) + numbers += "-" + if(y == 1 || y == global.using_map.overmap_size) + numbers += list("[round(x/10)]","[round(x%10)]") + + for(var/i = 1 to numbers.len) + var/image/I = image('icons/effects/numbers.dmi',numbers[i]) + I.pixel_x = 5*i - 2 + I.pixel_y = world.icon_size/2 - 3 + if(y == 1) + I.pixel_y = 3 + I.pixel_x = 5*i + 4 + if(y == global.using_map.overmap_size) + I.pixel_y = world.icon_size - 9 + I.pixel_x = 5*i + 4 + if(x == 1) + I.pixel_x = 5*i - 2 + if(x == global.using_map.overmap_size) + I.pixel_x = 5*i + 2 + overlays += I + + + + + +// List used to track which zlevels are being 'moved' by the proc below var/list/moving_levels = list() -//Proc to 'move' stars in spess -//yes it looks ugly, but it should only fire when state actually change. -//null direction stops movement +// Proc to 'move' stars in spess +// Yes it looks ugly, but it should only fire when state actually change. +// Null direction stops movement proc/toggle_move_stars(zlevel, direction) if(!zlevel) return @@ -35,6 +86,7 @@ proc/toggle_move_stars(zlevel, direction) AM.throw_at(get_step(T,reverse_direction(direction)), 5, 1) +/* //list used to cache empty zlevels to avoid nedless map bloat var/list/cached_space = list() @@ -99,3 +151,4 @@ proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A) testing("Catching [M] for future use") source.loc = null cached_space += source +*/ diff --git a/code/modules/overmap/helpers.dm b/code/modules/overmap/helpers.dm new file mode 100644 index 00000000000..e07be07ac02 --- /dev/null +++ b/code/modules/overmap/helpers.dm @@ -0,0 +1,5 @@ +/proc/get_overmap_sector(var/z) + if(using_map.use_overmap) + return map_sectors["[z]"] + else + return null diff --git a/code/modules/overmap/overmap_object.dm b/code/modules/overmap/overmap_object.dm new file mode 100644 index 00000000000..17a1262a821 --- /dev/null +++ b/code/modules/overmap/overmap_object.dm @@ -0,0 +1,38 @@ +/obj/effect/overmap + name = "map object" + icon = 'icons/obj/overmap.dmi' + icon_state = "object" + + var/known = 1 // Shows up on nav computers automatically + var/scannable // If set to TRUE will show up on ship sensors for detailed scans + +// Overlay of how this object should look on other skyboxes +/obj/effect/overmap/proc/get_skybox_representation() + return + +/obj/effect/overmap/proc/get_scan_data(mob/user) + return desc + +/obj/effect/overmap/Initialize() + . = ..() + if(!global.using_map.use_overmap) + return INITIALIZE_HINT_QDEL + + if(known) + //layer = ABOVE_LIGHTING_LAYER + plane = PLANE_LIGHTING_ABOVE + // TODO - Leshana HELM + // for(var/obj/machinery/computer/ship/helm/H in global.machines) + // H.get_known_sectors() +/* +TODO No need for this, we don't have skyboxes +/obj/effect/overmap/Crossed(var/obj/effect/overmap/visitable/other) + if(istype(other)) + for(var/obj/effect/overmap/visitable/O in loc) + SSskybox.rebuild_skyboxes(O.map_z) +/obj/effect/overmap/Uncrossed(var/obj/effect/overmap/visitable/other) + if(istype(other)) + SSskybox.rebuild_skyboxes(other.map_z) + for(var/obj/effect/overmap/visitable/O in loc) + SSskybox.rebuild_skyboxes(O.map_z) +*/ diff --git a/code/modules/overmap/sectors.dm b/code/modules/overmap/sectors.dm index 61a64283ed4..6942ebda7be 100644 --- a/code/modules/overmap/sectors.dm +++ b/code/modules/overmap/sectors.dm @@ -1,124 +1,137 @@ //=================================================================================== -//Hook for building overmap +//Overmap object representing zlevel(s) //=================================================================================== -var/global/list/map_sectors = list() - -/hook/startup/proc/build_map() - if(!config_legacy.use_overmap) - return 1 - testing("Building overmap...") - var/obj/effect/mapinfo/data - for(var/level in 1 to world.maxz) - data = locate("sector[level]") - if (data) - testing("Located sector \"[data.name]\" at [data.mapx],[data.mapy] corresponding to zlevel [level]") - map_sectors["[level]"] = new data.obj_type(data) - return 1 - -//=================================================================================== -//Metaobject for storing information about sector this zlevel is representing. -//Should be placed only once on every zlevel. -//=================================================================================== -/obj/effect/mapinfo/ - name = "map info metaobject" - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - invisibility = 101 - var/obj_type //type of overmap object it spawns - var/landing_area //type of area used as inbound shuttle landing, null if no shuttle landing area - var/zlevel - var/mapx //coordinates on the - var/mapy //overmap zlevel - var/known = 1 - -/obj/effect/mapinfo/New() - tag = "sector[z]" - zlevel = z - loc = null - -/obj/effect/mapinfo/sector - name = "generic sector" - obj_type = /obj/effect/map/sector - -/obj/effect/mapinfo/ship - name = "generic ship" - obj_type = /obj/effect/map/ship - - -//=================================================================================== -//Overmap object representing zlevel -//=================================================================================== - -/obj/effect/map +/obj/effect/overmap/visitable name = "map object" - icon = 'icons/obj/items.dmi' - icon_state = "sheet-plasteel" - var/map_z = 0 - var/area/shuttle/shuttle_landing - var/always_known = 1 + scannable = TRUE -/obj/effect/map/New(var/obj/effect/mapinfo/data) - map_z = data.zlevel - name = data.name - always_known = data.known - if (data.icon != 'icons/mob/screen1.dmi') - icon = data.icon - icon_state = data.icon_state - if(data.desc) - desc = data.desc - var/new_x = data.mapx ? data.mapx : rand(OVERMAP_EDGE, world.maxx - OVERMAP_EDGE) - var/new_y = data.mapy ? data.mapy : rand(OVERMAP_EDGE, world.maxy - OVERMAP_EDGE) - loc = locate(new_x, new_y, OVERMAP_ZLEVEL) + var/list/map_z = list() - if(data.landing_area) - shuttle_landing = locate(data.landing_area) + var/list/initial_generic_waypoints // Store landmark_tag of landmarks that should be added to the actual lists below on init. + var/list/initial_restricted_waypoints // For use with non-automatic landmarks (automatic ones add themselves). -/obj/effect/map/CanAllowThrough(atom/movable/A) - testing("[A] attempts to enter sector\"[name]\"") - return 1 + var/list/generic_waypoints = list() // Waypoints that any shuttle can use + var/list/restricted_waypoints = list() // Waypoints for specific shuttles + var/docking_codes -/obj/effect/map/Crossed(atom/movable/A) - testing("[A] has entered sector\"[name]\"") - if (istype(A,/obj/effect/map/ship)) - var/obj/effect/map/ship/S = A - S.current_sector = src + var/start_x // Coordinates for self placing + var/start_y // Will use random values if unset -/obj/effect/map/Uncrossed(atom/movable/A) - testing("[A] has left sector\"[name]\"") - if (istype(A,/obj/effect/map/ship)) - var/obj/effect/map/ship/S = A - S.current_sector = null + var/base = 0 // Starting sector, counts as station_levels + var/in_space = 1 // Can be accessed via lucky EVA -/obj/effect/map/sector + var/hide_from_reports = FALSE + + var/has_distress_beacon + +/obj/effect/overmap/visitable/Initialize() + . = ..() + if(. == INITIALIZE_HINT_QDEL) + return + + find_z_levels() // This populates map_z and assigns z levels to the ship. + register_z_levels() // This makes external calls to update global z level information. + + if(!global.using_map.overmap_z) + build_overmap() + + start_x = start_x || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE) + start_y = start_y || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE) + + forceMove(locate(start_x, start_y, global.using_map.overmap_z)) + + docking_codes = "[ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))]" + + testing("Located sector \"[name]\" at [start_x],[start_y], containing Z [english_list(map_z)]") + + LAZYADD(SSshuttle.sectors_to_initialize, src) // Queued for further init. Will populate the waypoint lists; waypoints not spawned yet will be added in as they spawn. + SSshuttle.process_init_queues() + +// This is called later in the init order by SSshuttle to populate sector objects. Importantly for subtypes, shuttles will be created by then. +/obj/effect/overmap/visitable/proc/populate_sector_objects() + +// TODO Implement +///obj/effect/overmap/visitable/proc/get_areas() +// return get_filtered_areas(list(/proc/area_belongs_to_zlevels = map_z)) + +/obj/effect/overmap/visitable/proc/find_z_levels() + map_z = GetConnectedZlevels(z) + +/obj/effect/overmap/visitable/proc/register_z_levels() + for(var/zlevel in map_z) + map_sectors["[zlevel]"] = src + + global.using_map.player_levels |= map_z + if(!in_space) + global.using_map.sealed_levels |= map_z + if(base) + global.using_map.station_levels |= map_z + global.using_map.contact_levels |= map_z + global.using_map.map_levels |= map_z + +// Helper for init. +/obj/effect/overmap/visitable/proc/check_ownership(obj/object) + if((object.z in map_z) && !(get_area(object) in SSshuttle.shuttle_areas)) + return 1 + +// If shuttle_name is false, will add to generic waypoints; otherwise will add to restricted. Does not do checks. +/obj/effect/overmap/visitable/proc/add_landmark(obj/effect/shuttle_landmark/landmark, shuttle_name) + landmark.sector_set(src, shuttle_name) + if(shuttle_name) + LAZYADD(restricted_waypoints[shuttle_name], landmark) + else + generic_waypoints += landmark + +/obj/effect/overmap/visitable/proc/remove_landmark(obj/effect/shuttle_landmark/landmark, shuttle_name) + if(shuttle_name) + var/list/shuttles = restricted_waypoints[shuttle_name] + LAZYREMOVE(shuttles, landmark) + else + generic_waypoints -= landmark + +/obj/effect/overmap/visitable/proc/get_waypoints(var/shuttle_name) + . = list() + for(var/obj/effect/overmap/visitable/contained in src) + . += contained.get_waypoints(shuttle_name) + for(var/thing in generic_waypoints) + .[thing] = name + if(shuttle_name in restricted_waypoints) + for(var/thing in restricted_waypoints[shuttle_name]) + .[thing] = name + +/obj/effect/overmap/visitable/proc/generate_skybox() + return + +/obj/effect/overmap/visitable/sector name = "generic sector" desc = "Sector with some stuff in it." + icon_state = "sector" anchored = 1 -//Space stragglers go here +// Because of the way these are spawned, they will potentially have their invisibility adjusted by the turfs they are mapped on +// prior to being moved to the overmap. This blocks that. Use set_invisibility to adjust invisibility as needed instead. +/obj/effect/overmap/visitable/sector/hide() -/obj/effect/map/sector/temporary - name = "Deep Space" - icon_state = "" - always_known = 0 +/proc/build_overmap() + if(!global.using_map.use_overmap) + return 1 -/obj/effect/map/sector/temporary/New(var/nx, var/ny, var/nz) - loc = locate(nx, ny, OVERMAP_ZLEVEL) - map_z = nz - map_sectors["[map_z]"] = src - testing("Temporary sector at [x],[y] was created, corresponding zlevel is [map_z].") + testing("Building overmap...") + world.maxz++ + global.using_map.overmap_z = world.maxz -/obj/effect/map/sector/temporary/Destroy() - map_sectors["[map_z]"] = null - testing("Temporary sector at [x],[y] was deleted.") - if (can_die()) - testing("Associated zlevel disappeared.") - world.maxz-- + testing("Putting overmap on [global.using_map.overmap_z]") + var/area/overmap/A = new + for (var/square in block(locate(1,1,global.using_map.overmap_z), locate(global.using_map.overmap_size,global.using_map.overmap_size,global.using_map.overmap_z))) + var/turf/T = square + if(T.x == global.using_map.overmap_size || T.y == global.using_map.overmap_size) + T = T.ChangeTurf(/turf/unsimulated/map/edge) + else + T = T.ChangeTurf(/turf/unsimulated/map) + ChangeArea(T, A) -/obj/effect/map/sector/temporary/proc/can_die(var/mob/observer) - testing("Checking if sector at [map_z] can die.") - for(var/mob/M in player_list) - if(M != observer && M.z == map_z) - testing("There are people on it.") - return 0 + global.using_map.sealed_levels |= global.using_map.overmap_z + + testing("Overmap build complete.") return 1 diff --git a/code/modules/overmap/spacetravel.dm b/code/modules/overmap/spacetravel.dm new file mode 100644 index 00000000000..4b0734f50bd --- /dev/null +++ b/code/modules/overmap/spacetravel.dm @@ -0,0 +1,114 @@ +// List used to cache empty zlevels to avoid nedless map bloat +var/list/cached_space = list() + +// Space stragglers go here + +/obj/effect/overmap/visitable/sector/temporary + name = "Deep Space" + invisibility = 101 + known = 0 + +/obj/effect/overmap/visitable/sector/temporary/New(var/nx, var/ny, var/nz) + loc = locate(nx, ny, global.using_map.overmap_z) + x = nx + y = ny + map_z += nz + map_sectors["[nz]"] = src + testing("Temporary sector at [x],[y] was created, corresponding zlevel is [nz].") + +/obj/effect/overmap/visitable/sector/temporary/Destroy() + map_sectors["[map_z]"] = null + testing("Temporary sector at [x],[y] was deleted.") + +/obj/effect/overmap/visitable/sector/temporary/proc/can_die(var/mob/observer) + testing("Checking if sector at [map_z[1]] can die.") + for(var/mob/M in global.player_list) + if(M != observer && (M.z in map_z)) + testing("There are people on it.") + return 0 + return 1 + +proc/get_deepspace(x,y) + var/obj/effect/overmap/visitable/sector/temporary/res = locate(x,y,global.using_map.overmap_z) + if(istype(res)) + return res + else if(cached_space.len) + res = cached_space[cached_space.len] + cached_space -= res + res.x = x + res.y = y + return res + else + return new /obj/effect/overmap/visitable/sector/temporary(x, y, global.using_map.get_empty_zlevel()) + +/atom/movable/proc/lost_in_space() + for(var/atom/movable/AM in contents) + if(!AM.lost_in_space()) + return FALSE + return TRUE + +/mob/lost_in_space() + return isnull(client) + +/mob/living/carbon/human/lost_in_space() + return isnull(client) && !key && stat == DEAD + +proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A) + if (!T || !A) + return + + var/obj/effect/overmap/visitable/M = map_sectors["[T.z]"] + if (!M) + return + + if(A.lost_in_space()) + if(!QDELETED(A)) + qdel(A) + return + + var/nx = 1 + var/ny = 1 + var/nz = 1 + + if(T.x <= TRANSITIONEDGE) + nx = world.maxx - TRANSITIONEDGE - 2 + ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (A.x >= (world.maxx - TRANSITIONEDGE - 1)) + nx = TRANSITIONEDGE + 2 + ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (T.y <= TRANSITIONEDGE) + ny = world.maxy - TRANSITIONEDGE -2 + nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + else if (A.y >= (world.maxy - TRANSITIONEDGE - 1)) + ny = TRANSITIONEDGE + 2 + nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + testing("[A] spacemoving from [M] ([M.x], [M.y]).") + + var/turf/map = locate(M.x,M.y,global.using_map.overmap_z) + var/obj/effect/overmap/visitable/TM + for(var/obj/effect/overmap/visitable/O in map) + if(O != M && O.in_space && prob(50)) + TM = O + break + if(!TM) + TM = get_deepspace(M.x,M.y) + nz = pick(TM.map_z) + + var/turf/dest = locate(nx,ny,nz) + if(dest) + A.forceMove(dest) + if(ismob(A)) + var/mob/D = A + if(D.pulling) + D.pulling.forceMove(dest) + + if(istype(M, /obj/effect/overmap/visitable/sector/temporary)) + var/obj/effect/overmap/visitable/sector/temporary/source = M + if (source.can_die()) + testing("Caching [M] for future use") + source.forceMove(null) + cached_space += source diff --git a/code/modules/rogueminer_vr/zone_console.dm b/code/modules/rogueminer_vr/zone_console.dm index 815433e9ef6..19d37167089 100644 --- a/code/modules/rogueminer_vr/zone_console.dm +++ b/code/modules/rogueminer_vr/zone_console.dm @@ -17,14 +17,17 @@ var/debug = 0 var/debug_scans = 0 var/scanning = 0 - var/legacy_zone = 0 //Disable scanning and whatnot. + var/legacy_zone = 0 // Disable scanning and whatnot. var/obj/machinery/computer/shuttle_control/belter/shuttle_control /obj/machinery/computer/roguezones/Initialize() . = ..() + shuttle_control = locate(/obj/machinery/computer/shuttle_control/belter) + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/roguezones/LateInitialize() if(!rm_controller) rm_controller = new /datum/controller/rogue() - shuttle_control = locate(/obj/machinery/computer/shuttle_control/belter) /obj/machinery/computer/roguezones/attack_ai(mob/user as mob) return attack_hand(user) @@ -49,7 +52,7 @@ data["difficulty"] = rm_controller.diffstep_strs[rm_controller.diffstep] data["occupied"] = curZoneOccupied data["scanning"] = scanning - data["updated"] = world.time - rm_controller.last_scan < 200 //Very recently scanned (20 seconds) + data["updated"] = world.time - rm_controller.last_scan < 200 // Very recently scanned (20 seconds) data["debug"] = debug if(!shuttle_control) @@ -66,9 +69,9 @@ data["shuttle_at_station"] = 0 var/can_scan = 0 - if(chargePercent >= 100) //Keep having weird problems with these in one 'if' statement - if(shuttle_control && (shuttle_control.z in GLOB.using_map.belter_docked_z)) //Even though I put them all in parens to avoid OoO problems... - if(!curZoneOccupied) //Not sure why. + if(chargePercent >= 100) // Keep having weird problems with these in one 'if' statement + if(shuttle_control && (shuttle_control.z in GLOB.using_map.belter_docked_z)) // Even though I put them all in parens to avoid OoO problems... + if(!curZoneOccupied) // Not sure why. if(!scanning) can_scan = 1 @@ -104,31 +107,32 @@ /obj/machinery/computer/roguezones/proc/scan_for_new_zone() if(scanning) return - //Set some kinda scanning var to pause UI input on console + // Set some kinda scanning var to pause UI input on console rm_controller.last_scan = world.time scanning = 1 sleep(60) - //Break the shuttle temporarily. + // Break the shuttle temporarily. shuttle_control.shuttle_tag = null - //Build and get a new zone. + // Build and get a new zone. var/datum/rogue/zonemaster/ZM_target = rm_controller.prepare_new_zone() - //Update shuttle destination. - var/datum/shuttle/ferry/S = SSshuttle.shuttles["Belter"] - S.area_offsite = ZM_target.myshuttle + // Update shuttle destination. + var/datum/shuttle/autodock/ferry/S = SSshuttle.shuttles["Belter"] + S.landmark_offsite = ZM_target.myshuttle_landmark + S.next_location = S.get_location_waypoint(!S.location) - //Re-enable shuttle. + // Re-enable shuttle. shuttle_control.shuttle_tag = "Belter" - //Update rm_previous + // Update rm_previous rm_controller.previous_zone = rm_controller.current_zone - //Update rm_current + // Update rm_current rm_controller.current_zone = ZM_target - //Unset scanning + // Unset scanning scanning = 0 return @@ -139,13 +143,13 @@ /obj/machinery/computer/roguezones/proc/failsafe_shuttle_recall() if(!shuttle_control) - return // Shuttle computer has been destroyed + return // Shuttle computer has been destroyed if (!(shuttle_control.z in GLOB.using_map.belter_belt_z)) - return // Usable only when shuttle is away + return // Usable only when shuttle is away if(rm_controller.current_zone && rm_controller.current_zone.is_occupied()) - return // Not usable if shuttle is in occupied zone + return // Not usable if shuttle is in occupied zone // Okay do it - var/datum/shuttle/ferry/S = SSshuttle.shuttles["Belter"] + var/datum/shuttle/autodock/ferry/S = SSshuttle.shuttles["Belter"] S.launch(usr) /obj/item/circuitboard/roguezones @@ -169,4 +173,4 @@ When a new zone has been scanned, your station's shuttle destination will be updated to direct it to the newly discovered area automatically.
You can then travel to the new area to mine in that location.

- This technology produced under license from Thinktronic Systems, LTD."} \ No newline at end of file + This technology produced under license from Thinktronic Systems, LTD."} diff --git a/code/modules/rogueminer_vr/zonemaster.dm b/code/modules/rogueminer_vr/zonemaster.dm index acdb707ba12..e0ee925ea78 100644 --- a/code/modules/rogueminer_vr/zonemaster.dm +++ b/code/modules/rogueminer_vr/zonemaster.dm @@ -4,36 +4,39 @@ ////////////////////////////// /datum/rogue/zonemaster - //our area + // Our area var/area/asteroid/rogue/myarea - var/area/shuttle/belter/myshuttle + // var/area/shuttle/belter/myshuttle + var/obj/effect/shuttle_landmark/myshuttle_landmark //world.time var/prepared_at = 0 - //accepting shuttles + // Accepting shuttles var/ready = 0 - //completely empty + // Completely empty var/clean = 1 - //scored or not + // Scored or not var/scored = 0 - //for scoring + // For scoring var/list/mineral_rocks = list() var/list/spawned_mobs = list() var/original_mobs = 0 - //in-use spawns from the area + // In-use spawns from the area var/obj/asteroid_spawner/list/rockspawns = list() var/obj/rogue_mobspawner/list/mobspawns = list() /datum/rogue/zonemaster/New(var/area/A) ASSERT(A) myarea = A - myshuttle = locate(myarea.shuttle_area) - spawn(10) //This is called from controller New() and freaks out if this calls back too fast. + myshuttle_landmark = locate(/obj/effect/shuttle_landmark) in myarea + if(!istype(myshuttle_landmark)) + warning("Zonemaster cannot find a shuttle landmark in its area '[A]'") + spawn(10) // This is called from controller New() and freaks out if this calls back too fast. rm_controller.mark_clean(src) /////////////////////////////// @@ -43,10 +46,10 @@ /datum/rogue/zonemaster/proc/is_occupied() var/humans = 0 for(var/mob/living/carbon/human/H in human_mob_list) - if(H.stat >= DEAD) //Conditions for exclusion here, like if disconnected people start blocking it. + if(H.stat >= DEAD) // Conditions for exclusion here, like if disconnected people start blocking it. continue var/area/A = get_area(H) - if((A == myarea) || (A == myshuttle)) //The loc of a turf is the area it is in. + if(A == myarea) // The loc of a turf is the area it is in. humans++ return humans @@ -54,7 +57,7 @@ ///// Asteroid Generation ///// /////////////////////////////// /datum/rogue/zonemaster/proc/generate_asteroid(var/core_min = 2, var/core_max = 5) - //Chance for a predefined structure instead, more common later + // Chance for a predefined structure instead, more common later if(prob(rm_controller.diffstep*4)) rm_controller.dbg("ZM(ga): Fell into prefab asteroid chance.") var/prefab = pick(rm_controller.prefabs["tier[rm_controller.diffstep]"]) @@ -65,47 +68,47 @@ var/datum/rogue/asteroid/A = new(rand(core_min,core_max)) rm_controller.dbg("ZM(ga): New asteroid with C:[A.coresize], TW:[A.type_wall].") - //Add the core to the asteroid's map + // Add the core to the asteroid's map rm_controller.dbg("ZM(ga): Starting core generation for [A.coresize] size core..") for(var/x = 1; x <= A.coresize, x++) for(var/y = 1; y <= A.coresize, y++) rm_controller.dbg("ZM(ga): Doing core-relative [x],[y] at [A.coresize+x],[A.coresize+y], [A.type_wall].") A.spot_add(A.coresize+x, A.coresize+y, A.type_wall) - var/max_armlen = A.coresize - 1 //Can tweak to change appearance. + var/max_armlen = A.coresize - 1 // Can tweak to change appearance. - //Add the arms to the asteroid's map - //Vertical arms - for(var/x = A.coresize+1, x <= A.coresize*2, x++) //Start at leftmost side of core, work towards higher X. + // Add the arms to the asteroid's map + // Vertical arms + for(var/x = A.coresize+1, x <= A.coresize*2, x++) // Start at leftmost side of core, work towards higher X. rm_controller.dbg("ZM(ga): Vert arms. My current column is x:[x].") var/B_arm = rand(0,max_armlen) var/T_arm = rand(0,max_armlen) rm_controller.dbg("ZM(ga): B/T. Going to make B:[B_arm], T:[T_arm] for x:[x].") - //Bottom arm - for(var/y = A.coresize, y > A.coresize-B_arm, y--) //Start at bottom edge of the core, work towards lower Y. + // Bottom arm + for(var/y = A.coresize, y > A.coresize-B_arm, y--) // Start at bottom edge of the core, work towards lower Y. A.spot_add(x,y,A.type_wall) - //Top arm - for(var/y = (A.coresize*2)+1, y < ((A.coresize*2)+1)+T_arm, y++) //Start at top edge of the core, work towards higher Y. + // Top arm + for(var/y = (A.coresize*2)+1, y < ((A.coresize*2)+1)+T_arm, y++) // Start at top edge of the core, work towards higher Y. A.spot_add(x,y,A.type_wall) - //Horizontal arms - for(var/y = A.coresize+1, y <= A.coresize*2, y++) //Start at lower side of core, work towards higher Y. + // Horizontal arms + for(var/y = A.coresize+1, y <= A.coresize*2, y++) // Start at lower side of core, work towards higher Y. rm_controller.dbg("ZM(ga): Horiz arms. My current row is y:[y].") var/R_arm = rand(0,max_armlen) var/L_arm = rand(0,max_armlen) rm_controller.dbg("ZM(ga): R/L. Going to make R:[R_arm], L:[L_arm] for y:[y].") - //Right arm - for(var/x = (A.coresize*2)+1, x <= ((A.coresize*2)+1)+R_arm, x++) //Start at right edge of core, work towards higher X. + // Right arm + for(var/x = (A.coresize*2)+1, x <= ((A.coresize*2)+1)+R_arm, x++) // Start at right edge of core, work towards higher X. A.spot_add(x,y,A.type_wall) - //Left arm - for(var/x = A.coresize, x > A.coresize-L_arm, x--) //Start at left edge of core, work towards lower X. + // Left arm + for(var/x = A.coresize, x > A.coresize-L_arm, x--) // Start at left edge of core, work towards lower X. A.spot_add(x,y,A.type_wall) - //Diagonals + // Diagonals // hao do rm_controller.dbg("ZM(ga): Asteroid generation done.") @@ -117,7 +120,7 @@ rm_controller.dbg("ZM(pa): Placing at point [SP.x],[SP.y],[SP.z].") SP.myasteroid = A - //Bottom-left corner of our bounding box + // Bottom-left corner of our bounding box var/BLx = SP.x - (A.width/2) var/BLy = SP.y - (A.width/2) rm_controller.dbg("ZM(pa): BLx is [BLx], BLy is [BLy].") @@ -140,10 +143,10 @@ for(var/T in curr_y) rm_controller.dbg("ZM(pa): Doing entry [T] in Y-list [Iy].") - if(ispath(T,/turf)) //We're spawning a turf + if(ispath(T,/turf)) // We're spawning a turf rm_controller.dbg("ZM(pa): Turf-generate mode.") - //Make sure we locate()'d a turf and not something else + // Make sure we locate()'d a turf and not something else if(!isturf(spot)) spot = get_turf(spot) var/turf/P = spot @@ -155,7 +158,7 @@ place_resources(newturf) newturf.update_icon(1) - else //Anything not a turf + else // Anything not a turf rm_controller.dbg("ZM(pa): Creating [T].") new T(spot) @@ -165,14 +168,14 @@ #define DIGSITESIZE_LOWER 4 #define DIGSITESIZE_UPPER 12 #define ARTIFACTSPAWNNUM_LOWER 6 - #define ARTIFACTSPAWNNUM_UPPER 12 //Replace with difficulty-based ones. + #define ARTIFACTSPAWNNUM_UPPER 12 // Replace with difficulty-based ones. - if(!M.mineral && prob(rm_controller.diffstep_chances[rm_controller.diffstep])) //Difficulty translates directly into ore chance + if(!M.mineral && prob(rm_controller.diffstep_chances[rm_controller.diffstep])) // Difficulty translates directly into ore chance rm_controller.dbg("ZM(par): Adding mineral to [M.x],[M.y].") M.make_ore(rm_controller.diffstep >= 3 ? 1 : 0) mineral_rocks += M - //If above difficulty threshold make rare ore instead (M.make_ore(1)) - //Increase with difficulty etc + // If above difficulty threshold make rare ore instead (M.make_ore(1)) + // Increase with difficulty etc if(!M.density) return @@ -232,17 +235,17 @@ archeo_turf.finds.Add(new /datum/find(digsite, rand(60, 140))) archeo_turf.finds.Add(new /datum/find(digsite, rand(150, 190))) - //sometimes a find will be close enough to the surface to show + // Sometimes a find will be close enough to the surface to show var/datum/find/F = archeo_turf.finds[1] if(F.excavation_required <= F.view_range) archeo_turf.archaeo_overlay = "overlay_archaeo[rand(1,3)]" archeo_turf.update_icon() - //have a chance for an artifact to spawn here, but not in animal or plant digsites + // Have a chance for an artifact to spawn here, but not in animal or plant digsites if(isnull(M.artifact_find) && digsite != DIGSITE_GARDEN && digsite != DIGSITE_ANIMAL) SSxenoarch.artifact_spawning_turfs.Add(archeo_turf) - //create artifact machinery + // Create artifact machinery var/num_artifacts_spawn = rand(ARTIFACTSPAWNNUM_LOWER, ARTIFACTSPAWNNUM_UPPER) while(SSxenoarch.artifact_spawning_turfs.len > num_artifacts_spawn) pick_n_take(SSxenoarch.artifact_spawning_turfs) @@ -256,13 +259,13 @@ #undef DIGSITESIZE_LOWER #undef DIGSITESIZE_UPPER #undef ARTIFACTSPAWNNUM_LOWER - #undef ARTIFACTSPAWNNUM_UPPER //Replace with difficulty-based ones. + #undef ARTIFACTSPAWNNUM_UPPER // Replace with difficulty-based ones. /////////////////////////////// ///// Zone Population ///////// /////////////////////////////// -//Overall 'prepare' proc (marks as ready) +// Overall 'prepare' proc (marks as ready) /datum/rogue/zonemaster/proc/prepare_zone(var/delay = 0) rm_controller.unmark_clean(src) rm_controller.dbg("ZM(p): Preparing zone with difficulty level [rm_controller.diffstep].") @@ -281,7 +284,7 @@ for(var/obj/rogue_mobspawner/SP in mobspawns) rm_controller.dbg("ZM(p): Spawning mob at [SP.x],[SP.y],[SP.z].") - //Make sure we can spawn a spacemob here + // Make sure we can spawn a spacemob here if(!istype(get_turf(SP),/turf/space)) rm_controller.dbg("ZM(p): Turf blocking mob spawn at [SP.x],[SP.y],[SP.z].") mobspawns -= SP @@ -307,7 +310,7 @@ rm_controller.mark_ready(src) return myarea -//Randomize the landmarks that are enabled +// Randomize the landmarks that are enabled /datum/rogue/zonemaster/proc/randomize_spawns(var/chance = 50) rm_controller.dbg("ZM(rs): Previously [rockspawns.len] rockspawns.") rockspawns.Cut() @@ -335,7 +338,7 @@ scored = 1 var/tally = bonus - //Ore-bearing rocks that were mined + // Ore-bearing rocks that were mined for(var/turf/T in mineral_rocks) var/has_minerals = 0 for(var/atom/I in T.contents) @@ -345,15 +348,15 @@ if(has_minerals == 0) tally += RM_DIFF_VALUE_ORE - mineral_rocks.Cut() //For good measure, to prevent rescoring. + mineral_rocks.Cut() // For good measure, to prevent rescoring. for(var/I = 1, I <= spawned_mobs.len, I++) if(isnull(spawned_mobs[I])) - tally += RM_DIFF_VALUE_MOB //Mobs so annihilated they were deleted + tally += RM_DIFF_VALUE_MOB // Mobs so annihilated they were deleted rm_controller.dbg("ZM(sz): Scoring one mob annihilated.") if(istype(spawned_mobs[I],/mob)) var/mob/M = spawned_mobs[I] - if(M.stat > 0) //Knocked out or dead or anything other than normal + if(M.stat > 0) // Knocked out or dead or anything other than normal tally += RM_DIFF_VALUE_MOB rm_controller.dbg("ZM(sz): Scoring one mob dead.") @@ -362,16 +365,16 @@ rm_controller.adjust_difficulty(tally) rm_controller.dbg("ZM(sz): Finished scoring and adjusted by [tally].") - world.log << "RM(stats): SCORE [myarea] for [tally]." //DEBUG code for playtest stats gathering. + world.log << "RM(stats): SCORE [myarea] for [tally]." // DEBUG code for playtest stats gathering. return tally -//Overall 'destroy' proc (marks as unready) +// Overall 'destroy' proc (marks as unready) /datum/rogue/zonemaster/proc/clean_zone(var/delay = 1) rm_controller.dbg("ZM(cz): Cleaning zone with area [myarea].") - world.log << "RM(stats): CLEAN start [myarea] at [world.time] prepared at [prepared_at]." //DEBUG code for playtest stats gathering. + world.log << "RM(stats): CLEAN start [myarea] at [world.time] prepared at [prepared_at]." // DEBUG code for playtest stats gathering. rm_controller.unmark_ready(src) - //Cut these lists so qdel can dereference the things properly + // Cut these lists so qdel can dereference the things properly mineral_rocks.Cut() spawned_mobs.Cut() rockspawns.Cut() @@ -380,6 +383,7 @@ var/ignored = list( /obj/asteroid_spawner, /obj/rogue_mobspawner, + /obj/effect/shuttle_landmark, /obj/effect/step_trigger/teleporter/roguemine_loop/north, /obj/effect/step_trigger/teleporter/roguemine_loop/south, /obj/effect/step_trigger/teleporter/roguemine_loop/east, @@ -389,27 +393,31 @@ if(I.type == /turf/space) I.overlays.Cut() continue + else if(!I.simulated) + continue else if(I.type in ignored) continue qdel(I) sleep(delay) - //A deletion so nice that I give it twice + // A deletion so nice that I give it twice for(var/atom/I in myarea.contents) if(I.type == /turf/space) I.overlays.Cut() continue + else if(!I.simulated) + continue else if(I.type in ignored) continue qdel(I) sleep(delay) - //Clean up vars + // Clean up vars scored = 0 original_mobs = 0 prepared_at = 0 - world.log << "RM(stats): CLEAN done [myarea] at [world.time]." //DEBUG code for playtest stats gathering. + world.log << "RM(stats): CLEAN done [myarea] at [world.time]." // DEBUG code for playtest stats gathering. rm_controller.dbg("ZM(cz): Finished cleaning up zone area [myarea].") rm_controller.mark_clean(src) @@ -419,4 +427,4 @@ ///// Mysterious Mystery ////// /////////////////////////////// -//Throw a meteor at a player in the zone \ No newline at end of file +// Throw a meteor at a player in the zone diff --git a/code/modules/shuttles/_defines.dm b/code/modules/shuttles/_defines.dm index ad8c39466b4..f1928b3ff44 100644 --- a/code/modules/shuttles/_defines.dm +++ b/code/modules/shuttles/_defines.dm @@ -1,4 +1,22 @@ -#define SHUTTLE_FLAGS_NONE 0 -#define SHUTTLE_FLAGS_PROCESS 1 -#define SHUTTLE_FLAGS_SUPPLY 2 -#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE) \ No newline at end of file +// Shuttle flags +#define SHUTTLE_FLAGS_NONE 0 +#define SHUTTLE_FLAGS_PROCESS 1 // Should be processed by shuttle subsystem +#define SHUTTLE_FLAGS_SUPPLY 2 // This is the supply shuttle. Why is this a tag? +#define SHUTTLE_FLAGS_ZERO_G 4 // Shuttle has no internal gravity generation +#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE) + +// shuttle_landmark flags +#define SLANDMARK_FLAG_AUTOSET 1 // If set, will set base area and turf type to same as where it was spawned at +#define SLANDMARK_FLAG_ZERO_G 2 // Zero-G shuttles moved here will lose gravity unless the area has ambient gravity. + +// Ferry shuttle location constants +#define FERRY_LOCATION_STATION 0 +#define FERRY_LOCATION_OFFSITE 1 +#define FERRY_GOING_TO_STATION 0 +#define FERRY_GOING_TO_OFFSITE 1 + +#ifndef DEBUG_SHUTTLES + #define log_shuttle(M) +#else + #define log_shuttle(M) log_debug("[M]") +#endif diff --git a/code/modules/shuttles/crashes.dm b/code/modules/shuttles/crashes.dm index 636bab0bcb2..08620b40210 100644 --- a/code/modules/shuttles/crashes.dm +++ b/code/modules/shuttles/crashes.dm @@ -3,47 +3,53 @@ // /datum/shuttle - var/list/crash_areas = null + var/list/crash_locations = null var/crash_message = "Oops. The shuttle blew up." // Announcement made when shuttle crashes /datum/shuttle/New() - if(crash_areas) - for(var/i in 1 to crash_areas.len) - crash_areas[i] = locate(crash_areas[i]) + if(crash_locations) + var/crash_location_ids = crash_locations + crash_locations = list() + for(var/location_tag in crash_location_ids) + var/obj/effect/shuttle_landmark/L = SSshuttle.get_landmark(location_tag) + if(L) + crash_locations += L ..() // Return 0 to let the jump continue, 1 to abort the jump. // Default implementation checks if the shuttle should crash and if so crashes it. -/datum/shuttle/proc/process_longjump(var/area/origin, var/area/intended_destination, var/direction) - if(should_crash()) - do_crash(origin) +/datum/shuttle/proc/process_longjump(var/obj/effect/shuttle_landmark/intended_destination) + if(should_crash(intended_destination)) + do_crash(intended_destination) return 1 // Decide if this is the time we crash. Return true for yes -/datum/shuttle/proc/should_crash(var/area/origin, var/area/intended_destination, var/direction) +/datum/shuttle/proc/should_crash(var/obj/effect/shuttle_landmark/intended_destination) return FALSE // Actually crash the shuttle -/datum/shuttle/proc/do_crash(var/area/source) +/datum/shuttle/proc/do_crash(var/obj/effect/shuttle_landmark/intended_destination) // Choose the target - var/area/target = pick(crash_areas) + var/obj/effect/shuttle_landmark/target = pick(crash_locations) ASSERT(istype(target)) // Blow up the target area? //command_announcement.Announce(departure_message,(announcer ? announcer : "[GLOB.using_map.boss_name]")) - //What people are we dealing with here + // What people are we dealing with here var/list/victims = list() - for(var/mob/living/L in source) - victims += L - spawn(0) - shake_camera(L,2 SECONDS,4) + for(var/area/A in shuttle_area) + for(var/mob/living/L in A) + victims += L + spawn(0) + shake_camera(L,2 SECONDS,4) - //SHAKA SHAKA SHAKA + // SHAKA SHAKA SHAKA sleep(2 SECONDS) // Move the shuttle - move(source, target) + if (!attempt_move(target)) + return // Lucky! // Hide people for(var/living in victims) @@ -54,9 +60,11 @@ L.loc = null // Blow up the shuttle - var/list/area_turfs = get_area_turfs(target) - var/turf/epicenter = pick(area_turfs) - var/boomsize = area_turfs.len / 10 // Bigger shuttle = bigger boom + var/list/shuttle_turfs = list() + for(var/area/A in shuttle_area) + shuttle_turfs += get_area_turfs(A) + var/turf/epicenter = pick(shuttle_turfs) + var/boomsize = shuttle_turfs.len / 10 // Bigger shuttle = bigger boom explosion(epicenter, 0, boomsize, boomsize*2, boomsize*3) moving_status = SHUTTLE_CRASHED command_announcement.Announce("[crash_message]", "Shuttle Alert") diff --git a/code/modules/shuttles/escape_pods.dm b/code/modules/shuttles/escape_pods.dm index 9ff0e8aa4c2..952e0ee41ff 100644 --- a/code/modules/shuttles/escape_pods.dm +++ b/code/modules/shuttles/escape_pods.dm @@ -1,57 +1,62 @@ -/datum/shuttle/ferry/escape_pod - var/datum/computer/file/embedded_program/docking/simple/escape_pod/arming_controller - category = /datum/shuttle/ferry/escape_pod +/datum/shuttle/autodock/ferry/escape_pod + var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/arming_controller + category = /datum/shuttle/autodock/ferry/escape_pod -/datum/shuttle/ferry/escape_pod/New() +/datum/shuttle/autodock/ferry/escape_pod/New() move_time = move_time + rand(-30, 60) if(name in SSshuttle.escape_pods) CRASH("An escape pod with the name '[name]' has already been defined.") SSshuttle.escape_pods[name] = src + ..() -/datum/shuttle/ferry/escape_pod/init_docking_controllers() - ..() - arming_controller = locate(dock_target_station) + // Find the arming controller (berth) - If not configured directly, try to read it from current location landmark + var/arming_controller_tag = arming_controller + if(!arming_controller && active_docking_controller) + arming_controller_tag = active_docking_controller.id_tag + arming_controller = SSshuttle.docking_registry[arming_controller_tag] if(!istype(arming_controller)) - warning("warning: escape pod with station dock tag [dock_target_station] could not find it's dock target!") + CRASH("Could not find arming controller for escape pod \"[name]\", tag was '[arming_controller_tag]'.") - if(docking_controller) - var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/controller_master = docking_controller.master - if(!istype(controller_master)) - warning("warning: escape pod with docking tag [docking_controller_tag] could not find its controller master!") - else - controller_master.pod = src + // Find the pod's own controller + var/datum/computer/file/embedded_program/docking/simple/prog = SSshuttle.docking_registry[docking_controller_tag] + var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/controller_master = prog.master + if(!istype(controller_master)) + CRASH("Escape pod \"[name]\" could not find it's controller master! docking_controller_tag=[docking_controller_tag]") + controller_master.pod = src -/datum/shuttle/ferry/escape_pod/can_launch() - if(arming_controller && !arming_controller.armed) //must be armed +/datum/shuttle/autodock/ferry/escape_pod/can_launch() + if(arming_controller && !arming_controller.armed) // Must be armed return 0 if(location) - return 0 //it's a one-way trip. + return 0 // It's a one-way trip. return ..() -/datum/shuttle/ferry/escape_pod/can_force() +/datum/shuttle/autodock/ferry/escape_pod/can_force() if (arming_controller.eject_time && world.time < arming_controller.eject_time + 50) - return 0 //dont allow force launching until 5 seconds after the arming controller has reached it's countdown + return 0 // Dont allow force launching until 5 seconds after the arming controller has reached it's countdown return ..() -/datum/shuttle/ferry/escape_pod/can_cancel() +/datum/shuttle/autodock/ferry/escape_pod/can_cancel() return 0 -//This controller goes on the escape pod itself +// This controller goes on the escape pod itself /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod name = "escape pod controller" - var/datum/shuttle/ferry/escape_pod/pod + program = /datum/computer/file/embedded_program/docking/simple + var/datum/shuttle/autodock/ferry/escape_pod/pod /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] + var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type data = list( "docking_status" = docking_program.get_docking_status(), "override_enabled" = docking_program.override_enabled, "door_state" = docking_program.memory["door_status"]["state"], "door_lock" = docking_program.memory["door_status"]["lock"], - "can_force" = pod.can_force() || (SSemergencyshuttle.departed && pod.can_launch()), //allow players to manually launch ahead of time if the shuttle leaves + "can_force" = pod.can_force() || (SSemergencyshuttle.departed && pod.can_launch()), // Allow players to manually launch ahead of time if the shuttle leaves "is_armed" = pod.arming_controller.armed, ) @@ -64,36 +69,34 @@ ui.set_auto_update(1) /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/Topic(href, href_list) - if(..()) - return 1 + if((. = ..())) + return if("manual_arm") pod.arming_controller.arm() + return TOPIC_REFRESH if("force_launch") if (pod.can_force()) pod.force_launch(src) - else if (SSemergencyshuttle.departed && pod.can_launch()) //allow players to manually launch ahead of time if the shuttle leaves + else if (SSemergencyshuttle.departed && pod.can_launch()) // Allow players to manually launch ahead of time if the shuttle leaves pod.launch(src) - + return TOPIC_REFRESH return 0 -//This controller is for the escape pod berth (station side) +// This controller is for the escape pod berth (station side) /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth name = "escape pod berth controller" - -/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/Initialize() - . = ..() - docking_program = new/datum/computer/file/embedded_program/docking/simple/escape_pod(src) - program = docking_program + program = /datum/computer/file/embedded_program/docking/simple/escape_pod_berth /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] + var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type var/armed = null - if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod)) - var/datum/computer/file/embedded_program/docking/simple/escape_pod/P = docking_program + if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth)) + var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = docking_program armed = P.armed data = list( @@ -114,44 +117,44 @@ if (!emagged) to_chat(user, "You emag the [src], arming the escape pod!") emagged = 1 - if (istype(docking_program, /datum/computer/file/embedded_program/docking/simple/escape_pod)) - var/datum/computer/file/embedded_program/docking/simple/escape_pod/P = docking_program + if (istype(program, /datum/computer/file/embedded_program/docking/simple/escape_pod_berth)) + var/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/P = program if (!P.armed) P.arm() return 1 -//A docking controller program for a simple door based docking port -/datum/computer/file/embedded_program/docking/simple/escape_pod +// A docking controller program for a simple door based docking port +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth var/armed = 0 - var/eject_delay = 10 //give latecomers some time to get out of the way if they don't make it onto the pod + var/eject_delay = 10 // Give latecomers some time to get out of the way if they don't make it onto the pod var/eject_time = null var/closing = 0 -/datum/computer/file/embedded_program/docking/simple/escape_pod/proc/arm() +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/proc/arm() if(!armed) armed = 1 open_door() -/datum/computer/file/embedded_program/docking/simple/escape_pod/receive_user_command(command) +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/receive_user_command(command) if (!armed) - return - ..(command) + return TRUE // Eat all commands. + return ..(command) -/datum/computer/file/embedded_program/docking/simple/escape_pod/process() +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/process() ..() if (eject_time && world.time >= eject_time && !closing) close_door() closing = 1 -/datum/computer/file/embedded_program/docking/simple/escape_pod/prepare_for_docking() +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/prepare_for_docking() return -/datum/computer/file/embedded_program/docking/simple/escape_pod/ready_for_docking() +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/ready_for_docking() return 1 -/datum/computer/file/embedded_program/docking/simple/escape_pod/finish_docking() - return //don't do anything - the doors only open when the pod is armed. +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/finish_docking() + return // Don't do anything - the doors only open when the pod is armed. -/datum/computer/file/embedded_program/docking/simple/escape_pod/prepare_for_undocking() +/datum/computer/file/embedded_program/docking/simple/escape_pod_berth/prepare_for_undocking() eject_time = world.time + eject_delay*10 diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm new file mode 100644 index 00000000000..3c6c9ffeccc --- /dev/null +++ b/code/modules/shuttles/landmarks.dm @@ -0,0 +1,187 @@ +// Making this separate from /obj/effect/landmark until that mess can be dealt with +/obj/effect/shuttle_landmark + name = "Nav Point" + icon = 'icons/effects/effects.dmi' + icon_state = "energynet" + anchored = 1 + unacidable = 1 + simulated = 0 + invisibility = 101 + + // ID of the landmark + var/landmark_tag + // ID of the controller on the dock side (intialize to id_tag, becomes reference) + var/datum/computer/file/embedded_program/docking/docking_controller + // Map of shuttle names to ID of controller used for this landmark for shuttles with multiple ones. + var/list/special_dock_targets + + // When the shuttle leaves this landmark, it will leave behind the base area, + // also used to determine if the shuttle can arrive here without obstruction + var/area/base_area + // Will also leave this type of turf behind if set. + var/turf/base_turf + // Name of the shuttle, null for generic waypoint + var/shuttle_restricted + // var/flags = 0 - Already defined on /atom ? Is it being used for anything? Can we reuse it safely? + +/obj/effect/shuttle_landmark/Initialize() + . = ..() + if(docking_controller) + . = INITIALIZE_HINT_LATELOAD + + if(flags & SLANDMARK_FLAG_AUTOSET) + base_area = get_area(src) + var/turf/T = get_turf(src) + if(T) + base_turf = T.type + else + base_area = locate(base_area || world.area) + + name = (name + " ([x],[y])") + SSshuttle.register_landmark(landmark_tag, src) + +/obj/effect/shuttle_landmark/LateInitialize() + if(!docking_controller) + return + var/docking_tag = docking_controller + docking_controller = SSshuttle.docking_registry[docking_tag] + if(!istype(docking_controller)) + log_error("Could not find docking controller for shuttle waypoint '[name]', docking tag was '[docking_tag]'.") + if(using_map.use_overmap) + var/obj/effect/overmap/visitable/location = map_sectors["[z]"] + if(location && location.docking_codes) + docking_controller.docking_codes = location.docking_codes + +/obj/effect/shuttle_landmark/forceMove() + var/obj/effect/overmap/visitable/map_origin = map_sectors["[z]"] + . = ..() + var/obj/effect/overmap/visitable/map_destination = map_sectors["[z]"] + if(map_origin != map_destination) + if(map_origin) + map_origin.remove_landmark(src, shuttle_restricted) + if(map_destination) + map_destination.add_landmark(src, shuttle_restricted) + +// Called when the landmark is added to an overmap sector. +/obj/effect/shuttle_landmark/proc/sector_set(var/obj/effect/overmap/visitable/O, shuttle_name) + shuttle_restricted = shuttle_name + +/obj/effect/shuttle_landmark/proc/is_valid(var/datum/shuttle/shuttle) + if(shuttle.current_location == src) + return FALSE + for(var/area/A in shuttle.shuttle_area) + var/list/translation = get_turf_translation(get_turf(shuttle.current_location), get_turf(src), A.contents) + if(check_collision(base_area, list_values(translation))) + return FALSE + var/conn = GetConnectedZlevels(z) + for(var/w in (z - shuttle.multiz) to z) + if(!(w in conn)) + return FALSE + return TRUE + +// This creates a graphical warning to where the shuttle is about to land in approximately five seconds. +/obj/effect/shuttle_landmark/proc/create_warning_effect(var/datum/shuttle/shuttle) + if(shuttle.current_location == src) + return // TOO LATE! + for(var/area/A in shuttle.shuttle_area) + var/list/translation = get_turf_translation(get_turf(shuttle.current_location), get_turf(src), A.contents) + for(var/T in list_values(translation)) + new /obj/effect/temporary_effect/shuttle_landing(T) // It'll delete itself when needed. + return + +// Should return a readable description of why not if it can't depart. +/obj/effect/shuttle_landmark/proc/cannot_depart(datum/shuttle/shuttle) + return FALSE + +/obj/effect/shuttle_landmark/proc/shuttle_departed(datum/shuttle/shuttle) + return + +/obj/effect/shuttle_landmark/proc/shuttle_arrived(datum/shuttle/shuttle) + return + +/proc/check_collision(area/target_area, list/target_turfs) + for(var/target_turf in target_turfs) + var/turf/target = target_turf + if(!target) + return TRUE // Collides with edge of map + if(target.loc != target_area) + return TRUE // Collides with another area + if(target.density) + return TRUE // Dense turf + return FALSE + +// +// Self-naming/numbering ones. +// +/obj/effect/shuttle_landmark/automatic + name = "Navpoint" + landmark_tag = "navpoint" + flags = SLANDMARK_FLAG_AUTOSET + +/obj/effect/shuttle_landmark/automatic/Initialize() + landmark_tag += "-[x]-[y]-[z]-[random_id("landmarks",1,9999)]" + return ..() + +/obj/effect/shuttle_landmark/automatic/sector_set(var/obj/effect/overmap/visitable/O) + ..() + name = ("[O.name] - [initial(name)] ([x],[y])") + +// Subtype that calls explosion on init to clear space for shuttles +/obj/effect/shuttle_landmark/automatic/clearing + var/radius = 10 + +/obj/effect/shuttle_landmark/automatic/clearing/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/shuttle_landmark/automatic/clearing/LateInitialize() + ..() + for(var/turf/T in range(radius, src)) + if(T.density) + T.ChangeTurf(get_base_turf_by_area(T)) + + +// Subtype that also queues a shuttle datum (for shuttles starting on maps loaded at runtime) +/obj/effect/shuttle_landmark/shuttle_initializer + var/datum/shuttle/shuttle_type + +/obj/effect/shuttle_landmark/shuttle_initializer/Initialize() + . = ..() + LAZYADD(SSshuttle.shuttles_to_initialize, shuttle_type) // Queue up for init. + +// +// Bluespace flare landmark beacon +// +/obj/item/device/spaceflare + name = "bluespace flare" + desc = "Burst transmitter used to broadcast all needed information for shuttle navigation systems. Has a flare attached for marking the spot where you probably shouldn't be standing." + icon_state = "bluflare" + light_color = "#3728ff" + var/active + +/obj/item/device/spaceflare/attack_self(var/mob/user) + if(!active) + visible_message("[user] pulls the cord, activating the [src].") + activate() + +/obj/item/device/spaceflare/proc/activate() + if(active) + return + var/turf/T = get_turf(src) + var/mob/M = loc + if(istype(M) && !M.unEquip(src, T)) + return + + active = 1 + anchored = 1 + + var/obj/effect/shuttle_landmark/automatic/mark = new(T) + mark.name = ("Beacon signal ([T.x],[T.y])") + T.hotspot_expose(1500, 5) + update_icon() + +/obj/item/device/spaceflare/update_icon() + . = ..() + if(active) + icon_state = "bluflare_on" + set_light(0.3, 0.1, 6, 2, "85d1ff") diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm index c1af96fdbe6..b5e05f1688e 100644 --- a/code/modules/shuttles/shuttle.dm +++ b/code/modules/shuttles/shuttle.dm @@ -1,6 +1,3 @@ -//These lists are populated in /datum/controller/subsystem/shuttles/proc/setup_shuttle_docks() -//Shuttle subsystem is instantiated in shuttles.dm. - //shuttle moving state defines are in setup.dm /datum/shuttle @@ -8,18 +5,56 @@ var/warmup_time = 0 var/moving_status = SHUTTLE_IDLE - var/docking_controller_tag //tag of the controller used to coordinate docking - var/datum/computer/file/embedded_program/docking/docking_controller //the controller itself. (micro-controller, not game controller) + var/list/shuttle_area // Initial value can be either a single area type or a list of area types + var/obj/effect/shuttle_landmark/current_location // This variable is type-abused initially: specify the landmark_tag, not the actual landmark. - var/arrive_time = 0 //the time at which the shuttle arrives when long jumping - var/depart_time = 0 //Similar to above, set when the shuttle leaves when long jumping, to compare against arrive time. - var/flags = SHUTTLE_FLAGS_PROCESS + var/tmp/arrive_time = 0 // The time at which the shuttle arrives when long jumping + var/flags = SHUTTLE_FLAGS_NONE + var/process_state = IDLE_STATE // Used with SHUTTLE_FLAGS_PROCESS, as well as to store current state. var/category = /datum/shuttle + var/multiz = 0 // How many multiz levels, starts at 0 TODO Leshana - Are we porting this? - var/ceiling_type = /turf/unsimulated/floor/shuttle_ceiling + var/ceiling_type // Type path of turf to roof over the shuttle when at multi-z landmarks. Ignored if null. -/datum/shuttle/New() + var/sound_takeoff = 'sound/effects/shuttles/shuttle_takeoff.ogg' + var/sound_landing = 'sound/effects/shuttles/shuttle_landing.ogg' + + var/knockdown = 1 // Whether shuttle downs non-buckled people when it moves + + var/defer_initialisation = FALSE // If this this shuttle should be initialised automatically. + // If set to true, you are responsible for initialzing the shuttle manually. + // Useful for shuttles that are initialized by map_template loading, or shuttles that are created in-game or not used. + + var/mothershuttle // Tag of mothershuttle + var/motherdock // Tag of mothershuttle landmark, defaults to starting location + + var/tmp/depart_time = 0 // Similar to above, set when the shuttle leaves when long jumping. Used for progress bars. + + // Future Thoughts: Baystation put "docking" stuff in a subtype, leaving base type pure and free of docking stuff. Is this best? + +/datum/shuttle/New(_name, var/obj/effect/shuttle_landmark/initial_location) ..() + if(_name) + src.name = _name + + var/list/areas = list() + if(!islist(shuttle_area)) + shuttle_area = list(shuttle_area) + for(var/T in shuttle_area) + var/area/A = locate(T) + if(!istype(A)) + CRASH("Shuttle \"[name]\" couldn't locate area [T].") + areas += A + shuttle_area = areas + + if(initial_location) + current_location = initial_location + else + current_location = SSshuttle.get_landmark(current_location) + if(!istype(current_location)) + log_debug("UM whoops, no initial? [src]") + CRASH("Shuttle '[name]' could not find its starting location landmark [current_location].") + if(src.name in SSshuttle.shuttles) CRASH("A shuttle with the name '[name]' is already defined.") SSshuttle.shuttles[src.name] = src @@ -31,25 +66,17 @@ SSsupply.shuttle = src /datum/shuttle/Destroy() + current_location = null SSshuttle.shuttles -= src.name SSshuttle.process_shuttles -= src + SSshuttle.shuttle_logs -= src if(SSsupply.shuttle == src) SSsupply.shuttle = null . = ..() -/datum/shuttle/process() - return - -/datum/shuttle/proc/init_docking_controllers() - if(docking_controller_tag) - docking_controller = locate(docking_controller_tag) - if(!istype(docking_controller)) - to_chat(world, "warning: shuttle with docking tag [docking_controller_tag] could not find its controller!") - // This creates a graphical warning to where the shuttle is about to land, in approximately five seconds. -/datum/shuttle/proc/create_warning_effect(area/landing_area) - for(var/turf/T in landing_area) - new /obj/effect/temporary_effect/shuttle_landing(T) // It'll delete itself when needed. +/datum/shuttle/proc/create_warning_effect(var/obj/effect/shuttle_landmark/destination) + destination.create_warning_effect(src) // Return false to abort a jump, before the 'warmup' phase. /datum/shuttle/proc/pre_warmup_checks() @@ -60,197 +87,273 @@ return TRUE // If you need an event to occur when the shuttle jumps in short or long jump, override this. -/datum/shuttle/proc/on_shuttle_departure(var/area/origin) - origin.shuttle_departed() +// Keep in mind that destination is the intended destination, the shuttle may or may not actually reach it.s +/datum/shuttle/proc/on_shuttle_departure(var/obj/effect/shuttle_landmark/origin, var/obj/effect/shuttle_landmark/destination) return // Similar to above, but when it finishes moving to the target. Short jump generally makes this occur immediately after the above proc. -/datum/shuttle/proc/on_shuttle_arrival(var/area/destination) - destination.shuttle_arrived() +// Keep in mind we might not actually have gotten to destination. Check current_location to be sure where we ended up. +/datum/shuttle/proc/on_shuttle_arrival(var/obj/effect/shuttle_landmark/origin, var/obj/effect/shuttle_landmark/destination) return -/datum/shuttle/proc/short_jump(var/area/origin,var/area/destination) +/datum/shuttle/proc/short_jump(var/obj/effect/shuttle_landmark/destination) if(moving_status != SHUTTLE_IDLE) return if(!pre_warmup_checks()) return + var/obj/effect/shuttle_landmark/start_location = current_location + // TODO - Figure out exactly when to play sounds. Before warmup_time delay? Should there be a sleep for waiting for sounds? or no? moving_status = SHUTTLE_WARMUP spawn(warmup_time*10) - make_sounds(origin, HYPERSPACE_WARMUP) + make_sounds(HYPERSPACE_WARMUP) create_warning_effect(destination) - sleep(5 SECONDS) // so the sound finishes. + sleep(5 SECONDS) // So the sound finishes. if(!post_warmup_checks()) - moving_status = SHUTTLE_IDLE + cancel_launch(null) + + if(!fuel_check()) //Fuel error (probably out of fuel) occured, so cancel the launch + cancel_launch(null) if (moving_status == SHUTTLE_IDLE) - make_sounds(origin, HYPERSPACE_END) - return //someone cancelled the launch + make_sounds(HYPERSPACE_END) + return // Someone cancelled the launch - on_shuttle_departure(origin) + moving_status = SHUTTLE_INTRANSIT // Shouldn't matter but just to be safe + on_shuttle_departure(start_location, destination) + + attempt_move(destination) - moving_status = SHUTTLE_INTRANSIT //shouldn't matter but just to be safe - move(origin, destination) moving_status = SHUTTLE_IDLE + on_shuttle_arrival(start_location, destination) - on_shuttle_arrival(destination) + make_sounds(HYPERSPACE_END) - make_sounds(destination, HYPERSPACE_END) - -/datum/shuttle/proc/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction) - //world << "shuttle/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]" +// TODO - Far Future - Would be great if this was driven by process too. +/datum/shuttle/proc/long_jump(var/obj/effect/shuttle_landmark/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time) + //to_world("shuttle/long_jump: current_location=[current_location], destination=[destination], interim=[interim], travel_time=[travel_time]") if(moving_status != SHUTTLE_IDLE) return if(!pre_warmup_checks()) return - //it would be cool to play a sound here + var/obj/effect/shuttle_landmark/start_location = current_location + // TODO - Figure out exactly when to play sounds. Before warmup_time delay? Should there be a sleep for waiting for sounds? or no? moving_status = SHUTTLE_WARMUP spawn(warmup_time*10) - make_sounds(departing, HYPERSPACE_WARMUP) - create_warning_effect(interim) // Really doubt someone is gonna get crushed in the interim area but for completeness's sake we'll make the warning. - sleep(5 SECONDS) // so the sound finishes. + make_sounds(HYPERSPACE_WARMUP) + create_warning_effect(interim) // Really doubt someone is gonna get crushed in the interim area but for completeness's sake we'll make the warning. + sleep(5 SECONDS) // So the sound finishes. if(!post_warmup_checks()) - moving_status = SHUTTLE_IDLE + cancel_launch(null) if (moving_status == SHUTTLE_IDLE) - make_sounds(departing, HYPERSPACE_END) - return //someone cancelled the launch + make_sounds(HYPERSPACE_END) + return // Someone cancelled the launch arrive_time = world.time + travel_time*10 - depart_time = world.time moving_status = SHUTTLE_INTRANSIT + on_shuttle_departure(start_location, destination) - on_shuttle_departure(departing) + if(attempt_move(interim, TRUE)) + interim.shuttle_arrived() - move(departing, interim, direction) - interim.shuttle_arrived() + if(process_longjump(current_location, destination)) //To hook custom shuttle code in + return //It handled it for us (shuttle crash or such) - if(process_longjump(departing, destination)) //VOREStation Edit - To hook custom shuttle code in - return //VOREStation Edit - It handled it for us (shuttle crash or such) + var/last_progress_sound = 0 + var/made_warning = FALSE + while (world.time < arrive_time) + // Make the shuttle make sounds every four seconds, since the sound file is five seconds. + if(last_progress_sound + 4 SECONDS < world.time) + make_sounds(HYPERSPACE_PROGRESS) + last_progress_sound = world.time - var/last_progress_sound = 0 - var/made_warning = FALSE - while (world.time < arrive_time) - // Make the shuttle make sounds every four seconds, since the sound file is five seconds. - if(last_progress_sound + 4 SECONDS < world.time) - make_sounds(interim, HYPERSPACE_PROGRESS) - last_progress_sound = world.time + if(arrive_time - world.time <= 5 SECONDS && !made_warning) + made_warning = TRUE + create_warning_effect(destination) + sleep(5) - if(arrive_time - world.time <= 5 SECONDS && !made_warning) - made_warning = TRUE - create_warning_effect(destination) - sleep(5) + if(!attempt_move(destination)) + attempt_move(start_location) // Try to go back to where we started. If that fails, I guess we're stuck in the interim location. - interim.shuttle_departed() - move(interim, destination, direction) + moving_status = SHUTTLE_IDLE + on_shuttle_arrival(start_location, destination) + make_sounds(HYPERSPACE_END) + +////////////////////////////// +// Forward declarations of public procs. They do nothing because this is not auto-dock. + +/datum/shuttle/proc/fuel_check() + return 1 // Fuel check should always pass in non-overmap shuttles (they have magic engines) + +/datum/shuttle/proc/cancel_launch(var/user) + // If we are past warming up its too late to cancel. + if (moving_status == SHUTTLE_WARMUP) moving_status = SHUTTLE_IDLE - on_shuttle_arrival(destination) - - make_sounds(destination, HYPERSPACE_END) - +/* + Docking stuff +*/ /datum/shuttle/proc/dock() - if (!docking_controller) - return - - var/dock_target = current_dock_target() - if (!dock_target) - return - - docking_controller.initiate_docking(dock_target) + return /datum/shuttle/proc/undock() - if (!docking_controller) - return - docking_controller.initiate_undocking() + return -/datum/shuttle/proc/current_dock_target() - return null +/datum/shuttle/proc/force_undock() + return -/datum/shuttle/proc/skip_docking_checks() - if (!docking_controller || !current_dock_target()) - return 1 //shuttles without docking controllers or at locations without docking ports act like old-style shuttles - return 0 +// Check if we are docked (or never dock) and thus have properly arrived. +/datum/shuttle/proc/check_docked() + return TRUE -//just moves the shuttle from A to B, if it can be moved -//A note to anyone overriding move in a subtype. move() must absolutely not, under any circumstances, fail to move the shuttle. -//If you want to conditionally cancel shuttle launches, that logic must go in short_jump() or long_jump() -/datum/shuttle/proc/move(var/area/origin, var/area/destination, var/direction=null) +// Check if we are undocked and thus probably ready to depart. +/datum/shuttle/proc/check_undocked() + return TRUE +/***************** +* Shuttle Moved Handling * (Observer Pattern Implementation: Shuttle Moved) +* Shuttle Pre Move Handling * (Observer Pattern Implementation: Shuttle Pre Move) +*****************/ + +// Move the shuttle to destination if possible. +// Returns TRUE if we actually moved, otherwise FALSE. +/datum/shuttle/proc/attempt_move(var/obj/effect/shuttle_landmark/destination, var/interim = FALSE) + if(current_location == destination) + log_shuttle("Shuttle [src] attempted to move to [destination] but is already there!") + return FALSE + + if(!destination.is_valid(src)) + log_shuttle("Shuttle [src] aborting attempt_move() because destination=[destination] is not valid") + return FALSE + if(current_location.cannot_depart(src)) + log_shuttle("Shuttle [src] aborting attempt_move() because current_location=[current_location] refuses.") + return FALSE + + log_shuttle("[src] moving to [destination]. Areas are [english_list(shuttle_area)]") + var/list/translation = list() + for(var/area/A in shuttle_area) + log_shuttle("Translating [A]") + translation += get_turf_translation(get_turf(current_location), get_turf(destination), A.contents) + var/old_location = current_location + + // Observer pattern pre-move + GLOB.shuttle_pre_move_event.raise_event(src, old_location, destination) + current_location.shuttle_departed(src) + + // Actually do it! (This never fails) + perform_shuttle_move(destination, translation) + + // Observer pattern post-move + destination.shuttle_arrived(src) + GLOB.shuttle_moved_event.raise_event(src, old_location, destination) + + return TRUE + +// Just moves the shuttle from A to B +// A note to anyone overriding move in a subtype. perform_shuttle_move() must absolutely not, under any circumstances, fail to move the shuttle. +// If you want to conditionally cancel shuttle launches, that logic must go in short_jump() or long_jump() +/datum/shuttle/proc/perform_shuttle_move(var/obj/effect/shuttle_landmark/destination, var/list/turf_translation) + log_shuttle("perform_shuttle_move() current=[current_location] destination=[destination]") //world << "move_shuttle() called for [name] leaving [origin] en route to [destination]." //world << "area_coming_from: [origin]" //world << "destination: [destination]" + ASSERT(current_location != destination) - if(origin == destination) - //world << "cancelling move, shuttle will overlap." - return + // If shuttle has no internal gravity, update our gravity with destination gravity + if((flags & SHUTTLE_FLAGS_ZERO_G)) + var/new_grav = 1 + if(destination.flags & SLANDMARK_FLAG_ZERO_G) + var/area/new_area = get_area(destination) + new_grav = new_area.has_gravity + for(var/area/our_area in shuttle_area) + if(our_area.has_gravity != new_grav) + our_area.gravitychange(new_grav) - if (docking_controller && !docking_controller.undocked()) - docking_controller.force_undock() + // TODO - Old code used to throw stuff out of the way instead of squashing. Should we? - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in destination) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - for(var/turf/T in dstturfs) - var/turf/D = locate(T.x, throwy - 1, T.z) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - - for(var/mob/living/carbon/bug in destination) - bug.gib() - - for(var/mob/living/simple_mob/pest in destination) - pest.gib() - - origin.move_contents_to(destination, direction=direction) - - for(var/mob/M in destination) - if(M.client) - spawn(0) - if(M.buckled) - to_chat(M, "Sudden acceleration presses you into \the [M.buckled]!") - shake_camera(M, 3, 1) + // Move, gib, or delete everything in our way! + for(var/turf/src_turf in turf_translation) + var/turf/dst_turf = turf_translation[src_turf] + if(src_turf.is_solid_structure()) // In case someone put a hole in the shuttle and you were lucky enough to be under it + for(var/atom/movable/AM in dst_turf) + //if(AM.movable_flags & MOVABLE_FLAG_DEL_SHUTTLE) + // qdel(AM) + // continue + if(!AM.simulated) + continue + if(isliving(AM)) + var/mob/living/bug = AM + bug.gib() else - to_chat(M, "The floor lurches beneath you!") - shake_camera(M, 10, 1) - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(3) + qdel(AM) //it just gets atomized I guess? TODO throw it into space somewhere, prevents people from using shuttles as an atom-smasher + + var/list/powernets = list() + for(var/area/A in shuttle_area) + // If there was a zlevel above our origin and we own the ceiling, erase our ceiling now we're leaving + if(ceiling_type && HasAbove(current_location.z)) + for(var/turf/TO in A.contents) + var/turf/TA = GetAbove(TO) + if(istype(TA, ceiling_type)) + TA.ChangeTurf(get_base_turf_by_area(TA), 1, 1) + if(knockdown) + for(var/mob/living/M in A) + spawn(0) + if(M.buckled) + to_chat(M, "Sudden acceleration presses you into \the [M.buckled]!") + shake_camera(M, 3, 1) + else + to_chat(M, "The floor lurches beneath you!") + shake_camera(M, 10, 1) + // TODO - tossing? + //M.visible_message("[M.name] is tossed around by the sudden acceleration!") + //M.throw_at_random(FALSE, 4, 1) + if(istype(M, /mob/living/carbon)) + M.Weaken(3) + // We only need to rebuild powernets for our cables. No need to check machines because they are on top of cables. + for(var/obj/structure/cable/C in A) + powernets |= C.powernet + + // Actually do the movement of everything - This replaces origin.move_contents_to(destination) + translate_turfs(turf_translation, current_location.base_area, current_location.base_turf) + current_location = destination + + // If there's a zlevel above our destination, paint in a ceiling on it so we retain our air + if(ceiling_type && HasAbove(current_location.z)) + for(var/area/A in shuttle_area) + for(var/turf/TD in A.contents) + var/turf/TA = GetAbove(TD) + if(istype(TA, get_base_turf_by_area(TA)) || isopenspace(TA)) + if(get_area(TA) in shuttle_area) + continue + TA.ChangeTurf(ceiling_type, TRUE, TRUE, TRUE) // Power-related checks. If shuttle contains power related machinery, update powernets. - var/update_power = 0 - for(var/obj/machinery/power/P in destination) - update_power = 1 - break + // Note: Old way was to rebuild ALL powernets: if(powernets.len) SSmachines.makepowernets() + // New way only rebuilds the powernets we have to + var/list/cables = list() + for(var/datum/powernet/P in powernets) + cables |= P.cables + qdel(P) + SSmachines.setup_powernets_for_cables(cables) - for(var/obj/structure/cable/C in destination) - update_power = 1 - break - - if(update_power) - SSmachines.makepowernets() return -//returns 1 if the shuttle has a valid arrive time +// Returns 1 if the shuttle has a valid arrive time /datum/shuttle/proc/has_arrive_time() return (moving_status == SHUTTLE_INTRANSIT) -/datum/shuttle/proc/make_sounds(var/area/A, var/sound_type) +/datum/shuttle/proc/make_sounds(var/sound_type) var/sound_to_play = null switch(sound_type) if(HYPERSPACE_WARMUP) @@ -259,9 +362,29 @@ sound_to_play = 'sound/effects/shuttles/hyperspace_progress.ogg' if(HYPERSPACE_END) sound_to_play = 'sound/effects/shuttles/hyperspace_end.ogg' - for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice - playsound(E, sound_to_play, 50, FALSE) + for(var/area/A in shuttle_area) + for(var/obj/machinery/door/E in A) // Dumb, I know, but playing it on the engines doesn't do it justice + playsound(E, sound_to_play, 50, FALSE) -/datum/shuttle/proc/message_passengers(area/A, var/message) - for(var/mob/M in A) - M.show_message(message, 2) +/datum/shuttle/proc/message_passengers(var/message) + for(var/area/A in shuttle_area) + for(var/mob/M in A) + M.show_message(message, 2) + +/datum/shuttle/proc/find_children() + . = list() + for(var/shuttle_name in SSshuttle.shuttles) + var/datum/shuttle/shuttle = SSshuttle.shuttles[shuttle_name] + if(shuttle.mothershuttle == name) + . += shuttle + +// Returns the areas in shuttle_area that are not actually child shuttles. +/datum/shuttle/proc/find_childfree_areas() + . = shuttle_area.Copy() + for(var/datum/shuttle/child in find_children()) + . -= child.shuttle_area + +/datum/shuttle/proc/get_location_name() + if(moving_status == SHUTTLE_INTRANSIT) + return "In transit" + return current_location.name diff --git a/code/modules/shuttles/shuttle_autodock.dm b/code/modules/shuttles/shuttle_autodock.dm new file mode 100644 index 00000000000..4218deacca2 --- /dev/null +++ b/code/modules/shuttles/shuttle_autodock.dm @@ -0,0 +1,220 @@ +#define DOCK_ATTEMPT_TIMEOUT 200 // How long in ticks we wait before assuming the docking controller is broken or blown up. + +// Subtype of shuttle that handles docking with docking controllers +// Consists of code pulled down from the old /datum/shuttle and up from /datum/shuttle/ferry +// Note: Since all known shuttles extend this type, this really could just be built into /datum/shuttle +// Why isn't it you ask? Eh, baystation did it this way and its convenient to keep the files smaller I guess. +/datum/shuttle/autodock + var/in_use = null // Tells the controller whether this shuttle needs processing, also attempts to prevent double-use + var/last_dock_attempt_time = 0 + + var/docking_controller_tag = null // ID of the controller on the shuttle (If multiple, this is the default one) + var/datum/computer/file/embedded_program/docking/shuttle_docking_controller // Controller on the shuttle (the one in use) + var/docking_codes + + var/tmp/obj/effect/shuttle_landmark/next_location //This is only used internally. + var/datum/computer/file/embedded_program/docking/active_docking_controller // Controller we are docked with (or trying to) + + var/obj/effect/shuttle_landmark/landmark_transition // This variable is type-abused initially: specify the landmark_tag, not the actual landmark. + var/move_time = 240 // The time spent in the transition area + + category = /datum/shuttle/autodock + flags = SHUTTLE_FLAGS_PROCESS | SHUTTLE_FLAGS_ZERO_G + +/datum/shuttle/autodock/New(var/_name, var/obj/effect/shuttle_landmark/start_waypoint) + ..(_name, start_waypoint) + + // Initial dock + active_docking_controller = current_location.docking_controller + update_docking_target(current_location) + if(active_docking_controller) + set_docking_codes(active_docking_controller.docking_codes) + else if(global.using_map.use_overmap) + var/obj/effect/overmap/visitable/location = map_sectors["[current_location.z]"] + if(location && location.docking_codes) + set_docking_codes(location.docking_codes) + dock() + + // Optional transition area + if(landmark_transition) + landmark_transition = SSshuttle.get_landmark(landmark_transition) + +/datum/shuttle/autodock/Destroy() + in_use = null + next_location = null + active_docking_controller = null + landmark_transition = null + + return ..() + +/datum/shuttle/autodock/proc/set_docking_codes(var/code) + docking_codes = code + if(shuttle_docking_controller) + shuttle_docking_controller.docking_codes = code + +/datum/shuttle/autodock/perform_shuttle_move() + force_undock() // Bye! Have a beautiful time! + ..() + +// Despite the name this actually updates the SHUTTLE docking conroller, not the active. +/datum/shuttle/autodock/proc/update_docking_target(var/obj/effect/shuttle_landmark/location) + var/current_dock_target + if(location && location.special_dock_targets && location.special_dock_targets[name]) + current_dock_target = location.special_dock_targets[name] + else + current_dock_target = docking_controller_tag + shuttle_docking_controller = SSshuttle.docking_registry[current_dock_target] + if(current_dock_target && !shuttle_docking_controller) + to_world("warning: shuttle [src] can't find its controller with tag [current_dock_target]!") +/* + Docking stuff +*/ +/datum/shuttle/autodock/dock() + if(active_docking_controller && shuttle_docking_controller) + shuttle_docking_controller.initiate_docking(active_docking_controller.id_tag) + last_dock_attempt_time = world.time + +/datum/shuttle/autodock/undock() + if(shuttle_docking_controller) + shuttle_docking_controller.initiate_undocking() + +/datum/shuttle/autodock/force_undock() + if(shuttle_docking_controller) + shuttle_docking_controller.force_undock() + +/datum/shuttle/autodock/check_docked() + if(shuttle_docking_controller) + return shuttle_docking_controller.docked() + return TRUE + +/datum/shuttle/autodock/check_undocked() + if(shuttle_docking_controller) + return shuttle_docking_controller.can_launch() + return TRUE + +// You also could just directly reference active_docking_controller +/datum/shuttle/autodock/proc/current_dock_target() + if(active_docking_controller) + return active_docking_controller.id_tag + return null + +// These checks are built into the check_docked() and check_undocked() procs +/datum/shuttle/autodock/proc/skip_docking_checks() + if (!shuttle_docking_controller || !current_dock_target()) + return TRUE // Shuttles without docking controllers or at locations without docking ports act like old-style shuttles + return FALSE + + +/* + Please ensure that long_jump() and short_jump() are only called from here. This applies to subtypes as well. + Doing so will ensure that multiple jumps cannot be initiated in parallel. +*/ +/datum/shuttle/autodock/process() + switch(process_state) + if (WAIT_LAUNCH) + if(check_undocked()) + //*** Ready to go + process_launch() + + if (FORCE_LAUNCH) + process_launch() + + if (WAIT_ARRIVE) + if (moving_status == SHUTTLE_IDLE) + //*** We made it to the destination, update stuff + process_arrived() + process_state = WAIT_FINISH + + if (WAIT_FINISH) + if (world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT || check_docked()) + //*** All done here + process_state = IDLE_STATE + arrived() + +// Not to be confused with the arrived() proc +/datum/shuttle/autodock/proc/process_arrived() + active_docking_controller = next_location.docking_controller + update_docking_target(next_location) + dock() + + next_location = null + in_use = null // Release lock + +/datum/shuttle/autodock/proc/get_travel_time() + return move_time + +/datum/shuttle/autodock/proc/process_launch() + if(!next_location || !next_location.is_valid(src) || current_location.cannot_depart(src)) + process_state = IDLE_STATE + in_use = null + return + if (get_travel_time() && landmark_transition) + . = long_jump(next_location, landmark_transition, get_travel_time()) + else + . = short_jump(next_location) + process_state = WAIT_ARRIVE + +/* + Guards - (These don't take docking status into account, just the state machine and move safety) +*/ +/datum/shuttle/autodock/proc/can_launch() + return (next_location && next_location.is_valid(src) && !current_location.cannot_depart(src) && moving_status == SHUTTLE_IDLE && !in_use) + +/datum/shuttle/autodock/proc/can_force() + return (next_location && next_location.is_valid(src) && !current_location.cannot_depart(src) && moving_status == SHUTTLE_IDLE && process_state == WAIT_LAUNCH) + +/datum/shuttle/autodock/proc/can_cancel() + return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH) + +/* + "Public" procs +*/ +// Queue shuttle for undock and launch by shuttle subsystem. +/datum/shuttle/autodock/proc/launch(var/user) + if (!can_launch()) return + + in_use = user // Obtain an exclusive lock on the shuttle + + process_state = WAIT_LAUNCH + undock() + +// Queue shuttle for forced undock and launch by shuttle subsystem. +/datum/shuttle/autodock/proc/force_launch(var/user) + if (!can_force()) return + + in_use = user // Obtain an exclusive lock on the shuttle + + process_state = FORCE_LAUNCH + +// Cancel queued launch. +/datum/shuttle/autodock/cancel_launch(var/user) + if (!can_cancel()) return + + moving_status = SHUTTLE_IDLE + process_state = WAIT_FINISH + in_use = null + + // Whatever we were doing with docking: stop it, then redock + force_undock() + spawn(1 SECOND) + dock() + +// Returns 1 if the shuttle is getting ready to move, but is not in transit yet +/datum/shuttle/autodock/proc/is_launching() + return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH) + +// /datum/shuttle/autodock/get_location_name() defined in shuttle.dm + +/datum/shuttle/autodock/proc/get_destination_name() + if(!next_location) + return "None" + return next_location.name + +// This gets called when the shuttle finishes arriving at it's destination +// This can be used by subtypes to do things when the shuttle arrives. +// Note that this is called when the shuttle leaves the WAIT_FINISHED state, the proc name is a little misleading +/datum/shuttle/autodock/proc/arrived() + return // Do nothing for now + +/obj/effect/shuttle_landmark/transit + flags = SLANDMARK_FLAG_ZERO_G diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index 4c4b21650fb..ba4079583d1 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -4,26 +4,23 @@ icon_screen = "shuttle" circuit = null - var/shuttle_tag // Used to coordinate data in shuttle controller. - var/hacked = 0 // Has been emagged, no access restrictions. + var/shuttle_tag // Used to coordinate data in shuttle controller. + var/hacked = 0 // Has been emagged, no access restrictions. + + var/ui_template = "shuttle_control_console.tmpl" /obj/machinery/computer/shuttle_control/attack_hand(user as mob) if(..(user)) return - //src.add_fingerprint(user) //shouldn't need fingerprints just for looking at it. + //src.add_fingerprint(user) // Shouldn't need fingerprints just for looking at it. if(!allowed(user)) - to_chat(user, "Access Denied.") + to_chat(user, "Access Denied.") return 1 ui_interact(user) -/obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - var/datum/shuttle/ferry/shuttle = SSshuttle.shuttles[shuttle_tag] - if (!istype(shuttle)) - return - +/obj/machinery/computer/shuttle_control/proc/get_ui_data(var/datum/shuttle/autodock/shuttle) var/shuttle_state switch(shuttle.moving_status) if(SHUTTLE_IDLE) shuttle_state = "idle" @@ -33,55 +30,100 @@ var/shuttle_status switch (shuttle.process_state) if(IDLE_STATE) + var/cannot_depart = shuttle.current_location.cannot_depart(shuttle) if (shuttle.in_use) shuttle_status = "Busy." - else if (!shuttle.location) - shuttle_status = "Standing-by at station." + else if(cannot_depart) + shuttle_status = cannot_depart else - shuttle_status = "Standing-by at offsite location." + shuttle_status = "Standing-by at \the [shuttle.get_location_name()]." + if(WAIT_LAUNCH, FORCE_LAUNCH) shuttle_status = "Shuttle has received command and will depart shortly." if(WAIT_ARRIVE) - shuttle_status = "Proceeding to destination." + shuttle_status = "Proceeding to \the [shuttle.get_destination_name()]." if(WAIT_FINISH) shuttle_status = "Arriving at destination now." - data = list( + return list( "shuttle_status" = shuttle_status, "shuttle_state" = shuttle_state, - "has_docking" = shuttle.docking_controller? 1 : 0, - "docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null, - "docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null, + "has_docking" = shuttle.shuttle_docking_controller ? 1 : 0, + "docking_status" = shuttle.shuttle_docking_controller?.get_docking_status(), + "docking_override" = shuttle.shuttle_docking_controller?.override_enabled, "can_launch" = shuttle.can_launch(), "can_cancel" = shuttle.can_cancel(), "can_force" = shuttle.can_force(), + "docking_codes" = shuttle.docking_codes ) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "shuttle_control_console.tmpl", "[shuttle_tag] Shuttle Control", 470, 310) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) +// This is a subset of the actual checks; contains those that give messages to the user. +// This enables us to give nice error messages as well as not even bother proceeding if we can't. +/obj/machinery/computer/shuttle_control/proc/can_move(var/datum/shuttle/autodock/shuttle, var/user) + var/cannot_depart = shuttle.current_location.cannot_depart(shuttle) + if(cannot_depart) + to_chat(user, "[cannot_depart]") + log_shuttle("Shuttle [shuttle] cannot depart [shuttle.current_location] because: [cannot_depart].") + return FALSE + if(!shuttle.next_location.is_valid(shuttle)) + to_chat(user, "Destination zone is invalid or obstructed.") + log_shuttle("Shuttle [shuttle] destination [shuttle.next_location] is invalid.") + return FALSE + return TRUE /obj/machinery/computer/shuttle_control/Topic(href, href_list) - if(..()) - return 1 + if((. = ..())) + return usr.set_machine(src) src.add_fingerprint(usr) - var/datum/shuttle/ferry/shuttle = SSshuttle.shuttles[shuttle_tag] - if (!istype(shuttle)) - return + var/datum/shuttle/autodock/shuttle = SSshuttle.shuttles[shuttle_tag] + if(!shuttle) + to_chat(usr, "Unable to establish link with the shuttle.") + return handle_topic_href(shuttle, href_list, usr) + +/obj/machinery/computer/shuttle_control/proc/handle_topic_href(var/datum/shuttle/autodock/shuttle, var/list/href_list, var/user) + if(!istype(shuttle)) + return TOPIC_NOACTION if(href_list["move"]) - shuttle.launch(src) + if(can_move(shuttle, user)) + shuttle.launch(src) + return TOPIC_REFRESH + return TOPIC_HANDLED + if(href_list["force"]) - shuttle.force_launch(src) - else if(href_list["cancel"]) + if(can_move(shuttle, user)) + shuttle.force_launch(src) + return TOPIC_REFRESH + return TOPIC_HANDLED + + if(href_list["cancel"]) shuttle.cancel_launch(src) + return TOPIC_REFRESH + + if(href_list["set_codes"]) + var/newcode = input("Input new docking codes", "Docking codes", shuttle.docking_codes) as text|null + if (newcode && CanInteract(usr, global.default_state)) + shuttle.set_docking_codes(uppertext(newcode)) + return TOPIC_REFRESH + +// We delegate populating data to another proc to make it easier for overriding types to add their data. +/obj/machinery/computer/shuttle_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/datum/shuttle/autodock/shuttle = SSshuttle.shuttles[shuttle_tag] + if (!istype(shuttle)) + to_chat(user, "Unable to establish link with the shuttle.") + return + + var/list/data = get_ui_data(shuttle) + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, ui_template, "[shuttle_tag] Shuttle Control", 470, 310) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) /obj/machinery/computer/shuttle_control/emag_act(var/remaining_charges, var/mob/user) if (!hacked) diff --git a/code/modules/shuttles/shuttle_console_multi.dm b/code/modules/shuttles/shuttle_console_multi.dm new file mode 100644 index 00000000000..9d6dccad56c --- /dev/null +++ b/code/modules/shuttles/shuttle_console_multi.dm @@ -0,0 +1,34 @@ +/obj/machinery/computer/shuttle_control/multi + ui_template = "shuttle_control_console_multi.tmpl" + +/obj/machinery/computer/shuttle_control/multi/get_ui_data(var/datum/shuttle/autodock/multi/shuttle) + . = ..() + if(istype(shuttle)) + . += list( + "destination_name" = shuttle.next_location ? shuttle.next_location.name : "No destination set.", + "can_pick" = shuttle.moving_status == SHUTTLE_IDLE, + "can_cloak" = shuttle.can_cloak ? 1 : 0, + "cloaked" = shuttle.cloaked ? 1 : 0, + "legit" = shuttle.legit ? 1 : 0, + // "engines_charging" = ((shuttle.last_move + (shuttle.cooldown SECONDS)) > world.time), // Replaced by longer warmup_time + ) + +/obj/machinery/computer/shuttle_control/multi/handle_topic_href(var/datum/shuttle/autodock/multi/shuttle, var/list/href_list) + if((. = ..()) != null) + return + + if(href_list["pick"]) + var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations() + if(dest_key && CanInteract(usr, global.default_state)) + shuttle.set_destination(dest_key, usr) + return TOPIC_REFRESH + + if(href_list["toggle_cloaked"]) + if(!shuttle.can_cloak) + return TOPIC_HANDLED + shuttle.cloaked = !shuttle.cloaked + if(shuttle.legit) + to_chat(usr, "Ship ATC inhibitor systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be notified of our arrival.") + else + to_chat(usr, "Ship stealth systems have been [(shuttle.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.") + return TOPIC_REFRESH diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index e06594228f1..5ce5b17ee53 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -1,72 +1,73 @@ -/datum/shuttle/ferry/emergency - category = /datum/shuttle/ferry/emergency +// Formerly /datum/shuttle/ferry/emergency +/datum/shuttle/autodock/ferry/emergency + category = /datum/shuttle/autodock/ferry/emergency -/datum/shuttle/ferry/emergency/New() +/datum/shuttle/autodock/ferry/emergency/New() + ..() if(SSemergencyshuttle.shuttle) CRASH("An emergency shuttle has already been defined.") SSemergencyshuttle.shuttle = src - ..() -/datum/shuttle/ferry/emergency/arrived() +/datum/shuttle/autodock/ferry/emergency/arrived() + . = ..() if (istype(in_use, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = in_use C.reset_authorization() SSemergencyshuttle.shuttle_arrived() -/datum/shuttle/ferry/emergency/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction) - //world << "shuttle/ferry/emergency/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]" +/datum/shuttle/autodock/ferry/emergency/long_jump(var/destination, var/interim, var/travel_time) if (!location) travel_time = SHUTTLE_TRANSIT_DURATION_RETURN else travel_time = SHUTTLE_TRANSIT_DURATION - //update move_time and launch_time so we get correct ETAs + // Update move_time and launch_time so we get correct ETAs move_time = travel_time SSemergencyshuttle.launch_time = world.time + ..(destination, interim, travel_time, direction) + +/datum/shuttle/autodock/ferry/emergency/perform_shuttle_move() + if (current_location == landmark_station) // Leaving the station + spawn(0) + emergency_shuttle.departed = 1 + var/estimated_time = round(emergency_shuttle.estimate_arrival_time()/60,1) + + if (emergency_shuttle.evac) + priority_announcement.Announce(replacetext(replacetext(using_map.emergency_shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s")) + else + priority_announcement.Announce(replacetext(replacetext(using_map.shuttle_leaving_dock, "%dock_name%", "[using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s")) ..() -/datum/shuttle/ferry/emergency/move(var/area/origin,var/area/destination) - ..(origin, destination) - - if (origin == area_station) //leaving the station - SSemergencyshuttle.departed = 1 - var/estimated_time = round(SSemergencyshuttle.estimate_arrival_time()/60,1) - - if (SSemergencyshuttle.evac) - priority_announcement.Announce(replacetext(replacetext(GLOB.using_map.emergency_shuttle_leaving_dock, "%dock_name%", "[GLOB.using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s")) - else - priority_announcement.Announce(replacetext(replacetext(GLOB.using_map.shuttle_leaving_dock, "%dock_name%", "[GLOB.using_map.dock_name]"), "%ETA%", "[estimated_time] minute\s")) - -/datum/shuttle/ferry/emergency/can_launch(var/user) +/datum/shuttle/autodock/ferry/emergency/can_launch(var/user) if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = user if (!C.has_authorization()) return 0 return ..() -/datum/shuttle/ferry/emergency/can_force(var/user) +/datum/shuttle/autodock/ferry/emergency/can_force(var/user) if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = user - //Initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. - //This is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. + // Initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. + // This is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. if (!(process_state == WAIT_LAUNCH || C.has_authorization())) return 0 return ..() -/datum/shuttle/ferry/emergency/can_cancel(var/user) +/datum/shuttle/autodock/ferry/emergency/can_cancel(var/user) if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = user if (!C.has_authorization()) return 0 return ..() -/datum/shuttle/ferry/emergency/launch(var/user) +/datum/shuttle/autodock/ferry/emergency/launch(var/user) if (!can_launch(user)) return - if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console + if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) // If we were given a command by an emergency shuttle console if (SSemergencyshuttle.autopilot) SSemergencyshuttle.autopilot = 0 to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!") @@ -77,10 +78,10 @@ ..(user) -/datum/shuttle/ferry/emergency/force_launch(var/user) +/datum/shuttle/autodock/ferry/emergency/force_launch(var/user) if (!can_force(user)) return - if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console + if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) // If we were given a command by an emergency shuttle console if (SSemergencyshuttle.autopilot) SSemergencyshuttle.autopilot = 0 to_chat(world, "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!") @@ -91,10 +92,10 @@ ..(user) -/datum/shuttle/ferry/emergency/cancel_launch(var/user) +/datum/shuttle/autodock/ferry/emergency/cancel_launch(var/user) if (!can_cancel(user)) return - if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console + if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) // If we were given a command by an emergency shuttle console if (SSemergencyshuttle.autopilot) SSemergencyshuttle.autopilot = 0 to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!") @@ -117,15 +118,15 @@ return (authorized.len >= req_authorizations || emagged) /obj/machinery/computer/shuttle_control/emergency/proc/reset_authorization() - //No need to reset emagged status. If they really want to go back to the station they can. + // No need to reset emagged status. If they really want to go back to the station they can. authorized = initial(authorized) -//returns 1 if the ID was accepted and a new authorization was added, 0 otherwise +// Returns 1 if the ID was accepted and a new authorization was added, 0 otherwise /obj/machinery/computer/shuttle_control/emergency/proc/read_authorization(var/obj/item/ident) if (!ident || !istype(ident)) return 0 if (authorized.len >= req_authorizations) - return 0 //don't need any more + return 0 // Don't need any more var/list/access var/auth_name @@ -141,7 +142,7 @@ dna_hash = ID.dna_hash if (!access || !istype(access)) - return 0 //not an ID + return 0 // Not an ID if (dna_hash in authorized) src.visible_message("\The [src] buzzes. That ID has already been scanned.") @@ -177,7 +178,7 @@ /obj/machinery/computer/shuttle_control/emergency/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] - var/datum/shuttle/ferry/emergency/shuttle = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/ferry/emergency/shuttle = SSshuttle.shuttles[shuttle_tag] if (!istype(shuttle)) return @@ -203,7 +204,7 @@ if(WAIT_FINISH) shuttle_status = "Arriving at destination now." - //build a list of authorizations + // Build a list of authorizations var/list/auth_list[req_authorizations] if (!emagged) @@ -211,7 +212,7 @@ for (var/dna_hash in authorized) auth_list[i++] = list("auth_name"=authorized[dna_hash], "auth_hash"=dna_hash) - while (i <= req_authorizations) //fill up the rest of the list with blank entries + while (i <= req_authorizations) // Fill up the rest of the list with blank entries auth_list[i++] = list("auth_name"="", "auth_hash"=null) else for (var/i = 1; i <= req_authorizations; i++) @@ -222,9 +223,9 @@ data = list( "shuttle_status" = shuttle_status, "shuttle_state" = shuttle_state, - "has_docking" = shuttle.docking_controller? 1 : 0, - "docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null, - "docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null, + "has_docking" = shuttle.active_docking_controller? 1 : 0, + "docking_status" = shuttle.active_docking_controller? shuttle.active_docking_controller.get_docking_status() : null, + "docking_override" = shuttle.active_docking_controller? shuttle.active_docking_controller.override_enabled : null, "can_launch" = shuttle.can_launch(src), "can_cancel" = shuttle.can_cancel(src), "can_force" = shuttle.can_force(src), @@ -250,8 +251,8 @@ authorized -= dna_hash if(!emagged && href_list["scanid"]) - //They selected an empty entry. Try to scan their id. + // They selected an empty entry. Try to scan their id. if (ishuman(usr)) var/mob/living/carbon/human/H = usr - if (!read_authorization(H.get_active_hand())) //try to read what's in their hand first + if (!read_authorization(H.get_active_hand())) // Try to read what's in their hand first read_authorization(H.wear_id) diff --git a/code/modules/shuttles/shuttle_ferry.dm b/code/modules/shuttles/shuttle_ferry.dm index f279ce5d343..dc179c19bd9 100644 --- a/code/modules/shuttles/shuttle_ferry.dm +++ b/code/modules/shuttles/shuttle_ferry.dm @@ -1,177 +1,49 @@ -#define DOCK_ATTEMPT_TIMEOUT 200 //how long in ticks we wait before assuming the docking controller is broken or blown up. +#define DOCK_ATTEMPT_TIMEOUT 200 // How long in ticks we wait before assuming the docking controller is broken or blown up. -/datum/shuttle/ferry - var/location = 0 //0 = at area_station, 1 = at area_offsite - var/direction = 0 //0 = going to station, 1 = going to offsite. - var/process_state = IDLE_STATE - var/always_process = FALSE +/datum/shuttle/autodock/ferry + var/location = FERRY_LOCATION_STATION // 0 = at area_station, 1 = at area_offsite + var/direction = FERRY_GOING_TO_STATION // 0 = going to station, 1 = going to offsite. - var/in_use = null //tells the controller whether this shuttle needs processing + var/always_process = FALSE // TODO -why should this exist? - var/area_transition - var/move_time = 0 //the time spent in the transition area - var/transit_direction = null //needed for area/move_contents_to() to properly handle shuttle corners - not exactly sure how it works. + var/obj/effect/shuttle_landmark/landmark_station // This variable is type-abused initially: specify the landmark_tag, not the actual landmark. + var/obj/effect/shuttle_landmark/landmark_offsite // This variable is type-abused initially: specify the landmark_tag, not the actual landmark. - var/area/area_station - var/area/area_offsite - //TODO: change location to a string and use a mapping for area and dock targets. - var/dock_target_station - var/dock_target_offsite + category = /datum/shuttle/autodock/ferry - var/last_dock_attempt_time = 0 - category = /datum/shuttle/ferry +/datum/shuttle/autodock/ferry/New(var/_name) + if(landmark_station) + landmark_station = SSshuttle.get_landmark(landmark_station) + if(landmark_offsite) + landmark_offsite = SSshuttle.get_landmark(landmark_offsite) -/datum/shuttle/ferry/New() - area_offsite = locate(area_offsite) - area_station = locate(area_station) - if(area_transition) - area_transition = locate(area_transition) - ..() + ..(_name, get_location_waypoint(location)) -/datum/shuttle/ferry/short_jump(var/area/origin,var/area/destination) - if(isnull(location)) - return + next_location = get_location_waypoint(!location) - if(!destination) - destination = get_location_area(!location) - if(!origin) - origin = get_location_area(location) - - direction = !location - ..(origin, destination) - -/datum/shuttle/ferry/long_jump(var/area/departing, var/area/destination, var/area/interim, var/travel_time, var/direction) - //world << "shuttle/ferry/long_jump: departing=[departing], destination=[destination], interim=[interim], travel_time=[travel_time]" - if(isnull(location)) - return - - if(!destination) - destination = get_location_area(!location) - if(!departing) - departing = get_location_area(location) - - direction = !location - ..(departing, destination, interim, travel_time, direction) - -/datum/shuttle/ferry/move(var/area/origin,var/area/destination) - ..(origin, destination) - - if (destination == area_station) location = 0 - if (destination == area_offsite) location = 1 - //if this is a long_jump retain the location we were last at until we get to the new one - -/datum/shuttle/ferry/dock() - ..() - last_dock_attempt_time = world.time - -/datum/shuttle/ferry/proc/get_location_area(location_id = null) +// Gets the shuttle landmark associated with the given location (defaults to current location) +/datum/shuttle/autodock/ferry/proc/get_location_waypoint(location_id = null) if (isnull(location_id)) location_id = location - if (!location_id) - return area_station - return area_offsite + if (location_id == FERRY_LOCATION_STATION) + return landmark_station + return landmark_offsite -/* - Please ensure that long_jump() and short_jump() are only called from here. This applies to subtypes as well. - Doing so will ensure that multiple jumps cannot be initiated in parallel. -*/ -/datum/shuttle/ferry/process() - switch(process_state) - if (WAIT_LAUNCH) - if (skip_docking_checks() || docking_controller.can_launch()) +/datum/shuttle/autodock/ferry/short_jump(var/destination) + direction = !location // Heading away from where we currently are + . = ..() - //world << "shuttle/ferry/process: area_transition=[area_transition], travel_time=[travel_time]" - if (move_time && area_transition) - long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction) - else - short_jump() +/datum/shuttle/autodock/ferry/long_jump(var/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time) + direction = !location // Heading away from where we currently are + . = ..() - process_state = WAIT_ARRIVE - - if (FORCE_LAUNCH) - if (move_time && area_transition) - long_jump(interim=area_transition, travel_time=move_time, direction=transit_direction) - else - short_jump() - - process_state = WAIT_ARRIVE - - if (WAIT_ARRIVE) - if (moving_status == SHUTTLE_IDLE) - dock() - in_use = null //release lock - process_state = WAIT_FINISH - - if (WAIT_FINISH) - if (skip_docking_checks() || docking_controller.docked() || world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT) - process_state = IDLE_STATE - arrived() - -/datum/shuttle/ferry/current_dock_target() - var/dock_target - if (!location) //station - dock_target = dock_target_station - else - dock_target = dock_target_offsite - return dock_target - - -/datum/shuttle/ferry/proc/launch(var/user) - if (!can_launch()) return - - in_use = user //obtain an exclusive lock on the shuttle - - process_state = WAIT_LAUNCH - undock() - -/datum/shuttle/ferry/proc/force_launch(var/user) - if (!can_force()) return - - in_use = user //obtain an exclusive lock on the shuttle - - process_state = FORCE_LAUNCH - -/datum/shuttle/ferry/proc/cancel_launch(var/user) - if (!can_cancel()) return - - moving_status = SHUTTLE_IDLE - process_state = WAIT_FINISH - in_use = null - - if (docking_controller && !docking_controller.undocked()) - docking_controller.force_undock() - - spawn(10) - dock() - - return - -/datum/shuttle/ferry/proc/can_launch() - if (moving_status != SHUTTLE_IDLE) - return 0 - - if (in_use) - return 0 - - return 1 - -/datum/shuttle/ferry/proc/can_force() - if (moving_status == SHUTTLE_IDLE && process_state == WAIT_LAUNCH) - return 1 - return 0 - -/datum/shuttle/ferry/proc/can_cancel() - if (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH) - return 1 - return 0 - -//returns 1 if the shuttle is getting ready to move, but is not in transit yet -/datum/shuttle/ferry/proc/is_launching() - return (moving_status == SHUTTLE_WARMUP || process_state == WAIT_LAUNCH || process_state == FORCE_LAUNCH) - -//This gets called when the shuttle finishes arriving at it's destination -//This can be used by subtypes to do things when the shuttle arrives. -/datum/shuttle/ferry/proc/arrived() - return //do nothing for now +/datum/shuttle/autodock/ferry/perform_shuttle_move() + ..() + if (current_location == landmark_station) location = FERRY_LOCATION_STATION + if (current_location == landmark_offsite) location = FERRY_LOCATION_OFFSITE +// Once we have arrived where we are going, plot a course back! +/datum/shuttle/autodock/ferry/process_arrived() + ..() + next_location = get_location_waypoint(!location) diff --git a/code/modules/shuttles/shuttle_specops.dm b/code/modules/shuttles/shuttle_specops.dm index aa59f1533d2..fcb3344405c 100644 --- a/code/modules/shuttles/shuttle_specops.dm +++ b/code/modules/shuttles/shuttle_specops.dm @@ -4,59 +4,31 @@ req_access = list(access_cent_specops) /obj/machinery/computer/shuttle_control/specops/attack_ai(user as mob) - to_chat(user, "Access Denied.") + to_chat(user, "Access Denied.") return 1 -//for shuttles that may use a different docking port at each location -/datum/shuttle/ferry/multidock - var/docking_controller_tag_station - var/docking_controller_tag_offsite - var/datum/computer/file/embedded_program/docking/docking_controller_station - var/datum/computer/file/embedded_program/docking/docking_controller_offsite - category = /datum/shuttle/ferry/multidock - -/datum/shuttle/ferry/multidock/init_docking_controllers() - if(docking_controller_tag_station) - docking_controller_station = locate(docking_controller_tag_station) - if(!istype(docking_controller_station)) - warning("warning: shuttle with docking tag [docking_controller_station] could not find its controller!") - if(docking_controller_tag_offsite) - docking_controller_offsite = locate(docking_controller_tag_offsite) - if(!istype(docking_controller_offsite)) - warning("warning: shuttle with docking tag [docking_controller_offsite] could not find its controller!") - if (!location) - docking_controller = docking_controller_station - else - docking_controller = docking_controller_offsite - -/datum/shuttle/ferry/multidock/move(var/area/origin,var/area/destination) - ..(origin, destination) - if (!location) - docking_controller = docking_controller_station - else - docking_controller = docking_controller_offsite - -/datum/shuttle/ferry/multidock/specops - var/specops_return_delay = 6000 //After moving, the amount of time that must pass before the shuttle may move again - var/specops_countdown_time = 600 //Length of the countdown when moving the shuttle +// Formerly /datum/shuttle/ferry/multidock/specops +/datum/shuttle/autodock/ferry/specops + var/specops_return_delay = 6000 // After moving, the amount of time that must pass before the shuttle may move again + var/specops_countdown_time = 600 // Length of the countdown when moving the shuttle var/obj/item/radio/intercom/announcer = null - var/reset_time = 0 //the world.time at which the shuttle will be ready to move again. + var/reset_time = 0 // The world.time at which the shuttle will be ready to move again. var/launch_prep = 0 var/cancel_countdown = 0 - category = /datum/shuttle/ferry/multidock/specops + category = /datum/shuttle/autodock/ferry/specops -/datum/shuttle/ferry/multidock/specops/New() +/datum/shuttle/autodock/ferry/specops/New() ..() - announcer = new /obj/item/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer = new /obj/item/radio/intercom(null) // We need a fake AI to announce some stuff below. Otherwise it will be wonky. announcer.config(list("Response Team" = 0)) -/datum/shuttle/ferry/multidock/specops/proc/radio_announce(var/message) +/datum/shuttle/autodock/ferry/specops/proc/radio_announce(var/message) if(announcer) announcer.autosay(message, "A.L.I.C.E.", "Response Team") -/datum/shuttle/ferry/multidock/specops/launch(var/user) +/datum/shuttle/autodock/ferry/specops/launch(var/user) if (!can_launch()) return @@ -64,16 +36,17 @@ var/obj/machinery/computer/C = user if(world.time <= reset_time) - C.visible_message("[GLOB.using_map.boss_name] will not allow the Special Operations shuttle to launch yet.") + C.visible_message("[global.using_map.boss_name] will not allow the Special Operations shuttle to launch yet.") if (((world.time - reset_time)/10) > 60) - C.visible_message("[-((world.time - reset_time)/10)/60] minutes remain!") + C.visible_message("[-((world.time - reset_time)/10)/60] minutes remain!") else - C.visible_message("[-(world.time - reset_time)/10] seconds remain!") + C.visible_message("[-(world.time - reset_time)/10] seconds remain!") return - C.visible_message("The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.") + C.visible_message("The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.") - if (location) //returning + // Returning + if (location) radio_announce("THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN") else radio_announce("THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH") @@ -81,31 +54,33 @@ sleep_until_launch() if (location) - var/obj/machinery/light/small/readylight/light = locate() in get_location_area() + var/obj/machinery/light/small/readylight/light = locate() in shuttle_area if(light) light.set_state(0) - //launch + // Launch radio_announce("ALERT: INITIATING LAUNCH SEQUENCE") ..(user) -/datum/shuttle/ferry/multidock/specops/move(var/area/origin,var/area/destination) - ..(origin, destination) +/datum/shuttle/autodock/ferry/specops/perform_shuttle_move() + ..() - spawn(20) - if (!location) //just arrived home - for(var/turf/T in get_area_turfs(destination)) + spawn(2 SECONDS) + if (!location) + // Just arrived home + for(var/turf/T in get_area_turfs(shuttle_area)) var/mob/M = locate(/mob) in T to_chat(M, "You have arrived at [GLOB.using_map.boss_name]. Operation has ended!") - else //just left for the station + else + // Fust left for the station launch_mauraders() - for(var/turf/T in get_area_turfs(destination)) + for(var/turf/T in get_area_turfs(shuttle_area)) var/mob/M = locate(/mob) in T to_chat(M, "You have arrived at [station_name()]. Commence operation!") var/obj/machinery/light/small/readylight/light = locate() in T if(light) light.set_state(1) -/datum/shuttle/ferry/multidock/specops/cancel_launch() +/datum/shuttle/autodock/ferry/specops/cancel_launch() if (!can_cancel()) return @@ -113,28 +88,27 @@ radio_announce("ALERT: LAUNCH SEQUENCE ABORTED") if (istype(in_use, /obj/machinery/computer)) var/obj/machinery/computer/C = in_use - C.visible_message("Launch sequence aborted.") - + C.visible_message("Launch sequence aborted.") ..() -/datum/shuttle/ferry/multidock/specops/can_launch() +/datum/shuttle/autodock/ferry/specops/can_launch() if(launch_prep) return 0 return ..() -//should be fine to allow forcing. process_state only becomes WAIT_LAUNCH after the countdown is over. -///datum/shuttle/ferry/multidock/specops/can_force() +// Should be fine to allow forcing. process_state only becomes WAIT_LAUNCH after the countdown is over. +///datum/shuttle/autodock/ferry/specops/can_force() // return 0 -/datum/shuttle/ferry/multidock/specops/can_cancel() +/datum/shuttle/autodock/ferry/specops/can_cancel() if(launch_prep) return 1 return ..() -/datum/shuttle/ferry/multidock/specops/proc/sleep_until_launch() - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. +/datum/shuttle/autodock/ferry/specops/proc/sleep_until_launch() + var/message_tracker[] = list(0,1,2,3,5,10,30,45) // Create a a list with potential time values. var/launch_time = world.time + specops_countdown_time var/time_until_launch @@ -148,12 +122,12 @@ // launch_time = world.timeofday + 10 // midnight rollover time_until_launch = (ticksleft / 10) - //All this does is announce the time before launch. - var/rounded_time_left = round(time_until_launch)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. + // All this does is announce the time before launch. + var/rounded_time_left = round(time_until_launch) // Round time so that it will report only once, not in fractions. + if(rounded_time_left in message_tracker) // If that time is in the list for message announce. radio_announce("ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN") - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. + message_tracker -= rounded_time_left // Remove the number from the list so it won't be called again next cycle. + // Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. sleep(5) @@ -161,13 +135,13 @@ /proc/launch_mauraders() - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. + var/area/centcom/specops/special_ops = locate() // Where is the specops area located? + // Begin Marauder launchpad. + spawn(0) // So it parallel processes it. for(var/obj/machinery/door/blast/M in special_ops) switch(M.id) if("ASSAULT0") - spawn(10)//1 second delay between each. + spawn(10) // 1 second delay between each. M.open() if("ASSAULT1") spawn(20) @@ -188,9 +162,9 @@ for(var/obj/effect/landmark/L in landmarks_list) if(L.name == "Marauder Exit") var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. + P.invisibility = 101 // So it is not seen by anyone. + P.failchance = 0 // So it has no fail chance when teleporting. + P.target = pick(spawn_marauder) // Where the marauder will arrive. spawn_marauder.Remove(P.target) sleep(10) @@ -210,10 +184,10 @@ spawn(40) M.drive() - sleep(50)//Doors remain open for 5 seconds. + sleep(50) // Doors remain open for 5 seconds. for(var/obj/machinery/door/blast/M in special_ops) - switch(M.id)//Doors close at the same time. + switch(M.id) // Doors close at the same time. if("ASSAULT0") spawn(0) M.close() @@ -226,8 +200,8 @@ if("ASSAULT3") spawn(0) M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. + special_ops.readyreset() // Reset firealarm after the team launched. + // End Marauder launchpad. /obj/machinery/light/small/readylight brightness_range = 5 diff --git a/code/modules/shuttles/shuttle_supply.dm b/code/modules/shuttles/shuttle_supply.dm index bd51066c3c5..1d6c3dfc785 100644 --- a/code/modules/shuttles/shuttle_supply.dm +++ b/code/modules/shuttles/shuttle_supply.dm @@ -1,82 +1,81 @@ -/datum/shuttle/ferry/supply - var/away_location = 1 //the location to hide at while pretending to be in-transit +// Formerly /datum/shuttle/ferry/supply +/datum/shuttle/autodock/ferry/supply + var/away_location = FERRY_LOCATION_OFFSITE // The location to hide at while pretending to be in-transit var/late_chance = 80 var/max_late_time = 300 - category = /datum/shuttle/ferry/supply + flags = SHUTTLE_FLAGS_PROCESS|SHUTTLE_FLAGS_SUPPLY + category = /datum/shuttle/autodock/ferry/supply -/datum/shuttle/ferry/supply/short_jump(var/area/origin,var/area/destination) +/datum/shuttle/autodock/ferry/supply/short_jump(var/obj/effect/shuttle_landmark/destination) if(moving_status != SHUTTLE_IDLE) return if(isnull(location)) return - if(!destination) - destination = get_location_area(!location) - if(!origin) - origin = get_location_area(location) - - //it would be cool to play a sound here + // It would be cool to play a sound here moving_status = SHUTTLE_WARMUP spawn(warmup_time*10) - make_sounds(origin, HYPERSPACE_WARMUP) - sleep(5 SECONDS) // so the sound finishes. + make_sounds(HYPERSPACE_WARMUP) + sleep(5 SECONDS) // So the sound finishes. if (moving_status == SHUTTLE_IDLE) - make_sounds(origin, HYPERSPACE_END) - return //someone cancelled the launch + make_sounds(HYPERSPACE_END) + return // Someone cancelled the launch if (at_station() && forbidden_atoms_check()) - //cancel the launch because of forbidden atoms. announce over supply channel? + // Cancel the launch because of forbidden atoms. announce over supply channel? moving_status = SHUTTLE_IDLE - make_sounds(origin, HYPERSPACE_END) + make_sounds(HYPERSPACE_END) return - if (!at_station()) //at centcom + if (!at_station()) // At centcom SSsupply.buy() - //We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period. - var/area/away_area = get_location_area(away_location) + // We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period. + var/obj/effect/shuttle_landmark/away_waypoint = get_location_waypoint(away_location) moving_status = SHUTTLE_INTRANSIT - //If we are at the away_area then we are just pretending to move, otherwise actually do the move - if (origin != away_area) - move(origin, away_area) + // If we are at the away_landmark then we are just pretending to move, otherwise actually do the move + if (next_location == away_waypoint) + attempt_move(away_waypoint) - //wait ETA here. + // Wait ETA here. arrive_time = world.time + SSsupply.movetime while (world.time <= arrive_time) sleep(5) - if (destination != away_area) - //late + if (next_location != away_waypoint) + // Late if (prob(late_chance)) sleep(rand(0,max_late_time)) - move(away_area, destination) + attempt_move(destination) moving_status = SHUTTLE_IDLE - make_sounds(destination, HYPERSPACE_END) + make_sounds(HYPERSPACE_END) - if (!at_station()) //at centcom + if (!at_station()) // At centcom SSsupply.sell() -// returns 1 if the supply shuttle should be prevented from moving because it contains forbidden atoms +// Returns 1 if the supply shuttle should be prevented from moving because it contains forbidden atoms /datum/shuttle/ferry/supply/proc/forbidden_atoms_check() if (!at_station()) - return 0 //if badmins want to send mobs or a nuke on the supply shuttle from centcom we don't care + return 0 // If badmins want to send mobs or a nuke on the supply shuttle from centcom we don't care - return SSsupply.forbidden_atoms_check(get_location_area()) + for(var/area/A in shuttle_area) + if(SSsupply.forbidden_atoms_check(A)) + return 1 -/datum/shuttle/ferry/supply/proc/at_station() +/datum/shuttle/autodock/ferry/supply/proc/at_station() return (!location) -//returns 1 if the shuttle is idle and we can still mess with the cargo shopping list -/datum/shuttle/ferry/supply/proc/idle() +// Returns 1 if the shuttle is idle and we can still mess with the cargo shopping list +/datum/shuttle/autodock/ferry/supply/proc/idle() return (moving_status == SHUTTLE_IDLE) -//returns the ETA in minutes -/datum/shuttle/ferry/supply/proc/eta_minutes() +// Returns the ETA in minutes +/datum/shuttle/autodock/ferry/supply/proc/eta_minutes() var/ticksleft = arrive_time - world.time return round(ticksleft/600,1) diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm index 0b851f0fffd..e128a6c5802 100644 --- a/code/modules/shuttles/shuttles_multi.dm +++ b/code/modules/shuttles/shuttles_multi.dm @@ -1,290 +1,63 @@ //This is a holder for things like the Skipjack and Nuke shuttle. -/datum/shuttle/multi_shuttle +// Formerly /datum/shuttle/multi_shuttle +/datum/shuttle/autodock/multi + var/list/destination_tags + var/list/destinations_cache = list() + var/last_cache_rebuild_time = 0 + category = /datum/shuttle/autodock/multi - flags = SHUTTLE_FLAGS_NONE var/cloaked = FALSE var/can_cloak = FALSE + var/at_origin = 1 - var/returned_home = 0 -// var/move_time = 240 - var/move_time = 60 var/cooldown = 20 - var/last_move = 0 //the time at which we last moved + var/last_move = 0 // The time at which we last moved var/announcer var/arrival_message var/departure_message - var/area/interim - var/area/last_departed var/start_location var/last_location - var/list/destinations - var/list/destination_dock_controller_tags = list() //optional, in case the shuttle has multiple docking ports like the ERT shuttle (even though that isn't a multi_shuttle) - var/list/destination_dock_controllers = list() - var/list/destination_dock_targets = list() - var/area/origin var/return_warning = 0 - var/legit = 0 //VOREStation Add - Whether or not a shuttle is a legit NT shuttle. - category = /datum/shuttle/multi_shuttle + var/legit = FALSE // Whether or not a shuttle is a legit NT shuttle. -/datum/shuttle/multi_shuttle/New() - origin = locate(origin) - interim = locate(interim) - for(var/destination in destinations) - destinations[destination] = locate(destinations[destination]) +/datum/shuttle/autodock/multi/New() ..() + start_location = current_location + last_location = current_location -/datum/shuttle/multi_shuttle/init_docking_controllers() - ..() - for(var/destination in destinations) - var/controller_tag = destination_dock_controller_tags[destination] - if(!controller_tag) - destination_dock_controllers[destination] = docking_controller - else - var/datum/computer/file/embedded_program/docking/C = locate(controller_tag) +/datum/shuttle/autodock/multi/proc/set_destination(var/destination_key, mob/user) + if(moving_status != SHUTTLE_IDLE) + return + next_location = destinations_cache[destination_key] + if(!next_location) + warning("Shuttle [src] set to destination we can't find: [destination_key]") - if(!istype(C)) - warning("warning: shuttle with docking tag [controller_tag] could not find its controller!") - else - destination_dock_controllers[destination] = C +/datum/shuttle/autodock/multi/proc/get_destinations() + if (last_cache_rebuild_time < SSshuttle.last_landmark_registration_time) + build_destinations_cache() + return destinations_cache - //might as well set this up here. - if(origin) last_departed = origin - last_location = start_location - //VOREStation Add - Set up origin dock controller - if(!(start_location in destination_dock_controller_tags)) - destination_dock_controllers[start_location] = docking_controller - //VOREStation Add End -/datum/shuttle/multi_shuttle/current_dock_target() - return destination_dock_targets[last_location] +/datum/shuttle/autodock/multi/proc/build_destinations_cache() + last_cache_rebuild_time = world.time + destinations_cache.Cut() + for(var/destination_tag in destination_tags) + var/obj/effect/shuttle_landmark/landmark = SSshuttle.get_landmark(destination_tag) + if (istype(landmark)) + destinations_cache["[landmark.name]"] = landmark -/datum/shuttle/multi_shuttle/move(var/area/origin, var/area/destination) +/datum/shuttle/autodock/multi/perform_shuttle_move() ..() last_move = world.time - if (destination == src.origin) - returned_home = 1 - docking_controller = destination_dock_controllers[last_location] - -/datum/shuttle/multi_shuttle/proc/announce_departure() +/datum/shuttle/autodock/multi/proc/announce_departure() if(cloaked || isnull(departure_message)) return + command_announcement.Announce(departure_message, (announcer ? announcer : "[using_map.boss_name]")) - command_announcement.Announce(departure_message,(announcer ? announcer : "[GLOB.using_map.boss_name]")) - -/datum/shuttle/multi_shuttle/proc/announce_arrival() +/datum/shuttle/autodock/multi/proc/announce_arrival() if(cloaked || isnull(arrival_message)) return - - command_announcement.Announce(arrival_message,(announcer ? announcer : "[GLOB.using_map.boss_name]")) - - -/obj/machinery/computer/shuttle_control/multi - icon_keyboard = "syndie_key" - icon_screen = "syndishuttle" - -/obj/machinery/computer/shuttle_control/multi/attack_hand(user as mob) - - if(..(user)) - return - src.add_fingerprint(user) - - var/datum/shuttle/multi_shuttle/MS = SSshuttle.shuttles[shuttle_tag] - if(!istype(MS)) return - - var/dat - dat = "
[shuttle_tag] Ship Control
" - - - if(MS.moving_status != SHUTTLE_IDLE) - dat += "Location: Moving
" - else - var/area/areacheck = get_area(src) - dat += "Location: [areacheck.name]
" - - if((MS.last_move + MS.cooldown*10) > world.time) - dat += "Engines charging.
" - else - dat += "Engines ready.
" - - //dat += "
[MS.legit ? "Inhibit ATC":"Toggle cloak"]
" //VOREStation Edit - Adds legit shuttles. //SYNC Edit: Below deals with cloak. - if(MS.can_cloak) - dat += "
Toggle cloaking field
" - dat += "Move ship
" - dat += "Return to base
" - - //Docking - dat += "


" - if(MS.skip_docking_checks()) - dat += "Docking Status: Not in use." - else - var/override_en = MS.docking_controller.override_enabled - var/docking_status = MS.docking_controller.get_docking_status() - - dat += "Docking Status: " - switch(docking_status) - if("undocked") - dat += "Undocked" - if("docking") - dat += "Docking" - if("undocking") - dat += "Undocking" - if("docked") - dat += "Docked" - - if(override_en) dat += " (Override Enabled)" - - dat += ". \[Refresh\]

" - - switch(docking_status) - if("undocked") - dat += "Dock" - if("docked") - dat += "Undock" - dat += "
" - - user << browse("[dat]", "window=[shuttle_tag]shuttlecontrol;size=300x600") - -//check if we're undocked, give option to force launch -/obj/machinery/computer/shuttle_control/proc/check_docking(datum/shuttle/multi_shuttle/MS) - if(MS.skip_docking_checks() || MS.docking_controller.can_launch()) - return 1 - - var/choice = alert("The shuttle is currently docked! Please undock before continuing.","Error","Cancel","Force Launch") - if(choice == "Cancel") - return 0 - - choice = alert("Forcing a shuttle launch while docked may result in severe injury, death and/or damage to property. Are you sure you wish to continue?", "Force Launch", "Force Launch", "Cancel") - if(choice == "Cancel") - return 0 - - return 1 - -/obj/machinery/computer/shuttle_control/multi/Topic(href, href_list) - if(..()) - return 1 - - usr.set_machine(src) - src.add_fingerprint(usr) - - var/datum/shuttle/multi_shuttle/MS = SSshuttle.shuttles[shuttle_tag] - if(!istype(MS)) return - - //world << "multi_shuttle: last_departed=[MS.last_departed], origin=[MS.origin], interim=[MS.interim], travel_time=[MS.move_time]" - - if(href_list["refresh"]) - updateUsrDialog() - return - - if (MS.moving_status != SHUTTLE_IDLE) - to_chat(usr, "[shuttle_tag] vessel is moving.") - return - - if(href_list["dock_command"]) - MS.dock() - return - - if(href_list["undock_command"]) - MS.undock() - return - - if(href_list["start"]) - if(MS.at_origin) - to_chat(usr, "You are already at the home base.") - return - - if((MS.last_move + MS.cooldown*10) > world.time) - to_chat(usr, "The ship's drive is inoperable while the engines are charging.") - return - - if(!check_docking(MS)) - updateUsrDialog() - return - - if(!MS.return_warning && !MS.legit) //VOREStation Add - Criminals only! - to_chat(usr, "Returning to your home base will end your mission. If you are sure, press the button again.") - //TODO: Actually end the mission. - MS.return_warning = 1 - return - - //VOREStation Add - Only long-jump if that's a thing you do - if(MS.interim) - MS.long_jump(MS.last_departed, MS.origin, MS.interim, MS.move_time) - else - MS.short_jump(MS.last_departed, MS.origin) - //VOREStation Add End - // No point giving a warning if it does literally nothing. -// if(!MS.return_warning) -// usr << "Returning to your home base will end your mission. If you are sure, press the button again." -// //TODO: Actually end the mission. -// MS.return_warning = 1 -// return - - //MS.long_jump(MS.last_departed, MS.origin, MS.interim, MS.move_time) //VOREStation Edit - MS.last_departed = MS.origin - MS.last_location = MS.start_location - MS.at_origin = 1 - - if(href_list["toggle_cloak"]) - if(!MS.can_cloak) - return - MS.cloaked = !MS.cloaked - to_chat(usr, " Ship [MS.legit ? "ATC inhibitor":"stealth"] systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be [MS.legit ? "notified":"warned"] of our arrival.") //VOREStation Edit - Adds legit shuttles. - //to_chat(usr, "Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.") //VOREStation Edit. - - if(href_list["move_multi"]) - if((MS.last_move + MS.cooldown*10) > world.time) - to_chat(usr, "The ship's drive is inoperable while the engines are charging.") - return - - if(!check_docking(MS)) - updateUsrDialog() - return - - var/choice = input("Select a destination.") as null|anything in MS.destinations - if(!choice) return - - to_chat(usr, "[shuttle_tag] main computer received message.") - - if(MS.at_origin) - MS.announce_arrival() - MS.last_departed = MS.origin - MS.at_origin = 0 - - - //VOREStation Add - Only long-jump if that's a thing you do - if(MS.interim) - MS.long_jump(MS.last_departed, MS.destinations[choice], MS.interim, MS.move_time) - else - MS.short_jump(MS.last_departed, MS.destinations[choice]) - //VOREStation Add End - MS.last_departed = MS.destinations[choice] - MS.last_location = choice - return - - else if(choice == MS.origin) - - MS.announce_departure() - - //VOREStation Add - Only long-jump if that's a thing you do - if(MS.interim) - MS.long_jump(MS.last_departed, MS.destinations[choice], MS.interim, MS.move_time) - else - MS.short_jump(MS.last_departed, MS.destinations[choice]) - return - //VOREStation Add End - - //VOREStation Add - Only long-jump if that's a thing you do - if(MS.interim) - MS.long_jump(MS.last_departed, MS.destinations[choice], MS.interim, MS.move_time) - else - MS.short_jump(MS.last_departed, MS.destinations[choice]) - //VOREStation Add End - - //MS.short_jump(MS.last_departed, MS.destinations[choice]) //VOREStation Removal - MS.last_departed = MS.destinations[choice] - MS.last_location = choice - - updateUsrDialog() + command_announcement.Announce(arrival_message, (announcer ? announcer : "[using_map.boss_name]")) diff --git a/code/modules/shuttles/shuttles_web.dm b/code/modules/shuttles/shuttles_web.dm index 87e8a646dc0..e835bef4d45 100644 --- a/code/modules/shuttles/shuttles_web.dm +++ b/code/modules/shuttles/shuttles_web.dm @@ -1,25 +1,23 @@ -//This shuttle traverses a "web" of route_datums to have a wider range of places to go and make flying feel like movement is actually occuring. -/datum/shuttle/web_shuttle - flags = SHUTTLE_FLAGS_NONE - var/visible_name = null // The pretty name shown to people in announcements, since the regular name var is used internally for other things. +// This shuttle traverses a "web" of route_datums to have a wider range of places to go and make flying feel like movement is actually occuring. +/datum/shuttle/autodock/web_shuttle + flags = SHUTTLE_FLAGS_ZERO_G + var/visible_name = null // The pretty name shown to people in announcements, since the regular name var is used internally for other things. var/cloaked = FALSE var/can_cloak = FALSE var/cooldown = 0 - var/last_move = 0 //the time at which we last moved - var/area/current_area = null + var/last_move = 0 // The time at which we last moved var/datum/shuttle_web_master/web_master = null var/web_master_type = null var/flight_time_modifier = 1.0 var/autopilot = FALSE var/can_autopilot = FALSE - var/autopilot_delay = 60 // How many ticks to not do anything when not following an autopath. Should equal two minutes. - var/autopilot_first_delay = null // If your want your shuttle to stay for a different amount of time for the first time, set this. - var/can_rename = TRUE // Lets the pilot rename the shuttle. Only available once. - category = /datum/shuttle/web_shuttle + var/autopilot_delay = 60 // How many ticks to not do anything when not following an autopath. Should equal two minutes. + var/autopilot_first_delay = null // If your want your shuttle to stay for a different amount of time for the first time, set this. + var/can_rename = TRUE // Lets the pilot rename the shuttle. Only available once. + category = /datum/shuttle/autodock/web_shuttle var/list/obj/item/clothing/head/pilot/helmets -/datum/shuttle/web_shuttle/New() - current_area = locate(current_area) +/datum/shuttle/autodock/web_shuttle/New() web_master = new web_master_type(src) build_destinations() if(autopilot) @@ -31,63 +29,66 @@ helmets = list() ..() -/datum/shuttle/web_shuttle/Destroy() - qdel(web_master) +/datum/shuttle/autodock/web_shuttle/Destroy() + QDEL_NULL(web_master) helmets.Cut() return ..() +/datum/shuttle/autodock/web_shuttle/current_dock_target() + // TODO - Probably don't even need to override this right? Debug testing code below will check! + . = web_master?.get_current_destination()?.my_landmark?.docking_controller?.id_tag + if (. != ..()) + warning("Web shuttle [src] had current_dock_target()=[.] but autodock.current_dock_target() = [..()]") -/datum/shuttle/web_shuttle/current_dock_target() - if(web_master) - return web_master.current_dock_target() - -/datum/shuttle/web_shuttle/move(var/area/origin, var/area/destination) +/datum/shuttle/autodock/web_shuttle/perform_shuttle_move() ..() last_move = world.time + active_docking_controller = current_location.docking_controller + update_docking_target(current_location) -/datum/shuttle/web_shuttle/short_jump() +/datum/shuttle/autodock/web_shuttle/short_jump() . = ..() update_helmets() -/datum/shuttle/web_shuttle/long_jump() +/datum/shuttle/autodock/web_shuttle/long_jump() . = ..() update_helmets() -/datum/shuttle/web_shuttle/on_shuttle_departure() +/datum/shuttle/autodock/web_shuttle/on_shuttle_departure() . = ..() web_master.on_shuttle_departure() update_helmets() -/datum/shuttle/web_shuttle/on_shuttle_arrival() +/datum/shuttle/autodock/web_shuttle/on_shuttle_arrival() . = ..() web_master.on_shuttle_arrival() update_helmets() -/datum/shuttle/web_shuttle/proc/build_destinations() +/datum/shuttle/autodock/web_shuttle/proc/build_destinations() return -/datum/shuttle/web_shuttle/process() +/datum/shuttle/autodock/web_shuttle/process() update_helmets() if(moving_status == SHUTTLE_IDLE) - if(web_master.autopath) // We're currently flying a path. + if(web_master.autopath) // We're currently flying a path. autopilot_say("Continuing route.") web_master.process_autopath() - else // Otherwise we are about to start one or just finished one. - if(autopilot_delay > 0) // Wait for awhile so people can get on and off. - if(docking_controller && !skip_docking_checks()) // Dock to the destination if possible. - var/docking_status = docking_controller.get_docking_status() + else // Otherwise we are about to start one or just finished one. + if(autopilot_delay > 0) // Wait for awhile so people can get on and off. + if(active_docking_controller && shuttle_docking_controller) // Dock to the destination if possible. + var/docking_status = shuttle_docking_controller.get_docking_status() if(docking_status == "undocked") dock() autopilot_say("Docking.") return else if(docking_status == "docking") - return // Give it a few more ticks to finish docking. + return // Give it a few more ticks to finish docking. - if(autopilot_delay % 10 == 0) // Every ten ticks. + if(autopilot_delay % 10 == 0) // Every ten ticks. var/seconds_left = autopilot_delay * 2 - if(seconds_left >= 60) // A minute + if(seconds_left >= 60) // A minute var/minutes_left = FLOOR(seconds_left / 60, 1) seconds_left = seconds_left % 60 autopilot_say("Departing in [minutes_left] minute\s[seconds_left ? ", [seconds_left] seconds":""].") @@ -95,27 +96,27 @@ autopilot_say("Departing in [seconds_left] seconds.") autopilot_delay-- - else // Time to go. - if(docking_controller && !skip_docking_checks()) // Undock if possible. - var/docking_status = docking_controller.get_docking_status() + else // Time to go. + if(active_docking_controller && shuttle_docking_controller) // Undock if possible. + var/docking_status = shuttle_docking_controller.get_docking_status() if(docking_status == "docked") undock() autopilot_say("Undocking.") return else if(docking_status == "undocking") - return // Give it a few more ticks to finish undocking. + return // Give it a few more ticks to finish undocking. autopilot_delay = initial(autopilot_delay) autopilot_say("Taking off.") web_master.process_autopath() -/datum/shuttle/web_shuttle/proc/update_helmets() +/datum/shuttle/autodock/web_shuttle/proc/update_helmets() for(var/helm in helmets) - if(!helm) - helmets -= helm - continue var/obj/item/clothing/head/pilot/H = helm - if(!H.shuttle_comp || get_area(H.shuttle_comp) != get_area(H)) + if(QDELETED(H)) + helmets -= H + continue + if(!H.shuttle_comp || !(get_area(H) in shuttle_area)) H.shuttle_comp = null H.audible_message("\The [H] pings as it loses it's connection with the ship.") H.update_hud("discon") @@ -123,31 +124,31 @@ else H.update_hud(moving_status) -/datum/shuttle/web_shuttle/proc/adjust_autopilot(on) +/datum/shuttle/autodock/web_shuttle/proc/adjust_autopilot(on) if(on) if(autopilot) return autopilot = TRUE autopilot_delay = initial(autopilot_delay) - SSshuttle.process_shuttles += src + SSshuttle.process_shuttles |= src else if(!autopilot) return autopilot = FALSE SSshuttle.process_shuttles -= src -/datum/shuttle/web_shuttle/proc/autopilot_say(message) // Makes the autopilot 'talk' to the passengers. +/datum/shuttle/autodock/web_shuttle/proc/autopilot_say(message) // Makes the autopilot 'talk' to the passengers. var/padded_message = "shuttle autopilot states, \"[message]\"" - message_passengers(current_area, padded_message) + message_passengers(padded_message) -/datum/shuttle/web_shuttle/proc/rename_shuttle(mob/user) +/datum/shuttle/autodock/web_shuttle/proc/rename_shuttle(mob/user) if(!can_rename) to_chat(user, "You can't rename this vessel.") return var/new_name = input(user, "Please enter a new name for this vessel. Note that you can only set its name once, so choose wisely.", "Rename Shuttle", visible_name) as null|text var/sanitized_name = sanitizeName(new_name, MAX_NAME_LEN, TRUE) if(sanitized_name) - //can_rename = FALSE //VOREStation Removal + //can_rename = FALSE to_chat(user, "You've renamed the vessel to '[sanitized_name]'.") message_admins("[key_name_admin(user)] renamed shuttle '[visible_name]' to '[sanitized_name]'.") visible_name = sanitized_name @@ -159,9 +160,11 @@ icon_state = "flightcomp_center" icon_keyboard = "flight_center_key" icon_screen = "flight_center" - var/list/my_doors //Should be list("id_tag" = "Pretty Door Name", ...) - var/list/my_sensors //Should be list("id_tag" = "Pretty Sensor Name", ...) + var/list/my_doors // Should be list("id_tag" = "Pretty Door Name", ...) + var/list/my_sensors // Should be list("id_tag" = "Pretty Sensor Name", ...) +// Note - Searching own area for doors/sensors is fine for legacy web shuttles as they are single-area. +// However if this code is copied to future multi-area shuttles, should search in all shuttle areas /obj/machinery/computer/shuttle_control/web/Initialize() . = ..() var/area/my_area = get_area(src) @@ -186,7 +189,7 @@ log_debug("[my_area] shuttle computer couldn't find [lost] sensor!") /obj/machinery/computer/shuttle_control/web/attackby(obj/I, mob/user) - var/datum/shuttle/web_shuttle/shuttle = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/web_shuttle/shuttle = SSshuttle.shuttles[shuttle_tag] if(shuttle && istype(I,/obj/item/clothing/head/pilot)) var/obj/item/clothing/head/pilot/H = I H.shuttle_comp = src @@ -208,7 +211,7 @@ /* // If nanoUI falls over and you want a non-nanoUI UI, feel free to uncomment this section. - var/datum/shuttle/web_shuttle/WS = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/web_shuttle/WS = SSshuttle.shuttles[shuttle_tag] if(!istype(WS)) message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.") return @@ -234,7 +237,7 @@ dat += "[route.display_route(WS.current_destination)]
" - //Docking + // Docking dat += "

" if(WS.skip_docking_checks()) dat += "Docking Status: Not in use." @@ -272,8 +275,9 @@ /obj/machinery/computer/shuttle_control/web/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] var/list/routes[0] - var/datum/shuttle/web_shuttle/shuttle = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/web_shuttle/shuttle = SSshuttle.shuttles[shuttle_tag] if(!istype(shuttle)) + to_chat(user, "Unable to establish link with the shuttle.") return var/list/R = shuttle.web_master.get_available_routes() @@ -290,7 +294,7 @@ routes.Add(list(list("name" = html_encode(capitalize(route.display_route(shuttle.web_master.current_destination) )), "index" = i, "travel_time" = travel_time))) - var/shuttle_location = shuttle.web_master.current_destination.name // Destination related, not loc. + var/shuttle_location = shuttle.web_master.current_destination.name // Destination related, not loc. var/future_location = null if(shuttle.web_master.future_destination) future_location = shuttle.web_master.future_destination.name @@ -310,7 +314,7 @@ var/total_time = shuttle.arrive_time - shuttle.depart_time var/percent_finished = 0 - if(total_time) // Need to check or we might divide by zero. + if(total_time) // Need to check or we might divide by zero. percent_finished = (elapsed_time / total_time) * 100 @@ -333,11 +337,11 @@ "future_location" = future_location, "shuttle_state" = shuttle_state, "routes" = routes, - "has_docking" = shuttle.docking_controller? 1 : 0, + "has_docking" = shuttle.shuttle_docking_controller? 1 : 0, "skip_docking" = shuttle.skip_docking_checks(), "is_moving" = shuttle.moving_status != SHUTTLE_IDLE, - "docking_status" = shuttle.docking_controller? shuttle.docking_controller.get_docking_status() : null, - "docking_override" = shuttle.docking_controller? shuttle.docking_controller.override_enabled : null, + "docking_status" = shuttle.shuttle_docking_controller? shuttle.shuttle_docking_controller.get_docking_status() : null, + "docking_override" = shuttle.shuttle_docking_controller? shuttle.shuttle_docking_controller.override_enabled : null, "is_in_transit" = shuttle.has_arrive_time(), "travel_progress" = between(0, percent_finished, 100), "time_left" = round( (total_time - elapsed_time) / 10), @@ -360,13 +364,13 @@ /obj/machinery/computer/shuttle_control/web/Topic(href, href_list) - if(..()) - return 1 + if((. = ..())) + return usr.set_machine(src) src.add_fingerprint(usr) - var/datum/shuttle/web_shuttle/WS = SSshuttle.shuttles[shuttle_tag] + var/datum/shuttle/autodock/web_shuttle/WS = SSshuttle.shuttles[shuttle_tag] if(!istype(WS)) message_admins("ERROR: Shuttle computer ([src]) ([shuttle_tag]) could not find their shuttle in the shuttles list.") return @@ -436,19 +440,38 @@ message_admins("ERROR: Shuttle computer was asked to travel to a nonexistant destination.") return + WS.next_location = target_destination.my_landmark + if(!can_move(WS, usr)) + return + WS.web_master.future_destination = target_destination to_chat(usr, "[WS.visible_name] flight computer received command.") - WS.web_master.reset_autopath() // Deviating from the path will almost certainly confuse the autopilot, so lets just reset its memory. + WS.web_master.reset_autopath() // Deviating from the path will almost certainly confuse the autopilot, so lets just reset its memory. var/travel_time = new_route.travel_time * WS.flight_time_modifier - + // TODO Change this to use proccess stuff of autodock! if(new_route.interim && new_route.travel_time) - WS.long_jump(WS.current_area, target_destination.my_area, new_route.interim, travel_time / 10) + WS.long_jump(target_destination.my_landmark, new_route.interim, travel_time / 10) else - WS.short_jump(WS.current_area, target_destination.my_area) + WS.short_jump(target_destination.my_landmark) ui_interact(usr) +// Check if we're undocked, give option to force launch +/obj/machinery/computer/shuttle_control/web/proc/check_docking(datum/shuttle/autodock/MS) + if(MS.skip_docking_checks() || MS.check_undocked()) + return 1 + + var/choice = alert("The shuttle is currently docked! Please undock before continuing.","Error","Cancel","Force Launch") + if(choice == "Cancel") + return 0 + + choice = alert("Forcing a shuttle launch while docked may result in severe injury, death and/or damage to property. Are you sure you wish to continue?", "Force Launch", "Force Launch", "Cancel") + if(choice == "Cancel") + return 0 + + return 1 + // Props, for now. /obj/structure/flight_left name = "flight computer meters" @@ -466,19 +489,26 @@ density = TRUE anchored = TRUE -//An object for creating a shuttle destination to dynamically loaded maps +// An object for creating a shuttle destination to dynamically loaded maps /obj/shuttle_connector name = "shuttle connector" - var/shuttle_name //Text name of the shuttle to connect to - var/list/destinations //Make sure this STARTS with a destination that builds a route to one that always exists as an anchor. + var/shuttle_name // Text name of the shuttle to connect to + var/list/destinations // Make sure this STARTS with a destination that builds a route to one that always exists as an anchor. /obj/shuttle_connector/Initialize() . = ..() - SSshuttle.OnDocksInitialized(CALLBACK(src, .proc/setup_routes)) + GLOB.shuttle_added.register_global(src, .proc/setup_routes) -/obj/shuttle_connector/proc/setup_routes() - if(destinations && shuttle_name) - var/datum/shuttle/web_shuttle/ES = SSshuttle.shuttles[shuttle_name] +/obj/shuttle_connector/Destroy() + GLOB.shuttle_added.unregister_global(src, .proc/setup_routes) + . = ..() + +// This is called whenever a shuttle is initialized. If its our shuttle, do our thing! +/obj/shuttle_connector/proc/setup_routes(var/new_shuttle) + var/datum/shuttle/autodock/web_shuttle/ES = SSshuttle.shuttles[shuttle_name] + if(ES != new_shuttle) + return // Its not our shuttle! Ignore! + if(destinations && istype(ES)) var/datum/shuttle_web_master/WM = ES.web_master for(var/new_dest in destinations) @@ -487,11 +517,13 @@ for(var/type_to_link in D.routes_to_make) var/travel_delay = D.routes_to_make[type_to_link] - D.link_destinations(WM.get_destination_by_type(type_to_link), D.preferred_interim_area, travel_delay) + D.link_destinations(WM.get_destination_by_type(type_to_link), D.preferred_interim_tag, travel_delay) + else + warning("[log_info_line()]'s shuttle [global.log_info_line(ES)] initialized but destinations:[destinations]") qdel(src) -//A sensor for detecting air outside shuttles! Handy, that. +// A sensor for detecting air outside shuttles! Handy, that. /obj/machinery/shuttle_sensor name = "environment sensor" icon = 'icons/obj/airlock_machines.dmi' @@ -499,7 +531,7 @@ var/id_tag /obj/machinery/shuttle_sensor/process() - return PROCESS_KILL //nty + return PROCESS_KILL //nty /obj/machinery/shuttle_sensor/proc/air_list() . = list("reading" = FALSE) diff --git a/code/modules/shuttles/web_datums.dm b/code/modules/shuttles/web_datums.dm index fc90e3f2b3e..832e2d75a64 100644 --- a/code/modules/shuttles/web_datums.dm +++ b/code/modules/shuttles/web_datums.dm @@ -8,7 +8,7 @@ /datum/shuttle_route var/datum/shuttle_destination/start = null // One of the two sides of this route. Start just means it was the creator of this route. var/datum/shuttle_destination/end = null // The second side. - var/area/interim = null // Where the shuttle sits during the movement. Make sure no other shuttle shares this or Very Bad Things will happen. + var/var/obj/effect/shuttle_landmark/interim // Where the shuttle sits during the movement. Make sure no other shuttle shares this or Very Bad Things will happen. var/travel_time = 0 // How long it takes to move from start to end, or end to start. Set to 0 for instant travel. var/one_way = FALSE // If true, you can't travel from end to start. @@ -16,7 +16,7 @@ start = _start end = _end if(_interim) - interim = locate(_interim) + interim = SSshuttle.get_landmark(_interim) travel_time = _time one_way = _oneway @@ -50,14 +50,12 @@ // This is the second datum, and contains information on all the potential destinations for a specific shuttle. /datum/shuttle_destination var/name = "a place" // Name of the destination, used for the flight computer. - var/area/my_area = null // Where the shuttle will move to when it actually arrives. + var/obj/effect/shuttle_landmark/my_landmark = null // Where the shuttle will move to when it actually arrives. var/datum/shuttle_web_master/master = null // The datum that does the coordination with the actual shuttle datum. var/list/routes = list() // Routes that are connected to this destination. - var/preferred_interim_area = null // When building a new route, use this interim area. + var/preferred_interim_tag = null // When building a new route, use interim landmark with this tag. var/skip_me = FALSE // We will not autocreate this one. Some map must be doing it. - var/dock_target = null // The tag_id that the shuttle will use to try to dock to the destination, if able. - var/radio_announce = 0 // Whether it will make a station announcement (0) or a radio announcement (1). var/announcer = null // The name of the 'announcer' that will say the arrival/departure messages. Defaults to the map's boss name if blank. // var/arrival_message = null // Message said if the ship enters this destination. Not announced if the ship is cloaked. @@ -72,7 +70,9 @@ var/list/routes_to_make = list() /datum/shuttle_destination/New(var/new_master) - my_area = locate(my_area) + my_landmark = SSshuttle.get_landmark(my_landmark) + if(!my_landmark) + log_debug("Web shuttle destination '[name]' could not find its landmark '[my_landmark]'.") master = new_master /datum/shuttle_destination/Destroy() @@ -88,7 +88,7 @@ already_made += src.type to_chat(world, "SHUTTLES: [name] is going to build destinations. already_made list is \[[english_list(already_made)]\]") for(var/type_to_make in destinations_to_create) - if(type_to_make in already_made) // Avoid circular initializations. + if(type_to_make in already_made) // Avoid circular initializations. to_chat(world, "SHUTTLES: [name] can't build [type_to_make] due to being a duplicate.") continue @@ -99,7 +99,7 @@ // Now link our new destination to us. var/travel_delay = destinations_to_create[type_to_make] - link_destinations(new_dest, preferred_interim_area, travel_delay) + link_destinations(new_dest, preferred_interim_tag, travel_delay) to_chat(world, "SHUTTLES: [name] has linked themselves to [new_dest.name]") to_chat(world, "SHUTTLES: [name] has finished building destinations. already_made list is \[[english_list(already_made)]\].") @@ -135,14 +135,14 @@ else global_announcer.autosay(get_arrival_message(),(announcer ? announcer : "[GLOB.using_map.boss_name]")) -/datum/shuttle_destination/proc/link_destinations(var/datum/shuttle_destination/other_place, var/area/interim_area, var/travel_time = 0) +/datum/shuttle_destination/proc/link_destinations(var/datum/shuttle_destination/other_place, var/interim_tag, var/travel_time = 0) // First, check to make sure this doesn't cause a duplicate route. for(var/datum/shuttle_route/R in routes) if(R.start == other_place || R.end == other_place) return // Now we can connect them. - var/datum/shuttle_route/new_route = new(src, other_place, interim_area, travel_time) + var/datum/shuttle_route/new_route = new(src, other_place, interim_tag, travel_time) routes += new_route other_place.routes += new_route @@ -166,7 +166,7 @@ // This is the third and final datum, which coordinates with the shuttle datum to tell it where it is, where it can go, and how long it will take. // It is also responsible for instancing all the destinations it has control over, and linking them together. /datum/shuttle_web_master - var/datum/shuttle/web_shuttle/my_shuttle = null // Ref to the shuttle this datum is coordinating with. + var/datum/shuttle/autodock/web_shuttle/my_shuttle = null // Ref to the shuttle this datum is coordinating with. var/datum/shuttle_destination/current_destination = null // Where the shuttle currently is. Bit of a misnomer. var/datum/shuttle_destination/future_destination = null // Where it will be in the near future. var/datum/shuttle_destination/starting_destination = null // Where the shuttle will start at, generally at the home base. @@ -204,7 +204,7 @@ for(var/datum/shuttle_destination/D in destinations) for(var/type_to_link in D.routes_to_make) var/travel_delay = D.routes_to_make[type_to_link] - D.link_destinations(get_destination_by_type(type_to_link), D.preferred_interim_area, travel_delay) + D.link_destinations(get_destination_by_type(type_to_link), D.preferred_interim_tag, travel_delay) /datum/shuttle_web_master/proc/on_shuttle_departure() current_destination.exit() @@ -214,11 +214,6 @@ future_destination.enter() current_destination = future_destination future_destination = null - my_shuttle.current_area = current_destination.my_area - -/datum/shuttle_web_master/proc/current_dock_target() - if(current_destination) - return current_destination.dock_target /datum/shuttle_web_master/proc/get_available_routes() if(current_destination) @@ -253,20 +248,21 @@ return FALSE future_destination = R.get_other_side(current_destination) - var/travel_time = R.travel_time * my_shuttle.flight_time_modifier * 2 // Autopilot is less efficent than having someone flying manually. + var/travel_time = R.travel_time * my_shuttle.flight_time_modifier * 2 // Autopilot is less efficent than having someone flying manually. + // TODO Change this to use proccess stuff of autodock! if(R.interim && R.travel_time > 0) - my_shuttle.long_jump(my_shuttle.current_area, future_destination.my_area, R.interim, travel_time / 10) + my_shuttle.long_jump(future_destination.my_landmark, R.interim, travel_time / 10) else - my_shuttle.short_jump(my_shuttle.current_area, future_destination.my_area) - return TRUE // Note this will return before the shuttle actually arrives. + my_shuttle.short_jump(future_destination.my_landmark) + return TRUE // Note this will return before the shuttle actually arrives. /datum/shuttle_web_master/proc/process_autopath() - if(!autopath) // If we don't have a path, get one. + if(!autopath) // If we don't have a path, get one. if(!autopaths.len) return choose_path() - if(!autopath) // Still nothing, oh well. + if(!autopath) // Still nothing, oh well. return var/datum/shuttle_destination/target = autopath.get_next_node() diff --git a/code/unit_tests/zas_tests.dm b/code/unit_tests/zas_tests.dm index e53b286e56d..ee156e4a6b0 100644 --- a/code/unit_tests/zas_tests.dm +++ b/code/unit_tests/zas_tests.dm @@ -78,18 +78,18 @@ return 1 /datum/unit_test/zas_area_test/supply_centcomm - name = "ZAS: Supply Shuttle (CentCom)" - area_path = /area/supply/dock + name = "ZAS: Supply Shuttle" + area_path = /area/shuttle/supply /datum/unit_test/zas_area_test/emergency_shuttle name = "ZAS: Emergency Shuttle" - area_path = /area/shuttle/escape/centcom + area_path = /area/shuttle/escape /datum/unit_test/zas_area_test/ai_chamber name = "ZAS: AI Chamber" area_path = /area/ai -// VOREStation Edit - We don't have this anymore - Tether +// We don't have this anymore - Tether // /datum/unit_test/zas_area_test/mining_shuttle_at_station // name = "ZAS: Mining Shuttle (Station)" // area_path = /area/shuttle/mining/station @@ -98,7 +98,7 @@ name = "ZAS: Cargo Maintenance" area_path = /area/maintenance/cargo -// VOREStation Edit - We don't have this anymore - Tether +// We don't have this anymore - Tether // /datum/unit_test/zas_area_test/eng_shuttle // name = "ZAS: Construction Site Shuttle (Station)" // area_path = /area/shuttle/constructionsite/station diff --git a/icons/effects/numbers.dmi b/icons/effects/numbers.dmi new file mode 100644 index 0000000000000000000000000000000000000000..fcf9463ccd22dec264ce1022d31e00f4a6d10950 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRv#0(^j0@@sb6lZ`>h%1nuvf^Clgu7d&edz{r z7)yfuf*Bm1-ADs++N(k$N?cNllZ!G7N;32F7#J$%1cwzAm45#cT=4Ph6D@CDt#fD2 z2X6>9xM=*~kx^&fhKE`_oU06!RvenKfJ?YZ%Lm9&UU6v70xs?*EgjBP7mhA(u zLi<;?tN=R6%G1R$gkz>@&p|;31CB!nPL`Oq7u<8owcp9TV8#r`i7{WYiVAPbrN2Bg pf%U{Ar8QCvq4IVYm~Ao|n0@yNOP2Rrt_PaJ;OXk;vd$@?2>^t%Z}|WK literal 0 HcmV?d00001 diff --git a/icons/obj/overmap.dmi b/icons/obj/overmap.dmi new file mode 100644 index 0000000000000000000000000000000000000000..859cd6c3afe5389a9d709159720bd45e26a228f9 GIT binary patch literal 10656 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 V6R|6Iz|KqHj@rH36)M&d{{j9QLbd<^ literal 0 HcmV?d00001 diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm index 8f9056261a0..beb60d57dea 100644 --- a/maps/~map_system/maps.dm +++ b/maps/~map_system/maps.dm @@ -24,21 +24,21 @@ var/list/all_maps = list() var/path var/list/zlevels = list() - var/zlevel_datum_type // If populated, all subtypes of this type will be instantiated and used to populate the *_levels lists. + var/zlevel_datum_type // If populated, all subtypes of this type will be instantiated and used to populate the *_levels lists. var/list/station_levels = list() // Z-levels the station exists on - var/list/admin_levels = list() // Z-levels for admin functionality (Centcom, shuttle transit, etc) + var/list/admin_levels = list() // Z-levels for admin functionality (Centcom, shuttle transit, etc) var/list/contact_levels = list() // Z-levels that can be contacted from the station, for eg announcements - var/list/player_levels = list() // Z-levels a character can typically reach - var/list/sealed_levels = list() // Z-levels that don't allow random transit at edge - var/list/xenoarch_exempt_levels = list() //Z-levels exempt from xenoarch finds and digsites spawning. - var/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump) + var/list/player_levels = list() // Z-levels a character can typically reach + var/list/sealed_levels = list() // Z-levels that don't allow random transit at edge + var/list/xenoarch_exempt_levels = list() // Z-levels exempt from xenoarch finds and digsites spawning. + var/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump) - var/list/map_levels // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset. + var/list/map_levels // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset. var/list/base_turf_by_z = list() // Custom base turf by Z-level. Defaults to world.turf for unlisted Z-levels var/list/usable_email_tlds = list("freemail.nt") - //This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there. + // This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there. var/list/accessible_z_levels = list() //List of additional z-levels to load above the existing .dmm file z-levels using the maploader. Must be map template >>> NAMES <<<. @@ -47,34 +47,33 @@ var/list/all_maps = list() //Similar to above, but only pick ONE to load, useful for random away missions and whatnot var/list/lateload_single_pick = list() - var/list/allowed_jobs = list() //Job datums to use. - //Works a lot better so if we get to a point where three-ish maps are used - //We don't have to C&P ones that are only common between two of them - //That doesn't mean we have to include them with the rest of the jobs though, especially for map specific ones. - //Also including them lets us override already created jobs, letting us keep the datums to a minimum mostly. - //This is probably a lot longer explanation than it needs to be. + var/list/allowed_jobs = list() // Job datums to use. + // Works a lot better so if we get to a point where three-ish maps are used + // We don't have to C&P ones that are only common between two of them + // That doesn't mean we have to include them with the rest of the jobs though, especially for map specific ones. + // Also including them lets us override already created jobs, letting us keep the datums to a minimum mostly. + // This is probably a lot longer explanation than it needs to be. var/list/holomap_smoosh // List of lists of zlevels to smoosh into single icons var/list/holomap_offset_x = list() var/list/holomap_offset_y = list() var/list/holomap_legend_x = list() var/list/holomap_legend_y = list() - var/list/meteor_strike_areas // VOREStation Edit - Areas meteor strikes may choose to hit. - var/ai_shell_restricted = FALSE //VOREStation Addition - are there z-levels restricted? - var/ai_shell_allowed_levels = list() //VOREStation Addition - which z-levels ARE we allowed to visit? + var/list/meteor_strike_areas // Areas meteor strikes may choose to hit. + var/ai_shell_restricted = FALSE // Are there z-levels restricted? + var/ai_shell_allowed_levels = list() // Which z-levels ARE we allowed to visit? - //VOREStation Addition Start - belter stuff + // Belter stuff var/list/belter_docked_z = list() var/list/belter_transit_z = list() var/list/belter_belt_z = list() - //VOREStation Addition End - belter stuff var/station_name = "BAD Station" var/station_short = "Baddy" - var/dock_name = "THE PirateBay" - var/dock_type = "station" //VOREStation Edit - for a list of valid types see the switch block in air_traffic.dm at line 148 - var/boss_name = "Captain Roger" - var/boss_short = "Cap'" + var/dock_name = "THE PirateBay" + var/dock_type = "station" // For a list of valid types see the switch block in air_traffic.dm at line 148 + var/boss_name = "Captain Roger" + var/boss_short = "Cap'" var/company_name = "BadMan" var/company_short = "BM" var/starsys_name = "Dull Star" @@ -83,38 +82,41 @@ var/list/all_maps = list() var/shuttle_leaving_dock var/shuttle_called_message var/shuttle_recall_message - var/shuttle_name = "NAS |Hawking|" //VS ADD + var/shuttle_name = "NAS |Hawking|" var/emergency_shuttle_docked_message var/emergency_shuttle_leaving_dock var/emergency_shuttle_called_message var/emergency_shuttle_recall_message - var/list/station_networks = list() // Camera networks that will show up on the console. + var/list/station_networks = list() // Camera networks that will show up on the console. var/list/secondary_networks = list() // Camera networks that exist, but don't show on regular camera monitors. var/bot_patrolling = TRUE // Determines if this map supports automated bot patrols var/allowed_spawns = list("Arrivals Shuttle","Gateway", "Cryogenic Storage", "Cyborg Storage") - // VOREStation Edit - Persistence! - var/datum/spawnpoint/spawnpoint_died = /datum/spawnpoint/arrivals // Used if you end the round dead. - var/datum/spawnpoint/spawnpoint_left = /datum/spawnpoint/arrivals // Used of you end the round at centcom. - var/datum/spawnpoint/spawnpoint_stayed = /datum/spawnpoint/cryo // Used if you end the round on the station. - // VOREStation Edit End + // Persistence! + var/datum/spawnpoint/spawnpoint_died = /datum/spawnpoint/arrivals // Used if you end the round dead. + var/datum/spawnpoint/spawnpoint_left = /datum/spawnpoint/arrivals // Used of you end the round at centcom. + var/datum/spawnpoint/spawnpoint_stayed = /datum/spawnpoint/cryo // Used if you end the round on the station. + var/use_overmap = 0 // If overmap should be used (including overmap space travel override) + var/overmap_size = 20 // Dimensions of overmap zlevel if overmap is used. + var/overmap_z = 0 // If 0 will generate overmap zlevel on init. Otherwise will populate the zlevel provided. + var/overmap_event_areas = 0 // How many event "clouds" will be generated - var/lobby_icon = 'icons/misc/title.dmi' // The icon which contains the lobby image(s) - var/list/lobby_screens = list("mockingjay00") // The list of lobby screen to pick() from. If left unset the first icon state is always selected. + var/lobby_icon = 'icons/misc/title.dmi' // The icon which contains the lobby image(s) + var/list/lobby_screens = list("mockingjay00") // The list of lobby screen to pick() from. If left unset the first icon state is always selected. - var/default_law_type = /datum/ai_laws/nanotrasen // The default lawset use by synth units, if not overriden by their laws var. + var/default_law_type = /datum/ai_laws/nanotrasen // The default lawset use by synth units, if not overriden by their laws var. - var/id_hud_icons = 'icons/mob/hud.dmi' // Used by the ID HUD (primarily sechud) overlay. + var/id_hud_icons = 'icons/mob/hud.dmi' // Used by the ID HUD (primarily sechud) overlay. // Some maps include areas for that map only and don't exist when not compiled, so Travis needs this to learn of new areas that are specific to a map. var/list/unit_test_exempt_areas = list() var/list/unit_test_exempt_from_atmos = list() var/list/unit_test_exempt_from_apc = list() - var/list/unit_test_z_levels //To test more than Z1, set your z-levels to test here. + var/list/unit_test_z_levels // To test more than Z1, set your z-levels to test here. /datum/map/New() ..() @@ -135,8 +137,8 @@ var/list/all_maps = list() // Used to apply various post-compile procedural effects to the map. /datum/map/proc/refresh_mining_turfs() // Update all turfs to ensure everything looks good post-generation. Yes, - // it's brute-forcey, but frankly the alternative is a mine turf rewrite. - for(var/turf/simulated/mineral/M in world) // Ugh. + // it's brute-forcey, but frankly the alternative is a mine turf rewrite. + for(var/turf/simulated/mineral/M in world) // Ugh. M.update_icon() CHECK_TICK @@ -174,7 +176,7 @@ var/list/all_maps = list() return Z.name // Another way to setup the map datum that can be convenient. Just declare all your zlevels as subtypes of a common -// subtype of /datum/map_z_level and set zlevel_datum_type on /datum/map to have the lists auto-initialized. +// subtype of /datum/map_z_level and set zlevel_datum_type on /datum/map to have the lists auto-initialized. // Structure to hold zlevel info together in one nice convenient package. /datum/map_z_level @@ -234,17 +236,17 @@ var/list/all_maps = list() // This list needs to be purged but people insist on adding more cruft to the radio. /datum/map/proc/default_internal_channels() return list( - num2text(PUB_FREQ) = list(), - num2text(AI_FREQ) = list(access_synth), - num2text(ENT_FREQ) = list(), - num2text(ERT_FREQ) = list(access_cent_specops), - num2text(COMM_FREQ) = list(access_heads), - num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics), - num2text(MED_FREQ) = list(access_medical_equip), + num2text(PUB_FREQ) = list(), + num2text(AI_FREQ) = list(access_synth), + num2text(ENT_FREQ) = list(), + num2text(ERT_FREQ) = list(access_cent_specops), + num2text(COMM_FREQ) = list(access_heads), + num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics), + num2text(MED_FREQ) = list(access_medical_equip), num2text(MED_I_FREQ) = list(access_medical_equip), - num2text(SEC_FREQ) = list(access_security), + num2text(SEC_FREQ) = list(access_security), num2text(SEC_I_FREQ) = list(access_security), - num2text(SCI_FREQ) = list(access_tox,access_robotics,access_xenobiology), - num2text(SUP_FREQ) = list(access_cargo), - num2text(SRV_FREQ) = list(access_janitor, access_hydroponics), + num2text(SCI_FREQ) = list(access_tox,access_robotics,access_xenobiology), + num2text(SUP_FREQ) = list(access_cargo), + num2text(SRV_FREQ) = list(access_janitor, access_hydroponics), ) diff --git a/nano/templates/shuttle_control_console_multi.tmpl b/nano/templates/shuttle_control_console_multi.tmpl new file mode 100644 index 00000000000..8b46ba7edfb --- /dev/null +++ b/nano/templates/shuttle_control_console_multi.tmpl @@ -0,0 +1,84 @@ +

Shuttle Status

+
+
+ {{:data.shuttle_status}} +
+ {{if data.can_cloak}} +
+ {{:data.legit ? "ATC Inhibitor" : "Cloaking Field"}} is {{:data.cloaked ? "enabled" : "disabled"}}. {{:helper.link('Toggle', 'arrowreturn-1-s', {'toggle_cloaked' : '1'}) }} +
+ {{/if}} +
+
+
+
+ Bluespace Drive: +
+
+ {{if data.shuttle_state == "idle"}} + IDLE + {{else data.shuttle_state == "warmup"}} + SPINNING UP + {{else data.shuttle_state == "in_transit"}} + ENGAGED + {{else}} + ERROR + {{/if}} +
+
+
+{{if data.has_docking}} +
+
+
+ Docking Status: +
+
+ {{if data.docking_status == "docked"}} + DOCKED + {{else data.docking_status == "docking"}} + {{if !data.docking_override}} + DOCKING + {{else}} + DOCKING-MANUAL + {{/if}} + {{else data.docking_status == "undocking"}} + {{if !data.docking_override}} + UNDOCKING + {{else}} + UNDOCKING-MANUAL + {{/if}} + {{else data.docking_status == "undocked"}} + UNDOCKED + {{else}} + ERROR + {{/if}} +
+
+ Docking Codes: +
+
+ {{:helper.link(data.docking_codes ? data.docking_codes : 'Not set', null, {'set_codes' : '1'}, null , null)}} +
+
+
+{{/if}} +
+
+ Current Destination: +
+ {{:data.destination_name}} +
+ {{:helper.link('Choose Destination', 'arrowreturn-1-s', {'pick' : '1'}, data.can_pick ? null : 'disabled' , null)}} +
+
+

Shuttle Control

+
+
+
+ {{:helper.link('Launch Shuttle', 'arrowthickstop-1-e', {'move' : '1'}, data.can_launch ? null : 'disabled' , null)}} + {{:helper.link('Cancel Launch', 'cancel', {'cancel' : '1'}, data.can_cancel ? null : 'disabled' , null)}} + {{:helper.link('Force Launch', 'alert', {'force' : '1'}, data.can_force ? null : 'disabled' , data.can_force ? 'redButton' : null)}} +
+
+
\ No newline at end of file diff --git a/sound/effects/shuttles/shuttle_landing.ogg b/sound/effects/shuttles/shuttle_landing.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fcb723416b9a3c9f9d9a70d994fac1bd587a491a GIT binary patch literal 115520 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

6Z*1_{Ytc7h}W=Gv7zs^a1CP( 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

K0P}ysk>PD7$uYEgQ3-#$;gzZ&dA=GweOt$ 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 z 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%0A^jYTKj9BTY3; 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

*V1=WKk_k5+YaGko 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 DtjsSh literal 0 HcmV?d00001 diff --git a/vorestation.dme b/vorestation.dme index 20364b86684..9bc5655d2aa 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -351,6 +351,8 @@ #include "code\datums\observation\_defines.dm" #include "code\datums\observation\equipped.dm" #include "code\datums\observation\observation.dm" +#include "code\datums\observation\shuttle_added.dm" +#include "code\datums\observation\shuttle_moved.dm" #include "code\datums\observation\turf_changed.dm" #include "code\datums\observation\unequipped.dm" #include "code\datums\observation\~cleanup.dm" @@ -514,6 +516,7 @@ #include "code\game\area\Away Mission areas.dm" #include "code\game\area\Space Station 13 areas.dm" #include "code\game\area\Space Station 13 areas_vr.dm" +#include "code\game\area\ss13_deprecated_areas.dm" #include "code\game\dna\dna2.dm" #include "code\game\dna\dna2_domutcheck.dm" #include "code\game\dna\dna2_helpers.dm" @@ -860,6 +863,7 @@ #include "code\game\machinery\doors\unpowered.dm" #include "code\game\machinery\doors\windowdoor.dm" #include "code\game\machinery\embedded_controller\airlock_controllers.dm" +#include "code\game\machinery\embedded_controller\airlock_controllers_dummy.dm" #include "code\game\machinery\embedded_controller\airlock_docking_controller.dm" #include "code\game\machinery\embedded_controller\airlock_docking_controller_multi.dm" #include "code\game\machinery\embedded_controller\airlock_program.dm" @@ -2915,7 +2919,9 @@ #include "code\modules\organs\subtypes\xenochimera.dm" #include "code\modules\organs\subtypes\xenos.dm" #include "code\modules\overmap\_defines.dm" +#include "code\modules\overmap\overmap_object.dm" #include "code\modules\overmap\sectors.dm" +#include "code\modules\overmap\spacetravel.dm" #include "code\modules\overmap\ships\ship.dm" #include "code\modules\overmap\ships\computers\engine_control.dm" #include "code\modules\overmap\ships\computers\helm.dm" @@ -3265,8 +3271,11 @@ #include "code\modules\shuttles\crashes.dm" #include "code\modules\shuttles\departmental.dm" #include "code\modules\shuttles\escape_pods.dm" +#include "code\modules\shuttles\landmarks.dm" #include "code\modules\shuttles\shuttle.dm" +#include "code\modules\shuttles\shuttle_autodock.dm" #include "code\modules\shuttles\shuttle_console.dm" +#include "code\modules\shuttles\shuttle_console_multi.dm" #include "code\modules\shuttles\shuttle_emergency.dm" #include "code\modules\shuttles\shuttle_ferry.dm" #include "code\modules\shuttles\shuttle_specops.dm"