mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-22 11:38:12 +01:00
Merge remote-tracking branch 'upstream/master' into TFF-Mining_Ops_Move
This commit is contained in:
@@ -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("|")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -55,4 +55,6 @@
|
||||
#define PTO_SCIENCE "Science"
|
||||
#define PTO_EXPLORATION "Exploration"
|
||||
#define PTO_CARGO "Cargo"
|
||||
#define PTO_CIVILIAN "Civilian"
|
||||
#define PTO_CIVILIAN "Civilian"
|
||||
|
||||
#define DEPARTMENT_TALON "ITV Talon"
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+11
-1
@@ -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) . += "<option value='?_src_=vars;[href_key]=TRUE;target=\ref[src]'>[name]</option>"
|
||||
@@ -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"
|
||||
|
||||
+13
-1
@@ -24,4 +24,16 @@
|
||||
if(A == myarea) //The loc of a turf is the area it is in.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
// 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
next_click = world.time + 1
|
||||
|
||||
if(client.buildmode)
|
||||
if(client && client.buildmode)
|
||||
build_click(src, client.buildmode, params, A)
|
||||
return
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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("<html><head><title>Automated Game Master Event System</title></head><body>")
|
||||
|
||||
// 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 += "<br>"
|
||||
|
||||
// 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 += "<br>"
|
||||
|
||||
dat += "Current GM Type: [GM.type]<br>"
|
||||
dat += "State: [can_fire ? "Active": "Inactive"]<br>"
|
||||
dat += "Status: [pre_event_checks(TRUE) ? "Ready" : "Suppressed"]<br><br>"
|
||||
|
||||
dat += "Staleness: [staleness] "
|
||||
dat += href(src, list("set_staleness" = 1), "\[Set\]")
|
||||
dat += "<br>"
|
||||
dat += "<i>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.</i><br>"
|
||||
|
||||
dat += "Danger: [danger] "
|
||||
dat += href(src, list("set_danger" = 1), "\[Set\]")
|
||||
dat += "<br>"
|
||||
dat += "<i>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.</i><br>"
|
||||
|
||||
dat += "<h2>Player Activity:</h2>"
|
||||
|
||||
dat += "<table border='1' style='width:100%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th>Category</th>"
|
||||
dat += "<th>Activity Percentage</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
dat += "<td>All Living Mobs</td>"
|
||||
dat += "<td>[metric.assess_all_living_mobs()]%</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
dat += "<td>All Ghosts</td>"
|
||||
dat += "<td>[metric.assess_all_dead_mobs()]%</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
dat += "<th colspan='2'>Departments</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/D in metric.departments)
|
||||
dat += "<tr>"
|
||||
dat += "<td>[D]</td>"
|
||||
dat += "<td>[metric.assess_department(D)]%</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
dat += "<th colspan='2'>Players</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/P in player_list)
|
||||
var/mob/M = P
|
||||
dat += "<tr>"
|
||||
dat += "<td>[M] ([M.ckey])</td>"
|
||||
dat += "<td>[metric.assess_player_activity(M)]%</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
|
||||
dat += "<h2>Events available:</h2>"
|
||||
|
||||
dat += "<table border='1' style='width:100%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th>Event Name</th>"
|
||||
dat += "<th>Involved Departments</th>"
|
||||
dat += "<th>Chaos</th>"
|
||||
dat += "<th>Chaotic Threshold</th>"
|
||||
dat += "<th>Weight</th>"
|
||||
dat += "<th>Buttons</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/E in available_events)
|
||||
var/datum/event2/meta/event = E
|
||||
dat += "<tr>"
|
||||
if(!event.enabled)
|
||||
dat += "<td><strike>[event.name]</strike></td>"
|
||||
else
|
||||
dat += "<td>[event.name]</td>"
|
||||
dat += "<td>[english_list(event.departments)]</td>"
|
||||
dat += "<td>[event.chaos]</td>"
|
||||
dat += "<td>[event.chaotic_threshold]</td>"
|
||||
dat += "<td>[event.get_weight()]</td>"
|
||||
dat += "<td>[href(event, list("force" = 1), "\[Force\]")] [href(event, list("toggle" = 1), "\[Toggle\]")]</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
|
||||
dat += "<h2>Events active:</h2>"
|
||||
|
||||
dat += "Current time: [world.time]"
|
||||
dat += "<table border='1' style='width:100%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th>Event Type</th>"
|
||||
dat += "<th>Time Started</th>"
|
||||
dat += "<th>Time to Announce</th>"
|
||||
dat += "<th>Time to End</th>"
|
||||
dat += "<th>Announced</th>"
|
||||
dat += "<th>Started</th>"
|
||||
dat += "<th>Ended</th>"
|
||||
dat += "<th>Buttons</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/E in SSevent_ticker.active_events)
|
||||
var/datum/event2/event/event = E
|
||||
dat += "<tr>"
|
||||
dat += "<td>[event.type]</td>"
|
||||
dat += "<td>[event.time_started]</td>"
|
||||
dat += "<td>[event.time_to_announce ? event.time_to_announce : "NULL"]</td>"
|
||||
dat += "<td>[event.time_to_end ? event.time_to_end : "NULL"]</td>"
|
||||
dat += "<td>[event.announced ? "Yes" : "No"]</td>"
|
||||
dat += "<td>[event.started ? "Yes" : "No"]</td>"
|
||||
dat += "<td>[event.ended ? "Yes" : "No"]</td>"
|
||||
dat += "<td>[href(event, list("abort" = 1), "\[Abort\]")]</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "</body></html>"
|
||||
|
||||
dat += "<h2>Events completed:</h2>"
|
||||
|
||||
dat += "<table border='1' style='width:100%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th>Event Type</th>"
|
||||
dat += "<th>Start Time</th>"
|
||||
dat += "<th>Finish Time</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
for(var/E in SSevent_ticker.finished_events)
|
||||
var/datum/event2/event/event = E
|
||||
dat += "<tr>"
|
||||
dat += "<td>[event.type]</td>"
|
||||
dat += "<td>[event.time_started]</td>"
|
||||
dat += "<td>[event.time_finished]</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "</body></html>"
|
||||
|
||||
var/datum/browser/popup = new(user, "game_master_debug", "Automated Game Master Event System", 800, 500, src)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
|
||||
|
||||
/datum/controller/subsystem/game_master/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["close"]) // Needed or the window re-opens after closing, making it last forever.
|
||||
return
|
||||
|
||||
if(!check_rights(R_ADMIN|R_EVENT|R_DEBUG))
|
||||
message_admins("[usr] has attempted to modify the Game Master values without sufficent privilages.")
|
||||
return
|
||||
|
||||
if(href_list["toggle"])
|
||||
can_fire = !can_fire
|
||||
message_admins("GM was [!can_fire ? "dis" : "en"]abled by [usr.key].")
|
||||
|
||||
if(href_list["toggle_time_restrictions"])
|
||||
GM.ignore_time_restrictions = !GM.ignore_time_restrictions
|
||||
message_admins("GM event time restrictions was [GM.ignore_time_restrictions ? "dis" : "en"]abled by [usr.key].")
|
||||
|
||||
if(href_list["toggle_chaos_throttle"])
|
||||
GM.ignore_round_chaos = !GM.ignore_round_chaos
|
||||
message_admins("GM event chaos restrictions was [GM.ignore_round_chaos ? "dis" : "en"]abled by [usr.key].")
|
||||
|
||||
if(href_list["force_choose_event"])
|
||||
do_event_decision()
|
||||
message_admins("[usr.key] forced the Game Master to choose an event immediately.")
|
||||
|
||||
if(href_list["change_gm"])
|
||||
choose_game_master(usr)
|
||||
|
||||
if(href_list["set_staleness"])
|
||||
var/amount = input(usr, "How much staleness should there be?", "Game Master") as null|num
|
||||
if(!isnull(amount))
|
||||
staleness = amount
|
||||
message_admins("GM staleness was set to [amount] by [usr.key].")
|
||||
|
||||
if(href_list["set_danger"])
|
||||
var/amount = input(usr, "How much danger should there be?", "Game Master") as null|num
|
||||
if(!isnull(amount))
|
||||
danger = amount
|
||||
message_admins("GM danger was set to [amount] by [usr.key].")
|
||||
|
||||
interact(usr) // To refresh the UI.
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Controller handling icon updates of open space turfs
|
||||
//
|
||||
|
||||
GLOBAL_VAR_INIT(open_space_initialised, FALSE)
|
||||
|
||||
SUBSYSTEM_DEF(open_space)
|
||||
name = "Open Space"
|
||||
wait = 2 // 5 times per second.
|
||||
init_order = INIT_ORDER_OPENSPACE
|
||||
var/list/turfs_to_process = list() // List of turfs queued for update.
|
||||
var/list/turfs_to_process_old = null // List of turfs currently being updated.
|
||||
var/counter = 1 // Can't use .len because we need to iterate in order
|
||||
var/static/image/over_OS_darkness // Image overlayed over the bottom turf with stuff in it.
|
||||
|
||||
/datum/controller/subsystem/open_space/Initialize(timeofday)
|
||||
over_OS_darkness = image('icons/turf/open_space.dmi', "black_open")
|
||||
over_OS_darkness.plane = OVER_OPENSPACE_PLANE
|
||||
over_OS_darkness.layer = MOB_LAYER
|
||||
initialize_open_space()
|
||||
// Pre-process open space turfs once before the round starts.
|
||||
fire(FALSE, TRUE)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/open_space/Recover()
|
||||
flags |= SS_NO_INIT // Make extra sure we don't initialize twice.
|
||||
. = ..()
|
||||
|
||||
/datum/controller/subsystem/open_space/fire(resumed = 0, init_tick_checks = FALSE)
|
||||
// We use a different list so any additions to the update lists during a delay from MC_TICK_CHECK
|
||||
// don't cause things to be cut from the list without being updated.
|
||||
|
||||
//If we're not resuming, this must mean it's a new iteration so we have to grab the turfs
|
||||
if (!resumed)
|
||||
src.counter = 1
|
||||
src.turfs_to_process_old = turfs_to_process
|
||||
turfs_to_process = list()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/turfs_to_process_old = src.turfs_to_process_old
|
||||
var/counter = src.counter
|
||||
while(counter <= turfs_to_process_old.len)
|
||||
var/turf/T = turfs_to_process_old[counter]
|
||||
counter += 1
|
||||
if(!QDELETED(T))
|
||||
update_turf(T)
|
||||
if (init_tick_checks)
|
||||
CHECK_TICK // Used during initialization processing
|
||||
else if (MC_TICK_CHECK)
|
||||
src.counter = counter // Save for when we're resumed
|
||||
return // Used during normal MC processing.
|
||||
|
||||
/datum/controller/subsystem/open_space/proc/update_turf(var/turf/T)
|
||||
for(var/atom/movable/A in T)
|
||||
A.fall()
|
||||
T.update_icon()
|
||||
|
||||
/datum/controller/subsystem/open_space/proc/add_turf(var/turf/T, var/recursive = 0)
|
||||
ASSERT(isturf(T))
|
||||
// Check for multiple additions
|
||||
// Pointless to process the same turf twice. But we need to push it to the end of the list
|
||||
// because any turfs below it need to process first.
|
||||
turfs_to_process -= T
|
||||
turfs_to_process += T
|
||||
if(recursive > 0)
|
||||
var/turf/above = GetAbove(T)
|
||||
if(above && isopenspace(above))
|
||||
add_turf(above, recursive)
|
||||
|
||||
// Queue the initial updates of open space turfs when the game starts. This will lag!
|
||||
/datum/controller/subsystem/open_space/proc/initialize_open_space()
|
||||
// Do initial setup from bottom to top.
|
||||
for(var/zlevel = 1 to world.maxz)
|
||||
for(var/turf/simulated/open/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel)))
|
||||
add_turf(T)
|
||||
CHECK_TICK
|
||||
GLOB.open_space_initialised = TRUE
|
||||
|
||||
/datum/controller/subsystem/open_space/stat_entry(msg_prefix)
|
||||
return ..("T [turfs_to_process.len]")
|
||||
|
||||
/turf/Entered(atom/movable/AM)
|
||||
. = ..()
|
||||
if(GLOB.open_space_initialised && !AM.invisibility && isobj(AM))
|
||||
var/turf/T = GetAbove(src)
|
||||
if(isopenspace(T))
|
||||
// log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src].Entered([AM])")
|
||||
SSopen_space.add_turf(T, 1)
|
||||
|
||||
/turf/Exited(atom/movable/AM)
|
||||
. = ..()
|
||||
if(GLOB.open_space_initialised && !AM.invisibility && isobj(AM))
|
||||
var/turf/T = GetAbove(src)
|
||||
if(isopenspace(T))
|
||||
// log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src].Exited([AM])")
|
||||
SSopen_space.add_turf(T, 1)
|
||||
|
||||
/obj/update_icon()
|
||||
. = ..()
|
||||
if(GLOB.open_space_initialised && !invisibility && isturf(loc))
|
||||
var/turf/T = GetAbove(src)
|
||||
if(isopenspace(T))
|
||||
// log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src].update_icon()")
|
||||
SSopen_space.add_turf(T, 1)
|
||||
|
||||
// Ouch... this is painful. But is there any other way?
|
||||
/* - No for now
|
||||
/obj/New()
|
||||
. = ..()
|
||||
if(open_space_initialised && !invisibility)
|
||||
var/turf/T = GetAbove(src)
|
||||
if(isopenspace(T))
|
||||
// log_debug("[T] ([T.x],[T.y],[T.z]) queued for update for [src]New()")
|
||||
OS_controller.add_turf(T, 1)
|
||||
*/
|
||||
|
||||
// We probably should hook Destroy() If we can think of something more efficient, lets hear it.
|
||||
/obj/Destroy()
|
||||
if(GLOB.open_space_initialised && !invisibility && isturf(loc))
|
||||
var/turf/T = GetAbove(src)
|
||||
if(isopenspace(T))
|
||||
SSopen_space.add_turf(T, 1)
|
||||
. = ..() // Important that this be at the bottom, or we will have been moved to nullspace.
|
||||
@@ -84,6 +84,7 @@ SUBSYSTEM_DEF(shuttles)
|
||||
if(shuttle)
|
||||
shuttles_made += shuttle
|
||||
hook_up_motherships(shuttles_made)
|
||||
hook_up_shuttle_objects(shuttles_made)
|
||||
shuttles_to_initialize = null
|
||||
|
||||
/datum/controller/subsystem/shuttles/proc/initialize_sectors()
|
||||
@@ -103,7 +104,7 @@ SUBSYSTEM_DEF(shuttles)
|
||||
try_add_landmark_tag(shuttle_landmark_tag, O)
|
||||
landmarks_still_needed -= shuttle_landmark_tag
|
||||
else if(istype(shuttle_landmark, /obj/effect/shuttle_landmark/automatic)) //These find their sector automatically
|
||||
O = map_sectors["[shuttle_landmark.z]"]
|
||||
O = get_overmap_sector(get_z(shuttle_landmark))
|
||||
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)
|
||||
@@ -165,6 +166,11 @@ SUBSYSTEM_DEF(shuttles)
|
||||
else
|
||||
error("Shuttle [S] was unable to find mothership [mothership]!")
|
||||
|
||||
// Let shuttles scan their owned areas for objects they want to configure (Called after mothership hookup)
|
||||
/datum/controller/subsystem/shuttles/proc/hook_up_shuttle_objects(shuttles_list)
|
||||
for(var/datum/shuttle/S in shuttles_list)
|
||||
S.populate_shuttle_objects()
|
||||
|
||||
// Admin command to halt/resume overmap
|
||||
/datum/controller/subsystem/shuttles/proc/toggle_overmap(new_setting)
|
||||
if(overmap_halted == new_setting)
|
||||
|
||||
@@ -68,11 +68,6 @@ SUBSYSTEM_DEF(skybox)
|
||||
/datum/controller/subsystem/skybox/proc/get_skybox(z)
|
||||
if(!skybox_cache["[z]"])
|
||||
skybox_cache["[z]"] = generate_skybox(z)
|
||||
if(global.using_map.use_overmap)
|
||||
var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
|
||||
if(istype(O))
|
||||
for(var/zlevel in O.map_z)
|
||||
skybox_cache["[zlevel]"] = skybox_cache["[z]"]
|
||||
return skybox_cache["[z]"]
|
||||
|
||||
/datum/controller/subsystem/skybox/proc/generate_skybox(z)
|
||||
@@ -92,7 +87,7 @@ SUBSYSTEM_DEF(skybox)
|
||||
res.overlays += base
|
||||
|
||||
if(global.using_map.use_overmap && settings.use_overmap_details)
|
||||
var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
|
||||
var/obj/effect/overmap/visitable/O = get_overmap_sector(z)
|
||||
if(istype(O))
|
||||
var/image/overmap = image(settings.icon)
|
||||
overmap.overlays += O.generate_skybox()
|
||||
@@ -114,7 +109,11 @@ SUBSYSTEM_DEF(skybox)
|
||||
skybox_cache["[z]"] = generate_skybox(z)
|
||||
|
||||
for(var/client/C)
|
||||
C.update_skybox(1)
|
||||
var/their_z = get_z(C.mob)
|
||||
if(!their_z) //Nullspace
|
||||
continue
|
||||
if(their_z in zlevels)
|
||||
C.update_skybox(1)
|
||||
|
||||
// Settings datum that maps can override to play with their skyboxes
|
||||
/datum/skybox_settings
|
||||
|
||||
@@ -0,0 +1,560 @@
|
||||
//
|
||||
// Ticker controls the state of the game, being responsible for round start, game mode, and round end.
|
||||
//
|
||||
SUBSYSTEM_DEF(ticker)
|
||||
name = "Gameticker"
|
||||
wait = 2 SECONDS
|
||||
init_order = INIT_ORDER_TICKER
|
||||
priority = FIRE_PRIORITY_TICKER
|
||||
flags = SS_NO_TICK_CHECK | SS_KEEP_TIMING
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME // Every runlevel!
|
||||
|
||||
var/const/restart_timeout = 3 MINUTES // Default time to wait before rebooting in desiseconds.
|
||||
var/current_state = GAME_STATE_INIT // We aren't even at pregame yet // TODO replace with CURRENT_GAME_STATE
|
||||
|
||||
/* Relies upon the following globals (TODO move those in here) */
|
||||
// var/master_mode = "extended" //The underlying game mode (so "secret" or the voted mode).
|
||||
// Set by SSvote when VOTE_GAMEMODE finishes.
|
||||
// var/round_progressing = 1 //Whether the lobby clock is ticking down.
|
||||
|
||||
var/pregame_timeleft = 0 // Time remaining until game starts in seconds. Set by config
|
||||
var/start_immediately = FALSE // If true there is no lobby phase, the game starts immediately.
|
||||
|
||||
var/hide_mode = FALSE // If the true game mode should be hidden (because we chose "secret")
|
||||
var/datum/game_mode/mode = null // The actual gamemode, if selected.
|
||||
|
||||
var/end_game_state = END_GAME_NOT_OVER // Track where we are ending game/round
|
||||
var/restart_timeleft // Time remaining until restart in desiseconds
|
||||
var/last_restart_notify // world.time of last restart warning.
|
||||
var/delay_end = FALSE // If set, the round will not restart on its own.
|
||||
|
||||
// var/login_music // music played in pregame lobby // VOREStation Edit - We do music differently
|
||||
|
||||
var/list/datum/mind/minds = list() // The people in the game. Used for objective tracking.
|
||||
|
||||
// TODO - I am sure there is a better place these can go.
|
||||
var/Bible_icon_state // icon_state the chaplain has chosen for his bible
|
||||
var/Bible_item_state // item_state the chaplain has chosen for his bible
|
||||
var/Bible_name // name of the bible
|
||||
var/Bible_deity_name
|
||||
|
||||
var/random_players = FALSE // If set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
|
||||
|
||||
// TODO - Should this go here or in the job subsystem?
|
||||
var/triai = FALSE // Global flag for Triumvirate AI being enabled
|
||||
|
||||
//station_explosion used to be a variable for every mob's hud. Which was a waste!
|
||||
//Now we have a general cinematic centrally held within the gameticker....far more efficient!
|
||||
var/obj/screen/cinematic = null
|
||||
|
||||
// This global variable exists for legacy support so we don't have to rename every 'ticker' to 'SSticker' yet.
|
||||
var/global/datum/controller/subsystem/ticker/ticker
|
||||
/datum/controller/subsystem/ticker/PreInit()
|
||||
global.ticker = src // TODO - Remove this! Change everything to point at SSticker intead
|
||||
|
||||
/datum/controller/subsystem/ticker/Initialize()
|
||||
pregame_timeleft = config.pregame_time
|
||||
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/ticker/fire(resumed = FALSE)
|
||||
switch(current_state)
|
||||
if(GAME_STATE_INIT)
|
||||
pregame_welcome()
|
||||
current_state = GAME_STATE_PREGAME
|
||||
if(GAME_STATE_PREGAME)
|
||||
pregame_tick()
|
||||
if(GAME_STATE_SETTING_UP)
|
||||
setup_tick()
|
||||
if(GAME_STATE_PLAYING)
|
||||
playing_tick()
|
||||
if(GAME_STATE_FINISHED)
|
||||
post_game_tick()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/pregame_welcome()
|
||||
to_chat(world, "<B><FONT color='blue'>Welcome to the pregame lobby!</FONT></B>")
|
||||
to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
|
||||
|
||||
// Called during GAME_STATE_PREGAME (RUNLEVEL_LOBBY)
|
||||
/datum/controller/subsystem/ticker/proc/pregame_tick()
|
||||
if(round_progressing && last_fire)
|
||||
pregame_timeleft -= (world.time - last_fire) / (1 SECOND)
|
||||
|
||||
if(start_immediately)
|
||||
pregame_timeleft = 0
|
||||
else if(SSvote.time_remaining)
|
||||
return // vote still going, wait for it.
|
||||
|
||||
// Time to start the game!
|
||||
if(pregame_timeleft <= 0)
|
||||
current_state = GAME_STATE_SETTING_UP
|
||||
Master.SetRunLevel(RUNLEVEL_SETUP)
|
||||
if(start_immediately)
|
||||
fire() // Don't wait for next tick, do it now!
|
||||
return
|
||||
|
||||
if(pregame_timeleft <= config.vote_autogamemode_timeleft && !SSvote.gamemode_vote_called)
|
||||
SSvote.autogamemode() // Start the game mode vote (if we haven't had one already)
|
||||
|
||||
// Called during GAME_STATE_SETTING_UP (RUNLEVEL_SETUP)
|
||||
/datum/controller/subsystem/ticker/proc/setup_tick(resumed = FALSE)
|
||||
if(!setup_choose_gamemode())
|
||||
// It failed, go back to lobby state and re-send the welcome message
|
||||
pregame_timeleft = config.pregame_time
|
||||
SSvote.gamemode_vote_called = FALSE // Allow another autogamemode vote
|
||||
current_state = GAME_STATE_PREGAME
|
||||
Master.SetRunLevel(RUNLEVEL_LOBBY)
|
||||
pregame_welcome()
|
||||
return
|
||||
// If we got this far we succeeded in picking a game mode. Punch it!
|
||||
setup_startgame()
|
||||
return
|
||||
|
||||
// Formerly the first half of setup() - The part that chooses the game mode.
|
||||
// Returns 0 if failed to pick a mode, otherwise 1
|
||||
/datum/controller/subsystem/ticker/proc/setup_choose_gamemode()
|
||||
//Create and announce mode
|
||||
if(master_mode == "secret")
|
||||
src.hide_mode = TRUE
|
||||
|
||||
var/list/runnable_modes = config.get_runnable_modes()
|
||||
if((master_mode == "random") || (master_mode == "secret"))
|
||||
if(!runnable_modes.len)
|
||||
to_chat(world, "<B>Unable to choose playable game mode.</B> Reverting to pregame lobby.")
|
||||
return 0
|
||||
if(secret_force_mode != "secret")
|
||||
src.mode = config.pick_mode(secret_force_mode)
|
||||
if(!src.mode)
|
||||
var/list/weighted_modes = list()
|
||||
for(var/datum/game_mode/GM in runnable_modes)
|
||||
weighted_modes[GM.config_tag] = config.probabilities[GM.config_tag]
|
||||
src.mode = gamemode_cache[pickweight(weighted_modes)]
|
||||
else
|
||||
src.mode = config.pick_mode(master_mode)
|
||||
|
||||
if(!src.mode)
|
||||
to_chat(world, "<span class='danger'>Serious error in mode setup!</span> Reverting to pregame lobby.") //Uses setup instead of set up due to computational context.
|
||||
return 0
|
||||
|
||||
job_master.ResetOccupations()
|
||||
src.mode.create_antagonists()
|
||||
src.mode.pre_setup()
|
||||
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
|
||||
|
||||
if(!src.mode.can_start())
|
||||
to_world("<B>Unable to start [mode.name].</B> Not enough players readied, [config.player_requirements[mode.config_tag]] players needed. Reverting to pregame lobby.")
|
||||
mode.fail_setup()
|
||||
mode = null
|
||||
job_master.ResetOccupations()
|
||||
return 0
|
||||
|
||||
if(hide_mode)
|
||||
to_world("<B>The current game mode is - Secret!</B>")
|
||||
if(runnable_modes.len)
|
||||
var/list/tmpmodes = new
|
||||
for (var/datum/game_mode/M in runnable_modes)
|
||||
tmpmodes+=M.name
|
||||
tmpmodes = sortList(tmpmodes)
|
||||
if(tmpmodes.len)
|
||||
to_chat(world, "<B>Possibilities:</B> [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]")
|
||||
else
|
||||
src.mode.announce()
|
||||
return 1
|
||||
|
||||
// Formerly the second half of setup() - The part that actually initializes everything and starts the game.
|
||||
/datum/controller/subsystem/ticker/proc/setup_startgame()
|
||||
setup_economy()
|
||||
create_characters() //Create player characters and transfer them.
|
||||
collect_minds()
|
||||
equip_characters()
|
||||
//data_core.manifest() //VOREStation Removal
|
||||
|
||||
callHook("roundstart")
|
||||
|
||||
spawn(0)//Forking here so we dont have to wait for this to finish
|
||||
mode.post_setup()
|
||||
//Cleanup some stuff
|
||||
for(var/obj/effect/landmark/start/S in landmarks_list)
|
||||
//Deleting Startpoints but we need the ai point to AI-ize people later
|
||||
if (S.name != "AI")
|
||||
qdel(S)
|
||||
to_chat(world, "<FONT color='blue'><B>Enjoy the game!</B></FONT>")
|
||||
world << sound('sound/AI/welcome.ogg') // Skie
|
||||
//Holiday Round-start stuff ~Carn
|
||||
Holiday_Game_Start()
|
||||
|
||||
var/list/adm = get_admin_counts()
|
||||
if(adm["total"] == 0)
|
||||
send2adminirc("A round has started with no admins online.")
|
||||
|
||||
/* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler
|
||||
master_controller.process() //Start master_controller.process()
|
||||
lighting_controller.process() //Start processing DynamicAreaLighting updates
|
||||
*/
|
||||
|
||||
processScheduler.start()
|
||||
current_state = GAME_STATE_PLAYING
|
||||
Master.SetRunLevel(RUNLEVEL_GAME)
|
||||
|
||||
if(config.sql_enabled)
|
||||
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
// Called during GAME_STATE_PLAYING (RUNLEVEL_GAME)
|
||||
/datum/controller/subsystem/ticker/proc/playing_tick(resumed = FALSE)
|
||||
mode.process() // So THIS is where we run mode.process() huh? Okay
|
||||
|
||||
if(mode.explosion_in_progress)
|
||||
return // wait until explosion is done.
|
||||
|
||||
// Calculate if game and/or mode are finished (Complicated by the continuous_rounds config option)
|
||||
var/game_finished = FALSE
|
||||
var/mode_finished = FALSE
|
||||
if (config.continous_rounds) // Game keeps going after mode ends.
|
||||
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
|
||||
mode_finished = ((end_game_state >= END_GAME_MODE_FINISHED) || mode.check_finished()) // Short circuit if already finished.
|
||||
else // Game ends when mode does
|
||||
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended
|
||||
mode_finished = game_finished
|
||||
|
||||
if(game_finished && mode_finished)
|
||||
end_game_state = END_GAME_READY_TO_END
|
||||
current_state = GAME_STATE_FINISHED
|
||||
Master.SetRunLevel(RUNLEVEL_POSTGAME)
|
||||
INVOKE_ASYNC(src, .proc/declare_completion)
|
||||
else if (mode_finished && (end_game_state < END_GAME_MODE_FINISHED))
|
||||
end_game_state = END_GAME_MODE_FINISHED // Only do this cleanup once!
|
||||
mode.cleanup()
|
||||
//call a transfer shuttle vote
|
||||
to_chat(world, "<span class='danger'>The round has ended!</span>")
|
||||
SSvote.autotransfer()
|
||||
|
||||
// Called during GAME_STATE_FINISHED (RUNLEVEL_POSTGAME)
|
||||
/datum/controller/subsystem/ticker/proc/post_game_tick()
|
||||
switch(end_game_state)
|
||||
if(END_GAME_READY_TO_END)
|
||||
callHook("roundend")
|
||||
|
||||
if (mode.station_was_nuked)
|
||||
feedback_set_details("end_proper", "nuke")
|
||||
restart_timeleft = 1 MINUTE // No point waiting five minutes if everyone's dead.
|
||||
if(!delay_end)
|
||||
to_chat(world, "<span class='notice'><b>Rebooting due to destruction of [station_name()] in [round(restart_timeleft/600)] minute\s.</b></span>")
|
||||
last_restart_notify = world.time
|
||||
else
|
||||
feedback_set_details("end_proper", "proper completion")
|
||||
restart_timeleft = restart_timeout
|
||||
|
||||
if(blackbox)
|
||||
blackbox.save_all_data_to_sql() // TODO - Blackbox or statistics subsystem
|
||||
|
||||
end_game_state = END_GAME_ENDING
|
||||
return
|
||||
if(END_GAME_ENDING)
|
||||
restart_timeleft -= (world.time - last_fire)
|
||||
if(delay_end)
|
||||
to_chat(world, "<span class='notice'><b>An admin has delayed the round end.</b></span>")
|
||||
end_game_state = END_GAME_DELAYED
|
||||
else if(restart_timeleft <= 0)
|
||||
world.Reboot()
|
||||
else if (world.time - last_restart_notify >= 1 MINUTE)
|
||||
to_chat(world, "<span class='notice'><b>Restarting in [round(restart_timeleft/600, 1)] minute\s.</b></span>")
|
||||
last_restart_notify = world.time
|
||||
return
|
||||
if(END_GAME_DELAYED)
|
||||
restart_timeleft -= (world.time - last_fire)
|
||||
if(!delay_end)
|
||||
end_game_state = END_GAME_ENDING
|
||||
else
|
||||
log_error("Ticker arrived at round end in an unexpected endgame state '[end_game_state]'.")
|
||||
end_game_state = END_GAME_READY_TO_END
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// These two below are not used! But they could be
|
||||
|
||||
// Use these preferentially to directly examining ticker.current_state to help prepare for transition to ticker as subsystem!
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/PreRoundStart()
|
||||
return (current_state < GAME_STATE_PLAYING)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/IsSettingUp()
|
||||
return (current_state == GAME_STATE_SETTING_UP)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/IsRoundInProgress()
|
||||
return (current_state == GAME_STATE_PLAYING)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
|
||||
return (current_state >= GAME_STATE_PLAYING)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// HELPER PROCS!
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
//Plus it provides an easy way to make cinematics for other events. Just use this as a template :)
|
||||
/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(var/station_missed=0, var/override = null)
|
||||
if( cinematic ) return //already a cinematic in progress!
|
||||
|
||||
//initialise our cinematic screen object
|
||||
cinematic = new(src)
|
||||
cinematic.icon = 'icons/effects/station_explosion.dmi'
|
||||
cinematic.icon_state = "station_intact"
|
||||
cinematic.layer = 100
|
||||
cinematic.plane = PLANE_PLAYER_HUD
|
||||
cinematic.mouse_opacity = 0
|
||||
cinematic.screen_loc = "1,0"
|
||||
|
||||
var/obj/structure/bed/temp_buckle = new(src)
|
||||
//Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around
|
||||
if(station_missed)
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
M.buckled = temp_buckle //buckles the mob so it can't do anything
|
||||
if(M.client)
|
||||
M.client.screen += cinematic //show every client the cinematic
|
||||
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
M.buckled = temp_buckle
|
||||
if(M.client)
|
||||
M.client.screen += cinematic
|
||||
|
||||
switch(M.z)
|
||||
if(0) //inside a crate or something
|
||||
var/turf/T = get_turf(M)
|
||||
if(T && T.z in using_map.station_levels) //we don't use M.death(0) because it calls a for(/mob) loop and
|
||||
M.health = 0
|
||||
M.set_stat(DEAD)
|
||||
if(1) //on a z-level 1 turf.
|
||||
M.health = 0
|
||||
M.set_stat(DEAD)
|
||||
|
||||
//Now animate the cinematic
|
||||
switch(station_missed)
|
||||
if(1) //nuke was nearby but (mostly) missed
|
||||
if( mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("mercenary") //Nuke wasn't on station when it blew up
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
flick("station_intact_fade_red",cinematic)
|
||||
cinematic.icon_state = "summary_nukefail"
|
||||
else
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
//flick("end",cinematic)
|
||||
|
||||
|
||||
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
|
||||
sleep(50)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
|
||||
|
||||
else //station was destroyed
|
||||
if( mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("mercenary") //Nuke Ops successfully bombed the station
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_nukewin"
|
||||
if("AI malfunction") //Malf (screen,explosion,summary)
|
||||
flick("intro_malf",cinematic)
|
||||
sleep(76)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_malf"
|
||||
if("blob") //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
else //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red", cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
if(M.loc.z in using_map.station_levels)
|
||||
M.death()//No mercy
|
||||
//If its actually the end of the round, wait for it to end.
|
||||
//Otherwise if its a verb it will continue on afterwards.
|
||||
sleep(300)
|
||||
|
||||
if(cinematic) qdel(cinematic) //end the cinematic
|
||||
if(temp_buckle) qdel(temp_buckle) //release everybody
|
||||
return
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/create_characters()
|
||||
for(var/mob/new_player/player in player_list)
|
||||
if(player && player.ready && player.mind)
|
||||
if(player.mind.assigned_role=="AI")
|
||||
player.close_spawn_windows()
|
||||
player.AIize()
|
||||
else if(!player.mind.assigned_role)
|
||||
continue
|
||||
else
|
||||
//VOREStation Edit Start
|
||||
var/mob/living/carbon/human/new_char = player.create_character()
|
||||
if(new_char)
|
||||
qdel(player)
|
||||
if(istype(new_char) && !(new_char.mind.assigned_role=="Cyborg"))
|
||||
data_core.manifest_inject(new_char)
|
||||
//VOREStation Edit End
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/collect_minds()
|
||||
for(var/mob/living/player in player_list)
|
||||
if(player.mind)
|
||||
minds += player.mind
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/equip_characters()
|
||||
var/captainless=1
|
||||
for(var/mob/living/carbon/human/player in player_list)
|
||||
if(player && player.mind && player.mind.assigned_role)
|
||||
if(player.mind.assigned_role == "Colony Director")
|
||||
captainless=0
|
||||
if(!player_is_antag(player.mind, only_offstation_roles = 1))
|
||||
job_master.EquipRank(player, player.mind.assigned_role, 0)
|
||||
UpdateFactionList(player)
|
||||
//equip_custom_items(player) //VOREStation Removal
|
||||
//player.apply_traits() //VOREStation Removal
|
||||
if(captainless)
|
||||
for(var/mob/M in player_list)
|
||||
if(!istype(M,/mob/new_player))
|
||||
to_chat(M, "Colony Directorship not forced on anyone.")
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/declare_completion()
|
||||
to_world("<br><br><br><H1>A round of [mode.name] has ended!</H1>")
|
||||
for(var/mob/Player in player_list)
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(Player.stat != DEAD)
|
||||
var/turf/playerTurf = get_turf(Player)
|
||||
if(emergency_shuttle.departed && emergency_shuttle.evac)
|
||||
if(isNotAdminLevel(playerTurf.z))
|
||||
to_chat(Player, "<font color='blue'><b>You survived the round, but remained on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else if(isAdminLevel(playerTurf.z))
|
||||
to_chat(Player, "<font color='green'><b>You successfully underwent crew transfer after events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else if(issilicon(Player))
|
||||
to_chat(Player, "<font color='green'><b>You remain operational after the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='blue'><b>You missed the crew transfer after the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
if(istype(Player,/mob/observer/dead))
|
||||
var/mob/observer/dead/O = Player
|
||||
if(!O.started_as_observer)
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
|
||||
to_world("<br>")
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
|
||||
if (aiPlayer.stat != 2)
|
||||
to_world("<b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws at the end of the round were:</b>")
|
||||
else
|
||||
to_world("<b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws when it was deactivated were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/robolist = "<b>The AI's loyal minions were:</b> "
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]"
|
||||
to_world("[robolist]")
|
||||
|
||||
var/dronecount = 0
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in mob_list)
|
||||
|
||||
if(istype(robo,/mob/living/silicon/robot/drone) && !istype(robo,/mob/living/silicon/robot/drone/swarm))
|
||||
dronecount++
|
||||
continue
|
||||
|
||||
if (!robo.connected_ai)
|
||||
if (robo.stat != 2)
|
||||
to_world("<b>[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:</b>")
|
||||
else
|
||||
to_world("<b>[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:</b>")
|
||||
|
||||
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
|
||||
robo.laws.show_laws(world)
|
||||
|
||||
if(dronecount)
|
||||
to_world("<b>There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] at the end of this round.</b>")
|
||||
|
||||
mode.declare_completion()//To declare normal completion.
|
||||
|
||||
//Ask the event manager to print round end information
|
||||
SSevents.RoundEnd()
|
||||
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
//Look into all mobs in world, dead or alive
|
||||
for(var/datum/mind/Mind in minds)
|
||||
var/temprole = Mind.special_role
|
||||
if(temprole) //if they are an antagonist of some sort.
|
||||
if(temprole in total_antagonists) //If the role exists already, add the name to it
|
||||
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
|
||||
else
|
||||
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
|
||||
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
|
||||
|
||||
//Now print them all into the log!
|
||||
log_game("Antagonists at round end were...")
|
||||
for(var/i in total_antagonists)
|
||||
log_game("[i]s[total_antagonists[i]].")
|
||||
|
||||
return 1
|
||||
|
||||
/datum/controller/subsystem/ticker/stat_entry()
|
||||
switch(current_state)
|
||||
if(GAME_STATE_INIT)
|
||||
..()
|
||||
if(GAME_STATE_PREGAME) // RUNLEVEL_LOBBY
|
||||
..("START [round_progressing ? "[round(pregame_timeleft)]s" : "(PAUSED)"]")
|
||||
if(GAME_STATE_SETTING_UP) // RUNLEVEL_SETUP
|
||||
..("SETUP")
|
||||
if(GAME_STATE_PLAYING) // RUNLEVEL_GAME
|
||||
..("GAME")
|
||||
if(GAME_STATE_FINISHED) // RUNLEVEL_POSTGAME
|
||||
switch(end_game_state)
|
||||
if(END_GAME_MODE_FINISHED)
|
||||
..("MODE OVER, WAITING")
|
||||
if(END_GAME_READY_TO_END)
|
||||
..("ENDGAME PROCESSING")
|
||||
if(END_GAME_ENDING)
|
||||
..("END IN [round(restart_timeleft/10)]s")
|
||||
if(END_GAME_DELAYED)
|
||||
..("END PAUSED")
|
||||
else
|
||||
..("ENDGAME ERROR:[end_game_state]")
|
||||
|
||||
/datum/controller/subsystem/ticker/Recover()
|
||||
flags |= SS_NO_INIT // Don't initialize again
|
||||
|
||||
current_state = SSticker.current_state
|
||||
mode = SSticker.mode
|
||||
pregame_timeleft = SSticker.pregame_timeleft
|
||||
|
||||
end_game_state = SSticker.end_game_state
|
||||
delay_end = SSticker.delay_end
|
||||
restart_timeleft = SSticker.restart_timeleft
|
||||
|
||||
minds = SSticker.minds
|
||||
|
||||
Bible_icon_state = SSticker.Bible_icon_state
|
||||
Bible_item_state = SSticker.Bible_item_state
|
||||
Bible_name = SSticker.Bible_name
|
||||
Bible_deity_name = SSticker.Bible_deity_name
|
||||
random_players = SSticker.random_players
|
||||
@@ -13,6 +13,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/duration
|
||||
var/mode
|
||||
var/question
|
||||
var/gamemode_vote_called = FALSE // Have we had a gamemode vote this round? Only auto-call if we haven't
|
||||
var/list/choices = list()
|
||||
var/list/gamemode_names = list()
|
||||
var/list/voted = list()
|
||||
@@ -257,6 +258,7 @@ SUBSYSTEM_DEF(vote)
|
||||
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
|
||||
|
||||
if(mode == VOTE_GAMEMODE && round_progressing)
|
||||
gamemode_vote_called = TRUE
|
||||
round_progressing = 0
|
||||
to_world("<font color='red'><b>Round start has been delayed.</b></font>")
|
||||
|
||||
|
||||
@@ -99,6 +99,9 @@ SUBSYSTEM_DEF(xenoarch)
|
||||
if(isnull(M.artifact_find) && digsite != DIGSITE_GARDEN && digsite != DIGSITE_ANIMAL)
|
||||
artifact_spawning_turfs.Add(archeo_turf)
|
||||
|
||||
//Larger maps will convince byond this is an infinite loop, so let go for a second
|
||||
CHECK_TICK
|
||||
|
||||
//create artifact machinery
|
||||
var/num_artifacts_spawn = rand(ARTIFACTSPAWNNUM_LOWER, ARTIFACTSPAWNNUM_UPPER)
|
||||
while(artifact_spawning_turfs.len > num_artifacts_spawn)
|
||||
|
||||
@@ -89,8 +89,6 @@
|
||||
|
||||
//Goon PS stuff, and other yet-to-be-subsystem things.
|
||||
options["LEGACY: master_controller"] = master_controller
|
||||
options["LEGACY: ticker"] = ticker
|
||||
options["LEGACY: tickerProcess"] = tickerProcess
|
||||
options["LEGACY: air_master"] = air_master
|
||||
options["LEGACY: job_master"] = job_master
|
||||
options["LEGACY: radio_controller"] = radio_controller
|
||||
|
||||
+168
-14
@@ -5,11 +5,16 @@
|
||||
|
||||
/datum/datacore
|
||||
var/name = "datacore"
|
||||
var/medical[] = list()
|
||||
var/general[] = list()
|
||||
var/security[] = list()
|
||||
//For general station crew
|
||||
var/static/list/medical = list()
|
||||
var/static/list/general = list()
|
||||
var/static/list/security = list()
|
||||
//For offmap spawns so they can have records accessible by certain things
|
||||
var/static/list/hidden_medical = list()
|
||||
var/static/list/hidden_general = list()
|
||||
var/static/list/hidden_security = list()
|
||||
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/locked[] = list()
|
||||
var/static/list/locked = list()
|
||||
|
||||
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC)
|
||||
@@ -22,6 +27,7 @@
|
||||
var/list/pla = new() //VOREStation Edit
|
||||
var/list/civ = new()
|
||||
var/list/bot = new()
|
||||
var/list/off = new()
|
||||
var/list/misc = new()
|
||||
var/list/isactive = new()
|
||||
var/dat = {"
|
||||
@@ -46,7 +52,7 @@
|
||||
if(OOC)
|
||||
var/active = 0
|
||||
for(var/mob/M in player_list)
|
||||
if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
|
||||
if(M.real_name == name && M.client && M.client.inactivity <= 10 MINUTES)
|
||||
active = 1
|
||||
break
|
||||
isactive[name] = active ? "Active" : "Inactive"
|
||||
@@ -84,6 +90,24 @@
|
||||
if(!department && !(name in heads))
|
||||
misc[name] = rank
|
||||
|
||||
//For the offmap spawns
|
||||
if(OOC)
|
||||
for(var/datum/data/record/t in hidden_general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/real_rank = make_list_rank(t.fields["real_rank"])
|
||||
|
||||
var/active = 0
|
||||
for(var/mob/M in player_list)
|
||||
if(M.real_name == name && M.client && M.client.inactivity <= 10 MINUTES)
|
||||
active = 1
|
||||
break
|
||||
isactive[name] = active ? "Active" : "Inactive"
|
||||
|
||||
var/datum/job/J = SSjob.get_job(real_rank)
|
||||
if(J?.offmap_spawn)
|
||||
off[name] = rank
|
||||
|
||||
// Synthetics don't have actual records, so we will pull them from here.
|
||||
for(var/mob/living/silicon/ai/ai in mob_list)
|
||||
bot[ai.name] = "Artificial Intelligence"
|
||||
@@ -142,6 +166,12 @@
|
||||
for(name in bot)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
// offmap spawners
|
||||
if(off.len > 0)
|
||||
dat += "<tr><th colspan=3>Offmap Spawns</th></tr>"
|
||||
for(name in off)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[off[name]]</td><td>[isactive[name]]</td></tr>"
|
||||
even = !even
|
||||
// misc guys
|
||||
if(misc.len > 0)
|
||||
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
|
||||
@@ -154,6 +184,117 @@
|
||||
dat = replacetext(dat, "\t", "")
|
||||
return dat
|
||||
|
||||
/*
|
||||
We can't just insert in HTML into the nanoUI so we need the raw data to play with.
|
||||
Instead of creating this list over and over when someone leaves their PDA open to the page
|
||||
we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change
|
||||
using /datum/datacore/proc/manifest_inject( ), or manifest_insert( )
|
||||
*/
|
||||
|
||||
var/global/list/PDA_Manifest = list()
|
||||
|
||||
/datum/datacore/proc/get_manifest_list()
|
||||
if(PDA_Manifest.len)
|
||||
return
|
||||
var/list/heads = list()
|
||||
var/list/sec = list()
|
||||
var/list/eng = list()
|
||||
var/list/med = list()
|
||||
var/list/sci = list()
|
||||
var/list/car = list()
|
||||
var/list/pla = list() // Planetside crew: Explorers, Pilots, S&S
|
||||
var/list/civ = list()
|
||||
var/list/bot = list()
|
||||
var/list/misc = list()
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
var/name = sanitize(t.fields["name"])
|
||||
var/rank = sanitize(t.fields["rank"])
|
||||
var/real_rank = make_list_rank(t.fields["real_rank"])
|
||||
|
||||
var/isactive = t.fields["p_stat"]
|
||||
var/department = 0
|
||||
var/depthead = 0 // Department Heads will be placed at the top of their lists.
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_COMMAND))
|
||||
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
depthead = 1
|
||||
if(rank=="Colony Director" && heads.len != 1)
|
||||
heads.Swap(1,heads.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SECURITY))
|
||||
sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && sec.len != 1)
|
||||
sec.Swap(1,sec.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_ENGINEERING))
|
||||
eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && eng.len != 1)
|
||||
eng.Swap(1,eng.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_MEDICAL))
|
||||
med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && med.len != 1)
|
||||
med.Swap(1,med.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_RESEARCH))
|
||||
sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && sci.len != 1)
|
||||
sci.Swap(1,sci.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_PLANET))
|
||||
pla[++pla.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CARGO))
|
||||
car[++car.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && car.len != 1)
|
||||
car.Swap(1,car.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CIVILIAN))
|
||||
civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && civ.len != 1)
|
||||
civ.Swap(1,civ.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SYNTHETIC))
|
||||
bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
|
||||
if(!department && !(name in heads))
|
||||
misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
|
||||
// Synthetics don't have actual records, so we will pull them from here.
|
||||
// Synths don't have records, which is the means by which isactive is retrieved, so I'm hardcoding it to active, don't really have any better means
|
||||
for(var/mob/living/silicon/ai/ai in mob_list)
|
||||
bot[++bot.len] = list("name" = ai.real_name, "rank" = "Artificial Intelligence", "active" = "Active")
|
||||
|
||||
for(var/mob/living/silicon/robot/robot in mob_list)
|
||||
// No combat/syndicate cyborgs, no drones, and no AI shells.
|
||||
if(robot.scrambledcodes || robot.shell || (robot.module && robot.module.hide_on_manifest))
|
||||
continue
|
||||
|
||||
bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active")
|
||||
|
||||
|
||||
PDA_Manifest = list(
|
||||
list("cat" = "Command", "elems" = heads),
|
||||
list("cat" = "Security", "elems" = sec),
|
||||
list("cat" = "Engineering", "elems" = eng),
|
||||
list("cat" = "Medical", "elems" = med),
|
||||
list("cat" = "Science", "elems" = sci),
|
||||
list("cat" = "Cargo", "elems" = car),
|
||||
list("cat" = "Exploration", "elems" = pla), // VOREStation Edit
|
||||
list("cat" = "Civilian", "elems" = civ),
|
||||
list("cat" = "Silicon", "elems" = bot),
|
||||
list("cat" = "Miscellaneous", "elems" = misc)
|
||||
)
|
||||
return
|
||||
|
||||
/datum/datacore/proc/manifest()
|
||||
spawn()
|
||||
for(var/mob/living/carbon/human/H in player_list)
|
||||
@@ -187,10 +328,13 @@
|
||||
/datum/datacore/proc/manifest_inject(var/mob/living/carbon/human/H)
|
||||
if(H.mind && !player_is_antag(H.mind, only_offstation_roles = 1))
|
||||
var/assignment = GetAssignment(H)
|
||||
var/hidden
|
||||
var/datum/job/J = SSjob.get_job(assignment)
|
||||
hidden = J?.offmap_spawn
|
||||
|
||||
var/id = generate_record_id()
|
||||
//General Record
|
||||
var/datum/data/record/G = CreateGeneralRecord(H, id)
|
||||
var/datum/data/record/G = CreateGeneralRecord(H, id, hidden)
|
||||
G.fields["name"] = H.real_name
|
||||
G.fields["real_rank"] = H.mind.assigned_role
|
||||
G.fields["rank"] = assignment
|
||||
@@ -212,7 +356,7 @@
|
||||
G.fields["notes"] = H.gen_record
|
||||
|
||||
//Medical Record
|
||||
var/datum/data/record/M = CreateMedicalRecord(H.real_name, id)
|
||||
var/datum/data/record/M = CreateMedicalRecord(H.real_name, id, hidden)
|
||||
M.fields["b_type"] = H.b_type
|
||||
M.fields["b_dna"] = H.dna.unique_enzymes
|
||||
M.fields["id_gender"] = gender2text(H.identifying_gender)
|
||||
@@ -224,7 +368,7 @@
|
||||
M.fields["notes"] = H.med_record
|
||||
|
||||
//Security Record
|
||||
var/datum/data/record/S = CreateSecurityRecord(H.real_name, id)
|
||||
var/datum/data/record/S = CreateSecurityRecord(H.real_name, id, hidden)
|
||||
if(H.get_FBP_type())
|
||||
S.fields["brain_type"] = H.get_FBP_type()
|
||||
else
|
||||
@@ -257,6 +401,7 @@
|
||||
L.fields["image"] = icon(cached_character_icon(H), dir = SOUTH)
|
||||
L.fields["antagfac"] = H.antag_faction
|
||||
L.fields["antagvis"] = H.antag_vis
|
||||
L.fields["offmap"] = hidden
|
||||
if(H.exploit_record && !jobban_isbanned(H, "Records"))
|
||||
L.fields["exploit_record"] = H.exploit_record
|
||||
else
|
||||
@@ -267,7 +412,7 @@
|
||||
/proc/generate_record_id()
|
||||
return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex
|
||||
|
||||
/datum/datacore/proc/CreateGeneralRecord(var/mob/living/carbon/human/H, var/id)
|
||||
/datum/datacore/proc/CreateGeneralRecord(var/mob/living/carbon/human/H, var/id, var/hidden)
|
||||
ResetPDAManifest()
|
||||
var/icon/front
|
||||
var/icon/side
|
||||
@@ -301,11 +446,14 @@
|
||||
G.fields["photo_front"] = front
|
||||
G.fields["photo_side"] = side
|
||||
G.fields["notes"] = "No notes found."
|
||||
general += G
|
||||
if(hidden)
|
||||
hidden_general += G
|
||||
else
|
||||
general += G
|
||||
|
||||
return G
|
||||
|
||||
/datum/datacore/proc/CreateSecurityRecord(var/name, var/id)
|
||||
/datum/datacore/proc/CreateSecurityRecord(var/name, var/id, var/hidden)
|
||||
ResetPDAManifest()
|
||||
var/datum/data/record/R = new /datum/data/record()
|
||||
R.name = "Security Record #[id]"
|
||||
@@ -319,11 +467,14 @@
|
||||
R.fields["ma_crim_d"] = "No major crime convictions."
|
||||
R.fields["notes"] = "No notes."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.security += R
|
||||
if(hidden)
|
||||
hidden_security += R
|
||||
else
|
||||
security += R
|
||||
|
||||
return R
|
||||
|
||||
/datum/datacore/proc/CreateMedicalRecord(var/name, var/id)
|
||||
/datum/datacore/proc/CreateMedicalRecord(var/name, var/id, var/hidden)
|
||||
ResetPDAManifest()
|
||||
var/datum/data/record/M = new()
|
||||
M.name = "Medical Record #[id]"
|
||||
@@ -342,7 +493,10 @@
|
||||
M.fields["cdi"] = "None"
|
||||
M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
M.fields["notes"] = "No notes found."
|
||||
data_core.medical += M
|
||||
if(hidden)
|
||||
hidden_medical += M
|
||||
else
|
||||
medical += M
|
||||
|
||||
return M
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Push button, receive event.
|
||||
// Returns a selected event datum.
|
||||
/datum/game_master/proc/choose_event()
|
||||
|
||||
/datum/game_master/proc/log_game_master(message)
|
||||
// SSgame_master.log_game_master(message) // VOREStation Edit - We don't use SSgame_master yet.
|
||||
@@ -0,0 +1,89 @@
|
||||
// The default game master tries to choose events with these goals in mind.
|
||||
// * Don't choose an event if the crew can't take it. E.g. no meteors after half of the crew died.
|
||||
// * Try to involve lots of people, particuarly in active departments.
|
||||
// * Avoid giving events to the same department multiple times in a row.
|
||||
/datum/game_master/default
|
||||
// If an event was done for a specific department, it is written here, so it doesn't do it again.
|
||||
var/last_department_used = null
|
||||
|
||||
|
||||
/datum/game_master/default/choose_event()
|
||||
log_game_master("Now starting event decision.")
|
||||
|
||||
var/list/most_active_departments = metric.assess_all_departments(3, list(last_department_used))
|
||||
var/list/best_events = decide_best_events(most_active_departments)
|
||||
|
||||
if(LAZYLEN(best_events))
|
||||
log_game_master("Got [best_events.len] choice\s for the next event.")
|
||||
var/list/weighted_events = list()
|
||||
|
||||
for(var/E in best_events)
|
||||
var/datum/event2/meta/event = E
|
||||
var/weight = event.get_weight()
|
||||
if(weight <= 0)
|
||||
continue
|
||||
weighted_events[event] = weight
|
||||
log_game_master("Filtered down to [weighted_events.len] choice\s.")
|
||||
|
||||
var/datum/event2/meta/choice = pickweight(weighted_events)
|
||||
|
||||
if(choice)
|
||||
log_game_master("[choice.name] was chosen, and is now being ran.")
|
||||
last_department_used = LAZYACCESS(choice.departments, 1)
|
||||
return choice
|
||||
|
||||
/datum/game_master/default/proc/decide_best_events(list/most_active_departments)
|
||||
if(!LAZYLEN(most_active_departments)) // Server's empty?
|
||||
log_game_master("Game Master failed to find any active departments.")
|
||||
return list()
|
||||
|
||||
var/list/best_events = list()
|
||||
if(most_active_departments.len >= 2)
|
||||
var/list/top_two = list(most_active_departments[1], most_active_departments[2])
|
||||
best_events = filter_events_by_departments(top_two)
|
||||
|
||||
if(LAZYLEN(best_events)) // We found something for those two, let's do it.
|
||||
return best_events
|
||||
|
||||
// Otherwise we probably couldn't find something for the second highest group, so let's ignore them.
|
||||
best_events = filter_events_by_departments(most_active_departments[1])
|
||||
|
||||
if(LAZYLEN(best_events))
|
||||
return best_events
|
||||
|
||||
// At this point we should expand our horizons.
|
||||
best_events = filter_events_by_departments(list(DEPARTMENT_EVERYONE))
|
||||
|
||||
if(LAZYLEN(best_events))
|
||||
return best_events
|
||||
|
||||
// Just give a random event if for some reason it still can't make up its mind.
|
||||
best_events = filter_events_by_departments()
|
||||
|
||||
if(LAZYLEN(best_events))
|
||||
return best_events
|
||||
|
||||
log_game_master("Game Master failed to find a suitable event, something very wrong is going on.")
|
||||
return list()
|
||||
|
||||
// Filters the available events down to events for specific departments.
|
||||
// Pass DEPARTMENT_EVERYONE if you want events that target the general population, like gravity failure.
|
||||
// If no list is passed, all the events will be returned.
|
||||
/datum/game_master/default/proc/filter_events_by_departments(list/departments)
|
||||
. = list()
|
||||
for(var/E in SSgame_master.available_events)
|
||||
var/datum/event2/meta/event = E
|
||||
if(!event.enabled)
|
||||
continue
|
||||
if(event.chaotic_threshold && !ignore_round_chaos)
|
||||
if(SSgame_master.danger > event.chaotic_threshold)
|
||||
continue
|
||||
// An event has to involve all of these departments to pass.
|
||||
var/viable = TRUE
|
||||
if(LAZYLEN(departments))
|
||||
for(var/department in departments)
|
||||
if(!LAZYFIND(departments, department))
|
||||
viable = FALSE
|
||||
break
|
||||
if(viable)
|
||||
. += event
|
||||
@@ -0,0 +1,44 @@
|
||||
// The `classic` game master tries to act like the old system, choosing events without any specific goals.
|
||||
// * Has no goals, and instead operates purely off of the weights of the events it has.
|
||||
// * Does not react to danger at all.
|
||||
/datum/game_master/classic/choose_event()
|
||||
var/list/weighted_events = list()
|
||||
for(var/E in SSgame_master.available_events)
|
||||
var/datum/event2/meta/event = E
|
||||
if(!event.enabled)
|
||||
continue
|
||||
weighted_events[event] = event.get_weight()
|
||||
|
||||
var/datum/event2/meta/choice = pickweight(weighted_events)
|
||||
|
||||
if(choice)
|
||||
log_game_master("[choice.name] was chosen, and is now being ran.")
|
||||
return choice
|
||||
|
||||
|
||||
// The `super_random` game master chooses events purely at random, ignoring weights entirely.
|
||||
// * Has no goals, and instead chooses randomly, ignoring weights.
|
||||
// * Does not react to danger at all.
|
||||
/datum/game_master/super_random/choose_event()
|
||||
return pick(SSgame_master.available_events)
|
||||
|
||||
|
||||
// The `brutal` game master tries to run dangerous events frequently.
|
||||
// * Chaotic events have their weights artifically boosted.
|
||||
// * Ignores accumulated danger.
|
||||
/datum/game_master/brutal
|
||||
ignore_round_chaos = TRUE
|
||||
|
||||
/datum/game_master/brutal/choose_event()
|
||||
var/list/weighted_events = list()
|
||||
for(var/E in SSgame_master.available_events)
|
||||
var/datum/event2/meta/event = E
|
||||
if(!event.enabled)
|
||||
continue
|
||||
weighted_events[event] = event.get_weight() + (event.chaos * 2)
|
||||
|
||||
var/datum/event2/meta/choice = pickweight(weighted_events)
|
||||
|
||||
if(choice)
|
||||
log_game_master("[choice.name] was chosen, and is now being ran.")
|
||||
return choice
|
||||
@@ -14,10 +14,25 @@ var/global/datum/repository/cameras/camera_repository = new()
|
||||
networks = list()
|
||||
..()
|
||||
|
||||
/datum/repository/cameras/proc/cameras_in_network(var/network)
|
||||
/datum/repository/cameras/proc/cameras_in_network(var/network, var/list/zlevels)
|
||||
setup_cache()
|
||||
var/list/network_list = networks[network]
|
||||
return network_list
|
||||
if(LAZYLEN(zlevels))
|
||||
var/list/filtered_cameras = list()
|
||||
for(var/list/C in network_list)
|
||||
//Camera is marked as always-visible
|
||||
if(C["omni"])
|
||||
filtered_cameras[++filtered_cameras.len] = C
|
||||
continue
|
||||
//Camera might be in an adjacent zlevel
|
||||
var/camz = C["z"]
|
||||
if(!camz) //It's inside something (helmet, communicator, etc) or nullspace or who knows
|
||||
camz = get_z(locate(C["camera"]) in cameranet.cameras)
|
||||
if(camz in zlevels)
|
||||
filtered_cameras[++filtered_cameras.len] = C //Can't add lists to lists with +=
|
||||
return filtered_cameras
|
||||
else
|
||||
return network_list
|
||||
|
||||
/datum/repository/cameras/proc/setup_cache()
|
||||
if(!invalidated)
|
||||
|
||||
@@ -35,48 +35,6 @@
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "Superconducting Transmission Coil crate"
|
||||
|
||||
/datum/supply_pack/eng/shield_capacitor
|
||||
name = "Shield Capacitor"
|
||||
contains = list(/obj/machinery/shield_capacitor)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "shield capacitor crate"
|
||||
|
||||
/datum/supply_pack/eng/shield_capacitor/advanced
|
||||
name = "Advanced Shield Capacitor"
|
||||
contains = list(/obj/machinery/shield_capacitor/advanced)
|
||||
cost = 30
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "advanced shield capacitor crate"
|
||||
|
||||
/datum/supply_pack/eng/bubble_shield
|
||||
name = "Bubble Shield Generator"
|
||||
contains = list(/obj/machinery/shield_gen)
|
||||
cost = 40
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "shield bubble generator crate"
|
||||
|
||||
/datum/supply_pack/eng/bubble_shield/advanced
|
||||
name = "Advanced Bubble Shield Generator"
|
||||
contains = list(/obj/machinery/shield_gen/advanced)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "advanced bubble shield generator crate"
|
||||
|
||||
/datum/supply_pack/eng/hull_shield
|
||||
name = "Hull Shield Generator"
|
||||
contains = list(/obj/machinery/shield_gen/external)
|
||||
cost = 80
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "shield hull generator crate"
|
||||
|
||||
/datum/supply_pack/eng/hull_shield/advanced
|
||||
name = "Advanced Hull Shield Generator"
|
||||
contains = list(/obj/machinery/shield_gen/external/advanced)
|
||||
cost = 120
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "advanced hull shield generator crate"
|
||||
|
||||
/datum/supply_pack/eng/electrical
|
||||
name = "Electrical maintenance crate"
|
||||
contains = list(
|
||||
@@ -173,29 +131,19 @@
|
||||
containername = "Particle Accelerator crate"
|
||||
access = access_ce
|
||||
|
||||
/datum/supply_pack/eng/shield_gen
|
||||
contains = list(/obj/item/weapon/circuitboard/shield_gen)
|
||||
name = "Bubble shield generator circuitry"
|
||||
cost = 30
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
containername = "bubble shield generator circuitry crate"
|
||||
access = access_ce
|
||||
|
||||
/datum/supply_pack/eng/shield_gen_ex
|
||||
contains = list(/obj/item/weapon/circuitboard/shield_gen_ex)
|
||||
name = "Hull shield generator circuitry"
|
||||
cost = 30
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
containername = "hull shield generator circuitry crate"
|
||||
access = access_ce
|
||||
|
||||
/datum/supply_pack/eng/shield_cap
|
||||
contains = list(/obj/item/weapon/circuitboard/shield_cap)
|
||||
name = "Bubble shield capacitor circuitry"
|
||||
cost = 30
|
||||
containertype = /obj/structure/closet/crate/secure/engineering
|
||||
containername = "shield capacitor circuitry crate"
|
||||
access = access_ce
|
||||
/datum/supply_pack/eng/shield_generator
|
||||
name = "Shield Generator Construction Kit"
|
||||
contains = list(
|
||||
/obj/item/weapon/circuitboard/shield_generator,
|
||||
/obj/item/weapon/stock_parts/capacitor,
|
||||
/obj/item/weapon/stock_parts/micro_laser,
|
||||
/obj/item/weapon/smes_coil,
|
||||
/obj/item/weapon/stock_parts/console_screen,
|
||||
/obj/item/weapon/stock_parts/subspace/amplifier
|
||||
)
|
||||
cost = 80
|
||||
containertype = /obj/structure/closet/crate/engineering
|
||||
containername = "shield generator construction kit crate"
|
||||
|
||||
/datum/supply_pack/eng/smbig
|
||||
name = "Supermatter Core"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/datum/supply_pack/munitions/expeditionguns
|
||||
name = "Frontier phaser (station-locked) crate"
|
||||
contains = list(
|
||||
/obj/item/weapon/gun/energy/frontier/locked = 2,
|
||||
/obj/item/weapon/gun/energy/frontier/locked/holdout = 1,
|
||||
/obj/item/weapon/gun/energy/locked/frontier = 2,
|
||||
/obj/item/weapon/gun/energy/locked/frontier/holdout = 1,
|
||||
)
|
||||
cost = 35
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
|
||||
@@ -53,6 +53,12 @@
|
||||
name = "Black Ammunition Duffle Bag"
|
||||
path = /obj/item/weapon/storage/backpack/dufflebag/syndie/ammo
|
||||
|
||||
/datum/uplink_item/item/tools/shield_diffuser
|
||||
name = "Handheld Shield Diffuser"
|
||||
desc = "A small device used to disrupt energy barriers, and allow passage through them."
|
||||
item_cost = 16
|
||||
path = /obj/item/weapon/shield_diffuser
|
||||
|
||||
/datum/uplink_item/item/tools/space_suit
|
||||
name = "Space Suit"
|
||||
item_cost = 15
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/datum/wires/shield_generator
|
||||
holder_type = /obj/machinery/power/shield_generator
|
||||
wire_count = 5
|
||||
|
||||
var/const/SHIELDGEN_WIRE_POWER = 1 // Cut to disable power input into the generator. Pulse does nothing. Mend to restore.
|
||||
var/const/SHIELDGEN_WIRE_HACK = 2 // Pulse to hack the generator, enabling hacked modes. Cut to unhack. Mend does nothing.
|
||||
var/const/SHIELDGEN_WIRE_CONTROL = 4 // Cut to lock most shield controls. Mend to unlock them. Pulse does nothing.
|
||||
var/const/SHIELDGEN_WIRE_AICONTROL = 8 // Cut to disable AI control. Mend to restore.
|
||||
var/const/SHIELDGEN_WIRE_NOTHING = 16 // A blank wire that doesn't have any specific function
|
||||
|
||||
/datum/wires/shield_generator/CanUse(var/mob/living/L)
|
||||
var/obj/machinery/power/shield_generator/S = holder
|
||||
if(S.panel_open)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/wires/shield_generator/GetInteractWindow()
|
||||
var/obj/machinery/power/shield_generator/S = holder
|
||||
. += ..()
|
||||
. += show_hint(0x1, S.mode_changes_locked, "The orange light is on.", "The orange light is off.")
|
||||
. += show_hint(0x2, S.ai_control_disabled, "The blue light is off.", "The blue light is blinking.")
|
||||
. += show_hint(0x4, S.hacked, "The violet light is pulsing.", "The violet light is steady.")
|
||||
. += show_hint(0x8, S.input_cut, "The red light is off.", "The red light is on.")
|
||||
|
||||
/datum/wires/shield_generator/UpdateCut(index, mended)
|
||||
var/obj/machinery/power/shield_generator/S = holder
|
||||
switch(index)
|
||||
if(SHIELDGEN_WIRE_POWER)
|
||||
S.input_cut = !mended
|
||||
if(SHIELDGEN_WIRE_HACK)
|
||||
if(!mended)
|
||||
S.hacked = 0
|
||||
if(S.check_flag(MODEFLAG_BYPASS))
|
||||
S.toggle_flag(MODEFLAG_BYPASS)
|
||||
if(S.check_flag(MODEFLAG_OVERCHARGE))
|
||||
S.toggle_flag(MODEFLAG_OVERCHARGE)
|
||||
if(SHIELDGEN_WIRE_CONTROL)
|
||||
S.mode_changes_locked = !mended
|
||||
if(SHIELDGEN_WIRE_AICONTROL)
|
||||
S.ai_control_disabled = !mended
|
||||
|
||||
/datum/wires/shield_generator/UpdatePulsed(var/index)
|
||||
var/obj/machinery/power/shield_generator/S = holder
|
||||
switch(index)
|
||||
if(SHIELDGEN_WIRE_HACK)
|
||||
S.hacked = 1
|
||||
@@ -52,120 +52,6 @@
|
||||
return copytext(rank, 2+length(prefix))
|
||||
return rank
|
||||
|
||||
|
||||
/*
|
||||
We can't just insert in HTML into the nanoUI so we need the raw data to play with.
|
||||
Instead of creating this list over and over when someone leaves their PDA open to the page
|
||||
we'll only update it when it changes. The PDA_Manifest global list is zeroed out upon any change
|
||||
using /datum/datacore/proc/manifest_inject( ), or manifest_insert( )
|
||||
*/
|
||||
|
||||
var/global/list/PDA_Manifest = list()
|
||||
|
||||
/datum/datacore/proc/get_manifest_list()
|
||||
if(PDA_Manifest.len)
|
||||
return
|
||||
var/list/heads = list()
|
||||
var/list/sec = list()
|
||||
var/list/eng = list()
|
||||
var/list/med = list()
|
||||
var/list/sci = list()
|
||||
var/list/car = list()
|
||||
var/list/pla = list() // Planetside crew: Explorers, Pilots, S&S
|
||||
var/list/civ = list()
|
||||
var/list/bot = list()
|
||||
var/list/misc = list()
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
var/name = sanitize(t.fields["name"])
|
||||
var/rank = sanitize(t.fields["rank"])
|
||||
var/real_rank = make_list_rank(t.fields["real_rank"])
|
||||
|
||||
var/isactive = t.fields["p_stat"]
|
||||
var/department = 0
|
||||
var/depthead = 0 // Department Heads will be placed at the top of their lists.
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_COMMAND))
|
||||
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
depthead = 1
|
||||
if(rank=="Colony Director" && heads.len != 1)
|
||||
heads.Swap(1,heads.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SECURITY))
|
||||
sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && sec.len != 1)
|
||||
sec.Swap(1,sec.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_ENGINEERING))
|
||||
eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && eng.len != 1)
|
||||
eng.Swap(1,eng.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_MEDICAL))
|
||||
med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && med.len != 1)
|
||||
med.Swap(1,med.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_RESEARCH))
|
||||
sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && sci.len != 1)
|
||||
sci.Swap(1,sci.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_PLANET))
|
||||
pla[++pla.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CARGO))
|
||||
car[++car.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && car.len != 1)
|
||||
car.Swap(1,car.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CIVILIAN))
|
||||
civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
if(depthead && civ.len != 1)
|
||||
civ.Swap(1,civ.len)
|
||||
|
||||
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SYNTHETIC))
|
||||
bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
department = 1
|
||||
|
||||
if(!department && !(name in heads))
|
||||
misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
|
||||
|
||||
// Synthetics don't have actual records, so we will pull them from here.
|
||||
// Synths don't have records, which is the means by which isactive is retrieved, so I'm hardcoding it to active, don't really have any better means
|
||||
for(var/mob/living/silicon/ai/ai in mob_list)
|
||||
bot[++bot.len] = list("name" = ai.real_name, "rank" = "Artificial Intelligence", "active" = "Active")
|
||||
|
||||
for(var/mob/living/silicon/robot/robot in mob_list)
|
||||
// No combat/syndicate cyborgs, no drones, and no AI shells.
|
||||
if(robot.scrambledcodes || robot.shell || (robot.module && robot.module.hide_on_manifest))
|
||||
continue
|
||||
|
||||
bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active")
|
||||
|
||||
|
||||
PDA_Manifest = list(
|
||||
list("cat" = "Command", "elems" = heads),
|
||||
list("cat" = "Security", "elems" = sec),
|
||||
list("cat" = "Engineering", "elems" = eng),
|
||||
list("cat" = "Medical", "elems" = med),
|
||||
list("cat" = "Science", "elems" = sci),
|
||||
list("cat" = "Cargo", "elems" = car),
|
||||
list("cat" = "Exploration", "elems" = pla), // VOREStation Edit
|
||||
list("cat" = "Civilian", "elems" = civ),
|
||||
list("cat" = "Silicon", "elems" = bot),
|
||||
list("cat" = "Miscellaneous", "elems" = misc)
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/effect/laser
|
||||
name = "laser"
|
||||
desc = "IT BURNS!!!"
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
title = "Security Announcement"
|
||||
announcement_type = "Security Announcement"
|
||||
|
||||
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0)
|
||||
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0, zlevel)
|
||||
if(!message)
|
||||
return
|
||||
var/message_title = new_title ? new_title : title
|
||||
@@ -42,28 +42,32 @@
|
||||
message = sanitize(message, extra = 0)
|
||||
message_title = sanitizeSafe(message_title)
|
||||
|
||||
Message(message, message_title)
|
||||
var/list/zlevels
|
||||
if(zlevel)
|
||||
zlevels = using_map.get_map_levels(zlevel, TRUE)
|
||||
|
||||
Message(message, message_title, zlevels)
|
||||
if(do_newscast)
|
||||
NewsCast(message, message_title)
|
||||
Sound(message_sound)
|
||||
Sound(message_sound, zlevels)
|
||||
Log(message, message_title)
|
||||
|
||||
datum/announcement/proc/Message(message as text, message_title as text)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", announcer ? announcer : ANNOUNCER_NAME)
|
||||
datum/announcement/proc/Message(var/message as text, var/message_title as text, var/list/zlevels)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", announcer ? announcer : ANNOUNCER_NAME, zlevels)
|
||||
|
||||
datum/announcement/minor/Message(message as text, message_title as text)
|
||||
global_announcer.autosay(message, announcer ? announcer : ANNOUNCER_NAME)
|
||||
datum/announcement/minor/Message(var/message as text, var/message_title as text, var/list/zlevels)
|
||||
global_announcer.autosay(message, announcer ? announcer : ANNOUNCER_NAME, zlevels)
|
||||
|
||||
datum/announcement/priority/Message(message as text, message_title as text)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", announcer ? announcer : ANNOUNCER_NAME)
|
||||
datum/announcement/priority/Message(var/message as text, var/message_title as text, var/list/zlevels)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", announcer ? announcer : ANNOUNCER_NAME, zlevels)
|
||||
|
||||
datum/announcement/priority/command/Message(message as text, message_title as text)
|
||||
global_announcer.autosay("<span class='alert'>[command_name()] - [message_title]:</span> [message]", ANNOUNCER_NAME)
|
||||
datum/announcement/priority/command/Message(var/message as text, var/message_title as text, var/list/zlevels)
|
||||
global_announcer.autosay("<span class='alert'>[command_name()] - [message_title]:</span> [message]", ANNOUNCER_NAME, zlevels)
|
||||
|
||||
datum/announcement/priority/security/Message(message as text, message_title as text)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", ANNOUNCER_NAME)
|
||||
datum/announcement/priority/security/Message(var/message as text, var/message_title as text, var/list/zlevels)
|
||||
global_announcer.autosay("<span class='alert'>[message_title]:</span> [message]", ANNOUNCER_NAME, zlevels)
|
||||
|
||||
datum/announcement/proc/NewsCast(message as text, message_title as text)
|
||||
datum/announcement/proc/NewsCast(var/message as text, var/message_title as text)
|
||||
if(!newscast)
|
||||
return
|
||||
|
||||
@@ -75,15 +79,18 @@ datum/announcement/proc/NewsCast(message as text, message_title as text)
|
||||
news.can_be_redacted = 0
|
||||
announce_newscaster_news(news)
|
||||
|
||||
datum/announcement/proc/PlaySound(var/message_sound)
|
||||
datum/announcement/proc/PlaySound(var/message_sound, var/list/zlevels)
|
||||
if(!message_sound)
|
||||
return
|
||||
|
||||
for(var/mob/M in player_list)
|
||||
if(zlevels && !(M.z in zlevels))
|
||||
continue
|
||||
if(!istype(M,/mob/new_player) && !isdeaf(M))
|
||||
M << message_sound
|
||||
|
||||
datum/announcement/proc/Sound(var/message_sound)
|
||||
PlaySound(message_sound)
|
||||
datum/announcement/proc/Sound(var/message_sound, var/list/zlevels)
|
||||
PlaySound(message_sound, zlevels)
|
||||
|
||||
datum/announcement/priority/Sound(var/message_sound)
|
||||
if(message_sound)
|
||||
@@ -107,11 +114,12 @@ datum/announcement/proc/Log(message as text, message_title as text)
|
||||
/proc/ion_storm_announcement()
|
||||
command_announcement.Announce("It has come to our attention that \the [station_name()] passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
|
||||
|
||||
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message)
|
||||
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message, var/channel = "Common", var/zlevel)
|
||||
if (ticker.current_state == GAME_STATE_PLAYING)
|
||||
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
|
||||
if(character.mind.role_alt_title)
|
||||
rank = character.mind.role_alt_title
|
||||
AnnounceArrivalSimple(character.real_name, rank, join_message)
|
||||
AnnounceArrivalSimple(character.real_name, rank, join_message, channel, zlevels)
|
||||
|
||||
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive at the station shortly", new_sound = 'sound/misc/notice3.ogg') //VOREStation Edit - Remove shuttle reference
|
||||
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer")
|
||||
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive at the station shortly", var/channel = "Common", var/list/zlevels)
|
||||
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer", channel, zlevels)
|
||||
|
||||
@@ -94,6 +94,7 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
|
||||
|
||||
|
||||
proc/statistic_cycle()
|
||||
set waitfor = 0
|
||||
if(!sqllogging)
|
||||
return
|
||||
while(1)
|
||||
|
||||
@@ -70,6 +70,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
flags = RAD_SHIELDED
|
||||
sound_env = SMALL_ENCLOSED
|
||||
base_turf = /turf/space
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/shuttle/arrival
|
||||
name = "\improper Arrival Shuttle"
|
||||
@@ -807,6 +808,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "\improper Construction Area"
|
||||
icon_state = "construction"
|
||||
|
||||
/area/hallway/secondary/entry
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/hallway/secondary/entry/fore
|
||||
name = "\improper Shuttle Dock Hallway - Mid"
|
||||
icon_state = "entry_1"
|
||||
@@ -981,6 +985,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "Sleep"
|
||||
flags = RAD_SHIELDED
|
||||
ambience = AMBIENCE_GENERIC
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/crew_quarters/toilet
|
||||
name = "\improper Dormitory Toilets"
|
||||
@@ -1281,6 +1286,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "Holodeck"
|
||||
dynamic_lighting = 0
|
||||
sound_env = LARGE_ENCLOSED
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/holodeck/alphadeck
|
||||
name = "\improper Holodeck Alpha"
|
||||
@@ -1380,6 +1386,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
name = "\improper Engine Room"
|
||||
icon_state = "engine"
|
||||
sound_env = LARGE_ENCLOSED
|
||||
forbid_events = TRUE
|
||||
|
||||
/area/engineering/engine_airlock
|
||||
name = "\improper Engine Room Airlock"
|
||||
|
||||
+5
-10
@@ -40,14 +40,7 @@
|
||||
var/list/forced_ambience = null
|
||||
var/sound_env = STANDARD_STATION
|
||||
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
|
||||
var/global/global_uid = 0
|
||||
var/uid
|
||||
|
||||
/area/New()
|
||||
uid = ++global_uid
|
||||
all_areas += src //Replace with /area in world? Byond optimizes X in world loops.
|
||||
|
||||
..()
|
||||
var/forbid_events = FALSE // If true, random events will not start inside this area.
|
||||
|
||||
/area/Initialize()
|
||||
. = ..()
|
||||
@@ -366,6 +359,8 @@ var/list/mob/living/forced_ambiance_list = new
|
||||
temp_airlock.prison_open()
|
||||
for(var/obj/machinery/door/window/temp_windoor in src)
|
||||
temp_windoor.open()
|
||||
for(var/obj/machinery/door/blast/temp_blast in src)
|
||||
temp_blast.open()
|
||||
|
||||
/area/has_gravity()
|
||||
return has_gravity
|
||||
@@ -398,7 +393,7 @@ var/list/mob/living/forced_ambiance_list = new
|
||||
var/list/teleportlocs = list()
|
||||
|
||||
/hook/startup/proc/setupTeleportLocs()
|
||||
for(var/area/AR in all_areas)
|
||||
for(var/area/AR in world)
|
||||
if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue
|
||||
if(teleportlocs.Find(AR.name)) continue
|
||||
var/turf/picked = pick(get_area_turfs(AR.type))
|
||||
@@ -413,7 +408,7 @@ var/list/teleportlocs = list()
|
||||
var/list/ghostteleportlocs = list()
|
||||
|
||||
/hook/startup/proc/setupGhostTeleportLocs()
|
||||
for(var/area/AR in all_areas)
|
||||
for(var/area/AR in world)
|
||||
if(ghostteleportlocs.Find(AR.name)) continue
|
||||
if(istype(AR, /area/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome) || istype(AR, /area/shuttle/specops/centcom))
|
||||
ghostteleportlocs += AR.name
|
||||
|
||||
@@ -185,6 +185,12 @@
|
||||
to_chat(user, "[bicon(src)] That's [f_name] [suffix]")
|
||||
to_chat(user,desc)
|
||||
|
||||
if(user.client?.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
|
||||
to_chat(user, description_info)
|
||||
|
||||
if(user.client?.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL)
|
||||
user.client.statpanel = "Examine" // Switch to stat panel
|
||||
|
||||
return distance == -1 || (get_dist(src, user) <= distance)
|
||||
|
||||
// called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set.
|
||||
@@ -197,6 +203,20 @@
|
||||
. = new_dir != dir
|
||||
dir = new_dir
|
||||
|
||||
// Called to set the atom's density and used to add behavior to density changes.
|
||||
/atom/proc/set_density(var/new_density)
|
||||
if(density == new_density)
|
||||
return FALSE
|
||||
density = !!new_density // Sanitize to be strictly 0 or 1
|
||||
return TRUE
|
||||
|
||||
// Called to set the atom's invisibility and usd to add behavior to invisibility changes.
|
||||
/atom/proc/set_invisibility(var/new_invisibility)
|
||||
if(invisibility == new_invisibility)
|
||||
return FALSE
|
||||
invisibility = new_invisibility
|
||||
return TRUE
|
||||
|
||||
/atom/proc/ex_act()
|
||||
return
|
||||
|
||||
|
||||
@@ -538,7 +538,8 @@
|
||||
cloak_animation(animation_time)
|
||||
|
||||
//Needs to be last so people can actually see the effect before we become invisible
|
||||
plane = CLOAKED_PLANE
|
||||
if(cloaked) // Ensure we are still cloaked after the animation delay
|
||||
plane = CLOAKED_PLANE
|
||||
|
||||
/atom/movable/proc/uncloak()
|
||||
if(!cloaked)
|
||||
@@ -573,7 +574,7 @@
|
||||
sleep(length+5)
|
||||
|
||||
//Remove those
|
||||
filters -= filters[our_filter]
|
||||
filters -= filter(type="wave", x = 0, y = 16, size = 8, offset = 1, flags = WAVE_SIDEWAYS)
|
||||
|
||||
//Back to original alpha
|
||||
alpha = initial_alpha
|
||||
@@ -597,7 +598,7 @@
|
||||
sleep(length+5)
|
||||
|
||||
//Remove those
|
||||
filters -= filters[our_filter]
|
||||
filters -= filter(type="wave", x=0, y = 16, size = 0, offset = 0, flags = WAVE_SIDEWAYS)
|
||||
|
||||
|
||||
// So cloaked things can see themselves, if necessary
|
||||
|
||||
@@ -54,7 +54,7 @@ In short:
|
||||
|
||||
|
||||
/datum/universal_state/hell/proc/AreaSet()
|
||||
for(var/area/A in all_areas)
|
||||
for(var/area/A in world)
|
||||
if(!istype(A,/area) || istype(A, /area/space))
|
||||
continue
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked
|
||||
return
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/AreaSet()
|
||||
for(var/area/A in all_areas)
|
||||
for(var/area/A in world)
|
||||
if(!istype(A,/area) || istype(A, /area/space) || istype(A,/area/beach))
|
||||
continue
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ var/hadevent = 0
|
||||
|
||||
|
||||
var/list/area/areas = list()
|
||||
for(var/area/A in all_areas)
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/security/prison) || istype(A, /area/security/brig))
|
||||
areas += A
|
||||
|
||||
|
||||
@@ -1,467 +0,0 @@
|
||||
var/global/datum/controller/gameticker/ticker
|
||||
|
||||
/datum/controller/gameticker
|
||||
var/const/restart_timeout = 3 MINUTES //One minute is 600.
|
||||
var/current_state = GAME_STATE_PREGAME
|
||||
|
||||
var/hide_mode = 0
|
||||
var/datum/game_mode/mode = null
|
||||
var/post_game = 0
|
||||
var/event_time = null
|
||||
var/event = 0
|
||||
|
||||
// var/login_music // music played in pregame lobby // VOREStation Edit - We do music differently
|
||||
|
||||
var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking.
|
||||
|
||||
var/Bible_icon_state // icon_state the chaplain has chosen for his bible
|
||||
var/Bible_item_state // item_state the chaplain has chosen for his bible
|
||||
var/Bible_name // name of the bible
|
||||
var/Bible_deity_name
|
||||
|
||||
var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
|
||||
|
||||
var/list/syndicate_coalition = list() // list of traitor-compatible factions
|
||||
var/list/factions = list() // list of all factions
|
||||
var/list/availablefactions = list() // list of factions with openings
|
||||
|
||||
var/pregame_timeleft = 0
|
||||
|
||||
var/delay_end = 0 //if set to nonzero, the round will not restart on it's own
|
||||
|
||||
var/triai = 0//Global holder for Triumvirate
|
||||
|
||||
var/round_end_announced = 0 // Spam Prevention. Announce round end only once.
|
||||
|
||||
/datum/controller/gameticker/proc/pregame()
|
||||
/* VOREStation Edit - We do music differently
|
||||
login_music = pick(\
|
||||
'sound/music/halloween/skeletons.ogg',\
|
||||
'sound/music/halloween/halloween.ogg',\
|
||||
'sound/music/halloween/ghosts.ogg'
|
||||
'sound/music/space.ogg',\
|
||||
'sound/music/traitor.ogg',\
|
||||
'sound/music/title2.ogg',\
|
||||
'sound/music/clouds.s3m',\
|
||||
'sound/music/space_oddity.ogg') //Ground Control to Major Tom, this song is cool, what's going on?
|
||||
*/ //VOREStation Edit End
|
||||
|
||||
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
|
||||
|
||||
|
||||
do
|
||||
pregame_timeleft = config.pregame_time
|
||||
to_chat(world, "<B><FONT color='blue'>Welcome to the pregame lobby!</FONT></B>")
|
||||
to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
|
||||
while(current_state == GAME_STATE_PREGAME)
|
||||
if(round_progressing)
|
||||
pregame_timeleft--
|
||||
if(pregame_timeleft == config.vote_autogamemode_timeleft)
|
||||
if(!SSvote.time_remaining)
|
||||
SSvote.autogamemode() //Quit calling this over and over and over and over.
|
||||
while(SSvote.time_remaining)
|
||||
sleep(1)
|
||||
if(pregame_timeleft <= 0)
|
||||
current_state = GAME_STATE_SETTING_UP
|
||||
Master.SetRunLevel(RUNLEVEL_SETUP)
|
||||
sleep(10)
|
||||
while (!setup())
|
||||
|
||||
|
||||
/datum/controller/gameticker/proc/setup()
|
||||
//Create and announce mode
|
||||
if(master_mode=="secret")
|
||||
src.hide_mode = 1
|
||||
|
||||
var/list/runnable_modes = config.get_runnable_modes()
|
||||
if((master_mode=="random") || (master_mode=="secret"))
|
||||
if(!runnable_modes.len)
|
||||
current_state = GAME_STATE_PREGAME
|
||||
Master.SetRunLevel(RUNLEVEL_LOBBY)
|
||||
to_chat(world, "<B>Unable to choose playable game mode.</B> Reverting to pregame lobby.")
|
||||
return 0
|
||||
if(secret_force_mode != "secret")
|
||||
src.mode = config.pick_mode(secret_force_mode)
|
||||
if(!src.mode)
|
||||
var/list/weighted_modes = list()
|
||||
for(var/datum/game_mode/GM in runnable_modes)
|
||||
weighted_modes[GM.config_tag] = config.probabilities[GM.config_tag]
|
||||
src.mode = gamemode_cache[pickweight(weighted_modes)]
|
||||
else
|
||||
src.mode = config.pick_mode(master_mode)
|
||||
|
||||
if(!src.mode)
|
||||
current_state = GAME_STATE_PREGAME
|
||||
Master.SetRunLevel(RUNLEVEL_LOBBY)
|
||||
to_chat(world, "<span class='danger'>Serious error in mode setup!</span> Reverting to pregame lobby.") //Uses setup instead of set up due to computational context.
|
||||
return 0
|
||||
|
||||
job_master.ResetOccupations()
|
||||
src.mode.create_antagonists()
|
||||
src.mode.pre_setup()
|
||||
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
|
||||
|
||||
if(!src.mode.can_start())
|
||||
to_world("<B>Unable to start [mode.name].</B> Not enough players readied, [config.player_requirements[mode.config_tag]] players needed. Reverting to pregame lobby.")
|
||||
current_state = GAME_STATE_PREGAME
|
||||
Master.SetRunLevel(RUNLEVEL_LOBBY)
|
||||
mode.fail_setup()
|
||||
mode = null
|
||||
job_master.ResetOccupations()
|
||||
return 0
|
||||
|
||||
if(hide_mode)
|
||||
to_world("<B>The current game mode is - Secret!</B>")
|
||||
if(runnable_modes.len)
|
||||
var/list/tmpmodes = new
|
||||
for (var/datum/game_mode/M in runnable_modes)
|
||||
tmpmodes+=M.name
|
||||
tmpmodes = sortList(tmpmodes)
|
||||
if(tmpmodes.len)
|
||||
to_chat(world, "<B>Possibilities:</B> [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]")
|
||||
else
|
||||
src.mode.announce()
|
||||
|
||||
setup_economy()
|
||||
current_state = GAME_STATE_PLAYING
|
||||
create_characters() //Create player characters and transfer them.
|
||||
collect_minds()
|
||||
equip_characters()
|
||||
//data_core.manifest() //VOREStation Removal
|
||||
|
||||
callHook("roundstart")
|
||||
|
||||
// TODO - Leshana - 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
|
||||
for(var/obj/effect/landmark/start/S in landmarks_list)
|
||||
//Deleting Startpoints but we need the ai point to AI-ize people later
|
||||
if (S.name != "AI")
|
||||
qdel(S)
|
||||
to_chat(world, "<FONT color='blue'><B>Enjoy the game!</B></FONT>")
|
||||
world << sound('sound/AI/welcome.ogg') // Skie
|
||||
//Holiday Round-start stuff ~Carn
|
||||
Holiday_Game_Start()
|
||||
|
||||
//start_events() //handles random events and space dust.
|
||||
//new random event system is handled from the MC.
|
||||
|
||||
var/admins_number = 0
|
||||
for(var/client/C)
|
||||
if(C.holder)
|
||||
admins_number++
|
||||
if(admins_number == 0)
|
||||
send2adminirc("A round has started with no admins online.")
|
||||
|
||||
/* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler
|
||||
master_controller.process() //Start master_controller.process()
|
||||
lighting_controller.process() //Start processing DynamicAreaLighting updates
|
||||
*/
|
||||
|
||||
processScheduler.start()
|
||||
Master.SetRunLevel(RUNLEVEL_GAME)
|
||||
|
||||
if(config.sql_enabled)
|
||||
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE
|
||||
|
||||
return 1
|
||||
|
||||
/datum/controller/gameticker
|
||||
//station_explosion used to be a variable for every mob's hud. Which was a waste!
|
||||
//Now we have a general cinematic centrally held within the gameticker....far more efficient!
|
||||
var/obj/screen/cinematic = null
|
||||
|
||||
//Plus it provides an easy way to make cinematics for other events. Just use this as a template :)
|
||||
proc/station_explosion_cinematic(var/station_missed=0, var/override = null)
|
||||
if( cinematic ) return //already a cinematic in progress!
|
||||
|
||||
//initialise our cinematic screen object
|
||||
cinematic = new(src)
|
||||
cinematic.icon = 'icons/effects/station_explosion.dmi'
|
||||
cinematic.icon_state = "station_intact"
|
||||
cinematic.layer = 100
|
||||
cinematic.plane = PLANE_PLAYER_HUD
|
||||
cinematic.mouse_opacity = 0
|
||||
cinematic.screen_loc = "1,0"
|
||||
|
||||
var/obj/structure/bed/temp_buckle = new(src)
|
||||
//Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around
|
||||
if(station_missed)
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
M.buckled = temp_buckle //buckles the mob so it can't do anything
|
||||
if(M.client)
|
||||
M.client.screen += cinematic //show every client the cinematic
|
||||
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
M.buckled = temp_buckle
|
||||
if(M.client)
|
||||
M.client.screen += cinematic
|
||||
|
||||
switch(M.z)
|
||||
if(0) //inside a crate or something
|
||||
var/turf/T = get_turf(M)
|
||||
if(T && T.z in using_map.station_levels) //we don't use M.death(0) because it calls a for(/mob) loop and
|
||||
M.health = 0
|
||||
M.set_stat(DEAD)
|
||||
if(1) //on a z-level 1 turf.
|
||||
M.health = 0
|
||||
M.set_stat(DEAD)
|
||||
|
||||
//Now animate the cinematic
|
||||
switch(station_missed)
|
||||
if(1) //nuke was nearby but (mostly) missed
|
||||
if( mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("mercenary") //Nuke wasn't on station when it blew up
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
flick("station_intact_fade_red",cinematic)
|
||||
cinematic.icon_state = "summary_nukefail"
|
||||
else
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
//flick("end",cinematic)
|
||||
|
||||
|
||||
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
|
||||
sleep(50)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
|
||||
|
||||
else //station was destroyed
|
||||
if( mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("mercenary") //Nuke Ops successfully bombed the station
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_nukewin"
|
||||
if("AI malfunction") //Malf (screen,explosion,summary)
|
||||
flick("intro_malf",cinematic)
|
||||
sleep(76)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_malf"
|
||||
if("blob") //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
else //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red", cinematic)
|
||||
world << sound('sound/effects/explosionfar.ogg')
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
for(var/mob/living/M in living_mob_list)
|
||||
if(M.loc.z in using_map.station_levels)
|
||||
M.death()//No mercy
|
||||
//If its actually the end of the round, wait for it to end.
|
||||
//Otherwise if its a verb it will continue on afterwards.
|
||||
sleep(300)
|
||||
|
||||
if(cinematic) qdel(cinematic) //end the cinematic
|
||||
if(temp_buckle) qdel(temp_buckle) //release everybody
|
||||
return
|
||||
|
||||
|
||||
proc/create_characters()
|
||||
for(var/mob/new_player/player in player_list)
|
||||
if(player && player.ready && player.mind)
|
||||
if(player.mind.assigned_role=="AI")
|
||||
player.close_spawn_windows()
|
||||
player.AIize()
|
||||
else if(!player.mind.assigned_role)
|
||||
continue
|
||||
else
|
||||
//VOREStation Edit Start
|
||||
var/mob/living/carbon/human/new_char = player.create_character()
|
||||
if(new_char)
|
||||
qdel(player)
|
||||
if(istype(new_char) && !(new_char.mind.assigned_role=="Cyborg"))
|
||||
data_core.manifest_inject(new_char)
|
||||
//VOREStation Edit End
|
||||
|
||||
|
||||
proc/collect_minds()
|
||||
for(var/mob/living/player in player_list)
|
||||
if(player.mind)
|
||||
ticker.minds += player.mind
|
||||
|
||||
|
||||
proc/equip_characters()
|
||||
var/captainless=1
|
||||
for(var/mob/living/carbon/human/player in player_list)
|
||||
if(player && player.mind && player.mind.assigned_role)
|
||||
if(player.mind.assigned_role == "Colony Director")
|
||||
captainless=0
|
||||
if(!player_is_antag(player.mind, only_offstation_roles = 1))
|
||||
job_master.EquipRank(player, player.mind.assigned_role, 0)
|
||||
UpdateFactionList(player)
|
||||
//equip_custom_items(player) //VOREStation Removal
|
||||
//player.apply_traits() //VOREStation Removal
|
||||
if(captainless)
|
||||
for(var/mob/M in player_list)
|
||||
if(!istype(M,/mob/new_player))
|
||||
to_chat(M, "Colony Directorship not forced on anyone.")
|
||||
|
||||
|
||||
process()
|
||||
if(current_state != GAME_STATE_PLAYING)
|
||||
return 0
|
||||
|
||||
mode.process()
|
||||
|
||||
// emergency_shuttle.process() //handled in scheduler
|
||||
|
||||
var/game_finished = 0
|
||||
var/mode_finished = 0
|
||||
if (config.continous_rounds)
|
||||
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
|
||||
mode_finished = (!post_game && mode.check_finished())
|
||||
else
|
||||
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended
|
||||
mode_finished = game_finished
|
||||
|
||||
if(!mode.explosion_in_progress && game_finished && (mode_finished || post_game))
|
||||
current_state = GAME_STATE_FINISHED
|
||||
Master.SetRunLevel(RUNLEVEL_POSTGAME)
|
||||
|
||||
spawn
|
||||
declare_completion()
|
||||
|
||||
spawn(50)
|
||||
callHook("roundend")
|
||||
|
||||
var/time_left
|
||||
|
||||
if (mode.station_was_nuked)
|
||||
feedback_set_details("end_proper","nuke")
|
||||
time_left = 1 MINUTE //No point waiting five minutes if everyone's dead.
|
||||
if(!delay_end)
|
||||
to_chat(world, "<span class='notice'><b>Rebooting due to destruction of station in [round(time_left/600)] minutes.</b></span>")
|
||||
else
|
||||
feedback_set_details("end_proper","proper completion")
|
||||
time_left = round(restart_timeout)
|
||||
|
||||
|
||||
if(blackbox)
|
||||
blackbox.save_all_data_to_sql()
|
||||
|
||||
if(!delay_end)
|
||||
while(time_left > 0)
|
||||
if(delay_end)
|
||||
break
|
||||
to_chat(world, "<span class='notice'><b>Restarting in [round(time_left/600)] minute\s.</b></span>")
|
||||
time_left -= 1 MINUTES
|
||||
sleep(600)
|
||||
if(!delay_end)
|
||||
world.Reboot()
|
||||
else
|
||||
to_chat(world, "<span class='notice'><b>An admin has delayed the round end.</b></span>")
|
||||
else
|
||||
to_chat(world, "<span class='notice'><b>An admin has delayed the round end.</b></span>")
|
||||
|
||||
else if (mode_finished)
|
||||
post_game = 1
|
||||
|
||||
mode.cleanup()
|
||||
|
||||
//call a transfer shuttle vote
|
||||
spawn(50)
|
||||
if(!round_end_announced) // Spam Prevention. Now it should announce only once.
|
||||
to_chat(world, "<span class='danger'>The round has ended!</span>")
|
||||
round_end_announced = 1
|
||||
SSvote.autotransfer()
|
||||
|
||||
return 1
|
||||
|
||||
/datum/controller/gameticker/proc/declare_completion()
|
||||
to_world("<br><br><br><H1>A round of [mode.name] has ended!</H1>")
|
||||
for(var/mob/Player in player_list)
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(Player.stat != DEAD)
|
||||
var/turf/playerTurf = get_turf(Player)
|
||||
if(emergency_shuttle.departed && emergency_shuttle.evac)
|
||||
if(isNotAdminLevel(playerTurf.z))
|
||||
to_chat(Player, "<font color='blue'><b>You survived the round, but remained on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else if(isAdminLevel(playerTurf.z))
|
||||
to_chat(Player, "<font color='green'><b>You successfully underwent crew transfer after events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else if(issilicon(Player))
|
||||
to_chat(Player, "<font color='green'><b>You remain operational after the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='blue'><b>You missed the crew transfer after the events on [station_name()] as [Player.real_name].</b></font>")
|
||||
else
|
||||
if(istype(Player,/mob/observer/dead))
|
||||
var/mob/observer/dead/O = Player
|
||||
if(!O.started_as_observer)
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
|
||||
else
|
||||
to_chat(Player, "<font color='red'><b>You did not survive the events on [station_name()]...</b></font>")
|
||||
to_world("<br>")
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
|
||||
if (aiPlayer.stat != 2)
|
||||
to_world("<b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws at the end of the round were:</b>")
|
||||
else
|
||||
to_world("<b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws when it was deactivated were:</b>")
|
||||
aiPlayer.show_laws(1)
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/robolist = "<b>The AI's loyal minions were:</b> "
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]"
|
||||
to_world("[robolist]")
|
||||
|
||||
var/dronecount = 0
|
||||
|
||||
for (var/mob/living/silicon/robot/robo in mob_list)
|
||||
|
||||
if(istype(robo,/mob/living/silicon/robot/drone) && !istype(robo,/mob/living/silicon/robot/drone/swarm))
|
||||
dronecount++
|
||||
continue
|
||||
|
||||
if (!robo.connected_ai)
|
||||
if (robo.stat != 2)
|
||||
to_world("<b>[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:</b>")
|
||||
else
|
||||
to_world("<b>[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:</b>")
|
||||
|
||||
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
|
||||
robo.laws.show_laws(world)
|
||||
|
||||
if(dronecount)
|
||||
to_world("<b>There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] at the end of this round.</b>")
|
||||
|
||||
mode.declare_completion()//To declare normal completion.
|
||||
|
||||
//Ask the event manager to print round end information
|
||||
SSevents.RoundEnd()
|
||||
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
//Look into all mobs in world, dead or alive
|
||||
for(var/datum/mind/Mind in minds)
|
||||
var/temprole = Mind.special_role
|
||||
if(temprole) //if they are an antagonist of some sort.
|
||||
if(temprole in total_antagonists) //If the role exists already, add the name to it
|
||||
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
|
||||
else
|
||||
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
|
||||
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
|
||||
|
||||
//Now print them all into the log!
|
||||
log_game("Antagonists at round end were...")
|
||||
for(var/i in total_antagonists)
|
||||
log_game("[i]s[total_antagonists[i]].")
|
||||
|
||||
return 1
|
||||
@@ -183,6 +183,8 @@
|
||||
var/turf/simulated/wall/W = T
|
||||
W.take_damage(wall_power) // Stronger walls can halt asteroids.
|
||||
|
||||
/obj/effect/meteor/proc/get_shield_damage()
|
||||
return max(((max(hits, 2)) * (heavy + 1) * rand(6, 12)) / hitpwr , 0)
|
||||
|
||||
//process getting 'hit' by colliding with a dense object
|
||||
//or randomly when ramming turfs
|
||||
@@ -307,6 +309,9 @@
|
||||
// Worst case scenario: Comparable to a standard yield EMP grenade.
|
||||
empulse(src, rand(1, 3), rand(2, 4), rand(3, 7), rand(5, 10))
|
||||
|
||||
/obj/effect/meteor/emp/get_shield_damage()
|
||||
return ..() * rand(2,4)
|
||||
|
||||
//Station buster Tunguska
|
||||
/obj/effect/meteor/tunguska
|
||||
name = "tunguska meteor"
|
||||
|
||||
@@ -12,45 +12,51 @@
|
||||
var/obj/item/weapon/disk/nuclear/the_disk = null
|
||||
var/active = 0
|
||||
|
||||
|
||||
attack_self()
|
||||
if(!active)
|
||||
active = 1
|
||||
workdisk()
|
||||
to_chat(usr, "<span class='notice'>You activate the pinpointer</span>")
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
to_chat(usr, "<span>You deactivate the pinpointer</span>")
|
||||
|
||||
proc/workdisk()
|
||||
if(!active) return
|
||||
if(!the_disk)
|
||||
the_disk = locate()
|
||||
if(!the_disk)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
set_dir(get_dir(src,the_disk))
|
||||
switch(get_dist(src,the_disk))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
spawn(5) .()
|
||||
|
||||
examine(mob/user)
|
||||
..(user)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in machines)
|
||||
if(bomb.timing)
|
||||
to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]")
|
||||
|
||||
/obj/item/weapon/pinpointer/Destroy()
|
||||
active = 0
|
||||
..()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/pinpointer/attack_self()
|
||||
if(!active)
|
||||
active = 1
|
||||
START_PROCESSING(SSobj, src)
|
||||
to_chat(usr, "<span class='notice'>You activate the pinpointer</span>")
|
||||
else
|
||||
active = 0
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
icon_state = "pinoff"
|
||||
to_chat(usr, "<span class='notice'>You deactivate the pinpointer</span>")
|
||||
|
||||
/obj/item/weapon/pinpointer/process()
|
||||
if(!active)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(!the_disk)
|
||||
the_disk = locate()
|
||||
if(!the_disk)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
|
||||
set_dir(get_dir(src,the_disk))
|
||||
|
||||
switch(get_dist(src,the_disk))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
/obj/item/weapon/pinpointer/examine(mob/user)
|
||||
..(user)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in machines)
|
||||
if(bomb.timing)
|
||||
to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]")
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer
|
||||
name = "Advanced Pinpointer"
|
||||
@@ -60,58 +66,49 @@
|
||||
var/turf/location = null
|
||||
var/obj/target = null
|
||||
|
||||
attack_self()
|
||||
if(!active)
|
||||
active = 1
|
||||
if(mode == 0)
|
||||
workdisk()
|
||||
if(mode == 1)
|
||||
worklocation()
|
||||
if(mode == 2)
|
||||
workobj()
|
||||
to_chat(usr, "<span class='notice'>You activate the pinpointer</span>")
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
to_chat(usr, "<span class='notice'>You deactivate the pinpointer</span>")
|
||||
/obj/item/weapon/pinpointer/advpinpointer/process()
|
||||
if(!active)
|
||||
return PROCESS_KILL
|
||||
if(mode == 0)
|
||||
..()
|
||||
if(mode == 1)
|
||||
worklocation()
|
||||
if(mode == 2)
|
||||
workobj()
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer/proc/worklocation()
|
||||
if(!location)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
|
||||
proc/worklocation()
|
||||
if(!active)
|
||||
return
|
||||
if(!location)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
set_dir(get_dir(src,location))
|
||||
switch(get_dist(src,location))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
spawn(5) .()
|
||||
set_dir(get_dir(src,location))
|
||||
|
||||
switch(get_dist(src,location))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
proc/workobj()
|
||||
if(!active)
|
||||
return
|
||||
if(!target)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
set_dir(get_dir(src,target))
|
||||
switch(get_dist(src,target))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
spawn(5) .()
|
||||
/obj/item/weapon/pinpointer/advpinpointer/proc/workobj()
|
||||
if(!target)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
|
||||
set_dir(get_dir(src,target))
|
||||
|
||||
switch(get_dist(src,target))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode()
|
||||
set category = "Object"
|
||||
@@ -140,7 +137,6 @@
|
||||
|
||||
to_chat(usr, "You set the pinpointer to locate [locationx],[locationy]")
|
||||
|
||||
|
||||
return attack_self()
|
||||
|
||||
if("Disk Recovery")
|
||||
@@ -150,9 +146,10 @@
|
||||
if("Other Signature")
|
||||
mode = 2
|
||||
switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA"))
|
||||
|
||||
if("Item")
|
||||
var/datum/objective/steal/itemlist
|
||||
itemlist = itemlist // To supress a 'variable defined but not used' error.
|
||||
itemlist = itemlist
|
||||
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in itemlist.possible_items
|
||||
if(!targetitem)
|
||||
return
|
||||
@@ -161,6 +158,7 @@
|
||||
to_chat(usr, "Failed to locate [targetitem]!")
|
||||
return
|
||||
to_chat(usr, "You set the pinpointer to locate [targetitem]")
|
||||
|
||||
if("DNA")
|
||||
var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "")
|
||||
if(!DNAstring)
|
||||
@@ -187,6 +185,7 @@
|
||||
/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user as mob)
|
||||
if(!active)
|
||||
active = 1
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(!mode)
|
||||
workdisk()
|
||||
to_chat(user, "<span class='notice'>Authentication Disk Locator active.</span>")
|
||||
@@ -195,30 +194,35 @@
|
||||
to_chat(user, "<span class='notice'>Shuttle Locator active.</span>")
|
||||
else
|
||||
active = 0
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
icon_state = "pinoff"
|
||||
to_chat(user, "<span class='notice'>You deactivate the pinpointer.</span>")
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/process()
|
||||
if(!active)
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/workdisk()
|
||||
if(!active) return
|
||||
if(mode) //Check in case the mode changes while operating
|
||||
worklocation()
|
||||
return
|
||||
switch(mode)
|
||||
if(0)
|
||||
workdisk()
|
||||
if(1)
|
||||
worklocation()
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/proc/workdisk()
|
||||
if(bomb_set) //If the bomb is set, lead to the shuttle
|
||||
mode = 1 //Ensures worklocation() continues to work
|
||||
worklocation()
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep
|
||||
visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed
|
||||
visible_message("<span class='notice'>Shuttle Locator active.</span>") //Lets the mob holding it know that the mode has changed
|
||||
return //Get outta here
|
||||
|
||||
if(!the_disk)
|
||||
the_disk = locate()
|
||||
if(!the_disk)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
// if(loc.z != the_disk.z) //If you are on a different z-level from the disk
|
||||
// icon_state = "pinonnull"
|
||||
// else
|
||||
|
||||
set_dir(get_dir(src, the_disk))
|
||||
|
||||
switch(get_dist(src, the_disk))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
@@ -229,29 +233,25 @@
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
spawn(5) .()
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/proc/worklocation()
|
||||
if(!active) return
|
||||
if(!mode)
|
||||
workdisk()
|
||||
return
|
||||
if(!bomb_set)
|
||||
mode = 0
|
||||
workdisk()
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
visible_message("<span class='notice'>Authentication Disk Locator active.</span>")
|
||||
return
|
||||
|
||||
if(!home)
|
||||
home = locate()
|
||||
if(!home)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
|
||||
if(loc.z != home.z) //If you are on a different z-level from the shuttle
|
||||
icon_state = "pinonnull"
|
||||
|
||||
else
|
||||
set_dir(get_dir(src, home))
|
||||
|
||||
switch(get_dist(src, home))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
@@ -262,8 +262,6 @@
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
spawn(5) .()
|
||||
|
||||
|
||||
// This one only points to the ship. Useful if there is no nuking to occur today.
|
||||
/obj/item/weapon/pinpointer/shuttle
|
||||
@@ -273,16 +271,17 @@
|
||||
/obj/item/weapon/pinpointer/shuttle/attack_self(mob/user as mob)
|
||||
if(!active)
|
||||
active = TRUE
|
||||
find_shuttle()
|
||||
START_PROCESSING(SSobj, src)
|
||||
to_chat(user, "<span class='notice'>Shuttle Locator active.</span>")
|
||||
else
|
||||
active = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
icon_state = "pinoff"
|
||||
to_chat(user, "<span class='notice'>You deactivate the pinpointer.</span>")
|
||||
|
||||
/obj/item/weapon/pinpointer/shuttle/proc/find_shuttle()
|
||||
/obj/item/weapon/pinpointer/shuttle/process()
|
||||
if(!active)
|
||||
return
|
||||
return PROCESS_KILL
|
||||
|
||||
if(!our_shuttle)
|
||||
for(var/obj/machinery/computer/shuttle_control/S in machines)
|
||||
@@ -296,8 +295,10 @@
|
||||
|
||||
if(loc.z != our_shuttle.z) //If you are on a different z-level from the shuttle
|
||||
icon_state = "pinonnull"
|
||||
|
||||
else
|
||||
set_dir(get_dir(src, our_shuttle))
|
||||
|
||||
switch(get_dist(src, our_shuttle))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
@@ -308,9 +309,6 @@
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
spawn(5)
|
||||
.()
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/shuttle/merc
|
||||
shuttle_comp_id = "Mercenary"
|
||||
|
||||
@@ -25,7 +25,7 @@ var/list/all_technomancer_assistance = typesof(/datum/technomancer/assistance) -
|
||||
/obj/item/weapon/technomancer_catalog
|
||||
name = "catalog"
|
||||
desc = "A \"book\" featuring a holographic display, metal cover, and miniaturized teleportation device, allowing the user to \
|
||||
requisition various things from.. where ever they came from."
|
||||
requisition various things from... wherever they came from."
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state ="scientology" //placeholder
|
||||
w_class = ITEMSIZE_SMALL
|
||||
@@ -40,6 +40,7 @@ var/list/all_technomancer_assistance = typesof(/datum/technomancer/assistance) -
|
||||
var/tab = 4 // Info tab, so new players can read it before doing anything.
|
||||
var/spell_tab = ALL_SPELLS
|
||||
var/show_scepter_text = 0
|
||||
var/universal = FALSE //VOREStation Add - Allows non-technomancers to use this catalog
|
||||
|
||||
/obj/item/weapon/technomancer_catalog/apprentice
|
||||
name = "apprentice's catalog"
|
||||
@@ -51,12 +52,22 @@ var/list/all_technomancer_assistance = typesof(/datum/technomancer/assistance) -
|
||||
budget = 2000
|
||||
max_budget = 2000
|
||||
|
||||
//VOREStation Add
|
||||
/obj/item/weapon/technomancer_catalog/universal
|
||||
name = "universal catalog"
|
||||
desc = "A catalog to be used with the KHI 'Universal Core', shamelessly \
|
||||
copied by a Kitsuhana designer from some group of 'technomancers' or another.<br>\
|
||||
The back of the book has <i>'Export Edition'</i> stamped on it."
|
||||
budget = 700
|
||||
max_budget = 700
|
||||
universal = TRUE
|
||||
//VOREStation Add End
|
||||
|
||||
// Proc: bind_to_owner()
|
||||
// Parameters: 1 (new_owner - mob that the book is trying to bind to)
|
||||
// Description: Links the catalog to hopefully the technomancer, so that only they can access it.
|
||||
/obj/item/weapon/technomancer_catalog/proc/bind_to_owner(var/mob/living/carbon/human/new_owner)
|
||||
if(!owner && technomancers.is_antagonist(new_owner.mind))
|
||||
if(!owner && (technomancers.is_antagonist(new_owner.mind) || universal)) //VOREStation Edit - Universal catalogs
|
||||
owner = new_owner
|
||||
|
||||
// Proc: New()
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
var/list/summoned_mobs = list() // Maintained horribly with maintain_summon_list().
|
||||
var/list/wards_in_use = list() // Wards don't count against the cap for other summons.
|
||||
var/max_summons = 10 // Maximum allowed summoned entities. Some cores will have different caps.
|
||||
var/universal = FALSE // Allows non-technomancers to use the core - VOREStation Add
|
||||
|
||||
/obj/item/weapon/technomancer_core/New()
|
||||
..()
|
||||
@@ -88,7 +89,7 @@
|
||||
if(world.time % 5 == 0) // Maintaining fat lists is expensive, I imagine.
|
||||
maintain_summon_list()
|
||||
if(wearer && wearer.mind)
|
||||
if(!(technomancers.is_antagonist(wearer.mind))) // In case someone tries to wear a stolen core.
|
||||
if(!(technomancers.is_antagonist(wearer.mind)) && !universal) // In case someone tries to wear a stolen core. //VOREStation Edit - Add universal cores
|
||||
wearer.adjust_instability(20)
|
||||
if(!wearer || wearer.stat == DEAD) // Unlock if we're dead or not worn.
|
||||
canremove = TRUE
|
||||
@@ -349,4 +350,19 @@
|
||||
set desc = "Toggles the locking mechanism on your manipulation core."
|
||||
|
||||
canremove = !canremove
|
||||
to_chat(usr, "<span class='notice'>You [canremove ? "de" : ""]activate the locking mechanism on \the [src].</span>")
|
||||
to_chat(usr, "<span class='notice'>You [canremove ? "de" : ""]activate the locking mechanism on \the [src].</span>")
|
||||
|
||||
//For the adminbuse! VOREStation Add
|
||||
/obj/item/weapon/technomancer_core/universal
|
||||
name = "universal core"
|
||||
desc = "A bewilderingly complex 'black box' that allows the wearer to accomplish amazing feats. \
|
||||
This one is a copy of a 'technomancer' core, shamelessly ripped off by a Kitsuhana pattern designer \
|
||||
for fun, so that he could perform impressive 'magic'. The pack sloshes slightly if you shake it.<br>\
|
||||
Under the straps, <i>'Export Edition'</i> is printed."
|
||||
energy = 7000
|
||||
max_energy = 7000
|
||||
regen_rate = 30 //233 seconds to full
|
||||
instability_modifier = 0.3
|
||||
spell_power_modifier = 0.7
|
||||
universal = TRUE
|
||||
//VOREStation Add End
|
||||
@@ -188,7 +188,7 @@
|
||||
if(core.loc != owner || owner.back != core) //Make sure the core's being worn.
|
||||
to_chat(owner, "<span class='danger'>You need to be wearing a core on your back!</span>")
|
||||
return 0
|
||||
if(!technomancers.is_antagonist(owner.mind)) //Now make sure the person using this is the actual antag.
|
||||
if(!technomancers.is_antagonist(owner.mind) && !core.universal) //Now make sure the person using this is the actual antag. //VOREStation Edit - Universal cores
|
||||
to_chat(owner, "<span class='danger'>You can't seem to figure out how to make the machine work properly.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -8,16 +8,30 @@
|
||||
ability_icon_state = "tech_mark"
|
||||
category = UTILITY_SPELLS
|
||||
|
||||
//The object to teleport to when Recall is used.
|
||||
/obj/effect/mark_spell
|
||||
name = "mark"
|
||||
desc = "This is a strange looking disturbance."
|
||||
opacity = 0
|
||||
density = 0
|
||||
anchored = 1
|
||||
/datum/technomancer_marker
|
||||
var/weakref/U
|
||||
var/image/I
|
||||
var/turf/T
|
||||
|
||||
/datum/technomancer_marker/New(var/mob/user)
|
||||
U = weakref(user)
|
||||
T = get_turf(user)
|
||||
I = image('icons/goonstation/featherzone.dmi', T, "spawn-wall")
|
||||
I.plane = TURF_PLANE
|
||||
I.layer = ABOVE_TURF_LAYER
|
||||
user.client?.images |= I
|
||||
spawn(23) //That's just how long the animation is
|
||||
I.icon_state = "spawn-wall-loop"
|
||||
|
||||
/datum/technomancer_marker/Destroy()
|
||||
var/mob/user = U?.resolve()
|
||||
user?.client?.images -= I
|
||||
I?.loc = null
|
||||
U = T = I = null
|
||||
return ..()
|
||||
|
||||
//This is global, to avoid looping through a list of all objects, or god forbid, looping through world.
|
||||
/var/global/obj/effect/mark_spell/mark_spell_ref = null
|
||||
GLOBAL_LIST_INIT(mark_spells, list())
|
||||
|
||||
/obj/item/weapon/spell/mark
|
||||
name = "mark"
|
||||
@@ -26,17 +40,20 @@
|
||||
cast_methods = CAST_USE
|
||||
aspect = ASPECT_TELE
|
||||
|
||||
/obj/item/weapon/spell/mark/on_use_cast(mob/living/user)
|
||||
/obj/item/weapon/spell/mark/on_use_cast(var/mob/living/user)
|
||||
if(!allowed_to_teleport()) // Otherwise you could teleport back to the admin Z-level.
|
||||
to_chat(user, "<span class='warning'>You can't teleport here!</span>")
|
||||
return 0
|
||||
if(pay_energy(1000))
|
||||
if(!mark_spell_ref)
|
||||
mark_spell_ref = new(get_turf(user))
|
||||
to_chat(user, "<span class='notice'>You mark \the [get_turf(user)] under you.</span>")
|
||||
else
|
||||
mark_spell_ref.forceMove(get_turf(user))
|
||||
var/datum/technomancer_marker/marker = GLOB.mark_spells[weakref(user)]
|
||||
//They have one in the list
|
||||
if(istype(marker))
|
||||
qdel(marker)
|
||||
to_chat(user, "<span class='notice'>Your mark is moved from its old position to \the [get_turf(user)] under you.</span>")
|
||||
//They don't have one yet
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You mark \the [get_turf(user)] under you.</span>")
|
||||
GLOB.mark_spells[weakref(user)] = new /datum/technomancer_marker(user)
|
||||
adjust_instability(5)
|
||||
return 1
|
||||
else
|
||||
@@ -62,9 +79,10 @@
|
||||
cast_methods = CAST_USE
|
||||
aspect = ASPECT_TELE
|
||||
|
||||
/obj/item/weapon/spell/recall/on_use_cast(mob/living/user)
|
||||
/obj/item/weapon/spell/recall/on_use_cast(var/mob/living/user)
|
||||
if(pay_energy(3000))
|
||||
if(!mark_spell_ref)
|
||||
var/datum/technomancer_marker/marker = GLOB.mark_spells[weakref(user)]
|
||||
if(!istype(marker))
|
||||
to_chat(user, "<span class='danger'>There's no Mark!</span>")
|
||||
return 0
|
||||
else
|
||||
@@ -86,7 +104,7 @@
|
||||
time_left--
|
||||
sleep(1 SECOND)
|
||||
|
||||
var/turf/target_turf = get_turf(mark_spell_ref)
|
||||
var/turf/target_turf = marker.T
|
||||
var/turf/old_turf = get_turf(user)
|
||||
|
||||
for(var/obj/item/weapon/grab/G in user.contents) // People the Technomancer is grabbing come along for the ride.
|
||||
|
||||
@@ -10,3 +10,10 @@ var/const/access_pilot = 67
|
||||
id = access_pilot
|
||||
desc = "Pilot"
|
||||
region = ACCESS_REGION_SUPPLY
|
||||
|
||||
/var/const/access_talon = 301
|
||||
/datum/access/talon
|
||||
id = access_talon
|
||||
desc = "Talon"
|
||||
access_type = ACCESS_TYPE_PRIVATE
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
var/outfit_type // What outfit datum does this job use in its default title?
|
||||
|
||||
var/offmap_spawn = FALSE // Do we require weird and special spawning and datacore handling?
|
||||
|
||||
// Description of the job's role and minimum responsibilities.
|
||||
var/job_description = "This Job doesn't have a description! Please report it!"
|
||||
|
||||
@@ -67,7 +69,7 @@
|
||||
|
||||
//give them an account in the station database
|
||||
var/money_amount = (rand(15,40) + rand(15,40)) * income * economic_modifier * ECO_MODIFIER //VOREStation Edit - Smoothed peaks, ECO_MODIFIER rather than per-species ones.
|
||||
var/datum/money_account/M = create_account(H.real_name, money_amount, null)
|
||||
var/datum/money_account/M = create_account(H.real_name, money_amount, null, offmap_spawn)
|
||||
if(H.mind)
|
||||
var/remembered_info = ""
|
||||
remembered_info += "<b>Your account number is:</b> #[M.account_number]<br>"
|
||||
|
||||
@@ -357,7 +357,11 @@ var/global/datum/controller/occupations/job_master
|
||||
else
|
||||
var/list/spawn_props = LateSpawn(H.client, rank)
|
||||
var/turf/T = spawn_props["turf"]
|
||||
H.forceMove(T)
|
||||
if(!T)
|
||||
to_chat(H, "<span class='critical'>You were unable to be spawned at your chosen late-join spawnpoint. Please verify your job/spawn point combination makes sense, and try another one.</span>")
|
||||
return
|
||||
else
|
||||
H.forceMove(T)
|
||||
|
||||
// Moving wheelchair if they have one
|
||||
if(H.buckled && istype(H.buckled, /obj/structure/bed/chair/wheelchair))
|
||||
@@ -458,8 +462,8 @@ var/global/datum/controller/occupations/job_master
|
||||
if("AI")
|
||||
return H
|
||||
if("Colony Director")
|
||||
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP)? null : sound('sound/misc/boatswain.ogg', volume=20)
|
||||
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound=announce_sound)
|
||||
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20)
|
||||
captain_announcement.Announce("All hands, [alt_title ? alt_title : "Colony Director"] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z)
|
||||
|
||||
//Deferred item spawning.
|
||||
if(spawn_in_storage && spawn_in_storage.len)
|
||||
@@ -608,12 +612,20 @@ var/global/datum/controller/occupations/job_master
|
||||
/datum/controller/occupations/proc/LateSpawn(var/client/C, var/rank)
|
||||
|
||||
var/datum/spawnpoint/spawnpos
|
||||
var/fail_deadly = FALSE
|
||||
|
||||
var/datum/job/J = SSjob.get_job(rank)
|
||||
fail_deadly = J?.offmap_spawn
|
||||
|
||||
//Spawn them at their preferred one
|
||||
if(C && C.prefs.spawnpoint)
|
||||
if(!(C.prefs.spawnpoint in using_map.allowed_spawns))
|
||||
to_chat(C, "<span class='warning'>Your chosen spawnpoint ([C.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.</span>")
|
||||
spawnpos = null
|
||||
if(fail_deadly)
|
||||
to_chat(C, "<span class='warning'>Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(C, "<span class='warning'>Your chosen spawnpoint ([C.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.</span>")
|
||||
spawnpos = null
|
||||
else
|
||||
spawnpos = spawntypes[C.prefs.spawnpoint]
|
||||
|
||||
@@ -623,12 +635,16 @@ var/global/datum/controller/occupations/job_master
|
||||
if(spawnpos.check_job_spawning(rank))
|
||||
.["turf"] = spawnpos.get_spawn_position()
|
||||
.["msg"] = spawnpos.msg
|
||||
.["channel"] = spawnpos.announce_channel
|
||||
else
|
||||
if(fail_deadly)
|
||||
to_chat(C, "<span class='warning'>Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Please correct your spawn point choice.</span>")
|
||||
return
|
||||
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.")
|
||||
var/spawning = pick(latejoin)
|
||||
.["turf"] = get_turf(spawning)
|
||||
.["msg"] = "will arrive at the station shortly" //VOREStation Edit - Grammar but mostly 'shuttle' reference removal, and this also applies to notified spawn-character verb use
|
||||
else
|
||||
else if(!fail_deadly)
|
||||
var/spawning = pick(latejoin)
|
||||
.["turf"] = get_turf(spawning)
|
||||
.["msg"] = "has arrived on the station"
|
||||
|
||||
@@ -45,6 +45,16 @@ var/const/BRIDGE =(1<<12)
|
||||
var/const/CLOWN =(1<<13) //VOREStation Add
|
||||
var/const/MIME =(1<<14) //VOREStation Add
|
||||
|
||||
//VOREStation Add
|
||||
var/const/TALON =(1<<3)
|
||||
|
||||
var/const/TALCAP =(1<<0)
|
||||
var/const/TALPIL =(1<<1)
|
||||
var/const/TALDOC =(1<<2)
|
||||
var/const/TALSEC =(1<<3)
|
||||
var/const/TALENG =(1<<4)
|
||||
//VOREStation Add End
|
||||
|
||||
/proc/guest_jobbans(var/job)
|
||||
return ( (job in SSjob.get_job_titles_in_department(DEPARTMENT_COMMAND)) || (job in SSjob.get_job_titles_in_department(DEPARTMENT_SYNTHETIC)) || (job in SSjob.get_job_titles_in_department(DEPARTMENT_SECURITY)) )
|
||||
|
||||
|
||||
@@ -254,8 +254,6 @@
|
||||
return
|
||||
if(occupant)
|
||||
occupant.Stasis(stasis_level)
|
||||
if(stasis_level >= 100 && occupant.timeofdeath)
|
||||
occupant.timeofdeath += 1 SECOND
|
||||
|
||||
if(filtering > 0)
|
||||
if(beaker)
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
/obj/machinery/alarm/proc/first_run()
|
||||
alarm_area = get_area(src)
|
||||
area_uid = alarm_area.uid
|
||||
area_uid = "\ref[alarm_area]"
|
||||
if(name == "alarm")
|
||||
name = "[alarm_area.name] Air Alarm"
|
||||
|
||||
@@ -387,7 +387,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 = command
|
||||
@@ -449,7 +449,7 @@
|
||||
|
||||
var/datum/signal/alert_signal = new
|
||||
alert_signal.source = src
|
||||
alert_signal.transmission_method = 1
|
||||
alert_signal.transmission_method = TRANSMISSION_RADIO
|
||||
alert_signal.data["zone"] = alarm_area.name
|
||||
alert_signal.data["type"] = "Atmospheric"
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
/obj/machinery/air_sensor/process()
|
||||
if(on)
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.data["tag"] = id_tag
|
||||
signal.data["timestamp"] = world.time
|
||||
|
||||
@@ -212,7 +212,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.source = src
|
||||
if(href_list["in_refresh_status"])
|
||||
input_info = null
|
||||
@@ -322,7 +322,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.source = src
|
||||
if(href_list["in_refresh_status"])
|
||||
input_info = null
|
||||
@@ -383,7 +383,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
injecting = 1
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
@@ -445,7 +445,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
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(
|
||||
"tag" = device_tag,
|
||||
@@ -463,7 +463,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
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(
|
||||
"tag" = device_tag,
|
||||
@@ -478,7 +478,7 @@ obj/machinery/computer/general_air_control/Destroy()
|
||||
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(
|
||||
"tag" = device_tag,
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.source = src
|
||||
signal.transmission_method = 1
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AM",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
var/busy = 0
|
||||
|
||||
var/on_open_network = 0
|
||||
var/always_visible = FALSE //Visable from any map, good for entertainment network cameras
|
||||
|
||||
var/affected_by_emp_until = 0
|
||||
|
||||
@@ -472,6 +473,7 @@
|
||||
cam["name"] = sanitize(c_tag)
|
||||
cam["deact"] = !can_use()
|
||||
cam["camera"] = "\ref[src]"
|
||||
cam["omni"] = always_visible
|
||||
cam["x"] = x
|
||||
cam["y"] = y
|
||||
cam["z"] = z
|
||||
|
||||
@@ -102,6 +102,7 @@ var/global/list/engineering_networks = list(
|
||||
/obj/machinery/camera/network/thunder
|
||||
network = list(NETWORK_THUNDER)
|
||||
invuln = 1
|
||||
always_visible = TRUE
|
||||
|
||||
// EMP
|
||||
|
||||
|
||||
@@ -43,11 +43,14 @@
|
||||
data["current_camera"] = current_camera ? current_camera.nano_structure() : null
|
||||
data["current_network"] = current_network
|
||||
data["networks"] = network ? network : list()
|
||||
|
||||
var/map_levels = using_map.get_map_levels(src.z, TRUE)
|
||||
data["map_levels"] = map_levels
|
||||
|
||||
if(current_network)
|
||||
data["cameras"] = camera_repository.cameras_in_network(current_network)
|
||||
data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels)
|
||||
if(current_camera)
|
||||
switch_to_camera(user, current_camera)
|
||||
data["map_levels"] = using_map.get_map_levels(src.z)
|
||||
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
@@ -91,9 +94,6 @@
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/security/attack_hand(var/mob/user as mob)
|
||||
if (using_map && !(src.z in using_map.contact_levels))
|
||||
to_chat(user, "<span class='danger'>Unable to establish a connection:</span> You're too far away from the station!")
|
||||
return
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
|
||||
if(!isAI(user))
|
||||
|
||||
@@ -546,7 +546,7 @@
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.transmission_method = TRANSMISSION_RADIO
|
||||
status_signal.data["command"] = command
|
||||
|
||||
switch(command)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
idle_power_usage = 250
|
||||
active_power_usage = 500
|
||||
circuit = /obj/item/weapon/circuitboard/crew
|
||||
var/datum/nano_module/crew_monitor/crew_monitor
|
||||
var/datum/nano_module/program/crew_monitor/crew_monitor
|
||||
|
||||
/obj/machinery/computer/crew/New()
|
||||
crew_monitor = new(src)
|
||||
|
||||
@@ -121,7 +121,7 @@ var/prison_shuttle_timeleft = 0
|
||||
if(!frequency) return
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.transmission_method = TRANSMISSION_RADIO
|
||||
status_signal.data["command"] = command
|
||||
frequency.post_signal(src, status_signal)
|
||||
return
|
||||
|
||||
@@ -91,19 +91,28 @@
|
||||
var/icon/side = active1.fields["photo_side"]
|
||||
user << browse_rsc(front, "front.png")
|
||||
user << browse_rsc(side, "side.png")
|
||||
dat += text("<table><tr><td> \
|
||||
Name: <A href='?src=\ref[src];choice=Edit Field;field=name'>[active1.fields["name"]]</A><BR> \
|
||||
ID: <A href='?src=\ref[src];choice=Edit Field;field=id'>[active1.fields["id"]]</A><BR>\n \
|
||||
Entity Classification: <A href='?src=\ref[src];field=brain_type'>[active1.fields["brain_type"]]</A><BR>\n \
|
||||
Sex: <A href='?src=\ref[src];choice=Edit Field;field=sex'>[active1.fields["sex"]]</A><BR>\n \
|
||||
Age: <A href='?src=\ref[src];choice=Edit Field;field=age'>[active1.fields["age"]]</A><BR>\n \
|
||||
Rank: <A href='?src=\ref[src];choice=Edit Field;field=rank'>[active1.fields["rank"]]</A><BR>\n \
|
||||
Fingerprint: <A href='?src=\ref[src];choice=Edit Field;field=fingerprint'>[active1.fields["fingerprint"]]</A><BR>\n \
|
||||
Physical Status: [active1.fields["p_stat"]]<BR>\n \
|
||||
Mental Status: [active1.fields["m_stat"]]<BR><BR>\n \
|
||||
Employment/skills summary:<BR> [decode(active1.fields["notes"])]<BR></td> \
|
||||
<td align = center valign = top>Photo:<br><img src=front.png height=80 width=80 border=4> \
|
||||
<img src=side.png height=80 width=80 border=4></td></tr></table>")
|
||||
dat += "<table><tr><td>"
|
||||
dat += "Name: <A href='?src=\ref[src];choice=Edit Field;field=name'>[active1.fields["name"]]</A><BR>"
|
||||
dat += "ID: <A href='?src=\ref[src];choice=Edit Field;field=id'>[active1.fields["id"]]</A><BR>\n"
|
||||
dat += "Entity Classification: <A href='?src=\ref[src];field=brain_type'>[active1.fields["brain_type"]]</A><BR>\n"
|
||||
dat += "Sex: <A href='?src=\ref[src];choice=Edit Field;field=sex'>[active1.fields["sex"]]</A><BR>\n"
|
||||
dat += "Age: <A href='?src=\ref[src];choice=Edit Field;field=age'>[active1.fields["age"]]</A><BR>\n"
|
||||
dat += "Rank: <A href='?src=\ref[src];choice=Edit Field;field=rank'>[active1.fields["rank"]]</A><BR>\n"
|
||||
dat += "Fingerprint: <A href='?src=\ref[src];choice=Edit Field;field=fingerprint'>[active1.fields["fingerprint"]]</A><BR>\n"
|
||||
dat += "Physical Status: [active1.fields["p_stat"]]<BR>\n"
|
||||
dat += "Mental Status: [active1.fields["m_stat"]]<BR><BR>\n"
|
||||
|
||||
dat += "Employment/skills summary:<BR>"
|
||||
dat += decode(active1.fields["notes"])
|
||||
dat += "<BR><BR><BR>"
|
||||
var/counter = 1
|
||||
while(src.active1.fields[text("com_[]", counter)])
|
||||
dat += text("[]<BR><A href='?src=\ref[];choice=del_c;del_c=[]'>Delete Entry</A><BR><BR>", src.active1.fields[text("com_[]", counter)], src, counter)
|
||||
counter++
|
||||
dat += "<A href='?src=\ref[src];choice=add_c'>Add Entry</A><BR><BR></td>"
|
||||
|
||||
dat += "<td align = center valign = top>Photo:<br><img src=front.png height=80 width=80 border=4>"
|
||||
dat += "<img src=side.png height=80 width=80 border=4></td></tr></table>"
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
dat += text("\n<A href='?src=\ref[];choice=Delete Record (ALL)'>Delete Record (ALL)</A><BR><BR>\n<A href='?src=\ref[];choice=Print Record'>Print Record</A><BR>\n<A href='?src=\ref[];choice=Return'>Back</A><BR>", src, src, src)
|
||||
@@ -285,6 +294,25 @@ What a mess.*/
|
||||
P.name = "Employment Record (Unknown/Invald Entry)"
|
||||
log_debug("[usr] ([usr.ckey]) attempted to print a null employee record, this should be investigated.")
|
||||
printing = null
|
||||
// Add comment
|
||||
if ("add_c")
|
||||
if (!( istype(src.active1, /datum/data/record) ))
|
||||
return
|
||||
var/a1 = src.active1
|
||||
var/t1 = sanitize(input("Add Comment:", "Emp. records", null, null) as message)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
var/counter = 1
|
||||
while(src.active1.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active1.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [game_year]<BR>[t1]")
|
||||
// Delete comment
|
||||
if ("del_c")
|
||||
var/target = href_list["del_c"]
|
||||
if (istype(src.active1, /datum/data/record) && src.active1.fields["com_[target]"])
|
||||
src.active1.fields["com_[target]"] = "<B>Deleted</B>"
|
||||
|
||||
|
||||
//RECORD DELETE
|
||||
if ("Delete All Records")
|
||||
temp = ""
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.transmission_method = TRANSMISSION_RADIO
|
||||
status_signal.data["command"] = command
|
||||
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
@@ -219,6 +219,7 @@
|
||||
var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward."
|
||||
var/on_store_visible_message_1 = "hums and hisses as it moves" //We need two variables because byond doesn't let us have variables inside strings at compile-time.
|
||||
var/on_store_visible_message_2 = "into storage."
|
||||
var/announce_channel = "Common"
|
||||
var/allow_occupant_types = list(/mob/living/carbon/human)
|
||||
var/disallow_occupant_types = list()
|
||||
|
||||
@@ -519,7 +520,7 @@
|
||||
control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]"
|
||||
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
|
||||
|
||||
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]")
|
||||
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE))
|
||||
//visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3)
|
||||
visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].</span>", 3)
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ obj/machinery/door/airlock/proc/command_completed(var/command)
|
||||
obj/machinery/door/airlock/proc/send_status(var/bumped = 0)
|
||||
if(radio_connection)
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.data["tag"] = id_tag
|
||||
signal.data["timestamp"] = world.time
|
||||
|
||||
@@ -172,7 +172,7 @@ obj/machinery/airlock_sensor/update_icon()
|
||||
|
||||
obj/machinery/airlock_sensor/attack_hand(mob/user)
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.data["tag"] = master_tag
|
||||
signal.data["command"] = command
|
||||
|
||||
@@ -186,7 +186,7 @@ obj/machinery/airlock_sensor/process()
|
||||
|
||||
if(abs(pressure - previousPressure) > 0.001 || previousPressure == null)
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.data["tag"] = id_tag
|
||||
signal.data["timestamp"] = world.time
|
||||
signal.data["pressure"] = num2text(pressure)
|
||||
@@ -263,7 +263,7 @@ obj/machinery/access_button/attack_hand(mob/user)
|
||||
|
||||
else if(radio_connection)
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.transmission_method = TRANSMISSION_RADIO //radio signal
|
||||
signal.data["tag"] = master_tag
|
||||
signal.data["command"] = command
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
src.density = 1
|
||||
update_nearby_tiles()
|
||||
src.update_icon()
|
||||
src.set_opacity(initial(opacity))
|
||||
src.set_opacity(1)
|
||||
sleep(15)
|
||||
src.operating = 0
|
||||
|
||||
@@ -244,8 +244,7 @@
|
||||
force_open()
|
||||
|
||||
if(autoclose && src.operating && !(stat & BROKEN || stat & NOPOWER))
|
||||
spawn(150)
|
||||
close()
|
||||
addtimer(CALLBACK(src, .proc/close, 15 SECONDS))
|
||||
return 1
|
||||
|
||||
// Proc: close()
|
||||
|
||||
@@ -290,6 +290,7 @@
|
||||
FA.anchored = 1
|
||||
FA.density = 1
|
||||
FA.wired = 1
|
||||
FA.glass = glass
|
||||
FA.update_icon()
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user