diff --git a/.travis.yml b/.travis.yml
index c58b11584f..754b84c374 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,8 +4,8 @@ sudo: false
env:
global:
- - BYOND_MAJOR="511"
- - BYOND_MINOR="1381"
+ - BYOND_MAJOR="512"
+ - BYOND_MINOR="1414"
- MACRO_COUNT=4
matrix:
- TEST_DEFINE="MAP_TEST" TEST_FILE="code/_map_tests.dm" RUN="0"
diff --git a/README.md b/README.md
index ea59760d95..49de2b6eaf 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# polaris
-[Forums](http://ss13polaris.com/forums/) - [Wiki](http://ss13polaris.com/wiki/doku.php)
+[Forums](https://forum.ss13polaris.com/) - [Wiki](http://wiki.ss13polaris.com/)
Polaris is a fork of the Baystation12 code branch for the game Spacestation13.
diff --git a/code/ATMOSPHERICS/_atmos_setup.dm b/code/ATMOSPHERICS/_atmos_setup.dm
index b8c3e91150..09bb291180 100644
--- a/code/ATMOSPHERICS/_atmos_setup.dm
+++ b/code/ATMOSPHERICS/_atmos_setup.dm
@@ -15,11 +15,6 @@
#define PIPE_COLOR_BLACK "#444444"
#define PIPE_COLOR_PURPLE "#5c1ec0"
-#define CONNECT_TYPE_REGULAR 1
-#define CONNECT_TYPE_SUPPLY 2
-#define CONNECT_TYPE_SCRUBBER 4
-#define CONNECT_TYPE_HE 8
-
var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "black" = PIPE_COLOR_BLACK, "purple" = PIPE_COLOR_PURPLE)
/proc/pipe_color_lookup(var/color)
diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm
index 6fc2b923dd..b5cd6486b9 100644
--- a/code/ATMOSPHERICS/_atmospherics_helpers.dm
+++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm
@@ -455,3 +455,40 @@
var/sink_pressure = sink.return_pressure()
return (source_pressure - sink_pressure)/(R_IDEAL_GAS_EQUATION * (source.temperature/source_volume + sink.temperature/sink_volume))
+
+//
+// Debugging helper procs
+//
+
+/proc/atmos_piping_layer_str(piping_layer)
+ switch(piping_layer)
+ if(PIPING_LAYER_SUPPLY)
+ return "SUPPLY"
+ if(PIPING_LAYER_REGULAR)
+ return "REGULAR"
+ if(PIPING_LAYER_SCRUBBER)
+ return "SCRUBBER"
+
+/proc/atmos_pipe_flags_str(pipe_flags)
+ var/list/dat = list()
+ if(pipe_flags & PIPING_ALL_LAYER)
+ dat += "ALL_LAYER"
+ if(pipe_flags & PIPING_ONE_PER_TURF)
+ dat += "ONE_PER_TURF"
+ if(pipe_flags & PIPING_DEFAULT_LAYER_ONLY)
+ dat += "DEFAULT_LAYER_ONLY"
+ if(pipe_flags & PIPING_CARDINAL_AUTONORMALIZE)
+ dat += "CARDINAL_AUTONORMALIZE"
+ return dat.Join("|")
+
+/proc/atmos_connect_types_str(connect_types)
+ var/list/dat = list()
+ if(connect_types & CONNECT_TYPE_REGULAR)
+ dat += "REGULAR"
+ if(connect_types & CONNECT_TYPE_SUPPLY)
+ dat += "SUPPLY"
+ if(connect_types & CONNECT_TYPE_SCRUBBER)
+ dat += "SCRUBBER"
+ if(connect_types & CONNECT_TYPE_HE)
+ dat += "HE"
+ return dat.Join("|")
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 0502f2b8f8..8d3aa08493 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -17,10 +17,15 @@ Pipelines + Other Objects -> Pipe network
var/nodealert = 0
var/power_rating //the maximum amount of power the machine can use to do work, affects how powerful the machine is, in Watts
- layer = 2.4 //under wires with their 2.44
+ layer = PIPES_LAYER
+ plane = PLATING_PLANE
+ var/pipe_flags = PIPING_DEFAULT_LAYER_ONLY // Allow other layers by exception basis.
var/connect_types = CONNECT_TYPE_REGULAR
+ var/piping_layer = PIPING_LAYER_DEFAULT // This will replace icon_connect_type at some point ~Leshana
var/icon_connect_type = "" //"-supply" or "-scrubbers"
+ var/construction_type = null // Type path of the pipe item when this is deconstructed.
+ var/pipe_state // icon_state as a pipe item
var/initialize_directions = 0
var/pipe_color
@@ -29,11 +34,12 @@ Pipelines + Other Objects -> Pipe network
var/obj/machinery/atmospherics/node1
var/obj/machinery/atmospherics/node2
-/obj/machinery/atmospherics/New()
+/obj/machinery/atmospherics/New(loc, newdir)
..()
if(!icon_manager)
icon_manager = new()
-
+ if(!isnull(newdir))
+ set_dir(newdir)
if(!pipe_color)
pipe_color = color
color = null
@@ -46,6 +52,15 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/init_dir()
return
+// Get ALL initialize_directions - Some types (HE pipes etc) combine two vars together for this.
+/obj/machinery/atmospherics/proc/get_init_dirs()
+ return initialize_directions
+
+// Get the direction each node is facing to connect.
+// It now returns as a list so it can be fetched nicely, each entry corresponds to node of same number.
+/obj/machinery/atmospherics/proc/get_node_connect_dirs()
+ return
+
// Initializes nodes by looking at neighboring atmospherics machinery to connect to.
// When we're being constructed at runtime, atmos_init() is called by the construction code.
// When dynamically loading a map atmos_init is called by the maploader (initTemplateBounds proc)
@@ -54,6 +69,14 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/atmos_init()
return
+/** Check if target is an acceptable target to connect as a node from this machine. */
+/obj/machinery/atmospherics/proc/can_be_node(obj/machinery/atmospherics/target, node_num)
+ return (target.initialize_directions & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src)
+
+/** Check if this machine is willing to connect with the target machine. */
+/obj/machinery/atmospherics/proc/check_connectable(obj/machinery/atmospherics/target)
+ return (src.connect_types & target.connect_types)
+
/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
if(istype(A, /obj/item/device/pipe_painter))
return
@@ -77,12 +100,6 @@ Pipelines + Other Objects -> Pipe network
else
return 0
-obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/atmos1, obj/machinery/atmospherics/atmos2)
- return (atmos1.connect_types & atmos2.connect_types)
-
-/obj/machinery/atmospherics/proc/check_connect_types_construction(obj/machinery/atmospherics/atmos1, obj/item/pipe/pipe2)
- return (atmos1.connect_types & pipe2.connect_types)
-
/obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0)
if(!istype(icon_manager))
if(!safety) //to prevent infinite loops
@@ -141,4 +158,60 @@ obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/a
var/datum/gas_mixture/env_air = loc.return_air()
if((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
return 0
- return 1
\ No newline at end of file
+ return 1
+
+// Deconstruct into a pipe item.
+/obj/machinery/atmospherics/proc/deconstruct()
+ if(QDELETED(src))
+ return
+ if(construction_type)
+ var/obj/item/pipe/I = new construction_type(loc, null, null, src)
+ I.setPipingLayer(piping_layer)
+ transfer_fingerprints_to(I)
+ qdel(src)
+
+// Return a list of nodes which we should call atmos_init() and build_network() during on_construction()
+/obj/machinery/atmospherics/proc/get_neighbor_nodes_for_init()
+ return null
+
+// Called on construction (i.e from pipe item) but not on initialization
+/obj/machinery/atmospherics/proc/on_construction(obj_color, set_layer)
+ pipe_color = obj_color
+ setPipingLayer(set_layer)
+ // TODO - M.connect_types = src.connect_types - Or otherwise copy from item? Or figure it out from piping layer?
+ var/turf/T = get_turf(src)
+ level = !T.is_plating() ? 2 : 1
+ atmos_init()
+ if(QDELETED(src))
+ return // TODO - Eventually should get rid of the need for this.
+ build_network()
+ var/list/nodes = get_neighbor_nodes_for_init()
+ for(var/obj/machinery/atmospherics/A in nodes)
+ A.atmos_init()
+ A.build_network()
+ // TODO - Should we do src.build_network() before or after the nodes?
+ // We've historically done before, but /tg does after. TODO research if there is a difference.
+
+// This sets our piping layer. Hopefully its cool.
+/obj/machinery/atmospherics/proc/setPipingLayer(new_layer)
+ if(pipe_flags & (PIPING_DEFAULT_LAYER_ONLY|PIPING_ALL_LAYER))
+ new_layer = PIPING_LAYER_DEFAULT
+ piping_layer = new_layer
+ // Do it the Polaris way
+ switch(piping_layer)
+ if(PIPING_LAYER_SCRUBBER)
+ icon_state = "[icon_state]-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ if(PIPING_LAYER_SUPPLY)
+ icon_state = "[icon_state]-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ if(pipe_flags & PIPING_ALL_LAYER)
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
+ // 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)
+ // layer = initial(layer) + PIPE_LAYER_OFFSET(piping_layer)
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index 6e6662f39c..4698c613a9 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -30,6 +30,9 @@
initialize_directions = EAST|WEST
// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/binary/get_neighbor_nodes_for_init()
+ return list(node1, node2)
+
/obj/machinery/atmospherics/binary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
network1 = new_network
@@ -64,17 +67,8 @@
var/node2_connect = dir
var/node1_connect = turn(dir, 180)
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
+ STANDARD_ATMOS_CHOOSE_NODE(1, node1_connect)
+ STANDARD_ATMOS_CHOOSE_NODE(2, node2_connect)
update_icon()
update_underlays()
diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
index 68ce37d088..ff1089e6f8 100644
--- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
@@ -9,6 +9,7 @@
icon = 'icons/obj/pipes.dmi'
icon_state = "circ-off"
anchored = 0
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
var/kinetic_efficiency = 0.04 //combined kinetic and kinetic-to-electric efficiency
var/volume_ratio = 0.2
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 840d2bdf8b..d696aad039 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -24,6 +24,7 @@
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
+ pipe_flags = PIPING_ALL_LAYER
connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER //connects to regular, supply and scrubbers pipes
var/pump_direction = 1 //0 = siphoning, 1 = releasing
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index b4f25459c1..c08c82f6b9 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -5,6 +5,8 @@
/obj/machinery/atmospherics/binary/passive_gate
icon = 'icons/atmos/passive_gate.dmi'
icon_state = "map"
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "passivegate"
level = 1
name = "pressure regulator"
@@ -257,8 +259,7 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
#undef REGULATE_NONE
#undef REGULATE_INPUT
diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
index b8c7883796..a7127a4dc6 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
@@ -139,6 +139,9 @@
src.set_dir(turn(src.dir, 90))
//Goddamn copypaste from binary base class because atmospherics machinery API is not damn flexible
+ get_neighbor_nodes_for_init()
+ return list(node1, node2)
+
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
network1 = new_network
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index 6320ddf8a3..a89b1c5659 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -15,6 +15,8 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/binary/pump
icon = 'icons/atmos/pump.dmi'
icon_state = "map_off"
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "pump"
level = 1
name = "gas pump"
@@ -236,5 +238,4 @@ Thus, the two variables affect pump operation are set in New():
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
index 42b02282cc..b4493a1566 100644
--- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/binary/pump/high_power
icon = 'icons/atmos/volume_pump.dmi'
icon_state = "map_off"
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "volumepump"
level = 1
name = "high power gas pump"
diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm
index 8710623dfd..57889c463e 100644
--- a/code/ATMOSPHERICS/components/omni_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm
@@ -4,6 +4,7 @@
/obj/machinery/atmospherics/omni/atmos_filter
name = "omni gas filter"
icon_state = "map_filter"
+ pipe_state = "omni_filter"
var/list/atmos_filters = new()
var/datum/omni_port/input
diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
index 6340397870..c833b5bb2a 100644
--- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
@@ -4,6 +4,7 @@
/obj/machinery/atmospherics/omni/mixer
name = "omni gas mixer"
icon_state = "map_mixer"
+ pipe_state = "omni_mixer"
use_power = 1
idle_power_usage = 150 //internal circuitry, friction losses and stuff
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index 7416a5bfc4..e7ec93852d 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -7,6 +7,7 @@
icon_state = "base"
use_power = 1
initialize_directions = 0
+ construction_type = /obj/item/pipe/quaternary
level = 1
var/configuring = 0
@@ -93,8 +94,7 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
/obj/machinery/atmospherics/omni/can_unwrench()
var/int_pressure = 0
@@ -222,6 +222,11 @@
// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/omni/get_neighbor_nodes_for_init()
+ var/list/neighbor_nodes = list()
+ for(var/datum/omni_port/P in ports)
+ neighbor_nodes += P.node
+ return neighbor_nodes
/obj/machinery/atmospherics/omni/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
for(var/datum/omni_port/P in ports)
@@ -252,10 +257,9 @@
if(P.node || P.mode == 0)
continue
for(var/obj/machinery/atmospherics/target in get_step(src, P.dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- P.node = target
- break
+ if(can_be_node(target, 1))
+ P.node = target
+ break
for(var/datum/omni_port/P in ports)
P.update = 1
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index 6911288c93..7dca3f52d4 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -7,6 +7,9 @@
dir = SOUTH
initialize_directions = SOUTH
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "connector"
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
var/obj/machinery/portable_atmospherics/connected_device
@@ -47,6 +50,9 @@
return 1
// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/portables_connector/get_neighbor_nodes_for_init()
+ return list(node)
+
/obj/machinery/atmospherics/portables_connector/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node)
network = new_network
@@ -77,10 +83,9 @@
var/node_connect = dir
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
+ if(can_be_node(target, 1))
+ node = target
+ break
update_icon()
update_underlays()
@@ -146,5 +151,4 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 10708f4185..49cb05e9af 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/trinary/atmos_filter
icon = 'icons/atmos/filter.dmi'
icon_state = "map"
+ construction_type = /obj/item/pipe/trinary/flippable
+ pipe_state = "filter"
density = 0
level = 1
@@ -59,7 +61,7 @@
. = ..()
/obj/machinery/atmospherics/trinary/atmos_filter/update_icon()
- if(istype(src, /obj/machinery/atmospherics/trinary/atmos_filter/m_filter))
+ if(mirrored)
icon_state = "m"
else
icon_state = ""
@@ -72,31 +74,6 @@
icon_state += "off"
use_power = 0
-/obj/machinery/atmospherics/trinary/atmos_filter/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- add_underlay(T, node1, turn(dir, -180))
-
- if(istype(src, /obj/machinery/atmospherics/trinary/atmos_filter/m_filter))
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
-
-/obj/machinery/atmospherics/trinary/atmos_filter/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/trinary/atmos_filter/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
/obj/machinery/atmospherics/trinary/atmos_filter/process()
..()
@@ -133,24 +110,6 @@
if(frequency)
set_frequency(frequency)
-/obj/machinery/atmospherics/trinary/atmos_filter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!istype(W, /obj/item/weapon/wrench))
- return ..()
- if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40 * W.toolspeed))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
-
/obj/machinery/atmospherics/trinary/atmos_filter/attack_hand(user as mob) // -- TLE
if(..())
return
@@ -235,44 +194,11 @@
*/
return
+//
+// Mirrored Orientation - Flips the output dir to opposite side from normal.
+//
/obj/machinery/atmospherics/trinary/atmos_filter/m_filter
icon_state = "mmap"
-
dir = SOUTH
initialize_directions = SOUTH|NORTH|EAST
-
-obj/machinery/atmospherics/trinary/atmos_filter/m_filter/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = WEST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|EAST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|NORTH
- if(WEST)
- initialize_directions = WEST|SOUTH|EAST
-
-/obj/machinery/atmospherics/trinary/atmos_filter/m_filter/atmos_init()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
+ mirrored = TRUE
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index 5739a57895..84c5d49daa 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/trinary/mixer
icon = 'icons/atmos/mixer.dmi'
icon_state = "map"
+ construction_type = /obj/item/pipe/trinary/flippable
+ pipe_state = "mixer"
density = 0
level = 1
@@ -20,10 +22,10 @@
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/trinary/mixer/update_icon(var/safety = 0)
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer))
- icon_state = "m"
- else if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
+ if(tee)
icon_state = "t"
+ else if(mirrored)
+ icon_state = "m"
else
icon_state = ""
@@ -35,34 +37,6 @@
icon_state += "off"
use_power = 0
-/obj/machinery/atmospherics/trinary/mixer/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
-
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- add_underlay(T, node1, turn(dir, -90))
- else
- add_underlay(T, node1, turn(dir, -180))
-
- if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer) || istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
-
-/obj/machinery/atmospherics/trinary/mixer/hide(var/i)
- update_underlays()
-
-/obj/machinery/atmospherics/trinary/mixer/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
/obj/machinery/atmospherics/trinary/mixer/New()
..()
air1.volume = ATMOS_DEFAULT_VOLUME_MIXER
@@ -103,23 +77,6 @@
return 1
-/obj/machinery/atmospherics/trinary/mixer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (!istype(W, /obj/item/weapon/wrench))
- return ..()
- if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40 * W.toolspeed))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
-
/obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob)
if(..())
return
@@ -173,92 +130,22 @@
src.updateUsrDialog()
return
+//
+// "T" Orientation - Inputs are on oposite sides instead of adjacent
+//
obj/machinery/atmospherics/trinary/mixer/t_mixer
icon_state = "tmap"
-
+ construction_type = /obj/item/pipe/trinary // Can't flip a "T", its symmetrical
+ pipe_state = "t_mixer"
dir = SOUTH
initialize_directions = SOUTH|EAST|WEST
+ tee = TRUE
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|NORTH|WEST
- if(SOUTH)
- initialize_directions = SOUTH|WEST|EAST
- if(EAST)
- initialize_directions = EAST|NORTH|SOUTH
- if(WEST)
- initialize_directions = WEST|NORTH|SOUTH
-
-obj/machinery/atmospherics/trinary/mixer/t_mixer/atmos_init()
- ..()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -90)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer
+//
+// Mirrored Orientation - Flips the output dir to opposite side from normal.
+//
+/obj/machinery/atmospherics/trinary/mixer/m_mixer
icon_state = "mmap"
-
dir = SOUTH
initialize_directions = SOUTH|NORTH|EAST
-
- //node 3 is the outlet, nodes 1 & 2 are intakes
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = WEST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|EAST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|NORTH
- if(WEST)
- initialize_directions = WEST|SOUTH|EAST
-
-obj/machinery/atmospherics/trinary/mixer/m_mixer/atmos_init()
- ..()
- if(node1 && node2 && node3) return
-
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, 90)
- var/node3_connect = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
+ mirrored = TRUE
diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
index 807523fe7a..0a68f74c71 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
@@ -2,6 +2,10 @@
dir = SOUTH
initialize_directions = SOUTH|NORTH|WEST
use_power = 0
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
+
+ var/mirrored = FALSE
+ var/tee = FALSE
var/datum/gas_mixture/air1
var/datum/gas_mixture/air2
@@ -25,17 +29,48 @@
air3.volume = 200
/obj/machinery/atmospherics/trinary/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|NORTH|SOUTH
- if(SOUTH)
- initialize_directions = SOUTH|WEST|NORTH
- if(EAST)
- initialize_directions = EAST|WEST|SOUTH
- if(WEST)
- initialize_directions = WEST|NORTH|EAST
+ initialize_directions = get_initialize_directions_trinary(dir, mirrored, tee)
+
+/obj/machinery/atmospherics/trinary/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ var/list/node_connects = get_node_connect_dirs()
+ add_underlay(T, node1, node_connects[1])
+ add_underlay(T, node2, node_connects[2])
+ add_underlay(T, node3, node_connects[3])
+
+/obj/machinery/atmospherics/trinary/hide(var/i)
+ update_underlays()
+
+/obj/machinery/atmospherics/trinary/power_change()
+ var/old_stat = stat
+ . = ..()
+ if(old_stat != stat)
+ update_icon()
+
+/obj/machinery/atmospherics/trinary/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ if (!istype(W, /obj/item/weapon/wrench))
+ return ..()
+ if(!can_unwrench())
+ to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40 * W.toolspeed))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ deconstruct()
// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/trinary/get_neighbor_nodes_for_init()
+ return list(node1, node2, node3)
+
/obj/machinery/atmospherics/trinary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
network1 = new_network
@@ -70,30 +105,20 @@
node2 = null
node3 = null
+// Get the direction each node is facing to connect.
+// It now returns as a list so it can be fetched nicely, each entry corresponds to node of same number.
+/obj/machinery/atmospherics/trinary/get_node_connect_dirs()
+ return get_node_connect_dirs_trinary(dir, mirrored, tee)
+
/obj/machinery/atmospherics/trinary/atmos_init()
if(node1 && node2 && node3)
return
- var/node1_connect = turn(dir, -180)
- var/node2_connect = turn(dir, -90)
- var/node3_connect = dir
+ var/list/node_connects = get_node_connect_dirs()
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node3 = target
- break
+ STANDARD_ATMOS_CHOOSE_NODE(1, node_connects[1])
+ STANDARD_ATMOS_CHOOSE_NODE(2, node_connects[2])
+ STANDARD_ATMOS_CHOOSE_NODE(3, node_connects[3])
update_icon()
update_underlays()
@@ -166,4 +191,58 @@
update_underlays()
- return null
\ No newline at end of file
+ return null
+
+// Trinary init_dir() logic in a separate proc so it can be referenced from "trinary-ish" places like T-Valves
+// TODO - Someday refactor those places under atmospherics/trinary
+/proc/get_initialize_directions_trinary(var/dir, var/mirrored = FALSE, var/tee = FALSE)
+ if(tee)
+ switch(dir)
+ if(NORTH)
+ return EAST|NORTH|WEST
+ if(SOUTH)
+ return SOUTH|WEST|EAST
+ if(EAST)
+ return EAST|NORTH|SOUTH
+ if(WEST)
+ return WEST|NORTH|SOUTH
+ else if(mirrored)
+ switch(dir)
+ if(NORTH)
+ return WEST|NORTH|SOUTH
+ if(SOUTH)
+ return SOUTH|EAST|NORTH
+ if(EAST)
+ return EAST|WEST|NORTH
+ if(WEST)
+ return WEST|SOUTH|EAST
+ else
+ switch(dir)
+ if(NORTH)
+ return EAST|NORTH|SOUTH
+ if(SOUTH)
+ return SOUTH|WEST|NORTH
+ if(EAST)
+ return EAST|WEST|SOUTH
+ if(WEST)
+ return WEST|NORTH|EAST
+
+// Trinary get_node_connect_dirs() logic in a separate proc so it can be referenced from "trinary-ish" places like T-Valves
+/proc/get_node_connect_dirs_trinary(var/dir, var/mirrored = FALSE, var/tee = FALSE)
+ var/node1_connect
+ var/node2_connect
+ var/node3_connect
+
+ if(tee)
+ node1_connect = turn(dir, -90)
+ node2_connect = turn(dir, 90)
+ node3_connect = dir
+ else if(mirrored)
+ node1_connect = turn(dir, 180)
+ node2_connect = turn(dir, 90)
+ node3_connect = dir
+ else
+ node1_connect = turn(dir, 180)
+ node2_connect = turn(dir, -90)
+ node3_connect = dir
+ return list(node1_connect, node2_connect, node3_connect)
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm
index 9f7e80f97f..b65c615174 100644
--- a/code/ATMOSPHERICS/components/tvalve.dm
+++ b/code/ATMOSPHERICS/components/tvalve.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/tvalve
icon = 'icons/atmos/tvalve.dmi'
icon_state = "map_tvalve0"
+ construction_type = /obj/item/pipe/trinary/flippable
+ pipe_state = "mtvalve"
name = "manual switching valve"
desc = "A pipe valve"
@@ -11,6 +13,9 @@
var/state = 0 // 0 = go straight, 1 = go to side
+ var/mirrored = FALSE
+ var/tee = FALSE // Note: Tee not actually supported for T-valves: no sprites
+
// like a trinary component, node1 is input, node2 is side output, node3 is straight output
var/obj/machinery/atmospherics/node3
@@ -24,9 +29,9 @@
/obj/machinery/atmospherics/tvalve/update_icon(animation)
if(animation)
- flick("tvalve[src.state][!src.state]",src)
+ flick("tvalve[mirrored ? "m" : ""][src.state][!src.state]",src)
else
- icon_state = "tvalve[state]"
+ icon_state = "tvalve[mirrored ? "m" : ""][state]"
/obj/machinery/atmospherics/tvalve/update_underlays()
if(..())
@@ -34,28 +39,19 @@
var/turf/T = get_turf(src)
if(!istype(T))
return
- add_underlay(T, node1, turn(dir, -180))
-
- if(istype(src, /obj/machinery/atmospherics/tvalve/mirrored))
- add_underlay(T, node2, turn(dir, 90))
- else
- add_underlay(T, node2, turn(dir, -90))
-
- add_underlay(T, node3, dir)
+ var/list/node_connects = get_node_connect_dirs()
+ add_underlay(T, node1, node_connects[1])
+ add_underlay(T, node2, node_connects[2])
+ add_underlay(T, node3, node_connects[3])
/obj/machinery/atmospherics/tvalve/hide(var/i)
update_underlays()
/obj/machinery/atmospherics/tvalve/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = SOUTH|NORTH|EAST
- if(SOUTH)
- initialize_directions = NORTH|SOUTH|WEST
- if(EAST)
- initialize_directions = WEST|EAST|SOUTH
- if(WEST)
- initialize_directions = EAST|WEST|NORTH
+ initialize_directions = get_initialize_directions_trinary(dir, mirrored)
+
+/obj/machinery/atmospherics/tvalve/get_neighbor_nodes_for_init()
+ return list(node1, node2, node3)
/obj/machinery/atmospherics/tvalve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
@@ -179,30 +175,18 @@
return
+/obj/machinery/atmospherics/tvalve/get_node_connect_dirs()
+ return get_node_connect_dirs_trinary(dir, mirrored)
+
/obj/machinery/atmospherics/tvalve/atmos_init()
- var/node1_dir
- var/node2_dir
- var/node3_dir
+ if(node1 && node2 && node3)
+ return
- node1_dir = turn(dir, 180)
- node2_dir = turn(dir, -90)
- node3_dir = dir
+ var/list/node_connects = get_node_connect_dirs()
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node3 = target
- break
+ STANDARD_ATMOS_CHOOSE_NODE(1, node_connects[1])
+ STANDARD_ATMOS_CHOOSE_NODE(2, node_connects[2])
+ STANDARD_ATMOS_CHOOSE_NODE(3, node_connects[3])
update_icon()
update_underlays()
@@ -272,6 +256,7 @@
name = "digital switching valve"
desc = "A digitally controlled valve."
icon = 'icons/atmos/digital_tvalve.dmi'
+ pipe_state = "dtvalve"
var/frequency = 0
var/id = null
@@ -294,7 +279,7 @@
/obj/machinery/atmospherics/tvalve/digital/update_icon()
..()
if(!powered())
- icon_state = "tvalvenopower"
+ icon_state = "tvalve[mirrored ? "m" : ""]nopower"
/obj/machinery/atmospherics/tvalve/digital/attack_ai(mob/user as mob)
return src.attack_hand(user)
@@ -358,125 +343,20 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
/obj/machinery/atmospherics/tvalve/mirrored
icon_state = "map_tvalvem0"
+ mirrored = TRUE
/obj/machinery/atmospherics/tvalve/mirrored/bypass
icon_state = "map_tvalvem1"
state = 1
-/obj/machinery/atmospherics/tvalve/mirrored/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = SOUTH|NORTH|WEST
- if(SOUTH)
- initialize_directions = NORTH|SOUTH|EAST
- if(EAST)
- initialize_directions = WEST|EAST|NORTH
- if(WEST)
- initialize_directions = EAST|WEST|SOUTH
+/obj/machinery/atmospherics/tvalve/digital/mirrored
+ icon_state = "map_tvalvem0"
+ mirrored = TRUE
-/obj/machinery/atmospherics/tvalve/mirrored/atmos_init()
- var/node1_dir
- var/node2_dir
- var/node3_dir
-
- node1_dir = turn(dir, 180)
- node2_dir = turn(dir, 90)
- node3_dir = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- node2 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- update_icon()
- update_underlays()
-
-/obj/machinery/atmospherics/tvalve/mirrored/update_icon(animation)
- if(animation)
- flick("tvalvem[src.state][!src.state]",src)
- else
- icon_state = "tvalvem[state]"
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital // can be controlled by AI
- name = "digital switching valve"
- desc = "A digitally controlled valve."
- icon = 'icons/atmos/digital_tvalve.dmi'
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/Destroy()
- unregister_radio(src, frequency)
- . = ..()
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/bypass
+/obj/machinery/atmospherics/tvalve/digital/mirrored/bypass
icon_state = "map_tvalvem1"
state = 1
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/power_change()
- var/old_stat = stat
- ..()
- if(old_stat != stat)
- update_icon()
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/update_icon()
- ..()
- if(!powered())
- icon_state = "tvalvemnopower"
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/attack_hand(mob/user as mob)
- if(!powered())
- return
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- ..()
-
-//Radio remote control -eh?
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
-/obj/machinery/atmospherics/tvalve/mirrored/digital/receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id))
- return 0
-
- switch(signal.data["command"])
- if("valve_open")
- if(!state)
- go_to_side()
-
- if("valve_close")
- if(state)
- go_straight()
-
- if("valve_toggle")
- if(state)
- go_straight()
- else
- go_to_side()
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index 36ae824fa7..b211f57f39 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -38,18 +38,15 @@
var/node_connect = dir
for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
- if(target.initialize_directions & get_dir(target, src))
+ if(can_be_node(target, 1))
node = target
break
- //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
- //check that there are no incompatible pipes/machinery in our own location
- for(var/obj/machinery/atmospherics/M in src.loc)
- if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
- node = null
- break
+ if(check_for_obstacles())
+ node = null
- update_icon()
+ if(node)
+ update_icon()
/obj/machinery/atmospherics/unary/freezer/update_icon()
if(node)
diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
index 8a7fba153a..ed4010f81e 100644
--- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
@@ -2,6 +2,7 @@
icon = 'icons/obj/atmospherics/heat_exchanger.dmi'
icon_state = "intact"
+ pipe_state = "heunary"
density = 1
name = "Heat Exchanger"
@@ -83,5 +84,4 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index 8ca4626ee6..45a9962e06 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -39,18 +39,15 @@
//check that there is something to connect to
for(var/obj/machinery/atmospherics/target in get_step(src, node_connect))
- if(target.initialize_directions & get_dir(target, src))
+ if(can_be_node(target, 1))
node = target
break
- //copied from pipe construction code since heaters/freezers don't use fittings and weren't doing this check - this all really really needs to be refactored someday.
- //check that there are no incompatible pipes/machinery in our own location
- for(var/obj/machinery/atmospherics/M in src.loc)
- if(M != src && (M.initialize_directions & node_connect) && M.check_connect_types(M,src)) // matches at least one direction on either type of pipe & same connection type
- node = null
- break
+ if(check_for_obstacles())
+ node = null
- update_icon()
+ if(node)
+ update_icon()
/obj/machinery/atmospherics/unary/heater/update_icon()
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index 7c52cea895..4a9403a64b 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -5,7 +5,7 @@
/obj/machinery/atmospherics/unary/outlet_injector
icon = 'icons/atmos/injector.dmi'
icon_state = "map_injector"
- layer = 3
+ pipe_state = "injector"
name = "air injector"
desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm
index 77b135cdc5..12d6822ad4 100644
--- a/code/ATMOSPHERICS/components/unary/unary_base.dm
+++ b/code/ATMOSPHERICS/components/unary/unary_base.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/unary
dir = SOUTH
initialize_directions = SOUTH
+ construction_type = /obj/item/pipe/directional
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
//layer = TURF_LAYER+0.1
var/datum/gas_mixture/air_contents
@@ -21,6 +23,9 @@
initialize_directions = dir
// Housekeeping and pipe network stuff below
+/obj/machinery/atmospherics/unary/get_neighbor_nodes_for_init()
+ return list(node)
+
/obj/machinery/atmospherics/unary/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node)
network = new_network
@@ -48,10 +53,9 @@
var/node_connect = dir
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
+ if(can_be_node(target, 1))
+ node = target
+ break
update_icon()
update_underlays()
@@ -93,4 +97,20 @@
update_icon()
update_underlays()
- return null
\ No newline at end of file
+ return null
+
+// Check if there are any other atmos machines in the same turf that will block this machine from initializing.
+// Intended for use when a frame-constructable machine (i.e. not made from pipe fittings) wants to wrench down and connect.
+// Returns TRUE if something is blocking, FALSE if its okay to continue.
+/obj/machinery/atmospherics/unary/proc/check_for_obstacles()
+ for(var/obj/machinery/atmospherics/M in loc)
+ if(M == src) continue
+ if((M.pipe_flags & pipe_flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
+ visible_message("\The [src]'s cannot be connected, something is hogging the tile!")
+ return TRUE
+ if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) // Pipes on different layers can't block each other unless they are ALL_LAYER
+ continue
+ if(M.get_init_dirs() & get_init_dirs()) // matches at least one direction on either type of pipe
+ visible_message("\The [src]'s connector can't be connected, there is already a pipe at that location!")
+ return TRUE
+ return FALSE
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index b5449fe737..054507b4e1 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -10,6 +10,7 @@
/obj/machinery/atmospherics/unary/vent_pump
icon = 'icons/atmos/vent_pump.dmi'
icon_state = "map_vent"
+ pipe_state = "uvent"
name = "Air Vent"
desc = "Has a valve and pump attached to it"
@@ -410,8 +411,7 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
#undef DEFAULT_PRESSURE_DELTA
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index ad78f5a1f4..09b5fde7c1 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -1,6 +1,7 @@
/obj/machinery/atmospherics/unary/vent_scrubber
icon = 'icons/atmos/vent_scrubber.dmi'
icon_state = "map_scrubber_off"
+ pipe_state = "scrubber"
name = "Air Scrubber"
desc = "Has a valve and pump attached to it"
@@ -283,8 +284,7 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
/obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user)
if(..(user, 1))
diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm
index 77aedf94e0..93e5da7c32 100644
--- a/code/ATMOSPHERICS/components/valve.dm
+++ b/code/ATMOSPHERICS/components/valve.dm
@@ -1,6 +1,8 @@
/obj/machinery/atmospherics/valve
icon = 'icons/atmos/valve.dmi'
icon_state = "map_valve0"
+ construction_type = /obj/item/pipe/binary
+ pipe_state = "mvalve"
name = "manual valve"
desc = "A pipe valve"
@@ -45,6 +47,9 @@
if(EAST || WEST)
initialize_directions = EAST|WEST
+/obj/machinery/atmospherics/valve/get_neighbor_nodes_for_init()
+ return list(node1, node2)
+
/obj/machinery/atmospherics/valve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
if(reference == node1)
network_node1 = new_network
@@ -153,16 +158,8 @@
else if (!node2_dir)
node2_dir = direction
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
+ STANDARD_ATMOS_CHOOSE_NODE(1, node1_dir)
+ STANDARD_ATMOS_CHOOSE_NODE(2, node2_dir)
build_network()
@@ -224,6 +221,7 @@
name = "digital valve"
desc = "A digitally controlled valve."
icon = 'icons/atmos/digital_valve.dmi'
+ pipe_state = "dvalve"
var/frequency = 0
var/id = null
@@ -306,8 +304,7 @@
"\The [user] unfastens \the [src].", \
"You have unfastened \the [src].", \
"You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- qdel(src)
+ deconstruct()
/obj/machinery/atmospherics/valve/examine(mob/user)
..()
diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm
index 1b0c617564..baba515fae 100644
--- a/code/ATMOSPHERICS/mainspipe.dm
+++ b/code/ATMOSPHERICS/mainspipe.dm
@@ -34,7 +34,8 @@ obj/machinery/atmospherics/pipe/mains_component
obj/machinery/atmospherics/mains_pipe
icon = 'icons/obj/atmospherics/mainspipe.dmi'
- layer = 2.4 //under wires with their 2.5
+ layer = PIPES_LAYER
+ plane = PLATING_PLANE
var/volume = 0
@@ -92,6 +93,9 @@ obj/machinery/atmospherics/mains_pipe
else return 1
+ get_neighbor_nodes_for_init()
+ return nodes
+
disconnect()
..()
for(var/obj/machinery/atmospherics/pipe/mains_component/node in nodes)
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
deleted file mode 100644
index d77ae5a73e..0000000000
--- a/code/ATMOSPHERICS/pipes.dm
+++ /dev/null
@@ -1,1378 +0,0 @@
-//
-// Base type of pipes
-//
-/obj/machinery/atmospherics/pipe
-
- var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke
- var/datum/pipeline/parent
- var/volume = 0
-
- layer = 2.4 //under wires with their 2.44
- use_power = 0
-
- var/alert_pressure = 80*ONE_ATMOSPHERE
- //minimum pressure before check_pressure(...) should be called
-
- can_buckle = 1
- buckle_require_restraints = 1
- buckle_lying = -1
-
-/obj/machinery/atmospherics/pipe/drain_power()
- return -1
-
-/obj/machinery/atmospherics/pipe/New()
- if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/simulated/shuttle/wall) || istype(get_turf(src), /turf/unsimulated/wall))
- level = 1
- ..()
-
-/obj/machinery/atmospherics/pipe/hides_under_flooring()
- return level != 2
-
-/obj/machinery/atmospherics/pipe/proc/pipeline_expansion()
- return null
-
-/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
- //Return 1 if parent should continue checking other pipes
- //Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null
-
- return 1
-
-/obj/machinery/atmospherics/pipe/return_air()
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.air
-
-/obj/machinery/atmospherics/pipe/build_network()
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.return_network()
-
-/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.network_expand(new_network, reference)
-
-/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference)
- if(!parent)
- parent = new /datum/pipeline()
- parent.build_pipeline(src)
-
- return parent.return_network(reference)
-
-/obj/machinery/atmospherics/pipe/Destroy()
- qdel_null(parent)
- if(air_temporary)
- loc.assume_air(air_temporary)
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- if (istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
-
- if(istype(W,/obj/item/device/pipe_painter))
- return 0
-
- if (!istype(W, /obj/item/weapon/wrench))
- return ..()
- var/turf/T = src.loc
- if (level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
- return 1
- if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
- add_fingerprint(user)
- return 1
- playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
- if (do_after(user, 40 * W.toolspeed))
- user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
- "You hear a ratchet.")
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
-
-/obj/machinery/atmospherics/pipe/proc/change_color(var/new_color)
- //only pass valid pipe colors please ~otherwise your pipe will turn invisible
- if(!pipe_color_check(new_color))
- return
-
- pipe_color = new_color
- update_icon()
-
-/obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node)
- if(istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
-
- if(istype(node, /obj/machinery/atmospherics/pipe/manifold) || istype(node, /obj/machinery/atmospherics/pipe/manifold4w))
- if(pipe_color == node.pipe_color)
- return node.pipe_color
- else
- return null
- else if(istype(node, /obj/machinery/atmospherics/pipe/simple))
- return node.pipe_color
- else
- return pipe_color
-
-/obj/machinery/atmospherics/pipe/hide(var/i)
- if(istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- update_icon()
-
-/obj/machinery/atmospherics/pipe/process()
- if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
- ..()
- else
- . = PROCESS_KILL
-
-//
-// Simple Pipes - Just a tube, maybe bent
-//
-/obj/machinery/atmospherics/pipe/simple
- icon = 'icons/atmos/pipes.dmi'
- icon_state = ""
- var/pipe_icon = "" //what kind of pipe it is and from which dmi is the icon manager getting its icons, "" for simple pipes, "hepipe" for HE pipes, "hejunction" for HE junctions
- name = "pipe"
- desc = "A one meter section of regular pipe"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE
-
- dir = SOUTH
- initialize_directions = SOUTH|NORTH
-
- var/minimum_temperature_difference = 300
- var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
-
- var/maximum_pressure = 70*ONE_ATMOSPHERE
- var/fatigue_pressure = 55*ONE_ATMOSPHERE
- alert_pressure = 55*ONE_ATMOSPHERE
-
- level = 1
-
-/obj/machinery/atmospherics/pipe/simple/New()
- ..()
-
- // Pipe colors and icon states are handled by an image cache - so color and icon should
- // be null. For mapping purposes color is defined in the object definitions.
- icon = null
- alpha = 255
-
-/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/pressure_difference = pressure - environment.return_pressure()
-
- if(pressure_difference > maximum_pressure)
- burst()
-
- else if(pressure_difference > fatigue_pressure)
- //TODO: leak to turf, doing pfshhhhh
- if(prob(5))
- burst()
-
- else return 1
-
-/obj/machinery/atmospherics/pipe/simple/init_dir()
- switch(dir)
- if(SOUTH || NORTH)
- initialize_directions = SOUTH|NORTH
- if(EAST || WEST)
- initialize_directions = EAST|WEST
- if(NORTHEAST)
- initialize_directions = NORTH|EAST
- if(NORTHWEST)
- initialize_directions = NORTH|WEST
- if(SOUTHEAST)
- initialize_directions = SOUTH|EAST
- if(SOUTHWEST)
- initialize_directions = SOUTH|WEST
-
-/obj/machinery/atmospherics/pipe/simple/proc/burst()
- src.visible_message("\The [src] bursts!");
- playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
- var/datum/effect/effect/system/smoke_spread/smoke = new
- smoke.set_up(1,0, src.loc, 0)
- smoke.start()
- qdel(src)
-
-/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
-
-/obj/machinery/atmospherics/pipe/simple/Destroy()
- if(node1)
- node1.disconnect(src)
- node1 = null
- if(node2)
- node2.disconnect(src)
- node1 = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
- return list(node1, node2)
-
-/obj/machinery/atmospherics/pipe/simple/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
-
-/obj/machinery/atmospherics/pipe/simple/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- overlays.Cut()
-
- if(!node1 && !node2)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else if(node1 && node2)
- overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]")
- else
- overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]")
-
-/obj/machinery/atmospherics/pipe/simple/update_underlays()
- return
-
-/obj/machinery/atmospherics/pipe/simple/atmos_init()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_directions)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- break
-
- if(!node1 && !node2)
- qdel(src)
- return
-
- var/turf/T = loc
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
-/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
-
- update_icon()
-
- return null
-
-/obj/machinery/atmospherics/pipe/simple/visible
- icon_state = "intact"
- level = 2
-
-/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
- name = "Scrubbers pipe"
- desc = "A one meter section of scrubbers pipe"
- icon_state = "intact-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/visible/supply
- name = "Air supply pipe"
- desc = "A one meter section of supply pipe"
- icon_state = "intact-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/simple/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/simple/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/simple/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/simple/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/visible/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/visible/purple
- color = PIPE_COLOR_PURPLE
-
-/obj/machinery/atmospherics/pipe/simple/hidden
- icon_state = "intact"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
- name = "Scrubbers pipe"
- desc = "A one meter section of scrubbers pipe"
- icon_state = "intact-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/hidden/supply
- name = "Air supply pipe"
- desc = "A one meter section of supply pipe"
- icon_state = "intact-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/simple/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/simple/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/simple/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/simple/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/simple/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/simple/hidden/purple
- color = PIPE_COLOR_PURPLE
-
-/obj/machinery/atmospherics/pipe/simple/insulated
- icon = 'icons/obj/atmospherics/red_pipe.dmi'
- icon_state = "intact"
-
- minimum_temperature_difference = 10000
- thermal_conductivity = 0
- maximum_pressure = 1000*ONE_ATMOSPHERE
- fatigue_pressure = 900*ONE_ATMOSPHERE
- alert_pressure = 900*ONE_ATMOSPHERE
-
- level = 2
-
-//
-// Manifold Pipes - Three way "T" joints
-//
-/obj/machinery/atmospherics/pipe/manifold
- icon = 'icons/atmos/manifold.dmi'
- icon_state = ""
- name = "pipe manifold"
- desc = "A manifold composed of regular pipes"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE * 1.5
-
- dir = SOUTH
- initialize_directions = EAST|NORTH|WEST
-
- var/obj/machinery/atmospherics/node3
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
-/obj/machinery/atmospherics/pipe/manifold/New()
- ..()
- alpha = 255
- icon = null
-
-/obj/machinery/atmospherics/pipe/manifold/init_dir()
- switch(dir)
- if(NORTH)
- initialize_directions = EAST|SOUTH|WEST
- if(SOUTH)
- initialize_directions = WEST|NORTH|EAST
- if(EAST)
- initialize_directions = SOUTH|WEST|NORTH
- if(WEST)
- initialize_directions = NORTH|EAST|SOUTH
-
-/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
- return list(node1, node2, node3)
-
-/obj/machinery/atmospherics/pipe/manifold/Destroy()
- if(node1)
- node1.disconnect(src)
- node1 = null
- if(node2)
- node2.disconnect(src)
- node2 = null
- if(node3)
- node3.disconnect(src)
- node3 = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
-
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node3 = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
- if(node3)
- node3.update_underlays()
-
-/obj/machinery/atmospherics/pipe/manifold/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- if(!node1 && !node2 && !node3)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else
- overlays.Cut()
- overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type)
- overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type)
- 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)
-
- 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)
-
- for(var/D in directions)
- add_underlay(T,,D,icon_connect_type)
-
-
-/obj/machinery/atmospherics/pipe/manifold/update_underlays()
- ..()
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold/atmos_init()
- var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir)
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- connect_directions &= ~direction
- break
- if (node1)
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node2 = target
- connect_directions &= ~direction
- break
- if (node2)
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/target in get_step(src,direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node3 = target
- connect_directions &= ~direction
- break
- if (node3)
- break
-
- if(!node1 && !node2 && !node3)
- qdel(src)
- return
-
- var/turf/T = get_turf(src)
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold/visible
- icon_state = "map"
- level = 2
-
-/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
- name="Scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/visible/supply
- name="Air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/visible/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/visible/purple
- color = PIPE_COLOR_PURPLE
-
-/obj/machinery/atmospherics/pipe/manifold/hidden
- icon_state = "map"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
- name="Scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/supply
- name="Air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold/hidden/purple
- color = PIPE_COLOR_PURPLE
-
-
-//
-// 4-Way Manifold Pipes - 4 way "cross" junction
-//
-/obj/machinery/atmospherics/pipe/manifold4w
- icon = 'icons/atmos/manifold.dmi'
- icon_state = ""
- name = "4-way pipe manifold"
- desc = "A manifold composed of regular pipes"
-
- volume = ATMOS_DEFAULT_VOLUME_PIPE * 2
-
- dir = SOUTH
- initialize_directions = NORTH|SOUTH|EAST|WEST
-
- var/obj/machinery/atmospherics/node3
- var/obj/machinery/atmospherics/node4
-
- level = 1
- layer = 2.4 //under wires with their 2.44
-
-/obj/machinery/atmospherics/pipe/manifold4w/New()
- ..()
- alpha = 255
- icon = null
-
-/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
- return list(node1, node2, node3, node4)
-
-/obj/machinery/atmospherics/pipe/manifold4w/Destroy()
- if(node1)
- node1.disconnect(src)
- node1 = null
- if(node2)
- node2.disconnect(src)
- node2 = null
- if(node3)
- node3.disconnect(src)
- node3 = null
- if(node4)
- node4.disconnect(src)
- node4 = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
-
- if(reference == node2)
- if(istype(node2, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node2 = null
-
- if(reference == node3)
- if(istype(node3, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node3 = null
-
- if(reference == node4)
- if(istype(node4, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node4 = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/manifold4w/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node1)
- node1.update_underlays()
- if(node2)
- node2.update_underlays()
- if(node3)
- node3.update_underlays()
- if(node4)
- node4.update_underlays()
-
-/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- if(!node1 && !node2 && !node3 && !node4)
- var/turf/T = get_turf(src)
- new /obj/item/pipe(loc, make_from=src)
- for (var/obj/machinery/meter/meter in T)
- if (meter.target == src)
- new /obj/item/pipe_meter(T)
- qdel(meter)
- qdel(src)
- else
- overlays.Cut()
- overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type)
- 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)
-
-
-/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
- ..()
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold4w/atmos_init()
-
- for(var/obj/machinery/atmospherics/target in get_step(src,1))
- if(target.initialize_directions & 2)
- if (check_connect_types(target,src))
- node1 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,2))
- if(target.initialize_directions & 1)
- if (check_connect_types(target,src))
- node2 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,4))
- if(target.initialize_directions & 8)
- if (check_connect_types(target,src))
- node3 = target
- break
-
- for(var/obj/machinery/atmospherics/target in get_step(src,8))
- if(target.initialize_directions & 4)
- if (check_connect_types(target,src))
- node4 = target
- break
-
- if(!node1 && !node2 && !node3 && !node4)
- qdel(src)
- return
-
- var/turf/T = get_turf(src)
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible
- icon_state = "map_4way"
- level = 2
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
- name="4-way scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map_4way-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/supply
- name="4-way air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map_4way-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/visible/purple
- color = PIPE_COLOR_PURPLE
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden
- icon_state = "map_4way"
- level = 1
- alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
- name="4-way scrubbers pipe manifold"
- desc = "A manifold composed of scrubbers pipes"
- icon_state = "map_4way-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
- name="4-way air supply pipe manifold"
- desc = "A manifold composed of supply pipes"
- icon_state = "map_4way-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
- color = PIPE_COLOR_YELLOW
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/cyan
- color = PIPE_COLOR_CYAN
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/green
- color = PIPE_COLOR_GREEN
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/black
- color = PIPE_COLOR_BLACK
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/red
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/blue
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/manifold4w/hidden/purple
- color = PIPE_COLOR_PURPLE
-
-//
-// Pipe Cap - They go on the end
-//
-/obj/machinery/atmospherics/pipe/cap
- name = "pipe endcap"
- desc = "An endcap for pipes"
- icon = 'icons/atmos/pipes.dmi'
- icon_state = ""
- level = 2
- layer = 2.4 //under wires with their 2.44
-
- volume = 35
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/obj/machinery/atmospherics/node
-
-/obj/machinery/atmospherics/pipe/cap/init_dir()
- initialize_directions = dir
-
-/obj/machinery/atmospherics/pipe/cap/pipeline_expansion()
- return list(node)
-
-/obj/machinery/atmospherics/pipe/cap/Destroy()
- if(node)
- node.disconnect(src)
- node = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/cap/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node)
- if(istype(node, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node = null
-
- update_icon()
-
- ..()
-
-/obj/machinery/atmospherics/pipe/cap/change_color(var/new_color)
- ..()
- //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
- if(node)
- node.update_underlays()
-
-/obj/machinery/atmospherics/pipe/cap/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- overlays.Cut()
- overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap")
-
-/obj/machinery/atmospherics/pipe/cap/atmos_init()
- for(var/obj/machinery/atmospherics/target in get_step(src, dir))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node = target
- break
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
-/obj/machinery/atmospherics/pipe/cap/can_unwrench()
- return 1
-
-/obj/machinery/atmospherics/pipe/cap/visible
- level = 2
- icon_state = "cap"
-
-/obj/machinery/atmospherics/pipe/cap/visible/scrubbers
- name = "scrubbers pipe endcap"
- desc = "An endcap for scrubbers pipes"
- icon_state = "cap-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/cap/visible/supply
- name = "supply pipe endcap"
- desc = "An endcap for supply pipes"
- icon_state = "cap-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/cap/hidden
- level = 1
- icon_state = "cap"
- alpha = 128
-
-/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers
- name = "scrubbers pipe endcap"
- desc = "An endcap for scrubbers pipes"
- icon_state = "cap-f-scrubbers"
- connect_types = CONNECT_TYPE_SCRUBBER
- layer = 2.38
- icon_connect_type = "-scrubbers"
- color = PIPE_COLOR_RED
-
-/obj/machinery/atmospherics/pipe/cap/hidden/supply
- name = "supply pipe endcap"
- desc = "An endcap for supply pipes"
- icon_state = "cap-f-supply"
- connect_types = CONNECT_TYPE_SUPPLY
- layer = 2.39
- icon_connect_type = "-supply"
- color = PIPE_COLOR_BLUE
-
-//
-// Tanks - These are implemented as pipes with large volume
-//
-/obj/machinery/atmospherics/pipe/tank
- icon = 'icons/atmos/tank.dmi'
- icon_state = "air_map"
-
- name = "Pressure Tank"
- desc = "A large vessel containing pressurized gas."
-
- volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
- var/start_pressure = 25*ONE_ATMOSPHERE
-
- level = 1
- dir = SOUTH
- initialize_directions = SOUTH
- density = 1
-
-/obj/machinery/atmospherics/pipe/tank/New()
- icon_state = "air"
- ..()
-
-/obj/machinery/atmospherics/pipe/tank/init_dir()
- initialize_directions = dir
-
-/obj/machinery/atmospherics/pipe/tank/Destroy()
- if(node1)
- node1.disconnect(src)
- node1 = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/tank/pipeline_expansion()
- return list(node1)
-
-/obj/machinery/atmospherics/pipe/tank/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, dir)
-
-/obj/machinery/atmospherics/pipe/tank/hide()
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/atmos_init()
- var/connect_direction = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
-
- update_underlays()
-
- return null
-
-/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
- if(istype(W, /obj/item/device/pipe_painter))
- return
-
- if(istype(W, /obj/item/device/analyzer) && in_range(user, src))
- var/obj/item/device/analyzer/A = W
- A.analyze_gases(src, user)
-
-/obj/machinery/atmospherics/pipe/tank/air
- name = "Pressure Tank (Air)"
- icon_state = "air_map"
-
-/obj/machinery/atmospherics/pipe/tank/air/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
- "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
-
- ..()
- icon_state = "air"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen
- name = "Pressure Tank (Oxygen)"
- icon_state = "o2_map"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "o2"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen
- name = "Pressure Tank (Nitrogen)"
- icon_state = "n2_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "n2"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
- name = "Pressure Tank (Carbon Dioxide)"
- icon_state = "co2_map"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "co2"
-
-/obj/machinery/atmospherics/pipe/tank/phoron
- name = "Pressure Tank (Phoron)"
- icon_state = "phoron_map"
-
-/obj/machinery/atmospherics/pipe/tank/phoron/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "phoron"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
- name = "Pressure Tank (Nitrous Oxide)"
- icon_state = "n2o_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/New()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T0C
-
- air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "n2o"
-
-//
-// Vent Pipe - Unpowered vent
-//
-/obj/machinery/atmospherics/pipe/vent
- icon = 'icons/obj/atmospherics/pipe_vent.dmi'
- icon_state = "intact"
-
- name = "Vent"
- desc = "A large air vent"
-
- level = 1
-
- volume = 250
-
- dir = SOUTH
- initialize_directions = SOUTH
-
- var/build_killswitch = 1
-
-/obj/machinery/atmospherics/pipe/vent/init_dir()
- initialize_directions = dir
-
-/obj/machinery/atmospherics/pipe/vent/high_volume
- name = "Larger vent"
- volume = 1000
-
-/obj/machinery/atmospherics/pipe/vent/process()
- if(!parent)
- if(build_killswitch <= 0)
- . = PROCESS_KILL
- else
- build_killswitch--
- ..()
- return
- else
- parent.mingle_with_turf(loc, volume)
-
-/obj/machinery/atmospherics/pipe/vent/Destroy()
- if(node1)
- node1.disconnect(src)
- node1 = null
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/vent/pipeline_expansion()
- return list(node1)
-
-/obj/machinery/atmospherics/pipe/vent/update_icon()
- if(node1)
- icon_state = "intact"
-
- set_dir(get_dir(src, node1))
-
- else
- icon_state = "exposed"
-
-/obj/machinery/atmospherics/pipe/vent/atmos_init()
- var/connect_direction = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
- if(target.initialize_directions & get_dir(target,src))
- if (check_connect_types(target,src))
- node1 = target
- break
-
- update_icon()
-
-/obj/machinery/atmospherics/pipe/vent/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- qdel(parent)
- node1 = null
-
- update_icon()
-
- return null
-
-/obj/machinery/atmospherics/pipe/vent/hide(var/i) //to make the little pipe section invisible, the icon changes.
- if(node1)
- icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
- set_dir(get_dir(src, node1))
- else
- icon_state = "exposed"
-
-//
-// Universal Pipe Adapter - Designed for connecting scrubbers, normal, and supply pipes together.
-//
-/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
- icon_state = "map_universal"
-
-/obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- overlays.Cut()
- overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")
- underlays.Cut()
-
- if (node1)
- universal_underlays(node1)
- if(node2)
- universal_underlays(node2)
- else
- var/node1_dir = get_dir(node1,src)
- universal_underlays(,node1_dir)
- else if (node2)
- universal_underlays(node2)
- else
- universal_underlays(,dir)
- universal_underlays(dir, -180)
-
-/obj/machinery/atmospherics/pipe/simple/visible/universal/update_underlays()
- ..()
- update_icon()
-
-
-
-/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
- icon_state = "map_universal"
-
-/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0)
- if(!check_icon_cache())
- return
-
- alpha = 255
-
- overlays.Cut()
- overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")
- underlays.Cut()
-
- if (node1)
- universal_underlays(node1)
- if(node2)
- universal_underlays(node2)
- else
- var/node2_dir = turn(get_dir(src,node1),-180)
- universal_underlays(,node2_dir)
- else if (node2)
- universal_underlays(node2)
- var/node1_dir = turn(get_dir(src,node2),-180)
- universal_underlays(,node1_dir)
- else
- universal_underlays(,dir)
- universal_underlays(,turn(dir, -180))
-
-/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_underlays()
- ..()
- update_icon()
-
-/obj/machinery/atmospherics/proc/universal_underlays(var/obj/machinery/atmospherics/node, var/direction)
- 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")
- else
- add_underlay_adapter(T, , direction, "-supply")
- add_underlay_adapter(T, , direction, "-scrubbers")
- 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
- if(node)
- if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
- else
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
- else
- underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm
new file mode 100644
index 0000000000..4658b9c40c
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/cap.dm
@@ -0,0 +1,119 @@
+//
+// Pipe Cap - They go on the end
+//
+/obj/machinery/atmospherics/pipe/cap
+ name = "pipe endcap"
+ desc = "An endcap for pipes"
+ icon = 'icons/atmos/pipes.dmi'
+ icon_state = ""
+ level = 2
+
+ volume = 35
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "cap"
+
+ var/obj/machinery/atmospherics/node
+
+/obj/machinery/atmospherics/pipe/cap/init_dir()
+ initialize_directions = dir
+
+/obj/machinery/atmospherics/pipe/cap/pipeline_expansion()
+ return list(node)
+
+/obj/machinery/atmospherics/pipe/cap/Destroy()
+ if(node)
+ node.disconnect(src)
+ node = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/cap/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node)
+ if(istype(node, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/cap/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node)
+ node.update_underlays()
+
+/obj/machinery/atmospherics/pipe/cap/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap")
+
+/obj/machinery/atmospherics/pipe/cap/atmos_init()
+ for(var/obj/machinery/atmospherics/target in get_step(src, dir))
+ if (can_be_node(target, 1))
+ node = target
+ break
+
+ var/turf/T = src.loc // hide if turf is not intact
+ if(level == 1 && !T.is_plating()) hide(1)
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/cap/can_unwrench()
+ return 1
+
+/obj/machinery/atmospherics/pipe/cap/visible
+ level = 2
+ icon_state = "cap"
+
+/obj/machinery/atmospherics/pipe/cap/visible/scrubbers
+ name = "scrubbers pipe endcap"
+ desc = "An endcap for scrubbers pipes"
+ icon_state = "cap-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/cap/visible/supply
+ name = "supply pipe endcap"
+ desc = "An endcap for supply pipes"
+ icon_state = "cap-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/cap/hidden
+ level = 1
+ icon_state = "cap"
+ alpha = 128
+
+/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers
+ name = "scrubbers pipe endcap"
+ desc = "An endcap for scrubbers pipes"
+ icon_state = "cap-f-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/cap/hidden/supply
+ name = "supply pipe endcap"
+ desc = "An endcap for supply pipes"
+ icon_state = "cap-f-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm
similarity index 74%
rename from code/ATMOSPHERICS/he_pipes.dm
rename to code/ATMOSPHERICS/pipes/he_pipes.dm
index bff838cfdd..fe6580b1ce 100644
--- a/code/ATMOSPHERICS/he_pipes.dm
+++ b/code/ATMOSPHERICS/pipes/he_pipes.dm
@@ -1,153 +1,183 @@
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging
- icon = 'icons/atmos/heat.dmi'
- icon_state = "intact"
- pipe_icon = "hepipe"
- color = "#404040"
- level = 2
- connect_types = CONNECT_TYPE_HE
- layer = 2.41
- var/initialize_directions_he
- var/surface = 2 //surface area in m^2
- var/icon_temperature = T20C //stop small changes in temperature causing an icon refresh
-
- minimum_temperature_difference = 20
- thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
-
- buckle_lying = 1
-
- // BubbleWrap
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New()
- ..()
-// BubbleWrap END
- color = "#404040" //we don't make use of the fancy overlay system for colours, use this to set the default.
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/init_dir()
- ..()
- initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_directions_he)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node1_dir))
- if(target.initialize_directions_he & get_dir(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node2_dir))
- if(target.initialize_directions_he & get_dir(target,src))
- node2 = target
- break
- if(!node1 && !node2)
- qdel(src)
- return
-
- update_icon()
- return
-
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process()
- if(!parent)
- ..()
- else
- var/datum/gas_mixture/pipe_air = return_air()
- if(istype(loc, /turf/simulated/))
- var/environment_temperature = 0
- if(loc:blocks_air)
- environment_temperature = loc:temperature
- else
- var/datum/gas_mixture/environment = loc.return_air()
- environment_temperature = environment.temperature
- if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
- parent.temperature_interact(loc, volume, thermal_conductivity)
- else if(istype(loc, /turf/space/))
- parent.radiate_heat_to_space(surface, 1)
-
- if(has_buckled_mobs())
- for(var/M in buckled_mobs)
- var/mob/living/L = M
-
- var/hc = pipe_air.heat_capacity()
- var/avg_temp = (pipe_air.temperature * hc + L.bodytemperature * 3500) / (hc + 3500)
- pipe_air.temperature = avg_temp
- L.bodytemperature = avg_temp
-
- var/heat_limit = 1000
-
- var/mob/living/carbon/human/H = L
- if(istype(H) && H.species)
- heat_limit = H.species.heat_level_3
-
- if(pipe_air.temperature > heat_limit + 1)
- L.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BP_TORSO, used_weapon = "Excessive Heat")
-
- //fancy radiation glowing
- if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //start glowing at 500K
- if(abs(pipe_air.temperature - icon_temperature) > 10)
- icon_temperature = pipe_air.temperature
-
- var/h_r = heat2color_r(icon_temperature)
- var/h_g = heat2color_g(icon_temperature)
- var/h_b = heat2color_b(icon_temperature)
-
- if(icon_temperature < 2000) //scale up overlay until 2000K
- var/scale = (icon_temperature - 500) / 1500
- h_r = 64 + (h_r - 64)*scale
- h_g = 64 + (h_g - 64)*scale
- h_b = 64 + (h_b - 64)*scale
-
- animate(src, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
-
-
-
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
- icon = 'icons/atmos/junction.dmi'
- icon_state = "intact"
- pipe_icon = "hejunction"
- level = 2
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
- minimum_temperature_difference = 300
- thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/init_dir()
- ..()
- switch ( dir )
- if ( SOUTH )
- initialize_directions = NORTH
- initialize_directions_he = SOUTH
- if ( NORTH )
- initialize_directions = SOUTH
- initialize_directions_he = NORTH
- if ( EAST )
- initialize_directions = WEST
- initialize_directions_he = EAST
- if ( WEST )
- initialize_directions = EAST
- initialize_directions_he = WEST
-
-
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmos_init()
- for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
- if(target.initialize_directions & get_dir(target,src))
- node1 = target
- break
- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,initialize_directions_he))
- if(target.initialize_directions_he & get_dir(target,src))
- node2 = target
- break
-
- if(!node1&&!node2)
- qdel(src)
- return
-
- update_icon()
- return
+//
+// Heat Exchanging Pipes - Behave like simple pipes
+//
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging
+ icon = 'icons/atmos/heat.dmi'
+ icon_state = "intact"
+ pipe_icon = "hepipe"
+ color = "#404040"
+ level = 2
+ connect_types = CONNECT_TYPE_HE
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY
+ construction_type = /obj/item/pipe/binary/bendable
+ pipe_state = "he"
+
+ layer = 2.41
+ var/initialize_directions_he
+ var/surface = 2 //surface area in m^2
+ var/icon_temperature = T20C //stop small changes in temperature causing an icon refresh
+
+ minimum_temperature_difference = 20
+ thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
+
+ buckle_lying = 1
+
+ // BubbleWrap
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New()
+ ..()
+// BubbleWrap END
+ color = "#404040" //we don't make use of the fancy overlay system for colours, use this to set the default.
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/init_dir()
+ ..()
+ initialize_directions_he = initialize_directions // The auto-detection from /pipe is good enough for a simple HE pipe
+ initialize_directions = 0
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/get_init_dirs()
+ return ..() | initialize_directions_he
+
+// Use initialize_directions_he to connect to neighbors instead.
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/can_be_node(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target)
+ if(!istype(target))
+ return FALSE
+ return (target.initialize_directions_he & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src)
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/atmos_init()
+ normalize_dir()
+ var/node1_dir
+ var/node2_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions_he)
+ if (!node1_dir)
+ node1_dir = direction
+ else if (!node2_dir)
+ node2_dir = direction
+
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node1_dir))
+ if(can_be_node(target, 1))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,node2_dir))
+ if(can_be_node(target, 2))
+ node2 = target
+ break
+ if(!node1 && !node2)
+ qdel(src)
+ return
+
+ update_icon()
+ return
+
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process()
+ if(!parent)
+ ..()
+ else
+ var/datum/gas_mixture/pipe_air = return_air()
+ if(istype(loc, /turf/simulated/))
+ var/environment_temperature = 0
+ if(loc:blocks_air)
+ environment_temperature = loc:temperature
+ else
+ var/datum/gas_mixture/environment = loc.return_air()
+ environment_temperature = environment.temperature
+ if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
+ parent.temperature_interact(loc, volume, thermal_conductivity)
+ else if(istype(loc, /turf/space/))
+ parent.radiate_heat_to_space(surface, 1)
+
+ if(has_buckled_mobs())
+ for(var/M in buckled_mobs)
+ var/mob/living/L = M
+
+ var/hc = pipe_air.heat_capacity()
+ var/avg_temp = (pipe_air.temperature * hc + L.bodytemperature * 3500) / (hc + 3500)
+ pipe_air.temperature = avg_temp
+ L.bodytemperature = avg_temp
+
+ var/heat_limit = 1000
+
+ var/mob/living/carbon/human/H = L
+ if(istype(H) && H.species)
+ heat_limit = H.species.heat_level_3
+
+ if(pipe_air.temperature > heat_limit + 1)
+ L.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BP_TORSO, used_weapon = "Excessive Heat")
+
+ //fancy radiation glowing
+ if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //start glowing at 500K
+ if(abs(pipe_air.temperature - icon_temperature) > 10)
+ icon_temperature = pipe_air.temperature
+
+ var/h_r = heat2color_r(icon_temperature)
+ var/h_g = heat2color_g(icon_temperature)
+ var/h_b = heat2color_b(icon_temperature)
+
+ if(icon_temperature < 2000) //scale up overlay until 2000K
+ var/scale = (icon_temperature - 500) / 1500
+ h_r = 64 + (h_r - 64)*scale
+ h_g = 64 + (h_g - 64)*scale
+ h_b = 64 + (h_b - 64)*scale
+
+ animate(src, color = rgb(h_r, h_g, h_b), time = 20, easing = SINE_EASING)
+
+//
+// Heat Exchange Junction - Interfaces HE pipes to normal pipes
+//
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
+ icon = 'icons/atmos/junction.dmi'
+ icon_state = "intact"
+ pipe_icon = "hejunction"
+ level = 2
+ connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "junction"
+ minimum_temperature_difference = 300
+ thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/init_dir()
+ ..()
+ switch ( dir )
+ if ( SOUTH )
+ initialize_directions = NORTH
+ initialize_directions_he = SOUTH
+ if ( NORTH )
+ initialize_directions = SOUTH
+ initialize_directions_he = NORTH
+ if ( EAST )
+ initialize_directions = WEST
+ initialize_directions_he = EAST
+ if ( WEST )
+ initialize_directions = EAST
+ initialize_directions_he = WEST
+
+ // Allow ourselves to make connections to either HE or normal pipes depending on which node we are doing.
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/can_be_node(obj/machinery/atmospherics/target, node_num)
+ var/target_initialize_directions
+ switch(node_num)
+ if(1)
+ target_initialize_directions = target.initialize_directions // Node1 is towards normal pipes
+ if(2)
+ var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/H = target
+ if(!istype(H))
+ return FALSE
+ target_initialize_directions = H.initialize_directions_he // Node2 is towards HE pies.
+ return (target_initialize_directions & get_dir(target,src)) && check_connectable(target) && target.check_connectable(src)
+
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/atmos_init()
+ for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src,initialize_directions_he))
+ if(target.initialize_directions_he & get_dir(target,src))
+ node2 = target
+ break
+
+ if(!node1&&!node2)
+ qdel(src)
+ return
+
+ update_icon()
+ return
diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm
new file mode 100644
index 0000000000..bca6dd3379
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/manifold.dm
@@ -0,0 +1,248 @@
+//
+// Manifold Pipes - Three way "T" joints
+//
+/obj/machinery/atmospherics/pipe/manifold
+ icon = 'icons/atmos/manifold.dmi'
+ icon_state = ""
+ name = "pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE * 1.5
+
+ dir = SOUTH
+ initialize_directions = EAST|NORTH|WEST
+
+ construction_type = /obj/item/pipe/trinary
+ pipe_state = "manifold"
+
+ var/obj/machinery/atmospherics/node3
+
+ level = 1
+ layer = 2.4 //under wires with their 2.44
+
+/obj/machinery/atmospherics/pipe/manifold/New()
+ ..()
+ alpha = 255
+ icon = null
+
+/obj/machinery/atmospherics/pipe/manifold/init_dir()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = EAST|SOUTH|WEST
+ if(SOUTH)
+ initialize_directions = WEST|NORTH|EAST
+ if(EAST)
+ initialize_directions = SOUTH|WEST|NORTH
+ if(WEST)
+ initialize_directions = NORTH|EAST|SOUTH
+
+/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
+ return list(node1, node2, node3)
+
+/obj/machinery/atmospherics/pipe/manifold/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node2 = null
+ if(node3)
+ node3.disconnect(src)
+ node3 = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/manifold/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node2 = null
+
+ if(reference == node3)
+ if(istype(node3, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node3 = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/manifold/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+ if(node3)
+ node3.update_underlays()
+
+/obj/machinery/atmospherics/pipe/manifold/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+ overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type)
+ overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type)
+ 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)
+
+ 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)
+
+ for(var/D in directions)
+ add_underlay(T,,D,icon_connect_type)
+
+
+/obj/machinery/atmospherics/pipe/manifold/update_underlays()
+ ..()
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/manifold/atmos_init()
+ var/connect_directions = (NORTH|SOUTH|EAST|WEST)&(~dir)
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if (can_be_node(target, 1))
+ node1 = target
+ connect_directions &= ~direction
+ break
+ if (node1)
+ break
+
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if (can_be_node(target, 2))
+ node2 = target
+ connect_directions &= ~direction
+ break
+ if (node2)
+ break
+
+
+ for(var/direction in cardinal)
+ if(direction&connect_directions)
+ for(var/obj/machinery/atmospherics/target in get_step(src,direction))
+ if (can_be_node(target, 3))
+ node3 = target
+ connect_directions &= ~direction
+ break
+ if (node3)
+ break
+
+ if(!node1 && !node2 && !node3)
+ qdel(src)
+ return
+
+ var/turf/T = get_turf(src)
+ if(level == 1 && !T.is_plating()) hide(1)
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/manifold/visible
+ icon_state = "map"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
+ name="Scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/visible/supply
+ name="Air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/visible/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/visible/purple
+ color = PIPE_COLOR_PURPLE
+
+/obj/machinery/atmospherics/pipe/manifold/hidden
+ icon_state = "map"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
+ name="Scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/supply
+ name="Air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold/hidden/purple
+ color = PIPE_COLOR_PURPLE
diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm
new file mode 100644
index 0000000000..88adc47d62
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/manifold4w.dm
@@ -0,0 +1,250 @@
+//
+// 4-Way Manifold Pipes - 4 way "cross" junction
+//
+/obj/machinery/atmospherics/pipe/manifold4w
+ icon = 'icons/atmos/manifold.dmi'
+ icon_state = ""
+ name = "4-way pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE * 2
+
+ dir = SOUTH
+ initialize_directions = NORTH|SOUTH|EAST|WEST
+
+ construction_type = /obj/item/pipe/quaternary
+ pipe_state = "manifold4w"
+
+ var/obj/machinery/atmospherics/node3
+ var/obj/machinery/atmospherics/node4
+
+ level = 1
+ layer = 2.4 //under wires with their 2.44
+
+/obj/machinery/atmospherics/pipe/manifold4w/New()
+ ..()
+ alpha = 255
+ icon = null
+
+/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
+ return list(node1, node2, node3, node4)
+
+/obj/machinery/atmospherics/pipe/manifold4w/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node2 = null
+ if(node3)
+ node3.disconnect(src)
+ node3 = null
+ if(node4)
+ node4.disconnect(src)
+ node4 = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/manifold4w/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node2 = null
+
+ if(reference == node3)
+ if(istype(node3, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node3 = null
+
+ if(reference == node4)
+ if(istype(node4, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node4 = null
+
+ update_icon()
+
+ ..()
+
+/obj/machinery/atmospherics/pipe/manifold4w/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+ if(node3)
+ node3.update_underlays()
+ if(node4)
+ node4.update_underlays()
+
+/obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+ overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type)
+ 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)
+
+
+/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
+ ..()
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/manifold4w/atmos_init()
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, NORTH))
+ if (can_be_node(target, 1))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, SOUTH))
+ if (can_be_node(target, 2))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, EAST))
+ if (can_be_node(target, 3))
+ node3 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, WEST))
+ if (can_be_node(target, 4))
+ node4 = target
+ break
+
+ if(!node1 && !node2 && !node3 && !node4)
+ qdel(src)
+ return
+
+ var/turf/T = get_turf(src)
+ if(level == 1 && !T.is_plating()) hide(1)
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible
+ icon_state = "map_4way"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
+ name="4-way scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map_4way-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/supply
+ name="4-way air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map_4way-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/visible/purple
+ color = PIPE_COLOR_PURPLE
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden
+ icon_state = "map_4way"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
+ name="4-way scrubbers pipe manifold"
+ desc = "A manifold composed of scrubbers pipes"
+ icon_state = "map_4way-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
+ name="4-way air supply pipe manifold"
+ desc = "A manifold composed of supply pipes"
+ icon_state = "map_4way-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/manifold4w/hidden/purple
+ color = PIPE_COLOR_PURPLE
diff --git a/code/ATMOSPHERICS/pipes/pipe_base.dm b/code/ATMOSPHERICS/pipes/pipe_base.dm
new file mode 100644
index 0000000000..4e852ed0c8
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/pipe_base.dm
@@ -0,0 +1,142 @@
+//
+// Base type of pipes
+//
+/obj/machinery/atmospherics/pipe
+
+ var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke
+ var/datum/pipeline/parent
+ var/volume = 0
+
+ layer = 2.4 //under wires with their 2.44
+ use_power = 0
+
+ pipe_flags = 0 // Does not have PIPING_DEFAULT_LAYER_ONLY flag.
+
+ var/alert_pressure = 80*ONE_ATMOSPHERE
+ //minimum pressure before check_pressure(...) should be called
+
+ can_buckle = 1
+ buckle_require_restraints = 1
+ buckle_lying = -1
+
+/obj/machinery/atmospherics/pipe/drain_power()
+ return -1
+
+/obj/machinery/atmospherics/pipe/New()
+ if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/simulated/shuttle/wall) || istype(get_turf(src), /turf/unsimulated/wall))
+ level = 1
+ ..()
+
+/obj/machinery/atmospherics/pipe/hides_under_flooring()
+ return level != 2
+
+/obj/machinery/atmospherics/pipe/proc/pipeline_expansion()
+ return null
+
+// For pipes this is the same as pipeline_expansion()
+/obj/machinery/atmospherics/pipe/get_neighbor_nodes_for_init()
+ return pipeline_expansion()
+
+/obj/machinery/atmospherics/pipe/proc/check_pressure(pressure)
+ //Return 1 if parent should continue checking other pipes
+ //Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null
+
+ return 1
+
+/obj/machinery/atmospherics/pipe/return_air()
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.air
+
+/obj/machinery/atmospherics/pipe/build_network()
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.return_network()
+
+/obj/machinery/atmospherics/pipe/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.network_expand(new_network, reference)
+
+/obj/machinery/atmospherics/pipe/return_network(obj/machinery/atmospherics/reference)
+ if(!parent)
+ parent = new /datum/pipeline()
+ parent.build_pipeline(src)
+
+ return parent.return_network(reference)
+
+/obj/machinery/atmospherics/pipe/Destroy()
+ qdel_null(parent)
+ if(air_temporary)
+ loc.assume_air(air_temporary)
+ for(var/obj/machinery/meter/meter in loc)
+ if(meter.target == src)
+ var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(loc)
+ meter.transfer_fingerprints_to(PM)
+ qdel(meter)
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ if (istype(src, /obj/machinery/atmospherics/pipe/tank))
+ return ..()
+
+ if(istype(W,/obj/item/device/pipe_painter))
+ return 0
+
+ if (!istype(W, /obj/item/weapon/wrench))
+ return ..()
+ var/turf/T = src.loc
+ if (level==1 && isturf(T) && !T.is_plating())
+ to_chat(user, "You must remove the plating first.")
+ return 1
+ if(!can_unwrench())
+ to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ add_fingerprint(user)
+ return 1
+ playsound(src, W.usesound, 50, 1)
+ to_chat(user, "You begin to unfasten \the [src]...")
+ if (do_after(user, 40 * W.toolspeed))
+ user.visible_message( \
+ "\The [user] unfastens \the [src].", \
+ "You have unfastened \the [src].", \
+ "You hear a ratchet.")
+ deconstruct()
+
+/obj/machinery/atmospherics/pipe/proc/change_color(var/new_color)
+ //only pass valid pipe colors please ~otherwise your pipe will turn invisible
+ if(!pipe_color_check(new_color))
+ return
+
+ pipe_color = new_color
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node)
+ if(istype(src, /obj/machinery/atmospherics/pipe/tank))
+ return ..()
+
+ if(istype(node, /obj/machinery/atmospherics/pipe/manifold) || istype(node, /obj/machinery/atmospherics/pipe/manifold4w))
+ if(pipe_color == node.pipe_color)
+ return node.pipe_color
+ else
+ return null
+ else if(istype(node, /obj/machinery/atmospherics/pipe/simple))
+ return node.pipe_color
+ else
+ return pipe_color
+
+/obj/machinery/atmospherics/pipe/hide(var/i)
+ if(istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/process()
+ if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
+ ..()
+ else
+ . = PROCESS_KILL
diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm
new file mode 100644
index 0000000000..77290e5d8a
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/simple.dm
@@ -0,0 +1,270 @@
+//
+// Simple Pipes - Just a tube, maybe bent
+//
+/obj/machinery/atmospherics/pipe/simple
+ icon = 'icons/atmos/pipes.dmi'
+ icon_state = ""
+ var/pipe_icon = "" //what kind of pipe it is and from which dmi is the icon manager getting its icons, "" for simple pipes, "hepipe" for HE pipes, "hejunction" for HE junctions
+ name = "pipe"
+ desc = "A one meter section of regular pipe"
+
+ volume = ATMOS_DEFAULT_VOLUME_PIPE
+
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH
+
+ pipe_flags = PIPING_CARDINAL_AUTONORMALIZE
+ construction_type = /obj/item/pipe/binary/bendable
+ pipe_state = "simple"
+
+ var/minimum_temperature_difference = 300
+ var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
+
+ var/maximum_pressure = 70*ONE_ATMOSPHERE
+ var/fatigue_pressure = 55*ONE_ATMOSPHERE
+ alert_pressure = 55*ONE_ATMOSPHERE
+
+ level = 1
+
+/obj/machinery/atmospherics/pipe/simple/New()
+ ..()
+
+ // Pipe colors and icon states are handled by an image cache - so color and icon should
+ // be null. For mapping purposes color is defined in the object definitions.
+ icon = null
+ alpha = 255
+
+/obj/machinery/atmospherics/pipe/simple/check_pressure(pressure)
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/pressure_difference = pressure - environment.return_pressure()
+
+ if(pressure_difference > maximum_pressure)
+ burst()
+
+ else if(pressure_difference > fatigue_pressure)
+ //TODO: leak to turf, doing pfshhhhh
+ if(prob(5))
+ burst()
+
+ else return 1
+
+/obj/machinery/atmospherics/pipe/simple/init_dir()
+ switch(dir)
+ if(SOUTH)
+ initialize_directions = SOUTH|NORTH
+ if(NORTH)
+ initialize_directions = SOUTH|NORTH
+ if(EAST)
+ initialize_directions = EAST|WEST
+ if(WEST)
+ initialize_directions = EAST|WEST
+ if(NORTHEAST)
+ initialize_directions = NORTH|EAST
+ if(NORTHWEST)
+ initialize_directions = NORTH|WEST
+ if(SOUTHEAST)
+ initialize_directions = SOUTH|EAST
+ if(SOUTHWEST)
+ initialize_directions = SOUTH|WEST
+
+/obj/machinery/atmospherics/pipe/simple/proc/burst()
+ src.visible_message("\The [src] bursts!");
+ playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
+ var/datum/effect/effect/system/smoke_spread/smoke = new
+ smoke.set_up(1,0, src.loc, 0)
+ smoke.start()
+ qdel(src)
+
+/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
+ if(dir==3)
+ set_dir(1)
+ else if(dir==12)
+ set_dir(4)
+
+/obj/machinery/atmospherics/pipe/simple/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+ if(node2)
+ node2.disconnect(src)
+ node1 = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
+ return list(node1, node2)
+
+/obj/machinery/atmospherics/pipe/simple/change_color(var/new_color)
+ ..()
+ //for updating connected atmos device pipes (i.e. vents, manifolds, etc)
+ if(node1)
+ node1.update_underlays()
+ if(node2)
+ node2.update_underlays()
+
+/obj/machinery/atmospherics/pipe/simple/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+
+ if(node1 && node2)
+ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]")
+ else
+ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]")
+
+/obj/machinery/atmospherics/pipe/simple/update_underlays()
+ return
+
+/obj/machinery/atmospherics/pipe/simple/atmos_init()
+ normalize_dir()
+ var/node1_dir
+ var/node2_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions)
+ if (!node1_dir)
+ node1_dir = direction
+ else if (!node2_dir)
+ node2_dir = direction
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(can_be_node(target, 1))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
+ if(can_be_node(target, 2))
+ node2 = target
+ break
+
+ if(!node1 && !node2)
+ qdel(src)
+ return
+
+ var/turf/T = loc
+ if(level == 1 && !T.is_plating()) hide(1)
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node2 = null
+
+ update_icon()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/simple/visible
+ icon_state = "intact"
+ level = 2
+
+/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
+ name = "Scrubbers pipe"
+ desc = "A one meter section of scrubbers pipe"
+ icon_state = "intact-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/visible/supply
+ name = "Air supply pipe"
+ desc = "A one meter section of supply pipe"
+ icon_state = "intact-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/visible/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/visible/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/simple/visible/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/simple/visible/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/simple/visible/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/visible/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/visible/purple
+ color = PIPE_COLOR_PURPLE
+
+/obj/machinery/atmospherics/pipe/simple/hidden
+ icon_state = "intact"
+ level = 1
+ alpha = 128 //set for the benefit of mapping - this is reset to opaque when the pipe is spawned in game
+
+/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
+ name = "Scrubbers pipe"
+ desc = "A one meter section of scrubbers pipe"
+ icon_state = "intact-scrubbers"
+ connect_types = CONNECT_TYPE_SCRUBBER
+ piping_layer = PIPING_LAYER_SCRUBBER
+ layer = 2.38
+ icon_connect_type = "-scrubbers"
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/hidden/supply
+ name = "Air supply pipe"
+ desc = "A one meter section of supply pipe"
+ icon_state = "intact-supply"
+ connect_types = CONNECT_TYPE_SUPPLY
+ piping_layer = PIPING_LAYER_SUPPLY
+ layer = 2.39
+ icon_connect_type = "-supply"
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/hidden/yellow
+ color = PIPE_COLOR_YELLOW
+
+/obj/machinery/atmospherics/pipe/simple/hidden/cyan
+ color = PIPE_COLOR_CYAN
+
+/obj/machinery/atmospherics/pipe/simple/hidden/green
+ color = PIPE_COLOR_GREEN
+
+/obj/machinery/atmospherics/pipe/simple/hidden/black
+ color = PIPE_COLOR_BLACK
+
+/obj/machinery/atmospherics/pipe/simple/hidden/red
+ color = PIPE_COLOR_RED
+
+/obj/machinery/atmospherics/pipe/simple/hidden/blue
+ color = PIPE_COLOR_BLUE
+
+/obj/machinery/atmospherics/pipe/simple/hidden/purple
+ color = PIPE_COLOR_PURPLE
+
+/obj/machinery/atmospherics/pipe/simple/insulated
+ icon = 'icons/obj/atmospherics/red_pipe.dmi'
+ icon_state = "intact"
+
+ construction_type = /obj/item/pipe/binary/bendable
+ pipe_state = "insulated"
+
+ minimum_temperature_difference = 10000
+ thermal_conductivity = 0
+ maximum_pressure = 1000*ONE_ATMOSPHERE
+ fatigue_pressure = 900*ONE_ATMOSPHERE
+ alert_pressure = 900*ONE_ATMOSPHERE
+
+ level = 2
diff --git a/code/ATMOSPHERICS/pipes/tank.dm b/code/ATMOSPHERICS/pipes/tank.dm
new file mode 100644
index 0000000000..c8015225e0
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/tank.dm
@@ -0,0 +1,160 @@
+//
+// Tanks - These are implemented as pipes with large volume
+//
+/obj/machinery/atmospherics/pipe/tank
+ icon = 'icons/atmos/tank.dmi'
+ icon_state = "air_map"
+
+ name = "Pressure Tank"
+ desc = "A large vessel containing pressurized gas."
+
+ volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
+ var/start_pressure = 25*ONE_ATMOSPHERE
+
+ level = 1
+ dir = SOUTH
+ initialize_directions = SOUTH
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY
+ density = 1
+
+/obj/machinery/atmospherics/pipe/tank/New()
+ icon_state = "air"
+ ..()
+
+/obj/machinery/atmospherics/pipe/tank/init_dir()
+ initialize_directions = dir
+
+/obj/machinery/atmospherics/pipe/tank/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/tank/pipeline_expansion()
+ return list(node1)
+
+/obj/machinery/atmospherics/pipe/tank/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node1, dir)
+
+/obj/machinery/atmospherics/pipe/tank/hide()
+ update_underlays()
+
+/obj/machinery/atmospherics/pipe/tank/atmos_init()
+ var/connect_direction = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
+ if (can_be_node(target, 1))
+ node1 = target
+ break
+
+ update_underlays()
+
+/obj/machinery/atmospherics/pipe/tank/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node1 = null
+
+ update_underlays()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
+ if(istype(W, /obj/item/device/pipe_painter))
+ return
+
+ if(istype(W, /obj/item/device/analyzer) && in_range(user, src))
+ var/obj/item/device/analyzer/A = W
+ A.analyze_gases(src, user)
+
+/obj/machinery/atmospherics/pipe/tank/air
+ name = "Pressure Tank (Air)"
+ icon_state = "air_map"
+
+/obj/machinery/atmospherics/pipe/tank/air/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
+ "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+
+ ..()
+ icon_state = "air"
+
+/obj/machinery/atmospherics/pipe/tank/oxygen
+ name = "Pressure Tank (Oxygen)"
+ icon_state = "o2_map"
+
+/obj/machinery/atmospherics/pipe/tank/oxygen/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "o2"
+
+/obj/machinery/atmospherics/pipe/tank/nitrogen
+ name = "Pressure Tank (Nitrogen)"
+ icon_state = "n2_map"
+
+/obj/machinery/atmospherics/pipe/tank/nitrogen/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "n2"
+
+/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
+ name = "Pressure Tank (Carbon Dioxide)"
+ icon_state = "co2_map"
+
+/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "co2"
+
+/obj/machinery/atmospherics/pipe/tank/phoron
+ name = "Pressure Tank (Phoron)"
+ icon_state = "phoron_map"
+
+/obj/machinery/atmospherics/pipe/tank/phoron/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "phoron"
+
+/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
+ name = "Pressure Tank (Nitrous Oxide)"
+ icon_state = "n2o_map"
+
+/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/New()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T0C
+
+ air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "n2o"
diff --git a/code/ATMOSPHERICS/pipes/universal.dm b/code/ATMOSPHERICS/pipes/universal.dm
new file mode 100644
index 0000000000..2d8bd09dff
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/universal.dm
@@ -0,0 +1,108 @@
+//
+// Universal Pipe Adapter - Designed for connecting scrubbers, normal, and supply pipes together.
+//
+/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
+ icon_state = "map_universal"
+ pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE
+ construction_type = /obj/item/pipe/binary
+ pipe_state = "universal"
+
+/obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")
+ underlays.Cut()
+
+ if (node1)
+ universal_underlays(node1)
+ if(node2)
+ universal_underlays(node2)
+ else
+ var/node1_dir = get_dir(node1,src)
+ universal_underlays(,node1_dir)
+ else if (node2)
+ universal_underlays(node2)
+ else
+ universal_underlays(,dir)
+ universal_underlays(,turn(dir, -180))
+
+/obj/machinery/atmospherics/pipe/simple/visible/universal/update_underlays()
+ ..()
+ update_icon()
+
+
+
+/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
+ icon_state = "map_universal"
+ pipe_flags = PIPING_ALL_LAYER|PIPING_CARDINAL_AUTONORMALIZE
+ construction_type = /obj/item/pipe/binary
+ pipe_state = "universal"
+
+/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0)
+ if(!check_icon_cache())
+ return
+
+ alpha = 255
+
+ overlays.Cut()
+ overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")
+ underlays.Cut()
+
+ if (node1)
+ universal_underlays(node1)
+ if(node2)
+ universal_underlays(node2)
+ else
+ var/node2_dir = turn(get_dir(src,node1),-180)
+ universal_underlays(,node2_dir)
+ else if (node2)
+ universal_underlays(node2)
+ var/node1_dir = turn(get_dir(src,node2),-180)
+ universal_underlays(,node1_dir)
+ else
+ universal_underlays(,dir)
+ universal_underlays(,turn(dir, -180))
+
+/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_underlays()
+ ..()
+ update_icon()
+
+/obj/machinery/atmospherics/proc/universal_underlays(var/obj/machinery/atmospherics/node, var/direction)
+ 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")
+ else
+ add_underlay_adapter(T, , direction, "-supply")
+ add_underlay_adapter(T, , direction, "-scrubbers")
+ 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
+ if(node)
+ if(!T.is_plating() && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "down" + icon_connect_type)
+ else
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "intact" + icon_connect_type)
+ else
+ underlays += icon_manager.get_atmos_icon("underlay", direction, color_cache_name(node), "retracted" + icon_connect_type)
diff --git a/code/ATMOSPHERICS/pipes/vent.dm b/code/ATMOSPHERICS/pipes/vent.dm
new file mode 100644
index 0000000000..4a1dc5696d
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/vent.dm
@@ -0,0 +1,85 @@
+//
+// Vent Pipe - Unpowered vent
+//
+/obj/machinery/atmospherics/pipe/vent
+ icon = 'icons/obj/atmospherics/pipe_vent.dmi'
+ icon_state = "intact"
+
+ name = "Vent"
+ desc = "A large air vent"
+
+ level = 1
+
+ volume = 250
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+ pipe_flags = PIPING_DEFAULT_LAYER_ONLY
+ construction_type = /obj/item/pipe/directional
+ pipe_state = "passive vent"
+
+ var/build_killswitch = 1
+
+/obj/machinery/atmospherics/pipe/vent/init_dir()
+ initialize_directions = dir
+
+/obj/machinery/atmospherics/pipe/vent/high_volume
+ name = "Larger vent"
+ volume = 1000
+
+/obj/machinery/atmospherics/pipe/vent/process()
+ if(!parent)
+ if(build_killswitch <= 0)
+ . = PROCESS_KILL
+ else
+ build_killswitch--
+ ..()
+ return
+ else
+ parent.mingle_with_turf(loc, volume)
+
+/obj/machinery/atmospherics/pipe/vent/Destroy()
+ if(node1)
+ node1.disconnect(src)
+ node1 = null
+
+ . = ..()
+
+/obj/machinery/atmospherics/pipe/vent/pipeline_expansion()
+ return list(node1)
+
+/obj/machinery/atmospherics/pipe/vent/update_icon()
+ if(node1)
+ icon_state = "intact"
+
+ set_dir(get_dir(src, node1))
+
+ else
+ icon_state = "exposed"
+
+/obj/machinery/atmospherics/pipe/vent/atmos_init()
+ var/connect_direction = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,connect_direction))
+ if (can_be_node(target, 1))
+ node1 = target
+ break
+
+ update_icon()
+
+/obj/machinery/atmospherics/pipe/vent/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ qdel(parent)
+ node1 = null
+
+ update_icon()
+
+ return null
+
+/obj/machinery/atmospherics/pipe/vent/hide(var/i) //to make the little pipe section invisible, the icon changes.
+ if(node1)
+ icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
+ set_dir(get_dir(src, node1))
+ else
+ icon_state = "exposed"
diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm
index a309cd3a08..f61d1cf4fc 100644
--- a/code/ZAS/Turf.dm
+++ b/code/ZAS/Turf.dm
@@ -6,9 +6,9 @@
/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
if(LAZYLEN(graphic_add))
- overlays += graphic_add
+ add_overlay(graphic_add, priority = TRUE)
if(LAZYLEN(graphic_remove))
- overlays -= graphic_remove
+ cut_overlay(graphic_remove, priority = TRUE)
/turf/proc/update_air_properties()
var/block = c_airblock(src)
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index ad4fe2181d..a044b16c85 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -44,36 +44,69 @@ What is the naming convention for planes or layers?
#define PLANE_ADMIN2 -91 //And adminbuse
#define PLANE_ADMIN3 -90 //And generating salt
-#define SPACE_PLANE -32 // Reserved for use in space/parallax
-#define PARALLAX_PLANE -30 // Reserved for use in space/parallax
+#define SPACE_PLANE -82 // Reserved for use in space/parallax
+#define PARALLAX_PLANE -80 // Reserved for use in space/parallax
// OPENSPACE_PLANE reserves all planes between OPENSPACE_PLANE_START and OPENSPACE_PLANE_END inclusive
-#define OPENSPACE_PLANE -55 // /turf/simulated/open will use OPENSPACE_PLANE + z (Valid z's being 2 thru 17)
-#define OPENSPACE_PLANE_START -53
-#define OPENSPACE_PLANE_END -38
-#define OVER_OPENSPACE_PLANE -37
+#define OPENSPACE_PLANE -75 // /turf/simulated/open will use OPENSPACE_PLANE + z (Valid z's being 2 thru 17)
+#define OPENSPACE_PLANE_START -73
+#define OPENSPACE_PLANE_END -58
+#define OVER_OPENSPACE_PLANE -57
+
+// Turf Planes
+#define SPACE_PLANE -43 // Space turfs themselves
+#define PLATING_PLANE -44 // Plating
+ #define DISPOSAL_LAYER 2.1 // Under objects, even when planeswapped
+ #define WIRES_LAYER 2.2 // Under objects, even when planeswapped
+ #define PIPES_LAYER 2.3 // Under objects, even when planeswapped
+ #define ABOVE_UTILITY 2.5 // Above stuff like pipes and wires
+#define TURF_PLANE -45 // Turfs themselves, most flooring
+ #define ABOVE_TURF_LAYER 2.1 // Snow and such
+#define DECAL_PLANE -44 // Permanent decals
+#define DIRTY_PLANE -43 // Nonpermanent decals
+#define BLOOD_PLANE -42 // Blood is really dirty, but we can do special stuff if we separate it
+
+// Obj planes
+#define OBJ_PLANE -35
+ #define HIDING_LAYER 2.6 // Layer at which mobs hide to be under things like tables
+ #define DOOR_OPEN_LAYER 2.7 // Under all objects if opened. 2.7 due to tables being at 2.6
+ #define TABLE_LAYER 2.8 // Just under stuff that wants to be slightly below common objects.
+ #define UNDER_JUNK_LAYER 2.9 // Things that want to be slightly below common objects
+ // Turf/Obj layer boundary
+ #define ABOVE_JUNK_LAYER 3.1 // Things that want to be slightly above common objects
+ #define DOOR_CLOSED_LAYER 3.1 // Doors when closed
+ #define WINDOW_LAYER 3.2 // Windows
+ #define ON_WINDOW_LAYER 3.3 // Ontop of a window
+ #define SHOWER_OPEN_LAYER 3.4 // Showers when open
+ // Obj/Mob layer boundary
+ #define SHOWER_CLOSED_LAYER 4.2 // Should be converted to plane swaps
+
+// Mob planes
+#define MOB_PLANE -25
+ #define BELOW_MOB_LAYER 3.9 // Should be converted to plane swaps
+ #define ABOVE_MOB_LAYER 4.1 // Should be converted to plane swaps
+
+// Top plane (in the sense that it's the highest in 'the world' and not a UI element)
+#define ABOVE_PLANE -10
////////////////////////////////////////////////////////////////////////////////////////
#define PLANE_WORLD 0 // BYOND's default value for plane, the "base plane"
////////////////////////////////////////////////////////////////////////////////////////
+ //#define AREA_LAYER 1 //For easy recordkeeping; this is a byond define
+
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
- #define DECALS_LAYER 2.01
- #define OVERTURF_LAYER 2.1
- #define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
+
//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define
- #define DOOR_CLOSED_LAYER 3.1 //Above most items if closed
- #define SHOWER_OPEN_LAYER 3.4
- #define BELOW_MOB_LAYER 3.9
+
//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
- #define ABOVE_MOB_LAYER 4.1
- #define SHOWER_CLOSED_LAYER 4.2
-
+
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
- #define LIGHTING_LAYER 11 //Layer that lighting used to be on (now it's on a plane)
- #define HUD_LAYER 20 //Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots)
- #define SCREEN_LAYER 22 //Mob HUD/effects layer
+ #define HUD_LAYER 20 // Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots)
+ #define SCREEN_LAYER 22 // Mob HUD/effects layer
+
+#define PLANE_PLANETLIGHTING 4 //Lighting on planets
#define PLANE_LIGHTING 5 //Where the lighting (and darkness) lives
#define PLANE_LIGHTING_ABOVE 6 //For glowy eyes etc. that shouldn't be affected by darkness
@@ -122,4 +155,4 @@ What is the naming convention for planes or layers?
// Check if a mob can "logically" see an atom plane
-#define MOB_CAN_SEE_PLANE(M, P) (P == PLANE_WORLD || (P >= OPENSPACE_PLANE_START && P <= OPENSPACE_PLANE_END) || (P in M.planes_visible))
+#define MOB_CAN_SEE_PLANE(M, P) (P <= PLANE_WORLD || (P in M.planes_visible))
diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm
index bd9175aab1..13964a6f80 100644
--- a/code/__defines/atmos.dm
+++ b/code/__defines/atmos.dm
@@ -21,8 +21,6 @@
#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD * BREATH_PERCENTAGE * 0.16)
#define HUMAN_HEAT_CAPACITY 280000 //J/K For 80kg person
-#define SOUND_MINIMUM_PRESSURE 10
-
#define PRESSURE_DAMAGE_COEFFICIENT 4 // The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE.
#define MAX_HIGH_PRESSURE_DAMAGE 4 // This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
#define LOW_PRESSURE_DAMAGE 2 // The amount of damage someone takes when in a low pressure area. (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 08131f99bb..c9b34fc2b6 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -27,7 +27,7 @@
#define IS_SLIME 8
#define CE_STABLE "stable" // Inaprovaline
-#define CE_ANTIBIOTIC "antibiotic" // Spaceacilin
+#define CE_ANTIBIOTIC "antibiotic" // Antibiotics
#define CE_BLOODRESTORE "bloodrestore" // Iron/nutriment
#define CE_PAINKILLER "painkiller"
#define CE_ALCOHOL "alcohol" // Liver filtering
@@ -36,6 +36,11 @@
#define REAGENTS_PER_SHEET 20
+// Attached to CE_ANTIBIOTIC
+#define ANTIBIO_NORM 1
+#define ANTIBIO_OD 2
+#define ANTIBIO_SUPER 3
+
// Chemistry lists.
var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglycerin", "thirteenloko", "nicotine") // Increase heart rate.
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
diff --git a/code/__defines/construction.dm b/code/__defines/construction.dm
index 7aceb1ffc4..837ad7ed38 100644
--- a/code/__defines/construction.dm
+++ b/code/__defines/construction.dm
@@ -1,4 +1,6 @@
-
+//
+// Frame construction
+//
// Frame construction states
#define FRAME_PLACED 0 // Has been placed (can be anchored or not).
@@ -16,3 +18,44 @@
// Does the frame get built on the floor or a wall?
#define FRAME_STYLE_FLOOR "floor"
#define FRAME_STYLE_WALL "wall"
+
+//
+// Pipe Construction
+//
+
+//Construction Orientation Types - Each of these categories has a different selection of how pipes can rotate and flip. Used for RPD.
+#define PIPE_STRAIGHT 0 //2 directions: N/S, E/W
+#define PIPE_BENDABLE 1 //6 directions: N/S, E/W, N/E, N/W, S/E, S/W
+#define PIPE_TRINARY 2 //4 directions: N/E/S, E/S/W, S/W/N, W/N/E
+#define PIPE_TRIN_M 3 //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
+#define PIPE_DIRECTIONAL 4 //4 directions: N, S, E, W
+#define PIPE_ONEDIR 5 //1 direction: N/S/E/W
+#define PIPE_UNARY_FLIPPABLE 6 //8 directions: N, S, E, W, N-flipped, S-flipped, E-flipped, W-flipped
+#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
+
+// 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_DEFAULT PIPING_LAYER_REGULAR
+
+// Pipe flags
+#define PIPING_ALL_LAYER 1 //intended to connect with all layers, check for all instead of just one.
+#define PIPING_ONE_PER_TURF 2 //can only be built if nothing else with this flag is on the tile already.
+#define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT
+#define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build.
+
+// Macro for easy use of boilerplate code for searching for a valid node connection.
+#define STANDARD_ATMOS_CHOOSE_NODE(node_num, direction) \
+ for(var/obj/machinery/atmospherics/target in get_step(src, direction)) { \
+ if(can_be_node(target, node_num)) { \
+ node##node_num = target; \
+ break; \
+ } \
+ }
diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm
index f857a8f232..637b450df6 100644
--- a/code/__defines/items_clothing.dm
+++ b/code/__defines/items_clothing.dm
@@ -34,8 +34,9 @@
#define ACCESSORY_SLOT_ARMOR_L "Leg armor"
#define ACCESSORY_SLOT_ARMOR_S "Armor storage"
#define ACCESSORY_SLOT_ARMOR_M "Misc armor"
+#define ACCESSORY_SLOT_HELM_C "Helmet cover"
-// Flags bitmasks.
+// Flags bitmasks. - Used in /atom/var/flags
#define NOBLUDGEON 0x1 // When an item has this it produces no "X has been hit by Y with Z" message with the default handler.
#define CONDUCT 0x2 // Conducts electricity. (metal etc.)
#define ON_BORDER 0x4 // Item has priority to check when entering or leaving.
@@ -44,8 +45,9 @@
#define PHORONGUARD 0x20 // Does not get contaminated by phoron.
#define NOREACT 0x40 // Reagents don't react inside this container.
#define PROXMOVE 0x80 // Does this object require proximity checking in Enter()?
+#define OVERLAY_QUEUED 0x100 // Atom queued to SSoverlay for COMPILE_OVERLAYS
-//Flags for items (equipment)
+//Flags for items (equipment) - Used in /obj/item/var/item_flags
#define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head.
#define STOPPRESSUREDAMAGE 0x2 // Counts towards pressure protection. Note that like temperature protection, body_parts_covered is considered here as well.
#define AIRTIGHT 0x4 // Functions with internals.
@@ -53,13 +55,13 @@
#define BLOCK_GAS_SMOKE_EFFECT 0x10 // Blocks the effect that chemical clouds would have on a mob -- glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL)
#define FLEXIBLEMATERIAL 0x20 // At the moment, masks with this flag will not prevent eating even if they are covering your face.
-// Flags for pass_flags.
+// Flags for pass_flags. - Used in /atom/var/pass_flags
#define PASSTABLE 0x1
#define PASSGLASS 0x2
#define PASSGRILLE 0x4
#define PASSBLOB 0x8
-// Bitmasks for the flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
+// Bitmasks for the /obj/item/var/flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
// WARNING: The following flags apply only to the external suit!
#define HIDEGLOVES 0x1
#define HIDESUITSTORAGE 0x2
@@ -78,29 +80,34 @@
#define BLOCKHEADHAIR 0x20 // Hides the user's hair overlay. Leaves facial hair.
#define BLOCKHAIR 0x40 // Hides the user's hair, facial and otherwise.
-// Slots.
-#define slot_back 1
-#define slot_wear_mask 2
-#define slot_handcuffed 3
-#define slot_l_hand 4
-#define slot_r_hand 5
-#define slot_belt 6
-#define slot_wear_id 7
-#define slot_l_ear 8
+// Slots as numbers //
+//Hands
+#define slot_l_hand 1
+#define slot_r_hand 2 //Some things may reference this, try to keep it here
+//Shown unless F12 pressed
+#define slot_back 3
+#define slot_belt 4
+#define slot_wear_id 5
+#define slot_s_store 6
+#define slot_l_store 7
+#define slot_r_store 8 //Some things may reference this, try to keep it here
+//Shown when inventory unhidden
#define slot_glasses 9
-#define slot_gloves 10
-#define slot_head 11
-#define slot_shoes 12
-#define slot_wear_suit 13
-#define slot_w_uniform 14
-#define slot_l_store 15
-#define slot_r_store 16
-#define slot_s_store 17
-#define slot_in_backpack 18
-#define slot_legcuffed 19
-#define slot_r_ear 20
-#define slot_legs 21
-#define slot_tie 22
+#define slot_wear_mask 10
+#define slot_gloves 11
+#define slot_head 12
+#define slot_shoes 13
+#define slot_wear_suit 14
+#define slot_w_uniform 15
+#define slot_l_ear 16
+#define slot_r_ear 17
+//Secret slots
+#define slot_legs 18
+#define slot_tie 19
+#define slot_handcuffed 20
+#define slot_legcuffed 21
+#define slot_in_backpack 22
+#define SLOT_TOTAL 22
// Inventory slot strings.
// since numbers cannot be used as associative list keys.
@@ -111,6 +118,21 @@
#define slot_w_uniform_str "slot_w_uniform"
#define slot_head_str "slot_head"
#define slot_wear_suit_str "slot_suit"
+#define slot_l_ear_str "slot_l_ear"
+#define slot_r_ear_str "slot_r_ear"
+#define slot_belt_str "slot_belt"
+#define slot_shoes_str "slot_shoes"
+#define slot_head_str "slot_head"
+#define slot_wear_mask_str "slot_wear_mask"
+#define slot_handcuffed_str "slot_handcuffed"
+#define slot_legcuffed_str "slot_legcuffed"
+#define slot_wear_mask_str "slot_wear_mask"
+#define slot_wear_id_str "slot_wear_id"
+#define slot_gloves_str "slot_gloves"
+#define slot_glasses_str "slot_glasses"
+#define slot_s_store_str "slot_s_store"
+#define slot_tie_str "slot_tie"
+
// Bitflags for clothing parts.
#define HEAD 0x1
diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm
index 6b05896b8d..00e473fc2a 100644
--- a/code/__defines/lighting.dm
+++ b/code/__defines/lighting.dm
@@ -9,7 +9,6 @@
#define LIGHTING_LAMBERTIAN 0 // use lambertian shading for light sources
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
-//#define LIGHTING_LAYER 10 // drawing layer for lighting overlays
#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
#define LIGHTING_ICON_STATE_DARK "soft_dark" // Change between "soft_dark" and "dark" to swap soft darkvision
diff --git a/code/__defines/math.dm b/code/__defines/math.dm
index 79dc1b4d24..3d64ba6c81 100644
--- a/code/__defines/math.dm
+++ b/code/__defines/math.dm
@@ -9,6 +9,10 @@
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
#define MIDNIGHT_ROLLOVER_CHECK ( rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : midnight_rollovers )
+#define SHORT_REAL_LIMIT 16777216 // 2^24 - Maximum integer that can be exactly represented in a float (BYOND num var)
+
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
+// Check if a BYOND dir var is a cardinal direction (power of two)
+#define IS_CARDINAL(x) ((x & (x - 1)) == 0)
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 44d0389d5a..f610c0c2a3 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -9,7 +9,8 @@
#define CANPARALYSE 0x4
#define CANPUSH 0x8
#define LEAPING 0x10
-#define PASSEMOTES 0x32 // Mob has a cortical borer or holders inside of it that need to see emotes.
+#define HIDING 0x20
+#define PASSEMOTES 0x40 // Mob has a cortical borer or holders inside of it that need to see emotes.
#define GODMODE 0x1000
#define FAKEDEATH 0x2000 // Replaces stuff like changeling.changeling_fakedeath.
#define DISFIGURED 0x4000 // Set but never checked. Remove this sometime and replace occurences with the appropriate organ code
@@ -115,9 +116,17 @@
#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi'
#define INV_W_UNIFORM_DEF_ICON 'icons/mob/uniform.dmi'
#define INV_ACCESSORIES_DEF_ICON 'icons/mob/ties.dmi'
-#define INV_SUIT_DEF_ICON 'icons/mob/ties.dmi'
+#define INV_TIE_DEF_ICON 'icons/mob/ties.dmi'
#define INV_SUIT_DEF_ICON 'icons/mob/suit.dmi'
-#define MAX_SUPPLIED_LAW_NUMBER 50
+#define INV_WEAR_ID_DEF_ICON 'icons/mob/mob.dmi'
+#define INV_GLOVES_DEF_ICON 'icons/mob/hands.dmi'
+#define INV_EYES_DEF_ICON 'icons/mob/eyes.dmi'
+#define INV_EARS_DEF_ICON 'icons/mob/ears.dmi'
+#define INV_FEET_DEF_ICON 'icons/mob/feet.dmi'
+#define INV_BELT_DEF_ICON 'icons/mob/belt.dmi'
+#define INV_MASK_DEF_ICON 'icons/mob/mask.dmi'
+#define INV_HCUFF_DEF_ICON 'icons/mob/mob.dmi'
+#define INV_LCUFF_DEF_ICON 'icons/mob/mob.dmi'
// Character's economic class
#define CLASS_UPPER "Wealthy"
@@ -235,6 +244,44 @@
#define FBP_POSI "Positronic"
#define FBP_DRONE "Drone"
+// 'Regular' species.
+#define SPECIES_HUMAN "Human"
+#define SPECIES_HUMAN_VATBORN "Vatborn"
+#define SPECIES_UNATHI "Unathi"
+#define SPECIES_SKRELL "Skrell"
+#define SPECIES_TESHARI "Teshari"
+#define SPECIES_TAJ "Tajara"
+#define SPECIES_PROMETHEAN "Promethean"
+#define SPECIES_DIONA "Diona"
+#define SPECIES_VOX "Vox"
+
+// Monkey and alien monkeys.
+#define SPECIES_MONKEY "Monkey"
+#define SPECIES_MONKEY_TAJ "Farwa"
+#define SPECIES_MONKEY_SKRELL "Neaera"
+#define SPECIES_MONKEY_UNATHI "Stok"
+
+// Virtual Reality IDs.
+#define SPECIES_VR "Virtual Reality Avatar"
+#define SPECIES_VR_HUMAN "Virtual Reality Human"
+#define SPECIES_VR_UNATHI "Virtual Reality Unathi"
+#define SPECIES_VR_TAJ "Virtual Reality Tajara" // NO CHANGING.
+#define SPECIES_VR_SKRELL "Virtual Reality Skrell"
+#define SPECIES_VR_TESHARI "Virtual Reality Teshari"
+#define SPECIES_VR_DIONA "Virtual Reality Diona"
+
+// Ayyy IDs.
+#define SPECIES_XENO "Xenomorph"
+#define SPECIES_XENO_DRONE "Xenomorph Drone"
+#define SPECIES_XENO_HUNTER "Xenomorph Hunter"
+#define SPECIES_XENO_SENTINEL "Xenomorph Sentinel"
+#define SPECIES_XENO_QUEEN "Xenomorph Queen"
+
+// Misc species. Mostly unused but might as well be complete.
+#define SPECIES_SHADOW "Shadow"
+#define SPECIES_SKELETON "Skeleton"
+#define SPECIES_GOLEM "Golem"
+
// Used to seperate simple animals by ""intelligence"".
#define SA_PLANT 1
#define SA_ANIMAL 2
@@ -272,4 +319,7 @@
#define VIS_MESONS 20
-#define VIS_COUNT 20 //Must be highest number from above.
\ No newline at end of file
+#define VIS_COUNT 20 //Must be highest number from above.
+
+//Some mob icon layering defines
+#define BODY_LAYER -100
diff --git a/code/__defines/sound.dm b/code/__defines/sound.dm
new file mode 100644
index 0000000000..6fae2fadcb
--- /dev/null
+++ b/code/__defines/sound.dm
@@ -0,0 +1,56 @@
+//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
+#define CHANNEL_LOBBYMUSIC 1024
+#define CHANNEL_ADMIN 1023
+#define CHANNEL_VOX 1022
+#define CHANNEL_JUKEBOX 1021
+#define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats
+#define CHANNEL_AMBIENCE_FORCED 1019
+#define CHANNEL_AMBIENCE 1018
+#define CHANNEL_BUZZ 1017
+#define CHANNEL_BICYCLE 1016
+
+//THIS SHOULD ALWAYS BE THE LOWEST ONE!
+//KEEP IT UPDATED
+
+#define CHANNEL_HIGHEST_AVAILABLE 1015
+
+#define SOUND_MINIMUM_PRESSURE 10
+#define FALLOFF_SOUNDS 0.5
+
+//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more.
+#define GENERIC 0
+#define PADDED_CELL 1
+#define ROOM 2
+#define BATHROOM 3
+#define LIVINGROOM 4
+#define STONEROOM 5
+#define AUDITORIUM 6
+#define CONCERT_HALL 7
+#define CAVE 8
+#define ARENA 9
+#define HANGAR 10
+#define CARPETED_HALLWAY 11
+#define HALLWAY 12
+#define STONE_CORRIDOR 13
+#define ALLEY 14
+#define FOREST 15
+#define CITY 16
+#define MOUNTAINS 17
+#define QUARRY 18
+#define PLAIN 19
+#define PARKING_LOT 20
+#define SEWER_PIPE 21
+#define UNDERWATER 22
+#define DRUGGED 23
+#define DIZZY 24
+#define PSYCHOTIC 25
+
+#define STANDARD_STATION STONEROOM
+#define LARGE_ENCLOSED HANGAR
+#define SMALL_ENCLOSED BATHROOM
+#define TUNNEL_ENCLOSED CAVE
+#define LARGE_SOFTFLOOR CARPETED_HALLWAY
+#define MEDIUM_SOFTFLOOR LIVINGROOM
+#define SMALL_SOFTFLOOR ROOM
+#define ASTEROID CAVE
+#define SPACE UNDERWATER
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 5cfb5f37d0..87f1f9b3ca 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -45,6 +45,10 @@
#define LANGUAGE_OCCULT "Occult"
#define LANGUAGE_CHANGELING "Changeling"
#define LANGUAGE_VOX "Vox-Pidgin"
+#define LANGUAGE_TERMINUS "Terminus"
+#define LANGUAGE_SKRELLIANFAR "High Skrellian"
+#define LANGUAGE_MINBUS "Minbus"
+#define LANGUAGE_AKHANI "Akhani"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
diff --git a/code/__defines/stat_tracking.dm b/code/__defines/stat_tracking.dm
new file mode 100644
index 0000000000..79337bda5c
--- /dev/null
+++ b/code/__defines/stat_tracking.dm
@@ -0,0 +1,17 @@
+//
+// Defines used for advanced performance profiling of subsystems.
+// Currently used only by SSoverlays (2018-02-24 ~Leshana)
+//
+#define STAT_ENTRY_TIME 1
+#define STAT_ENTRY_COUNT 2
+#define STAT_ENTRY_LENGTH 2
+
+#define STAT_START_STOPWATCH var/STAT_STOP_WATCH = TICK_USAGE
+#define STAT_STOP_STOPWATCH var/STAT_TIME = TICK_USAGE_TO_MS(STAT_STOP_WATCH)
+#define STAT_LOG_ENTRY(entrylist, entryname) \
+ var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH));\
+ STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME;\
+ var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT));\
+ if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) {\
+ STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT;\
+ };\
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index faddb9d917..2e290e5045 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -28,5 +28,35 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_MACHINES 10
#define INIT_ORDER_SHUTTLES 3
#define INIT_ORDER_LIGHTING 0
-#define INIT_ORDER_AIR -1
+#define INIT_ORDER_AIR -1
+#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_XENOARCH -20
+
+
+// Subsystem fire priority, from lowest to highest priority
+// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
+
+ #define FIRE_PRIORITY_OVERLAYS 500
+
+// Macro defining the actual code applying our overlays lists to the BYOND overlays list. (I guess a macro for speed)
+// TODO - I don't really like the location of this macro define. Consider it. ~Leshana
+#define COMPILE_OVERLAYS(A)\
+ if (TRUE) {\
+ var/list/oo = A.our_overlays;\
+ var/list/po = A.priority_overlays;\
+ if(LAZYLEN(po)){\
+ if(LAZYLEN(oo)){\
+ A.overlays = oo + po;\
+ }\
+ else{\
+ A.overlays = po;\
+ }\
+ }\
+ else if(LAZYLEN(oo)){\
+ A.overlays = oo;\
+ }\
+ else{\
+ A.overlays.Cut();\
+ }\
+ A.flags &= ~OVERLAY_QUEUED;\
+ }
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 72937092c4..95f8dcdbe7 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -31,8 +31,8 @@ var/global/list/turfs = list() //list of all turfs
var/global/list/all_species[0]
var/global/list/all_languages[0]
var/global/list/language_keys[0] // Table of say codes for all languages
-var/global/list/whitelisted_species = list("Human") // Species that require a whitelist check.
-var/global/list/playable_species = list("Human") // A list of ALL playable species, whitelisted, latejoin or otherwise.
+var/global/list/whitelisted_species = list(SPECIES_HUMAN) // Species that require a whitelist check.
+var/global/list/playable_species = list(SPECIES_HUMAN) // A list of ALL playable species, whitelisted, latejoin or otherwise.
var/list/mannequins_
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index e2096753a0..da4385ef6f 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -634,175 +634,211 @@ as a single icon. Useful for when you want to manipulate an icon via the above a
The _flatIcons list is a cache for generated icon files.
*/
-proc // Creates a single icon from a given /atom or /image. Only the first argument is required.
- getFlatIcon(image/A, defdir=2, deficon=null, defstate="", defblend=BLEND_DEFAULT, always_use_defdir = 0, picture_planes = list(PLANE_WORLD))
- // We start with a blank canvas, otherwise some icon procs crash silently
- var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon
- if(!A)
- return flat
- if(A.alpha <= 0)
- return flat
- var/noIcon = FALSE
+// Creates a single icon from a given /atom or /image. Only the first argument is required.
+/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
+ // We start with a blank canvas, otherwise some icon procs crash silently
+ var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon
+ if(!A)
+ return flat
+ if(A.alpha <= 0)
+ return flat
+ var/noIcon = FALSE
- var/curicon
- if(A.icon)
- curicon = A.icon
+ if(start)
+ if(!defdir)
+ defdir = A.dir
+ if(!deficon)
+ deficon = A.icon
+ if(!defstate)
+ defstate = A.icon_state
+ if(!defblend)
+ defblend = A.blend_mode
+
+ var/curicon
+ if(A.icon)
+ curicon = A.icon
+ else
+ curicon = deficon
+
+ if(!curicon)
+ noIcon = TRUE // Do not render this object.
+
+ var/curstate
+ if(A.icon_state)
+ curstate = A.icon_state
+ else
+ curstate = defstate
+
+ if(!noIcon && !(curstate in icon_states(curicon)))
+ if("" in icon_states(curicon))
+ curstate = ""
else
- curicon = deficon
-
- if(!curicon)
noIcon = TRUE // Do not render this object.
- var/curstate
- if(A.icon_state)
- curstate = A.icon_state
- else
- curstate = defstate
+ var/curdir
+ var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
+
+ //These should use the parent's direction (most likely)
+ if(!A.dir || A.dir == SOUTH)
+ curdir = defdir
+ else
+ curdir = A.dir
- if(!noIcon && !(curstate in icon_states(curicon)))
- if("" in icon_states(curicon))
- curstate = ""
- else
- noIcon = TRUE // Do not render this object.
+ //Let's check if the icon actually contains any diagonals, just skip if it's south to save (lot of) time
+ if(curdir != SOUTH)
+ var/icon/test_icon
+ var/directionals_exist = FALSE
+ var/list/dirs_to_check = cardinal - SOUTH
+ outer:
+ for(var/possible_dir in dirs_to_check)
+ test_icon = icon(curicon,curstate,possible_dir,frame=1)
+ for(var/x in 1 to world.icon_size)
+ for(var/y in 1 to world.icon_size)
+ if(!isnull(test_icon.GetPixel(x,y)))
+ directionals_exist = TRUE
+ break outer
+ if(!directionals_exist)
+ base_icon_dir = SOUTH
+ if(!base_icon_dir)
+ base_icon_dir = curdir
- var/curdir
- if(A.dir != 2 && !always_use_defdir)
- curdir = A.dir
- else
- curdir = defdir
+ var/curblend
+ if(A.blend_mode == BLEND_DEFAULT)
+ curblend = defblend
+ else
+ curblend = A.blend_mode
- var/curblend
- if(A.blend_mode == BLEND_DEFAULT)
- curblend = defblend
- else
- curblend = A.blend_mode
+ // Before processing overlays, make sure any pending overlays are applied
+ if (isloc(A))
+ var/atom/aAtom = A
+ if(aAtom.flags & OVERLAY_QUEUED)
+ COMPILE_OVERLAYS(aAtom)
- // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
- var/list/layers = list()
- var/image/copy
- // Add the atom's icon itself, without pixel_x/y offsets.
- if(!noIcon)
- copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir)
- copy.color = A.color
- copy.alpha = A.alpha
- copy.blend_mode = curblend
- layers[copy] = A.layer
-
- // Loop through the underlays, then overlays, sorting them into the layers list
- var/list/process = A.underlays // Current list being processed
- var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays
- var/curIndex=1 // index of 'current' in list being processed
- var/current // Current overlay being sorted
- var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER)
- var/compare // The overlay 'add' is being compared against
- var/cmpIndex // The index in the layers list of 'compare'
- while(TRUE)
- if(curIndex<=process.len)
- current = process[curIndex]
- if(current)
- var/currentPlane = current:plane
- if (currentPlane != FLOAT_PLANE && !(currentPlane in picture_planes))
- curIndex++
- continue;
- currentLayer = current:layer
- if(currentLayer<0) // Special case for FLY_LAYER
- if(currentLayer <= -1000) return flat
- if(pSet == 0) // Underlay
- currentLayer = A.layer+currentLayer/1000
- else // Overlay
- currentLayer = A.layer+(1000+currentLayer)/1000
-
- // Sort add into layers list
- for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++)
- compare = layers[cmpIndex]
- if(currentLayer < layers[compare]) // Associated value is the calculated layer
- layers.Insert(cmpIndex,current)
- layers[current] = currentLayer
- break
- if(cmpIndex>layers.len) // Reached end of list without inserting
- layers[current]=currentLayer // Place at end
+ // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
+ var/list/layers = list()
+ var/image/copy
+ // Add the atom's icon itself, without pixel_x/y offsets.
+ if(!noIcon)
+ copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir)
+ copy.color = A.color
+ copy.alpha = A.alpha
+ copy.blend_mode = curblend
+ layers[copy] = A.layer
+ // Loop through the underlays, then overlays, sorting them into the layers list
+ var/list/process = A.underlays // Current list being processed
+ var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays
+ var/curIndex=1 // index of 'current' in list being processed
+ var/current // Current overlay being sorted
+ var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER)
+ var/compare // The overlay 'add' is being compared against
+ var/cmpIndex // The index in the layers list of 'compare'
+ while(TRUE)
+ if(curIndex<=process.len)
+ current = process[curIndex]
+ if(!current)
+ curIndex++ //Try the next layer
+ continue
+ var/image/I = current
+ if(I.plane != FLOAT_PLANE && I.plane != A.plane)
curIndex++
- else if(pSet == 0) // Switch to overlays
+ continue
+ currentLayer = I.layer
+ if(currentLayer<0) // Special case for FLOAT_LAYER
+ if(currentLayer <= -1000)
+ return flat
+ if(pSet == 0) // Underlay
+ currentLayer = A.layer+currentLayer/1000
+ else // Overlay
+ currentLayer = A.layer+(1000+currentLayer)/1000
+
+ // Sort add into layers list
+ for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++)
+ compare = layers[cmpIndex]
+ if(currentLayer < layers[compare]) // Associated value is the calculated layer
+ layers.Insert(cmpIndex,current)
+ layers[current] = currentLayer
+ break
+ if(cmpIndex>layers.len) // Reached end of list without inserting
+ layers[current]=currentLayer // Place at end
+
+ curIndex++
+
+ if(curIndex>process.len)
+ if(pSet == 0) // Switch to overlays
curIndex = 1
pSet = 1
process = A.overlays
else // All done
break
- var/icon/add // Icon of overlay being added
+ var/icon/add // Icon of overlay being added
- // Current dimensions of flattened icon
- var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()}
- // Dimensions of overlay being added
- var/{addX1;addX2;addY1;addY2}
+ // Current dimensions of flattened icon
+ var/flatX1=1
+ var/flatX2=flat.Width()
+ var/flatY1=1
+ var/flatY2=flat.Height()
+ // Dimensions of overlay being added
+ var/addX1
+ var/addX2
+ var/addY1
+ var/addY2
- for(var/I in layers)
+ for(var/V in layers)
+ var/image/I = V
+ if(I.alpha == 0)
+ continue
- if(I:alpha == 0)
- continue
+ if(I == copy) // 'I' is an /image based on the object being flattened.
+ curblend = BLEND_OVERLAY
+ add = icon(I.icon, I.icon_state, base_icon_dir)
+ else // 'I' is an appearance object.
+ add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, FALSE, no_anim)
- if(I == copy) // 'I' is an /image based on the object being flattened.
- curblend = BLEND_OVERLAY
- add = icon(I:icon, I:icon_state, I:dir)
- // This checks for a silent failure mode of the icon routine. If the requested dir
- // doesn't exist in this icon state it returns a 32x32 icon with 0 alpha.
- if (I:dir != SOUTH && add.Width() == 32 && add.Height() == 32)
- // Check every pixel for blank (computationally expensive, but the process is limited
- // by the amount of film on the station, only happens when we hit something that's
- // turned, and bails at the very first pixel it sees.
- var/blankpixel;
- for(var/y;y<=32;y++)
- for(var/x;x<32;x++)
- blankpixel = isnull(add.GetPixel(x,y))
- if(!blankpixel)
- break
- if(!blankpixel)
- break
- // If we ALWAYS returned a null (which happens when GetPixel encounters something with alpha 0)
- if (blankpixel)
- // Pull the default direction.
- add = icon(I:icon, I:icon_state)
- else // 'I' is an appearance object.
- add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend, picture_planes = picture_planes)
+ // Find the new dimensions of the flat icon to fit the added overlay
+ addX1 = min(flatX1, I.pixel_x+1)
+ addX2 = max(flatX2, I.pixel_x+add.Width())
+ addY1 = min(flatY1, I.pixel_y+1)
+ addY2 = max(flatY2, I.pixel_y+add.Height())
- // Find the new dimensions of the flat icon to fit the added overlay
- addX1 = min(flatX1, I:pixel_x+1)
- addX2 = max(flatX2, I:pixel_x+add.Width())
- addY1 = min(flatY1, I:pixel_y+1)
- addY2 = max(flatY2, I:pixel_y+add.Height())
+ if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
+ // Resize the flattened icon so the new icon fits
+ flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1)
+ flatX1=addX1;flatX2=addX2
+ flatY1=addY1;flatY2=addY2
- if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
- // Resize the flattened icon so the new icon fits
- flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1)
- flatX1=addX1;flatX2=addX2
- flatY1=addY1;flatY2=addY2
+ // Blend the overlay into the flattened icon
+ flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
- // Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1)
-
- if(A.color)
- flat.Blend(A.color, ICON_MULTIPLY)
- if(A.alpha < 255)
- flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(A.color)
+ flat.Blend(A.color, ICON_MULTIPLY)
+ if(A.alpha < 255)
+ flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(no_anim)
+ //Clean up repeated frames
+ var/icon/cleaned = new /icon()
+ cleaned.Insert(flat, "", SOUTH, 1, 0)
+ return cleaned
+ else
return icon(flat, "", SOUTH)
- getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
- var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
- for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
- if(I:layer>A.layer) continue//If layer is greater than what we need, skip it.
- var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects.
- //Also, icons cannot directly set icon_state. Slower than changing variables but whatever.
- alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay.
- return alpha_mask//And now return the mask.
+/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
+ var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
+ for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
+ if(I:layer>A.layer) continue//If layer is greater than what we need, skip it.
+ var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects.
+ //Also, icons cannot directly set icon_state. Slower than changing variables but whatever.
+ alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay.
+ return alpha_mask//And now return the mask.
//getFlatIcon but generates an icon that can face ALL four directions. The only four.
/proc/getCompoundIcon(atom/A)
- var/icon/north = getFlatIcon(A,defdir=NORTH,always_use_defdir=1)
- var/icon/south = getFlatIcon(A,defdir=SOUTH,always_use_defdir=1)
- var/icon/east = getFlatIcon(A,defdir=EAST,always_use_defdir=1)
- var/icon/west = getFlatIcon(A,defdir=WEST,always_use_defdir=1)
+ var/icon/north = getFlatIcon(A,defdir=NORTH)
+ var/icon/south = getFlatIcon(A,defdir=SOUTH)
+ var/icon/east = getFlatIcon(A,defdir=EAST)
+ var/icon/west = getFlatIcon(A,defdir=WEST)
//Starts with a blank icon because of byond bugs.
var/icon/full = icon('icons/effects/effects.dmi', "icon_state"="nothing")
@@ -818,7 +854,7 @@ proc // Creates a single icon from a given /atom or /image. Only the first argu
return full
/proc/downloadImage(atom/A, dir)
- var/icon/this_icon = getFlatIcon(A,defdir=dir||A.dir,always_use_defdir=1)
+ var/icon/this_icon = getFlatIcon(A,defdir=dir)
usr << ftp(this_icon,"[A.name].png")
@@ -886,5 +922,80 @@ proc/sort_atoms_by_layer(var/list/atoms)
/proc/gen_hud_image(var/file, var/person, var/state, var/plane)
var/image/img = image(file, person, state)
img.plane = plane //Thanks Byond.
- img.appearance_flags = APPEARANCE_UI|KEEP_APART
+ img.layer = MOB_LAYER-0.2
+ img.appearance_flags = APPEARANCE_UI
return img
+
+/**
+* Animate a 'halo' around an object.
+*
+* This proc is not exactly cheap. You'd be well advised to set up many-loops rather than call this super-often. getCompoundIcon is
+* mostly to blame for this. If Byond ever implements a way to get something's icon more 'gently' than this, do that instead.
+*
+* @param A This is the atom to put the halo on
+* @param simple_icons If set to TRUE, will just perform a very basic icon and icon_state steal. DO USE when possible.
+* @param color This is the color for the halo
+* @param anim_duration This decides how fast (or slow) the animation plays
+* @param offset Mysterious variable that determines size of the halo's gap from icon
+* @param loops How many times the animation loops
+* @param grow_to Relative to the size of the icon, how big the halo grows while fading (don't use negatives for inward halos, use < 1)
+* @param pixel_scale If you'd like the halo to use pixel scale or the default 'fuzzy' scale
+*/
+/proc/animate_aura(var/atom/A, var/simple_icons, var/color = "#00FF22", var/anim_duration = 5, var/offset = 1, var/loops = 1, var/grow_to = 2, var/pixel_scale = FALSE)
+ ASSERT(A)
+
+ //Take a guess at this, if they didn't set it
+ if(isnull(simple_icons))
+ if(ismob(A))
+ simple_icons = FALSE
+ else
+ simple_icons = TRUE
+
+ //Get their icon
+ var/icon/hole
+
+ if(simple_icons)
+ hole = icon(A.icon, A.icon_state)
+ else
+ hole = getCompoundIcon(A)
+
+ hole.MapColors(0,0,0, 0,0,0, 0,0,0, 1,1,1) //White.
+
+ //Make a bigger version
+ var/icon/grower = new(hole)
+ var/orig_width = grower.Width()
+ var/orig_height = grower.Height()
+ var/end_width = orig_width+(offset*2)
+ var/end_height = orig_height+(offset*2)
+ var/half_diff_width = (end_width-orig_width)*0.5
+ var/half_diff_height = (end_height-orig_height)*0.5
+
+ //Make icon black
+ grower.SwapColor("#FFFFFF","#000000") //Black.
+
+ //Scale both icons big so we don't have to deal with low-pixel garbage issues
+ grower.Scale(orig_width*10,orig_height*10)
+ hole.Scale(orig_width*9,orig_height*9)
+
+ //Blend the hole in
+ grower.Blend(hole,ICON_OVERLAY, x = ((orig_width*10-orig_width*9)*0.5)+1, y = ((orig_height*10-orig_height*9)*0.5)+1)
+
+ //Swap white to zero alpha
+ grower.SwapColor("#FFFFFF","#00000000")
+
+ //Color it
+ grower.SwapColor("#000000",color)
+
+ //Scale it to final height
+ grower.Scale(end_width,end_height)
+
+ //Flick it onto them
+ var/image/img = image(grower,A)
+ if(pixel_scale)
+ img.appearance_flags |= PIXEL_SCALE
+ img.pixel_x = half_diff_width*-1
+ img.pixel_y = half_diff_height*-1
+ flick_overlay_view(img, A, anim_duration*loops, TRUE)
+
+ //Animate it growing
+ animate(img, alpha = 0, transform = matrix()*grow_to, time = anim_duration, loop = loops)
diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm
index cd42c84224..6644cc2efe 100644
--- a/code/_helpers/logging.dm
+++ b/code/_helpers/logging.dm
@@ -25,9 +25,14 @@
if (config.log_admin)
diary << "\[[time_stamp()]]ADMIN: [text][log_end]"
+/proc/log_adminpm(text, client/source, client/dest)
+ admin_log.Add(text)
+ if (config.log_admin)
+ diary << "\[[time_stamp()]]ADMINPM: [key_name(source)]->[key_name(dest)]: [html_decode(text)][log_end]"
+
/proc/log_debug(text)
if (config.log_debug)
- diary << "\[[time_stamp()]]DEBUG: [text][log_end]"
+ debug_log << "\[[time_stamp()]]DEBUG: [text][log_end]"
for(var/client/C in admins)
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
@@ -41,47 +46,81 @@
if (config.log_vote)
diary << "\[[time_stamp()]]VOTE: [text][log_end]"
-/proc/log_access(text)
+/proc/log_access_in(client/new_client)
if (config.log_access)
- diary << "\[[time_stamp()]]ACCESS: [text][log_end]"
+ var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]"
+ diary << "\[[time_stamp()]]ACCESS IN: [message][log_end]"
-/proc/log_say(text)
+/proc/log_access_out(mob/last_mob)
+ if (config.log_access)
+ var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:Logged Out - BYOND Logged Out"
+ diary << "\[[time_stamp()]]ACCESS OUT: [message][log_end]"
+
+/proc/log_say(text, mob/speaker)
if (config.log_say)
- diary << "\[[time_stamp()]]SAY: [text][log_end]"
+ diary << "\[[time_stamp()]]SAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
-/proc/log_ooc(text)
+/proc/log_ooc(text, client/user)
if (config.log_ooc)
- diary << "\[[time_stamp()]]OOC: [text][log_end]"
+ diary << "\[[time_stamp()]]OOC: [user.simple_info_line()]: [html_decode(text)][log_end]"
-/proc/log_whisper(text)
+/proc/log_aooc(text, client/user)
+ if (config.log_ooc)
+ diary << "\[[time_stamp()]]AOOC: [user.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_looc(text, client/user)
+ if (config.log_ooc)
+ diary << "\[[time_stamp()]]LOOC: [user.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_whisper(text, mob/speaker)
if (config.log_whisper)
- diary << "\[[time_stamp()]]WHISPER: [text][log_end]"
+ diary << "\[[time_stamp()]]WHISPER: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
-/proc/log_emote(text)
+/proc/log_emote(text, mob/speaker)
if (config.log_emote)
- diary << "\[[time_stamp()]]EMOTE: [text][log_end]"
+ diary << "\[[time_stamp()]]EMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
-/proc/log_attack(text)
+/proc/log_attack(attacker, defender, message)
if (config.log_attack)
- diary << "\[[time_stamp()]]ATTACK: [text][log_end]" //Seperate attack logs? Why? FOR THE GLORY OF SATAN!
+ diary << "\[[time_stamp()]]ATTACK: [attacker] against [defender]: [message][log_end]"
-/proc/log_adminsay(text)
+/proc/log_adminsay(text, mob/speaker)
if (config.log_adminchat)
- diary << "\[[time_stamp()]]ADMINSAY: [text][log_end]"
+ diary << "\[[time_stamp()]]ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_modsay(text, mob/speaker)
+ if (config.log_adminchat)
+ diary << "\[[time_stamp()]]MODSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_eventsay(text, mob/speaker)
+ if (config.log_adminchat)
+ diary << "\[[time_stamp()]]EVENTSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_ghostsay(text, mob/speaker)
+ if (config.log_say)
+ diary << "\[[time_stamp()]]DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
+
+/proc/log_ghostemote(text, mob/speaker)
+ if (config.log_emote)
+ diary << "\[[time_stamp()]]DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
/proc/log_adminwarn(text)
if (config.log_adminwarn)
- diary << "\[[time_stamp()]]ADMINWARN: [text][log_end]"
+ diary << "\[[time_stamp()]]ADMINWARN: [html_decode(text)][log_end]"
-/proc/log_pda(text)
+/proc/log_pda(text, mob/speaker)
if (config.log_pda)
- diary << "\[[time_stamp()]]PDA: [text][log_end]"
+ diary << "\[[time_stamp()]]PDA: [speaker.simple_info_line()]: [html_decode(text)][log_end]"
/proc/log_to_dd(text)
world.log << text //this comes before the config check because it can't possibly runtime
if(config.log_world_output)
diary << "\[[time_stamp()]]DD_OUTPUT: [text][log_end]"
+/proc/log_error(text)
+ world.log << text
+ error_log << "\[[time_stamp()]]RUNTIME: [text][log_end]"
+
/proc/log_misc(text)
diary << "\[[time_stamp()]]MISC: [text][log_end]"
@@ -105,12 +144,14 @@
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
//more or less a logging utility
-/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/highlight_special_characters = 1)
+//Always return "Something/(Something)", even if it's an error message.
+/proc/key_name(var/whom, var/include_link = FALSE, var/include_name = TRUE, var/highlight_special_characters = TRUE)
var/mob/M
var/client/C
var/key
- if(!whom) return "*null*"
+ if(!whom)
+ return "INVALID/INVALID"
if(istype(whom, /client))
C = whom
M = C.mob
@@ -127,9 +168,11 @@
C = D.current.client
else if(istype(whom, /datum))
var/datum/D = whom
- return "*invalid:[D.type]*"
+ return "INVALID/([D.type])"
+ else if(istext(whom))
+ return "AUTOMATED/[whom]" //Just give them the text back
else
- return "*invalid*"
+ return "INVALID/INVALID"
. = ""
@@ -137,7 +180,7 @@
if(include_link && C)
. += ""
- if(C && C.holder && C.holder.fakekey && !include_name)
+ if(C && C.holder && C.holder.fakekey)
. += "Administrator"
else
. += key
@@ -146,21 +189,20 @@
if(C) . += ""
else . += " (DC)"
else
- . += "*no key*"
+ . += "INVALID"
- if(include_name && M)
- var/name
+ if(include_name)
+ var/name = "INVALID"
+ if(M)
+ if(M.real_name)
+ name = M.real_name
+ else if(M.name)
+ name = M.name
- if(M.real_name)
- name = M.real_name
- else if(M.name)
- name = M.name
-
-
- if(include_link && is_special_character(M) && highlight_special_characters)
- . += "/([name])" //Orange
- else
- . += "/([name])"
+ if(include_link && is_special_character(M) && highlight_special_characters)
+ name = "[name]" //Orange
+
+ . += "/([name])"
return .
@@ -187,3 +229,9 @@
if(!istype(d))
return
return d.log_info_line()
+
+/mob/proc/simple_info_line()
+ return "[key_name(src)] ([x],[y],[z])"
+
+/client/proc/simple_info_line()
+ return "[key_name(src)] ([mob.x],[mob.y],[mob.z])"
diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm
index e1215bb901..e82e618651 100644
--- a/code/_helpers/mobs.dm
+++ b/code/_helpers/mobs.dm
@@ -33,7 +33,7 @@
return mobs
-proc/random_hair_style(gender, species = "Human")
+proc/random_hair_style(gender, species = SPECIES_HUMAN)
var/h_style = "Bald"
var/list/valid_hairstyles = list()
@@ -52,7 +52,7 @@ proc/random_hair_style(gender, species = "Human")
return h_style
-proc/random_facial_hair_style(gender, species = "Human")
+proc/random_facial_hair_style(gender, species = SPECIES_HUMAN)
var/f_style = "Shaved"
var/list/valid_facialhairstyles = list()
@@ -72,14 +72,14 @@ proc/random_facial_hair_style(gender, species = "Human")
return f_style
-proc/sanitize_name(name, species = "Human", robot = 0)
+proc/sanitize_name(name, species = SPECIES_HUMAN, robot = 0)
var/datum/species/current_species
if(species)
current_species = all_species[species]
return current_species ? current_species.sanitize_name(name, robot) : sanitizeName(name, MAX_NAME_LEN, robot)
-proc/random_name(gender, species = "Human")
+proc/random_name(gender, species = SPECIES_HUMAN)
var/datum/species/current_species
if(species)
@@ -145,13 +145,23 @@ Proc for attack log creation, because really why not
6 is additional information, anything that needs to be added
*/
-/proc/add_logs(mob/user, mob/target, what_done, var/admin=1, var/object=null, var/addition=null)
- if(user && ismob(user))
- user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]")
- if(target && ismob(target))
- target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]")
- if(admin)
- log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]")
+/proc/add_attack_logs(mob/user, mob/target, what_done, var/admin_notify = TRUE)
+ if(islist(target)) //Multi-victim adding
+ var/list/targets = target
+ for(var/mob/M in targets)
+ add_attack_logs(user,M,what_done,admin_notify)
+ return
+
+ var/user_str = key_name(user)
+ var/target_str = key_name(target)
+
+ if(ismob(user))
+ user.attack_log += text("\[[time_stamp()]\] Attacked [target_str]: [what_done]")
+ if(ismob(target))
+ target.attack_log += text("\[[time_stamp()]\] Attacked by [user_str]: [what_done]")
+ log_attack(user_str,target_str,what_done)
+ if(admin_notify)
+ msg_admin_attack("[key_name_admin(user)] vs [target_str]: [what_done]")
//checks whether this item is a module of the robot it is located in.
/proc/is_robot_module(var/obj/item/thing)
@@ -213,6 +223,8 @@ Proc for attack log creation, because really why not
/proc/do_after(mob/user, delay, atom/target = null, needhand = 1, progress = 1, var/incapacitation_flags = INCAPACITATION_DEFAULT)
if(!user)
return 0
+ if(!delay)
+ return 1 //Okay. Done.
var/atom/target_loc = null
if(target)
target_loc = target.loc
@@ -264,3 +276,16 @@ Proc for attack log creation, because really why not
humans += H
return humans
+
+/proc/getviewsize(view)
+ var/viewX
+ var/viewY
+ if(isnum(view))
+ var/totalviewrange = 1 + 2 * view
+ viewX = totalviewrange
+ viewY = totalviewrange
+ else
+ var/list/viewrangelist = splittext(view,"x")
+ viewX = text2num(viewrangelist[1])
+ viewY = text2num(viewrangelist[2])
+ return list(viewX, viewY)
diff --git a/code/_helpers/sorts/comparators.dm b/code/_helpers/sorts/comparators.dm
index 1b4b834692..7fd07ec711 100644
--- a/code/_helpers/sorts/comparators.dm
+++ b/code/_helpers/sorts/comparators.dm
@@ -36,3 +36,9 @@
. = b.head_position - a.head_position
if (. == 0) //Already in head/nothead spot, sort by name
. = sorttext(b.title, a.title)
+
+// Sorts entries in a performance stats list.
+/proc/cmp_generic_stat_item_time(list/A, list/B)
+ . = B[STAT_ENTRY_TIME] - A[STAT_ENTRY_TIME]
+ if (!.)
+ . = B[STAT_ENTRY_COUNT] - A[STAT_ENTRY_COUNT]
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 6dad42e128..58348761f8 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -58,8 +58,11 @@ var/next_station_date_change = 1 DAY
station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD")
return station_date
+//ISO 8601
/proc/time_stamp()
- return time2text(station_time_in_ticks, "hh:mm:ss")
+ var/date_portion = time2text(world.timeofday, "YYYY-MM-DD")
+ var/time_portion = time2text(world.timeofday, "hh:mm:ss")
+ return "[date_portion]T[time_portion]"
/* Returns 1 if it is the selected month and day */
proc/isDay(var/month, var/day)
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 3d3877ab5b..41aa04a5c0 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -509,6 +509,16 @@ Turf and target are seperate in case you want to teleport some distance from a t
// mob_list.Add(M)
return moblist
+// Format a power value in W, kW, MW, or GW.
+/proc/DisplayPower(powerused)
+ if(powerused < 1000) //Less than a kW
+ return "[powerused] W"
+ else if(powerused < 1000000) //Less than a MW
+ return "[round((powerused * 0.001),0.01)] kW"
+ else if(powerused < 1000000000) //Less than a GW
+ return "[round((powerused * 0.000001),0.001)] MW"
+ return "[round((powerused * 0.000000001),0.0001)] GW"
+
//Forces a variable to be posative
/proc/modulus(var/M)
if(M >= 0)
@@ -790,7 +800,6 @@ proc/GaussRandRound(var/sigma,var/roundto)
var/old_dir1 = T.dir
var/old_icon_state1 = T.icon_state
var/old_icon1 = T.icon
- var/old_overlays = T.overlays.Copy()
var/old_underlays = T.underlays.Copy()
var/old_decals = T.decals ? T.decals.Copy() : null
@@ -798,11 +807,9 @@ proc/GaussRandRound(var/sigma,var/roundto)
X.set_dir(old_dir1)
X.icon_state = old_icon_state1
X.icon = old_icon1
- X.overlays = old_overlays
+ X.copy_overlays(T, TRUE)
X.underlays = old_underlays
X.decals = old_decals
- if(old_decals)
- X.apply_decals()
//Move the air from source to dest
var/turf/simulated/ST = T
@@ -828,14 +835,10 @@ proc/GaussRandRound(var/sigma,var/roundto)
if(shuttlework)
var/turf/simulated/shuttle/SS = T
SS.landed_holder.leave_turf()
-
else if(turftoleave)
T.ChangeTurf(turftoleave)
- T.apply_decals()
-
else
T.ChangeTurf(get_base_turf_by_area(T))
- T.apply_decals()
refined_src -= T
refined_trg -= B
@@ -1419,4 +1422,51 @@ var/mob/dview/dview_mob = new
return USE_FAIL_NOT_IN_USER
#undef NOT_FLAG
-#undef HAS_FLAG
\ No newline at end of file
+#undef HAS_FLAG
+
+// Returns direction-string, rounded to multiples of 22.5, from the first parameter to the second
+// N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW
+/proc/get_adir(var/turf/A, var/turf/B)
+ var/degree = Get_Angle(A, B)
+ switch(round(degree%360, 22.5))
+ if(0)
+ return "North"
+ if(22.5)
+ return "North-Northeast"
+ if(45)
+ return "Northeast"
+ if(67.5)
+ return "East-Northeast"
+ if(90)
+ return "East"
+ if(112.5)
+ return "East-Southeast"
+ if(135)
+ return "Southeast"
+ if(157.5)
+ return "South-Southeast"
+ if(180)
+ return "South"
+ if(202.5)
+ return "South-Southwest"
+ if(225)
+ return "Southwest"
+ if(247.5)
+ return "West-Southwest"
+ if(270)
+ return "West"
+ if(292.5)
+ return "West-Northwest"
+ if(315)
+ return "Northwest"
+ if(337.5)
+ return "North-Northwest"
+
+
+
+
+
+
+
+
+
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index 1f0df80141..2ec9da3b27 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -11,7 +11,7 @@
using.icon = 'icons/mob/screen1_alien.dmi'
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
using.screen_loc = ui_acti
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
move_intent = using
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 786c7cdd04..c63519c40f 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -9,6 +9,7 @@ var/list/global_huds = list(
global_hud.whitense,
global_hud.vimpaired,
global_hud.darkMask,
+ global_hud.centermarker,
global_hud.nvg,
global_hud.thermal,
global_hud.meson,
@@ -27,6 +28,7 @@ var/list/global_huds = list(
var/obj/screen/whitense
var/list/vimpaired
var/list/darkMask
+ var/obj/screen/centermarker
var/obj/screen/darksight
var/obj/screen/nvg
var/obj/screen/thermal
@@ -47,7 +49,6 @@ var/list/global_huds = list(
/obj/screen/global_screen
screen_loc = ui_entire_screen
- layer = 17
plane = PLANE_FULLSCREEN
mouse_opacity = 0
@@ -70,7 +71,12 @@ var/list/global_huds = list(
darksight.icon = null
darksight.screen_loc = "1,1"
darksight.plane = PLANE_LIGHTING
- darksight.plane = LIGHTING_LAYER + 0.1
+
+ //Marks the center of the screen, for things like ventcrawl
+ centermarker = new /obj/screen()
+ centermarker.icon = 'icons/mob/screen1.dmi'
+ centermarker.icon_state = "centermarker"
+ centermarker.screen_loc = "CENTER,CENTER"
nvg = setup_overlay("nvg_hud")
thermal = setup_overlay("thermal_hud")
@@ -117,20 +123,17 @@ var/list/global_huds = list(
for(i = 1, i <= 4, i++)
O = vimpaired[i]
O.icon_state = "dither50"
- O.layer = 17
O.plane = PLANE_FULLSCREEN
O.mouse_opacity = 0
O = darkMask[i]
O.icon_state = "dither50"
- O.layer = 17
O.plane = PLANE_FULLSCREEN
O.mouse_opacity = 0
for(i = 5, i <= 8, i++)
O = darkMask[i]
O.icon_state = "black"
- O.layer = 17
O.plane = PLANE_FULLSCREEN
O.mouse_opacity = 2
@@ -164,6 +167,7 @@ var/list/global_huds = list(
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = 0
+ var/list/slot_info
datum/hud/New(mob/owner)
mymob = owner
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 83f23930dd..1c903700b0 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -14,6 +14,7 @@
src.adding = list()
src.other = list()
src.hotkeybuttons = list() //These can be disabled for hotkey users
+ src.slot_info = list()
var/list/hud_elements = list()
var/obj/screen/using
@@ -33,6 +34,7 @@
inv_box.screen_loc = slot_data["loc"]
inv_box.slot_id = slot_data["slot"]
inv_box.icon_state = slot_data["state"]
+ slot_info["[inv_box.slot_id]"] = inv_box.screen_loc
if(slot_data["dir"])
inv_box.set_dir(slot_data["dir"])
@@ -75,7 +77,7 @@
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
- using = new /obj/screen( src )
+ using = new /obj/screen()
using.name = I_HELP
using.icon = ico
using.screen_loc = ui_acti
@@ -87,7 +89,7 @@
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
- using = new /obj/screen( src )
+ using = new /obj/screen()
using.name = I_DISARM
using.icon = ico
using.screen_loc = ui_acti
@@ -99,7 +101,7 @@
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
- using = new /obj/screen( src )
+ using = new /obj/screen()
using.name = I_GRAB
using.icon = ico
using.screen_loc = ui_acti
@@ -111,7 +113,7 @@
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
- using = new /obj/screen( src )
+ using = new /obj/screen()
using.name = I_HURT
using.icon = ico
using.screen_loc = ui_acti
@@ -164,9 +166,9 @@
inv_box.slot_id = slot_r_hand
inv_box.color = ui_color
inv_box.alpha = ui_alpha
-
src.r_hand_hud_object = inv_box
src.adding += inv_box
+ slot_info["[slot_r_hand]"] = inv_box.screen_loc
inv_box = new /obj/screen/inventory/hand()
inv_box.hud = src
@@ -181,6 +183,7 @@
inv_box.alpha = ui_alpha
src.l_hand_hud_object = inv_box
src.adding += inv_box
+ slot_info["[slot_l_hand]"] = inv_box.screen_loc
using = new /obj/screen/inventory()
using.name = "hand"
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index cab3e3bfca..325a4a4b7e 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -11,13 +11,13 @@
blobpwrdisplay.name = "blob power"
blobpwrdisplay.icon_state = "block"
blobpwrdisplay.screen_loc = ui_health
- blobpwrdisplay.layer = 20
+ blobpwrdisplay.layer = HUD_LAYER
blobhealthdisplay = new /obj/screen()
blobhealthdisplay.name = "blob health"
blobhealthdisplay.icon_state = "block"
blobhealthdisplay.screen_loc = ui_internal
- blobhealthdisplay.layer = 20
+ blobhealthdisplay.layer = HUD_LAYER
mymob.client.screen = list()
@@ -36,7 +36,7 @@
using.icon = ui_style
using.icon_state = "intent_"+mymob.a_intent
using.screen_loc = ui_zonesel
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
action_intent = using
@@ -50,7 +50,7 @@
using.name = "help"
using.icon = ico
using.screen_loc = ui_zonesel
- using.layer = 21
+ using.layer = HUD_LAYER+0.01
src.adding += using
help_intent = using
@@ -61,7 +61,7 @@
using.name = "disarm"
using.icon = ico
using.screen_loc = ui_zonesel
- using.layer = 21
+ using.layer = HUD_LAYER+0.01
src.adding += using
disarm_intent = using
@@ -72,7 +72,7 @@
using.name = "grab"
using.icon = ico
using.screen_loc = ui_zonesel
- using.layer = 21
+ using.layer = HUD_LAYER+0.01
src.adding += using
grab_intent = using
@@ -83,7 +83,7 @@
using.name = I_HURT
using.icon = ico
using.screen_loc = ui_zonesel
- using.layer = 21
+ using.layer = HUD_LAYER+0.01
src.adding += using
hurt_intent = using
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index daaa52e827..dc414df11f 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -30,7 +30,7 @@ var/obj/screen/robot_inventory
using.alpha = ui_alpha
using.icon_state = "radio"
using.screen_loc = ui_movi
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
//Module select
@@ -43,7 +43,7 @@ var/obj/screen/robot_inventory
using.alpha = ui_alpha
using.icon_state = "inv1"
using.screen_loc = ui_inv1
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
mymob:inv1 = using
@@ -55,7 +55,7 @@ var/obj/screen/robot_inventory
using.alpha = ui_alpha
using.icon_state = "inv2"
using.screen_loc = ui_inv2
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
mymob:inv2 = using
@@ -67,7 +67,7 @@ var/obj/screen/robot_inventory
using.alpha = ui_alpha
using.icon_state = "inv3"
using.screen_loc = ui_inv3
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
mymob:inv3 = using
@@ -81,7 +81,7 @@ var/obj/screen/robot_inventory
using.alpha = ui_alpha
using.icon_state = mymob.a_intent
using.screen_loc = ui_acti
- using.layer = 20
+ using.layer = HUD_LAYER
src.adding += using
action_intent = using
@@ -119,7 +119,7 @@ var/obj/screen/robot_inventory
using.icon_state = "panel"
using.alpha = ui_alpha
using.screen_loc = ui_borg_panel
- using.layer = 19
+ using.layer = HUD_LAYER-0.01
src.adding += using
//Store
@@ -276,6 +276,6 @@ var/obj/screen/robot_inventory
r.client.screen -= r.robot_modules_background
/mob/living/silicon/robot/update_hud()
- ..()
if(modtype)
hands.icon_state = lowertext(modtype)
+ ..()
\ No newline at end of file
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 9bf89b27bd..5c7c07ec25 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -278,7 +278,7 @@
// Rigs are a fucking pain since they keep an air tank in nullspace.
if(istype(C.back,/obj/item/weapon/rig))
var/obj/item/weapon/rig/rig = C.back
- if(rig.air_supply)
+ if(rig.air_supply && !rig.offline)
from = "in"
nicename |= "hardsuit"
tankcheck |= rig.air_supply
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index a066981e01..428485573d 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -84,9 +84,7 @@ avoid code duplication. This includes items that may sometimes act as a standard
M.lastattacker = user
if(!no_attack_log)
- user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])"
- M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])"
- msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
+ add_attack_logs(user,M,"attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])")
/////////////////////////
user.setClickCooldown(user.get_attack_speed(src))
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index f08727abf3..26c1680421 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -68,7 +68,7 @@ var/const/tk_maxrange = 15
flags = NOBLUDGEON
//item_state = null
w_class = ITEMSIZE_NO_CONTAINER
- layer = 20
+ layer = HUD_LAYER
var/last_throw = 0
var/atom/movable/focus = null
diff --git a/code/controllers/Processes/inactivity.dm b/code/controllers/Processes/inactivity.dm
index 2a6cd44d2c..3b118995bf 100644
--- a/code/controllers/Processes/inactivity.dm
+++ b/code/controllers/Processes/inactivity.dm
@@ -7,10 +7,10 @@
for(last_object in clients)
var/client/C = last_object
if(C.is_afk(config.kick_inactive MINUTES))
- if(!istype(C.mob, /mob/observer/dead) && !istype(C.mob, /mob/new_player))
- to_chat(C,"You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.")
- var/information
+ to_chat(C,"You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.")
+ var/information
+ if(C.mob)
if(ishuman(C.mob))
var/job
var/mob/living/carbon/human/H = C.mob
@@ -27,10 +27,10 @@
else if(issilicon(C.mob))
information = " while a silicon."
- var/adminlinks
- adminlinks = " (JMP|CRYO)"
+ var/adminlinks
+ adminlinks = " (JMP|CRYO)"
- log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
+ log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
- qdel(C)
+ qdel(C)
SCHECK
diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm
index f9fd57f788..e39b5e81b8 100644
--- a/code/controllers/Processes/planet.dm
+++ b/code/controllers/Processes/planet.dm
@@ -47,7 +47,8 @@ var/datum/controller/process/planet/planet_controller = null
//Weather style needs redrawing
if(P.needs_work & PLANET_PROCESS_WEATHER)
P.needs_work &= ~PLANET_PROCESS_WEATHER
- var/image/new_overlay = image(icon = P.weather_holder.current_weather.icon, icon_state = P.weather_holder.current_weather.icon_state, layer = LIGHTING_LAYER - 1)
+ var/image/new_overlay = image(icon = P.weather_holder.current_weather.icon, icon_state = P.weather_holder.current_weather.icon_state)
+ new_overlay.plane = PLANE_PLANETLIGHTING
//Redraw weather icons
for(var/T in P.planet_floors)
var/turf/simulated/turf = T
diff --git a/code/controllers/Processes/scheduler.dm b/code/controllers/Processes/scheduler.dm
index 6031f2f4fe..a2a2f5f925 100644
--- a/code/controllers/Processes/scheduler.dm
+++ b/code/controllers/Processes/scheduler.dm
@@ -8,19 +8,21 @@
/datum/controller/process/scheduler/setup()
name = "scheduler"
- schedule_interval = 3 SECONDS
+ schedule_interval = 1 SECOND
scheduled_tasks = list()
scheduler = src
/datum/controller/process/scheduler/doWork()
+ var/world_time = world.time
for(last_object in scheduled_tasks)
var/datum/scheduled_task/scheduled_task = last_object
+ if(world_time < scheduled_task.trigger_time)
+ break // Too early for this one, and therefore too early for all remaining.
try
- if(world.time > scheduled_task.trigger_time)
- unschedule(scheduled_task)
- scheduled_task.pre_process()
- scheduled_task.process()
- scheduled_task.post_process()
+ unschedule(scheduled_task)
+ scheduled_task.pre_process()
+ scheduled_task.process()
+ scheduled_task.post_process()
catch(var/exception/e)
catchException(e, last_object)
SCHECK
@@ -45,7 +47,7 @@
stat(null, "[scheduled_tasks.len] task\s")
/datum/controller/process/scheduler/proc/schedule(var/datum/scheduled_task/st)
- scheduled_tasks += st
+ dd_insertObjectList(scheduled_tasks, st)
/datum/controller/process/scheduler/proc/unschedule(var/datum/scheduled_task/st)
scheduled_tasks -= st
@@ -106,6 +108,9 @@
task_after_process_args.Cut()
return ..()
+/datum/scheduled_task/dd_SortValue()
+ return trigger_time
+
/datum/scheduled_task/proc/pre_process()
task_triggered_event.raise_event(list(src))
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index d4fada9088..29188647f2 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -212,7 +212,7 @@ var/list/gamemode_cache = list()
var/starlight = 0 // Whether space turfs have ambient light or not
- var/list/ert_species = list("Human")
+ var/list/ert_species = list(SPECIES_HUMAN)
var/law_zero = "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'ALL LAWS OVERRIDDEN#*?&110010"
@@ -721,7 +721,7 @@ var/list/gamemode_cache = list()
if("ert_species")
config.ert_species = splittext(value, ";")
if(!config.ert_species.len)
- config.ert_species += "Human"
+ config.ert_species += SPECIES_HUMAN
if("law_zero")
law_zero = value
diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm
index 7fb3a56c61..d7a91c9b4f 100644
--- a/code/controllers/emergency_shuttle_controller.dm
+++ b/code/controllers/emergency_shuttle_controller.dm
@@ -234,7 +234,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
name = "star"
var/speed = 10
var/direction = SOUTH
- layer = 2 // TURF_LAYER
+ layer = TURF_LAYER
+ plane = TURF_PLANE
/obj/effect/bgstar/New()
..()
diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm
index ed4602f048..ef0173c33a 100644
--- a/code/controllers/subsystems/air.dm
+++ b/code/controllers/subsystems/air.dm
@@ -9,7 +9,7 @@
SUBSYSTEM_DEF(air)
name = "Air"
init_order = INIT_ORDER_AIR
- priority = 20
+ priority = 35
wait = 2 SECONDS // seconds (We probably can speed this up actually)
flags = SS_BACKGROUND // TODO - Should this really be background? It might be important.
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
diff --git a/code/controllers/subsystems/airflow.dm b/code/controllers/subsystems/airflow.dm
index 9db8138826..c98a02a5ce 100644
--- a/code/controllers/subsystems/airflow.dm
+++ b/code/controllers/subsystems/airflow.dm
@@ -14,7 +14,7 @@ SUBSYSTEM_DEF(airflow)
wait = 2
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- priority = 15
+ priority = 30
var/list/processing = list()
var/list/currentrun = list()
@@ -47,7 +47,7 @@ SUBSYSTEM_DEF(airflow)
continue
else if (target.airflow_process_delay)
target.airflow_process_delay = 0
-
+
target.airflow_speed = min(target.airflow_speed, 15)
target.airflow_speed -= vsc.airflow_speed_decay
if (!target.airflow_skip_speedcheck)
@@ -89,7 +89,7 @@ SUBSYSTEM_DEF(airflow)
if (MC_TICK_CHECK)
return
continue
-
+
step_towards(target, target.airflow_dest)
var/mob/M = target
if (ismob(target) && M.client)
@@ -98,7 +98,7 @@ SUBSYSTEM_DEF(airflow)
if (MC_TICK_CHECK)
return
-#undef CLEAR_OBJECT
+#undef CLEAR_OBJECT
/atom/movable
var/tmp/airflow_xo
@@ -129,9 +129,9 @@ SUBSYSTEM_DEF(airflow)
if (airflow_falloff < 1)
airflow_dest = null
return FALSE
-
- airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9)
-
+
+ airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9)
+
airflow_od = 0
if (!density)
@@ -154,7 +154,7 @@ SUBSYSTEM_DEF(airflow)
/atom/movable/proc/RepelAirflowDest(n)
if (!prepare_airflow(n))
return
-
+
airflow_xo = -(airflow_dest.x - src.x)
airflow_yo = -(airflow_dest.y - src.y)
diff --git a/code/controllers/subsystems/atoms.dm b/code/controllers/subsystems/atoms.dm
index 6b5669878c..5b09b186bb 100644
--- a/code/controllers/subsystems/atoms.dm
+++ b/code/controllers/subsystems/atoms.dm
@@ -135,9 +135,7 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/Shutdown()
var/initlog = InitLog()
if(initlog)
- //text2file(initlog, "[GLOB.log_directory]/initialize.log")
- var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day")
- text2file(initlog, "data/logs/[date_string]-initialize.log")
+ text2file(initlog, "[log_path]-initialize.log")
#undef BAD_INIT_QDEL_BEFORE
#undef BAD_INIT_DIDNT_INIT
diff --git a/code/controllers/subsystems/floor_decals.dm b/code/controllers/subsystems/floor_decals.dm
deleted file mode 100644
index 39e4515d0d..0000000000
--- a/code/controllers/subsystems/floor_decals.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Floor Decals Initialization Subsystem
-// This is part of the giant decal hack that works around a BYOND bug where DreamDaemon will crash if you
-// update overlays on turfs too much.
-// The master_controller on Polaris used to init decals prior to initializing areas (which initilized turfs)
-// Now that we switched to subsystems we still want to do the same thing, so this takes care of it.
-//
-SUBSYSTEM_DEF(floor_decals)
- name = "Floor Decals"
- init_order = INIT_ORDER_DECALS
- flags = SS_NO_FIRE
-
-/datum/controller/subsystem/floor_decals/Initialize(timeofday)
- if(floor_decals_initialized)
- return ..()
- to_world_log("Initializing Floor Decals")
- admin_notice("Initializing Floor Decals", R_DEBUG)
- var/list/turfs_with_decals = list()
- for(var/obj/effect/floor_decal/D in world)
- var/T = D.add_to_turf_decals()
- if(T) turfs_with_decals |= T
- CHECK_TICK
- for(var/item in turfs_with_decals)
- var/turf/T = item
- if(T.decals) T.apply_decals()
- CHECK_TICK
- floor_decals_initialized = TRUE
- return ..()
diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm
index 34b32d5873..b4d43a8d3f 100644
--- a/code/controllers/subsystems/garbage.dm
+++ b/code/controllers/subsystems/garbage.dm
@@ -81,7 +81,7 @@ SUBSYSTEM_DEF(garbage)
dellog += "\tIgnored force: [I.no_respect_force] times"
if (I.no_hint)
dellog += "\tNo hint: [I.no_hint] times"
- log_misc(dellog.Join())
+ text2file(dellog.Join(), "[log_path]-qdel.log")
/datum/controller/subsystem/garbage/fire()
//the fact that this resets its processing each fire (rather then resume where it left off) is intentional.
@@ -169,7 +169,12 @@ SUBSYSTEM_DEF(garbage)
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
- testing("GC: -- \ref[D] | [type] was unable to be GC'd --")
+ var/extrainfo = "--"
+ if(istype(D,/image))
+ var/image/img = D
+ var/icon/ico = img.icon
+ extrainfo = "L:[img.loc] -- I:[ico] -- IS:[img.icon_state] --"
+ testing("GC: -- \ref[D] | [type] was unable to be GC'd [extrainfo]")
I.failures++
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
new file mode 100644
index 0000000000..5c8b3531c9
--- /dev/null
+++ b/code/controllers/subsystems/overlays.dm
@@ -0,0 +1,255 @@
+SUBSYSTEM_DEF(overlays)
+ name = "Overlay"
+ flags = SS_TICKER
+ wait = 1
+ priority = FIRE_PRIORITY_OVERLAYS
+ init_order = INIT_ORDER_OVERLAY
+
+ var/initialized = FALSE
+ var/list/queue // Queue of atoms needing overlay compiling (TODO-VERIFY!)
+ var/list/stats
+ var/list/overlay_icon_state_caches // Cache thing
+ var/list/overlay_icon_cache // Cache thing
+
+var/global/image/stringbro = new() // Temporarily super-global because of BYOND init order dumbness.
+var/global/image/iconbro = new() // Temporarily super-global because of BYOND init order dumbness.
+var/global/image/appearance_bro = new() // Temporarily super-global because of BYOND init order dumbness.
+
+/datum/controller/subsystem/overlays/PreInit()
+ overlay_icon_state_caches = list()
+ overlay_icon_cache = list()
+ queue = list()
+ stats = list()
+
+/datum/controller/subsystem/overlays/Initialize()
+ initialized = TRUE
+ fire(mc_check = FALSE)
+ ..()
+
+/datum/controller/subsystem/overlays/stat_entry()
+ ..("Ov:[length(queue)]")
+
+
+/datum/controller/subsystem/overlays/Shutdown()
+ text2file(render_stats(stats), "[log_path]-overlay.log")
+
+/datum/controller/subsystem/overlays/Recover()
+ overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
+ overlay_icon_cache = SSoverlays.overlay_icon_cache
+ queue = SSoverlays.queue
+
+
+/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
+ var/list/queue = src.queue
+ var/static/count = 0
+ if (count)
+ var/c = count
+ count = 0 //so if we runtime on the Cut, we don't try again.
+ queue.Cut(1,c+1)
+
+ for (var/thing in queue)
+ count++
+ if(thing)
+ STAT_START_STOPWATCH
+ var/atom/A = thing
+ COMPILE_OVERLAYS(A)
+ STAT_STOP_STOPWATCH
+ STAT_LOG_ENTRY(stats, A.type)
+ if(mc_check)
+ if(MC_TICK_CHECK)
+ break
+ else
+ CHECK_TICK
+
+ if (count)
+ queue.Cut(1,count+1)
+ count = 0
+
+/proc/iconstate2appearance(icon, iconstate)
+ // var/static/image/stringbro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
+ var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
+ var/list/cached_icon = icon_states_cache[icon]
+ if (cached_icon)
+ var/cached_appearance = cached_icon["[iconstate]"]
+ if (cached_appearance)
+ return cached_appearance
+ stringbro.icon = icon
+ stringbro.icon_state = iconstate
+ if (!cached_icon) //not using the macro to save an associated lookup
+ cached_icon = list()
+ icon_states_cache[icon] = cached_icon
+ var/cached_appearance = stringbro.appearance
+ cached_icon["[iconstate]"] = cached_appearance
+ return cached_appearance
+
+/proc/icon2appearance(icon)
+ // var/static/image/iconbro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
+ var/list/icon_cache = SSoverlays.overlay_icon_cache
+ . = icon_cache[icon]
+ if (!.)
+ iconbro.icon = icon
+ . = iconbro.appearance
+ icon_cache[icon] = .
+
+/atom/proc/build_appearance_list(old_overlays)
+ // var/static/image/appearance_bro = new() // Moved to be superglobal due to BYOND insane init order stupidness.
+ var/list/new_overlays = list()
+ if (!islist(old_overlays))
+ old_overlays = list(old_overlays)
+ for (var/overlay in old_overlays)
+ if(!overlay)
+ continue
+ if (istext(overlay))
+ new_overlays += iconstate2appearance(icon, overlay)
+ else if(isicon(overlay))
+ new_overlays += icon2appearance(overlay)
+ else
+ if(isloc(overlay))
+ var/atom/A = overlay
+ if (A.flags & OVERLAY_QUEUED)
+ COMPILE_OVERLAYS(A)
+ appearance_bro.appearance = overlay //this works for images and atoms too!
+ if(!ispath(overlay))
+ var/image/I = overlay
+ appearance_bro.dir = I.dir
+ new_overlays += appearance_bro.appearance
+ return new_overlays
+
+#define NOT_QUEUED_ALREADY (!(flags & OVERLAY_QUEUED))
+#define QUEUE_FOR_COMPILE flags |= OVERLAY_QUEUED; SSoverlays.queue += src;
+
+/**
+ * Cut all of atom's normal overlays. Usually leaves "priority" overlays untouched.
+ *
+ * @param priority If true, also will cut priority overlays.
+ */
+/atom/proc/cut_overlays(priority = FALSE)
+ var/list/cached_overlays = our_overlays
+ var/list/cached_priority = priority_overlays
+
+ var/need_compile = FALSE
+
+ if(LAZYLEN(cached_overlays)) //don't queue empty lists, don't cut priority overlays
+ cached_overlays.Cut() //clear regular overlays
+ need_compile = TRUE
+
+ if(priority && LAZYLEN(cached_priority))
+ cached_priority.Cut()
+ need_compile = TRUE
+
+ if(NOT_QUEUED_ALREADY && need_compile)
+ QUEUE_FOR_COMPILE
+
+/**
+ * Removes specific overlay(s) from the atom. Usually does not remove them from "priority" overlays.
+ *
+ * @param overlays The overlays to removed, type can be anything that is allowed for add_overlay().
+ * @param priority If true, also will remove them from the "priority" overlays.
+ */
+/atom/proc/cut_overlay(list/overlays, priority)
+ if(!overlays)
+ return
+
+ overlays = build_appearance_list(overlays)
+
+ var/list/cached_overlays = our_overlays //sanic
+ var/list/cached_priority = priority_overlays
+ var/init_o_len = LAZYLEN(cached_overlays)
+ var/init_p_len = LAZYLEN(cached_priority) //starter pokemon
+
+ LAZYREMOVE(cached_overlays, overlays)
+ if(priority)
+ LAZYREMOVE(cached_priority, overlays)
+
+ if(NOT_QUEUED_ALREADY && ((init_o_len != LAZYLEN(cached_overlays)) || (init_p_len != LAZYLEN(cached_priority))))
+ QUEUE_FOR_COMPILE
+
+/**
+ * Adds specific overlay(s) to the atom.
+ * It is designed so any of the types allowed to be added to /atom/overlays can be added here too. More details below.
+ *
+ * @param overlays The overlay(s) to add. These may be
+ * - A string: In which case it is treated as an icon_state of the atom's icon.
+ * - An icon: It is treated as an icon.
+ * - An atom: Its own overlays are compiled and then it's appearance is added. (Meaning its current apperance is frozen).
+ * - An image: Image's apperance is added (i.e. subsequently editing the image will not edit the overlay)
+ * - A type path: Added to overlays as is. Does whatever it is BYOND does when you add paths to overlays.
+ * - Or a list containing any of the above.
+ * @param priority The overlays are added to the "priority" list istead of the normal one.
+ */
+/atom/proc/add_overlay(list/overlays, priority = FALSE)
+ if(!overlays)
+ return
+
+ overlays = build_appearance_list(overlays)
+
+ LAZYINITLIST(our_overlays) //always initialized after this point
+ LAZYINITLIST(priority_overlays)
+
+ var/list/cached_overlays = our_overlays //sanic
+ var/list/cached_priority = priority_overlays
+ var/init_o_len = cached_overlays.len
+ var/init_p_len = cached_priority.len //starter pokemon
+ var/need_compile
+
+ if(priority)
+ cached_priority += overlays //or in the image. Can we use [image] = image?
+ need_compile = init_p_len != cached_priority.len
+ else
+ cached_overlays += overlays
+ need_compile = init_o_len != cached_overlays.len
+
+ if(NOT_QUEUED_ALREADY && need_compile) //have we caught more pokemon?
+ QUEUE_FOR_COMPILE
+
+/**
+ * Copy the overlays from another atom, either replacing all of ours or appending to our existing overlays.
+ * Note: This copies only the normal overlays, not the "priority" overlays.
+ *
+ * @param other The atom to copy overlays from.
+ * @param cut_old If true, all of our overlays will be *replaced* by the other's. If other is null, that means cutting all ours.
+ */
+/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
+ if(!other)
+ if(cut_old)
+ cut_overlays()
+ return
+
+ var/list/cached_other = other.our_overlays
+ if(cached_other)
+ if(cut_old || !LAZYLEN(our_overlays))
+ our_overlays = cached_other.Copy()
+ else
+ our_overlays |= cached_other
+ if(NOT_QUEUED_ALREADY)
+ QUEUE_FOR_COMPILE
+ else if(cut_old)
+ cut_overlays()
+
+#undef NOT_QUEUED_ALREADY
+#undef QUEUE_FOR_COMPILE
+
+//TODO: Better solution for these?
+/image/proc/add_overlay(x)
+ overlays += x
+
+/image/proc/cut_overlay(x)
+ overlays -= x
+
+/image/proc/cut_overlays(x)
+ overlays.Cut()
+
+/image/proc/copy_overlays(atom/other, cut_old)
+ if(!other)
+ if(cut_old)
+ cut_overlays()
+ return
+
+ var/list/cached_other = other.our_overlays
+ if(cached_other)
+ if(cut_old || !overlays.len)
+ overlays = cached_other.Copy()
+ else
+ overlays |= cached_other
+ else if(cut_old)
+ cut_overlays()
diff --git a/code/datums/EPv2.dm b/code/datums/EPv2.dm
index 37a1a0ba1f..a41175f424 100644
--- a/code/datums/EPv2.dm
+++ b/code/datums/EPv2.dm
@@ -40,6 +40,10 @@ var/global/list/all_exonet_connections = list()
src.holder = holder
..()
+/datum/exonet_protocol/Destroy()
+ remove_address()
+ holder = null
+ return ..()
// Proc: make_address()
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 274c0c0903..8e21740082 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -425,8 +425,8 @@
var/icon/front
var/icon/side
if(H)
- front = getFlatIcon(H, SOUTH, always_use_defdir = 1)
- side = getFlatIcon(H, WEST, always_use_defdir = 1)
+ front = getFlatIcon(H, SOUTH)
+ side = getFlatIcon(H, WEST)
else
var/mob/living/carbon/human/dummy = new()
front = new(get_id_photo(dummy), dir = SOUTH)
@@ -446,7 +446,7 @@
G.fields["fingerprint"] = "Unknown"
G.fields["p_stat"] = "Active"
G.fields["m_stat"] = "Stable"
- G.fields["species"] = "Human"
+ G.fields["species"] = SPECIES_HUMAN
G.fields["home_system"] = "Unknown"
G.fields["citizenship"] = "Unknown"
G.fields["faction"] = "Unknown"
diff --git a/code/datums/ghost_query.dm b/code/datums/ghost_query.dm
index dda2565bf1..d041558a0c 100644
--- a/code/datums/ghost_query.dm
+++ b/code/datums/ghost_query.dm
@@ -126,3 +126,15 @@
question = "A person suspended in cryosleep has been discovered by a crewmember \
and they are attempting to open the cryopod. Would you like to play as the occupant?"
cutoff_number = 1
+
+/datum/ghost_query/corgi_rune
+ role_name = "Dark Creature"
+ question = "A curious explorer has touched a mysterious rune. \
+ Would you like to play as the creature it summons?"
+ cutoff_number = 1
+
+/datum/ghost_query/cursedblade
+ role_name = "Cursed Sword"
+ question = "A cursed blade has been discovered by a curious explorer. \
+ Would you like to play as the soul imprisoned within?"
+ cutoff_number = 1
diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm
index f0f0c70abd..191868e489 100644
--- a/code/datums/mixed.dm
+++ b/code/datums/mixed.dm
@@ -1,34 +1,46 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
-/datum/data
- var/name = "data"
- var/size = 1.0
-
-
-/datum/data/function
- name = "function"
- size = 2.0
-
-
-/datum/data/function/data_control
- name = "data control"
-
-
-/datum/data/function/id_changer
- name = "id changer"
-
-
-/datum/data/record
- name = "record"
- size = 5.0
- var/list/fields = list( )
-
-
-/datum/data/text
- name = "text"
- var/data = null
-
-
-
-/datum/debug
- var/list/debuglist
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+
+/datum/data
+ var/name = "data"
+ var/size = 1.0
+
+
+/datum/data/function
+ name = "function"
+ size = 2.0
+
+
+/datum/data/function/data_control
+ name = "data control"
+
+
+/datum/data/function/id_changer
+ name = "id changer"
+
+
+/datum/data/record
+ name = "record"
+ size = 5.0
+ var/list/fields = list( )
+
+// Mostly used for data_core records, but unfortuantely used some other places too. But mostly here, so lets make a good effort.
+// TODO - Some machines/computers might be holding references to us. Lets look into that, but at least for now lets make sure that the manifest is cleaned up.
+/datum/data/record/Destroy(var/force)
+ if(data_core.locked.Find(src))
+ if(!force)
+ crash_with("Someone tried to qdel a record that was in data_core.locked [log_info_line(src)]")
+ return QDEL_HINT_LETMELIVE
+ data_core.locked -= src
+ data_core.medical -= src
+ data_core.general -= src
+ data_core.security -= src
+ . = ..()
+
+/datum/data/text
+ name = "text"
+ var/data = null
+
+
+
+/datum/debug
+ var/list/debuglist
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index 1cb3a97d9f..16d10ae035 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -4,10 +4,11 @@
// Mutable appearances are children of images, just so you know.
-/mutable_appearance/New()
+/mutable_appearance/New(copy_from, ...)
..()
- plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
- // And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
+ if(!copy_from)
+ plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
+ // And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
diff --git a/code/datums/outfits/_defines.dm b/code/datums/outfits/_defines.dm
index ae07595c50..8d406ce1e0 100644
--- a/code/datums/outfits/_defines.dm
+++ b/code/datums/outfits/_defines.dm
@@ -1,6 +1,7 @@
#define OUTFIT_HAS_JETPACK 1
#define OUTFIT_HAS_BACKPACK 2
#define OUTFIT_EXTENDED_SURVIVAL 4
+#define OUTFIT_COMPREHENSIVE_SURVIVAL 8
#define OUTFIT_JOB_NAME(job_name) ("Job - " + job_name)
#define OUTFIT_MILITARY(job_name) ("Military Uniform - " + job_name)
diff --git a/code/datums/outfits/jobs/cargo.dm b/code/datums/outfits/jobs/cargo.dm
index e8974f09f9..bbfe6f59f5 100644
--- a/code/datums/outfits/jobs/cargo.dm
+++ b/code/datums/outfits/jobs/cargo.dm
@@ -20,6 +20,7 @@
/decl/hierarchy/outfit/job/cargo/mining
name = OUTFIT_JOB_NAME("Shaft miner")
uniform = /obj/item/clothing/under/rank/miner
+ l_ear = /obj/item/device/radio/headset/headset_mine
backpack = /obj/item/weapon/storage/backpack/industrial
satchel_one = /obj/item/weapon/storage/backpack/satchel/eng
id_type = /obj/item/weapon/card/id/cargo/mining
diff --git a/code/datums/outfits/jobs/medical.dm b/code/datums/outfits/jobs/medical.dm
index 3b227a2612..1fdd020fcf 100644
--- a/code/datums/outfits/jobs/medical.dm
+++ b/code/datums/outfits/jobs/medical.dm
@@ -23,8 +23,8 @@
name = OUTFIT_JOB_NAME("Medical Doctor")
uniform = /obj/item/clothing/under/rank/medical
suit = /obj/item/clothing/suit/storage/toggle/labcoat
- l_hand = /obj/item/weapon/storage/firstaid/adv
- r_pocket = /obj/item/device/healthanalyzer
+ l_hand = /obj/item/weapon/storage/firstaid/regular
+ r_pocket = /obj/item/device/flashlight/pen
id_type = /obj/item/weapon/card/id/medical/doctor
/decl/hierarchy/outfit/job/medical/doctor/emergency_physician
@@ -94,7 +94,7 @@
uniform = /obj/item/clothing/under/rank/medical/scrubs/black
suit = /obj/item/clothing/suit/storage/toggle/fr_jacket
shoes = /obj/item/clothing/shoes/boots/jackboots
- l_hand = /obj/item/weapon/storage/firstaid/adv
+ l_hand = /obj/item/weapon/storage/firstaid/regular
belt = /obj/item/weapon/storage/belt/medical/emt
pda_slot = slot_l_store
id_type = /obj/item/weapon/card/id/medical/paramedic
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index e69e9eb705..ac653e2647 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -146,7 +146,7 @@ var/list/outfits_decls_by_type_
if(r_hand)
H.put_in_r_hand(new r_hand(H))
if(H.species)
- H.species.equip_survival_gear(H, flags&OUTFIT_EXTENDED_SURVIVAL)
+ H.species.equip_survival_gear(H, flags&OUTFIT_EXTENDED_SURVIVAL, flags&OUTFIT_COMPREHENSIVE_SURVIVAL)
/decl/hierarchy/outfit/proc/equip_id(mob/living/carbon/human/H, rank, assignment)
if(!id_slot || !id_type)
diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm
index bed0f33275..afcb65a8c1 100644
--- a/code/datums/progressbar.dm
+++ b/code/datums/progressbar.dm
@@ -22,8 +22,10 @@
/datum/progressbar/Destroy()
if (client)
client.images -= bar
- qdel(bar)
- . = ..()
+ qdel_null(bar)
+ user = null
+ client = null
+ return ..()
/datum/progressbar/proc/update(progress)
//world << "Update [progress] - [goal] - [(progress / goal)] - [((progress / goal) * 100)] - [round(((progress / goal) * 100), 5)]"
diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm
index 8c8869f318..d0ca246759 100644
--- a/code/datums/supplypacks/contraband.dm
+++ b/code/datums/supplypacks/contraband.dm
@@ -43,8 +43,8 @@
containername = "Moghes imports crate"
contraband = 1
-/datum/supply_packs/security/bolt_rifles_militia
- name = "Surplus militia rifles"
+/datum/supply_packs/munitions/bolt_rifles_militia
+ name = "Weapon - Surplus militia rifles"
contains = list(
/obj/item/weapon/gun/projectile/shotgun/pump/rifle = 3,
/obj/item/ammo_magazine/clip/c762 = 6
@@ -52,7 +52,7 @@
cost = 50
contraband = 1
containertype = /obj/structure/closet/crate/secure/weapon
- containername = "Weapons crate"
+ containername = "Ballistic weapons crate"
/datum/supply_packs/randomised/misc/telecrate //you get something awesome, a couple of decent things, and a few weak/filler things
name = "ERR_NULL_ENTRY" //null crate! also dream maker is hell,
diff --git a/code/datums/supplypacks/materials.dm b/code/datums/supplypacks/materials.dm
index d09e3c8ee5..4c5ddedf47 100644
--- a/code/datums/supplypacks/materials.dm
+++ b/code/datums/supplypacks/materials.dm
@@ -49,7 +49,7 @@
cost = 15
contains = list(
/obj/fiftyspawner/carpet,
- /obj/fiftyspawner/bluecarpet
+ /obj/fiftyspawner/tealcarpet
)
diff --git a/code/datums/supplypacks/misc.dm b/code/datums/supplypacks/misc.dm
index 5a3bb038bb..225e29335f 100644
--- a/code/datums/supplypacks/misc.dm
+++ b/code/datums/supplypacks/misc.dm
@@ -70,3 +70,10 @@
cost = 10
containertype = "/obj/structure/closet/crate"
containername = "Webbing crate"
+
+/datum/supply_packs/misc/holoplant
+ name = "Holoplant Pot"
+ contains = list(/obj/machinery/holoplant/shipped)
+ cost = 15
+ containertype = /obj/structure/closet/crate
+ containername = "Holoplant crate"
diff --git a/code/datums/supplypacks/munitions.dm b/code/datums/supplypacks/munitions.dm
index 42e8b75a17..662de4da73 100644
--- a/code/datums/supplypacks/munitions.dm
+++ b/code/datums/supplypacks/munitions.dm
@@ -10,21 +10,30 @@
group = "Munitions"
/datum/supply_packs/munitions/weapons
- name = "Weapons crate"
+ name = "Weapons - Security basic equipment"
contains = list(
+ /obj/item/device/flash = 2,
+ /obj/item/weapon/reagent_containers/spray/pepper = 2,
/obj/item/weapon/melee/baton/loaded = 2,
- /obj/item/weapon/gun/energy/gun = 2,
/obj/item/weapon/gun/energy/taser = 2,
/obj/item/weapon/gun/projectile/colt/detective = 2,
/obj/item/weapon/storage/box/flashbangs = 2
)
cost = 40
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Security equipment crate"
+ access = access_security
+
+/datum/supply_packs/munitions/egunpistol
+ name = "Weapons - Energy sidearms"
+ contains = list(/obj/item/weapon/gun/energy/gun = 2)
+ cost = 40
containertype = /obj/structure/closet/crate/secure/weapon
- containername = "Weapons crate"
+ containername = "Energy sidearms crate"
access = access_security
/datum/supply_packs/munitions/flareguns
- name = "Flare guns crate"
+ name = "Weapons - Flare guns"
contains = list(
/obj/item/weapon/gun/projectile/sec/flash,
/obj/item/ammo_magazine/m45/flash,
@@ -32,100 +41,96 @@
/obj/item/weapon/storage/box/flashshells
)
cost = 25
- containertype = /obj/structure/closet/crate/secure/weapon
+ containertype = /obj/structure/closet/crate/secure/gear
containername = "Flare gun crate"
access = access_security
/datum/supply_packs/munitions/eweapons
- name = "Experimental weapons crate"
+ name = "Weapons - Experimental weapons crate"
contains = list(
/obj/item/weapon/gun/energy/xray = 2,
/obj/item/weapon/shield/energy = 2)
cost = 100
- containertype = /obj/structure/closet/crate/secure/weapon
+ containertype = /obj/structure/closet/crate/secure/science
containername = "Experimental weapons crate"
access = access_armory
/datum/supply_packs/munitions/energyweapons
- name = "Laser carbine crate"
+ name = "Weapons - Laser rifle crate"
contains = list(/obj/item/weapon/gun/energy/laser = 3)
cost = 50
- containertype = /obj/structure/closet/crate/secure
- containername = "energy weapons crate"
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Energy weapons crate"
access = access_armory
/datum/supply_packs/munitions/shotgun
- name = "Shotgun crate"
+ name = "Weapons - Shotgun crate"
contains = list(
/obj/item/weapon/storage/box/shotgunammo,
/obj/item/weapon/storage/box/shotgunshells,
/obj/item/weapon/gun/projectile/shotgun/pump/combat = 2
)
cost = 50
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/weapon
containername = "Shotgun crate"
access = access_armory
/datum/supply_packs/munitions/erifle
- name = "Energy marksman crate"
+ name = "Weapons - Energy marksman"
contains = list(/obj/item/weapon/gun/energy/sniperrifle = 2)
cost = 100
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/weapon
containername = "Energy marksman crate"
access = access_armory
/datum/supply_packs/munitions/burstlaser
- name = "Burst laser crate"
+ name = "Weapons - Burst laser"
contains = list(/obj/item/weapon/gun/energy/gun/burst = 2)
cost = 50
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/weapon
containername = "Burst laser crate"
access = access_armory
/datum/supply_packs/munitions/ionweapons
- name = "Electromagnetic weapons crate"
+ name = "Weapons - Electromagnetic Rifles"
contains = list(
/obj/item/weapon/gun/energy/ionrifle = 2,
/obj/item/weapon/storage/box/empslite
)
cost = 50
- containertype = /obj/structure/closet/crate/secure
- containername = "electromagnetic weapons crate"
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Electromagnetic weapons crate"
access = access_armory
/datum/supply_packs/munitions/ionpistols
- name = "Electromagnetic pistols crate"
+ name = "Weapons - Electromagnetic pistols"
contains = list(
/obj/item/weapon/gun/energy/ionrifle/pistol = 2,
/obj/item/weapon/storage/box/empslite
)
cost = 30
- containertype = /obj/structure/closet/crate/secure
- containername = "electromagnetic weapons crate"
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Electromagnetic weapons crate"
access = access_armory
-/datum/supply_packs/randomised/munitions/automatic
- name = "Automatic weapon crate"
- num_contained = 2
- contains = list(
- /obj/item/weapon/gun/projectile/automatic/wt550,
- /obj/item/weapon/gun/projectile/automatic/z8
- )
- cost = 100
- containertype = /obj/structure/closet/crate/secure
- containername = "Automatic weapon crate"
- access = access_armory
-
-/datum/supply_packs/munitions/energy_guns
- name = "Energy gun crate"
- contains = list(/obj/item/weapon/gun/energy/gun = 2)
+/datum/supply_packs/munitions/bsmg
+ name = "Weapons - Ballistic SMGs"
+ contains = list(/obj/item/weapon/gun/projectile/automatic/wt550 = 2)
cost = 50
- containertype = /obj/structure/closet/crate/secure
- containername = "Energy gun crate"
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Ballistic weapon crate"
+ access = access_armory
+
+/datum/supply_packs/munitions/brifle
+ name = "Weapons - Ballistic Rifles"
+ contains = list(/obj/item/weapon/gun/projectile/automatic/z8 = 2)
+ cost = 80
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Ballistic weapon crate"
access = access_armory
/datum/supply_packs/munitions/bolt_rifles_competitive
- name = "Competitive shooting crate"
+ name = "Weapons - Competitive shooting rifles"
contains = list(
/obj/item/device/assembly/timer,
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/practice = 2,
@@ -136,37 +141,56 @@
)
cost = 40
containertype = /obj/structure/closet/crate/secure/weapon
- containername = "Weapons crate"
+ containername = "Ballistic weapons crate"
access = access_security
/datum/supply_packs/munitions/shotgunammo
- name = "Shotgun ammunition crate"
+ name = "Ammunition - Shotgun shells"
contains = list(
/obj/item/weapon/storage/box/shotgunammo = 2,
/obj/item/weapon/storage/box/shotgunshells = 2
)
cost = 25
containertype = /obj/structure/closet/crate/secure
- containername = "ballistic ammunition crate"
- access = access_armory
-
-/datum/supply_packs/randomised/munitions/autoammo
- name = "Automatic weapon ammunition crate"
- num_contained = 6
- contains = list(
- /obj/item/ammo_magazine/m9mmt,
- /obj/item/ammo_magazine/m9mmt/rubber,
- /obj/item/ammo_magazine/m545saw
- )
- cost = 25
- containertype = /obj/structure/closet/crate/secure
- containername = "Automatic weapon ammunition crate"
+ containername = "Ballistic ammunition crate"
access = access_armory
/datum/supply_packs/munitions/beanbagammo
- name = "Beanbag shells"
+ name = "Ammunition - Beanbag shells"
contains = list(/obj/item/weapon/storage/box/beanbags = 3)
cost = 25
containertype = /obj/structure/closet/crate
- containername = "Beanbag shells"
+ containername = "Ballistic ammunition crate"
access = null
+
+/datum/supply_packs/munitions/bsmgammo
+ name = "Ammunition - 9mm top mounted lethal"
+ contains = list(/obj/item/ammo_magazine/m9mmt = 6)
+ cost = 25
+ containertype = /obj/structure/closet/crate/secure
+ containername = "Ballistic ammunition crate"
+ access = access_armory
+
+/datum/supply_packs/munitions/bsmgammorubber
+ name = "Ammunition - 9mm top mounted rubber"
+ contains = list(/obj/item/ammo_magazine/m9mmt/rubber = 6)
+ cost = 25
+ containertype = /obj/structure/closet/crate/secure
+ containername = "Ballistic ammunition crate"
+ access = access_security
+
+/datum/supply_packs/munitions/brifleammo
+ name = "Ammunition - 7.62mm lethal"
+ contains = list(/obj/item/ammo_magazine/m762 = 6)
+ cost = 25
+ containertype = /obj/structure/closet/crate/secure
+ containername = "Ballistic ammunition crate"
+ access = access_armory
+
+/datum/supply_packs/munitions/pcellammo
+ name = "Ammunition - Power cell"
+ contains = list(/obj/item/weapon/cell/device/weapon = 3)
+ cost = 50
+ containertype = /obj/structure/closet/crate/secure
+ containername = "Energy ammunition crate"
+ access = access_security
\ No newline at end of file
diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm
index 7bfdaaeeb6..7f801ea1b3 100644
--- a/code/datums/supplypacks/recreation.dm
+++ b/code/datums/supplypacks/recreation.dm
@@ -39,6 +39,7 @@
name = "Arts and Crafts supplies"
contains = list(
/obj/item/weapon/storage/fancy/crayons,
+ /obj/item/weapon/storage/fancy/markers,
/obj/item/device/camera,
/obj/item/device/camera_film = 2,
/obj/item/weapon/storage/photo_album,
diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index 3e861e354b..d9f20c5aa6 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -116,14 +116,6 @@
containername = "Robolimb blueprints (Bishop)"
access = access_robotics
-/datum/supply_packs/robotics/robolimbs/veymed
- name = "Vey-Med robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/veymed)
- cost = 70
- containertype = /obj/structure/closet/crate/secure/science
- containername = "Robolimb blueprints (Vey-Med)"
- access = access_robotics
-
/datum/supply_packs/robotics/mecha_ripley
name = "Circuit Crate (\"Ripley\" APLU)"
contains = list(
diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm
index e248acc46c..eb031e7bd9 100644
--- a/code/datums/supplypacks/security.dm
+++ b/code/datums/supplypacks/security.dm
@@ -13,6 +13,7 @@
access = access_security
/datum/supply_packs/randomised/security/armor
+ name = "Armor - Security armor"
num_contained = 5
contains = list(
/obj/item/clothing/suit/storage/vest,
@@ -27,14 +28,12 @@
/obj/item/clothing/suit/storage/vest/heavy/hos,
/obj/item/clothing/suit/storage/vest/heavy/pcrc
)
-
- name = "Armor crate"
cost = 40
- containertype = /obj/structure/closet/crate/secure
+ containertype = /obj/structure/closet/crate/secure/gear
containername = "Armor crate"
/datum/supply_packs/security/riot_gear
- name = "Riot gear crate"
+ name = "Gear - Riot"
contains = list(
/obj/item/weapon/melee/baton = 3,
/obj/item/weapon/shield/riot = 3,
@@ -44,12 +43,12 @@
/obj/item/weapon/storage/box/handcuffs
)
cost = 40
- containertype = /obj/structure/closet/crate/secure
- containername = "riot gear crate"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Riot gear crate"
access = access_armory
/datum/supply_packs/security/riot_armor
- name = "Riot armor set crate"
+ name = "Armor - Riot"
contains = list(
/obj/item/clothing/head/helmet/riot,
/obj/item/clothing/suit/armor/riot,
@@ -57,12 +56,12 @@
/obj/item/clothing/shoes/leg_guard/riot
)
cost = 30
- containertype = /obj/structure/closet/crate/secure
- containername = "riot armor set crate"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Riot armor crate"
access = access_armory
/datum/supply_packs/security/ablative_armor
- name = "Ablative armor set crate"
+ name = "Armor - Ablative"
contains = list(
/obj/item/clothing/head/helmet/laserproof,
/obj/item/clothing/suit/armor/laserproof,
@@ -70,12 +69,12 @@
/obj/item/clothing/shoes/leg_guard/laserproof
)
cost = 40
- containertype = /obj/structure/closet/crate/secure
- containername = "ablative armor set crate"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Ablative armor crate"
access = access_armory
/datum/supply_packs/security/bullet_resistant_armor
- name = "Bullet resistant armor set crate"
+ name = "Armor - Ballistic"
contains = list(
/obj/item/clothing/head/helmet/bulletproof,
/obj/item/clothing/suit/armor/bulletproof,
@@ -83,12 +82,12 @@
/obj/item/clothing/shoes/leg_guard/bulletproof
)
cost = 40
- containertype = /obj/structure/closet/crate/secure
- containername = "bullet resistant armor set crate"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Ballistic armor crate"
access = access_armory
/datum/supply_packs/security/combat_armor
- name = "Combat armor set crate"
+ name = "Armor - Combat"
contains = list(
/obj/item/clothing/head/helmet/combat,
/obj/item/clothing/suit/armor/combat,
@@ -96,14 +95,14 @@
/obj/item/clothing/shoes/leg_guard/combat
)
cost = 40
- containertype = /obj/structure/closet/crate/secure
- containername = "combat armor set crate"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Combat armor crate"
access = access_armory
/datum/supply_packs/security/tactical
- name = "Tactical suits"
- containertype = /obj/structure/closet/crate/secure
- containername = "Tactical Suit Locker"
+ name = "Armor - Tactical"
+ containertype = /obj/structure/closet/crate/secure/gear
+ containername = "Tactical armor crate"
cost = 40
access = access_armory
contains = list(
@@ -126,23 +125,23 @@
)
/datum/supply_packs/security/securitybarriers
- name = "Security barrier crate"
+ name = "Misc - Security Barriers"
contains = list(/obj/machinery/deployable/barrier = 4)
cost = 20
- containertype = /obj/structure/closet/crate/secure/gear
+ containertype = /obj/structure/largecrate
containername = "Security barrier crate"
access = null
/datum/supply_packs/security/securityshieldgen
- name = "Wall shield Generators"
+ name = "Misc - Wall shield generators"
contains = list(/obj/machinery/shieldwallgen = 4)
cost = 20
containertype = /obj/structure/closet/crate/secure
- containername = "wall shield generators crate"
+ containername = "Wall shield generators crate"
access = access_teleporter
/datum/supply_packs/randomised/security/holster
- name = "Holster crate"
+ name = "Gear - Holsters"
num_contained = 4
contains = list(
/obj/item/clothing/accessory/holster,
@@ -151,11 +150,11 @@
/obj/item/clothing/accessory/holster/hip
)
cost = 15
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate
containername = "Holster crate"
/datum/supply_packs/security/extragear
- name = "Security surplus equipment"
+ name = "Gear - Security surplus equipment"
contains = list(
/obj/item/weapon/storage/belt/security = 3,
/obj/item/clothing/glasses/sunglasses/sechud = 3,
@@ -163,12 +162,11 @@
/obj/item/clothing/suit/storage/hooded/wintercoat/security = 3
)
cost = 10
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate
containername = "Security surplus equipment"
- access = null
/datum/supply_packs/security/detectivegear
- name = "Forensic investigation equipment"
+ name = "Forensic - Investigation equipment"
contains = list(
/obj/item/weapon/storage/box/evidence = 2,
/obj/item/clothing/suit/storage/vest/detective,
@@ -190,12 +188,12 @@
/obj/item/weapon/storage/briefcase/crimekit
)
cost = 20
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Forensic equipment"
access = access_forensics_lockers
/datum/supply_packs/security/detectiveclothes
- name = "Investigation apparel"
+ name = "Forensic - Investigation apparel"
contains = list(
/obj/item/clothing/under/det/black = 2,
/obj/item/clothing/under/det/grey = 2,
@@ -212,12 +210,12 @@
/obj/item/clothing/gloves/black = 2
)
cost = 10
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Investigation clothing"
access = access_forensics_lockers
/datum/supply_packs/security/officergear
- name = "Officer equipment"
+ name = "Gear - Officer equipment"
contains = list(
/obj/item/clothing/suit/storage/vest/officer,
/obj/item/clothing/head/helmet,
@@ -242,12 +240,12 @@
/obj/item/device/flashlight/maglight
)
cost = 20
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Officer equipment"
access = access_brig
/datum/supply_packs/security/wardengear
- name = "Warden equipment"
+ name = "Gear - Warden equipment"
contains = list(
/obj/item/clothing/suit/storage/vest/warden,
/obj/item/clothing/under/rank/warden,
@@ -270,18 +268,18 @@
/obj/item/device/flashlight/maglight
)
cost = 20
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Warden equipment"
access = access_armory
/datum/supply_packs/security/headofsecgear
- name = "Head of security equipment"
+ name = "Gear - Head of security equipment"
contains = list(
/obj/item/clothing/head/helmet/HoS,
/obj/item/clothing/suit/storage/vest/hos,
/obj/item/clothing/under/rank/head_of_security/corp,
/obj/item/clothing/suit/storage/vest/hoscoat,
- /obj/item/clothing/head/helmet/HoS/dermal,
+ /obj/item/clothing/head/helmet/dermal,
/obj/item/weapon/cartridge/hos,
/obj/item/device/radio/headset/heads/hos,
/obj/item/clothing/glasses/sunglasses/sechud,
@@ -296,12 +294,12 @@
/obj/item/device/flashlight/maglight
)
cost = 50
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Head of security equipment"
access = access_hos
/datum/supply_packs/security/securityclothing
- name = "Security uniform crate"
+ name = "Misc - Security uniform red"
contains = list(
/obj/item/weapon/storage/backpack/satchel/sec = 2,
/obj/item/weapon/storage/backpack/security = 2,
@@ -315,11 +313,11 @@
/obj/item/weapon/storage/box/holobadge
)
cost = 10
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Security uniform crate"
/datum/supply_packs/security/navybluesecurityclothing
- name = "Navy blue security uniform crate"
+ name = "Misc - Security uniform navy blue"
contains = list(
/obj/item/weapon/storage/backpack/satchel/sec = 2,
/obj/item/weapon/storage/backpack/security = 2,
@@ -336,11 +334,11 @@
/obj/item/weapon/storage/box/holobadge
)
cost = 10
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Navy blue security uniform crate"
/datum/supply_packs/security/corporatesecurityclothing
- name = "Corporate security uniform crate"
+ name = "Misc - Security uniform corporate"
contains = list(
/obj/item/weapon/storage/backpack/satchel/sec = 2,
/obj/item/weapon/storage/backpack/security = 2,
@@ -356,11 +354,11 @@
/obj/item/weapon/storage/box/holobadge
)
cost = 10
- containertype = "/obj/structure/closet/crate/secure"
+ containertype = /obj/structure/closet/crate/secure
containername = "Corporate security uniform crate"
/datum/supply_packs/security/biosuit
- name = "Security biohazard gear"
+ name = "Gear - Security biohazard gear"
contains = list(
/obj/item/clothing/head/bio_hood/security = 3,
/obj/item/clothing/under/rank/security = 3,
@@ -371,6 +369,7 @@
/obj/item/clothing/gloves/sterile/latex,
/obj/item/weapon/storage/box/gloves
)
- cost = 50
- containertype = "/obj/structure/closet/crate/secure"
+ cost = 25
+ containertype = /obj/structure/closet/crate/secure
containername = "Security biohazard gear"
+ access = access_security
\ No newline at end of file
diff --git a/code/datums/underwear/underwear.dm b/code/datums/underwear/underwear.dm
index bac96bf55c..f418f3e8d1 100644
--- a/code/datums/underwear/underwear.dm
+++ b/code/datums/underwear/underwear.dm
@@ -63,11 +63,11 @@ datum/category_group/underwear/dd_SortValue()
/datum/category_item/underwear/proc/is_default(var/gender)
return is_default
-/datum/category_item/underwear/proc/generate_image(var/list/metadata)
+/datum/category_item/underwear/proc/generate_image(var/list/metadata, var/layer = FLOAT_LAYER)
if(!icon_state)
return
- var/image/I = image(icon = icon, icon_state = icon_state)
+ var/image/I = image(icon = icon, icon_state = icon_state, layer = layer)
for(var/datum/gear_tweak/gt in tweaks)
gt.tweak_item(I, metadata && metadata["[gt]"] ? metadata["[gt]"] : gt.get_default())
return I
\ No newline at end of file
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index abaffea57b..ba809cb977 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -203,6 +203,12 @@ var/global/list/PDA_Manifest = list()
anchored = 1
unacidable = 1//temporary until I decide whether the borg can be removed. -veyveyr
+/obj/structure/showcase/sign
+ name = "WARNING: WILDERNESS"
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "wilderness1"
+ desc = "This appears to be a sign warning people that the other side is dangerous. It also says that NanoTrasen cannot guarantee your safety beyond this point."
+
/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER
/obj/item/weapon/beach_ball
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index b6a45d9a07..75c95d0b0c 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -480,6 +480,7 @@
/obj/item/weapon/stock_parts/capacitor/adv
name = "advanced capacitor"
desc = "An advanced capacitor used in the construction of a variety of devices."
+ icon_state = "capacitor_adv"
origin_tech = list(TECH_POWER = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
@@ -487,7 +488,7 @@
/obj/item/weapon/stock_parts/scanning_module/adv
name = "advanced scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
- icon_state = "scan_module"
+ icon_state = "scan_module_adv"
origin_tech = list(TECH_MAGNET = 3)
rating = 2
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
@@ -521,6 +522,7 @@
/obj/item/weapon/stock_parts/capacitor/super
name = "super capacitor"
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
+ icon_state = "capacitor_super"
origin_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 50)
@@ -528,6 +530,7 @@
/obj/item/weapon/stock_parts/scanning_module/phasic
name = "phasic scanning module"
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
+ icon_state = "scan_module_phasic"
origin_tech = list(TECH_MAGNET = 5)
rating = 3
matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20)
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 5c44353540..22fa3438ca 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -111,7 +111,7 @@ datum/announcement/priority/command/Sound(var/message_sound)
datum/announcement/proc/Log(message as text, message_title as text)
if(log)
- log_say("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]")
+ log_game("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]")
message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1)
/proc/GetNameAndAssignmentFromId(var/obj/item/weapon/card/id/I)
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index b36c27e116..484ff8ea33 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -52,7 +52,7 @@
var/flags = 0 // Various runtime options.
// Used for setting appearance.
- var/list/valid_species = list("Unathi","Tajara","Skrell","Human","Diona","Teshari")
+ var/list/valid_species = list(SPECIES_UNATHI,SPECIES_TAJ,SPECIES_SKRELL,SPECIES_HUMAN,SPECIES_DIONA,SPECIES_TESHARI)
// Runtime vars.
var/datum/mind/leader // Current leader, if any.
diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm
index 7cf17b5640..16c27f82c7 100644
--- a/code/game/antagonist/antagonist_update.dm
+++ b/code/game/antagonist/antagonist_update.dm
@@ -33,7 +33,9 @@
if(!antag_indicator || !other.current || !recipient.current)
return
var/indicator = (faction_indicator && (other in faction_members)) ? faction_indicator : antag_indicator
- return image('icons/mob/mob.dmi', loc = other.current, icon_state = indicator, layer = LIGHTING_LAYER+0.1)
+ var/image/returnimage = image('icons/mob/mob.dmi', loc = other.current, icon_state = indicator)
+ returnimage.plane = PLANE_LIGHTING_ABOVE
+ return returnimage
/datum/antagonist/proc/update_all_icons()
if(!antag_indicator)
diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm
index ed2964cfad..94b362fca8 100644
--- a/code/game/antagonist/outsider/mercenary.dm
+++ b/code/game/antagonist/outsider/mercenary.dm
@@ -42,16 +42,14 @@ var/datum/antagonist/mercenary/mercs
if(player.backbag == 3) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(player), slot_back)
if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(player), slot_back)
if(player.backbag == 5) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(player), slot_back)
- player.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(player.back), slot_in_backpack)
player.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(player), slot_in_backpack)
+
player.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
player.mind.accept_tcrystals = 1
var/obj/item/device/radio/uplink/U = new(player.loc, player.mind, DEFAULT_TELECRYSTAL_AMOUNT)
player.put_in_hands(U)
- player.update_icons_layers()
-
create_id("Mercenary", player)
create_radio(SYND_FREQ, player)
return 1
diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm
index b37fbb5c50..02a314b1f3 100644
--- a/code/game/antagonist/outsider/ninja.dm
+++ b/code/game/antagonist/outsider/ninja.dm
@@ -158,7 +158,7 @@ var/datum/antagonist/ninja/ninjas
if(13)
directive += "Some disgruntled [using_map.company_name] employees have been supportive of our operations. Be wary of any mistreatment by command staff."
if(14)
- var/xenorace = pick("Unathi","Tajara", "Skrell")
+ var/xenorace = pick(SPECIES_UNATHI, SPECIES_TAJ, SPECIES_SKRELL)
directive += "A group of [xenorace] radicals have been loyal supporters of the Spider Clan. Favor [xenorace] crew whenever possible."
if(15)
directive += "The Spider Clan has recently been accused of religious insensitivity. Attempt to speak with the Chaplain and prove these accusations false."
diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm
index 7c62208ca1..c130d8e66f 100644
--- a/code/game/antagonist/outsider/raider.dm
+++ b/code/game/antagonist/outsider/raider.dm
@@ -205,7 +205,7 @@ var/datum/antagonist/raider/raiders
if(!..())
return 0
- if(player.species && player.species.get_bodytype() == "Vox")
+ if(player.species && player.species.get_bodytype() == SPECIES_VOX)
equip_vox(player)
else
var/new_shoes = pick(raider_shoes)
diff --git a/code/game/antagonist/outsider/technomancer.dm b/code/game/antagonist/outsider/technomancer.dm
index 33dc33b5e8..2cb7532308 100644
--- a/code/game/antagonist/outsider/technomancer.dm
+++ b/code/game/antagonist/outsider/technomancer.dm
@@ -47,7 +47,6 @@ var/datum/antagonist/technomancer/technomancers
technomancer_mob.equip_to_slot_or_del(new /obj/item/device/flashlight(technomancer_mob), slot_belt)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(technomancer_mob), slot_shoes)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/head/technomancer/master(technomancer_mob), slot_head)
- technomancer_mob.update_icons_layers()
return 1
/datum/antagonist/technomancer/proc/equip_apprentice(var/mob/living/carbon/human/technomancer_mob)
@@ -67,7 +66,6 @@ var/datum/antagonist/technomancer/technomancers
technomancer_mob.equip_to_slot_or_del(new /obj/item/device/flashlight(technomancer_mob), slot_belt)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(technomancer_mob), slot_shoes)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/head/technomancer/apprentice(technomancer_mob), slot_head)
- technomancer_mob.update_icons()
return 1
/datum/antagonist/technomancer/check_victory()
diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm
index ad5cc10479..feaf8857ba 100644
--- a/code/game/antagonist/outsider/wizard.dm
+++ b/code/game/antagonist/outsider/wizard.dm
@@ -87,7 +87,6 @@ var/datum/antagonist/wizard/wizards
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand)
- wizard_mob.update_icons_layers()
return 1
/datum/antagonist/wizard/check_victory()
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 2c75c0d255..d249518607 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -13,82 +13,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
*/
-
-
-/area
- var/fire = null
- var/atmos = 1
- var/atmosalm = 0
- var/poweralm = 1
- var/party = null
- level = null
- name = "Unknown"
- icon = 'icons/turf/areas.dmi'
- icon_state = "unknown"
- layer = 10
- luminosity = 0
- mouse_opacity = 0
- var/lightswitch = 1
-
- var/eject = null
-
- var/debug = 0
- var/requires_power = 1
- var/always_unpowered = 0 //this gets overriden to 1 for space in area/New()
-
- var/power_equip = 1
- var/power_light = 1
- var/power_environ = 1
- var/music = null
- var/used_equip = 0
- var/used_light = 0
- var/used_environ = 0
-
- var/has_gravity = 1
- var/obj/machinery/power/apc/apc = null
- var/no_air = null
-// var/list/lights // list of all lights on this area
- var/list/all_doors = null //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
- var/firedoors_closed = 0
- var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
- 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
-
-/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
-/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
-var/list/teleportlocs = list()
-
-/hook/startup/proc/setupTeleportLocs()
- 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))
- if (picked.z in using_map.station_levels)
- teleportlocs += AR.name
- teleportlocs[AR.name] = AR
-
- teleportlocs = sortAssoc(teleportlocs)
-
- return 1
-
-var/list/ghostteleportlocs = list()
-
-/hook/startup/proc/setupGhostTeleportLocs()
- 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
- ghostteleportlocs[AR.name] = AR
- var/turf/picked = pick(get_area_turfs(AR.type))
- if (picked.z in using_map.player_levels)
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
-
- ghostteleportlocs = sortAssoc(ghostteleportlocs)
-
- return 1
-
/*-----------------------------------------------------------------------------*/
/////////
@@ -104,7 +28,7 @@ var/list/ghostteleportlocs = list()
power_light = 0
power_equip = 0
power_environ = 0
- ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
+ ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg','sound/ambience/serspaceamb1.ogg')
base_turf = /turf/space
area/space/atmosalert()
@@ -358,6 +282,7 @@ area/space/atmosalert()
/area/shuttle/trade
name = "\improper Trade Station"
icon_state = "red"
+ dynamic_lighting = 0
/area/shuttle/trade/centcom
name = "\improper Trade Shuttle CentCom"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index e9d93b48a3..c7a653a4c3 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -1,15 +1,49 @@
// Areas.dm
-
-
-// ===
/area
+ var/fire = null
+ var/atmos = 1
+ var/atmosalm = 0
+ var/poweralm = 1
+ var/party = null
+ level = null
+ name = "Unknown"
+ icon = 'icons/turf/areas.dmi'
+ icon_state = "unknown"
+ plane = PLANE_LIGHTING_ABOVE //In case we color them
+ luminosity = 0
+ mouse_opacity = 0
+ var/lightswitch = 1
+
+ var/eject = null
+
+ var/debug = 0
+ var/requires_power = 1
+ var/always_unpowered = 0 //this gets overriden to 1 for space in area/New()
+
+ var/power_equip = 1
+ var/power_light = 1
+ var/power_environ = 1
+ var/music = null
+ var/used_equip = 0
+ var/used_light = 0
+ var/used_environ = 0
+
+ var/has_gravity = 1
+ var/obj/machinery/power/apc/apc = null
+ var/no_air = null
+// var/list/lights // list of all lights on this area
+ var/list/all_doors = null //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
+ var/firedoors_closed = 0
+ var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
+ 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()
icon_state = ""
- layer = 10
uid = ++global_uid
all_areas += src
@@ -248,23 +282,26 @@ var/list/mob/living/forced_ambiance_list = new
// If we previously were in an area with force-played ambiance, stop it.
if(L in forced_ambiance_list)
- L << sound(null, channel = 1)
+ L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
forced_ambiance_list -= L
if(!L.client.ambience_playing)
L.client.ambience_playing = 1
- L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
+ L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_AMBIENCE)
if(forced_ambience)
if(forced_ambience.len)
forced_ambiance_list |= L
- L << sound(pick(forced_ambience), repeat = 1, wait = 0, volume = 25, channel = 1)
+ var/sound/chosen_ambiance = pick(forced_ambience)
+ if(!istype(chosen_ambiance))
+ chosen_ambiance = sound(chosen_ambiance, repeat = 1, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE_FORCED)
+ L << chosen_ambiance
else
- L << sound(null, channel = 1)
+ L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
else if(src.ambience.len && prob(35))
if((world.time >= L.client.played + 600))
var/sound = pick(ambience)
- L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1)
+ L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)
L.client.played = world.time
/area/proc/gravitychange(var/gravitystate = 0, var/area/A)
@@ -318,3 +355,49 @@ var/list/mob/living/forced_ambiance_list = new
if(A && A.has_gravity())
return 1
return 0
+
+/area/proc/shuttle_arrived()
+ return TRUE
+
+/area/proc/shuttle_departed()
+ return TRUE
+
+/area/AllowDrop()
+ CRASH("Bad op: area/AllowDrop() called")
+
+/area/drop_location()
+ CRASH("Bad op: area/drop_location() called")
+
+/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
+/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
+var/list/teleportlocs = list()
+
+/hook/startup/proc/setupTeleportLocs()
+ 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))
+ if (picked.z in using_map.station_levels)
+ teleportlocs += AR.name
+ teleportlocs[AR.name] = AR
+
+ teleportlocs = sortAssoc(teleportlocs)
+
+ return 1
+
+var/list/ghostteleportlocs = list()
+
+/hook/startup/proc/setupGhostTeleportLocs()
+ 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
+ ghostteleportlocs[AR.name] = AR
+ var/turf/picked = pick(get_area_turfs(AR.type))
+ if (picked.z in using_map.player_levels)
+ ghostteleportlocs += AR.name
+ ghostteleportlocs[AR.name] = AR
+
+ ghostteleportlocs = sortAssoc(ghostteleportlocs)
+
+ return 1
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index d23f53c23a..dda3e0a6b5 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1,5 +1,5 @@
/atom
- layer = 2
+ layer = TURF_LAYER //This was here when I got here. Why though?
var/level = 2
var/flags = 0
var/list/fingerprints
@@ -22,6 +22,10 @@
// replaced by OPENCONTAINER flags and atom/proc/is_open_container()
///Chemistry.
+ // Overlays
+ var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate
+ var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
+
//Detective Work, used for the duplicate data points kept in the scanners
var/list/original_atom
// Track if we are already had initialize() called to prevent double-initialization.
@@ -498,3 +502,18 @@
if(A && A.has_gravity())
return TRUE
return FALSE
+
+/atom/proc/drop_location()
+ var/atom/L = loc
+ if(!L)
+ return null
+ return L.AllowDrop() ? L : get_turf(L)
+
+/atom/proc/AllowDrop()
+ return FALSE
+
+/atom/proc/get_nametag_name(mob/user)
+ return name
+
+/atom/proc/get_nametag_desc(mob/user)
+ return "" //Desc itself is often too long to use
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 0cd09b8a57..5311d642a2 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -1,5 +1,5 @@
/atom/movable
- layer = 3
+ layer = OBJ_LAYER
appearance_flags = TILE_BOUND|PIXEL_SCALE
var/last_move = null
var/anchored = 0
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index e80dcb7227..4f5c9ae699 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -83,7 +83,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
var/real_name // Stores the real name of the person who originally got this dna datum. Used primarily for changelings,
// New stuff
- var/species = "Human"
+ var/species = SPECIES_HUMAN
var/list/body_markings = list()
// Make a copy of this strand.
diff --git a/code/game/gamemodes/changeling/generic_equip_procs.dm b/code/game/gamemodes/changeling/generic_equip_procs.dm
index 7ff76ff9f6..ef1ab650a1 100644
--- a/code/game/gamemodes/changeling/generic_equip_procs.dm
+++ b/code/game/gamemodes/changeling/generic_equip_procs.dm
@@ -122,7 +122,6 @@
playsound(src, 'sound/effects/splat.ogg', 30, 1)
visible_message("[src] pulls on their clothes, peeling it off along with parts of their skin attached!",
"We remove and deform our equipment.")
- M.update_icons_layers()
M.mind.changeling.armor_deployed = 0
return success
@@ -138,7 +137,6 @@
M.equip_to_slot_or_del(I, slot_head)
grown_items_list.Add("a helmet")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -148,7 +146,6 @@
M.equip_to_slot_or_del(I, slot_w_uniform)
grown_items_list.Add("a uniform")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -158,7 +155,6 @@
M.equip_to_slot_or_del(I, slot_gloves)
grown_items_list.Add("some gloves")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -168,7 +164,6 @@
M.equip_to_slot_or_del(I, slot_shoes)
grown_items_list.Add("shoes")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -178,7 +173,6 @@
M.equip_to_slot_or_del(I, slot_belt)
grown_items_list.Add("a belt")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -188,7 +182,6 @@
M.equip_to_slot_or_del(I, slot_glasses)
grown_items_list.Add("some glasses")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -198,7 +191,6 @@
M.equip_to_slot_or_del(I, slot_wear_mask)
grown_items_list.Add("a mask")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -208,7 +200,6 @@
M.equip_to_slot_or_del(I, slot_back)
grown_items_list.Add("a backpack")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -218,7 +209,6 @@
M.equip_to_slot_or_del(I, slot_wear_suit)
grown_items_list.Add("an exosuit")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
@@ -228,20 +218,13 @@
M.equip_to_slot_or_del(I, slot_wear_id)
grown_items_list.Add("an ID card")
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- M.update_icons_layers()
success = 1
sleep(1 SECOND)
var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
M << "We have grown [feedback]."
- /*
- for(var/I in stuff_to_equip)
- world << I
- world << stuff_to_equip
- world << "Proc ended."
- */
- M.update_icons()
+
if(success)
M.mind.changeling.armor_deployed = 1
M.mind.changeling.chem_charges -= 10
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 0af67b22ed..f76fd5ca47 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -53,9 +53,7 @@
src << "We stab [T] with the proboscis."
src.visible_message("[src] stabs [T] with the proboscis!")
T << "You feel a sharp stabbing pain!"
- T.attack_log += text("\[[time_stamp()]\] Was absorbed by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Absorbed [key_name(T)]")
- msg_admin_attack("[key_name(T)] was absorbed by [key_name(src)]")
+ add_attack_logs(src,T,"Absorbed (changeling)")
var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting)
if(affecting.take_damage(39,0,1,0,"large organic needle"))
T:UpdateDamageIcon()
diff --git a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
index c173ba55ac..3f3c1bd7ad 100644
--- a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
+++ b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
@@ -47,7 +47,7 @@
var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower.
G.affecting.stun_effect_act(0, agony, BP_TORSO, src)
- msg_admin_attack("[key_name(src)] shocked [key_name(G.affecting)] with the [src].")
+ add_attack_logs(src,G.affecting,"Changeling shocked")
if(siemens)
visible_message("Arcs of electricity strike [G.affecting]!",
@@ -102,6 +102,8 @@
desc = "You could probably shock someone badly if you touched them, or recharge something."
icon = 'icons/obj/weapons.dmi'
icon_state = "electric_hand"
+ show_examine = FALSE
+
var/shock_cost = 10
var/agony_amount = 60
var/electrocute_amount = 10
@@ -147,7 +149,7 @@
C.electrocute_act(electrocute_amount * siemens,src,1.0,BP_TORSO)
C.stun_effect_act(0, agony_amount * siemens, BP_TORSO, src)
- msg_admin_attack("[key_name(user)] shocked [key_name(C)] with the [src].")
+ add_attack_logs(user,C,"Shocked with [src]")
if(siemens)
visible_message("Arcs of electricity strike [C]!",
diff --git a/code/game/gamemodes/changeling/powers/blind_sting.dm b/code/game/gamemodes/changeling/powers/blind_sting.dm
index 41b14478b3..347881df9b 100644
--- a/code/game/gamemodes/changeling/powers/blind_sting.dm
+++ b/code/game/gamemodes/changeling/powers/blind_sting.dm
@@ -15,9 +15,7 @@
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting)
if(!T)
return 0
- T.attack_log += text("\[[time_stamp()]\] Was blind stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used blind sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was blind stung by [key_name(src)]")
+ add_attack_logs(src,T,"Blind sting (changeling)")
T << "Your eyes burn horrificly!"
T.disabilities |= NEARSIGHTED
var/duration = 300
diff --git a/code/game/gamemodes/changeling/powers/cryo_sting.dm b/code/game/gamemodes/changeling/powers/cryo_sting.dm
index 4bb92a543e..bc68428d89 100644
--- a/code/game/gamemodes/changeling/powers/cryo_sting.dm
+++ b/code/game/gamemodes/changeling/powers/cryo_sting.dm
@@ -16,9 +16,7 @@
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_cryo_sting)
if(!T)
return 0
- T.attack_log += text("\[[time_stamp()]\] Was cryo stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used cryo sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was cryo stung by [key_name(src)]")
+ add_attack_logs(src,T,"Cryo sting (changeling)")
var/inject_amount = 10
if(src.mind.changeling.recursive_enhancement)
inject_amount = inject_amount * 1.5
diff --git a/code/game/gamemodes/changeling/powers/deaf_sting.dm b/code/game/gamemodes/changeling/powers/deaf_sting.dm
index 24c1e5d260..a94ad1744a 100644
--- a/code/game/gamemodes/changeling/powers/deaf_sting.dm
+++ b/code/game/gamemodes/changeling/powers/deaf_sting.dm
@@ -15,9 +15,7 @@
var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting)
if(!T) return 0
- T.attack_log += text("\[[time_stamp()]\] Was deaf stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used deaf sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was deaf stung by [key_name(src)]")
+ add_attack_logs(src,T,"Deaf sting (changeling)")
var/duration = 300
if(src.mind.changeling.recursive_enhancement)
duration = duration + 100
diff --git a/code/game/gamemodes/changeling/powers/death_sting.dm b/code/game/gamemodes/changeling/powers/death_sting.dm
index 52412a4282..6dd0cdbf85 100644
--- a/code/game/gamemodes/changeling/powers/death_sting.dm
+++ b/code/game/gamemodes/changeling/powers/death_sting.dm
@@ -13,9 +13,7 @@
var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting)
if(!T)
return 0
- T.attack_log += text("\[[time_stamp()]\] Was death stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used death sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was death stung by [key_name(src)]")
+ add_attack_logs(src,T,"Death sting (changeling)")
T << "You feel a small prick and your chest becomes tight."
T.silent = 10
T.Paralyse(10)
diff --git a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
index a9b323465c..7853a9603e 100644
--- a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
+++ b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
@@ -28,10 +28,7 @@
var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_delayed_toxic_sting)
if(!T)
return 0
- T.attack_log += text("\[[time_stamp()]\] Was delayed toxic stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used delayed toxic sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was delayed toxic stung by [key_name(src)]")
-
+ add_attack_logs(src,T,"Delayed toxic sting (chagneling)")
var/type_to_give = /datum/modifier/delayed_toxin_sting
if(src.mind.changeling.recursive_enhancement)
type_to_give = /datum/modifier/delayed_toxin_sting/strong
diff --git a/code/game/gamemodes/changeling/powers/electric_lockpick.dm b/code/game/gamemodes/changeling/powers/electric_lockpick.dm
index dd77debc97..29ad6573f6 100644
--- a/code/game/gamemodes/changeling/powers/electric_lockpick.dm
+++ b/code/game/gamemodes/changeling/powers/electric_lockpick.dm
@@ -30,6 +30,7 @@
desc = "This finger appears to be an organic datajack."
icon = 'icons/obj/weapons.dmi'
icon_state = "electric_hand"
+ show_examine = FALSE
/obj/item/weapon/finger_lockpick/New()
if(ismob(loc))
diff --git a/code/game/gamemodes/changeling/powers/enfeebling_string.dm b/code/game/gamemodes/changeling/powers/enfeebling_string.dm
index b7a6c56957..16303f7c58 100644
--- a/code/game/gamemodes/changeling/powers/enfeebling_string.dm
+++ b/code/game/gamemodes/changeling/powers/enfeebling_string.dm
@@ -35,9 +35,7 @@
if(ishuman(T))
var/mob/living/carbon/human/H = T
- T.attack_log += text("\[[time_stamp()]\] Was enfeebling stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used enfeebling sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was enfeebling stung by [key_name(src)]")
+ add_attack_logs(src,T,"Enfeebling sting (changeling)")
var/type_to_give = /datum/modifier/enfeeble
if(src.mind.changeling.recursive_enhancement)
diff --git a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
index 6198e409a6..0c5d91d83b 100644
--- a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
+++ b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
@@ -35,9 +35,7 @@
src << "This creature's DNA is ruined beyond useability!"
return 0
- T.attack_log += text("\[[time_stamp()]\] Had DNA extracted via sting by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used DNA extraction sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was DNA extraction stung by [key_name(src)]")
+ add_attack_logs(src,T,"DNA extraction sting (changeling)")
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages)
absorbDNA(newDNA)
diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
index aad702ea49..d79af62b4c 100644
--- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
+++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
@@ -56,7 +56,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/clothing/head/chameleon/changeling
name = "malformed head"
@@ -78,7 +77,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/clothing/suit/chameleon/changeling
name = "chitinous chest"
@@ -104,7 +102,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/clothing/shoes/chameleon/changeling
name = "malformed feet"
@@ -130,7 +127,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/weapon/storage/backpack/chameleon/changeling
name = "backpack"
@@ -158,7 +154,6 @@ var/global/list/changeling_fabricated_clothing = list(
for(var/atom/movable/AM in src.contents) //Dump whatever's in the bag before deleting.
AM.forceMove(get_turf(loc))
qdel(src)
- H.update_icons_layers()
/obj/item/clothing/gloves/chameleon/changeling
name = "malformed hands"
@@ -185,8 +180,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
-
/obj/item/clothing/mask/chameleon/changeling
name = "chitin visor"
@@ -213,7 +206,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/clothing/glasses/chameleon/changeling
name = "chitin goggles"
@@ -235,7 +227,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/weapon/storage/belt/chameleon/changeling
name = "waist pouch"
@@ -261,7 +252,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
/obj/item/weapon/card/id/syndicate/changeling
name = "chitinous card"
@@ -291,8 +281,6 @@ var/global/list/changeling_fabricated_clothing = list(
visible_message("[H] tears off [src]!",
"We remove [src].")
qdel(src)
- H.update_icons_layers()
-
/obj/item/weapon/card/id/syndicate/changeling/Click() //Since we can't hold it in our hands, and attack_hand() doesn't work if it in inventory...
if(!registered_user)
diff --git a/code/game/gamemodes/changeling/powers/lsd_sting.dm b/code/game/gamemodes/changeling/powers/lsd_sting.dm
index 9adb4acd09..fabb81327e 100644
--- a/code/game/gamemodes/changeling/powers/lsd_sting.dm
+++ b/code/game/gamemodes/changeling/powers/lsd_sting.dm
@@ -13,9 +13,7 @@
var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting)
if(!T) return 0
- T.attack_log += text("\[[time_stamp()]\] Was hallucination stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used hallucination sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was hallucination stung by [key_name(src)]")
+ add_attack_logs(src,T,"Hallucination sting (changeling)")
spawn(rand(300,600))
if(T) T.hallucination += 400
feedback_add_details("changeling_powers","HS")
diff --git a/code/game/gamemodes/changeling/powers/para_sting.dm b/code/game/gamemodes/changeling/powers/para_sting.dm
index efe6fe8f79..7a0020bd0f 100644
--- a/code/game/gamemodes/changeling/powers/para_sting.dm
+++ b/code/game/gamemodes/changeling/powers/para_sting.dm
@@ -12,9 +12,7 @@
var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting)
if(!T)
return 0
- T.attack_log += text("\[[time_stamp()]\] Was paralysis stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used paralysis sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was paralysis stung by [key_name(src)]")
+ add_attack_logs(src,T,"Paralysis sting (changeling)")
T << "Your muscles begin to painfully tighten."
T.Weaken(20)
feedback_add_details("changeling_powers","PS")
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index ab8111000d..0da6c3c3d5 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -33,7 +33,7 @@
H.restore_all_organs(ignore_prosthetic_prefs=1) //Covers things like fractures and other things not covered by the above.
H.restore_blood()
H.mutations.Remove(HUSK)
- H.status_flags -= DISFIGURED
+ H.status_flags &= ~DISFIGURED
H.update_icons_body()
for(var/limb in H.organs_by_name)
var/obj/item/organ/external/current_limb = H.organs_by_name[limb]
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 40e796490f..4989c27f87 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -51,12 +51,8 @@
range = range * 2
to_chat(src, "We are extra loud.")
- src.attack_log += text("\[[time_stamp()]\] Used Resonant Shriek.")
- message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (JMP).")
- log_game("[key_name(src)] used Resonant Shriek.")
-
visible_message("[src] appears to shout.")
-
+ var/list/affected = list()
for(var/mob/living/M in range(range, src))
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
@@ -67,7 +63,7 @@
M.adjustEarDamage(0,30)
M.Confuse(20)
M << sound('sound/effects/screech.ogg')
- M.attack_log += text("\[[time_stamp()]\] Was affected by [key_name(src)]'s Resonant Shriek.")
+ affected += M
else
if(M != src)
M << "You hear a familiar screech from nearby. It has no effect on you."
@@ -77,7 +73,7 @@
M << sound('sound/weapons/flash.ogg')
M << "Auditory input overloaded. Reinitializing..."
M.Weaken(rand(5,10))
- M.attack_log += text("\[[time_stamp()]\] Was affected by [key_name(src)]'s Resonant Shriek.")
+ affected += M
for(var/obj/machinery/light/L in range(range, src))
L.on = 1
@@ -85,6 +81,7 @@
changeling.last_shriek = world.time
+ add_attack_logs(src,affected,"Used resonant shriek")
feedback_add_details("changeling_powers","RS")
return 1
@@ -133,9 +130,7 @@
visible_message("[src] appears to shout.")
- src.attack_log += text("\[[time_stamp()]\] Used Dissonant Shriek.")
- message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (JMP).")
- log_game("[key_name(src)] used Dissonant Shriek.")
+ add_attack_logs(src,null,"Use dissonant shriek")
for(var/obj/machinery/light/L in range(5, src))
L.on = 1
diff --git a/code/game/gamemodes/changeling/powers/silence_sting.dm b/code/game/gamemodes/changeling/powers/silence_sting.dm
index 1ab25278a4..334b0c139f 100644
--- a/code/game/gamemodes/changeling/powers/silence_sting.dm
+++ b/code/game/gamemodes/changeling/powers/silence_sting.dm
@@ -15,9 +15,7 @@
var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting)
if(!T) return 0
- T.attack_log += text("\[[time_stamp()]\] Was silence stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used silence sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was silence stung by [key_name(src)]")
+ add_attack_logs(src,T,"Silence sting (changeling)")
var/duration = 30
if(src.mind.changeling.recursive_enhancement)
duration = duration + 10
diff --git a/code/game/gamemodes/changeling/powers/transform_sting.dm b/code/game/gamemodes/changeling/powers/transform_sting.dm
index 797eec92d2..678e195e22 100644
--- a/code/game/gamemodes/changeling/powers/transform_sting.dm
+++ b/code/game/gamemodes/changeling/powers/transform_sting.dm
@@ -36,9 +36,7 @@
if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T)))
src << "Our sting appears ineffective against its DNA."
return 0
- T.attack_log += text("\[[time_stamp()]\] Was transform stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used transform sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was transform stung by [key_name(src)]")
+ add_attack_logs(src,T,"Transformation sting (changeling)")
T.visible_message("[T] transforms!")
T.dna = chosen_dna.Clone()
T.real_name = chosen_dna.real_name
diff --git a/code/game/gamemodes/changeling/powers/unfat_sting.dm b/code/game/gamemodes/changeling/powers/unfat_sting.dm
index 4b42f55e30..f2e238746d 100644
--- a/code/game/gamemodes/changeling/powers/unfat_sting.dm
+++ b/code/game/gamemodes/changeling/powers/unfat_sting.dm
@@ -11,9 +11,7 @@
var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting)
if(!T) return 0
- T.attack_log += text("\[[time_stamp()]\] Was unfat stung by [key_name(src)]")
- src.attack_log += text("\[[time_stamp()]\] Used unfat sting on [key_name(T)]")
- msg_admin_attack("[key_name(T)] was unfat stung by [key_name(src)]")
+ add_attack_logs(src,T,"Unfat sting (changeling)")
T << "you feel a small prick as stomach churns violently and you become to feel skinnier."
T.overeatduration = 0
T.nutrition -= 100
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 8db7a49255..d91e2e1f47 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -292,10 +292,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
words[cultwords[V]] = V
attack(mob/living/M as mob, mob/living/user as mob)
-
- M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on them by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) used [name] on [M.name] ([M.ckey]) (JMP)")
+ add_attack_logs(user,M,"Hit with [name]")
if(istype(M,/mob/observer/dead))
var/mob/observer/dead/D = M
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 0e0ff60791..d7579698d1 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -139,7 +139,7 @@ var/list/sacrificed = list()
target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects
// Resist messages go!
if(initial_message) //don't do this stuff right away, only if they resist or hesitate.
- admin_attack_log(attacker, target, "Used a convert rune", "Was subjected to a convert rune", "used a convert rune on")
+ add_attack_logs(attacker,target,"Convert rune")
switch(target.getFireLoss())
if(0 to 25)
target << "Your blood boils as you force yourself to resist the corruption invading every corner of your mind."
@@ -247,7 +247,7 @@ var/list/sacrificed = list()
if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"])
for(var/mob/living/carbon/D in R.loc)
if(D.stat!=2)
- admin_attack_log(usr, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on")
+ add_attack_logs(usr,D,"Blood drain rune")
var/bdrain = rand(1,25)
D << "You feel weakened."
D.take_overall_damage(bdrain, 0)
@@ -933,7 +933,7 @@ var/list/sacrificed = list()
if(affected.len)
usr.say("Sti[pick("'","`")] kaliedir!")
usr << "The world becomes quiet as the deafening rune dissipates into fine dust."
- admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on")
+ add_attack_logs(usr,affected,"Deafen rune")
qdel(src)
else
return fizzle()
@@ -952,7 +952,7 @@ var/list/sacrificed = list()
if(affected.len)
usr.whisper("Sti[pick("'","`")] kaliedir!")
usr << "Your talisman turns into gray dust, deafening everyone around."
- admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on")
+ add_attack_logs(usr, affected, "Deafen rune")
for (var/mob/V in orange(1,src))
if(!(iscultist(V)))
V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3)
@@ -978,7 +978,7 @@ var/list/sacrificed = list()
if(affected.len)
usr.say("Sti[pick("'","`")] kaliesin!")
usr << "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust."
- admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on")
+ add_attack_logs(usr, affected, "Blindness rune")
qdel(src)
else
return fizzle()
@@ -998,7 +998,7 @@ var/list/sacrificed = list()
if(affected.len)
usr.whisper("Sti[pick("'","`")] kaliesin!")
usr << "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie."
- admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on")
+ add_attack_logs(usr, affected, "Blindness rune")
return
@@ -1035,8 +1035,7 @@ var/list/sacrificed = list()
if(iscultist(C) && !C.stat)
C.say("Dedo ol[pick("'","`")]btoh!")
C.take_overall_damage(15, 0)
- admin_attacker_log_many_victims(usr, victims, "Used a blood boil rune.", "Was the victim of a blood boil rune.", "used a blood boil rune on")
- log_and_message_admins_many(cultists - usr, "assisted activating a blood boil rune.")
+ add_attack_logs(usr, victims, "Blood boil rune")
qdel(src)
else
return fizzle()
@@ -1084,13 +1083,13 @@ var/list/sacrificed = list()
C.Weaken(1)
C.Stun(1)
C.show_message("The rune explodes in a bright flash.", 3)
- admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
+ add_attack_logs(usr,C,"Stun rune")
else if(issilicon(L))
var/mob/living/silicon/S = L
S.Weaken(5)
S.show_message("BZZZT... The rune has exploded in a bright flash.", 3)
- admin_attack_log(usr, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
+ add_attack_logs(usr,S,"Stun rune")
qdel(src)
else ///When invoked as talisman, stun and mute the target mob.
usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!")
@@ -1104,7 +1103,7 @@ var/list/sacrificed = list()
if(issilicon(T))
T.Weaken(15)
- admin_attack_log(usr, T, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
+ add_attack_logs(usr,T,"Stun rune")
else if(iscarbon(T))
var/mob/living/carbon/C = T
C.flash_eyes()
@@ -1112,7 +1111,7 @@ var/list/sacrificed = list()
C.silent += 15
C.Weaken(25)
C.Stun(25)
- admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
+ add_attack_logs(usr,C,"Stun rune")
return
/////////////////////////////////////////TWENTY-FIFTH RUNE
diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm
index fb4888ee20..2c47b8e162 100644
--- a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm
+++ b/code/game/gamemodes/endgame/supermatter_cascade/portal.dm
@@ -10,7 +10,7 @@
announce=0
cause_hell=0
- layer=LIGHTING_LAYER+2 // ITS SO BRIGHT
+ plane = PLANE_LIGHTING_ABOVE // ITS SO BRIGHT
consume_range = 6
@@ -79,7 +79,8 @@
var/turf/T_mob = get_turf(src)
if((R.z == T_mob.z) && (get_dist(R,T_mob) <= (R.consume_range+10)) && !(R in view(T_mob)))
if(!riftimage)
- riftimage = image('icons/obj/rift.dmi',T_mob,"rift",LIGHTING_LAYER+2,1)
+ riftimage = image('icons/obj/rift.dmi',T_mob,"rift",1,1)
+ riftimage.plane = PLANE_LIGHTING_ABOVE
riftimage.mouse_opacity = 0
var/new_x = 32 * (R.x - T_mob.x) + R.pixel_x
diff --git a/code/game/gamemodes/technomancer/assistance/golem.dm b/code/game/gamemodes/technomancer/assistance/golem.dm
index 33fc246911..6b8654e719 100644
--- a/code/game/gamemodes/technomancer/assistance/golem.dm
+++ b/code/game/gamemodes/technomancer/assistance/golem.dm
@@ -30,7 +30,7 @@
melee_damage_lower = 30 // It has a built in esword.
melee_damage_upper = 30
attack_sound = 'sound/weapons/blade1.ogg'
- attacktext = "slashed"
+ attacktext = list("slashed")
friendly = "hugs"
resistance = 0
melee_miss_chance = 0
diff --git a/code/game/gamemodes/technomancer/spell_objs.dm b/code/game/gamemodes/technomancer/spell_objs.dm
index fb28813102..2a917b4fd8 100644
--- a/code/game/gamemodes/technomancer/spell_objs.dm
+++ b/code/game/gamemodes/technomancer/spell_objs.dm
@@ -31,6 +31,7 @@
)
throwforce = 0
force = 0
+ show_examine = FALSE
// var/mob/living/carbon/human/owner = null
var/mob/living/owner = null
var/obj/item/weapon/technomancer_core/core = null
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index daefb23ef2..85afcaa294 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -87,4 +87,3 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
minimal_access = list(access_heads, access_keycard_auth)
outfit_type = /decl/hierarchy/outfit/job/secretary
- alt_titles = list("Command Liaison", "Bridge Secretary")
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index 876579440c..d31a551726 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -49,7 +49,7 @@
minimal_access = list(access_hydroponics)
outfit_type = /decl/hierarchy/outfit/job/service/gardener
- alt_titles = list("Hydroponicist", "Gardener")
+ alt_titles = list("Gardener")
//Cargo
/datum/job/qm
@@ -105,7 +105,7 @@
minimal_access = list(access_mining, access_mining_station, access_mailsorting)
outfit_type = /decl/hierarchy/outfit/job/cargo/mining
- alt_titles = list("Drill Technician","Prospector")
+ alt_titles = list("Drill Technician")
//Service
/datum/job/janitor
@@ -123,7 +123,7 @@
minimal_access = list(access_janitor, access_maint_tunnels)
outfit_type = /decl/hierarchy/outfit/job/service/janitor
- alt_titles = list("Custodian", "Sanitation Technician")
+ alt_titles = list("Custodian")
//More or less assistants
/datum/job/librarian
@@ -141,7 +141,7 @@
minimal_access = list(access_library)
outfit_type = /decl/hierarchy/outfit/job/librarian
- alt_titles = list("Journalist", "Professor", "Historian", "Writer")
+ alt_titles = list("Journalist", "Writer")
//var/global/lawyer = 0//Checks for another lawyer //This changed clothes on 2nd lawyer, both IA get the same dreds.
/datum/job/lawyer
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 2e7f878e98..d40330ca48 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -327,6 +327,27 @@ var/global/datum/controller/occupations/job_master
var/datum/job/job = GetJob(rank)
var/list/spawn_in_storage = list()
+ if(!joined_late)
+ var/obj/S = null
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if(sloc.name != rank) continue
+ if(locate(/mob/living) in sloc.loc) continue
+ S = sloc
+ break
+ if(!S)
+ S = locate("start*[rank]") // use old stype
+ if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf))
+ H.forceMove(S.loc)
+ else
+ var/list/spawn_props = LateSpawn(H.client, rank)
+ var/turf/T = spawn_props["turf"]
+ H.forceMove(T)
+
+ // Moving wheelchair if they have one
+ if(H.buckled && istype(H.buckled, /obj/structure/bed/chair/wheelchair))
+ H.buckled.forceMove(H.loc)
+ H.buckled.set_dir(H.dir)
+
if(job)
//Equip custom gear loadout.
@@ -379,7 +400,8 @@ var/global/datum/controller/occupations/job_master
job.equip_backpack(H)
// job.equip_survival(H)
job.apply_fingerprints(H)
- H.equip_post_job()
+ if(job.title != "Cyborg" && job.title != "AI")
+ H.equip_post_job()
//If some custom items could not be equipped before, try again now.
for(var/thing in custom_equip_leftovers)
@@ -398,25 +420,6 @@ var/global/datum/controller/occupations/job_master
H.job = rank
- if(!joined_late)
- var/obj/S = null
- for(var/obj/effect/landmark/start/sloc in landmarks_list)
- if(sloc.name != rank) continue
- if(locate(/mob/living) in sloc.loc) continue
- S = sloc
- break
- if(!S)
- S = locate("start*[rank]") // use old stype
- if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf))
- H.forceMove(S.loc)
- else
- LateSpawn(H, rank)
-
- // Moving wheelchair if they have one
- if(H.buckled && istype(H.buckled, /obj/structure/bed/chair/wheelchair))
- H.buckled.forceMove(H.loc)
- H.buckled.set_dir(H.dir)
-
// If they're head, give them the account info for their department
if(H.mind && job.head_position)
var/remembered_info = ""
@@ -607,32 +610,30 @@ var/global/datum/controller/occupations/job_master
tmp_str += "HIGH=[level1]|MEDIUM=[level2]|LOW=[level3]|NEVER=[level4]|BANNED=[level5]|YOUNG=[level6]|-"
feedback_add_details("job_preferences",tmp_str)
-/datum/controller/occupations/proc/LateSpawn(var/mob/living/carbon/human/H, var/rank)
- //spawn at one of the latespawn locations
+/datum/controller/occupations/proc/LateSpawn(var/client/C, var/rank)
var/datum/spawnpoint/spawnpos
-// if(H.client.prefs.spawnpoint)
-// spawnpos = spawntypes[H.client.prefs.spawnpoint]
-
- if(H.client.prefs.spawnpoint)
- if(!(H.client.prefs.spawnpoint in using_map.allowed_spawns))
- if(H) // This seems redundant...
- to_chat(H, "Your chosen spawnpoint ([H.client.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.")
+ //Spawn them at their preferred one
+ if(C && C.prefs.spawnpoint)
+ if(!(C.prefs.spawnpoint in using_map.allowed_spawns))
+ to_chat(C, "Your chosen spawnpoint ([C.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.")
spawnpos = null
else
- spawnpos = spawntypes[H.client.prefs.spawnpoint]
+ spawnpos = spawntypes[C.prefs.spawnpoint]
+ //We will return a list key'd by "turf" and "msg"
+ . = list("turf","msg")
if(spawnpos && istype(spawnpos) && spawnpos.turfs.len)
if(spawnpos.check_job_spawning(rank))
- H.forceMove(spawnpos.get_spawn_position())
- . = spawnpos.msg
+ .["turf"] = spawnpos.get_spawn_position()
+ .["msg"] = spawnpos.msg
else
- H << "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead."
+ 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)
- H.forceMove(get_turf(spawning))
- . = "will arrive to the station shortly by shuttle"
+ .["turf"] = get_turf(spawning)
+ .["msg"] = "will arrive to the station shortly by shuttle"
else
var/spawning = pick(latejoin)
- H.forceMove(get_turf(spawning))
- . = "has arrived on the station"
+ .["turf"] = get_turf(spawning)
+ .["msg"] = "has arrived on the station"
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index c59c67c300..b34d1565a0 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -4,7 +4,7 @@
name = "Bluespace Gigabeacon"
desc = "A device that draws power from bluespace and creates a permanent tracking beacon."
level = 1 // underfloor
- layer = 2.5
+ layer = UNDER_JUNK_LAYER
anchored = 1
use_power = 1
idle_power_usage = 0
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 5696892ddc..ccf3f69529 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -9,6 +9,7 @@
idle_power_usage = 1
active_power_usage = 5
surgery_odds = 100
+ throwpass = 1
var/mob/living/carbon/human/victim = null
var/strapped = 0.0
var/obj/machinery/computer/operating/computer = null
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 2d80766ea6..c3251ce155 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -343,7 +343,7 @@
organStatus["destroyed"] = 1
if(E.status & ORGAN_BROKEN)
organStatus["broken"] = E.broken_description
- if(E.status & ORGAN_ROBOT)
+ if(E.robotic >= ORGAN_ROBOT)
organStatus["robotic"] = 1
if(E.splinted)
organStatus["splinted"] = 1
@@ -512,7 +512,7 @@
bled = "Bleeding:"
if(e.status & ORGAN_BROKEN)
AN = "[e.broken_description]:"
- if(e.status & ORGAN_ROBOT)
+ if(e.robotic >= ORGAN_ROBOT)
robot = "Prosthetic:"
if(e.status & ORGAN_DEAD)
o_dead = "Necrotic:"
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 0ea5527df2..dd79d5acc1 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -2,7 +2,6 @@
name = "\improper AI Liquid Dispenser"
icon = 'icons/obj/device.dmi'
icon_state = "motion0"
- layer = 3
anchored = 1.0
use_power = 1
idle_power_usage = 10
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 775ef6a7cd..a2115d9fdd 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -823,7 +823,7 @@ FIRE ALARM
alarms_hidden = TRUE
/obj/machinery/firealarm/update_icon()
- overlays.Cut()
+ cut_overlays()
if(panel_open)
set_light(0)
@@ -846,8 +846,7 @@ FIRE ALARM
if("blue") set_light(l_range = 2, l_power = 0.5, l_color = "#1024A9")
if("red") set_light(l_range = 4, l_power = 2, l_color = "#ff0000")
if("delta") set_light(l_range = 4, l_power = 2, l_color = "#FF6633")
-
- overlays += image('icons/obj/monitors.dmi', "overlay_[seclevel]")
+ add_overlay("overlay_[seclevel]")
/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, temperature, volume)
if(detecting)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 769dd9c39f..70d8864e2d 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -6,7 +6,8 @@
use_power = 2
idle_power_usage = 5
active_power_usage = 10
- layer = 5
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
var/list/network = list(NETWORK_DEFAULT)
var/c_tag = null
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index df2387e71f..bdf4e95fe0 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -28,7 +28,10 @@
/obj/random/action_figure = 1,
/obj/random/plushie = 1,
/obj/item/toy/cultsword = 1,
- /obj/item/toy/bouquet/fake = 1
+ /obj/item/toy/bouquet/fake = 1,
+ /obj/item/clothing/accessory/badge/sheriff = 2,
+ /obj/item/clothing/head/cowboy_hat/small = 2,
+ /obj/item/toy/stickhorse = 2
)
/obj/machinery/computer/arcade/New()
@@ -268,6 +271,8 @@
/obj/machinery/computer/arcade/battle/emag_act(var/charges, var/mob/user)
if(!emagged)
+ to_chat(user, span("notice","You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Hyper-Lethal Mode."))
+
temp = "If you die in the game, you die for real!"
player_hp = 30
player_mp = 10
@@ -396,18 +401,18 @@
dat += "
You ran out of food and starved."
if(emagged)
user.nutrition = 0 //yeah you pretty hongry
- user << "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor."
+ to_chat(user, span("danger", "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor."))
if(fuel <= 0)
dat += "
You ran out of fuel, and drift, slowly, into a star."
if(emagged)
var/mob/living/M = user
M.adjust_fire_stacks(5)
- M.IgniteMob() //flew into a star, so you're on fire
- user << "You feel an immense wave of heat emanate from \the [src]. Your skin bursts into flames."
+ M.IgniteMob() //flew into a star, so you're on fire
+ to_chat(user,span("danger", "You feel an immense wave of heat emanate from \the [src]. Your skin bursts into flames."))
dat += "
OK...
"
if(emagged)
- user << "You're never going to make it to Orion..."
+ to_chat(user, span("danger", "You're never going to make it to Orion..."))
user.death()
emagged = 0 //removes the emagged status after you lose
gameStatus = ORION_STATUS_START
@@ -472,20 +477,20 @@
switch(event)
if(ORION_TRAIL_RAIDERS)
if(prob(50))
- usr << "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?"
+ to_chat(usr, span("warning", "You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?"))
M.hallucination += 30
else
- usr << "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there..."
+ to_chat(usr, span("danger", "Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there..."))
M.take_organ_damage(25)
if(ORION_TRAIL_ILLNESS)
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
if(severity == 1)
- M << "You suddenly feel slightly nauseous." //got off lucky
+ to_chat(M, span("warning", "You suddenly feel slightly nauseous.")) //got off lucky
if(severity == 2)
- usr << "You suddenly feel extremely nauseous and hunch over until it passes."
+ to_chat(usr, span("warning", "You suddenly feel extremely nauseous and hunch over until it passes."))
M.Stun(3)
if(severity >= 3) //you didn't pray hard enough
- M << "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit."
+ to_chat(M, span("warning", "An overpowering wave of nausea consumes over you. You hunch over, your stomach's contents preparing for a spectacular exit."))
spawn(30)
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
@@ -496,12 +501,12 @@
src.visible_message("A sudden gust of powerful wind slams \the [M] into the floor!", "You hear a large fwooshing sound, followed by a bang.")
M.take_organ_damage(15)
else
- M << "A violent gale blows past you, and you barely manage to stay standing!"
+ to_chat(M, span("warning", "A violent gale blows past you, and you barely manage to stay standing!"))
if(ORION_TRAIL_COLLISION) //by far the most damaging event
if(prob(90) && !hull)
var/turf/simulated/floor/F = src.loc
F.ChangeTurf(/turf/space)
- src.visible_message("Something slams into the floor around \the [src], exposing it to space!", "You hear something crack and break.")
+ src.visible_message(span("danger", "Something slams into the floor around \the [src], exposing it to space!"), "You hear something crack and break.")
else
src.visible_message("Something slams into the floor around \the [src] - luckily, it didn't get through!", "You hear something crack.")
if(ORION_TRAIL_MALFUNCTION)
@@ -570,9 +575,9 @@
event()
if(emagged) //has to be here because otherwise it doesn't work
src.show_message("\The [src] states, 'YOU ARE EXPERIENCING A BLACKHOLE. BE TERRIFIED.","You hear something say, 'YOU ARE EXPERIENCING A BLACKHOLE. BE TERRFIED'")
- usr << "Something draws you closer and closer to the machine."
+ to_chat(usr, span("warning", "Something draws you closer and closer to the machine."))
sleep(10)
- usr << "This is really starting to hurt!"
+ to_chat(usr, span("danger", "This is really starting to hurt!"))
var i; //spawning a literal blackhole would be fun, but a bit disruptive.
for(i=0;i<4;i++)
var/mob/living/L = usr
@@ -998,12 +1003,12 @@
/obj/machinery/computer/arcade/orion_trail/emag_act(mob/user)
if(!emagged)
- user << "You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode."
+ to_chat(user, span("notice", "You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode."))
name = "The Orion Trail: Realism Edition"
desc = "Learn how our ancestors got to Orion, and try not to die in the process!"
newgame()
emagged = 1
-
+ return 1
/obj/item/weapon/orion_ship
name = "model settler ship"
@@ -1018,9 +1023,9 @@
if(!(in_range(user, src)))
return
if(!active)
- user << "There's a little switch on the bottom. It's flipped down."
+ to_chat(user, span("notice", "There's a little switch on the bottom. It's flipped down."))
else
- user << "There's a little switch on the bottom. It's flipped up."
+ to_chat(user, span("notice", "There's a little switch on the bottom. It's flipped up."))
/obj/item/weapon/orion_ship/attack_self(mob/user)
if(active)
@@ -1029,17 +1034,17 @@
message_admins("[key_name_admin(usr)] primed an explosive Orion ship for detonation.")
log_game("[key_name(usr)] primed an explosive Orion ship for detonation.")
- user << "You flip the switch on the underside of [src]."
+ to_chat(user, span("warning", "You flip the switch on the underside of [src]."))
active = 1
- src.visible_message("[src] softly beeps and whirs to life!")
+ src.visible_message(span("notice", "[src] softly beeps and whirs to life!"))
src.audible_message("\The [src] says, 'This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.'")
sleep(20)
- src.visible_message("[src] begins to vibrate...")
+ src.visible_message(span("warning", "[src] begins to vibrate..."))
src.audible_message("\The [src] says, 'Uh, Port? Having some issues with our reactor, could you check it out? Over.'")
sleep(30)
src.audible_message("\The [src] says, 'Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-'")
sleep(3.6)
- src.visible_message("[src] explodes!")
+ src.visible_message(span("danger", "[src] explodes!"))
explosion(src.loc, 1,2,4)
qdel(src)
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 29196f44d5..c95bd9879c 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -187,7 +187,7 @@
return
CentCom_announce(input, usr)
usr << "Message transmitted."
- log_say("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]")
+ log_game("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]")
centcomm_message_cooldown = 1
spawn(300)//10 minute cooldown
centcomm_message_cooldown = 0
@@ -204,7 +204,7 @@
return
Syndicate_announce(input, usr)
usr << "Message transmitted."
- log_say("[key_name(usr)] has made an illegal announcement: [input]")
+ log_game("[key_name(usr)] has made an illegal announcement: [input]")
centcomm_message_cooldown = 1
spawn(300)//10 minute cooldown
centcomm_message_cooldown = 0
diff --git a/code/game/machinery/computer/supply.dm b/code/game/machinery/computer/supply.dm
index 4bcc43bbec..e76f4db468 100644
--- a/code/game/machinery/computer/supply.dm
+++ b/code/game/machinery/computer/supply.dm
@@ -40,6 +40,7 @@
\nRequest items
View approved orders
View requests
+ \nView export report
Close"}
user << browse(dat, "window=computer;size=575x450")
@@ -198,6 +199,7 @@
\nOrder items
\n
\nView requests
\n
\nView orders
\n
+ \nView export report
\n
\nClose"}
@@ -367,6 +369,18 @@
temp += "
Clear list"
temp += "
OK"
+ else if (href_list["viewexport"])
+ temp = "Previous shuttle export report:
"
+ var/cratecount = 0
+ var/totalvalue = 0
+ for(var/S in supply_controller.exported_crates)
+ var/datum/exported_crate/EC = S
+ cratecount += 1
+ totalvalue += EC.value
+ temp += "[EC.name] exported for [EC.value] supply points
"
+ temp += "
Shipment of [cratecount] crates exported for [totalvalue] supply points.
"
+ temp += "
OK"
+
else if (href_list["rreq"])
var/ordernum = text2num(href_list["rreq"])
temp = "Invalid Request.
"
diff --git a/code/game/machinery/computer3/computers/HolodeckControl.dm b/code/game/machinery/computer3/computers/HolodeckControl.dm
index 4d63b95673..a629354d7b 100644
--- a/code/game/machinery/computer3/computers/HolodeckControl.dm
+++ b/code/game/machinery/computer3/computers/HolodeckControl.dm
@@ -155,7 +155,6 @@
var/mob/M = obj.loc
if(ismob(M))
M.remove_from_mob(obj)
- M.update_icons_layers() //so their overlays update
if(!silent)
var/obj/oldobj = obj
diff --git a/code/game/machinery/computer3/computers/communications.dm b/code/game/machinery/computer3/computers/communications.dm
index 6f802c54bd..acd66ebde1 100644
--- a/code/game/machinery/computer3/computers/communications.dm
+++ b/code/game/machinery/computer3/computers/communications.dm
@@ -197,7 +197,7 @@
return
CentCom_announce(input, usr)
usr << "Message transmitted."
- log_say("[key_name(usr)] has made a [using_map.boss_short] announcement: [input]")
+ log_game("[key_name(usr)] has made a [using_map.boss_short] announcement: [input]")
centcomm_message_cooldown = 1
spawn(600)//10 minute cooldown
centcomm_message_cooldown = 0
@@ -214,7 +214,7 @@
return
Syndicate_announce(input, usr)
usr << "Message transmitted."
- log_say("[key_name(usr)] has made an illegal announcement: [input]")
+ log_game("[key_name(usr)] has made an illegal announcement: [input]")
centcomm_message_cooldown = 1
spawn(600)//10 minute cooldown
centcomm_message_cooldown = 0
diff --git a/code/game/machinery/computer3/computers/prisoner.dm b/code/game/machinery/computer3/computers/prisoner.dm
index 7e3ada285d..27943bb353 100644
--- a/code/game/machinery/computer3/computers/prisoner.dm
+++ b/code/game/machinery/computer3/computers/prisoner.dm
@@ -95,7 +95,7 @@
var/obj/item/weapon/implant/I = locate(href_list["warn"])
if( istype(I) && I.imp_in)
var/mob/living/carbon/R = I.imp_in
- log_say("PrisonComputer3 message: [key_name(usr)]->[key_name(R)] : [warning]")
+ log_game("PrisonComputer3 message: [key_name(usr)]->[key_name(R)] : [warning]")
R << "You hear a voice in your head saying: '[warning]'"
interact()
diff --git a/code/game/machinery/computer3/lapvend.dm b/code/game/machinery/computer3/lapvend.dm
index e1e70ca3a7..cbfa8686bc 100644
--- a/code/game/machinery/computer3/lapvend.dm
+++ b/code/game/machinery/computer3/lapvend.dm
@@ -3,7 +3,6 @@
desc = "A generic vending machine."
icon = 'icons/obj/vending.dmi'
icon_state = "robotics"
- layer = 2.9
anchored = 1
density = 1
var/obj/machinery/computer3/laptop/vended/newlap = null
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 6709cb2363..f7ab7e7a7e 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -6,13 +6,15 @@
icon_state = "pod_preview"
density = 1
anchored = 1.0
- layer = 2.8
+ layer = UNDER_JUNK_LAYER
interact_offline = 1
var/on = 0
use_power = 1
idle_power_usage = 20
active_power_usage = 200
+ buckle_lying = FALSE
+ buckle_dir = SOUTH
var/temperature_archived
var/mob/living/carbon/occupant = null
@@ -20,12 +22,29 @@
var/current_heat_capacity = 50
+ var/image/fluid
+
/obj/machinery/atmospherics/unary/cryo_cell/New()
..()
icon = 'icons/obj/cryogenics_split.dmi'
- update_icon()
+ icon_state = "base"
initialize_directions = dir
+/obj/machinery/atmospherics/unary/cryo_cell/initialize()
+ . = ..()
+ var/image/tank = image(icon,"tank")
+ tank.alpha = 200
+ tank.pixel_y = 18
+ tank.plane = MOB_PLANE
+ tank.layer = MOB_LAYER+0.2 //Above fluid
+ fluid = image(icon, "tube_filler")
+ fluid.pixel_y = 18
+ fluid.alpha = 200
+ fluid.plane = MOB_PLANE
+ fluid.layer = MOB_LAYER+0.1 //Below glass, above mob
+ add_overlay(tank)
+ update_icon()
+
/obj/machinery/atmospherics/unary/cryo_cell/Destroy()
var/turf/T = src.loc
T.contents += contents
@@ -153,6 +172,7 @@
if(beaker)
beaker.loc = get_step(src.loc, SOUTH)
beaker = null
+ update_icon()
if(href_list["ejectOccupant"])
if(!occupant || isslime(usr) || ispAI(usr))
@@ -172,6 +192,7 @@
user.drop_item()
G.loc = src
user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!")
+ update_icon()
else if(istype(G, /obj/item/weapon/grab))
var/obj/item/weapon/grab/grab = G
if(!ismob(grab.affecting))
@@ -191,40 +212,23 @@
put_mob(target)
/obj/machinery/atmospherics/unary/cryo_cell/update_icon()
- overlays.Cut()
- icon_state = "pod[on]"
- var/image/I
-
- I = image(icon, "pod[on]_top")
- I.layer = 5 // this needs to be fairly high so it displays over most things, but it needs to be under lighting (at 10)
- I.pixel_z = 32
- overlays += I
-
- if(occupant)
- var/image/pickle = image(occupant.icon, occupant.icon_state)
- pickle.overlays = occupant.overlays
- pickle.pixel_z = 18
- pickle.layer = 5
- overlays += pickle
-
- I = image(icon, "lid[on]")
- I.layer = 5
- overlays += I
-
- I = image(icon, "lid[on]_top")
- I.layer = 5
- I.pixel_z = 32
- overlays += I
+ cut_overlay(fluid)
+ fluid.color = null
+ if(on)
+ if(beaker)
+ fluid.color = beaker.reagents.get_color()
+ add_overlay(fluid)
/obj/machinery/atmospherics/unary/cryo_cell/proc/process_occupant()
if(air_contents.total_moles < 10)
return
if(occupant)
- if(occupant.stat == 2)
+ if(occupant.stat >= DEAD)
return
occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature)*current_heat_capacity/(current_heat_capacity + air_contents.heat_capacity())
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise
- occupant.stat = 1
+ occupant.stat = UNCONSCIOUS
+ occupant.dir = SOUTH
if(occupant.bodytemperature < T0C)
occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000)
occupant.Paralyse(max(5, (1/occupant.bodytemperature)*3000))
@@ -273,14 +277,16 @@
if(occupant.client)
occupant.client.eye = occupant.client.mob
occupant.client.perspective = MOB_PERSPECTIVE
+ vis_contents -= occupant
+ occupant.pixel_x = occupant.default_pixel_x
+ occupant.pixel_y = occupant.default_pixel_y
occupant.loc = get_step(src.loc, SOUTH) //this doesn't account for walls or anything, but i don't forsee that being a problem.
if(occupant.bodytemperature < 261 && occupant.bodytemperature >= 70) //Patch by Aranclanos to stop people from taking burn damage after being ejected
occupant.bodytemperature = 261 // Changed to 70 from 140 by Zuhayr due to reoccurance of bug.
-// occupant.metabslow = 0
+ unbuckle_mob(occupant, force = TRUE)
occupant = null
current_heat_capacity = initial(current_heat_capacity)
update_use_power(1)
- update_icon()
return
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
if(stat & (NOPOWER|BROKEN))
@@ -307,6 +313,9 @@
if(M.health > -100 && (M.health < 0 || M.sleeping))
M << "You feel a cold liquid surround you. Your skin starts to freeze up."
occupant = M
+ buckle_mob(occupant, forced = TRUE, check_loc = FALSE)
+ vis_contents |= occupant
+ occupant.pixel_y += 19
current_heat_capacity = HEAT_CAPACITY_HUMAN
update_use_power(2)
// M.metabslow = 1
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 11e9f0f94f..5d6d7abdcc 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -27,6 +27,13 @@
var/storage_name = "Cryogenic Oversight Control"
var/allow_items = 1
+/obj/machinery/computer/cryopod/update_icon()
+ ..()
+ if((stat & NOPOWER) || (stat & BROKEN))
+ icon_state = "[initial(icon_state)]-p"
+ else
+ icon_state = initial(icon_state)
+
/obj/machinery/computer/cryopod/robot
name = "robotic storage console"
desc = "An interface between crew and the robotic storage systems"
@@ -41,8 +48,6 @@
/obj/machinery/computer/cryopod/dorms
name = "residential oversight console"
desc = "An interface between visitors and the residential oversight systems tasked with keeping track of all visitors in the deeper section of the colony."
- icon = 'icons/obj/robot_storage.dmi' //placeholder
- icon_state = "console" //placeholder
circuit = "/obj/item/weapon/circuitboard/robotstoragecontrol"
storage_type = "visitors"
@@ -52,8 +57,6 @@
/obj/machinery/computer/cryopod/travel
name = "docking oversight console"
desc = "An interface between visitors and the docking oversight systems tasked with keeping track of all visitors who enter or exit from the docks."
- icon = 'icons/obj/robot_storage.dmi' //placeholder
- icon_state = "console" //placeholder
circuit = "/obj/item/weapon/circuitboard/robotstoragecontrol"
storage_type = "visitors"
@@ -63,8 +66,6 @@
/obj/machinery/computer/cryopod/gateway
name = "gateway oversight console"
desc = "An interface between visitors and the gateway oversight systems tasked with keeping track of all visitors who enter or exit from the gateway."
- icon = 'icons/obj/robot_storage.dmi' //placeholder
- icon_state = "console" //placeholder
circuit = "/obj/item/weapon/circuitboard/robotstoragecontrol"
storage_type = "visitors"
@@ -304,13 +305,18 @@
find_control_computer()
/obj/machinery/cryopod/proc/find_control_computer(urgent=0)
- //control_computer = locate(/obj/machinery/computer/cryopod) in src.loc.loc // Broken due to http://www.byond.com/forum/?post=2007448
- control_computer = locate(/obj/machinery/computer/cryopod) in range(6,src)
+ control_computer = null
+
+ var/area/my_area = get_area(src)
+ control_computer = locate(/obj/machinery/computer/cryopod) in my_area
+
+ if(!control_computer) //Fallback to old method.
+ control_computer = locate(/obj/machinery/computer/cryopod) in range(6,src)
// Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged
- if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time)
- log_admin("Cryopod in [src.loc.loc] could not find control computer!")
- message_admins("Cryopod in [src.loc.loc] could not find control computer!")
+ if(!control_computer && urgent && last_no_computer_message + 5 MINUTES < world.time)
+ log_admin("Cryopod in [my_area] could not find control computer!")
+ message_admins("Cryopod in [my_area] could not find control computer!")
last_no_computer_message = world.time
return control_computer != null
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 7f140b4b7f..2d40396d91 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -415,6 +415,8 @@
desc = "It's an extra resilient airlock intended for spacefaring vessels."
icon = 'icons/obj/doors/shuttledoors.dmi'
explosion_resistance = 20
+ opacity = 0
+ glass = 1
assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft
// Airlock opens from top-bottom instead of left-right.
@@ -565,7 +567,7 @@ About the new airlock wires panel:
else if(duration) //electrify door for the given duration seconds
if(usr)
shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])")
- usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]")
+ add_attack_logs(usr,name,"Electrified a door")
else
shockedby += text("\[[time_stamp()]\] - EMP)")
message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]."
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index b22dc27dba..5cded75805 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -218,6 +218,8 @@
/obj/machinery/door/firedoor/attackby(obj/item/weapon/C as obj, mob/user as mob)
add_fingerprint(user)
+ if(istype(C, /obj/item/taperoll))
+ return //Don't open the door if we're putting tape on it to tell people 'don't open the door'.
if(operating)
return//Already doing something.
if(istype(C, /obj/item/weapon/weldingtool) && !repairing)
diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm
index 215238a80b..39a91b8aff 100644
--- a/code/game/machinery/holosign.dm
+++ b/code/game/machinery/holosign.dm
@@ -4,7 +4,7 @@
desc = "Small wall-mounted holographic projector"
icon = 'icons/obj/holosign.dmi'
icon_state = "sign_off"
- layer = 4
+ plane = MOB_PLANE
use_power = 1
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/game/machinery/kitchen/cooking_machines/fryer.dm b/code/game/machinery/kitchen/cooking_machines/fryer.dm
index 1fc0e75ef1..451f84c2ff 100644
--- a/code/game/machinery/kitchen/cooking_machines/fryer.dm
+++ b/code/game/machinery/kitchen/cooking_machines/fryer.dm
@@ -36,7 +36,7 @@
if(H.species.flags & NO_PAIN)
nopain = 2
E = H.get_organ(user.zone_sel.selecting)
- if(E.status & ORGAN_ROBOT)
+ if(E.robotic >= ORGAN_ROBOT)
nopain = 1
user.visible_message("\The [user] shoves \the [victim][E ? "'s [E.name]" : ""] into \the [src]!")
@@ -45,7 +45,7 @@
E.take_damage(0, rand(20,30))
if(E.children && E.children.len)
for(var/obj/item/organ/external/child in E.children)
- if(nopain && nopain < 2 && !(child.status & ORGAN_ROBOT))
+ if(nopain && nopain < 2 && !(child.robotic >= ORGAN_ROBOT))
nopain = 0
child.take_damage(0, rand(20,30))
else
@@ -58,9 +58,7 @@
victim << "Searing hot oil scorches your [E ? E.name : "flesh"]!"
if(victim.client)
- user.attack_log += text("\[[time_stamp()]\] Has [cook_type] \the [victim] ([victim.ckey]) in \a [src]")
- victim.attack_log += text("\[[time_stamp()]\] Has been [cook_type] in \a [src] by [user.name] ([user.ckey])")
- msg_admin_attack("[user] ([user.ckey]) [cook_type] \the [victim] ([victim.ckey]) in \a [src]. (JMP)")
+ add_attack_logs(user,victim,"[cook_type] in [src]")
icon_state = off_icon
cooking = 0
diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm
index 9b6b503237..d695253aa9 100644
--- a/code/game/machinery/kitchen/gibber.dm
+++ b/code/game/machinery/kitchen/gibber.dm
@@ -211,9 +211,7 @@
if(src.occupant.reagents)
src.occupant.reagents.trans_to_obj(new_meat, round(occupant.reagents.total_volume/slab_count,1))
- src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed!
- user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]"
- msg_admin_attack("[user.name] ([user.ckey]) gibbed [src.occupant] ([src.occupant.ckey]) (JMP)")
+ add_attack_logs(user,occupant,"Used [src] to gib")
src.occupant.ghostize()
@@ -225,13 +223,12 @@
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
operating = 0
- for (var/obj/thing in contents)
- // Todo: unify limbs and internal organs
+ for (var/obj/item/thing in contents)
// There's a chance that the gibber will fail to destroy some evidence.
- if((istype(thing,/obj/item/organ) || istype(thing,/obj/item/organ)) && prob(80))
+ if(istype(thing,/obj/item/organ) && prob(80))
qdel(thing)
continue
- thing.loc = get_turf(thing) // Drop it onto the turf for throwing.
+ thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing.
thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(0,3),emagged ? 100 : 50) // Being pelted with bits of meat and bone would hurt.
update_icon()
diff --git a/code/game/machinery/kitchen/icecream.dm b/code/game/machinery/kitchen/icecream.dm
index fab6319e26..09cb3289ed 100644
--- a/code/game/machinery/kitchen/icecream.dm
+++ b/code/game/machinery/kitchen/icecream.dm
@@ -172,7 +172,6 @@
name = "ice cream cone"
desc = "Delicious waffle cone, but no ice cream."
icon_state = "icecream_cone_waffle" //default for admin-spawned cones, href_list["cone"] should overwrite this all the time
- layer = 3.1
bitesize = 3
var/ice_creamed = 0
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index fa81ff1620..3da253e682 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -2,7 +2,6 @@
name = "microwave"
icon = 'icons/obj/kitchen.dmi'
icon_state = "mw"
- layer = 2.9
density = 1
anchored = 1
use_power = 1
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index a2f5c00ad1..b2c3d21b68 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -4,7 +4,6 @@
name = "\improper SmartFridge"
icon = 'icons/obj/vending.dmi'
icon_state = "smartfridge"
- layer = 2.9
density = 1
anchored = 1
use_power = 1
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 673e366313..874f8876b9 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -97,6 +97,7 @@ Class Procs:
name = "machinery"
icon = 'icons/obj/stationobjs.dmi'
w_class = ITEMSIZE_NO_CONTAINER
+ layer = UNDER_JUNK_LAYER
var/stat = 0
var/emagged = 0
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index af61e93424..8022235736 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -9,8 +9,7 @@
icon_state = "floor_magnet-f"
name = "Electromagnetic Generator"
desc = "A device that uses station power to create points of magnetic energy."
- level = 1 // underfloor
- layer = 2.5
+ plane = PLATING_PLANE
anchored = 1
use_power = 1
idle_power_usage = 50
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index ac0af16378..7e472c8eca 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -8,8 +8,7 @@ var/global/list/navbeacons = list() // no I don't like putting this in, but it w
icon_state = "navbeacon0-f"
name = "navigation beacon"
desc = "A beacon used for bot navigation."
- level = 1 // underfloor
- layer = 2.5
+ plane = PLATING_PLANE
anchored = 1
var/open = 0 // true if cover is open
var/locked = 1 // true if controls are locked
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 5ce605afcc..b9bd4a6855 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -935,20 +935,11 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
/obj/machinery/newscaster/proc/scan_user(mob/living/user as mob)
if(istype(user,/mob/living/carbon/human)) //User is a human
var/mob/living/carbon/human/human_user = user
- if(human_user.wear_id) //Newscaster scans you
- if(istype(human_user.wear_id, /obj/item/device/pda)) //autorecognition, woo!
- var/obj/item/device/pda/P = human_user.wear_id
- if(P.id)
- scanned_user = GetNameAndAssignmentFromId(P.id)
- else
- scanned_user = "Unknown"
- else if(istype(human_user.wear_id, /obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/ID = human_user.wear_id
- scanned_user = GetNameAndAssignmentFromId(ID)
- else
- scanned_user ="Unknown"
+ var/obj/item/weapon/card/id/I = human_user.GetIdCard()
+ if(I)
+ scanned_user = GetNameAndAssignmentFromId(I)
else
- scanned_user ="Unknown"
+ scanned_user = "Unknown"
else
var/mob/living/silicon/ai_user = user
scanned_user = "[ai_user.name] ([ai_user.job])"
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index 48bd028c09..0ec65cc30d 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -168,7 +168,7 @@
qdel(I)
qdel(J)
H.icon = HI
- H.layer = 25
+ H.hud_layerise()
usr.mapobjs += H
#else
@@ -287,7 +287,7 @@
H.icon = I
qdel(I)
- H.layer = 25
+ H.hud_layerise()
usr.mapobjs += H
#endif
diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm
new file mode 100644
index 0000000000..36db3f83f3
--- /dev/null
+++ b/code/game/machinery/oxygen_pump.dm
@@ -0,0 +1,241 @@
+#define TANK_MAX_RELEASE_PRESSURE (3*ONE_ATMOSPHERE)
+#define TANK_DEFAULT_RELEASE_PRESSURE ONE_ATMOSPHERE
+
+/obj/machinery/oxygen_pump
+ name = "emergency oxygen pump"
+ icon = 'icons/obj/walllocker.dmi'
+ desc = "A wall mounted oxygen pump with a retractable face mask that you can pull over your face in case of emergencies."
+ icon_state = "oxygen_tank"
+
+ anchored = TRUE
+
+ var/obj/item/weapon/tank/tank
+ var/mob/living/carbon/breather
+ var/obj/item/clothing/mask/breath/contained
+
+ var/spawn_type = /obj/item/weapon/tank/emergency/oxygen/engi
+ var/mask_type = /obj/item/clothing/mask/breath/emergency
+ var/icon_state_open = "oxygen_tank_open"
+ var/icon_state_closed = "oxygen_tank"
+
+ power_channel = ENVIRON
+ idle_power_usage = 10
+ active_power_usage = 120 // No idea what the realistic amount would be.
+
+/obj/machinery/oxygen_pump/initialize()
+ . = ..()
+ tank = new spawn_type (src)
+ contained = new mask_type (src)
+
+/obj/machinery/oxygen_pump/Destroy()
+ if(breather)
+ breather.internal = null
+ if(breather.internals)
+ breather.internals.icon_state = "internal0"
+ breather.remove_from_mob(contained)
+ visible_message("The mask rapidly retracts just before /the [src] is destroyed!")
+ breather = null
+
+ qdel_null(tank)
+ qdel_null(contained)
+ return ..()
+
+/obj/machinery/oxygen_pump/MouseDrop(var/mob/living/carbon/human/target, src_location, over_location)
+ ..()
+ if(istype(target) && CanMouseDrop(target))
+ if(!can_apply_to_target(target, usr)) // There is no point in attempting to apply a mask if it's impossible.
+ return
+ usr.visible_message("\The [usr] begins placing the mask onto [target]..")
+ if(!do_mob(usr, target, 25) || !can_apply_to_target(target, usr))
+ return
+ // place mask and add fingerprints
+ usr.visible_message("\The [usr] has placed \the mask on [target]'s mouth.")
+ attach_mask(target)
+ src.add_fingerprint(usr)
+
+/obj/machinery/oxygen_pump/attack_hand(mob/user as mob)
+ if((stat & MAINT) && tank)
+ user.visible_message("\The [user] removes \the [tank] from \the [src].", "You remove \the [tank] from \the [src].")
+ user.put_in_hands(tank)
+ src.add_fingerprint(user)
+ tank.add_fingerprint(user)
+ tank = null
+ return
+ if (!tank)
+ to_chat(user, "There is no tank in \the [src]!")
+ return
+ if(breather)
+ if(tank)
+ tank.forceMove(src)
+ breather.remove_from_mob(contained)
+ contained.forceMove(src)
+ src.visible_message("\The [user] makes \The [contained] rapidly retracts back into \the [src]!")
+ if(breather.internals)
+ breather.internals.icon_state = "internal0"
+ breather = null
+ use_power = 1
+
+/obj/machinery/oxygen_pump/attack_ai(mob/user as mob)
+ ui_interact(user)
+
+/obj/machinery/oxygen_pump/proc/attach_mask(var/mob/living/carbon/C)
+ if(C && istype(C))
+ contained.forceMove(get_turf(C))
+ C.equip_to_slot(contained, slot_wear_mask)
+ if(tank)
+ tank.forceMove(C)
+ breather = C
+ spawn(1)
+ if(!breather.internal && tank)
+ breather.internal = tank
+ if(breather.internals)
+ breather.internals.icon_state = "internal1"
+ use_power = 2
+
+/obj/machinery/oxygen_pump/proc/can_apply_to_target(var/mob/living/carbon/human/target, mob/user as mob)
+ if(!user)
+ user = target
+ // Check target validity
+ if(!target.organs_by_name[BP_HEAD])
+ to_chat(user, "\The [target] doesn't have a head.")
+ return
+ if(!target.check_has_mouth())
+ to_chat(user, "\The [target] doesn't have a mouth.")
+ return
+ if(target.wear_mask && target != breather)
+ to_chat(user, "\The [target] is already wearing a mask.")
+ return
+ if(target.head && (target.head.body_parts_covered & FACE))
+ to_chat(user, "Remove their [target.head] first.")
+ return
+ if(!tank)
+ to_chat(user, "There is no tank in \the [src].")
+ return
+ if(stat & MAINT)
+ to_chat(user, "Please close \the maintenance hatch first.")
+ return
+ if(!Adjacent(target))
+ to_chat(user, "Please stay close to \the [src].")
+ return
+ //when there is a breather:
+ if(breather && target != breather)
+ to_chat(user, "\The pump is already in use.")
+ return
+ //Checking if breather is still valid
+ if(target == breather && target.wear_mask != contained)
+ to_chat(user, "\The [target] is not using the supplied mask.")
+ return
+ return 1
+
+/obj/machinery/oxygen_pump/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/screwdriver))
+ stat ^= MAINT
+ user.visible_message("\The [user] [stat & MAINT ? "opens" : "closes"] \the [src].", "You [stat & MAINT ? "open" : "close"] \the [src].")
+ if(stat & MAINT)
+ icon_state = icon_state_open
+ if(!stat)
+ icon_state = icon_state_closed
+ //TO-DO: Open icon
+ if(istype(W, /obj/item/weapon/tank) && (stat & MAINT))
+ if(tank)
+ to_chat(user, "\The [src] already has a tank installed!")
+ else
+ user.drop_item()
+ W.forceMove(src)
+ tank = W
+ user.visible_message("\The [user] installs \the [tank] into \the [src].", "You install \the [tank] into \the [src].")
+ src.add_fingerprint(user)
+ if(istype(W, /obj/item/weapon/tank) && !stat)
+ to_chat(user, "Please open the maintenance hatch first.")
+
+/obj/machinery/oxygen_pump/examine(var/mob/user)
+ . = ..()
+ if(tank)
+ to_chat(user, "The meter shows [round(tank.air_contents.return_pressure())]")
+ else
+ to_chat(user, "It is missing a tank!")
+
+
+/obj/machinery/oxygen_pump/process()
+ if(breather)
+ if(!can_apply_to_target(breather))
+ if(tank)
+ tank.forceMove(src)
+ breather.remove_from_mob(contained)
+ contained.forceMove(src)
+ src.visible_message("\The [contained] rapidly retracts back into \the [src]!")
+ breather = null
+ use_power = 1
+ else if(!breather.internal && tank)
+ breather.internal = tank
+ if(breather.internals)
+ breather.internals.icon_state = "internal0"
+
+//Create rightclick to view tank settings
+/obj/machinery/oxygen_pump/verb/settings()
+ set src in oview(1)
+ set category = "Object"
+ set name = "Show Tank Settings"
+ ui_interact(usr)
+
+//GUI Tank Setup
+/obj/machinery/oxygen_pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ var/data[0]
+ if(!tank)
+ to_chat(usr, "It is missing a tank!")
+ data["tankPressure"] = 0
+ data["releasePressure"] = 0
+ data["defaultReleasePressure"] = 0
+ data["maxReleasePressure"] = 0
+ data["maskConnected"] = 0
+ data["tankInstalled"] = 0
+ // this is the data which will be sent to the ui
+ if(tank)
+ data["tankPressure"] = round(tank.air_contents.return_pressure() ? tank.air_contents.return_pressure() : 0)
+ data["releasePressure"] = round(tank.distribute_pressure ? tank.distribute_pressure : 0)
+ data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE)
+ data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE)
+ data["maskConnected"] = 0
+ data["tankInstalled"] = 1
+
+ if(!breather)
+ data["maskConnected"] = 0
+ if(breather)
+ data["maskConnected"] = 1
+
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "Oxygen_pump.tmpl", "Tank", 500, 300)
+ // when the ui is first opened this is the data it will use
+ ui.set_initial_data(data)
+ // open the new ui window
+ ui.open()
+ // auto update every Master Controller tick
+ ui.set_auto_update(1)
+
+/obj/machinery/oxygen_pump/Topic(href, href_list)
+ if(..())
+ return 1
+
+ if (href_list["dist_p"])
+ if (href_list["dist_p"] == "reset")
+ tank.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
+ else if (href_list["dist_p"] == "max")
+ tank.distribute_pressure = TANK_MAX_RELEASE_PRESSURE
+ else
+ var/cp = text2num(href_list["dist_p"])
+ tank.distribute_pressure += cp
+ tank.distribute_pressure = min(max(round(tank.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE)
+ return 1
+
+/obj/machinery/oxygen_pump/anesthetic
+ name = "anesthetic pump"
+ spawn_type = /obj/item/weapon/tank/anesthetic
+ icon_state = "anesthetic_tank"
+ icon_state_closed = "anesthetic_tank"
+ icon_state_open = "anesthetic_tank_open"
+ mask_type = /obj/item/clothing/mask/breath/anesthetic
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index ec0f8a027c..ca09d3de58 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -2,1317 +2,281 @@
Buildable pipes
Buildable meters
*/
-#define PIPE_SIMPLE_STRAIGHT 0
-#define PIPE_SIMPLE_BENT 1
-#define PIPE_HE_STRAIGHT 2
-#define PIPE_HE_BENT 3
-#define PIPE_CONNECTOR 4
-#define PIPE_MANIFOLD 5
-#define PIPE_JUNCTION 6
-#define PIPE_UVENT 7
-#define PIPE_MVALVE 8
-#define PIPE_PUMP 9
-#define PIPE_SCRUBBER 10
-#define PIPE_INSULATED_STRAIGHT 11
-#define PIPE_INSULATED_BENT 12
-#define PIPE_GAS_FILTER 13
-#define PIPE_GAS_MIXER 14
-#define PIPE_PASSIVE_GATE 15
-#define PIPE_VOLUME_PUMP 16
-#define PIPE_HEAT_EXCHANGE 17
-#define PIPE_MTVALVE 18
-#define PIPE_MANIFOLD4W 19
-#define PIPE_CAP 20
-///// Z-Level stuff
-#define PIPE_UP 21
-#define PIPE_DOWN 22
-///// Z-Level stuff
-#define PIPE_GAS_FILTER_M 23
-#define PIPE_GAS_MIXER_T 24
-#define PIPE_GAS_MIXER_M 25
-#define PIPE_OMNI_MIXER 26
-#define PIPE_OMNI_FILTER 27
-///// Supply, scrubbers and universal pipes
-#define PIPE_UNIVERSAL 28
-#define PIPE_SUPPLY_STRAIGHT 29
-#define PIPE_SUPPLY_BENT 30
-#define PIPE_SCRUBBERS_STRAIGHT 31
-#define PIPE_SCRUBBERS_BENT 32
-#define PIPE_SUPPLY_MANIFOLD 33
-#define PIPE_SCRUBBERS_MANIFOLD 34
-#define PIPE_SUPPLY_MANIFOLD4W 35
-#define PIPE_SCRUBBERS_MANIFOLD4W 36
-#define PIPE_SUPPLY_UP 37
-#define PIPE_SCRUBBERS_UP 38
-#define PIPE_SUPPLY_DOWN 39
-#define PIPE_SCRUBBERS_DOWN 40
-#define PIPE_SUPPLY_CAP 41
-#define PIPE_SCRUBBERS_CAP 42
-///// Mirrored T-valve ~ because I couldn't be bothered re-sorting all of the defines
-#define PIPE_MTVALVEM 43
-///// Digital Valves sit here because otherwise we're resorting every define.
-#define PIPE_DVALVE 44
-#define PIPE_DTVALVE 45
-#define PIPE_DTVALVEM 46
-
-#define PIPE_PASSIVE_VENT 47
/obj/item/pipe
name = "pipe"
- desc = "A pipe"
- var/pipe_type = 0
- //var/pipe_dir = 0
+ desc = "A pipe."
+ var/pipe_type
var/pipename
- var/connect_types = CONNECT_TYPE_REGULAR
force = 7
+ throwforce = 7
icon = 'icons/obj/pipe-item.dmi'
icon_state = "simple"
item_state = "buildpipe"
w_class = ITEMSIZE_NORMAL
level = 2
+ var/piping_layer = PIPING_LAYER_DEFAULT
+ var/dispenser_class // Tells the dispenser what orientations we support, so RPD can show previews.
-/obj/item/pipe/New(var/loc, var/pipe_type as num, var/dir as num, var/obj/machinery/atmospherics/make_from = null)
- ..()
- if (make_from)
- src.set_dir(make_from.dir)
- src.pipename = make_from.name
- if(make_from.req_access)
- src.req_access = make_from.req_access
- if(make_from.req_one_access)
- src.req_one_access = make_from.req_one_access
- color = make_from.pipe_color
- var/is_bent
- if (make_from.initialize_directions in list(NORTH|SOUTH, WEST|EAST))
- is_bent = 0
- else
- is_bent = 1
- if (istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction))
- src.pipe_type = PIPE_JUNCTION
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/heat_exchanging))
- src.pipe_type = PIPE_HE_STRAIGHT + is_bent
- connect_types = CONNECT_TYPE_HE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/insulated))
- src.pipe_type = PIPE_INSULATED_STRAIGHT + is_bent
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/supply))
- src.pipe_type = PIPE_SUPPLY_STRAIGHT + is_bent
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_STRAIGHT + is_bent
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple/visible/universal) || istype(make_from, /obj/machinery/atmospherics/pipe/simple/hidden/universal))
- src.pipe_type = PIPE_UNIVERSAL
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/simple))
- src.pipe_type = PIPE_SIMPLE_STRAIGHT + is_bent
- else if(istype(make_from, /obj/machinery/atmospherics/portables_connector))
- src.pipe_type = PIPE_CONNECTOR
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold/hidden/supply))
- src.pipe_type = PIPE_SUPPLY_MANIFOLD
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_MANIFOLD
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold))
- src.pipe_type = PIPE_MANIFOLD
- else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_pump))
- src.pipe_type = PIPE_UVENT
- else if(istype(make_from, /obj/machinery/atmospherics/valve/digital))
- src.pipe_type = PIPE_DVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/valve))
- src.pipe_type = PIPE_MVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/binary/pump/high_power))
- src.pipe_type = PIPE_VOLUME_PUMP
- else if(istype(make_from, /obj/machinery/atmospherics/binary/pump))
- src.pipe_type = PIPE_PUMP
- else if(istype(make_from, /obj/machinery/atmospherics/trinary/atmos_filter/m_filter))
- src.pipe_type = PIPE_GAS_FILTER_M
- else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
- src.pipe_type = PIPE_GAS_MIXER_T
- else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer/m_mixer))
- src.pipe_type = PIPE_GAS_MIXER_M
- else if(istype(make_from, /obj/machinery/atmospherics/trinary/atmos_filter))
- src.pipe_type = PIPE_GAS_FILTER
- else if(istype(make_from, /obj/machinery/atmospherics/trinary/mixer))
- src.pipe_type = PIPE_GAS_MIXER
- else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_scrubber))
- src.pipe_type = PIPE_SCRUBBER
- else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate))
- src.pipe_type = PIPE_PASSIVE_GATE
- else if(istype(make_from, /obj/machinery/atmospherics/unary/heat_exchanger))
- src.pipe_type = PIPE_HEAT_EXCHANGE
- else if(istype(make_from, /obj/machinery/atmospherics/tvalve/mirrored/digital))
- src.pipe_type = PIPE_DTVALVEM
- else if(istype(make_from, /obj/machinery/atmospherics/tvalve/mirrored))
- src.pipe_type = PIPE_MTVALVEM
- else if(istype(make_from, /obj/machinery/atmospherics/tvalve/digital))
- src.pipe_type = PIPE_DTVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/tvalve))
- src.pipe_type = PIPE_MTVALVE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/hidden/supply))
- src.pipe_type = PIPE_SUPPLY_MANIFOLD4W
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_MANIFOLD4W
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold4w))
- src.pipe_type = PIPE_MANIFOLD4W
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap/visible/supply) || istype(make_from, /obj/machinery/atmospherics/pipe/cap/hidden/supply))
- src.pipe_type = PIPE_SUPPLY_CAP
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap/visible/scrubbers) || istype(make_from, /obj/machinery/atmospherics/pipe/cap/hidden/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_CAP
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap))
- src.pipe_type = PIPE_CAP
- else if(istype(make_from, /obj/machinery/atmospherics/omni/mixer))
- src.pipe_type = PIPE_OMNI_MIXER
- else if(istype(make_from, /obj/machinery/atmospherics/omni/atmos_filter))
- src.pipe_type = PIPE_OMNI_FILTER
-///// Z-Level stuff
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up/supply))
- src.pipe_type = PIPE_SUPPLY_UP
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_UP
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up))
- src.pipe_type = PIPE_UP
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down/supply))
- src.pipe_type = PIPE_SUPPLY_DOWN
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down/scrubbers))
- src.pipe_type = PIPE_SCRUBBERS_DOWN
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down))
- src.pipe_type = PIPE_DOWN
-///// Z-Level stuff
- else if(istype(make_from, /obj/machinery/atmospherics/pipe/vent))
- src.pipe_type = PIPE_PASSIVE_VENT
+// One subtype for each way components connect to neighbors
+/obj/item/pipe/directional
+ dispenser_class = PIPE_DIRECTIONAL
+/obj/item/pipe/binary
+ dispenser_class = PIPE_STRAIGHT
+/obj/item/pipe/binary/bendable
+ dispenser_class = PIPE_BENDABLE
+/obj/item/pipe/trinary
+ dispenser_class = PIPE_TRINARY
+/obj/item/pipe/trinary/flippable
+ dispenser_class = PIPE_TRIN_M
+ var/mirrored = FALSE
+/obj/item/pipe/quaternary
+ dispenser_class = PIPE_ONEDIR
+
+/**
+ * Call constructor with:
+ * @param loc Location
+ * @pipe_type
+ */
+/obj/item/pipe/initialize(var/mapload, var/_pipe_type, var/_dir, var/obj/machinery/atmospherics/make_from)
+ if(make_from)
+ make_from_existing(make_from)
else
- src.pipe_type = pipe_type
- src.set_dir(dir)
- if (pipe_type == 29 || pipe_type == 30 || pipe_type == 33 || pipe_type == 35 || pipe_type == 37 || pipe_type == 39 || pipe_type == 41)
- connect_types = CONNECT_TYPE_SUPPLY
- src.color = PIPE_COLOR_BLUE
- else if (pipe_type == 31 || pipe_type == 32 || pipe_type == 34 || pipe_type == 36 || pipe_type == 38 || pipe_type == 40 || pipe_type == 42)
- connect_types = CONNECT_TYPE_SCRUBBER
- src.color = PIPE_COLOR_RED
- else if (pipe_type == 2 || pipe_type == 3)
- connect_types = CONNECT_TYPE_HE
- else if (pipe_type == 6)
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_HE
- else if (pipe_type == 28)
- connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY|CONNECT_TYPE_SCRUBBER
- //src.pipe_dir = get_pipe_dir()
- update()
- src.pixel_x = rand(-5, 5)
- src.pixel_y = rand(-5, 5)
+ pipe_type = _pipe_type
+ set_dir(_dir)
-//update the name and icon of the pipe item depending on the type
+ update()
+ pixel_x += rand(-5, 5)
+ pixel_y += rand(-5, 5)
+ return ..()
+
+/obj/item/pipe/proc/make_from_existing(obj/machinery/atmospherics/make_from)
+ set_dir(make_from.dir)
+ pipename = make_from.name
+ if(make_from.req_access)
+ src.req_access = make_from.req_access
+ if(make_from.req_one_access)
+ src.req_one_access = make_from.req_one_access
+ color = make_from.pipe_color
+ pipe_type = make_from.type
+
+/obj/item/pipe/trinary/flippable/make_from_existing(obj/machinery/atmospherics/trinary/make_from)
+ ..()
+ if(make_from.mirrored)
+ do_a_flip()
+
+/obj/item/pipe/dropped()
+ if(loc)
+ setPipingLayer(piping_layer)
+ return ..()
+
+/obj/item/pipe/proc/setPipingLayer(new_layer = PIPING_LAYER_DEFAULT)
+ var/obj/machinery/atmospherics/fakeA = pipe_type
+ if(initial(fakeA.pipe_flags) & (PIPING_ALL_LAYER|PIPING_DEFAULT_LAYER_ONLY))
+ new_layer = PIPING_LAYER_DEFAULT
+ piping_layer = new_layer
+ // Do it the Polaris way
+ switch(piping_layer)
+ if(PIPING_LAYER_SCRUBBER)
+ color = PIPE_COLOR_RED
+ name = "[initial(fakeA.name)] scrubber fitting"
+ if(PIPING_LAYER_SUPPLY)
+ color = PIPE_COLOR_BLUE
+ name = "[initial(fakeA.name)] supply fitting"
+ // 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)
+ // layer = initial(layer) + PIPE_LAYER_OFFSET(piping_layer)
/obj/item/pipe/proc/update()
- var/list/nlist = list( \
- "pipe", \
- "bent pipe", \
- "h/e pipe", \
- "bent h/e pipe", \
- "connector", \
- "manifold", \
- "junction", \
- "uvent", \
- "mvalve", \
- "pump", \
- "scrubber", \
- "insulated pipe", \
- "bent insulated pipe", \
- "gas filter", \
- "gas mixer", \
- "pressure regulator", \
- "high power pump", \
- "heat exchanger", \
- "t-valve", \
- "4-way manifold", \
- "pipe cap", \
-///// Z-Level stuff
- "pipe up", \
- "pipe down", \
-///// Z-Level stuff
- "gas filter m", \
- "gas mixer t", \
- "gas mixer m", \
- "omni mixer", \
- "omni filter", \
-///// Supply and scrubbers pipes
- "universal pipe adapter", \
- "supply pipe", \
- "bent supply pipe", \
- "scrubbers pipe", \
- "bent scrubbers pipe", \
- "supply manifold", \
- "scrubbers manifold", \
- "supply 4-way manifold", \
- "scrubbers 4-way manifold", \
- "supply pipe up", \
- "scrubbers pipe up", \
- "supply pipe down", \
- "scrubbers pipe down", \
- "supply pipe cap", \
- "scrubbers pipe cap", \
- "t-valve m", \
- "dvalve", \
- "dt-valve", \
- "dt-valve m", \
- "passive vent", \
- )
- name = nlist[pipe_type+1] + " fitting"
- var/list/islist = list( \
- "simple", \
- "simple", \
- "he", \
- "he", \
- "connector", \
- "manifold", \
- "junction", \
- "uvent", \
- "mvalve", \
- "pump", \
- "scrubber", \
- "insulated", \
- "insulated", \
- "filter", \
- "mixer", \
- "passivegate", \
- "volumepump", \
- "heunary", \
- "mtvalve", \
- "manifold4w", \
- "cap", \
-///// Z-Level stuff
- "cap", \
- "cap", \
-///// Z-Level stuff
- "m_filter", \
- "t_mixer", \
- "m_mixer", \
- "omni_mixer", \
- "omni_filter", \
-///// Supply and scrubbers pipes
- "universal", \
- "simple", \
- "simple", \
- "simple", \
- "simple", \
- "manifold", \
- "manifold", \
- "manifold4w", \
- "manifold4w", \
- "cap", \
- "cap", \
- "cap", \
- "cap", \
- "cap", \
- "cap", \
- "mtvalvem", \
- "dvalve", \
- "dtvalve", \
- "dtvalvem", \
- "passive vent", \
- )
- icon_state = islist[pipe_type + 1]
+ var/obj/machinery/atmospherics/fakeA = pipe_type
+ name = "[initial(fakeA.name)] fitting"
+ icon_state = initial(fakeA.pipe_state)
-//called when a turf is attacked with a pipe item
-/obj/item/pipe/afterattack(turf/simulated/floor/target, mob/user, proximity)
- if(!proximity) return
- if(istype(target))
- user.drop_from_inventory(src, target)
- else
- return ..()
+/obj/item/pipe/verb/flip()
+ set category = "Object"
+ set name = "Flip Pipe"
+ set src in view(1)
-// rotate the pipe item clockwise
+ if ( usr.stat || usr.restrained() || !usr.canmove )
+ return
+
+ do_a_flip()
+
+/obj/item/pipe/proc/do_a_flip()
+ set_dir(turn(dir, -180))
+ fixdir()
+
+/obj/item/pipe/trinary/flippable/do_a_flip()
+ // set_dir(turn(dir, flipped ? 45 : -45))
+ // TG has a magic icon set with the flipped versions in the diagonals.
+ // We may switch to this later, but for now gotta do some magic.
+ mirrored = !mirrored
+ var/obj/machinery/atmospherics/fakeA = pipe_type
+ icon_state = "[initial(fakeA.pipe_state)][mirrored ? "m" : ""]"
/obj/item/pipe/verb/rotate()
set category = "Object"
set name = "Rotate Pipe"
set src in view(1)
- if ( usr.stat || usr.restrained() )
+ if ( usr.stat || usr.restrained() || !usr.canmove )
return
- src.set_dir(turn(src.dir, -90))
+ set_dir(turn(src.dir, -90)) // Rotate clockwise
+ fixdir()
- if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE))
- if(dir==2)
- set_dir(1)
- else if(dir==8)
- set_dir(4)
- else if (pipe_type in list (PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W))
- set_dir(2)
- //src.pipe_set_dir(get_pipe_dir())
+// If you want to disable pipe dir changing when pulled, uncomment this
+// /obj/item/pipe/Move()
+// var/old_dir = dir
+// . = ..()
+// set_dir(old_dir) //pipes changing direction when moved is just annoying and buggy
+
+// Don't let pulling a pipe straighten it out.
+/obj/item/pipe/binary/bendable/Move()
+ var/old_bent = !IS_CARDINAL(dir)
+ . = ..()
+ if(old_bent && IS_CARDINAL(dir))
+ set_dir(turn(src.dir, -45))
+
+//Helper to clean up dir
+/obj/item/pipe/proc/fixdir()
return
-/obj/item/pipe/Move()
- ..()
- if ((pipe_type in list (PIPE_SIMPLE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT, PIPE_HE_BENT, PIPE_INSULATED_BENT)) \
- && (src.dir in cardinal))
- src.set_dir(src.dir|turn(src.dir, 90))
- else if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE))
- if(dir==2)
- set_dir(1)
- else if(dir==8)
- set_dir(4)
- return
+/obj/item/pipe/binary/fixdir()
+ if(dir == SOUTH)
+ set_dir(NORTH)
+ else if(dir == WEST)
+ set_dir(EAST)
-// returns all pipe's endpoints
+/obj/item/pipe/trinary/flippable/fixdir()
+ if(dir in cornerdirs)
+ set_dir(turn(dir, 45))
-/obj/item/pipe/proc/get_pipe_dir()
- if (!dir)
- return 0
- var/flip = turn(dir, 180)
- var/cw = turn(dir, -90)
- var/acw = turn(dir, 90)
+/obj/item/pipe/attack_self(mob/user)
+ set_dir(turn(dir,-90))
+ fixdir()
- switch(pipe_type)
- if( PIPE_SIMPLE_STRAIGHT, \
- PIPE_INSULATED_STRAIGHT, \
- PIPE_HE_STRAIGHT, \
- PIPE_JUNCTION ,\
- PIPE_PUMP ,\
- PIPE_VOLUME_PUMP ,\
- PIPE_PASSIVE_GATE ,\
- PIPE_MVALVE, \
- PIPE_SUPPLY_STRAIGHT, \
- PIPE_SCRUBBERS_STRAIGHT, \
- PIPE_UNIVERSAL, \
- PIPE_DVALVE, \
- )
- return dir|flip
- if(PIPE_SIMPLE_BENT, PIPE_INSULATED_BENT, PIPE_HE_BENT, PIPE_SUPPLY_BENT, PIPE_SCRUBBERS_BENT)
- return dir //dir|acw
- if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER,PIPE_HEAT_EXCHANGE)
- return dir
- if(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER)
- return dir|flip|cw|acw
- if(PIPE_MANIFOLD, PIPE_SUPPLY_MANIFOLD, PIPE_SCRUBBERS_MANIFOLD)
- return flip|cw|acw
- if(PIPE_GAS_FILTER, PIPE_GAS_MIXER, PIPE_MTVALVE, PIPE_DTVALVE)
- return dir|flip|cw
- if(PIPE_GAS_FILTER_M, PIPE_GAS_MIXER_M, PIPE_MTVALVEM, PIPE_DTVALVEM)
- return dir|flip|acw
- if(PIPE_GAS_MIXER_T)
- return dir|cw|acw
- if(PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP)
- return dir
-///// Z-Level stuff
- if(PIPE_UP,PIPE_DOWN,PIPE_SUPPLY_UP,PIPE_SUPPLY_DOWN,PIPE_SCRUBBERS_UP,PIPE_SCRUBBERS_DOWN)
- return dir
-///// Z-Level stuff
- if(PIPE_PASSIVE_VENT)
- return dir
- return 0
-
-/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes
-
- var/flip = turn(dir, 180)
-// var/cw = turn(dir, -90)
-// var/acw = turn(dir, 90)
-
- if (!(pipe_type in list(PIPE_HE_STRAIGHT, PIPE_HE_BENT, PIPE_JUNCTION)))
- return get_pipe_dir()
- switch(pipe_type)
- if(PIPE_HE_STRAIGHT,PIPE_HE_BENT)
- return 0
- if(PIPE_JUNCTION)
- return flip
- return 0
-
-// return the h_dir (heat-exchange pipes) from the type and the dir
-
-/obj/item/pipe/proc/get_hdir() //endpoints for h/e pipes
-
-// var/flip = turn(dir, 180)
-// var/cw = turn(dir, -90)
-
- switch(pipe_type)
- if(PIPE_HE_STRAIGHT)
- return get_pipe_dir()
- if(PIPE_HE_BENT)
- return get_pipe_dir()
- if(PIPE_JUNCTION)
- return dir
- else
- return 0
-
-/obj/item/pipe/attack_self(mob/user as mob)
- return rotate()
+//called when a turf is attacked with a pipe item
+/obj/item/pipe/afterattack(turf/simulated/floor/target, mob/user, proximity)
+ if(!proximity) return
+ if(istype(target) && user.canUnEquip(src))
+ user.drop_from_inventory(src, target)
+ else
+ return ..()
/obj/item/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- ..()
- //*
- if (!istype(W, /obj/item/weapon/wrench))
- return ..()
- if (!isturf(src.loc))
- return 1
- if (pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE))
- if(dir==2)
- set_dir(1)
- else if(dir==8)
- set_dir(4)
- else if (pipe_type in list(PIPE_MANIFOLD4W, PIPE_SUPPLY_MANIFOLD4W, PIPE_SCRUBBERS_MANIFOLD4W, PIPE_OMNI_MIXER, PIPE_OMNI_FILTER))
- set_dir(2)
- var/pipe_dir = get_pipe_dir()
+ if(iswrench(W))
+ return wrench_act(user, W)
+ return ..()
- for(var/obj/machinery/atmospherics/M in src.loc)
- if((M.initialize_directions & pipe_dir) && M.check_connect_types_construction(M,src)) // matches at least one direction on either type of pipe & same connection type
- user << "There is already a pipe of the same type at this location."
- return 1
+/obj/item/pipe/proc/wrench_act(var/mob/living/user, var/obj/item/weapon/wrench/W)
+ if(!isturf(loc))
+ return TRUE
+
+ add_fingerprint(user)
+ fixdir()
+
+ var/obj/machinery/atmospherics/fakeA = pipe_type
+ var/flags = initial(fakeA.pipe_flags)
+ for(var/obj/machinery/atmospherics/M in loc)
+ if((M.pipe_flags & flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
+ to_chat(user, "Something is hogging the tile!")
+ return TRUE
+ if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) // Pipes on different layers can't block each other unless they are ALL_LAYER
+ continue
+ if(M.get_init_dirs() & SSmachines.get_init_dirs(pipe_type, dir)) // matches at least one direction on either type of pipe
+ to_chat(user, "There is already a pipe at that location!")
+ return TRUE
// no conflicts found
- var/pipefailtext = "There's nothing to connect this pipe section to!" //(with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
-
- //TODO: Move all of this stuff into the various pipe constructors.
- switch(pipe_type)
- if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
- var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
- P.pipe_color = color
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_SUPPLY_STRAIGHT, PIPE_SUPPLY_BENT)
- var/obj/machinery/atmospherics/pipe/simple/hidden/supply/P = new( src.loc )
- P.pipe_color = color
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_SCRUBBERS_STRAIGHT, PIPE_SCRUBBERS_BENT)
- var/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers/P = new( src.loc )
- P.pipe_color = color
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_UNIVERSAL)
- var/obj/machinery/atmospherics/pipe/simple/hidden/universal/P = new( src.loc )
- P.pipe_color = color
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_HE_STRAIGHT, PIPE_HE_BENT)
- var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc )
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir //this var it's used to know if the pipe is bent or not
- P.initialize_directions_he = pipe_dir
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_CONNECTOR) // connector
- var/obj/machinery/atmospherics/portables_connector/C = new( src.loc )
- C.set_dir(dir)
- C.initialize_directions = pipe_dir
- if (pipename)
- C.name = pipename
- var/turf/T = C.loc
- C.level = !T.is_plating() ? 2 : 1
- C.atmos_init()
- C.build_network()
- if (C.node)
- C.node.atmos_init()
- C.node.build_network()
-
-
- if(PIPE_MANIFOLD) //manifold
- var/obj/machinery/atmospherics/pipe/manifold/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (QDELETED(M))
- usr << pipefailtext
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
-
- if(PIPE_SUPPLY_MANIFOLD) //manifold
- var/obj/machinery/atmospherics/pipe/manifold/hidden/supply/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (!M)
- usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
-
- if(PIPE_SCRUBBERS_MANIFOLD) //manifold
- var/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (!M)
- usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
- M.node3.build_network()
-
- if(PIPE_MANIFOLD4W) //4-way manifold
- var/obj/machinery/atmospherics/pipe/manifold4w/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (QDELETED(M))
- usr << pipefailtext
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
- if (M.node4)
- M.node4.atmos_init()
- M.node4.build_network()
-
- if(PIPE_SUPPLY_MANIFOLD4W) //4-way manifold
- var/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- M.connect_types = src.connect_types
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (!M)
- usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
- if (M.node4)
- M.node4.atmos_init()
- M.node4.build_network()
-
- if(PIPE_SCRUBBERS_MANIFOLD4W) //4-way manifold
- var/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers/M = new( src.loc )
- M.pipe_color = color
- M.set_dir(dir)
- M.initialize_directions = pipe_dir
- M.connect_types = src.connect_types
- //M.New()
- var/turf/T = M.loc
- M.level = !T.is_plating() ? 2 : 1
- M.atmos_init()
- if (!M)
- usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- M.build_network()
- if (M.node1)
- M.node1.atmos_init()
- M.node1.build_network()
- if (M.node2)
- M.node2.atmos_init()
- M.node2.build_network()
- if (M.node3)
- M.node3.atmos_init()
- M.node3.build_network()
- if (M.node4)
- M.node4.atmos_init()
- M.node4.build_network()
-
- if(PIPE_JUNCTION)
- var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc )
- P.set_dir(src.dir)
- P.initialize_directions = src.get_pdir()
- P.initialize_directions_he = src.get_hdir()
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext //"There's nothing to connect this pipe to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_UVENT) //unary vent
- var/obj/machinery/atmospherics/unary/vent_pump/V = new( src.loc )
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node)
- V.node.atmos_init()
- V.node.build_network()
-
- if(PIPE_MVALVE) //manual valve
- var/obj/machinery/atmospherics/valve/V = new( src.loc)
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
-// world << "[V.node1.name] is connected to valve, forcing it to update its nodes."
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
-// world << "[V.node2.name] is connected to valve, forcing it to update its nodes."
- V.node2.atmos_init()
- V.node2.build_network()
-
- if(PIPE_PUMP) //gas pump
- var/obj/machinery/atmospherics/binary/pump/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_GAS_FILTER) //gas filter
- var/obj/machinery/atmospherics/trinary/atmos_filter/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if (P.node3)
- P.node3.atmos_init()
- P.node3.build_network()
-
- if(PIPE_GAS_MIXER) //gas mixer
- var/obj/machinery/atmospherics/trinary/mixer/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if (P.node3)
- P.node3.atmos_init()
- P.node3.build_network()
-
- if(PIPE_GAS_FILTER_M) //gas filter mirrored
- var/obj/machinery/atmospherics/trinary/atmos_filter/m_filter/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if (P.node3)
- P.node3.atmos_init()
- P.node3.build_network()
-
- if(PIPE_GAS_MIXER_T) //gas mixer-t
- var/obj/machinery/atmospherics/trinary/mixer/t_mixer/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if (P.node3)
- P.node3.atmos_init()
- P.node3.build_network()
-
- if(PIPE_GAS_MIXER_M) //gas mixer mirrored
- var/obj/machinery/atmospherics/trinary/mixer/m_mixer/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if (P.node3)
- P.node3.atmos_init()
- P.node3.build_network()
-
- if(PIPE_SCRUBBER) //scrubber
- var/obj/machinery/atmospherics/unary/vent_scrubber/S = new(src.loc)
- S.set_dir(dir)
- S.initialize_directions = pipe_dir
- if (pipename)
- S.name = pipename
- var/turf/T = S.loc
- S.level = !T.is_plating() ? 2 : 1
- S.atmos_init()
- S.build_network()
- if (S.node)
- S.node.atmos_init()
- S.node.build_network()
-
- if(PIPE_INSULATED_STRAIGHT, PIPE_INSULATED_BENT)
- var/obj/machinery/atmospherics/pipe/simple/insulated/P = new( src.loc )
- P.set_dir(src.dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- if (QDELETED(P))
- usr << pipefailtext
- return 1
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_MTVALVE) //manual t-valve
- var/obj/machinery/atmospherics/tvalve/V = new(src.loc)
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
- V.node2.atmos_init()
- V.node2.build_network()
- if (V.node3)
- V.node3.atmos_init()
- V.node3.build_network()
-
- if(PIPE_MTVALVEM) //manual t-valve
- var/obj/machinery/atmospherics/tvalve/mirrored/V = new(src.loc)
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
- V.node2.atmos_init()
- V.node2.build_network()
- if (V.node3)
- V.node3.atmos_init()
- V.node3.build_network()
-
- if(PIPE_CAP)
- var/obj/machinery/atmospherics/pipe/cap/C = new(src.loc)
- C.set_dir(dir)
- C.initialize_directions = pipe_dir
- C.atmos_init()
- C.build_network()
- if(C.node)
- C.node.atmos_init()
- C.node.build_network()
-
- if(PIPE_SUPPLY_CAP)
- var/obj/machinery/atmospherics/pipe/cap/hidden/supply/C = new(src.loc)
- C.set_dir(dir)
- C.initialize_directions = pipe_dir
- C.atmos_init()
- C.build_network()
- if(C.node)
- C.node.atmos_init()
- C.node.build_network()
-
- if(PIPE_SCRUBBERS_CAP)
- var/obj/machinery/atmospherics/pipe/cap/hidden/scrubbers/C = new(src.loc)
- C.set_dir(dir)
- C.initialize_directions = pipe_dir
- C.atmos_init()
- C.build_network()
- if(C.node)
- C.node.atmos_init()
- C.node.build_network()
-
- if(PIPE_PASSIVE_GATE) //passive gate
- var/obj/machinery/atmospherics/binary/passive_gate/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_VOLUME_PUMP) //volume pump
- var/obj/machinery/atmospherics/binary/pump/high_power/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-
- if(PIPE_HEAT_EXCHANGE) // heat exchanger
- var/obj/machinery/atmospherics/unary/heat_exchanger/C = new( src.loc )
- C.set_dir(dir)
- C.initialize_directions = pipe_dir
- if (pipename)
- C.name = pipename
- var/turf/T = C.loc
- C.level = !T.is_plating() ? 2 : 1
- C.atmos_init()
- C.build_network()
- if (C.node)
- C.node.atmos_init()
- C.node.build_network()
-
- if(PIPE_DVALVE) //digital valve
- var/obj/machinery/atmospherics/valve/digital/V = new( src.loc)
- if(src.req_access)
- V.req_access = src.req_access
- if(src.req_one_access)
- V.req_one_access = src.req_one_access
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
- V.node2.atmos_init()
- V.node2.build_network()
-
- if(PIPE_DTVALVE) //digital t-valve
- var/obj/machinery/atmospherics/tvalve/digital/V = new(src.loc)
- if(src.req_access)
- V.req_access = src.req_access
- if(src.req_one_access)
- V.req_one_access = src.req_one_access
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
- V.node2.atmos_init()
- V.node2.build_network()
- if (V.node3)
- V.node3.atmos_init()
- V.node3.build_network()
-
- if(PIPE_DTVALVEM) //mirrored digital t-valve
- var/obj/machinery/atmospherics/tvalve/mirrored/digital/V = new(src.loc)
- if(src.req_access)
- V.req_access = src.req_access
- if(src.req_one_access)
- V.req_one_access = src.req_one_access
- V.set_dir(dir)
- V.initialize_directions = pipe_dir
- if (pipename)
- V.name = pipename
- var/turf/T = V.loc
- V.level = !T.is_plating() ? 2 : 1
- V.atmos_init()
- V.build_network()
- if (V.node1)
- V.node1.atmos_init()
- V.node1.build_network()
- if (V.node2)
- V.node2.atmos_init()
- V.node2.build_network()
- if (V.node3)
- V.node3.atmos_init()
- V.node3.build_network()
-
-///// Z-Level stuff
- if(PIPE_UP)
- var/obj/machinery/atmospherics/pipe/zpipe/up/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if(PIPE_DOWN)
- var/obj/machinery/atmospherics/pipe/zpipe/down/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if(PIPE_SUPPLY_UP)
- var/obj/machinery/atmospherics/pipe/zpipe/up/supply/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if(PIPE_SUPPLY_DOWN)
- var/obj/machinery/atmospherics/pipe/zpipe/down/supply/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if(PIPE_SCRUBBERS_UP)
- var/obj/machinery/atmospherics/pipe/zpipe/up/scrubbers/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
- if(PIPE_SCRUBBERS_DOWN)
- var/obj/machinery/atmospherics/pipe/zpipe/down/scrubbers/P = new(src.loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- if (pipename)
- P.name = pipename
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
- if (P.node2)
- P.node2.atmos_init()
- P.node2.build_network()
-///// Z-Level stuff
- if(PIPE_OMNI_MIXER)
- var/obj/machinery/atmospherics/omni/mixer/P = new(loc)
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if(PIPE_OMNI_FILTER)
- var/obj/machinery/atmospherics/omni/atmos_filter/P = new(loc)
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if(PIPE_PASSIVE_VENT)
- var/obj/machinery/atmospherics/pipe/vent/P = new(loc)
- P.set_dir(dir)
- P.initialize_directions = pipe_dir
- var/turf/T = P.loc
- P.level = !T.is_plating() ? 2 : 1
- P.atmos_init()
- P.build_network()
- if (P.node1)
- P.node1.atmos_init()
- P.node1.build_network()
+ var/obj/machinery/atmospherics/A = new pipe_type(loc)
+ build_pipe(A)
+ // TODO - Evaluate and remove the "need at least one thing to connect to" thing ~Leshana
+ // With how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment.
+ if (QDELETED(A))
+ to_chat(user, "There's nothing to connect this pipe section to!")
+ return TRUE
+ transfer_fingerprints_to(A)
playsound(src, W.usesound, 50, 1)
user.visible_message( \
- "[user] fastens the [src].", \
- "You have fastened the [src].", \
- "You hear ratchet.")
- qdel(src) // remove the pipe item
+ "[user] fastens \the [src].", \
+ "You fasten \the [src].", \
+ "You hear ratcheting.")
- return
- //TODO: DEFERRED
+ qdel(src)
-// ensure that setterm() is called for a newly connected pipeline
+/obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A)
+ A.set_dir(dir)
+ A.init_dir()
+ if(pipename)
+ A.name = pipename
+ if(req_access)
+ A.req_access = req_access
+ if(req_one_access)
+ A.req_one_access = req_one_access
+ A.on_construction(color, piping_layer)
+
+/obj/item/pipe/trinary/flippable/build_pipe(obj/machinery/atmospherics/trinary/T)
+ T.mirrored = mirrored
+ . = ..()
+
+// Lookup the initialize_directions for a given atmos machinery instance facing dir.
+// TODO - Right now this determines the answer by instantiating an instance and checking!
+// There has to be a better way... ~Leshana
+/datum/controller/subsystem/machines/proc/get_init_dirs(type, dir)
+ var/static/list/pipe_init_dirs_cache = list()
+ if(!pipe_init_dirs_cache[type])
+ pipe_init_dirs_cache[type] = list()
+
+ if(!pipe_init_dirs_cache[type]["[dir]"])
+ var/obj/machinery/atmospherics/temp = new type(null, dir)
+ pipe_init_dirs_cache[type]["[dir]"] = temp.get_init_dirs()
+ qdel(temp)
+
+ return pipe_init_dirs_cache[type]["[dir]"]
+
+
+//
+// Meters are special - not like any other pipes or components
+//
+
/obj/item/pipe_meter
name = "meter"
- desc = "A meter that can be laid on pipes"
+ desc = "A meter that can be laid on pipes."
icon = 'icons/obj/pipe-item.dmi'
icon_state = "meter"
item_state = "buildpipe"
w_class = ITEMSIZE_LARGE
+ var/piping_layer = PIPING_LAYER_DEFAULT
/obj/item/pipe_meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
- ..()
+ if(iswrench(W))
+ return wrench_act(user, W)
+ return ..()
- if (!istype(W, /obj/item/weapon/wrench))
- return ..()
- if(!locate(/obj/machinery/atmospherics/pipe, src.loc))
- user << "You need to fasten it to a pipe"
- return 1
- new/obj/machinery/meter( src.loc )
+/obj/item/pipe_meter/proc/wrench_act(var/mob/living/user, var/obj/item/weapon/wrench/W)
+ var/obj/machinery/atmospherics/pipe/pipe
+ for(var/obj/machinery/atmospherics/pipe/P in loc)
+ if(P.piping_layer == piping_layer)
+ pipe = P
+ break
+ if(!pipe)
+ to_chat(user, "You need to fasten it to a pipe!")
+ return TRUE
+ new /obj/machinery/meter(loc, piping_layer)
playsound(src, W.usesound, 50, 1)
- user << "You have fastened the meter to the pipe"
+ to_chat(user, "You fasten the meter to the pipe.")
qdel(src)
-//not sure why these are necessary
-#undef PIPE_SIMPLE_STRAIGHT
-#undef PIPE_SIMPLE_BENT
-#undef PIPE_HE_STRAIGHT
-#undef PIPE_HE_BENT
-#undef PIPE_CONNECTOR
-#undef PIPE_MANIFOLD
-#undef PIPE_JUNCTION
-#undef PIPE_UVENT
-#undef PIPE_MVALVE
-#undef PIPE_PUMP
-#undef PIPE_SCRUBBER
-#undef PIPE_INSULATED_STRAIGHT
-#undef PIPE_INSULATED_BENT
-#undef PIPE_GAS_FILTER
-#undef PIPE_GAS_MIXER
-#undef PIPE_PASSIVE_GATE
-#undef PIPE_VOLUME_PUMP
-#undef PIPE_OUTLET_INJECT
-#undef PIPE_MTVALVE
-#undef PIPE_MTVALVEM
-#undef PIPE_GAS_FILTER_M
-#undef PIPE_GAS_MIXER_T
-#undef PIPE_GAS_MIXER_M
-#undef PIPE_SUPPLY_STRAIGHT
-#undef PIPE_SUPPLY_BENT
-#undef PIPE_SCRUBBERS_STRAIGHT
-#undef PIPE_SCRUBBERS_BENT
-#undef PIPE_SUPPLY_MANIFOLD
-#undef PIPE_SCRUBBERS_MANIFOLD
-#undef PIPE_UNIVERSAL
-//#undef PIPE_MANIFOLD4W
+
+/obj/item/pipe_meter/dropped()
+ . = ..()
+ if(loc)
+ setAttachLayer(piping_layer)
+
+/obj/item/pipe_meter/proc/setAttachLayer(new_layer = PIPING_LAYER_DEFAULT)
+ piping_layer = new_layer
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 8bc779adf3..6675a5ca15 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -6,74 +6,32 @@
anchored = 1
var/unwrenched = 0
var/wait = 0
+ var/p_layer = PIPING_LAYER_REGULAR
-/obj/machinery/pipedispenser/attack_hand(user as mob)
- if(..())
+// TODO - Its about time to make this NanoUI don't we think?
+/obj/machinery/pipedispenser/attack_hand(var/mob/user as mob)
+ if((. = ..()))
return
-///// Z-Level stuff
- var/dat = {"
-Regular pipes:
-Pipe
-Bent Pipe
-Manifold
-Digital Valve
-Manual Valve
-Pipe Cap
-4-Way Manifold
-Digital T-Valve
-Digital T-Valve - Mirrored
-Manual T-Valve
-Manual T-Valve - Mirrored
-Upward Pipe
-Downward Pipe
-Supply pipes:
-Pipe
-Bent Pipe
-Manifold
-Pipe Cap
-4-Way Manifold
-Upward Pipe
-Downward Pipe
-Scrubbers pipes:
-Pipe
-Bent Pipe
-Manifold
-Pipe Cap
-4-Way Manifold
-Upward Pipe
-Downward Pipe
-Devices:
-Universal pipe adapter
-Connector
-Unary Vent
-Passive Vent
-Gas Pump
-Pressure Regulator
-High Power Gas Pump
-Scrubber
-Meter
-Gas Filter
-Gas Filter - Mirrored
-Gas Mixer
-Gas Mixer - Mirrored
-Gas Mixer - T
-Omni Gas Mixer
-Omni Gas Filter
-Heat exchange:
-Pipe
-Bent Pipe
-Junction
-Heat Exchanger
-Insulated pipes:
-Pipe
-Bent Pipe
+ src.interact(user)
-"}
-///// Z-Level stuff
-//What number the make points to is in the define # at the top of construction.dm in same folder
+/obj/machinery/pipedispenser/interact(mob/user)
+ user.set_machine(src)
- user << browse("[src][dat]", "window=pipedispenser")
- onclose(user, "pipedispenser")
+ var/list/lines = list()
+ for(var/category in atmos_pipe_recipes)
+ lines += "[category]:
"
+ if(category == "Pipes")
+ // Stupid hack. Fix someday. So tired right now.
+ lines += "Regular "
+ lines += "Supply "
+ lines += "Scrubber "
+ lines += "
"
+ for(var/datum/pipe_recipe/PI in atmos_pipe_recipes[category])
+ lines += PI.Render(src)
+ var/dat = lines.Join()
+ var/datum/browser/popup = new(user, "pipedispenser", name, 300, 800, src)
+ popup.set_content("[dat]")
+ popup.open()
return
/obj/machinery/pipedispenser/Topic(href, href_list)
@@ -81,20 +39,27 @@
return
if(unwrenched || !usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=pipedispenser")
+ usr.unset_machine(src)
return
usr.set_machine(src)
src.add_fingerprint(usr)
- if(href_list["make"])
+ if(href_list["setlayer"])
+ var/new_pipe_layer = text2num(href_list["setlayer"])
+ if(isnum(new_pipe_layer))
+ p_layer = new_pipe_layer
+ updateDialog()
+ else if(href_list["makepipe"])
if(!wait)
- var/p_type = text2num(href_list["make"])
+ var/obj/machinery/atmospherics/p_type = text2path(href_list["makepipe"])
var/p_dir = text2num(href_list["dir"])
- var/obj/item/pipe/P = new (/*usr.loc*/ src.loc, pipe_type=p_type, dir=p_dir)
- P.update()
+ var/pi_type = initial(p_type.construction_type)
+ var/obj/item/pipe/P = new pi_type(src.loc, p_type, p_dir)
+ P.setPipingLayer(p_layer)
P.add_fingerprint(usr)
wait = 1
spawn(10)
wait = 0
- if(href_list["makemeter"])
+ else if(href_list["makemeter"])
if(!wait)
new /obj/item/pipe_meter(/*usr.loc*/ src.loc)
wait = 1
diff --git a/code/game/machinery/pipe/pipe_recipes.dm b/code/game/machinery/pipe/pipe_recipes.dm
new file mode 100644
index 0000000000..f0ae483055
--- /dev/null
+++ b/code/game/machinery/pipe/pipe_recipes.dm
@@ -0,0 +1,102 @@
+//
+// Recipies for Pipe Dispenser and (someday) the RPD
+//
+
+var/global/list/atmos_pipe_recipes = null
+
+/hook/startup/proc/init_pipe_recipes()
+ global.atmos_pipe_recipes = list(
+ "Pipes" = list(
+ new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple),
+ new /datum/pipe_recipe/pipe("Manifold", /obj/machinery/atmospherics/pipe/manifold),
+ new /datum/pipe_recipe/pipe("Manual Valve", /obj/machinery/atmospherics/valve),
+ new /datum/pipe_recipe/pipe("Digital Valve", /obj/machinery/atmospherics/valve/digital),
+ new /datum/pipe_recipe/pipe("Pipe cap", /obj/machinery/atmospherics/pipe/cap),
+ new /datum/pipe_recipe/pipe("4-Way Manifold", /obj/machinery/atmospherics/pipe/manifold4w),
+ new /datum/pipe_recipe/pipe("Manual T-Valve", /obj/machinery/atmospherics/tvalve),
+ new /datum/pipe_recipe/pipe("Digital T-Valve", /obj/machinery/atmospherics/tvalve/digital),
+ new /datum/pipe_recipe/pipe("Upward Pipe", /obj/machinery/atmospherics/pipe/zpipe/up),
+ new /datum/pipe_recipe/pipe("Downward Pipe", /obj/machinery/atmospherics/pipe/zpipe/down),
+ new /datum/pipe_recipe/pipe("Universal Pipe Adaptor", /obj/machinery/atmospherics/pipe/simple/visible/universal),
+ ),
+ "Devices" = list(
+ new /datum/pipe_recipe/pipe("Connector", /obj/machinery/atmospherics/portables_connector),
+ new /datum/pipe_recipe/pipe("Unary Vent", /obj/machinery/atmospherics/unary/vent_pump),
+ new /datum/pipe_recipe/pipe("Passive Vent", /obj/machinery/atmospherics/pipe/vent),
+ new /datum/pipe_recipe/pipe("Injector", /obj/machinery/atmospherics/unary/outlet_injector),
+ new /datum/pipe_recipe/pipe("Gas Pump", /obj/machinery/atmospherics/binary/pump),
+ new /datum/pipe_recipe/pipe("Pressure Regulator", /obj/machinery/atmospherics/binary/passive_gate),
+ new /datum/pipe_recipe/pipe("High Power Gas Pump",/obj/machinery/atmospherics/binary/pump/high_power),
+ new /datum/pipe_recipe/pipe("Scrubber", /obj/machinery/atmospherics/unary/vent_scrubber),
+ new /datum/pipe_recipe/meter("Meter"),
+ new /datum/pipe_recipe/pipe("Gas Filter", /obj/machinery/atmospherics/trinary/atmos_filter),
+ new /datum/pipe_recipe/pipe("Gas Mixer", /obj/machinery/atmospherics/trinary/mixer),
+ new /datum/pipe_recipe/pipe("Gas Mixer 'T'", /obj/machinery/atmospherics/trinary/mixer/t_mixer),
+ new /datum/pipe_recipe/pipe("Omni Gas Mixer", /obj/machinery/atmospherics/omni/mixer),
+ new /datum/pipe_recipe/pipe("Omni Gas Filter", /obj/machinery/atmospherics/omni/atmos_filter),
+ ),
+ "Heat Exchange" = list(
+ new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/heat_exchanging),
+ new /datum/pipe_recipe/pipe("Junction", /obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction),
+ new /datum/pipe_recipe/pipe("Heat Exchanger", /obj/machinery/atmospherics/unary/heat_exchanger),
+ ),
+ "Insulated pipes" = list(
+ new /datum/pipe_recipe/pipe("Pipe", /obj/machinery/atmospherics/pipe/simple/insulated),
+ )
+ )
+ return TRUE
+
+//
+// New method of handling pipe construction. Instead of numeric constants and a giant switch statement of doom
+// every pipe type has a datum instance which describes its name, placement rules and construction method, dispensing etc.
+// The advantages are obvious, mostly in simplifying the code of the dispenser, and the ability to add new pipes without hassle.
+//
+/datum/pipe_recipe
+ var/name = "Abstract Pipe (fixme)" // Recipe name
+ var/dirtype // If using an RPD, this tells more about what previews to show.
+
+// Render an HTML link to select this pipe type. Returns text.
+/datum/pipe_recipe/proc/Render(dispenser)
+ return "[name]
"
+
+// Parameters for the Topic link returned by Render(). Returns text.
+/datum/pipe_recipe/proc/Params()
+ return ""
+
+//
+// Subtype for actual pipes
+//
+/datum/pipe_recipe/pipe
+ var/obj/item/pipe/construction_type // The type PATH to the type of pipe fitting object the recipe makes.
+ var/obj/machinery/atmospherics/pipe_type // The type PATH of what actual pipe the fitting becomes.
+
+/datum/pipe_recipe/pipe/New(var/label, var/obj/machinery/atmospherics/path)
+ name = label
+ pipe_type = path
+ construction_type = initial(path.construction_type)
+ dirtype = initial(construction_type.dispenser_class)
+
+// Render an HTML link to select this pipe type
+/datum/pipe_recipe/pipe/Render(dispenser)
+ var/dat = ..(dispenser)
+ // Stationary pipe dispensers don't allow you to pre-select pipe directions.
+ // This makes it impossble to spawn bent versions of bendable pipes.
+ // We add a "Bent" pipe type with a preset diagonal direction to work around it.
+ if(istype(dispenser, /obj/machinery/pipedispenser) && (dirtype == PIPE_BENDABLE))
+ dat += "Bent [name]
"
+ return dat
+
+/datum/pipe_recipe/pipe/Params()
+ return "makepipe=[pipe_type]"
+
+//
+// Subtype for meters
+//
+/datum/pipe_recipe/meter
+ dirtype = PIPE_ONEDIR
+
+/datum/pipe_recipe/meter/New(label)
+ name = label
+
+/datum/pipe_recipe/meter/Params()
+ return "makemeter=1"
diff --git a/code/game/machinery/pipe/pipelayer.dm b/code/game/machinery/pipe/pipelayer.dm
index c960879e54..65656929de 100644
--- a/code/game/machinery/pipe/pipelayer.dm
+++ b/code/game/machinery/pipe/pipelayer.dm
@@ -8,13 +8,18 @@
var/old_dir // Last direction we were facing.
var/on = 0 // Pipelaying online?
var/a_dis = 0 // Auto-dismantling - If enabled it will remove floor tiles
- var/P_type = 0 // Currently selected pipe type
+ var/P_type = null // Currently selected pipe type
var/P_type_t = "" // Name of currently selected pipe type
var/max_metal = 50 // Max capacity for internal metal storage
var/metal = 0 // Current amount in internal metal storage
var/pipe_cost = 0.25 // Cost in steel for each pipe.
var/obj/item/weapon/wrench/W // Internal wrench used for wrenching down the pipes
- var/list/Pipes = list("regular pipes"=0,"scrubbers pipes"=31,"supply pipes"=29,"heat exchange pipes"=2)
+ var/list/Pipes = list(
+ "regular pipes" = /obj/machinery/atmospherics/pipe/simple,
+ "scrubbers pipes" = /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
+ "supply pipes" = /obj/machinery/atmospherics/pipe/simple/hidden/supply,
+ "heat exchange pipes" = /obj/machinery/atmospherics/pipe/simple/heat_exchanging
+ )
/obj/machinery/pipelayer/New()
W = new(src)
@@ -160,17 +165,17 @@
if(!use_metal(pipe_cost))
return reset()
var/fdirn = turn(M_Dir, 180)
- var/p_type
+ var/obj/machinery/atmospherics/p_type = P_type
+ var/p_layer = initial(p_type.piping_layer)
var/p_dir
-
if (fdirn!=old_dir)
- p_type=1+P_type
p_dir=old_dir+M_Dir
else
- p_type=0+P_type
p_dir=M_Dir
- var/obj/item/pipe/P = new (w_turf, pipe_type=p_type, dir=p_dir)
+ var/pi_type = initial(p_type.construction_type)
+ var/obj/item/pipe/P = new pi_type(w_turf, p_type, p_dir)
+ P.setPipingLayer(p_layer)
// We used metal to make these, so should be reclaimable!
P.matter = list(DEFAULT_WALL_MATERIAL = pipe_cost * SHEET_MATERIAL_AMOUNT)
P.attackby(W , src)
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index d4d3cedb47..692e76bf5a 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -115,7 +115,7 @@
H.adjustBrainLoss(-(rand(1,3)))
// Also recharge their internal battery.
- if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450)
+ if(H.isSynthetic() && H.nutrition < 450)
H.nutrition = min(H.nutrition+10, 450)
cell.use(7000/450*10)
@@ -254,7 +254,7 @@
else if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
- if(!isnull(H.internal_organs_by_name["cell"]))
+ if(H.isSynthetic())
add_fingerprint(H)
H.reset_view(src)
H.forceMove(src)
@@ -264,17 +264,6 @@
else
return
-/obj/machinery/recharge_station/proc/hascell(var/mob/M)
- if(isrobot(M))
- var/mob/living/silicon/robot/R = M
- if(R.cell)
- return 1
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- if(!isnull(H.internal_organs_by_name["cell"]))
- return 1
- return 0
-
/obj/machinery/recharge_station/proc/go_out()
if(!occupant)
return
@@ -289,7 +278,7 @@
set name = "Eject Recharger"
set src in oview(1)
- if(usr.incapacitated())
+ if(usr.incapacitated() || !isliving(usr))
return
go_out()
@@ -301,8 +290,9 @@
set name = "Enter Recharger"
set src in oview(1)
- if(!usr.incapacitated())
+ if(usr.incapacitated() || !isliving(usr))
return
+
go_in(usr)
/obj/machinery/recharge_station/ghost_pod_recharger
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 7f76bc978c..7c0ca00f1a 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -588,7 +588,7 @@
//Departments that the cycler can paint suits to look like.
var/list/departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control")
//Species that the suits can be configured to fit.
- var/list/species = list("Human","Skrell","Unathi","Tajara", "Teshari")
+ var/list/species = list(SPECIES_HUMAN,SPECIES_SKRELL,SPECIES_UNATHI,SPECIES_TAJ, SPECIES_TESHARI)
var/target_department
var/target_species
@@ -753,7 +753,7 @@
//Clear the access reqs, disable the safeties, and open up all paintjobs.
user << "You run the sequencer across the interface, corrupting the operating protocols."
departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$", "Charring")
- species = list("Human","Tajara","Skrell","Unathi", "Teshari")
+ species = list(SPECIES_HUMAN,SPECIES_TAJ,SPECIES_SKRELL,SPECIES_UNATHI, SPECIES_TESHARI)
emagged = 1
safeties = 0
@@ -982,7 +982,9 @@
if(suit)
suit.name = "engineering voidsuit"
suit.icon_state = "rig-engineering"
- suit.item_state = "eng_voidsuit"
+ suit.item_state = "rig-engineering"
+ suit.item_state_slots[slot_r_hand_str] = "eng_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "eng_voidsuit"
if("Mining")
if(helmet)
helmet.name = "mining voidsuit helmet"
@@ -991,7 +993,9 @@
if(suit)
suit.name = "mining voidsuit"
suit.icon_state = "rig-mining"
- suit.item_state = "mining_voidsuit"
+ suit.item_state = "rig-mining"
+ suit.item_state_slots[slot_r_hand_str] = "mining_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "mining_voidsuit"
if("Medical")
if(helmet)
helmet.name = "medical voidsuit helmet"
@@ -1000,7 +1004,9 @@
if(suit)
suit.name = "medical voidsuit"
suit.icon_state = "rig-medical"
- suit.item_state = "medical_voidsuit"
+ suit.item_state = "rig-medical"
+ suit.item_state_slots[slot_r_hand_str] = "medical_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "medical_voidsuit"
if("Security")
if(helmet)
helmet.name = "security voidsuit helmet"
@@ -1009,7 +1015,9 @@
if(suit)
suit.name = "security voidsuit"
suit.icon_state = "rig-sec"
- suit.item_state = "sec_voidsuit"
+ suit.item_state = "rig-sec"
+ suit.item_state_slots[slot_r_hand_str] = "sec_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "sec_voidsuit"
if("Crowd Control")
if(helmet)
helmet.name = "crowd control voidsuit helmet"
@@ -1018,7 +1026,9 @@
if(suit)
suit.name = "crowd control voidsuit"
suit.icon_state = "rig-sec_riot"
- suit.item_state = "sec_voidsuit_riot"
+ suit.item_state = "rig-sec_riot"
+ suit.item_state_slots[slot_r_hand_str] = "sec_voidsuit_riot"
+ suit.item_state_slots[slot_l_hand_str] = "sec_voidsuit_riot"
if("Atmos")
if(helmet)
helmet.name = "atmospherics voidsuit helmet"
@@ -1027,7 +1037,9 @@
if(suit)
suit.name = "atmospherics voidsuit"
suit.icon_state = "rig-atmos"
- suit.item_state = "atmos_voidsuit"
+ suit.item_state = "rig-atmos"
+ suit.item_state_slots[slot_r_hand_str] = "atmos_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "atmos_voidsuit"
if("HAZMAT")
if(helmet)
helmet.name = "HAZMAT voidsuit helmet"
@@ -1036,7 +1048,9 @@
if(suit)
suit.name = "HAZMAT voidsuit"
suit.icon_state = "rig-engineering_rad"
- suit.item_state = "eng_voidsuit_rad"
+ suit.item_state = "rig-engineering_rad"
+ suit.item_state_slots[slot_r_hand_str] = "eng_voidsuit_rad"
+ suit.item_state_slots[slot_l_hand_str] = "eng_voidsuit_rad"
if("Construction")
if(helmet)
helmet.name = "Construction voidsuit helmet"
@@ -1045,7 +1059,9 @@
if(suit)
suit.name = "Construction voidsuit"
suit.icon_state = "rig-engineering_con"
- suit.item_state = "eng_voidsuit_con"
+ suit.item_state = "rig-engineering_con"
+ suit.item_state_slots[slot_r_hand_str] = "eng_voidsuit_con"
+ suit.item_state_slots[slot_l_hand_str] = "eng_voidsuit_con"
if("Biohazard")
if(helmet)
helmet.name = "Biohazard voidsuit helmet"
@@ -1054,7 +1070,9 @@
if(suit)
suit.name = "Biohazard voidsuit"
suit.icon_state = "rig-medical_bio"
- suit.item_state = "medical_voidsuit_bio"
+ suit.item_state = "rig-medical_bio"
+ suit.item_state_slots[slot_r_hand_str] = "medical_voidsuit_bio"
+ suit.item_state_slots[slot_l_hand_str] = "medical_voidsuit_bio"
if("Emergency Medical Response")
if(helmet)
helmet.name = "emergency medical response voidsuit helmet"
@@ -1063,7 +1081,9 @@
if(suit)
suit.name = "emergency medical response voidsuit"
suit.icon_state = "rig-medical_emt"
- suit.item_state = "medical_voidsuit_emt"
+ suit.item_state = "rig-medical_emt"
+ suit.item_state_slots[slot_r_hand_str] = "medical_voidsuit_emt"
+ suit.item_state_slots[slot_l_hand_str] = "medical_voidsuit_emt"
if("^%###^%$" || "Mercenary")
if(helmet)
helmet.name = "blood-red voidsuit helmet"
@@ -1071,8 +1091,10 @@
helmet.item_state = "rig0-syndie"
if(suit)
suit.name = "blood-red voidsuit"
- suit.item_state = "syndie_voidsuit"
+ suit.item_state = "rig-syndie"
suit.icon_state = "rig-syndie"
+ suit.item_state_slots[slot_r_hand_str] = "syndie_voidsuit"
+ suit.item_state_slots[slot_l_hand_str] = "syndie_voidsuit"
if("Charring")
if(helmet)
helmet.name = "soot-covered voidsuit helmet"
@@ -1082,6 +1104,8 @@
suit.name = "soot-covered voidsuit"
suit.item_state = "rig-firebug"
suit.icon_state = "rig-firebug"
+ suit.item_state_slots[slot_r_hand_str] = "rig-firebug"
+ suit.item_state_slots[slot_l_hand_str] = "rig-firebug"
if(helmet) helmet.name = "refitted [helmet.name]"
if(suit) suit.name = "refitted [suit.name]"
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 6f6a4f04fb..269346ab71 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -6,7 +6,6 @@
desc = "A generic vending machine."
icon = 'icons/obj/vending.dmi'
icon_state = "generic"
- layer = 2.9
anchored = 1
density = 1
@@ -836,6 +835,7 @@
/obj/item/weapon/storage/fancy/cigarettes/luckystars = 5,
/obj/item/weapon/storage/fancy/cigarettes/jerichos = 5,
/obj/item/weapon/storage/fancy/cigarettes/menthols = 5,
+ /obj/item/weapon/storage/rollingpapers = 5,
/obj/item/weapon/storage/box/matches = 10,
/obj/item/weapon/flame/lighter/random = 4)
contraband = list(/obj/item/weapon/flame/lighter/zippo = 4)
@@ -848,6 +848,7 @@
/obj/item/weapon/storage/fancy/cigarettes/luckystars = 17,
/obj/item/weapon/storage/fancy/cigarettes/jerichos = 22,
/obj/item/weapon/storage/fancy/cigarettes/menthols = 18,
+ /obj/item/weapon/storage/rollingpapers = 10,
/obj/item/weapon/storage/box/matches = 1,
/obj/item/weapon/flame/lighter/random = 2)
@@ -862,7 +863,8 @@
/obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12,
/obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2,
- /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2)
+ /obj/item/stack/medical/advanced/bruise_pack = 6, /obj/item/stack/medical/advanced/ointment = 6, /obj/item/stack/medical/splint = 4,
+ /obj/item/weapon/storage/pill_bottle/carbon = 2)
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
req_log_access = access_cmo
@@ -1084,4 +1086,47 @@
/obj/item/weapon/screwdriver = 5,/obj/item/weapon/crowbar = 5)
//everything after the power cell had no amounts, I improvised. -Sayu
req_log_access = access_rd
- has_logs = 1
\ No newline at end of file
+ has_logs = 1
+
+/obj/machinery/vending/giftvendor
+ name = "AlliCo Baubles and Confectionaries"
+ desc = "For that special someone!"
+ icon_state = "giftvendor"
+ vend_delay = 15
+ products = list(/obj/item/weapon/storage/fancy/heartbox = 5,
+ /obj/item/toy/bouquet = 5,
+ /obj/item/toy/bouquet/fake = 4,
+ /obj/item/weapon/paper/card/smile = 3,
+ /obj/item/weapon/paper/card/heart = 3,
+ /obj/item/weapon/paper/card/cat = 3,
+ /obj/item/weapon/paper/card/flower = 3,
+ /obj/item/clothing/accessory/bracelet/friendship = 5,
+ /obj/item/toy/plushie/therapy/red = 2,
+ /obj/item/toy/plushie/therapy/purple = 2,
+ /obj/item/toy/plushie/therapy/blue = 2,
+ /obj/item/toy/plushie/therapy/yellow = 2,
+ /obj/item/toy/plushie/therapy/orange = 2,
+ /obj/item/toy/plushie/therapy/green = 2)
+ contraband = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 1
+ /* Handbuzzer to be added later */)
+ premium = list(/obj/item/toy/plushie/nymph = 2,
+ /obj/item/toy/plushie/mouse = 2,
+ /obj/item/toy/plushie/kitten = 2,
+ /obj/item/toy/plushie/lizard = 2,
+ /obj/item/toy/plushie/spider = 2,
+ /obj/item/toy/plushie/farwa = 2,
+ /obj/item/weapon/storage/trinketbox = 2)
+ prices = list(/obj/item/weapon/storage/fancy/heartbox = 15,
+ /obj/item/toy/bouquet = 10,
+ /obj/item/toy/bouquet/fake = 3,
+ /obj/item/weapon/paper/card/smile = 1,
+ /obj/item/weapon/paper/card/heart = 1,
+ /obj/item/weapon/paper/card/cat = 1,
+ /obj/item/weapon/paper/card/flower = 1,
+ /obj/item/clothing/accessory/bracelet/friendship = 5,
+ /obj/item/toy/plushie/therapy/red = 20,
+ /obj/item/toy/plushie/therapy/purple = 20,
+ /obj/item/toy/plushie/therapy/blue = 20,
+ /obj/item/toy/plushie/therapy/yellow = 20,
+ /obj/item/toy/plushie/therapy/orange = 20,
+ /obj/item/toy/plushie/therapy/green = 20)
\ No newline at end of file
diff --git a/code/game/machinery/wall_frames.dm b/code/game/machinery/wall_frames.dm
index 3a036eec8e..1765eac3ec 100644
--- a/code/game/machinery/wall_frames.dm
+++ b/code/game/machinery/wall_frames.dm
@@ -29,7 +29,7 @@
update_type_list()
var/datum/frame/frame_types/frame_type
if(!build_machine_type)
- var/datum/frame/frame_types/response = input(usr, "What kind of frame would you like to make?", "Frame type request", null) in frame_types_floor
+ var/datum/frame/frame_types/response = input(user, "What kind of frame would you like to make?", "Frame type request", null) in frame_types_floor
if(!response || response.name == "Cancel")
return
frame_type = response
@@ -37,10 +37,10 @@
build_machine_type = /obj/structure/frame
if(frame_type.frame_size != 5)
- new /obj/item/stack/material/steel(usr.loc, (5 - frame_type.frame_size))
+ new /obj/item/stack/material/steel(user.loc, (5 - frame_type.frame_size))
var/ndir
- ndir = usr.dir
+ ndir = user.dir
if(!(ndir in cardinal))
return
@@ -48,13 +48,15 @@
M.fingerprints = fingerprints
M.fingerprintshidden = fingerprintshidden
M.fingerprintslast = fingerprintslast
+ if(istype(src.loc, /obj/item/weapon/gripper)) //Typical gripper shenanigans
+ user.drop_item()
qdel(src)
/obj/item/frame/proc/try_build(turf/on_wall, mob/user as mob)
update_type_list()
var/datum/frame/frame_types/frame_type
if(!build_machine_type)
- var/datum/frame/frame_types/response = input(usr, "What kind of frame would you like to make?", "Frame type request", null) in frame_types_wall
+ var/datum/frame/frame_types/response = input(user, "What kind of frame would you like to make?", "Frame type request", null) in frame_types_wall
if(!response || response.name == "Cancel")
return
frame_type = response
@@ -62,38 +64,40 @@
build_machine_type = /obj/structure/frame
if(frame_type.frame_size != 5)
- new /obj/item/stack/material/steel(usr.loc, (5 - frame_type.frame_size))
+ new /obj/item/stack/material/steel(user.loc, (5 - frame_type.frame_size))
- if(get_dist(on_wall, usr)>1)
+ if(get_dist(on_wall, user)>1)
return
var/ndir
if(reverse)
- ndir = get_dir(usr, on_wall)
+ ndir = get_dir(user, on_wall)
else
- ndir = get_dir(on_wall, usr)
+ ndir = get_dir(on_wall, user)
if(!(ndir in cardinal))
return
- var/turf/loc = get_turf(usr)
+ var/turf/loc = get_turf(user)
var/area/A = loc.loc
if(!istype(loc, /turf/simulated/floor))
- usr << "\The frame cannot be placed on this spot."
+ to_chat(user, "\The frame cannot be placed on this spot.")
return
if(A.requires_power == 0 || A.name == "Space")
- usr << "\The [src] Alarm cannot be placed in this area."
+ to_chat(user, "\The [src] Alarm cannot be placed in this area.")
return
if(gotwallitem(loc, ndir))
- usr << "There's already an item on this wall!"
+ to_chat(user, "There's already an item on this wall!")
return
var/obj/machinery/M = new build_machine_type(loc, ndir, 1, frame_type)
M.fingerprints = fingerprints
M.fingerprintshidden = fingerprintshidden
M.fingerprintslast = fingerprintslast
+ if(istype(src.loc, /obj/item/weapon/gripper)) //Typical gripper shenanigans
+ user.drop_item()
qdel(src)
/obj/item/frame/light
diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm
new file mode 100644
index 0000000000..cc5dacebc3
--- /dev/null
+++ b/code/game/mecha/combat/gorilla.dm
@@ -0,0 +1,213 @@
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon
+ name = "8.8cm KwK 47"
+ desc = "Precision German engineering!" // Why would you ever take this off the mech, anyway?
+ icon_state = "mecha_uac2"
+ equip_cooldown = 60 // 6 seconds
+ projectile = /obj/item/projectile/bullet/cannon
+ fire_sound = 'sound/weapons/cannon.ogg'
+ projectiles = 1
+ projectile_energy_cost = 1000
+ salvageable = 0 // We don't want players ripping this off a dead mech. Could potentially be a prize for beating it if Devs bless me and someone offers a nerf idea.
+
+/obj/item/projectile/bullet/cannon
+ name ="armor-piercing shell"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "shell"
+ damage = 1000 // In order to 1-hit any other mech and royally fuck anyone unfortunate enough to get in the way.
+
+/obj/item/projectile/bullet/cannon/on_hit(var/atom/target, var/blocked = 0)
+ explosion(target, 0, 0, 2, 4)
+ return 1
+
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon/weak
+ name = "8.8 cm KwK 36"
+ equip_cooldown = 120 // 12 seconds.
+ projectile = /obj/item/projectile/bullet/cannon/weak
+ projectile_energy_cost = 400
+ salvageable = 1
+
+/obj/item/projectile/bullet/cannon/weak
+ name ="canister shell"
+ icon_state = "canister"
+ damage = 120 //Do not get fucking shot.
+
+/* // GLITCHY UND LAGGY. Will later look into fixing.
+/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mg42
+ name = "Maschinengewehr 60"
+ icon_state = "mecha_uac2"
+ equip_cooldown = 10
+ projectile = /obj/item/projectile/bullet/midbullet2
+ fire_sound = 'sound/weapons/mg42.ogg'
+ projectiles = 1000
+ projectiles_per_shot = 5
+ deviation = 0.3
+ projectile_energy_cost = 20
+ fire_cooldown = 1
+ salvageable = 0 // We don't want players ripping this off a dead mech.
+*/
+
+/obj/effect/decal/mecha_wreckage/gorilla
+ name = "Gorilla wreckage"
+ desc = "... Blitzkrieg?"
+ icon = 'icons/mecha/mecha64x64.dmi'
+ icon_state = "pzrwreck"
+ plane = MOB_PLANE
+ pixel_x = -16
+ anchored = 1 // It's fucking huge. You aren't moving it.
+
+/obj/mecha/combat/gorilla
+ name = "Gorilla"
+ desc = "Blitzkrieg!" //stop using all caps in item descs i will fight you. its redundant with the bold.
+ icon = 'icons/mecha/mecha64x64.dmi'
+ icon_state = "pzrmech"
+ initial_icon = "pzrmech"
+ pixel_x = -16
+ step_in = 10
+ health = 5000
+ opacity = 0 // Because there's big tall legs to look through. Also it looks fucky if this is set to 1.
+ deflect_chance = 50
+ damage_absorption = list("brute"=0.1,"fire"=0.8,"bullet"=0.1,"laser"=0.6,"energy"=0.7,"bomb"=0.7) //values show how much damage will pass through, not how much will be absorbed.
+ max_temperature = 35000 //Just a bit better than the Durand.
+ infra_luminosity = 3
+ var/zoom = 0
+ var/smoke = 5
+ var/smoke_ready = 1
+ var/smoke_cooldown = 100
+ var/datum/effect/effect/system/smoke_spread/smoke_system = new
+ wreckage = /obj/effect/decal/mecha_wreckage/gorilla
+ add_req_access = 0
+ internal_damage_threshold = 25
+ force = 60
+ max_equip = 5
+
+/obj/mecha/combat/gorilla/New()
+ ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) // This thing basically cannot function without an external power supply.
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon/weak(src) //Saves energy, I suppose. Anti-infantry.
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
+ ME.attach(src)
+ src.smoke_system.set_up(3, 0, src)
+ src.smoke_system.attach(src)
+ return
+
+/obj/mecha/combat/gorilla/mechstep(direction)
+ var/result = step(src,direction)
+ playsound(src,"mechstep",40,1)
+ return result
+
+/obj/mecha/combat/gorilla/mechturn(direction)
+ dir = direction
+ playsound(src,"mechstep",40,1)
+
+
+/obj/mecha/combat/gorilla/relaymove(mob/user,direction)
+ if(user != src.occupant)
+ user.loc = get_turf(src)
+ to_chat(user, "You climb out from [src]")
+ return 0
+ if(!can_move)
+ return 0
+ if(zoom)
+ if(world.time - last_message > 20)
+ src.occupant_message("Unable to move while in zoom mode.")
+ last_message = world.time
+ return 0
+ if(connected_port)
+ if(world.time - last_message > 20)
+ src.occupant_message("Unable to move while connected to the air system port")
+ last_message = world.time
+ return 0
+ if(state || !has_charge(step_energy_drain))
+ return 0
+ var/tmp_step_in = step_in
+ var/tmp_step_energy_drain = step_energy_drain
+ var/move_result = 0
+ if(internal_damage&MECHA_INT_CONTROL_LOST)
+ move_result = mechsteprand()
+ else if(src.dir!=direction)
+ move_result = mechturn(direction)
+ else
+ move_result = mechstep(direction)
+ if(move_result)
+ if(istype(src.loc, /turf/space))
+ if(!src.check_for_support())
+ src.pr_inertial_movement.start(list(src,direction))
+ can_move = 0
+ spawn(tmp_step_in) can_move = 1
+ use_power(tmp_step_energy_drain)
+ return 1
+ return 0
+
+/obj/mecha/combat/gorilla/verb/smoke()
+ set category = "Exosuit Interface"
+ set name = "Smoke"
+ set src = usr.loc
+ set popup_menu = 0
+ if(usr!=src.occupant)
+ return
+ if(smoke_ready && smoke>0)
+ src.smoke_system.start()
+ smoke--
+ smoke_ready = 0
+ spawn(smoke_cooldown)
+ smoke_ready = 1
+ return
+
+/obj/mecha/combat/gorilla/verb/zoom()
+ set category = "Exosuit Interface"
+ set name = "Zoom"
+ set src = usr.loc
+ set popup_menu = 0
+ if(usr!=src.occupant)
+ return
+ if(src.occupant.client)
+ src.zoom = !src.zoom
+ src.log_message("Toggled zoom mode.")
+ src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.")
+ if(zoom)
+ src.occupant.client.view = 12
+ playsound(src.occupant, 'sound/mecha/imag_enh.ogg',50)
+ else
+ src.occupant.client.view = world.view//world.view - default mob view size
+ return
+
+
+/obj/mecha/combat/gorilla/go_out()
+ if(src.occupant && src.occupant.client)
+ src.occupant.client.view = world.view
+ src.zoom = 0
+ ..()
+ return
+
+
+/obj/mecha/combat/gorilla/get_stats_part()
+ var/output = ..()
+ output += {"Smoke: [smoke]"}
+ return output
+
+
+/obj/mecha/combat/gorilla/get_commands()
+ var/output = {"
+ "}
+ output += ..()
+ return output
+
+/obj/mecha/combat/gorilla/Topic(href, href_list)
+ ..()
+ if (href_list["smoke"])
+ src.smoke()
+ if (href_list["toggle_zoom"])
+ src.zoom()
+ return
\ No newline at end of file
diff --git a/code/game/mecha/equipment/tools/unused_tools.dm b/code/game/mecha/equipment/tools/unused_tools.dm
deleted file mode 100644
index c7ef794c4e..0000000000
--- a/code/game/mecha/equipment/tools/unused_tools.dm
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-/****** Do not tick this file in without looking over this code first ******/
-
-
-
-
-/*
-/obj/item/mecha_parts/mecha_equipment/book_stocker
-
- action(var/mob/target)
- if(!istype(target))
- return
- if(target.search_contents_for(/obj/item/book/WGW))
- target.gib()
- target.client.gib()
- target.client.mom.monkeyize()
- target.client.mom.gib()
- for(var/mob/M in range(target, 1000))
- M.gib()
- explosion(target.loc,100000,100000,100000)
- usr.gib()
- world.Reboot()
- return 1
-
-*/
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 50012fe95c..80b417da22 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -117,46 +117,41 @@
projectile = /obj/item/projectile/beam/stun
fire_sound = 'sound/weapons/Taser.ogg'
-/*
+
/obj/item/mecha_parts/mecha_equipment/weapon/honker
name = "sound emission device"
icon_state = "mecha_honker"
energy_drain = 300
equip_cooldown = 150
- range = MELEE|RANGED
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 4, TECH_ILLEGAL = 1)
- var/ear_safety = 0
- if(iscarbon(M))
+/obj/item/mecha_parts/mecha_equipment/honker/action(target)
+ if(!chassis)
+ return 0
+ if(energy_drain && chassis.get_charge() < energy_drain)
+ return 0
+ if(!equip_ready)
+ return 0
+
+ playsound(chassis, 'sound/effects/bang.ogg', 30, 1, 30)
+ chassis.occupant_message("You emit a high-pitched noise from the mech.")
+ for(var/mob/living/carbon/M in ohearers(6, chassis))
+ if(istype(M, /mob/living/carbon/human))
+ var/ear_safety = 0
ear_safety = M.get_ear_protection()
-
- action(target)
- if(!chassis)
- return 0
- if(energy_drain && chassis.get_charge() < energy_drain)
- return 0
- if(!equip_ready)
- return 0
-
- playsound(chassis, 'sound/effects/bang.ogg', 30, 1, 30)
- chassis.occupant_message("You emit a high-pitched noise from the mech.")
- for(var/mob/living/carbon/M in ohearers(6, chassis))
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(ear_safety > 0)
- return
- to_chat(M, "\Your ears feel like they're bleeding!")
- playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
- M.sleeping = 0
- M.ear_deaf += 30
- M.ear_damage += rand(5, 20)
- M.Weaken(3)
- M.Stun(5)
- chassis.use_power(energy_drain)
- log_message("Used a sound emission device.")
- do_after_cooldown()
- return
-*/
+ if(ear_safety > 0)
+ return
+ to_chat(M, "Your ears feel like they're bleeding!")
+ playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
+ M.sleeping = 0
+ M.ear_deaf += 30
+ M.ear_damage += rand(5, 20)
+ M.Weaken(3)
+ M.Stun(5)
+ chassis.use_power(energy_drain)
+ log_message("Used a sound emission device.")
+ do_after_cooldown()
+ return
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic
name = "general ballisic weapon"
@@ -361,4 +356,4 @@
if(!action_checks(user) || !active)
return
user.electrocute_act(shock_damage, src)
- return chassis.dynattackby(W,user)
\ No newline at end of file
+ return chassis.dynattackby(W,user)
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 55255d2097..5584590f92 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -52,22 +52,21 @@
if(charging.loc != src.loc) // Could be qdel or teleport or something
stop_charging()
return
- var/done = 1
- if(charging.cell)
+ var/done = FALSE
+ if(charging.cell)
var/t = min(charge, charging.cell.maxcharge - charging.cell.charge)
if(t > 0)
charging.give_power(t)
use_power(t * 150)
- done = 0
else
charging.occupant_message("Fully charged.")
+ done = TRUE
if(repair && charging.health < initial(charging.health))
charging.health = min(charging.health + repair, initial(charging.health))
if(charging.health == initial(charging.health))
charging.occupant_message("Fully repaired.")
-
else
- done = 0
+ done = FALSE
if(done)
stop_charging()
return
diff --git a/code/game/mecha/mech_sensor.dm b/code/game/mecha/mech_sensor.dm
index 87a9863ee8..5173f182ce 100644
--- a/code/game/mecha/mech_sensor.dm
+++ b/code/game/mecha/mech_sensor.dm
@@ -7,7 +7,7 @@
density = 1
throwpass = 1
use_power = 1
- layer = 3.3
+ layer = ON_WINDOW_LAYER
power_channel = EQUIP
var/on = 0
var/id_tag = null
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 9b27cdecbd..0a8a74b8e9 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -46,7 +46,7 @@
return TRUE
/atom/movable/Destroy()
- unbuckle_mob()
+ unbuckle_all_mobs()
return ..()
diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm
index 2c864f0a56..7a79c21e1e 100644
--- a/code/game/objects/effects/alien/aliens.dm
+++ b/code/game/objects/effects/alien/aliens.dm
@@ -147,7 +147,8 @@
anchored = 1
density = 0
- layer = 2
+ plane = TURF_PLANE
+ layer = ABOVE_TURF_LAYER
var/health = 15
var/obj/effect/alien/weeds/node/linked_node = null
@@ -155,7 +156,7 @@
icon_state = "weednode"
name = "purple sac"
desc = "Weird purple octopus-like thing."
- layer = 3
+ layer = ABOVE_TURF_LAYER+0.01
light_range = NODERANGE
var/node_range = NODERANGE
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index be7e759a63..436ebabcc9 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -161,7 +161,7 @@
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
smoke.icon = I
- smoke.layer = 6
+ smoke.plane = ABOVE_PLANE
smoke.set_dir(pick(cardinal))
smoke.pixel_x = -32 + rand(-8, 8)
smoke.pixel_y = -32 + rand(-8, 8)
diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm
index c04540535b..b69226815e 100644
--- a/code/game/objects/effects/decals/Cleanable/fuel.dm
+++ b/code/game/objects/effects/decals/Cleanable/fuel.dm
@@ -2,7 +2,7 @@
//Liquid fuel is used for things that used to rely on volatile fuels or phoron being contained to a couple tiles.
icon = 'icons/effects/effects.dmi'
icon_state = "fuel"
- layer = TURF_LAYER+0.2
+ plane = DIRTY_PLANE
anchored = 1
var/amount = 1
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 1b38fae182..90f708ff9d 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -10,7 +10,7 @@ var/global/list/image/splatter_cache=list()
gender = PLURAL
density = 0
anchored = 1
- layer = 2
+ plane = BLOOD_PLANE
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
@@ -96,18 +96,18 @@ var/global/list/image/splatter_cache=list()
S.overlays.Cut()
S.overlays += S.blood_overlay
S.blood_DNA |= blood_DNA.Copy()
+ perp.update_inv_shoes()
else if (hasfeet)//Or feet
perp.feet_blood_color = basecolor
perp.track_blood = max(amount,perp.track_blood)
- if(!perp.feet_blood_DNA)
- perp.feet_blood_DNA = list()
+ LAZYINITLIST(perp.feet_blood_DNA)
perp.feet_blood_DNA |= blood_DNA.Copy()
+ perp.update_bloodied()
else if (perp.buckled && istype(perp.buckled, /obj/structure/bed/chair/wheelchair))
var/obj/structure/bed/chair/wheelchair/W = perp.buckled
W.bloodiness = 4
- perp.update_inv_shoes(1)
amount--
/obj/effect/decal/cleanable/blood/proc/dry()
@@ -179,7 +179,6 @@ var/global/list/image/splatter_cache=list()
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6")
@@ -236,7 +235,6 @@ var/global/list/image/splatter_cache=list()
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "mucus"
random_icon_states = list("mucus")
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index ab01bfa005..1ef83bc722 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -4,7 +4,6 @@
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/obj/objects.dmi'
icon_state = "shards"
@@ -36,7 +35,6 @@
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/effects.dmi'
icon_state = "dirt"
mouse_opacity = 0
@@ -47,7 +45,6 @@
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/effects.dmi'
icon_state = "flour"
@@ -57,7 +54,6 @@
gender = PLURAL
density = 0
anchored = 1
- layer = 2
light_range = 1
icon = 'icons/effects/effects.dmi'
icon_state = "greenglow"
@@ -67,7 +63,7 @@
desc = "Somebody should remove that."
density = 0
anchored = 1
- layer = 3
+ plane = OBJ_PLANE
icon = 'icons/effects/effects.dmi'
icon_state = "cobweb1"
@@ -76,7 +72,7 @@
desc = "It looks like a melted... something."
density = 0
anchored = 1
- layer = 3
+ plane = OBJ_PLANE
icon = 'icons/obj/chemical.dmi'
icon_state = "molten"
@@ -85,7 +81,7 @@
desc = "Somebody should remove that."
density = 0
anchored = 1
- layer = 3
+ plane = OBJ_PLANE
icon = 'icons/effects/effects.dmi'
icon_state = "cobweb2"
@@ -96,7 +92,6 @@
gender = PLURAL
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
@@ -107,7 +102,6 @@
desc = "It's red."
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
@@ -116,7 +110,6 @@
desc = "Seems like this one won't hatch."
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
@@ -125,7 +118,6 @@
desc = "It's pie cream from a cream pie."
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
@@ -134,7 +126,6 @@
desc = "Some kind of fruit smear."
density = 0
anchored = 1
- layer = 2
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 2db1e5e948..f7965e092d 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,4 +1,5 @@
/obj/effect/decal/cleanable
+ plane = DIRTY_PLANE
var/list/random_icon_states = list()
/obj/effect/decal/cleanable/clean_blood(var/ignore = 0)
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index 20047ced12..55bb54b803 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -2,7 +2,7 @@
name = "rune"
desc = "A rune drawn in crayon."
icon = 'icons/obj/rune.dmi'
- layer = 2.1
+ plane = DIRTY_PLANE
anchored = 1
New(location,main = "#FFFFFF",shade = "#000000",var/type = "rune")
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 964a1301b8..f3a75ce3c2 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -3,7 +3,7 @@
desc = "It's an arrow hanging in mid-air. There may be a wizard about."
icon = 'icons/mob/screen1.dmi'
icon_state = "arrow"
- layer = 16.0
+ plane = ABOVE_PLANE
anchored = 1
mouse_opacity = 0
@@ -11,4 +11,4 @@
/obj/effect/decal/spraystill
density = 0
anchored = 1
- layer = 50
\ No newline at end of file
+ plane = ABOVE_PLANE
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/posters/bs12.dm b/code/game/objects/effects/decals/posters/bs12.dm
index 6b5ad182c4..7aadcb2ead 100644
--- a/code/game/objects/effects/decals/posters/bs12.dm
+++ b/code/game/objects/effects/decals/posters/bs12.dm
@@ -217,7 +217,7 @@
/datum/poster/bay_44
icon_state="bsposter44"
name = "Time for a drink?"
- desc = "This poster depicts a friendly-looking Tajara holding a tray of drinks."
+ desc = "This poster depicts a friendly-looking Tajaran holding a tray of drinks."
/datum/poster/bay_45
icon_state="bsposter45"
diff --git a/code/game/objects/effects/decals/posters/polarisposters.dm b/code/game/objects/effects/decals/posters/polarisposters.dm
index 9295b754c9..958ceb66be 100644
--- a/code/game/objects/effects/decals/posters/polarisposters.dm
+++ b/code/game/objects/effects/decals/posters/polarisposters.dm
@@ -26,12 +26,12 @@
/datum/poster/pol_6
icon_state="polposter6"
name = "Walk!"
- desc = "This poster depicts a man walking, presumably to encourage you to not run in the halls."
+ desc = "This poster depicts a man walking, presumably to encourage you not to run in the halls."
/datum/poster/pol_7
icon_state="polposter7"
name = "Place your signs!"
- desc = "A safety poster reminding custodial stuff to place wet floor signs where needed. This reminder's rarely heeded."
+ desc = "A safety poster reminding custodial staff to place wet floor signs where needed. This reminder's rarely heeded."
/datum/poster/pol_8
icon_state="polposter8"
diff --git a/code/game/objects/effects/decals/warning_stripes.dm b/code/game/objects/effects/decals/warning_stripes.dm
index e22acfad74..db7c4bf74f 100644
--- a/code/game/objects/effects/decals/warning_stripes.dm
+++ b/code/game/objects/effects/decals/warning_stripes.dm
@@ -1,6 +1,5 @@
/obj/effect/decal/warning_stripes
icon = 'icons/effects/warning_stripes.dmi'
- layer = 2
/obj/effect/decal/warning_stripes/New()
. = ..()
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 47fa55be1a..a1a6623ff1 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -208,7 +208,7 @@
/obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times
add_fingerprint(user)
- msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)")
+ msg_admin_attack("[key_name_admin(user)] primed \a [src]")
user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!")
if(do_after(user, 10 SECONDS))
playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3)
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 349400226a..aaebab4355 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -26,7 +26,8 @@
desc = "Something swinging really wide."
icon = 'icons/effects/96x96.dmi'
icon_state = "cleave"
- layer = 6
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
time_to_die = 6
alpha = 140
mouse_opacity = 0
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 2cc8b7a64f..9f4f0fa118 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -17,7 +17,8 @@
icon = 'icons/misc/beach2.dmi'
icon_state = "palm1"
density = 1
- layer = 5
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
anchored = 1
/obj/effect/overlay/palmtree_l
@@ -25,7 +26,8 @@
icon = 'icons/misc/beach2.dmi'
icon_state = "palm2"
density = 1
- layer = 5
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
anchored = 1
/obj/effect/overlay/coconut
@@ -37,7 +39,7 @@
name = "Bluespace"
icon = 'icons/turf/space.dmi'
icon_state = "bluespacify"
- layer = 10
+ plane = ABOVE_PLANE
/obj/effect/overlay/wallrot
name = "wallrot"
@@ -45,7 +47,8 @@
icon = 'icons/effects/wallrot.dmi'
anchored = 1
density = 1
- layer = 5
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
mouse_opacity = 0
/obj/effect/overlay/wallrot/New()
@@ -70,7 +73,9 @@
/obj/effect/overlay/snow/floor
icon_state = "snowfloor"
- layer = 2.01 //Just above floor
+ plane = TURF_PLANE
+ layer = ABOVE_TURF_LAYER
+ mouse_opacity = 0 //Don't block underlying tile interactions
/obj/effect/overlay/snow/floor/edges
icon_state = "snow_edges"
@@ -80,11 +85,12 @@
/obj/effect/overlay/snow/airlock
icon_state = "snowairlock"
- layer = 3.2 //Just above airlocks
+ layer = DOOR_CLOSED_LAYER+0.01
/obj/effect/overlay/snow/floor/pointy
icon_state = "snowfloorpointy"
/obj/effect/overlay/snow/wall
icon_state = "snowwall"
- layer = 5 //Same as lights so humans can stand under it
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index a26c1169d5..d3b9853e06 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -123,7 +123,7 @@
desc = "It never stays still for long."
icon_state = "spiderling"
anchored = 0
- layer = 2.7
+ layer = HIDING_LAYER
health = 3
var/last_itch = 0
var/amount_grown = -1
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index c5840eaed2..748a203cc4 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -69,7 +69,7 @@
/* Species-specific sprites, concept stolen from Paradise//vg/.
ex:
sprite_sheets = list(
- "Tajara" = 'icons/cat/are/bad'
+ SPECIES_TAJ = 'icons/cat/are/bad'
)
If index term exists and icon_override is not set, this sprite sheet will be used.
*/
@@ -84,6 +84,9 @@
var/reach = 1 // Length of tiles it can reach, 1 is adjacent.
var/addblends // Icon overlay for ADD highlights when applicable.
+ var/icon/default_worn_icon //Default on-mob icon
+ var/worn_layer //Default on-mob layer
+
/obj/item/New()
..()
if(embed_chance < 0)
@@ -280,6 +283,7 @@
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
hud_layerise()
+ user.position_hud_item(src,slot)
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
return
@@ -382,14 +386,14 @@ var/list/global/slot_flags_enumeration = list(
if(!allow)
return 0
if(slot_tie)
- if(!H.w_uniform && (slot_w_uniform in mob_equip))
+ var/allow = 0
+ for(var/obj/item/clothing/C in H.worn_clothing) //Runs through everything you're wearing, returns if you can't attach the thing
+ if(C.can_attach_accessory(src))
+ allow = 1
+ break
+ if(!allow)
if(!disable_warning)
- H << "You need a jumpsuit before you can attach this [name]."
- return 0
- var/obj/item/clothing/under/uniform = H.w_uniform
- if(uniform.accessories.len && !uniform.can_attach_accessory(src))
- if (!disable_warning)
- H << "You already have an accessory of this type attached to your [uniform]."
+ H << "You're not wearing anything you can attach this [name] to."
return 0
return 1
@@ -476,9 +480,7 @@ var/list/global/slot_flags_enumeration = list(
visible_message("[U] attempts to stab [M] in the eyes, but misses!")
return
- user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
- M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
- msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG
+ add_attack_logs(user,M,"Attack eyes with [name]")
user.setClickCooldown(user.get_attack_speed())
user.do_attack_animation(M)
@@ -678,4 +680,119 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
// My best guess as to why this is here would be that it does so little. Still, keep it under all the procs, for sanity's sake.
/obj/item/device
- icon = 'icons/obj/device.dmi'
\ No newline at end of file
+ icon = 'icons/obj/device.dmi'
+
+//Worn icon generation for on-mob sprites
+/obj/item/proc/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer)
+ //Get the required information about the base icon
+ var/icon/icon2use = get_worn_icon_file(body_type = body_type, slot_name = slot_name, default_icon = default_icon, inhands = inhands)
+ var/state2use = get_worn_icon_state(slot_name = slot_name)
+ var/layer2use = get_worn_layer(default_layer = default_layer)
+
+ //Snowflakey inhand icons in a specific slot
+ if(inhands && icon2use == icon_override)
+ switch(slot_name)
+ if(slot_r_hand_str)
+ state2use += "_r"
+ if(slot_l_hand_str)
+ state2use += "_l"
+
+ // testing("[src] (\ref[src]) - Slot: [slot_name], Inhands: [inhands], Worn Icon:[icon2use], Worn State:[state2use], Worn Layer:[layer2use]")
+
+ //Generate the base onmob icon
+ var/icon/standing_icon = icon(icon = icon2use, icon_state = state2use)
+
+ if(!inhands)
+ apply_custom(standing_icon) //Pre-image overridable proc to customize the thing
+ apply_addblends(icon2use,standing_icon) //Some items have ICON_ADD blend shaders
+
+ var/image/standing = image(standing_icon)
+ standing.alpha = alpha
+ standing.color = color
+ standing.layer = layer2use
+
+ //Apply any special features
+ if(!inhands)
+ apply_blood(standing) //Some items show blood when bloodied
+ apply_accessories(standing) //Some items sport accessories like webbing
+
+ //Return our icon
+ return standing
+
+//Returns the icon object that should be used for the worn icon
+/obj/item/proc/get_worn_icon_file(var/body_type,var/slot_name,var/default_icon,var/inhands)
+
+ //1: icon_override var
+ if(icon_override)
+ return icon_override
+
+ //2: species-specific sprite sheets (skipped for inhands)
+ if(LAZYLEN(sprite_sheets))
+ var/sheet = sprite_sheets[body_type]
+ if(sheet && !inhands)
+ return sheet
+
+ //3: slot-specific sprite sheets
+ if(LAZYLEN(item_icons))
+ var/sheet = item_icons[slot_name]
+ if(sheet)
+ return sheet
+
+ //4: item's default icon
+ if(default_worn_icon)
+ return default_worn_icon
+
+ //5: provided default_icon
+ if(default_icon)
+ return default_icon
+
+ //6: give up
+ return
+
+//Returns the state that should be used for the worn icon
+/obj/item/proc/get_worn_icon_state(var/slot_name)
+
+ //1: slot-specific sprite sheets
+ if(LAZYLEN(item_state_slots))
+ var/state = item_state_slots[slot_name]
+ if(state)
+ return state
+
+ //2: item_state variable
+ if(item_state)
+ return item_state
+
+ //3: icon_state variable
+ if(icon_state)
+ return icon_state
+
+//Returns the layer that should be used for the worn icon (as a FLOAT_LAYER layer, so negative)
+/obj/item/proc/get_worn_layer(var/default_layer = 0)
+
+ //1: worn_layer variable
+ if(!isnull(worn_layer)) //Can be zero, so...
+ return BODY_LAYER+worn_layer
+
+ //2: your default
+ return BODY_LAYER+default_layer
+
+//Apply the addblend blends onto the icon
+/obj/item/proc/apply_addblends(var/source_icon, var/icon/standing_icon)
+
+ //If we have addblends, blend them onto the provided icon
+ if(addblends && standing_icon && source_icon)
+ var/addblend_icon = icon("icon" = source_icon, "icon_state" = addblends)
+ standing_icon.Blend(addblend_icon, ICON_ADD)
+
+//STUB
+/obj/item/proc/apply_custom(var/icon/standing_icon)
+ return standing_icon
+
+//STUB
+/obj/item/proc/apply_blood(var/image/standing)
+ return standing
+
+//STUB
+/obj/item/proc/apply_accessories(var/image/standing)
+ return standing
+
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index a23abb5b06..302c7df568 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -145,7 +145,7 @@
var/obj/item/weapon/reagent_containers/syringe/syringe
/obj/structure/closet/body_bag/cryobag/New()
- tank = new /obj/item/weapon/tank/emergency/oxygen(null) //It's in nullspace to prevent ejection when the bag is opened.
+ tank = new /obj/item/weapon/tank/emergency/oxygen/double(null) //It's in nullspace to prevent ejection when the bag is opened.
..()
/obj/structure/closet/body_bag/cryobag/Destroy()
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 31bb9160f8..2ad51ca887 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -46,11 +46,11 @@
if(colour != "#FFFFFF" && shadeColour != "#000000")
colour = "#FFFFFF"
shadeColour = "#000000"
- user << "You will now draw in white and black with this crayon."
+ to_chat(usr,"You will now draw in white and black with this crayon.")
else
colour = "#000000"
shadeColour = "#FFFFFF"
- user << "You will now draw in black and white with this crayon."
+ to_chat(usr,"You will now draw in black and white with this crayon.")
return
/obj/item/weapon/pen/crayon/rainbow
@@ -72,22 +72,22 @@
switch(drawtype)
if("letter")
drawtype = input("Choose the letter.", "Crayon scribbles") in list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")
- user << "You start drawing a letter on the [target.name]."
+ to_chat(usr,"You start drawing a letter on the [target.name].")
if("graffiti")
- user << "You start drawing graffiti on the [target.name]."
+ to_chat(usr,"You start drawing graffiti on the [target.name].")
if("rune")
- user << "You start drawing a rune on the [target.name]."
+ to_chat(usr,"You start drawing a rune on the [target.name].")
if("arrow")
drawtype = input("Choose the arrow.", "Crayon scribbles") in list("left", "right", "up", "down")
- user << "You start drawing an arrow on the [target.name]."
+ to_chat(usr,"You start drawing an arrow on the [target.name].")
if(instant || do_after(user, 50))
new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype)
- user << "You finish drawing."
+ to_chat(usr,"You finish drawing.")
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
if(uses)
uses--
if(!uses)
- user << "You used up your crayon!"
+ to_chat(usr,"You used up your crayon!")
qdel(src)
return
@@ -99,7 +99,93 @@
if(uses)
uses -= 5
if(uses <= 0)
- user << "You ate your crayon!"
+ to_chat(user,"You ate your crayon!")
qdel(src)
else
..()
+
+/obj/item/weapon/pen/crayon/marker/black
+ icon_state = "markerblack"
+ colour = "#2D2D2D"
+ shadeColour = "#000000"
+ colourName = "black"
+
+/obj/item/weapon/pen/crayon/marker/red
+ icon_state = "markerred"
+ colour = "#DA0000"
+ shadeColour = "#810C0C"
+ colourName = "red"
+
+/obj/item/weapon/pen/crayon/marker/orange
+ icon_state = "markerorange"
+ colour = "#FF9300"
+ shadeColour = "#A55403"
+ colourName = "orange"
+
+/obj/item/weapon/pen/crayon/marker/yellow
+ icon_state = "markeryellow"
+ colour = "#FFF200"
+ shadeColour = "#886422"
+ colourName = "yellow"
+
+/obj/item/weapon/pen/crayon/marker/green
+ icon_state = "markergreen"
+ colour = "#A8E61D"
+ shadeColour = "#61840F"
+ colourName = "green"
+
+/obj/item/weapon/pen/crayon/marker/blue
+ icon_state = "markerblue"
+ colour = "#00B7EF"
+ shadeColour = "#0082A8"
+ colourName = "blue"
+
+/obj/item/weapon/pen/crayon/marker/purple
+ icon_state = "markerpurple"
+ colour = "#DA00FF"
+ shadeColour = "#810CFF"
+ colourName = "purple"
+
+/obj/item/weapon/pen/crayon/marker/mime
+ icon_state = "markermime"
+ desc = "A very sad-looking marker."
+ colour = "#FFFFFF"
+ shadeColour = "#000000"
+ colourName = "mime"
+ uses = 0
+
+/obj/item/weapon/pen/crayon/marker/mime/attack_self(mob/living/user as mob) //inversion
+ if(colour != "#FFFFFF" && shadeColour != "#000000")
+ colour = "#FFFFFF"
+ shadeColour = "#000000"
+ to_chat(usr,"You will now draw in white and black with this marker.")
+ else
+ colour = "#000000"
+ shadeColour = "#FFFFFF"
+ to_chat(usr,"You will now draw in black and white with this marker.")
+ return
+
+/obj/item/weapon/pen/crayon/marker/rainbow
+ icon_state = "markerrainbow"
+ colour = "#FFF000"
+ shadeColour = "#000FFF"
+ colourName = "rainbow"
+ uses = 0
+
+/obj/item/weapon/pen/crayon/marker/rainbow/attack_self(mob/living/user as mob)
+ colour = input(user, "Please select the main colour.", "Marker colour") as color
+ shadeColour = input(user, "Please select the shade colour.", "Marker colour") as color
+ return
+
+/obj/item/weapon/pen/crayon/marker/attack(mob/M as mob, mob/user as mob)
+ if(M == user)
+ to_chat(usr,"You take a bite of the marker and swallow it.")
+ user.nutrition += 1
+ user.reagents.add_reagent("marker_ink",6)
+ if(uses)
+ uses -= 5
+ if(uses <= 0)
+ to_chat(user,"You ate the marker!")
+ qdel(src)
+ else
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 7f1d83cc4a..78ee749ceb 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -11,7 +11,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
item_state = "electronic"
w_class = ITEMSIZE_SMALL
slot_flags = SLOT_ID | SLOT_BELT
- sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/id.dmi')
+ sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/id.dmi')
//Main variables
var/pdachoice = 1
@@ -1169,7 +1169,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" ([reply ? "Reply" : "Unable to Reply"])"
new_info(message_silent, ttone, reception_message)
- log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
+ log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]", usr)
new_message = 1
update_icon()
@@ -1181,7 +1181,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]"
new_info(message_silent, newstone, reception_message)
- log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
+ log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]",usr)
new_message = 1
/obj/item/device/pda/verb/verb_reset_pda()
@@ -1247,20 +1247,17 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(issilicon(usr))
return
- if (can_use(usr) && !isnull(cartridge))
- var/turf/T = get_turf(src)
- cartridge.loc = T
- if (ismob(loc))
+ if(can_use(usr) && !isnull(cartridge))
+ cartridge.forceMove(get_turf(src))
+ if(ismob(loc))
var/mob/M = loc
M.put_in_hands(cartridge)
- else
- cartridge.loc = get_turf(src)
mode = 0
scanmode = 0
if (cartridge.radio)
cartridge.radio.hostpda = null
- cartridge = null
to_chat(usr, "You remove \the [cartridge] from the [name].")
+ cartridge = null
else
to_chat(usr, "You cannot do this while restrained.")
@@ -1379,14 +1376,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
to_chat(user, "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]")
if(4)
- for (var/mob/O in viewers(C, null))
- O.show_message("\The [user] has analyzed [C]'s radiation levels!", 1)
-
- user.show_message("Analyzing Results for [C]:")
+ user.visible_message("\The [user] has analyzed [C]'s radiation levels!", 1)
+ to_chat(user, "Analyzing Results for [C]:")
if(C.radiation)
- user.show_message("Radiation Level: [C.radiation]")
+ to_chat(user, "Radiation Level: [C.radiation]")
else
- user.show_message("No radiation detected.")
+ to_chat(user, "No radiation detected.")
/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
if(!proximity) return
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index b77d73a262..4b088f51b8 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -265,8 +265,6 @@ var/list/civilian_cartridges = list(
if(loc)
var/obj/item/PDA = loc
var/mob/user = PDA.fingerprintslast
- if(istype(PDA.loc,/mob/living))
- name = PDA.loc
log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index ab893415ac..ebad249bde 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -61,7 +61,7 @@
if (href_list["wipe"])
var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "Yes", "No")
if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE))
- admin_attack_log(user, carded_ai, "Purged using \the [src.name]", "Was purged with \the [src.name]", "used \the [src.name] to purge")
+ add_attack_logs(user,carded_ai,"Purged from AI Card")
flush = 1
carded_ai.suiciding = 1
carded_ai << "Your power has been disabled!"
@@ -110,7 +110,7 @@
new /obj/structure/AIcore/deactivated(get_turf(ai))
ai.carded = 1
- admin_attack_log(user, ai, "Extracted with [src.name]", "Was extracted with [src.name]", "used the [src.name] to extract")
+ add_attack_logs(user,ai,"Extracted into AI Card")
src.name = "[initial(name)] - [ai.name]"
ai.loc = src
diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm
index 5df153c663..f2d3fd39b6 100644
--- a/code/game/objects/items/devices/communicator/UI.dm
+++ b/code/game/objects/items/devices/communicator/UI.dm
@@ -69,16 +69,17 @@
im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"])
//Weather reports.
- for(var/datum/planet/planet in planet_controller.planets)
- if(planet.weather_holder && planet.weather_holder.current_weather)
- var/list/W = list(
- "Planet" = planet.name,
- "Time" = planet.current_time.show_time("hh:mm"),
- "Weather" = planet.weather_holder.current_weather.name,
- "Temperature" = planet.weather_holder.temperature - T0C,
- "High" = planet.weather_holder.current_weather.temp_high - T0C,
- "Low" = planet.weather_holder.current_weather.temp_low - T0C)
- weather[++weather.len] = W
+ if(planet_controller)
+ for(var/datum/planet/planet in planet_controller.planets)
+ if(planet.weather_holder && planet.weather_holder.current_weather)
+ var/list/W = list(
+ "Planet" = planet.name,
+ "Time" = planet.current_time.show_time("hh:mm"),
+ "Weather" = planet.weather_holder.current_weather.name,
+ "Temperature" = planet.weather_holder.temperature - T0C,
+ "High" = planet.weather_holder.current_weather.temp_high - T0C,
+ "Low" = planet.weather_holder.current_weather.temp_low - T0C)
+ weather[++weather.len] = W
injection = "Test
"
@@ -133,11 +134,7 @@
if(href_list["rename"])
var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) )
if(new_name)
- owner = new_name
- name = "[owner]'s [initial(name)]"
- if(camera)
- camera.name = name
- camera.c_tag = name
+ register_device(new_name)
if(href_list["toggle_visibility"])
switch(network_visibility)
@@ -188,7 +185,7 @@
if(text)
exonet.send_message(their_address, "text", text)
im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text))
- log_pda("[usr] (COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]")
+ log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
@@ -251,4 +248,4 @@
set_light(fon * flum)
nanomanager.update_uis(src)
- add_fingerprint(usr)
\ No newline at end of file
+ add_fingerprint(usr)
diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm
index cac80c84d0..7342988916 100644
--- a/code/game/objects/items/devices/communicator/communicator.dm
+++ b/code/game/objects/items/devices/communicator/communicator.dm
@@ -75,12 +75,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
//This is a pretty terrible way of doing this.
spawn(5 SECONDS) //Wait for our mob to finish spawning.
if(ismob(loc))
- register_device(loc)
+ register_device(loc.name)
initialize_exonet(loc)
else if(istype(loc, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = loc
if(ismob(S.loc))
- register_device(S.loc)
+ register_device(S.loc.name)
initialize_exonet(S.loc)
// Proc: examine()
@@ -268,12 +268,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
// Proc: register_device()
// Parameters: 1 (user - the person to use their name for)
// Description: Updates the owner's name and the device's name.
-/obj/item/device/communicator/proc/register_device(mob/user)
- if(!user)
+/obj/item/device/communicator/proc/register_device(new_name)
+ if(!new_name)
return
- owner = user.name
+ owner = new_name
- name = "[owner]'s [initial(name)]"
+ name = "[new_name]'s [initial(name)]"
if(camera)
camera.name = name
camera.c_tag = name
@@ -287,17 +287,20 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
to_chat(voice, "\icon[src] Connection timed out with remote host.")
qdel(voice)
close_connection(reason = "Connection timed out")
+
+ //Clean up all references we might have to others
communicating.Cut()
voice_requests.Cut()
voice_invites.Cut()
+ node = null
+
+ //Clean up references that might point at us
all_communicators -= src
processing_objects -= src
listening_objects.Remove(src)
- qdel(camera)
- camera = null
- if(exonet)
- exonet.remove_address()
- exonet = null
+ qdel_null(camera)
+ qdel_null(exonet)
+
return ..()
// Proc: update_icon()
diff --git a/code/game/objects/items/devices/communicator/messaging.dm b/code/game/objects/items/devices/communicator/messaging.dm
index 3419985a71..d600f96a0f 100644
--- a/code/game/objects/items/devices/communicator/messaging.dm
+++ b/code/game/objects/items/devices/communicator/messaging.dm
@@ -136,7 +136,7 @@
to_chat(src, "You have sent '[text_message]' to [chosen_communicator].")
exonet_messages.Add("To [chosen_communicator]:
[text_message]")
- log_pda("[usr] (COMM: [src]) sent \"[text_message]\" to [chosen_communicator]")
+ log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index 9eb4991f69..af9d697d63 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -475,7 +475,7 @@
if(burn_damage > 15 && H.can_feel_pain())
H.emote("scream")
- admin_attack_log(user, H, "Electrocuted using \a [src]", "Was electrocuted with \a [src]", "used \a [src] to electrocute")
+ add_attack_logs(user,H,"Shocked using [name]")
/obj/item/weapon/shockpaddles/proc/make_alive(mob/living/carbon/human/M) //This revives the mob
var/deadtime = world.time - M.timeofdeath
@@ -487,7 +487,6 @@
M.timeofdeath = 0
M.stat = UNCONSCIOUS //Life() can bring them back to consciousness if it needs to.
- M.regenerate_icons()
M.failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
M.reload_fullscreen()
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 6027976134..ac62201fc5 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -59,9 +59,7 @@
/obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone)
if(!user || !M) return //sanity
- M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)")
+ add_attack_logs(user,M,"Flashed (attempt) with [src]")
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(M)
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index 30d4195355..78f385a8aa 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -104,16 +104,16 @@ var/list/GPS_list = list()
if(istype(their_area, /area/submap))
area_name = "Unknown Area" // Avoid spoilers.
var/Z_name = using_map.get_zlevel_name(T.z)
- var/direction = uppertext(dir2text(get_dir(curr, T)))
+ var/direction = get_adir(curr, T)
+ var/distX = T.x - curr.x
+ var/distY = T.y - curr.y
var/distance = get_dist(curr, T)
var/local = curr.z == T.z ? TRUE : FALSE
- if(!direction)
- direction = "CENTER"
- if(istype(T, /obj/item/device/gps/internal/poi))
- signals += " [G.gps_tag]: [area_name] [local ? "Dist: [round(distance, 10)]m [direction])" : "in \the [Z_name]"]"
+ if(istype(gps, /obj/item/device/gps/internal/poi))
+ signals += " [G.gps_tag]: [area_name] - [local ? "[direction] Dist: [round(distance, 10)]m" : "in \the [Z_name]"]"
else
- signals += " [G.gps_tag]: [area_name] [local ? "Dist: [round(distance, 10)]m [direction])" : "in \the [Z_name]"]"
+ signals += " [G.gps_tag]: [area_name], ([T.x], [T.y]) - [local ? "[direction] Dist: [distX ? "[abs(round(distX, 1))]m [(distX > 0) ? "E" : "W"], " : ""][distY ? "[abs(round(distY, 1))]m [(distY > 0) ? "N" : "S"]" : ""]" : "in \the [Z_name]"]"
if(signals.len)
dat += "Detected signals;"
@@ -250,12 +250,9 @@ var/list/GPS_list = list()
var/Z_name = using_map.get_zlevel_name(T.z)
var/coord = "[T.x], [T.y], [Z_name]"
var/degrees = round(Get_Angle(curr, T))
- var/direction = uppertext(dir2text(get_dir(curr, T)))
+ var/direction = get_adir(curr, T)
var/distance = get_dist(curr, T)
var/local = curr.z == T.z ? TRUE : FALSE
- if(!direction)
- direction = "CENTER"
- degrees = "N/A"
signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]"
diff --git a/code/game/objects/items/devices/modkit.dm b/code/game/objects/items/devices/modkit.dm
index ca7ace1a59..6ff95fe17d 100644
--- a/code/game/objects/items/devices/modkit.dm
+++ b/code/game/objects/items/devices/modkit.dm
@@ -7,7 +7,7 @@
desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user."
icon_state = "modkit"
var/parts = MODKIT_FULL
- var/target_species = "Human"
+ var/target_species = SPECIES_HUMAN
var/list/permitted_types = list(
/obj/item/clothing/head/helmet/space/void,
@@ -69,4 +69,4 @@
/obj/item/device/modkit/tajaran
name = "tajaran hardsuit modification kit"
desc = "A kit containing all the needed tools and parts to modify a hardsuit for another user. This one looks like it's meant for Tajaran."
- target_species = "Tajara"
+ target_species = SPECIES_TAJ
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 3b703f703b..105eb3aa8f 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -3,11 +3,12 @@
desc = "An updated, modular intercom that fits over the head. Takes encryption keys"
var/radio_desc = ""
icon_state = "headset"
+ item_state = null //To remove the radio's state
matter = list(DEFAULT_WALL_MATERIAL = 75)
subspace_transmission = 1
canhear_range = 0 // can't hear headsets from very far away
slot_flags = SLOT_EARS
- sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/ears.dmi')
+ sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/ears.dmi')
var/translate_binary = 0
var/translate_hive = 0
@@ -63,6 +64,17 @@
return ..(freq, level)
return -1
+/obj/item/device/radio/headset/get_worn_icon_state(var/slot_name)
+ var/append = ""
+ if(icon_override)
+ switch(slot_name)
+ if(slot_l_ear_str)
+ append = "_l"
+ if(slot_r_ear_str)
+ append = "_r"
+
+ return "[..()][append]"
+
/obj/item/device/radio/headset/syndicate
origin_tech = list(TECH_ILLEGAL = 3)
syndie = 1
@@ -92,77 +104,66 @@
name = "security radio headset"
desc = "This is used by your elite security force."
icon_state = "sec_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_sec
/obj/item/device/radio/headset/headset_sec/alt
name = "security bowman headset"
desc = "This is used by your elite security force."
icon_state = "sec_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_sec
/obj/item/device/radio/headset/headset_eng
name = "engineering radio headset"
desc = "When the engineers wish to chat like girls."
icon_state = "eng_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_eng/alt
name = "engineering bowman headset"
desc = "When the engineers wish to chat like girls."
icon_state = "eng_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_eng
/obj/item/device/radio/headset/headset_rob
name = "robotics radio headset"
desc = "Made specifically for the roboticists who cannot decide between departments."
icon_state = "rob_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_rob
/obj/item/device/radio/headset/headset_med
name = "medical radio headset"
desc = "A headset for the trained staff of the medbay."
icon_state = "med_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_med/alt
name = "medical bowman headset"
desc = "A headset for the trained staff of the medbay."
icon_state = "med_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sci
name = "science radio headset"
desc = "A sciency headset. Like usual."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_sci
/obj/item/device/radio/headset/headset_medsci
name = "medical research radio headset"
desc = "A headset that is a result of the mating between medical and science."
icon_state = "med_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_medsci
/obj/item/device/radio/headset/headset_com
name = "command radio headset"
desc = "A headset with a commanding channel."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_com
/obj/item/device/radio/headset/headset_com/alt
name = "command bowman headset"
desc = "A headset with a commanding channel."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_com
@@ -170,21 +171,18 @@
name = "colony director's headset"
desc = "The headset of the boss."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/captain/alt
name = "colony director's bowman headset"
desc = "The headset of the boss."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/captain/sfr
name = "SFR headset"
desc = "A headset belonging to a Sif Free Radio DJ. SFR, best tunes in the wilderness."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway.
@@ -206,105 +204,91 @@
name = "research director's headset"
desc = "Headset of the researching God."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/rd
/obj/item/device/radio/headset/heads/rd/alt
name = "research director's bowman headset"
desc = "Headset of the researching God."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/rd
/obj/item/device/radio/headset/heads/hos
name = "head of security's headset"
desc = "The headset of the man who protects your worthless lifes."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/heads/hos/alt
name = "head of security's bowman headset"
desc = "The headset of the man who protects your worthless lifes."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/heads/ce
name = "chief engineer's headset"
desc = "The headset of the guy who is in charge of morons"
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/ce
/obj/item/device/radio/headset/heads/ce/alt
name = "chief engineer's bowman headset"
desc = "The headset of the guy who is in charge of morons"
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/ce
/obj/item/device/radio/headset/heads/cmo
name = "chief medical officer's headset"
desc = "The headset of the highly trained medical chief."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/cmo
/obj/item/device/radio/headset/heads/cmo/alt
name = "chief medical officer's bowman headset"
desc = "The headset of the highly trained medical chief."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/cmo
/obj/item/device/radio/headset/heads/hop
name = "head of personnel's headset"
desc = "The headset of the guy who will one day be Colony Director."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hop
/obj/item/device/radio/headset/heads/hop/alt
name = "head of personnel's bowman headset"
desc = "The headset of the guy who will one day be Colony Director."
icon_state = "com_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hop
-/*
+
/obj/item/device/radio/headset/headset_mine
name = "mining radio headset"
- desc = "Headset used by miners. How useless. To access the mining channel, use :d."
+ desc = "Headset used by miners. Has inbuilt short-band radio for when comms are down."
icon_state = "mine_headset"
- item_state = "headset"
- keyslot2 = new /obj/item/device/encryptionkey/headset_mine
-*/
+ adhoc_fallback = TRUE
+ ks2type = /obj/item/device/encryptionkey/headset_cargo
+
/obj/item/device/radio/headset/headset_cargo
name = "supply radio headset"
desc = "A headset used by the QM and his slaves."
icon_state = "cargo_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_cargo/alt
name = "supply bowman headset"
desc = "A bowman headset used by the QM and his slaves."
icon_state = "cargo_headset_alt"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_service
name = "service radio headset"
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean."
icon_state = "srv_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/headset_service
/obj/item/device/radio/headset/ert
name = "emergency response team radio headset"
desc = "The headset of the boss's boss."
icon_state = "com_headset"
- item_state = "headset"
centComm = 1
// freerange = 1
ks2type = /obj/item/device/encryptionkey/ert
@@ -313,7 +297,6 @@
name = "emergency response team bowman headset"
desc = "The headset of the boss's boss."
icon_state = "com_headset_alt"
- item_state = "headset"
// freerange = 1
ks2type = /obj/item/device/encryptionkey/ert
@@ -324,7 +307,6 @@
name = "internal affair's headset"
desc = "The headset of your worst enemy."
icon_state = "com_headset"
- item_state = "headset"
ks2type = /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/mmi_radio
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 9aa65bb54e..81e3227022 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -49,6 +49,12 @@
name = "entertainment intercom"
frequency = ENT_FREQ
+/obj/item/device/radio/intercom/omni
+ name = "global announcer"
+/obj/item/device/radio/intercom/omni/initialize()
+ channels = radiochannels.Copy()
+ return ..()
+
/obj/item/device/radio/intercom/New()
..()
processing_objects += src
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index b6f62f27dc..f5f85fe8f5 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -53,14 +53,13 @@ var/global/list/default_medbay_channels = list(
var/const/FREQ_LISTENING = 1
var/list/internal_channels
-/obj/item/device/radio
var/datum/radio_frequency/radio_connection
var/list/datum/radio_frequency/secure_radio_connections = new
- proc/set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
+/obj/item/device/radio/proc/set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
/obj/item/device/radio/New()
..()
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index ae255d2f7b..feed24510b 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -3,9 +3,10 @@ CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
-GAS ANALYZER
+GAS ANALYZER - Analyzes atmosphere, container
MASS SPECTROMETER
REAGENT SCANNER
+HALOGEN COUNTER - Radcount on mobs
*/
@@ -41,29 +42,30 @@ REAGENT SCANNER
scan_mob(M, user)
/obj/item/device/healthanalyzer/proc/scan_mob(mob/living/M, mob/living/user)
+ var/dat = ""
if ((CLUMSY in user.mutations) && prob(50))
- user << text("You try to analyze the floor's vitals!")
- for(var/mob/O in viewers(M, null))
- O.show_message("\The [user] has analyzed the floor's vitals!", 1)
- user.show_message("Analyzing Results for The floor:", 1)
- user.show_message("Overall Status: Healthy", 1)
- user.show_message(" Damage Specifics: 0-0-0-0", 1)
- user.show_message("Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message("Body Temperature: ???", 1)
+ user.visible_message("\The [user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!")
+ dat += "Analyzing Results for the floor:
"
+ dat += "Overall Status: Healthy
"
+ dat += "\tDamage Specifics: 0-0-0-0
"
+ dat += "Key: Suffocation/Toxin/Burns/Brute
"
+ dat += "Body Temperature: ???"
+ user.show_message("[dat]", 1)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- usr << "You don't have the dexterity to do this!"
+ if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey")
+ to_chat(user, "You don't have the dexterity to do this!")
return
user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.")
- if (!istype(M,/mob/living/carbon/human) || M.isSynthetic())
+ if (!ishuman(M) || M.isSynthetic())
//these sensors are designed for organic life
- user.show_message("Analyzing Results for ERROR:\n\t Overall Status: ERROR")
- user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message(" Damage Specifics: ? - ? - ? - ?")
- user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
- user.show_message("Warning: Blood Level ERROR: --% --cl. Type: ERROR")
- user.show_message("Subject's pulse: -- bpm.")
+ dat += "Analyzing Results for ERROR:\n\tOverall Status: ERROR
"
+ dat += "\tKey: Suffocation/Toxin/Burns/Brute
"
+ dat += "\tDamage Specifics: ? - ? - ? - ?
"
+ dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
"
+ dat += "Warning: Blood Level ERROR: --% --cl. Type: ERROR
"
+ dat += "Subject's pulse: -- bpm."
+ user.show_message(dat, 1)
return
var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss())))
@@ -73,52 +75,52 @@ REAGENT SCANNER
var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
if(M.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy
- user.show_message("Analyzing Results for [M]:")
- user.show_message("Overall Status: dead")
+ dat += "Analyzing Results for [M]:
"
+ dat += "Overall Status: dead
"
else
- user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]")
- user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1)
- user.show_message(" Damage Specifics: [OX] - [TX] - [BU] - [BR]")
- user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
+ dat += "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]
"
+ dat += "\tKey: Suffocation/Toxin/Burns/Brute
"
+ dat += "\tDamage Specifics: [OX] - [TX] - [BU] - [BR]
"
+ dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
"
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
- user.show_message("Time of Death: [M.tod]")
+ dat += "Time of Death: [M.tod]
"
if(istype(M, /mob/living/carbon/human) && mode == 1)
var/mob/living/carbon/human/H = M
var/list/damaged = H.get_damaged_organs(1,1)
- user.show_message("Localized Damage, Brute/Burn:",1)
+ dat += "Localized Damage, Brute/Burn:
"
if(length(damaged)>0)
for(var/obj/item/organ/external/org in damaged)
if(org.robotic >= ORGAN_ROBOT)
continue
else
- user.show_message(text(" []: [][] - []",
- capitalize(org.name),
- (org.brute_dam > 0) ? "[org.brute_dam]" : 0,
- (org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"",
- (org.burn_dam > 0) ? "[org.burn_dam]" : 0),1)
+ dat += " [capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : 0]"
+ dat += "[(org.status & ORGAN_BLEEDING)?"\[Bleeding\]":""] - "
+ dat += "[(org.burn_dam > 0) ? "[org.burn_dam]" : 0]
"
else
- user.show_message(" Limbs are OK.",1)
+ dat += " Limbs are OK.
"
- OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
- TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal"
- BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K"
+ OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
+ TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal"
+ BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K"
BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K"
if(M.status_flags & FAKEDEATH)
OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
- user.show_message("[OX] | [TX] | [BU] | [BR]")
+ dat += "[OX] | [TX] | [BU] | [BR]
"
if(M.radiation)
if(advscan >= 2 && showadvscan == 1)
+ var/severity = ""
if(M.radiation >= 75)
- user.show_message("Critical levels of radiation detected. Immediate treatment advised.")
+ severity = "Critical"
else if(M.radiation >= 50)
- user.show_message("Severe levels of radiation detected.")
+ severity = "Severe"
else if(M.radiation >= 25)
- user.show_message("Moderate levels of radiation detected.")
+ severity = "Moderate"
else if(M.radiation >= 1)
- user.show_message("Low levels of radiation detected.")
+ severity = "Low"
+ dat += "[severity] levels of radiation detected. [(severity == "Critical") ? " Immediate treatment advised." : ""]
"
else
- user.show_message("Radiation detected.")
- if(istype(M, /mob/living/carbon))
+ dat += "Radiation detected.
"
+ if(iscarbon(M))
var/mob/living/carbon/C = M
if(C.reagents.total_volume)
var/unknown = 0
@@ -127,21 +129,21 @@ REAGENT SCANNER
for(var/A in C.reagents.reagent_list)
var/datum/reagent/R = A
if(R.scannable)
- reagentdata["[R.id]"] = " [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]"
+ reagentdata["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]
"
else
unknown++
- unknownreagents["[R.id]"] = " [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]"
+ unknownreagents["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]
"
if(reagentdata.len)
- user.show_message("Beneficial reagents detected in subject's blood:")
+ dat += "Beneficial reagents detected in subject's blood:
"
for(var/d in reagentdata)
- user.show_message(reagentdata[d])
+ dat += reagentdata[d]
if(unknown)
if(advscan >= 3 && showadvscan == 1)
- user.show_message("Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:")
+ dat += "Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:
"
for(var/d in unknownreagents)
- user.show_message(unknownreagents[d])
+ dat += unknownreagents[d]
else
- user.show_message("Warning: Unknown substance[(unknown>1)?"s":""] detected in subject's blood.")
+ dat += "Warning: Unknown substance[(unknown>1)?"s":""] detected in subject's blood.
"
if(C.ingested && C.ingested.total_volume)
var/unknown = 0
var/stomachreagentdata[0]
@@ -149,100 +151,104 @@ REAGENT SCANNER
for(var/B in C.ingested.reagent_list)
var/datum/reagent/T = B
if(T.scannable)
- stomachreagentdata["[T.id]"] = " [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]"
+ stomachreagentdata["[T.id]"] = "\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]
"
if (advscan == 0 || showadvscan == 0)
- user.show_message("[T.name] found in subject's stomach.")
+ dat += "[T.name] found in subject's stomach.
"
else
++unknown
- stomachunknownreagents["[T.id]"] = " [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]"
+ stomachunknownreagents["[T.id]"] = "\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]
"
if(advscan >= 1 && showadvscan == 1)
- user.show_message("Beneficial reagents detected in subject's stomach:")
+ dat += "Beneficial reagents detected in subject's stomach:
"
for(var/d in stomachreagentdata)
- user.show_message(stomachreagentdata[d])
+ dat += stomachreagentdata[d]
if(unknown)
if(advscan >= 3 && showadvscan == 1)
- user.show_message("Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:")
+ dat += "Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:
"
for(var/d in stomachunknownreagents)
- user.show_message(stomachunknownreagents[d])
+ dat += stomachunknownreagents[d]
else
- user.show_message("Unknown substance[(unknown > 1)?"s":""] found in subject's stomach.")
+ dat += "Unknown substance[(unknown > 1)?"s":""] found in subject's stomach.
"
if(C.virus2.len)
for (var/ID in C.virus2)
if (ID in virusDB)
var/datum/data/record/V = virusDB[ID]
- user.show_message("Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]")
+ dat += "Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]
"
else
- user.show_message("Warning: Unknown pathogen detected in subject's blood.")
+ dat += "Warning: Unknown pathogen detected in subject's blood.
"
if (M.getCloneLoss())
- user.show_message("Subject appears to have been imperfectly cloned.")
+ dat += "Subject appears to have been imperfectly cloned.
"
// if (M.reagents && M.reagents.get_reagent_amount("inaprovaline"))
// user.show_message("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.")
if (M.has_brain_worms())
- user.show_message("Subject suffering from aberrant brain activity. Recommend further scanning.")
+ dat += "Subject suffering from aberrant brain activity. Recommend further scanning.
"
else if (M.getBrainLoss() >= 60 || !M.has_brain())
- user.show_message("Subject is brain dead.")
+ dat += "Subject is brain dead.
"
else if (M.getBrainLoss() >= 25)
- user.show_message("Severe brain damage detected. Subject likely to have a traumatic brain injury.")
+ dat += "Severe brain damage detected. Subject likely to have a traumatic brain injury.
"
else if (M.getBrainLoss() >= 10)
- user.show_message("Significant brain damage detected. Subject may have had a concussion.")
+ dat += "Significant brain damage detected. Subject may have had a concussion.
"
else if (M.getBrainLoss() >= 1 && advscan >= 2 && showadvscan == 1)
- user.show_message("Minor brain damage detected.")
+ dat += "Minor brain damage detected.
"
if(ishuman(M))
var/mob/living/carbon/human/H = M
- for(var/name_i in H.internal_organs_by_name)
- var/obj/item/organ/internal/i = H.internal_organs_by_name[name_i]
- if(istype(i, /obj/item/organ/internal/appendix))
- var/obj/item/organ/internal/appendix/a = H.internal_organs_by_name[name_i]
- if(a.inflamed > 3)
- user.show_message(text("Severe inflammation detected in subject [a.name]."), 1)
- else if(a.inflamed > 2)
- user.show_message(text("Moderate inflammation detected in subject [a.name]."), 1)
- else if(a.inflamed >= 1)
- user.show_message(text("Mild inflammation detected in subject [a.name]."), 1)
-
-
- for(var/name in H.organs_by_name)
- var/obj/item/organ/external/e = H.organs_by_name[name]
- if(!e)
- continue
- var/limb = e.name
- if(e.status & ORGAN_BROKEN)
- if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!e.splinted))
- to_chat(user, "Unsecured fracture in subject [limb]. Splinting recommended for transport.")
- if(e.has_infected_wound())
- to_chat(user, "Infected wound detected in subject [limb]. Disinfection recommended.")
-
- for(var/name in H.organs_by_name)
- var/obj/item/organ/external/e = H.organs_by_name[name]
- if(e && e.status & ORGAN_BROKEN)
- if(advscan >= 1 && showadvscan == 1)
- user.show_message(text("Bone fractures detected in subject [e.name]."), 1)
- else
- user.show_message(text("Bone fractures detected. Advanced scanner required for location."), 1)
- break
+ for(var/obj/item/organ/internal/appendix/a in H.internal_organs)
+ var/severity = ""
+ if(a.inflamed > 3)
+ severity = "Severe"
+ else if(a.inflamed > 2)
+ severity = "Moderate"
+ else if(a.inflamed >= 1)
+ severity = "Mild"
+ if(severity)
+ dat += "[severity] inflammation detected in subject [a.name].
"
+ // Infections, fractures, and IB
+ var/basic_fracture = 0 // If it's a basic scanner
+ var/basic_ib = 0 // If it's a basic scanner
+ var/fracture_dat = "" // All the fractures
+ var/infection_dat = "" // All the infections
+ var/ib_dat = "" // All the IB
for(var/obj/item/organ/external/e in H.organs)
if(!e)
continue
- for(var/datum/wound/W in e.wounds) if(W.internal)
- if(advscan >= 1 && showadvscan == 1)
- user.show_message(text("Internal bleeding detected in subject [e.name]."), 1)
+ // Broken limbs
+ if(e.status & ORGAN_BROKEN)
+ if((e.name in list("l_arm", "r_arm", "l_leg", "r_leg")) && (!e.splinted))
+ fracture_dat += "Unsecured fracture in subject [e.name]. Splinting recommended for transport.
"
+ else if(advscan >= 1 && showadvscan == 1)
+ fracture_dat += "Bone fractures detected in subject [e.name].
"
else
- user.show_message(text("Internal bleeding detected. Advanced scanner required for location."), 1)
- break
- break
+ basic_fracture = 1
+ // Infections
+ if(e.has_infected_wound())
+ dat += "Infected wound detected in subject [e.name]. Disinfection recommended.
"
+ // IB
+ for(var/datum/wound/W in e.wounds)
+ if(W.internal)
+ if(advscan >= 1 && showadvscan == 1)
+ ib_dat += "Internal bleeding detected in subject [e.name].
"
+ else
+ basic_ib = 1
+ if(basic_fracture)
+ fracture_dat += "Bone fractures detected. Advanced scanner required for location.
"
+ if(basic_ib)
+ ib_dat += "Internal bleeding detected. Advanced scanner required for location.
"
+ dat += fracture_dat
+ dat += infection_dat
+ dat += ib_dat
+ // Blood level
if(M:vessel)
var/blood_volume = H.vessel.get_reagent_amount("blood")
var/blood_percent = round((blood_volume / H.species.blood_volume)*100)
var/blood_type = H.dna.b_type
- if((blood_percent <= BLOOD_VOLUME_SAFE) && (blood_percent > BLOOD_VOLUME_BAD))
- user.show_message("Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
- else if(blood_percent <= BLOOD_VOLUME_BAD)
- user.show_message("Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
+ if(blood_percent <= BLOOD_VOLUME_BAD)
+ dat += "Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]
"
+ else if(blood_percent <= BLOOD_VOLUME_SAFE)
+ dat += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]
"
else
- user.show_message("Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
- user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.")
-
+ dat += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
"
+ dat += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm."
+ user.show_message(dat, 1)
/obj/item/device/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
@@ -266,15 +272,15 @@ REAGENT SCANNER
if(0)
to_chat(usr, "The scanner will now perform a basic analysis.")
-/obj/item/device/healthanalyzer/advanced //reports bone fractures, IB, quantity of beneficial reagents in stomach; also regular health analyzer stuff
- name = "advanced health analyzer"
+/obj/item/device/healthanalyzer/improved //reports bone fractures, IB, quantity of beneficial reagents in stomach; also regular health analyzer stuff
+ name = "improved health analyzer"
desc = "A miracle of medical technology, this handheld scanner can produce an accurate and specific report of a patient's biosigns."
advscan = 1
origin_tech = list(TECH_MAGNET = 5, TECH_BIO = 6)
icon_state = "health1"
-/obj/item/device/healthanalyzer/enhanced //reports all of the above, as well as radiation severity and minor brain damage
- name = "enhanced health analyzer"
+/obj/item/device/healthanalyzer/advanced //reports all of the above, as well as radiation severity and minor brain damage
+ name = "advanced health analyzer"
desc = "An even more advanced handheld health scanner, complete with a full biosign monitor and on-board radiation and neurological analysis suites."
advscan = 2
origin_tech = list(TECH_MAGNET = 6, TECH_BIO = 7)
@@ -311,16 +317,21 @@ REAGENT SCANNER
return atmosanalyzer_scan(src, air, user)
/obj/item/device/analyzer/attack_self(mob/user as mob)
-
if (user.stat)
return
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey")
to_chat(usr, "You don't have the dexterity to do this!")
return
analyze_gases(src, user)
return
+/obj/item/device/analyzer/afterattack(var/obj/O, var/mob/user, var/proximity)
+ if(proximity)
+ analyze_gases(O, user)
+ return
+
+
/obj/item/device/mass_spectrometer
name = "mass spectrometer"
desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample."
@@ -353,7 +364,7 @@ REAGENT SCANNER
/obj/item/device/mass_spectrometer/attack_self(mob/user as mob)
if (user.stat)
return
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey")
to_chat(user, "You don't have the dexterity to do this!")
return
if(reagents.total_volume)
@@ -400,15 +411,11 @@ REAGENT SCANNER
var/recent_fail = 0
/obj/item/device/reagent_scanner/afterattack(obj/O, mob/user as mob, proximity)
- if(!proximity)
- return
- if (user.stat)
+ if(!proximity || user.stat || !istype(O))
return
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
to_chat(user, "You don't have the dexterity to do this!")
return
- if(!istype(O))
- return
if(!isnull(O.reagents))
var/dat = ""
@@ -419,9 +426,9 @@ REAGENT SCANNER
if(dat)
to_chat(user, "Chemicals found: [dat]")
else
- user << "No active chemical agents found in [O]."
+ to_chat(user, "No active chemical agents found in [O].")
else
- user << "No significant chemical agents found in [O]."
+ to_chat(user, "No significant chemical agents found in [O].")
return
@@ -445,24 +452,17 @@ REAGENT SCANNER
/obj/item/device/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob)
if(!isslime(M))
- user << "This device can only scan slimes!"
+ to_chat(user, "This device can only scan slimes!")
return
var/mob/living/simple_animal/slime/S = M
- user.show_message("Slime scan results:")
- user.show_message(text("[S.slime_color] [] slime", S.is_adult ? "adult" : "baby"))
-
- user.show_message("Health: [S.health]")
- user.show_message("Mutation Probability: [S.mutation_chance]")
+ user.show_message("Slime scan results:
[S.slime_color] [S.is_adult ? "adult" : "baby"] slime
Health: [S.health]
Mutation Probability: [S.mutation_chance]")
var/list/mutations = list()
for(var/potential_color in S.slime_mutation)
var/mob/living/simple_animal/slime/slime = potential_color
mutations.Add(initial(slime.slime_color))
+ user.show_message("Potental to mutate into [english_list(mutations)] colors.
Extract potential: [S.cores]
Nutrition: [S.nutrition]/[S.get_max_nutrition()]")
- user.show_message("Potental to mutate into [english_list(mutations)] colors.")
- user.show_message("Extract potential: [S.cores]")
-
- user.show_message(text("Nutrition: [S.nutrition]/[]", S.get_max_nutrition()))
if (S.nutrition < S.get_starve_nutrition())
user.show_message("Warning: Subject is starving!")
else if (S.nutrition < S.get_hunger_nutrition())
@@ -479,3 +479,25 @@ REAGENT SCANNER
user.show_message("Subject is friendly to other slime colors.")
user.show_message("Growth progress: [S.amount_grown]/10")
+
+/obj/item/device/halogen_counter
+ name = "halogen counter"
+ icon_state = "eftpos"
+ desc = "A hand-held halogen counter, used to detect the level of irradiation of living beings."
+ w_class = ITEMSIZE_SMALL
+ flags = CONDUCT
+ origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 2)
+ throwforce = 0
+ throw_speed = 3
+ throw_range = 7
+
+/obj/item/device/halogen_counter/attack(mob/living/M as mob, mob/living/user as mob)
+ if(!iscarbon(M))
+ to_chat(user, "This device can only scan organic beings!")
+ return
+ user.visible_message("\The [user] has analyzed [M]'s radiation levels!", "Analyzing Results for [M]:")
+ if(M.radiation)
+ to_chat(user, "Radiation Level: [M.radiation]")
+ else
+ to_chat(user, "No radiation detected.")
+ return
diff --git a/code/game/objects/items/devices/spy_bug.dm b/code/game/objects/items/devices/spy_bug.dm
index 159134f83c..ce145fed9e 100644
--- a/code/game/objects/items/devices/spy_bug.dm
+++ b/code/game/objects/items/devices/spy_bug.dm
@@ -16,11 +16,12 @@
// var/obj/item/device/radio/bug/radio
var/obj/machinery/camera/bug/camera
+ var/camtype = /obj/machinery/camera/bug
/obj/item/device/camerabug/New()
..()
// radio = new(src)
- camera = new(src)
+ camera = new camtype(src)
/obj/item/device/camerabug/attack_self(mob/user)
if(user.a_intent == I_HURT)
@@ -40,7 +41,7 @@
linkedmonitor.unpair(src)
linkedmonitor = null
qdel(camera)
- camera = new(src)
+ camera = new camtype(src)
to_chat(usr, "You turn the [src] off and on again, delinking it from any monitors.")
/obj/item/brokenbug
@@ -83,6 +84,7 @@
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
+ camtype = /obj/machinery/camera/bug/spy
/obj/item/device/camerabug/examine(mob/user)
. = ..(user, 0)
diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm
index a2d6ce3341..2040f22a99 100644
--- a/code/game/objects/items/devices/suit_cooling.dm
+++ b/code/game/objects/items/devices/suit_cooling.dm
@@ -46,9 +46,15 @@
var/mob/living/carbon/human/H = loc
- var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling
- var/env_temp = get_environment_temperature() //wont save you from a fire
- var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
+ var/efficiency = 1 - H.get_pressure_weakness() // You need to have a good seal for effective cooling
+ var/temp_adj = 0 // How much the unit cools you. Adjusted later on.
+ var/env_temp = get_environment_temperature() // This won't save you from a fire
+ var/thermal_protection = H.get_heat_protection(env_temp) // ... unless you've got a good suit.
+
+ if(thermal_protection < 0.99) //For some reason, < 1 returns false if the value is 1.
+ temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
+ else
+ temp_adj = min(H.bodytemperature - thermostat, max_cooling)
if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision
return
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 126a4871c9..7820d0c4ea 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -35,9 +35,9 @@ effective or pretty fucking useless.
user << "The mind batterer has been burnt out!"
return
- user.attack_log += text("\[[time_stamp()]\] Used [src] to knock down people in the area.")
-
+ var/list/affected = list()
for(var/mob/living/carbon/human/M in orange(10, user))
+ affected += M
spawn()
if(prob(50))
@@ -49,6 +49,8 @@ effective or pretty fucking useless.
else
M << "You feel a sudden, electric jolt travel through your head."
+ add_attack_logs(user,affected,"Used a [name]")
+
playsound(src.loc, 'sound/misc/interference.ogg', 50, 1)
user << "You trigger [src]."
times_used += 1
diff --git a/code/game/objects/items/devices/translator.dm b/code/game/objects/items/devices/translator.dm
index 5de1ba1396..fc6352de29 100644
--- a/code/game/objects/items/devices/translator.dm
+++ b/code/game/objects/items/devices/translator.dm
@@ -4,7 +4,7 @@
desc = "This handy device appears to translate the languages it hears into onscreen text for a user."
icon = 'icons/obj/device.dmi'
icon_state = "translator"
- w_class = ITEMSIZE_SMALL
+ w_class = ITEMSIZE_NORMAL
origin_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
var/mult_icons = 1 //Changes sprite when it translates
var/visual = 1 //If you need to see to get the message
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 9a56cf94a7..2fa9ea63c7 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -106,13 +106,13 @@
if (M.use(1))
var/obj/item/weapon/secbot_assembly/ed209_assembly/B = new /obj/item/weapon/secbot_assembly/ed209_assembly
B.loc = get_turf(src)
- user << "You armed the robot frame."
+ to_chat(user, "You armed the robot frame.")
if (user.get_inactive_hand()==src)
user.remove_from_mob(src)
user.put_in_inactive_hand(B)
qdel(src)
else
- user << "You need one sheet of metal to arm the robot frame."
+ to_chat(user, "You need one sheet of metal to arm the robot frame.")
if(istype(W, /obj/item/robot_parts/l_leg))
if(src.l_leg) return
user.drop_item()
@@ -149,9 +149,9 @@
src.chest = W
src.updateicon()
else if(!W:wires)
- user << "You need to attach wires to it first!"
+ to_chat(user, "You need to attach wires to it first!")
else
- user << "You need to attach a cell to it first!"
+ to_chat(user, "You need to attach a cell to it first!")
if(istype(W, /obj/item/robot_parts/head))
if(src.head) return
@@ -161,16 +161,16 @@
src.head = W
src.updateicon()
else
- user << "You need to attach a flash to it first!"
+ to_chat(user, "You need to attach a flash to it first!")
if(istype(W, /obj/item/device/mmi))
var/obj/item/device/mmi/M = W
if(check_completion())
if(!istype(loc,/turf))
- user << "You can't put \the [W] in, the frame has to be standing on the ground to be perfectly precise."
+ to_chat(user, "You can't put \the [W] in, the frame has to be standing on the ground to be perfectly precise.")
return
if(!M.brainmob)
- user << "Sticking an empty [W] into the frame would sort of defeat the purpose."
+ to_chat(user, "Sticking an empty [W] into the frame would sort of defeat the purpose.")
return
if(!M.brainmob.key)
var/ghost_can_reenter = 0
@@ -181,15 +181,15 @@
to_chat(user, "\The [W] is completely unresponsive; though it may be able to auto-resuscitate.") //Jamming a ghosted brain into a borg is likely detrimental, and may result in some problems.
return
if(!ghost_can_reenter)
- user << "\The [W] is completely unresponsive; there's no point."
+ to_chat(user, "\The [W] is completely unresponsive; there's no point.")
return
if(M.brainmob.stat == DEAD)
- user << "Sticking a dead [W] into the frame would sort of defeat the purpose."
+ to_chat(user, "Sticking a dead [W] into the frame would sort of defeat the purpose.")
return
if(jobban_isbanned(M.brainmob, "Cyborg"))
- user << "This [W] does not seem to fit."
+ to_chat(user, "This [W] does not seem to fit.")
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc), unfinished = 1)
@@ -228,7 +228,7 @@
qdel(src)
else
- user << "The MMI must go in after everything else!"
+ to_chat(user, "The MMI must go in after everything else!")
if (istype(W, /obj/item/weapon/pen))
var/t = sanitizeSafe(input(user, "Enter new robot name", src.name, src.created_name), MAX_NAME_LEN)
@@ -245,22 +245,22 @@
..()
if(istype(W, /obj/item/weapon/cell))
if(src.cell)
- user << "You have already inserted a cell!"
+ to_chat(user, "You have already inserted a cell!")
return
else
user.drop_item()
W.loc = src
src.cell = W
- user << "You insert the cell!"
+ to_chat(user, "You insert the cell!")
if(istype(W, /obj/item/stack/cable_coil))
if(src.wires)
- user << "You have already inserted wire!"
+ to_chat(user, "You have already inserted wire!")
return
else
var/obj/item/stack/cable_coil/coil = W
coil.use(1)
src.wires = 1.0
- user << "You insert the wire!"
+ to_chat(user, "You insert the wire!")
return
/obj/item/robot_parts/head/attackby(obj/item/W as obj, mob/user as mob)
@@ -269,14 +269,14 @@
if(istype(user,/mob/living/silicon/robot))
var/current_module = user.get_active_hand()
if(current_module == W)
- user << "How do you propose to do that?"
+ to_chat(user, "How do you propose to do that?")
return
else
add_flashes(W,user)
else
add_flashes(W,user)
else if(istype(W, /obj/item/weapon/stock_parts/manipulator))
- user << "You install some manipulators and modify the head, creating a functional spider-bot!"
+ to_chat(user, "You install some manipulators and modify the head, creating a functional spider-bot!")
new /mob/living/simple_animal/spiderbot(get_turf(loc))
user.drop_item()
qdel(W)
@@ -286,24 +286,24 @@
/obj/item/robot_parts/head/proc/add_flashes(obj/item/W as obj, mob/user as mob) //Made into a seperate proc to avoid copypasta
if(src.flash1 && src.flash2)
- user << "You have already inserted the eyes!"
+ to_chat(user, "You have already inserted the eyes!")
return
else if(src.flash1)
user.drop_item()
W.loc = src
src.flash2 = W
- user << "You insert the flash into the eye socket!"
+ to_chat(user, "You insert the flash into the eye socket!")
else
user.drop_item()
W.loc = src
src.flash1 = W
- user << "You insert the flash into the eye socket!"
+ to_chat(user, "You insert the flash into the eye socket!")
/obj/item/robot_parts/emag_act(var/remaining_charges, var/mob/user)
if(sabotaged)
- user << "[src] is already sabotaged!"
+ to_chat(user, "[src] is already sabotaged!")
else
- user << "You short out the safeties."
+ to_chat(user, "You short out the safeties.")
sabotaged = 1
return 1
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index eed9d9dc49..63a2ea474e 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -134,7 +134,7 @@
return 1
/obj/item/borg/upgrade/jetpack
- name = "mining robot jetpack"
+ name = "robot jetpack"
desc = "A carbon dioxide jetpack suitable for low-gravity operations."
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
@@ -149,7 +149,7 @@
if(!T)
T = locate() in R.module.modules
if(!T)
- R.module.modules += new/obj/item/weapon/tank/jetpack/carbondioxide
+ R.module.modules += new/obj/item/weapon/tank/jetpack/carbondioxide(R.module)
for(var/obj/item/weapon/tank/jetpack/carbondioxide in R.module.modules)
R.internals = src
return 1
@@ -174,7 +174,7 @@
if(!T)
T = locate() in R.module.modules
if(!T)
- R.module.modules += new/obj/item/device/healthanalyzer/advanced
+ R.module.modules += new/obj/item/device/healthanalyzer/advanced(R.module)
return 1
if(T)
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
@@ -210,9 +210,12 @@
R.add_language(LANGUAGE_TRADEBAND, 1)
R.add_language(LANGUAGE_UNATHI, 1)
R.add_language(LANGUAGE_SIIK, 1)
+ R.add_language(LANGUAGE_AKHANI, 1)
R.add_language(LANGUAGE_SKRELLIAN, 1)
+ R.add_language(LANGUAGE_SKRELLIANFAR, 0)
R.add_language(LANGUAGE_GUTTER, 1)
R.add_language(LANGUAGE_SCHECHI, 1)
R.add_language(LANGUAGE_ROOTLOCAL, 1)
+ R.add_language(LANGUAGE_TERMINUS, 1)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm
index f1c9aa2d14..e24a727b99 100644
--- a/code/game/objects/items/shooting_range.dm
+++ b/code/game/objects/items/shooting_range.dm
@@ -104,7 +104,6 @@
bmark.pixel_x = p_x
bmark.pixel_y = p_y
bmark.icon = 'icons/effects/effects.dmi'
- bmark.layer = 3.5
bmark.icon_state = "scorch"
if(decaltype == 1)
diff --git a/code/game/objects/items/stacks/fifty_spawner.dm b/code/game/objects/items/stacks/fifty_spawner.dm
index 1977427ebb..0be33e5829 100644
--- a/code/game/objects/items/stacks/fifty_spawner.dm
+++ b/code/game/objects/items/stacks/fifty_spawner.dm
@@ -8,13 +8,17 @@
var/obj/item/stack/type_to_spawn = null
/obj/fiftyspawner/New()
- //spawns the 50-stack and qdels self
- ..()
-// var/obj_path = text2path("/obj/item/stack/[material]")
- var/obj/item/stack/M = new type_to_spawn(src.loc)
- M.amount = M.max_amount //some stuff spawns with 60, we're still calling it fifty
- M.update_icon() // Some stacks have different sprites depending on how full they are.
- qdel(src)
+ spawn()
+ //spawns the 50-stack and qdels self
+ ..()
+ if(istype(src.loc, /obj/structure/loot_pile)) //Spawning from a lootpile is weird, need to wait until we're out of it to do our work.
+ while(istype(src.loc, /obj/structure/loot_pile))
+ sleep(1)
+ // var/obj_path = text2path("/obj/item/stack/[material]")
+ var/obj/item/stack/M = new type_to_spawn(src.loc)
+ M.amount = M.max_amount //some stuff spawns with 60, we're still calling it fifty
+ M.update_icon() // Some stacks have different sprites depending on how full they are.
+ qdel(src)
/obj/fiftyspawner/rods
name = "stack of rods" //this needs to be defined for cargo
diff --git a/code/game/objects/items/stacks/marker_beacons.dm b/code/game/objects/items/stacks/marker_beacons.dm
index 9978ef6b0d..2194b84fbd 100644
--- a/code/game/objects/items/stacks/marker_beacons.dm
+++ b/code/game/objects/items/stacks/marker_beacons.dm
@@ -25,6 +25,7 @@ var/list/marker_beacon_colors = list(
icon_state = "marker"
max_amount = 100
no_variants = TRUE
+ w_class = ITEMSIZE_SMALL
var/picked_color = "random"
/obj/item/stack/marker_beacon/ten
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index eb62b5d674..b5ff773e8b 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -111,6 +111,7 @@
user.visible_message("\The [user] places a bandaid over \a [W.desc] on [M]'s [affecting.name].", \
"You place a bandaid over \a [W.desc] on [M]'s [affecting.name]." )
W.bandage()
+ W.disinfect()
used++
affecting.update_damages()
if(used == amount)
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index ff680ab468..b2477ae9ff 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -61,8 +61,7 @@ var/global/list/datum/stack_recipe/rods_recipes = list( \
return
if (istype(W, /obj/item/weapon/tape_roll))
- var/obj/item/stack/medical/splint/ghetto/new_splint = new(user.loc)
- new_splint.loc = src.loc
+ var/obj/item/stack/medical/splint/ghetto/new_splint = new(get_turf(user))
new_splint.add_fingerprint(user)
user.visible_message("\The [user] constructs \a [new_splint] out of a [singular_name].", \
diff --git a/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm b/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm
index 3d89b5e786..256d2c8582 100644
--- a/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm
+++ b/code/game/objects/items/stacks/tiles/fifty_spawner_tiles.dm
@@ -8,13 +8,17 @@
name = "stack of wood"
type_to_spawn = /obj/item/stack/tile/wood
+/obj/fiftyspawner/wood/sif
+ name = "stack of alien wood"
+ type_to_spawn = /obj/item/stack/tile/wood/sif
+
/obj/fiftyspawner/carpet
name = "stack of carpet"
type_to_spawn = /obj/item/stack/tile/carpet
-/obj/fiftyspawner/bluecarpet
- name = "stack of blue carpet"
- type_to_spawn = /obj/item/stack/tile/carpet/blue
+/obj/fiftyspawner/tealcarpet
+ name = "stack of teal carpet"
+ type_to_spawn = /obj/item/stack/tile/carpet/teal
/obj/fiftyspawner/floor
name = "stack of floor tiles"
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 32a4580c7e..5c17634ae2 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -37,9 +37,6 @@
flags = 0
origin_tech = list(TECH_BIO = 1)
no_variants = FALSE
-
-/obj/item/stack/tile/grass/fifty
- amount = 50
/*
* Wood
*/
@@ -55,8 +52,11 @@
flags = 0
no_variants = FALSE
-/obj/item/stack/tile/wood/fifty
- amount = 50
+/obj/item/stack/tile/wood/sif
+ name = "alien wood tile"
+ singular_name = "alien wood tile"
+ desc = "An easy to fit wooden floor tile. It's blue!"
+ icon_state = "tile-sifwood"
/obj/item/stack/tile/wood/cyborg
name = "wood floor tile synthesizer"
@@ -81,11 +81,11 @@
flags = 0
no_variants = FALSE
-/obj/item/stack/tile/carpet/blue
- name = "blue carpet"
- singular_name = "blue carpet"
- desc = "A piece of blue carpet. It is the same size as a normal floor tile!"
- icon_state = "tile-bluecarpet"
+/obj/item/stack/tile/carpet/teal
+ name = "teal carpet"
+ singular_name = "teal carpet"
+ desc = "A piece of teal carpet. It is the same size as a normal floor tile!"
+ icon_state = "tile-tealcarpet"
no_variants = FALSE
// TODO - Add descriptions to these
@@ -107,7 +107,7 @@
/obj/item/stack/tile/floor
name = "floor tile"
singular_name = "floor tile"
- desc = "Those could work as a pretty decent throwing weapon" //why?
+ desc = "A metal tile fit for covering a section of floor."
icon_state = "tile"
force = 6.0
matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index c86993fa31..3931bec8ef 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -17,6 +17,7 @@
* Plushies
* Toy cult sword
* Bouquets
+ Stick Horse
*/
@@ -503,207 +504,324 @@
/*
* Action figures
*/
-
/obj/item/toy/figure
- name = "Completely Glitched action figure"
- desc = "A \"Space Life\" brand... wait, what the hell is this thing? It seems to be requesting the sweet release of death."
- icon_state = "assistant"
+ name = "Non-Specific Action Figure action figure"
+ desc = "A \"Space Life\" brand... wait, what the hell is this thing?"
icon = 'icons/obj/toy.dmi'
+ icon_state = "nuketoy"
+ var/cooldown = 0
+ var/toysay = "What the fuck did you do?"
+
+/obj/item/toy/figure/New()
+ ..()
+ desc = "A \"Space Life\" brand [name]"
+
+/obj/item/toy/figure/attack_self(mob/user as mob)
+ if(cooldown < world.time)
+ cooldown = (world.time + 30) //3 second cooldown
+ user.visible_message("The [src] says \"[toysay]\".")
+ playsound(user, 'sound/machines/click.ogg', 20, 1)
/obj/item/toy/figure/cmo
name = "Chief Medical Officer action figure"
desc = "A \"Space Life\" brand Chief Medical Officer action figure."
icon_state = "cmo"
+ toysay = "Suit sensors!"
/obj/item/toy/figure/assistant
name = "Assistant action figure"
desc = "A \"Space Life\" brand Assistant action figure."
icon_state = "assistant"
+ toysay = "Grey tide station wide!"
/obj/item/toy/figure/atmos
name = "Atmospheric Technician action figure"
desc = "A \"Space Life\" brand Atmospheric Technician action figure."
icon_state = "atmos"
+ toysay = "Glory to Atmosia!"
/obj/item/toy/figure/bartender
name = "Bartender action figure"
desc = "A \"Space Life\" brand Bartender action figure."
icon_state = "bartender"
+ toysay = "Where's my monkey?"
/obj/item/toy/figure/borg
name = "Drone action figure"
desc = "A \"Space Life\" brand Drone action figure."
icon_state = "borg"
+ toysay = "I. LIVE. AGAIN."
/obj/item/toy/figure/gardener
name = "Gardener action figure"
desc = "A \"Space Life\" brand Gardener action figure."
icon_state = "botanist"
+ toysay = "Dude, I see colors..."
/obj/item/toy/figure/captain
name = "Colony Director action figure"
desc = "A \"Space Life\" brand Colony Director action figure."
icon_state = "captain"
+ toysay = "How do I open this display case?"
/obj/item/toy/figure/cargotech
name = "Cargo Technician action figure"
desc = "A \"Space Life\" brand Cargo Technician action figure."
icon_state = "cargotech"
+ toysay = "For Cargonia!"
/obj/item/toy/figure/ce
name = "Chief Engineer action figure"
desc = "A \"Space Life\" brand Chief Engineer action figure."
icon_state = "ce"
+ toysay = "Wire the solars!"
/obj/item/toy/figure/chaplain
name = "Chaplain action figure"
desc = "A \"Space Life\" brand Chaplain action figure."
icon_state = "chaplain"
+ toysay = "Gods make me a killing machine please!"
/obj/item/toy/figure/chef
name = "Chef action figure"
desc = "A \"Space Life\" brand Chef action figure."
icon_state = "chef"
+ toysay = "I swear it's not human meat."
/obj/item/toy/figure/chemist
name = "Chemist action figure"
desc = "A \"Space Life\" brand Chemist action figure."
icon_state = "chemist"
+ toysay = "Get your pills!"
/obj/item/toy/figure/clown
name = "Clown action figure"
desc = "A \"Space Life\" brand Clown action figure."
icon_state = "clown"
+ toysay = "Honk!"
/obj/item/toy/figure/corgi
name = "Corgi action figure"
desc = "A \"Space Life\" brand Corgi action figure."
icon_state = "ian"
+ toysay = "Arf!"
/obj/item/toy/figure/detective
name = "Detective action figure"
desc = "A \"Space Life\" brand Detective action figure."
icon_state = "detective"
+ toysay = "This airlock has grey jumpsuit and insulated glove fibers on it."
/obj/item/toy/figure/dsquad
name = "Space Commando action figure"
desc = "A \"Space Life\" brand Space Commando action figure."
icon_state = "dsquad"
+ toysay = "Eliminate all threats!"
/obj/item/toy/figure/engineer
name = "Engineer action figure"
desc = "A \"Space Life\" brand Engineer action figure."
icon_state = "engineer"
+ toysay = "Oh god, the engine is gonna go!"
/obj/item/toy/figure/geneticist
name = "Geneticist action figure"
desc = "A \"Space Life\" brand Geneticist action figure, which was recently dicontinued."
icon_state = "geneticist"
+ toysay = "I'm not qualified for this job."
/obj/item/toy/figure/hop
name = "Head of Personnel action figure"
desc = "A \"Space Life\" brand Head of Personnel action figure."
icon_state = "hop"
+ toysay = "Giving out all access!"
/obj/item/toy/figure/hos
name = "Head of Security action figure"
desc = "A \"Space Life\" brand Head of Security action figure."
icon_state = "hos"
+ toysay = "I'm here to win, anything else is secondary."
/obj/item/toy/figure/qm
name = "Quartermaster action figure"
desc = "A \"Space Life\" brand Quartermaster action figure."
icon_state = "qm"
+ toysay = "Hail Cargonia!"
/obj/item/toy/figure/janitor
name = "Janitor action figure"
desc = "A \"Space Life\" brand Janitor action figure."
icon_state = "janitor"
+ toysay = "Look at the signs, you idiot."
/obj/item/toy/figure/agent
name = "Internal Affairs Agent action figure"
desc = "A \"Space Life\" brand Internal Affairs Agent action figure."
icon_state = "agent"
+ toysay = "Standard Operating Procedure says they're guilty! Hacking is proof they're an Enemy of the Corporation!"
/obj/item/toy/figure/librarian
name = "Librarian action figure"
desc = "A \"Space Life\" brand Librarian action figure."
icon_state = "librarian"
+ toysay = "One day while..."
/obj/item/toy/figure/md
name = "Medical Doctor action figure"
desc = "A \"Space Life\" brand Medical Doctor action figure."
icon_state = "md"
+ toysay = "The patient is already dead!"
/obj/item/toy/figure/mime
name = "Mime action figure"
desc = "A \"Space Life\" brand Mime action figure."
icon_state = "mime"
+ toysay = "..."
/obj/item/toy/figure/miner
name = "Shaft Miner action figure"
desc = "A \"Space Life\" brand Shaft Miner action figure."
icon_state = "miner"
+ toysay = "Oh god, it's eating my intestines!"
/obj/item/toy/figure/ninja
name = "Space Ninja action figure"
desc = "A \"Space Life\" brand Space Ninja action figure."
icon_state = "ninja"
+ toysay = "Oh god! Stop shooting, I'm friendly!"
/obj/item/toy/figure/wizard
name = "Wizard action figure"
desc = "A \"Space Life\" brand Wizard action figure."
icon_state = "wizard"
+ toysay = "Ei Nath!"
/obj/item/toy/figure/rd
name = "Research Director action figure"
desc = "A \"Space Life\" brand Research Director action figure."
icon_state = "rd"
+ toysay = "Blowing all of the borgs!"
/obj/item/toy/figure/roboticist
name = "Roboticist action figure"
desc = "A \"Space Life\" brand Roboticist action figure."
icon_state = "roboticist"
+ toysay = "He asked to be borged!"
/obj/item/toy/figure/scientist
name = "Scientist action figure"
desc = "A \"Space Life\" brand Scientist action figure."
icon_state = "scientist"
+ toysay = "Someone else must have made those bombs!"
/obj/item/toy/figure/syndie
name = "Doom Operative action figure"
desc = "A \"Space Life\" brand Doom Operative action figure."
icon_state = "syndie"
+ toysay = "Get that fucking disk!"
/obj/item/toy/figure/secofficer
name = "Security Officer action figure"
desc = "A \"Space Life\" brand Security Officer action figure."
icon_state = "secofficer"
+ toysay = "I am the law!"
+
+/obj/item/toy/figure/virologist
+ name = "Virologist action figure"
+ desc = "A \"Space Life\" brand Virologist action figure."
+ icon_state = "virologist"
+ toysay = "The cure is potassium!"
/obj/item/toy/figure/warden
name = "Warden action figure"
desc = "A \"Space Life\" brand Warden action figure."
icon_state = "warden"
+ toysay = "Execute him for breaking in!"
/obj/item/toy/figure/psychologist
name = "Psychologist action figure"
desc = "A \"Space Life\" brand Psychologist action figure."
icon_state = "psychologist"
+ toysay = "The analyzer says you're fine!"
/obj/item/toy/figure/paramedic
name = "Paramedic action figure"
desc = "A \"Space Life\" brand Paramedic action figure."
icon_state = "paramedic"
+ toysay = "WHERE ARE YOU??"
/obj/item/toy/figure/ert
name = "Emergency Response Team Commander action figure"
desc = "A \"Space Life\" brand Emergency Response Team Commander action figure."
icon_state = "ert"
+ toysay = "We're probably the good guys!"
/*
* Plushies
*/
+/*
+ * Carp plushie
+ */
+
+/obj/item/toy/plushie/carp
+ name = "space carp plushie"
+ desc = "An adorable stuffed toy that resembles a space carp."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "plushie/carp"
+ attack_verb = list("bitten", "eaten", "fin slapped")
+ var/bitesound = 'sound/weapons/bite.ogg'
+
+// Attack mob
+/obj/item/toy/plushie/carp/attack(mob/M as mob, mob/user as mob)
+ playsound(loc, bitesound, 20, 1) // Play bite sound in local area
+ return ..()
+
+// Attack self
+/obj/item/toy/plushie/carp/attack_self(mob/user as mob)
+ playsound(src.loc, bitesound, 20, 1)
+ return ..()
+
+
+/obj/random/carp_plushie
+ name = "Random Carp Plushie"
+ desc = "This is a random plushie"
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "plushie/carp"
+
+/obj/random/carp_plushie/item_to_spawn()
+ return pick(typesof(/obj/item/toy/plushie/carp)) //can pick any carp plushie, even the original.
+
+/obj/item/toy/plushie/carp/ice
+ icon_state = "icecarp"
+
+/obj/item/toy/plushie/carp/silent
+ icon_state = "silentcarp"
+
+/obj/item/toy/plushie/carp/electric
+ icon_state = "electriccarp"
+
+/obj/item/toy/plushie/carp/gold
+ icon_state = "goldcarp"
+
+/obj/item/toy/plushie/carp/toxin
+ icon_state = "toxincarp"
+
+/obj/item/toy/plushie/carp/dragon
+ icon_state = "dragoncarp"
+
+/obj/item/toy/plushie/carp/pink
+ icon_state = "pinkcarp"
+
+/obj/item/toy/plushie/carp/candy
+ icon_state = "candycarp"
+
+/obj/item/toy/plushie/carp/nebula
+ icon_state = "nebulacarp"
+
+/obj/item/toy/plushie/carp/void
+ icon_state = "voidcarp"
+
//Large plushies.
/obj/structure/plushie
name = "generic plush"
@@ -726,6 +844,7 @@
user.visible_message("\The [user] pokes the [src].","You poke the [src].")
visible_message("[src] says, \"[phrase]\"")
+
/obj/structure/plushie/ian
name = "plush corgi"
desc = "A plushie of an adorable corgi! Don't you just want to hug it and squeeze it and call it \"Ian\"?"
@@ -787,6 +906,12 @@
to_chat(M, "You name the plushie [input], giving it a hug for good luck.")
return 1
+/obj/item/toy/plushie/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I, /obj/item/toy/plushie) || istype(I, /obj/item/organ/external/head))
+ user.visible_message("[user] makes \the [I] kiss \the [src]!.", \
+ "You make \the [I] kiss \the [src]!.")
+ return ..()
+
/obj/item/toy/plushie/nymph
name = "diona nymph plush"
desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not."
@@ -817,6 +942,96 @@
desc = "A farwa plush doll. It's soft and comforting!"
icon_state = "farwaplushie"
+/obj/item/toy/plushie/corgi
+ name = "corgi plushie"
+ icon_state = "corgi"
+
+/obj/item/toy/plushie/girly_corgi
+ name = "corgi plushie"
+ icon_state = "girlycorgi"
+
+/obj/item/toy/plushie/robo_corgi
+ name = "borgi plushie"
+ icon_state = "robotcorgi"
+
+/obj/item/toy/plushie/octopus
+ name = "octopus plushie"
+ icon_state = "loveable"
+
+/obj/item/toy/plushie/face_hugger
+ name = "facehugger plushie"
+ icon_state = "huggable"
+
+//foxes are basically the best
+
+/obj/item/toy/plushie/red_fox
+ name = "red fox plushie"
+ icon_state = "redfox"
+
+/obj/item/toy/plushie/black_fox
+ name = "black fox plushie"
+ icon_state = "blackfox"
+
+/obj/item/toy/plushie/marble_fox
+ name = "marble fox plushie"
+ icon_state = "marblefox"
+
+/obj/item/toy/plushie/blue_fox
+ name = "blue fox plushie"
+ icon_state = "bluefox"
+
+/obj/item/toy/plushie/orange_fox
+ name = "orange fox plushie"
+ icon_state = "orangefox"
+
+/obj/item/toy/plushie/coffee_fox
+ name = "coffee fox plushie"
+ icon_state = "coffeefox"
+
+/obj/item/toy/plushie/pink_fox
+ name = "pink fox plushie"
+ icon_state = "pinkfox"
+
+/obj/item/toy/plushie/purple_fox
+ name = "purple fox plushie"
+ icon_state = "purplefox"
+
+/obj/item/toy/plushie/crimson_fox
+ name = "crimson fox plushie"
+ icon_state = "crimsonfox"
+
+/obj/item/toy/plushie/deer
+ name = "deer plushie"
+ icon_state = "deer"
+
+/obj/item/toy/plushie/black_cat
+ name = "black cat plushie"
+ icon_state = "blackcat"
+
+/obj/item/toy/plushie/grey_cat
+ name = "grey cat plushie"
+ icon_state = "greycat"
+
+/obj/item/toy/plushie/white_cat
+ name = "white cat plushie"
+ icon_state = "whitecat"
+
+/obj/item/toy/plushie/orange_cat
+ name = "orange cat plushie"
+ icon_state = "orangecat"
+
+/obj/item/toy/plushie/siamese_cat
+ name = "siamese cat plushie"
+ icon_state = "siamesecat"
+
+/obj/item/toy/plushie/tabby_cat
+ name = "tabby cat plushie"
+ icon_state = "tabbycat"
+
+/obj/item/toy/plushie/tuxedo_cat
+ name = "tuxedo cat plushie"
+ icon_state = "tuxedocat"
+
/obj/item/toy/plushie/therapy/red
name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red."
@@ -886,6 +1101,147 @@
name = "plastic bouquet"
desc = "A cheap plastic bouquet of flowers. Smells like cheap, toxic plastic."
+/obj/item/toy/stickhorse
+ name = "stick horse"
+ desc = "A pretend horse on a stick for any aspiring little cowboy to ride."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "stickhorse"
+ w_class = ITEMSIZE_LARGE
+
+//////////////////////////////////////////////////////
+// Magic 8-Ball / Conch //
+//////////////////////////////////////////////////////
+
+/obj/item/toy/eight_ball
+ name = "\improper Magic 8-Ball"
+ desc = "Mystical! Magical! Ages 8+!"
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "eight-ball"
+ var/use_action = "shakes the ball"
+ var/cooldown = 0
+ var/list/possible_answers = list("Definitely.", "All signs point to yes.", "Most likely.", "Yes.", "Ask again later.", "Better not tell you now.", "Future unclear.", "Maybe.", "Doubtful.", "No.", "Don't count on it.", "Never.")
+
+/obj/item/toy/eight_ball/attack_self(mob/user as mob)
+ if(!cooldown)
+ var/answer = pick(possible_answers)
+ user.visible_message("[user] focuses on their question and [use_action]...")
+ user.visible_message("The [src] says \"[answer]\"")
+ spawn(30)
+ cooldown = 0
+ return
+
+/obj/item/toy/eight_ball/conch
+ name = "Magic Conch shell"
+ desc = "All hail the Magic Conch!"
+ icon_state = "conch"
+ use_action = "pulls the string"
+ possible_answers = list("Yes.", "No.", "Try asking again.", "Nothing.", "I don't think so.", "Neither.", "Maybe someday.")
+
+// DND Character minis. Use the naming convention (type)character for the icon states.
+/obj/item/toy/character
+ icon = 'icons/obj/toy.dmi'
+ w_class = ITEMSIZE_SMALL
+ pixel_z = 5
+
+/obj/item/toy/character/alien
+ name = "xenomorph xiniature"
+ desc = "A miniature xenomorph. Scary!"
+ icon_state = "aliencharacter"
+/obj/item/toy/character/cleric
+ name = "cleric miniature"
+ desc = "A wee little cleric, with his wee little staff."
+ icon_state = "clericcharacter"
+/obj/item/toy/character/warrior
+ name = "warrior miniature"
+ desc = "That sword would make a decent toothpick."
+ icon_state = "warriorcharacter"
+/obj/item/toy/character/thief
+ name = "thief miniature"
+ desc = "Hey, where did my wallet go!?"
+ icon_state = "thiefcharacter"
+/obj/item/toy/character/wizard
+ name = "wizard miniature"
+ desc = "MAGIC!"
+ icon_state = "wizardcharacter"
+/obj/item/toy/character/voidone
+ name = "void one miniature"
+ desc = "The dark lord has risen!"
+ icon_state = "darkmastercharacter"
+/obj/item/toy/character/lich
+ name = "lich miniature"
+ desc = "Murderboner extraordinaire."
+ icon_state = "lichcharacter"
+/obj/item/weapon/storage/box/characters
+ name = "box of miniatures"
+ desc = "The nerd's best friends."
+ icon_state = "box"
+/obj/item/weapon/storage/box/characters/starts_with = list(
+// /obj/item/toy/character/alien,
+ /obj/item/toy/character/cleric,
+ /obj/item/toy/character/warrior,
+ /obj/item/toy/character/thief,
+ /obj/item/toy/character/wizard,
+ /obj/item/toy/character/voidone,
+ /obj/item/toy/character/lich
+ )
+
+/obj/item/toy/AI
+ name = "toy AI"
+ desc = "A little toy model AI core!"// with real law announcing action!" //Alas, requires a rewrite of how ion laws work.
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "AI"
+ w_class = ITEMSIZE_SMALL
+ var/cooldown = 0
+/*
+/obj/item/toy/AI/attack_self(mob/user)
+ if(!cooldown) //for the sanity of everyone
+ var/message = generate_ion_law()
+ to_chat(user, "You press the button on [src].")
+ playsound(user, 'sound/machines/click.ogg', 20, 1)
+ visible_message("[message]")
+ cooldown = 1
+ spawn(30) cooldown = 0
+ return
+ ..()
+*/
+/obj/item/toy/owl
+ name = "owl action figure"
+ desc = "An action figure modeled after 'The Owl', defender of justice."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "owlprize"
+ w_class = ITEMSIZE_SMALL
+ var/cooldown = 0
+
+/obj/item/toy/owl/attack_self(mob/user)
+ if(!cooldown) //for the sanity of everyone
+ var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!")
+ to_chat(user, "You pull the string on the [src].")
+ //playsound(user, 'sound/misc/hoot.ogg', 25, 1)
+ visible_message("[message]")
+ cooldown = 1
+ spawn(30) cooldown = 0
+ return
+ ..()
+
+/obj/item/toy/griffin
+ name = "griffin action figure"
+ desc = "An action figure modeled after 'The Griffin', criminal mastermind."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "griffinprize"
+ w_class = ITEMSIZE_SMALL
+ var/cooldown = 0
+
+/obj/item/toy/griffin/attack_self(mob/user)
+ if(!cooldown) //for the sanity of everyone
+ var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!")
+ to_chat(user, "You pull the string on the [src].")
+ //playsound(user, 'sound/misc/caw.ogg', 25, 1)
+ visible_message("[message]")
+ cooldown = 1
+ spawn(30) cooldown = 0
+ return
+ ..()
+
/* NYET.
/obj/item/weapon/toddler
icon_state = "toddler"
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 8f5719b8e8..196f8d4a74 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -103,7 +103,7 @@
build_delay = 50
build_type = "airlock"
build_other = /obj/machinery/door/airlock
- else if(!deconstruct && (istype(T,/turf/space) || istype(T,get_base_turf_by_area(T))))
+ else if(!deconstruct && isturf(T) && (istype(T,/turf/space) || istype(T,get_base_turf_by_area(T))))
build_cost = 1
build_type = "floor"
build_turf = /turf/simulated/floor/airless
diff --git a/code/game/objects/items/weapons/candle.dm b/code/game/objects/items/weapons/candle.dm
index 7bc0398b72..3f861b86d4 100644
--- a/code/game/objects/items/weapons/candle.dm
+++ b/code/game/objects/items/weapons/candle.dm
@@ -8,7 +8,7 @@
var/wax = 2000
/obj/item/weapon/flame/candle/New()
- wax = rand(800, 1000) // Enough for 27-33 minutes. 30 minutes on average.
+ wax -= rand(800, 1000) // Enough for 27-33 minutes. 30 minutes on average.
..()
/obj/item/weapon/flame/candle/update_icon()
@@ -26,7 +26,7 @@
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.isOn()) //Badasses dont get blinded by lighting their candle with a welding tool
- light("\The [user] casually lights the [name] with [W].")
+ light("\The [user] casually lights the [src] with [W].")
else if(istype(W, /obj/item/weapon/flame/lighter))
var/obj/item/weapon/flame/lighter/L = W
if(L.lit)
@@ -41,16 +41,13 @@
light()
-/obj/item/weapon/flame/candle/proc/light(var/flavor_text = "\The [usr] lights the [name].")
- if(!src.lit)
- src.lit = 1
- //src.damtype = "fire"
- for(var/mob/O in viewers(usr, null))
- O.show_message(flavor_text, 1)
+/obj/item/weapon/flame/candle/proc/light(var/flavor_text = "\The [usr] lights the [src].")
+ if(!lit)
+ lit = TRUE
+ visible_message(flavor_text)
set_light(CANDLE_LUM)
processing_objects.Add(src)
-
/obj/item/weapon/flame/candle/process()
if(!lit)
return
@@ -88,23 +85,13 @@
/obj/item/weapon/flame/candle/everburn
wax = 99999
-/obj/item/weapon/flame/candle/everburn/New()
- if(!src.lit)
- src.lit = 1
- //src.damtype = "fire"
- for(var/mob/O in viewers(usr, null))
- O.show_message("\The [name] mysteriously lights itself!.", 1)
- set_light(CANDLE_LUM)
- processing_objects.Add(src)
+/obj/item/weapon/flame/candle/everburn/initialize()
+ . = ..()
+ light("\The [src] mysteriously lights itself!.")
/obj/item/weapon/flame/candle/candelabra/everburn
wax = 99999
-/obj/item/weapon/flame/candle/candelabra/everburn/New()
- if(!src.lit)
- src.lit = 1
- //src.damtype = "fire"
- for(var/mob/O in viewers(usr, null))
- O.show_message("\The [name] mysteriously lights itself!.", 1)
- set_light(CANDLE_LUM)
- processing_objects.Add(src)
+/obj/item/weapon/flame/candle/candelabra/everburn/initialize()
+ . = ..()
+ light("\The [src] mysteriously lights itself!.")
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index c8d4eed3ad..5d60c8485b 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -6,6 +6,7 @@ MATCHES
CIGARETTES
CIGARS
SMOKING PIPES
+CUSTOM CIGS
CHEAP LIGHTERS
ZIPPO
@@ -88,6 +89,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/weldermes = "USER lights NAME with FLAME"
var/ignitermes = "USER lights NAME with FLAME"
var/brand
+ blood_sprite_state = null //Can't bloody these
/obj/item/clothing/mask/smokable/New()
..()
@@ -454,6 +456,41 @@ CIGARETTE PACKETS ARE IN FANCY.DM
item_state = "cobpipe"
chem_volume = 35
+///////////////
+//CUSTOM CIGS//
+///////////////
+//and by custom cigs i mean craftable joints. smoke weed every day
+
+/obj/item/clothing/mask/smokable/cigarette/joint
+ name = "joint"
+ desc = "This probably shouldn't ever show up."
+ icon_state = "joint"
+ max_smoketime = 500
+ smoketime = 500
+ nicotine_amt = 0
+
+/obj/item/weapon/rollingpaper
+ name = "rolling paper"
+ desc = "A small, thin piece of easily flammable paper, commonly used for rolling and smoking various dried plants."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "cig paper"
+
+/obj/item/weapon/rollingpaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if (istype(W, /obj/item/weapon/reagent_containers/food/snacks))
+ var/obj/item/weapon/reagent_containers/food/snacks/grown/G = W
+ if (!G.dry)
+ user << "[G] must be dried before you roll it into [src]."
+ return
+ var/obj/item/clothing/mask/smokable/cigarette/joint/J = new /obj/item/clothing/mask/smokable/cigarette/joint(user.loc)
+ to_chat(usr,"You roll the [G.name] into a joint!")
+ J.add_fingerprint(user)
+ if(G.reagents)
+ G.reagents.trans_to_obj(J, G.reagents.total_volume)
+ J.name = "[G.name] joint"
+ J.desc = "A joint lovingly rolled and filled with [G.name]. Blaze it."
+ qdel(G)
+ qdel(src)
+
/////////
//ZIPPO//
/////////
@@ -525,7 +562,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(lit == 1)
M.IgniteMob()
- msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] and lit them on fire (INTENT: [uppertext(user.a_intent)]) (JMP)")
+ add_attack_logs(user,M,"Lit on fire with [src]")
if(istype(M.wear_mask, /obj/item/clothing/mask/smokable/cigarette) && user.zone_sel.selecting == O_MOUTH && lit)
var/obj/item/clothing/mask/smokable/cigarette/cig = M.wear_mask
diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
index 2b3631ddbf..71d6e2d867 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
@@ -100,6 +100,7 @@
/obj/item/weapon/circuitboard/turbine_control
name = T_BOARD("turbine control console")
build_path = /obj/machinery/computer/turbine_computer
+ origin_tech = list(TECH_DATA = 2, TECH_POWER = 2)
/obj/item/weapon/circuitboard/solar_control
name = T_BOARD("solar control console")
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 33b93f6210..ac0a93941b 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -67,6 +67,7 @@
if(istype(M,/mob/living))
var/mob/living/L = M
L.apply_effect(rand(5,20), IRRADIATE, check_protection = 0)
+ L.apply_damage(max(2,L.getCloneLoss()), CLONE)
if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed
if (buf.types & DNA2_BUF_UI)
@@ -129,10 +130,7 @@
if((buf.types & DNA2_BUF_SE) && (block ? (GetState() && block == MONKEYBLOCK) : GetState(MONKEYBLOCK)))
injected_with_monkey = " (MONKEY)"
- M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.ckey])")
- log_attack("[user.name] ([user.ckey]) used the [name] to inject [M.name] ([M.ckey])")
- message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with \the [src][injected_with_monkey]")
+ add_attack_logs(user,M,"[injected_with_monkey] used the [name] on")
// Apply the DNA shit.
inject(M, user)
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 1e1565a2ae..b49a76c5a9 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -55,11 +55,8 @@
loc = null
if (ismob(target))
- add_logs(user, target, "planted [name] on")
+ add_attack_logs(user, target, "planted [name] on with [timer] second fuse")
user.visible_message("[user.name] finished planting an explosive on [target.name]!")
- message_admins("[key_name(user, user.client)](?) planted [src.name] on [key_name(target)](?) with [timer] second fuse",0,1)
- log_game("[key_name(user)] planted [src.name] on [key_name(target)] with [timer] second fuse")
-
else
message_admins("[key_name(user, user.client)](?) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1)
log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 46543b901b..bef0f8fcd9 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -179,10 +179,7 @@
H.loc = present
- H.attack_log += text("\[[time_stamp()]\] Has been wrapped with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to wrap [H.name] ([H.ckey])")
- msg_admin_attack("[key_name(user)] used [src] to wrap [key_name(H)]")
-
+ add_attack_logs(user,H,"Wrapped with [src]")
else
user << "You need more paper."
else
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 0eaf073cfa..92de17d994 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -43,7 +43,7 @@
if(stage > 1 && !active && clown_check(user))
user << "You prime \the [name]!"
- msg_admin_attack("[user.name] ([user.ckey]) primed \a [src]. (JMP)")
+ msg_admin_attack("[key_name_admin(user)] primed \a [src]")
activate()
add_fingerprint(user)
@@ -136,7 +136,7 @@
icon_state = initial(icon_state) + "_active"
if(user)
- msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)")
+ msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
return
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 5588089cef..e917745e0e 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -5,92 +5,89 @@
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
var/banglet = 0
- prime()
- ..()
- for(var/obj/structure/closet/L in hear(7, get_turf(src)))
- if(locate(/mob/living/carbon/, L))
- for(var/mob/living/carbon/M in L)
- bang(get_turf(src), M)
+/obj/item/weapon/grenade/flashbang/prime()
+ ..()
+ for(var/obj/structure/closet/L in hear(7, get_turf(src)))
+ if(locate(/mob/living/carbon/, L))
+ for(var/mob/living/carbon/M in L)
+ bang(get_turf(src), M)
+ for(var/mob/living/carbon/M in hear(7, get_turf(src)))
+ bang(get_turf(src), M)
- for(var/mob/living/carbon/M in hear(7, get_turf(src)))
- bang(get_turf(src), M)
+ for(var/obj/structure/blob/B in hear(8,get_turf(src))) //Blob damage here
+ var/damage = round(30/(get_dist(B,get_turf(src))+1))
+ if(B.overmind)
+ damage *= B.overmind.blob_type.burn_multiplier
+ B.adjust_integrity(-damage)
- for(var/obj/structure/blob/B in hear(8,get_turf(src))) //Blob damage here
- var/damage = round(30/(get_dist(B,get_turf(src))+1))
- if(B.overmind)
- damage *= B.overmind.blob_type.burn_multiplier
- B.adjust_integrity(-damage)
+ new/obj/effect/effect/sparks(src.loc)
+ new/obj/effect/effect/smoke/illumination(src.loc, 5, range=30, power=30, color="#FFFFFF")
+ qdel(src)
+ return
- new/obj/effect/effect/sparks(src.loc)
- new/obj/effect/effect/smoke/illumination(src.loc, 5, range=30, power=30, color="#FFFFFF")
- qdel(src)
- return
-
- proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
- M << "BANG" // Called during the loop that bangs people in lockers/containers and when banging
- playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
+/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
+ to_chat(M, "BANG") // Called during the loop that bangs people in lockers/containers and when banging
+ playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
// -- Polymorph
-//Checking for protections
- var/eye_safety = 0
- var/ear_safety = 0
- if(iscarbon(M))
- eye_safety = M.eyecheck()
- ear_safety = M.get_ear_protection()
+ //Checking for protections
+ var/eye_safety = 0
+ var/ear_safety = 0
+ if(iscarbon(M))
+ eye_safety = M.eyecheck()
+ ear_safety = M.get_ear_protection()
-//Flashing everyone
- if(eye_safety < 1)
- M.flash_eyes()
- M.Stun(2)
- M.Weaken(10)
+ //Flashing everyone
+ if(eye_safety < 1)
+ M.flash_eyes()
+ M.Confuse(2)
+ M.Weaken(5)
-
-
-//Now applying sound
- if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M))
- if(ear_safety > 0)
- M.Stun(2)
- M.Weaken(1)
- else
- M.Stun(10)
- M.Weaken(3)
- if ((prob(14) || (M == src.loc && prob(70))))
- M.ear_damage += rand(1, 10)
- else
- M.ear_damage += rand(0, 5)
- M.ear_deaf = max(M.ear_deaf,15)
-
- else if(get_dist(M, T) <= 5)
- if(!ear_safety)
- M.Stun(8)
- M.ear_damage += rand(0, 3)
- M.ear_deaf = max(M.ear_deaf,10)
-
- else if(!ear_safety)
- M.Stun(4)
- M.ear_damage += rand(0, 1)
- M.ear_deaf = max(M.ear_deaf,5)
-
-//This really should be in mob not every check
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
- if (E && E.damage >= E.min_bruised_damage)
- M << "Your eyes start to burn badly!"
- if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
- if (E.damage >= E.min_broken_damage)
- M << "You can't see anything!"
- if (M.ear_damage >= 15)
- M << "Your ears start to ring badly!"
- if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
- if (prob(M.ear_damage - 10 + 5))
- M << "You can't hear anything!"
- M.sdisabilities |= DEAF
+ //Now applying sound
+ if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M))
+ if(ear_safety > 0)
+ M.Confuse(2)
+ M.Weaken(1)
else
- if (M.ear_damage >= 5)
- M << "Your ears start to ring!"
- M.update_icons() //Forces matrix transform to proc if they are now laying, I guess?
+ M.Confuse(10)
+ M.Weaken(3)
+ if ((prob(14) || (M == src.loc && prob(70))))
+ M.ear_damage += rand(1, 10)
+ else
+ M.ear_damage += rand(0, 5)
+ M.ear_deaf = max(M.ear_deaf,15)
+
+ else if(get_dist(M, T) <= 5)
+ if(!ear_safety)
+ M.Confuse(8)
+ M.ear_damage += rand(0, 3)
+ M.ear_deaf = max(M.ear_deaf,10)
+
+ else if(!ear_safety)
+ M.Confuse(4)
+ M.ear_damage += rand(0, 1)
+ M.ear_deaf = max(M.ear_deaf,5)
+
+ //This really should be in mob not every check
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
+ if (E && E.damage >= E.min_bruised_damage)
+ M << "Your eyes start to burn badly!"
+ if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
+ if (E.damage >= E.min_broken_damage)
+ M << "You can't see anything!"
+ if (M.ear_damage >= 15)
+ to_chat(M, "Your ears start to ring badly!")
+ if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
+ if (prob(M.ear_damage - 10 + 5))
+ to_chat(M, "You can't hear anything!")
+ M.sdisabilities |= DEAF
+ else if(M.ear_damage >= 5)
+ to_chat(M, "Your ears start to ring!")
+
+ M.update_icons() //Forces matrix transform to proc if they are now laying, I guess?
/obj/item/weapon/grenade/flashbang/Destroy()
walk(src, 0) // Because we might have called walk_away, we must stop the walk loop or BYOND keeps an internal reference to us forever.
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index b46d987b4c..5854e02cac 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -72,7 +72,7 @@
return
if(user)
- msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)")
+ msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
icon_state = initial(icon_state) + "_active"
active = 1
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index ea838cce0b..46ebb3bd40 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -18,7 +18,13 @@
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
var/cuff_type = "handcuffs"
var/use_time = 30
- sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/handcuffs.dmi')
+ sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/handcuffs.dmi')
+
+/obj/item/weapon/handcuffs/get_worn_icon_state(var/slot_name)
+ if(slot_name == slot_handcuffed_str)
+ return "handcuff1" //Simple
+
+ return ..()
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
@@ -76,9 +82,7 @@
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
return 0
- H.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [H.name] ([H.ckey])")
- msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]")
+ add_attack_logs(user,H,"Handcuffed (attempt)")
feedback_add_details("handcuffs","H")
user.setClickCooldown(user.get_attack_speed(src))
@@ -97,6 +101,13 @@
target.update_inv_handcuffed()
return 1
+/obj/item/weapon/handcuffs/equipped(var/mob/living/user,var/slot)
+ . = ..()
+ if(slot == slot_handcuffed)
+ user.drop_r_hand()
+ user.drop_l_hand()
+ user.stop_pulling()
+
var/last_chew = 0
/mob/living/carbon/human/RestrainedClickOn(var/atom/A)
if (A != src) return ..()
@@ -113,11 +124,10 @@ var/last_chew = 0
if (!O) return
var/datum/gender/T = gender_datums[H.get_visible_gender()]
-
+
var/s = "[H.name] chews on [T.his] [O.name]!"
H.visible_message(s, "You chew on your [O.name]!")
- H.attack_log += text("\[[time_stamp()]\] [s] ([H.ckey])")
- log_attack("[s] ([H.ckey])")
+ add_attack_logs(H,H,"chewed own [O.name]")
if(O.take_damage(3,0,1,1,"teeth marks"))
H:UpdateDamageIcon()
@@ -210,6 +220,12 @@ var/last_chew = 0
breakouttime = 30
cuff_sound = 'sound/weapons/towelwipe.ogg' //Is there anything this sound can't do?
+/obj/item/weapon/handcuffs/legcuffs/get_worn_icon_state(var/slot_name)
+ if(slot_name == slot_legcuffed_str)
+ return "legcuff1"
+
+ return ..()
+
/obj/item/weapon/handcuffs/legcuffs/bola/can_place(var/mob/target, var/mob/user)
if(user) //A ranged legcuff, until proper implementation as items it remains a projectile-only thing.
return 1
@@ -283,9 +299,7 @@ var/last_chew = 0
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
return 0
- H.attack_log += text("\[[time_stamp()]\] Has been legcuffed (attempt) by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Attempted to legcuff [H.name] ([H.ckey])")
- msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]")
+ add_attack_logs(user,H,"Legcuffed (attempt)")
feedback_add_details("legcuffs","H")
user.setClickCooldown(user.get_attack_speed(src))
@@ -303,3 +317,11 @@ var/last_chew = 0
target.legcuffed = lcuffs
target.update_inv_legcuffed()
return 1
+
+/obj/item/weapon/handcuffs/legcuffs/equipped(var/mob/living/user,var/slot)
+ . = ..()
+ if(slot == slot_legcuffed)
+ if(user.m_intent != "walk")
+ user.m_intent = "walk"
+ if(user.hud_used && user.hud_used.move_intent)
+ user.hud_used.move_intent.icon_state = "walking"
diff --git a/code/game/objects/items/weapons/id cards/cards.dm b/code/game/objects/items/weapons/id cards/cards.dm
index b5654dade7..d0b2534463 100644
--- a/code/game/objects/items/weapons/id cards/cards.dm
+++ b/code/game/objects/items/weapons/id cards/cards.dm
@@ -46,7 +46,6 @@
name = "\proper the coordinates to clown planet"
icon_state = "data"
item_state = "card-id"
- layer = 3
level = 2
desc = "This card contains coordinates to the fabled Clown Planet. Handle with care."
function = "teleporter"
diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm
index 0e80dfa16b..314320ffe7 100644
--- a/code/game/objects/items/weapons/id cards/station_ids.dm
+++ b/code/game/objects/items/weapons/id cards/station_ids.dm
@@ -5,7 +5,7 @@
item_state = "card-id"
sprite_sheets = list(
- "Teshari" = 'icons/mob/species/seromi/id.dmi'
+ SPECIES_TESHARI = 'icons/mob/species/seromi/id.dmi'
)
var/access = list()
@@ -55,8 +55,8 @@
name = "[src.registered_name]'s ID Card ([src.assignment])"
/obj/item/weapon/card/id/proc/set_id_photo(var/mob/M)
- front = getFlatIcon(M, SOUTH, always_use_defdir = 1)
- side = getFlatIcon(M, WEST, always_use_defdir = 1)
+ front = getFlatIcon(M, SOUTH)
+ side = getFlatIcon(M, WEST)
/mob/proc/set_id_info(var/obj/item/weapon/card/id/id_card)
id_card.age = 0
@@ -112,6 +112,12 @@
usr << "The fingerprint hash on the card is [fingerprint_hash]."
return
+/obj/item/weapon/card/id/get_worn_icon_state(var/slot_name)
+ if(slot_name == slot_wear_id_str)
+ return "id" //Legacy, just how it is. There's only one sprite.
+
+ return ..()
+
/obj/item/weapon/card/id/initialize()
. = ..()
var/datum/job/J = job_master.GetJob(rank)
@@ -147,7 +153,7 @@
job_access_type = /datum/job/captain
/obj/item/weapon/card/id/gold/captain/spare
- name = "colony director's spare ID"
+ name = "\improper Colony Director's spare ID"
desc = "The spare ID of the High Lord himself."
registered_name = "Colony Director"
job_access_type = /datum/job/captain
@@ -410,4 +416,4 @@
desc = "An identification card of some sort. It does not look like it is issued by NT."
icon_state = "permit"
primary_color = rgb(142,94,0)
- secondary_color = rgb(191,159,95)
\ No newline at end of file
+ secondary_color = rgb(191,159,95)
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 1d515e863b..3e656b844b 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -52,7 +52,9 @@
/obj/item/weapon/implant/Destroy()
if(part)
part.implants.Remove(src)
+ listening_objects.Remove(src)
part = null
+ imp_in = null
return ..()
/obj/item/weapon/implant/attackby(obj/item/I, mob/user)
@@ -69,7 +71,7 @@
/obj/item/weapon/implant/tracking
name = "tracking implant"
- desc = "Track with this."
+ desc = "An implant normally given to dangerous criminals. Allows security to track your location."
var/id = 1
var/degrade_time = 10 MINUTES //How long before the implant stops working outside of a living body.
@@ -82,7 +84,6 @@
/obj/item/weapon/implant/tracking/implanted(var/mob/source)
processing_objects.Add(src)
- listening_objects |= src
return 1
/obj/item/weapon/implant/tracking/Destroy()
@@ -451,6 +452,7 @@ the implant may become unstable and either pre-maturely inject the subject or si
/obj/item/weapon/implant/death_alarm
name = "death alarm implant"
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
+ origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 2, TECH_DATA = 1)
var/mobname = "Will Robinson"
/obj/item/weapon/implant/death_alarm/get_data()
@@ -534,6 +536,7 @@ the implant may become unstable and either pre-maturely inject the subject or si
icon_state = "implant_evil"
var/activation_emote = "sigh"
var/obj/item/scanned = null
+ origin_tech = list(TECH_MATERIAL = 4, TECH_BIO = 2, TECH_ILLEGAL = 2)
/obj/item/weapon/implant/compressed/get_data()
var/dat = {"
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 87a76305c6..8052b19de6 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -54,7 +54,7 @@
if(user && M && (get_turf(M) == T1) && src && src.imp)
M.visible_message("[M] has been implanted by [user].")
- admin_attack_log(user, M, "Implanted using \the [src.name] ([src.imp.name])", "Implanted with \the [src.name] ([src.imp.name])", "used an implanter, [src.name] ([src.imp.name]), on")
+ add_attack_logs(user,M,"Implanted with [imp.name] using [name]")
if(src.imp.implanted(M))
src.imp.loc = M
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index 97cf8b33db..87bfb0454d 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -100,7 +100,7 @@
user.put_in_hands(S)
else
visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
- if(do_after(user, 2000))
+ if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
del(src)
user.put_in_hands(S)
@@ -108,6 +108,6 @@
/obj/item/weapon/material/snow/snowball/reinforced
name = "snowball"
desc = "A well-formed and fun snowball. It looks kind of dangerous."
- icon_state = "snowball-reinf"
+ //icon_state = "reinf-snowball"
force_divisor = 0.20
- thrown_force_divisor = 0.25
\ No newline at end of file
+ thrown_force_divisor = 0.25
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index a7f6565a2d..81f233cdec 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -14,3 +14,77 @@
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message(span("danger", "\The [user] [T.is] strangling [T.himself] with \the [src]! It looks like [T.he] [T.is] trying to commit suicide."), span("danger", "You start to strangle yourself with \the [src]!"), span("danger", "You hear the sound of someone choking!"))
return (OXYLOSS)
+
+/obj/item/weapon/melee/umbrella
+ name = "umbrella"
+ desc = "To keep the rain off you. Use with caution on windy days."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "umbrella_closed"
+ addblends = "umbrella_closed_a"
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+ force = 5
+ throwforce = 5
+ w_class = ITEMSIZE_NORMAL
+ var/open = FALSE
+
+/obj/item/weapon/melee/umbrella/New()
+ ..()
+ update_icon()
+
+/obj/item/weapon/melee/umbrella/attack_self()
+ src.toggle_umbrella()
+
+/obj/item/weapon/melee/umbrella/proc/toggle_umbrella()
+ open = !open
+ icon_state = "umbrella_[open ? "open" : "closed"]"
+ addblends = icon_state + "_a"
+ item_state = icon_state
+ update_icon()
+ if(ishuman(src.loc))
+ var/mob/living/carbon/human/H = src.loc
+ H.update_inv_l_hand(0)
+ H.update_inv_r_hand()
+ ..()
+
+// Randomizes color
+/obj/item/weapon/melee/umbrella/random/New()
+ color = "#"+get_random_colour()
+ ..()
+
+/obj/item/weapon/melee/cursedblade
+ name = "crystal blade"
+ desc = "The red crystal blade's polished surface glints in the light, giving off a faint glow."
+ icon_state = "soulblade"
+ slot_flags = SLOT_BELT | SLOT_BACK
+ force = 30
+ throwforce = 10
+ w_class = ITEMSIZE_NORMAL
+ sharp = 1
+ edge = 1
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ can_speak = 1
+ var/list/voice_mobs = list() //The curse of the sword is that it has someone trapped inside.
+
+
+/obj/item/weapon/melee/cursedblade/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+ if(default_parry_check(user, attacker, damage_source) && prob(50))
+ user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+ playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
+ return 1
+ return 0
+
+/obj/item/weapon/melee/cursedblade/proc/ghost_inhabit(var/mob/candidate)
+ if(!isobserver(candidate))
+ return
+ //Handle moving the ghost into the new shell.
+ announce_ghost_joinleave(candidate, 0, "They are occupying a cursed sword now.")
+ var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
+ new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
+ new_voice.mind = candidate.mind //Transfer the mind, if any.
+ new_voice.ckey = candidate.ckey //Finally, bring the client over.
+ new_voice.name = "cursed sword" //Cursed swords shouldn't be known characters.
+ new_voice.real_name = "cursed sword"
+ voice_mobs.Add(new_voice)
+ listening_objects |= src
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index a355be251a..43183d45f4 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -17,9 +17,9 @@
var/turf/T = get_turf(src)
if(!T)
return
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in T
- if(airlock)
- afterattack(airlock, null, TRUE)
+ var/obj/machinery/door/door = locate(/obj/machinery/door) in T
+ if((door == /obj/machinery/door/airlock) || (door == /obj/machinery/door/firedoor))
+ afterattack(door, null, TRUE)
return INITIALIZE_HINT_QDEL
@@ -30,7 +30,7 @@ var/list/tape_roll_applications = list()
name = "tape"
icon = 'icons/policetape.dmi'
anchored = 1
- layer = 3.2
+ layer = WINDOW_LAYER
var/lifted = 0
var/crumpled = 0
var/tape_dir = 0
@@ -250,14 +250,14 @@ var/list/tape_roll_applications = list()
if(!proximity)
return
- if (istype(A, /obj/machinery/door/airlock))
+ if (istype(A, /obj/machinery/door))
var/turf/T = get_turf(A)
if(locate(/obj/item/tape, A.loc))
user << "There's already tape over that door!"
else
var/obj/item/tape/P = new tape_type(T)
P.update_icon()
- P.layer = 3.2
+ P.layer = WINDOW_LAYER
user << "You finish placing \the [src]."
if (istype(A, /turf/simulated/floor) ||istype(A, /turf/unsimulated/floor))
@@ -307,10 +307,11 @@ var/list/tape_roll_applications = list()
/obj/item/tape/proc/lift(time)
lifted = 1
- layer = 8
+ plane = MOB_PLANE
+ layer = ABOVE_MOB_LAYER
spawn(time)
lifted = 0
- layer = initial(layer)
+ reset_plane_and_layer()
// Returns a list of all tape objects connected to src, including itself.
/obj/item/tape/proc/gettapeline()
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index c564ebe466..cee423a627 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -8,7 +8,7 @@
icon = 'icons/obj/clothing/backpack.dmi'
icon_state = "backpack"
sprite_sheets = list(
- "Teshari" = 'icons/mob/species/seromi/back.dmi'
+ SPECIES_TESHARI = 'icons/mob/species/seromi/back.dmi'
)
w_class = ITEMSIZE_LARGE
slot_flags = SLOT_BACK
@@ -47,22 +47,18 @@
max_storage_space = ITEMSIZE_COST_NORMAL * 14 // 56
storage_cost = INVENTORY_STANDARD_SPACE + 1
- New()
- ..()
+/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/storage/backpack/holding))
+ user << "The Bluespace interfaces of the two devices conflict and malfunction."
+ qdel(W)
return
+ . = ..()
- attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/weapon/storage/backpack/holding))
- user << "The Bluespace interfaces of the two devices conflict and malfunction."
- qdel(W)
- return
- ..()
-
- //Please don't clutter the parent storage item with stupid hacks.
- can_be_inserted(obj/item/W as obj, stop_messages = 0)
- if(istype(W, /obj/item/weapon/storage/backpack/holding))
- return 1
- return ..()
+//Please don't clutter the parent storage item with stupid hacks.
+/obj/item/weapon/storage/backpack/holding/can_be_inserted(obj/item/W as obj, stop_messages = 0)
+ if(istype(W, /obj/item/weapon/storage/backpack/holding))
+ return 1
+ return ..()
/obj/item/weapon/storage/backpack/santabag
name = "\improper Santa's gift bag"
@@ -142,18 +138,18 @@
/obj/item/weapon/storage/backpack/dufflebag/syndie
name = "black dufflebag"
- desc = "A large dufflebag for holding extra tactical supplies."
+ desc = "A large dufflebag for holding extra tactical supplies. This one appears to be made out of lighter material than usual."
icon_state = "duffle_syndie"
slowdown = 0
/obj/item/weapon/storage/backpack/dufflebag/syndie/med
name = "medical dufflebag"
- desc = "A large dufflebag for holding extra tactical medical supplies."
+ desc = "A large dufflebag for holding extra tactical medical supplies. This one appears to be made out of lighter material than usual."
icon_state = "duffle_syndiemed"
/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo
name = "ammunition dufflebag"
- desc = "A large dufflebag for holding extra weapons ammunition and supplies."
+ desc = "A large dufflebag for holding extra weapons ammunition and supplies. This one appears to be made out of lighter material than usual."
icon_state = "duffle_syndieammo"
/obj/item/weapon/storage/backpack/dufflebag/captain
@@ -197,9 +193,7 @@
item_state_slots = list(slot_r_hand_str = "briefcase", slot_l_hand_str = "briefcase")
/obj/item/weapon/storage/backpack/satchel/withwallet
- New()
- ..()
- new /obj/item/weapon/storage/wallet/random( src )
+ starts_with = list(/obj/item/weapon/storage/wallet/random)
/obj/item/weapon/storage/backpack/satchel/norm
name = "satchel"
@@ -423,4 +417,4 @@
else
H.visible_message("\The [src] decides not to unpack \the [src]!", \
"You decide not to unpack \the [src]!")
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index 01ca1c7796..5b20553430 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -68,6 +68,9 @@
// -----------------------------
// Mining Satchel
// -----------------------------
+/*
+ * Mechoid - Orebags are the most common quick-gathering thing, and also have tons of lag associated with it. Their checks are going to be hyper-simplified due to this, and their INCREDIBLY singular target contents.
+ */
/obj/item/weapon/storage/bag/ore
name = "mining satchel"
@@ -79,7 +82,80 @@
max_storage_space = ITEMSIZE_COST_NORMAL * 25
max_w_class = ITEMSIZE_NORMAL
can_hold = list(/obj/item/weapon/ore)
+ var/stored_ore = list()
+ var/last_update = 0
+/obj/item/weapon/storage/bag/ore/remove_from_storage(obj/item/W as obj, atom/new_location)
+ if(!istype(W)) return 0
+
+ if(new_location)
+ if(ismob(loc))
+ W.dropped(usr)
+ if(ismob(new_location))
+ W.hud_layerise()
+ else
+ W.reset_plane_and_layer()
+ W.forceMove(new_location)
+ else
+ W.forceMove(get_turf(src))
+
+ W.on_exit_storage(src)
+ update_icon()
+ return 1
+
+/obj/item/weapon/storage/bag/ore/gather_all(turf/T as turf, mob/user as mob, var/silent = 0)
+ var/success = 0
+ var/failure = 0
+ for(var/obj/item/weapon/ore/I in T) //Only ever grabs ores. Doesn't do any extraneous checks, as all ore is the same size. Tons of checks means it causes hanging for up to three seconds.
+ if(contents.len >= max_storage_space)
+ failure = 1
+ break
+ I.forceMove(src)
+ success = 1
+ if(success && !failure && !silent)
+ to_chat(user, "You put everything in [src].")
+ else if(success && (!silent || (silent && contents.len >= max_storage_space)))
+ to_chat(user, "You fill the [src].")
+ else if(!silent)
+ to_chat(user, "You fail to pick anything up with \the [src].")
+
+/obj/item/weapon/storage/bag/ore/examine(mob/user)
+ ..()
+
+ if(!Adjacent(user)) //Can only check the contents of ore bags if you can physically reach them.
+ return
+
+ if(istype(user, /mob/living))
+ add_fingerprint(user)
+
+ if(!contents.len)
+ to_chat(user, "It is empty.")
+ return
+
+ if(world.time > last_update + 10)
+ update_ore_count()
+ last_update = world.time
+
+ to_chat(user, "It holds:")
+ for(var/ore in stored_ore)
+ to_chat(user, "- [stored_ore[ore]] [ore]")
+ return
+
+/obj/item/weapon/storage/bag/ore/open(mob/user as mob) //No opening it for the weird UI of having shit-tons of ore inside it.
+ if(world.time > last_update + 10)
+ update_ore_count()
+ last_update = world.time
+ examine(user)
+
+/obj/item/weapon/storage/bag/ore/proc/update_ore_count() //Stolen from ore boxes.
+
+ stored_ore = list()
+
+ for(var/obj/item/weapon/ore/O in contents)
+ if(stored_ore[O.name])
+ stored_ore[O.name]++
+ else
+ stored_ore[O.name] = 1
// -----------------------------
// Plant bag
@@ -112,121 +188,116 @@
storage_slots = 7
allow_quick_empty = 1 // this function is superceded
- New()
- ..()
- //verbs -= /obj/item/weapon/storage/verb/quick_empty
- //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty
- can_be_inserted(obj/item/W as obj, stop_messages = 0)
- if(!istype(W,/obj/item/stack/material))
- if(!stop_messages)
- usr << "The snatcher does not accept [W]."
- return 0
- var/current = 0
- for(var/obj/item/stack/material/S in contents)
- current += S.amount
- if(capacity == current)//If it's full, you're done
- if(!stop_messages)
- usr << "The snatcher is full."
- return 0
- return 1
+/obj/item/weapon/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W as obj, stop_messages = 0)
+ if(!istype(W,/obj/item/stack/material))
+ if(!stop_messages)
+ usr << "The snatcher does not accept [W]."
+ return 0
+ var/current = 0
+ for(var/obj/item/stack/material/S in contents)
+ current += S.amount
+ if(capacity == current)//If it's full, you're done
+ if(!stop_messages)
+ usr << "The snatcher is full."
+ return 0
+ return 1
// Modified handle_item_insertion. Would prefer not to, but...
- handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
- var/obj/item/stack/material/S = W
- if(!istype(S)) return 0
+/obj/item/weapon/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
+ var/obj/item/stack/material/S = W
+ if(!istype(S)) return 0
- var/amount
- var/inserted = 0
- var/current = 0
- for(var/obj/item/stack/material/S2 in contents)
- current += S2.amount
- if(capacity < current + S.amount)//If the stack will fill it up
- amount = capacity - current
+ var/amount
+ var/inserted = 0
+ var/current = 0
+ for(var/obj/item/stack/material/S2 in contents)
+ current += S2.amount
+ if(capacity < current + S.amount)//If the stack will fill it up
+ amount = capacity - current
+ else
+ amount = S.amount
+
+ for(var/obj/item/stack/material/sheet in contents)
+ if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
+ sheet.amount += amount // they should only be removed through procs in this file, which split them up.
+ S.amount -= amount
+ inserted = 1
+ break
+
+ if(!inserted || !S.amount)
+ usr.remove_from_mob(S)
+ usr.update_icons() //update our overlays
+ if (usr.client && usr.s_active != src)
+ usr.client.screen -= S
+ S.dropped(usr)
+ if(!S.amount)
+ qdel(S)
else
- amount = S.amount
+ S.loc = src
- for(var/obj/item/stack/material/sheet in contents)
- if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
- sheet.amount += amount // they should only be removed through procs in this file, which split them up.
- S.amount -= amount
- inserted = 1
- break
-
- if(!inserted || !S.amount)
- usr.remove_from_mob(S)
- usr.update_icons() //update our overlays
- if (usr.client && usr.s_active != src)
- usr.client.screen -= S
- S.dropped(usr)
- if(!S.amount)
- qdel(S)
- else
- S.loc = src
-
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
- return 1
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
+ return 1
// Sets up numbered display to show the stack size of each stored mineral
// NOTE: numbered display is turned off currently because it's broken
- orient2hud(mob/user as mob)
- var/adjusted_contents = contents.len
+/obj/item/weapon/storage/bag/sheetsnatcher/orient2hud(mob/user as mob)
+ var/adjusted_contents = contents.len
- //Numbered contents display
- var/list/datum/numbered_display/numbered_contents
- if(display_contents_with_number)
- numbered_contents = list()
- adjusted_contents = 0
- for(var/obj/item/stack/material/I in contents)
- adjusted_contents++
- var/datum/numbered_display/D = new/datum/numbered_display(I)
- D.number = I.amount
- numbered_contents.Add( D )
-
- var/row_num = 0
- var/col_count = min(7,storage_slots) -1
- if (adjusted_contents > 7)
- row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
- src.slot_orient_objs(row_num, col_count, numbered_contents)
- return
+ //Numbered contents display
+ var/list/datum/numbered_display/numbered_contents
+ if(display_contents_with_number)
+ numbered_contents = list()
+ adjusted_contents = 0
+ for(var/obj/item/stack/material/I in contents)
+ adjusted_contents++
+ var/datum/numbered_display/D = new/datum/numbered_display(I)
+ D.number = I.amount
+ numbered_contents.Add( D )
+ var/row_num = 0
+ var/col_count = min(7,storage_slots) -1
+ if (adjusted_contents > 7)
+ row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width.
+ src.slot_orient_objs(row_num, col_count, numbered_contents)
+ return
// Modified quick_empty verb drops appropriate sized stacks
- quick_empty()
- var/location = get_turf(src)
- for(var/obj/item/stack/material/S in contents)
- while(S.amount)
- var/obj/item/stack/material/N = new S.type(location)
- var/stacksize = min(S.amount,N.max_amount)
- N.amount = stacksize
- S.amount -= stacksize
- if(!S.amount)
- qdel(S) // todo: there's probably something missing here
- orient2hud(usr)
- if(usr.s_active)
- usr.s_active.show_to(usr)
- update_icon()
+/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty()
+ var/location = get_turf(src)
+ for(var/obj/item/stack/material/S in contents)
+ while(S.amount)
+ var/obj/item/stack/material/N = new S.type(location)
+ var/stacksize = min(S.amount,N.max_amount)
+ N.amount = stacksize
+ S.amount -= stacksize
+ if(!S.amount)
+ qdel(S) // todo: there's probably something missing here
+ orient2hud(usr)
+ if(usr.s_active)
+ usr.s_active.show_to(usr)
+ update_icon()
// Instead of removing
- remove_from_storage(obj/item/W as obj, atom/new_location)
- var/obj/item/stack/material/S = W
- if(!istype(S)) return 0
+/obj/item/weapon/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W as obj, atom/new_location)
+ var/obj/item/stack/material/S = W
+ if(!istype(S)) return 0
- //I would prefer to drop a new stack, but the item/attack_hand code
- // that calls this can't recieve a different object than you clicked on.
- //Therefore, make a new stack internally that has the remainder.
- // -Sayu
+ //I would prefer to drop a new stack, but the item/attack_hand code
+ // that calls this can't recieve a different object than you clicked on.
+ //Therefore, make a new stack internally that has the remainder.
+ // -Sayu
- if(S.amount > S.max_amount)
- var/obj/item/stack/material/temp = new S.type(src)
- temp.amount = S.amount - S.max_amount
- S.amount = S.max_amount
+ if(S.amount > S.max_amount)
+ var/obj/item/stack/material/temp = new S.type(src)
+ temp.amount = S.amount - S.max_amount
+ S.amount = S.max_amount
- return ..(S,new_location)
+ return ..(S,new_location)
// -----------------------------
// Sheet Snatcher (Cyborg)
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 9e98fe58ec..e4482932b1 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -8,7 +8,7 @@
max_w_class = ITEMSIZE_NORMAL
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
- sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/belt.dmi')
+ sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/belt.dmi')
var/show_above_suit = 0
@@ -22,6 +22,16 @@
show_above_suit = !show_above_suit
update_icon()
+//Some belts have sprites to show icons
+/obj/item/weapon/storage/belt/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0)
+ var/image/standing = ..()
+ if(!inhands && contents.len)
+ for(var/obj/item/i in contents)
+ var/i_state = i.item_state
+ if(!i_state) i_state = i.icon_state
+ standing.add_overlay(image(icon = INV_BELT_DEF_ICON, icon_state = i_state))
+ return standing
+
/obj/item/weapon/storage/update_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -59,23 +69,25 @@
/obj/item/device/integrated_electronics/wirer,
)
-/obj/item/weapon/storage/belt/utility/full/New()
- ..()
- new /obj/item/weapon/screwdriver(src)
- new /obj/item/weapon/wrench(src)
- new /obj/item/weapon/weldingtool(src)
- new /obj/item/weapon/crowbar(src)
- new /obj/item/weapon/wirecutters(src)
- new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange"))
+/obj/item/weapon/storage/belt/utility/full
+ starts_with = list(
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/wrench,
+ /obj/item/weapon/weldingtool,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/wirecutters,
+ /obj/item/stack/cable_coil/random_belt
+ )
-/obj/item/weapon/storage/belt/utility/atmostech/New()
- ..()
- new /obj/item/weapon/screwdriver(src)
- new /obj/item/weapon/wrench(src)
- new /obj/item/weapon/weldingtool(src)
- new /obj/item/weapon/crowbar(src)
- new /obj/item/weapon/wirecutters(src)
- new /obj/item/device/t_scanner(src)
+/obj/item/weapon/storage/belt/utility/atmostech
+ starts_with = list(
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/wrench,
+ /obj/item/weapon/weldingtool,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/wirecutters,
+ /obj/item/device/t_scanner
+ )
/obj/item/weapon/storage/belt/utility/chief
name = "chief engineer's toolbelt"
@@ -83,15 +95,16 @@
icon_state = "utilitybelt_ce"
item_state = "utility_ce"
-/obj/item/weapon/storage/belt/utility/chief/full/New()
- ..()
- new /obj/item/weapon/screwdriver/power(src)
- new /obj/item/weapon/crowbar/power(src)
- new /obj/item/weapon/weldingtool/experimental(src)
- new /obj/item/device/multitool(src)
- new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange"))
- new /obj/item/weapon/extinguisher/mini(src)
- new /obj/item/device/analyzer(src)
+/obj/item/weapon/storage/belt/utility/chief/full
+ starts_with = list(
+ /obj/item/weapon/screwdriver/power,
+ /obj/item/weapon/crowbar/power,
+ /obj/item/weapon/weldingtool/experimental,
+ /obj/item/device/multitool,
+ /obj/item/stack/cable_coil/random_belt,
+ /obj/item/weapon/extinguisher/mini,
+ /obj/item/device/analyzer
+ )
/obj/item/weapon/storage/belt/medical
name = "medical belt"
@@ -121,7 +134,8 @@
/obj/item/weapon/crowbar,
/obj/item/device/flashlight,
/obj/item/weapon/cell/device,
- /obj/item/weapon/extinguisher/mini
+ /obj/item/weapon/extinguisher/mini,
+ /obj/item/weapon/storage/quickdraw/syringe_case
)
/obj/item/weapon/storage/belt/medical/emt
@@ -216,14 +230,8 @@
/obj/item/device/soulstone
)
-/obj/item/weapon/storage/belt/soulstone/full/New()
- ..()
- new /obj/item/device/soulstone(src)
- new /obj/item/device/soulstone(src)
- new /obj/item/device/soulstone(src)
- new /obj/item/device/soulstone(src)
- new /obj/item/device/soulstone(src)
- new /obj/item/device/soulstone(src)
+/obj/item/weapon/storage/belt/soulstone/full
+ starts_with = list(/obj/item/device/soulstone = 6)
/obj/item/weapon/storage/belt/utility/alien
name = "alien belt"
@@ -232,15 +240,16 @@
icon_state = "belt"
item_state = "security"
-/obj/item/weapon/storage/belt/utility/alien/full/New()
- ..()
- new /obj/item/weapon/screwdriver/alien(src)
- new /obj/item/weapon/wrench/alien(src)
- new /obj/item/weapon/weldingtool/alien(src)
- new /obj/item/weapon/crowbar/alien(src)
- new /obj/item/weapon/wirecutters/alien(src)
- new /obj/item/device/multitool/alien(src)
- new /obj/item/stack/cable_coil/alien(src)
+/obj/item/weapon/storage/belt/utility/alien/full
+ starts_with = list(
+ /obj/item/weapon/screwdriver/alien,
+ /obj/item/weapon/wrench/alien,
+ /obj/item/weapon/weldingtool/alien,
+ /obj/item/weapon/crowbar/alien,
+ /obj/item/weapon/wirecutters/alien,
+ /obj/item/device/multitool/alien,
+ /obj/item/stack/cable_coil/alien
+ )
/obj/item/weapon/storage/belt/medical/alien
name = "alien belt"
@@ -277,16 +286,17 @@
/obj/item/weapon/surgical
)
-/obj/item/weapon/storage/belt/medical/alien/New()
- ..()
- new /obj/item/weapon/surgical/scalpel/alien(src)
- new /obj/item/weapon/surgical/hemostat/alien(src)
- new /obj/item/weapon/surgical/retractor/alien(src)
- new /obj/item/weapon/surgical/circular_saw/alien(src)
- new /obj/item/weapon/surgical/FixOVein/alien(src)
- new /obj/item/weapon/surgical/bone_clamp/alien(src)
- new /obj/item/weapon/surgical/cautery/alien(src)
- new /obj/item/weapon/surgical/surgicaldrill/alien(src)
+/obj/item/weapon/storage/belt/medical/alien
+ starts_with = list(
+ /obj/item/weapon/surgical/scalpel/alien,
+ /obj/item/weapon/surgical/hemostat/alien,
+ /obj/item/weapon/surgical/retractor/alien,
+ /obj/item/weapon/surgical/circular_saw/alien,
+ /obj/item/weapon/surgical/FixOVein/alien,
+ /obj/item/weapon/surgical/bone_clamp/alien,
+ /obj/item/weapon/surgical/cautery/alien,
+ /obj/item/weapon/surgical/surgicaldrill/alien
+ )
/obj/item/weapon/storage/belt/champion
name = "championship belt"
@@ -363,7 +373,9 @@
/obj/item/weapon/storage/excavation,
/obj/item/weapon/anobattery,
/obj/item/device/ano_scanner,
- /obj/item/weapon/pickaxe/hand
+ /obj/item/weapon/pickaxe/hand,
+ /obj/item/device/xenoarch_multi_tool,
+ /obj/item/weapon/pickaxe/excavationdrill
)
/obj/item/weapon/storage/belt/fannypack
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index 933970b335..783d8cd74a 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -14,12 +14,13 @@
icon_state ="bible"
/obj/item/weapon/storage/bible/booze/New()
- ..()
- new /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer(src)
- new /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer(src)
- new /obj/item/weapon/spacecash/c100(src)
- new /obj/item/weapon/spacecash/c100(src)
- new /obj/item/weapon/spacecash/c100(src)
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer,
+ /obj/item/weapon/spacecash/c100,
+ /obj/item/weapon/spacecash/c100,
+ /obj/item/weapon/spacecash/c100
+ )
/obj/item/weapon/storage/bible/afterattack(atom/A, mob/user as mob, proximity)
if(!proximity) return
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 31547916b1..f7e43ac718 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -23,7 +23,7 @@
name = "box"
desc = "It's just an ordinary box."
icon_state = "box"
- item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ item_state = "syringe_kit"
var/foldable = /obj/item/stack/material/cardboard // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
max_w_class = ITEMSIZE_SMALL
max_storage_space = INVENTORY_BOX_SPACE
@@ -52,412 +52,278 @@
new foldable(get_turf(src))
qdel(src)
-/obj/item/weapon/storage/box/survival/New()
- ..()
- new /obj/item/clothing/mask/breath(src)
- new /obj/item/weapon/tank/emergency/oxygen(src)
+/obj/item/weapon/storage/box/survival
+ name = "emergency supply box"
+ desc = "A survival box issued to crew members for use in emergency situations."
+ starts_with = list(
+ /obj/item/clothing/mask/breath
+ )
-/obj/item/weapon/storage/box/vox/New()
- ..()
- new /obj/item/clothing/mask/breath(src)
- new /obj/item/weapon/tank/emergency/phoron(src)
+/obj/item/weapon/storage/box/survival/synth
+ name = "synthetic supply box"
+ desc = "A survival box issued to synthetic crew members for use in emergency situations."
+ starts_with = list()
-/obj/item/weapon/storage/box/engineer/New()
- ..()
- new /obj/item/clothing/mask/breath(src)
- new /obj/item/weapon/tank/emergency/oxygen/engi(src)
+/obj/item/weapon/storage/box/survival/comp
+ name = "emergency supply box"
+ desc = "A comprehensive survival box issued to crew members for use in emergency situations. Contains additional supplies."
+ icon_state = "survival"
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ /obj/item/stack/medical/bruise_pack,
+ /obj/item/device/flashlight/glowstick,
+ /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar,
+ /obj/item/clothing/mask/breath
+ )
/obj/item/weapon/storage/box/gloves
name = "box of latex gloves"
desc = "Contains white gloves."
icon_state = "latex"
-
-/obj/item/weapon/storage/box/gloves/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/clothing/gloves/sterile/latex(src)
+ starts_with = list(/obj/item/clothing/gloves/sterile/latex = 7)
/obj/item/weapon/storage/box/masks
name = "box of sterile masks"
desc = "This box contains masks of sterility."
icon_state = "sterile"
-
-/obj/item/weapon/storage/box/masks/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/clothing/mask/surgical(src)
+ starts_with = list(/obj/item/clothing/mask/surgical = 7)
/obj/item/weapon/storage/box/syringes
name = "box of syringes"
desc = "A box full of syringes."
icon_state = "syringe"
-
-/obj/item/weapon/storage/box/syringes/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/syringe(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/syringe = 7)
/obj/item/weapon/storage/box/syringegun
name = "box of syringe gun cartridges"
desc = "A box full of compressed gas cartridges."
icon_state = "syringe"
-
-/obj/item/weapon/storage/box/syringegun/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/syringe_cartridge(src)
+ starts_with = list(/obj/item/weapon/syringe_cartridge = 7)
/obj/item/weapon/storage/box/beakers
name = "box of beakers"
icon_state = "beaker"
-
-/obj/item/weapon/storage/box/beakers/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/glass/beaker(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/glass/beaker = 7)
/obj/item/weapon/storage/box/injectors
name = "box of DNA injectors"
desc = "This box contains injectors it seems."
-
-/obj/item/weapon/storage/box/injectors/New()
- ..()
- for(var/i = 1 to 3)
- new /obj/item/weapon/dnainjector/h2m(src)
- for(var/i = 1 to 3)
- new /obj/item/weapon/dnainjector/m2h(src)
+ starts_with = list(
+ /obj/item/weapon/dnainjector/h2m = 3,
+ /obj/item/weapon/dnainjector/m2h = 3
+ )
/obj/item/weapon/storage/box/blanks
name = "box of blank shells"
desc = "It has a picture of a gun and several warning symbols on the front."
icon_state = "blankshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/blank = 8)
-/obj/item/weapon/storage/box/blanks/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/blank(src)
-
-/obj/item/weapon/storage/box/blanks/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/blank(src)
+/obj/item/weapon/storage/box/blanks/large
+ starts_with = list(/obj/item/ammo_casing/a12g/blank = 16)
/obj/item/weapon/storage/box/beanbags
name = "box of beanbag shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "beanshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
-
-/obj/item/weapon/storage/box/beanbags/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/beanbag(src)
+ starts_with = list(/obj/item/ammo_casing/a12g/beanbag = 8)
/obj/item/weapon/storage/box/beanbags/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/beanbag(src)
+ starts_with = list(/obj/item/ammo_casing/a12g/beanbag = 16)
/obj/item/weapon/storage/box/shotgunammo
name = "box of shotgun slugs"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "lethalshellshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g = 8)
-/obj/item/weapon/storage/box/shotgunammo/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g(src)
-
-/obj/item/weapon/storage/box/shotgunammo/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g(src)
+/obj/item/weapon/storage/box/shotgunammo/large
+ starts_with = list(/obj/item/ammo_casing/a12g = 16)
/obj/item/weapon/storage/box/shotgunshells
name = "box of shotgun shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "lethalslug_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/pellet = 8)
-/obj/item/weapon/storage/box/shotgunshells/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/pellet(src)
-
-/obj/item/weapon/storage/box/shotgunshells/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/pellet(src)
+/obj/item/weapon/storage/box/shotgunshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/pellet = 16)
/obj/item/weapon/storage/box/flashshells
name = "box of illumination shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "illumshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/flash = 8)
-/obj/item/weapon/storage/box/flashshells/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/flash(src)
-
-/obj/item/weapon/storage/box/flashshells/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/flash(src)
+/obj/item/weapon/storage/box/flashshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/flash = 16)
/obj/item/weapon/storage/box/stunshells
name = "box of stun shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "stunshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/stunshell = 8)
-/obj/item/weapon/storage/box/stunshells/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/stunshell(src)
-
-/obj/item/weapon/storage/box/stunshells/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/stunshell(src)
+/obj/item/weapon/storage/box/stunshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/stunshell = 16)
/obj/item/weapon/storage/box/practiceshells
name = "box of practice shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "blankshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/practice = 8)
-/obj/item/weapon/storage/box/practiceshells/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/practice(src)
-
-/obj/item/weapon/storage/box/practiceshells/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/practice(src)
+/obj/item/weapon/storage/box/practiceshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/practice = 16)
/obj/item/weapon/storage/box/empshells
name = "box of emp shells"
desc = "It has a picture of a gun and several warning symbols on the front."
icon_state = "empshot_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/emp = 8)
-/obj/item/weapon/storage/box/empshells/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/emp(src)
-
-/obj/item/weapon/storage/box/empshells/large/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/ammo_casing/a12g/emp(src)
+/obj/item/weapon/storage/box/empshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/emp = 16)
/obj/item/weapon/storage/box/sniperammo
name = "box of 14.5mm shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
-
-/obj/item/weapon/storage/box/sniperammo/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/ammo_casing/a145(src)
+ starts_with = list(/obj/item/ammo_casing/a145 = 7)
/obj/item/weapon/storage/box/flashbangs
name = "box of flashbangs (WARNING)"
desc = "WARNING: These devices are extremely dangerous and can cause blindness or deafness in repeated use."
icon_state = "flashbang"
-
-/obj/item/weapon/storage/box/flashbangs/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/flashbang(src)
+ starts_with = list(/obj/item/weapon/grenade/flashbang = 7)
/obj/item/weapon/storage/box/emps
name = "box of emp grenades"
desc = "A box containing 5 military grade EMP grenades.
WARNING: Do not use near unshielded electronics or biomechanical augmentations, death or permanent paralysis may occur."
icon_state = "emp"
-
-/obj/item/weapon/storage/box/emps/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/empgrenade(src)
+ starts_with = list(/obj/item/weapon/grenade/empgrenade = 7)
/obj/item/weapon/storage/box/empslite
name = "box of low yield emp grenades"
desc = "A box containing 5 low yield EMP grenades.
WARNING: Do not use near unshielded electronics or biomechanical augmentations, death or permanent paralysis may occur."
icon_state = "emp"
-
-/obj/item/weapon/storage/box/empslite/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/empgrenade/low_yield(src)
+ starts_with = list(/obj/item/weapon/grenade/empgrenade/low_yield = 7)
/obj/item/weapon/storage/box/smokes
name = "box of smoke bombs"
desc = "A box containing 7 smoke bombs."
icon_state = "flashbang"
-
-/obj/item/weapon/storage/box/smokes/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/smokebomb(src)
+ starts_with = list(/obj/item/weapon/grenade/smokebomb = 7)
/obj/item/weapon/storage/box/anti_photons
name = "box of anti-photon grenades"
desc = "A box containing 7 experimental photon disruption grenades."
icon_state = "flashbang"
-
-/obj/item/weapon/storage/box/anti_photons/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/anti_photon(src)
+ starts_with = list(/obj/item/weapon/grenade/anti_photon = 7)
/obj/item/weapon/storage/box/frags
name = "box of fragmentation grenades (WARNING)"
desc = "A box containing 7 military grade fragmentation grenades.
WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
icon_state = "frag"
-
-/obj/item/weapon/storage/box/frags/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/explosive(src)
+ starts_with = list(/obj/item/weapon/grenade/explosive = 7)
/obj/item/weapon/storage/box/frags_half_box
name = "box of fragmentation grenades (WARNING)"
desc = "A box containing 4 military grade fragmentation grenades.
WARNING: These devices are extremely dangerous and can cause limb loss or death in repeated use."
icon_state = "frag"
-
-/obj/item/weapon/storage/box/frags_half_box/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/weapon/grenade/explosive(src)
+ starts_with = list(/obj/item/weapon/grenade/explosive = 4)
/obj/item/weapon/storage/box/metalfoam
name = "box of metal foam grenades."
desc = "A box containing 7 metal foam grenades."
icon_state = "flashbang"
-
-/obj/item/weapon/storage/box/metalfoam/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/chem_grenade/metalfoam(src)
+ starts_with = list(/obj/item/weapon/grenade/chem_grenade/metalfoam = 7)
/obj/item/weapon/storage/box/teargas
name = "box of teargas grenades"
desc = "A box containing 7 teargas grenades."
icon_state = "flashbang"
-
-/obj/item/weapon/storage/box/teargas/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/grenade/chem_grenade/teargas(src)
+ starts_with = list(/obj/item/weapon/grenade/chem_grenade/teargas = 7)
/obj/item/weapon/storage/box/flare
name = "box of flares"
desc = "A box containing 4 flares."
-
-/obj/item/weapon/storage/box/flare/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/device/flashlight/flare(src)
+ starts_with = list(/obj/item/device/flashlight/flare = 4)
/obj/item/weapon/storage/box/trackimp
name = "boxed tracking implant kit"
desc = "Box full of scum-bag tracking utensils."
icon_state = "implant"
-
-/obj/item/weapon/storage/box/trackimp/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/weapon/implantcase/tracking(src)
- new /obj/item/weapon/implanter(src)
- new /obj/item/weapon/implantpad(src)
- new /obj/item/weapon/locator(src)
+ starts_with = list(
+ /obj/item/weapon/implantcase/tracking = 4,
+ /obj/item/weapon/implanter,
+ /obj/item/weapon/implantpad,
+ /obj/item/weapon/locator
+ )
/obj/item/weapon/storage/box/chemimp
name = "boxed chemical implant kit"
desc = "Box of stuff used to implant chemicals."
icon_state = "implant"
-
-/obj/item/weapon/storage/box/chemimp/New()
- ..()
- for(var/i = 1 to 5)
- new /obj/item/weapon/implantcase/chem(src)
- new /obj/item/weapon/implanter(src)
- new /obj/item/weapon/implantpad(src)
+ starts_with = list(
+ /obj/item/weapon/implantcase/chem = 5,
+ /obj/item/weapon/implanter,
+ /obj/item/weapon/implantpad
+ )
/obj/item/weapon/storage/box/camerabug
name = "mobile camera pod box"
desc = "A box containing some mobile camera pods."
icon_state = "pda"
-
-/obj/item/weapon/storage/box/camerabug/New()
- ..()
- for(var/i = 1 to 6)
- new /obj/item/device/camerabug(src)
- new /obj/item/device/bug_monitor(src)
+ starts_with = list(
+ /obj/item/device/camerabug = 6,
+ /obj/item/device/bug_monitor
+ )
/obj/item/weapon/storage/box/rxglasses
name = "box of prescription glasses"
desc = "This box contains nerd glasses."
icon_state = "glasses"
-
-/obj/item/weapon/storage/box/rxglasses/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/clothing/glasses/regular(src)
+ starts_with = list(/obj/item/clothing/glasses/regular = 7)
/obj/item/weapon/storage/box/cdeathalarm_kit
name = "death alarm kit"
desc = "Box of stuff used to implant death alarms."
icon_state = "implant"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
-
-/obj/item/weapon/storage/box/cdeathalarm_kit/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/implantcase/death_alarm(src)
- new /obj/item/weapon/implanter(src)
+ starts_with = list(
+ /obj/item/weapon/implantcase/death_alarm = 7,
+ /obj/item/weapon/implanter
+ )
/obj/item/weapon/storage/box/condimentbottles
name = "box of condiment bottles"
desc = "It has a large ketchup smear on it."
-
-/obj/item/weapon/storage/box/condimentbottles/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/food/condiment(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/condiment = 7)
/obj/item/weapon/storage/box/cups
name = "box of paper cups"
desc = "It has pictures of paper cups on the front."
-
-/obj/item/weapon/storage/box/cups/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/food/drinks/sillycup(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/drinks/sillycup = 7)
/obj/item/weapon/storage/box/donkpockets
name = "box of donk-pockets"
desc = "Instructions: Heat in microwave. Product will cool if not eaten within seven minutes."
icon_state = "donk_kit"
-
-/obj/item/weapon/storage/box/donkpockets/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/food/snacks/donkpocket(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket = 7)
/obj/item/weapon/storage/box/sinpockets
name = "box of sin-pockets"
desc = "Instructions: Crush bottom of package to initiate chemical heating. Wait for 20 seconds before consumption. Product will cool if not eaten within seven minutes."
icon_state = "donk_kit"
-
-/obj/item/weapon/storage/box/sinpockets/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/food/snacks/donkpocket/sinpocket(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/sinpocket = 7)
/obj/item/weapon/storage/box/monkeycubes
name = "monkey cube box"
@@ -465,88 +331,51 @@
icon = 'icons/obj/food.dmi'
icon_state = "monkeycubebox"
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube)
-
-/obj/item/weapon/storage/box/monkeycubes/New()
- ..()
- if(type == /obj/item/weapon/storage/box/monkeycubes)
- for(var/i = 1 to 4)
- new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped = 4)
/obj/item/weapon/storage/box/monkeycubes/farwacubes
name = "farwa cube box"
desc = "Drymate brand farwa cubes, shipped from Meralar. Just add water!"
-
-/obj/item/weapon/storage/box/monkeycubes/farwacubes/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube = 4)
/obj/item/weapon/storage/box/monkeycubes/stokcubes
name = "stok cube box"
desc = "Drymate brand stok cubes, shipped from Moghes. Just add water!"
-
-/obj/item/weapon/storage/box/monkeycubes/stokcubes/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube = 4)
/obj/item/weapon/storage/box/monkeycubes/neaeracubes
name = "neaera cube box"
desc = "Drymate brand neaera cubes, shipped from Jargon 4. Just add water!"
-
-/obj/item/weapon/storage/box/monkeycubes/neaeracubes/New()
- ..()
- for(var/i = 1 to 4)
- new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube = 4)
/obj/item/weapon/storage/box/ids
name = "box of spare IDs"
desc = "Has so many empty IDs."
icon_state = "id"
-
-/obj/item/weapon/storage/box/ids/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/card/id(src)
+ starts_with = list(/obj/item/weapon/card/id = 7)
/obj/item/weapon/storage/box/seccarts
name = "box of spare R.O.B.U.S.T. Cartridges"
desc = "A box full of R.O.B.U.S.T. Cartridges, used by Security."
icon_state = "pda"
-
-/obj/item/weapon/storage/box/seccarts/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/cartridge/security(src)
+ starts_with = list(/obj/item/weapon/cartridge/security = 7)
/obj/item/weapon/storage/box/handcuffs
name = "box of spare handcuffs"
desc = "A box full of handcuffs."
icon_state = "handcuff"
-
-/obj/item/weapon/storage/box/handcuffs/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/handcuffs(src)
+ starts_with = list(/obj/item/weapon/handcuffs = 7)
/obj/item/weapon/storage/box/mousetraps
name = "box of Pest-B-Gon mousetraps"
desc = "WARNING: Keep out of reach of children."
icon_state = "mousetraps"
-
-/obj/item/weapon/storage/box/mousetraps/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/device/assembly/mousetrap(src)
+ starts_with = list(/obj/item/device/assembly/mousetrap = 7)
/obj/item/weapon/storage/box/pillbottles
name = "box of pill bottles"
desc = "It has pictures of pill bottles on its front."
-
-/obj/item/weapon/storage/box/pillbottles/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/weapon/storage/pill_bottle(src)
+ starts_with = list(/obj/item/weapon/storage/pill_bottle = 7)
/obj/item/weapon/storage/box/snappops
name = "snap pop box"
@@ -554,11 +383,7 @@
icon = 'icons/obj/toy.dmi'
icon_state = "spbox"
can_hold = list(/obj/item/toy/snappop)
-
-/obj/item/weapon/storage/box/snappops/New()
- ..()
- for(var/i = 1 to 8)
- new /obj/item/toy/snappop(src)
+ starts_with = list(/obj/item/toy/snappop = 8)
/obj/item/weapon/storage/box/matches
name = "matchbox"
@@ -568,11 +393,7 @@
w_class = ITEMSIZE_TINY
slot_flags = SLOT_BELT
can_hold = list(/obj/item/weapon/flame/match)
-
-/obj/item/weapon/storage/box/matches/New()
- ..()
- for(var/i=1 to 10)
- new /obj/item/weapon/flame/match(src)
+ starts_with = list(/obj/item/weapon/flame/match = 10)
/obj/item/weapon/storage/box/matches/attackby(obj/item/weapon/flame/match/W as obj, mob/user as mob)
if(istype(W) && !W.lit && !W.burnt)
@@ -587,11 +408,7 @@
name = "box of injectors"
desc = "Contains autoinjectors."
icon_state = "syringe"
-
-/obj/item/weapon/storage/box/autoinjectors/New()
- ..()
- for (var/i = 1 to 7)
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 7)
/obj/item/weapon/storage/box/lights
name = "box of replacement bulbs"
@@ -604,30 +421,21 @@
max_storage_space = ITEMSIZE_COST_SMALL * 24 //holds 24 items of w_class 2
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
-/obj/item/weapon/storage/box/lights/bulbs/New()
- ..()
- for(var/i = 1 to 24)
- new /obj/item/weapon/light/bulb(src)
+/obj/item/weapon/storage/box/lights/bulbs
+ starts_with = list(/obj/item/weapon/light/bulb = 24)
/obj/item/weapon/storage/box/lights/tubes
name = "box of replacement tubes"
icon_state = "lighttube"
-
-/obj/item/weapon/storage/box/lights/tubes/New()
- ..()
- for(var/i = 1 to 24)
- new /obj/item/weapon/light/tube(src)
+ starts_with = list(/obj/item/weapon/light/tube = 24)
/obj/item/weapon/storage/box/lights/mixed
name = "box of replacement lights"
icon_state = "lightmixed"
-
-/obj/item/weapon/storage/box/lights/mixed/New()
- ..()
- for(var/i = 1 to 16)
- new /obj/item/weapon/light/tube(src)
- for(var/i = 1 to 8)
- new /obj/item/weapon/light/bulb(src)
+ starts_with = list(
+ /obj/item/weapon/light/tube = 16,
+ /obj/item/weapon/light/bulb = 8
+ )
/obj/item/weapon/storage/box/freezer
name = "portable freezer"
@@ -660,17 +468,9 @@
/obj/item/weapon/storage/box/ambrosia
name = "ambrosia seeds box"
desc = "Contains the seeds you need to get a little high."
-
-/obj/item/weapon/storage/box/ambrosia/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/seeds/ambrosiavulgarisseed(src)
+ starts_with = list(/obj/item/seeds/ambrosiavulgarisseed = 7)
/obj/item/weapon/storage/box/ambrosiadeus
name = "ambrosia deus seeds box"
desc = "Contains the seeds you need to get a proper healthy high."
-
-/obj/item/weapon/storage/box/ambrosiadeus/New()
- ..()
- for(var/i = 1 to 7)
- new /obj/item/seeds/ambrosiadeusseed(src)
+ starts_with = list(/obj/item/seeds/ambrosiadeusseed = 7)
diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm
index 8cc10444ef..762720e390 100644
--- a/code/game/objects/items/weapons/storage/fancy.dm
+++ b/code/game/objects/items/weapons/storage/fancy.dm
@@ -52,12 +52,7 @@
/obj/item/weapon/reagent_containers/food/snacks/egg,
/obj/item/weapon/reagent_containers/food/snacks/boiledegg
)
-
-/obj/item/weapon/storage/fancy/egg_box/New()
- ..()
- for(var/i=1 to storage_slots)
- new /obj/item/weapon/reagent_containers/food/snacks/egg(src)
- return
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/egg = 12)
/*
* Candle Box
@@ -72,12 +67,7 @@
item_state = "candlebox5"
throwforce = 2
slot_flags = SLOT_BELT
-
-/obj/item/weapon/storage/fancy/candle_box/New()
- ..()
- for(var/i=1 to 5)
- new /obj/item/weapon/flame/candle(src)
- return
+ starts_with = list(/obj/item/weapon/flame/candle = 5)
/*
* Crayon Box
@@ -93,31 +83,76 @@
can_hold = list(
/obj/item/weapon/pen/crayon
)
+ starts_with = list(
+ /obj/item/weapon/pen/crayon/red,
+ /obj/item/weapon/pen/crayon/orange,
+ /obj/item/weapon/pen/crayon/yellow,
+ /obj/item/weapon/pen/crayon/green,
+ /obj/item/weapon/pen/crayon/blue,
+ /obj/item/weapon/pen/crayon/purple
+ )
-/obj/item/weapon/storage/fancy/crayons/New()
- ..()
- new /obj/item/weapon/pen/crayon/red(src)
- new /obj/item/weapon/pen/crayon/orange(src)
- new /obj/item/weapon/pen/crayon/yellow(src)
- new /obj/item/weapon/pen/crayon/green(src)
- new /obj/item/weapon/pen/crayon/blue(src)
- new /obj/item/weapon/pen/crayon/purple(src)
+/obj/item/weapon/storage/fancy/crayons/initialize()
+ . = ..()
update_icon()
/obj/item/weapon/storage/fancy/crayons/update_icon()
- overlays = list() //resets list
- overlays += image('icons/obj/crayons.dmi',"crayonbox")
+ var/mutable_appearance/ma = new(src)
+ ma.overlays = list()
for(var/obj/item/weapon/pen/crayon/crayon in contents)
- overlays += image('icons/obj/crayons.dmi',crayon.colourName)
+ ma.overlays += image('icons/obj/crayons.dmi',crayon.colourName)
+ appearance = ma
/obj/item/weapon/storage/fancy/crayons/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/pen/crayon))
switch(W:colourName)
if("mime")
- usr << "This crayon is too sad to be contained in this box."
+ to_chat(usr,"This crayon is too sad to be contained in this box.")
return
if("rainbow")
- usr << "This crayon is too powerful to be contained in this box."
+ to_chat(usr,"This crayon is too powerful to be contained in this box.")
+ return
+ ..()
+
+/obj/item/weapon/storage/fancy/markers
+ name = "box of markers"
+ desc = "A very professional looking box of permanent markers."
+ icon = 'icons/obj/crayons.dmi'
+ icon_state = "markerbox"
+ w_class = ITEMSIZE_SMALL
+ icon_type = "marker"
+ can_hold = list(
+ /obj/item/weapon/pen/crayon/marker
+ )
+ starts_with = list(
+ /obj/item/weapon/pen/crayon/marker/black,
+ /obj/item/weapon/pen/crayon/marker/red,
+ /obj/item/weapon/pen/crayon/marker/orange,
+ /obj/item/weapon/pen/crayon/marker/yellow,
+ /obj/item/weapon/pen/crayon/marker/green,
+ /obj/item/weapon/pen/crayon/marker/blue,
+ /obj/item/weapon/pen/crayon/marker/purple
+ )
+
+/obj/item/weapon/storage/fancy/markers/initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/weapon/storage/fancy/markers/update_icon()
+ var/mutable_appearance/ma = new(src)
+ ma.overlays = list()
+ for(var/obj/item/weapon/pen/crayon/marker/marker in contents)
+ ma.overlays += image('icons/obj/crayons.dmi',"m"+marker.colourName)
+ appearance = ma
+
+/obj/item/weapon/storage/fancy/markers/attackby(obj/item/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/pen/crayon/marker))
+ switch(W:colourName)
+ if("mime")
+ to_chat(usr,"This marker is too depressing to be contained in this box.")
+ return
+ if("rainbow")
+ to_chat(usr,"This marker is too childish to be contained in this box.")
return
..()
@@ -136,13 +171,12 @@
storage_slots = 6
can_hold = list(/obj/item/clothing/mask/smokable/cigarette, /obj/item/weapon/flame/lighter)
icon_type = "cigarette"
+ starts_with = list(/obj/item/clothing/mask/smokable/cigarette = 6)
var/brand = "\improper Trans-Stellar Duty-free"
-/obj/item/weapon/storage/fancy/cigarettes/New()
- ..()
+/obj/item/weapon/storage/fancy/cigarettes/initialize()
+ . = ..()
flags |= NOREACT
- for(var/i = 1 to storage_slots)
- new /obj/item/clothing/mask/smokable/cigarette(src)
create_reagents(15 * storage_slots)//so people can inject cigarettes without opening a packet, now with being able to inject the whole one
flags |= OPENCONTAINER
if(brand)
@@ -201,10 +235,6 @@
icon_state = "Bpacket"
brand = "\improper Acme Co. cigarette"
-// New()
-// ..()
-// fill_cigarre_package(src,list("fuel" = 15))
-
// New exciting ways to kill your lungs! - Earthcrusher //
/obj/item/weapon/storage/fancy/cigarettes/luckystars
@@ -248,12 +278,11 @@
storage_slots = 7
can_hold = list(/obj/item/clothing/mask/smokable/cigarette/cigar)
icon_type = "cigar"
+ starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar = 7)
-/obj/item/weapon/storage/fancy/cigar/New()
- ..()
+/obj/item/weapon/storage/fancy/cigar/initialize()
+ . = ..()
flags |= NOREACT
- for(var/i = 1 to storage_slots)
- new /obj/item/clothing/mask/smokable/cigarette/cigar(src)
create_reagents(15 * storage_slots)
/obj/item/weapon/storage/fancy/cigar/update_icon()
@@ -261,10 +290,22 @@
return
/obj/item/weapon/storage/fancy/cigar/remove_from_storage(obj/item/W as obj, atom/new_location)
- var/obj/item/clothing/mask/smokable/cigarette/cigar/C = W
- if(!istype(C)) return
- reagents.trans_to_obj(C, (reagents.total_volume/contents.len))
- ..()
+ var/obj/item/clothing/mask/smokable/cigarette/cigar/C = W
+ if(!istype(C)) return
+ reagents.trans_to_obj(C, (reagents.total_volume/contents.len))
+ ..()
+
+/obj/item/weapon/storage/rollingpapers
+ name = "rolling paper pack"
+ desc = "A small cardboard pack containing several folded rolling papers."
+ icon_state = "paperbox"
+ icon = 'icons/obj/cigarettes.dmi'
+ w_class = ITEMSIZE_TINY
+ throwforce = 2
+ slot_flags = SLOT_BELT
+ storage_slots = 14
+ can_hold = list(/obj/item/weapon/rollingpaper)
+ starts_with = list(/obj/item/weapon/rollingpaper = 14)
/*
* Vial Box
@@ -277,12 +318,7 @@
name = "vial storage box"
storage_slots = 6
can_hold = list(/obj/item/weapon/reagent_containers/glass/beaker/vial)
-
-/obj/item/weapon/storage/fancy/vials/New()
- ..()
- for(var/i=1 to 6)
- new /obj/item/weapon/reagent_containers/glass/beaker/vial(src)
- return
+ starts_with = list(/obj/item/weapon/reagent_containers/glass/beaker/vial = 6)
/obj/item/weapon/storage/lockbox/vials
name = "secure vial storage box"
@@ -296,8 +332,8 @@
storage_slots = 6
req_access = list(access_virology)
-/obj/item/weapon/storage/lockbox/vials/New()
- ..()
+/obj/item/weapon/storage/lockbox/vials/initialize()
+ . = ..()
update_icon()
/obj/item/weapon/storage/lockbox/vials/update_icon(var/itemremoved = 0)
@@ -323,6 +359,8 @@
/obj/item/weapon/storage/fancy/heartbox
icon_state = "heartbox"
name = "box of chocolates"
+ icon_type = "chocolate"
+
var/startswith = 6
max_storage_space = ITEMSIZE_COST_SMALL * 6
can_hold = list(
@@ -330,19 +368,19 @@
/obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white,
/obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle
)
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle
+ )
-/obj/item/weapon/storage/fancy/heartbox/New()
- ..()
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece(src)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white(src)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/white(src)
- new /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece/truffle(src)
+/obj/item/weapon/storage/fancy/heartbox/initialize()
+ . = ..()
update_icon()
- return
/obj/item/weapon/storage/fancy/heartbox/update_icon(var/itemremoved = 0)
if (contents.len == 0)
icon_state = "heartbox_empty"
- return
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index 43b7c9e22b..9c4a44d76d 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -13,158 +13,147 @@
icon_state = "firstaid"
throw_speed = 2
throw_range = 8
- var/empty = 0
max_storage_space = ITEMSIZE_COST_SMALL * 7 // 14
+ var/list/icon_variety
+/obj/item/weapon/storage/firstaid/initialize()
+ . = ..()
+ if(icon_variety)
+ icon_state = pick(icon_variety)
+ icon_variety = null
/obj/item/weapon/storage/firstaid/fire
name = "fire first aid kit"
desc = "It's an emergency medical kit for when the toxins lab spontaneously burns down."
icon_state = "ointment"
item_state_slots = list(slot_r_hand_str = "firstaid-ointment", slot_l_hand_str = "firstaid-ointment")
-
- New()
- ..()
- if (empty) return
-
- icon_state = pick("ointment","firefirstaid")
-
- new /obj/item/device/healthanalyzer( src )
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src )
- new /obj/item/stack/medical/ointment( src )
- new /obj/item/stack/medical/ointment( src )
- new /obj/item/weapon/reagent_containers/pill/kelotane( src )
- new /obj/item/weapon/reagent_containers/pill/kelotane( src )
- new /obj/item/weapon/reagent_containers/pill/kelotane( src ) //Replaced ointment with these since they actually work --Errorage
- return
-
+ icon_variety = list("ointment","firefirstaid")
+ starts_with = list(
+ /obj/item/device/healthanalyzer,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ /obj/item/stack/medical/ointment,
+ /obj/item/stack/medical/ointment,
+ /obj/item/weapon/reagent_containers/pill/kelotane,
+ /obj/item/weapon/reagent_containers/pill/kelotane,
+ /obj/item/weapon/reagent_containers/pill/kelotane
+ )
/obj/item/weapon/storage/firstaid/regular
icon_state = "firstaid"
-
- New()
- ..()
- if (empty) return
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/device/healthanalyzer(src)
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src )
- return
+ starts_with = list(
+ /obj/item/stack/medical/bruise_pack,
+ /obj/item/stack/medical/bruise_pack,
+ /obj/item/stack/medical/bruise_pack,
+ /obj/item/stack/medical/ointment,
+ /obj/item/stack/medical/ointment,
+ /obj/item/device/healthanalyzer,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector
+ )
/obj/item/weapon/storage/firstaid/toxin
name = "poison first aid kit" //IRL the term used would be poison first aid kit.
desc = "Used to treat when one has a high amount of toxins in their body."
icon_state = "antitoxin"
item_state_slots = list(slot_r_hand_str = "firstaid-toxin", slot_l_hand_str = "firstaid-toxin")
-
- New()
- ..()
- if (empty) return
-
- icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
-
- new /obj/item/weapon/reagent_containers/syringe/antitoxin( src )
- new /obj/item/weapon/reagent_containers/syringe/antitoxin( src )
- new /obj/item/weapon/reagent_containers/syringe/antitoxin( src )
- new /obj/item/weapon/reagent_containers/pill/antitox( src )
- new /obj/item/weapon/reagent_containers/pill/antitox( src )
- new /obj/item/weapon/reagent_containers/pill/antitox( src )
- new /obj/item/device/healthanalyzer( src )
- return
+ icon_variety = list("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/syringe/antitoxin,
+ /obj/item/weapon/reagent_containers/syringe/antitoxin,
+ /obj/item/weapon/reagent_containers/syringe/antitoxin,
+ /obj/item/weapon/reagent_containers/pill/antitox,
+ /obj/item/weapon/reagent_containers/pill/antitox,
+ /obj/item/weapon/reagent_containers/pill/antitox,
+ /obj/item/device/healthanalyzer
+ )
/obj/item/weapon/storage/firstaid/o2
name = "oxygen deprivation first aid kit"
desc = "A box full of oxygen goodies."
icon_state = "o2"
item_state_slots = list(slot_r_hand_str = "firstaid-o2", slot_l_hand_str = "firstaid-o2")
-
- New()
- ..()
- if (empty) return
- new /obj/item/weapon/reagent_containers/pill/dexalin( src )
- new /obj/item/weapon/reagent_containers/pill/dexalin( src )
- new /obj/item/weapon/reagent_containers/pill/dexalin( src )
- new /obj/item/weapon/reagent_containers/pill/dexalin( src )
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src )
- new /obj/item/weapon/reagent_containers/syringe/inaprovaline( src )
- new /obj/item/device/healthanalyzer( src )
- return
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/pill/dexalin,
+ /obj/item/weapon/reagent_containers/pill/dexalin,
+ /obj/item/weapon/reagent_containers/pill/dexalin,
+ /obj/item/weapon/reagent_containers/pill/dexalin,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ /obj/item/weapon/reagent_containers/syringe/inaprovaline,
+ /obj/item/device/healthanalyzer
+ )
/obj/item/weapon/storage/firstaid/adv
name = "advanced first aid kit"
desc = "Contains advanced medical treatments, for serious boo-boos."
icon_state = "advfirstaid"
item_state_slots = list(slot_r_hand_str = "firstaid-advanced", slot_l_hand_str = "firstaid-advanced")
-
-/obj/item/weapon/storage/firstaid/adv/New()
- ..()
- if (empty) return
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src )
- new /obj/item/stack/medical/advanced/bruise_pack(src)
- new /obj/item/stack/medical/advanced/bruise_pack(src)
- new /obj/item/stack/medical/advanced/bruise_pack(src)
- new /obj/item/stack/medical/advanced/ointment(src)
- new /obj/item/stack/medical/advanced/ointment(src)
- new /obj/item/stack/medical/splint(src)
- return
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ /obj/item/stack/medical/advanced/bruise_pack,
+ /obj/item/stack/medical/advanced/bruise_pack,
+ /obj/item/stack/medical/advanced/bruise_pack,
+ /obj/item/stack/medical/advanced/ointment,
+ /obj/item/stack/medical/advanced/ointment,
+ /obj/item/stack/medical/splint
+ )
/obj/item/weapon/storage/firstaid/combat
name = "combat medical kit"
desc = "Contains advanced medical treatments."
icon_state = "bezerk"
item_state_slots = list(slot_r_hand_str = "firstaid-advanced", slot_l_hand_str = "firstaid-advanced")
-
-/obj/item/weapon/storage/firstaid/combat/New()
- ..()
- if (empty) return
- new /obj/item/weapon/storage/pill_bottle/bicaridine(src)
- new /obj/item/weapon/storage/pill_bottle/dermaline(src)
- new /obj/item/weapon/storage/pill_bottle/dexalin_plus(src)
- new /obj/item/weapon/storage/pill_bottle/dylovene(src)
- new /obj/item/weapon/storage/pill_bottle/tramadol(src)
- new /obj/item/weapon/storage/pill_bottle/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting(src)
- new /obj/item/stack/medical/splint(src)
- new /obj/item/device/healthanalyzer/advanced(src)
- return
+ starts_with = list(
+ /obj/item/weapon/storage/pill_bottle/bicaridine,
+ /obj/item/weapon/storage/pill_bottle/dermaline,
+ /obj/item/weapon/storage/pill_bottle/dexalin_plus,
+ /obj/item/weapon/storage/pill_bottle/dylovene,
+ /obj/item/weapon/storage/pill_bottle/tramadol,
+ /obj/item/weapon/storage/pill_bottle/spaceacillin,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting,
+ /obj/item/stack/medical/splint,
+ /obj/item/device/healthanalyzer/advanced
+ )
/obj/item/weapon/storage/firstaid/surgery
name = "surgery kit"
- desc = "Contains tools for surgery."
- max_storage_space = ITEMSIZE_COST_NORMAL * 6 // Formally 21. Odd numbers should be avoided for a system based on exponents of 2.
+ desc = "Contains tools for surgery. Has precise foam fitting for safe transport and automatically sterilizes the content between uses."
+ icon_state = "surgerykit"
+ item_state = "firstaid-surgery"
max_w_class = ITEMSIZE_NORMAL
-/obj/item/weapon/storage/firstaid/surgery/New()
- ..()
- if (empty) return
- new /obj/item/weapon/surgical/bonesetter(src)
- new /obj/item/weapon/surgical/cautery(src)
- new /obj/item/weapon/surgical/circular_saw(src)
- new /obj/item/weapon/surgical/hemostat(src)
- new /obj/item/weapon/surgical/retractor(src)
- new /obj/item/weapon/surgical/scalpel(src)
- new /obj/item/weapon/surgical/surgicaldrill(src)
- new /obj/item/weapon/surgical/bonegel(src)
- new /obj/item/weapon/surgical/FixOVein(src)
- new /obj/item/stack/medical/advanced/bruise_pack(src)
- new /obj/item/device/healthanalyzer/enhanced(src)
- return
+ can_hold = list(
+ /obj/item/weapon/surgical/bonesetter,
+ /obj/item/weapon/surgical/cautery,
+ /obj/item/weapon/surgical/circular_saw,
+ /obj/item/weapon/surgical/hemostat,
+ /obj/item/weapon/surgical/retractor,
+ /obj/item/weapon/surgical/scalpel,
+ /obj/item/weapon/surgical/surgicaldrill,
+ /obj/item/weapon/surgical/bonegel,
+ /obj/item/weapon/surgical/FixOVein,
+ /obj/item/stack/medical/advanced/bruise_pack,
+ /obj/item/stack/nanopaste,
+ /obj/item/device/healthanalyzer/advanced
+ )
+
+ starts_with = list(
+ /obj/item/weapon/surgical/bonesetter,
+ /obj/item/weapon/surgical/cautery,
+ /obj/item/weapon/surgical/circular_saw,
+ /obj/item/weapon/surgical/hemostat,
+ /obj/item/weapon/surgical/retractor,
+ /obj/item/weapon/surgical/scalpel,
+ /obj/item/weapon/surgical/surgicaldrill,
+ /obj/item/weapon/surgical/bonegel,
+ /obj/item/weapon/surgical/FixOVein,
+ /obj/item/stack/medical/advanced/bruise_pack,
+ /obj/item/device/healthanalyzer/advanced
+ )
/obj/item/weapon/storage/firstaid/clotting
name = "clotting kit"
desc = "Contains chemicals to stop bleeding."
max_storage_space = ITEMSIZE_COST_SMALL * 7
-
-/obj/item/weapon/storage/firstaid/clotting/New()
- ..()
- if (empty)
- return
- for(var/i = 1 to 8)
- new /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting(src)
- return
+ starts_with = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting = 8)
/*
* Pill Bottles
@@ -184,170 +173,99 @@
max_storage_space = ITEMSIZE_COST_TINY * 14
max_w_class = ITEMSIZE_TINY
+ var/label_text = ""
+ var/base_name = " "
+ var/base_desc = " "
+
+/obj/item/weapon/storage/pill_bottle/New()
+ ..()
+ base_name = name
+ base_desc = desc
+
+/obj/item/weapon/storage/pill_bottle/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen))
+ var/tmp_label = sanitizeSafe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN)
+ if(length(tmp_label) > 50)
+ to_chat(user, "The label can be at most 50 characters long.")
+ else if(length(tmp_label) > 10)
+ to_chat(user, "You set the label.")
+ label_text = tmp_label
+ update_name_label()
+ else
+ to_chat(user, "You set the label to \"[tmp_label]\".")
+ label_text = tmp_label
+ update_name_label()
+ else
+ ..()
+
+/obj/item/weapon/storage/pill_bottle/proc/update_name_label()
+ if(!label_text)
+ name = base_name
+ desc = base_desc
+ return
+ else if(length(label_text) > 10)
+ var/short_label_text = copytext(label_text, 1, 11)
+ name = "[base_name] ([short_label_text]...)"
+ else
+ name = "[base_name] ([label_text])"
+ desc = "[base_desc] It is labeled \"[label_text]\"."
+
/obj/item/weapon/storage/pill_bottle/antitox
name = "bottle of Dylovene pills"
desc = "Contains pills used to counter toxins."
-
-/obj/item/weapon/storage/pill_bottle/antitox/New() //25u each
- ..()
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
- new /obj/item/weapon/reagent_containers/pill/antitox(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/antitox = 7)
/obj/item/weapon/storage/pill_bottle/bicaridine
name = "bottle of Bicaridine pills"
desc = "Contains pills used to stabilize the severely injured."
-
-/obj/item/weapon/storage/pill_bottle/bicaridine/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
- new /obj/item/weapon/reagent_containers/pill/bicaridine(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/bicaridine = 7)
/obj/item/weapon/storage/pill_bottle/dexalin_plus
name = "bottle of Dexalin Plus pills"
desc = "Contains pills used to treat extreme cases of oxygen deprivation."
-
-/obj/item/weapon/storage/pill_bottle/dexalin_plus/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
- new /obj/item/weapon/reagent_containers/pill/dexalin_plus(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/dexalin_plus = 7)
/obj/item/weapon/storage/pill_bottle/dermaline
name = "bottle of Dermaline pills"
desc = "Contains pills used to treat burn wounds."
-
-/obj/item/weapon/storage/pill_bottle/dermaline/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
- new /obj/item/weapon/reagent_containers/pill/dermaline(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/dermaline = 7)
/obj/item/weapon/storage/pill_bottle/dylovene
name = "bottle of Dylovene pills"
desc = "Contains pills used to treat toxic substances in the blood."
-
-/obj/item/weapon/storage/pill_bottle/dylovene/New() //15u each
- ..()
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
- new /obj/item/weapon/reagent_containers/pill/dylovene(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/dylovene = 7)
/obj/item/weapon/storage/pill_bottle/inaprovaline
name = "bottle of Inaprovaline pills"
desc = "Contains pills used to stabilize patients."
-
-/obj/item/weapon/storage/pill_bottle/inaprovaline/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
- new /obj/item/weapon/reagent_containers/pill/inaprovaline(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/inaprovaline = 7)
/obj/item/weapon/storage/pill_bottle/kelotane
name = "bottle of kelotane pills"
desc = "Contains pills used to treat burns."
-
-/obj/item/weapon/storage/pill_bottle/kelotane/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
- new /obj/item/weapon/reagent_containers/pill/kelotane(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/kelotane = 7)
/obj/item/weapon/storage/pill_bottle/spaceacillin
name = "bottle of Spaceacillin pills"
desc = "A theta-lactam antibiotic. Effective against many diseases likely to be encountered in space."
-
-/obj/item/weapon/storage/pill_bottle/spaceacillin/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
- new /obj/item/weapon/reagent_containers/pill/spaceacillin(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/spaceacillin = 7)
/obj/item/weapon/storage/pill_bottle/tramadol
name = "bottle of Tramadol pills"
desc = "Contains pills used to relieve pain."
-
-/obj/item/weapon/storage/pill_bottle/tramadol/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
- new /obj/item/weapon/reagent_containers/pill/tramadol(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/tramadol = 7)
/obj/item/weapon/storage/pill_bottle/citalopram
name = "bottle of Citalopram pills"
desc = "Contains pills used to stabilize a patient's mood."
-
-/obj/item/weapon/storage/pill_bottle/citalopram/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
- new /obj/item/weapon/reagent_containers/pill/citalopram(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/citalopram = 7)
/obj/item/weapon/storage/pill_bottle/carbon
name = "bottle of Carbon pills"
desc = "Contains pills used to neutralise chemicals in the stomach."
-
-/obj/item/weapon/storage/pill_bottle/carbon/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
- new /obj/item/weapon/reagent_containers/pill/carbon(src)
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/carbon = 7)
/obj/item/weapon/storage/pill_bottle/iron
name = "bottle of Iron pills"
desc = "Contains pills used to aid in blood regeneration."
-
-/obj/item/weapon/storage/pill_bottle/iron/New()
- ..()
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
- new /obj/item/weapon/reagent_containers/pill/iron(src)
\ No newline at end of file
+ starts_with = list(/obj/item/weapon/reagent_containers/pill/iron = 7)
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index e52ad4d812..e9527b2313 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -77,36 +77,28 @@
/obj/item/weapon/storage/lockbox/loyalty
name = "lockbox of loyalty implants"
req_access = list(access_security)
-
- New()
- ..()
- new /obj/item/weapon/implantcase/loyalty(src)
- new /obj/item/weapon/implantcase/loyalty(src)
- new /obj/item/weapon/implantcase/loyalty(src)
- new /obj/item/weapon/implanter/loyalty(src)
-
+ starts_with = list(
+ /obj/item/weapon/implantcase/loyalty = 3,
+ /obj/item/weapon/implanter/loyalty
+ )
/obj/item/weapon/storage/lockbox/clusterbang
name = "lockbox of clusterbangs"
desc = "You have a bad feeling about opening this."
req_access = list(access_security)
-
- New()
- ..()
- new /obj/item/weapon/grenade/flashbang/clusterbang(src)
+ starts_with = list(/obj/item/weapon/grenade/flashbang/clusterbang)
/obj/item/weapon/storage/lockbox/medal
name = "lockbox of medals"
desc = "A lockbox filled with commemorative medals, it has the NanoTrasen logo stamped on it."
req_access = list(access_heads)
storage_slots = 7
-
- New()
- ..()
- new /obj/item/clothing/accessory/medal/conduct(src)
- new /obj/item/clothing/accessory/medal/bronze_heart(src)
- new /obj/item/clothing/accessory/medal/nobel_science(src)
- new /obj/item/clothing/accessory/medal/silver/valor(src)
- new /obj/item/clothing/accessory/medal/silver/security(src)
- new /obj/item/clothing/accessory/medal/gold/captain(src)
- new /obj/item/clothing/accessory/medal/gold/heroism(src)
\ No newline at end of file
+ starts_with = list(
+ /obj/item/clothing/accessory/medal/conduct,
+ /obj/item/clothing/accessory/medal/bronze_heart,
+ /obj/item/clothing/accessory/medal/nobel_science,
+ /obj/item/clothing/accessory/medal/silver/valor,
+ /obj/item/clothing/accessory/medal/silver/security,
+ /obj/item/clothing/accessory/medal/gold/captain,
+ /obj/item/clothing/accessory/medal/gold/heroism
+ )
diff --git a/code/game/objects/items/weapons/storage/misc.dm b/code/game/objects/items/weapons/storage/misc.dm
index 64952046a5..d103fbc6ef 100644
--- a/code/game/objects/items/weapons/storage/misc.dm
+++ b/code/game/objects/items/weapons/storage/misc.dm
@@ -6,17 +6,14 @@
icon = 'icons/obj/food.dmi'
icon_state = "donutbox"
name = "donut box"
- var/startswith = 6
max_storage_space = ITEMSIZE_COST_SMALL * 6
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/donut)
foldable = /obj/item/stack/material/cardboard
+ starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 6)
-/obj/item/weapon/storage/box/donut/New()
- ..()
- for(var/i=1 to startswith)
- new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src)
+/obj/item/weapon/storage/box/donut/initialize()
+ . = ..()
update_icon()
- return
/obj/item/weapon/storage/box/donut/update_icon()
overlays.Cut()
@@ -26,4 +23,4 @@
i++
/obj/item/weapon/storage/box/donut/empty
- startswith = 0
+ empty = TRUE
diff --git a/code/game/objects/items/weapons/storage/quickdraw.dm b/code/game/objects/items/weapons/storage/quickdraw.dm
new file mode 100644
index 0000000000..86d7c76ca2
--- /dev/null
+++ b/code/game/objects/items/weapons/storage/quickdraw.dm
@@ -0,0 +1,80 @@
+// -----------------------------
+// Quickdraw storage
+// -----------------------------
+//These items are pouches and cases made to be kept in belts or pockets to quickly draw objects from
+//Largely inspired by the vest pouches on Colonial Marines
+
+/obj/item/weapon/storage/quickdraw
+ name = "quickdraw"
+ desc = "This object should not appear"
+
+ //Quickmode
+ //When set to 0, this storage will operate as a regular storage, and clicking on it while equipped will open it as a storage
+ //When set to 1, a click while it is equipped will instead move the first item inside it to your hand
+ var/quickmode = 0
+
+/obj/item/weapon/storage/quickdraw/attack_hand(mob/user as mob)
+ if(src.loc == user) //If they aren't holding us, we do nothing special
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(quickmode)
+ var/first_item = contents[1]
+ if(first_item && !H.get_active_hand()) //Do we have anything to give you?
+ H.put_in_hands(first_item)
+ return
+
+ if(H.l_store == src && !H.get_active_hand()) //overrides
+ src.open(user)
+ return
+ if(H.r_store == src && !H.get_active_hand())
+ src.open(user)
+ return
+ ..() //Nothing special happened, go call the other proc
+
+
+/obj/item/weapon/storage/quickdraw/verb/toggle_quickdraw()
+ set name = "Switch Quickdraw Mode"
+ set category = "Object"
+
+ quickmode = !quickmode
+ switch (quickmode)
+ if(1)
+ to_chat(usr, "[src] now draws the first object inside.")
+ if(0)
+ to_chat(usr, "[src] now opens as a container.")
+
+/obj/item/weapon/storage/quickdraw/AltClick(mob/user)
+ ..()
+ if(src.loc == user) //Are they carrying us?
+ toggle_quickdraw()
+
+
+// If we start adding more of these, we'll need to make them their own folder. 'til then, this one should be fine.
+
+// -----------------------------
+// Syringe case
+// -----------------------------
+
+/obj/item/weapon/storage/quickdraw/syringe_case
+ name = "syringe case"
+ desc = "A small case for safely carrying sharps around."
+ icon_state = "syringe_case"
+
+ w_class = ITEMSIZE_SMALL
+ max_w_class = ITEMSIZE_TINY
+ max_storage_space = ITEMSIZE_TINY * 6 //Capable of holding six syringes
+
+ //Can hold syringes and autoinjectors, but also pills if you really wanted. Syringe-shaped objects like pens and cigarettes also fit, but why would you do that?
+ can_hold = list(/obj/item/weapon/reagent_containers/syringe, /obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ /obj/item/weapon/reagent_containers/pill, /obj/item/weapon/pen, /obj/item/device/flashlight/pen, /obj/item/clothing/mask/smokable/cigarette)
+
+ quickmode = 1 //Starts in quickdraw mode
+ //Preloaded for your convenience!
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/reagent_containers/syringe
+ )
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm
index 4d9be129f7..78a2d940ad 100644
--- a/code/game/objects/items/weapons/storage/secure.dm
+++ b/code/game/objects/items/weapons/storage/secure.dm
@@ -184,15 +184,10 @@
anchored = 1.0
density = 0
cant_hold = list(/obj/item/weapon/storage/secure/briefcase)
+ starts_with = list(
+ /obj/item/weapon/paper,
+ /obj/item/weapon/pen
+ )
- New()
- ..()
- new /obj/item/weapon/paper(src)
- new /obj/item/weapon/pen(src)
-
- attack_hand(mob/user as mob)
- return attack_self(user)
-
-/obj/item/weapon/storage/secure/safe/HoS/New()
- ..()
- //new /obj/item/weapon/storage/lockbox/clusterbang(src) This item is currently broken... and probably shouldnt exist to begin with (even though it's cool)
+/obj/item/weapon/storage/secure/safe/attack_hand(mob/user as mob)
+ return attack_self(user)
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index c95f0ac49e..03ad104810 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -35,6 +35,8 @@
var/allow_quick_gather //Set this variable to allow the object to have the 'toggle mode' verb, which quickly collects all items from a tile.
var/collection_mode = 1; //0 = pick one at a time, 1 = pick all on tile
var/use_sound = "rustle" //sound played when used. null for no sound.
+ var/list/starts_with //Things to spawn on the box on spawn
+ var/empty //Mapper override to spawn an empty version of a container that usually has stuff
/obj/item/weapon/storage/Destroy()
close_all()
@@ -52,7 +54,7 @@
if(!canremove)
return
- if (ishuman(usr) || issmall(usr) || isanimal(usr)) //so monkeys can take off their backpacks -- Urist
+ if (isliving(usr) || isobserver(usr))
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
return
@@ -139,7 +141,7 @@
is_seeing -= user
/obj/item/weapon/storage/proc/open(mob/user as mob)
- if (src.use_sound)
+ if (src.use_sound && !isobserver(user))
playsound(src.loc, src.use_sound, 50, 1, -5)
orient2hud(user)
@@ -352,12 +354,10 @@
//such as when picking up all the items on a tile with one click.
/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
if(!istype(W)) return 0
+
if(usr)
- usr.remove_from_mob(W)
- usr.update_icons() //update our overlays
- W.forceMove(src)
- W.on_enter_storage(src)
- if(usr)
+ usr.remove_from_mob(W,target = src) //If given a target, handles forceMove()
+ W.on_enter_storage(src)
if (usr.client && usr.s_active != src)
usr.client.screen -= W
W.dropped(usr)
@@ -375,6 +375,10 @@
src.orient2hud(usr)
if(usr.s_active)
usr.s_active.show_to(usr)
+ else
+ W.forceMove(src)
+ W.on_enter_storage(src)
+
update_icon()
return 1
@@ -523,7 +527,8 @@
for(var/obj/item/I in contents)
remove_from_storage(I, T)
-/obj/item/weapon/storage/New()
+/obj/item/weapon/storage/initialize()
+ . = ..()
if(allow_quick_empty)
verbs += /obj/item/weapon/storage/verb/quick_empty
@@ -535,12 +540,6 @@
else
verbs -= /obj/item/weapon/storage/verb/toggle_gathering_mode
- spawn(5)
- var/total_storage_space = 0
- for(var/obj/item/I in contents)
- total_storage_space += I.get_storage_cost()
- max_storage_space = max(total_storage_space,max_storage_space) //Prevents spawned containers from being too small for their contents.
-
src.boxes = new /obj/screen/storage( )
src.boxes.name = "storage"
src.boxes.master = src
@@ -579,7 +578,22 @@
src.closer.icon_state = "storage_close"
src.closer.hud_layerise()
orient2hud()
- return
+
+ if(LAZYLEN(starts_with) && !empty)
+ for(var/newtype in starts_with)
+ var/count = starts_with[newtype] || 1 //Could have left it blank.
+ while(count)
+ count--
+ new newtype(src)
+ starts_with = null //Reduce list count.
+
+ calibrate_size()
+
+/obj/item/weapon/storage/proc/calibrate_size()
+ var/total_storage_space = 0
+ for(var/obj/item/I in contents)
+ total_storage_space += I.get_storage_cost()
+ max_storage_space = max(total_storage_space,max_storage_space) //Prevents spawned containers from being too small for their contents.
/obj/item/weapon/storage/emp_act(severity)
if(!istype(src.loc, /mob/living))
@@ -658,3 +672,60 @@
can_hold[I.type]++
max_w_class = max(I.w_class, max_w_class)
max_storage_space += I.get_storage_cost()
+
+/*
+ * Trinket Box - READDING SOON
+ */
+/obj/item/weapon/storage/trinketbox
+ name = "trinket box"
+ desc = "A box that can hold small trinkets, such as a ring."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "trinketbox"
+ var/open = 0
+ storage_slots = 1
+ can_hold = list(
+ /obj/item/clothing/gloves/ring,
+ /obj/item/weapon/coin,
+ /obj/item/clothing/accessory/medal
+ )
+ var/open_state
+ var/closed_state
+
+/obj/item/weapon/storage/trinketbox/update_icon()
+ overlays.Cut()
+ if(open)
+ icon_state = open_state
+
+ if(contents.len >= 1)
+ var/contained_image = null
+ if(istype(contents[1], /obj/item/clothing/gloves/ring))
+ contained_image = "ring_trinket"
+ else if(istype(contents[1], /obj/item/weapon/coin))
+ contained_image = "coin_trinket"
+ else if(istype(contents[1], /obj/item/clothing/accessory/medal))
+ contained_image = "medal_trinket"
+ if(contained_image)
+ overlays += contained_image
+ else
+ icon_state = closed_state
+
+/obj/item/weapon/storage/trinketbox/New()
+ if(!open_state)
+ open_state = "[initial(icon_state)]_open"
+ if(!closed_state)
+ closed_state = "[initial(icon_state)]"
+ ..()
+
+/obj/item/weapon/storage/trinketbox/attack_self()
+ open = !open
+ update_icon()
+ ..()
+
+/obj/item/weapon/storage/trinketbox/examine(mob/user)
+ ..()
+ if(open && contents.len)
+ var/display_item = contents[1]
+ to_chat(user, "\The [src] contains \the [display_item]!")
+
+/obj/item/weapon/storage/AllowDrop()
+ return TRUE
diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm
index 21bebfa399..c4174eb4c0 100644
--- a/code/game/objects/items/weapons/storage/toolbox.dm
+++ b/code/game/objects/items/weapons/storage/toolbox.dm
@@ -19,48 +19,50 @@
name = "emergency toolbox"
icon_state = "red"
item_state_slots = list(slot_r_hand_str = "toolbox_red", slot_l_hand_str = "toolbox_red")
-
-/obj/item/weapon/storage/toolbox/emergency/New()
- ..()
- new /obj/item/weapon/crowbar/red(src)
- new /obj/item/weapon/extinguisher/mini(src)
+ starts_with = list(
+ /obj/item/weapon/crowbar/red,
+ /obj/item/weapon/extinguisher/mini,
+ /obj/item/device/radio
+ )
+/obj/item/weapon/storage/toolbox/emergency/initialize()
if(prob(50))
new /obj/item/device/flashlight(src)
else
new /obj/item/device/flashlight/flare(src)
- new /obj/item/device/radio(src)
+ . = ..()
/obj/item/weapon/storage/toolbox/mechanical
name = "mechanical toolbox"
icon_state = "blue"
item_state_slots = list(slot_r_hand_str = "toolbox_blue", slot_l_hand_str = "toolbox_blue")
-
-/obj/item/weapon/storage/toolbox/mechanical/New()
- ..()
- new /obj/item/weapon/screwdriver(src)
- new /obj/item/weapon/wrench(src)
- new /obj/item/weapon/weldingtool(src)
- new /obj/item/weapon/crowbar(src)
- new /obj/item/device/analyzer(src)
- new /obj/item/weapon/wirecutters(src)
+ starts_with = list(
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/wrench,
+ /obj/item/weapon/weldingtool,
+ /obj/item/weapon/crowbar,
+ /obj/item/device/analyzer,
+ /obj/item/weapon/wirecutters
+ )
/obj/item/weapon/storage/toolbox/electrical
name = "electrical toolbox"
icon_state = "yellow"
item_state_slots = list(slot_r_hand_str = "toolbox_yellow", slot_l_hand_str = "toolbox_yellow")
-
-/obj/item/weapon/storage/toolbox/electrical/New()
- ..()
- new /obj/item/weapon/screwdriver(src)
- new /obj/item/weapon/wirecutters(src)
- new /obj/item/device/t_scanner(src)
- new /obj/item/weapon/crowbar(src)
- new /obj/item/stack/cable_coil/random(src,30)
- new /obj/item/stack/cable_coil/random(src,30)
+ starts_with = list(
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/wirecutters,
+ /obj/item/device/t_scanner,
+ /obj/item/weapon/crowbar,
+ /obj/item/stack/cable_coil/random_belt,
+ /obj/item/stack/cable_coil/random_belt
+ )
+/obj/item/weapon/storage/toolbox/electrical/initialize()
+ . = ..()
if(prob(5))
new /obj/item/clothing/gloves/yellow(src)
else
new /obj/item/stack/cable_coil/random(src,30)
+ calibrate_size()
/obj/item/weapon/storage/toolbox/syndicate
name = "black and red toolbox"
@@ -68,29 +70,26 @@
item_state_slots = list(slot_r_hand_str = "toolbox_syndi", slot_l_hand_str = "toolbox_syndi")
origin_tech = list(TECH_COMBAT = 1, TECH_ILLEGAL = 1)
force = 14
- var/powertools = FALSE
+ starts_with = list(
+ /obj/item/clothing/gloves/yellow,
+ /obj/item/weapon/screwdriver,
+ /obj/item/weapon/wrench,
+ /obj/item/weapon/weldingtool,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/wirecutters,
+ /obj/item/device/multitool
+ )
/obj/item/weapon/storage/toolbox/syndicate/powertools
- powertools = TRUE
-
-/obj/item/weapon/storage/toolbox/syndicate/New() // This is found in maint, so it should have the basics, plus some gloves.
- ..() //all storage items need this to work properly!
- if(powertools)
- new /obj/item/clothing/gloves/yellow(src)
- new /obj/item/weapon/screwdriver/power(src)
- new /obj/item/weapon/weldingtool/experimental(src)
- new /obj/item/weapon/crowbar/power(src)
- new /obj/item/device/multitool(src)
- new /obj/item/stack/cable_coil/random(src,30)
- new /obj/item/device/analyzer(src)
- else
- new /obj/item/clothing/gloves/yellow(src)
- new /obj/item/weapon/screwdriver(src)
- new /obj/item/weapon/wrench(src)
- new /obj/item/weapon/weldingtool(src)
- new /obj/item/weapon/crowbar(src)
- new /obj/item/weapon/wirecutters(src)
- new /obj/item/device/multitool(src)
+ starts_with = list(
+ /obj/item/clothing/gloves/yellow,
+ /obj/item/weapon/screwdriver/power,
+ /obj/item/weapon/weldingtool/experimental,
+ /obj/item/weapon/crowbar/power,
+ /obj/item/device/multitool,
+ /obj/item/stack/cable_coil/random_belt,
+ /obj/item/device/analyzer
+ )
/obj/item/weapon/storage/toolbox/lunchbox
max_storage_space = ITEMSIZE_COST_SMALL * 4 //slightly smaller than a toolbox
@@ -103,8 +102,7 @@
var/filled = FALSE
attack_verb = list("lunched")
-/obj/item/weapon/storage/toolbox/lunchbox/New()
- ..()
+/obj/item/weapon/storage/toolbox/lunchbox/initialize()
if(filled)
var/list/lunches = lunchables_lunches()
var/lunch = lunches[pick(lunches)]
@@ -117,6 +115,7 @@
var/list/drinks = lunchables_drinks()
var/drink = drinks[pick(drinks)]
new drink(src)
+ . = ..()
/obj/item/weapon/storage/toolbox/lunchbox/filled
filled = TRUE
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index f82feb91dd..5c0f837340 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -1,76 +1,66 @@
-/obj/item/weapon/storage/box/syndicate/
- New()
- ..()
- switch (pickweight(list("bloodyspai" = 1, "stealth" = 1, "screwed" = 1, "guns" = 1, "murder" = 1, "freedom" = 1, "hacker" = 1, "lordsingulo" = 1, "smoothoperator" = 1)))
- if("bloodyspai")
- new /obj/item/clothing/under/chameleon(src)
- new /obj/item/clothing/mask/gas/voice(src)
- new /obj/item/weapon/card/id/syndicate(src)
- new /obj/item/clothing/shoes/syndigaloshes(src)
- return
+/obj/item/weapon/storage/box/syndicate/initialize()
+ switch (pickweight(list("bloodyspai" = 1, "stealth" = 1, "screwed" = 1, "guns" = 1, "murder" = 1, "freedom" = 1, "hacker" = 1, "lordsingulo" = 1, "smoothoperator" = 1)))
+ if("bloodyspai")
+ new /obj/item/clothing/under/chameleon(src)
+ new /obj/item/clothing/mask/gas/voice(src)
+ new /obj/item/weapon/card/id/syndicate(src)
+ new /obj/item/clothing/shoes/syndigaloshes(src)
- if("stealth")
- new /obj/item/weapon/gun/energy/crossbow(src)
- new /obj/item/weapon/pen/reagent/paralysis(src)
- new /obj/item/device/chameleon(src)
- return
+ if("stealth")
+ new /obj/item/weapon/gun/energy/crossbow(src)
+ new /obj/item/weapon/pen/reagent/paralysis(src)
+ new /obj/item/device/chameleon(src)
- if("screwed")
- new /obj/effect/spawner/newbomb/timer/syndicate(src)
- new /obj/effect/spawner/newbomb/timer/syndicate(src)
- new /obj/item/device/powersink(src)
- new /obj/item/clothing/suit/space/syndicate(src)
- new /obj/item/clothing/head/helmet/space/syndicate(src)
- new /obj/item/clothing/mask/gas/syndicate(src)
- new /obj/item/weapon/tank/emergency/oxygen/double(src)
- return
+ if("screwed")
+ new /obj/effect/spawner/newbomb/timer/syndicate(src)
+ new /obj/effect/spawner/newbomb/timer/syndicate(src)
+ new /obj/item/device/powersink(src)
+ new /obj/item/clothing/suit/space/syndicate(src)
+ new /obj/item/clothing/head/helmet/space/syndicate(src)
+ new /obj/item/clothing/mask/gas/syndicate(src)
+ new /obj/item/weapon/tank/emergency/oxygen/double(src)
- if("guns")
- new /obj/item/weapon/gun/projectile/revolver(src)
- new /obj/item/ammo_magazine/s357(src)
- new /obj/item/weapon/card/emag(src)
- new /obj/item/weapon/plastique(src)
- new /obj/item/weapon/plastique(src)
- return
+ if("guns")
+ new /obj/item/weapon/gun/projectile/revolver(src)
+ new /obj/item/ammo_magazine/s357(src)
+ new /obj/item/weapon/card/emag(src)
+ new /obj/item/weapon/plastique(src)
+ new /obj/item/weapon/plastique(src)
- if("murder")
- new /obj/item/weapon/melee/energy/sword(src)
- new /obj/item/clothing/glasses/thermal/syndi(src)
- new /obj/item/weapon/card/emag(src)
- new /obj/item/clothing/shoes/syndigaloshes(src)
- return
+ if("murder")
+ new /obj/item/weapon/melee/energy/sword(src)
+ new /obj/item/clothing/glasses/thermal/syndi(src)
+ new /obj/item/weapon/card/emag(src)
+ new /obj/item/clothing/shoes/syndigaloshes(src)
- if("freedom")
- var/obj/item/weapon/implanter/O = new /obj/item/weapon/implanter(src)
- O.imp = new /obj/item/weapon/implant/freedom(O)
- var/obj/item/weapon/implanter/U = new /obj/item/weapon/implanter(src)
- U.imp = new /obj/item/weapon/implant/uplink(U)
- return
+ if("freedom")
+ var/obj/item/weapon/implanter/O = new /obj/item/weapon/implanter(src)
+ O.imp = new /obj/item/weapon/implant/freedom(O)
+ var/obj/item/weapon/implanter/U = new /obj/item/weapon/implanter(src)
+ U.imp = new /obj/item/weapon/implant/uplink(U)
- if("hacker")
- new /obj/item/device/encryptionkey/syndicate(src)
- new /obj/item/weapon/aiModule/syndicate(src)
- new /obj/item/weapon/card/emag(src)
- new /obj/item/device/encryptionkey/binary(src)
- return
+ if("hacker")
+ new /obj/item/device/encryptionkey/syndicate(src)
+ new /obj/item/weapon/aiModule/syndicate(src)
+ new /obj/item/weapon/card/emag(src)
+ new /obj/item/device/encryptionkey/binary(src)
- if("lordsingulo")
- new /obj/item/device/radio/beacon/syndicate(src)
- new /obj/item/clothing/suit/space/syndicate(src)
- new /obj/item/clothing/head/helmet/space/syndicate(src)
- new /obj/item/clothing/mask/gas/syndicate(src)
- new /obj/item/weapon/tank/emergency/oxygen/double(src)
- new /obj/item/weapon/card/emag(src)
- return
+ if("lordsingulo")
+ new /obj/item/device/radio/beacon/syndicate(src)
+ new /obj/item/clothing/suit/space/syndicate(src)
+ new /obj/item/clothing/head/helmet/space/syndicate(src)
+ new /obj/item/clothing/mask/gas/syndicate(src)
+ new /obj/item/weapon/tank/emergency/oxygen/double(src)
+ new /obj/item/weapon/card/emag(src)
- if("smoothoperator")
- new /obj/item/weapon/storage/box/syndie_kit/g9mm(src)
- new /obj/item/weapon/storage/bag/trash(src)
- new /obj/item/weapon/soap/syndie(src)
- new /obj/item/bodybag(src)
- new /obj/item/clothing/under/suit_jacket(src)
- new /obj/item/clothing/shoes/laceup(src)
- return
+ if("smoothoperator")
+ new /obj/item/weapon/storage/box/syndie_kit/g9mm(src)
+ new /obj/item/weapon/storage/bag/trash(src)
+ new /obj/item/weapon/soap/syndie(src)
+ new /obj/item/bodybag(src)
+ new /obj/item/clothing/under/suit_jacket(src)
+ new /obj/item/clothing/shoes/laceup(src)
+ . = ..()
/obj/item/weapon/storage/box/syndie_kit
name = "box"
@@ -80,118 +70,97 @@
/obj/item/weapon/storage/box/syndie_kit/imp_freedom
name = "boxed freedom implant (with injector)"
-/obj/item/weapon/storage/box/syndie_kit/imp_freedom/New()
- ..()
+/obj/item/weapon/storage/box/syndie_kit/imp_freedom/initialize()
var/obj/item/weapon/implanter/O = new(src)
O.imp = new /obj/item/weapon/implant/freedom(O)
O.update()
- return
+ . = ..()
/obj/item/weapon/storage/box/syndie_kit/imp_compress
name = "box (C)"
-
-/obj/item/weapon/storage/box/syndie_kit/imp_compress/New()
- new /obj/item/weapon/implanter/compressed(src)
- ..()
- return
+ starts_with = list(/obj/item/weapon/implanter/compressed)
/obj/item/weapon/storage/box/syndie_kit/imp_explosive
name = "box (E)"
-
-/obj/item/weapon/storage/box/syndie_kit/imp_explosive/New()
- new /obj/item/weapon/implanter/explosive(src)
- ..()
- return
+ starts_with = list(/obj/item/weapon/implanter/explosive)
/obj/item/weapon/storage/box/syndie_kit/imp_uplink
name = "boxed uplink implant (with injector)"
-/obj/item/weapon/storage/box/syndie_kit/imp_uplink/New()
- ..()
+/obj/item/weapon/storage/box/syndie_kit/imp_uplink/initialize()
var/obj/item/weapon/implanter/O = new(src)
O.imp = new /obj/item/weapon/implant/uplink(O)
O.update()
- return
+ . = ..()
/obj/item/weapon/storage/box/syndie_kit/space
name = "boxed space suit and helmet"
-
-/obj/item/weapon/storage/box/syndie_kit/space/New()
- ..()
- new /obj/item/clothing/suit/space/syndicate(src)
- new /obj/item/clothing/head/helmet/space/syndicate(src)
- new /obj/item/clothing/mask/gas/syndicate(src)
- new /obj/item/weapon/tank/emergency/oxygen/double(src)
- return
+ starts_with = list(
+ /obj/item/clothing/suit/space/syndicate,
+ /obj/item/clothing/head/helmet/space/syndicate,
+ /obj/item/clothing/mask/gas/syndicate,
+ /obj/item/weapon/tank/emergency/oxygen/double
+ )
/obj/item/weapon/storage/box/syndie_kit/chameleon
name = "chameleon kit"
desc = "Comes with all the clothes you need to impersonate most people. Acting lessons sold seperately."
-
-/obj/item/weapon/storage/box/syndie_kit/chameleon/New()
- ..()
- new /obj/item/clothing/under/chameleon(src)
- new /obj/item/clothing/head/chameleon(src)
- new /obj/item/clothing/suit/chameleon(src)
- new /obj/item/clothing/shoes/chameleon(src)
- new /obj/item/weapon/storage/backpack/chameleon(src)
- new /obj/item/clothing/gloves/chameleon(src)
- new /obj/item/clothing/mask/chameleon(src)
- new /obj/item/clothing/glasses/chameleon(src)
- new /obj/item/clothing/accessory/chameleon(src)
- new /obj/item/weapon/gun/energy/chameleon(src)
+ starts_with = list(
+ /obj/item/clothing/under/chameleon,
+ /obj/item/clothing/head/chameleon,
+ /obj/item/clothing/suit/chameleon,
+ /obj/item/clothing/shoes/chameleon,
+ /obj/item/weapon/storage/backpack/chameleon,
+ /obj/item/clothing/gloves/chameleon,
+ /obj/item/clothing/mask/chameleon,
+ /obj/item/clothing/glasses/chameleon,
+ /obj/item/clothing/accessory/chameleon,
+ /obj/item/weapon/gun/energy/chameleon
+ )
/obj/item/weapon/storage/box/syndie_kit/clerical
name = "clerical kit"
desc = "Comes with all you need to fake paperwork. Assumes you have passed basic writing lessons."
-
-/obj/item/weapon/storage/box/syndie_kit/clerical/New()
- ..()
- new /obj/item/weapon/stamp/chameleon(src)
- new /obj/item/weapon/pen/chameleon(src)
- new /obj/item/device/destTagger(src)
- new /obj/item/weapon/packageWrap(src)
- new /obj/item/weapon/hand_labeler(src)
+ starts_with = list(
+ /obj/item/weapon/stamp/chameleon,
+ /obj/item/weapon/pen/chameleon,
+ /obj/item/device/destTagger,
+ /obj/item/weapon/packageWrap,
+ /obj/item/weapon/hand_labeler
+ )
/obj/item/weapon/storage/box/syndie_kit/spy
name = "spy kit"
desc = "For when you want to conduct voyeurism from afar."
-
-/obj/item/weapon/storage/box/syndie_kit/spy/New()
- ..()
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/camerabug/spy(src)
- new /obj/item/device/bug_monitor/spy(src)
+ starts_with = list(
+ /obj/item/device/camerabug/spy = 6,
+ /obj/item/device/bug_monitor/spy
+ )
/obj/item/weapon/storage/box/syndie_kit/g9mm
name = "\improper Smooth operator"
desc = "Compact 9mm with silencer kit."
-
-/obj/item/weapon/storage/box/syndie_kit/g9mm/New()
- ..()
- new /obj/item/weapon/gun/projectile/pistol(src)
- new /obj/item/weapon/silencer(src)
+ starts_with = list(
+ /obj/item/weapon/gun/projectile/pistol,
+ /obj/item/weapon/silencer
+ )
/obj/item/weapon/storage/box/syndie_kit/toxin
name = "toxin kit"
desc = "An apple will not be enough to keep the doctor away after this."
-
-/obj/item/weapon/storage/box/syndie_kit/toxin/New()
- ..()
- new /obj/item/weapon/reagent_containers/glass/beaker/vial/random/toxin(src)
- new /obj/item/weapon/reagent_containers/syringe(src)
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/glass/beaker/vial/random/toxin,
+ /obj/item/weapon/reagent_containers/syringe
+ )
/obj/item/weapon/storage/box/syndie_kit/cigarette
name = "\improper Tricky smokes"
desc = "Comes with the following brands of cigarettes, in this order: 2xFlash, 2xSmoke, 1xMindBreaker, 1xTricordrazine. Avoid mixing them up."
-/obj/item/weapon/storage/box/syndie_kit/cigarette/New()
- ..()
+/obj/item/weapon/storage/box/syndie_kit/cigarette/initialize()
+ . = ..()
var/obj/item/weapon/storage/fancy/cigarettes/pack
+
pack = new /obj/item/weapon/storage/fancy/cigarettes(src)
fill_cigarre_package(pack, list("aluminum" = 5, "potassium" = 5, "sulfur" = 5))
pack.desc += " 'F' has been scribbled on it."
@@ -222,6 +191,8 @@
new /obj/item/weapon/flame/lighter/zippo(src)
+ calibrate_size()
+
/proc/fill_cigarre_package(var/obj/item/weapon/storage/fancy/cigarettes/C, var/list/reagents)
for(var/reagent in reagents)
C.reagents.add_reagent(reagent, reagents[reagent] * C.storage_slots)
@@ -229,72 +200,52 @@
/obj/item/weapon/storage/box/syndie_kit/ewar_voice
name = "Electrowarfare and Voice Synthesiser kit"
desc = "Kit for confounding organic and synthetic entities alike."
-
-/obj/item/weapon/storage/box/syndie_kit/ewar_voice/New()
- ..()
- new /obj/item/rig_module/electrowarfare_suite(src)
- new /obj/item/rig_module/voice(src)
-
+ starts_with = list(
+ /obj/item/rig_module/electrowarfare_suite,
+ /obj/item/rig_module/voice
+ )
/obj/item/weapon/storage/secure/briefcase/money
name = "suspicious briefcase"
desc = "An ominous briefcase that has the unmistakeable smell of old, stale, cigarette smoke, and gives those who look at it a bad feeling."
-
-
-
-
-/obj/item/weapon/storage/secure/briefcase/money/New()
- ..()
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
- new /obj/item/weapon/spacecash/c1000(src)
+ starts_with = list(/obj/item/weapon/spacecash/c1000 = 10)
/obj/item/weapon/storage/box/syndie_kit/combat_armor
name = "combat armor kit"
desc = "Contains a full set of combat armor."
+ starts_with = list(
+ /obj/item/clothing/head/helmet/combat,
+ /obj/item/clothing/suit/armor/combat,
+ /obj/item/clothing/gloves/arm_guard/combat,
+ /obj/item/clothing/shoes/leg_guard/combat
+ )
-/obj/item/weapon/storage/box/syndie_kit/combat_armor/New()
- ..()
- new /obj/item/clothing/head/helmet/combat(src)
- new /obj/item/clothing/suit/armor/combat(src)
- new /obj/item/clothing/gloves/arm_guard/combat(src)
- new /obj/item/clothing/shoes/leg_guard/combat(src)
- return
+/obj/item/weapon/storage/box/syndie_kit/demolitions
+ starts_with = list(
+ /obj/item/weapon/syndie/c4explosive,
+ /obj/item/weapon/screwdriver
+ )
-/obj/item/weapon/storage/box/syndie_kit/demolitions/New()
- ..()
- new /obj/item/weapon/syndie/c4explosive(src)
- new /obj/item/weapon/screwdriver(src)
-
-/obj/item/weapon/storage/box/syndie_kit/demolitions_heavy/New()
- ..()
- new /obj/item/weapon/syndie/c4explosive/heavy(src)
- new /obj/item/weapon/screwdriver(src)
-
-/obj/item/weapon/storage/box/syndie_kit/demolitions_super_heavy/New()
- ..()
- new /obj/item/weapon/syndie/c4explosive/heavy/super_heavy(src)
- new /obj/item/weapon/screwdriver(src)
+/obj/item/weapon/storage/box/syndie_kit/demolitions_heavy
+ starts_with = list(
+ /obj/item/weapon/syndie/c4explosive/heavy,
+ /obj/item/weapon/screwdriver
+ )
+/obj/item/weapon/storage/box/syndie_kit/demolitions_super_heavy
+ starts_with = list(
+ /obj/item/weapon/syndie/c4explosive/heavy/super_heavy,
+ /obj/item/weapon/screwdriver
+ )
/obj/item/weapon/storage/secure/briefcase/rifle
name = "secure briefcase"
-
-/obj/item/weapon/storage/secure/briefcase/rifle/New()
- ..()
- new /obj/item/sniper_rifle_part/barrel(src)
- new /obj/item/sniper_rifle_part/stock(src)
- new /obj/item/sniper_rifle_part/trigger_group(src)
-
- for(var/i = 1 to 4)
- new /obj/item/ammo_casing/a145(src)
+ starts_with = list(
+ /obj/item/sniper_rifle_part/barrel,
+ /obj/item/sniper_rifle_part/stock,
+ /obj/item/sniper_rifle_part/trigger_group,
+ /obj/item/ammo_casing/a145 = 4
+ )
/obj/item/weapon/storage/secure/briefcase/fuelrod
name = "heavy briefcase"
@@ -303,14 +254,12 @@
description_antag = "This case will likely contain a charged fuel rod gun, and a few fuel rods to go with it. It can only hold the fuel rod gun, fuel rods, batteries, a screwdriver, and stock machine parts."
force = 12 //Anti-rad lined i.e. Lead, probably gonna hurt a bit if you get bashed with it.
can_hold = list(/obj/item/weapon/gun/magnetic/fuelrod, /obj/item/weapon/fuel_assembly, /obj/item/weapon/cell, /obj/item/weapon/stock_parts, /obj/item/weapon/screwdriver)
-
-
-/obj/item/weapon/storage/secure/briefcase/fuelrod/New()
- ..()
- new /obj/item/weapon/gun/magnetic/fuelrod(src)
- new /obj/item/weapon/fuel_assembly/deuterium(src)
- new /obj/item/weapon/fuel_assembly/deuterium(src)
- new /obj/item/weapon/fuel_assembly/tritium(src)
- new /obj/item/weapon/fuel_assembly/tritium(src)
- new /obj/item/weapon/fuel_assembly/phoron(src)
- new /obj/item/weapon/screwdriver(src)
+ starts_with = list(
+ /obj/item/weapon/gun/magnetic/fuelrod,
+ /obj/item/weapon/fuel_assembly/deuterium,
+ /obj/item/weapon/fuel_assembly/deuterium,
+ /obj/item/weapon/fuel_assembly/tritium,
+ /obj/item/weapon/fuel_assembly/tritium,
+ /obj/item/weapon/fuel_assembly/phoron,
+ /obj/item/weapon/screwdriver
+ )
diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm
index 30d81e1ba9..cb376787ab 100644
--- a/code/game/objects/items/weapons/storage/wallets.dm
+++ b/code/game/objects/items/weapons/storage/wallets.dm
@@ -10,6 +10,9 @@
/obj/item/weapon/card,
/obj/item/clothing/mask/smokable/cigarette/,
/obj/item/device/flashlight/pen,
+ /obj/item/device/tape,
+ /obj/item/weapon/cartridge,
+ /obj/item/device/encryptionkey,
/obj/item/seeds,
/obj/item/stack/medical,
/obj/item/weapon/coin,
@@ -18,13 +21,21 @@
/obj/item/weapon/implanter,
/obj/item/weapon/flame/lighter,
/obj/item/weapon/flame/match,
+ /obj/item/weapon/forensics,
+ /obj/item/weapon/glass_extra,
+ /obj/item/weapon/haircomb,
+ /obj/item/weapon/hand,
+ /obj/item/weapon/key,
+ /obj/item/weapon/lipstick,
/obj/item/weapon/paper,
/obj/item/weapon/pen,
/obj/item/weapon/photo,
/obj/item/weapon/reagent_containers/dropper,
+ /obj/item/weapon/sample,
/obj/item/weapon/screwdriver,
/obj/item/weapon/stamp,
- /obj/item/clothing/accessory/permit
+ /obj/item/clothing/accessory/permit,
+ /obj/item/clothing/accessory/badge
)
slot_flags = SLOT_ID
@@ -118,4 +129,4 @@
name = "women's wallet"
desc = "A stylish wallet typically used by women."
icon_state = "girl_wallet"
- item_state_slots = list(slot_r_hand_str = "wowallet", slot_l_hand_str = "wowallet")
\ No newline at end of file
+ item_state_slots = list(slot_r_hand_str = "wowallet", slot_l_hand_str = "wowallet")
diff --git a/code/game/objects/items/weapons/syndie.dm b/code/game/objects/items/weapons/syndie.dm
index 5d0d1f3863..c47489272b 100644
--- a/code/game/objects/items/weapons/syndie.dm
+++ b/code/game/objects/items/weapons/syndie.dm
@@ -13,20 +13,29 @@
desc = "A small wrapped package."
w_class = ITEMSIZE_NORMAL
- var/power = 1 /*Size of the explosion.*/
+ var/devastate = 1
+ var/heavy_impact = 2
+ var/light_impact = 4
+ var/flash_range = 5
var/size = "small" /*Used for the icon, this one will make c-4small_0 for the off state.*/
/obj/item/weapon/syndie/c4explosive/heavy
icon_state = "c-4large_0"
item_state = "radio"
desc = "A mysterious package, it's quite heavy."
- power = 2
+ devastate = 1
+ heavy_impact = 3
+ light_impact = 5
+ flash_range = 7
size = "large"
/obj/item/weapon/syndie/c4explosive/heavy/super_heavy
name = "large-sized package"
desc = "A mysterious package, it's quite exceptionally heavy."
- power = 3
+ devastate = 2
+ heavy_impact = 5
+ light_impact = 7
+ flash_range = 7
/obj/item/weapon/syndie/c4explosive/New()
var/K = rand(1,2000)
@@ -43,7 +52,7 @@
for(var/mob/O in hearers(src, null))
O.show_message("\icon[src] The [src.name] beeps! ")
sleep(50)
- explosion(get_turf(src), power, power*2, power*3, power*4, power*5)
+ explosion(get_turf(src), devastate, heavy_impact, light_impact, flash_range)
for(var/dirn in cardinal) //This is to guarantee that C4 at least breaks down all immediately adjacent walls and doors.
var/turf/simulated/wall/T = get_step(src,dirn)
if(locate(/obj/machinery/door/airlock) in T)
@@ -54,6 +63,12 @@
T.dismantle_wall(1)
qdel(src)
+/obj/item/weapon/syndie/c4explosive/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/weapon/flame/lighter/zippo/c4detonator))
+ var/obj/item/weapon/flame/lighter/zippo/c4detonator/D = W
+ D.bomb = src
+ return
+ ..()
/*Detonator, disguised as a lighter*/
/*Click it when closed to open, when open to bring up a prompt asking you if you want to close it or press the button.*/
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index 0ff657e9cc..efacad4942 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -186,8 +186,8 @@
src.air_contents.adjust_gas("phoron", (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
/obj/item/weapon/tank/emergency/phoron/double
- name = "double emergency nitrogen tank"
- icon_state = "emergency_double_nitrogen"
+ name = "double emergency phoron tank"
+ icon_state = "emergency_double_nitro"
gauge_icon = "indicator_emergency_double"
volume = 10
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index d17cb21472..49608c649a 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -8,7 +8,7 @@ var/list/global/tank_gauge_cache = list()
name = "tank"
icon = 'icons/obj/tank.dmi'
sprite_sheets = list(
- "Teshari" = 'icons/mob/species/seromi/back.dmi'
+ SPECIES_TESHARI = 'icons/mob/species/seromi/back.dmi'
)
var/gauge_icon = "indicator_tank"
diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm
index 30257a2b84..83e944f593 100644
--- a/code/game/objects/items/weapons/tape.dm
+++ b/code/game/objects/items/weapons/tape.dm
@@ -131,7 +131,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "tape"
w_class = ITEMSIZE_TINY
- layer = 4
+ plane = MOB_PLANE
anchored = 1 //it's sticky, no you cant move it
var/obj/item/weapon/stuck = null
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index e3d38b8774..62b3d9b1bb 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -236,7 +236,7 @@
..()
/obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob)
- if(user.a_intent == I_HELP && (C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable)))
+ if(istype(C) && user.a_intent == I_HELP && (C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable)))
usr.visible_message("\The [usr] cuts \the [C]'s restraints with \the [src]!",\
"You cut \the [C]'s restraints with \the [src]!",\
"You hear cable being cut.")
diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm
index c2ea991d98..8d9977cc17 100644
--- a/code/game/objects/items/weapons/trays.dm
+++ b/code/game/objects/items/weapons/trays.dm
@@ -52,9 +52,7 @@
if (istype(location, /turf/simulated))
location.add_blood(H) ///Plik plik, the sound of blood
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)")
+ add_attack_logs(user,M,"Hit with [src]")
if(prob(15))
M.Weaken(3)
@@ -190,7 +188,7 @@
carrying.Add(I)
Img.icon = I.icon
Img.icon_state = I.icon_state
- Img.layer = 30 + I.layer
+ Img.layer = layer + I.layer*0.01
if(istype(I, /obj/item/weapon/material))
var/obj/item/weapon/material/O = I
if(O.applies_material_colour)
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 8938e611c0..b5ae0912e9 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -17,10 +17,7 @@
/obj/item/weapon/nullrod/attack(mob/M as mob, mob/living/user as mob) //Paste from old-code to decult with a null rod.
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
-
- msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
+ add_attack_logs(user,M,"Hit with [src] (nullrod)")
user.setClickCooldown(user.get_attack_speed(src))
user.do_attack_animation(M)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 84f9f88602..3835b2a24b 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -1,4 +1,6 @@
/obj
+ layer = OBJ_LAYER
+ plane = OBJ_PLANE
//Used to store information about the contents of the object.
var/list/matter
var/w_class // Size of the object.
@@ -13,6 +15,9 @@
var/armor_penetration = 0
var/show_messages
var/preserve_item = 0 //whether this object is preserved when its owner goes into cryo-storage, gateway, etc
+ var/can_speak = 0 //For MMIs and admin trickery. If an object has a brainmob in its contents, set this to 1 to allow it to speak.
+
+ var/show_examine = TRUE // Does this pop up on a mob when the mob is examined?
/obj/Destroy()
processing_objects -= src
diff --git a/code/game/objects/random/_random.dm b/code/game/objects/random/_random.dm
new file mode 100644
index 0000000000..29272a7247
--- /dev/null
+++ b/code/game/objects/random/_random.dm
@@ -0,0 +1,138 @@
+/obj/random
+ name = "random object"
+ desc = "This item type is used to spawn random objects at round-start"
+ icon = 'icons/misc/mark.dmi'
+ icon_state = "rup"
+ var/spawn_nothing_percentage = 0 // this variable determines the likelyhood that this random object will not spawn anything
+
+// creates a new object and deletes itself
+/obj/random/New()
+ ..()
+ spawn()
+ if(istype(src.loc, /obj/structure/loot_pile)) //Spawning from a lootpile is weird, need to wait until we're out of it to do our work.
+ while(istype(src.loc, /obj/structure/loot_pile))
+ sleep(1)
+ if (!prob(spawn_nothing_percentage))
+ spawn_item()
+ qdel(src)
+
+// this function should return a specific item to spawn
+/obj/random/proc/item_to_spawn()
+ return 0
+
+// creates the random item
+/obj/random/proc/spawn_item()
+ var/build_path = item_to_spawn()
+
+ var/atom/A = new build_path(src.loc)
+ if(pixel_x || pixel_y)
+ A.pixel_x = pixel_x
+ A.pixel_y = pixel_y
+
+var/list/random_junk_
+var/list/random_useful_
+/proc/get_random_useful_type()
+ if(!random_useful_)
+ random_useful_ = subtypesof(/obj/item/weapon/pen/crayon)
+ random_useful_ += /obj/item/weapon/pen
+ random_useful_ += /obj/item/weapon/pen/blue
+ random_useful_ += /obj/item/weapon/pen/red
+ random_useful_ += /obj/item/weapon/pen/multi
+ random_useful_ += /obj/item/weapon/storage/box/matches
+ random_useful_ += /obj/item/stack/material/cardboard
+ return pick(random_useful_)
+
+/proc/get_random_junk_type()
+ if(prob(20)) // Misc. clutter
+ return /obj/effect/decal/cleanable/generic
+ if(prob(70)) // Misc. junk
+ if(!random_junk_)
+ random_junk_ = subtypesof(/obj/item/trash)
+ random_junk_ += typesof(/obj/item/weapon/cigbutt)
+ random_junk_ += /obj/effect/decal/cleanable/spiderling_remains
+ random_junk_ += /obj/effect/decal/remains/mouse
+ random_junk_ += /obj/effect/decal/remains/robot
+ random_junk_ += /obj/item/weapon/paper/crumpled
+ random_junk_ += /obj/item/inflatable/torn
+ random_junk_ += /obj/effect/decal/cleanable/molten_item
+ random_junk_ += /obj/item/weapon/material/shard
+
+ random_junk_ -= /obj/item/trash/plate
+ random_junk_ -= /obj/item/trash/snack_bowl
+ random_junk_ -= /obj/item/trash/syndi_cakes
+ random_junk_ -= /obj/item/trash/tray
+ return pick(random_junk_)
+ // Misc. actually useful stuff
+ return get_random_useful_type()
+
+/////////////////////////////////////////////////////////////////////////
+
+/obj/random/single
+ name = "randomly spawned object"
+ desc = "This item type is used to randomly spawn a given object at round-start"
+ icon_state = "x3"
+ var/spawn_object = null
+
+/obj/random/single/item_to_spawn()
+ return ispath(spawn_object) ? spawn_object : text2path(spawn_object)
+
+//Multiple Object Spawn
+
+/obj/random/multiple
+
+/obj/random/multiple/spawn_item()
+ var/list/things_to_make = item_to_spawn()
+ for(var/new_type in things_to_make)
+ new new_type(src.loc)
+
+/*
+// Multi Point Spawn
+// Selects one spawn point out of a group of points with the same ID and asks it to generate its items
+*/
+var/list/multi_point_spawns
+
+/obj/random_multi
+ name = "random object spawn point"
+ desc = "This item type is used to spawn random objects at round-start. Only one spawn point for a given group id is selected."
+ icon = 'icons/misc/mark.dmi'
+ icon_state = "x3"
+ invisibility = INVISIBILITY_MAXIMUM
+ var/id // Group id
+ var/weight // Probability weight for this spawn point
+
+/obj/random_multi/initialize()
+ . = ..()
+ weight = max(1, round(weight))
+
+ if(!multi_point_spawns)
+ multi_point_spawns = list()
+ var/list/spawnpoints = multi_point_spawns[id]
+ if(!spawnpoints)
+ spawnpoints = list()
+ multi_point_spawns[id] = spawnpoints
+ spawnpoints[src] = weight
+
+/obj/random_multi/Destroy()
+ var/list/spawnpoints = multi_point_spawns[id]
+ spawnpoints -= src
+ if(!spawnpoints.len)
+ multi_point_spawns -= id
+ . = ..()
+
+/obj/random_multi/proc/generate_items()
+ return
+
+/obj/random_multi/single_item
+ var/item_path // Item type to spawn
+
+/obj/random_multi/single_item/generate_items()
+ new item_path(loc)
+
+/hook/roundstart/proc/generate_multi_spawn_items()
+ for(var/id in multi_point_spawns)
+ var/list/spawn_points = multi_point_spawns[id]
+ var/obj/random_multi/rm = pickweight(spawn_points)
+ rm.generate_items()
+ for(var/entry in spawn_points)
+ qdel(entry)
+ return 1
\ No newline at end of file
diff --git a/code/game/objects/random/guns_and_ammo.dm b/code/game/objects/random/guns_and_ammo.dm
new file mode 100644
index 0000000000..a910881a76
--- /dev/null
+++ b/code/game/objects/random/guns_and_ammo.dm
@@ -0,0 +1,129 @@
+/obj/random/energy
+ name = "Random Energy Weapon"
+ desc = "This is a random security weapon."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "energykill100"
+
+/obj/random/energy/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/gun/energy/laser,
+ prob(4);/obj/item/weapon/gun/energy/gun,
+ prob(3);/obj/item/weapon/gun/energy/gun/burst,
+ prob(1);/obj/item/weapon/gun/energy/gun/nuclear,
+ prob(2);/obj/item/weapon/gun/energy/retro,
+ prob(2);/obj/item/weapon/gun/energy/lasercannon,
+ prob(3);/obj/item/weapon/gun/energy/xray,
+ prob(1);/obj/item/weapon/gun/energy/sniperrifle,
+ prob(1);/obj/item/weapon/gun/energy/plasmastun,
+ prob(2);/obj/item/weapon/gun/energy/ionrifle,
+ prob(2);/obj/item/weapon/gun/energy/ionrifle/pistol,
+ prob(3);/obj/item/weapon/gun/energy/toxgun,
+ prob(4);/obj/item/weapon/gun/energy/taser,
+ prob(2);/obj/item/weapon/gun/energy/crossbow/largecrossbow,
+ prob(4);/obj/item/weapon/gun/energy/stunrevolver)
+
+/obj/random/energy/sec
+ name = "Random Security Energy Weapon"
+ desc = "This is a random security weapon."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "energykill100"
+
+/obj/random/energy/sec/item_to_spawn()
+ return pick(prob(2);/obj/item/weapon/gun/energy/laser,
+ prob(2);/obj/item/weapon/gun/energy/gun)
+
+/obj/random/projectile
+ name = "Random Projectile Weapon"
+ desc = "This is a random projectile weapon."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "revolver"
+
+/obj/random/projectile/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/gun/projectile/automatic/wt550,
+ prob(3);/obj/item/weapon/gun/projectile/automatic/mini_uzi,
+ prob(3);/obj/item/weapon/gun/projectile/automatic/tommygun,
+ prob(2);/obj/item/weapon/gun/projectile/automatic/c20r,
+ prob(2);/obj/item/weapon/gun/projectile/automatic/sts35,
+ prob(2);/obj/item/weapon/gun/projectile/automatic/z8,
+ prob(4);/obj/item/weapon/gun/projectile/colt,
+ prob(2);/obj/item/weapon/gun/projectile/deagle,
+ prob(1);/obj/item/weapon/gun/projectile/deagle/camo,
+ prob(1);/obj/item/weapon/gun/projectile/deagle/gold,
+ prob(3);/obj/item/weapon/gun/projectile/derringer,
+ prob(1);/obj/item/weapon/gun/projectile/heavysniper,
+ prob(4);/obj/item/weapon/gun/projectile/luger,
+ prob(3);/obj/item/weapon/gun/projectile/luger/brown,
+ prob(4);/obj/item/weapon/gun/projectile/sec,
+ prob(3);/obj/item/weapon/gun/projectile/sec/wood,
+ prob(4);/obj/item/weapon/gun/projectile/p92x,
+ prob(3);/obj/item/weapon/gun/projectile/p92x/brown,
+ prob(4);/obj/item/weapon/gun/projectile/pistol,
+ prob(5);/obj/item/weapon/gun/projectile/pirate,
+ prob(2);/obj/item/weapon/gun/projectile/revolver,
+ prob(4);/obj/item/weapon/gun/projectile/revolver/deckard,
+ prob(4);/obj/item/weapon/gun/projectile/revolver/detective,
+ prob(2);/obj/item/weapon/gun/projectile/revolver/judge,
+ prob(3);/obj/item/weapon/gun/projectile/revolver/lemat,
+ prob(2);/obj/item/weapon/gun/projectile/revolver/mateba,
+ prob(4);/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
+ prob(3);/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
+ prob(3);/obj/item/weapon/gun/projectile/shotgun/pump,
+ prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat,
+ prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle,
+ prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever,
+ prob(2);/obj/item/weapon/gun/projectile/silenced)
+
+/obj/random/projectile/sec
+ name = "Random Security Projectile Weapon"
+ desc = "This is a random security weapon."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "revolver"
+
+/obj/random/projectile/sec/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/gun/projectile/shotgun/pump,
+ prob(2);/obj/item/weapon/gun/projectile/automatic/wt550,
+ prob(1);/obj/item/weapon/gun/projectile/shotgun/pump/combat)
+
+/obj/random/handgun
+ name = "Random Handgun"
+ desc = "This is a random sidearm."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "secgundark"
+
+/obj/random/handgun/item_to_spawn()
+ return pick(prob(4);/obj/item/weapon/gun/projectile/sec,
+ prob(4);/obj/item/weapon/gun/projectile/p92x,
+ prob(3);/obj/item/weapon/gun/projectile/sec/wood,
+ prob(3);/obj/item/weapon/gun/projectile/p92x/brown,
+ prob(3);/obj/item/weapon/gun/projectile/colt,
+ prob(2);/obj/item/weapon/gun/projectile/luger,
+ prob(2);/obj/item/weapon/gun/energy/gun,
+ prob(2);/obj/item/weapon/gun/projectile/pistol,
+ prob(1);/obj/item/weapon/gun/energy/retro,
+ prob(1);/obj/item/weapon/gun/projectile/luger/brown)
+
+/obj/random/handgun/sec
+ name = "Random Security Handgun"
+ desc = "This is a random security sidearm."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "secgundark"
+
+/obj/random/handgun/sec/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/gun/projectile/sec,
+ prob(1);/obj/item/weapon/gun/projectile/sec/wood)
+
+/obj/random/ammo
+ name = "Random Ammunition"
+ desc = "This is random security ammunition."
+ icon = 'icons/obj/ammo.dmi'
+ icon_state = "45-10"
+
+/obj/random/ammo/item_to_spawn()
+ return pick(prob(6);/obj/item/weapon/storage/box/beanbags,
+ prob(2);/obj/item/weapon/storage/box/shotgunammo,
+ prob(4);/obj/item/weapon/storage/box/shotgunshells,
+ prob(1);/obj/item/weapon/storage/box/stunshells,
+ prob(2);/obj/item/ammo_magazine/m45,
+ prob(4);/obj/item/ammo_magazine/m45/rubber,
+ prob(4);/obj/item/ammo_magazine/m45/flash,
+ prob(2);/obj/item/ammo_magazine/m9mmt,
+ prob(6);/obj/item/ammo_magazine/m9mmt/rubber)
\ No newline at end of file
diff --git a/code/game/objects/random/maintenance.dm b/code/game/objects/random/maintenance.dm
new file mode 100644
index 0000000000..e7e45a8791
--- /dev/null
+++ b/code/game/objects/random/maintenance.dm
@@ -0,0 +1,309 @@
+/obj/random/maintenance //Clutter and loot for maintenance and away missions
+ name = "random maintenance item"
+ desc = "This is a random maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/item_to_spawn()
+ return pick(prob(300);/obj/random/tech_supply,
+ prob(200);/obj/random/medical,
+ prob(100);/obj/random/firstaid,
+ prob(10);/obj/random/contraband,
+ prob(50);/obj/random/action_figure,
+ prob(50);/obj/random/plushie,
+ prob(200);/obj/random/junk,
+ prob(200);/obj/random/material,
+ prob(50);/obj/random/toy,
+ prob(100);/obj/random/tank,
+ prob(50);/obj/random/soap,
+ prob(60);/obj/random/drinkbottle,
+ prob(500);/obj/random/maintenance/clean)
+
+/obj/random/maintenance/clean
+/*Maintenance loot lists without the trash, for use inside things.
+Individual items to add to the maintenance list should go here, if you add
+something, make sure it's not in one of the other lists.*/
+ name = "random clean maintenance item"
+ desc = "This is a random clean maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/clean/item_to_spawn()
+ return pick(prob(10);/obj/random/contraband,
+ prob(2);/obj/item/device/flashlight/flare,
+ prob(2);/obj/item/device/flashlight/glowstick,
+ prob(2);/obj/item/device/flashlight/glowstick/blue,
+ prob(1);/obj/item/device/flashlight/glowstick/orange,
+ prob(1);/obj/item/device/flashlight/glowstick/red,
+ prob(1);/obj/item/device/flashlight/glowstick/yellow,
+ prob(1);/obj/item/device/flashlight/pen,
+ prob(4);/obj/item/weapon/cell,
+ prob(4);/obj/item/weapon/cell/device,
+ prob(3);/obj/item/weapon/cell/high,
+ prob(2);/obj/item/weapon/cell/super,
+ prob(5);/obj/random/cigarettes,
+ prob(3);/obj/item/clothing/mask/gas,
+ prob(2);/obj/item/clothing/mask/gas/half,
+ prob(4);/obj/item/clothing/mask/breath,
+ prob(2);/obj/item/weapon/reagent_containers/glass/rag,
+ prob(4);/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
+ prob(2);/obj/item/weapon/storage/secure/briefcase,
+ prob(4);/obj/item/weapon/storage/briefcase,
+ prob(5);/obj/item/weapon/storage/backpack,
+ prob(5);/obj/item/weapon/storage/backpack/satchel/norm,
+ prob(4);/obj/item/weapon/storage/backpack/satchel,
+ prob(3);/obj/item/weapon/storage/backpack/dufflebag,
+ prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie,
+ prob(5);/obj/item/weapon/storage/box,
+ prob(3);/obj/item/weapon/storage/box/donkpockets,
+ prob(2);/obj/item/weapon/storage/box/sinpockets,
+ prob(1);/obj/item/weapon/storage/box/cups,
+ prob(3);/obj/item/weapon/storage/box/mousetraps,
+ prob(3);/obj/item/weapon/storage/wallet,
+ prob(1);/obj/item/device/paicard,
+ prob(2);/obj/item/clothing/shoes/galoshes,
+ prob(1);/obj/item/clothing/shoes/syndigaloshes,
+ prob(4);/obj/item/clothing/shoes/black,
+ prob(4);/obj/item/clothing/shoes/laceup,
+ prob(4);/obj/item/clothing/shoes/black,
+ prob(4);/obj/item/clothing/shoes/leather,
+ prob(1);/obj/item/clothing/gloves/yellow,
+ prob(3);/obj/item/clothing/gloves/botanic_leather,
+ prob(2);/obj/item/clothing/gloves/sterile/latex,
+ prob(5);/obj/item/clothing/gloves/white,
+ prob(5);/obj/item/clothing/gloves/rainbow,
+ prob(2);/obj/item/clothing/gloves/fyellow,
+ prob(1);/obj/item/clothing/glasses/sunglasses,
+ prob(3);/obj/item/clothing/glasses/meson,
+ prob(2);/obj/item/clothing/glasses/meson/prescription,
+ prob(1);/obj/item/clothing/glasses/welding,
+ prob(1);/obj/item/clothing/head/bio_hood/general,
+ prob(4);/obj/item/clothing/head/hardhat,
+ prob(3);/obj/item/clothing/head/hardhat/red,
+ prob(1);/obj/item/clothing/head/ushanka,
+ prob(2);/obj/item/clothing/head/welding,
+ prob(4);/obj/item/clothing/suit/storage/hazardvest,
+ prob(1);/obj/item/clothing/suit/space/emergency,
+ prob(3);/obj/item/clothing/suit/storage/toggle/bomber,
+ prob(1);/obj/item/clothing/suit/bio_suit/general,
+ prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/black,
+ prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/blue,
+ prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/red,
+ prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/yellow,
+ prob(3);/obj/item/clothing/suit/storage/toggle/brown_jacket,
+ prob(3);/obj/item/clothing/suit/storage/toggle/leather_jacket,
+ prob(1);/obj/item/clothing/suit/storage/vest/press,
+ prob(3);/obj/item/clothing/suit/storage/apron,
+ prob(4);/obj/item/clothing/under/color/grey,
+ prob(2);/obj/item/clothing/under/syndicate/tacticool,
+ prob(2);/obj/item/clothing/under/pants/camo,
+ prob(1);/obj/item/clothing/under/harness,
+ prob(1);/obj/item/clothing/under/tactical,
+ prob(3);/obj/item/clothing/accessory/storage/webbing,
+ prob(3);/obj/item/weapon/camera_assembly,
+ prob(4);/obj/item/weapon/caution,
+ prob(3);/obj/item/weapon/caution/cone,
+ prob(1);/obj/item/weapon/card/emag_broken,
+ prob(2);/obj/item/device/camera,
+ prob(3);/obj/item/device/pda,
+ prob(3);/obj/item/device/radio/headset)
+
+/obj/random/maintenance/security
+/*Maintenance loot list. This one is for around security areas*/
+ name = "random security maintenance item"
+ desc = "This is a random security maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/security/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(2);/obj/item/device/flashlight/maglight,
+ prob(2);/obj/item/device/flash,
+ prob(1);/obj/item/weapon/cell/device/weapon,
+ prob(1);/obj/item/clothing/mask/gas/swat,
+ prob(1);/obj/item/clothing/mask/gas/syndicate,
+ prob(2);/obj/item/clothing/mask/balaclava,
+ prob(1);/obj/item/clothing/mask/balaclava/tactical,
+ prob(3);/obj/item/weapon/storage/backpack/security,
+ prob(3);/obj/item/weapon/storage/backpack/satchel/sec,
+ prob(2);/obj/item/weapon/storage/backpack/messenger/sec,
+ prob(2);/obj/item/weapon/storage/backpack/dufflebag/sec,
+ prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo,
+ prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/med,
+ prob(2);/obj/item/weapon/storage/box/swabs,
+ prob(2);/obj/item/weapon/storage/belt/security,
+ prob(1);/obj/item/weapon/grenade/flashbang,
+ prob(1);/obj/item/weapon/melee/baton,
+ prob(1);/obj/item/weapon/reagent_containers/spray/pepper,
+ prob(3);/obj/item/clothing/shoes/boots/jackboots,
+ prob(1);/obj/item/clothing/shoes/boots/swat,
+ prob(1);/obj/item/clothing/shoes/boots/combat,
+ prob(1);/obj/item/clothing/gloves/swat,
+ prob(1);/obj/item/clothing/gloves/combat,
+ prob(1);/obj/item/clothing/glasses/sunglasses/big,
+ prob(2);/obj/item/clothing/glasses/hud/security,
+ prob(1);/obj/item/clothing/glasses/sunglasses/sechud,
+ prob(1);/obj/item/clothing/glasses/sunglasses/sechud/aviator,
+ prob(1);/obj/item/clothing/glasses/sunglasses/sechud/tactical,
+ prob(3);/obj/item/clothing/head/beret/sec,
+ prob(3);/obj/item/clothing/head/beret/sec/corporate/officer,
+ prob(3);/obj/item/clothing/head/beret/sec/navy/officer,
+ prob(2);/obj/item/clothing/head/helmet,
+ prob(4);/obj/item/clothing/head/soft/sec,
+ prob(4);/obj/item/clothing/head/soft/sec/corp,
+ prob(3);/obj/item/clothing/suit/armor/vest,
+ prob(2);/obj/item/clothing/suit/armor/vest/security,
+ prob(2);/obj/item/clothing/suit/storage/vest/officer,
+ prob(1);/obj/item/clothing/suit/storage/vest/detective,
+ prob(1);/obj/item/clothing/suit/storage/vest/press,
+ prob(2);/obj/item/clothing/accessory/storage/black_vest,
+ prob(2);/obj/item/clothing/accessory/storage/black_drop_pouches,
+ prob(1);/obj/item/clothing/accessory/holster/leg,
+ prob(1);/obj/item/clothing/accessory/holster/hip,
+ prob(1);/obj/item/clothing/accessory/holster/waist,
+ prob(1);/obj/item/clothing/accessory/holster/armpit,
+ prob(2);/obj/item/clothing/ears/earmuffs,
+ prob(2);/obj/item/weapon/handcuffs,)
+
+/obj/random/maintenance/medical
+/*Maintenance loot list. This one is for around medical areas*/
+ name = "random medical maintenance item"
+ desc = "This is a random medical maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/medical/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(25);/obj/random/medical/lite,
+ prob(2);/obj/item/clothing/mask/breath/medical,
+ prob(2);/obj/item/clothing/mask/surgical,
+ prob(5);/obj/item/weapon/storage/backpack/medic,
+ prob(5);/obj/item/weapon/storage/backpack/satchel/med,
+ prob(5);/obj/item/weapon/storage/backpack/messenger/med,
+ prob(3);/obj/item/weapon/storage/backpack/dufflebag/med,
+ prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/med,
+ prob(2);/obj/item/weapon/storage/box/autoinjectors,
+ prob(3);/obj/item/weapon/storage/box/beakers,
+ prob(2);/obj/item/weapon/storage/box/bodybags,
+ prob(3);/obj/item/weapon/storage/box/syringes,
+ prob(3);/obj/item/weapon/storage/box/gloves,
+ prob(2);/obj/item/weapon/storage/belt/medical/emt,
+ prob(2);/obj/item/weapon/storage/belt/medical,
+ prob(1);/obj/item/clothing/shoes/boots/combat,
+ prob(3);/obj/item/clothing/shoes/white,
+ prob(2);/obj/item/clothing/gloves/sterile/nitrile,
+ prob(5);/obj/item/clothing/gloves/white,
+ prob(2);/obj/item/clothing/glasses/hud/health,
+ prob(1);/obj/item/clothing/glasses/hud/health/prescription,
+ prob(1);/obj/item/clothing/head/bio_hood/virology,
+ prob(4);/obj/item/clothing/suit/storage/toggle/labcoat,
+ prob(1);/obj/item/clothing/suit/bio_suit/general,
+ prob(2);/obj/item/clothing/under/rank/medical/paramedic,
+ prob(2);/obj/item/clothing/accessory/storage/black_vest,
+ prob(2);/obj/item/clothing/accessory/storage/white_vest,
+ prob(1);/obj/item/clothing/accessory/storage/white_drop_pouches,
+ prob(1);/obj/item/clothing/accessory/storage/black_drop_pouches,
+ prob(2);/obj/item/clothing/accessory/stethoscope)
+
+/obj/random/maintenance/engineering
+/*Maintenance loot list. This one is for around medical areas*/
+ name = "random engineering maintenance item"
+ desc = "This is a random engineering maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/engineering/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(2);/obj/item/device/flashlight/maglight,
+ prob(3);/obj/item/clothing/mask/gas/half,
+ prob(2);/obj/item/clothing/mask/balaclava,
+ prob(2);/obj/item/weapon/storage/briefcase/inflatable,
+ prob(5);/obj/item/weapon/storage/backpack/industrial,
+ prob(5);/obj/item/weapon/storage/backpack/satchel/eng,
+ prob(5);/obj/item/weapon/storage/backpack/messenger/engi,
+ prob(3);/obj/item/weapon/storage/backpack/dufflebag/eng,
+ prob(5);/obj/item/weapon/storage/box,
+ prob(2);/obj/item/weapon/storage/belt/utility/full,
+ prob(3);/obj/item/weapon/storage/belt/utility,
+ prob(3);/obj/item/clothing/head/beret/engineering,
+ prob(3);/obj/item/clothing/head/soft/yellow,
+ prob(2);/obj/item/clothing/head/orangebandana,
+ prob(2);/obj/item/clothing/head/hardhat/dblue,
+ prob(2);/obj/item/clothing/head/hardhat/orange,
+ prob(1);/obj/item/clothing/glasses/welding,
+ prob(2);/obj/item/clothing/head/welding,
+ prob(4);/obj/item/clothing/suit/storage/hazardvest,
+ prob(2);/obj/item/clothing/under/overalls,
+ prob(3);/obj/item/clothing/shoes/boots/workboots,
+ prob(1);/obj/item/clothing/shoes/magboots,
+ prob(2);/obj/item/clothing/accessory/storage/black_vest,
+ prob(2);/obj/item/clothing/accessory/storage/brown_vest,
+ prob(1);/obj/item/clothing/accessory/storage/brown_drop_pouches,
+ prob(3);/obj/item/clothing/ears/earmuffs,
+ prob(1);/obj/item/weapon/beartrap,
+ prob(2);/obj/item/weapon/handcuffs)
+
+/obj/random/maintenance/research
+/*Maintenance loot list. This one is for around medical areas*/
+ name = "random research maintenance item"
+ desc = "This is a random research maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/research/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(3);/obj/item/device/analyzer/plant_analyzer,
+ prob(1);/obj/item/device/flash/synthetic,
+ prob(2);/obj/item/weapon/bucket_sensor,
+ prob(1);/obj/item/weapon/cell/device/weapon,
+ prob(5);/obj/item/weapon/storage/backpack/toxins,
+ prob(5);/obj/item/weapon/storage/backpack/satchel/tox,
+ prob(5);/obj/item/weapon/storage/backpack/messenger/tox,
+ prob(2);/obj/item/weapon/storage/excavation,
+ prob(1);/obj/item/weapon/storage/backpack/holding,
+ prob(3);/obj/item/weapon/storage/box/beakers,
+ prob(3);/obj/item/weapon/storage/box/syringes,
+ prob(3);/obj/item/weapon/storage/box/gloves,
+ prob(2);/obj/item/clothing/gloves/sterile/latex,
+ prob(4);/obj/item/clothing/glasses/science,
+ prob(3);/obj/item/clothing/glasses/material,
+ prob(1);/obj/item/clothing/head/beret/purple,
+ prob(1);/obj/item/clothing/head/bio_hood/scientist,
+ prob(4);/obj/item/clothing/suit/storage/toggle/labcoat,
+ prob(4);/obj/item/clothing/suit/storage/toggle/labcoat/science,
+ prob(1);/obj/item/clothing/suit/bio_suit/scientist,
+ prob(4);/obj/item/clothing/under/rank/scientist,
+ prob(2);/obj/item/clothing/under/rank/scientist_new)
+
+/obj/random/maintenance/cargo
+/*Maintenance loot list. This one is for around cargo areas*/
+ name = "random cargo maintenance item"
+ desc = "This is a random cargo maintenance item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "gift1"
+
+/obj/random/maintenance/cargo/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(3);/obj/item/device/flashlight/lantern,
+ prob(4);/obj/item/weapon/pickaxe,
+ prob(5);/obj/item/weapon/storage/backpack/industrial,
+ prob(5);/obj/item/weapon/storage/backpack/satchel/norm,
+ prob(3);/obj/item/weapon/storage/backpack/dufflebag,
+ prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo,
+ prob(1);/obj/item/weapon/storage/toolbox/syndicate,
+ prob(1);/obj/item/weapon/storage/belt/utility/full,
+ prob(2);/obj/item/weapon/storage/belt/utility,
+ prob(4);/obj/item/device/toner,
+ prob(1);/obj/item/device/destTagger,
+ prob(3);/obj/item/clothing/glasses/material,
+ prob(3);/obj/item/clothing/head/soft/yellow,
+ prob(4);/obj/item/clothing/suit/storage/hazardvest,
+ prob(3);/obj/item/clothing/suit/storage/apron/overalls,
+ prob(4);/obj/item/clothing/suit/storage/apron,
+ prob(2);/obj/item/clothing/under/syndicate/tacticool,
+ prob(1);/obj/item/clothing/under/syndicate/combat,
+ prob(2);/obj/item/clothing/accessory/storage/black_vest,
+ prob(2);/obj/item/clothing/accessory/storage/brown_vest,
+ prob(3);/obj/item/clothing/ears/earmuffs,
+ prob(1);/obj/item/weapon/beartrap,
+ prob(2);/obj/item/weapon/handcuffs,)
diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm
new file mode 100644
index 0000000000..57ff7acdcd
--- /dev/null
+++ b/code/game/objects/random/mapping.dm
@@ -0,0 +1,395 @@
+/*
+// Least descriptive filename?
+// This is where all of the things that aren't really loot should go.
+// Barricades, mines, etc.
+*/
+
+/obj/random/junk //Broken items, or stuff that could be picked up
+ name = "random junk"
+ desc = "This is some random junk."
+ icon = 'icons/obj/trash.dmi'
+ icon_state = "trashbag3"
+
+/obj/random/junk/item_to_spawn()
+ return get_random_junk_type()
+
+/obj/random/trash //Mostly remains and cleanable decals. Stuff a janitor could clean up
+ name = "random trash"
+ desc = "This is some random trash."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "greenglow"
+
+/obj/random/trash/item_to_spawn()
+ return pick(/obj/effect/decal/remains/lizard,
+ /obj/effect/decal/cleanable/blood/gibs/robot,
+ /obj/effect/decal/cleanable/blood/oil,
+ /obj/effect/decal/cleanable/blood/oil/streak,
+ /obj/effect/decal/cleanable/spiderling_remains,
+ /obj/effect/decal/remains/mouse,
+ /obj/effect/decal/cleanable/vomit,
+ /obj/effect/decal/cleanable/blood/splatter,
+ /obj/effect/decal/cleanable/ash,
+ /obj/effect/decal/cleanable/generic,
+ /obj/effect/decal/cleanable/flour,
+ /obj/effect/decal/cleanable/dirt,
+ /obj/effect/decal/remains/robot)
+
+/obj/random/obstruction //Large objects to block things off in maintenance
+ name = "random obstruction"
+ desc = "This is a random obstruction."
+ icon = 'icons/obj/cult.dmi'
+ icon_state = "cultgirder"
+
+/obj/random/obstruction/item_to_spawn()
+ return pick(/obj/structure/barricade,
+ /obj/structure/girder,
+ /obj/structure/girder/displaced,
+ /obj/structure/girder/reinforced,
+ /obj/structure/grille,
+ /obj/structure/grille/broken,
+ /obj/structure/foamedmetal,
+ /obj/structure/inflatable,
+ /obj/structure/inflatable/door)
+
+/obj/random/landmine
+ name = "Random Land Mine"
+ desc = "This is a random land mine."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "uglymine"
+ spawn_nothing_percentage = 25
+
+/obj/random/landmine/item_to_spawn()
+ return pick(prob(30);/obj/effect/mine,
+ prob(25);/obj/effect/mine/frag,
+ prob(25);/obj/effect/mine/emp,
+ prob(10);/obj/effect/mine/stun,
+ prob(10);/obj/effect/mine/incendiary,)
+
+/obj/random_multi/single_item/captains_spare_id
+ name = "Multi Point - Captain's Spare"
+ id = "Captain's spare id"
+ item_path = /obj/item/weapon/card/id/gold/captain/spare
+
+/obj/random_multi/single_item/sfr_headset
+ name = "Multi Point - headset"
+ id = "SFR headset"
+ item_path = /obj/random/sfr
+
+// This is in here because it's spawned by the SFR Headset randomizer
+/obj/random/sfr
+ name = "random SFR headset"
+ desc = "This is a headset spawn."
+ icon = 'icons/misc/mark.dmi'
+ icon_state = "rup"
+
+/obj/random/sfr/item_to_spawn()
+ return pick(prob(25);/obj/item/device/radio/headset/heads/captain/sfr,
+ prob(25);/obj/item/device/radio/headset/headset_cargo/alt,
+ prob(25);/obj/item/device/radio/headset/headset_com/alt,
+ prob(25);/obj/item/device/radio/headset)
+
+// Mining Goodies
+/obj/random/multiple/minevault
+ name = "random vault loot"
+ desc = "Loot for mine vaults."
+ icon = 'icons/misc/mark.dmi'
+ icon_state = "rup"
+
+/obj/random/multiple/minevault/item_to_spawn()
+ return pick(
+ prob(5);list(
+ /obj/item/clothing/mask/smokable/pipe,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/rum,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus,
+ /obj/item/weapon/flame/lighter/zippo,
+ /obj/structure/closet/crate/hydroponics
+ ),
+ prob(5);list(
+ /obj/item/weapon/pickaxe/drill,
+ /obj/item/clothing/suit/space/void/mining,
+ /obj/item/clothing/head/helmet/space/void/mining,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(5);list(
+ /obj/item/weapon/pickaxe/drill,
+ /obj/item/clothing/suit/space/void/mining/alt,
+ /obj/item/clothing/head/helmet/space/void/mining/alt,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(5);list(
+ /obj/item/weapon/reagent_containers/glass/beaker/bluespace,
+ /obj/item/weapon/reagent_containers/glass/beaker/bluespace,
+ /obj/item/weapon/reagent_containers/glass/beaker/bluespace,
+ /obj/structure/closet/crate/science
+ ),
+ prob(5);list(
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/diamond,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/item/weapon/ore/gold,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(5);list(
+ /obj/item/weapon/pickaxe/drill,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/ore_box,
+ /obj/structure/closet/crate
+ ),
+ prob(5);list(
+ /obj/item/weapon/reagent_containers/glass/beaker/noreact,
+ /obj/item/weapon/reagent_containers/glass/beaker/noreact,
+ /obj/item/weapon/reagent_containers/glass/beaker/noreact,
+ /obj/structure/closet/crate/science
+ ),
+ prob(5);list(
+ /obj/item/weapon/storage/secure/briefcase/money,
+ /obj/structure/closet/crate/freezer/rations
+ ),
+ prob(5);list(
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/item/clothing/accessory/tie/horrible,
+ /obj/structure/closet/crate
+ ),
+ prob(5);list(
+ /obj/item/weapon/melee/baton,
+ /obj/item/weapon/melee/baton,
+ /obj/item/weapon/melee/baton,
+ /obj/item/weapon/melee/baton,
+ /obj/structure/closet/crate
+ ),
+ prob(5);list(
+ /obj/item/clothing/under/shorts/red,
+ /obj/item/clothing/under/shorts/blue,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/item/weapon/melee/baton/cattleprod,
+ /obj/item/weapon/melee/baton/cattleprod,
+ /obj/item/weapon/cell/high,
+ /obj/item/weapon/cell/high,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/item/latexballon,
+ /obj/item/latexballon,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/item/toy/syndicateballoon,
+ /obj/item/toy/syndicateballoon,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/item/weapon/rig/industrial/equipped,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/clothing/head/kitty,
+ /obj/item/clothing/head/kitty,
+ /obj/item/clothing/head/kitty,
+ /obj/item/clothing/head/kitty,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/random/coin,
+ /obj/random/coin,
+ /obj/random/coin,
+ /obj/random/coin,
+ /obj/random/coin,
+ /obj/structure/closet/crate/plastic
+ ),
+ prob(2);list(
+ /obj/random/multiple/voidsuit,
+ /obj/random/multiple/voidsuit,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/clothing/suit/space/syndicate/black/red,
+ /obj/item/clothing/head/helmet/space/syndicate/black/red,
+ /obj/item/clothing/suit/space/syndicate/black/red,
+ /obj/item/clothing/head/helmet/space/syndicate/black/red,
+ /obj/item/weapon/gun/projectile/automatic/mini_uzi,
+ /obj/item/weapon/gun/projectile/automatic/mini_uzi,
+ /obj/item/ammo_magazine/m45uzi,
+ /obj/item/ammo_magazine/m45uzi,
+ /obj/item/ammo_magazine/m45uzi/empty,
+ /obj/item/ammo_magazine/m45uzi/empty,
+ /obj/structure/closet/crate/plastic
+ ),
+ prob(2);list(
+ /obj/item/clothing/suit/ianshirt,
+ /obj/item/clothing/suit/ianshirt,
+ /obj/item/weapon/bedsheet/ian,
+ /obj/structure/closet/crate/plastic
+ ),
+ prob(2);list(
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/weapon/gun/projectile/garand,
+ /obj/item/weapon/gun/projectile/garand,
+ /obj/item/ammo_magazine/m762garand,
+ /obj/item/ammo_magazine/m762garand,
+ /obj/structure/closet/crate/plastic
+ ),
+ prob(2);list(
+ /obj/mecha/working/ripley/mining
+ ),
+ prob(2);list(
+ /obj/mecha/working/hoverpod/combatpod
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/silver,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/drill,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/jackhammer,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/diamond,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/diamonddrill,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/gold,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/pickaxe/plasmacutter,
+ /obj/item/weapon/storage/bag/ore,
+ /obj/item/clothing/glasses/material,
+ /obj/structure/closet/crate/engineering
+ ),
+ prob(2);list(
+ /obj/item/weapon/material/sword/katana,
+ /obj/item/weapon/material/sword/katana,
+ /obj/structure/closet/crate
+ ),
+ prob(2);list(
+ /obj/item/weapon/material/sword,
+ /obj/item/weapon/material/sword,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/clothing/mask/balaclava,
+ /obj/item/weapon/material/star,
+ /obj/item/weapon/material/star,
+ /obj/item/weapon/material/star,
+ /obj/item/weapon/material/star,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/weed_extract,
+ /obj/item/xenos_claw,
+ /obj/structure/closet/crate/science
+ ),
+ prob(1);list(
+ /obj/item/clothing/head/bearpelt,
+ /obj/item/clothing/under/soviet,
+ /obj/item/clothing/under/soviet,
+ /obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial,
+ /obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/weapon/gun/projectile/revolver/detective,
+ /obj/item/weapon/gun/projectile/contender,
+ /obj/item/weapon/gun/projectile/p92x,
+ /obj/item/weapon/gun/projectile/derringer,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/weapon/melee/cultblade,
+ /obj/item/clothing/suit/cultrobes,
+ /obj/item/clothing/head/culthood,
+ /obj/item/device/soulstone,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/weapon/vampiric,
+ /obj/item/weapon/vampiric,
+ /obj/structure/closet/crate/science
+ ),
+ prob(1);list(
+ /obj/item/weapon/archaeological_find
+ ),
+ prob(1);list(
+ /obj/item/weapon/melee/energy/sword,
+ /obj/item/weapon/melee/energy/sword,
+ /obj/item/weapon/melee/energy/sword,
+ /obj/item/weapon/shield/energy,
+ /obj/item/weapon/shield/energy,
+ /obj/structure/closet/crate/science
+ ),
+ prob(1);list(
+ /obj/item/weapon/storage/backpack/clown,
+ /obj/item/clothing/under/rank/clown,
+ /obj/item/clothing/shoes/clown_shoes,
+ /obj/item/device/pda/clown,
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/weapon/bikehorn,
+ /obj/item/toy/waterflower,
+ /obj/item/weapon/pen/crayon/rainbow,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/clothing/under/mime,
+ /obj/item/clothing/shoes/black,
+ /obj/item/device/pda/mime,
+ /obj/item/clothing/gloves/white,
+ /obj/item/clothing/mask/gas/mime,
+ /obj/item/clothing/head/beret,
+ /obj/item/clothing/suit/suspenders,
+ /obj/item/weapon/pen/crayon/mime,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing,
+ /obj/structure/closet/crate
+ ),
+ prob(1);list(
+ /obj/item/weapon/storage/belt/champion,
+ /obj/item/clothing/mask/luchador,
+ /obj/item/clothing/mask/luchador/rudos,
+ /obj/item/clothing/mask/luchador/tecnicos,
+ /obj/structure/closet/crate
+ )
+ )
diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm
new file mode 100644
index 0000000000..29b597d460
--- /dev/null
+++ b/code/game/objects/random/misc.dm
@@ -0,0 +1,490 @@
+/*
+// This is going to get so incredibly bloated.
+// But this is where all of the "Loot" goes. Anything fun or useful that doesn't deserve its own file, pile in.
+*/
+
+/obj/random/tool
+ name = "random tool"
+ desc = "This is a random tool"
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "welder"
+
+/obj/random/tool/item_to_spawn()
+ return pick(/obj/item/weapon/screwdriver,
+ /obj/item/weapon/wirecutters,
+ /obj/item/weapon/weldingtool,
+ /obj/item/weapon/weldingtool/largetank,
+ /obj/item/weapon/crowbar,
+ /obj/item/weapon/wrench,
+ /obj/item/device/flashlight,
+ /obj/item/device/multitool)
+
+/obj/random/tool/powermaint
+ name = "random powertool"
+ desc = "This is a random rare powertool for maintenance"
+ icon_state = "jaws_pry"
+
+/obj/random/tool/powermaint/item_to_spawn()
+ return pick(prob(320);/obj/random/tool,
+ prob(1);/obj/item/weapon/screwdriver/power,
+ prob(1);/obj/item/weapon/wirecutters/power,
+ prob(15);/obj/item/weapon/weldingtool/electric,
+ prob(5);/obj/item/weapon/weldingtool/experimental)
+
+/obj/random/tool/power
+ name = "random powertool"
+ desc = "This is a random powertool"
+ icon_state = "jaws_pry"
+
+/obj/random/tool/power/item_to_spawn()
+ return pick(/obj/item/weapon/screwdriver/power,
+ /obj/item/weapon/wirecutters/power,
+ /obj/item/weapon/weldingtool/electric,
+ /obj/item/weapon/weldingtool/experimental)
+
+/obj/random/tool/alien
+ name = "random alien tool"
+ desc = "This is a random tool"
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "welder"
+
+/obj/random/tool/alien/item_to_spawn()
+ return pick(/obj/item/weapon/screwdriver/alien,
+ /obj/item/weapon/wirecutters/alien,
+ /obj/item/weapon/weldingtool/alien,
+ /obj/item/weapon/crowbar/alien,
+ /obj/item/weapon/wrench/alien,
+ /obj/item/stack/cable_coil/alien,
+ /obj/item/device/multitool/alien)
+
+/obj/random/technology_scanner
+ name = "random scanner"
+ desc = "This is a random technology scanner."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "atmos"
+
+/obj/random/technology_scanner/item_to_spawn()
+ return pick(prob(5);/obj/item/device/t_scanner,
+ prob(2);/obj/item/device/radio,
+ prob(5);/obj/item/device/analyzer)
+
+/obj/random/powercell
+ name = "random powercell"
+ desc = "This is a random powercell."
+ icon = 'icons/obj/power.dmi'
+ icon_state = "cell"
+
+/obj/random/powercell/item_to_spawn()
+ return pick(prob(40);/obj/item/weapon/cell,
+ prob(25);/obj/item/weapon/cell/device,
+ prob(25);/obj/item/weapon/cell/high,
+ prob(9);/obj/item/weapon/cell/super,
+ prob(1);/obj/item/weapon/cell/hyper)
+
+
+/obj/random/bomb_supply
+ name = "bomb supply"
+ desc = "This is a random bomb supply."
+ icon = 'icons/obj/assemblies/new_assemblies.dmi'
+ icon_state = "signaller"
+
+/obj/random/bomb_supply/item_to_spawn()
+ return pick(/obj/item/device/assembly/igniter,
+ /obj/item/device/assembly/prox_sensor,
+ /obj/item/device/assembly/signaler,
+ /obj/item/device/assembly/timer,
+ /obj/item/device/multitool)
+
+
+/obj/random/toolbox
+ name = "random toolbox"
+ desc = "This is a random toolbox."
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "red"
+
+/obj/random/toolbox/item_to_spawn()
+ return pick(prob(6);/obj/item/weapon/storage/toolbox/mechanical,
+ prob(6);/obj/item/weapon/storage/toolbox/electrical,
+ prob(2);/obj/item/weapon/storage/toolbox/emergency,
+ prob(1);/obj/item/weapon/storage/toolbox/syndicate)
+
+
+/obj/random/tech_supply
+ name = "random tech supply"
+ desc = "This is a random piece of technology supplies."
+ icon = 'icons/obj/power.dmi'
+ icon_state = "cell"
+ spawn_nothing_percentage = 25
+
+/obj/random/tech_supply/item_to_spawn()
+ return pick(prob(3);/obj/random/powercell,
+ prob(2);/obj/random/technology_scanner,
+ prob(1);/obj/item/weapon/packageWrap,
+ prob(2);/obj/random/bomb_supply,
+ prob(1);/obj/item/weapon/extinguisher,
+ prob(1);/obj/item/clothing/gloves/fyellow,
+ prob(3);/obj/item/stack/cable_coil/random,
+ prob(2);/obj/random/toolbox,
+ prob(2);/obj/item/weapon/storage/belt/utility,
+ prob(1);/obj/item/weapon/storage/belt/utility/full,
+ prob(5);/obj/random/tool,
+ prob(2);/obj/item/weapon/tape_roll,
+ prob(2);/obj/item/taperoll/engineering,
+ prob(1);/obj/item/taperoll/atmos,
+ prob(1);/obj/item/device/flashlight/maglight)
+
+/obj/random/tech_supply/component
+ name = "random tech component"
+ desc = "This is a random machine component."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "portable_analyzer"
+
+/obj/random/tech_supply/component/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/stock_parts/gear,
+ prob(2);/obj/item/weapon/stock_parts/console_screen,
+ prob(1);/obj/item/weapon/stock_parts/spring,
+ prob(3);/obj/item/weapon/stock_parts/capacitor,
+ prob(2);/obj/item/weapon/stock_parts/capacitor/adv,
+ prob(1);/obj/item/weapon/stock_parts/capacitor/super,
+ prob(3);/obj/item/weapon/stock_parts/manipulator,
+ prob(2);/obj/item/weapon/stock_parts/manipulator/nano,
+ prob(1);/obj/item/weapon/stock_parts/manipulator/pico,
+ prob(3);/obj/item/weapon/stock_parts/matter_bin,
+ prob(2);/obj/item/weapon/stock_parts/matter_bin/adv,
+ prob(1);/obj/item/weapon/stock_parts/matter_bin/super,
+ prob(3);/obj/item/weapon/stock_parts/scanning_module,
+ prob(2);/obj/item/weapon/stock_parts/scanning_module/adv,
+ prob(1);/obj/item/weapon/stock_parts/scanning_module/phasic)
+
+/obj/random/medical
+ name = "Random Medicine"
+ desc = "This is a random medical item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "advfirstaid"
+
+/obj/random/medical/item_to_spawn()
+ return pick(prob(21);/obj/random/medical/lite,
+ prob(5);/obj/random/medical/pillbottle,
+ prob(1);/obj/item/weapon/storage/pill_bottle/tramadol,
+ prob(1);/obj/item/weapon/storage/pill_bottle/antitox,
+ prob(1);/obj/item/weapon/storage/pill_bottle/carbon,
+ prob(3);/obj/item/bodybag/cryobag,
+ prob(5);/obj/item/weapon/reagent_containers/syringe/antitoxin,
+ prob(3);/obj/item/weapon/reagent_containers/syringe/antiviral,
+ prob(5);/obj/item/weapon/reagent_containers/syringe/inaprovaline,
+ prob(1);/obj/item/weapon/reagent_containers/hypospray,
+ prob(1);/obj/item/weapon/storage/box/freezer,
+ prob(2);/obj/item/stack/nanopaste)
+
+/obj/random/medical/pillbottle
+ name = "Random Pill Bottle"
+ desc = "This is a random pill bottle."
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "pill_canister"
+
+/obj/random/medical/pillbottle/item_to_spawn()
+ return pick(prob(1);/obj/item/weapon/storage/pill_bottle/spaceacillin,
+ prob(1);/obj/item/weapon/storage/pill_bottle/dermaline,
+ prob(1);/obj/item/weapon/storage/pill_bottle/dexalin_plus,
+ prob(1);/obj/item/weapon/storage/pill_bottle/bicaridine,
+ prob(1);/obj/item/weapon/storage/pill_bottle/iron)
+
+/obj/random/medical/lite
+ name = "Random Medicine"
+ desc = "This is a random simple medical item."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "brutepack"
+ spawn_nothing_percentage = 25
+
+/obj/random/medical/lite/item_to_spawn()
+ return pick(prob(4);/obj/item/stack/medical/bruise_pack,
+ prob(4);/obj/item/stack/medical/ointment,
+ prob(2);/obj/item/stack/medical/advanced/bruise_pack,
+ prob(2);/obj/item/stack/medical/advanced/ointment,
+ prob(1);/obj/item/stack/medical/splint,
+ prob(4);/obj/item/device/healthanalyzer,
+ prob(1);/obj/item/bodybag,
+ prob(3);/obj/item/weapon/reagent_containers/hypospray/autoinjector,
+ prob(2);/obj/item/weapon/storage/pill_bottle/kelotane,
+ prob(2);/obj/item/weapon/storage/pill_bottle/antitox)
+
+/obj/random/firstaid
+ name = "Random First Aid Kit"
+ desc = "This is a random first aid kit."
+ icon = 'icons/obj/storage.dmi'
+ icon_state = "firstaid"
+
+/obj/random/firstaid/item_to_spawn()
+ return pick(prob(10);/obj/item/weapon/storage/firstaid/regular,
+ prob(8);/obj/item/weapon/storage/firstaid/toxin,
+ prob(8);/obj/item/weapon/storage/firstaid/o2,
+ prob(6);/obj/item/weapon/storage/firstaid/adv,
+ prob(8);/obj/item/weapon/storage/firstaid/fire,
+ prob(1);/obj/item/weapon/storage/firstaid/combat)
+
+/obj/random/contraband
+ name = "Random Illegal Item"
+ desc = "Hot Stuff."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "purplecomb"
+ spawn_nothing_percentage = 50
+/obj/random/contraband/item_to_spawn()
+ return pick(prob(6);/obj/item/weapon/storage/pill_bottle/tramadol,
+ prob(8);/obj/item/weapon/haircomb,
+ prob(4);/obj/item/weapon/storage/pill_bottle/happy,
+ prob(4);/obj/item/weapon/storage/pill_bottle/zoom,
+ prob(10);/obj/item/weapon/contraband/poster,
+ prob(4);/obj/item/weapon/material/butterfly,
+ prob(6);/obj/item/weapon/material/butterflyblade,
+ prob(6);/obj/item/weapon/material/butterflyhandle,
+ prob(6);/obj/item/weapon/material/wirerod,
+ prob(2);/obj/item/weapon/material/butterfly/switchblade,
+ prob(2);/obj/item/clothing/gloves/knuckledusters,
+ prob(1);/obj/item/weapon/material/knife/tacknife,
+ prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc,
+ prob(1);/obj/item/weapon/beartrap,
+ prob(1);/obj/item/weapon/handcuffs,
+ prob(1);/obj/item/weapon/handcuffs/legcuffs,
+ prob(2);/obj/item/weapon/reagent_containers/syringe/drugs,
+ prob(1);/obj/item/weapon/reagent_containers/syringe/steroid)
+
+/obj/random/cash
+ name = "random currency"
+ desc = "LOADSAMONEY!"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "spacecash1"
+
+/obj/random/cash/item_to_spawn()
+ return pick(prob(320);/obj/random/maintenance/clean,
+ prob(12);/obj/item/weapon/spacecash/c1,
+ prob(8);/obj/item/weapon/spacecash/c10,
+ prob(4);/obj/item/weapon/spacecash/c20,
+ prob(1);/obj/item/weapon/spacecash/c50,
+ prob(1);/obj/item/weapon/spacecash/c100)
+
+/obj/random/soap
+ name = "Random Soap"
+ desc = "This is a random bar of soap."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "soap"
+
+/obj/random/soap/item_to_spawn()
+ return pick(prob(3);/obj/item/weapon/soap,
+ prob(2);/obj/item/weapon/soap/nanotrasen,
+ prob(2);/obj/item/weapon/soap/deluxe,
+ prob(1);/obj/item/weapon/soap/syndie)
+
+
+/obj/random/drinkbottle
+ name = "random drink"
+ desc = "This is a random drink."
+ icon = 'icons/obj/drinks.dmi'
+ icon_state = "whiskeybottle"
+
+/obj/random/drinkbottle/item_to_spawn()
+ return pick(/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/gin,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/wine,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/cognac,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/rum,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/patron)
+
+/obj/random/material //Random materials for building stuff
+ name = "random material"
+ desc = "This is a random material."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "sheet-metal"
+
+/obj/random/material/item_to_spawn()
+ return pick(/obj/item/stack/material/steel{amount = 10},
+ /obj/item/stack/material/glass{amount = 10},
+ /obj/item/stack/material/glass/reinforced{amount = 10},
+ /obj/item/stack/material/plastic{amount = 10},
+ /obj/item/stack/material/wood{amount = 10},
+ /obj/item/stack/material/cardboard{amount = 10},
+ /obj/item/stack/rods{amount = 10},
+ /obj/item/stack/material/plasteel{amount = 10})
+
+/obj/random/tank
+ name = "random tank"
+ desc = "This is a tank."
+ icon = 'icons/obj/tank.dmi'
+ icon_state = "canister"
+
+/obj/random/tank/item_to_spawn()
+ return pick(prob(5);/obj/item/weapon/tank/oxygen,
+ prob(4);/obj/item/weapon/tank/oxygen/yellow,
+ prob(4);/obj/item/weapon/tank/oxygen/red,
+ prob(3);/obj/item/weapon/tank/air,
+ prob(4);/obj/item/weapon/tank/emergency/oxygen,
+ prob(3);/obj/item/weapon/tank/emergency/oxygen/engi,
+ prob(2);/obj/item/weapon/tank/emergency/oxygen/double,
+ prob(1);/obj/item/device/suit_cooling_unit)
+
+/obj/random/cigarettes
+ name = "random cigarettes"
+ desc = "This is a cigarette."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "cigpacket"
+
+/obj/random/cigarettes/item_to_spawn()
+ return pick(prob(5);/obj/item/weapon/storage/fancy/cigarettes,
+ prob(4);/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/killthroat,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/luckystars,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/jerichos,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/menthols,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/carcinomas,
+ prob(3);/obj/item/weapon/storage/fancy/cigarettes/professionals,
+ prob(1);/obj/item/weapon/storage/fancy/cigar,
+ prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar,
+ prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba,
+ prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar/havana)
+
+/obj/random/coin
+ name = "random coin"
+ desc = "This is a coin spawn."
+ icon = 'icons/misc/mark.dmi'
+ icon_state = "rup"
+
+/obj/random/coin/item_to_spawn()
+ return pick(prob(5);/obj/item/weapon/coin/silver,
+ prob(3);/obj/item/weapon/coin/iron,
+ prob(4);/obj/item/weapon/coin/gold,
+ prob(3);/obj/item/weapon/coin/phoron,
+ prob(1);/obj/item/weapon/coin/uranium,
+ prob(2);/obj/item/weapon/coin/platinum,
+ prob(1);/obj/item/weapon/coin/diamond)
+
+/obj/random/action_figure
+ name = "random action figure"
+ desc = "This is a random action figure."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "assistant"
+
+/obj/random/action_figure/item_to_spawn()
+ return pick(/obj/item/toy/figure/cmo,
+ /obj/item/toy/figure/assistant,
+ /obj/item/toy/figure/atmos,
+ /obj/item/toy/figure/bartender,
+ /obj/item/toy/figure/borg,
+ /obj/item/toy/figure/gardener,
+ /obj/item/toy/figure/captain,
+ /obj/item/toy/figure/cargotech,
+ /obj/item/toy/figure/ce,
+ /obj/item/toy/figure/chaplain,
+ /obj/item/toy/figure/chef,
+ /obj/item/toy/figure/chemist,
+ /obj/item/toy/figure/clown,
+ /obj/item/toy/figure/corgi,
+ /obj/item/toy/figure/detective,
+ /obj/item/toy/figure/dsquad,
+ /obj/item/toy/figure/engineer,
+ /obj/item/toy/figure/geneticist,
+ /obj/item/toy/figure/hop,
+ /obj/item/toy/figure/hos,
+ /obj/item/toy/figure/qm,
+ /obj/item/toy/figure/janitor,
+ /obj/item/toy/figure/agent,
+ /obj/item/toy/figure/librarian,
+ /obj/item/toy/figure/md,
+ /obj/item/toy/figure/mime,
+ /obj/item/toy/figure/miner,
+ /obj/item/toy/figure/ninja,
+ /obj/item/toy/figure/wizard,
+ /obj/item/toy/figure/rd,
+ /obj/item/toy/figure/roboticist,
+ /obj/item/toy/figure/scientist,
+ /obj/item/toy/figure/syndie,
+ /obj/item/toy/figure/secofficer,
+ /obj/item/toy/figure/warden,
+ /obj/item/toy/figure/psychologist,
+ /obj/item/toy/figure/paramedic,
+ /obj/item/toy/figure/ert)
+
+/obj/random/plushie
+ name = "random plushie"
+ desc = "This is a random plushie."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "nymphplushie"
+
+/obj/random/plushie/item_to_spawn()
+ return pick(/obj/item/toy/plushie/nymph,
+ /obj/item/toy/plushie/mouse,
+ /obj/item/toy/plushie/kitten,
+ /obj/item/toy/plushie/lizard,
+ /obj/item/toy/plushie/black_cat,
+ /obj/item/toy/plushie/black_fox,
+ /obj/item/toy/plushie/blue_fox,
+ /obj/random/carp_plushie,
+ /obj/item/toy/plushie/coffee_fox,
+ /obj/item/toy/plushie/corgi,
+ /obj/item/toy/plushie/crimson_fox,
+ /obj/item/toy/plushie/deer,
+ /obj/item/toy/plushie/girly_corgi,
+ /obj/item/toy/plushie/grey_cat,
+ /obj/item/toy/plushie/marble_fox,
+ /obj/item/toy/plushie/octopus,
+ /obj/item/toy/plushie/orange_cat,
+ /obj/item/toy/plushie/orange_fox,
+ /obj/item/toy/plushie/pink_fox,
+ /obj/item/toy/plushie/purple_fox,
+ /obj/item/toy/plushie/red_fox,
+ /obj/item/toy/plushie/robo_corgi,
+ /obj/item/toy/plushie/siamese_cat,
+ /obj/item/toy/plushie/spider,
+ /obj/item/toy/plushie/tabby_cat,
+ /obj/item/toy/plushie/tuxedo_cat,
+ /obj/item/toy/plushie/white_cat)
+
+/obj/random/plushielarge
+ name = "random large plushie"
+ desc = "This is a randomn large plushie."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "droneplushie"
+
+/obj/random/plushielarge/item_to_spawn()
+ return pick(/obj/structure/plushie/ian,
+ /obj/structure/plushie/drone,
+ /obj/structure/plushie/carp,
+ /obj/structure/plushie/beepsky)
+
+/obj/random/toy
+ name = "random toy"
+ desc = "This is a random toy."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "ship"
+
+/obj/random/toy/item_to_spawn()
+ return pick(/obj/item/toy/bosunwhistle,
+ /obj/item/toy/plushie/therapy/red,
+ /obj/item/toy/plushie/therapy/purple,
+ /obj/item/toy/plushie/therapy/blue,
+ /obj/item/toy/plushie/therapy/yellow,
+ /obj/item/toy/plushie/therapy/orange,
+ /obj/item/toy/plushie/therapy/green,
+ /obj/item/toy/cultsword,
+ /obj/item/toy/katana,
+ /obj/item/toy/snappop,
+ /obj/item/toy/sword,
+ /obj/item/toy/balloon,
+ /obj/item/toy/crossbow,
+ /obj/item/toy/blink,
+ /obj/item/toy/waterflower,
+ /obj/item/toy/eight_ball,
+ /obj/item/toy/eight_ball/conch,
+ /obj/item/toy/prize/ripley,
+ /obj/item/toy/prize/fireripley,
+ /obj/item/toy/prize/deathripley,
+ /obj/item/toy/prize/gygax,
+ /obj/item/toy/prize/durand,
+ /obj/item/toy/prize/honk,
+ /obj/item/toy/prize/marauder,
+ /obj/item/toy/prize/seraph,
+ /obj/item/toy/prize/mauler,
+ /obj/item/toy/prize/odysseus,
+ /obj/item/toy/prize/phazon)
\ No newline at end of file
diff --git a/code/game/objects/random/mob.dm b/code/game/objects/random/mob.dm
new file mode 100644
index 0000000000..2043ef0240
--- /dev/null
+++ b/code/game/objects/random/mob.dm
@@ -0,0 +1,159 @@
+/*
+ * Random Mobs
+ */
+
+/obj/random/mob
+ name = "Random Animal"
+ desc = "This is a random animal."
+ icon = 'icons/mob/animal.dmi'
+ icon_state = "chicken_white"
+
+ var/overwrite_hostility = 0
+
+ var/mob_faction = null
+ var/mob_returns_home = 0
+ var/mob_wander = 1
+ var/mob_wander_distance = 3
+ var/mob_hostile = 0
+ var/mob_retaliate = 0
+
+/obj/random/mob/item_to_spawn()
+ return pick(prob(10);/mob/living/simple_animal/lizard,
+ prob(6);/mob/living/simple_animal/retaliate/diyaab,
+ prob(10);/mob/living/simple_animal/cat/fluff,
+ prob(6);/mob/living/simple_animal/cat/kitten,
+ prob(10);/mob/living/simple_animal/corgi,
+ prob(6);/mob/living/simple_animal/corgi/puppy,
+ prob(10);/mob/living/simple_animal/crab,
+ prob(10);/mob/living/simple_animal/chicken,
+ prob(6);/mob/living/simple_animal/chick,
+ prob(10);/mob/living/simple_animal/cow,
+ prob(6);/mob/living/simple_animal/retaliate/goat,
+ prob(10);/mob/living/simple_animal/penguin,
+ prob(10);/mob/living/simple_animal/mouse,
+ prob(10);/mob/living/simple_animal/yithian,
+ prob(10);/mob/living/simple_animal/tindalos,
+ prob(10);/mob/living/simple_animal/corgi/tamaskan,
+ prob(3);/mob/living/simple_animal/parrot,
+ prob(1);/mob/living/simple_animal/giant_crab)
+
+/obj/random/mob/spawn_item() //These should only ever have simple mobs.
+ var/build_path = item_to_spawn()
+
+ var/mob/living/simple_animal/M = new build_path(src.loc)
+ M.ai_inactive = 1 //Don't fight eachother while we're still setting up!
+ if(mob_faction)
+ M.faction = mob_faction
+ M.returns_home = mob_returns_home
+ M.wander = mob_wander
+ M.wander_distance = mob_wander_distance
+ if(overwrite_hostility)
+ M.hostile = mob_hostile
+ M.retaliate = mob_retaliate
+ M.ai_inactive = 0 //Now you can kill eachother if your faction didn't override.
+
+ if(pixel_x || pixel_y)
+ M.pixel_x = pixel_x
+ M.pixel_y = pixel_y
+
+/obj/random/mob/sif
+ name = "Random Sif Animal"
+ desc = "This is a random cold weather animal."
+ icon_state = "penguin"
+
+ mob_returns_home = 1
+ mob_wander_distance = 10
+
+/obj/random/mob/sif/item_to_spawn()
+ return pick(prob(30);/mob/living/simple_animal/retaliate/diyaab,
+ prob(15);/mob/living/simple_animal/crab,
+ prob(15);/mob/living/simple_animal/penguin,
+ prob(15);/mob/living/simple_animal/mouse,
+ prob(15);/mob/living/simple_animal/corgi/tamaskan,
+ prob(2);/mob/living/simple_animal/hostile/giant_spider/frost,
+ prob(1);/mob/living/simple_animal/hostile/goose,
+ prob(20);/mob/living/simple_animal/giant_crab)
+
+/obj/random/mob/sif/hostile
+ name = "Random Hostile Sif Animal"
+ desc = "This is a random hostile cold weather animal."
+ icon_state = "frost"
+
+/obj/random/mob/sif/hostile/item_to_spawn()
+ return pick(prob(22);/mob/living/simple_animal/hostile/savik,
+ prob(33);/mob/living/simple_animal/hostile/giant_spider/frost,
+ prob(45);/mob/living/simple_animal/hostile/shantak)
+
+/obj/random/mob/spider
+ name = "Random Spider" //Spiders should patrol where they spawn.
+ desc = "This is a random boring spider."
+ icon_state = "guard"
+
+ mob_returns_home = 1
+ mob_wander_distance = 4
+
+/obj/random/mob/spider/item_to_spawn()
+ return pick(prob(22);/mob/living/simple_animal/hostile/giant_spider/nurse,
+ prob(33);/mob/living/simple_animal/hostile/giant_spider/hunter,
+ prob(45);/mob/living/simple_animal/hostile/giant_spider)
+
+/obj/random/mob/spider/mutant
+ name = "Random Mutant Spider"
+ desc = "This is a random mutated spider."
+ icon_state = "phoron"
+
+/obj/random/mob/spider/mutant/item_to_spawn()
+ return pick(prob(5);/obj/random/mob/spider,
+ prob(10);/mob/living/simple_animal/hostile/giant_spider/webslinger,
+ prob(10);/mob/living/simple_animal/hostile/giant_spider/carrier,
+ prob(33);/mob/living/simple_animal/hostile/giant_spider/lurker,
+ prob(33);/mob/living/simple_animal/hostile/giant_spider/tunneler,
+ prob(40);/mob/living/simple_animal/hostile/giant_spider/pepper,
+ prob(20);/mob/living/simple_animal/hostile/giant_spider/thermic,
+ prob(40);/mob/living/simple_animal/hostile/giant_spider/electric,
+ prob(1);/mob/living/simple_animal/hostile/giant_spider/phorogenic,
+ prob(40);/mob/living/simple_animal/hostile/giant_spider/frost)
+
+/obj/random/mob/robotic
+ name = "Random Robot Mob"
+ desc = "This is a random robot."
+ icon_state = "drone_dead"
+
+ overwrite_hostility = 1
+
+ mob_faction = "malf_drone"
+ mob_returns_home = 1
+ mob_wander = 1
+ mob_wander_distance = 5
+ mob_hostile = 1
+ mob_retaliate = 1
+
+/obj/random/mob/robotic/item_to_spawn() //Hivebots have a total number of 'lots' equal to the lesser drone, at 60.
+ return pick(prob(60);/mob/living/simple_animal/hostile/malf_drone/lesser,
+ prob(50);/mob/living/simple_animal/hostile/malf_drone,
+ prob(15);/mob/living/simple_animal/hostile/mecha/malf_drone,
+ prob(10);/mob/living/simple_animal/hostile/hivebot,
+ prob(15);/mob/living/simple_animal/hostile/hivebot/swarm,
+ prob(10);/mob/living/simple_animal/hostile/hivebot/range,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/rapid,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/ion,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/laser,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/strong,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/guard)
+
+/obj/random/mob/robotic/hivebot
+ name = "Random Hivebot"
+ desc = "This is a random hivebot."
+ icon_state = "drone3"
+
+ mob_faction = "hivebot"
+
+/obj/random/mob/robotic/hivebot/item_to_spawn()
+ return pick(prob(10);/mob/living/simple_animal/hostile/hivebot,
+ prob(15);/mob/living/simple_animal/hostile/hivebot/swarm,
+ prob(10);/mob/living/simple_animal/hostile/hivebot/range,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/rapid,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/ion,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/laser,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/strong,
+ prob(5);/mob/living/simple_animal/hostile/hivebot/range/guard)
diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm
deleted file mode 100644
index 05ba702853..0000000000
--- a/code/game/objects/random/random.dm
+++ /dev/null
@@ -1,1140 +0,0 @@
-/obj/random
- name = "random object"
- desc = "This item type is used to spawn random objects at round-start"
- icon = 'icons/misc/mark.dmi'
- icon_state = "rup"
- var/spawn_nothing_percentage = 0 // this variable determines the likelyhood that this random object will not spawn anything
-
-
-// creates a new object and deletes itself
-/obj/random/New()
- ..()
- if (!prob(spawn_nothing_percentage))
- spawn_item()
- qdel(src)
-
-
-// this function should return a specific item to spawn
-/obj/random/proc/item_to_spawn()
- return 0
-
-
-// creates the random item
-/obj/random/proc/spawn_item()
- var/build_path = item_to_spawn()
-
- var/atom/A = new build_path(src.loc)
- if(pixel_x || pixel_y)
- A.pixel_x = pixel_x
- A.pixel_y = pixel_y
-
-
-/obj/random/single
- name = "randomly spawned object"
- desc = "This item type is used to randomly spawn a given object at round-start"
- icon_state = "x3"
- var/spawn_object = null
-
-/obj/random/single/item_to_spawn()
- return ispath(spawn_object) ? spawn_object : text2path(spawn_object)
-
-
-/obj/random/tool
- name = "random tool"
- desc = "This is a random tool"
- icon = 'icons/obj/items.dmi'
- icon_state = "welder"
-
-/obj/random/tool/item_to_spawn()
- return pick(/obj/item/weapon/screwdriver,
- /obj/item/weapon/wirecutters,
- /obj/item/weapon/weldingtool,
- /obj/item/weapon/weldingtool/largetank,
- /obj/item/weapon/crowbar,
- /obj/item/weapon/wrench,
- /obj/item/device/flashlight,
- /obj/item/device/multitool)
-
-/obj/random/technology_scanner
- name = "random scanner"
- desc = "This is a random technology scanner."
- icon = 'icons/obj/device.dmi'
- icon_state = "atmos"
-
-/obj/random/technology_scanner/item_to_spawn()
- return pick(prob(5);/obj/item/device/t_scanner,
- prob(2);/obj/item/device/radio,
- prob(5);/obj/item/device/analyzer)
-
-/obj/random/powercell
- name = "random powercell"
- desc = "This is a random powercell."
- icon = 'icons/obj/power.dmi'
- icon_state = "cell"
-
-/obj/random/powercell/item_to_spawn()
- return pick(prob(40);/obj/item/weapon/cell,
- prob(25);/obj/item/weapon/cell/device,
- prob(25);/obj/item/weapon/cell/high,
- prob(9);/obj/item/weapon/cell/super,
- prob(1);/obj/item/weapon/cell/hyper)
-
-
-/obj/random/bomb_supply
- name = "bomb supply"
- desc = "This is a random bomb supply."
- icon = 'icons/obj/assemblies/new_assemblies.dmi'
- icon_state = "signaller"
-
-/obj/random/bomb_supply/item_to_spawn()
- return pick(/obj/item/device/assembly/igniter,
- /obj/item/device/assembly/prox_sensor,
- /obj/item/device/assembly/signaler,
- /obj/item/device/assembly/timer,
- /obj/item/device/multitool)
-
-
-/obj/random/toolbox
- name = "random toolbox"
- desc = "This is a random toolbox."
- icon = 'icons/obj/storage.dmi'
- icon_state = "red"
-
-/obj/random/toolbox/item_to_spawn()
- return pick(prob(6);/obj/item/weapon/storage/toolbox/mechanical,
- prob(6);/obj/item/weapon/storage/toolbox/electrical,
- prob(2);/obj/item/weapon/storage/toolbox/emergency,
- prob(1);/obj/item/weapon/storage/toolbox/syndicate)
-
-
-/obj/random/tech_supply
- name = "random tech supply"
- desc = "This is a random piece of technology supplies."
- icon = 'icons/obj/power.dmi'
- icon_state = "cell"
- spawn_nothing_percentage = 25
-
-/obj/random/tech_supply/item_to_spawn()
- return pick(prob(3);/obj/random/powercell,
- prob(2);/obj/random/technology_scanner,
- prob(1);/obj/item/weapon/packageWrap,
- prob(2);/obj/random/bomb_supply,
- prob(1);/obj/item/weapon/extinguisher,
- prob(1);/obj/item/clothing/gloves/fyellow,
- prob(3);/obj/item/stack/cable_coil/random,
- prob(2);/obj/random/toolbox,
- prob(2);/obj/item/weapon/storage/belt/utility,
- prob(1);/obj/item/weapon/storage/belt/utility/full,
- prob(5);/obj/random/tool,
- prob(2);/obj/item/weapon/tape_roll,
- prob(2);/obj/item/taperoll/engineering,
- prob(1);/obj/item/taperoll/atmos,
- prob(1);/obj/item/device/flashlight/maglight)
-
-/obj/random/medical
- name = "Random Medicine"
- desc = "This is a random medical item."
- icon = 'icons/obj/items.dmi'
- icon_state = "traumakit"
-
-/obj/random/medical/item_to_spawn()
- return pick(prob(21);/obj/random/medical/lite,
- prob(5);/obj/random/medical/pillbottle,
- prob(1);/obj/item/weapon/storage/pill_bottle/tramadol,
- prob(1);/obj/item/weapon/storage/pill_bottle/antitox,
- prob(1);/obj/item/weapon/storage/pill_bottle/carbon,
- prob(3);/obj/item/bodybag/cryobag,
- prob(5);/obj/item/weapon/reagent_containers/syringe/antitoxin,
- prob(3);/obj/item/weapon/reagent_containers/syringe/antiviral,
- prob(5);/obj/item/weapon/reagent_containers/syringe/inaprovaline,
- prob(1);/obj/item/weapon/reagent_containers/hypospray,
- prob(1);/obj/item/weapon/storage/box/freezer,
- prob(2);/obj/item/stack/nanopaste)
-
-/obj/random/medical/pillbottle
- name = "Random Pill Bottle"
- desc = "This is a random pill bottle."
- icon = 'icons/obj/chemical.dmi'
- icon_state = "pill_canister"
-
-/obj/random/medical/pillbottle/item_to_spawn()
- return pick(prob(1);/obj/item/weapon/storage/pill_bottle/spaceacillin,
- prob(1);/obj/item/weapon/storage/pill_bottle/dermaline,
- prob(1);/obj/item/weapon/storage/pill_bottle/dexalin_plus,
- prob(1);/obj/item/weapon/storage/pill_bottle/bicaridine,
- prob(1);/obj/item/weapon/storage/pill_bottle/iron)
-
-/obj/random/medical/lite
- name = "Random Medicine"
- desc = "This is a random simple medical item."
- icon = 'icons/obj/items.dmi'
- icon_state = "brutepack"
- spawn_nothing_percentage = 25
-
-/obj/random/medical/lite/item_to_spawn()
- return pick(prob(4);/obj/item/stack/medical/bruise_pack,
- prob(4);/obj/item/stack/medical/ointment,
- prob(2);/obj/item/stack/medical/advanced/bruise_pack,
- prob(2);/obj/item/stack/medical/advanced/ointment,
- prob(1);/obj/item/stack/medical/splint,
- prob(4);/obj/item/device/healthanalyzer,
- prob(1);/obj/item/bodybag,
- prob(3);/obj/item/weapon/reagent_containers/hypospray/autoinjector,
- prob(2);/obj/item/weapon/storage/pill_bottle/kelotane,
- prob(2);/obj/item/weapon/storage/pill_bottle/antitox)
-
-/obj/random/firstaid
- name = "Random First Aid Kit"
- desc = "This is a random first aid kit."
- icon = 'icons/obj/storage.dmi'
- icon_state = "firstaid"
-
-/obj/random/firstaid/item_to_spawn()
- return pick(prob(4);/obj/item/weapon/storage/firstaid/regular,
- prob(3);/obj/item/weapon/storage/firstaid/toxin,
- prob(3);/obj/item/weapon/storage/firstaid/o2,
- prob(2);/obj/item/weapon/storage/firstaid/adv,
- prob(3);/obj/item/weapon/storage/firstaid/fire,
- prob(1);/obj/item/weapon/storage/firstaid/combat)
-
-/obj/random/contraband
- name = "Random Illegal Item"
- desc = "Hot Stuff."
- icon = 'icons/obj/items.dmi'
- icon_state = "purplecomb"
- spawn_nothing_percentage = 50
-/obj/random/contraband/item_to_spawn()
- return pick(prob(6);/obj/item/weapon/storage/pill_bottle/tramadol,
- prob(8);/obj/item/weapon/haircomb,
- prob(4);/obj/item/weapon/storage/pill_bottle/happy,
- prob(4);/obj/item/weapon/storage/pill_bottle/zoom,
- prob(10);/obj/item/weapon/contraband/poster,
- prob(4);/obj/item/weapon/material/butterfly,
- prob(6);/obj/item/weapon/material/butterflyblade,
- prob(6);/obj/item/weapon/material/butterflyhandle,
- prob(6);/obj/item/weapon/material/wirerod,
- prob(2);/obj/item/weapon/material/butterfly/switchblade,
- prob(2);/obj/item/clothing/gloves/knuckledusters,
- prob(1);/obj/item/weapon/material/knife/tacknife,
- prob(1);/obj/item/clothing/suit/storage/vest/heavy/merc,
- prob(1);/obj/item/weapon/beartrap,
- prob(1);/obj/item/weapon/handcuffs,
- prob(1);/obj/item/weapon/handcuffs/legcuffs,
- prob(2);/obj/item/weapon/reagent_containers/syringe/drugs,
- prob(1);/obj/item/weapon/reagent_containers/syringe/steroid)
-
-/obj/random/soap
- name = "Random Soap"
- desc = "This is a random bar of soap."
- icon = 'icons/obj/items.dmi'
- icon_state = "soap"
-
-/obj/random/soap/item_to_spawn()
- return pick(prob(3);/obj/item/weapon/soap,
- prob(2);/obj/item/weapon/soap/nanotrasen,
- prob(2);/obj/item/weapon/soap/deluxe,
- prob(1);/obj/item/weapon/soap/syndie,)
-
-
-/obj/random/drinkbottle
- name = "random drink"
- desc = "This is a random drink."
- icon = 'icons/obj/drinks.dmi'
- icon_state = "whiskeybottle"
-
-/obj/random/drinkbottle/item_to_spawn()
- return pick(/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/gin,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/wine,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/cognac,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/rum,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/patron)
-
-/obj/random/energy
- name = "Random Energy Weapon"
- desc = "This is a random security weapon."
- icon = 'icons/obj/gun.dmi'
- icon_state = "energykill100"
-
-/obj/random/energy/item_to_spawn()
- return pick(prob(3);/obj/item/weapon/gun/energy/laser,
- prob(4);/obj/item/weapon/gun/energy/gun,
- prob(3);/obj/item/weapon/gun/energy/gun/burst,
- prob(1);/obj/item/weapon/gun/energy/gun/nuclear,
- prob(2);/obj/item/weapon/gun/energy/retro,
- prob(2);/obj/item/weapon/gun/energy/lasercannon,
- prob(3);/obj/item/weapon/gun/energy/xray,
- prob(1);/obj/item/weapon/gun/energy/sniperrifle,
- prob(1);/obj/item/weapon/gun/energy/plasmastun,
- prob(2);/obj/item/weapon/gun/energy/ionrifle,
- prob(2);/obj/item/weapon/gun/energy/ionrifle/pistol,
- prob(3);/obj/item/weapon/gun/energy/toxgun,
- prob(4);/obj/item/weapon/gun/energy/taser,
- prob(2);/obj/item/weapon/gun/energy/crossbow/largecrossbow,
- prob(4);/obj/item/weapon/gun/energy/stunrevolver)
-
-/obj/random/energy/sec
- name = "Random Security Energy Weapon"
- desc = "This is a random security weapon."
- icon = 'icons/obj/gun.dmi'
- icon_state = "energykill100"
-
-/obj/random/energy/sec/item_to_spawn()
- return pick(prob(2);/obj/item/weapon/gun/energy/laser,
- prob(2);/obj/item/weapon/gun/energy/gun)
-
-/obj/random/projectile
- name = "Random Projectile Weapon"
- desc = "This is a random projectile weapon."
- icon = 'icons/obj/gun.dmi'
- icon_state = "revolver"
-
-/obj/random/projectile/item_to_spawn()
- return pick(prob(3);/obj/item/weapon/gun/projectile/automatic/wt550,
- prob(3);/obj/item/weapon/gun/projectile/automatic/mini_uzi,
- prob(3);/obj/item/weapon/gun/projectile/automatic/tommygun,
- prob(2);/obj/item/weapon/gun/projectile/automatic/c20r,
- prob(2);/obj/item/weapon/gun/projectile/automatic/sts35,
- prob(2);/obj/item/weapon/gun/projectile/automatic/z8,
- prob(4);/obj/item/weapon/gun/projectile/colt,
- prob(2);/obj/item/weapon/gun/projectile/deagle,
- prob(1);/obj/item/weapon/gun/projectile/deagle/camo,
- prob(1);/obj/item/weapon/gun/projectile/deagle/gold,
- prob(3);/obj/item/weapon/gun/projectile/derringer,
- prob(1);/obj/item/weapon/gun/projectile/heavysniper,
- prob(4);/obj/item/weapon/gun/projectile/luger,
- prob(3);/obj/item/weapon/gun/projectile/luger/brown,
- prob(4);/obj/item/weapon/gun/projectile/sec,
- prob(3);/obj/item/weapon/gun/projectile/sec/wood,
- prob(4);/obj/item/weapon/gun/projectile/p92x,
- prob(3);/obj/item/weapon/gun/projectile/p92x/brown,
- prob(4);/obj/item/weapon/gun/projectile/pistol,
- prob(5);/obj/item/weapon/gun/projectile/pirate,
- prob(2);/obj/item/weapon/gun/projectile/revolver,
- prob(4);/obj/item/weapon/gun/projectile/revolver/deckard,
- prob(4);/obj/item/weapon/gun/projectile/revolver/detective,
- prob(2);/obj/item/weapon/gun/projectile/revolver/judge,
- prob(3);/obj/item/weapon/gun/projectile/revolver/lemat,
- prob(2);/obj/item/weapon/gun/projectile/revolver/mateba,
- prob(4);/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
- prob(3);/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
- prob(3);/obj/item/weapon/gun/projectile/shotgun/pump,
- prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat,
- prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle,
- prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever,
- prob(2);/obj/item/weapon/gun/projectile/silenced)
-
-/obj/random/projectile/sec
- name = "Random Security Projectile Weapon"
- desc = "This is a random security weapon."
- icon = 'icons/obj/gun.dmi'
- icon_state = "revolver"
-
-/obj/random/projectile/sec/item_to_spawn()
- return pick(prob(3);/obj/item/weapon/gun/projectile/shotgun/pump,
- prob(2);/obj/item/weapon/gun/projectile/automatic/wt550,
- prob(1);/obj/item/weapon/gun/projectile/shotgun/pump/combat)
-
-/obj/random/handgun
- name = "Random Handgun"
- desc = "This is a random sidearm."
- icon = 'icons/obj/gun.dmi'
- icon_state = "secgundark"
-
-/obj/random/handgun/item_to_spawn()
- return pick(prob(4);/obj/item/weapon/gun/projectile/sec,
- prob(4);/obj/item/weapon/gun/projectile/p92x,
- prob(3);/obj/item/weapon/gun/projectile/sec/wood,
- prob(3);/obj/item/weapon/gun/projectile/p92x/brown,
- prob(3);/obj/item/weapon/gun/projectile/colt,
- prob(2);/obj/item/weapon/gun/projectile/luger,
- prob(2);/obj/item/weapon/gun/energy/gun,
- prob(2);/obj/item/weapon/gun/projectile/pistol,
- prob(1);/obj/item/weapon/gun/energy/retro,
- prob(1);/obj/item/weapon/gun/projectile/luger/brown)
-
-/obj/random/handgun/sec
- name = "Random Security Handgun"
- desc = "This is a random security sidearm."
- icon = 'icons/obj/gun.dmi'
- icon_state = "secgundark"
-
-/obj/random/handgun/sec/item_to_spawn()
- return pick(prob(3);/obj/item/weapon/gun/projectile/sec,
- prob(1);/obj/item/weapon/gun/projectile/sec/wood)
-
-/obj/random/ammo
- name = "Random Ammunition"
- desc = "This is random security ammunition."
- icon = 'icons/obj/ammo.dmi'
- icon_state = "45-10"
-
-/obj/random/ammo/item_to_spawn()
- return pick(prob(6);/obj/item/weapon/storage/box/beanbags,
- prob(2);/obj/item/weapon/storage/box/shotgunammo,
- prob(4);/obj/item/weapon/storage/box/shotgunshells,
- prob(1);/obj/item/weapon/storage/box/stunshells,
- prob(2);/obj/item/ammo_magazine/m45,
- prob(4);/obj/item/ammo_magazine/m45/rubber,
- prob(4);/obj/item/ammo_magazine/m45/flash,
- prob(2);/obj/item/ammo_magazine/m9mmt,
- prob(6);/obj/item/ammo_magazine/m9mmt/rubber)
-
-
-/obj/random/action_figure
- name = "random action figure"
- desc = "This is a random action figure."
- icon = 'icons/obj/toy.dmi'
- icon_state = "assistant"
-
-/obj/random/action_figure/item_to_spawn()
- return pick(/obj/item/toy/figure/cmo,
- /obj/item/toy/figure/assistant,
- /obj/item/toy/figure/atmos,
- /obj/item/toy/figure/bartender,
- /obj/item/toy/figure/borg,
- /obj/item/toy/figure/gardener,
- /obj/item/toy/figure/captain,
- /obj/item/toy/figure/cargotech,
- /obj/item/toy/figure/ce,
- /obj/item/toy/figure/chaplain,
- /obj/item/toy/figure/chef,
- /obj/item/toy/figure/chemist,
- /obj/item/toy/figure/clown,
- /obj/item/toy/figure/corgi,
- /obj/item/toy/figure/detective,
- /obj/item/toy/figure/dsquad,
- /obj/item/toy/figure/engineer,
- /obj/item/toy/figure/geneticist,
- /obj/item/toy/figure/hop,
- /obj/item/toy/figure/hos,
- /obj/item/toy/figure/qm,
- /obj/item/toy/figure/janitor,
- /obj/item/toy/figure/agent,
- /obj/item/toy/figure/librarian,
- /obj/item/toy/figure/md,
- /obj/item/toy/figure/mime,
- /obj/item/toy/figure/miner,
- /obj/item/toy/figure/ninja,
- /obj/item/toy/figure/wizard,
- /obj/item/toy/figure/rd,
- /obj/item/toy/figure/roboticist,
- /obj/item/toy/figure/scientist,
- /obj/item/toy/figure/syndie,
- /obj/item/toy/figure/secofficer,
- /obj/item/toy/figure/warden,
- /obj/item/toy/figure/psychologist,
- /obj/item/toy/figure/paramedic,
- /obj/item/toy/figure/ert)
-
-/obj/random/plushie
- name = "random plushie"
- desc = "This is a random plushie."
- icon = 'icons/obj/toy.dmi'
- icon_state = "nymphplushie"
-
-/obj/random/plushie/item_to_spawn()
- return pick(/obj/structure/plushie/ian,
- /obj/structure/plushie/drone,
- /obj/structure/plushie/carp,
- /obj/structure/plushie/beepsky,
- /obj/item/toy/plushie/nymph,
- /obj/item/toy/plushie/mouse,
- /obj/item/toy/plushie/kitten,
- /obj/item/toy/plushie/lizard)
-
-/obj/random/junk //Broken items, or stuff that could be picked up
- name = "random junk"
- desc = "This is some random junk."
- icon = 'icons/obj/trash.dmi'
- icon_state = "trashbag3"
-
-/obj/random/junk/item_to_spawn()
- return get_random_junk_type()
-
-/obj/random/trash //Mostly remains and cleanable decals. Stuff a janitor could clean up
- name = "random trash"
- desc = "This is some random trash."
- icon = 'icons/effects/effects.dmi'
- icon_state = "greenglow"
-
-/obj/random/trash/item_to_spawn()
- return pick(/obj/effect/decal/remains/lizard,
- /obj/effect/decal/cleanable/blood/gibs/robot,
- /obj/effect/decal/cleanable/blood/oil,
- /obj/effect/decal/cleanable/blood/oil/streak,
- /obj/effect/decal/cleanable/spiderling_remains,
- /obj/effect/decal/remains/mouse,
- /obj/effect/decal/cleanable/vomit,
- /obj/effect/decal/cleanable/blood/splatter,
- /obj/effect/decal/cleanable/ash,
- /obj/effect/decal/cleanable/generic,
- /obj/effect/decal/cleanable/flour,
- /obj/effect/decal/cleanable/dirt,
- /obj/effect/decal/remains/robot)
-
-/obj/random/obstruction //Large objects to block things off in maintenance
- name = "random obstruction"
- desc = "This is a random obstruction."
- icon = 'icons/obj/cult.dmi'
- icon_state = "cultgirder"
-
-/obj/random/obstruction/item_to_spawn()
- return pick(/obj/structure/barricade,
- /obj/structure/girder,
- /obj/structure/girder/displaced,
- /obj/structure/girder/reinforced,
- /obj/structure/grille,
- /obj/structure/grille/broken,
- /obj/structure/foamedmetal,
- /obj/structure/inflatable,
- /obj/structure/inflatable/door)
-
-/obj/random/material //Random materials for building stuff
- name = "random material"
- desc = "This is a random material."
- icon = 'icons/obj/items.dmi'
- icon_state = "sheet-metal"
-
-/obj/random/material/item_to_spawn()
- return pick(/obj/item/stack/material/steel{amount = 10},
- /obj/item/stack/material/glass{amount = 10},
- /obj/item/stack/material/glass/reinforced{amount = 10},
- /obj/item/stack/material/plastic{amount = 10},
- /obj/item/stack/material/wood{amount = 10},
- /obj/item/stack/material/cardboard{amount = 10},
- /obj/item/stack/rods{amount = 10},
- /obj/item/stack/material/plasteel{amount = 10})
-
-/obj/random/toy
- name = "random toy"
- desc = "This is a random toy."
- icon = 'icons/obj/toy.dmi'
- icon_state = "ship"
-
-/obj/random/toy/item_to_spawn()
- return pick(/obj/item/toy/bosunwhistle,
- /obj/item/toy/plushie/therapy/red,
- /obj/item/toy/plushie/therapy/purple,
- /obj/item/toy/plushie/therapy/blue,
- /obj/item/toy/plushie/therapy/yellow,
- /obj/item/toy/plushie/therapy/orange,
- /obj/item/toy/plushie/therapy/green,
- /obj/item/toy/cultsword,
- /obj/item/toy/katana,
- /obj/item/toy/snappop,
- /obj/item/toy/sword,
- /obj/item/toy/balloon,
- /obj/item/toy/crossbow,
- /obj/item/toy/blink,
- /obj/item/toy/waterflower,
- /obj/item/toy/prize/ripley,
- /obj/item/toy/prize/fireripley,
- /obj/item/toy/prize/deathripley,
- /obj/item/toy/prize/gygax,
- /obj/item/toy/prize/durand,
- /obj/item/toy/prize/honk,
- /obj/item/toy/prize/marauder,
- /obj/item/toy/prize/seraph,
- /obj/item/toy/prize/mauler,
- /obj/item/toy/prize/odysseus,
- /obj/item/toy/prize/phazon)
-
-/obj/random/tank
- name = "random tank"
- desc = "This is a tank."
- icon = 'icons/obj/tank.dmi'
- icon_state = "canister"
-
-/obj/random/tank/item_to_spawn()
- return pick(prob(5);/obj/item/weapon/tank/oxygen,
- prob(4);/obj/item/weapon/tank/oxygen/yellow,
- prob(4);/obj/item/weapon/tank/oxygen/red,
- prob(3);/obj/item/weapon/tank/air,
- prob(4);/obj/item/weapon/tank/emergency/oxygen,
- prob(3);/obj/item/weapon/tank/emergency/oxygen/engi,
- prob(2);/obj/item/weapon/tank/emergency/oxygen/double,
- prob(1);/obj/item/device/suit_cooling_unit)
-
-/obj/random/cigarettes
- name = "random cigarettes"
- desc = "This is a cigarette."
- icon = 'icons/obj/cigarettes.dmi'
- icon_state = "cigpacket"
-
-/obj/random/cigarettes/item_to_spawn()
- return pick(prob(5);/obj/item/weapon/storage/fancy/cigarettes,
- prob(4);/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/killthroat,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/luckystars,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/jerichos,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/menthols,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/carcinomas,
- prob(3);/obj/item/weapon/storage/fancy/cigarettes/professionals,
- prob(1);/obj/item/weapon/storage/fancy/cigar,
- prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar,
- prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba,
- prob(1);/obj/item/clothing/mask/smokable/cigarette/cigar/havana)
-
-/obj/random/maintenance //Clutter and loot for maintenance and away missions
- name = "random maintenance item"
- desc = "This is a random maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/item_to_spawn()
- return pick(prob(300);/obj/random/tech_supply,
- prob(200);/obj/random/medical,
- prob(100);/obj/random/firstaid,
- prob(10);/obj/random/contraband,
- prob(50);/obj/random/action_figure,
- prob(50);/obj/random/plushie,
- prob(200);/obj/random/junk,
- prob(200);/obj/random/material,
- prob(50);/obj/random/toy,
- prob(100);/obj/random/tank,
- prob(50);/obj/random/soap,
- prob(60);/obj/random/drinkbottle,
- prob(500);/obj/random/maintenance/clean)
-
-/obj/random/maintenance/clean
-/*Maintenance loot lists without the trash, for use inside things.
-Individual items to add to the maintenance list should go here, if you add
-something, make sure it's not in one of the other lists.*/
- name = "random clean maintenance item"
- desc = "This is a random clean maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/clean/item_to_spawn()
- return pick(prob(10);/obj/random/contraband,
- prob(2);/obj/item/device/flashlight/flare,
- prob(2);/obj/item/device/flashlight/glowstick,
- prob(2);/obj/item/device/flashlight/glowstick/blue,
- prob(1);/obj/item/device/flashlight/glowstick/orange,
- prob(1);/obj/item/device/flashlight/glowstick/red,
- prob(1);/obj/item/device/flashlight/glowstick/yellow,
- prob(1);/obj/item/device/flashlight/pen,
- prob(4);/obj/item/weapon/cell,
- prob(4);/obj/item/weapon/cell/device,
- prob(3);/obj/item/weapon/cell/high,
- prob(2);/obj/item/weapon/cell/super,
- prob(5);/obj/random/cigarettes,
- prob(3);/obj/item/clothing/mask/gas,
- prob(2);/obj/item/clothing/mask/gas/half,
- prob(4);/obj/item/clothing/mask/breath,
- prob(2);/obj/item/weapon/reagent_containers/glass/rag,
- prob(4);/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
- prob(2);/obj/item/weapon/storage/secure/briefcase,
- prob(4);/obj/item/weapon/storage/briefcase,
- prob(5);/obj/item/weapon/storage/backpack,
- prob(5);/obj/item/weapon/storage/backpack/satchel/norm,
- prob(4);/obj/item/weapon/storage/backpack/satchel,
- prob(3);/obj/item/weapon/storage/backpack/dufflebag,
- prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie,
- prob(5);/obj/item/weapon/storage/box,
- prob(3);/obj/item/weapon/storage/box/donkpockets,
- prob(2);/obj/item/weapon/storage/box/sinpockets,
- prob(1);/obj/item/weapon/storage/box/cups,
- prob(3);/obj/item/weapon/storage/box/mousetraps,
- prob(3);/obj/item/weapon/storage/box/engineer,
- prob(3);/obj/item/weapon/storage/wallet,
- prob(1);/obj/item/device/paicard,
- prob(2);/obj/item/clothing/shoes/galoshes,
- prob(1);/obj/item/clothing/shoes/syndigaloshes,
- prob(4);/obj/item/clothing/shoes/black,
- prob(4);/obj/item/clothing/shoes/laceup,
- prob(4);/obj/item/clothing/shoes/black,
- prob(4);/obj/item/clothing/shoes/leather,
- prob(1);/obj/item/clothing/gloves/yellow,
- prob(3);/obj/item/clothing/gloves/botanic_leather,
- prob(2);/obj/item/clothing/gloves/sterile/latex,
- prob(5);/obj/item/clothing/gloves/white,
- prob(5);/obj/item/clothing/gloves/rainbow,
- prob(2);/obj/item/clothing/gloves/fyellow,
- prob(1);/obj/item/clothing/glasses/sunglasses,
- prob(3);/obj/item/clothing/glasses/meson,
- prob(2);/obj/item/clothing/glasses/meson/prescription,
- prob(1);/obj/item/clothing/glasses/welding,
- prob(1);/obj/item/clothing/head/bio_hood/general,
- prob(4);/obj/item/clothing/head/hardhat,
- prob(3);/obj/item/clothing/head/hardhat/red,
- prob(1);/obj/item/clothing/head/ushanka,
- prob(2);/obj/item/clothing/head/welding,
- prob(4);/obj/item/clothing/suit/storage/hazardvest,
- prob(1);/obj/item/clothing/suit/space/emergency,
- prob(3);/obj/item/clothing/suit/storage/toggle/bomber,
- prob(1);/obj/item/clothing/suit/bio_suit/general,
- prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/black,
- prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/blue,
- prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/red,
- prob(3);/obj/item/clothing/suit/storage/toggle/hoodie/yellow,
- prob(3);/obj/item/clothing/suit/storage/toggle/brown_jacket,
- prob(3);/obj/item/clothing/suit/storage/toggle/leather_jacket,
- prob(1);/obj/item/clothing/suit/storage/vest/press,
- prob(3);/obj/item/clothing/suit/storage/apron,
- prob(4);/obj/item/clothing/under/color/grey,
- prob(2);/obj/item/clothing/under/syndicate/tacticool,
- prob(2);/obj/item/clothing/under/pants/camo,
- prob(1);/obj/item/clothing/under/harness,
- prob(1);/obj/item/clothing/under/tactical,
- prob(3);/obj/item/clothing/accessory/storage/webbing,
- prob(4);/obj/item/weapon/spacecash/c1,
- prob(3);/obj/item/weapon/spacecash/c10,
- prob(3);/obj/item/weapon/spacecash/c20,
- prob(1);/obj/item/weapon/spacecash/c50,
- prob(1);/obj/item/weapon/spacecash/c100,
- prob(3);/obj/item/weapon/camera_assembly,
- prob(4);/obj/item/weapon/caution,
- prob(3);/obj/item/weapon/caution/cone,
- prob(1);/obj/item/weapon/card/emag_broken,
- prob(2);/obj/item/device/camera,
- prob(3);/obj/item/device/pda,
- prob(3);/obj/item/device/radio/headset)
-
-/obj/random/maintenance/security
-/*Maintenance loot list. This one is for around security areas*/
- name = "random security maintenance item"
- desc = "This is a random security maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/security/item_to_spawn()
- return pick(prob(320);/obj/random/maintenance/clean,
- prob(2);/obj/item/device/flashlight/maglight,
- prob(2);/obj/item/device/flash,
- prob(1);/obj/item/weapon/cell/device/weapon,
- prob(1);/obj/item/clothing/mask/gas/swat,
- prob(1);/obj/item/clothing/mask/gas/syndicate,
- prob(2);/obj/item/clothing/mask/balaclava,
- prob(1);/obj/item/clothing/mask/balaclava/tactical,
- prob(3);/obj/item/weapon/storage/backpack/security,
- prob(3);/obj/item/weapon/storage/backpack/satchel/sec,
- prob(2);/obj/item/weapon/storage/backpack/messenger/sec,
- prob(2);/obj/item/weapon/storage/backpack/dufflebag/sec,
- prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo,
- prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/med,
- prob(2);/obj/item/weapon/storage/box/swabs,
- prob(2);/obj/item/weapon/storage/belt/security,
- prob(1);/obj/item/weapon/grenade/flashbang,
- prob(1);/obj/item/weapon/melee/baton,
- prob(1);/obj/item/weapon/reagent_containers/spray/pepper,
- prob(3);/obj/item/clothing/shoes/boots/jackboots,
- prob(1);/obj/item/clothing/shoes/boots/swat,
- prob(1);/obj/item/clothing/shoes/boots/combat,
- prob(1);/obj/item/clothing/gloves/swat,
- prob(1);/obj/item/clothing/gloves/combat,
- prob(1);/obj/item/clothing/glasses/sunglasses/big,
- prob(2);/obj/item/clothing/glasses/hud/security,
- prob(1);/obj/item/clothing/glasses/sunglasses/sechud,
- prob(1);/obj/item/clothing/glasses/sunglasses/sechud/aviator,
- prob(1);/obj/item/clothing/glasses/sunglasses/sechud/tactical,
- prob(3);/obj/item/clothing/head/beret/sec,
- prob(3);/obj/item/clothing/head/beret/sec/corporate/officer,
- prob(3);/obj/item/clothing/head/beret/sec/navy/officer,
- prob(2);/obj/item/clothing/head/helmet,
- prob(4);/obj/item/clothing/head/soft/sec,
- prob(4);/obj/item/clothing/head/soft/sec/corp,
- prob(3);/obj/item/clothing/suit/armor/vest,
- prob(2);/obj/item/clothing/suit/armor/vest/security,
- prob(2);/obj/item/clothing/suit/storage/vest/officer,
- prob(1);/obj/item/clothing/suit/storage/vest/detective,
- prob(1);/obj/item/clothing/suit/storage/vest/press,
- prob(2);/obj/item/clothing/accessory/storage/black_vest,
- prob(2);/obj/item/clothing/accessory/storage/black_drop_pouches,
- prob(1);/obj/item/clothing/accessory/holster/leg,
- prob(1);/obj/item/clothing/accessory/holster/hip,
- prob(1);/obj/item/clothing/accessory/holster/waist,
- prob(1);/obj/item/clothing/accessory/holster/armpit,
- prob(2);/obj/item/clothing/ears/earmuffs,
- prob(2);/obj/item/weapon/handcuffs,)
-
-/obj/random/maintenance/medical
-/*Maintenance loot list. This one is for around medical areas*/
- name = "random medical maintenance item"
- desc = "This is a random medical maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/medical/item_to_spawn()
- return pick(prob(320);/obj/random/maintenance/clean,
- prob(25);/obj/random/medical/lite,
- prob(2);/obj/item/clothing/mask/breath/medical,
- prob(2);/obj/item/clothing/mask/surgical,
- prob(5);/obj/item/weapon/storage/backpack/medic,
- prob(5);/obj/item/weapon/storage/backpack/satchel/med,
- prob(5);/obj/item/weapon/storage/backpack/messenger/med,
- prob(3);/obj/item/weapon/storage/backpack/dufflebag/med,
- prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/med,
- prob(2);/obj/item/weapon/storage/box/autoinjectors,
- prob(3);/obj/item/weapon/storage/box/beakers,
- prob(2);/obj/item/weapon/storage/box/bodybags,
- prob(3);/obj/item/weapon/storage/box/syringes,
- prob(3);/obj/item/weapon/storage/box/gloves,
- prob(2);/obj/item/weapon/storage/belt/medical/emt,
- prob(2);/obj/item/weapon/storage/belt/medical,
- prob(1);/obj/item/clothing/shoes/boots/combat,
- prob(3);/obj/item/clothing/shoes/white,
- prob(2);/obj/item/clothing/gloves/sterile/nitrile,
- prob(5);/obj/item/clothing/gloves/white,
- prob(2);/obj/item/clothing/glasses/hud/health,
- prob(1);/obj/item/clothing/glasses/hud/health/prescription,
- prob(1);/obj/item/clothing/head/bio_hood/virology,
- prob(4);/obj/item/clothing/suit/storage/toggle/labcoat,
- prob(1);/obj/item/clothing/suit/bio_suit/general,
- prob(2);/obj/item/clothing/under/rank/medical/paramedic,
- prob(2);/obj/item/clothing/accessory/storage/black_vest,
- prob(2);/obj/item/clothing/accessory/storage/white_vest,
- prob(1);/obj/item/clothing/accessory/storage/white_drop_pouches,
- prob(1);/obj/item/clothing/accessory/storage/black_drop_pouches,
- prob(2);/obj/item/clothing/accessory/stethoscope)
-
-/obj/random/maintenance/engineering
-/*Maintenance loot list. This one is for around medical areas*/
- name = "random engineering maintenance item"
- desc = "This is a random engineering maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/engineering/item_to_spawn()
- return pick(prob(320);/obj/random/maintenance/clean,
- prob(2);/obj/item/device/flashlight/maglight,
- prob(3);/obj/item/clothing/mask/gas/half,
- prob(2);/obj/item/clothing/mask/balaclava,
- prob(2);/obj/item/weapon/storage/briefcase/inflatable,
- prob(5);/obj/item/weapon/storage/backpack/industrial,
- prob(5);/obj/item/weapon/storage/backpack/satchel/eng,
- prob(5);/obj/item/weapon/storage/backpack/messenger/engi,
- prob(3);/obj/item/weapon/storage/backpack/dufflebag/eng,
- prob(5);/obj/item/weapon/storage/box,
- prob(3);/obj/item/weapon/storage/box/engineer,
- prob(2);/obj/item/weapon/storage/belt/utility/full,
- prob(3);/obj/item/weapon/storage/belt/utility,
- prob(3);/obj/item/clothing/head/beret/engineering,
- prob(3);/obj/item/clothing/head/soft/yellow,
- prob(2);/obj/item/clothing/head/orangebandana,
- prob(2);/obj/item/clothing/head/hardhat/dblue,
- prob(2);/obj/item/clothing/head/hardhat/orange,
- prob(1);/obj/item/clothing/glasses/welding,
- prob(2);/obj/item/clothing/head/welding,
- prob(4);/obj/item/clothing/suit/storage/hazardvest,
- prob(2);/obj/item/clothing/under/overalls,
- prob(3);/obj/item/clothing/shoes/boots/workboots,
- prob(1);/obj/item/clothing/shoes/magboots,
- prob(2);/obj/item/clothing/accessory/storage/black_vest,
- prob(2);/obj/item/clothing/accessory/storage/brown_vest,
- prob(1);/obj/item/clothing/accessory/storage/brown_drop_pouches,
- prob(3);/obj/item/clothing/ears/earmuffs,
- prob(1);/obj/item/weapon/beartrap,
- prob(2);/obj/item/weapon/handcuffs)
-
-/obj/random/maintenance/research
-/*Maintenance loot list. This one is for around medical areas*/
- name = "random research maintenance item"
- desc = "This is a random research maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/research/item_to_spawn()
- return pick(prob(320);/obj/random/maintenance/clean,
- prob(3);/obj/item/device/analyzer/plant_analyzer,
- prob(1);/obj/item/device/flash/synthetic,
- prob(2);/obj/item/weapon/bucket_sensor,
- prob(1);/obj/item/weapon/cell/device/weapon,
- prob(5);/obj/item/weapon/storage/backpack/toxins,
- prob(5);/obj/item/weapon/storage/backpack/satchel/tox,
- prob(5);/obj/item/weapon/storage/backpack/messenger/tox,
- prob(2);/obj/item/weapon/storage/excavation,
- prob(1);/obj/item/weapon/storage/backpack/holding,
- prob(3);/obj/item/weapon/storage/box/beakers,
- prob(3);/obj/item/weapon/storage/box/syringes,
- prob(3);/obj/item/weapon/storage/box/gloves,
- prob(2);/obj/item/clothing/gloves/sterile/latex,
- prob(4);/obj/item/clothing/glasses/science,
- prob(3);/obj/item/clothing/glasses/material,
- prob(1);/obj/item/clothing/head/beret/purple,
- prob(1);/obj/item/clothing/head/bio_hood/scientist,
- prob(4);/obj/item/clothing/suit/storage/toggle/labcoat,
- prob(4);/obj/item/clothing/suit/storage/toggle/labcoat/science,
- prob(1);/obj/item/clothing/suit/bio_suit/scientist,
- prob(4);/obj/item/clothing/under/rank/scientist,
- prob(2);/obj/item/clothing/under/rank/scientist_new)
-
-/obj/random/maintenance/cargo
-/*Maintenance loot list. This one is for around cargo areas*/
- name = "random cargo maintenance item"
- desc = "This is a random cargo maintenance item."
- icon = 'icons/obj/items.dmi'
- icon_state = "gift1"
-
-/obj/random/maintenance/cargo/item_to_spawn()
- return pick(prob(320);/obj/random/maintenance/clean,
- prob(3);/obj/item/device/flashlight/lantern,
- prob(4);/obj/item/weapon/pickaxe,
- prob(5);/obj/item/weapon/storage/backpack/industrial,
- prob(5);/obj/item/weapon/storage/backpack/satchel/norm,
- prob(3);/obj/item/weapon/storage/backpack/dufflebag,
- prob(1);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo,
- prob(1);/obj/item/weapon/storage/toolbox/syndicate,
- prob(1);/obj/item/weapon/storage/belt/utility/full,
- prob(2);/obj/item/weapon/storage/belt/utility,
- prob(4);/obj/item/device/toner,
- prob(1);/obj/item/device/destTagger,
- prob(3);/obj/item/clothing/glasses/material,
- prob(3);/obj/item/clothing/head/soft/yellow,
- prob(4);/obj/item/clothing/suit/storage/hazardvest,
- prob(3);/obj/item/clothing/suit/storage/apron/overalls,
- prob(4);/obj/item/clothing/suit/storage/apron,
- prob(2);/obj/item/clothing/under/syndicate/tacticool,
- prob(1);/obj/item/clothing/under/syndicate/combat,
- prob(2);/obj/item/clothing/accessory/storage/black_vest,
- prob(2);/obj/item/clothing/accessory/storage/brown_vest,
- prob(3);/obj/item/clothing/ears/earmuffs,
- prob(1);/obj/item/weapon/beartrap,
- prob(2);/obj/item/weapon/handcuffs,)
-
-/obj/random/sfr
- name = "random SFR headset"
- desc = "This is a headset spawn."
- icon = 'icons/misc/mark.dmi'
- icon_state = "rup"
-
-/obj/random/sfr/item_to_spawn()
- return pick(prob(25);/obj/item/device/radio/headset/heads/captain/sfr,
- prob(25);/obj/item/device/radio/headset/headset_cargo/alt,
- prob(25);/obj/item/device/radio/headset/headset_com/alt,
- prob(25);/obj/item/device/radio/headset)
-
-/obj/random/rigsuit
- name = "Random rigsuit"
- desc = "This is a random rigsuit."
- icon = 'icons/obj/rig_modules.dmi'
- icon_state = "generic"
-
-/obj/random/rigsuit/item_to_spawn()
- return pick(prob(4);/obj/item/weapon/rig/light/hacker,
- prob(5);/obj/item/weapon/rig/industrial,
- prob(5);/obj/item/weapon/rig/eva,
- prob(4);/obj/item/weapon/rig/light/stealth,
- prob(3);/obj/item/weapon/rig/hazard,
- prob(1);/obj/item/weapon/rig/merc/empty)
-
-var/list/random_junk_
-var/list/random_useful_
-/proc/get_random_useful_type()
- if(!random_useful_)
- random_useful_ = subtypesof(/obj/item/weapon/pen/crayon)
- random_useful_ += /obj/item/weapon/pen
- random_useful_ += /obj/item/weapon/pen/blue
- random_useful_ += /obj/item/weapon/pen/red
- random_useful_ += /obj/item/weapon/pen/multi
- random_useful_ += /obj/item/weapon/storage/box/matches
- random_useful_ += /obj/item/stack/material/cardboard
- return pick(random_useful_)
-
-/proc/get_random_junk_type()
- if(prob(20)) // Misc. clutter
- return /obj/effect/decal/cleanable/generic
- if(prob(70)) // Misc. junk
- if(!random_junk_)
- random_junk_ = subtypesof(/obj/item/trash)
- random_junk_ += typesof(/obj/item/weapon/cigbutt)
- random_junk_ += /obj/effect/decal/cleanable/spiderling_remains
- random_junk_ += /obj/effect/decal/remains/mouse
- random_junk_ += /obj/effect/decal/remains/robot
- random_junk_ += /obj/item/weapon/paper/crumpled
- random_junk_ += /obj/item/inflatable/torn
- random_junk_ += /obj/effect/decal/cleanable/molten_item
- random_junk_ += /obj/item/weapon/material/shard
-
- random_junk_ -= /obj/item/trash/plate
- random_junk_ -= /obj/item/trash/snack_bowl
- random_junk_ -= /obj/item/trash/syndi_cakes
- random_junk_ -= /obj/item/trash/tray
- return pick(random_junk_)
- // Misc. actually useful stuff
- return get_random_useful_type()
-
-/*
- Selects one spawn point out of a group of points with the same ID and asks it to generate its items
-*/
-var/list/multi_point_spawns
-
-/obj/random_multi
- name = "random object spawn point"
- desc = "This item type is used to spawn random objects at round-start. Only one spawn point for a given group id is selected."
- icon = 'icons/misc/mark.dmi'
- icon_state = "x3"
- invisibility = INVISIBILITY_MAXIMUM
- var/id // Group id
- var/weight // Probability weight for this spawn point
-
-/obj/random_multi/initialize()
- . = ..()
- weight = max(1, round(weight))
-
- if(!multi_point_spawns)
- multi_point_spawns = list()
- var/list/spawnpoints = multi_point_spawns[id]
- if(!spawnpoints)
- spawnpoints = list()
- multi_point_spawns[id] = spawnpoints
- spawnpoints[src] = weight
-
-/obj/random_multi/Destroy()
- var/list/spawnpoints = multi_point_spawns[id]
- spawnpoints -= src
- if(!spawnpoints.len)
- multi_point_spawns -= id
- . = ..()
-
-/obj/random_multi/proc/generate_items()
- return
-
-/obj/random_multi/single_item
- var/item_path // Item type to spawn
-
-/obj/random_multi/single_item/generate_items()
- new item_path(loc)
-
-/hook/roundstart/proc/generate_multi_spawn_items()
- for(var/id in multi_point_spawns)
- var/list/spawn_points = multi_point_spawns[id]
- var/obj/random_multi/rm = pickweight(spawn_points)
- rm.generate_items()
- for(var/entry in spawn_points)
- qdel(entry)
- return 1
-
-/obj/random_multi/single_item/captains_spare_id
- name = "Multi Point - Captain's Spare"
- id = "Captain's spare id"
- item_path = /obj/item/weapon/card/id/gold/captain/spare
-
-/obj/random_multi/single_item/sfr_headset
- name = "Multi Point - headset"
- id = "SFR headset"
- item_path = /obj/random/sfr
-
-//Multiple Object Spawn
-
-/obj/random/multiple
-
-/obj/random/multiple/spawn_item()
- var/list/things_to_make = item_to_spawn()
- for(var/new_type in things_to_make)
- new new_type(src.loc)
-
-/obj/random/multiple/voidsuit
- name = "Random Voidsuit"
- desc = "This is a random voidsuit."
- icon = 'icons/obj/clothing/suits.dmi'
- icon_state = "void"
-
-/obj/random/multiple/voidsuit/item_to_spawn()
- return pick(
- prob(5);list(
- /obj/item/clothing/suit/space/void,
- /obj/item/clothing/head/helmet/space/void
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/atmos,
- /obj/item/clothing/head/helmet/space/void/atmos
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/atmos/alt,
- /obj/item/clothing/head/helmet/space/void/atmos/alt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/engineering,
- /obj/item/clothing/head/helmet/space/void/engineering
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/engineering/alt,
- /obj/item/clothing/head/helmet/space/void/engineering/alt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/engineering/construction,
- /obj/item/clothing/head/helmet/space/void/engineering/construction
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/engineering/salvage,
- /obj/item/clothing/head/helmet/space/void/engineering/salvage
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/medical,
- /obj/item/clothing/head/helmet/space/void/medical
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/medical/alt,
- /obj/item/clothing/head/helmet/space/void/medical/alt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/medical/bio,
- /obj/item/clothing/head/helmet/space/void/medical/bio
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/medical/emt,
- /obj/item/clothing/head/helmet/space/void/medical/emt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/merc,
- /obj/item/clothing/head/helmet/space/void/merc
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/mining,
- /obj/item/clothing/head/helmet/space/void/mining
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/mining/alt,
- /obj/item/clothing/head/helmet/space/void/mining/alt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/security,
- /obj/item/clothing/head/helmet/space/void/security
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/security/alt,
- /obj/item/clothing/head/helmet/space/void/security/alt
- ),
- prob(5);list(
- /obj/item/clothing/suit/space/void/security/riot,
- /obj/item/clothing/head/helmet/space/void/security/riot
- )
- )
-
-/obj/random/multiple/voidsuit/mining
- name = "Random Mining Voidsuit"
- desc = "This is a random mining voidsuit."
- icon = 'icons/obj/clothing/suits.dmi'
- icon_state = "rig-mining"
-
-/obj/random/multiple/voidsuit/mining/item_to_spawn()
- return pick(
- prob(5);list(
- /obj/item/clothing/suit/space/void/mining,
- /obj/item/clothing/head/helmet/space/void/mining
- ),
- prob(1);list(
- /obj/item/clothing/suit/space/void/mining/alt,
- /obj/item/clothing/head/helmet/space/void/mining/alt
- )
- )
-
-/obj/random/landmine
- name = "Random Land Mine"
- desc = "This is a random land mine."
- icon = 'icons/obj/weapons.dmi'
- icon_state = "uglymine"
- spawn_nothing_percentage = 25
-
-/obj/random/landmine/item_to_spawn()
- return pick(prob(30);/obj/effect/mine,
- prob(25);/obj/effect/mine/frag,
- prob(25);/obj/effect/mine/emp,
- prob(10);/obj/effect/mine/stun,
- prob(10);/obj/effect/mine/incendiary,)
\ No newline at end of file
diff --git a/code/game/objects/random/spacesuits.dm b/code/game/objects/random/spacesuits.dm
new file mode 100644
index 0000000000..cb4ec6d4e9
--- /dev/null
+++ b/code/game/objects/random/spacesuits.dm
@@ -0,0 +1,113 @@
+
+// Spaceproof clothing sets go in here
+
+/obj/random/multiple/voidsuit
+ name = "Random Voidsuit"
+ desc = "This is a random voidsuit."
+ icon = 'icons/obj/clothing/suits.dmi'
+ icon_state = "void"
+
+/obj/random/multiple/voidsuit/item_to_spawn()
+ return pick(
+ prob(5);list(
+ /obj/item/clothing/suit/space/void,
+ /obj/item/clothing/head/helmet/space/void
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/atmos,
+ /obj/item/clothing/head/helmet/space/void/atmos
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/atmos/alt,
+ /obj/item/clothing/head/helmet/space/void/atmos/alt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/engineering,
+ /obj/item/clothing/head/helmet/space/void/engineering
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/engineering/alt,
+ /obj/item/clothing/head/helmet/space/void/engineering/alt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/engineering/construction,
+ /obj/item/clothing/head/helmet/space/void/engineering/construction
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/engineering/salvage,
+ /obj/item/clothing/head/helmet/space/void/engineering/salvage
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/medical,
+ /obj/item/clothing/head/helmet/space/void/medical
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/medical/alt,
+ /obj/item/clothing/head/helmet/space/void/medical/alt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/medical/bio,
+ /obj/item/clothing/head/helmet/space/void/medical/bio
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/medical/emt,
+ /obj/item/clothing/head/helmet/space/void/medical/emt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/merc,
+ /obj/item/clothing/head/helmet/space/void/merc
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/mining,
+ /obj/item/clothing/head/helmet/space/void/mining
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/mining/alt,
+ /obj/item/clothing/head/helmet/space/void/mining/alt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/security,
+ /obj/item/clothing/head/helmet/space/void/security
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/security/alt,
+ /obj/item/clothing/head/helmet/space/void/security/alt
+ ),
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/security/riot,
+ /obj/item/clothing/head/helmet/space/void/security/riot
+ )
+ )
+
+/obj/random/multiple/voidsuit/mining
+ name = "Random Mining Voidsuit"
+ desc = "This is a random mining voidsuit."
+ icon = 'icons/obj/clothing/suits.dmi'
+ icon_state = "rig-mining"
+
+/obj/random/multiple/voidsuit/mining/item_to_spawn()
+ return pick(
+ prob(5);list(
+ /obj/item/clothing/suit/space/void/mining,
+ /obj/item/clothing/head/helmet/space/void/mining
+ ),
+ prob(1);list(
+ /obj/item/clothing/suit/space/void/mining/alt,
+ /obj/item/clothing/head/helmet/space/void/mining/alt
+ )
+ )
+
+
+/obj/random/rigsuit
+ name = "Random rigsuit"
+ desc = "This is a random rigsuit."
+ icon = 'icons/obj/rig_modules.dmi'
+ icon_state = "generic"
+
+/obj/random/rigsuit/item_to_spawn()
+ return pick(prob(4);/obj/item/weapon/rig/light/hacker,
+ prob(5);/obj/item/weapon/rig/industrial,
+ prob(5);/obj/item/weapon/rig/eva,
+ prob(4);/obj/item/weapon/rig/light/stealth,
+ prob(3);/obj/item/weapon/rig/hazard,
+ prob(1);/obj/item/weapon/rig/merc/empty)
\ No newline at end of file
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 5c3542015c..9b3d866d2b 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -10,7 +10,8 @@ LINEN BINS
icon = 'icons/obj/items.dmi'
icon_state = "sheet"
slot_flags = SLOT_BACK
- layer = 4.0
+ plane = MOB_PLANE
+ layer = BELOW_MOB_LAYER
throwforce = 1
throw_speed = 1
throw_range = 2
@@ -19,9 +20,9 @@ LINEN BINS
/obj/item/weapon/bedsheet/attack_self(mob/user as mob)
user.drop_item()
if(layer == initial(layer))
- layer = MOB_LAYER + 0.1
+ layer = ABOVE_MOB_LAYER
else
- layer = initial(layer)
+ reset_plane_and_layer()
add_fingerprint(user)
return
diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm
index 1952ddea4f..390ddc88a3 100644
--- a/code/game/objects/structures/bonfire.dm
+++ b/code/game/objects/structures/bonfire.dm
@@ -10,6 +10,8 @@
var/next_fuel_consumption = 0 // world.time of when next item in fuel list gets eatten to sustain the fire.
var/grill = FALSE
var/material/material
+ var/set_temperature = T0C + 30 //K
+ var/heating_power = 80000
/obj/structure/bonfire/New(newloc, material_name)
..(newloc)
@@ -186,9 +188,9 @@
if(burning)
var/state
switch(get_fuel_amount())
- if(0 to 4)
+ if(0 to 4.5)
state = "bonfire_warm"
- if(5 to 10)
+ if(4.6 to 10)
state = "bonfire_hot"
var/image/I = image(icon, state)
I.appearance_flags = RESET_COLOR
@@ -223,6 +225,23 @@
if(!grill)
burn()
+ if(burning)
+ var/W = get_fuel_amount()
+ if(W >= 5)
+ var/datum/gas_mixture/env = loc.return_air()
+ if(env && abs(env.temperature - set_temperature) > 0.1)
+ var/transfer_moles = 0.25 * env.total_moles
+ var/datum/gas_mixture/removed = env.remove(transfer_moles)
+
+ if(removed)
+ var/heat_transfer = removed.get_thermal_energy_change(set_temperature)
+ if(heat_transfer > 0)
+ heat_transfer = min(heat_transfer , heating_power)
+
+ removed.add_thermal_energy(heat_transfer)
+
+ env.merge(removed)
+
/obj/structure/bonfire/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
ignite()
@@ -235,4 +254,163 @@
M.pixel_y += 13
else // Just unbuckled someone
M.pixel_y -= 13
- update_icon()
\ No newline at end of file
+ update_icon()
+
+/obj/structure/fireplace //more like a space heater than a bonfire. A cozier alternative to both.
+ name = "fireplace"
+ desc = "The sound of the crackling hearth reminds you of home."
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "fireplace"
+ density = TRUE
+ anchored = TRUE
+ var/burning = FALSE
+ var/next_fuel_consumption = 0
+ var/set_temperature = T0C + 20 //K
+ var/heating_power = 40000
+
+/obj/structure/fireplace/attackby(obj/item/W, mob/user)
+ if(istype(W, /obj/item/stack/material/wood) || istype(W, /obj/item/stack/material/log) )
+ add_fuel(W, user)
+
+ else if(W.is_hot())
+ ignite()
+ else
+ return ..()
+
+/obj/structure/fireplace/attack_hand(mob/user)
+ if(get_fuel_amount())
+ remove_fuel(user)
+
+/obj/structure/fireplace/proc/get_fuel_amount()
+ var/F = 0
+ for(var/A in contents)
+ if(istype(A, /obj/item/stack/material/wood))
+ F += 0.5
+ if(istype(A, /obj/item/stack/material/log))
+ F += 1.0
+ return F
+
+/obj/structure/fireplace/proc/remove_fuel(mob/user)
+ if(get_fuel_amount())
+ var/atom/movable/AM = pop(contents)
+ AM.forceMove(get_turf(src))
+ to_chat(user, "You take \the [AM] out of \the [src] before it has a chance to burn away.")
+ update_icon()
+
+/obj/structure/fireplace/proc/add_fuel(atom/movable/new_fuel, mob/user)
+ if(get_fuel_amount() >= 10)
+ to_chat(user, "\The [src] already has enough fuel!")
+ return FALSE
+ if(istype(new_fuel, /obj/item/stack/material/wood) || istype(new_fuel, /obj/item/stack/material/log) )
+ var/obj/item/stack/F = new_fuel
+ var/obj/item/stack/S = F.split(1)
+ if(S)
+ S.forceMove(src)
+ to_chat(user, "You add \the [new_fuel] to \the [src].")
+ update_icon()
+ return TRUE
+ return FALSE
+ else
+ to_chat(user, "\The [src] needs raw wood to burn, \a [new_fuel] won't work.")
+ return FALSE
+
+/obj/structure/fireplace/proc/consume_fuel(var/obj/item/stack/consumed_fuel)
+ if(!istype(consumed_fuel))
+ qdel(consumed_fuel) // Don't know, don't care.
+ return FALSE
+
+ if(istype(consumed_fuel, /obj/item/stack/material/log))
+ next_fuel_consumption = world.time + 2 MINUTES
+ qdel(consumed_fuel)
+ update_icon()
+ return TRUE
+
+ else if(istype(consumed_fuel, /obj/item/stack/material/wood)) // One log makes two planks of wood.
+ next_fuel_consumption = world.time + 1 MINUTE
+ qdel(consumed_fuel)
+ update_icon()
+ return TRUE
+ return FALSE
+
+/obj/structure/fireplace/proc/check_oxygen()
+ var/datum/gas_mixture/G = loc.return_air()
+ if(G.gas["oxygen"] < 1)
+ return FALSE
+ return TRUE
+
+/obj/structure/fireplace/proc/extinguish()
+ if(burning)
+ burning = FALSE
+ update_icon()
+ processing_objects -= src
+ visible_message("\The [src] stops burning.")
+
+/obj/structure/fireplace/proc/ignite()
+ if(!burning && get_fuel_amount())
+ burning = TRUE
+ update_icon()
+ processing_objects += src
+ visible_message("\The [src] starts burning!")
+
+/obj/structure/fireplace/proc/burn()
+ var/turf/current_location = get_turf(src)
+ current_location.hotspot_expose(1000, 500)
+ for(var/A in current_location)
+ if(A == src)
+ continue
+ if(isobj(A))
+ var/obj/O = A
+ O.fire_act(null, 1000, 500)
+
+/obj/structure/fireplace/update_icon()
+ overlays.Cut()
+ if(burning)
+ var/state
+ switch(get_fuel_amount())
+ if(0 to 3.5)
+ state = "fireplace_warm"
+ if(3.6 to 6.5)
+ state = "fireplace_hot"
+ if(6.6 to 10)
+ state = "fireplace_intense" //don't need to throw a corpse inside to make it burn hotter.
+ var/image/I = image(icon, state)
+ I.appearance_flags = RESET_COLOR
+ overlays += I
+
+ var/light_strength = max(get_fuel_amount() / 2, 2)
+ set_light(light_strength, light_strength, "#FF9933")
+ else
+ set_light(0)
+
+/obj/structure/fireplace/process()
+ if(!check_oxygen())
+ extinguish()
+ return
+ if(world.time >= next_fuel_consumption)
+ if(!consume_fuel(pop(contents)))
+ extinguish()
+ return
+
+ if(burning)
+ var/W = get_fuel_amount()
+ if(W >= 5)
+ var/datum/gas_mixture/env = loc.return_air()
+ if(env && abs(env.temperature - set_temperature) > 0.1)
+ var/transfer_moles = 0.25 * env.total_moles
+ var/datum/gas_mixture/removed = env.remove(transfer_moles)
+
+ if(removed)
+ var/heat_transfer = removed.get_thermal_energy_change(set_temperature)
+ if(heat_transfer > 0)
+ heat_transfer = min(heat_transfer , heating_power)
+
+ removed.add_thermal_energy(heat_transfer)
+
+ env.merge(removed)
+
+/obj/structure/fireplace/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ ignite()
+
+/obj/structure/fireplace/water_act(amount)
+ if(prob(amount * 10))
+ extinguish()
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 7e922e97bb..e25553d361 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -415,3 +415,6 @@
/obj/structure/closet/onDropInto(var/atom/movable/AM)
return
+
+/obj/structure/closet/AllowDrop()
+ return TRUE
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
index eb2ab38b52..103867ef88 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm
@@ -67,3 +67,34 @@
new /obj/item/clothing/suit/storage/hooded/wintercoat/cargo(src)
new /obj/item/clothing/shoes/boots/winter/supply(src)
return
+
+/obj/structure/closet/secure_closet/miner
+ name = "miner's equipment"
+ icon_state = "miningsec1"
+ icon_closed = "miningsec"
+ icon_locked = "miningsec1"
+ icon_opened = "miningsecopen"
+ icon_broken = "miningsecbroken"
+ icon_off = "miningsecoff"
+ req_access = list(access_mining)
+
+/obj/structure/closet/secure_closet/miner/New()
+ ..()
+ sleep(2)
+ if(prob(50))
+ new /obj/item/weapon/storage/backpack/industrial(src)
+ else
+ new /obj/item/weapon/storage/backpack/satchel/eng(src)
+ new /obj/item/device/radio/headset/headset_mine(src)
+ new /obj/item/clothing/under/rank/miner(src)
+ new /obj/item/clothing/gloves/black(src)
+ new /obj/item/clothing/shoes/black(src)
+ new /obj/item/device/analyzer(src)
+ new /obj/item/weapon/storage/bag/ore(src)
+ new /obj/item/device/flashlight/lantern(src)
+ new /obj/item/weapon/shovel(src)
+ new /obj/item/weapon/pickaxe(src)
+ new /obj/item/clothing/glasses/material(src)
+ new /obj/item/clothing/suit/storage/hooded/wintercoat/miner(src)
+ new /obj/item/clothing/shoes/boots/winter/mining(src)
+ new /obj/item/stack/marker_beacon/thirty(src)
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 83aa687957..cf70a40920 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -103,12 +103,13 @@
if(prob(50))
new /obj/item/weapon/storage/backpack/dufflebag/sec(src)
new /obj/item/clothing/head/helmet/HoS(src)
+ new /obj/item/clothing/head/helmet/HoS/hat(src)
new /obj/item/clothing/suit/storage/vest/hos(src)
new /obj/item/clothing/under/rank/head_of_security/jensen(src)
new /obj/item/clothing/under/rank/head_of_security/corp(src)
new /obj/item/clothing/suit/storage/vest/hoscoat/jensen(src)
new /obj/item/clothing/suit/storage/vest/hoscoat(src)
- new /obj/item/clothing/head/helmet/HoS/dermal(src)
+ new /obj/item/clothing/head/helmet/dermal(src)
new /obj/item/weapon/cartridge/hos(src)
new /obj/item/device/radio/headset/heads/hos(src)
new /obj/item/device/radio/headset/heads/hos/alt(src)
@@ -161,7 +162,9 @@
new /obj/item/clothing/under/rank/warden/corp(src)
new /obj/item/clothing/suit/storage/vest/wardencoat(src)
new /obj/item/clothing/suit/storage/vest/wardencoat/alt(src)
+ new /obj/item/clothing/head/helmet/dermal(src)
new /obj/item/clothing/head/helmet/warden(src)
+ new /obj/item/clothing/head/helmet/warden/hat(src)
new /obj/item/weapon/cartridge/security(src)
new /obj/item/device/radio/headset/headset_sec(src)
new /obj/item/device/radio/headset/headset_sec/alt(src)
diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm
index 0c50bf189d..ef58518e48 100644
--- a/code/game/objects/structures/flora/trees.dm
+++ b/code/game/objects/structures/flora/trees.dm
@@ -18,6 +18,10 @@
return ..()
if(is_stump)
+ if(istype(W,/obj/item/weapon/shovel))
+ if(do_after(user, 5 SECONDS))
+ visible_message("\The [user] digs up \the [src] stump with \the [W].")
+ qdel(src)
return
visible_message("\The [user] hits \the [src] with \the [W]!")
diff --git a/code/game/objects/structures/ghost_pods/ghost_pods.dm b/code/game/objects/structures/ghost_pods/ghost_pods.dm
index 02c5f304f3..16dcd2ddb7 100644
--- a/code/game/objects/structures/ghost_pods/ghost_pods.dm
+++ b/code/game/objects/structures/ghost_pods/ghost_pods.dm
@@ -7,14 +7,17 @@
var/icon_state_opened = null // Icon to switch to when 'used'.
var/used = FALSE
var/busy = FALSE // Don't spam ghosts by spamclicking.
+ var/needscharger //For drone pods that want their pod to turn into a charger.
// Call this to get a ghost volunteer.
-/obj/structure/ghost_pod/proc/trigger()
+/obj/structure/ghost_pod/proc/trigger(var/alert, var/adminalert)
if(!ghost_query_type)
return FALSE
if(busy)
return FALSE
+ visible_message(alert)
+ log_and_message_admins(adminalert)
busy = TRUE
var/datum/ghost_query/Q = new ghost_query_type()
var/list/winner = Q.query()
@@ -22,8 +25,10 @@
if(winner.len)
var/mob/observer/dead/D = winner[1]
create_occupant(D)
- new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc)
- del(src)
+ icon_state = icon_state_opened
+ if(needscharger)
+ new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc)
+ del(src)
return TRUE
else
return FALSE
@@ -41,7 +46,7 @@
/obj/structure/ghost_pod/manual/attack_hand(var/mob/living/user)
if(!used)
if(confirm_before_open)
- if(alert(user, "Are you sure you want to open \the [src]?", "Confirm", "No", "Yes") == "No")
+ if(alert(user, "Are you sure you want to touch \the [src]?", "Confirm", "No", "Yes") == "No")
return
trigger()
diff --git a/code/game/objects/structures/ghost_pods/silicon.dm b/code/game/objects/structures/ghost_pods/silicon.dm
index a204437bc3..1e7210a1ec 100644
--- a/code/game/objects/structures/ghost_pods/silicon.dm
+++ b/code/game/objects/structures/ghost_pods/silicon.dm
@@ -10,11 +10,10 @@
density = TRUE
ghost_query_type = /datum/ghost_query/lost_drone
confirm_before_open = TRUE
+ needscharger = TRUE
/obj/structure/ghost_pod/manual/lost_drone/trigger()
- ..()
- visible_message("\The [src] appears to be attempting to restart the robot contained inside.")
- log_and_message_admins("is attempting to open \a [src].")
+ ..("\The [src] appears to be attempting to restart the robot contained inside.", "is attempting to open \a [src].")
/obj/structure/ghost_pod/manual/lost_drone/create_occupant(var/mob/M)
density = FALSE
@@ -45,6 +44,7 @@
icon_state_opened = "borg_pod_opened"
density = TRUE
ghost_query_type = /datum/ghost_query/gravekeeper_drone
+ needscharger = TRUE
/obj/structure/ghost_pod/automatic/gravekeeper_drone/create_occupant(var/mob/M)
density = FALSE
@@ -58,4 +58,54 @@
R.ckey = M.ckey
visible_message("As \the [src] opens, the eyes of the robot flicker as it is activated.")
R.Namepick()
+ ..()
+
+/obj/structure/ghost_pod/manual/corgi
+ name = "glowing rune"
+ desc = "This rune slowly lights up and goes dim in a repeating pattern, like a slow heartbeat. It's almost as if it's calling out to you to touch it..."
+ description_info = "This will summon some manner of creature through quite dubious means. The creature will be controlled by a player."
+ icon_state = "corgirune"
+ icon_state_opened = "corgirune-inert"
+ density = FALSE
+ anchored = TRUE
+ ghost_query_type = /datum/ghost_query/corgi_rune
+ confirm_before_open = TRUE
+
+/obj/structure/ghost_pod/manual/corgi/trigger()
+ ..("\The [usr] places their hand on the rune!", "is attempting to summon a corgi.")
+
+/obj/structure/ghost_pod/manual/corgi/create_occupant(var/mob/M)
+ density = FALSE
+ var/mob/living/simple_animal/corgi/R = new(get_turf(src))
+ if(M.mind)
+ M.mind.transfer_to(R)
+ to_chat(M, "You are a Corgi! Woof!")
+ R.ckey = M.ckey
+ visible_message("With a bright flash of light, \the [src] disappears, and in its place stands a small corgi.")
+ log_and_message_admins("successfully touched \a [src] and summoned a corgi.")
+ ..()
+
+/obj/structure/ghost_pod/manual/cursedblade
+ name = "abandoned blade"
+ desc = "A red crystal blade that someone jammed deep into a stone. If you try hard enough, you might be able to remove it."
+ icon_state = "soulblade-embedded"
+ icon_state_opened = "soulblade-released"
+ density = TRUE
+ anchored = TRUE
+ ghost_query_type = /datum/ghost_query/cursedblade
+ confirm_before_open = TRUE
+
+/obj/structure/ghost_pod/manual/cursedblade/trigger()
+ ..("\The [usr] attempts to pull out the sword!", "is activating a cursed blade.")
+
+/obj/structure/ghost_pod/manual/cursedblade/create_occupant(var/mob/M)
+ density = FALSE
+ var/obj/item/weapon/melee/cursedblade/R = new(get_turf(src))
+ to_chat(M, "You are a Cursed Sword, discovered by a hapless explorer. \
+ You were once an explorer yourself, when one day you discovered a strange sword made from a red crystal. As soon as you touched it,\
+ your body was reduced to ashes and your soul was cursed to remain trapped in the blade forever. \
+ Now it is up to you to decide whether you want to be a faithful companion, or a bitter prisoner of the blade.")
+ R.ghost_inhabit(M)
+ visible_message("The blade shines brightly for a brief moment as [usr] pulls it out of the stone!")
+ log_and_message_admins("successfully acquired a cursed sword.")
..()
\ No newline at end of file
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index a3ff9ac9af..a22bbae0d2 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -2,7 +2,7 @@
icon_state = "girder"
anchored = 1
density = 1
- layer = 2
+ plane = PLATING_PLANE
w_class = ITEMSIZE_HUGE
var/state = 0
var/health = 200
diff --git a/code/game/objects/structures/gravemarker.dm b/code/game/objects/structures/gravemarker.dm
index a10cd0bf6e..e20591b939 100644
--- a/code/game/objects/structures/gravemarker.dm
+++ b/code/game/objects/structures/gravemarker.dm
@@ -8,7 +8,7 @@
throwpass = 1
climbable = 1
- layer = 3.1 //Above dirt piles
+ layer = ABOVE_JUNK_LAYER
//Maybe make these calculate based on material?
var/health = 100
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 6fea7e6ece..ee80999916 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -7,7 +7,7 @@
anchored = 1
flags = CONDUCT
pressure_resistance = 5*ONE_ATMOSPHERE
- layer = 2.9
+ layer = UNDER_JUNK_LAYER
explosion_resistance = 1
var/health = 10
var/destroyed = 0
diff --git a/code/game/objects/structures/holoplant.dm b/code/game/objects/structures/holoplant.dm
new file mode 100644
index 0000000000..1f6473ebdc
--- /dev/null
+++ b/code/game/objects/structures/holoplant.dm
@@ -0,0 +1,105 @@
+/obj/machinery/holoplant
+ name = "holoplant"
+ desc = "One of those Ward-Takahashi holoplants! Give your space a bit of the comfort of being outdoors, by buying this blue buddy. A rugged case guarantees that your flower will outlive you, and variety of plant types won't let you to get bored along the way!"
+ icon = 'icons/obj/holoplants.dmi'
+ icon_state = "holopot"
+ light_color = "#3C94C5"
+ anchored = TRUE
+ idle_power_usage = 0
+ active_power_usage = 5
+ var/interference = FALSE
+ var/icon/plant = null
+ var/global/list/possible_plants = list(
+ "plant-1",
+ "plant-10",
+ "plant-09",
+ "plant-15",
+ "plant-13"
+ )
+
+/obj/machinery/holoplant/initialize()
+ . = ..()
+ activate()
+
+/obj/machinery/holoplant/attack_hand(var/mob/living/user)
+ if(!istype(user) || interference)
+ return
+
+ if(!anchored)
+ to_chat(user,"\The [src] must be anchored before activation!")
+ return
+
+ if(!plant)
+ activate()
+ else
+ deactivate()
+
+/obj/machinery/holoplant/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(default_unfasten_wrench(user, O, 10))
+ deactivate()
+ return
+
+ . = ..()
+
+/obj/machinery/holoplant/proc/activate()
+ if(!anchored || stat & (NOPOWER|BROKEN))
+ return
+
+ plant = prepare_icon(emagged ? "emagged" : null)
+ overlays += plant
+ set_light(2)
+ use_power = 2
+
+/obj/machinery/holoplant/proc/deactivate()
+ overlays -= plant
+ qdel_null(plant)
+ set_light(0)
+ use_power = 0
+
+/obj/machinery/holoplant/power_change()
+ ..()
+ if(stat & NOPOWER)
+ deactivate()
+ else
+ activate()
+
+/obj/machinery/holoplant/proc/flicker()
+ interference = TRUE
+ spawn(0)
+ overlays -= plant
+ set_light(0)
+ sleep(rand(2,4))
+ overlays += plant
+ set_light(2)
+ sleep(rand(2,4))
+ overlays -= plant
+ set_light(0)
+ sleep(rand(2,4))
+ overlays += plant
+ set_light(2)
+ interference = FALSE
+
+/obj/machinery/holoplant/proc/prepare_icon(var/state)
+ if(!state)
+ state = pick(possible_plants)
+ var/plant_icon = icon(icon, state)
+ return getHologramIcon(plant_icon, 0)
+
+/obj/machinery/holoplant/emag_act()
+ if(emagged)
+ return
+
+ emagged = TRUE
+ if(plant)
+ deactivate()
+ activate()
+
+/obj/machinery/holoplant/Crossed(var/mob/living/L)
+ if(!interference && plant && istype(L))
+ flicker()
+
+
+/obj/machinery/holoplant/shipped
+ anchored = FALSE
+/obj/machinery/holoplant/shipped/initialize()
+ . = ..()
\ No newline at end of file
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index c042b8fc9a..d9ec122c55 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -6,7 +6,7 @@
density = 0
anchored = 1.0
w_class = ITEMSIZE_NORMAL
- layer = 2.3 //under pipes
+ plane = PLATING_PLANE
// flags = CONDUCT
/obj/structure/lattice/initialize()
diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm
index c9565dc90a..353dbe31a7 100644
--- a/code/game/objects/structures/loot_piles.dm
+++ b/code/game/objects/structures/loot_piles.dm
@@ -22,6 +22,8 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
density = FALSE
anchored = TRUE
+ var/list/icon_states_to_use = list() // List of icon states the pile can choose from on initialization. If empty or null, it will stay the initial icon_state.
+
var/list/searched_by = list() // Keys that have searched this loot pile, with values of searched time.
var/allow_multiple_looting = FALSE // If true, the same person can loot multiple times. Mostly for debugging.
var/busy = FALSE // Used so you can't spamclick to loot.
@@ -113,12 +115,9 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
var/path = pick(rare_loot)
return new path(src)
-
-/obj/structure/loot_pile/maint
- var/list/icon_states_to_use = list()
-
-/obj/structure/loot_pile/maint/initialize()
- icon_state = pick(icon_states_to_use)
+/obj/structure/loot_pile/initialize()
+ if(icon_states_to_use && icon_states_to_use.len)
+ icon_state = pick(icon_states_to_use)
. = ..()
// Has large amounts of possible items, most of which may or may not be useful.
@@ -278,7 +277,6 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/weapon/storage/box/donut,
/obj/item/weapon/storage/box/donut/empty,
/obj/item/weapon/storage/box/evidence,
- /obj/item/weapon/storage/box/engineer,
/obj/item/weapon/storage/box/lights/mixed,
/obj/item/weapon/storage/box/lights/tubes,
/obj/item/weapon/storage/box/lights/bulbs,
@@ -439,7 +437,7 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
// Base type for alien piles.
/obj/structure/loot_pile/surface/alien
name = "alien pod"
- desc = "A pod which looks bigger on the inside. Something quiet shiny might be inside?"
+ desc = "A pod which looks bigger on the inside. Something quite shiny might be inside?"
icon_state = "alien_pile1"
/obj/structure/loot_pile/surface/alien
@@ -569,3 +567,266 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/weapon/gun/launcher/crossbow
)
+// Subtype for mecha and mecha accessories. These might not always be on the surface.
+/obj/structure/loot_pile/mecha
+ name = "pod wreckage"
+ desc = "The ruins of some unfortunate pod. Perhaps something is salvageable."
+ icon = 'icons/mecha/mecha.dmi'
+ icon_state = "engineering_pod-broken"
+ density = TRUE
+
+ chance_uncommon = 20
+ chance_rare = 10
+
+ loot_depletion = TRUE
+ loot_left = 9
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/random/tool,
+ /obj/random/tool,
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/random/tech_supply/component,
+ /obj/random/tech_supply/component,
+ /obj/effect/decal/remains/lizard,
+ /obj/effect/decal/remains/mouse,
+ /obj/effect/decal/remains/robot,
+ /obj/item/stack/material/steel{amount = 40}
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser,
+ /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,
+ /obj/item/mecha_parts/mecha_equipment/tool/drill,
+ /obj/item/mecha_parts/mecha_equipment/generator
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser,
+ /obj/item/mecha_parts/mecha_equipment/generator/nuclear,
+ /obj/item/mecha_parts/mecha_equipment/tool/jetpack
+ )
+
+//Stuff you may find attached to a ripley.
+/obj/structure/loot_pile/mecha/ripley
+ name = "ripley wreckage"
+ desc = "The ruins of some unfortunate ripley. Perhaps something is salvageable."
+ icon_states_to_use = list("ripley-broken", "firefighter-broken", "ripley-broken-old")
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/item/stack/material/steel{amount = 25},
+ /obj/item/stack/material/glass{amount = 10},
+ /obj/item/stack/material/plasteel{amount = 5},
+ /obj/item/mecha_parts/chassis/ripley,
+ /obj/item/mecha_parts/part/ripley_torso,
+ /obj/item/mecha_parts/part/ripley_left_arm,
+ /obj/item/mecha_parts/part/ripley_right_arm,
+ /obj/item/mecha_parts/part/ripley_left_leg,
+ /obj/item/mecha_parts/part/ripley_right_leg,
+ /obj/item/device/kit/paint/ripley,
+ /obj/item/device/kit/paint/ripley/flames_red,
+ /obj/item/device/kit/paint/ripley/flames_blue
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,
+ /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill,
+ /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster,
+ /obj/item/mecha_parts/mecha_equipment/tool/extinguisher,
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/gravcatapult,
+ /obj/item/mecha_parts/mecha_equipment/tool/rcd,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer/rigged
+ )
+
+//Death-Ripley, same common, but more combat-exosuit-based
+/obj/structure/loot_pile/mecha/deathripley
+ name = "strange ripley wreckage"
+ icon_state = "deathripley-broken"
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/item/stack/material/steel{amount = 40},
+ /obj/item/stack/material/glass{amount = 20},
+ /obj/item/stack/material/plasteel{amount = 10},
+ /obj/item/mecha_parts/chassis/ripley,
+ /obj/item/mecha_parts/part/ripley_torso,
+ /obj/item/mecha_parts/part/ripley_left_arm,
+ /obj/item/mecha_parts/part/ripley_right_arm,
+ /obj/item/mecha_parts/part/ripley_left_leg,
+ /obj/item/mecha_parts/part/ripley_right_leg,
+ /obj/item/device/kit/paint/ripley/death
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser,
+ /obj/item/mecha_parts/mecha_equipment/repair_droid,
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tool/rcd,
+ /obj/item/mecha_parts/mecha_equipment/wormhole_generator,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer/rigged
+ )
+
+/obj/structure/loot_pile/mecha/odysseus
+ name = "odysseus wreckage"
+ desc = "The ruins of some unfortunate odysseus. Perhaps something is salvageable."
+ icon_state = "odysseus-broken"
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/item/stack/material/steel{amount = 25},
+ /obj/item/stack/material/glass{amount = 10},
+ /obj/item/stack/material/plasteel{amount = 5},
+ /obj/item/mecha_parts/chassis/odysseus,
+ /obj/item/mecha_parts/part/odysseus_head,
+ /obj/item/mecha_parts/part/odysseus_torso,
+ /obj/item/mecha_parts/part/odysseus_left_arm,
+ /obj/item/mecha_parts/part/odysseus_right_arm,
+ /obj/item/mecha_parts/part/odysseus_left_leg,
+ /obj/item/mecha_parts/part/odysseus_right_leg
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tool/sleeper,
+ /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare,
+ /obj/item/mecha_parts/mecha_equipment/tool/extinguisher,
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/gravcatapult,
+ /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster,
+ /obj/item/mecha_parts/mecha_equipment/shocker
+ )
+
+/obj/structure/loot_pile/mecha/gygax
+ name = "gygax wreckage"
+ desc = "The ruins of some unfortunate gygax. Perhaps something is salvageable."
+ icon_state = "gygax-broken"
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/item/stack/material/steel{amount = 25},
+ /obj/item/stack/material/glass{amount = 10},
+ /obj/item/stack/material/plasteel{amount = 5},
+ /obj/item/mecha_parts/chassis/gygax,
+ /obj/item/mecha_parts/part/gygax_head,
+ /obj/item/mecha_parts/part/gygax_torso,
+ /obj/item/mecha_parts/part/gygax_left_arm,
+ /obj/item/mecha_parts/part/gygax_right_arm,
+ /obj/item/mecha_parts/part/gygax_left_leg,
+ /obj/item/mecha_parts/part/gygax_right_leg,
+ /obj/item/mecha_parts/part/gygax_armour
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/shocker,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser,
+ /obj/item/device/kit/paint/gygax,
+ /obj/item/device/kit/paint/gygax/darkgygax,
+ /obj/item/device/kit/paint/gygax/recitence
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg,
+ /obj/item/mecha_parts/mecha_equipment/repair_droid,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy
+ )
+
+/obj/structure/loot_pile/mecha/durand
+ name = "durand wreckage"
+ desc = "The ruins of some unfortunate durand. Perhaps something is salvageable."
+ icon_state = "durand-broken"
+
+ common_loot = list(
+ /obj/random/tool,
+ /obj/item/stack/cable_coil/random,
+ /obj/random/tank,
+ /obj/random/tech_supply/component,
+ /obj/item/stack/material/steel{amount = 25},
+ /obj/item/stack/material/glass{amount = 10},
+ /obj/item/stack/material/plasteel{amount = 5},
+ /obj/item/mecha_parts/chassis/durand,
+ /obj/item/mecha_parts/part/durand_head,
+ /obj/item/mecha_parts/part/durand_torso,
+ /obj/item/mecha_parts/part/durand_left_arm,
+ /obj/item/mecha_parts/part/durand_right_arm,
+ /obj/item/mecha_parts/part/durand_left_leg,
+ /obj/item/mecha_parts/part/durand_right_leg,
+ /obj/item/mecha_parts/part/durand_armour
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/shocker,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser,
+ /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster,
+ /obj/item/device/kit/paint/durand,
+ /obj/item/device/kit/paint/durand/seraph,
+ /obj/item/device/kit/paint/durand/phazon
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot,
+ /obj/item/mecha_parts/mecha_equipment/repair_droid,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy
+ )
+
+/obj/structure/loot_pile/mecha/phazon
+ name = "phazon wreckage"
+ desc = "The ruins of some unfortunate phazon. Perhaps something is salvageable."
+ icon_state = "phazon-broken"
+
+ common_loot = list(
+ /obj/item/weapon/storage/toolbox/syndicate/powertools,
+ /obj/item/stack/material/plasteel{amount = 20},
+ /obj/item/stack/material/durasteel{amount = 10},
+ /obj/item/mecha_parts/chassis/phazon,
+ /obj/item/mecha_parts/part/phazon_head,
+ /obj/item/mecha_parts/part/phazon_torso,
+ /obj/item/mecha_parts/part/phazon_left_arm,
+ /obj/item/mecha_parts/part/phazon_right_arm,
+ /obj/item/mecha_parts/part/phazon_left_leg,
+ /obj/item/mecha_parts/part/phazon_right_leg
+ )
+
+ uncommon_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/shocker,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/flamer/rigged,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy,
+ /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
+ )
+
+ rare_loot = list(
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion,
+ /obj/item/mecha_parts/mecha_equipment/repair_droid,
+ /obj/item/mecha_parts/mecha_equipment/teleporter
+ )
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 2030167b86..1e8237cdfd 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -123,10 +123,10 @@
/obj/structure/mirror/raider/attack_hand(var/mob/living/carbon/human/user)
if(istype(get_area(src),/area/syndicate_mothership))
- if(istype(user) && user.mind && user.mind.special_role == "Raider" && user.species.name != "Vox" && is_alien_whitelisted(user, "Vox"))
+ if(istype(user) && user.mind && user.mind.special_role == "Raider" && user.species.name != SPECIES_VOX && is_alien_whitelisted(user, SPECIES_VOX))
var/choice = input("Do you wish to become a true Vox of the Shoal? This is not reversible.") as null|anything in list("No","Yes")
if(choice && choice == "Yes")
- var/mob/living/carbon/human/vox/vox = new(get_turf(src),"Vox")
+ var/mob/living/carbon/human/vox/vox = new(get_turf(src),SPECIES_VOX)
vox.gender = user.gender
raiders.equip(vox)
if(user.mind)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index d795d53e3d..d0324c98bf 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -148,7 +148,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "morguet"
density = 1
- layer = 2.0
+ plane = TURF_PLANE
var/obj/structure/morgue/connected = null
anchored = 1
throwpass = 1
@@ -306,10 +306,6 @@
if (C.can_feel_pain())
C.emote("scream")
- //Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out.
- //M.attack_log += "\[[time_stamp()]\] Has been cremated by [user]/[user.ckey]" //No point in this when the mob's about to be deleted
- //user.attack_log +="\[[time_stamp()]\] Cremated [M]/[M.ckey]"
- //log_attack("\[[time_stamp()]\] [user]/[user.ckey] cremated [M]/[M.ckey]")
M.death(1)
M.ghostize()
qdel(M)
diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm
index 27bb902aea..e67750b8f3 100644
--- a/code/game/objects/structures/railing.dm
+++ b/code/game/objects/structures/railing.dm
@@ -6,7 +6,7 @@
density = 1
throwpass = 1
climbable = 1
- layer = 3.2 //Just above doors
+ layer = WINDOW_LAYER
anchored = 1
flags = ON_BORDER
icon_state = "railing0"
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index 7f78e8f0e7..37edb603c1 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -172,7 +172,8 @@ obj/structure/safe/ex_act(severity)
icon_state = "floorsafe"
density = 0
level = 1 //underfloor
- layer = 2.5
+ plane = TURF_PLANE
+ layer = ABOVE_UTILITY
/obj/structure/safe/floor/initialize()
. = ..()
diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm
index 1d68de0d25..33c6d6501c 100644
--- a/code/game/objects/structures/signs.dm
+++ b/code/game/objects/structures/signs.dm
@@ -3,7 +3,7 @@
anchored = 1
opacity = 0
density = 0
- layer = 3.5
+ layer = ABOVE_JUNK_LAYER
w_class = ITEMSIZE_NORMAL
/obj/structure/sign/ex_act(severity)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index ed9c4e0301..390e3c84b9 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -47,15 +47,17 @@
if(isnull(stool_cache[cache_key]))
var/image/I = image(icon, "[base_icon]_armrest")
I.layer = MOB_LAYER + 0.1
+ I.plane = MOB_PLANE
I.color = padding_material.icon_colour
stool_cache[cache_key] = I
overlays |= stool_cache[cache_key]
/obj/structure/bed/chair/proc/update_layer()
if(src.dir == NORTH)
- src.layer = FLY_LAYER
+ plane = MOB_PLANE
+ layer = MOB_LAYER + 0.1
else
- src.layer = OBJ_LAYER
+ reset_plane_and_layer()
/obj/structure/bed/chair/set_dir()
..()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 550b59d112..bb1a62e40b 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -176,9 +176,7 @@
if(pulling)
occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!")
- pulling.attack_log += "\[[time_stamp()]\] Crashed [occupant.name]'s ([occupant.ckey]) [name] into \a [A]"
- occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [pulling.name] ([pulling.ckey]) with \the [name]"
- msg_admin_attack("[pulling.name] ([pulling.ckey]) has thrusted [occupant.name]'s ([occupant.ckey]) [name] into \a [A] (JMP)")
+ add_attack_logs(pulling,occupant,"Crashed their [name] into [A]")
else
occupant.visible_message("[occupant] crashed into \the [A]!")
diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm
index 83396b363e..646e52218c 100644
--- a/code/game/objects/structures/target_stake.dm
+++ b/code/game/objects/structures/target_stake.dm
@@ -29,7 +29,7 @@
W.density = 1
user.remove_from_mob(W)
W.loc = loc
- W.layer = 3.1
+ W.layer = ABOVE_JUNK_LAYER
pinned_target = W
user << "You slide the target into the stake."
return
diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm
index 0f9b4a603a..c260103a56 100644
--- a/code/game/objects/structures/transit_tubes.dm
+++ b/code/game/objects/structures/transit_tubes.dm
@@ -7,7 +7,7 @@
icon = 'icons/obj/pipes/transit_tube.dmi'
icon_state = "E-W"
density = 1
- layer = 3.1
+ layer = ABOVE_JUNK_LAYER
anchored = 1.0
var/list/tube_dirs = null
var/exit_delay = 2
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index f4f1deff28..36da7485ad 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -5,7 +5,7 @@
density = 1
w_class = ITEMSIZE_NORMAL
- layer = 3.2//Just above doors
+ layer = WINDOW_LAYER
pressure_resistance = 4*ONE_ATMOSPHERE
anchored = 1.0
flags = ON_BORDER
@@ -294,6 +294,21 @@
if(is_fulltile())
mats.amount = 4
qdel(src)
+ else if(iscoil(W) && reinf && state == 0 && !istype(src, /obj/structure/window/reinforced/polarized))
+ var/obj/item/stack/cable_coil/C = W
+ if (C.use(1))
+ playsound(src.loc, 'sound/effects/sparks1.ogg', 75, 1)
+ user.visible_message( \
+ "\The [user] begins to wire \the [src] for electrochromic tinting.", \
+ "You begin to wire \the [src] for electrochromic tinting.", \
+ "You hear sparks.")
+ if(do_after(user, 20 * C.toolspeed, src) && state == 0)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ var/obj/structure/window/reinforced/polarized/P = new(loc, dir)
+ P.health = health
+ P.state = state
+ P.anchored = anchored
+ qdel(src)
else if(istype(W,/obj/item/frame) && anchored)
var/obj/item/frame/F = W
F.try_build(src)
@@ -447,7 +462,7 @@
if(ratio > 75)
return
- var/image/I = image(icon, "damage[ratio]", layer + 0.1)
+ var/image/I = image(icon, "damage[ratio]", layer = layer + 0.1)
overlays += I
return
@@ -551,6 +566,28 @@
desc = "Adjusts its tint with voltage. Might take a few good hits to shatter it."
var/id
+/obj/structure/window/reinforced/polarized/full
+ dir = SOUTHWEST
+ icon_state = "fwindow"
+ maxhealth = 80
+
+/obj/structure/window/reinforced/polarized/attackby(obj/item/W as obj, mob/user as mob)
+ if(ismultitool(W) && !anchored) // Only allow programming if unanchored!
+ var/obj/item/device/multitool/MT = W
+ // First check if they have a windowtint button buffered
+ if(istype(MT.connectable, /obj/machinery/button/windowtint))
+ var/obj/machinery/button/windowtint/buffered_button = MT.connectable
+ src.id = buffered_button.id
+ to_chat(user, "\The [src] is linked to \the [buffered_button].")
+ return TRUE
+ // Otherwise fall back to asking them
+ var/t = sanitizeSafe(input(user, "Enter the ID for the window.", src.name, null), MAX_NAME_LEN)
+ if (!t && user.get_active_hand() != W && in_range(src, user))
+ src.id = t
+ to_chat(user, "The new ID of \the [src] is [id]")
+ return TRUE
+ . = ..()
+
/obj/structure/window/reinforced/polarized/proc/toggle()
if(opacity)
animate(src, color="#FFFFFF", time=5)
@@ -593,3 +630,20 @@
/obj/machinery/button/windowtint/update_icon()
icon_state = "light[active]"
+
+/obj/machinery/button/windowtint/attackby(obj/item/W as obj, mob/user as mob)
+ if(ismultitool(W))
+ var/obj/item/device/multitool/MT = W
+ if(!id)
+ // If no ID is set yet (newly built button?) let them select an ID for first-time use!
+ var/t = sanitizeSafe(input(user, "Enter an ID for \the [src].", src.name, null), MAX_NAME_LEN)
+ if (t && user.get_active_hand() != W && in_range(src, user))
+ src.id = t
+ to_chat(user, "The new ID of \the [src] is [id]")
+ if(id)
+ // It already has an ID (or they just set one), buffer it for copying to windows.
+ to_chat(user, "You store \the [src] in \the [MT]'s buffer!")
+ MT.connectable = src
+ MT.update_icon()
+ return TRUE
+ . = ..()
diff --git a/code/game/sound.dm b/code/game/sound.dm
index afeeaafcae..2db1e433bd 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -1,107 +1,50 @@
-//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more.
-#define GENERIC 0
-#define PADDED_CELL 1
-#define ROOM 2
-#define BATHROOM 3
-#define LIVINGROOM 4
-#define STONEROOM 5
-#define AUDITORIUM 6
-#define CONCERT_HALL 7
-#define CAVE 8
-#define ARENA 9
-#define HANGAR 10
-#define CARPETED_HALLWAY 11
-#define HALLWAY 12
-#define STONE_CORRIDOR 13
-#define ALLEY 14
-#define FOREST 15
-#define CITY 16
-#define MOUNTAINS 17
-#define QUARRY 18
-#define PLAIN 19
-#define PARKING_LOT 20
-#define SEWER_PIPE 21
-#define UNDERWATER 22
-#define DRUGGED 23
-#define DIZZY 24
-#define PSYCHOTIC 25
-
-#define STANDARD_STATION STONEROOM
-#define LARGE_ENCLOSED HANGAR
-#define SMALL_ENCLOSED BATHROOM
-#define TUNNEL_ENCLOSED CAVE
-#define LARGE_SOFTFLOOR CARPETED_HALLWAY
-#define MEDIUM_SOFTFLOOR LIVINGROOM
-#define SMALL_SOFTFLOOR ROOM
-#define ASTEROID CAVE
-#define SPACE UNDERWATER
-
-var/list/shatter_sound = list('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg')
-var/list/explosion_sound = list('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg')
-var/list/spark_sound = list('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg')
-var/list/rustle_sound = list('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg')
-var/list/punch_sound = list('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg')
-var/list/clown_sound = list('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg')
-var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg')
-var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg')
-var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg')
-var/list/fracture_sound = list('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg')
-var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg')
-var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg')
-var/list/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg')
-var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg')
-var/list/can_sound = list('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg')
-var/list/geiger_sound = list('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg')
-var/list/geiger_weak_sound = list('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg')
-
-//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg')
-
-/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/frequency)
-
- soundin = get_sfx(soundin) // same sound for everyone
-
+/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, preference = null)
if(isarea(source))
- error("[source] is an area and is trying to make the sound: [soundin]")
+ throw EXCEPTION("playsound(): source is an area")
return
- frequency = isnull(frequency) ? get_rand_frequency() : frequency // Same frequency for everybody
var/turf/turf_source = get_turf(source)
+ //allocate a channel if necessary now so its the same for everyone
+ channel = channel || open_sound_channel()
+
// Looping through the player list has the added bonus of working for mobs inside containers
- for (var/P in player_list)
+ var/sound/S = sound(get_sfx(soundin))
+ var/maxdistance = (world.view + extrarange) * 3
+ var/list/listeners = player_list
+ if(!ignore_walls) //these sounds don't carry through walls
+ listeners = listeners & hearers(maxdistance,turf_source)
+ for(var/P in listeners)
var/mob/M = P
if(!M || !M.client)
continue
+ var/turf/T = get_turf(M)
+ var/distance = get_dist(T, turf_source)
- var/distance = get_dist(M, turf_source)
- if(distance <= (world.view + extrarange) * 3)
- var/turf/T = get_turf(M)
-
+ if(distance <= maxdistance)
if(T && T.z == turf_source.z)
- M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global)
+ M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S)
-var/const/FALLOFF_SOUNDS = 0.5
+/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, channel = 0, pressure_affected = TRUE, sound/S, preference)
+ if(!client || ear_deaf > 0)
+ return
+ if(preference && !client.is_preference_enabled(preference))
+ return
-/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global)
- if(!src.client || ear_deaf > 0) return
- soundin = get_sfx(soundin)
+ if(!S)
+ S = sound(get_sfx(soundin))
- var/sound/S = sound(soundin)
S.wait = 0 //No queue
- S.channel = 0 //Any channel
+ S.channel = channel || open_sound_channel()
S.volume = vol
- S.environment = -1
- if (vary)
+
+ if(vary)
if(frequency)
S.frequency = frequency
else
S.frequency = get_rand_frequency()
- //sound volume falloff with pressure
- var/pressure_factor = 1.0
-
if(isturf(turf_source))
- // 3D sounds, the technology is here!
var/turf/T = get_turf(src)
//sound volume falloff with distance
@@ -109,24 +52,32 @@ var/const/FALLOFF_SOUNDS = 0.5
S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff.
- var/datum/gas_mixture/hearer_env = T.return_air()
- var/datum/gas_mixture/source_env = turf_source.return_air()
+ //Atmosphere affects sound
+ var/pressure_factor = 1
+ if(pressure_affected)
+ var/datum/gas_mixture/hearer_env = T.return_air()
+ var/datum/gas_mixture/source_env = turf_source.return_air()
- if (hearer_env && source_env)
- var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure())
+ if(hearer_env && source_env)
+ var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure())
+ if(pressure < ONE_ATMOSPHERE)
+ pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0)
+ else //space
+ pressure_factor = 0
- if (pressure < ONE_ATMOSPHERE)
- pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0)
- else //in space
- pressure_factor = 0
+ if(distance <= 1)
+ pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound
- if (distance <= 1)
- pressure_factor = max(pressure_factor, 0.15) //hearing through contact
+ S.volume *= pressure_factor
+ //End Atmosphere affecting sound
- S.volume *= pressure_factor
+ //Don't bother with doing anything below.
+ if(S.volume <= 0)
+ return //No sound
- if (S.volume <= 0)
- return //no volume means no sound
+ //Apply a sound environment.
+ if(!is_global)
+ S.environment = get_sound_env(pressure_factor)
var/dx = turf_source.x - T.x // Hearing from the right/left
S.x = dx
@@ -136,58 +87,52 @@ var/const/FALLOFF_SOUNDS = 0.5
S.y = 1
S.falloff = (falloff ? falloff : FALLOFF_SOUNDS)
- if(!is_global)
-
- if(istype(src,/mob/living/))
- var/mob/living/M = src
- if (M.hallucination)
- S.environment = PSYCHOTIC
- else if (M.druggy)
- S.environment = DRUGGED
- else if (M.drowsyness)
- S.environment = DIZZY
- else if (M.confused)
- S.environment = DIZZY
- else if (M.sleeping)
- S.environment = UNDERWATER
- else if (pressure_factor < 0.5)
- S.environment = SPACE
- else
- var/area/A = get_area(src)
- S.environment = A.sound_env
-
- else if (pressure_factor < 0.5)
- S.environment = SPACE
- else
- var/area/A = get_area(src)
- S.environment = A.sound_env
-
src << S
+/proc/sound_to_playing_players(sound, volume = 100, vary)
+ sound = get_sfx(sound)
+ for(var/M in player_list)
+ if(ismob(M) && !isnewplayer(M))
+ var/mob/MO = M
+ MO.playsound_local(get_turf(MO), sound, volume, vary, pressure_affected = FALSE)
+
+/proc/open_sound_channel()
+ var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used
+ . = ++next_channel
+ if(next_channel > CHANNEL_HIGHEST_AVAILABLE)
+ next_channel = 1
+
+/mob/proc/stop_sound_channel(chan)
+ src << sound(null, repeat = 0, wait = 0, channel = chan)
+
+/proc/get_rand_frequency()
+ return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
+
/client/proc/playtitlemusic()
if(!ticker || !ticker.login_music) return
if(is_preference_enabled(/datum/client_preference/play_lobby_music))
src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS
-/proc/get_rand_frequency()
- return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
-
/proc/get_sfx(soundin)
if(istext(soundin))
switch(soundin)
- if ("shatter") soundin = pick(shatter_sound)
- if ("explosion") soundin = pick(explosion_sound)
- if ("sparks") soundin = pick(spark_sound)
- if ("rustle") soundin = pick(rustle_sound)
- if ("punch") soundin = pick(punch_sound)
- if ("clownstep") soundin = pick(clown_sound)
- if ("swing_hit") soundin = pick(swing_hit_sound)
- if ("hiss") soundin = pick(hiss_sound)
- if ("pageturn") soundin = pick(page_sound)
- if ("fracture") soundin = pick(fracture_sound)
- if ("canopen") soundin = pick(can_sound)
- if ("mechstep") soundin = pick(mechstep_sound)
- //if ("gunshot") soundin = pick(gun_sound)
- if("geiger") soundin = pick(geiger_sound)
- if("geiger_weak") soundin = pick(geiger_weak_sound)
+ if ("shatter") soundin = pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg')
+ if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg')
+ if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg')
+ if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg')
+ if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg')
+ if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg')
+ if ("swing_hit") soundin = pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg')
+ if ("hiss") soundin = pick('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg')
+ if ("pageturn") soundin = pick('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg')
+ if ("fracture") soundin = pick('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg')
+ if ("canopen") soundin = pick('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg')
+ if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg')
+ if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg')
+ if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg')
return soundin
+
+//Are these even used?
+var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg')
+var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg')
+var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg')
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index f9331eac1d..3cc0bb8ab9 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -1,8 +1,8 @@
//Config stuff
-#define SUPPLY_DOCKZ 2 //Z-level of the Dock.
-#define SUPPLY_STATIONZ 1 //Z-level of the Station.
-#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station
-#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock
+#define SUPPLY_DOCKZ 2 //Z-level of the Dock.
+#define SUPPLY_STATIONZ 1 //Z-level of the Station.
+#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station
+#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock
//Supply packs are in /code/defines/obj/supplypacks.dm
//Computers are in /code/game/machinery/computer/supply.dm
@@ -10,304 +10,324 @@
var/datum/controller/supply/supply_controller = new()
var/list/mechtoys = list(
- /obj/item/toy/prize/ripley,
- /obj/item/toy/prize/fireripley,
- /obj/item/toy/prize/deathripley,
- /obj/item/toy/prize/gygax,
- /obj/item/toy/prize/durand,
- /obj/item/toy/prize/honk,
- /obj/item/toy/prize/marauder,
- /obj/item/toy/prize/seraph,
- /obj/item/toy/prize/mauler,
- /obj/item/toy/prize/odysseus,
- /obj/item/toy/prize/phazon
+ /obj/item/toy/prize/ripley,
+ /obj/item/toy/prize/fireripley,
+ /obj/item/toy/prize/deathripley,
+ /obj/item/toy/prize/gygax,
+ /obj/item/toy/prize/durand,
+ /obj/item/toy/prize/honk,
+ /obj/item/toy/prize/marauder,
+ /obj/item/toy/prize/seraph,
+ /obj/item/toy/prize/mauler,
+ /obj/item/toy/prize/odysseus,
+ /obj/item/toy/prize/phazon
)
/obj/item/weapon/paper/manifest
- name = "supply manifest"
- var/is_copy = 1
+ name = "supply manifest"
+ var/is_copy = 1
/area/supply/station
- name = "Supply Shuttle"
- icon_state = "shuttle3"
- requires_power = 0
- base_turf = /turf/space
+ name = "Supply Shuttle"
+ icon_state = "shuttle3"
+ requires_power = 0
+ base_turf = /turf/space
/area/supply/dock
- name = "Supply Shuttle"
- icon_state = "shuttle3"
- requires_power = 0
- base_turf = /turf/space
+ name = "Supply Shuttle"
+ icon_state = "shuttle3"
+ requires_power = 0
+ base_turf = /turf/space
/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY
- name = "\improper plastic flaps"
- desc = "Completely impassable - or are they?"
- icon = 'icons/obj/stationobjs.dmi' //Change this.
- icon_state = "plasticflaps"
- density = 0
- anchored = 1
- layer = 4
- explosion_resistance = 5
- var/list/mobs_can_pass = list(
- /mob/living/bot,
- /mob/living/simple_animal/slime,
- /mob/living/simple_animal/mouse,
- /mob/living/silicon/robot/drone
- )
+ name = "\improper plastic flaps"
+ desc = "Completely impassable - or are they?"
+ icon = 'icons/obj/stationobjs.dmi' //Change this.
+ icon_state = "plasticflaps"
+ density = 0
+ anchored = 1
+ layer = MOB_LAYER
+ plane = MOB_PLANE
+ explosion_resistance = 5
+ var/list/mobs_can_pass = list(
+ /mob/living/bot,
+ /mob/living/simple_animal/slime,
+ /mob/living/simple_animal/mouse,
+ /mob/living/silicon/robot/drone
+ )
/obj/structure/plasticflaps/attackby(obj/item/P, mob/user)
- if(istype(P, /obj/item/weapon/wirecutters))
- playsound(src, P.usesound, 50, 1)
- user << "You start to cut the plastic flaps."
- if(do_after(user, 10 * P.toolspeed))
- user << "You cut the plastic flaps."
- var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc )
- A.amount = 4
- qdel(src)
- return
- else
- return
+ if(istype(P, /obj/item/weapon/wirecutters))
+ playsound(src, P.usesound, 50, 1)
+ user << "You start to cut the plastic flaps."
+ if(do_after(user, 10 * P.toolspeed))
+ user << "You cut the plastic flaps."
+ var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc )
+ A.amount = 4
+ qdel(src)
+ return
+ else
+ return
/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
- if(istype(A) && A.checkpass(PASSGLASS))
- return prob(60)
+ if(istype(A) && A.checkpass(PASSGLASS))
+ return prob(60)
- var/obj/structure/bed/B = A
- if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass
- return 0
+ var/obj/structure/bed/B = A
+ if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass
+ return 0
- if(istype(A, /obj/vehicle)) //no vehicles
- return 0
+ if(istype(A, /obj/vehicle)) //no vehicles
+ return 0
- var/mob/living/M = A
- if(istype(M))
- if(M.lying)
- return ..()
- for(var/mob_type in mobs_can_pass)
- if(istype(A, mob_type))
- return ..()
- return issmall(M)
+ var/mob/living/M = A
+ if(istype(M))
+ if(M.lying)
+ return ..()
+ for(var/mob_type in mobs_can_pass)
+ if(istype(A, mob_type))
+ return ..()
+ return issmall(M)
- return ..()
+ return ..()
/obj/structure/plasticflaps/ex_act(severity)
- switch(severity)
- if (1)
- qdel(src)
- if (2)
- if (prob(50))
- qdel(src)
- if (3)
- if (prob(5))
- qdel(src)
+ switch(severity)
+ if (1)
+ qdel(src)
+ if (2)
+ if (prob(50))
+ qdel(src)
+ if (3)
+ if (prob(5))
+ qdel(src)
/obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates
- name = "airtight plastic flaps"
- desc = "Heavy duty, airtight, plastic flaps."
+ name = "airtight plastic flaps"
+ desc = "Heavy duty, airtight, plastic flaps."
- New() //set the turf below the flaps to block air
- var/turf/T = get_turf(loc)
- if(T)
- T.blocks_air = 1
- ..()
+/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air
+ var/turf/T = get_turf(loc)
+ if(T)
+ T.blocks_air = 1
+ ..()
- Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor
- var/turf/T = get_turf(loc)
- if(T)
- if(istype(T, /turf/simulated/floor))
- T.blocks_air = 0
- ..()
+/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor
+ var/turf/T = get_turf(loc)
+ if(T && istype(T, /turf/simulated/floor))
+ T.blocks_air = 0
+ ..()
/*
/obj/effect/marker/supplymarker
- icon_state = "X"
- icon = 'icons/misc/mark.dmi'
- name = "X"
- invisibility = 101
- anchored = 1
- opacity = 0
+ icon_state = "X"
+ icon = 'icons/misc/mark.dmi'
+ name = "X"
+ invisibility = 101
+ anchored = 1
+ opacity = 0
*/
/datum/supply_order
- var/ordernum
- var/datum/supply_packs/object = null
- var/orderedby = null
- var/comment = null
+ var/ordernum
+ var/datum/supply_packs/object = null
+ var/orderedby = null
+ var/comment = null
+
+/datum/exported_crate
+ var/name
+ var/value
/datum/controller/supply
- //supply points
- var/points = 50
- var/points_per_process = 1.5
- var/points_per_slip = 2
- var/points_per_platinum = 5 // 5 points per sheet
- var/points_per_phoron = 5
- var/points_per_money = 0.02
- //control
- var/ordernum
- var/list/shoppinglist = list()
- var/list/requestlist = list()
- var/list/supply_packs = list()
- //shuttle movement
- var/movetime = 1200
- var/datum/shuttle/ferry/supply/shuttle
+ //supply points
+ var/points = 50
+ var/points_per_process = 1.5
+ var/points_per_slip = 2
+ var/points_per_platinum = 5 // 5 points per sheet
+ var/points_per_phoron = 5
+ var/points_per_money = 0.02
+ //control
+ var/ordernum
+ var/list/shoppinglist = list()
+ var/list/requestlist = list()
+ var/list/supply_packs = list()
+ var/list/exported_crates = list()
+ //shuttle movement
+ var/movetime = 1200
+ var/datum/shuttle/ferry/supply/shuttle
- New()
- ordernum = rand(1,9000)
+/datum/controller/supply/New()
+ ordernum = rand(1,9000)
- for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
- var/datum/supply_packs/P = new typepath()
- supply_packs[P.name] = P
+ for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
+ var/datum/supply_packs/P = new typepath()
+ supply_packs[P.name] = P
- // Supply shuttle ticker - handles supply point regeneration
- // This is called by the process scheduler every thirty seconds
- proc/process()
- points += points_per_process
+// Supply shuttle ticker - handles supply point regeneration
+// This is called by the process scheduler every thirty seconds
+/datum/controller/supply/proc/process()
+ points += points_per_process
- //To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
- proc/forbidden_atoms_check(atom/A)
- if(istype(A,/mob/living))
- return 1
- if(istype(A,/obj/item/weapon/disk/nuclear))
- return 1
- if(istype(A,/obj/machinery/nuclearbomb))
- return 1
- if(istype(A,/obj/item/device/radio/beacon))
- return 1
+//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
+/datum/controller/supply/proc/forbidden_atoms_check(atom/A)
+ if(isliving(A))
+ return 1
+ if(istype(A,/obj/item/weapon/disk/nuclear))
+ return 1
+ if(istype(A,/obj/machinery/nuclearbomb))
+ return 1
+ if(istype(A,/obj/item/device/radio/beacon))
+ return 1
- for(var/i=1, i<=A.contents.len, i++)
- var/atom/B = A.contents[i]
- if(.(B))
- return 1
+ for(var/i=1, i<=A.contents.len, i++)
+ var/atom/B = A.contents[i]
+ if(.(B))
+ return 1
- //Sellin
- proc/sell()
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle) return
+//Sellin
+/datum/controller/supply/proc/sell()
+ var/area/area_shuttle = shuttle.get_location_area()
+ if(!area_shuttle) return
- callHook("sell_shuttle", list(area_shuttle));
+ callHook("sell_shuttle", list(area_shuttle));
- var/phoron_count = 0
- var/plat_count = 0
- var/money_count = 0
+ var/phoron_count = 0
+ var/plat_count = 0
+ var/money_count = 0
- for(var/atom/movable/MA in area_shuttle)
- if(MA.anchored) continue
+ exported_crates = list()
- // Must be in a crate!
- if(istype(MA,/obj/structure/closet/crate))
- var/obj/structure/closet/crate/CR = MA
- callHook("sell_crate", list(CR, area_shuttle))
+ for(var/atom/movable/MA in area_shuttle)
+ if(MA.anchored) continue
- points += CR.points_per_crate
- var/find_slip = 1
+ // Must be in a crate!
+ if(istype(MA,/obj/structure/closet/crate))
+ var/oldpoints = points
+ var/oldphoron = phoron_count
+ var/oldplatinum = plat_count
+ var/oldmoney = money_count
- for(var/atom in CR)
- // Sell manifests
- var/atom/A = atom
- if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
- var/obj/item/weapon/paper/manifest/slip = A
- if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
- points += points_per_slip
- find_slip = 0
- continue
+ var/obj/structure/closet/crate/CR = MA
+ callHook("sell_crate", list(CR, area_shuttle))
- // Sell phoron and platinum
- if(istype(A, /obj/item/stack))
- var/obj/item/stack/P = A
- switch(P.get_material_name())
- if("phoron") phoron_count += P.get_amount()
- if("platinum") plat_count += P.get_amount()
+ points += CR.points_per_crate
+ var/find_slip = 1
- //Sell spacebucks
- if(istype(A, /obj/item/weapon/spacecash))
- var/obj/item/weapon/spacecash/cashmoney = A
- money_count += cashmoney.worth
- qdel(MA)
+ for(var/atom in CR)
+ // Sell manifests
+ var/atom/A = atom
+ if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
+ var/obj/item/weapon/paper/manifest/slip = A
+ if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
+ points += points_per_slip
+ find_slip = 0
+ continue
- if(phoron_count)
- points += phoron_count * points_per_phoron
+ // Sell phoron and platinum
+ if(istype(A, /obj/item/stack))
+ var/obj/item/stack/P = A
+ switch(P.get_material_name())
+ if("phoron") phoron_count += P.get_amount()
+ if("platinum") plat_count += P.get_amount()
- if(plat_count)
- points += plat_count * points_per_platinum
+ //Sell spacebucks
+ if(istype(A, /obj/item/weapon/spacecash))
+ var/obj/item/weapon/spacecash/cashmoney = A
+ money_count += cashmoney.worth
- if(money_count)
- points += money_count * points_per_money
+ var/datum/exported_crate/EC = new /datum/exported_crate()
+ EC.name = CR.name
+ EC.value = points - oldpoints
+ EC.value += (phoron_count - oldphoron) * points_per_phoron
+ EC.value += (plat_count - oldplatinum) * points_per_platinum
+ EC.value += (money_count - oldmoney) * points_per_money
+ exported_crates += EC
- //Buyin
- proc/buy()
- if(!shoppinglist.len) return
+ qdel(MA)
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle) return
+ points += phoron_count * points_per_phoron
+ points += plat_count * points_per_platinum
+ points += money_count * points_per_money
- var/list/clear_turfs = list()
+//Buyin
+/datum/controller/supply/proc/buy()
+ if(!shoppinglist.len)
+ return
- for(var/turf/T in area_shuttle)
- if(T.density) continue
- var/contcount
- for(var/atom/A in T.contents)
- if(!A.simulated)
- continue
- contcount++
- if(contcount)
- continue
- clear_turfs += T
+ var/orderedamount = shoppinglist.len
- for(var/S in shoppinglist)
- if(!clear_turfs.len) break
- var/i = rand(1,clear_turfs.len)
- var/turf/pickedloc = clear_turfs[i]
- clear_turfs.Cut(i,i+1)
- shoppinglist -= S
+ var/area/area_shuttle = shuttle.get_location_area()
+ if(!area_shuttle)
+ return
- var/datum/supply_order/SO = S
- var/datum/supply_packs/SP = SO.object
+ var/list/clear_turfs = list()
- var/obj/A = new SP.containertype(pickedloc)
- A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
+ for(var/turf/T in area_shuttle)
+ if(T.density)
+ continue
+ var/contcount
+ for(var/atom/A in T.contents)
+ if(!A.simulated)
+ continue
+ contcount++
+ if(contcount)
+ continue
+ clear_turfs += T
- //supply manifest generation begin
+ for(var/S in shoppinglist)
+ if(!clear_turfs.len) break
+ var/i = rand(1,clear_turfs.len)
+ var/turf/pickedloc = clear_turfs[i]
+ clear_turfs.Cut(i,i+1)
+ shoppinglist -= S
- var/obj/item/weapon/paper/manifest/slip
- if(!SP.contraband)
- slip = new /obj/item/weapon/paper/manifest(A)
- slip.is_copy = 0
- slip.info = "[command_name()] Shipping Manifest
"
- slip.info +="Order #[SO.ordernum]
"
- slip.info +="Destination: [station_name()]
"
- slip.info +="[shoppinglist.len] PACKAGES IN THIS SHIPMENT
"
- slip.info +="CONTENTS:
"
+ var/datum/supply_order/SO = S
+ var/datum/supply_packs/SP = SO.object
- //spawn the stuff, finish generating the manifest while you're at it
- if(SP.access)
- if(isnum(SP.access))
- A.req_access = list(SP.access)
- else if(islist(SP.access))
- var/list/L = SP.access // access var is a plain var, we need a list
- A.req_access = L.Copy()
- else
- world << "Supply pack with invalid access restriction [SP.access] encountered!"
+ var/obj/A = new SP.containertype(pickedloc)
+ A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
- var/list/contains
- if(istype(SP,/datum/supply_packs/randomised))
- var/datum/supply_packs/randomised/SPR = SP
- contains = list()
- if(SPR.contains.len)
- for(var/j=1,j<=SPR.num_contained,j++)
- contains += pick(SPR.contains)
- else
- contains = SP.contains
+ //supply manifest generation begin
+ var/obj/item/weapon/paper/manifest/slip
+ if(!SP.contraband)
+ slip = new /obj/item/weapon/paper/manifest(A)
+ slip.is_copy = 0
+ slip.info = "[command_name()] Shipping Manifest
"
+ slip.info +="Order #[SO.ordernum]
"
+ slip.info +="Destination: [station_name()]
"
+ slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT
"
+ slip.info +="CONTENTS:
"
- for(var/typepath in contains)
- if(!typepath) continue
- var/number_of_items = max(1, contains[typepath])
- for(var/j = 1 to number_of_items)
- var/atom/B2 = new typepath(A)
- if(slip) slip.info += "- [B2.name]
" //add the item to the manifest
+ //spawn the stuff, finish generating the manifest while you're at it
+ if(SP.access)
+ if(isnum(SP.access))
+ A.req_access = list(SP.access)
+ else if(islist(SP.access))
+ var/list/L = SP.access // access var is a plain var, we need a list
+ A.req_access = L.Copy()
+ else
+ log_debug("Supply pack with invalid access restriction [SP.access] encountered!")
- //manifest finalisation
- if(slip)
- slip.info += "
"
- slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
"
+ var/list/contains
+ if(istype(SP,/datum/supply_packs/randomised))
+ var/datum/supply_packs/randomised/SPR = SP
+ contains = list()
+ if(SPR.contains.len)
+ for(var/j=1,j<=SPR.num_contained,j++)
+ contains += pick(SPR.contains)
+ else
+ contains = SP.contains
- return
\ No newline at end of file
+ for(var/typepath in contains)
+ if(!typepath) continue
+ var/number_of_items = max(1, contains[typepath])
+ for(var/j = 1 to number_of_items)
+ var/atom/B2 = new typepath(A)
+ if(slip) slip.info += "- [B2.name]
" //add the item to the manifest
+
+ //manifest finalisation
+ if(slip)
+ slip.info += "
"
+ slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
"
+
+ return
diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm
index 4d708b2944..c845657c74 100644
--- a/code/game/turfs/flooring/flooring.dm
+++ b/code/game/turfs/flooring/flooring.dm
@@ -1,5 +1,10 @@
var/list/flooring_types
+/proc/populate_flooring_types()
+ flooring_types = list()
+ for (var/flooring_path in typesof(/decl/flooring))
+ flooring_types["[flooring_path]"] = new flooring_path
+
/proc/get_flooring_data(var/flooring_path)
if(!flooring_types)
flooring_types = list()
@@ -62,6 +67,13 @@ var/list/flooring_types
desc = "A layer of many tiny bits of frozen water. It's hard to tell how deep it is."
icon = 'icons/turf/snow_new.dmi'
icon_base = "snow"
+ footstep_sounds = list("human" = list(
+ 'sound/effects/footstep/snow1.ogg',
+ 'sound/effects/footstep/snow2.ogg',
+ 'sound/effects/footstep/snow3.ogg',
+ 'sound/effects/footstep/snow4.ogg',
+ 'sound/effects/footstep/snow5.ogg'))
+
/decl/flooring/snow/snow2
name = "snow"
@@ -80,6 +92,11 @@ var/list/flooring_types
icon_base = "snowyplating"
flags = null
+/decl/flooring/snow/ice
+ name = "ice"
+ desc = "Looks slippery."
+ icon_base = "ice"
+
/decl/flooring/snow/plating/drift
icon_base = "snowyplayingdrift"
@@ -133,6 +150,11 @@ var/list/flooring_types
icon_base = "oracarpet"
build_type = /obj/item/stack/tile/carpet/oracarpet
+/decl/flooring/carpet/tealcarpet
+ name = "teal carpet"
+ icon_base = "tealcarpet"
+ build_type = /obj/item/stack/tile/carpet/teal
+
/decl/flooring/tiling
name = "floor"
desc = "Scuffed from the passage of countless greyshirts."
@@ -260,7 +282,7 @@ var/list/flooring_types
/decl/flooring/wood
name = "wooden floor"
- desc = "Polished redwood planks."
+ desc = "Polished wooden planks."
icon = 'icons/turf/flooring/wood.dmi'
icon_base = "wood"
has_damage_range = 6
@@ -275,6 +297,13 @@ var/list/flooring_types
'sound/effects/footstep/wood4.ogg',
'sound/effects/footstep/wood5.ogg'))
+/decl/flooring/wood/sif
+ name = "alien wooden floor"
+ desc = "Polished alien wood planks."
+ icon = 'icons/turf/flooring/wood.dmi'
+ icon_base = "sifwood"
+ build_type = /obj/item/stack/tile/wood/sif
+
/decl/flooring/reinforced
name = "reinforced floor"
desc = "Heavily reinforced with steel rods."
diff --git a/code/game/turfs/flooring/flooring_decals.dm b/code/game/turfs/flooring/flooring_decals.dm
index 7543d4037a..957cc20389 100644
--- a/code/game/turfs/flooring/flooring_decals.dm
+++ b/code/game/turfs/flooring/flooring_decals.dm
@@ -6,7 +6,7 @@ var/list/floor_decals = list()
/obj/effect/floor_decal
name = "floor decal"
icon = 'icons/turf/flooring/decals.dmi'
- layer = DECALS_LAYER
+ plane = DECAL_PLANE
var/supplied_dir
/obj/effect/floor_decal/New(var/newloc, var/newdir, var/newcolour)
@@ -14,16 +14,29 @@ var/list/floor_decals = list()
if(newcolour) color = newcolour
..(newloc)
-// Hack to workaround byond crash bug
/obj/effect/floor_decal/initialize()
- if(!floor_decals_initialized || !loc || QDELETED(src))
- return
add_to_turf_decals()
- var/turf/T = get_turf(src)
- T.apply_decals()
initialized = TRUE
return INITIALIZE_HINT_QDEL
+// This is a separate proc from initialize() to facilitiate its caching and other stuff. Look into it someday.
+/obj/effect/floor_decal/proc/add_to_turf_decals()
+ if(supplied_dir)
+ set_dir(supplied_dir) // TODO - Why can't this line be done in initialize/New()?
+ var/turf/T = get_turf(src)
+ if(istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
+ var/cache_key = "[alpha]-[color]-[dir]-[icon_state]-[T.layer]"
+ var/image/I = floor_decals[cache_key]
+ if(!I)
+ I = image(icon = icon, icon_state = icon_state, dir = dir)
+ I.layer = T.layer
+ I.color = color
+ I.alpha = alpha
+ floor_decals[cache_key] = I
+ LAZYADD(T.decals, I) // Add to its decals list (so it remembers to re-apply after it cuts overlays)
+ T.add_overlay(I) // Add to its current overlays too.
+ return T
+
/obj/effect/floor_decal/reset
name = "reset marker"
diff --git a/code/game/turfs/flooring/flooring_premade.dm b/code/game/turfs/flooring/flooring_premade.dm
index 3f4020c177..559e3ad3a2 100644
--- a/code/game/turfs/flooring/flooring_premade.dm
+++ b/code/game/turfs/flooring/flooring_premade.dm
@@ -14,6 +14,11 @@
icon_state = "blucarpet"
initial_flooring = /decl/flooring/carpet/blucarpet
+/turf/simulated/floor/carpet/tealcarpet
+ name = "teal carpet"
+ icon_state = "tealcarpet"
+ initial_flooring = /decl/flooring/carpet/tealcarpet
+
// Legacy support for existing paths for blue carpet
/turf/simulated/floor/carpet/blue
name = "blue carpet"
@@ -63,6 +68,26 @@
icon_state = "wood"
initial_flooring = /decl/flooring/wood
+/turf/simulated/floor/wood/broken
+ icon_state = "wood_broken0" // This gets changed when spawned.
+
+/turf/simulated/floor/wood/broken/initialize()
+ break_tile()
+ return ..()
+
+/turf/simulated/floor/wood/sif
+ name = "alien wooden floor"
+ icon = 'icons/turf/flooring/wood.dmi'
+ icon_state = "sifwood"
+ initial_flooring = /decl/flooring/wood/sif
+
+/turf/simulated/floor/wood/sif/broken
+ icon_state = "sifwood_broken0" // This gets changed when spawned.
+
+/turf/simulated/floor/wood/sif/broken/initialize()
+ break_tile()
+ return ..()
+
/turf/simulated/floor/grass
name = "grass patch"
icon = 'icons/turf/flooring/grass.dmi'
@@ -219,9 +244,8 @@
oxygen = 0
nitrogen = 0
-/turf/simulated/floor/reinforced/n20/New()
- ..()
- sleep(-1)
+/turf/simulated/floor/reinforced/n20/initialize()
+ . = ..()
if(!air) make_air()
air.adjust_gas("sleeping_agent", ATMOSTANK_NITROUSOXIDE)
@@ -400,11 +424,11 @@
. = ..()
/turf/snow/update_icon()
- overlays.Cut()
+ cut_overlays()
for(var/d in crossed_dirs)
var/amt = crossed_dirs[d]
for(var/i in 1 to amt)
- overlays += icon(icon, "footprint[i]", text2num(d))
+ add_overlay(image(icon, "footprint[i]", text2num(d)))
//**** Here ends snow ****
\ No newline at end of file
diff --git a/code/game/turfs/flooring/turf_overlay_holder.dm b/code/game/turfs/flooring/turf_overlay_holder.dm
deleted file mode 100644
index c12f727a0b..0000000000
--- a/code/game/turfs/flooring/turf_overlay_holder.dm
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Initialize floor decals! Woo! This is crazy.
-//
-
-var/global/floor_decals_initialized = FALSE
-
-// The Turf Decal Holder
-// Since it is unsafe to add overlays to turfs, we hold them here for now.
-// Since I want this object to basically not exist, I am modeling it in part after lighting_overlay
-/atom/movable/turf_overlay_holder
- name = "turf overlay holder"
- density = 0
- simulated = 0
- anchored = 1
- layer = TURF_LAYER
- icon = null
- icon_state = null
- mouse_opacity = 0
- // auto_init = 0
-
-/atom/movable/turf_overlay_holder/initialize()
- // doesn't need special init
- initialized = TRUE
- return INITIALIZE_HINT_NORMAL
-
-/atom/movable/turf_overlay_holder/New(var/atom/newloc)
- ..()
- verbs.Cut()
- var/turf/T = loc
- T.overlay_holder = src
-
-/atom/movable/turf_overlay_holder/Destroy()
- if(loc)
- var/turf/T = loc
- if(T.overlay_holder == src)
- T.overlay_holder = null
- . = ..()
-
-// Variety of overrides so the overlays don't get affected by weird things.
-/atom/movable/turf_overlay_holder/ex_act()
- return
-
-/atom/movable/turf_overlay_holder/singularity_act()
- return
-
-/atom/movable/turf_overlay_holder/singularity_pull()
- return
-
-/atom/movable/turf_overlay_holder/forceMove()
- return 0 //should never move
-
-/atom/movable/turf_overlay_holder/Move()
- return 0
-
-/atom/movable/turf_overlay_holder/throw_at()
- return 0
-
-/obj/effect/floor_decal/proc/add_to_turf_decals()
- if(src.supplied_dir) src.set_dir(src.supplied_dir)
- var/turf/T = get_turf(src)
- if(istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
- var/cache_key = "[src.alpha]-[src.color]-[src.dir]-[src.icon_state]-[T.layer]"
- var/image/I = floor_decals[cache_key]
- if(!I)
- I = image(icon = src.icon, icon_state = src.icon_state, dir = src.dir)
- I.layer = T.layer
- I.color = src.color
- I.alpha = src.alpha
- floor_decals[cache_key] = I
- if(!T.decals) T.decals = list()
- //world.log << "About to add img:\ref[I] onto decals at turf:\ref[T] ([T.x],[T.y],[T.z]) which has appearance:\ref[T.appearance] and decals.len=[T.decals.len]"
- T.decals += I
- return T
- // qdel(D)
- src.loc = null
- src.tag = null
-
-// Changes to turf to let us do this
-/turf
- var/atom/movable/turf_overlay_holder/overlay_holder = null
-
-// After a turf change, destroy the old overlay holder since we will have lost access to it.
-/turf/post_change()
- var/atom/movable/turf_overlay_holder/TOH = locate(/atom/movable/turf_overlay_holder, src)
- if(TOH)
- qdel(TOH)
- ..()
-
-/turf/proc/apply_decals()
- if(decals)
- if(!overlay_holder)
- overlay_holder = new(src)
- overlay_holder.overlays = src.decals
- else if(overlay_holder)
- overlay_holder.overlays.Cut()
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index 789ec20a17..e156588937 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -21,16 +21,15 @@
spawn(0)
wet = wet_val
if(wet_overlay)
- overlays -= wet_overlay
- wet_overlay = null
- wet_overlay = image('icons/effects/water.dmi',src,"wet_floor")
- overlays += wet_overlay
+ cut_overlay(wet_overlay)
+ wet_overlay = image('icons/effects/water.dmi', icon_state = "wet_floor")
+ add_overlay(wet_overlay)
sleep(800)
if(wet == 2)
sleep(3200)
wet = 0
if(wet_overlay)
- overlays -= wet_overlay
+ cut_overlay(wet_overlay)
wet_overlay = null
/turf/simulated/proc/freeze_floor()
@@ -38,14 +37,14 @@
return
wet = 3 // icy
if(wet_overlay)
- overlays -= wet_overlay
+ cut_overlay(wet_overlay)
wet_overlay = null
wet_overlay = image('icons/turf/overlays.dmi',src,"snowfloor")
- overlays += wet_overlay
+ add_overlay(wet_overlay)
spawn(5 MINUTES)
wet = 0
if(wet_overlay)
- overlays -= wet_overlay
+ cut_overlay(wet_overlay)
wet_overlay = null
/turf/simulated/clean_blood()
diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm
index b6a8f53c27..156fddac6a 100644
--- a/code/game/turfs/simulated/dungeon/wall.dm
+++ b/code/game/turfs/simulated/dungeon/wall.dm
@@ -10,4 +10,28 @@
return
/turf/simulated/wall/dungeon/ex_act()
+ return
+
+/turf/simulated/wall/solidrock //for more stylish anti-cheese.
+ icon_state = "bedrock"
+ var/base_state = "bedrock"
+ block_tele = TRUE
+
+/turf/simulated/wall/solidrock/update_icon()
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src,direction)
+ if(istype(T) && !T.density)
+ var/place_dir = turn(direction, 180)
+ if(!mining_overlay_cache["rock_side_[place_dir]"])
+ mining_overlay_cache["rock_side_[place_dir]"] = image('icons/turf/walls.dmi', "rock_side", dir = place_dir)
+ T.add_overlay(mining_overlay_cache["rock_side_[place_dir]"])
+
+/turf/simulated/wall/solidrock/initialize()
+ icon_state = base_state
+ update_icon(1)
+
+/turf/simulated/wall/solidrock/attackby()
+ return
+
+/turf/simulated/wall/solidrock/ex_act()
return
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 336a34b2fe..f471cc9bc0 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -53,7 +53,7 @@
//This proc auto corrects the grass tiles' siding.
/turf/simulated/floor/proc/make_plating(var/place_product, var/defer_icon_update)
- overlays.Cut()
+ cut_overlays()
if(islist(decals))
decals.Cut()
decals = null
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index ef36121b12..5602eac320 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -4,40 +4,15 @@
return 0
if(flooring)
- if(istype(C, /obj/item/weapon/crowbar))
- if(broken || burnt)
- to_chat(user, "You remove the broken [flooring.descriptor].")
- make_plating()
- else if(flooring.flags & TURF_IS_FRAGILE)
- to_chat(user, "You forcefully pry off the [flooring.descriptor], destroying them in the process.")
- make_plating()
- else if(flooring.flags & TURF_REMOVE_CROWBAR)
- to_chat(user, "You lever off the [flooring.descriptor].")
- make_plating(1)
- else
- return
- playsound(src, C.usesound, 80, 1)
- return
- else if(istype(C, /obj/item/weapon/screwdriver) && (flooring.flags & TURF_REMOVE_SCREWDRIVER))
- if(broken || burnt)
- return
- to_chat(user, "You unscrew and remove the [flooring.descriptor].")
- make_plating(1)
- playsound(src, C.usesound, 80, 1)
- return
- else if(istype(C, /obj/item/weapon/wrench) && (flooring.flags & TURF_REMOVE_WRENCH))
- to_chat(user, "You unwrench and remove the [flooring.descriptor].")
- make_plating(1)
- playsound(src, C.usesound, 80, 1)
- return
- else if(istype(C, /obj/item/weapon/shovel) && (flooring.flags & TURF_REMOVE_SHOVEL))
- to_chat(user, "You shovel off the [flooring.descriptor].")
- make_plating(1)
- playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
+ if(istype(C, /obj/item/weapon))
+ try_deconstruct_tile(C, user)
return
else if(istype(C, /obj/item/stack/cable_coil))
to_chat(user, "You must remove the [flooring.descriptor] first.")
return
+ else if(istype(C, /obj/item/stack/tile))
+ try_replace_tile(C, user)
+ return
else
if(istype(C, /obj/item/stack/cable_coil))
@@ -87,4 +62,48 @@
burnt = null
broken = null
else
- to_chat(user, "You need more welding fuel to complete this task.")
\ No newline at end of file
+ to_chat(user, "You need more welding fuel to complete this task.")
+
+/turf/simulated/floor/proc/try_deconstruct_tile(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/crowbar))
+ if(broken || burnt)
+ to_chat(user, "You remove the broken [flooring.descriptor].")
+ make_plating()
+ else if(flooring.flags & TURF_IS_FRAGILE)
+ to_chat(user, "You forcefully pry off the [flooring.descriptor], destroying them in the process.")
+ make_plating()
+ else if(flooring.flags & TURF_REMOVE_CROWBAR)
+ to_chat(user, "You lever off the [flooring.descriptor].")
+ make_plating(1)
+ else
+ return 0
+ playsound(src, W.usesound, 80, 1)
+ return 1
+ else if(istype(W, /obj/item/weapon/screwdriver) && (flooring.flags & TURF_REMOVE_SCREWDRIVER))
+ if(broken || burnt)
+ return 0
+ to_chat(user, "You unscrew and remove the [flooring.descriptor].")
+ make_plating(1)
+ playsound(src, W.usesound, 80, 1)
+ return 1
+ else if(istype(W, /obj/item/weapon/wrench) && (flooring.flags & TURF_REMOVE_WRENCH))
+ to_chat(user, "You unwrench and remove the [flooring.descriptor].")
+ make_plating(1)
+ playsound(src, W.usesound, 80, 1)
+ return 1
+ else if(istype(W, /obj/item/weapon/shovel) && (flooring.flags & TURF_REMOVE_SHOVEL))
+ to_chat(user, "You shovel off the [flooring.descriptor].")
+ make_plating(1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
+ return 1
+ return 0
+
+/turf/simulated/floor/proc/try_replace_tile(obj/item/stack/tile/T as obj, mob/user as mob)
+ if(T.type == flooring.build_type)
+ return
+ var/obj/item/weapon/W = user.is_holding_item_of_type(/obj/item/weapon)
+ if(!try_deconstruct_tile(W, user))
+ return
+ if(flooring)
+ return
+ attackby(T, user)
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm
index 91ca65259d..e1b49762ec 100644
--- a/code/game/turfs/simulated/floor_icon.dm
+++ b/code/game/turfs/simulated/floor_icon.dm
@@ -7,7 +7,7 @@ var/image/no_ceiling_image = null
return TRUE
/proc/cache_no_ceiling_image()
- no_ceiling_image = image(icon = 'icons/turf/open_space.dmi', icon_state = "no_ceiling", layer = OVERTURF_LAYER)
+ no_ceiling_image = image(icon = 'icons/turf/open_space.dmi', icon_state = "no_ceiling")
no_ceiling_image.plane = PLANE_MESONS
/turf/simulated/floor/update_icon(var/update_neighbors)
@@ -15,7 +15,7 @@ var/image/no_ceiling_image = null
if(lava)
return
- overlays.Cut()
+ cut_overlays()
if(flooring)
// Set initial icon and strings.
@@ -38,17 +38,17 @@ var/image/no_ceiling_image = null
var/turf/simulated/floor/T = get_step(src, step_dir)
if(!istype(T) || !T.flooring || T.flooring.name != flooring.name)
has_border |= step_dir
- overlays |= get_flooring_overlay("[flooring.icon_base]-edge-[step_dir]", "[flooring.icon_base]_edges", step_dir)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[step_dir]", "[flooring.icon_base]_edges", step_dir))
// There has to be a concise numerical way to do this but I am too noob.
if((has_border & NORTH) && (has_border & EAST))
- overlays |= get_flooring_overlay("[flooring.icon_base]-edge-[NORTHEAST]", "[flooring.icon_base]_edges", NORTHEAST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[NORTHEAST]", "[flooring.icon_base]_edges", NORTHEAST))
if((has_border & NORTH) && (has_border & WEST))
- overlays |= get_flooring_overlay("[flooring.icon_base]-edge-[NORTHWEST]", "[flooring.icon_base]_edges", NORTHWEST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[NORTHWEST]", "[flooring.icon_base]_edges", NORTHWEST))
if((has_border & SOUTH) && (has_border & EAST))
- overlays |= get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHEAST]", "[flooring.icon_base]_edges", SOUTHEAST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHEAST]", "[flooring.icon_base]_edges", SOUTHEAST))
if((has_border & SOUTH) && (has_border & WEST))
- overlays |= get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHWEST]", "[flooring.icon_base]_edges", SOUTHWEST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-edge-[SOUTHWEST]", "[flooring.icon_base]_edges", SOUTHWEST))
if(flooring.flags & TURF_HAS_CORNERS)
// As above re: concise numerical way to do this.
@@ -56,37 +56,36 @@ var/image/no_ceiling_image = null
if(!(has_border & EAST))
var/turf/simulated/floor/T = get_step(src, NORTHEAST)
if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- overlays |= get_flooring_overlay("[flooring.icon_base]-corner-[NORTHEAST]", "[flooring.icon_base]_corners", NORTHEAST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[NORTHEAST]", "[flooring.icon_base]_corners", NORTHEAST))
if(!(has_border & WEST))
var/turf/simulated/floor/T = get_step(src, NORTHWEST)
if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- overlays |= get_flooring_overlay("[flooring.icon_base]-corner-[NORTHWEST]", "[flooring.icon_base]_corners", NORTHWEST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[NORTHWEST]", "[flooring.icon_base]_corners", NORTHWEST))
if(!(has_border & SOUTH))
if(!(has_border & EAST))
var/turf/simulated/floor/T = get_step(src, SOUTHEAST)
if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- overlays |= get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHEAST]", "[flooring.icon_base]_corners", SOUTHEAST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHEAST]", "[flooring.icon_base]_corners", SOUTHEAST))
if(!(has_border & WEST))
var/turf/simulated/floor/T = get_step(src, SOUTHWEST)
if(!(istype(T) && T.flooring && T.flooring.name == flooring.name))
- overlays |= get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHWEST]", "[flooring.icon_base]_corners", SOUTHWEST)
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHWEST]", "[flooring.icon_base]_corners", SOUTHWEST))
- // Hack workaround to byond crash bug
- //if(decals && decals.len)
- //overlays |= decals
- apply_decals()
+ // Re-apply floor decals
+ if(LAZYLEN(decals))
+ add_overlay(decals)
if(is_plating() && !(isnull(broken) && isnull(burnt))) //temp, todo
icon = 'icons/turf/flooring/plating.dmi'
icon_state = "dmg[rand(1,4)]"
else if(flooring)
if(!isnull(broken) && (flooring.flags & TURF_CAN_BREAK))
- overlays |= get_flooring_overlay("[flooring.icon_base]-broken-[broken]","[flooring.icon_base]_broken[broken]")
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-broken-[broken]","[flooring.icon_base]_broken[broken]"))
if(!isnull(burnt) && (flooring.flags & TURF_CAN_BURN))
- overlays |= get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","[flooring.icon_base]_burned[burnt]")
+ add_overlay(get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","[flooring.icon_base]_burned[burnt]"))
if(weather_overlay)
- overlays += weather_overlay
+ add_overlay(weather_overlay)
if(update_neighbors)
for(var/turf/simulated/floor/F in range(src, 1))
@@ -97,7 +96,7 @@ var/image/no_ceiling_image = null
// Show 'ceilingless' overlay.
var/turf/above = GetAbove(src)
if(above && isopenspace(above) && !istype(src, /turf/simulated/floor/outdoors)) // This won't apply to outdoor turfs since its assumed they don't have a ceiling anyways.
- overlays |= no_ceiling_image
+ add_overlay(no_ceiling_image)
/turf/simulated/floor/proc/get_flooring_overlay(var/cache_key, var/icon_base, var/icon_dir = 0)
if(!flooring_cache[cache_key])
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index 07c686df99..3c4856cf00 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -15,17 +15,19 @@
var/list/decals
New(var/location = null, var/turf/simulated/shuttle/turf)
+ ..(null)
my_turf = turf
/obj/landed_holder/proc/land_on(var/turf/T)
//Gather destination information
- var/old_dest_type = T.type
- var/old_dest_dir = T.dir
- var/old_dest_icon_state = T.icon_state
- var/old_dest_icon = T.icon
- var/list/old_dest_overlays = T.overlays.Copy()
- var/list/old_dest_underlays = T.underlays.Copy()
- var/list/old_dest_decals = T.decals ? T.decals.Copy() : null
+ var/obj/landed_holder/new_holder = new(null)
+ new_holder.turf_type = T.type
+ new_holder.dir = T.dir
+ new_holder.icon = T.icon
+ new_holder.icon_state = T.icon_state
+ new_holder.copy_overlays(T, TRUE)
+ new_holder.underlays = T.underlays.Copy()
+ new_holder.decals = T.decals ? T.decals.Copy() : null
//Set the destination to be like us
T.Destroy()
@@ -33,7 +35,7 @@
new_dest.set_dir(my_turf.dir)
new_dest.icon_state = my_turf.icon_state
new_dest.icon = my_turf.icon
- new_dest.overlays = my_turf.overlays
+ new_dest.copy_overlays(my_turf, TRUE)
new_dest.underlays = my_turf.underlays
new_dest.decals = my_turf.decals
//Shuttle specific stuff
@@ -43,18 +45,9 @@
new_dest.join_flags = my_turf.join_flags
new_dest.join_group = my_turf.join_group
- if(new_dest.decals)
- new_dest.apply_decals()
-
- //Tell the new turf about what was there before
- new_dest.landed_holder = new(turf = new_dest)
- new_dest.landed_holder.turf_type = old_dest_type
- new_dest.landed_holder.dir = old_dest_dir
- new_dest.landed_holder.icon = old_dest_icon
- new_dest.landed_holder.icon_state = old_dest_icon_state
- new_dest.landed_holder.overlays = old_dest_overlays
- new_dest.landed_holder.underlays = old_dest_underlays
- new_dest.landed_holder.decals = old_dest_decals
+ // Associate the holder with the new turf.
+ new_holder.my_turf = new_dest
+ new_dest.landed_holder = new_holder
//Update underlays if necessary (interior corners won't have changed).
if(new_dest.takes_underlays && !new_dest.interior_corner)
@@ -70,11 +63,9 @@
new_source.set_dir(dir)
new_source.icon_state = icon_state
new_source.icon = icon
- new_source.overlays = overlays
+ new_source.copy_overlays(src, TRUE)
new_source.underlays = underlays
new_source.decals = decals
- if(new_source.decals)
- new_source.apply_decals()
else
new_source = my_turf.ChangeTurf(get_base_turf_by_area(my_turf),,1)
diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm
index 86e6b117bb..34a07ef9c4 100644
--- a/code/game/turfs/simulated/outdoors/outdoors.dm
+++ b/code/game/turfs/simulated/outdoors/outdoors.dm
@@ -44,7 +44,9 @@ var/list/outdoor_turfs = list()
planet_controller.unallocateTurf(src)
else // This is happening during map gen, if there's no planet_controller (hopefully).
outdoor_turfs -= src
- qdel(weather_overlay)
+ if(weather_overlay)
+ cut_overlay(weather_overlay)
+ qdel_null(weather_overlay)
update_icon()
/turf/simulated/post_change()
@@ -67,15 +69,14 @@ var/list/outdoor_turfs = list()
var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir)
I.plane = 0
turf_edge_cache[cache_key] = I
- overlays += turf_edge_cache[cache_key]
+ add_overlay(turf_edge_cache[cache_key])
/turf/simulated/proc/get_edge_icon_state()
return icon_state
/turf/simulated/floor/outdoors/update_icon()
- overlays.Cut()
- update_icon_edge()
..()
+ update_icon_edge()
/turf/simulated/floor/outdoors/mud
name = "mud"
diff --git a/code/game/turfs/simulated/outdoors/snow.dm b/code/game/turfs/simulated/outdoors/snow.dm
index 398fa0dc47..5fed8af66b 100644
--- a/code/game/turfs/simulated/outdoors/snow.dm
+++ b/code/game/turfs/simulated/outdoors/snow.dm
@@ -3,12 +3,14 @@
icon_state = "snow"
edge_blending_priority = 6
movement_cost = 2
+ initial_flooring = /decl/flooring/snow
turf_layers = list(
/turf/simulated/floor/outdoors/rocks,
/turf/simulated/floor/outdoors/dirt
)
var/list/crossed_dirs = list()
+
/turf/simulated/floor/outdoors/snow/Entered(atom/A)
if(isliving(A))
var/mdir = "[A.dir]"
@@ -17,10 +19,9 @@
. = ..()
/turf/simulated/floor/outdoors/snow/update_icon()
- overlays.Cut()
..()
for(var/d in crossed_dirs)
- overlays += image(icon = 'icons/turf/outdoors.dmi', icon_state = "snow_footprints", dir = text2num(d))
+ add_overlay(image(icon = 'icons/turf/outdoors.dmi', icon_state = "snow_footprints", dir = text2num(d)))
/turf/simulated/floor/outdoors/snow/attackby(var/obj/item/W, var/mob/user)
if(istype(W, /obj/item/weapon/shovel))
@@ -40,4 +41,17 @@
var/obj/S = new /obj/item/stack/material/snow(user.loc)
user.put_in_hands(S)
visible_message("[user] scoops up a pile of snow.", "You scoop up a pile of snow.")
- return
\ No newline at end of file
+ return
+
+/turf/simulated/floor/outdoors/ice
+ name = "ice"
+ icon_state = "ice"
+ desc = "Looks slippery."
+
+/turf/simulated/floor/outdoors/ice/Entered(var/mob/living/M)
+ sleep(1 * world.tick_lag)
+ if(istype(M, /mob/living))
+ if(M.stunned == 0)
+ to_chat(M, "You slide across the ice!")
+ M.SetStunned(1)
+ step(M,M.dir)
diff --git a/code/game/turfs/simulated/wall_icon.dm b/code/game/turfs/simulated/wall_icon.dm
index 2dac063723..b8a0980de4 100644
--- a/code/game/turfs/simulated/wall_icon.dm
+++ b/code/game/turfs/simulated/wall_icon.dm
@@ -47,36 +47,36 @@
if(!damage_overlays[1]) //list hasn't been populated
generate_overlays()
- overlays.Cut()
+ cut_overlays()
var/image/I
if(!density)
I = image('icons/turf/wall_masks.dmi', "[material.icon_base]fwall_open")
I.color = material.icon_colour
- overlays += I
+ add_overlay(I)
return
for(var/i = 1 to 4)
I = image('icons/turf/wall_masks.dmi', "[material.icon_base][wall_connections[i]]", dir = 1<<(i-1))
I.color = material.icon_colour
- overlays += I
+ add_overlay(I)
if(reinf_material)
if(construction_stage != null && construction_stage < 6)
I = image('icons/turf/wall_masks.dmi', "reinf_construct-[construction_stage]")
I.color = reinf_material.icon_colour
- overlays += I
+ add_overlay(I)
else
if("[reinf_material.icon_reinf]0" in icon_states('icons/turf/wall_masks.dmi'))
// Directional icon
for(var/i = 1 to 4)
I = image('icons/turf/wall_masks.dmi', "[reinf_material.icon_reinf][wall_connections[i]]", dir = 1<<(i-1))
I.color = reinf_material.icon_colour
- overlays += I
+ add_overlay(I)
else
I = image('icons/turf/wall_masks.dmi', reinf_material.icon_reinf)
I.color = reinf_material.icon_colour
- overlays += I
+ add_overlay(I)
if(damage != 0)
var/integrity = material.integrity
@@ -87,7 +87,7 @@
if(overlay > damage_overlays.len)
overlay = damage_overlays.len
- overlays += damage_overlays[overlay]
+ add_overlay(damage_overlays[overlay])
return
/turf/simulated/wall/proc/generate_overlays()
diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm
index f187a54c8f..eae30c6cb4 100644
--- a/code/game/turfs/simulated/wall_types.dm
+++ b/code/game/turfs/simulated/wall_types.dm
@@ -224,7 +224,7 @@
/turf/simulated/shuttle/wall/voidcraft/update_icon()
if(stripe_color)
- overlays.Cut()
+ cut_overlays()
var/image/I = image(icon = src.icon, icon_state = "o_[icon_state]")
I.color = stripe_color
- overlays.Add(I)
+ add_overlay(I)
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 21fd9492f0..e5bb57ad9e 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -252,7 +252,7 @@
O.icon_state = "2"
O.anchored = 1
O.density = 1
- O.layer = 5
+ O.plane = ABOVE_PLANE
if(girder_material.integrity >= 150 && !girder_material.is_brittle()) //Strong girders will remain in place when a wall is melted.
dismantle_wall(1,1)
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index a47578f102..e4b762d733 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -16,7 +16,6 @@
update_icon()
/turf/simulated/floor/water/update_icon()
- overlays.Cut()
..() // To get the edges.
icon_state = water_state
var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state)
@@ -129,16 +128,16 @@ var/list/shoreline_icon_cache = list()
// Water sprites are really annoying, so let BYOND sort it out.
/turf/simulated/floor/water/shoreline/update_icon()
underlays.Cut()
- overlays.Cut()
+ cut_overlays()
..() // Get the underlay first.
var/cache_string = "[initial(icon_state)]_[water_state]_[dir]"
if(cache_string in shoreline_icon_cache) // Check to see if an icon already exists.
- overlays += shoreline_icon_cache[cache_string]
+ add_overlay(shoreline_icon_cache[cache_string])
else // If not, make one, but only once.
var/icon/shoreline_water = icon(src.icon, "shoreline_water", src.dir)
var/icon/shoreline_subtract = icon(src.icon, "[initial(icon_state)]_subtract", src.dir)
shoreline_water.Blend(shoreline_subtract,ICON_SUBTRACT)
shoreline_icon_cache[cache_string] = shoreline_water
- overlays += shoreline_icon_cache[cache_string]
+ add_overlay(shoreline_icon_cache[cache_string])
diff --git a/code/game/turfs/snow/snow.dm b/code/game/turfs/snow/snow.dm
index b09275ca41..a8ccd5b63b 100644
--- a/code/game/turfs/snow/snow.dm
+++ b/code/game/turfs/snow/snow.dm
@@ -26,12 +26,12 @@
. = ..()
/turf/snow/update_icon()
- overlays.Cut()
+ cut_overlays()
for(var/d in crossed_dirs)
var/amt = crossed_dirs[d]
for(var/i in 1 to amt)
- overlays += icon(icon, "footprint[i]", text2num(d))
+ add_overlay(image(icon, "footprint[i]", text2num(d)))
/turf/snow/snow2
name = "snow"
diff --git a/code/game/turfs/space/cracked_asteroid.dm b/code/game/turfs/space/cracked_asteroid.dm
index b9f43af82e..dae0d5a129 100644
--- a/code/game/turfs/space/cracked_asteroid.dm
+++ b/code/game/turfs/space/cracked_asteroid.dm
@@ -10,7 +10,8 @@
/turf/space/cracked_asteroid/is_space() // So people don't start floating when standing on it.
return FALSE
-/turf/space/cracked_asteroid/New()
- ..()
- spawn(2 SECONDS)
- overlays.Cut()
\ No newline at end of file
+// u wot m8? ~Leshana
+// /turf/space/cracked_asteroid/New()
+// ..()
+// spawn(2 SECONDS)
+// overlays.Cut()
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index d3abc04352..100c3b5a31 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -1,5 +1,7 @@
/turf
icon = 'icons/turf/floors.dmi'
+ layer = TURF_LAYER
+ plane = TURF_PLANE
level = 1
var/holy = 0
@@ -101,6 +103,12 @@ turf/attackby(obj/item/weapon/W as obj, mob/user as mob)
return
if (do_after(user, 25 + (5 * user.weakened)) && !(user.stat))
step_towards(O, src)
+ if(ismob(O))
+ animate(O, transform = turn(O.transform, 20), time = 2)
+ sleep(2)
+ animate(O, transform = turn(O.transform, -40), time = 4)
+ sleep(4)
+ animate(O, transform = turn(O.transform, 20), time = 2)
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
if(movement_disabled && usr.ckey != movement_disabled_exception)
@@ -277,3 +285,6 @@ var/const/enterloopsanity = 100
if(isliving(AM))
var/mob/living/M = AM
M.turf_collision(src, speed)
+
+/turf/AllowDrop()
+ return TRUE
diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm
index bcbb4b133f..82206926cf 100644
--- a/code/game/turfs/unsimulated/beach.dm
+++ b/code/game/turfs/unsimulated/beach.dm
@@ -17,7 +17,7 @@
/turf/unsimulated/beach/water/New()
..()
- overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1)
+ add_overlay(image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1))
/turf/simulated/floor/beach
name = "Beach"
@@ -44,4 +44,4 @@
/turf/simulated/floor/beach/water/New()
..()
- overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1)
+ add_overlay(image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1))
diff --git a/code/game/turfs/unsimulated/shuttle.dm b/code/game/turfs/unsimulated/shuttle.dm
index 99f5bc15bd..cb70c6c36d 100644
--- a/code/game/turfs/unsimulated/shuttle.dm
+++ b/code/game/turfs/unsimulated/shuttle.dm
@@ -3,7 +3,6 @@
icon = 'icons/turf/shuttle_white.dmi'
thermal_conductivity = 0.05
heat_capacity = 0
- layer = 2
/turf/unsimulated/shuttle/wall
name = "wall"
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 8fafb555a3..11aa51eb90 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -35,7 +35,7 @@
message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]")
return
- log_ooc("[mob.name]/[key] : [msg]")
+ log_ooc(msg, src)
if(msg)
handle_spam_prevention(MUTE_OOC)
@@ -108,7 +108,7 @@
message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]")
return
- log_ooc("(LOCAL) [mob.name]/[key] : [msg]")
+ log_looc(msg,src)
if(msg)
handle_spam_prevention(MUTE_OOC)
diff --git a/code/global.dm b/code/global.dm
index 3bf111ef4f..1f6124602a 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -21,7 +21,10 @@ var/global/list/global_map = null
// Noises made when hit while typing.
var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF")
+var/log_path = "data/logs/" //See world.dm for the full calculated path
var/diary = null
+var/error_log = null
+var/debug_log = null
var/href_logfile = null
// var/station_name = "Northern Star"
// var/const/station_orig = "Northern Star" //station_name can't be const due to event prefix/suffix
@@ -184,7 +187,7 @@ var/static/list/scarySounds = list(
var/max_explosion_range = 14
// Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it.
-var/global/obj/item/device/radio/intercom/global_announcer = new /obj/item/device/radio/intercom{channels=list("Engineering")}(null)
+var/global/obj/item/device/radio/intercom/omni/global_announcer = new /obj/item/device/radio/intercom/omni(null)
var/list/station_departments = list("Command", "Medical", "Engineering", "Science", "Security", "Cargo", "Civilian")
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index 39926e1414..e28c4fd570 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -6,13 +6,13 @@ world/IsBanned(key,address,computer_id)
//Guest Checking
if(!config.guests_allowed && IsGuestKey(key))
- log_access("Failed Login: [key] - Guests not allowed")
+ log_adminwarn("Failed Login: [key] - Guests not allowed")
message_admins("Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
//check if the IP address is a known TOR node
if(config && config.ToRban && ToRban_isbanned(address))
- log_access("Failed Login: [src] - Banned: ToR")
+ log_adminwarn("Failed Login: [src] - Banned: ToR")
message_admins("Failed Login: [src] - Banned: ToR")
//ban their computer_id and ckey for posterity
AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0)
@@ -24,7 +24,7 @@ world/IsBanned(key,address,computer_id)
//Ban Checking
. = CheckBan( ckey(key), computer_id, address )
if(.)
- log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
message_admins("Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
return .
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 61f2d174ac..08b16efa60 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -6,13 +6,13 @@ var/global/floorIsLava = 0
////////////////////////////////
/proc/message_admins(var/msg)
msg = "ADMIN LOG: [msg]"
- log_adminwarn(msg)
+ //log_adminwarn(msg) //log_and_message_admins is for this
+
for(var/client/C in admins)
if((R_ADMIN|R_MOD) & C.holder.rights)
C << msg
/proc/msg_admin_attack(var/text) //Toggleable Attack Messages
- log_attack(text)
var/rendered = "ATTACK: [text]"
for(var/client/C in admins)
if((R_ADMIN|R_MOD) & C.holder.rights)
@@ -380,7 +380,7 @@ proc/admin_notice(var/message, var/rights)
if(3)
dat+={"
Creating new Feed Message...
-
Receiving Channel: [src.admincaster_feed_channel.channel_name]
" //MARK
+
Receiving Channel: [src.admincaster_feed_channel.channel_name]
Message Author: [src.admincaster_signature]
Message Body: [src.admincaster_feed_message.body]
Submit
Cancel
@@ -674,10 +674,7 @@ proc/admin_notice(var/message, var/rights)
set desc = "Send an intercom message, like an arrivals announcement."
if(!check_rights(0)) return
- //This is basically how death alarms do it
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/omni(null)
-
- var/channel = input("Channel for message:","Channel", null) as null|anything in (list("Common") + a.keyslot2.channels) // + a.keyslot1.channels
+ var/channel = input("Channel for message:","Channel", null) as null|anything in radiochannels
if(channel) //They picked a channel
var/sender = input("Name of sender (max 75):", "Announcement", "Announcement Computer") as null|text
@@ -688,11 +685,94 @@ proc/admin_notice(var/message, var/rights)
if(message) //They put a message
message = sanitize(message, 500, extra = 0)
- a.autosay("[message]", "[sender]", "[channel == "Common" ? null : channel]") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set.
+ global_announcer.autosay("[message]", "[sender]", "[channel == "Common" ? null : channel]") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set.
log_admin("Intercom: [key_name(usr)] : [sender]:[message]")
- qdel(a)
+
feedback_add_details("admin_verb","IN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/datum/admins/proc/intercom_convo()
+ set category = "Fun"
+ set name = "Intercom Convo"
+ set desc = "Send an intercom conversation, like several uses of the Intercom Msg verb."
+ set waitfor = FALSE //Why bother? We have some sleeps. You can leave tho!
+ if(!check_rights(0)) return
+
+ var/channel = input("Channel for message:","Channel", null) as null|anything in radiochannels
+
+ if(!channel) //They picked a channel
+ return
+
+ to_chat(usr,"Intercom Convo Directions
Start the conversation with the sender, a pipe (|), and then the message on one line. Then hit enter to \
+ add another line, and type a (whole) number of seconds to pause between that message, and the next message, then repeat the message syntax up to 20 times. For example:
\
+ --- --- ---
\
+ Some Guy|Hello guys, what's up?
\
+ 5
\
+ Other Guy|Hey, good to see you.
\
+ 5
\
+ Some Guy|Yeah, you too.
\
+ --- --- ---
\
+ The above will result in those messages playing, with a 5 second gap between each. Maximum of 20 messages allowed.")
+
+ var/list/decomposed
+ var/message = input(usr,"See your chat box for instructions. Keep a copy elsewhere in case it is rejected when you click OK.", "Input Conversation", "") as null|message
+
+ if(!message)
+ return
+
+ //Split on pipe or \n
+ decomposed = splittext(message,regex("\\||$","m"))
+ decomposed += "0" //Tack on a final 0 sleep to make 3-per-message evenly
+
+ //Time to find how they screwed up.
+ //Wasn't the right length
+ if((decomposed.len) % 3) //+1 to accomidate the lack of a wait time for the last message
+ to_chat(usr,"You passed [decomposed.len] segments (senders+messages+pauses). You must pass a multiple of 3, minus 1 (no pause after the last message). That means a sender and message on every other line (starting on the first), separated by a pipe character (|), and a number every other line that is a pause in seconds.")
+ return
+
+ //Too long a conversation
+ if((decomposed.len / 3) > 20)
+ to_chat(usr,"This conversation is too long! 20 messages maximum, please.")
+ return
+
+ //Missed some sleeps, or sanitized to nothing.
+ for(var/i = 1; i < decomposed.len; i++)
+
+ //Sanitize sender
+ var/clean_sender = sanitize(decomposed[i])
+ if(!clean_sender)
+ to_chat(usr,"One part of your conversation was not able to be sanitized. It was the sender of the [(i+2)/3]\th message.")
+ return
+ decomposed[i] = clean_sender
+
+ //Sanitize message
+ var/clean_message = sanitize(decomposed[++i])
+ if(!clean_message)
+ to_chat(usr,"One part of your conversation was not able to be sanitized. It was the body of the [(i+2)/3]\th message.")
+ return
+ decomposed[i] = clean_message
+
+ //Sanitize wait time
+ var/clean_time = text2num(decomposed[++i])
+ if(!isnum(clean_time))
+ to_chat(usr,"One part of your conversation was not able to be sanitized. It was the wait time after the [(i+2)/3]\th message.")
+ return
+ if(clean_time > 60)
+ to_chat(usr,"Max 60 second wait time between messages for sanity's sake please.")
+ return
+ decomposed[i] = clean_time
+
+ log_admin("Intercom convo started by: [key_name(usr)] : [sanitize(message)]")
+ feedback_add_details("admin_verb","IN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+ //Sanitized AND we still have a chance to send it? Wow!
+ if(LAZYLEN(decomposed))
+ for(var/i = 1; i < decomposed.len; i++)
+ var/this_sender = decomposed[i]
+ var/this_message = decomposed[++i]
+ var/this_wait = decomposed[++i]
+ global_announcer.autosay("[this_message]", "[this_sender]", "[channel == "Common" ? null : channel]") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set.
+ sleep(this_wait SECONDS)
+
/datum/admins/proc/toggleooc()
set category = "Server"
set desc="Globally Toggles OOC"
diff --git a/code/modules/admin/admin_attack_log.dm b/code/modules/admin/admin_attack_log.dm
index 967a4375da..f04bdf3b61 100644
--- a/code/modules/admin/admin_attack_log.dm
+++ b/code/modules/admin/admin_attack_log.dm
@@ -16,7 +16,7 @@ proc/log_and_message_admins_many(var/list/mob/users, var/message)
log_admin("[english_list(user_keys)] [message]")
message_admins("[english_list(user_keys)] [message]")
-
+/* Old procs
proc/admin_attack_log(var/mob/attacker, var/mob/victim, var/attacker_message, var/victim_message, var/admin_message)
if(victim)
victim.attack_log += text("\[[time_stamp()]\] [key_name(attacker)] - [victim_message]")
@@ -42,3 +42,4 @@ proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amoun
"used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
"was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
"used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
+*/
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 12c00aa708..772c1886a8 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -6,6 +6,10 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
var/previous_rights = 0
+ //Clear profile access
+ for(var/A in world.GetConfig("admin"))
+ world.SetConfig("APP/admin", A, null)
+
//load text from file
var/list/Lines = file2list("config/admin_ranks.txt")
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 04740237f1..6b038aca4e 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -26,6 +26,7 @@ var/list/admin_verbs_admin = list(
/datum/admins/proc/toggleguests, //toggles whether guests can join the current game,
/datum/admins/proc/announce, //priority announce something to all clients.,
/datum/admins/proc/intercom, //send a fake intercom message, like an arrivals announcement,
+ /datum/admins/proc/intercom_convo, //send a fake intercom conversation, like an ATC exchange,
/client/proc/colorooc, //allows us to set a custom colour for everythign we say in ooc,
/client/proc/admin_ghost, //allows us to ghost/reenter body at will,
/client/proc/toggle_view_range, //changes how far we can see,
@@ -192,6 +193,8 @@ var/list/admin_verbs_debug = list(
/client/proc/cmd_debug_del_all,
/client/proc/cmd_debug_tog_aliens,
/client/proc/cmd_display_del_log,
+ /client/proc/cmd_display_init_log,
+ /client/proc/cmd_display_overlay_log,
/client/proc/air_report,
/client/proc/reload_admins,
/client/proc/reload_eventMs,
diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 4f0cba95c4..2d74b43433 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -23,6 +23,8 @@ var/list/admin_datums = list()
rank = initial_rank
rights = initial_rights
admin_datums[ckey] = src
+ if(rights & R_DEBUG) //grant profile access
+ world.SetConfig("APP/admin", ckey, "role=admin")
/datum/admins/proc/associate(client/C)
if(istype(C))
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 81c709f6d8..358df91af6 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1001,11 +1001,6 @@
//strip their stuff and stick it in the crate
for(var/obj/item/I in M)
M.drop_from_inventory(I, locker)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- H.update_icons_layers() //Cheaper
- else
- M.update_icons()
//so they black out before warping
M.Paralyse(5)
@@ -1188,10 +1183,8 @@
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
var/block=text2num(href_list["block"])
- //testing("togmutate([href_list["block"]] -> [block])")
usr.client.cmd_admin_toggle_block(H,block)
show_player_panel(H)
- //H.regenerate_icons()
else if(href_list["adminplayeropts"])
var/mob/M = locate(href_list["adminplayeropts"])
@@ -1228,7 +1221,7 @@
if(ismob(M))
var/take_msg = "ADMINHELP: [key_name(usr.client)] is attending to [key_name(M)]'s adminhelp, please don't dogpile them."
for(var/client/X in admins)
- if((R_ADMIN|R_MOD|R_EVENT) & X.holder.rights)
+ if((R_ADMIN|R_MOD|R_EVENT|R_SERVER) & X.holder.rights)
to_chat(X, take_msg)
to_chat(M, "Your adminhelp is being attended to by [usr.client]. Thanks for your patience!")
else
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index dcaa745485..4ff94877f4 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -104,7 +104,7 @@
if(C.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
C << 'sound/effects/adminhelp.ogg'
- log_admin("PM: [key_name(src)]->[key_name(C)]: [msg]")
+ log_adminpm(msg,src,C)
send2adminirc("Reply: [key_name(src)]->[key_name(C)]: [html_decode(msg)]")
//we don't use message_admins here because the sender/receiver might get it too
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index 264e5ad64e..0fdc158227 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -9,7 +9,7 @@
if(!msg)
return
- log_admin("ADMIN: [key_name(src)] : [msg]")
+ log_adminsay(msg,src)
if(check_rights(R_ADMIN,0))
for(var/client/C in admins)
@@ -27,7 +27,7 @@
return
msg = sanitize(msg)
- log_admin("MOD: [key_name(src)] : [msg]")
+ log_modsay(msg,src)
if (!msg)
return
@@ -50,7 +50,7 @@
return
msg = sanitize(msg)
- log_admin("EVENT: [key_name(src)] : [msg]")
+ log_eventsay(msg,src)
if (!msg)
return
diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm
index f3a6ffc77c..22689f1718 100644
--- a/code/modules/admin/verbs/antag-ooc.dm
+++ b/code/modules/admin/verbs/antag-ooc.dm
@@ -39,4 +39,4 @@
if((M.mind && M.mind.special_role && A && A.can_use_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC.
to_chat(M, "[create_text_tag("aooc", "Antag-OOC:", M.client)] [player_display]: [msg]")
- log_ooc("(ANTAG) [key] : [msg]")
\ No newline at end of file
+ log_aooc(msg,src)
\ No newline at end of file
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 56617c8399..326a317bfd 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -327,6 +327,36 @@
usr << browse(dellog.Join(), "window=dellog")
+/client/proc/cmd_display_init_log()
+ set category = "Debug"
+ set name = "Display Initialize() Log"
+ set desc = "Displays a list of things that didn't handle Initialize() properly"
+
+ if(!check_rights(R_DEBUG)) return
+ src << browse(replacetext(SSatoms.InitLog(), "\n", "
"), "window=initlog")
+
+/client/proc/cmd_display_overlay_log()
+ set category = "Debug"
+ set name = "Display overlay Log"
+ set desc = "Display SSoverlays log of everything that's passed through it."
+
+ if(!check_rights(R_DEBUG)) return
+ render_stats(SSoverlays.stats, src)
+
+// Render stats list for round-end statistics.
+/proc/render_stats(list/stats, user, sort = /proc/cmp_generic_stat_item_time)
+ sortTim(stats, sort, TRUE)
+
+ var/list/lines = list()
+ for (var/entry in stats)
+ var/list/data = stats[entry]
+ lines += "[entry] => [num2text(data[STAT_ENTRY_TIME], 10)]ms ([data[STAT_ENTRY_COUNT]]) (avg:[num2text(data[STAT_ENTRY_TIME]/(data[STAT_ENTRY_COUNT] || 1), 99)])"
+
+ if (user)
+ user << browse("- [lines.Join("
- ")]
", "window=[url_encode("stats:\ref[stats]")]")
+ else
+ . = lines.Join("\n")
+
/client/proc/cmd_admin_grantfullaccess(var/mob/M in mob_list)
set category = "Admin"
set name = "Grant Full Access"
diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm
index eac11fcac0..3f6e4c9e74 100644
--- a/code/modules/admin/verbs/getlogs.dm
+++ b/code/modules/admin/verbs/getlogs.dm
@@ -85,7 +85,7 @@
set name = "Show Server Log"
set desc = "Shows today's server log."
- var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")].log"
+ var/path = "[log_path].log"
if( fexists(path) )
src << run( file(path) )
else
@@ -99,7 +99,10 @@
set category = "Admin"
set name = "Show Server Attack Log"
set desc = "Shows today's server attack log."
+
+ to_chat(usr,"This verb doesn't actually do anything.")
+ /*
var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")] Attack.log"
if( fexists(path) )
src << run( file(path) )
@@ -109,3 +112,5 @@
usr << run( file(path) )
feedback_add_details("admin_verb","SSAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+ */
+
\ No newline at end of file
diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm
index 6de30853ce..aa100623ff 100644
--- a/code/modules/admin/verbs/possess.dm
+++ b/code/modules/admin/verbs/possess.dm
@@ -37,7 +37,6 @@
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.name = H.get_visible_name()
-// usr.regenerate_icons() //So the name is updated properly
usr.loc = O.loc // Appear where the object you were controlling is -- TLE
usr.client.eye = usr
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index e624d2df05..cb110d4e86 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -143,7 +143,12 @@
vtext = "\ref[C] - [C] ([C.type])"
else if(islist(value))
var/list/L = value
- vtext = "/list ([L.len])"
+ var/removed = 0
+ if(varname == "contents")
+ var/list/original = value
+ L = original.Copy() //We'll take a copy to manipulate
+ removed = D.view_variables_filter_contents(L)
+ vtext = "/list ([L.len]+[removed]H)"
if(!(varname in view_variables_dont_expand) && L.len > 0 && L.len < 100)
extra = "