diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm
index a724fa11f0b..76b520a45fa 100644
--- a/code/ATMOSPHERICS/_atmospherics_helpers.dm
+++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm
@@ -468,6 +468,10 @@
return "REGULAR"
if(PIPING_LAYER_SCRUBBER)
return "SCRUBBER"
+ if(PIPING_LAYER_FUEL)
+ return "FUEL"
+ if(PIPING_LAYER_AUX)
+ return "AUX"
/proc/atmos_pipe_flags_str(pipe_flags)
var/list/dat = list()
@@ -489,6 +493,10 @@
dat += "SUPPLY"
if(connect_types & CONNECT_TYPE_SCRUBBER)
dat += "SCRUBBER"
+ if(connect_types & CONNECT_TYPE_FUEL)
+ dat += "FUEL"
+ if(connect_types & CONNECT_TYPE_AUX)
+ dat += "AUX"
if(connect_types & CONNECT_TYPE_HE)
dat += "HE"
return dat.Join("|")
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index acb1da7b022..6559f28f267 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -209,8 +209,18 @@ Pipelines + Other Objects -> Pipe network
connect_types = CONNECT_TYPE_SUPPLY
layer = PIPES_SUPPLY_LAYER
icon_connect_type = "-supply"
+ if(PIPING_LAYER_FUEL)
+ icon_state = "[icon_state]-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ if(PIPING_LAYER_AUX)
+ icon_state = "[icon_state]-aux"
+ connect_types = CONNECT_TYPE_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
if(pipe_flags & PIPING_ALL_LAYER)
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER|CONNECT_TYPE_FUEL|CONNECT_TYPE_AUX
// Or if we were to do it the TG way...
// pixel_x = PIPE_PIXEL_OFFSET_X(piping_layer)
// pixel_y = PIPE_PIXEL_OFFSET_Y(piping_layer)
diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
index 044d6b0c13d..72e623351a2 100644
--- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
@@ -6,8 +6,8 @@
/obj/machinery/atmospherics/binary/circulator
name = "circulator"
desc = "A gas circulator turbine and heat exchanger."
- icon = 'icons/obj/pipes.dmi'
- icon_state = "circ-off"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "circ-unassembled"
anchored = 0
pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
@@ -22,6 +22,7 @@
var/last_stored_energy_transferred = 0
var/volume_capacity_used = 0
var/stored_energy = 0
+ var/temperature_overlay
density = 1
@@ -76,15 +77,19 @@
update_icon()
/obj/machinery/atmospherics/binary/circulator/update_icon()
- if(stat & (BROKEN|NOPOWER) || !anchored)
- icon_state = "circ-p"
- else if(last_pressure_delta > 0 && recent_moles_transferred > 0)
- if(last_pressure_delta > 5*ONE_ATMOSPHERE)
- icon_state = "circ-run"
+ icon_state = anchored ? "circ-assembled" : "circ-unassembled"
+ cut_overlays()
+ if (stat & (BROKEN|NOPOWER) || !anchored)
+ return 1
+ if (last_pressure_delta > 0 && recent_moles_transferred > 0)
+ if (temperature_overlay)
+ add_overlay(temperature_overlay)
+ if (last_pressure_delta > 5*ONE_ATMOSPHERE)
+ add_overlay("circ-run")
else
- icon_state = "circ-slow"
+ add_overlay("circ-slow")
else
- icon_state = "circ-off"
+ add_overlay("circ-off")
return 1
@@ -97,6 +102,7 @@
"You hear a ratchet.")
if(anchored)
+ temperature_overlay = null
if(dir & (NORTH|SOUTH))
initialize_directions = NORTH|SOUTH
else if(dir & (EAST|WEST))
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 2f276160fe7..809cc987ebb 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -176,7 +176,7 @@
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index 191e6291ea6..1c501e87f0f 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -151,7 +151,7 @@
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index e241cc944b9..0df02174976 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -18,6 +18,7 @@ Thus, the two variables affect pump operation are set in New():
construction_type = /obj/item/pipe/directional
pipe_state = "pump"
level = 1
+ var/base_icon = "pump"
name = "gas pump"
desc = "A pump that moves gas from one place to another."
@@ -49,12 +50,31 @@ Thus, the two variables affect pump operation are set in New():
icon_state = "map_on"
use_power = USE_POWER_IDLE
+/obj/machinery/atmospherics/binary/pump/fuel
+ icon_state = "map_off-fuel"
+ base_icon = "pump-fuel"
+ icon_connect_type = "-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+
+/obj/machinery/atmospherics/binary/pump/fuel/on
+ icon_state = "map_on-fuel"
+ use_power = USE_POWER_IDLE
+
+/obj/machinery/atmospherics/binary/pump/aux
+ icon_state = "map_off-aux"
+ base_icon = "pump-aux"
+ icon_connect_type = "-aux"
+ connect_types = CONNECT_TYPE_AUX
+
+/obj/machinery/atmospherics/binary/pump/aux/on
+ icon_state = "map_on-aux"
+ use_power = USE_POWER_IDLE
/obj/machinery/atmospherics/binary/pump/update_icon()
if(!powered())
- icon_state = "off"
+ icon_state = "[base_icon]-off"
else
- icon_state = "[use_power ? "on" : "off"]"
+ icon_state = "[use_power ? "[base_icon]-on" : "[base_icon]-off"]"
/obj/machinery/atmospherics/binary/pump/update_underlays()
if(..())
@@ -62,8 +82,8 @@ Thus, the two variables affect pump operation are set in New():
var/turf/T = get_turf(src)
if(!istype(T))
return
- add_underlay(T, node1, turn(dir, -180))
- add_underlay(T, node2, dir)
+ add_underlay(T, node1, turn(dir, -180), node1?.icon_connect_type)
+ add_underlay(T, node2, dir, node2?.icon_connect_type)
/obj/machinery/atmospherics/binary/pump/hide(var/i)
update_underlays()
@@ -108,7 +128,7 @@ Thus, the two variables affect pump operation are set in New():
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index fd5033100b1..5b489441db3 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -21,6 +21,20 @@
use_power = USE_POWER_OFF
level = 1
+/obj/machinery/atmospherics/portables_connector/fuel
+ icon_state = "map_connector-fuel"
+ pipe_state = "connector-fuel"
+ icon_connect_type = "-fuel"
+ pipe_flags = PIPING_ONE_PER_TURF
+ connect_types = CONNECT_TYPE_FUEL
+
+/obj/machinery/atmospherics/portables_connector/aux
+ icon_state = "map_connector-aux"
+ pipe_state = "connector-aux"
+ icon_connect_type = "-aux"
+ pipe_flags = PIPING_ONE_PER_TURF
+ connect_types = CONNECT_TYPE_AUX
+
/obj/machinery/atmospherics/portables_connector/init_dir()
initialize_directions = dir
@@ -33,7 +47,7 @@
var/turf/T = get_turf(src)
if(!istype(T))
return
- add_underlay(T, node, dir)
+ add_underlay(T, node, dir, node?.icon_connect_type)
/obj/machinery/atmospherics/portables_connector/hide(var/i)
update_underlays()
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index 3c342c3cdbe..5eeab2c8e48 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -107,7 +107,7 @@
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index 534d8e01305..194a28ddc93 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -53,6 +53,11 @@
use_power = USE_POWER_IDLE
icon_state = "map_vent_out"
+/obj/machinery/atmospherics/unary/vent_pump/aux
+ icon_state = "map_vent_aux"
+ icon_connect_type = "-aux"
+ connect_types = CONNECT_TYPE_AUX //connects to aux pipes
+
/obj/machinery/atmospherics/unary/vent_pump/siphon
pump_direction = 0
@@ -80,7 +85,7 @@
icon = null
initial_loc = get_area(loc)
- area_uid = initial_loc.uid
+ area_uid = "\ref[initial_loc]"
if (!id_tag)
assign_uid()
id_tag = num2text(uid)
@@ -98,6 +103,11 @@
power_channel = EQUIP
power_rating = 45000 //15 kW ~ 20 HP //VOREStation Edit - 45000
+/obj/machinery/atmospherics/unary/vent_pump/high_volume/aux
+ icon_state = "map_vent_aux"
+ icon_connect_type = "-aux"
+ connect_types = CONNECT_TYPE_AUX //connects to aux pipes
+
/obj/machinery/atmospherics/unary/vent_pump/high_volume/New()
..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
@@ -253,7 +263,7 @@
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 6e3f9ef0422..1c1c696b989 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -38,7 +38,7 @@
icon = null
initial_loc = get_area(loc)
- area_uid = initial_loc.uid
+ area_uid = "\ref[initial_loc]"
if (!id_tag)
assign_uid()
id_tag = num2text(uid)
@@ -93,7 +93,7 @@
return 0
var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
+ signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"area" = area_uid,
diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm
index 1e32aa62952..2a63bb3a20a 100644
--- a/code/ATMOSPHERICS/pipes/cap.dm
+++ b/code/ATMOSPHERICS/pipes/cap.dm
@@ -93,6 +93,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/cap/visible/fuel
+ name = "fuel pipe endcap"
+ desc = "An endcap for fuel pipes"
+ icon_state = "cap-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/cap/visible/aux
+ name = "aux pipe endcap"
+ desc = "An endcap for aux pipes"
+ icon_state = "cap-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/cap/hidden
level = 1
icon_state = "cap"
@@ -117,3 +137,23 @@
layer = PIPES_SUPPLY_LAYER
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/cap/visible/fuel
+ name = "fuel pipe endcap"
+ desc = "An endcap for fuel pipes"
+ icon_state = "cap-f-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/cap/hidden/aux
+ name = "aux pipe endcap"
+ desc = "An endcap for aux pipes"
+ icon_state = "cap-f-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
\ No newline at end of file
diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm
index f44bfc56866..a17f78e50df 100644
--- a/code/ATMOSPHERICS/pipes/manifold.dm
+++ b/code/ATMOSPHERICS/pipes/manifold.dm
@@ -108,16 +108,23 @@
underlays.Cut()
var/turf/T = get_turf(src)
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
- var/node1_direction = get_dir(src, node1)
- var/node2_direction = get_dir(src, node2)
- var/node3_direction = get_dir(src, node3)
+ // Unfortunately our nodes are not in consistent directions (see atmos_init()) so do the dance...
+ var/list/directions = list(NORTH, SOUTH, EAST, WEST) // UN-connected directions
directions -= dir
+ if(node1)
+ var/node1_direction = get_dir(src, node1)
+ add_underlay(T, node1, node1_direction, icon_connect_type)
+ directions -= node1_direction
+ if(node2)
+ var/node2_direction = get_dir(src, node2)
+ add_underlay(T, node2, node2_direction, icon_connect_type)
+ directions -= node2_direction
+ if(node3)
+ var/node3_direction = get_dir(src, node3)
+ add_underlay(T, node3, node3_direction, icon_connect_type)
+ directions -= node3_direction
- directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
- directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
- directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
for(var/D in directions)
add_underlay(T,,D,icon_connect_type)
@@ -195,6 +202,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/manifold/visible/fuel
+ name="Fuel pipe manifold"
+ desc = "A manifold composed of fuel pipes"
+ icon_state = "map-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/visible/aux
+ name="Aux pipe manifold"
+ desc = "A manifold composed of aux pipes"
+ icon_state = "map-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/manifold/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -241,6 +268,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/manifold/hidden/fuel
+ name="Fuel pipe manifold"
+ desc = "A manifold composed of fuel pipes"
+ icon_state = "map-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/aux
+ name="Aux pipe manifold"
+ desc = "A manifold composed of aux pipes"
+ icon_state = "map-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
color = PIPE_COLOR_YELLOW
diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm
index 197c1a090b7..7273ac5288e 100644
--- a/code/ATMOSPHERICS/pipes/manifold4w.dm
+++ b/code/ATMOSPHERICS/pipes/manifold4w.dm
@@ -107,36 +107,12 @@
overlays += icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type)
underlays.Cut()
- /*
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
-
-
- directions -= add_underlay(node1)
- directions -= add_underlay(node2)
- directions -= add_underlay(node3)
- directions -= add_underlay(node4)
-
- for(var/D in directions)
- add_underlay(,D)
- */
-
var/turf/T = get_turf(src)
- var/list/directions = list(NORTH, SOUTH, EAST, WEST)
- var/node1_direction = get_dir(src, node1)
- var/node2_direction = get_dir(src, node2)
- var/node3_direction = get_dir(src, node3)
- var/node4_direction = get_dir(src, node4)
-
- directions -= dir
-
- directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
- directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
- directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
- directions -= add_underlay(T,node4,node4_direction,icon_connect_type)
-
- for(var/D in directions)
- add_underlay(T,,D,icon_connect_type)
-
+ // Take advantage of the fact that our nodes are *always* in the same directions (see atmos_init())
+ add_underlay(T, node1, NORTH, icon_connect_type)
+ add_underlay(T, node2, SOUTH, icon_connect_type)
+ add_underlay(T, node3, EAST, icon_connect_type)
+ add_underlay(T, node4, WEST, icon_connect_type)
/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
..()
@@ -197,6 +173,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/manifold4w/visible/fuel
+ name="4-way fuel pipe manifold"
+ desc = "A manifold composed of fuel pipes"
+ icon_state = "map_4way-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/aux
+ name="4-way aux pipe manifold"
+ desc = "A manifold composed of aux pipes"
+ icon_state = "map_4way-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -243,6 +239,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/fuel
+ name="4-way fuel pipe manifold"
+ desc = "A manifold composed of fuel pipes"
+ icon_state = "map_4way-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/aux
+ name="4-way aux pipe manifold"
+ desc = "A manifold composed of aux pipes"
+ icon_state = "map_4way-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
color = PIPE_COLOR_YELLOW
diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm
index eb980c3b476..215f3498b78 100644
--- a/code/ATMOSPHERICS/pipes/simple.dm
+++ b/code/ATMOSPHERICS/pipes/simple.dm
@@ -203,6 +203,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/simple/visible/fuel
+ name = "Fuel pipe"
+ desc = "A one meter section of fuel pipe"
+ icon_state = "intact-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/visible/aux
+ name = "Aux pipe"
+ desc = "A one meter section of aux pipe"
+ icon_state = "intact-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/simple/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -249,6 +269,26 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
+/obj/machinery/atmospherics/pipe/simple/hidden/fuel
+ name = "Fuel pipe"
+ desc = "A one meter section of fuel pipe"
+ icon_state = "intact-fuel"
+ connect_types = CONNECT_TYPE_FUEL
+ piping_layer = PIPING_LAYER_FUEL
+ layer = PIPES_FUEL_LAYER
+ icon_connect_type = "-fuel"
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/hidden/aux
+ name = "Aux pipe"
+ desc = "A one meter section of aux pipe"
+ icon_state = "intact-aux"
+ connect_types = CONNECT_TYPE_AUX
+ piping_layer = PIPING_LAYER_AUX
+ layer = PIPES_AUX_LAYER
+ icon_connect_type = "-aux"
+ color = PIPE_COLOR_CYAN
+
/obj/machinery/atmospherics/pipe/simple/hidden/yellow
color = PIPE_COLOR_YELLOW
diff --git a/code/ATMOSPHERICS/pipes/tank.dm b/code/ATMOSPHERICS/pipes/tank.dm
index 751c9ed6076..8a68ba369c5 100644
--- a/code/ATMOSPHERICS/pipes/tank.dm
+++ b/code/ATMOSPHERICS/pipes/tank.dm
@@ -136,6 +136,7 @@
/obj/machinery/atmospherics/pipe/tank/phoron
name = "Pressure Tank (Phoron)"
icon_state = "phoron_map"
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_FUEL
/obj/machinery/atmospherics/pipe/tank/phoron/New()
air_temporary = new
diff --git a/code/ATMOSPHERICS/pipes/universal.dm b/code/ATMOSPHERICS/pipes/universal.dm
index 00d2746947a..a72ef219f78 100644
--- a/code/ATMOSPHERICS/pipes/universal.dm
+++ b/code/ATMOSPHERICS/pipes/universal.dm
@@ -4,7 +4,7 @@
/obj/machinery/atmospherics/pipe/simple/visible/universal
name="Universal pipe adapter"
desc = "An adapter for regular, supply and scrubbers pipes"
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER|CONNECT_TYPE_FUEL|CONNECT_TYPE_AUX
icon_state = "map_universal"
pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE
construction_type = /obj/item/pipe/binary
@@ -42,7 +42,7 @@
/obj/machinery/atmospherics/pipe/simple/hidden/universal
name="Universal pipe adapter"
desc = "An adapter for regular, supply and scrubbers pipes"
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER|CONNECT_TYPE_FUEL|CONNECT_TYPE_AUX
icon_state = "map_universal"
pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE
construction_type = /obj/item/pipe/binary
@@ -81,21 +81,42 @@
var/turf/T = loc
if(node)
var/node_dir = get_dir(src,node)
- if(node.icon_connect_type == "-supply")
- add_underlay_adapter(T, , node_dir, "")
- add_underlay_adapter(T, node, node_dir, "-supply")
- add_underlay_adapter(T, , node_dir, "-scrubbers")
- else if (node.icon_connect_type == "-scrubbers")
- add_underlay_adapter(T, , node_dir, "")
- add_underlay_adapter(T, , node_dir, "-supply")
- add_underlay_adapter(T, node, node_dir, "-scrubbers")
- else
- add_underlay_adapter(T, node, node_dir, "")
- add_underlay_adapter(T, , node_dir, "-supply")
- add_underlay_adapter(T, , node_dir, "-scrubbers")
+ switch(node.icon_connect_type)
+ if("-supply")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, node, node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ add_underlay_adapter(T, , node_dir, "-fuel")
+ add_underlay_adapter(T, , node_dir, "-aux")
+ if ("-scrubbers")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, node, node_dir, "-scrubbers")
+ add_underlay_adapter(T, , node_dir, "-fuel")
+ add_underlay_adapter(T, , node_dir, "-aux")
+ if ("-fuel")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ add_underlay_adapter(T, node, node_dir, "-fuel")
+ add_underlay_adapter(T, , node_dir, "-aux")
+ if ("-aux")
+ add_underlay_adapter(T, , node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ add_underlay_adapter(T, , node_dir, "-fuel")
+ add_underlay_adapter(T, node, node_dir, "-aux")
+ else
+ add_underlay_adapter(T, node, node_dir, "")
+ add_underlay_adapter(T, , node_dir, "-supply")
+ add_underlay_adapter(T, , node_dir, "-scrubbers")
+ add_underlay_adapter(T, , node_dir, "-fuel")
+ add_underlay_adapter(T, , node_dir, "-aux")
else
add_underlay_adapter(T, , direction, "-supply")
add_underlay_adapter(T, , direction, "-scrubbers")
+ add_underlay_adapter(T, , direction, "-fuel")
+ add_underlay_adapter(T, , direction, "-aux")
add_underlay_adapter(T, , direction, "")
/obj/machinery/atmospherics/proc/add_underlay_adapter(var/turf/T, var/obj/machinery/atmospherics/node, var/direction, var/icon_connect_type) //modified from add_underlay, does not make exposed underlays
diff --git a/code/ATMOSPHERICS/pipes/vent.dm b/code/ATMOSPHERICS/pipes/vent.dm
index 4a1dc5696dc..5090631a2be 100644
--- a/code/ATMOSPHERICS/pipes/vent.dm
+++ b/code/ATMOSPHERICS/pipes/vent.dm
@@ -16,7 +16,7 @@
initialize_directions = SOUTH
pipe_flags = PIPING_DEFAULT_LAYER_ONLY
construction_type = /obj/item/pipe/directional
- pipe_state = "passive vent"
+ pipe_state = "passive_vent"
var/build_killswitch = 1
diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm
index 6acc667f2d9..57161ffac8c 100644
--- a/code/__defines/MC.dm
+++ b/code/__defines/MC.dm
@@ -1,4 +1,5 @@
#define MC_TICK_CHECK ( ( TICK_USAGE > Master.current_ticklimit || src.state != SS_RUNNING ) ? pause() : 0 )
+#define CURRENT_RUNLEVEL (2 ** (Master.current_runlevel - 1))
#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = Master.current_ticklimit; var/split_tick_phases = ##phase_count
#define MC_SPLIT_TICK \
diff --git a/code/__defines/_tick.dm b/code/__defines/_tick.dm
index 1f112f711ba..54ac7d398d9 100644
--- a/code/__defines/_tick.dm
+++ b/code/__defines/_tick.dm
@@ -1,5 +1,5 @@
-#define TICK_LIMIT_RUNNING 85 //VOREStation Emergency Edit
+#define TICK_LIMIT_RUNNING 80
#define TICK_LIMIT_TO_RUN 70
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
diff --git a/code/__defines/construction.dm b/code/__defines/construction.dm
index f1488033225..5c0d6404477 100644
--- a/code/__defines/construction.dm
+++ b/code/__defines/construction.dm
@@ -34,19 +34,25 @@
#define PIPE_TRIN_T 7 //8 directions: N->S+E, S->N+E, N->S+W, S->N+W, E->W+S, W->E+S, E->W+N, W->E+N
// Pipe connectivity bit flags
-#define CONNECT_TYPE_REGULAR 1
-#define CONNECT_TYPE_SUPPLY 2
-#define CONNECT_TYPE_SCRUBBER 4
-#define CONNECT_TYPE_HE 8
-#define CONNECT_TYPE_FUEL 16 // TODO - Implement this! Its piping so better ask Leshana
+#define CONNECT_TYPE_REGULAR 1 //Center of tile, 'normal'
+#define CONNECT_TYPE_SUPPLY 2 //Atmos air supply pipes
+#define CONNECT_TYPE_SCRUBBER 4 //Atmos air scrubber pipes
+#define CONNECT_TYPE_HE 8 //Heat exchanger pipes
+#define CONNECT_TYPE_FUEL 16 //Fuel pipes for overmap ships
+#define CONNECT_TYPE_AUX 32 //Aux pipes for 'other' things (airlocks, etc)
// We are based on the three named layers of supply, regular, and scrubber.
#define PIPING_LAYER_SUPPLY 1
#define PIPING_LAYER_REGULAR 2
#define PIPING_LAYER_SCRUBBER 3
+#define PIPING_LAYER_FUEL 4
+#define PIPING_LAYER_AUX 5
#define PIPING_LAYER_DEFAULT PIPING_LAYER_REGULAR
// We offset the layer values of the different pipe types to ensure they look nice
+#define PIPES_SCRUBBER_LAYER (PIPES_LAYER - 0.05)
+#define PIPES_AUX_LAYER (PIPES_LAYER - 0.04)
+#define PIPES_FUEL_LAYER (PIPES_LAYER - 0.03)
#define PIPES_SCRUBBER_LAYER (PIPES_LAYER - 0.02)
#define PIPES_SUPPLY_LAYER (PIPES_LAYER - 0.01)
#define PIPES_HE_LAYER (PIPES_LAYER + 0.01)
diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm
index 59d2879ba54..02f1b11ee13 100644
--- a/code/__defines/gamemode.dm
+++ b/code/__defines/gamemode.dm
@@ -1,7 +1,16 @@
-#define GAME_STATE_PREGAME 1
-#define GAME_STATE_SETTING_UP 2
-#define GAME_STATE_PLAYING 3
-#define GAME_STATE_FINISHED 4
+// Ticker game states, turns out these are equivilent to runlevels1
+#define GAME_STATE_INIT 0 // RUNLEVEL_INIT
+#define GAME_STATE_PREGAME 1 // RUNLEVEL_LOBBY
+#define GAME_STATE_SETTING_UP 2 // RUNLEVEL_SETUP
+#define GAME_STATE_PLAYING 3 // RUNLEVEL_GAME
+#define GAME_STATE_FINISHED 4 // RUNLEVEL_POSTGAME
+
+//End game state, to manage round end.
+#define END_GAME_NOT_OVER 1 // Still playing normally
+#define END_GAME_MODE_FINISHED 2 // Mode has finished but game has not, wait for game to end too.
+#define END_GAME_READY_TO_END 3 // Game and Mode have finished, do rounded stuff.
+#define END_GAME_ENDING 4 // Just waiting for ending timer.
+#define END_GAME_DELAYED 5 // Admin has delayed the round.
// Security levels.
#define SEC_LEVEL_GREEN 0
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index 47226383ea8..e121f552168 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -52,3 +52,4 @@
//---------------
//#define isturf(D) istype(D, /turf) //Built in
#define isopenspace(A) istype(A, /turf/simulated/open)
+#define isspace(A) istype(A, /turf/space)
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index ed07f11c1e4..3c561cc291d 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -70,10 +70,27 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
#define NETWORK_ALARM_ATMOS "Atmosphere Alarms"
#define NETWORK_ALARM_POWER "Power Alarms"
#define NETWORK_ALARM_FIRE "Fire Alarms"
+#define NETWORK_TALON_HELMETS "TalonHelmets" //VOREStation Add
+#define NETWORK_TALON_SHIP "TalonShip" //VOREStation Add
// Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them.
var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret", NETWORK_COMMUNICATORS)
+#define TRANSMISSION_WIRE 0 //Is this ever used? I don't think it is.
+#define TRANSMISSION_RADIO 1 //Radio transmissions (like airlock controller to pump)
+#define TRANSMISSION_SUBSPACE 2 //Like headsets
+#define TRANSMISSION_BLUESPACE 3 //Point-to-point links
+
+#define SIGNAL_NORMAL 0 //Normal subspace signals
+#define SIGNAL_SIMPLE 1 //Normal inter-machinery(?) signals
+#define SIGNAL_FAKE 2 //Untrackable signals
+#define SIGNAL_TEST 4 //Unlogged signals
+
+#define DATA_NORMAL 0 //Normal data
+#define DATA_INTERCOM 1 //Intercoms only
+#define DATA_LOCAL 2 //Intercoms and SBRs
+#define DATA_ANTAG 3 //Antag interception
+#define DATA_FAKE 4 //Not from a real mob
//singularity defines
#define STAGE_ONE 1
diff --git a/code/__defines/misc_vr.dm b/code/__defines/misc_vr.dm
index e6a71a36144..bf6cb4d150a 100644
--- a/code/__defines/misc_vr.dm
+++ b/code/__defines/misc_vr.dm
@@ -55,4 +55,6 @@
#define PTO_SCIENCE "Science"
#define PTO_EXPLORATION "Exploration"
#define PTO_CARGO "Cargo"
-#define PTO_CIVILIAN "Civilian"
\ No newline at end of file
+#define PTO_CIVILIAN "Civilian"
+
+#define DEPARTMENT_TALON "ITV Talon"
diff --git a/code/__defines/preferences.dm b/code/__defines/preferences.dm
new file mode 100644
index 00000000000..0bb289d2e14
--- /dev/null
+++ b/code/__defines/preferences.dm
@@ -0,0 +1,6 @@
+#define EXAMINE_MODE_DEFAULT 0
+#define EXAMINE_MODE_INCLUDE_USAGE 1
+#define EXAMINE_MODE_SWITCH_TO_PANEL 2
+
+// Should be one higher than the above
+#define EXAMINE_MODE_MAX 3
\ No newline at end of file
diff --git a/code/__defines/shields.dm b/code/__defines/shields.dm
new file mode 100644
index 00000000000..be892a1d6eb
--- /dev/null
+++ b/code/__defines/shields.dm
@@ -0,0 +1,49 @@
+
+#define SHIELD_DAMTYPE_PHYSICAL 1 // Physical damage - bullets, meteors, various hand objects - aka. "brute" damtype.
+#define SHIELD_DAMTYPE_EM 2 // Electromagnetic damage - Ion weaponry, stun beams, ...
+#define SHIELD_DAMTYPE_HEAT 3 // Heat damage - Lasers, fire
+
+// TODO - Thats power not energy you silly goose! I think we mean 45 kilojoules
+#define ENERGY_PER_HP (45 KILOWATTS)// Base amount energy that will be deducted from the generator's internal reserve per 1 HP of damage taken
+#define ENERGY_UPKEEP_PER_TILE (4 KILOWATTS) // Base upkeep per tile protected. Multiplied by various enabled shield modes. Without them the field does literally nothing.
+#define ENERGY_UPKEEP_IDLE 45 // Base upkeep when idle; modified by other factors.
+
+// This shield model is slightly inspired by Sins of a Solar Empire series. In short, shields are designed to analyze what hits them, and adapt themselves against that type of damage.
+// This means shields will become increasingly effective against things like emitters - as they will adapt to heat damage, however they will be vulnerable to brute and EM damage.
+// In a theoretical assault scenario, it is best to combine all damage types, so mitigation can't build up. The value is capped to prevent full scale invulnerability.
+
+#define MAX_MITIGATION_BASE 40 // % Base maximal reachable mitigation.
+#define MAX_MITIGATION_RESEARCH 10 // % Added to MAX_MITIGATION_BASE when generator is built using more advanced components. This value is added for each "tier" of used component, ie. basic one has 1, the best one has 5. Actual maximum should be 90% in this case (with best components). Make sure you won't get above 100%!
+#define MITIGATION_HIT_GAIN 5 // Mitigation gain per hit of respective damage type.
+#define MITIGATION_HIT_LOSS 4 // Mitigation loss per hit. If we get hit once by EM damage type, EM mitigation will grow, while Physical and Heat mitigation values drop.
+#define MITIGATION_LOSS_PASSIVE 0.5 // Mitigation of all damage types will drop by this every tick, up to 0.
+
+// Shield modes allow you to calibrate the field to fit specific needs. It is, for example, possible to create a field that will block airflow, but let people pass.
+// Relevant mode bitflags (maximal of 16 flags due to current BYOND limitations)
+#define MODEFLAG_HYPERKINETIC 1
+#define MODEFLAG_PHOTONIC 2
+#define MODEFLAG_NONHUMANS 4
+#define MODEFLAG_HUMANOIDS 8
+#define MODEFLAG_ANORGANIC 16
+#define MODEFLAG_ATMOSPHERIC 32
+#define MODEFLAG_HULL 64
+#define MODEFLAG_BYPASS 128
+#define MODEFLAG_OVERCHARGE 256
+#define MODEFLAG_MODULATE 512
+#define MODEFLAG_MULTIZ 1024
+#define MODEFLAG_EM 2048
+
+// Return codes for shield hits.
+#define SHIELD_ABSORBED 1 // The shield has completely absorbed the hit
+#define SHIELD_BREACHED_MINOR 2 // The hit was absorbed, but a small gap will be created in the field (1-3 tiles)
+#define SHIELD_BREACHED_MAJOR 3 // Same as above, with 2-5 tile gap
+#define SHIELD_BREACHED_CRITICAL 4 // Same as above, with 4-8 tile gap
+#define SHIELD_BREACHED_FAILURE 5 // Same as above, with 8-16 tile gap. Occurs when the hit exhausts all remaining shield energy.
+
+#define SHIELD_OFF 0 // The shield is offline
+#define SHIELD_DISCHARGING 1 // The shield is shutting down and discharging.
+#define SHIELD_RUNNING 2 // The shield is running
+#define SHIELD_IDLE 3 // The shield is being kept at an idle state
+#define SHIELD_SPINNING_UP 4 // Going from idle to running
+
+#define SHIELD_SHUTDOWN_DISPERSION_RATE (10000 KILOWATTS) // The rate at which shield energy disperses when shutdown is initiated.
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index bacd4ebd370..656b0dff2ab 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -53,6 +53,7 @@
#define LANGUAGE_AKHANI "Akhani"
#define LANGUAGE_ALAI "Alai"
#define LANGUAGE_ZADDAT "Vedahq"
+#define LANGUAGE_BLOB "Blob"
#define LANGUAGE_GIBBERISH "Babel"
// Language flags.
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index 1790890dfbb..37f4bff5f9d 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -57,6 +57,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_SKYBOX 30
#define INIT_ORDER_MAPPING 25
#define INIT_ORDER_DECALS 20
+#define INIT_ORDER_JOB 17
#define INIT_ORDER_ATOMS 15
#define INIT_ORDER_MACHINES 10
#define INIT_ORDER_SHUTTLES 3
@@ -69,10 +70,12 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_HOLOMAPS -5
#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_ALARM -7
+#define INIT_ORDER_OPENSPACE -10
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
#define INIT_ORDER_AI -22
-#define INIT_ORDER_JOB -23
+#define INIT_ORDER_GAME_MASTER -24
+#define INIT_ORDER_TICKER -50
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
@@ -91,6 +94,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_OBJ 40
#define FIRE_PRIORITY_PROCESS 45
#define FIRE_PRIORITY_DEFAULT 50
+#define FIRE_PRIORITY_TICKER 60
#define FIRE_PRIORITY_PLANETS 75
#define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_PROJECTILES 150
diff --git a/code/__defines/typeids.dm b/code/__defines/typeids.dm
index 53028be2943..6ee99f62a05 100644
--- a/code/__defines/typeids.dm
+++ b/code/__defines/typeids.dm
@@ -2,5 +2,5 @@
#define TYPEID_NULL "0"
#define TYPEID_NORMAL_LIST "f"
//helper macros
-#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, length(ref)-6) ) )
+#define GET_TYPEID(ref) ( ( (length(ref) <= 10) ? "TYPEID_NULL" : copytext(ref, 4, -7) ) )
#define IS_NORMAL_LIST(L) (GET_TYPEID("\ref[L]") == TYPEID_NORMAL_LIST)
diff --git a/code/__defines/vv.dm b/code/__defines/vv.dm
index 97e3a02e0d8..e71d6e2f8f1 100644
--- a/code/__defines/vv.dm
+++ b/code/__defines/vv.dm
@@ -27,7 +27,7 @@
#define VV_NORMAL_LIST_NO_EXPAND_THRESHOLD 50
#define VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD 150
-#define IS_VALID_ASSOC_KEY(V) (istext(V) || isdatum(V) || islist(V))
+#define IS_VALID_ASSOC_KEY(V) (!isnum(V))
//Helpers for vv_get_dropdown()
#define VV_DROPDOWN_OPTION(href_key, name) . += ""
@@ -35,6 +35,16 @@
//Helpers for vv_do_topic(list/href_list)
#define IF_VV_OPTION(href_key) if(href_list[href_key])
+// vv_do_list() keys
+#define VV_HK_LIST_ADD "listadd"
+#define VV_HK_LIST_EDIT "listedit"
+#define VV_HK_LIST_CHANGE "listchange"
+#define VV_HK_LIST_REMOVE "listremove"
+#define VV_HK_LIST_ERASE_NULLS "listnulls"
+#define VV_HK_LIST_ERASE_DUPES "listdupes"
+#define VV_HK_LIST_SHUFFLE "listshuffle"
+#define VV_HK_LIST_SET_LENGTH "listlen"
+
// /datum
#define VV_HK_DELETE "delete"
#define VV_HK_EXPOSE "expose"
diff --git a/code/_helpers/events.dm b/code/_helpers/events.dm
index e31d24783e8..2d15bb3aa9d 100644
--- a/code/_helpers/events.dm
+++ b/code/_helpers/events.dm
@@ -24,4 +24,16 @@
if(A == myarea) //The loc of a turf is the area it is in.
return 1
return 0
-
\ No newline at end of file
+
+// Returns a list of area instances, or a subtypes of them, that are mapped in somewhere.
+// Avoid feeding it `/area`, as it will likely cause a lot of lag as it evaluates every single area coded in.
+/proc/get_all_existing_areas_of_types(list/area_types)
+ . = list()
+ for(var/area_type in area_types)
+ var/list/types = typesof(area_type)
+ for(var/T in types)
+ // Test for existance.
+ var/area/A = locate(T)
+ if(!istype(A) || !A.contents.len) // Empty contents list means it's not on the map.
+ continue
+ . += A
\ No newline at end of file
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 6b924ef082b..17a25448500 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -246,7 +246,7 @@
var/turf/speaker = get_turf(R)
if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker))
- speaker_coverage[T] = T
+ speaker_coverage[T] = R
// Try to find all the players who can hear the message
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index ae218f750ec..a0a38bf9d15 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -676,7 +676,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
//Returns: all the areas in the world
/proc/return_areas()
var/list/area/areas = list()
- for(var/area/A in all_areas)
+ for(var/area/A in world)
areas += A
return areas
@@ -694,7 +694,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
areatype = areatemp.type
var/list/areas = new/list()
- for(var/area/N in all_areas)
+ for(var/area/N in world)
if(istype(N, areatype)) areas += N
return areas
@@ -708,7 +708,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
areatype = areatemp.type
var/list/turfs = new/list()
- for(var/area/N in all_areas)
+ for(var/area/N in world)
if(istype(N, areatype))
for(var/turf/T in N) turfs += T
return turfs
@@ -723,7 +723,7 @@ proc/GaussRandRound(var/sigma,var/roundto)
areatype = areatemp.type
var/list/atoms = new/list()
- for(var/area/N in all_areas)
+ for(var/area/N in world)
if(istype(N, areatype))
for(var/atom/A in N)
atoms += A
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index b9ce4c7f5aa..ea40e3dc0e0 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -43,7 +43,7 @@
next_click = world.time + 1
- if(client.buildmode)
+ if(client && client.buildmode)
build_click(src, client.buildmode, params, A)
return
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index e31dd5e56ab..8a61b872515 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -358,11 +358,13 @@
mymob.radio_use_icon.color = ui_color
mymob.radio_use_icon.alpha = ui_alpha
- mymob.client.screen = list()
+ if(mymob.client)
+ mymob.client.screen = list()
+
+ mymob.client.screen += hud_elements
+ mymob.client.screen += src.adding + src.hotkeybuttons
+ mymob.client.screen += mymob.client.void
- mymob.client.screen += hud_elements
- mymob.client.screen += src.adding + src.hotkeybuttons
- mymob.client.screen += mymob.client.void
inventory_shown = 0
return
diff --git a/code/_onclick/hud/skybox.dm b/code/_onclick/hud/skybox.dm
index 492a11e5889..c6a3d5d2595 100644
--- a/code/_onclick/hud/skybox.dm
+++ b/code/_onclick/hud/skybox.dm
@@ -44,17 +44,10 @@
. = ..()
client.update_skybox(TRUE)
-/mob/Move()
- var/old_z = get_z(src)
- . = ..()
- if(. && client)
- client.update_skybox(old_z != get_z(src))
-
-/mob/forceMove()
- var/old_z = get_z(src)
- . = ..()
- if(. && client)
- client.update_skybox(old_z != get_z(src))
+/mob/onTransitZ(old_z, new_z)
+ ..()
+ if(old_z != new_z)
+ client?.update_skybox(TRUE)
/mob/set_viewsize()
. = ..()
diff --git a/code/controllers/Processes/emergencyShuttle.dm b/code/controllers/Processes/emergencyShuttle.dm
deleted file mode 100644
index e7289311b95..00000000000
--- a/code/controllers/Processes/emergencyShuttle.dm
+++ /dev/null
@@ -1,9 +0,0 @@
-/datum/controller/process/emergencyShuttle/setup()
- name = "emergency shuttle"
- schedule_interval = 20 // every 2 seconds
-
- if(!emergency_shuttle)
- emergency_shuttle = new
-
-/datum/controller/process/emergencyShuttle/doWork()
- emergency_shuttle.process()
diff --git a/code/controllers/Processes/game_master.dm b/code/controllers/Processes/game_master.dm
deleted file mode 100644
index 7f89f3ab135..00000000000
--- a/code/controllers/Processes/game_master.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/controller/process/game_master/setup()
- name = "\improper GM controller"
- schedule_interval = 600 // every 60 seconds
-
-/datum/controller/process/game_master/doWork()
- game_master.process()
\ No newline at end of file
diff --git a/code/controllers/Processes/ticker.dm b/code/controllers/Processes/ticker.dm
deleted file mode 100644
index a70bb74c5ff..00000000000
--- a/code/controllers/Processes/ticker.dm
+++ /dev/null
@@ -1,42 +0,0 @@
-var/global/datum/controller/process/ticker/tickerProcess
-
-/datum/controller/process/ticker
- var/lastTickerTimeDuration
- var/lastTickerTime
-
-/datum/controller/process/ticker/setup()
- name = "ticker"
- schedule_interval = 20 // every 2 seconds
-
- lastTickerTime = world.timeofday
-
- if(!ticker)
- ticker = new
-
- tickerProcess = src
-
- spawn(0)
- if(ticker)
- ticker.pregame()
-
-/datum/controller/process/ticker/doWork()
- var/currentTime = world.timeofday
-
- if(currentTime < lastTickerTime) // check for midnight rollover
- lastTickerTimeDuration = (currentTime - (lastTickerTime - TICKS_IN_DAY)) / TICKS_IN_SECOND
- else
- lastTickerTimeDuration = (currentTime - lastTickerTime) / TICKS_IN_SECOND
-
- lastTickerTime = currentTime
-
- ticker.process()
-
-/datum/controller/process/ticker/proc/getLastTickerTimeDuration()
- return lastTickerTimeDuration
-
-// Use these preferentially to directly examining ticker.current_state to help prepare for transition to ticker as subsystem!
-/datum/controller/process/ticker/proc/HasRoundStarted()
- return (ticker && ticker.current_state >= GAME_STATE_PLAYING)
-
-/datum/controller/process/ticker/proc/IsRoundInProgress()
- return (ticker && ticker.current_state == GAME_STATE_PLAYING)
diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm
index 0b53ed169d6..3b3512bbf92 100644
--- a/code/controllers/communications.dm
+++ b/code/controllers/communications.dm
@@ -125,6 +125,8 @@ var/const/EXP_FREQ = 1361
var/const/MED_I_FREQ = 1485
var/const/SEC_I_FREQ = 1475
+var/const/TALON_FREQ = 1481 //VOREStation Add
+
var/list/radiochannels = list(
"Common" = PUB_FREQ,
"Science" = SCI_FREQ,
@@ -142,7 +144,8 @@ var/list/radiochannels = list(
"AI Private" = AI_FREQ,
"Entertainment" = ENT_FREQ,
"Medical(I)" = MED_I_FREQ,
- "Security(I)" = SEC_I_FREQ
+ "Security(I)" = SEC_I_FREQ,
+ "Talon" = TALON_FREQ //VOREStation Add
)
// central command channels, i.e deathsquid & response teams
@@ -154,6 +157,8 @@ var/list/ANTAG_FREQS = list(SYND_FREQ, RAID_FREQ)
//Department channels, arranged lexically
var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
+var/list/OFFMAP_FREQS = list(TALON_FREQ) //VOREStation Add
+
#define TRANSMISSION_WIRE 0
#define TRANSMISSION_RADIO 1
@@ -189,7 +194,10 @@ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC
return "entradio"
if(frequency in DEPT_FREQS)
return "deptradio"
-
+ //VOREStation Add
+ if(frequency in OFFMAP_FREQS)
+ return "expradio"
+ //VOREStation Add End
return "radio"
/* filters */
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index b41bf83b45a..e1c50f90d19 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -264,10 +264,12 @@ var/list/gamemode_cache = list()
var/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
var/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
+ var/defib_timer = 10 // How long until someone can't be defibbed anymore, in minutes.
+ var/defib_braindamage_timer = 2 // How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get.
+
// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
var/disable_cid_warn_popup = FALSE
-
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -877,6 +879,12 @@ var/list/gamemode_cache = list()
if("sqlite_feedback_cooldown")
config.sqlite_feedback_cooldown = text2num(value)
+ if("defib_timer")
+ config.defib_timer = text2num(value)
+
+ if("defib_braindamage_timer")
+ config.defib_braindamage_timer = text2num(value)
+
if("disable_cid_warn_popup")
config.disable_cid_warn_popup = TRUE
diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm
index 54f97e20606..d6e272f9c95 100644
--- a/code/controllers/emergency_shuttle_controller.dm
+++ b/code/controllers/emergency_shuttle_controller.dm
@@ -2,7 +2,7 @@
// Controls the emergency shuttle
-var/global/datum/emergency_shuttle_controller/emergency_shuttle
+var/global/datum/emergency_shuttle_controller/emergency_shuttle = new
/datum/emergency_shuttle_controller
var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm TODO - is it really?
@@ -75,8 +75,10 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
/datum/emergency_shuttle_controller/proc/set_launch_countdown(var/seconds)
wait_for_launch = 1
launch_time = world.time + seconds*10
+ START_PROCESSING(SSprocessing, src)
/datum/emergency_shuttle_controller/proc/stop_launch_countdown()
+ STOP_PROCESSING(SSprocessing, src)
wait_for_launch = 0
//calls the shuttle for an emergency evacuation
@@ -94,7 +96,7 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
evac = 1
emergency_shuttle_called.Announce(replacetext(using_map.emergency_shuttle_called_message, "%ETA%", "[estimated_time] minute\s"))
- for(var/area/A in all_areas)
+ for(var/area/A in world)
if(istype(A, /area/hallway))
A.readyalert()
@@ -120,13 +122,13 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
/datum/emergency_shuttle_controller/proc/recall()
if (!can_recall()) return
- wait_for_launch = 0
+ stop_launch_countdown()
shuttle.cancel_launch(src)
if (evac)
emergency_shuttle_recalled.Announce(using_map.emergency_shuttle_recall_message)
- for(var/area/A in all_areas)
+ for(var/area/A in world)
if(istype(A, /area/hallway))
A.readyreset()
evac = 0
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index cc6b224b5bf..07cf0712461 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -50,8 +50,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/current_runlevel //for scheduling different subsystems for different stages of the round
- var/dbg_is_running_subsystem = FALSE // TEMPORARY DEBUGGING - true only while we are actually waiting on a subsystem
-
var/static/restart_clear = 0
var/static/restart_timeout = 0
var/static/restart_count = 0
@@ -476,11 +474,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
queue_node.state = SS_RUNNING
- dbg_is_running_subsystem = TRUE // TEMPORARY DEBUGGING
tick_usage = TICK_USAGE
var/state = queue_node.ignite(queue_node_paused)
tick_usage = TICK_USAGE - tick_usage
- dbg_is_running_subsystem = FALSE // TEMPORARY DEBUGGING
if (state == SS_RUNNING)
state = SS_IDLE
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 8c0b6fa5de9..7115c77a61b 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -168,11 +168,12 @@
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
-
- if(can_fire && !(SS_NO_FIRE & flags))
- msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
- else
+ if(SS_NO_FIRE & flags)
+ msg = "NO FIRE\t[msg]"
+ else if(can_fire <= 0)
msg = "OFFLINE\t[msg]"
+ else
+ msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
var/title = name
if (can_fire)
@@ -202,3 +203,15 @@
//usually called via datum/controller/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash)
//should attempt to salvage what it can from the old instance of subsystem
/datum/controller/subsystem/Recover()
+
+// Suspends this subsystem from being queued for running. If already in the queue, sleeps until idle. Returns FALSE if the subsystem was already suspended.
+/datum/controller/subsystem/proc/suspend()
+ . = (can_fire > 0) // Return true if we were previously runnable, false if previously suspended.
+ can_fire = FALSE
+ // Safely sleep in a loop until the subsystem is idle, (or its been un-suspended somehow)
+ while(can_fire <= 0 && state != SS_IDLE)
+ stoplag() // Safely sleep in a loop until
+
+// Wakes a suspended subsystem.
+/datum/controller/subsystem/proc/wake()
+ can_fire = TRUE
diff --git a/code/controllers/subsystems/events.dm b/code/controllers/subsystems/events.dm
index 6de40f464d5..226c09f4924 100644
--- a/code/controllers/subsystems/events.dm
+++ b/code/controllers/subsystems/events.dm
@@ -1,5 +1,5 @@
SUBSYSTEM_DEF(events)
- name = "Events"
+ name = "Events" // VOREStation Edit - This is still the main events subsystem for us.
wait = 2 SECONDS
var/tmp/list/currentrun = null
diff --git a/code/controllers/subsystems/events2.dm b/code/controllers/subsystems/events2.dm
new file mode 100644
index 00000000000..2a73498b1d6
--- /dev/null
+++ b/code/controllers/subsystems/events2.dm
@@ -0,0 +1,37 @@
+// This is a simple ticker for the new event system.
+// The logic that determines what events get chosen is held inside a seperate subsystem.
+
+SUBSYSTEM_DEF(event_ticker)
+ name = "Events (Ticker)"
+ wait = 2 SECONDS
+ runlevels = RUNLEVEL_GAME
+
+ // List of `/datum/event2/event`s that are currently active, and receiving process() ticks.
+ var/list/active_events = list()
+
+ // List of `/datum/event2/event`s that finished, and are here for showing at roundend, if that's desired.
+ var/list/finished_events = list()
+
+// Process active events.
+/datum/controller/subsystem/event_ticker/fire(resumed)
+ for(var/E in active_events)
+ var/datum/event2/event/event = E
+ event.process()
+ if(event.finished)
+ event_finished(event)
+
+// Starts an event, independent of the GM system.
+// This means it will always run, and won't affect the GM system in any way, e.g. not putting the event off limits after one use.
+/datum/controller/subsystem/event_ticker/proc/start_event(event_type)
+ var/datum/event2/event/E = new event_type()
+ E.execute()
+ event_started(E)
+
+/datum/controller/subsystem/event_ticker/proc/event_started(datum/event2/event/E)
+ log_debug("Event [E.type] is now being ran.")
+ active_events += E
+
+/datum/controller/subsystem/event_ticker/proc/event_finished(datum/event2/event/E)
+ log_debug("Event [E.type] has finished.")
+ active_events -= E
+ finished_events += E
\ No newline at end of file
diff --git a/code/controllers/subsystems/game_master.dm b/code/controllers/subsystems/game_master.dm
new file mode 100644
index 00000000000..d5326bfba61
--- /dev/null
+++ b/code/controllers/subsystems/game_master.dm
@@ -0,0 +1,369 @@
+// This is a sort of successor to the various event systems created over the years. It is designed to be just a tad smarter than the
+// previous ones, checking various things like player count, department size and composition, individual player activity,
+// individual player (IC) skill, and such, in order to try to choose the best events to take in order to add spice or variety to
+// the round.
+
+// This subsystem holds the logic that chooses events. Actual event processing is handled in a seperate subsystem.
+SUBSYSTEM_DEF(game_master)
+ name = "Events (Game Master)"
+ wait = 1 MINUTE
+ runlevels = RUNLEVEL_GAME
+
+ // The GM object is what actually chooses events.
+ // It's held in a seperate object for better encapsulation, and allows for different 'flavors' of GMs to be made, that choose events differently.
+ var/datum/game_master/GM = null
+ var/game_master_type = /datum/game_master/default
+
+ var/list/available_events = list() // A list of meta event objects.
+
+ var/danger = 0 // The GM's best guess at how chaotic the round is. High danger makes it hold back.
+ var/staleness = -20 // Determines liklihood of the GM doing something, increases over time.
+
+ var/next_event = 0 // Minimum amount of time of nothingness until the GM can pick something again.
+
+ var/debug_messages = FALSE // If true, debug information is written to `log_debug()`.
+
+/datum/controller/subsystem/game_master/Initialize()
+ var/list/subtypes = subtypesof(/datum/event2/meta)
+ for(var/T in subtypes)
+ var/datum/event2/meta/M = new T()
+ if(!M.name)
+ continue
+ available_events += M
+
+ GM = new game_master_type()
+
+ if(config && !config.enable_game_master)
+ can_fire = FALSE
+
+ return ..()
+
+/datum/controller/subsystem/game_master/fire(resumed)
+ adjust_staleness(1)
+ adjust_danger(-1)
+
+ var/global_afk = metric.assess_all_living_mobs()
+ global_afk = abs(global_afk - 100)
+ global_afk = round(global_afk / 100, 0.1)
+ adjust_staleness(global_afk) // Staleness increases faster if more people are less active.
+
+ if(GM.ignore_time_restrictions || next_event < world.time)
+ if(prob(staleness) && pre_event_checks())
+ do_event_decision()
+
+
+/datum/controller/subsystem/game_master/proc/do_event_decision()
+ log_game_master("Going to choose an event.")
+ var/datum/event2/meta/event_picked = GM.choose_event()
+ if(event_picked)
+ run_event(event_picked)
+ next_event = world.time + rand(GM.decision_cooldown_lower_bound, GM.decision_cooldown_upper_bound)
+
+/datum/controller/subsystem/game_master/proc/debug_gm()
+ can_fire = TRUE
+ staleness = 100
+ debug_messages = TRUE
+
+/datum/controller/subsystem/game_master/proc/run_event(datum/event2/meta/chosen_event)
+ var/datum/event2/event/E = chosen_event.make_event()
+
+ chosen_event.times_ran++
+
+ if(!chosen_event.reusable)
+ // Disable this event, so it only gets picked once.
+ chosen_event.enabled = FALSE
+ if(chosen_event.event_class)
+ // Disable similar events, too.
+ for(var/M in available_events)
+ var/datum/event2/meta/meta = M
+ if(meta.event_class == chosen_event.event_class)
+ meta.enabled = FALSE
+
+ SSevent_ticker.event_started(E)
+ adjust_danger(chosen_event.chaos)
+ adjust_staleness(-(10 + chosen_event.chaos)) // More chaotic events reduce staleness more, e.g. a 25 chaos event will reduce it by 35.
+
+
+// Tell the game master that something dangerous happened, e.g. someone dying, station explosions.
+/datum/controller/subsystem/game_master/proc/adjust_danger(amount)
+ amount *= GM.danger_modifier
+ danger = round(between(0, danger + amount, 1000), 0.1)
+
+// Tell the game master that things are getting boring if positive, or something interesting if negative..
+/datum/controller/subsystem/game_master/proc/adjust_staleness(amount)
+ amount *= GM.staleness_modifier
+ staleness = round( between(-20, staleness + amount, 100), 0.1)
+
+// These are ran before committing to an event.
+// Returns TRUE if the system is allowed to procede, otherwise returns FALSE.
+/datum/controller/subsystem/game_master/proc/pre_event_checks(quiet = FALSE)
+ if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
+ if(!quiet)
+ log_game_master("Unable to start event: Ticker is nonexistant, or the game is not ongoing.")
+ return FALSE
+ if(GM.ignore_time_restrictions)
+ return TRUE
+ if(next_event > world.time) // Sanity.
+ if(!quiet)
+ log_game_master("Unable to start event: Time until next event is approximately [round((next_event - world.time) / (1 MINUTE))] minute(s)")
+ return FALSE
+
+ // Last minute antagging is bad for humans to do, so the GM will respect the start and end of the round.
+ var/mills = round_duration_in_ticks
+ var/mins = round((mills % 36000) / 600)
+ var/hours = round(mills / 36000)
+
+// if(hours < 1 && mins <= 20) // Don't do anything for the first twenty minutes of the round.
+// if(!quiet)
+// log_debug("Game Master unable to start event: It is too early.")
+// return FALSE
+ if(hours >= 2 && mins >= 40) // Don't do anything in the last twenty minutes of the round, as well.
+ if(!quiet)
+ log_game_master("Unable to start event: It is too late.")
+ return FALSE
+ return TRUE
+
+/datum/controller/subsystem/game_master/proc/choose_game_master(mob/user)
+ var/list/subtypes = subtypesof(/datum/game_master)
+ var/new_gm_path = input(user, "What kind of Game Master do you want?", "New Game Master", /datum/game_master/default) as null|anything in subtypes
+ if(new_gm_path)
+ log_and_message_admins("has swapped the current GM ([GM.type]) for a new GM ([new_gm_path]).")
+ GM = new new_gm_path(src)
+
+/datum/controller/subsystem/game_master/proc/log_game_master(message)
+ if(debug_messages)
+ log_debug("GAME MASTER: [message]")
+
+
+// This object makes the actual decisions.
+/datum/game_master
+ // Multiplier for how much 'danger' is accumulated. Higer generally makes it possible for more dangerous events to be picked.
+ var/danger_modifier = 1.0
+
+ // Ditto. Higher numbers generally result in more events occuring in a round.
+ var/staleness_modifier = 1.0
+
+ var/decision_cooldown_lower_bound = 5 MINUTES // Lower bound for how long to wait until -the potential- for another event being decided.
+ var/decision_cooldown_upper_bound = 20 MINUTES // Same, but upper bound.
+
+ var/ignore_time_restrictions = FALSE // Useful for debugging without needing to wait 20 minutes each time.
+ var/ignore_round_chaos = FALSE // If true, the system will happily choose back to back intense events like meteors and blobs, Dwarf Fortress style.
+
+/client/proc/show_gm_status()
+ set category = "Debug"
+ set name = "Show GM Status"
+ set desc = "Shows you what the GM is thinking. If only that existed in real life..."
+
+ if(check_rights(R_ADMIN|R_EVENT|R_DEBUG))
+ SSgame_master.interact(usr)
+ else
+ to_chat(usr, span("warning", "You do not have sufficent rights to view the GM panel, sorry."))
+
+/datum/controller/subsystem/game_master/proc/interact(var/client/user)
+ if(!user)
+ return
+
+ // Using lists for string tree conservation.
+ var/list/dat = list("
Automated Game Master Event System")
+
+ // Makes the system turn on or off.
+ dat += href(src, list("toggle" = 1), "\[Toggle GM\]")
+ dat += " | "
+
+ // Makes the system not care about staleness or being near round-end.
+ dat += href(src, list("toggle_time_restrictions" = 1), "\[Toggle Time Restrictions\]")
+ dat += " | "
+
+ // Makes the system not care about how chaotic the round might be.
+ dat += href(src, list("toggle_chaos_throttle" = 1), "\[Toggle Chaos Throttling\]")
+ dat += " | "
+
+ // Makes the system immediately choose an event, while still bound to factors like danger, weights, and department staffing.
+ dat += href(src, list("force_choose_event" = 1), "\[Force Event Decision\]")
+ dat += " "
+
+ // Swaps out the current GM for a new one with different ideas on what a good event might be.
+ dat += href(src, list("change_gm" = 1), "\[Change GM\]")
+ dat += " "
+
+ dat += "Current GM Type: [GM.type] "
+ dat += "State: [can_fire ? "Active": "Inactive"] "
+ dat += "Status: [pre_event_checks(TRUE) ? "Ready" : "Suppressed"]
"
+
+ dat += "Staleness: [staleness] "
+ dat += href(src, list("set_staleness" = 1), "\[Set\]")
+ dat += " "
+ dat += "Staleness is an estimate of how boring the round might be, and if an event should be done. It is increased passively over time, \
+ and increases faster if people are AFK. It deceases when events and certain 'interesting' things happen in the round. "
+
+ dat += "Danger: [danger] "
+ dat += href(src, list("set_danger" = 1), "\[Set\]")
+ dat += " "
+ dat += "Danger is an estimate of how chaotic the round has been so far. It is decreased passively over time, and is increased by having \
+ certain chaotic events be selected, or chaotic things happen in the round. A sufficently high amount of danger will make the system \
+ avoid using destructive events, to avoid pushing the station over the edge. "
+
+ dat += "
Player Activity:
"
+
+ dat += "
"
+ dat += "
"
+ dat += "
Category
"
+ dat += "
Activity Percentage
"
+ dat += "
"
+
+ dat += "
"
+ dat += "
All Living Mobs
"
+ dat += "
[metric.assess_all_living_mobs()]%
"
+ dat += "
"
+
+ dat += "
"
+ dat += "
All Ghosts
"
+ dat += "
[metric.assess_all_dead_mobs()]%
"
+ dat += "
"
+
+ dat += "
"
+ dat += "
Departments"
+ dat += "
"
+
+ for(var/D in metric.departments)
+ dat += "
"
+ dat += "
[D]
"
+ dat += "
[metric.assess_department(D)]%
"
+ dat += "
"
+
+ dat += "
"
+ dat += "
Players"
+ dat += "
"
+
+ for(var/P in player_list)
+ var/mob/M = P
+ dat += "
"
+ dat += "
[M] ([M.ckey])
"
+ dat += "
[metric.assess_player_activity(M)]%
"
+ dat += "
"
+ dat += "
"
+
+ dat += "
Events available:
"
+
+ dat += "
"
+ dat += "
"
+ dat += "
Event Name
"
+ dat += "
Involved Departments
"
+ dat += "
Chaos
"
+ dat += "
Chaotic Threshold
"
+ dat += "
Weight
"
+ dat += "
Buttons
"
+ dat += "
"
+
+ for(var/E in available_events)
+ var/datum/event2/meta/event = E
+ dat += "