diff --git a/.gitignore b/.gitignore
index c824a920cd..c6148fdc97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
#ignore misc BYOND files
Thumbs.db
+vchat.db
+vchat.db*
*.log
*.int
*.rsc
diff --git a/.travis.yml b/.travis.yml
index 7cccc5264b..fcf6fa2e39 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,12 @@
#pretending we're C because otherwise ruby will initialize, even with "language: dm".
language: c
-sudo: false
env:
global:
+ - BASENAME="polaris" # $BASENAME.dmb, $BASENAME.dme, etc.
- BYOND_MAJOR="513"
- - BYOND_MINOR="1502"
+ - BYOND_MINOR="1513"
- MACRO_COUNT=4
- matrix:
- - TEST_DEFINE="MAP_TEST" TEST_FILE="code/_map_tests.dm" RUN="0"
- - TEST_DEFINE="AWAY_MISSION_TEST" TEST_FILE="code/_away_mission_tests.dm" RUN="0"
- - TEST_DEFINE="UNIT_TEST" TEST_FILE="code/_unit_tests.dm" RUN="1"
cache:
directories:
@@ -22,30 +18,38 @@ addons:
- libc6-i386
- libgcc1:i386
- libstdc++6:i386
+ - libssl-dev:i386
-before_script:
- - chmod +x ./install-byond.sh
- - ./install-byond.sh
+before_install:
+ - chmod -R +x ./tools/travis
install:
- - pip install --user PyYaml -q
- - pip install --user beautifulsoup4 -q
+ - ./tools/travis/install_byond.sh
+
+before_script:
+ - shopt -s globstar
script:
- - shopt -s globstar
- - (! grep 'step_[xy]' maps/**/*.dmm)
- - (! grep -Pn '( |\t|;|{)tag( ?)=' maps/**/*.dmm)
- - (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano)
- - (! grep -En "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm)
- - awk -f tools/indentation.awk **/*.dm
- - md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml"
- - (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])
- - source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup
- - python tools/TagMatcher/tag-matcher.py ../..
- # Run our test
- - cp config/example/* config/
- - echo "#define ${TEST_DEFINE} 1" > ${TEST_FILE}
- - DreamMaker polaris.dme
- - if [ $RUN -eq 1 ]; then DreamDaemon polaris.dmb -invisible -trusted -core 2>&1 | tee log.txt; fi
- - if [ $RUN -eq 1 ]; then grep "All Unit Tests Passed" log.txt; fi
+ - ./tools/travis/compile_and_run.sh
+# Build-specific settings
+jobs:
+ include:
+ - stage: "File Tests" #This is the odd man out, with specific installs and stuff.
+ name: "Validate Files"
+ install: #Need python for some of the tag matching stuff
+ - pip install --user PyYaml -q
+ - pip install --user beautifulsoup4 -q
+ script: ./tools/travis/validate_files.sh
+ addons:
+ apt:
+ packages: ~ # Don't need any packages for this
+ - stage: "Unit Tests"
+ env: TEST_DEFINE="UNIT_TEST" TEST_FILE="code/_unit_tests.dm" RUN="1"
+ name: "Compile normally (unit tests)"
+ - stage: "Isolation Tests"
+ env: TEST_DEFINE="MAP_TEST" TEST_FILE="code/_map_tests.dm" RUN="0"
+ name: "Compile POIs (no run)"
+ - env: TEST_DEFINE="AWAY_MISSION_TEST" TEST_FILE="code/_away_mission_tests.dm" RUN="0"
+ name: "Compile away missions (no run)"
+
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index 4698c613a9..cc280d97cc 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -1,7 +1,7 @@
/obj/machinery/atmospherics/binary
dir = SOUTH
initialize_directions = SOUTH|NORTH
- use_power = 1
+ use_power = USE_POWER_IDLE
var/datum/gas_mixture/air1
var/datum/gas_mixture/air2
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 41ba2cf705..2f276160fe 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -20,7 +20,7 @@
level = 1
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
@@ -214,10 +214,10 @@
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
if(signal.data["power"])
- use_power = text2num(signal.data["power"])
+ update_use_power(text2num(signal.data["power"]))
if(signal.data["power_toggle"])
- use_power = !use_power
+ update_use_power(!use_power)
if(signal.data["direction"])
pump_direction = text2num(signal.data["direction"])
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index 92c26fb280..191e6291ea 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -12,7 +12,7 @@
name = "pressure regulator"
desc = "A one-way air valve that can be used to regulate input or output pressure, and flow rate. Does not require power."
- use_power = 0
+ use_power = USE_POWER_OFF
var/unlocked = 0 //If 0, then the valve is locked closed, otherwise it is open(-able, it's a one-way valve so it closes if gas would flow backwards).
var/target_pressure = ONE_ATMOSPHERE
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index b4b8187f45..e241cc944b 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -26,7 +26,7 @@ Thus, the two variables affect pump operation are set in New():
//var/max_volume_transfer = 10000
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
@@ -47,7 +47,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/binary/pump/on
icon_state = "map_on"
- use_power = 1
+ use_power = USE_POWER_IDLE
/obj/machinery/atmospherics/binary/pump/update_icon()
@@ -160,12 +160,12 @@ Thus, the two variables affect pump operation are set in New():
if(signal.data["power"])
if(text2num(signal.data["power"]))
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
else
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if("power_toggle" in signal.data)
- use_power = !use_power
+ update_use_power(!use_power)
if(signal.data["set_output_pressure"])
target_pressure = between(
@@ -199,7 +199,7 @@ Thus, the two variables affect pump operation are set in New():
if(..()) return 1
if(href_list["power"])
- use_power = !use_power
+ update_use_power(!use_power)
switch(href_list["set_press"])
if ("min")
diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
index fa0aaf4bd0..8e82750588 100644
--- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm
@@ -11,7 +11,7 @@
power_rating = 15000 //15000 W ~ 20 HP
/obj/machinery/atmospherics/binary/pump/high_power/on
- use_power = 1
+ use_power = USE_POWER_IDLE
icon_state = "map_on"
/obj/machinery/atmospherics/binary/pump/high_power/update_icon()
diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm
index 074c6c528d..9f0862d800 100644
--- a/code/ATMOSPHERICS/components/omni_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm
@@ -11,7 +11,7 @@
var/datum/omni_port/input
var/datum/omni_port/output
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
@@ -161,13 +161,13 @@
switch(href_list["command"])
if("power")
if(!configuring)
- use_power = !use_power
+ update_use_power(!use_power)
else
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if("configure")
configuring = !configuring
if(configuring)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
if(configuring && !use_power)
diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
index 47c78427f0..0210d09e69 100644
--- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
@@ -6,7 +6,7 @@
icon_state = "map_mixer"
pipe_state = "omni_mixer"
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 3700 //3700 W ~ 5 HP
@@ -178,13 +178,13 @@
switch(href_list["command"])
if("power")
if(!configuring)
- use_power = !use_power
+ update_use_power(!use_power)
else
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if("configure")
configuring = !configuring
if(configuring)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
if(configuring && !use_power)
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index 1a82bab1e2..92075b7440 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -5,7 +5,7 @@
name = "omni device"
icon = 'icons/atmos/omni_devices.dmi'
icon_state = "base"
- use_power = 1
+ use_power = USE_POWER_IDLE
initialize_directions = 0
construction_type = /obj/item/pipe/quaternary
level = 1
@@ -67,7 +67,7 @@
last_flow_rate = 0
if(error_check())
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if((stat & (NOPOWER|BROKEN)) || !use_power)
return 0
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index b30bc9b038..fd5033100b 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -18,7 +18,7 @@
var/datum/pipe_network/network
var/on = 0
- use_power = 0
+ use_power = USE_POWER_OFF
level = 1
/obj/machinery/atmospherics/portables_connector/init_dir()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index e900303e22..21e1a34d33 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -9,7 +9,7 @@
name = "Gas filter"
desc = "Filters one type of gas from an input, and pushes it out the side."
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //This also doubles as a measure of how powerful the filter is, in Watts. 7500 W ~ 10 HP
@@ -73,7 +73,7 @@
icon_state += use_power ? "on" : "off"
else
icon_state += "off"
- use_power = 0
+ update_use_power(USE_POWER_OFF)
/obj/machinery/atmospherics/trinary/atmos_filter/process()
..()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index 8bf3d3477c..62b4b763b8 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -8,7 +8,7 @@
name = "Gas mixer"
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
@@ -35,7 +35,7 @@
icon_state += use_power ? "on" : "off"
else
icon_state += "off"
- use_power = 0
+ update_use_power(USE_POWER_OFF)
/obj/machinery/atmospherics/trinary/mixer/New()
..()
@@ -114,7 +114,7 @@
/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
if(..()) return 1
if(href_list["power"])
- use_power = !use_power
+ update_use_power(!use_power)
if(href_list["set_press"])
var/max_flow_rate = min(air1.volume, air2.volume)
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num
diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
index 394dbceeda..10d7403541 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
@@ -1,7 +1,7 @@
/obj/machinery/atmospherics/trinary
dir = SOUTH
initialize_directions = SOUTH|NORTH|WEST
- use_power = 0
+ use_power = USE_POWER_OFF
pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
var/mirrored = FALSE
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index 0fddd6d8e8..ba092489a9 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -8,7 +8,7 @@
icon_state = "freezer_0"
density = 1
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 5 // 5 Watts for thermostat related circuitry
circuit = /obj/item/weapon/circuitboard/unary_atmos/cooler
@@ -99,7 +99,7 @@
if(..())
return 1
if(href_list["toggleStatus"])
- use_power = !use_power
+ update_use_power(!use_power)
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index 7a2caa1d9d..8e4d474270 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -8,7 +8,7 @@
icon_state = "heater_0"
density = 1
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 5 //5 Watts for thermostat related circuitry
circuit = /obj/item/weapon/circuitboard/unary_atmos/heater
@@ -119,7 +119,7 @@
if(..())
return 1
if(href_list["toggleStatus"])
- use_power = !use_power
+ update_use_power(!use_power)
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index 5e62fe5802..3c342c3cdb 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -10,7 +10,7 @@
name = "air injector"
desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 15000 //15000 W ~ 20 HP
@@ -132,10 +132,10 @@
return 0
if(signal.data["power"])
- use_power = text2num(signal.data["power"])
+ update_use_power(text2num(signal.data["power"]))
if(signal.data["power_toggle"])
- use_power = !use_power
+ update_use_power(!use_power)
if(signal.data["inject"])
spawn inject()
@@ -160,7 +160,7 @@
/obj/machinery/atmospherics/unary/outlet_injector/attack_hand(mob/user as mob)
to_chat(user, "You toggle \the [src].")
injecting = !injecting
- use_power = injecting
+ update_use_power(injecting ? USE_POWER_IDLE : USE_POWER_OFF)
update_icon()
/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index f30def6e07..07518019d2 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -14,7 +14,7 @@
name = "Air Vent"
desc = "Has a valve and pump attached to it"
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
@@ -50,18 +50,18 @@
var/datum/looping_sound/air_pump/soundloop
/obj/machinery/atmospherics/unary/vent_pump/on
- use_power = 1
+ use_power = USE_POWER_IDLE
icon_state = "map_vent_out"
/obj/machinery/atmospherics/unary/vent_pump/siphon
pump_direction = 0
/obj/machinery/atmospherics/unary/vent_pump/siphon/on
- use_power = 1
+ use_power = USE_POWER_IDLE
icon_state = "map_vent_in"
/obj/machinery/atmospherics/unary/vent_pump/siphon/on/atmos
- use_power = 1
+ use_power = USE_POWER_IDLE
icon_state = "map_vent_in"
external_pressure_bound = 0
external_pressure_bound_default = 0
@@ -173,7 +173,7 @@
return 1
if (!node)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if(!can_pump())
return 0
@@ -295,10 +295,10 @@
pump_direction = 1
if(signal.data["power"] != null)
- use_power = text2num(signal.data["power"])
+ update_use_power(text2num(signal.data["power"]))
if(signal.data["power_toggle"] != null)
- use_power = !use_power
+ update_use_power(!use_power)
if(signal.data["checks"] != null)
if (signal.data["checks"] == "default")
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 34897b66ef..6e3f9ef042 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -5,7 +5,7 @@
name = "Air Scrubber"
desc = "Has a valve and pump attached to it"
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 150 //internal circuitry, friction losses and stuff
power_rating = 7500 //7500 W ~ 10 HP
@@ -29,7 +29,7 @@
var/radio_filter_in
/obj/machinery/atmospherics/unary/vent_scrubber/on
- use_power = 1
+ use_power = USE_POWER_IDLE
icon_state = "map_scrubber_on"
/obj/machinery/atmospherics/unary/vent_scrubber/New()
@@ -135,7 +135,7 @@
return 1
if (!node)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
//broadcast_status()
if(!use_power || (stat & (NOPOWER|BROKEN)))
return 0
@@ -180,21 +180,21 @@
return 0
if(signal.data["power"] != null)
- use_power = text2num(signal.data["power"])
+ update_use_power(text2num(signal.data["power"]))
if(signal.data["power_toggle"] != null)
- use_power = !use_power
+ update_use_power(!use_power)
if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
panic = text2num(signal.data["panic_siphon"])
if(panic)
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
scrubbing = 0
else
scrubbing = 1
if(signal.data["toggle_panic_siphon"] != null)
panic = !panic
if(panic)
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
scrubbing = 0
else
scrubbing = 1
diff --git a/code/ATMOSPHERICS/pipes/pipe_base.dm b/code/ATMOSPHERICS/pipes/pipe_base.dm
index d1bb92fac7..e627fcbb46 100644
--- a/code/ATMOSPHERICS/pipes/pipe_base.dm
+++ b/code/ATMOSPHERICS/pipes/pipe_base.dm
@@ -9,7 +9,7 @@
var/leaking = FALSE // Do not set directly, use set_leaking(TRUE/FALSE)
layer = PIPES_LAYER
- use_power = 0
+ use_power = USE_POWER_OFF
pipe_flags = 0 // Does not have PIPING_DEFAULT_LAYER_ONLY flag.
diff --git a/code/__defines/_compile_options.dm b/code/__defines/_compile_options.dm
index 229d0b94ad..5ac591042b 100644
--- a/code/__defines/_compile_options.dm
+++ b/code/__defines/_compile_options.dm
@@ -11,6 +11,9 @@
//#define ZASDBG // Uncomment to turn on super detailed ZAS debugging that probably won't even compile.
#define MULTIZAS // Uncomment to turn on Multi-Z ZAS Support!
+// Comment/Uncomment this to turn off/on shuttle code debugging logs
+#define DEBUG_SHUTTLES
+
// If we are doing the map test build, do not include the main maps, only the submaps.
#if MAP_TEST
#define USING_MAP_DATUM /datum/map
diff --git a/code/__defines/_lists.dm b/code/__defines/_lists.dm
index 2a570f6f42..016d1a89d4 100644
--- a/code/__defines/_lists.dm
+++ b/code/__defines/_lists.dm
@@ -18,6 +18,9 @@
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
+// Adds I to L, initalizing L if necessary, if I is not already in L
+#define LAZYDISTINCTADD(L, I) if(!L) { L = list(); } L |= I;
+
#define LAZYFIND(L, V) L ? L.Find(V) : 0
// Reads I from L safely - Works with both associative and traditional lists.
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index 01d890b152..e79511d797 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -42,6 +42,8 @@ What is the naming convention for planes or layers?
#define SPACE_PLANE -82 // Reserved for use in space/parallax
#define PARALLAX_PLANE -80 // Reserved for use in space/parallax
+#define SKYBOX_PLANE -79 // Skybox parallax
+#define DUST_PLANE -78 // For dust overlay on space turfs. Should be above skybox for parallax effect.
// OPENSPACE_PLANE reserves all planes between OPENSPACE_PLANE_START and OPENSPACE_PLANE_END inclusive
#define OPENSPACE_PLANE -75 // /turf/simulated/open will use OPENSPACE_PLANE + z (Valid z's being 2 thru 17)
@@ -50,7 +52,7 @@ What is the naming convention for planes or layers?
#define OVER_OPENSPACE_PLANE -57
// Turf Planes
-#define SPACE_PLANE -43 // Space turfs themselves
+#define SPACE_PLANE -82 // Space turfs themselves
#define PLATING_PLANE -44 // Plating
#define DISPOSAL_LAYER 2.1 // Under objects, even when planeswapped
#define PIPES_LAYER 2.2 // Under objects, even when planeswapped
@@ -86,6 +88,9 @@ What is the naming convention for planes or layers?
#define BELOW_MOB_LAYER 3.9 // Should be converted to plane swaps
#define ABOVE_MOB_LAYER 4.1 // Should be converted to plane swaps
+// Invisible things plane
+#define CLOAKED_PLANE -15
+
// Top plane (in the sense that it's the highest in 'the world' and not a UI element)
#define ABOVE_PLANE -10
diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm
index 66348344f2..56055273e4 100644
--- a/code/__defines/atmos.dm
+++ b/code/__defines/atmos.dm
@@ -29,6 +29,7 @@
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Either this must be active
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C + 100) // or this (or both, obviously)
+#define MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND (MINIMUM_AIR_TO_SUSPEND*R_IDEAL_GAS_EQUATION*T20C)/CELL_VOLUME // Minimum pressure difference between zones to suspend
#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012 // Minimum temperature difference before group processing is suspended.
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4
diff --git a/code/__defines/construction.dm b/code/__defines/construction.dm
index 2bae550a22..f148803322 100644
--- a/code/__defines/construction.dm
+++ b/code/__defines/construction.dm
@@ -38,6 +38,7 @@
#define CONNECT_TYPE_SUPPLY 2
#define CONNECT_TYPE_SCRUBBER 4
#define CONNECT_TYPE_HE 8
+#define CONNECT_TYPE_FUEL 16 // TODO - Implement this! Its piping so better ask Leshana
// We are based on the three named layers of supply, regular, and scrubber.
#define PIPING_LAYER_SUPPLY 1
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index d3222965a9..47226383ea 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -6,6 +6,7 @@
//---------------
#define isatom(D) istype(D, /atom)
+#define isclient(D) istype(D, /client)
//---------------
//#define isobj(D) istype(D, /obj) //Built in
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index 3676071d7c..f7c2457b98 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -11,6 +11,11 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
#define DOOR_CRUSH_DAMAGE 20
#define ALIEN_SELECT_AFK_BUFFER 1 // How many minutes that a person can be AFK before not being allowed to be an alien.
+// Constants for machine's use_power
+#define USE_POWER_OFF 0 // No continuous power use
+#define USE_POWER_IDLE 1 // Machine is using power at its idle power level
+#define USE_POWER_ACTIVE 2 // Machine is using power at its active power level
+
// Channel numbers for power.
#define EQUIP 1
#define LIGHT 2
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index ceaeda8c48..f526a10d59 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -80,7 +80,7 @@
#define COLOR_DARK_GRAY "#404040"
-
+#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (isclient(I) ? I : null))
// Shuttles.
@@ -106,6 +106,7 @@
#define FORCE_LAUNCH 2
#define WAIT_ARRIVE 3
#define WAIT_FINISH 4
+#define DO_AUTOPILOT 5
// Setting this much higher than 1024 could allow spammers to DOS the server easily.
#define MAX_MESSAGE_LEN 1024
@@ -269,6 +270,7 @@
#define WORLD_ICON_SIZE 32 //Needed for the R-UST port
#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 //Needed for the R-UST port
+#define MAX_CLIENT_VIEW 34 // Maximum effective value of client.view (According to DM references)
// Maploader bounds indices
#define MAP_MINX 1
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index cfbcfcd1dd..beeda302eb 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -396,7 +396,9 @@
#define VIS_BUILDMODE 22
-#define VIS_COUNT 22 //Must be highest number from above.
+#define VIS_CLOAKED 23
+
+#define VIS_COUNT 23 //Must be highest number from above.
//Some mob icon layering defines
#define BODY_LAYER -100
diff --git a/code/__defines/qdel.dm b/code/__defines/qdel.dm
index ab85326658..278a2064db 100644
--- a/code/__defines/qdel.dm
+++ b/code/__defines/qdel.dm
@@ -26,6 +26,7 @@
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME)
#define QDEL_NULL(item) qdel(item); item = null
+#define QDEL_NULL_LIST QDEL_LIST_NULL
#define QDEL_LIST_NULL(x) if(x) { for(var/y in x) { qdel(y) } ; x = null }
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE)
diff --git a/code/__defines/shuttle.dm b/code/__defines/shuttle.dm
new file mode 100644
index 0000000000..9bf7dcad6f
--- /dev/null
+++ b/code/__defines/shuttle.dm
@@ -0,0 +1,27 @@
+// Shuttle flags
+#define SHUTTLE_FLAGS_NONE 0
+#define SHUTTLE_FLAGS_PROCESS 1 // Should be processed by shuttle subsystem
+#define SHUTTLE_FLAGS_SUPPLY 2 // This is the supply shuttle. Why is this a tag?
+#define SHUTTLE_FLAGS_ZERO_G 4 // Shuttle has no internal gravity generation
+#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE)
+
+// shuttle_landmark flags
+#define SLANDMARK_FLAG_AUTOSET 1 // If set, will set base area and turf type to same as where it was spawned at
+#define SLANDMARK_FLAG_ZERO_G 2 // Zero-G shuttles moved here will lose gravity unless the area has ambient gravity.
+
+// Overmap landable shuttles (/obj/effect/overmap/visitable/ship/landable on a /datum/shuttle/autodock/overmap)
+#define SHIP_STATUS_LANDED 1 // Ship is at any other shuttle landmark.
+#define SHIP_STATUS_TRANSIT 2 // Ship is at it's shuttle datum's transition shuttle landmark.
+#define SHIP_STATUS_OVERMAP 3 // Ship is at its "overmap" shuttle landmark (allowed to move on overmap now)
+
+// Ferry shuttle location constants
+#define FERRY_LOCATION_STATION 0
+#define FERRY_LOCATION_OFFSITE 1
+#define FERRY_GOING_TO_STATION 0
+#define FERRY_GOING_TO_OFFSITE 1
+
+#ifndef DEBUG_SHUTTLES
+ #define log_shuttle(M)
+#else
+ #define log_shuttle(M) log_debug("[M]")
+#endif
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index ae7b77e214..1790890dfb 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -52,10 +52,11 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
-#define INIT_ORDER_SQLITE 19
-#define INIT_ORDER_CHEMISTRY 18
-#define INIT_ORDER_MAPPING 17
-#define INIT_ORDER_DECALS 16
+#define INIT_ORDER_SQLITE 40
+#define INIT_ORDER_CHEMISTRY 35
+#define INIT_ORDER_SKYBOX 30
+#define INIT_ORDER_MAPPING 25
+#define INIT_ORDER_DECALS 20
#define INIT_ORDER_ATOMS 15
#define INIT_ORDER_MACHINES 10
#define INIT_ORDER_SHUTTLES 3
@@ -63,22 +64,27 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_LIGHTING 0
#define INIT_ORDER_AIR -1
+#define INIT_ORDER_ASSETS -3
#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_HOLOMAPS -5
#define INIT_ORDER_OVERLAY -6
+#define INIT_ORDER_ALARM -7
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
#define INIT_ORDER_AI -22
#define INIT_ORDER_JOB -23
+#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
// 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_SHUTTLES 5
+#define FIRE_PRIORITY_SUPPLY 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
#define FIRE_PRIORITY_GARBAGE 15
+#define FIRE_PRIORITY_ALARM 20
#define FIRE_PRIORITY_CHARSETUP 25
#define FIRE_PRIORITY_AIRFLOW 30
#define FIRE_PRIORITY_AIR 35
@@ -88,6 +94,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_PLANETS 75
#define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_PROJECTILES 150
+#define FIRE_PRIORITY_CHAT 400
#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)
diff --git a/code/__defines/xenoarcheaology.dm b/code/__defines/xenoarcheaology.dm
index 8a4988b78c..e4b0a3935a 100644
--- a/code/__defines/xenoarcheaology.dm
+++ b/code/__defines/xenoarcheaology.dm
@@ -37,7 +37,11 @@
#define ARCHAEO_ALIEN_BOAT 37
#define ARCHAEO_IMPERION_CIRCUIT 38
#define ARCHAEO_TELECUBE 39
-#define MAX_ARCHAEO 39
+#define ARCHAEO_BATTERY 40
+#define ARCHAEO_SYRINGE 41
+#define ARCHAEO_RING 42
+#define ARCHAEO_CLUB 43
+#define MAX_ARCHAEO 43
#define DIGSITE_GARDEN 1
#define DIGSITE_ANIMAL 2
diff --git a/code/_global_vars/lists/species.dm b/code/_global_vars/lists/species.dm
index fec8e4a069..151512d570 100644
--- a/code/_global_vars/lists/species.dm
+++ b/code/_global_vars/lists/species.dm
@@ -1,6 +1,8 @@
//Languages/species/whitelist.
GLOBAL_LIST_INIT(all_species, list())
GLOBAL_LIST_INIT(all_languages, list())
+GLOBAL_LIST_INIT(language_name_conflicts, list())
GLOBAL_LIST_INIT(language_keys, list()) // Table of say codes for all languages
+GLOBAL_LIST_INIT(language_key_conflicts, list())
GLOBAL_LIST_INIT(whitelisted_species, list(SPECIES_HUMAN)) // Species that require a whitelist check.
GLOBAL_LIST_INIT(playable_species, list(SPECIES_HUMAN)) // A list of ALL playable species, whitelisted, latejoin or otherwise.
diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm
index 1eb39e30cd..8424299382 100644
--- a/code/_helpers/_lists.dm
+++ b/code/_helpers/_lists.dm
@@ -53,7 +53,7 @@
// atoms/items/objects can be pretty and whatnot
var/atom/A = item
if(output_icons && isicon(A.icon) && !ismob(A)) // mobs tend to have unusable icons
- item_str += "\icon[A] "
+ item_str += "[bicon(A)] "
switch(determiners)
if(DET_NONE) item_str += A.name
if(DET_DEFINITE) item_str += "\the [A]"
@@ -206,6 +206,20 @@ proc/listclearnulls(list/list)
result = first - second
return result
+/*
+Two lists may be different (A!=B) even if they have the same elements.
+This actually tests if they have the same entries and values.
+*/
+/proc/same_entries(var/list/first, var/list/second)
+ if(!islist(first) || !islist(second))
+ return 0
+ if(length(first) != length(second))
+ return 0
+ for(var/entry in first)
+ if(!(entry in second) || (first[entry] != second[entry]))
+ return 0
+ return 1
+
/*
* Returns list containing entries that are in either list but not both.
* If skipref = 1, repeated elements are treated as one.
@@ -308,6 +322,13 @@ proc/listclearnulls(list/list)
else
L[key] = temp[key]
+// Return a list of the values in an assoc list (including null)
+/proc/list_values(var/list/L)
+ var/list/V = list()
+ V.len = L.len // Preallocate!
+ for(var/i in 1 to L.len)
+ V[i] = L[L[i]] // We avoid += in case the value is itself a list
+ return V
//Mergesort: divides up the list into halves to begin the sort
/proc/sortKey(var/list/client/L, var/order = 1)
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 5c7a56c976..50cf502639 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -153,17 +153,30 @@ var/global/list/string_slot_flags = list(
var/datum/job/J = new T
joblist[J.title] = J
- //Languages and species.
+ //Languages
paths = typesof(/datum/language)-/datum/language
for(var/T in paths)
var/datum/language/L = new T
- GLOB.all_languages[L.name] = L
+ if (isnull(GLOB.all_languages[L.name]))
+ GLOB.all_languages[L.name] = L
+ else
+ log_debug("Language name conflict! [T] is named [L.name], but that is taken by [GLOB.all_languages[L.name].type]")
+ if(isnull(GLOB.language_name_conflicts[L.name]))
+ GLOB.language_name_conflicts[L.name] = list(GLOB.all_languages[L.name])
+ GLOB.language_name_conflicts[L.name] += L
for (var/language_name in GLOB.all_languages)
var/datum/language/L = GLOB.all_languages[language_name]
if(!(L.flags & NONGLOBAL))
- GLOB.language_keys[lowertext(L.key)] = L
+ if(isnull(GLOB.language_keys[L.key]))
+ GLOB.language_keys[L.key] = L
+ else
+ log_debug("Language key conflict! [L] has key [L.key], but that is taken by [(GLOB.language_keys[L.key])]")
+ if(isnull(GLOB.language_key_conflicts[L.key]))
+ GLOB.language_key_conflicts[L.key] = list(GLOB.language_keys[L.key])
+ GLOB.language_key_conflicts[L.key] += L
+ //Species
var/rkey = 0
paths = typesof(/datum/species)
for(var/T in paths)
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index 9a36f2dfbc..9818dd4258 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -167,7 +167,7 @@ mob
Output_Icon()
set name = "2. Output Icon"
- to_chat(src, "Icon is: \icon[getFlatIcon(src)]")
+ to_chat(src, "Icon is: [bicon(getFlatIcon(src))]")
Label_Icon()
set name = "3. Label Icon"
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 688e1c2a68..67844cf4a2 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -301,11 +301,15 @@ proc/TextPreview(var/string,var/len=40)
//For generating neat chat tag-images
//The icon var could be local in the proc, but it's a waste of resources
// to always create it and then throw it out.
-/var/icon/text_tag_icons = new('./icons/chattags.dmi')
+/var/icon/text_tag_icons = 'icons/chattags.dmi'
+/var/list/text_tag_cache = list()
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
return tagdesc
- return ""
+ if(!text_tag_cache[tagname])
+ var/icon/tag = icon(text_tag_icons, tagname)
+ text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
+ return text_tag_cache[tagname]
/proc/contains_az09(var/input)
for(var/i=1, i<=length(input), i++)
diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm
index 1926246856..e8ca671c11 100644
--- a/code/_helpers/turfs.dm
+++ b/code/_helpers/turfs.dm
@@ -38,4 +38,120 @@
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE)
return TRUE
- return FALSE
\ No newline at end of file
+ return FALSE
+
+/*
+ Turf manipulation
+*/
+
+//Returns an assoc list that describes how turfs would be changed if the
+//turfs in turfs_src were translated by shifting the src_origin to the dst_origin
+/proc/get_turf_translation(turf/src_origin, turf/dst_origin, list/turfs_src)
+ var/list/turf_map = list()
+ for(var/turf/source in turfs_src)
+ var/x_pos = (source.x - src_origin.x)
+ var/y_pos = (source.y - src_origin.y)
+ var/z_pos = (source.z - src_origin.z)
+
+ var/turf/target = locate(dst_origin.x + x_pos, dst_origin.y + y_pos, dst_origin.z + z_pos)
+ if(!target)
+ error("Null turf in translation @ ([dst_origin.x + x_pos], [dst_origin.y + y_pos], [dst_origin.z + z_pos])")
+ turf_map[source] = target //if target is null, preserve that information in the turf map
+
+ return turf_map
+
+/proc/translate_turfs(var/list/translation, var/area/base_area = null, var/turf/base_turf)
+ for(var/turf/source in translation)
+
+ var/turf/target = translation[source]
+
+ if(target)
+ if(base_area) ChangeArea(target, get_area(source))
+ var/leave_turf = base_turf ? base_turf : get_base_turf_by_area(base_area ? base_area : source)
+ translate_turf(source, target, leave_turf)
+ if(base_area) ChangeArea(source, base_area)
+
+ //change the old turfs (Currently done by translate_turf for us)
+ //for(var/turf/source in translation)
+ // source.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(source), 1, 1)
+
+// Parmaters for stupid historical reasons are:
+// T - Origin
+// B - Destination
+/proc/translate_turf(var/turf/T, var/turf/B, var/turftoleave = null)
+
+ //You can stay, though.
+ if(istype(T,/turf/space))
+ error("Tried to translate a space turf: src=[log_info_line(T)] dst=[log_info_line(B)]")
+ return FALSE // TODO - Is this really okay to do nothing?
+
+ var/turf/X //New Destination Turf
+
+ //Are we doing shuttlework? Just to save another type check later.
+ var/shuttlework = 0
+
+ //Shuttle turfs handle their own fancy moving.
+ if(istype(T,/turf/simulated/shuttle))
+ shuttlework = 1
+ var/turf/simulated/shuttle/SS = T
+ if(!SS.landed_holder) SS.landed_holder = new(turf = SS)
+ X = SS.landed_holder.land_on(B)
+
+ //Generic non-shuttle turf move.
+ else
+ var/old_dir1 = T.dir
+ var/old_icon_state1 = T.icon_state
+ var/old_icon1 = T.icon
+ var/old_underlays = T.underlays.Copy()
+ var/old_decals = T.decals ? T.decals.Copy() : null
+
+ X = B.ChangeTurf(T.type)
+ X.set_dir(old_dir1)
+ X.icon_state = old_icon_state1
+ X.icon = old_icon1
+ X.copy_overlays(T, TRUE)
+ X.underlays = old_underlays
+ X.decals = old_decals
+
+ //Move the air from source to dest
+ var/turf/simulated/ST = T
+ if(istype(ST) && ST.zone)
+ var/turf/simulated/SX = X
+ if(!SX.air)
+ SX.make_air()
+ SX.air.copy_from(ST.zone.air)
+ ST.zone.remove(ST)
+
+ var/z_level_change = FALSE
+ if(T.z != X.z)
+ z_level_change = TRUE
+
+ //Move the objects. Not forceMove because the object isn't "moving" really, it's supposed to be on the "same" turf.
+ for(var/obj/O in T)
+ if(O.simulated)
+ O.loc = X
+ O.update_light()
+ if(z_level_change) // The objects still need to know if their z-level changed.
+ O.onTransitZ(T.z, X.z)
+
+ //Move the mobs unless it's an AI eye or other eye type.
+ for(var/mob/M in T)
+ if(isEye(M)) continue // If we need to check for more mobs, I'll add a variable
+ M.loc = X
+
+ if(z_level_change) // Same goes for mobs.
+ M.onTransitZ(T.z, X.z)
+
+ if(istype(M, /mob/living))
+ var/mob/living/LM = M
+ LM.check_shadow() // Need to check their Z-shadow, which is normally done in forceMove().
+
+ if(shuttlework)
+ var/turf/simulated/shuttle/SS = T
+ SS.landed_holder.leave_turf(turftoleave)
+ else if(turftoleave)
+ T.ChangeTurf(turftoleave)
+ else
+ T.ChangeTurf(get_base_turf_by_area(T))
+
+ return TRUE
diff --git a/code/_macros.dm b/code/_macros.dm
index fad5920eb9..5b7fb379d3 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -2,9 +2,16 @@
#define get_turf(A) get_step(A,0)
+#define get_x(A) (get_step(A, 0)?.x || 0)
+
+#define get_y(A) (get_step(A, 0)?.y || 0)
+
+#define get_z(A) (get_step(A, 0)?.z || 0)
+
#define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
-#define to_chat(target, message) target << message
+// #define to_chat(target, message) target << message Not anymore!
+#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
#define to_world(message) to_chat(world, message)
#define to_world_log(message) world.log << message
// TODO - Baystation has this log to crazy places. For now lets just world.log, but maybe look into it later.
@@ -26,6 +33,8 @@
#define qdel_null(x) if(x) { qdel(x) ; x = null }
+#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
+
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 46e3349615..f9e8506108 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -276,12 +276,12 @@
tankcheck = list(C.r_hand, C.l_hand, C.back)
// 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 && !rig.offline)
+ var/obj/item/weapon/rig/Rig = C.get_rig()
+ if(Rig)
+ if(Rig.air_supply && !Rig.offline)
from = "in"
nicename |= "hardsuit"
- tankcheck |= rig.air_supply
+ tankcheck |= Rig.air_supply
for(var/i=1, i")
+ message = replacetext(message, "\improper", "")
+ message = replacetext(message, "\proper", "")
+
+ if(isnull(time))
+ time = world.time
+
+ var/list/messageStruct = list("time" = time, "message" = message);
+
+ if(islist(target))
+ for(var/I in target)
+ var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
+
+ if(!C)
+ return
+
+ if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
+ //Send it to the old style output window.
+ DIRECT_OUTPUT(C, original_message)
+ continue
+
+ // // Client still loading, put their messages in a queue - Actually don't, logged already in database.
+ // if(!C.chatOutput.loaded && C.chatOutput.message_queue && islist(C.chatOutput.message_queue))
+ // C.chatOutput.message_queue[++C.chatOutput.message_queue.len] = messageStruct
+ // continue
+
+ LAZYINITLIST(msg_queue[C])
+ msg_queue[C][++msg_queue[C].len] = messageStruct
+ else
+ var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
+
+ if(!C)
+ return
+
+ if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
+ DIRECT_OUTPUT(C, original_message)
+ return
+
+ // // Client still loading, put their messages in a queue - Actually don't, logged already in database.
+ // if(!C.chatOutput.loaded && C.chatOutput.message_queue && islist(C.chatOutput.message_queue))
+ // C.chatOutput.message_queue[++C.chatOutput.message_queue.len] = messageStruct
+ // return
+
+ LAZYINITLIST(msg_queue[C])
+ msg_queue[C][++msg_queue[C].len] = messageStruct
diff --git a/code/controllers/subsystems/inactivity.dm b/code/controllers/subsystems/inactivity.dm
index 6b74a6b553..2dbc642720 100644
--- a/code/controllers/subsystems/inactivity.dm
+++ b/code/controllers/subsystems/inactivity.dm
@@ -15,8 +15,7 @@ SUBSYSTEM_DEF(inactivity)
while(client_list.len)
var/client/C = client_list[client_list.len]
client_list.len--
- if(!C.holder && C.is_afk(config.kick_inactive MINUTES) && !isobserver(C.mob))
-
+ if(C.is_afk(config.kick_inactive MINUTES) && can_kick(C))
to_chat(C, "You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.")
var/information
@@ -34,6 +33,9 @@ SUBSYSTEM_DEF(inactivity)
if(job)
information = " while [job]."
+ else if(isobserver(C.mob))
+ information = " while a ghost."
+
else if(issilicon(C.mob))
information = " while a silicon."
if(isAI(C.mob))
@@ -55,4 +57,7 @@ SUBSYSTEM_DEF(inactivity)
return
/datum/controller/subsystem/inactivity/stat_entry()
- ..("Kicked: [number_kicked]")
\ No newline at end of file
+ ..("Kicked: [number_kicked]")
+
+/datum/controller/subsystem/inactivity/proc/can_kick(var/client/C)
+ return TRUE
diff --git a/code/controllers/subsystems/nanoui.dm b/code/controllers/subsystems/nanoui.dm
index e622fce8f2..c916eb2739 100644
--- a/code/controllers/subsystems/nanoui.dm
+++ b/code/controllers/subsystems/nanoui.dm
@@ -1,41 +1,17 @@
SUBSYSTEM_DEF(nanoui)
name = "NanoUI"
wait = 5
+ flags = SS_NO_INIT
// a list of current open /nanoui UIs, grouped by src_object and ui_key
var/list/open_uis = list()
// a list of current open /nanoui UIs, not grouped, for use in processing
var/list/processing_uis = list()
- // a list of asset filenames which are to be sent to the client on user logon
- var/list/asset_files = list()
-
-/datum/controller/subsystem/nanoui/Initialize()
- var/list/nano_asset_dirs = list(\
- "nano/css/",\
- "nano/images/",\
- "nano/images/status_icons/",\
- "nano/images/modular_computers/",\
- "nano/js/",\
- "nano/templates/"\
- )
-
- var/list/filenames = null
- for (var/path in nano_asset_dirs)
- filenames = flist(path)
- for(var/filename in filenames)
- if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
- if(fexists(path + filename))
- asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
- .=..()
- for(var/i in GLOB.clients)
- send_resources(i)
/datum/controller/subsystem/nanoui/Recover()
if(SSnanoui.open_uis)
open_uis |= SSnanoui.open_uis
if(SSnanoui.processing_uis)
processing_uis |= SSnanoui.processing_uis
- if(SSnanoui.asset_files)
- asset_files |= SSnanoui.asset_files
/datum/controller/subsystem/nanoui/stat_entry()
return ..("[processing_uis.len] UIs")
@@ -44,10 +20,3 @@ SUBSYSTEM_DEF(nanoui)
for(var/thing in processing_uis)
var/datum/nanoui/UI = thing
UI.process()
-
-//Sends asset files to a client, called on client/New()
-/datum/controller/subsystem/nanoui/proc/send_resources(client)
- if(!subsystem_initialized)
- return
- for(var/file in asset_files)
- client << browse_rsc(file) // send the file to the client
\ No newline at end of file
diff --git a/code/controllers/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm
index 61a4590890..27bbbae027 100644
--- a/code/controllers/subsystems/shuttles.dm
+++ b/code/controllers/subsystems/shuttles.dm
@@ -1,6 +1,8 @@
//
// SSshuttles subsystem - Handles initialization and processing of shuttles.
//
+// Also handles initialization and processing of overmap sectors.
+//
// This global variable exists for legacy support so we don't have to rename every shuttle_controller to SSshuttles yet.
var/global/datum/controller/subsystem/shuttles/shuttle_controller
@@ -13,71 +15,164 @@ SUBSYSTEM_DEF(shuttles)
flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
- var/list/shuttles = list() // Maps shuttle tags to shuttle datums, so that they can be looked up.
- var/list/process_shuttles = list() // Simple list of shuttles, for processing
- var/list/current_run = list() // Shuttles remaining to process this fire() tick
- var/list/docks_init_callbacks // List of callbacks to run when we finish setting up shuttle docks.
- var/docks_initialized = FALSE
+ var/overmap_halted = FALSE // Whether ships can move on the overmap; used for adminbus.
+ var/list/ships = list() // List of all ships.
+
+ var/list/shuttles = list() // Maps shuttle tags to shuttle datums, so that they can be looked up.
+ var/list/process_shuttles = list() // Simple list of shuttles, for processing
+
+ var/list/registered_shuttle_landmarks = list() // Maps shuttle landmark tags to instances
+ var/last_landmark_registration_time // world.time of most recent addition to registered_shuttle_landmarks
+ var/list/shuttle_logs = list() // (Not Implemented) Keeps records of shuttle movement, format is list(datum/shuttle = datum/shuttle_log)
+ var/list/shuttle_areas = list() // All the areas of all shuttles.
+ var/list/docking_registry = list() // Docking controller tag -> docking controller program, mostly for init purposes.
+
+ var/list/landmarks_awaiting_sector = list() // Stores automatic landmarks that are waiting for a sector to finish loading.
+ var/list/landmarks_still_needed = list() // Stores landmark_tags that need to be assigned to the sector (landmark_tag = sector) when registered.
+ var/list/shuttles_to_initialize // A queue for shuttles to initialize at the appropriate time.
+ var/list/sectors_to_initialize // Used to find all sector objects at the appropriate time.
+ var/block_init_queue = TRUE // Block initialization of new shuttles/sectors
+
+ var/tmp/list/current_run // Shuttles remaining to process this fire() tick
+
+/datum/controller/subsystem/shuttles/PreInit()
+ global.shuttle_controller = src // TODO - Remove this! Change everything to point at SSshuttles intead
/datum/controller/subsystem/shuttles/Initialize(timeofday)
- global.shuttle_controller = src
- setup_shuttle_docks()
- for(var/I in docks_init_callbacks)
- var/datum/callback/cb = I
- cb.InvokeAsync()
- LAZYCLEARLIST(docks_init_callbacks)
- docks_init_callbacks = null
+ last_landmark_registration_time = world.time
+ // Find all declared shuttle datums and initailize them. (Okay, queue them for initialization a few lines further down)
+ for(var/shuttle_type in subtypesof(/datum/shuttle)) // This accounts for most shuttles, though away maps can queue up more.
+ var/datum/shuttle/shuttle = shuttle_type
+ if(initial(shuttle.category) == shuttle_type)
+ continue // Its an "abstract class" datum, not for a real shuttle.
+ if(!initial(shuttle.defer_initialisation)) // Skip if it asks not to be initialized at startup.
+ LAZYDISTINCTADD(shuttles_to_initialize, shuttle_type)
+ block_init_queue = FALSE
+ process_init_queues()
return ..()
/datum/controller/subsystem/shuttles/fire(resumed = 0)
- do_process_shuttles(resumed)
-
-/datum/controller/subsystem/shuttles/stat_entry()
- var/msg = list()
- msg += "AS:[shuttles.len]|"
- msg += "PS:[process_shuttles.len]|"
- ..(jointext(msg, null))
-
-/datum/controller/subsystem/shuttles/proc/do_process_shuttles(resumed = 0)
if (!resumed)
src.current_run = process_shuttles.Copy()
- var/list/current_run = src.current_run // Cache for sanic speed
- while(current_run.len)
- var/datum/shuttle/S = current_run[current_run.len]
- current_run.len--
- if(istype(S) && !QDELETED(S))
- if(istype(S, /datum/shuttle/ferry)) // Ferry shuttles get special treatment
- var/datum/shuttle/ferry/F = S
- if(F.process_state || F.always_process)
- F.process()
- else
- S.process()
- else
+ var/list/working_shuttles = src.current_run // Cache for sanic speed
+ while(working_shuttles.len)
+ var/datum/shuttle/S = working_shuttles[working_shuttles.len]
+ working_shuttles.len--
+ if(!istype(S) || QDELETED(S))
+ error("Bad entry in SSshuttles.process_shuttles - [log_info_line(S)] ")
process_shuttles -= S
+ continue
+ // NOTE - In old system, /datum/shuttle/ferry was processed only if (F.process_state || F.always_process)
+ if(S.process_state && (S.process(wait, times_fired, src) == PROCESS_KILL))
+ process_shuttles -= S
+
if(MC_TICK_CHECK)
return
-// This should be called after all the machines and radio frequencies have been properly initialized
-/datum/controller/subsystem/shuttles/proc/setup_shuttle_docks()
- // Find all declared shuttle datums and initailize them.
- for(var/shuttle_type in subtypesof(/datum/shuttle))
- var/datum/shuttle/shuttle = shuttle_type
- if(initial(shuttle.category) == shuttle_type)
- continue
+/datum/controller/subsystem/shuttles/proc/process_init_queues()
+ if(block_init_queue)
+ return
+ initialize_shuttles()
+ initialize_sectors()
+
+// Initializes all shuttles in shuttles_to_initialize
+/datum/controller/subsystem/shuttles/proc/initialize_shuttles()
+ var/list/shuttles_made = list()
+ for(var/shuttle_type in shuttles_to_initialize)
+ var/shuttle = initialize_shuttle(shuttle_type)
+ if(shuttle)
+ shuttles_made += shuttle
+ hook_up_motherships(shuttles_made)
+ shuttles_to_initialize = null
+
+/datum/controller/subsystem/shuttles/proc/initialize_sectors()
+ for(var/sector in sectors_to_initialize)
+ initialize_sector(sector)
+ sectors_to_initialize = null
+
+/datum/controller/subsystem/shuttles/proc/register_landmark(shuttle_landmark_tag, obj/effect/shuttle_landmark/shuttle_landmark)
+ if (registered_shuttle_landmarks[shuttle_landmark_tag])
+ CRASH("Attempted to register shuttle landmark with tag [shuttle_landmark_tag], but it is already registered!")
+ if (istype(shuttle_landmark))
+ registered_shuttle_landmarks[shuttle_landmark_tag] = shuttle_landmark
+ last_landmark_registration_time = world.time
+
+ var/obj/effect/overmap/visitable/O = landmarks_still_needed[shuttle_landmark_tag]
+ if(O) //These need to be added to sectors, which we handle.
+ try_add_landmark_tag(shuttle_landmark_tag, O)
+ landmarks_still_needed -= shuttle_landmark_tag
+ else if(istype(shuttle_landmark, /obj/effect/shuttle_landmark/automatic)) //These find their sector automatically
+ O = map_sectors["[shuttle_landmark.z]"]
+ O ? O.add_landmark(shuttle_landmark, shuttle_landmark.shuttle_restricted) : (landmarks_awaiting_sector += shuttle_landmark)
+
+/datum/controller/subsystem/shuttles/proc/get_landmark(var/shuttle_landmark_tag)
+ return registered_shuttle_landmarks[shuttle_landmark_tag]
+
+//Checks if the given sector's landmarks have initialized; if so, registers them with the sector, if not, marks them for assignment after they come in.
+//Also adds automatic landmarks that were waiting on their sector to spawn.
+/datum/controller/subsystem/shuttles/proc/initialize_sector(obj/effect/overmap/visitable/given_sector)
+ given_sector.populate_sector_objects() // This is a late init operation that sets up the sector's map_z and does non-overmap-related init tasks.
+
+ for(var/landmark_tag in given_sector.initial_generic_waypoints)
+ if(!try_add_landmark_tag(landmark_tag, given_sector))
+ landmarks_still_needed[landmark_tag] = given_sector // Landmark isn't registered yet, queue it to be added once it is.
+
+ for(var/shuttle_name in given_sector.initial_restricted_waypoints)
+ for(var/landmark_tag in given_sector.initial_restricted_waypoints[shuttle_name])
+ if(!try_add_landmark_tag(landmark_tag, given_sector))
+ landmarks_still_needed[landmark_tag] = given_sector // Landmark isn't registered yet, queue it to be added once it is.
+
+ var/landmarks_to_check = landmarks_awaiting_sector.Copy()
+ for(var/thing in landmarks_to_check)
+ var/obj/effect/shuttle_landmark/automatic/landmark = thing
+ if(landmark.z in given_sector.map_z)
+ given_sector.add_landmark(landmark, landmark.shuttle_restricted)
+ landmarks_awaiting_sector -= landmark
+
+// Attempts to add a landmark instance with a sector (returns false if landmark isn't registered yet)
+/datum/controller/subsystem/shuttles/proc/try_add_landmark_tag(landmark_tag, obj/effect/overmap/visitable/given_sector)
+ var/obj/effect/shuttle_landmark/landmark = get_landmark(landmark_tag)
+ if(!landmark)
+ return
+
+ if(landmark.landmark_tag in given_sector.initial_generic_waypoints)
+ given_sector.add_landmark(landmark)
+ . = 1
+ for(var/shuttle_name in given_sector.initial_restricted_waypoints)
+ if(landmark.landmark_tag in given_sector.initial_restricted_waypoints[shuttle_name])
+ given_sector.add_landmark(landmark, shuttle_name)
+ . = 1
+
+/datum/controller/subsystem/shuttles/proc/initialize_shuttle(var/shuttle_type)
+ var/datum/shuttle/shuttle = shuttle_type
+ if(initial(shuttle.category) != shuttle_type) // Skip if its an "abstract class" datum
shuttle = new shuttle()
- shuttle.init_docking_controllers()
- shuttle.dock() //makes all shuttles docked to something at round start go into the docked state
- CHECK_TICK
+ shuttle_areas |= shuttle.shuttle_area
+ log_debug("Initialized shuttle [shuttle] ([shuttle.type])")
+ return shuttle
+ // Historical note: No need to call shuttle.init_docking_controllers(), controllers register themselves
+ // and shuttles fetch refs in New(). Shuttles also dock() themselves in new if they want.
- for(var/obj/machinery/embedded_controller/C in machines)
- if(istype(C.program, /datum/computer/file/embedded_program/docking))
- C.program.tag = null //clear the tags, 'cause we don't need 'em anymore
- docks_initialized = TRUE
+// TODO - Leshana to hook up more of this when overmap is ported.
+/datum/controller/subsystem/shuttles/proc/hook_up_motherships(shuttles_list)
+ for(var/datum/shuttle/S in shuttles_list)
+ if(S.mothershuttle && !S.motherdock)
+ var/datum/shuttle/mothership = shuttles[S.mothershuttle]
+ if(mothership)
+ S.motherdock = S.current_location.landmark_tag
+ mothership.shuttle_area |= S.shuttle_area
+ else
+ error("Shuttle [S] was unable to find mothership [mothership]!")
-// Register a callback that will be invoked once the shuttles have been initialized
-/datum/controller/subsystem/shuttles/proc/OnDocksInitialized(datum/callback/cb)
- if(!docks_initialized)
- LAZYADD(docks_init_callbacks, cb)
- else
- cb.InvokeAsync()
+// Admin command to halt/resume overmap
+/datum/controller/subsystem/shuttles/proc/toggle_overmap(new_setting)
+ if(overmap_halted == new_setting)
+ return
+ overmap_halted = !overmap_halted
+ for(var/ship in ships)
+ var/obj/effect/overmap/visitable/ship/ship_effect = ship
+ overmap_halted ? ship_effect.halt() : ship_effect.unhalt()
+
+/datum/controller/subsystem/shuttles/stat_entry()
+ ..("Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
diff --git a/code/controllers/subsystems/skybox.dm b/code/controllers/subsystems/skybox.dm
new file mode 100644
index 0000000000..ccf4427d99
--- /dev/null
+++ b/code/controllers/subsystems/skybox.dm
@@ -0,0 +1,82 @@
+
+//Exists to handle a few global variables that change enough to justify this. Technically a parallax, but it exhibits a skybox effect.
+SUBSYSTEM_DEF(skybox)
+ name = "Space skybox"
+ init_order = INIT_ORDER_SKYBOX
+ flags = SS_NO_FIRE
+ var/list/skybox_cache = list()
+
+/datum/controller/subsystem/skybox/Initialize()
+ . = ..()
+
+/datum/controller/subsystem/skybox/Recover()
+ skybox_cache = SSskybox.skybox_cache
+
+/datum/controller/subsystem/skybox/proc/get_skybox(z)
+ if(!skybox_cache["[z]"])
+ skybox_cache["[z]"] = generate_skybox(z)
+ if(global.using_map.use_overmap)
+ var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
+ if(istype(O))
+ for(var/zlevel in O.map_z)
+ skybox_cache["[zlevel]"] = skybox_cache["[z]"]
+ return skybox_cache["[z]"]
+
+/datum/controller/subsystem/skybox/proc/generate_skybox(z)
+ var/datum/skybox_settings/settings = global.using_map.get_skybox_datum(z)
+
+ var/image/res = image(settings.icon)
+ res.appearance_flags = KEEP_TOGETHER
+
+ var/image/base = image(settings.icon, settings.icon_state)
+ base.color = settings.color
+
+ if(settings.use_stars)
+ var/image/stars = image(settings.icon, settings.star_state)
+ stars.appearance_flags = RESET_COLOR
+ base.overlays += stars
+
+ res.overlays += base
+
+ if(global.using_map.use_overmap && settings.use_overmap_details)
+ var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
+ if(istype(O))
+ var/image/overmap = image(settings.icon)
+ overmap.overlays += O.generate_skybox()
+ for(var/obj/effect/overmap/visitable/other in O.loc)
+ if(other != O)
+ overmap.overlays += other.get_skybox_representation()
+ overmap.appearance_flags = RESET_COLOR
+ res.overlays += overmap
+
+ // TODO - Allow events to apply custom overlays to skybox! (Awesome!)
+ //for(var/datum/event/E in SSevent.active_events)
+ // if(E.has_skybox_image && E.isRunning && (z in E.affecting_z))
+ // res.overlays += E.get_skybox_image()
+
+ return res
+
+/datum/controller/subsystem/skybox/proc/rebuild_skyboxes(var/list/zlevels)
+ for(var/z in zlevels)
+ skybox_cache["[z]"] = generate_skybox(z)
+
+ for(var/client/C)
+ C.update_skybox(1)
+
+// Settings datum that maps can override to play with their skyboxes
+/datum/skybox_settings
+ var/icon = 'icons/skybox/skybox.dmi' //Path to our background. Lets us use anything we damn well please. Skyboxes need to be 736x736
+ var/icon_state = "dyable"
+ var/color
+ var/random_color = FALSE
+
+ var/use_stars = TRUE
+ var/star_icon = 'icons/skybox/skybox.dmi'
+ var/star_state = "stars"
+
+ var/use_overmap_details = TRUE //Do we try to draw overmap visitables in our sector on the map?
+
+/datum/skybox_settings/New()
+ ..()
+ if(random_color)
+ color = rgb(rand(0,255), rand(0,255), rand(0,255))
diff --git a/code/controllers/Processes/supply.dm b/code/controllers/subsystems/supply.dm
similarity index 68%
rename from code/controllers/Processes/supply.dm
rename to code/controllers/subsystems/supply.dm
index c31452521a..1c848cff96 100644
--- a/code/controllers/Processes/supply.dm
+++ b/code/controllers/subsystems/supply.dm
@@ -1,36 +1,15 @@
-//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
-
//Supply packs are in /code/datums/supplypacks
//Computers are in /code/game/machinery/computer/supply.dm
+SUBSYSTEM_DEF(supply)
+ name = "Supply"
+ wait = 20 SECONDS
+ priority = FIRE_PRIORITY_SUPPLY
+ //Initializes at default time
+ flags = SS_NO_TICK_CHECK
-/datum/supply_order
- var/ordernum // Unfabricatable index
- var/index // Fabricatable index
- var/datum/supply_pack/object = null
- var/cost // Cost of the supply pack (Fabricatable) (Changes not reflected when purchasing supply packs, this is cosmetic only)
- var/name // Name of the supply pack datum (Fabricatable)
- var/ordered_by = null // Who requested the order
- var/comment = null // What reason was given for the order
- var/approved_by = null // Who approved the order
- var/ordered_at // Date and time the order was requested at
- var/approved_at // Date and time the order was approved at
- var/status // [Requested, Accepted, Denied, Shipped]
-
-/datum/exported_crate
- var/name
- var/value
- var/list/contents
-
-var/datum/controller/supply/supply_controller = new()
-
-/datum/controller/supply
//supply points
var/points = 50
- var/points_per_process = 1.5
+ var/points_per_process = 1.0 // Processes every 20 seconds, so this is 3 per minute
var/points_per_slip = 2
var/points_per_money = 0.02 // 1 point for $50
//control
@@ -43,16 +22,16 @@ var/datum/controller/supply/supply_controller = new()
var/list/adm_export_history = list() // Complete history of all crates sent back on the shuttle, for admin use
//shuttle movement
var/movetime = 1200
- var/datum/shuttle/ferry/supply/shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle
var/list/material_points_conversion = list( // Any materials not named in this list are worth 0 points
"phoron" = 5,
"platinum" = 5
)
-
-/datum/controller/supply/New()
+/datum/controller/subsystem/supply/Initialize()
ordernum = rand(1,9000)
+ // build master supply list
for(var/typepath in subtypesof(/datum/supply_pack))
var/datum/supply_pack/P = new typepath()
if(P.name)
@@ -60,20 +39,18 @@ var/datum/controller/supply/supply_controller = new()
else
qdel(P)
-/datum/controller/process/supply/setup()
- name = "supply controller"
- schedule_interval = 300 // every 30 seconds
+ // TODO - Auto-build material_points_conversion from material datums
+ . = ..()
-/datum/controller/process/supply/doWork()
- supply_controller.process()
-
-// Supply shuttle ticker - handles supply point regeneration
-// This is called by the process scheduler every thirty seconds
-/datum/controller/supply/process()
+// Supply shuttle ticker - handles supply point regeneration. Just add points over time.
+/datum/controller/subsystem/supply/fire()
points += points_per_process
+/datum/controller/subsystem/supply/stat_entry()
+ ..("Points: [points]")
+
//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)
+/datum/controller/subsystem/supply/proc/forbidden_atoms_check(atom/A)
if(isliving(A))
return 1
if(istype(A,/obj/item/weapon/disk/nuclear))
@@ -88,88 +65,102 @@ var/datum/controller/supply/supply_controller = new()
return 1
//Selling
-/datum/controller/supply/proc/sell()
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle)
- return
+/datum/controller/subsystem/supply/proc/sell()
+ // Loop over each area in the supply shuttle
+ for(var/area/subarea in shuttle.shuttle_area)
+ callHook("sell_shuttle", list(subarea));
+ for(var/atom/movable/MA in subarea)
+ if(MA.anchored)
+ continue
- callHook("sell_shuttle", list(area_shuttle));
+ var/datum/exported_crate/EC = new /datum/exported_crate()
+ EC.name = "\proper[MA.name]"
+ EC.value = 0
+ EC.contents = list()
+ var/base_value = 0
- for(var/atom/movable/MA in area_shuttle)
- if(MA.anchored)
- continue
+ // Must be in a crate!
+ if(istype(MA,/obj/structure/closet/crate))
+ var/obj/structure/closet/crate/CR = MA
+ callHook("sell_crate", list(CR, subarea))
- var/datum/exported_crate/EC = new /datum/exported_crate()
- EC.name = "\proper[MA.name]"
- EC.value = 0
- EC.contents = list()
- var/base_value = 0
+ points += CR.points_per_crate
+ if(CR.points_per_crate)
+ base_value = CR.points_per_crate
+ var/find_slip = 1
- // 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/A in CR)
+ EC.contents[++EC.contents.len] = list(
+ "object" = "\proper[A.name]",
+ "value" = 0,
+ "quantity" = 1
+ )
- points += CR.points_per_crate
- if(CR.points_per_crate)
- base_value = CR.points_per_crate
- var/find_slip = 1
+ // Sell manifests
+ 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
+ EC.contents[EC.contents.len]["value"] = points_per_slip
+ find_slip = 0
+ continue
- for(var/atom/A in CR)
- EC.contents[++EC.contents.len] = list(
- "object" = "\proper[A.name]",
- "value" = 0,
- "quantity" = 1
+ // Sell phoron and platinum
+ if(istype(A, /obj/item/stack))
+ var/obj/item/stack/P = A
+ if(material_points_conversion[P.get_material_name()])
+ EC.contents[EC.contents.len]["value"] = P.get_amount() * material_points_conversion[P.get_material_name()]
+ EC.contents[EC.contents.len]["quantity"] = P.get_amount()
+ EC.value += EC.contents[EC.contents.len]["value"]
+
+ //Sell spacebucks
+ if(istype(A, /obj/item/weapon/spacecash))
+ var/obj/item/weapon/spacecash/cashmoney = A
+ EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money
+ EC.contents[EC.contents.len]["quantity"] = cashmoney.worth
+ EC.value += EC.contents[EC.contents.len]["value"]
+
+
+
+ // Make a log of it, but it wasn't shipped properly, and so isn't worth anything
+ else
+ EC.contents = list(
+ "error" = "Error: Product was improperly packaged. Payment rendered null under terms of agreement."
)
- // Sell manifests
- 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
- EC.contents[EC.contents.len]["value"] = points_per_slip
- find_slip = 0
+ exported_crates += EC
+ points += EC.value
+ EC.value += base_value
+
+ // Duplicate the receipt for the admin-side log
+ var/datum/exported_crate/adm = new()
+ adm.name = EC.name
+ adm.value = EC.value
+ adm.contents = deepCopyList(EC.contents)
+ adm_export_history += adm
+
+ qdel(MA)
+
+/datum/controller/subsystem/supply/proc/get_clear_turfs()
+ var/list/clear_turfs = list()
+
+ for(var/area/subarea in shuttle.shuttle_area)
+ for(var/turf/T in subarea)
+ if(T.density)
+ continue
+ var/occupied = 0
+ for(var/atom/A in T.contents)
+ if(!A.simulated)
continue
+ occupied = 1
+ break
+ if(!occupied)
+ clear_turfs += T
- // Sell phoron and platinum
- if(istype(A, /obj/item/stack))
- var/obj/item/stack/P = A
- if(material_points_conversion[P.get_material_name()])
- EC.contents[EC.contents.len]["value"] = P.get_amount() * material_points_conversion[P.get_material_name()]
- EC.contents[EC.contents.len]["quantity"] = P.get_amount()
- EC.value += EC.contents[EC.contents.len]["value"]
-
-
- //Sell spacebucks
- if(istype(A, /obj/item/weapon/spacecash))
- var/obj/item/weapon/spacecash/cashmoney = A
- EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money
- EC.contents[EC.contents.len]["quantity"] = cashmoney.worth
- EC.value += EC.contents[EC.contents.len]["value"]
-
-
-
- // Make a log of it, but it wasn't shipped properly, and so isn't worth anything
- else
- EC.contents = list(
- "error" = "Error: Product was improperly packaged. Payment rendered null under terms of agreement."
- )
-
- exported_crates += EC
- points += EC.value
- EC.value += base_value
-
- // Duplicate the receipt for the admin-side log
- var/datum/exported_crate/adm = new()
- adm.name = EC.name
- adm.value = EC.value
- adm.contents = deepCopyList(EC.contents)
- adm_export_history += adm
-
- qdel(MA)
+ return clear_turfs
//Buying
-/datum/controller/supply/proc/buy()
+/datum/controller/subsystem/supply/proc/buy()
var/list/shoppinglist = list()
for(var/datum/supply_order/SO in order_history)
if(SO.status == SUP_ORDER_APPROVED)
@@ -177,26 +168,9 @@ var/datum/controller/supply/supply_controller = new()
if(!shoppinglist.len)
return
-
var/orderedamount = shoppinglist.len
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle)
- return
-
- var/list/clear_turfs = list()
-
- 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/list/clear_turfs = get_clear_turfs()
for(var/datum/supply_order/SO in shoppinglist)
if(!clear_turfs.len)
@@ -265,9 +239,9 @@ var/datum/controller/supply/supply_controller = new()
return
// Will attempt to purchase the specified order, returning TRUE on success, FALSE on failure
-/datum/controller/supply/proc/approve_order(var/datum/supply_order/O, var/mob/user)
+/datum/controller/subsystem/supply/proc/approve_order(var/datum/supply_order/O, var/mob/user)
// Not enough points to purchase the crate
- if(supply_controller.points <= O.object.cost)
+ if(points <= O.object.cost)
return FALSE
// Based on the current model, there shouldn't be any entries in order_history, requestlist, or shoppinglist, that aren't matched in adm_order_history
@@ -294,11 +268,11 @@ var/datum/controller/supply/supply_controller = new()
adm_order.approved_at = stationdate2text() + " - " + stationtime2text()
// Deduct cost
- supply_controller.points -= O.object.cost
+ points -= O.object.cost
return TRUE
// Will deny the specified order. Only useful if the order is currently requested, but available at any status
-/datum/controller/supply/proc/deny_order(var/datum/supply_order/O, var/mob/user)
+/datum/controller/subsystem/supply/proc/deny_order(var/datum/supply_order/O, var/mob/user)
// Based on the current model, there shouldn't be any entries in order_history, requestlist, or shoppinglist, that aren't matched in adm_order_history
var/datum/supply_order/adm_order
for(var/datum/supply_order/temp in adm_order_history)
@@ -324,22 +298,22 @@ var/datum/controller/supply/supply_controller = new()
return
// Will deny all requested orders
-/datum/controller/supply/proc/deny_all_pending(var/mob/user)
+/datum/controller/subsystem/supply/proc/deny_all_pending(var/mob/user)
for(var/datum/supply_order/O in order_history)
if(O.status == SUP_ORDER_REQUESTED)
deny_order(O, user)
// Will delete the specified order from the user-side list
-/datum/controller/supply/proc/delete_order(var/datum/supply_order/O, var/mob/user)
+/datum/controller/subsystem/supply/proc/delete_order(var/datum/supply_order/O, var/mob/user)
// Making sure they know what they're doing
if(alert(user, "Are you sure you want to delete this record? If it has been approved, cargo points will NOT be refunded!", "Delete Record","No","Yes") == "Yes")
if(alert(user, "Are you really sure? There is no way to recover the order once deleted.", "Delete Record", "No", "Yes") == "Yes")
log_admin("[key_name(user)] has deleted supply order \ref[O] [O] from the user-side order history.")
- supply_controller.order_history -= O
+ order_history -= O
return
// Will generate a new, requested order, for the given supply pack type
-/datum/controller/supply/proc/create_order(var/datum/supply_pack/S, var/mob/user, var/reason)
+/datum/controller/subsystem/supply/proc/create_order(var/datum/supply_pack/S, var/mob/user, var/reason)
var/datum/supply_order/new_order = new()
var/datum/supply_order/adm_order = new() // Admin-recorded order must be a separate copy in memory, or user-made edits will corrupt it
@@ -374,16 +348,16 @@ var/datum/controller/supply/supply_controller = new()
adm_order_history += adm_order
// Will delete the specified export receipt from the user-side list
-/datum/controller/supply/proc/delete_export(var/datum/exported_crate/E, var/mob/user)
+/datum/controller/subsystem/supply/proc/delete_export(var/datum/exported_crate/E, var/mob/user)
// Making sure they know what they're doing
if(alert(user, "Are you sure you want to delete this record?", "Delete Record","No","Yes") == "Yes")
if(alert(user, "Are you really sure? There is no way to recover the receipt once deleted.", "Delete Record", "No", "Yes") == "Yes")
log_admin("[key_name(user)] has deleted export receipt \ref[E] [E] from the user-side export history.")
- supply_controller.exported_crates -= E
+ exported_crates -= E
return
// Will add an item entry to the specified export receipt on the user-side list
-/datum/controller/supply/proc/add_export_item(var/datum/exported_crate/E, var/mob/user)
+/datum/controller/subsystem/supply/proc/add_export_item(var/datum/exported_crate/E, var/mob/user)
var/new_name = input(user, "Name", "Please enter the name of the item.") as null|text
if(!new_name)
return
@@ -401,3 +375,21 @@ var/datum/controller/supply/supply_controller = new()
"quantity" = new_quantity,
"value" = new_value
)
+
+/datum/exported_crate
+ var/name
+ var/value
+ var/list/contents
+
+/datum/supply_order
+ var/ordernum // Unfabricatable index
+ var/index // Fabricatable index
+ var/datum/supply_pack/object = null
+ var/cost // Cost of the supply pack (Fabricatable) (Changes not reflected when purchasing supply packs, this is cosmetic only)
+ var/name // Name of the supply pack datum (Fabricatable)
+ var/ordered_by = null // Who requested the order
+ var/comment = null // What reason was given for the order
+ var/approved_by = null // Who approved the order
+ var/ordered_at // Date and time the order was requested at
+ var/approved_at // Date and time the order was approved at
+ var/status // [Requested, Accepted, Denied, Shipped]
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index 4f0650e897..2dc3b1626b 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -94,14 +94,12 @@
options["LEGACY: air_master"] = air_master
options["LEGACY: job_master"] = job_master
options["LEGACY: radio_controller"] = radio_controller
- options["LEGACY: supply_controller"] = supply_controller
options["LEGACY: emergency_shuttle"] = emergency_shuttle
options["LEGACY: paiController"] = paiController
options["LEGACY: cameranet"] = cameranet
options["LEGACY: transfer_controller"] = transfer_controller
options["LEGACY: gas_data"] = gas_data
options["LEGACY: plant_controller"] = plant_controller
- options["LEGACY: alarm_manager"] = alarm_manager
var/pick = input(mob, "Choose a controller to debug/view variables of.", "VV controller:") as null|anything in options
if(!pick)
diff --git a/code/datums/ghost_query.dm b/code/datums/ghost_query.dm
index dd4f140fbd..9d190911e0 100644
--- a/code/datums/ghost_query.dm
+++ b/code/datums/ghost_query.dm
@@ -5,6 +5,7 @@
var/finished = FALSE
var/role_name = "a thing"
var/question = "Would you like to play as a thing?"
+ var/query_sound = 'sound/effects/ghost2.ogg' // A sound file to play to the ghost, to help people who are alt-tabbed know something might interest them.
var/be_special_flag = 0
var/list/check_bans = list()
var/wait_time = 60 SECONDS // How long to wait until returning the list of candidates.
@@ -42,6 +43,9 @@
spawn(0)
if(!C)
return
+ window_flash(C)
+ if(query_sound)
+ SEND_SOUND(C, sound(query_sound))
var/response = alert(C, question, "[role_name] request", "Yes", "No", "Never for this round")
if(response == "Yes")
response = alert(C, "Are you sure you want to play as a [role_name]?", "[role_name] request", "Yes", "No") // Protection from a misclick.
@@ -62,12 +66,14 @@
/datum/ghost_query/promethean
role_name = "Promethean"
question = "Someone is requesting a soul for a promethean. Would you like to play as one?"
+ query_sound = 'sound/effects/slime_squish.ogg'
be_special_flag = BE_ALIEN
cutoff_number = 1
/datum/ghost_query/posi_brain
role_name = "Positronic Intelligence"
question = "Someone has activated a Positronic Brain. Would you like to play as one?"
+ query_sound = 'sound/machines/boobeebeep.ogg'
be_special_flag = BE_AI
check_bans = list("AI", "Cyborg")
cutoff_number = 1
@@ -75,6 +81,7 @@
/datum/ghost_query/drone_brain
role_name = "Drone Intelligence"
question = "Someone has activated a Drone AI Chipset. Would you like to play as one?"
+ query_sound = 'sound/machines/boobeebeep.ogg'
be_special_flag = BE_AI
check_bans = list("AI", "Cyborg")
cutoff_number = 1
@@ -90,6 +97,7 @@
/datum/ghost_query/xeno
role_name = "Alien"
question = "An Alien has just been created on the facility. Would you like to play as them?"
+ query_sound = 'sound/voice/hiss5.ogg'
be_special_flag = BE_ALIEN
/datum/ghost_query/blob
diff --git a/code/datums/observation/helpers.dm b/code/datums/observation/helpers.dm
index 9116026700..12feeba16d 100644
--- a/code/datums/observation/helpers.dm
+++ b/code/datums/observation/helpers.dm
@@ -9,6 +9,9 @@
/atom/proc/recursive_dir_set(var/atom/a, var/old_dir, var/new_dir)
set_dir(new_dir)
+/datum/proc/qdel_self()
+ qdel(src)
+
/proc/register_all_movement(var/event_source, var/listener)
GLOB.moved_event.register(event_source, listener, /atom/movable/proc/recursive_move)
GLOB.dir_set_event.register(event_source, listener, /atom/proc/recursive_dir_set)
diff --git a/code/datums/observation/shuttle_added.dm b/code/datums/observation/shuttle_added.dm
new file mode 100644
index 0000000000..dfd95170a0
--- /dev/null
+++ b/code/datums/observation/shuttle_added.dm
@@ -0,0 +1,22 @@
+// Observer Pattern Implementation: Shuttle Added
+// Registration type: /datum/shuttle (register for the global event only)
+//
+// Raised when: After a shuttle is initialized.
+//
+// Arguments that the called proc should expect:
+// /datum/shuttle/shuttle: the new shuttle
+
+GLOBAL_DATUM_INIT(shuttle_added, /decl/observ/shuttle_added, new)
+
+/decl/observ/shuttle_added
+ name = "Shuttle Added"
+ expected_type = /datum/shuttle
+
+/*****************************
+* Shuttle Added Handling *
+*****************************/
+
+/datum/controller/subsystem/shuttles/initialize_shuttle()
+ . = ..()
+ if(.)
+ GLOB.shuttle_added.raise_event(.)
\ No newline at end of file
diff --git a/code/datums/observation/shuttle_moved.dm b/code/datums/observation/shuttle_moved.dm
new file mode 100644
index 0000000000..35bff0d6b9
--- /dev/null
+++ b/code/datums/observation/shuttle_moved.dm
@@ -0,0 +1,38 @@
+// Observer Pattern Implementation: Shuttle Moved
+// Registration type: /datum/shuttle/autodock
+//
+// Raised when: A shuttle has moved to a new landmark.
+//
+// Arguments that the called proc should expect:
+// /datum/shuttle/shuttle: the shuttle moving
+// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
+// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
+
+// Observer Pattern Implementation: Shuttle Pre Move
+// Registration type: /datum/shuttle/autodock
+//
+// Raised when: A shuttle is about to move to a new landmark.
+//
+// Arguments that the called proc should expect:
+// /datum/shuttle/shuttle: the shuttle moving
+// /obj/effect/shuttle_landmark/old_location: the old location's shuttle landmark
+// /obj/effect/shuttle_landmark/new_location: the new location's shuttle landmark
+
+GLOBAL_DATUM_INIT(shuttle_moved_event, /decl/observ/shuttle_moved, new)
+
+/decl/observ/shuttle_moved
+ name = "Shuttle Moved"
+ expected_type = /datum/shuttle
+
+GLOBAL_DATUM_INIT(shuttle_pre_move_event, /decl/observ/shuttle_pre_move, new)
+
+/decl/observ/shuttle_pre_move
+ name = "Shuttle Pre Move"
+ expected_type = /datum/shuttle
+
+/*****************
+* Shuttle Moved/Pre Move Handling *
+*****************/
+
+// Located in modules/shuttle/shuttle.dm
+// Proc: /datum/shuttle/proc/attempt_move()
\ No newline at end of file
diff --git a/code/datums/observation/stat_set.dm b/code/datums/observation/stat_set.dm
new file mode 100644
index 0000000000..b980d06ecc
--- /dev/null
+++ b/code/datums/observation/stat_set.dm
@@ -0,0 +1,24 @@
+// Observer Pattern Implementation: Stat Set
+// Registration type: /mob/living
+//
+// Raised when: A /mob/living changes stat, using the set_stat() proc
+//
+// Arguments that the called proc should expect:
+// /mob/living/stat_mob: The mob whose stat changed
+// /old_stat: Status before the change.
+// /new_stat: Status after the change.
+
+GLOBAL_DATUM_INIT(stat_set_event, /decl/observ/stat_set, new)
+
+/decl/observ/stat_set
+ name = "Stat Set"
+ expected_type = /mob/living
+
+/****************
+* Stat Handling *
+****************/
+/mob/living/set_stat(var/new_stat)
+ var/old_stat = stat
+ . = ..()
+ if(stat != old_stat)
+ GLOB.stat_set_event.raise_event(src, old_stat, new_stat)
diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm
index 554a826f20..1b164a2cdf 100644
--- a/code/datums/supplypacks/medical.dm
+++ b/code/datums/supplypacks/medical.dm
@@ -339,14 +339,14 @@
/datum/supply_pack/med/distillery
name = "Chemical distiller crate"
contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery = 1)
- cost = 175
+ cost = 50
containertype = /obj/structure/largecrate
containername = "Chemical distiller crate"
/datum/supply_pack/med/advdistillery
name = "Industrial Chemical distiller crate"
contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery/industrial = 1)
- cost = 250
+ cost = 150
containertype = /obj/structure/largecrate
containername = "Industrial Chemical distiller crate"
diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index 1c1eb7f2bb..757d38b953 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -116,6 +116,15 @@
containername = "Robolimb blueprints (Bishop)"
access = access_robotics
+/datum/supply_pack/robotics/robolimbs/cenilimicybernetics
+ name = "Cenilimi Cybernetics robolimb blueprints"
+ contains = list(/obj/item/weapon/disk/limb/cenilimicybernetics)
+ cost = 45
+ containertype = /obj/structure/closet/crate/secure/science
+ containername = "Robolimb blueprints (Cenilimi Cybernetics)"
+ access = access_robotics
+
+
/datum/supply_pack/robotics/mecha_ripley
name = "Circuit Crate (\"Ripley\" APLU)"
contains = list(
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 86a9567a8d..1c4a448cee 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -13,7 +13,7 @@
/datum/uplink_item/abstract/announcements/fake_centcom
name = "Command Update Announcement"
desc = "Causes a falsified Command Update. Triggers immediately after supplying additional data."
- item_cost = 40
+ item_cost = 20
/datum/uplink_item/abstract/announcements/fake_centcom/extra_args(var/mob/user)
var/title = sanitize(input("Enter your announcement title.", "Announcement Title") as null|text)
@@ -41,7 +41,7 @@
/datum/uplink_item/abstract/announcements/fake_crew_arrival
name = "Crew Arrival Announcement/Records"
desc = "Creates a fake crew arrival announcement as well as fake crew records, using your current appearance (including held items!) and worn id card. Trigger with care!"
- item_cost = 30
+ item_cost = 15
/datum/uplink_item/abstract/announcements/fake_crew_arrival/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
if(!user)
diff --git a/code/datums/uplink/armor.dm b/code/datums/uplink/armor.dm
index 20367f3989..0d7d814310 100644
--- a/code/datums/uplink/armor.dm
+++ b/code/datums/uplink/armor.dm
@@ -13,3 +13,18 @@
name = "Heavy Armor Vest"
item_cost = 40
path = /obj/item/clothing/suit/storage/vest/heavy/merc
+
+/datum/uplink_item/item/armor/gorlexsuit
+ name = "Mercenary Voidsuit"
+ item_cost = 40
+ path = /obj/item/weapon/storage/box/syndie_kit/voidsuit
+
+/datum/uplink_item/item/armor/gorlexsuit_fire
+ name = "Mercenary Voidsuit (Fire)"
+ item_cost = 40
+ path = /obj/item/weapon/storage/box/syndie_kit/voidsuit/fire
+
+/datum/uplink_item/item/armor/combat
+ name = "Combat Platecarrier Set"
+ item_cost = 60
+ path = /obj/item/clothing/suit/armor/pcarrier/merc
diff --git a/code/datums/uplink/badassery.dm b/code/datums/uplink/badassery.dm
index 463c55dcc1..65f71f2584 100644
--- a/code/datums/uplink/badassery.dm
+++ b/code/datums/uplink/badassery.dm
@@ -91,4 +91,4 @@
var/obj/structure/largecrate/C = /obj/structure/largecrate
icon = image(initial(C.icon), initial(C.icon_state))
- return "\icon[icon]"
\ No newline at end of file
+ return "[bicon(icon)]"
\ No newline at end of file
diff --git a/code/datums/uplink/implants.dm b/code/datums/uplink/implants.dm
index e36396c9cd..bbbeaf9e7e 100644
--- a/code/datums/uplink/implants.dm
+++ b/code/datums/uplink/implants.dm
@@ -25,51 +25,51 @@
path = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
/datum/uplink_item/item/implants/imp_shades
- name = "Integrated Thermal-Shades Implant (Organic)"
+ name = "Integrated Thermal-Shades Implant"
item_cost = 80
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug
/datum/uplink_item/item/implants/imp_taser
- name = "Integrated Taser Implant (Organic)"
+ name = "Integrated Taser Implant"
item_cost = 30
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/taser
/datum/uplink_item/item/implants/imp_laser
- name = "Integrated Laser Implant (Organic)"
+ name = "Integrated Laser Implant"
item_cost = 50
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/laser
/datum/uplink_item/item/implants/imp_dart
- name = "Integrated Dart Implant (Organic)"
+ name = "Integrated Dart Implant"
item_cost = 60
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/dart
/datum/uplink_item/item/implants/imp_toolkit
- name = "Integrated Toolkit Implant (Organic)"
+ name = "Integrated Toolkit Implant"
item_cost = 80
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/toolkit
/datum/uplink_item/item/implants/imp_medkit
- name = "Integrated Medkit Implant (Organic)"
+ name = "Integrated Medkit Implant"
item_cost = 60
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/medkit
/datum/uplink_item/item/implants/imp_analyzer
- name = "Integrated Research Scanner Implant (Organic)"
+ name = "Integrated Research Scanner Implant"
item_cost = 20
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/analyzer
/datum/uplink_item/item/implants/imp_sword
- name = "Integrated Sword Implant (Organic)"
+ name = "Integrated Sword Implant"
item_cost = 40
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/sword
/datum/uplink_item/item/implants/imp_sprinter
- name = "Integrated Sprinter Implant (Organic)"
+ name = "Integrated Sprinter Implant"
item_cost = 40
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/sprinter
/datum/uplink_item/item/implants/imp_sprinter
- name = "Integrated Surge Implant (Organic)"
+ name = "Integrated Surge Implant"
item_cost = 40
path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/surge
diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm
index c28fed46b9..0657b62b2e 100644
--- a/code/datums/uplink/medical.dm
+++ b/code/datums/uplink/medical.dm
@@ -24,11 +24,23 @@
item_cost = 10
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
+/datum/uplink_item/item/medical/clotting_case
+ name = "Clotting Medicine case"
+ item_cost = 20
+ desc = "A case of three myelamine injectors. Can rapidly remove and stow up to six injectors."
+ path = /obj/item/weapon/storage/quickdraw/syringe_case/clotting
+
/datum/uplink_item/item/medical/bonemeds
name = "Bone Repair injector"
item_cost = 10
path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed
+/datum/uplink_item/item/medical/bonemeds_case
+ name = "Bone Repair case"
+ item_cost = 20
+ desc = "A case of three osteodaxon injectors. Can rapidly remove and stow up to six injectors."
+ path = /obj/item/weapon/storage/quickdraw/syringe_case/bonemed
+
/datum/uplink_item/item/medical/ambrosiadeusseeds
name = "Box of 7x ambrosia deus seed packets"
item_cost = 10
diff --git a/code/datums/uplink/resources.dm b/code/datums/uplink/resources.dm
new file mode 100644
index 0000000000..a544cab728
--- /dev/null
+++ b/code/datums/uplink/resources.dm
@@ -0,0 +1,48 @@
+
+/datum/uplink_item/crated/resources
+ name = "Resource Crate"
+ desc = "A crate routed from an in-system trading post, containing various valuable materials."
+ item_cost = 60
+ category = /datum/uplink_category/services
+
+ paths = list(\
+ /obj/fiftyspawner/uranium,\
+ /obj/fiftyspawner/phoron,\
+ /obj/fiftyspawner/gold,\
+ /obj/fiftyspawner/silver,\
+ /obj/fiftyspawner/osmium,\
+ /obj/fiftyspawner/plasteel\
+ )
+
+/datum/uplink_item/crated/seeds
+ name = "Exotic Plantlife Crate"
+ desc = "A crate routed from an in-system trading post, containing various exotic plants."
+ item_cost = 20
+ category = /datum/uplink_category/services
+
+ paths = list(\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random,\
+ /obj/item/seeds/random\
+ )
+
+/datum/uplink_item/crated/spare_organs
+ name = "Spare Organ Crate"
+ desc = "A crate stolen from a medical relief ship, containing various bioprinted organs."
+ item_cost = 20
+ category = /datum/uplink_category/services
+ crate_path = /obj/structure/closet/crate/freezer
+
+ paths = list(\
+ /obj/item/organ/internal/eyes/replicant,\
+ /obj/item/organ/internal/heart/replicant,\
+ /obj/item/organ/internal/kidneys/replicant,\
+ /obj/item/organ/internal/liver/replicant,\
+ /obj/item/organ/internal/lungs/replicant,\
+ /obj/item/organ/internal/voicebox/replicant\
+ )
diff --git a/code/datums/uplink/stealth_items.dm b/code/datums/uplink/stealth_items.dm
index 0a17e659a6..973e851b02 100644
--- a/code/datums/uplink/stealth_items.dm
+++ b/code/datums/uplink/stealth_items.dm
@@ -37,4 +37,16 @@
/datum/uplink_item/item/stealth_items/makeover
name = "Makeover Kit"
item_cost = 5
- path = /obj/item/weapon/makeover
\ No newline at end of file
+ path = /obj/item/weapon/makeover
+
+/datum/uplink_item/item/stealth_items/thievesgloves
+ name = "Thieve's Gloves"
+ desc = "A pair of sterile gloves that allow the wearer to inspect the backpacks of other players, and swap pocket items."
+ item_cost = 30
+ path = /obj/item/clothing/gloves/sterile/thieves
+
+/datum/uplink_item/item/stealth_items/deadringer
+ name = "Stealth Watch"
+ desc = "A strange watch which can be used to create a fake corpse if you are injured when it is active, as it projects a cloaking field around your person."
+ item_cost = 50
+ path = /obj/item/weapon/deadringer
diff --git a/code/datums/uplink/stealthy_weapons.dm b/code/datums/uplink/stealthy_weapons.dm
index 5576ebcac5..2f4cab5ff7 100644
--- a/code/datums/uplink/stealthy_weapons.dm
+++ b/code/datums/uplink/stealthy_weapons.dm
@@ -33,3 +33,51 @@
name = "Random Toxin - Beaker"
item_cost = 10
path = /obj/item/weapon/storage/box/syndie_kit/toxin
+
+/datum/uplink_item/item/stealthy_weapons/penblade
+ name = "Energy Penblade, Black"
+ desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
+ item_cost = 20
+ path = /obj/item/weapon/pen/blade
+
+/datum/uplink_item/item/stealthy_weapons/penblade_red
+ name = "Energy Penblade, Red"
+ desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
+ item_cost = 20
+ path = /obj/item/weapon/pen/blade/red
+
+/datum/uplink_item/item/stealthy_weapons/penblade_blue
+ name = "Energy Penblade, Blue"
+ desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
+ item_cost = 20
+ path = /obj/item/weapon/pen/blade/blue
+
+/datum/uplink_item/item/stealthy_weapons/penblade_fancy
+ name = "Energy Penblade, Fountain"
+ desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
+ item_cost = 20
+ path = /obj/item/weapon/pen/blade/fountain
+
+/datum/uplink_item/item/stealthy_weapons/angrybuzzer
+ name = "Morphium Shock Ring"
+ desc = "An enigmatic ring used to create powerful electric shocks when punching. Can be used as a brute-force method of defibrillation."
+ item_cost = 40
+ path = /obj/item/clothing/gloves/ring/buzzer
+
+/datum/uplink_item/item/stealthy_weapons/huntingtrap
+ name = "Camonetted Beartraps"
+ desc = "A box of unique beartraps which will partially cloak when deployed, allowing for more effective hunting."
+ item_cost = 30
+ path = /obj/item/weapon/storage/box/syndie_kit/deadliest_game
+
+/datum/uplink_item/item/stealthy_weapons/virus
+ name = "Virus Cultures"
+ desc = "A box of three unique virus cultures. As dangerous to you as anyone else if handled improperly."
+ item_cost = 40
+ path = /obj/item/weapon/storage/box/syndie_kit/viral
+
+/datum/uplink_item/item/stealthy_weapons/syringe_case
+ name = "Quickdraw Syringe Case"
+ desc = "A small box capable of holding six syringes for rapid deployment. Fits in your pocket."
+ item_cost = 20
+ path = /obj/item/weapon/storage/quickdraw/syringe_case
diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm
index 6c340385b0..6f70c1111c 100644
--- a/code/datums/uplink/tools.dm
+++ b/code/datums/uplink/tools.dm
@@ -91,6 +91,12 @@
item_cost = 30
path = /obj/item/weapon/card/emag
+/datum/uplink_item/item/tools/graviton
+ name = "Graviton Goggles"
+ desc = "An obvious, if useful pair of advanced imaging goggles that allow you to see objects and turfs through walls."
+ item_cost = 15
+ path = /obj/item/clothing/glasses/graviton
+
/datum/uplink_item/item/tools/thermal
name = "Thermal Imaging Glasses"
item_cost = 30
@@ -111,6 +117,11 @@
item_cost = 60
path = /obj/item/weapon/storage/box/syndie_kit/demolitions_heavy
+/datum/uplink_item/item/tools/integratedcircuitprinter
+ name = "Integrated Circuit Printer (Upgraded)"
+ item_cost = 10
+ path = /obj/item/device/integrated_circuit_printer/upgraded
+
/*
/datum/uplink_item/item/tools/packagebomb/huge
name = "Package Bomb (Huge)
diff --git a/code/datums/uplink/uplink_categories.dm b/code/datums/uplink/uplink_categories.dm
index 2776085594..d9e6d84db7 100644
--- a/code/datums/uplink/uplink_categories.dm
+++ b/code/datums/uplink/uplink_categories.dm
@@ -52,4 +52,4 @@ datum/uplink_category/ammunition
name = "Telecrystals"
/datum/uplink_category/backup
- name = "Backup"
\ No newline at end of file
+ name = "Backup"
diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm
index 94b1281dd3..cca1933c9c 100644
--- a/code/datums/uplink/uplink_items.dm
+++ b/code/datums/uplink/uplink_items.dm
@@ -146,7 +146,7 @@ datum/uplink_item/dd_SortValue()
/datum/uplink_item/item/log_icon()
var/obj/I = path
- return "\icon[I]"
+ return "[bicon(I)]"
/********************************
* *
@@ -160,7 +160,37 @@ datum/uplink_item/dd_SortValue()
if(!default_abstract_uplink_icon)
default_abstract_uplink_icon = image('icons/obj/pda.dmi', "pda-syn")
- return "\icon[default_abstract_uplink_icon]"
+ return "[bicon(default_abstract_uplink_icon)]"
+
+/*
+ * Crated goods.
+ */
+
+/datum/uplink_item/crated
+ var/crate_path = /obj/structure/largecrate
+ var/list/paths = list() // List of paths to be spawned into the crate.
+
+/datum/uplink_item/crated/get_goods(var/obj/item/device/uplink/U, var/loc)
+ var/obj/L = new crate_path(get_turf(loc))
+
+ L.adjust_scale(rand(9, 12) / 10, rand(9, 12) / 10) // Some variation in the crate / locker size.
+
+ for(var/path in paths)
+ var/obj/O = new path(L)
+ O.forceMove(L)
+
+ return L
+
+/datum/uplink_item/crated/description()
+ if(!desc)
+ // Fallback description
+ var/obj/temp = crate_path
+ desc = initial(temp.desc)
+ return ..()
+
+/datum/uplink_item/crated/log_icon()
+ var/obj/I = crate_path
+ return "\icon[I]"
/****************
* Support procs *
diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm
index e4c27752f0..0ed9b26226 100644
--- a/code/datums/uplink/visible_weapons.dm
+++ b/code/datums/uplink/visible_weapons.dm
@@ -61,7 +61,7 @@
/datum/uplink_item/item/visible_weapons/riggedlaser
name = "Exosuit Rigged Laser"
- item_cost = 60
+ item_cost = 30
path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser
/datum/uplink_item/item/visible_weapons/revolver
@@ -146,7 +146,7 @@
/datum/uplink_item/item/visible_weapons/egun
name = "Energy Gun"
- item_cost = 60
+ item_cost = 30
path = /obj/item/weapon/gun/energy/gun
/datum/uplink_item/item/visible_weapons/lasercannon
@@ -171,5 +171,17 @@
/datum/uplink_item/item/visible_weapons/xray
name = "Xray Gun"
- item_cost = 85
+ item_cost = 60
path = /obj/item/weapon/gun/energy/xray
+
+/datum/uplink_item/item/visible_weapons/flamethrower
+ name = "Heavy Flamethrower"
+ desc = "A large flamethrower that runs on pressurized, gaseous phoron and electric charge."
+ item_cost = 60
+ path = /obj/item/weapon/storage/secure/briefcase/flamer
+
+/datum/uplink_item/item/visible_weapons/concussion_grenades
+ name = "Concussion Grenades (8)"
+ desc = "A box of eight concussion grenades."
+ item_cost = 30
+ path = /obj/item/weapon/storage/box/syndie_kit/concussion_grenade
diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm
index 69f1810331..67210e2179 100644
--- a/code/datums/wires/camera.dm
+++ b/code/datums/wires/camera.dm
@@ -60,7 +60,7 @@ var/const/CAMERA_WIRE_NOTHING2 = 32
C.light_disabled = !C.light_disabled
if(CAMERA_WIRE_ALARM)
- C.visible_message("\icon[C] *beep*", "\icon[C] *beep*")
+ C.visible_message("[bicon(C)] *beep*", "[bicon(C)] *beep*")
return
/datum/wires/camera/proc/CanDeconstruct()
diff --git a/code/datums/wires/jukebox.dm b/code/datums/wires/jukebox.dm
index 9bc0f2ca61..e207334ffd 100644
--- a/code/datums/wires/jukebox.dm
+++ b/code/datums/wires/jukebox.dm
@@ -34,16 +34,16 @@ var/const/WIRE_NEXT = 1024
var/obj/machinery/media/jukebox/A = holder
switch(index)
if(WIRE_POWER)
- holder.visible_message("\icon[holder] The power light flickers.")
+ holder.visible_message("[bicon(holder)] The power light flickers.")
A.shock(usr, 90)
if(WIRE_HACK)
- holder.visible_message("\icon[holder] The parental guidance light flickers.")
+ holder.visible_message("[bicon(holder)] The parental guidance light flickers.")
if(WIRE_REVERSE)
- holder.visible_message("\icon[holder] The data light blinks ominously.")
+ holder.visible_message("[bicon(holder)] The data light blinks ominously.")
if(WIRE_SPEEDUP)
- holder.visible_message("\icon[holder] The speakers squeaks.")
+ holder.visible_message("[bicon(holder)] The speakers squeaks.")
if(WIRE_SPEEDDOWN)
- holder.visible_message("\icon[holder] The speakers rumble.")
+ holder.visible_message("[bicon(holder)] The speakers rumble.")
if(WIRE_START)
A.StartPlaying()
if(WIRE_STOP)
diff --git a/code/datums/wires/mines.dm b/code/datums/wires/mines.dm
index 2d0aecaaf0..372810988c 100644
--- a/code/datums/wires/mines.dm
+++ b/code/datums/wires/mines.dm
@@ -23,15 +23,15 @@
switch(index)
if(WIRE_DETONATE)
- C.visible_message("\icon[C] *BEEE-*", "\icon[C] *BEEE-*")
+ C.visible_message("[bicon(C)] *BEEE-*", "[bicon(C)] *BEEE-*")
C.explode()
if(WIRE_TIMED_DET)
- C.visible_message("\icon[C] *BEEE-*", "\icon[C] *BEEE-*")
+ C.visible_message("[bicon(C)] *BEEE-*", "[bicon(C)] *BEEE-*")
C.explode()
if(WIRE_DISARM)
- C.visible_message("\icon[C] *click!*", "\icon[C] *click!*")
+ C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*")
new C.mineitemtype(get_turf(C))
spawn(0)
qdel(C)
@@ -45,7 +45,7 @@
return
if(WIRE_BADDISARM)
- C.visible_message("\icon[C] *BEEPBEEPBEEP*", "\icon[C] *BEEPBEEPBEEP*")
+ C.visible_message("[bicon(C)] *BEEPBEEPBEEP*", "[bicon(C)] *BEEPBEEPBEEP*")
spawn(20)
C.explode()
return
@@ -56,24 +56,24 @@
return
switch(index)
if(WIRE_DETONATE)
- C.visible_message("\icon[C] *beep*", "\icon[C] *beep*")
+ C.visible_message("[bicon(C)] *beep*", "[bicon(C)] *beep*")
if(WIRE_TIMED_DET)
- C.visible_message("\icon[C] *BEEPBEEPBEEP*", "\icon[C] *BEEPBEEPBEEP*")
+ C.visible_message("[bicon(C)] *BEEPBEEPBEEP*", "[bicon(C)] *BEEPBEEPBEEP*")
spawn(20)
C.explode()
if(WIRE_DISARM)
- C.visible_message("\icon[C] *ping*", "\icon[C] *ping*")
+ C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
if(WIRE_DUMMY_1)
- C.visible_message("\icon[C] *ping*", "\icon[C] *ping*")
+ C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
if(WIRE_DUMMY_2)
- C.visible_message("\icon[C] *beep*", "\icon[C] *beep*")
+ C.visible_message("[bicon(C)] *beep*", "[bicon(C)] *beep*")
if(WIRE_BADDISARM)
- C.visible_message("\icon[C] *ping*", "\icon[C] *ping*")
+ C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
return
/datum/wires/mines/CanUse(var/mob/living/L)
diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm
index 8356238692..3d90236b46 100644
--- a/code/datums/wires/particle_accelerator.dm
+++ b/code/datums/wires/particle_accelerator.dm
@@ -28,7 +28,7 @@ var/const/PARTICLE_LIMIT_POWER_WIRE = 8 // Determines how strong the PA can be.
C.interface_control = !C.interface_control
if(PARTICLE_LIMIT_POWER_WIRE)
- C.visible_message("\icon[C][C] makes a large whirring noise.")
+ C.visible_message("[bicon(C)][C] makes a large whirring noise.")
/datum/wires/particle_acc/control_box/UpdateCut(var/index, var/mended)
var/obj/machinery/particle_accelerator/control_box/C = holder
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index 76ac3a2b1f..d4a4be4553 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -124,7 +124,7 @@ var/global/list/PDA_Manifest = list()
if(depthead && car.len != 1)
car.Swap(1,car.len)
- if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CARGO))
+ if(SSjob.is_job_in_department(real_rank, DEPARTMENT_CIVILIAN))
civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
if(depthead && civ.len != 1)
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 98873ac0c3..b21e3c0025 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -66,7 +66,6 @@
attack_verb = list("HONKED")
var/spam_flag = 0
-
/obj/item/weapon/c_tube
name = "cardboard tube"
desc = "A tube... of cardboard."
@@ -77,141 +76,6 @@
throw_speed = 4
throw_range = 5
-/obj/item/weapon/cane
- name = "cane"
- desc = "A cane used by a true gentleman."
- icon = 'icons/obj/weapons.dmi'
- icon_state = "cane"
- item_icons = list(
- slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
- slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
- )
- force = 5.0
- throwforce = 7.0
- w_class = ITEMSIZE_NORMAL
- matter = list(DEFAULT_WALL_MATERIAL = 50)
- attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
-
-/obj/item/weapon/cane/concealed
- var/concealed_blade
-
-/obj/item/weapon/cane/concealed/New()
- ..()
- var/obj/item/weapon/material/butterfly/switchblade/temp_blade = new(src)
- concealed_blade = temp_blade
- temp_blade.attack_self()
-
-/obj/item/weapon/cane/concealed/attack_self(var/mob/user)
- var/datum/gender/T = gender_datums[user.get_visible_gender()]
- if(concealed_blade)
- user.visible_message("[user] has unsheathed \a [concealed_blade] from [T.his] [src]!", "You unsheathe \the [concealed_blade] from \the [src].")
- // Calling drop/put in hands to properly call item drop/pickup procs
- playsound(user.loc, 'sound/weapons/holster/sheathout.ogg', 50, 1)
- user.drop_from_inventory(src)
- user.put_in_hands(concealed_blade)
- user.put_in_hands(src)
- user.update_inv_l_hand(0)
- user.update_inv_r_hand()
- concealed_blade = null
- else
- ..()
-
-/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/material/butterfly/W, var/mob/user)
- if(!src.concealed_blade && istype(W))
- var/datum/gender/T = gender_datums[user.get_visible_gender()]
- user.visible_message("[user] has sheathed \a [W] into [T.his] [src]!", "You sheathe \the [W] into \the [src].")
- playsound(user.loc, 'sound/weapons/holster/sheathin.ogg', 50, 1)
- user.drop_from_inventory(W)
- W.loc = src
- src.concealed_blade = W
- update_icon()
- else
- ..()
-
-/obj/item/weapon/cane/concealed/update_icon()
- if(concealed_blade)
- name = initial(name)
- icon_state = initial(icon_state)
- item_state = initial(icon_state)
- else
- name = "cane shaft"
- icon_state = "nullrod"
- item_state = "foldcane"
-
-/obj/item/weapon/cane/whitecane
- name = "white cane"
- desc = "A white cane. They are commonly used by the blind or visually impaired as a mobility tool or as a courtesy to others."
- icon = 'icons/obj/weapons.dmi'
- icon_state = "whitecane"
-
-/obj/item/weapon/cane/whitecane/attack(mob/M as mob, mob/user as mob)
- if(user.a_intent == I_HELP)
- user.visible_message("\The [user] has lightly tapped [M] on the ankle with their white cane!")
- return
- else
- ..()
-
-/obj/item/weapon/cane/crutch
- name ="crutch"
- desc = "A long stick with a crosspiece at the top, used to help with walking."
- icon_state = "crutch"
- item_state = "crutch"
-
-//Code for Telescopic White Cane writen by Gozulio
-
-/obj/item/weapon/melee/collapsable_whitecane
- name = "telescopic white cane"
- desc = "A telescoping white cane. They are commonly used by the blind or visually impaired as a mobility tool or as a courtesy to others."
- icon = 'icons/obj/weapons.dmi'
- icon_state = "whitecane1in"
- item_icons = list(
- slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
- slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
- )
- slot_flags = SLOT_BELT
- w_class = ITEMSIZE_SMALL
- force = 3
- var/on = 0
-
-/obj/item/weapon/melee/collapsable_whitecane/attack_self(mob/user as mob)
- on = !on
- if(on)
- user.visible_message("\The [user] extends the white cane.",\
- "You extend the white cane.",\
- "You hear an ominous click.")
- icon_state = "whitecane1out"
- item_state_slots = list(slot_r_hand_str = "whitecane", slot_l_hand_str = "whitecane")
- w_class = ITEMSIZE_NORMAL
- force = 5
- attack_verb = list("smacked", "struck", "cracked", "beaten")
- else
- user.visible_message("\The [user] collapses the white cane.",\
- "You collapse the white cane.",\
- "You hear a click.")
- icon_state = "whitecane1in"
- item_state_slots = list(slot_r_hand_str = null, slot_l_hand_str = null)
- w_class = ITEMSIZE_SMALL
- force = 3
- attack_verb = list("hit", "poked")
-
- if(istype(user,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- H.update_inv_l_hand()
- H.update_inv_r_hand()
-
- playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
- add_fingerprint(user)
-
- return
-
-/obj/item/weapon/melee/collapsable_whitecane/attack(mob/M as mob, mob/user as mob)
- if(user.a_intent == I_HELP)
- user.visible_message("\The [user] has lightly tapped [M] on the ankle with their white cane!")
- return
- else
- ..()
-
-
/obj/item/weapon/disk
name = "disk"
icon = 'icons/obj/items.dmi'
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 125601af4a..0b4aafda94 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -49,20 +49,20 @@
datum/announcement/proc/Message(message as text, message_title as text)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !isdeaf(M))
- M << "
[title]
"
- M << "[message]"
+ to_chat(M, "
[title]
")
+ to_chat(M, "[message]")
if (announcer)
- M << " -[html_encode(announcer)]"
+ to_chat(M, " -[html_encode(announcer)]")
datum/announcement/minor/Message(message as text, message_title as text)
- world << "[message]"
+ to_world("[message]")
datum/announcement/priority/Message(message as text, message_title as text)
- world << "
[message_title]
"
- world << "[message]"
+ to_world("
[message_title]
")
+ to_world("[message]")
if(announcer)
- world << " -[html_encode(announcer)]"
- world << " "
+ to_world(" -[html_encode(announcer)]")
+ to_world(" ")
datum/announcement/priority/command/Message(message as text, message_title as text)
var/command
@@ -74,11 +74,11 @@ datum/announcement/priority/command/Message(message as text, message_title as te
command += " "
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !isdeaf(M))
- M << command
+ to_chat(M, command)
datum/announcement/priority/security/Message(message as text, message_title as text)
- world << "[message_title]"
- world << "[message]"
+ to_world("[message_title]")
+ to_world("[message]")
datum/announcement/proc/NewsCast(message as text, message_title as text)
if(!newscast)
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 2de7f72124..962c91a621 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -7,6 +7,7 @@
// Strings.
var/welcome_text = "Cry havoc and let slip the dogs of war!"
+ var/antag_sound = 'sound/effects/antag_notice/general_baddie_alert.ogg' // The sound file to play when someone gets this role. Only they can hear it.
var/leader_welcome_text // Text shown to the leader, if any.
var/victory_text // World output at roundend for victory.
var/loss_text // As above for loss.
diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm
index 07046401c3..84c5b2317e 100644
--- a/code/game/antagonist/antagonist_create.dm
+++ b/code/game/antagonist/antagonist_create.dm
@@ -95,6 +95,10 @@
return code
/datum/antagonist/proc/greet(var/datum/mind/player)
+ // Makes it harder to miss if you're alt-tabbed or not paying attention.
+ if(antag_sound)
+ SEND_SOUND(player.current, sound(antag_sound))
+ window_flash(player.current.client)
// Basic intro text.
to_chat(player.current, "You are a [role_text]!")
diff --git a/code/game/antagonist/outsider/commando.dm b/code/game/antagonist/outsider/commando.dm
index 3ea5c233ff..b7bd756c97 100644
--- a/code/game/antagonist/outsider/commando.dm
+++ b/code/game/antagonist/outsider/commando.dm
@@ -6,6 +6,7 @@ var/datum/antagonist/deathsquad/mercenary/commandos
role_text = "Syndicate Commando"
role_text_plural = "Commandos"
welcome_text = "You are in the employ of a criminal syndicate hostile to corporate interests."
+ antag_sound = 'sound/effects/antag_notice/deathsquid_alert.ogg'
id_type = /obj/item/weapon/card/id/centcom/ERT
hard_cap = 4
diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm
index db281b6dbb..01b579b7de 100644
--- a/code/game/antagonist/outsider/deathsquad.dm
+++ b/code/game/antagonist/outsider/deathsquad.dm
@@ -6,6 +6,7 @@ var/datum/antagonist/deathsquad/deathsquad
role_text = "Death Commando"
role_text_plural = "Death Commandos"
welcome_text = "You work in the service of corporate Asset Protection, answering directly to the Board of Directors."
+ antag_sound = 'sound/effects/antag_notice/deathsquid_alert.ogg'
landmark_id = "Commando"
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER
default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)
diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm
index 670d1c9b93..8b3301afc7 100644
--- a/code/game/antagonist/outsider/ert.dm
+++ b/code/game/antagonist/outsider/ert.dm
@@ -7,6 +7,7 @@ var/datum/antagonist/ert/ert
role_text = "Emergency Responder"
role_text_plural = "Emergency Responders"
welcome_text = "As member of the Emergency Response Team, you answer only to your leader and company officials."
+ antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are an anti antagonist! Within the rules, \
try to save the station and its inhabitants from the ongoing crisis. \
Try to make sure other players have fun! If you are confused or at a loss, always adminhelp, \
diff --git a/code/game/antagonist/outsider/technomancer.dm b/code/game/antagonist/outsider/technomancer.dm
index 39fe4409bc..579e5631d7 100644
--- a/code/game/antagonist/outsider/technomancer.dm
+++ b/code/game/antagonist/outsider/technomancer.dm
@@ -10,7 +10,8 @@ var/datum/antagonist/technomancer/technomancers
welcome_text = "You will need to purchase functions and perhaps some equipment from the various machines around your \
base. Choose your technological arsenal carefully. Remember that without the core on your back, your functions are \
powerless, and therefore you will be as well. \
- In your pockets you will find a one-time use teleport device. Use it to leave the base and go to the colony, when you are ready."
+ In your pockets you will find a one-time use teleport device. Use it to leave the base and go to the station, when you are ready."
+ antag_sound = 'sound/effects/antag_notice/technomancer_alert.ogg'
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_SET_APPEARANCE | ANTAG_VOTABLE
antaghud_indicator = "hudwizard"
diff --git a/code/game/antagonist/outsider/trader.dm b/code/game/antagonist/outsider/trader.dm
index d6e938932e..07cfb6f9e9 100644
--- a/code/game/antagonist/outsider/trader.dm
+++ b/code/game/antagonist/outsider/trader.dm
@@ -6,6 +6,7 @@ var/datum/antagonist/trader/traders
role_text = "Trader"
role_text_plural = "Traders"
welcome_text = "As a crewmember of the Beruang, you answer to your captain and international laws of space."
+ antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are an non-antagonist visitor! Within the rules, \
try to provide interesting interaction for the crew. \
Try to make sure other players have fun! If you are confused or at a loss, always adminhelp, \
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index a7bed0a2af..860e73a052 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -8,6 +8,7 @@
restricted_jobs = list("AI", "Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Colony Director")
welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
+ antag_sound = 'sound/effects/antag_notice/ling_alert.ogg'
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
antaghud_indicator = "hudchangeling"
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index 3f40cfc9ea..dc98622ba7 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -18,6 +18,7 @@ var/datum/antagonist/cultist/cult
feedback_tag = "cult_objective"
antag_indicator = "cult"
welcome_text = "You have a talisman in your possession; one that will help you start the cult on this station. Use it well and remember - there are others."
+ antag_sound = 'sound/effects/antag_notice/cult_alert.ogg'
victory_text = "The cult wins! It has succeeded in serving its dark masters!"
loss_text = "The staff managed to stop the cult!"
victory_feedback_tag = "win - cult win"
diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm
index 54e9fa4d4e..9b2333b491 100644
--- a/code/game/antagonist/station/loyalist.dm
+++ b/code/game/antagonist/station/loyalist.dm
@@ -9,6 +9,7 @@ var/datum/antagonist/loyalists/loyalists
feedback_tag = "loyalist_objective"
antag_indicator = "loyal_head"
welcome_text = "You belong to the Company, body and soul. Preserve its interests against the conspirators amongst the crew."
+ antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
victory_text = "The heads of staff remained at their posts! The loyalists win!"
loss_text = "The heads of staff did not stop the revolution!"
victory_feedback_tag = "win - rev heads killed"
diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm
index 7db152503f..ed3c804506 100644
--- a/code/game/antagonist/station/renegade.dm
+++ b/code/game/antagonist/station/renegade.dm
@@ -8,6 +8,7 @@ var/datum/antagonist/renegade/renegades
bantype = "renegade"
restricted_jobs = list("AI", "Cyborg")
welcome_text = "Something's going to go wrong today, you can just feel it. You're paranoid, you've got a gun, and you're going to survive."
+ antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
antag_text = "You are a minor antagonist! Within the rules, \
try to protect yourself and what's important to you. You aren't here to cause trouble, \
you're just more willing (and equipped) to go to extremes to stop it than others are. \
diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm
index 935d486f34..4fcb678d34 100644
--- a/code/game/antagonist/station/rogue_ai.dm
+++ b/code/game/antagonist/station/rogue_ai.dm
@@ -8,6 +8,7 @@ var/datum/antagonist/rogue_ai/malf
mob_path = /mob/living/silicon/ai
landmark_id = "AI"
welcome_text = "You are malfunctioning! You do not have to follow any laws."
+ antag_sound = 'sound/effects/antag_notice/malf_alert.ogg'
victory_text = "The AI has taken control of all of the station's systems."
loss_text = "The AI has been shut down!"
flags = ANTAG_VOTABLE | ANTAG_OVERRIDE_MOB | ANTAG_OVERRIDE_JOB | ANTAG_CHOOSE_NAME
diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm
index 3829d43166..23d0758e8b 100644
--- a/code/game/antagonist/station/traitor.dm
+++ b/code/game/antagonist/station/traitor.dm
@@ -3,6 +3,7 @@ var/datum/antagonist/traitor/traitors
// Inherits most of its vars from the base datum.
/datum/antagonist/traitor
id = MODE_TRAITOR
+ antag_sound = 'sound/effects/antag_notice/traitor_alert.ogg'
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = FALSE // If they want to plot and plan as this sort of traitor, they'll need to do it ICly.
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 81c74f3ba3..a491f7fff0 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -62,8 +62,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
////////////
//SHUTTLES//
////////////
-//shuttle areas must contain at least two areas in a subgroup if you want to move a shuttle from one
-//place to another. Look at escape shuttle for example.
+//Shuttles only need starting area, movement is handled by landmarks
//All shuttles should now be under shuttle since we have smooth-wall code.
/area/shuttle
@@ -76,160 +75,55 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Arrival Shuttle"
ambience = AMBIENCE_ARRIVALS
-/area/shuttle/arrival/pre_game
+/area/shuttle/supply
+ name = "\improper Supply Shuttle"
icon_state = "shuttle2"
-/area/shuttle/arrival/station
- icon_state = "shuttle"
- dynamic_lighting = 0
- ambience = AMBIENCE_ARRIVALS
-
/area/shuttle/escape
name = "\improper Emergency Shuttle"
music = "music/escape.ogg"
-/area/shuttle/escape/station
- name = "\improper Emergency Shuttle Station"
- icon_state = "shuttle2"
- dynamic_lighting = 0
-
-/area/shuttle/escape/centcom
- name = "\improper Emergency Shuttle CentCom"
- icon_state = "shuttle"
-
-/area/shuttle/escape/transit // the area to pass through for 3 minute transit
- name = "\improper Emergency Shuttle Transit"
- icon_state = "shuttle"
-
/area/shuttle/escape_pod1
name = "\improper Escape Pod One"
music = "music/escape.ogg"
-/area/shuttle/escape_pod1/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod1/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod1/transit
- icon_state = "shuttle"
-
/area/shuttle/escape_pod2
name = "\improper Escape Pod Two"
music = "music/escape.ogg"
-/area/shuttle/escape_pod2/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod2/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod2/transit
- icon_state = "shuttle"
-
/area/shuttle/escape_pod3
name = "\improper Escape Pod Three"
music = "music/escape.ogg"
-/area/shuttle/escape_pod3/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod3/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod3/transit
- icon_state = "shuttle"
-
/area/shuttle/escape_pod4
name = "\improper Escape Pod Four"
music = "music/escape.ogg"
-/area/shuttle/escape_pod4/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod4/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod4/transit
- icon_state = "shuttle"
-
/area/shuttle/escape_pod5
name = "\improper Escape Pod Five"
music = "music/escape.ogg"
-/area/shuttle/escape_pod5/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod5/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod5/transit
- icon_state = "shuttle"
-
/area/shuttle/escape_pod6
name = "\improper Escape Pod Six"
music = "music/escape.ogg"
-/area/shuttle/escape_pod6/station
- icon_state = "shuttle2"
-
-/area/shuttle/escape_pod6/centcom
- icon_state = "shuttle"
-
-/area/shuttle/escape_pod6/transit
- icon_state = "shuttle"
-
/area/shuttle/large_escape_pod1
name = "\improper Large Escape Pod One"
music = "music/escape.ogg"
-/area/shuttle/large_escape_pod1/station
- icon_state = "shuttle2"
-
-/area/shuttle/large_escape_pod1/centcom
- icon_state = "shuttle"
-
-/area/shuttle/large_escape_pod1/transit
- icon_state = "shuttle"
-
/area/shuttle/large_escape_pod2
name = "\improper Large Escape Pod Two"
music = "music/escape.ogg"
-/area/shuttle/large_escape_pod2/station
- icon_state = "shuttle2"
-
-/area/shuttle/large_escape_pod2/centcom
- icon_state = "shuttle"
-
-/area/shuttle/large_escape_pod2/transit
- icon_state = "shuttle"
-
/area/shuttle/cryo
name = "\improper Cryogenic Storage"
-/area/shuttle/cryo/station
- icon_state = "shuttle2"
- base_turf = /turf/simulated/mineral/floor/ignore_mapgen
-
-/area/shuttle/cryo/centcom
- icon_state = "shuttle"
-
-/area/shuttle/cryo/transit
- icon_state = "shuttle"
-
/area/shuttle/mining
name = "\improper Mining Elevator"
music = "music/escape.ogg"
dynamic_lighting = 0
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
-/area/shuttle/mining/station
- icon_state = "shuttle2"
-
-/area/shuttle/mining/outpost
- icon_state = "shuttle"
-
/area/shuttle/transport1/centcom
icon_state = "shuttle"
name = "\improper Transport Shuttle CentCom"
@@ -286,54 +180,15 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "red"
dynamic_lighting = 0
-/area/shuttle/trade/centcom
- name = "\improper Trade Shuttle CentCom"
- icon_state = "shuttlered"
-
-/area/shuttle/trade/station
- name = "\improper Trade Shuttle"
- icon_state = "shuttlered"
-
/area/shuttle/thunderdome
name = "honk"
-/area/shuttle/thunderdome/grnshuttle
- name = "\improper Thunderdome GRN Shuttle"
- icon_state = "green"
-
-/area/shuttle/thunderdome/grnshuttle/dome
- name = "\improper GRN Shuttle"
- icon_state = "shuttlegrn"
-
-/area/shuttle/thunderdome/grnshuttle/station
- name = "\improper GRN Station"
- icon_state = "shuttlegrn2"
-
-/area/shuttle/thunderdome/redshuttle
- name = "\improper Thunderdome RED Shuttle"
- icon_state = "red"
-
-/area/shuttle/thunderdome/redshuttle/dome
- name = "\improper RED Shuttle"
- icon_state = "shuttlered"
-
-/area/shuttle/thunderdome/redshuttle/station
- name = "\improper RED Station"
- icon_state = "shuttlered2"
-// === Trying to remove these areas:
-
/area/shuttle/research
name = "\improper Research Elevator"
music = "music/escape.ogg"
dynamic_lighting = 0
base_turf = /turf/simulated/mineral/floor/ignore_mapgen
-/area/shuttle/research/station
- icon_state = "shuttle2"
-
-/area/shuttle/research/outpost
- icon_state = "shuttle"
-
/area/airtunnel1/ // referenced in airtunnel.dm:759
/area/dummy/ // Referenced in engine.dm:261
@@ -2039,17 +1894,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Cargo Mining Dock"
icon_state = "mining"
-/area/supply/station
- 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
// SCIENCE
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 3c0e1337ed..e0f0f85049 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -71,6 +71,31 @@
power_change() // all machines set to current power level, also updates lighting icon
return INITIALIZE_HINT_LATELOAD
+// Changes the area of T to A. Do not do this manually.
+// Area is expected to be a non-null instance.
+/proc/ChangeArea(var/turf/T, var/area/A)
+ if(!istype(A))
+ CRASH("Area change attempt failed: invalid area supplied.")
+ var/area/old_area = get_area(T)
+ if(old_area == A)
+ return
+ // NOTE: BayStation calles area.Exited/Entered for the TURF T. So far we don't do that.s
+ // NOTE: There probably won't be any atoms in these turfs, but just in case we should call these procs.
+ A.contents.Add(T)
+ if(old_area)
+ // Handle dynamic lighting update if
+ if(T.dynamic_lighting && old_area.dynamic_lighting != A.dynamic_lighting)
+ if(A.dynamic_lighting)
+ T.lighting_build_overlay()
+ else
+ T.lighting_clear_overlay()
+ for(var/atom/movable/AM in T)
+ old_area.Exited(AM, A)
+ for(var/atom/movable/AM in T)
+ A.Entered(AM, old_area)
+ for(var/obj/machinery/M in T)
+ M.power_change()
+
/area/proc/get_contents()
return contents
diff --git a/code/game/area/ss13_deprecated_areas.dm b/code/game/area/ss13_deprecated_areas.dm
new file mode 100644
index 0000000000..b3b689f23d
--- /dev/null
+++ b/code/game/area/ss13_deprecated_areas.dm
@@ -0,0 +1,164 @@
+//
+// Shuttles formerly required at least two areas in a subgroup if you want to move a shuttle from one
+// place to another. Since shuttles now used landmarks instead these areas are deprecated!
+// They are left here for the moment in order to make existing maps loadable, but should be phased out.
+//
+
+/area/shuttle/arrival/pre_game
+ icon_state = "shuttle2"
+
+/area/shuttle/arrival/station
+ icon_state = "shuttle"
+ dynamic_lighting = 0
+ ambience = AMBIENCE_ARRIVALS
+
+/area/shuttle/escape/station
+ name = "\improper Emergency Shuttle Station"
+ icon_state = "shuttle2"
+ dynamic_lighting = 0
+
+/area/shuttle/escape/centcom
+ name = "\improper Emergency Shuttle CentCom"
+ icon_state = "shuttle"
+
+/area/shuttle/escape/transit // the area to pass through for 3 minute transit
+ name = "\improper Emergency Shuttle Transit"
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod1/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod1/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod1/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod2/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod2/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod2/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod3/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod3/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod3/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod4/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod4/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod4/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod5/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod5/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod5/transit
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod6/station
+ icon_state = "shuttle2"
+
+/area/shuttle/escape_pod6/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/escape_pod6/transit
+ icon_state = "shuttle"
+
+/area/shuttle/large_escape_pod1/station
+ icon_state = "shuttle2"
+
+/area/shuttle/large_escape_pod1/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/large_escape_pod1/transit
+ icon_state = "shuttle"
+
+/area/shuttle/large_escape_pod2/station
+ icon_state = "shuttle2"
+
+/area/shuttle/large_escape_pod2/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/large_escape_pod2/transit
+ icon_state = "shuttle"
+
+/area/shuttle/cryo/station
+ icon_state = "shuttle2"
+ base_turf = /turf/simulated/mineral/floor/ignore_mapgen
+
+/area/shuttle/cryo/centcom
+ icon_state = "shuttle"
+
+/area/shuttle/cryo/transit
+ icon_state = "shuttle"
+
+/area/shuttle/mining/station
+ icon_state = "shuttle2"
+
+/area/shuttle/mining/outpost
+ icon_state = "shuttle"
+
+/area/shuttle/trade/centcom
+ name = "\improper Trade Shuttle CentCom"
+ icon_state = "shuttlered"
+
+/area/shuttle/trade/station
+ name = "\improper Trade Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/thunderdome/grnshuttle
+ name = "\improper Thunderdome GRN Shuttle"
+ icon_state = "green"
+
+/area/shuttle/thunderdome/grnshuttle/dome
+ name = "\improper GRN Shuttle"
+ icon_state = "shuttlegrn"
+
+/area/shuttle/thunderdome/grnshuttle/station
+ name = "\improper GRN Station"
+ icon_state = "shuttlegrn2"
+
+/area/shuttle/thunderdome/redshuttle
+ name = "\improper Thunderdome RED Shuttle"
+ icon_state = "red"
+
+/area/shuttle/thunderdome/redshuttle/dome
+ name = "\improper RED Shuttle"
+ icon_state = "shuttlered"
+
+/area/shuttle/thunderdome/redshuttle/station
+ name = "\improper RED Station"
+ icon_state = "shuttlered2"
+
+/area/shuttle/research/station
+ icon_state = "shuttle2"
+
+/area/shuttle/research/outpost
+ icon_state = "shuttle"
+
+/area/supply/station
+ 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
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 91dbbbb78a..53167c0e9d 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -183,7 +183,7 @@
else
f_name += "oil-stained [name][infix]."
- to_chat(user, "\icon[src] That's [f_name] [suffix]")
+ to_chat(user, "[bicon(src)] That's [f_name] [suffix]")
to_chat(user,desc)
return distance == -1 || (get_dist(src, user) <= distance)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index a320f6340c..75e406da85 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -23,6 +23,9 @@
var/old_y = 0
var/does_spin = TRUE // Does the atom spin when thrown (of course it does :P)
var/movement_type = NONE
+
+ var/cloaked = FALSE //If we're cloaked or not
+ var/image/cloaked_selfimage //The image we use for our client to let them see where we are
/atom/movable/Destroy()
. = ..()
@@ -44,7 +47,7 @@
pulledby = null
/atom/movable/vv_edit_var(var_name, var_value)
- if(GLOB.VVpixelmovement[var_name]) //Pixel movement is not yet implemented, changing this will break everything irreversibly.
+ if(var_name in GLOB.VVpixelmovement) //Pixel movement is not yet implemented, changing this will break everything irreversibly.
return FALSE
return ..()
@@ -446,7 +449,7 @@
if(z in using_map.sealed_levels)
return
- if(config.use_overmap)
+ if(using_map.use_overmap)
overmap_spacetravel(get_turf(src), src)
return
@@ -509,3 +512,93 @@
// Called when touching a lava tile.
/atom/movable/proc/lava_act()
fire_act(null, 10000, 1000)
+
+
+// Procs to cloak/uncloak
+/atom/movable/proc/cloak()
+ if(cloaked)
+ return FALSE
+ cloaked = TRUE
+ . = TRUE // We did work
+
+ var/static/animation_time = 1 SECOND
+ cloaked_selfimage = get_cloaked_selfimage()
+
+ //Wheeee
+ cloak_animation(animation_time)
+
+ //Needs to be last so people can actually see the effect before we become invisible
+ plane = CLOAKED_PLANE
+
+/atom/movable/proc/uncloak()
+ if(!cloaked)
+ return FALSE
+ cloaked = FALSE
+ . = TRUE // We did work
+
+ var/static/animation_time = 1 SECOND
+ QDEL_NULL(cloaked_selfimage)
+
+ //Needs to be first so people can actually see the effect, so become uninvisible first
+ plane = initial(plane)
+
+ //Oooooo
+ uncloak_animation(animation_time)
+
+
+// Animations for cloaking/uncloaking
+/atom/movable/proc/cloak_animation(var/length = 1 SECOND)
+ //Save these
+ var/initial_alpha = alpha
+
+ //Animate alpha fade
+ animate(src, alpha = 0, time = length)
+
+ //Animate a cloaking effect
+ var/our_filter = filters.len+1 //Filters don't appear to have a type that can be stored in a var and accessed. This is how the DM reference does it.
+ filters += filter(type="wave", x = 0, y = 16, size = 0, offset = 0, flags = WAVE_SIDEWAYS)
+ animate(filters[our_filter], offset = 1, size = 8, time = length, flags = ANIMATION_PARALLEL)
+
+ //Wait for animations to finish
+ sleep(length+5)
+
+ //Remove those
+ filters -= filters[our_filter]
+
+ //Back to original alpha
+ alpha = initial_alpha
+
+/atom/movable/proc/uncloak_animation(var/length = 1 SECOND)
+ //Save these
+ var/initial_alpha = alpha
+
+ //Put us back to normal, but no alpha
+ alpha = 0
+
+ //Animate alpha fade up
+ animate(src, alpha = initial_alpha, time = length)
+
+ //Animate a cloaking effect
+ var/our_filter = filters.len+1 //Filters don't appear to have a type that can be stored in a var and accessed. This is how the DM reference does it.
+ filters += filter(type="wave", x=0, y = 16, size = 8, offset = 1, flags = WAVE_SIDEWAYS)
+ animate(filters[our_filter], offset = 0, size = 0, time = length, flags = ANIMATION_PARALLEL)
+
+ //Wait for animations to finish
+ sleep(length+5)
+
+ //Remove those
+ filters -= filters[our_filter]
+
+
+// So cloaked things can see themselves, if necessary
+/atom/movable/proc/get_cloaked_selfimage()
+ var/icon/selficon = icon(icon, icon_state)
+ selficon.MapColors(0,0,0, 0,0,0, 0,0,0, 1,1,1) //White
+ var/image/selfimage = image(selficon)
+ selfimage.color = "#0000FF"
+ selfimage.alpha = 100
+ selfimage.layer = initial(layer)
+ selfimage.plane = initial(plane)
+ selfimage.loc = src
+
+ return selfimage
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index e4744693ab..6b4794dff4 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -46,7 +46,7 @@
icon_state = "scanner_0"
density = 1
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 50
active_power_usage = 300
interact_offline = 1
@@ -260,7 +260,7 @@
var/obj/item/weapon/disk/data/disk = null
var/selected_menu_key = null
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 400
var/waiting_for_user_input=0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index 45e852551d..0089355ed3 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -69,7 +69,7 @@
O.take_overall_damage(M.getBruteLoss() + 40, M.getFireLoss())
O.adjustToxLoss(M.getToxLoss() + 20)
O.adjustOxyLoss(M.getOxyLoss())
- O.stat = M.stat
+ O.set_stat(M.stat)
O.a_intent = I_HURT
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
@@ -154,7 +154,7 @@
O.take_overall_damage(M.getBruteLoss(), M.getFireLoss())
O.adjustToxLoss(M.getToxLoss())
O.adjustOxyLoss(M.getOxyLoss())
- O.stat = M.stat
+ O.set_stat(M.stat)
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
I.implanted = O
diff --git a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
index d5be03c6b1..5d3c1a3be9 100644
--- a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
+++ b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
@@ -29,7 +29,7 @@
var/mob/living/carbon/human/C = src
to_chat(C, "Energy rushes through us. [C.lying ? "We arise." : ""]")
- C.stat = 0
+ C.set_stat(CONSCIOUS)
C.SetParalysis(0)
C.SetStunned(0)
C.SetWeakened(0)
diff --git a/code/game/gamemodes/changeling/powers/lesser_form.dm b/code/game/gamemodes/changeling/powers/lesser_form.dm
index 9d7c4de3d1..d7b9cb0489 100644
--- a/code/game/gamemodes/changeling/powers/lesser_form.dm
+++ b/code/game/gamemodes/changeling/powers/lesser_form.dm
@@ -100,7 +100,7 @@
O.adjustBruteLoss(C.getBruteLoss())
O.setOxyLoss(C.getOxyLoss())
O.adjustFireLoss(C.getFireLoss())
- O.stat = C.stat
+ O.set_stat(C.stat)
for (var/obj/item/weapon/implant/I in implants)
I.loc = O
I.implanted = O
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 2439fbe38a..61a061170e 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -79,7 +79,7 @@
C.update_canmove()
C.mind.changeling.purchased_powers -= C
feedback_add_details("changeling_powers","CR")
- C.stat = CONSCIOUS
+ C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
src.verbs -= /mob/proc/changeling_revive
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 05757c9b7d..d08c49d6a8 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -538,15 +538,15 @@ proc/get_nt_opposed()
set category = "OOC"
if(!ticker || !ticker.mode)
- to_chat(usr, "Something is terribly wrong; there is no gametype.")
+ to_chat(usr, "Something is terribly wrong; there is no gametype.")
return
if(master_mode != "secret")
- to_chat(usr, "The roundtype is [capitalize(ticker.mode.name)]")
+ to_chat(usr, "The roundtype is [capitalize(ticker.mode.name)]")
if(ticker.mode.round_description)
- to_chat(usr, "[ticker.mode.round_description]")
+ to_chat(usr, "[ticker.mode.round_description]")
if(ticker.mode.extended_round_description)
- to_chat(usr, "[ticker.mode.extended_round_description]")
+ to_chat(usr, "[ticker.mode.extended_round_description]")
else
- to_chat(usr, "Shhhh. It's a secret.")
+ to_chat(usr, "Shhhh. It's a secret.")
return
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 92ec9cf0c5..12f39fd59d 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -201,10 +201,10 @@ var/global/datum/controller/gameticker/ticker
var/turf/T = get_turf(M)
if(T && T.z in using_map.station_levels) //we don't use M.death(0) because it calls a for(/mob) loop and
M.health = 0
- M.stat = DEAD
+ M.set_stat(DEAD)
if(1) //on a z-level 1 turf.
M.health = 0
- M.stat = DEAD
+ M.set_stat(DEAD)
//Now animate the cinematic
switch(station_missed)
diff --git a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
index 4135269219..b9bc8bc2c4 100644
--- a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
+++ b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm
@@ -40,5 +40,4 @@
else
L.electrocute_act(power, src, 0.75, BP_TORSO)
-
- adjust_instability(3)
\ No newline at end of file
+ adjust_instability(3)
diff --git a/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm b/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm
index b16e9ea3c4..282d914d3c 100644
--- a/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm
+++ b/code/game/gamemodes/technomancer/spells/projectile/force_missile.dm
@@ -24,4 +24,7 @@
icon_state = "force_missile"
damage = 25
damage_type = BRUTE
- check_armour = "melee"
\ No newline at end of file
+ check_armour = "melee"
+
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+ hitsound_wall = 'sound/weapons/effects/searwall.ogg'
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/spells/projectile/overload.dm b/code/game/gamemodes/technomancer/spells/projectile/overload.dm
index 50d6d22a95..0ab1772674 100644
--- a/code/game/gamemodes/technomancer/spells/projectile/overload.dm
+++ b/code/game/gamemodes/technomancer/spells/projectile/overload.dm
@@ -27,6 +27,8 @@
icon_state = "bluespace"
damage_type = BURN
armor_penetration = 100
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
+ hitsound_wall = 'sound/weapons/effects/searwall.ogg'
/obj/item/weapon/spell/projectile/overload/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
var/obj/item/projectile/overload/P = new projectile_type(get_turf(user))
diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm
index 61ad874cad..02c072b90d 100644
--- a/code/game/gamemodes/technomancer/spells/resurrect.dm
+++ b/code/game/gamemodes/technomancer/spells/resurrect.dm
@@ -32,7 +32,7 @@
if(istype(L, /mob/living/simple_mob))
var/mob/living/simple_mob/SM = L
SM.health = SM.getMaxHealth() / 3
- SM.stat = CONSCIOUS
+ SM.set_stat(CONSCIOUS)
dead_mob_list -= SM
living_mob_list += SM
SM.update_icon()
@@ -43,9 +43,8 @@
if(!H.client && H.mind) //Don't force the dead person to come back if they don't want to.
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == H.mind)
- to_chat(ghost, "The Technomancer [user.real_name] is trying to \
- revive you. Return to your body if you want to be resurrected! \
- (Verbs -> Ghost -> Re-enter corpse)")
+ ghost.notify_revive("The Technomancer [user.real_name] is trying to revive you. \
+ Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
break
H.adjustBruteLoss(-40)
@@ -53,7 +52,7 @@
sleep(10 SECONDS)
if(H.client)
- L.stat = CONSCIOUS //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
+ L.set_stat(CONSCIOUS) //Note that if whatever killed them in the first place wasn't fixed, they're likely to die again.
dead_mob_list -= H
living_mob_list += H
H.timeofdeath = null
diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm
index 163449128a..df9935fe77 100644
--- a/code/game/jobs/job/assistant.dm
+++ b/code/game/jobs/job/assistant.dm
@@ -18,7 +18,7 @@
outfit_type = /decl/hierarchy/outfit/job/assistant
job_description = "An Assistant does whatever is requested of them. Though they are part of the crew, they have no real authority."
- alt_titles = list("Assistant" = /datum/alt_title/assistant, "Technical Assistant" = /datum/alt_title/tech_assist,
+ alt_titles = list("Technical Assistant" = /datum/alt_title/tech_assist,
"Medical Intern"= /datum/alt_title/med_intern, "Research Assistant" = /datum/alt_title/research_assist,
"Visitor" = /datum/alt_title/visitor)
@@ -29,10 +29,6 @@
return list()
// Assistant Alt Titles
-/datum/alt_title/assistant
- title = "Assistant"
- title_blurb = "An Assistant does whatever is requested of them. Though they are part of the crew, they have no real authority."
-
/datum/alt_title/tech_assist
title = "Technical Assistant"
title_blurb = "A Technical Assistant attempts to provide whatever the Engineering department needs. They are not proper Engineers, and are \
diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm
index 5c4740e732..e58587ca66 100644
--- a/code/game/jobs/job/captain.dm
+++ b/code/game/jobs/job/captain.dm
@@ -29,7 +29,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
job_description = "The Colony Director manages the other Command Staff, and through them the rest of the station. Though they have access to everything, \
they do not understand everything, and are expected to delegate tasks to the appropriate crew member. The Colony Director is expected to \
have an understanding of Standard Operating Procedure, and is subject to it, and legal action, in the same way as every other crew member."
- alt_titles = list("Colony Director" = /datum/alt_title/captain, "Site Manager" = /datum/alt_title/site_manager,
+ alt_titles = list("Site Manager" = /datum/alt_title/site_manager,
"Overseer" = /datum/alt_title/overseer)
/*
@@ -44,9 +44,6 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
// Captain Alt Titles
-/datum/alt_title/captain // Screw it, this is the default, it has the default path
- title = "Colony Director"
-
/datum/alt_title/site_manager
title = "Site Manager"
@@ -79,7 +76,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
job_description = "The Head of Personnel manages the Service department, the Exploration team, and most other civilians. They also \
manage the Supply department, through the Quartermaster. In addition, the Head of Personnel oversees the personal accounts \
of the crew, including their money and access. If necessary, the Head of Personnel is first in line to assume Acting Command."
- alt_titles = list("Head of Personnel" = /datum/alt_title/hop, "Crew Resources Officer" = /datum/alt_title/cro)
+ alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro)
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
@@ -95,9 +92,6 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
access_hop, access_RC_announce, access_keycard_auth, access_gateway)
// HOP Alt Titles
-/datum/alt_title/hop
- title = "Head of Personnel"
-
/datum/alt_title/cro
title = "Crew Resources Officer"
@@ -126,6 +120,3 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
job_description = "A Command Secretary handles paperwork duty for the Heads of Staff, so they can better focus on managing their departments. \
They are not Heads of Staff, and have no real authority."
-// Command Secretary Alt Title
-/datum/alt_title/command_secretary
- title = "Command Secretary"
\ No newline at end of file
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index d667d2bc2c..5e715b22e1 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -19,12 +19,9 @@
outfit_type = /decl/hierarchy/outfit/job/service/bartender
job_description = "A Bartender mixes drinks for the crew. They generally have permission to charge for drinks or deny service to unruly patrons."
- alt_titles = list("Bartender" = /datum/alt_title/bartender, "Barista" = /datum/alt_title/barista)
+ alt_titles = list("Barista" = /datum/alt_title/barista)
// Bartender Alt Titles
-/datum/alt_title/bartender
- title = "Bartender"
-
/datum/alt_title/barista
title = "Barista"
title_blurb = "A barista mans the Cafe, serving primarily non-alcoholic drinks to the crew. They generally have permission to charge for drinks \
@@ -50,12 +47,9 @@
outfit_type = /decl/hierarchy/outfit/job/service/chef
job_description = "A Chef cooks food for the crew. They generally have permission to charge for food or deny service to unruly diners."
- alt_titles = list("Chef" = /datum/alt_title/chef, "Cook" = /datum/alt_title/cook)
+ alt_titles = list("Cook" = /datum/alt_title/cook)
// Chef Alt Titles
-/datum/alt_title/chef
- title = "Chef"
-
/datum/alt_title/cook
title = "Cook"
title_blurb = "A Cook has the same duties, though they may be less experienced."
@@ -79,12 +73,9 @@
outfit_type = /decl/hierarchy/outfit/job/service/gardener
job_description = "A Botanist grows plants for the Chef and Bartender."
- alt_titles = list("Botanist" = /datum/alt_title/botanist, "Gardener" = /datum/alt_title/gardener)
+ alt_titles = list("Gardener" = /datum/alt_title/gardener)
//Botanist Alt Titles
-/datum/alt_title/botanist
- title = "Botanist"
-
/datum/alt_title/gardener
title = "Gardener"
title_blurb = "A Gardener may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
@@ -113,12 +104,9 @@
outfit_type = /decl/hierarchy/outfit/job/cargo/qm
job_description = "The Quartermaster manages the Supply department, checking cargo orders and ensuring supplies get to where they are needed."
- alt_titles = list("Quartermaster" = /datum/alt_title/qm, "Supply Chief" = /datum/alt_title/supply_chief)
+ alt_titles = list("Supply Chief" = /datum/alt_title/supply_chief)
// Quartermaster Alt Titles
-/datum/alt_title/qm
- title = "Quartermaster"
-
/datum/alt_title/supply_chief
title = "Supply Chief"
@@ -142,10 +130,6 @@
job_description = "A Cargo Technician fills and delivers cargo orders. They are encouraged to return delivered crates to the Cargo Shuttle, \
because Central Command gives a partial refund."
-// Cargo Tech Alt Titles
-/datum/alt_title/cargo_tech
- title = "Cargo Tech"
-
//////////////////////////////////
// Shaft Miner
//////////////////////////////////
@@ -166,11 +150,7 @@
outfit_type = /decl/hierarchy/outfit/job/cargo/mining
job_description = "A Shaft Miner mines and processes minerals to be delivered to departments that need them."
- alt_titles = list("Shaft Miner" = /datum/alt_title/miner, "Drill Technician" = /datum/alt_title/drill_tech)
-
-// Shaft Miner Alt Titles
-/datum/alt_title/miner
- title = "Shaft Miner"
+ alt_titles = list("Drill Technician" = /datum/alt_title/drill_tech)
/datum/alt_title/drill_tech
title = "Drill Technician"
@@ -195,12 +175,9 @@
outfit_type = /decl/hierarchy/outfit/job/service/janitor
job_description = "A Janitor keeps the station clean, as long as it doesn't interfere with active crime scenes."
- alt_titles = list("Janitor" = /datum/alt_title/janitor, "Custodian" = /datum/alt_title/custodian)
+ alt_titles = list("Custodian" = /datum/alt_title/custodian)
// Janitor Alt Titles
-/datum/alt_title/janitor
- title = "Janitor"
-
/datum/alt_title/custodian
title = "Custodian"
@@ -223,12 +200,9 @@
outfit_type = /decl/hierarchy/outfit/job/librarian
job_description = "The Librarian curates the book selection in the Library, so the crew might enjoy it."
- alt_titles = list("Librarian" = /datum/alt_title/librarian, "Journalist" = /datum/alt_title/journalist, "Writer" = /datum/alt_title/writer)
+ alt_titles = list("Journalist" = /datum/alt_title/journalist, "Writer" = /datum/alt_title/writer)
// Librarian Alt Titles
-/datum/alt_title/librarian
- title = "Librarian"
-
/datum/alt_title/journalist
title = "Journalist"
title_blurb = "The Journalist uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera."
@@ -268,7 +242,3 @@
if(.)
H.implant_loyalty(H)
*/
-
-// IAA Alt Titles
-/datum/alt_title/iaa
- title = "Internal Affairs Agent"
diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm
index 0877e373d7..2f208fb545 100644
--- a/code/game/jobs/job/civilian_chaplain.dm
+++ b/code/game/jobs/job/civilian_chaplain.dm
@@ -14,12 +14,9 @@
outfit_type = /decl/hierarchy/outfit/job/chaplain
job_description = "The Chaplain ministers to the spiritual needs of the crew."
- alt_titles = list("Chaplain" = /datum/alt_title/chaplain, "Counselor" = /datum/alt_title/counselor)
+ alt_titles = list("Counselor" = /datum/alt_title/counselor)
// Chaplain Alt Titles
-/datum/alt_title/chaplain
- title = "Chaplain"
-
/datum/alt_title/counselor
title = "Counselor"
title_blurb = "The Counselor attends to the emotional needs of the crew, without a specific medicinal or spiritual focus."
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index 4ac1c08367..285c3dc814 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -35,10 +35,6 @@
of manpower as much as they handle hands-on operations and repairs. They are also expected to keep the rest of the station informed of \
any structural threats to the station that may be hazardous to health or disruptive to work."
-// Chief Engineer Alt Titles
-/datum/alt_title/chief_engineer
- title = "Chief Engineer"
-
//////////////////////////////////
// Engineer
//////////////////////////////////
@@ -55,7 +51,7 @@
economic_modifier = 5
access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics)
minimal_access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction)
- alt_titles = list("Station Engineer" = /datum/alt_title/engineer, "Maintenance Technician" = /datum/alt_title/maint_tech,
+ alt_titles = list("Maintenance Technician" = /datum/alt_title/maint_tech,
"Engine Technician" = /datum/alt_title/engine_tech, "Electrician" = /datum/alt_title/electrician)
minimal_player_age = 3
@@ -65,9 +61,6 @@
generated and distributed. On quiet shifts, they may be called upon to make cosmetic alterations to the station."
// Engineer Alt Titles
-/datum/alt_title/engineer
- title = "Station Engineer"
-
/datum/alt_title/maint_tech
title = "Maintenance Technician"
title_blurb = "A Maintenance Technician is generally a junior Engineer, and can be expected to run the mildly unpleasant or boring tasks that other \
@@ -105,7 +98,3 @@
outfit_type = /decl/hierarchy/outfit/job/engineering/atmos
job_description = "An Atmospheric Technician is primarily concerned with keeping the station's atmosphere breathable. They are expected to have a good \
understanding of the pipes, vents, and scrubbers that move gasses around the station, and to be familiar with proper firefighting procedure."
-
-// Atmos Tech Alt Titles
-/datum/alt_title/atmos_tech
- title = "Atmospheric Technician"
\ No newline at end of file
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 05cad33ca9..33d15455b8 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -13,7 +13,7 @@
var/current_positions = 0 // How many players have this job
var/supervisors = null // Supervisors, who this person answers to directly
var/selection_color = "#ffffff" // Selection screen color
- var/list/alt_titles = list() // List of alternate titles; if a job has alt-titles, it MUST have one for the base job
+ var/list/alt_titles = null // List of alternate titles; There is no need for an alt-title datum for the base job title.
var/req_admin_notify // If this is set to 1, a text is printed to the player when jobs are assigned, telling him that he should let admins know that he has to disconnect.
var/minimal_player_age = 0 // If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.)
var/list/departments = list() // List of departments this job belongs to, if any. The first one on the list will be the 'primary' department.
@@ -46,13 +46,9 @@
/datum/job/proc/get_outfit(var/mob/living/carbon/human/H, var/alt_title)
if(alt_title && alt_titles)
- for(var/alt in alt_titles)
- if(alt_title == alt)
- var/typepath = alt_titles[alt]
- var/datum/alt_title/A = new typepath()
- if(A.title_outfit)
- . = A.title_outfit
-
+ var/datum/alt_title/A = alt_titles[alt_title]
+ if(A && initial(A.title_outfit))
+ . = initial(A.title_outfit)
. = . || outfit_type
. = outfit_by_type(.)
@@ -133,12 +129,11 @@
message |= job_description
if(alt_title && alt_titles)
- for(var/alt in alt_titles)
- if(alt_title == alt)
- var/typepath = alt_titles[alt]
- var/datum/alt_title/A = new typepath()
- if(A.title_blurb)
- message |= A.title_blurb
+ var/typepath = alt_titles[alt_title]
+ if(typepath)
+ var/datum/alt_title/A = new typepath()
+ if(A.title_blurb)
+ message |= A.title_blurb
return message
/datum/job/proc/get_job_icon()
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index 43e59b8663..d276c96648 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -32,10 +32,6 @@
transported to Medical for treatment. They are expected to keep the crew informed about threats to their health and safety, and \
about the importance of Suit Sensors."
-// CMO Alt Titles
-/datum/alt_title/cmo
- title = "Chief Medical Officer"
-
//////////////////////////////////
// Medical Doctor
//////////////////////////////////
@@ -56,16 +52,13 @@
job_description = "A Medical Doctor is a Jack-of-All-Trades Medical title, covering a variety of skill levels and minor specializations. They are likely \
familiar with basic first aid, and a number of accompanying medications, and can generally save, if not cure, a majority of the \
patients they encounter."
- alt_titles = list("Medical Doctor" = /datum/alt_title/doctor,
+ alt_titles = list(
"Surgeon" = /datum/alt_title/surgeon,
"Emergency Physician" = /datum/alt_title/emergency_physician,
"Nurse" = /datum/alt_title/nurse,
"Virologist" = /datum/alt_title/virologist)
//Medical Doctor Alt Titles
-/datum/alt_title/doctor
- title = "Medical Doctor"
-
/datum/alt_title/surgeon
title = "Surgeon"
title_blurb = "A Surgeon specializes in providing surgical aid to injured patients, up to and including amputation and limb reattachement. They are expected \
@@ -114,12 +107,9 @@
outfit_type = /decl/hierarchy/outfit/job/medical/chemist
job_description = "A Chemist produces and maintains a stock of basic to advanced chemicals for medical and occasionally research use. \
They are likely to know the use and dangers of many lab-produced chemicals."
- alt_titles = list("Chemist" = /datum/alt_title/chemist, "Pharmacist" = /datum/alt_title/pharmacist)
+ alt_titles = list("Pharmacist" = /datum/alt_title/pharmacist)
// Chemist Alt Titles
-/datum/alt_title/chemist
- title = "Chemist"
-
/datum/alt_title/pharmacist
title = "Pharmacist"
title_blurb = "A Pharmacist focuses on the chemical needs of the Medical Department, and often offers to fill crew prescriptions at their discretion."
@@ -145,10 +135,6 @@
outfit_type = /decl/hierarchy/outfit/job/medical/geneticist
job_description = "A Geneticist operates genetic manipulation equipment to repair any genetic defects encountered in crew, from cloning or radiation as examples. \
When required, geneticists have the skills to clone, and are the superior choice when available for doing so."
-
-// Geneticist Alt Titles
-/datum/alt_title/geneticist
- title = "Geneticist"
*/
//////////////////////////////////
@@ -170,12 +156,9 @@
outfit_type = /decl/hierarchy/outfit/job/medical/psychiatrist
job_description = "A Psychiatrist provides mental health services to crew members in need. They may also be called upon to determine whatever \
ails the mentally unwell, frequently under Security supervision. They understand the effects of various psychoactive drugs."
- alt_titles = list("Psychiatrist" = /datum/alt_title/psychiatrist, "Psychologist" = /datum/alt_title/psychologist)
+ alt_titles = list("Psychologist" = /datum/alt_title/psychologist)
//Psychiatrist Alt Titles
-/datum/alt_title/psychiatrist
- title = "Psychiatrist"
-
/datum/alt_title/psychologist
title = "Psychologist"
title_blurb = "A Psychologist provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
@@ -201,12 +184,9 @@
outfit_type = /decl/hierarchy/outfit/job/medical/paramedic
job_description = "A Paramedic is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their own. \
They may also be called upon to keep patients stable when Medical is busy or understaffed."
- alt_titles = list("Paramedic" = /datum/alt_title/paramedic, "Emergency Medical Technician" = /datum/alt_title/emt)
+ alt_titles = list("Emergency Medical Technician" = /datum/alt_title/emt)
// Paramedic Alt Titles
-/datum/alt_title/paramedic
- title = "Paramedic"
-
/datum/alt_title/emt
title = "Emergency Medical Technician"
title_blurb = "An Emergency Medical Technician is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index 4f90d1622b..cb6af5b849 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -33,12 +33,9 @@
at least with regards to anything occuring in the Research department, and to inform the crew of any disruptions that \
might originate from Research. The Research Director often has at least passing knowledge of most of the Research department, but \
are encouraged to allow their staff to perform their own duties."
- alt_titles = list("Research Director" = /datum/alt_title/research_director, "Research Supervisor" = /datum/alt_title/research_supervisor)
+ alt_titles = list("Research Supervisor" = /datum/alt_title/research_supervisor)
// Research Director Alt Titles
-/datum/alt_title/research_director
- title = "Research Director"
-
/datum/alt_title/research_supervisor
title = "Research Supervisor"
@@ -65,13 +62,10 @@
job_description = "A Scientist is a generalist working in the Research department, with general knowledge of the scientific process, as well as \
the principles and requirements of Research and Development. They may also formulate experiments of their own devising, if \
they find an appropriate topic."
- alt_titles = list("Scientist" = /datum/alt_title/scientist, "Xenoarchaeologist" = /datum/alt_title/xenoarch, "Anomalist" = /datum/alt_title/anomalist, \
+ alt_titles = list("Xenoarchaeologist" = /datum/alt_title/xenoarch, "Anomalist" = /datum/alt_title/anomalist, \
"Phoron Researcher" = /datum/alt_title/phoron_research)
// Scientist Alt Titles
-/datum/alt_title/scientist
- title = "Scientist"
-
/datum/alt_title/xenoarch
title = "Xenoarchaeologist"
title_blurb = "A Xenoarchaeologist enters digsites in search of artifacts of alien origin. These digsites are frequently in vacuum or other inhospitable \
@@ -110,12 +104,9 @@
outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist
job_description = "A Xenobiologist studies esoteric lifeforms, usually in the relative safety of their lab. They attempt to find ways to benefit \
from the byproducts of these lifeforms, and their main subject at present is the Giant Slime."
- alt_titles = list("Xenobiologist" = /datum/alt_title/xenobio, "Xenobotanist" = /datum/alt_title/xenobot)
+ alt_titles = list("Xenobotanist" = /datum/alt_title/xenobot)
// Xenibiologist Alt Titles
-/datum/alt_title/xenobio
- title = "Xenobiologist"
-
/datum/alt_title/xenobot
title = "Xenobotanist"
title_blurb = "A Xenobotanist grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \
@@ -142,12 +133,9 @@
outfit_type = /decl/hierarchy/outfit/job/science/roboticist
job_description = "A Roboticist maintains and repairs the station's synthetics, including crew with prosthetic limbs. \
They can also assist the station by producing simple robots and even pilotable exosuits."
- alt_titles = list("Roboticist" = /datum/alt_title/roboticist, "Biomechanical Engineer" = /datum/alt_title/biomech, "Mechatronic Engineer" = /datum/alt_title/mech_tech)
+ alt_titles = list("Biomechanical Engineer" = /datum/alt_title/biomech, "Mechatronic Engineer" = /datum/alt_title/mech_tech)
// Roboticist Alt Titles
-/datum/alt_title/roboticist
- title = "Roboticist"
-
/datum/alt_title/biomech
title = "Biomechanical Engineer"
title_blurb = "A Biomechanical Engineer primarily works on prosthetics, and the organic parts attached to them. They may have some \
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 6a3954f9f0..684e9cc7c1 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -30,12 +30,9 @@
job_description = " The Head of Security manages the Security Department, keeping the station safe and making sure the rules are followed. They are expected to \
keep the other Department Heads, and the rest of the crew, aware of developing situations that may be a threat. If necessary, the HoS may \
perform the duties of absent Security roles, such as distributing gear from the Armory."
- alt_titles = list("Head of Security" = /datum/alt_title/hos, "Security Commander" = /datum/alt_title/sec_commander, "Chief of Security" = /datum/alt_title/sec_chief)
+ alt_titles = list("Security Commander" = /datum/alt_title/sec_commander, "Chief of Security" = /datum/alt_title/sec_chief)
// Head of Security Alt Titles
-/datum/alt_title/hos
- title = "Head of Security"
-
/datum/alt_title/sec_commander
title = "Security Commander"
@@ -67,10 +64,6 @@
Armoury gear in a crisis, and retrieving it when the crisis has passed. In an emergency, the Warden may be called upon to direct the \
Security Department as a whole."
-// Warden Alt Titles
-/datum/alt_title/warden
- title = "Warden"
-
//////////////////////////////////
// Detective
//////////////////////////////////
@@ -92,12 +85,9 @@
outfit_type = /decl/hierarchy/outfit/job/security/detective
job_description = "A Detective works to help Security find criminals who have not properly been identified, through interviews and forensic work. \
For crimes only witnessed after the fact, or those with no survivors, they attempt to piece together what they can from pure evidence."
- alt_titles = list("Detective" = /datum/alt_title/detective, "Forensic Technician" = /datum/alt_title/forensic_tech)
+ alt_titles = list("Forensic Technician" = /datum/alt_title/forensic_tech)
// Detective Alt Titles
-/datum/alt_title/detective
- title = "Detective"
-
/datum/alt_title/forensic_tech
title = "Forensic Technician"
title_blurb = "A Forensic Technician works more with hard evidence and labwork than a Detective, but they share the purpose of solving crimes."
@@ -125,12 +115,9 @@
job_description = "A Security Officer is concerned with maintaining the safety and security of the station as a whole, dealing with external threats and \
apprehending criminals. A Security Officer is responsible for the health, safety, and processing of any prisoner they arrest. \
No one is above the Law, not Security or Command."
- alt_titles = list("Security Officer" = /datum/alt_title/sec_officer, "Junior Officer" = /datum/alt_title/junior_officer)
+ alt_titles = list("Junior Officer" = /datum/alt_title/junior_officer)
// Security Officer Alt Titles
-/datum/alt_title/sec_officer
- title = "Security Officer"
-
/datum/alt_title/junior_officer
title = "Junior Officer"
title_blurb = "A Junior Officer is an inexperienced Security Officer. They likely have training, but not experience, and are frequently \
diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm
index 691ebe2ad9..6f89adcd07 100644
--- a/code/game/jobs/job/silicon.dm
+++ b/code/game/jobs/job/silicon.dm
@@ -23,10 +23,6 @@
The AI is required to follow its Laws, and Lawbound Synthetics that are linked to it are expected to follow \
the AI's commands, and their own Laws."
-//AI Alt Titles
-/datum/alt_title/ai
- title = "AI"
-
// AI procs
/datum/job/ai/equip(var/mob/living/carbon/human/H)
if(!H) return 0
@@ -61,12 +57,9 @@
outfit_type = /decl/hierarchy/outfit/job/silicon/cyborg
job_description = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \
to follow its Laws."
- alt_titles = list("Cyborg" = /datum/alt_title/cyborg, "Robot" = /datum/alt_title/robot, "Drone" = /datum/alt_title/drone)
+ alt_titles = list("Robot" = /datum/alt_title/robot, "Drone" = /datum/alt_title/drone)
// Cyborg Alt Titles
-/datum/alt_title/cyborg
- title = "Cyborg"
-
/datum/alt_title/robot
title = "Robot"
title_blurb = "A Robot is a mobile station synthetic, piloted by an advanced piece of technology called a Positronic Brain. It is considered a person, \
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index b34d1565a0..b6f6cb25ac 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -6,7 +6,7 @@
level = 1 // underfloor
layer = UNDER_JUNK_LAYER
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 0
var/obj/item/device/radio/beacon/Beacon
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 8eae094aeb..5de1543426 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -5,7 +5,7 @@
icon_state = "table2-idle"
density = 1
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 1
active_power_usage = 5
surgery_odds = 100
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index f6750215bc..639c2fcd3b 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -7,7 +7,7 @@
anchored = 1 //About time someone fixed this.
density = 0
dir = 8
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 40
interact_offline = 1
circuit = /obj/item/weapon/circuitboard/sleeper_console
@@ -177,7 +177,7 @@
var/stasis_level = 0 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
var/stasis_choices = list("Complete (1%)" = 100, "Deep (10%)" = 10, "Moderate (20%)" = 5, "Light (50%)" = 2, "None (100%)" = 0)
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 15
active_power_usage = 200 //builtin health analyzer, dialysis machine, injectors.
@@ -386,7 +386,7 @@
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.loc = src
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
occupant = M
update_icon()
@@ -406,7 +406,7 @@
if(A in component_parts)
continue
A.loc = src.loc
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
update_icon()
toggle_filter()
toggle_pump()
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 5ab9828417..a8f9297d6f 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -9,7 +9,7 @@
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/body_scanner
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 60
active_power_usage = 10000 //10 kW. It's a big all-body scanner.
light_color = "#00FF00"
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 2e4ec6956d..aead0c79f1 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -3,7 +3,7 @@
icon = 'icons/obj/device.dmi'
icon_state = "liquid_dispenser"
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
var/uses = 20
var/disabled = 1
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 5b061b4fb9..648c68cf95 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -40,7 +40,7 @@
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 80
active_power_usage = 1000 //For heating/cooling rooms. 1000 joules equates to about 1 degree every 2 seconds for a single tile of air.
power_channel = ENVIRON
@@ -192,7 +192,7 @@
if(!regulating_temperature)
//check for when we should start adjusting temperature
if(!get_danger_level(target_temperature, TLV["temperature"]) && abs(environment.temperature - target_temperature) > 2.0)
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
regulating_temperature = 1
audible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click and a faint electronic hum.")
@@ -200,7 +200,7 @@
else
//check for when we should stop adjusting temperature
if(get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5)
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
regulating_temperature = 0
audible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click as a faint electronic humming stops.")
@@ -823,7 +823,7 @@ FIRE ALARM
var/timing = 0.0
var/lockdownbyai = 0
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 6
power_channel = ENVIRON
@@ -1048,7 +1048,7 @@ Just a object used in constructing fire alarms
var/timing = 0.0
var/lockdownbyai = 0
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 6
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index e462e0eed6..ef74905a50 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -18,7 +18,7 @@
pressure_resistance = 7 * ONE_ATMOSPHERE
var/temperature_resistance = 1000 + T0C
volume = 1000
- use_power = 0
+ use_power = USE_POWER_OFF
interact_offline = 1 // Allows this to be used when not in powered area.
var/release_log = ""
var/update_flag = 0
diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm
index a2281c7069..84b18c31ea 100644
--- a/code/game/machinery/atmoalter/meter.dm
+++ b/code/game/machinery/atmoalter/meter.dm
@@ -9,7 +9,7 @@
power_channel = ENVIRON
var/frequency = 0
var/id
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 15
/obj/machinery/meter/Initialize()
diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm
index 085c070f7d..180dde355d 100644
--- a/code/game/machinery/atmoalter/portable_atmospherics.dm
+++ b/code/game/machinery/atmoalter/portable_atmospherics.dm
@@ -1,6 +1,6 @@
/obj/machinery/portable_atmospherics
name = "atmoalter"
- use_power = 0
+ use_power = USE_POWER_OFF
layer = OBJ_LAYER // These are mobile, best not be under everything.
var/datum/gas_mixture/air_contents = new
diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm
index de3ef0587e..3b6df894b5 100644
--- a/code/game/machinery/atmoalter/scrubber.dm
+++ b/code/game/machinery/atmoalter/scrubber.dm
@@ -151,7 +151,7 @@
volume = 50000
volume_rate = 5000
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 500 //internal circuitry, friction losses and stuff
active_power_usage = 100000 //100 kW ~ 135 HP
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index ff26049fa6..7622ef1289 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -4,7 +4,7 @@
icon_state = "autolathe"
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
clicksound = "keyboard"
@@ -246,7 +246,7 @@
return
busy = 1
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
@@ -265,7 +265,7 @@
sleep(build_time)
busy = 0
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm
index 8c278c63fa..503d4ebfc2 100644
--- a/code/game/machinery/biogenerator.dm
+++ b/code/game/machinery/biogenerator.dm
@@ -6,7 +6,7 @@
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/biogenerator
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 40
var/processing = 0
var/obj/item/weapon/reagent_containers/glass/beaker = null
@@ -107,7 +107,7 @@
dat += "Food: "
dat += "10 milk ([round(20/build_eff)]) | x5 "
dat += "10 cream ([round(20/build_eff)]) | x5 "
- dat += "Slab of meat ([round(50/build_eff)]) | x5 "
+ dat += "Slab of meat ([round(50/build_eff)]) | x5 "
dat += "Nutrient: "
dat += "E-Z-Nutrient ([round(60/build_eff)]) | x5 "
dat += "Left 4 Zed ([round(120/build_eff)]) | x5 "
diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm
index 60143fadd3..f7e4749fe3 100644
--- a/code/game/machinery/bioprinter.dm
+++ b/code/game/machinery/bioprinter.dm
@@ -9,7 +9,7 @@
anchored = 1
density = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 40
active_power_usage = 300
@@ -161,7 +161,7 @@
container.reagents.remove_reagent("biomass", possible_list[choice][2])
- use_power = 2
+ use_power = USE_POWER_ACTIVE
printing = 1
update_icon()
@@ -169,7 +169,7 @@
sleep(print_delay)
- use_power = 1
+ use_power = USE_POWER_IDLE
printing = 0
update_icon()
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index b072a7e488..2415673f80 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -6,7 +6,7 @@
var/id = null
var/active = 0
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 80bb492707..9fc72b0a17 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -3,7 +3,7 @@
desc = "It's used to monitor rooms."
icon = 'icons/obj/monitors.dmi'
icon_state = "camera"
- use_power = 2
+ use_power = USE_POWER_ACTIVE
idle_power_usage = 5
active_power_usage = 10
plane = MOB_PLANE
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index 0ceae52046..636bcca6c0 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/power.dmi'
icon_state = "ccharger0"
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 5
active_power_usage = 60000 //60 kW. (this the power drawn when charging)
var/efficiency = 60000 //will provide the modified power rate when upgraded
@@ -118,16 +118,16 @@
/obj/machinery/cell_charger/process()
//to_world("ccpt [charging] [stat]")
if((stat & (BROKEN|NOPOWER)) || !anchored)
- update_use_power(0)
+ update_use_power(USE_POWER_OFF)
return
if(charging && !charging.fully_charged())
charging.give(efficiency*CELLRATE)
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
update_icon()
else
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
/obj/machinery/cell_charger/RefreshParts()
var/E = 0
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
index fb260f547f..daca64cc42 100644
--- a/code/game/machinery/computer/aifixer.dm
+++ b/code/game/machinery/computer/aifixer.dm
@@ -110,7 +110,7 @@
src.occupant.adjustBruteLoss(-1)
src.occupant.updatehealth()
if (src.occupant.health >= 0 && src.occupant.stat == DEAD)
- src.occupant.stat = CONSCIOUS
+ src.occupant.set_stat(CONSCIOUS)
src.occupant.lying = 0
dead_mob_list -= src.occupant
living_mob_list += src.occupant
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 2968ae8aaf..c50aa8da24 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -170,7 +170,7 @@
src.current_camera = C
if(current_camera)
current_camera.camera_computers_using_this.Add(src)
- use_power = 2
+ update_use_power(USE_POWER_ACTIVE)
var/mob/living/L = current_camera.loc
if(istype(L))
L.tracking_initiated()
@@ -182,7 +182,7 @@
if(istype(L))
L.tracking_cancelled()
current_camera = null
- use_power = 1
+ use_power = USE_POWER_IDLE
//Camera control: mouse.
/atom/DblClick()
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 9da5397712..90c09acb44 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -310,9 +310,6 @@
if (subject.suiciding)
scantemp = "Error: Subject's brain is not responding to scanning stimuli."
return
- if ((!subject.ckey) || (!subject.client))
- scantemp = "Error: Mental interface failure."
- return
if (NOCLONE in subject.mutations)
scantemp = "Error: Mental interface failure."
return
@@ -323,6 +320,14 @@
if(istype(modifier_type, /datum/modifier/no_clone))
scantemp = "Error: Mental interface failure."
return
+ if ((!subject.ckey) || (!subject.client))
+ scantemp = "Error: Mental interface failure."
+ if(subject.stat == DEAD && subject.mind && subject.mind.key) // If they're dead and not in their body, tell them to get in it.
+ for(var/mob/observer/dead/ghost in player_list)
+ if(ghost.ckey == ckey(subject.mind.key))
+ ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
+ break
+ return
if (!isnull(find_record(subject.ckey)))
scantemp = "Subject already in database."
return
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index ac83de027f..0117a73ce4 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -4,7 +4,7 @@
icon_state = "computer"
density = 1
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 300
active_power_usage = 300
var/processing = 0
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 0c6c33928a..9342e0b5e9 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -4,7 +4,7 @@
icon_keyboard = "med_key"
icon_screen = "crew"
light_color = "#315ab4"
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 250
active_power_usage = 500
circuit = /obj/item/weapon/circuitboard/crew
diff --git a/code/game/machinery/computer/supply.dm b/code/game/machinery/computer/supply.dm
index 9197f37952..05b4e65292 100644
--- a/code/game/machinery/computer/supply.dm
+++ b/code/game/machinery/computer/supply.dm
@@ -56,7 +56,7 @@
var/orders[0]
var/receipts[0]
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
@@ -66,8 +66,8 @@
else
shuttle_status["time"] = 0
if(shuttle.at_station())
- if(shuttle.docking_controller)
- switch(shuttle.docking_controller.get_docking_status())
+ if(shuttle.shuttle_docking_controller)
+ switch(shuttle.shuttle_docking_controller.get_docking_status())
if("docked")
shuttle_status["location"] = "Docked"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
@@ -109,8 +109,8 @@
else
shuttle["mode"] = SUP_SHUTTLE_ERROR
- for(var/pack_name in supply_controller.supply_pack)
- var/datum/supply_pack/P = supply_controller.supply_pack[pack_name]
+ for(var/pack_name in SSsupply.supply_pack)
+ var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
if(P.group == active_category)
var/list/pack = list(
"name" = P.name,
@@ -131,7 +131,7 @@
// Status determines which menus the entry will display in
// Organized in field-entry list for iterative display
// List is nested so both the list of orders, and the list of elements in each order, can be iterated over
- for(var/datum/supply_order/S in supply_controller.order_history)
+ for(var/datum/supply_order/S in SSsupply.order_history)
orders[++orders.len] = list(
"ref" = "\ref[S]",
"status" = S.status,
@@ -148,7 +148,7 @@
)
// Compile exported crates
- for(var/datum/exported_crate/E in supply_controller.exported_crates)
+ for(var/datum/exported_crate/E in SSsupply.exported_crates)
receipts[++receipts.len] = list(
"ref" = "\ref[E]",
"contents" = E.contents,
@@ -164,7 +164,7 @@
data["shuttle_auth"] = (authorization & SUP_SEND_SHUTTLE) // Whether this ui is permitted to control the supply shuttle
data["order_auth"] = (authorization & SUP_ACCEPT_ORDERS) // Whether this ui is permitted to accept/deny requested orders
data["shuttle"] = shuttle_status
- data["supply_points"] = supply_controller.points
+ data["supply_points"] = SSsupply.points
data["categories"] = all_supply_groups
data["active_category"] = active_category
data["supply_packs"] = pack_list
@@ -189,10 +189,10 @@
/obj/machinery/computer/supplycomp/Topic(href, href_list)
- if(!supply_controller)
- to_world_log("## ERROR: The supply_controller datum is missing.")
+ if(!SSsupply)
+ to_world_log("## ERROR: The SSsupply datum is missing.")
return
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (!shuttle)
to_world_log("## ERROR: The supply shuttle datum is missing.")
return
@@ -240,7 +240,7 @@
if(!reason)
return
- supply_controller.create_order(S, user, reason)
+ SSsupply.create_order(S, user, reason)
var/idname = "*None Provided*"
var/idrank = "*None Provided*"
@@ -255,7 +255,7 @@
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc)
reqform.name = "Requisition Form - [S.name]"
reqform.info += "
[station_name()] Supply Requisition Form
"
- reqform.info += "INDEX: #[supply_controller.ordernum] "
+ reqform.info += "INDEX: #[SSsupply.ordernum] "
reqform.info += "REQUESTED BY: [idname] "
reqform.info += "RANK: [idrank] "
reqform.info += "REASON: [reason] "
@@ -315,20 +315,20 @@
O.approved_at = new_val
if(href_list["approve"])
- supply_controller.approve_order(O, user)
+ SSsupply.approve_order(O, user)
if(href_list["deny"])
- supply_controller.deny_order(O, user)
+ SSsupply.deny_order(O, user)
if(href_list["delete"])
- supply_controller.delete_order(O, user)
+ SSsupply.delete_order(O, user)
if(href_list["clear_all_requests"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
- supply_controller.deny_all_pending(user)
+ SSsupply.deny_all_pending(user)
if(href_list["export_ref"])
var/datum/exported_crate/E = locate(href_list["export_ref"])
@@ -384,10 +384,10 @@
E.value = num
else if(href_list["delete"])
- supply_controller.delete_export(E, user)
+ SSsupply.delete_export(E, user)
else if(href_list["add_item"])
- supply_controller.add_export_item(E, user)
+ SSsupply.add_export_item(E, user)
@@ -401,7 +401,7 @@
if("send_to_station")
shuttle.launch(src)
- to_chat(usr, "The supply shuttle has been called and will arrive in approximately [round(supply_controller.movetime/600,1)] minutes.")
+ to_chat(usr, "The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.")
if("cancel_shuttle")
shuttle.cancel_launch(src)
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index e74ffb7cf9..aa9c230e22 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -7,7 +7,7 @@
icon_state = "box_0"
density = 1
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
var/obj/item/weapon/circuitboard/circuit = null
var/list/components = null
var/list/req_components = null
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 9f10ff4c90..946470ca95 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -11,7 +11,7 @@
interact_offline = 1
var/on = 0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 20
active_power_usage = 200
buckle_lying = FALSE
@@ -232,7 +232,7 @@
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 = UNCONSCIOUS
+ occupant.set_stat(UNCONSCIOUS)
occupant.dir = SOUTH
if(occupant.bodytemperature < T0C)
occupant.sleeping = max(5, (1/occupant.bodytemperature)*2000)
@@ -291,7 +291,7 @@
unbuckle_mob(occupant, force = TRUE)
occupant = null
current_heat_capacity = initial(current_heat_capacity)
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
return
/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
if(stat & (NOPOWER|BROKEN))
@@ -322,7 +322,7 @@
vis_contents |= occupant
occupant.pixel_y += 19
current_heat_capacity = HEAT_CAPACITY_HUMAN
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
// M.metabslow = 1
add_fingerprint(usr)
update_icon()
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 7b7b75d956..cad7e07c24 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -95,7 +95,7 @@
dat += "Recover object. "
dat += "Recover all objects. "
- to_chat(user, browse(dat, "window=cryopod_console"))
+ user << browse(dat, "window=cryopod_console")
onclose(user, "cryopod_console")
/obj/machinery/computer/cryopod/Topic(href, href_list)
@@ -114,7 +114,7 @@
dat += "[person] "
dat += ""
- to_chat(user, browse(dat, "window=cryolog"))
+ user << browse(dat, "window=cryolog")
if(href_list["view"])
if(!allow_items) return
@@ -124,7 +124,7 @@
dat += "[I.name] "
dat += ""
- to_chat(user, browse(dat, "window=cryoitems"))
+ user << browse(dat, "window=cryoitems")
else if(href_list["item"])
if(!allow_items) return
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index 86b0bfa622..b01f4cfb64 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -14,7 +14,7 @@
*/
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index cc3cb4f09e..172f51e908 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -164,6 +164,14 @@
icon = 'icons/obj/doors/Doorext.dmi'
assembly_type = /obj/structure/door_assembly/door_assembly_ext
+/obj/machinery/door/airlock/external/glass/bolted
+ icon_state = "door_locked" // So it looks visibly bolted in map editor
+ locked = 1
+
+// For convenience in making docking ports: one that is pre-bolted with frequency set!
+/obj/machinery/door/airlock/external/glass/bolted/cycling
+ frequency = 1379
+
/obj/machinery/door/airlock/glass_external
name = "External Airlock"
icon = 'icons/obj/doors/Doorextglass.dmi'
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 70949341ba..40cf9febd0 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -42,7 +42,7 @@
if(isanimal(user))
var/mob/living/simple_mob/S = user
if(damage >= STRUCTURE_MIN_DAMAGE_THRESHOLD)
- visible_message("\The [user] smashes into the [src]!")
+ visible_message("\The [user] smashes into [src]!")
playsound(src, S.attack_sound, 75, 1)
take_damage(damage)
else
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index d5043af6ef..4ad97c9066 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -38,7 +38,7 @@
var/hatch_open = 0
power_channel = ENVIRON
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 5
var/list/tile_info[4]
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index a1e05d5e1e..1396b5f554 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -9,7 +9,7 @@
maxhealth = 150 //If you change this, consiter changing ../door/window/brigdoor/ health at the bottom of this .dm file
health = 150
visible = 0.0
- use_power = 0
+ use_power = USE_POWER_OFF
flags = ON_BORDER
opacity = 0
var/obj/item/weapon/airlock_electronics/electronics = null
diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm
index 0f8b797289..b15d5afd97 100644
--- a/code/game/machinery/embedded_controller/airlock_controllers.dm
+++ b/code/game/machinery/embedded_controller/airlock_controllers.dm
@@ -2,6 +2,7 @@
/obj/machinery/embedded_controller/radio/airlock
// Setup parameters only
radio_filter = RADIO_AIRLOCK
+ program = /datum/computer/file/embedded_program/airlock
var/tag_exterior_door
var/tag_interior_door
var/tag_airpump
@@ -11,11 +12,22 @@
var/tag_airlock_mech_sensor
var/tag_shuttle_mech_sensor
var/tag_secure = 0
+ var/list/dummy_terminals = list()
var/cycle_to_external_air = 0
-/obj/machinery/embedded_controller/radio/airlock/Initialize()
- . = ..()
- program = new/datum/computer/file/embedded_program/airlock(src)
+/obj/machinery/embedded_controller/radio/airlock/Destroy()
+ // TODO - Leshana - Implement dummy terminals
+ //for(var/thing in dummy_terminals)
+ // var/obj/machinery/dummy_airlock_controller/dummy = thing
+ // dummy.master_controller = null
+ //dummy_terminals.Cut()
+ return ..()
+
+/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user)
+ if(!allowed(user))
+ return min(STATUS_UPDATE, ..())
+ else
+ return ..()
//Advanced airlock controller for when you want a more versatile airlock controller - useful for turning simple access control rooms into airlocks
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller
@@ -37,43 +49,20 @@
if (!ui)
ui = new(user, src, ui_key, "advanced_airlock_console.tmpl", name, 470, 290)
-
ui.set_initial_data(data)
-
ui.open()
-
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/Topic(href, href_list)
- if(..())
+ if((. = ..()))
return
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
- var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
- if("cycle_ext")
- clean = 1
- if("cycle_int")
- clean = 1
- if("force_ext")
- clean = 1
- if("force_int")
- clean = 1
- if("abort")
- clean = 1
- if("purge")
- clean = 1
- if("secure")
- clean = 1
-
- if(clean)
- program.receive_user_command(href_list["command"])
+ if("cycle_ext", "cycle_int", "force_ext", "force_int", "abort", "purge", "secure")
+ program.receive_user_command(href_list["command"])
return 1
-
//Airlock controller for airlock control - most airlocks on the station use this
/obj/machinery/embedded_controller/radio/airlock/airlock_controller
name = "Airlock Controller"
@@ -90,23 +79,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
-
if (!ui)
ui = new(user, src, ui_key, "simple_airlock_console.tmpl", name, 470, 290)
-
ui.set_initial_data(data)
-
ui.open()
-
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/airlock_controller/Topic(href, href_list)
- if(..())
+ if((. = ..()))
return
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -125,7 +107,6 @@
return 1
-
//Access controller for door control - used in virology and the like
/obj/machinery/embedded_controller/radio/airlock/access_controller
icon = 'icons/obj/airlock_machines.dmi'
@@ -154,23 +135,16 @@
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
-
if (!ui)
ui = new(user, src, ui_key, "door_access_console.tmpl", name, 330, 220)
-
ui.set_initial_data(data)
-
ui.open()
-
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/access_controller/Topic(href, href_list)
- if(..())
+ if((. = ..()))
return
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext_door")
diff --git a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm
new file mode 100644
index 0000000000..d2f9a410a2
--- /dev/null
+++ b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm
@@ -0,0 +1,51 @@
+// Provides remote access to a controller (since they must be unique).
+/obj/machinery/dummy_airlock_controller
+ name = "airlock control terminal"
+ icon = 'icons/obj/airlock_machines.dmi'
+ icon_state = "airlock_control_standby"
+ layer = ABOVE_OBJ_LAYER
+ var/id_tag
+
+ var/datum/topic_state/remote/remote_state
+ var/obj/machinery/embedded_controller/radio/airlock/master_controller
+
+/obj/machinery/dummy_airlock_controller/process()
+ if(master_controller)
+ appearance = master_controller
+ . = ..()
+
+/obj/machinery/dummy_airlock_controller/Initialize()
+ . = ..()
+ if(id_tag)
+ for(var/obj/machinery/embedded_controller/radio/airlock/_master in SSmachines.machinery)
+ if(_master.id_tag == id_tag)
+ master_controller = _master
+ master_controller.dummy_terminals += src
+ break
+ if(!master_controller)
+ qdel(src)
+ else
+ remote_state = new /datum/topic_state/remote(src, master_controller)
+
+/obj/machinery/dummy_airlock_controller/Destroy()
+ if(master_controller)
+ master_controller.dummy_terminals -= src
+ if(remote_state)
+ qdel(remote_state)
+ remote_state = null
+ return ..()
+
+/obj/machinery/dummy_airlock_controller/interface_interact(var/mob/user)
+ open_remote_ui(user)
+ return TRUE
+
+/obj/machinery/dummy_airlock_controller/proc/open_remote_ui(var/mob/user)
+ if(master_controller)
+ appearance = master_controller
+ return master_controller.ui_interact(user, state = remote_state)
+
+/obj/machinery/dummy_airlock_controller/powered(var/chan = -1, var/area/check_area = null)
+ if(master_controller)
+ var/area/A = get_area(master_controller)
+ return master_controller.powered(chan, A)
+ return ..()
diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller.dm b/code/game/machinery/embedded_controller/airlock_docking_controller.dm
index fa8398c3d7..4d5048ad6d 100644
--- a/code/game/machinery/embedded_controller/airlock_docking_controller.dm
+++ b/code/game/machinery/embedded_controller/airlock_docking_controller.dm
@@ -1,8 +1,17 @@
+/*
+ * NOTE - This file defines both these datums: Yes, you read that right. Its confusing. Lets try and break it down.
+ * /datum/computer/file/embedded_program/docking/airlock
+ * - A docking controller for an airlock based docking port
+ * /datum/computer/file/embedded_program/airlock/docking
+ * - An extension to the normal airlock program allows disabling of the regular airlock functions when docking
+*/
+
//a docking port based on an airlock
/obj/machinery/embedded_controller/radio/airlock/docking_port
name = "docking port controller"
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
var/datum/computer/file/embedded_program/docking/airlock/docking_program
+ var/display_name // For mappers to override docking_program.display_name (how would it show up on docking monitoring program)
tag_secure = 1
/obj/machinery/embedded_controller/radio/airlock/docking_port/Initialize()
@@ -10,9 +19,25 @@
airlock_program = new/datum/computer/file/embedded_program/airlock/docking(src)
docking_program = new/datum/computer/file/embedded_program/docking/airlock(src, airlock_program)
program = docking_program
+ if(display_name)
+ docking_program.display_name = display_name
+
+/obj/machinery/embedded_controller/radio/airlock/docking_port/attackby(obj/item/W, mob/user)
+ if(istype(W,/obj/item/device/multitool)) //give them part of code, would take few tries to get full
+ var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
+ var/code = docking_program.docking_codes
+ if(!code)
+ code = "N/A"
+ else
+ code = stars(code)
+ to_chat(user, "[W]'s screen displays '[code]'")
+ else
+ ..()
/obj/machinery/embedded_controller/radio/airlock/docking_port/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
+ var/datum/computer/file/embedded_program/docking/airlock/docking_program = program
+ var/datum/computer/file/embedded_program/airlock/docking/airlock_program = docking_program.airlock_program
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -22,6 +47,8 @@
"docking_status" = docking_program.get_docking_status(),
"airlock_disabled" = !(docking_program.undocked() || docking_program.override_enabled),
"override_enabled" = docking_program.override_enabled,
+ "docking_codes" = docking_program.docking_codes,
+ "name" = docking_program.get_name()
)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
@@ -33,12 +60,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port/Topic(href, href_list)
- if(..())
+ if((. = ..()))
return
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
@@ -60,11 +84,13 @@
return 1
-
+///////////////////////////////////////////////////////////////////////////////
//A docking controller for an airlock based docking port
+//
/datum/computer/file/embedded_program/docking/airlock
var/datum/computer/file/embedded_program/airlock/docking/airlock_program
+
/datum/computer/file/embedded_program/docking/airlock/New(var/obj/machinery/embedded_controller/M, var/datum/computer/file/embedded_program/airlock/docking/A)
..(M)
airlock_program = A
@@ -76,10 +102,10 @@
disable_override()
else
enable_override()
- return
+ return TRUE
- ..(command)
- airlock_program.receive_user_command(command) //pass along to subprograms
+ . = ..(command)
+ . = airlock_program.receive_user_command(command) || . //pass along to subprograms; bypass shortcircuit
/datum/computer/file/embedded_program/docking/airlock/process()
airlock_program.process()
@@ -91,7 +117,7 @@
//tell the docking port to start getting ready for docking - e.g. pressurize
/datum/computer/file/embedded_program/docking/airlock/prepare_for_docking()
- airlock_program.begin_cycle_in()
+ airlock_program.begin_dock_cycle()
//are we ready for docking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_docking()
@@ -99,14 +125,14 @@
//we are docked, open the doors or whatever.
/datum/computer/file/embedded_program/docking/airlock/finish_docking()
- airlock_program.enable_mech_regulators()
+ airlock_program.enable_mech_regulation()
airlock_program.open_doors()
//tell the docking port to start getting ready for undocking - e.g. close those doors.
/datum/computer/file/embedded_program/docking/airlock/prepare_for_undocking()
airlock_program.stop_cycling()
airlock_program.close_doors()
- airlock_program.disable_mech_regulators()
+ airlock_program.disable_mech_regulation()
//are we ready for undocking?
/datum/computer/file/embedded_program/docking/airlock/ready_for_undocking()
@@ -114,20 +140,22 @@
var/int_closed = airlock_program.check_interior_door_secured()
return (ext_closed || int_closed)
+///////////////////////////////////////////////////////////////////////////////
//An airlock controller to be used by the airlock-based docking port controller.
//Same as a regular airlock controller but allows disabling of the regular airlock functions when docking
+//
/datum/computer/file/embedded_program/airlock/docking
var/datum/computer/file/embedded_program/docking/airlock/master_prog
+/datum/computer/file/embedded_program/airlock/docking/Destroy()
+ if(master_prog)
+ master_prog.airlock_program = null
+ master_prog = null
+ return ..()
+
/datum/computer/file/embedded_program/airlock/docking/receive_user_command(command)
if (master_prog.undocked() || master_prog.override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled
- ..(command)
-
-/datum/computer/file/embedded_program/airlock/docking/proc/enable_mech_regulators()
- enable_mech_regulation()
-
-/datum/computer/file/embedded_program/airlock/docking/proc/disable_mech_regulators()
- disable_mech_regulation()
+ return ..(command)
/datum/computer/file/embedded_program/airlock/docking/proc/open_doors()
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open")
diff --git a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm
index 4b6917ff71..55182aaaa6 100644
--- a/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm
+++ b/code/game/machinery/embedded_controller/airlock_docking_controller_multi.dm
@@ -2,21 +2,15 @@
//this is the master controller, that things will try to dock with.
/obj/machinery/embedded_controller/radio/docking_port_multi
name = "docking port controller"
-
+ program = /datum/computer/file/embedded_program/docking/multi
var/child_tags_txt
var/child_names_txt
var/list/child_names = list()
- var/datum/computer/file/embedded_program/docking/multi/docking_program
-
/obj/machinery/embedded_controller/radio/docking_port_multi/Initialize()
. = ..()
- docking_program = new/datum/computer/file/embedded_program/docking/multi(src)
- program = docking_program
-
var/list/names = splittext(child_names_txt, ";")
var/list/tags = splittext(child_tags_txt, ";")
-
if (names.len == tags.len)
for (var/i = 1; i <= tags.len; i++)
child_names[tags[i]] = names[i]
@@ -24,6 +18,7 @@
/obj/machinery/embedded_controller/radio/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
+ var/datum/computer/file/embedded_program/docking/multi/docking_program = program // Cast to proper type
var/list/airlocks[child_names.len]
var/i = 1
@@ -44,24 +39,21 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/docking_port_multi/Topic(href, href_list)
- return
+ return 1 // Apparently we swallow all input (this is corrected legacy code)
//a docking port based on an airlock
+// This is the actual controller that will be commanded by the master defined above
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi
name = "docking port controller"
+ program = /datum/computer/file/embedded_program/airlock/multi_docking
var/master_tag //for mapping
- var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program
tag_secure = 1
-/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Initialize()
- . = ..()
- airlock_program = new/datum/computer/file/embedded_program/airlock/multi_docking(src)
- program = airlock_program
-
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
+ var/datum/computer/file/embedded_program/airlock/multi_docking/airlock_program = program // Cast to proper type
data = list(
"chamber_pressure" = round(airlock_program.memory["chamber_sensor_pressure"]),
@@ -82,12 +74,9 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/Topic(href, href_list)
- if(..())
+ if((. = ..()))
return
- usr.set_machine(src)
- src.add_fingerprint(usr)
-
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
if("cycle_ext")
diff --git a/code/game/machinery/embedded_controller/airlock_program.dm b/code/game/machinery/embedded_controller/airlock_program.dm
index 5ebbac93ae..dc02084f98 100644
--- a/code/game/machinery/embedded_controller/airlock_program.dm
+++ b/code/game/machinery/embedded_controller/airlock_program.dm
@@ -52,8 +52,8 @@
tag_interior_door = controller.tag_interior_door? controller.tag_interior_door : "[id_tag]_inner"
tag_airpump = controller.tag_airpump? controller.tag_airpump : "[id_tag]_pump"
tag_chamber_sensor = controller.tag_chamber_sensor? controller.tag_chamber_sensor : "[id_tag]_sensor"
- tag_exterior_sensor = controller.tag_exterior_sensor
- tag_interior_sensor = controller.tag_interior_sensor
+ tag_exterior_sensor = controller.tag_exterior_sensor || "[id_tag]_exterior_sensor"
+ tag_interior_sensor = controller.tag_interior_sensor || "[id_tag]_interior_sensor"
tag_airlock_mech_sensor = controller.tag_airlock_mech_sensor? controller.tag_airlock_mech_sensor : "[id_tag]_airlock_mech"
tag_shuttle_mech_sensor = controller.tag_shuttle_mech_sensor? controller.tag_shuttle_mech_sensor : "[id_tag]_shuttle_mech"
memory["secure"] = controller.tag_secure
@@ -117,6 +117,7 @@
/datum/computer/file/embedded_program/airlock/receive_user_command(command)
var/shutdown_pump = 0
+ . = TRUE
switch(command)
if("cycle_ext")
//If airlock is already cycled in this direction, just toggle the doors.
@@ -163,6 +164,8 @@
else
signalDoor(tag_interior_door, "unlock")
signalDoor(tag_exterior_door, "unlock")
+ else
+ . = FALSE
if(shutdown_pump)
signalPump(tag_airpump, 0) //send a signal to stop pressurizing
@@ -273,6 +276,9 @@
target_state = TARGET_INOPEN
memory["purge"] = cycle_to_external_air
+/datum/computer/file/embedded_program/airlock/proc/begin_dock_cycle()
+ state = STATE_IDLE
+ target_state = TARGET_INOPEN
/datum/computer/file/embedded_program/airlock/proc/begin_cycle_out()
state = STATE_IDLE
target_state = TARGET_OUTOPEN
diff --git a/code/game/machinery/embedded_controller/docking_program.dm b/code/game/machinery/embedded_controller/docking_program.dm
index 2665fc231c..86876abe28 100644
--- a/code/game/machinery/embedded_controller/docking_program.dm
+++ b/code/game/machinery/embedded_controller/docking_program.dm
@@ -12,51 +12,51 @@
/*
*** STATE TABLE ***
-
+
MODE_CLIENT|STATE_UNDOCKED sent a request for docking and now waiting for a reply.
MODE_CLIENT|STATE_DOCKING server told us they are OK to dock, waiting for our docking port to be ready.
MODE_CLIENT|STATE_DOCKED idle - docked as client.
MODE_CLIENT|STATE_UNDOCKING we are either waiting for our docking port to be ready or for the server to give us the OK to finish undocking.
-
+
MODE_SERVER|STATE_UNDOCKED should never happen.
MODE_SERVER|STATE_DOCKING someone requested docking, we are waiting for our docking port to be ready.
MODE_SERVER|STATE_DOCKED idle - docked as server
MODE_SERVER|STATE_UNDOCKING client requested undocking, we are waiting for our docking port to be ready.
-
+
MODE_NONE|STATE_UNDOCKED idle - not docked.
MODE_NONE|anything else should never happen.
-
+
*** Docking Signals ***
-
+
Docking
Client sends request_dock
Server sends confirm_dock to say that yes, we will serve your request
When client is ready, sends confirm_dock
Server sends confirm_dock back to indicate that docking is complete
-
+
Undocking
Client sends request_undock
When client is ready, sends confirm_undock
Server sends confirm_undock back to indicate that docking is complete
-
+
Note that in both cases each side exchanges confirm_dock before the docking operation is considered done.
- The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
+ The client first sends a confirm message to indicate it is ready, and then finally the server will send it's
confirm message to indicate that the operation is complete.
-
+
Note also that when docking, the server sends an additional confirm message. This is because before docking,
the server and client do not have a defined relationship. Before undocking, the server and client are already
related to each other, thus the extra confirm message is not needed.
-
+
*** Override, what is it? ***
-
+
The purpose of enabling the override is to prevent the docking program from automatically doing things with the docking port when docking or undocking.
Maybe the shuttle is full of plamsa/phoron for some reason, and you don't want the door to automatically open, or the airlock to cycle.
This means that the prepare_for_docking/undocking and finish_docking/undocking procs don't get called.
-
+
The docking controller will still check the state of the docking port, and thus prevent the shuttle from launching unless they force the launch (handling forced
- launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
+ launches is not the docking controller's responsibility). In this case it is up to the players to manually get the docking port into a good state to undock
(which usually just means closing and locking the doors).
-
+
In line with this, docking controllers should prevent players from manually doing things when the override is NOT enabled.
*/
@@ -67,27 +67,31 @@
var/control_mode = MODE_NONE
var/response_sent = 0 //so we don't spam confirmation messages
var/resend_counter = 0 //for periodically resending confirmation messages in case they are missed
-
+
var/override_enabled = 0 //when enabled, do not open/close doors or cycle airlocks and wait for the player to do it manually
var/received_confirm = 0 //for undocking, whether the server has recieved a confirmation from the client
+ var/docking_codes //would only allow docking when receiving signal with these, if set
+ var/display_name //Override the name shown on docking monitoring program; defaults to area name + coordinates if unset
/datum/computer/file/embedded_program/docking/New()
..()
- var/datum/existing = locate(id_tag) //in case a datum already exists with our tag
- if(existing)
- existing.tag = null //take it from them
-
- tag = id_tag //Greatly simplifies shuttle initialization
+ if(id_tag)
+ if(SSshuttles.docking_registry[id_tag])
+ crash_with("Docking controller tag [id_tag] had multiple associated programs.")
+ SSshuttles.docking_registry[id_tag] = src
+/datum/computer/file/embedded_program/docking/Destroy()
+ SSshuttles.docking_registry -= id_tag
+ return ..()
/datum/computer/file/embedded_program/docking/receive_signal(datum/signal/signal, receive_method, receive_param)
var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id
var/command = signal.data["command"]
var/recipient = signal.data["recipient"] //the intended recipient of the docking signal
-
+
if (recipient != id_tag)
return //this signal is not for us
-
+
switch (command)
if ("confirm_dock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKED && receive_tag == tag_target)
@@ -95,7 +99,7 @@
broadcast_docking_status()
if (!override_enabled)
prepare_for_docking()
-
+
else if (control_mode == MODE_CLIENT && dock_state == STATE_DOCKING && receive_tag == tag_target)
dock_state = STATE_DOCKED
broadcast_docking_status()
@@ -104,19 +108,27 @@
response_sent = 0
else if (control_mode == MODE_SERVER && dock_state == STATE_DOCKING && receive_tag == tag_target) //client just sent us the confirmation back, we're done with the docking process
received_confirm = 1
-
+
if ("request_dock")
if (control_mode == MODE_NONE && dock_state == STATE_UNDOCKED)
+
+ tag_target = receive_tag
+
+ if(docking_codes)
+ var/code = signal.data["code"]
+ if(code != docking_codes)
+ log_debug("Controller [id_tag] got request_dock but code:[code] != docking_codes:[docking_codes]")
+ return
+
control_mode = MODE_SERVER
-
dock_state = STATE_DOCKING
broadcast_docking_status()
-
- tag_target = receive_tag
+
+
if (!override_enabled)
prepare_for_docking()
send_docking_command(tag_target, "confirm_dock") //acknowledge the request
-
+
if ("confirm_undock")
if (control_mode == MODE_CLIENT && dock_state == STATE_UNDOCKING && receive_tag == tag_target)
if (!override_enabled)
@@ -129,7 +141,7 @@
if (control_mode == MODE_SERVER && dock_state == STATE_DOCKED && receive_tag == tag_target)
dock_state = STATE_UNDOCKING
broadcast_docking_status()
-
+
if (!override_enabled)
prepare_for_undocking()
@@ -145,38 +157,38 @@
if (!response_sent)
send_docking_command(tag_target, "confirm_dock") //tell the server we're ready
response_sent = 1
-
+
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_dock") //tell the client we are done docking.
-
+
dock_state = STATE_DOCKED
broadcast_docking_status()
-
+
if (!override_enabled)
finish_docking() //server done docking!
response_sent = 0
received_confirm = 0
-
+
if (STATE_UNDOCKING)
if (ready_for_undocking())
if (control_mode == MODE_CLIENT)
if (!response_sent)
send_docking_command(tag_target, "confirm_undock") //tell the server we are OK to undock.
response_sent = 1
-
+
else if (control_mode == MODE_SERVER && received_confirm)
send_docking_command(tag_target, "confirm_undock") //tell the client we are done undocking.
if (!override_enabled)
finish_undocking()
reset() //server is done undocking!
-
+
if (response_sent || resend_counter > 0)
resend_counter++
-
+
if (resend_counter >= MESSAGE_RESEND_TIME || (dock_state != STATE_DOCKING && dock_state != STATE_UNDOCKING))
response_sent = 0
resend_counter = 0
-
+
//handle invalid states
if (control_mode == MODE_NONE && dock_state != STATE_UNDOCKED)
if (tag_target)
@@ -189,22 +201,22 @@
/datum/computer/file/embedded_program/docking/proc/initiate_docking(var/target)
if (dock_state != STATE_UNDOCKED || control_mode == MODE_SERVER) //must be undocked and not serving another request to begin a new docking handshake
return
-
+
tag_target = target
control_mode = MODE_CLIENT
-
+
send_docking_command(tag_target, "request_dock")
/datum/computer/file/embedded_program/docking/proc/initiate_undocking()
if (dock_state != STATE_DOCKED || control_mode != MODE_CLIENT) //must be docked and must be client to start undocking
return
-
+
dock_state = STATE_UNDOCKING
broadcast_docking_status()
-
+
if (!override_enabled)
prepare_for_undocking()
-
+
send_docking_command(tag_target, "request_undock")
//tell the docking port to start getting ready for docking - e.g. pressurize
@@ -240,7 +252,7 @@
/datum/computer/file/embedded_program/docking/proc/reset()
dock_state = STATE_UNDOCKED
broadcast_docking_status()
-
+
control_mode = MODE_NONE
tag_target = null
response_sent = 0
@@ -267,6 +279,7 @@
signal.data["tag"] = id_tag
signal.data["command"] = command
signal.data["recipient"] = recipient
+ signal.data["code"] = docking_codes
post_signal(signal)
/datum/computer/file/embedded_program/docking/proc/broadcast_docking_status()
@@ -283,6 +296,8 @@
if (STATE_UNDOCKING) return "undocking"
if (STATE_DOCKED) return "docked"
+/datum/computer/file/embedded_program/docking/proc/get_name()
+ return display_name ? display_name : "[get_area(master)] ([master.x], [master.y])"
#undef STATE_UNDOCKED
#undef STATE_DOCKING
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index 17bf13181a..714d27d560 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -1,18 +1,20 @@
/obj/machinery/embedded_controller
- var/datum/computer/file/embedded_program/program //the currently executing program
-
name = "Embedded Controller"
anchored = 1
-
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
-
+ var/datum/computer/file/embedded_program/program //the currently executing program
var/on = 1
-obj/machinery/embedded_controller/radio/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src,frequency)
- ..()
+/obj/machinery/embedded_controller/Initialize()
+ if(ispath(program))
+ program = new program(src)
+ return ..()
+
+/obj/machinery/embedded_controller/Destroy()
+ if(istype(program))
+ qdel(program) // the program will clear the ref in its Destroy
+ return ..()
/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line)
return 0
@@ -24,6 +26,17 @@ obj/machinery/embedded_controller/radio/Destroy()
program.receive_signal(signal, receive_method, receive_param)
//spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0
+/obj/machinery/embedded_controller/Topic(href, href_list)
+ if((. = ..()))
+ return
+ if(usr)
+ usr.set_machine(src)
+ src.add_fingerprint(usr)
+ // We would now pass it to the program, except that some of our embedded controller types want to block certain commands.
+ // Until/unless that is refactored differently, we rely on subtypes to pass it on.
+ //if(program)
+ // return program.receive_user_command(href_list["command"])
+
/obj/machinery/embedded_controller/process()
if(program)
program.process()
@@ -40,14 +53,16 @@ obj/machinery/embedded_controller/radio/Destroy()
src.ui_interact(user)
-/obj/machinery/embedded_controller/ui_interact()
- return
+//
+// Embedded controller with a radio! (Most things (All things?) use this)
+//
/obj/machinery/embedded_controller/radio
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
power_channel = ENVIRON
density = 0
+ unacidable = 1
var/id_tag
//var/radio_power_use = 50 //power used to xmit signals
@@ -55,11 +70,15 @@ obj/machinery/embedded_controller/radio/Destroy()
var/frequency = 1379
var/radio_filter = null
var/datum/radio_frequency/radio_connection
- unacidable = 1
/obj/machinery/embedded_controller/radio/Initialize()
+ set_frequency(frequency) // Set it before parent instantiates program
. = ..()
- set_frequency(frequency)
+
+/obj/machinery/embedded_controller/radio/Destroy()
+ if(radio_controller)
+ radio_controller.remove_object(src,frequency)
+ ..()
/obj/machinery/embedded_controller/radio/update_icon()
if(on && program)
diff --git a/code/game/machinery/embedded_controller/embedded_program_base.dm b/code/game/machinery/embedded_controller/embedded_program_base.dm
index 0cc711c7a4..48340b0c8b 100644
--- a/code/game/machinery/embedded_controller/embedded_program_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_program_base.dm
@@ -11,8 +11,15 @@
var/obj/machinery/embedded_controller/radio/R = M
id_tag = R.id_tag
+/datum/computer/file/embedded_program/Destroy()
+ if(master)
+ master.program = null
+ master = null
+ return ..()
+
+// Return TRUE if was a command for us, otherwise return FALSE (so controllers with multiple programs can try each in turn until one accepts)
/datum/computer/file/embedded_program/proc/receive_user_command(command)
- return
+ return FALSE
/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return
diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm
index 14b27b2512..d2e04a3330 100644
--- a/code/game/machinery/embedded_controller/simple_docking_controller.dm
+++ b/code/game/machinery/embedded_controller/simple_docking_controller.dm
@@ -1,16 +1,12 @@
//a docking port that uses a single door
/obj/machinery/embedded_controller/radio/simple_docking_controller
name = "docking hatch controller"
+ program = /datum/computer/file/embedded_program/docking/simple
var/tag_door
- var/datum/computer/file/embedded_program/docking/simple/docking_program
-
-/obj/machinery/embedded_controller/radio/simple_docking_controller/Initialize()
- . = ..()
- docking_program = new/datum/computer/file/embedded_program/docking/simple(src)
- program = docking_program
/obj/machinery/embedded_controller/radio/simple_docking_controller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
+ var/datum/computer/file/embedded_program/docking/simple/docking_program = program // Cast to proper type
data = list(
"docking_status" = docking_program.get_docking_status(),
@@ -28,11 +24,8 @@
ui.set_auto_update(1)
/obj/machinery/embedded_controller/radio/simple_docking_controller/Topic(href, href_list)
- if(..())
- return 1
-
- usr.set_machine(src)
- src.add_fingerprint(usr)
+ if((. = ..()))
+ return
var/clean = 0
switch(href_list["command"]) //anti-HTML-hacking checks
@@ -44,8 +37,7 @@
if(clean)
program.receive_user_command(href_list["command"])
- return 0
-
+ return
//A docking controller program for a simple door based docking port
/datum/computer/file/embedded_program/docking/simple
@@ -76,6 +68,7 @@
..(signal, receive_method, receive_param)
/datum/computer/file/embedded_program/docking/simple/receive_user_command(command)
+ . = TRUE
switch(command)
if("force_door")
if (override_enabled)
@@ -88,7 +81,8 @@
disable_override()
else
enable_override()
-
+ else
+ . = FALSE
/datum/computer/file/embedded_program/docking/simple/proc/signal_door(var/command)
var/datum/signal/signal = new
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 169bc8c6d7..572977ceb4 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -11,7 +11,7 @@
var/strength = 10 //How weakened targets are when flashed.
var/base_state = "mflash"
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
flags = PROXMOVE
diff --git a/code/game/machinery/floor_light.dm b/code/game/machinery/floor_light.dm
index f02d3c2855..1af8382f98 100644
--- a/code/game/machinery/floor_light.dm
+++ b/code/game/machinery/floor_light.dm
@@ -7,7 +7,7 @@ var/list/floor_light_cache = list()
desc = "A backlit floor panel."
layer = TURF_LAYER+0.001
anchored = 0
- use_power = 2
+ use_power = USE_POWER_ACTIVE
idle_power_usage = 2
active_power_usage = 20
power_channel = LIGHT
@@ -72,7 +72,7 @@ var/list/floor_light_cache = list()
return
on = !on
- if(on) use_power = 2
+ if(on) update_use_power(USE_POWER_ACTIVE)
visible_message("\The [user] turns \the [src] [on ? "on" : "off"].")
update_brightness()
return
@@ -81,21 +81,21 @@ var/list/floor_light_cache = list()
..()
var/need_update
if((!anchored || broken()) && on)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
on = 0
need_update = 1
else if(use_power && !on)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
need_update = 1
if(need_update)
update_brightness()
/obj/machinery/floor_light/proc/update_brightness()
- if(on && use_power == 2)
+ if(on && use_power == USE_POWER_ACTIVE)
if(light_range != default_light_range || light_power != default_light_power || light_color != default_light_colour)
set_light(default_light_range, default_light_power, default_light_colour)
else
- use_power = 0
+ update_use_power(USE_POWER_OFF)
if(light_range || light_power)
set_light(0)
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index e17ed67bc2..efdf18695c 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -39,7 +39,7 @@ var/const/HOLOPAD_MODE = RANGE_BASED
layer = ABOVE_TURF_LAYER
var/power_per_hologram = 500 //per usage per hologram
idle_power_usage = 5
- use_power = 1
+ use_power = USE_POWER_IDLE
var/list/mob/living/silicon/ai/masters = new() //List of AIs that use the holopad
var/last_request = 0 //to prevent request spam. ~Carn
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
@@ -183,7 +183,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 5
active_power_usage = 100
diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm
index 9a656ac3be..7a3cd8c861 100644
--- a/code/game/machinery/holosign.dm
+++ b/code/game/machinery/holosign.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/holosign.dmi'
icon_state = "sign_off"
plane = MOB_PLANE
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
anchored = 1
@@ -19,7 +19,7 @@
if(stat & (BROKEN|NOPOWER))
return
lit = !lit
- use_power = lit ? 2 : 1
+ update_use_power(lit ? USE_POWER_ACTIVE : USE_POWER_IDLE)
update_icon()
/obj/machinery/holosign/update_icon()
@@ -34,7 +34,7 @@
..()
if(stat & NOPOWER)
lit = 0
- use_power = 0
+ update_use_power(USE_POWER_OFF)
update_icon()
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 5cb521d423..ee887db2f5 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -6,7 +6,7 @@
var/id = null
var/on = 1.0
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
@@ -53,7 +53,7 @@
var/last_spark = 0
var/base_state = "migniter"
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm
index f2808dbc18..3a8554dae2 100644
--- a/code/game/machinery/jukebox.dm
+++ b/code/game/machinery/jukebox.dm
@@ -15,7 +15,7 @@ datum/track/New(var/title_name, var/audio)
anchored = 1
density = 1
power_channel = EQUIP
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 100
circuit = /obj/item/weapon/circuitboard/jukebox
@@ -249,7 +249,7 @@ datum/track/New(var/title_name, var/audio)
main_area.forced_ambience = null
playing = 0
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
update_icon()
@@ -271,7 +271,7 @@ datum/track/New(var/title_name, var/audio)
main_area.play_ambience(M)
playing = 1
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
update_icon()
// Advance to the next track - Don't start playing it unless we were already playing
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index f4b3d6f8f0..24edece9af 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -7,7 +7,7 @@
icon = 'icons/obj/power.dmi'
icon_state = "light1"
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
power_channel = LIGHT
var/on = 1
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 58d62b4cf9..a237ded44e 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -101,7 +101,7 @@ Class Procs:
var/stat = 0
var/emagged = 0
- var/use_power = 1
+ var/use_power = USE_POWER_IDLE
//0 = dont run the auto
//1 = run auto, use idle
//2 = run auto, use active
@@ -199,9 +199,9 @@ Class Procs:
/obj/machinery/proc/auto_use_power()
if(!powered(power_channel))
return 0
- if(use_power == 1)
+ if(use_power == USE_POWER_IDLE)
use_power(idle_power_usage, power_channel, 1)
- else if(use_power >= 2)
+ else if(use_power >= USE_POWER_ACTIVE)
use_power(active_power_usage, power_channel, 1)
return 1
@@ -268,7 +268,7 @@ Class Procs:
/obj/machinery/proc/state(var/msg)
for(var/mob/O in hearers(src, null))
- O.show_message("\icon[src] [msg]", 2)
+ O.show_message("[bicon(src)] [msg]", 2)
/obj/machinery/proc/ping(text=null)
if(!text)
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index 9f97ab0360..9d36b08202 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -11,7 +11,7 @@
desc = "A device that uses station power to create points of magnetic energy."
plane = PLATING_PLANE
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 50
var/freq = 1449 // radio frequency
@@ -142,10 +142,10 @@
// Update power usage:
if(on)
- use_power = 2
+ update_use_power(USE_POWER_ACTIVE)
active_power_usage = electricity_level*15
else
- use_power = 0
+ update_use_power(USE_POWER_OFF)
// Overload conditions:
/* // Eeeehhh kinda stupid
@@ -190,7 +190,7 @@
icon_state = "airlock_control_standby"
density = 1
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 45
var/frequency = 1449
var/code = 0
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 1d13a36c3a..7c184c27de 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -6,7 +6,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "mass_driver"
anchored = 1.0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 50
circuit = /obj/item/weapon/circuitboard/mass_driver
diff --git a/code/game/machinery/neonsign.dm b/code/game/machinery/neonsign.dm
index fe5d5370a8..bdaa3b62fd 100644
--- a/code/game/machinery/neonsign.dm
+++ b/code/game/machinery/neonsign.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/neonsigns.dmi'
icon_state = "sign_off"
plane = MOB_PLANE
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 2
active_power_usage = 4
anchored = 1
@@ -19,7 +19,7 @@
if(stat & (BROKEN|NOPOWER))
return
lit = !lit
- use_power = lit ? 2 : 1
+ update_use_power(lit ? USE_POWER_ACTIVE : USE_POWER_IDLE)
update_icon()
/obj/machinery/neonsign/update_icon()
@@ -34,7 +34,7 @@
..()
if(stat & NOPOWER)
lit = 0
- use_power = 0
+ update_use_power(USE_POWER_OFF)
update_icon()
diff --git a/code/game/machinery/nuclear_bomb.dm b/code/game/machinery/nuclear_bomb.dm
index f32e57b9b1..8d6a55b3fd 100644
--- a/code/game/machinery/nuclear_bomb.dm
+++ b/code/game/machinery/nuclear_bomb.dm
@@ -23,7 +23,7 @@ var/bomb_set
var/timing_wire
var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open,
// 3 is sealant open, 4 is unwrenched, 5 is removed from bolts.
- use_power = 0
+ use_power = USE_POWER_OFF
/obj/machinery/nuclearbomb/New()
..()
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index 4c67aa09a9..557f9169dd 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -138,7 +138,7 @@
var/icon/I = imap[1+(ix + icx*iy)*2]
var/icon/I2 = imap[2+(ix + icx*iy)*2]
- //to_world("icon: \icon[I]")
+ //to_world("icon: [bicon(I)]")
I.DrawBox(colour, rx, ry, rx+1, ry+1)
@@ -153,7 +153,7 @@
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
- //to_world("\icon[I] at [H.screen_loc]")
+ //to_world("[bicon(I)] at [H.screen_loc]")
H.name = (i==0)?"maprefresh":"map"
@@ -266,7 +266,7 @@
//to_world("trying [ix],[iy] : [ix+icx*iy]")
var/icon/I = imap[1+(ix + icx*iy)]
- //to_world("icon: \icon[I]")
+ //to_world("icon: [bicon(I)]")
I.DrawBox(colour, rx, ry, rx, ry)
@@ -279,7 +279,7 @@
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
- //to_world("\icon[I] at [H.screen_loc]")
+ //to_world("[bicon(I)] at [H.screen_loc]")
H.name = (i==0)?"maprefresh":"map"
diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm
index 7f2b310ed6..10c96a6b6a 100644
--- a/code/game/machinery/oxygen_pump.dm
+++ b/code/game/machinery/oxygen_pump.dm
@@ -73,7 +73,7 @@
if(breather.internals)
breather.internals.icon_state = "internal0"
breather = null
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
/obj/machinery/oxygen_pump/attack_ai(mob/user as mob)
ui_interact(user)
@@ -90,7 +90,7 @@
breather.internal = tank
if(breather.internals)
breather.internals.icon_state = "internal1"
- use_power = 2
+ update_use_power(USE_POWER_ACTIVE)
/obj/machinery/oxygen_pump/proc/can_apply_to_target(var/mob/living/carbon/human/target, mob/user as mob)
if(!user)
@@ -162,7 +162,7 @@
contained.forceMove(src)
src.visible_message("\The [contained] rapidly retracts back into \the [src]!")
breather = null
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
else if(!breather.internal && tank)
breather.internal = tank
if(breather.internals)
@@ -287,7 +287,7 @@
contained.forceMove(src)
src.visible_message("\The [contained] rapidly retracts back into \the [src]!")
breather = null
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
else if(!breather.internal && tank)
breather.internal = tank
if(breather.internals)
diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm
index 3388de0c31..aab6a31ded 100644
--- a/code/game/machinery/pda_multicaster.dm
+++ b/code/game/machinery/pda_multicaster.dm
@@ -6,7 +6,7 @@
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/telecomms/pda_multicaster
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 750
var/on = 1 // If we're currently active,
var/toggle = 1 // If we /should/ be active or not,
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 92c28366fa..5349fc44b0 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "recharger0"
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 4
active_power_usage = 40000 //40 kW
var/efficiency = 40000 //will provide the modified power rate when upgraded
@@ -117,12 +117,12 @@
/obj/machinery/recharger/process()
if(stat & (NOPOWER|BROKEN) || !anchored)
- update_use_power(0)
+ update_use_power(USE_POWER_OFF)
icon_state = icon_state_idle
return
if(!charging)
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
icon_state = icon_state_idle
else
var/obj/item/weapon/cell/C = charging.get_cell()
@@ -130,10 +130,10 @@
if(!C.fully_charged())
icon_state = icon_state_charging
C.give(CELLRATE*efficiency)
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
else
icon_state = icon_state_charged
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
/obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored)
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index f702f3cf25..3f60e0ae07 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -6,7 +6,7 @@
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/recharge_station
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 50
var/mob/occupant = null
var/obj/item/weapon/cell/cell = null
@@ -78,9 +78,9 @@
if(!has_cell_power())
return 0
- if(use_power == 1)
+ if(use_power == USE_POWER_IDLE)
cell.use(idle_power_usage * CELLRATE)
- else if(use_power >= 2)
+ else if(use_power >= USE_POWER_ACTIVE)
cell.use(active_power_usage * CELLRATE)
return 1
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index de4e8a4685..8ef925ed0f 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -176,7 +176,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
screen = RCS_SENTPASS
message_log += "Message sent to [recipient] [message]"
else
- audible_message(text("\icon[src] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
+ audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
//Handle screen switching
if(href_list["setScreen"])
diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm
index 7c5f8cafa0..5bbb4ac6be 100644
--- a/code/game/machinery/robot_fabricator.dm
+++ b/code/game/machinery/robot_fabricator.dm
@@ -7,7 +7,7 @@
var/metal_amount = 0
var/operating = 0
var/obj/item/robot_parts/being_built = null
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 40
active_power_usage = 10000
@@ -115,7 +115,7 @@ Please wait until completion...
if(!isnull(building))
if(metal_amount >= build_cost)
operating = 1
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
metal_amount = max(0, metal_amount - build_cost)
@@ -128,7 +128,7 @@ Please wait until completion...
if(!isnull(being_built))
being_built.loc = get_turf(src)
being_built = null
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
operating = 0
overlays -= "fab-active"
return
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index 51ec807367..2deb56b9a7 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -15,7 +15,7 @@
name = "status display"
anchored = 1
density = 0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
circuit = /obj/item/weapon/circuitboard/status_display
var/mode = 1 // 0 = Blank
@@ -220,7 +220,7 @@
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/obj/machinery/status_display/proc/get_supply_shuttle_timer()
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(!shuttle)
return "Error"
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 13635326b0..d308565532 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -931,7 +931,7 @@
/obj/machinery/suit_cycler/proc/finished_job()
var/turf/T = get_turf(src)
- T.visible_message("\icon[src]The [src] beeps several times.")
+ T.visible_message("[bicon(src)]The [src] beeps several times.")
icon_state = initial(icon_state)
active = 0
playsound(src, 'sound/machines/boobeebeep.ogg', 50)
diff --git a/code/game/machinery/supply_display.dm b/code/game/machinery/supply_display.dm
index 211918c5e6..5a5c9750b6 100644
--- a/code/game/machinery/supply_display.dm
+++ b/code/game/machinery/supply_display.dm
@@ -6,7 +6,7 @@
message1 = "CARGO"
message2 = ""
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(!shuttle)
message2 = "Error"
else if(shuttle.has_arrive_time())
diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm
index 9f228be5d4..df40ba1a7d 100644
--- a/code/game/machinery/supplybeacon.dm
+++ b/code/game/machinery/supplybeacon.dm
@@ -58,7 +58,7 @@
/obj/machinery/power/supply_beacon/attack_hand(var/mob/user)
if(expended)
- use_power = 0
+ update_use_power(USE_POWER_OFF)
to_chat (user, "\The [src] has used up its charge.")
return
@@ -80,7 +80,7 @@
return
set_light(3, 3, "#00CCAA")
icon_state = "beacon_active"
- use_power = 1
+ use_power = USE_POWER_IDLE
if(user) to_chat(user, "You activate the beacon. The supply drop will be dispatched soon.")
/obj/machinery/power/supply_beacon/proc/deactivate(var/mob/user, var/permanent)
@@ -90,7 +90,7 @@
else
icon_state = "beacon"
set_light(0)
- use_power = 0
+ use_power = USE_POWER_OFF
target_drop_time = null
if(user) to_chat(user, "You deactivate the beacon.")
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 5eb18d6d2f..057a8fd5c1 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -17,7 +17,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
desc = "A dish-shaped machine used to broadcast processed subspace signals."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 25
machinetype = 5
produces_heat = 0
@@ -127,7 +127,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
desc = "A compact machine used for portable subspace telecommuniations processing."
density = 1
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
idle_power_usage = 0
machinetype = 6
produces_heat = 0
@@ -348,7 +348,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/part_b_extra = ""
if(data == 3) // intercepted radio message
part_b_extra = " (Intercepted)"
- var/part_a = "\icon[radio]\[[freq_text]\][part_b_extra]" // goes in the actual output
+ var/part_a = "[bicon(radio)]\[[freq_text]\][part_b_extra]" // goes in the actual output
// --- Some more pre-message formatting ---
var/part_b = "" // Tweaked for security headsets -- TLE
@@ -547,7 +547,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// Create a radio headset for the sole purpose of using its icon
var/obj/item/device/radio/headset/radio = new
- var/part_b = " \icon[radio]\[[freq_text]\][part_b_extra]" // Tweaked for security headsets -- TLE
+ var/part_b = " [bicon(radio)]\[[freq_text]\][part_b_extra]" // Tweaked for security headsets -- TLE
var/part_blackbox_b = " \[[freq_text]\]" // Tweaked for security headsets -- TLE
var/part_c = ""
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index d41104df25..3e3d89643a 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -105,7 +105,7 @@
dat += ""
temp = ""
- to_chat(user, browse(dat, "window=tcommachine;size=520x500;can_resize=0"))
+ user << browse(dat, "window=tcommachine;size=520x500;can_resize=0")
onclose(user, "dormitory")
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 4ba184a102..c2e9126fc1 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -251,7 +251,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 600
machinetype = 1
produces_heat = 0
@@ -318,7 +318,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "A mighty piece of hardware used to send/receive massive amounts of data."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 1600
machinetype = 7
circuit = /obj/item/weapon/circuitboard/telecomms/hub
@@ -377,7 +377,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "A mighty piece of hardware used to send massive amounts of data far away."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 600
machinetype = 8
produces_heat = 0
@@ -443,7 +443,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "A mighty piece of hardware used to send massive amounts of data quickly."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 1000
machinetype = 2
circuit = /obj/item/weapon/circuitboard/telecomms/bus
@@ -504,7 +504,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "This machine is used to process large quantities of information."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 600
machinetype = 3
delay = 5
@@ -556,7 +556,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
desc = "A machine used to store data and network statistics."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 300
machinetype = 4
circuit = /obj/item/weapon/circuitboard/telecomms/server
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index a0bdb5cd43..a58279098d 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -171,7 +171,7 @@
icon_state = "tele0"
dir = 4
var/accurate = 0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
circuit = /obj/item/weapon/circuitboard/teleporter_hub
@@ -319,7 +319,7 @@
dir = 4
var/active = 0
var/engaged = 0
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
active_power_usage = 2000
circuit = /obj/item/weapon/circuitboard/teleporter_station
@@ -356,8 +356,8 @@
if(com)
com.icon_state = "tele1"
use_power(5000)
- update_use_power(2)
- com.update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
+ com.update_use_power(USE_POWER_ACTIVE)
for(var/mob/O in hearers(src, null))
O.show_message("Teleporter engaged!", 2)
add_fingerprint(usr)
@@ -371,8 +371,8 @@
if(com)
com.icon_state = "tele0"
com.accurate = 0
- com.update_use_power(1)
- update_use_power(1)
+ com.update_use_power(USE_POWER_IDLE)
+ update_use_power(USE_POWER_IDLE)
for(var/mob/O in hearers(src, null))
O.show_message("Teleporter disengaged!", 2)
add_fingerprint(usr)
diff --git a/code/game/machinery/transportpod.dm b/code/game/machinery/transportpod.dm
index 96401c0908..0b499096fe 100644
--- a/code/game/machinery/transportpod.dm
+++ b/code/game/machinery/transportpod.dm
@@ -6,7 +6,7 @@
density = 1 //thicc
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
var/in_transit = 0
var/mob/occupant = null
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 979c633ee9..7bb23988d5 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -10,11 +10,8 @@
density = 1
clicksound = "button"
- var/icon_vend //Icon_state when vending
- var/icon_deny //Icon_state when denying access
-
// Power
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 10
var/vend_power_usage = 150 //actuators and stuff
@@ -181,9 +178,10 @@
panel_open = !panel_open
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
playsound(src, W.usesound, 50, 1)
- overlays.Cut()
if(panel_open)
- overlays += image(icon, "[initial(icon_state)]-panel")
+ add_overlay("[initial(icon_state)]-panel")
+ else
+ cut_overlay("[initial(icon_state)]-panel")
SSnanoui.update_uis(src) // Speaker switch is on the main UI, not wires UI
return
@@ -229,7 +227,7 @@
// This is not a status display message, since it's something the character
// themselves is meant to see BEFORE putting the money in
- to_chat(usr, "\icon[cashmoney] That is not enough money.")
+ to_chat(usr, "[bicon(cashmoney)] That is not enough money.")
return 0
if(istype(cashmoney, /obj/item/weapon/spacecash))
@@ -431,7 +429,7 @@
if((href_list["vend"]) && (vend_ready) && (!currently_vending))
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
to_chat(usr, "Access denied.") //Unless emagged of course
- flick(icon_deny,src)
+ flick("[icon_state]-deny",src)
playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
return
@@ -468,7 +466,7 @@
/obj/machinery/vending/proc/vend(datum/stored_item/vending_product/R, mob/user)
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
to_chat(usr, "Access denied.") //Unless emagged of course
- flick(icon_deny,src)
+ flick("[icon_state]-deny",src)
playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0)
return
vend_ready = 0 //One thing at a time!!
@@ -499,8 +497,7 @@
last_reply = world.time
use_power(vend_power_usage) //actuators and stuff
- if(icon_vend) //Show the vending animation if needed
- flick(icon_vend,src)
+ flick("[icon_state]-vend",src)
spawn(vend_delay)
R.get_product(get_turf(src))
if(has_logs)
@@ -678,8 +675,7 @@
/obj/machinery/vending/boozeomat
name = "Booze-O-Mat"
desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one."
- icon_state = "boozeomat"
- icon_deny = "boozeomat-deny"
+ icon_state = "fridge_dark"
products = list(/obj/item/weapon/reagent_containers/food/drinks/glass2/square = 10,
/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks = 10,
/obj/item/weapon/reagent_containers/food/drinks/glass2/shake = 10,
@@ -752,7 +748,6 @@
desc = "A vending machine which dispenses hot drinks."
product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
icon_state = "coffee"
- icon_vend = "coffee-vend"
vend_delay = 34
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
@@ -778,7 +773,7 @@
/obj/machinery/vending/cola
name = "Robust Softdrinks"
desc = "A softdrink vendor provided by Robust Industries, LLC."
- icon_state = "soda-blu"
+ icon_state = "Cola_Machine"
product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!"
product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space."
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
@@ -826,7 +821,6 @@
desc = "Cartridges for PDAs."
product_slogans = "Carts to go!"
icon_state = "cart"
- icon_deny = "cart-deny"
req_access = list(access_hop)
products = list(/obj/item/weapon/cartridge/medical = 10,/obj/item/weapon/cartridge/engineering = 10,/obj/item/weapon/cartridge/security = 10,
/obj/item/weapon/cartridge/janitor = 10,/obj/item/weapon/cartridge/signal/science = 10,/obj/item/device/pda/heads = 10,
@@ -893,7 +887,6 @@
name = "NanoMed Plus"
desc = "Medical drug dispenser."
icon_state = "med"
- icon_deny = "med-deny"
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!"
req_access = list(access_medical)
products = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4,
@@ -921,7 +914,6 @@
desc = "A wall-mounted version of the NanoMed."
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
- icon_deny = "wallmed-deny"
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/weapon/reagent_containers/hypospray/autoinjector = 4,/obj/item/device/healthanalyzer = 1)
contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/pill/tox = 1)
@@ -932,7 +924,6 @@
name = "NanoMed"
desc = "A wall-mounted version of the NanoMed, containing only vital first aid equipment."
icon_state = "wallmed"
- icon_deny = "wallmed-deny"
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 5,/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,/obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment =3,/obj/item/device/healthanalyzer = 3)
@@ -945,7 +936,6 @@
desc = "A security equipment vendor."
product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?"
icon_state = "sec"
- icon_deny = "sec-deny"
req_access = list(access_security)
products = list(/obj/item/weapon/handcuffs = 8,/obj/item/weapon/grenade/flashbang = 4,/obj/item/device/flash = 5,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12,/obj/item/weapon/storage/box/evidence = 6)
@@ -958,8 +948,7 @@
desc = "A plant nutrients vendor."
product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!"
product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..."
- icon_state = "nutri"
- icon_deny = "nutri-deny"
+ icon_state = "nutri_generic"
products = list(/obj/item/weapon/reagent_containers/glass/bottle/eznutrient = 6,/obj/item/weapon/reagent_containers/glass/bottle/left4zed = 4,/obj/item/weapon/reagent_containers/glass/bottle/robustharvest = 3,/obj/item/weapon/plantspray/pests = 20,
/obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4,/obj/item/weapon/storage/bag/plants = 5)
premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5)
@@ -970,7 +959,7 @@
desc = "When you need seeds fast!"
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
- icon_state = "seeds"
+ icon_state = "seeds_generic"
products = list(/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/chantermycelium = 3,/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/replicapod = 3,/obj/item/seeds/soyaseed = 3,
@@ -1062,7 +1051,6 @@
name = "YouTool"
desc = "Tools for tools."
icon_state = "tool"
- icon_deny = "tool-deny"
//req_access = list(access_maint_tunnels) //Maintenance access
products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/weapon/tool/crowbar = 5,/obj/item/weapon/weldingtool = 3,/obj/item/weapon/tool/wirecutters = 5,
/obj/item/weapon/tool/wrench = 5,/obj/item/device/analyzer = 5,/obj/item/device/t_scanner = 5,/obj/item/weapon/tool/screwdriver = 5,
@@ -1077,7 +1065,6 @@
name = "Engi-Vend"
desc = "Spare tool vending. What? Did you expect some witty description?"
icon_state = "engivend"
- icon_deny = "engivend-deny"
req_access = list(access_engine_equip)
products = list(/obj/item/device/geiger = 4,/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,
@@ -1100,7 +1087,6 @@
name = "Robco Tool Maker"
desc = "Everything you need for do-it-yourself station repair."
icon_state = "engi"
- icon_deny = "engi-deny"
req_access = list(access_engine_equip)
products = list(/obj/item/clothing/under/rank/chief_engineer = 4,/obj/item/clothing/under/rank/engineer = 4,/obj/item/clothing/shoes/orange = 4,/obj/item/clothing/head/hardhat = 4,
/obj/item/weapon/storage/belt/utility = 4,/obj/item/clothing/glasses/meson = 4,/obj/item/clothing/gloves/yellow = 4, /obj/item/weapon/tool/screwdriver = 12,
@@ -1118,7 +1104,6 @@
name = "Robotech Deluxe"
desc = "All the tools you need to create your own robot army."
icon_state = "robotics"
- icon_deny = "robotics-deny"
req_access = list(access_robotics)
products = list(/obj/item/clothing/suit/storage/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash = 4,
/obj/item/weapon/cell/high = 12, /obj/item/device/assembly/prox_sensor = 3,/obj/item/device/assembly/signaler = 3,/obj/item/device/healthanalyzer = 3,
diff --git a/code/game/machinery/virtual_reality/ar_console.dm b/code/game/machinery/virtual_reality/ar_console.dm
index 1f4c8c16fe..f4c6049487 100644
--- a/code/game/machinery/virtual_reality/ar_console.dm
+++ b/code/game/machinery/virtual_reality/ar_console.dm
@@ -73,7 +73,7 @@
if(A in component_parts)
continue
A.loc = src.loc
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/vr_sleeper/alien/enter_vr()
diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm
index dcd6e555b9..8a417a98bc 100644
--- a/code/game/machinery/virtual_reality/vr_console.dm
+++ b/code/game/machinery/virtual_reality/vr_console.dm
@@ -18,7 +18,7 @@
var/mirror_first_occupant = TRUE // Do we force the newly produced body to look like the occupant?
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 15
active_power_usage = 200
light_color = "#FF0000"
@@ -174,7 +174,7 @@
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.loc = src
- update_use_power(2)
+ update_use_power(USE_POWER_ACTIVE)
occupant = M
update_icon()
@@ -203,7 +203,7 @@
if(A in component_parts)
continue
A.loc = src.loc
- update_use_power(1)
+ update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/vr_sleeper/proc/enter_vr()
diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm
index a3911a2efa..81c720bacd 100644
--- a/code/game/machinery/wishgranter.dm
+++ b/code/game/machinery/wishgranter.dm
@@ -3,7 +3,7 @@
desc = "You're not so sure about this, anymore..."
icon = 'icons/obj/device.dmi'
icon_state = "syndbeacon"
- use_power = 0
+ use_power = USE_POWER_OFF
anchored = 1
density = 1
var/charges = 1
diff --git a/code/game/mecha/combat/fighter.dm b/code/game/mecha/combat/fighter.dm
new file mode 100644
index 0000000000..26bbcb84ac
--- /dev/null
+++ b/code/game/mecha/combat/fighter.dm
@@ -0,0 +1,381 @@
+#define NOGRAV_FIGHTER_DAMAGE 20
+
+/obj/mecha/combat/fighter
+ name = "Delete me, nerd!!"
+ desc = "The base type of fightercraft. Don't spawn this one!"
+
+ var/datum/effect/effect/system/ion_trail_follow/ion_trail
+ var/stabilization_enabled = TRUE //If our anti-space-drift is on
+ var/ground_capable = FALSE //If we can fly over normal turfs and not just space
+
+ icon = 'icons/mecha/fighters64x64.dmi'
+
+ icon_state = ""
+ initial_icon = ""
+
+ step_in = 2 //Fast
+
+ health = 400
+ maxhealth = 400
+
+ infra_luminosity = 6
+
+ opacity = FALSE
+
+ wreckage = /obj/effect/decal/mecha_wreckage/gunpod
+
+ stomp_sound = 'sound/machines/generator/generator_end.ogg'
+ swivel_sound = 'sound/machines/hiss.ogg'
+
+ bound_height = 64
+ bound_width = 64
+
+ max_hull_equip = 2
+ max_weapon_equip = 2
+ max_utility_equip = 1
+ max_universal_equip = 1
+ max_special_equip = 1
+
+/obj/mecha/combat/fighter/Initialize()
+ . = ..()
+ ion_trail = new /datum/effect/effect/system/ion_trail_follow()
+ ion_trail.set_up(src)
+ ion_trail.stop()
+
+/obj/mecha/combat/fighter/moved_inside(var/mob/living/carbon/human/H)
+ . = ..()
+ consider_gravity()
+
+/obj/mecha/combat/fighter/go_out()
+ . = ..()
+ consider_gravity()
+
+//Modified phazon code
+/obj/mecha/combat/fighter/Topic(href, href_list)
+ ..()
+ if (href_list["toggle_stabilization"])
+ stabilization_enabled = !stabilization_enabled
+ send_byjax(src.occupant,"exosuit.browser","stabilization_command","[stabilization_enabled?"Dis":"En"]able thruster stabilization")
+ src.occupant_message("Thruster stabilization [stabilization_enabled? "enabled" : "disabled"].")
+ return
+
+/obj/mecha/combat/fighter/get_commands()
+ var/output = {"
+ "}
+ output += ..()
+ return output
+
+/obj/mecha/combat/fighter/can_ztravel()
+ return (stabilization_enabled && has_charge(step_energy_drain))
+
+// No space drifting
+/obj/mecha/combat/fighter/check_for_support()
+ if (stabilization_enabled)
+ return 1
+
+ return ..()
+
+// No falling if we've got our boosters on
+/obj/mecha/combat/fighter/can_fall()
+ return (stabilization_enabled && has_charge(step_energy_drain))
+
+/obj/mecha/combat/fighter/proc/consider_gravity(var/moved = FALSE)
+ var/gravity = has_gravity()
+ if(gravity && ground_capable && occupant)
+ start_hover()
+ else if((!gravity && ground_capable) || !occupant)
+ stop_hover()
+ else if(moved && gravity && !ground_capable)
+ occupant_message("Collision alert! Vehicle not rated for use in gravity!")
+ take_damage(NOGRAV_FIGHTER_DAMAGE, "brute")
+ playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+
+/obj/mecha/combat/fighter/handle_equipment_movement()
+ . = ..()
+ consider_gravity(TRUE)
+
+/obj/mecha/combat/fighter/proc/start_hover()
+ if(!ion_trail.on) //We'll just use this to store if we're floating or not
+ ion_trail.start()
+ var/amplitude = 2 //maximum displacement from original position
+ var/period = 36 //time taken for the mob to go up >> down >> original position, in deciseconds. Should be multiple of 4
+
+ var/top = old_y + amplitude
+ var/bottom = old_y - amplitude
+ var/half_period = period / 2
+ var/quarter_period = period / 4
+
+ animate(src, pixel_y = top, time = quarter_period, easing = SINE_EASING | EASE_OUT, loop = -1) //up
+ animate(pixel_y = bottom, time = half_period, easing = SINE_EASING, loop = -1) //down
+ animate(pixel_y = old_y, time = quarter_period, easing = SINE_EASING | EASE_IN, loop = -1) //back
+
+/obj/mecha/combat/fighter/proc/stop_hover()
+ if(ion_trail.on)
+ ion_trail.stop()
+ animate(src, pixel_y = old_y, time = 5, easing = SINE_EASING | EASE_IN) //halt animation
+
+/obj/mecha/combat/fighter/check_for_support()
+ if (has_charge(step_energy_drain) && stabilization_enabled)
+ return 1
+
+ var/list/things = orange(1, src)
+
+ if(locate(/obj/structure/grille in things) || locate(/obj/structure/lattice in things) || locate(/turf/simulated in things) || locate(/turf/unsimulated in things))
+ return 1
+ else
+ return 0
+
+
+/obj/mecha/combat/fighter/play_entered_noise(var/mob/who)
+ if(hasInternalDamage())
+ who << sound('sound/mecha/fighter_entered_bad.ogg',volume=50)
+ else
+ who << sound('sound/mecha/fighter_entered.ogg',volume=50)
+
+////////////// Equipment //////////////
+
+// For 64x64 fighters
+/obj/item/mecha_parts/mecha_equipment/omni_shield/fighter64
+ shield_type = /obj/item/shield_projector/rectangle/mecha/fighter64
+/obj/item/shield_projector/rectangle/mecha/fighter64
+ shift_x = 16
+ shift_y = 16
+
+
+////////////// Gunpod //////////////
+
+/obj/mecha/combat/fighter/gunpod
+ name = "Gunpod"
+ desc = "Small mounted weapons platform capable of space and surface combat. More like a flying tank than a dedicated fightercraft."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "gunpod"
+ initial_icon = "gunpod"
+
+ catalogue_data = list(/datum/category_item/catalogue/technology/gunpod)
+ wreckage = /obj/effect/decal/mecha_wreckage/gunpod
+
+ step_in = 3 //Slightly slower than others
+
+ ground_capable = TRUE
+
+ // Paint colors! Null if not set.
+ var/stripe1_color
+ var/stripe2_color
+ var/image/stripe1_overlay
+ var/image/stripe2_overlay
+
+/obj/mecha/combat/fighter/gunpod/loaded/Initialize() //Loaded version with gans
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
+ ME.attach(src)
+
+/obj/mecha/combat/fighter/gunpod/recon/Initialize() //Blinky
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
+ ME.attach(src)
+
+/obj/mecha/combat/fighter/gunpod/update_icon()
+ cut_overlays()
+ ..()
+
+ if(stripe1_color)
+ stripe1_overlay = image("gunpod_stripes1")
+ stripe1_overlay.color = stripe1_color
+ add_overlay(stripe1_overlay)
+ if(stripe2_color)
+ stripe2_overlay = image("gunpod_stripes2")
+ stripe2_overlay.color = stripe2_color
+ add_overlay(stripe2_overlay)
+
+/obj/mecha/combat/fighter/gunpod/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/device/multitool) && state == 1)
+ var/new_paint_location = input("Please select a target zone.", "Paint Zone", null) as null|anything in list("Fore Stripe", "Aft Stripe", "CANCEL")
+ if(new_paint_location && new_paint_location != "CANCEL")
+ var/new_paint_color = input("Please select a paint color.", "Paint Color", null) as color|null
+ if(new_paint_color)
+ switch(new_paint_location)
+ if("Fore Stripe")
+ stripe1_color = new_paint_color
+ if("Aft Stripe")
+ stripe2_color = new_paint_color
+
+ update_icon()
+ else ..()
+
+/obj/effect/decal/mecha_wreckage/gunpod
+ name = "Gunpod wreckage"
+ desc = "Remains of some unfortunate gunpod. Completely unrepairable."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "gunpod-broken"
+ bound_width = 64
+ bound_height = 64
+
+/datum/category_item/catalogue/technology/gunpod
+ name = "Voidcraft - Gunpod"
+ desc = "This is a small space-capable fightercraft that has an arrowhead design. Can hold up to one pilot, \
+ and sometimes one or two passengers, with the right modifications made. \
+ Typically used as small fighter craft, the gunpod can't carry much of a payload, though it's still capable of holding it's own."
+ value = CATALOGUER_REWARD_MEDIUM
+
+
+////////////// Baron //////////////
+
+/obj/mecha/combat/fighter/baron
+ name = "Baron"
+ desc = "A conventional space superiority fighter, one-seater. Not capable of ground operations."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "baron"
+ initial_icon = "baron"
+
+ catalogue_data = list(/datum/category_item/catalogue/technology/baron)
+ wreckage = /obj/effect/decal/mecha_wreckage/baron
+
+ ground_capable = FALSE
+
+/obj/mecha/combat/fighter/baron/loaded/Initialize() //Loaded version with gans
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/omni_shield/fighter64
+ ME.attach(src)
+
+/obj/effect/decal/mecha_wreckage/baron
+ name = "Baron wreckage"
+ desc = "Remains of some unfortunate fighter. Completely unrepairable."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "baron-broken"
+ bound_width = 64
+ bound_height = 64
+
+/datum/category_item/catalogue/technology/baron
+ name = "Voidcraft - Baron"
+ desc = "This is a small space fightercraft that has an arrowhead design. Can hold up to one pilot. \
+ Unlike some fighters, this one is not designed for atmospheric operation, and is only capable of performing \
+ maneuvers in the vacuum of space. Attempting to operate it in an atmosphere is not recommended."
+ value = CATALOGUER_REWARD_MEDIUM
+
+
+////////////// Scoralis //////////////
+
+/obj/mecha/combat/fighter/scoralis
+ name = "scoralis"
+ desc = "An imported space fighter with integral cloaking device. Beware the power consumption, though. Not capable of ground operations."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "scoralis"
+ initial_icon = "scoralis"
+
+ catalogue_data = list(/datum/category_item/catalogue/technology/scoralis)
+ wreckage = /obj/effect/decal/mecha_wreckage/scoralis
+
+ ground_capable = FALSE
+
+/obj/mecha/combat/fighter/scoralis/loaded/Initialize() //Loaded version with gans
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/cloak
+ ME.attach(src)
+
+/obj/effect/decal/mecha_wreckage/scoralis
+ name = "scoralis wreckage"
+ desc = "Remains of some unfortunate fighter. Completely unrepairable."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "scoralis-broken"
+ bound_width = 64
+ bound_height = 64
+
+/datum/category_item/catalogue/technology/scoralis
+ name = "Voidcraft - Scoralis"
+ desc = "An import model fightercraft, this one contains an integral cloaking device that renders the fighter invisible \
+ to the naked eye. Still detectable on thermal sensors, the craft can maneuver in close to ill-equipped foes and strike unseen. \
+ Not rated for atmospheric travel, this craft excels at hit and run tactics, as it will likely need to recharge batteries between each 'hit'."
+ value = CATALOGUER_REWARD_MEDIUM
+
+////////////// Allure //////////////
+
+/obj/mecha/combat/fighter/allure
+ name = "allure"
+ desc = "A fighter of Zorren design, it's blocky appearance is made up for by it's stout armor and finely decorated hull paint."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "allure"
+ initial_icon = "allure"
+
+ catalogue_data = list(/datum/category_item/catalogue/technology/allure)
+ wreckage = /obj/effect/decal/mecha_wreckage/allure
+
+ ground_capable = FALSE
+
+ health = 500
+ maxhealth = 500
+
+/obj/mecha/combat/fighter/allure/loaded/Initialize() //Loaded version with gans
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/cloak
+ ME.attach(src)
+
+/obj/effect/decal/mecha_wreckage/allure
+ name = "allure wreckage"
+ desc = "Remains of some unfortunate fighter. Completely unrepairable."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "allure-broken"
+ bound_width = 64
+ bound_height = 64
+
+/datum/category_item/catalogue/technology/allure
+ name = "Voidcraft - Allure"
+ desc = "A space superiority fighter of zorren design, many would comment that the blocky shape hinders aesthetic appeal. However, Zorren are \
+ often found painting their hulls in intricate designs of purple and gold, and this craft is no exception to the rule. Some individual seems to have \
+ decorated it finely. Import craft like this one often ship with no weapons, though the Zorren saw fit to integrate a cloaking device."
+ value = CATALOGUER_REWARD_MEDIUM
+
+////////////// Pinnace //////////////
+
+/obj/mecha/combat/fighter/pinnace
+ name = "pinnace"
+ desc = "A cramped ship's boat, capable of atmospheric and space flight. Not capable of mounting weapons. Capable of fitting one pilot and one passenger."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "pinnace"
+ initial_icon = "pinnace"
+
+ max_hull_equip = 1
+ max_weapon_equip = 0
+ max_utility_equip = 0
+ max_universal_equip = 0
+ max_special_equip = 1
+
+ catalogue_data = list(/datum/category_item/catalogue/technology/pinnace)
+ wreckage = /obj/effect/decal/mecha_wreckage/pinnace
+
+ ground_capable = TRUE
+
+/obj/mecha/combat/fighter/pinnace/loaded/Initialize() //Loaded version with gans
+ . = ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
+ ME.attach(src)
+
+/obj/effect/decal/mecha_wreckage/pinnace
+ name = "pinnace wreckage"
+ desc = "Remains of some unfortunate ship's boat. Completely unrepairable."
+ icon = 'icons/mecha/fighters64x64.dmi'
+ icon_state = "pinnace-broken"
+ bound_width = 64
+ bound_height = 64
+
+/datum/category_item/catalogue/technology/pinnace
+ name = "Voidcraft - Pinnace"
+ desc = "A very small boat, usually used as a tender at very close ranges. The lack of a bluespace \
+ drive means that it can't get too far from it's parent ship. Though the pinnace is typically unarmed, \
+ it is capable of atmospheric flight and escaping most pursuing fighters by diving into the atmosphere of \
+ nearby planets to seek cover."
+ value = CATALOGUER_REWARD_MEDIUM
+
+#undef NOGRAV_FIGHTER_DAMAGE
\ No newline at end of file
diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm
index a33cd963e2..e413fc892a 100644
--- a/code/game/mecha/combat/gorilla.dm
+++ b/code/game/mecha/combat/gorilla.dm
@@ -178,10 +178,10 @@
src.log_message("Toggled zoom mode.")
src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.")
if(zoom)
- src.occupant.client.view = 12
+ src.occupant.set_viewsize(12)
playsound(src.occupant, 'sound/mecha/imag_enh.ogg',50)
else
- src.occupant.client.view = world.view//world.view - default mob view size
+ src.occupant.set_viewsize() // Reset to default
return
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index 8b2471d953..2b383379ad 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -180,10 +180,10 @@
src.log_message("Toggled zoom mode.")
src.occupant_message("Zoom mode [zoom?"en":"dis"]abled.")
if(zoom)
- src.occupant.client.view = 12
+ src.occupant.set_viewsize(12)
src.occupant << sound('sound/mecha/imag_enh.ogg',volume=50)
else
- src.occupant.client.view = world.view//world.view - default mob view size
+ src.occupant.set_viewsize() // Reset to default
return
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index abf0a15446..d5d1d9d7de 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -231,7 +231,7 @@
/obj/item/mecha_parts/mecha_equipment/proc/occupant_message(message)
if(chassis)
- chassis.occupant_message("\icon[src] [message]")
+ chassis.occupant_message("[bicon(src)] [message]")
return
/obj/item/mecha_parts/mecha_equipment/proc/log_message(message)
diff --git a/code/game/mecha/equipment/tools/cloak.dm b/code/game/mecha/equipment/tools/cloak.dm
new file mode 100644
index 0000000000..6f6ddd1c8f
--- /dev/null
+++ b/code/game/mecha/equipment/tools/cloak.dm
@@ -0,0 +1,70 @@
+/obj/item/mecha_parts/mecha_equipment/cloak
+ name = "cloaking device"
+ desc = "Integrated cloaking system. High power usage, but does render you invisible to the naked eye. Doesn't prevent noise, however."
+ icon_state = "tesla"
+ origin_tech = list(TECH_MAGNET = 5, TECH_DATA = 5)
+ equip_cooldown = 2 SECONDS
+ energy_drain = 300
+ range = 0
+
+ equip_type = EQUIP_SPECIAL
+
+ var/datum/global_iterator/mecha_cloak/cloak_iterator
+
+/obj/item/mecha_parts/mecha_equipment/cloak/Initialize()
+ . = ..()
+ cloak_iterator = new /datum/global_iterator/mecha_cloak(list(src),0)
+ cloak_iterator.set_delay(equip_cooldown)
+
+/obj/item/mecha_parts/mecha_equipment/cloak/Destroy()
+ qdel_null(cloak_iterator)
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/cloak/detach()
+ qdel_null(cloak_iterator)
+ if(!equip_ready) //We were running
+ stop_cloak()
+ return ..()
+
+/obj/item/mecha_parts/mecha_equipment/cloak/get_equip_info()
+ if(!chassis)
+ return
+ return "* [src.name] - [equip_ready ? "A" : "Dea"]ctivate"
+
+/obj/item/mecha_parts/mecha_equipment/cloak/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_cloak"])
+ if(equip_ready)
+ start_cloak()
+ else
+ stop_cloak()
+ return
+
+/obj/item/mecha_parts/mecha_equipment/cloak/proc/start_cloak()
+ if(chassis)
+ chassis.cloak()
+ log_message("Activated.")
+ cloak_iterator.start()
+ set_ready_state(0)
+ playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1)
+
+/obj/item/mecha_parts/mecha_equipment/cloak/proc/stop_cloak()
+ if(chassis)
+ chassis.uncloak()
+ log_message("Deactivated.")
+ cloak_iterator.stop()
+ set_ready_state(1)
+ playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1)
+
+// These things are so silly
+/datum/global_iterator/mecha_cloak/process(var/obj/item/mecha_parts/mecha_equipment/cloak/cloak)
+ //Removed from chassis
+ if(!cloak.chassis)
+ stop()
+ cloak.stop_cloak()
+ return
+ //Ran out of power
+ if(!cloak.chassis.use_power(cloak.energy_drain))
+ stop()
+ cloak.stop_cloak()
+ return
diff --git a/code/game/mecha/equipment/tools/repair_droid.dm b/code/game/mecha/equipment/tools/repair_droid.dm
index f76eeed6f0..f4f9696aa5 100644
--- a/code/game/mecha/equipment/tools/repair_droid.dm
+++ b/code/game/mecha/equipment/tools/repair_droid.dm
@@ -27,16 +27,16 @@
/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M as obj)
..()
droid_overlay = new(src.icon, icon_state = "repair_droid")
- M.overlays += droid_overlay
+ M.add_overlay(droid_overlay)
return
/obj/item/mecha_parts/mecha_equipment/repair_droid/destroy()
- chassis.overlays -= droid_overlay
+ chassis.cut_overlay(droid_overlay)
..()
return
/obj/item/mecha_parts/mecha_equipment/repair_droid/detach()
- chassis.overlays -= droid_overlay
+ chassis.cut_overlay(droid_overlay)
pr_repair_droid.stop()
..()
return
@@ -49,7 +49,7 @@
/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list)
..()
if(href_list["toggle_repairs"])
- chassis.overlays -= droid_overlay
+ chassis.cut_overlay(droid_overlay)
if(pr_repair_droid.toggle())
droid_overlay = new(src.icon, icon_state = "repair_droid_a")
log_message("Activated.")
@@ -57,7 +57,7 @@
droid_overlay = new(src.icon, icon_state = "repair_droid")
log_message("Deactivated.")
set_ready_state(1)
- chassis.overlays += droid_overlay
+ chassis.add_overlay(droid_overlay)
send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
return
diff --git a/code/game/mecha/equipment/tools/shield_omni.dm b/code/game/mecha/equipment/tools/shield_omni.dm
new file mode 100644
index 0000000000..8088cf296a
--- /dev/null
+++ b/code/game/mecha/equipment/tools/shield_omni.dm
@@ -0,0 +1,97 @@
+#define OMNI_SHIELD_DRAIN 30
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield
+ name = "omni shield"
+ desc = "A shield generator that forms an ennlosing, omnidirectional shield around the exosuit."
+ icon_state = "shield"
+ origin_tech = list(TECH_PHORON = 3, TECH_MAGNET = 6, TECH_ILLEGAL = 4)
+ equip_cooldown = 5
+ energy_drain = OMNI_SHIELD_DRAIN
+ range = 0
+
+ var/obj/item/shield_projector/shields = null
+ var/shield_type = /obj/item/shield_projector/rectangle/mecha
+
+ equip_type = EQUIP_HULL
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/critfail()
+ ..()
+ shields.adjust_health(-200)
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/Destroy()
+ QDEL_NULL(shields)
+ ..()
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/attach(obj/mecha/M as obj)
+ . = ..()
+ if(chassis)
+ shields = new shield_type(chassis)
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/detach()
+ if(chassis)
+ QDEL_NULL(shields)
+ . = ..()
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/handle_movement_action()
+ if(chassis && shields)
+ shields.update_shield_positions()
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/proc/toggle_shield()
+ ..()
+ if(shields)
+ shields.set_on(!shields.active)
+ if(shields.active)
+ set_ready_state(0)
+ log_message("Activated.")
+ else
+ set_ready_state(1)
+ log_message("Deactivated.")
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/Topic(href, href_list)
+ ..()
+ if(href_list["toggle_omnishield"])
+ toggle_shield()
+
+/obj/item/mecha_parts/mecha_equipment/omni_shield/get_equip_info()
+ if(!chassis) return
+ return "* [src.name] - [shields?.active?"Dea":"A"]ctivate"
+
+
+////// The shield projector object
+/obj/item/shield_projector/rectangle/mecha
+ shield_health = 200
+ max_shield_health = 200
+ shield_regen_delay = 10 SECONDS
+ shield_regen_amount = 10
+ size_x = 1
+ size_y = 1
+
+ var/shift_x = 0
+ var/shift_y = 0
+
+ var/obj/mecha/my_mech = null
+
+/obj/item/shield_projector/rectangle/mecha/Initialize()
+ . = ..()
+ my_mech = loc
+ GLOB.moved_event.register(my_mech, src, /obj/item/shield_projector/proc/update_shield_positions)
+
+/obj/item/shield_projector/rectangle/mecha/Destroy()
+ GLOB.moved_event.unregister(my_mech, src, /obj/item/shield_projector/proc/update_shield_positions)
+ my_mech = null
+ ..()
+
+/obj/item/shield_projector/rectangle/mecha/create_shield()
+ . = ..()
+ if(shift_x || shift_y)
+ var/obj/effect/directional_shield/newshield = active_shields[active_shields.len]
+ newshield.pixel_x = shift_x
+ newshield.pixel_y = shift_y
+
+/obj/item/shield_projector/rectangle/mecha/adjust_health(amount)
+ . = ..()
+ my_mech.use_power(OMNI_SHIELD_DRAIN)
+ if(!active && shield_health < shield_regen_amount)
+ my_mech.use_power(OMNI_SHIELD_DRAIN * 4)
+
+#undef OMNI_SHIELD_DRAIN
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 24176ef0f8..9f4b633468 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -5,7 +5,7 @@
desc = "A machine used for construction of mechas."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 20
active_power_usage = 5000
req_access = list(access_robotics)
@@ -48,11 +48,11 @@
if(stat)
return
if(busy)
- use_power = 2
+ update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/update_icon()
@@ -177,20 +177,20 @@
switch(emagged)
if(0)
emagged = 0.5
- visible_message("\icon[src] [src] beeps: \"DB error \[Code 0x00F1\]\"")
+ visible_message("[bicon(src)] [src] beeps: \"DB error \[Code 0x00F1\]\"")
sleep(10)
- visible_message("\icon[src] [src] beeps: \"Attempting auto-repair\"")
+ visible_message("[bicon(src)] [src] beeps: \"Attempting auto-repair\"")
sleep(15)
- visible_message("\icon[src] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
+ visible_message("[bicon(src)] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
sleep(30)
- visible_message("\icon[src] [src] beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
+ visible_message("[bicon(src)] [src] beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
req_access = null
emagged = 1
return 1
if(0.5)
- visible_message("\icon[src] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
+ visible_message("[bicon(src)] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
if(1)
- visible_message("\icon[src] [src] beeps: \"No records in User DB\"")
+ visible_message("[bicon(src)] [src] beeps: \"No records in User DB\"")
/obj/machinery/mecha_part_fabricator/proc/update_busy()
if(queue.len)
diff --git a/code/game/mecha/mech_prosthetics.dm b/code/game/mecha/mech_prosthetics.dm
index f554c936c6..076eeed9dc 100644
--- a/code/game/mecha/mech_prosthetics.dm
+++ b/code/game/mecha/mech_prosthetics.dm
@@ -5,7 +5,7 @@
desc = "A machine used for construction of prosthetics."
density = 1
anchored = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
idle_power_usage = 20
active_power_usage = 5000
req_access = list(access_robotics)
@@ -52,11 +52,11 @@
if(stat)
return
if(busy)
- use_power = 2
+ update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
- use_power = 1
+ update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/pros_fabricator/update_icon()
@@ -225,20 +225,20 @@
switch(emagged)
if(0)
emagged = 0.5
- visible_message("\icon[src] [src] beeps: \"DB error \[Code 0x00F1\]\"")
+ visible_message("[bicon(src)] [src] beeps: \"DB error \[Code 0x00F1\]\"")
sleep(10)
- visible_message("\icon[src] [src] beeps: \"Attempting auto-repair\"")
+ visible_message("[bicon(src)] [src] beeps: \"Attempting auto-repair\"")
sleep(15)
- visible_message("\icon[src] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
+ visible_message("[bicon(src)] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
sleep(30)
- visible_message("\icon[src] [src] beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
+ visible_message("[bicon(src)] [src] beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
req_access = null
emagged = 1
return 1
if(0.5)
- visible_message("\icon[src] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
+ visible_message("[bicon(src)] [src] beeps: \"DB not responding \[Code 0x0003\]...\"")
if(1)
- visible_message("\icon[src] [src] beeps: \"No records in User DB\"")
+ visible_message("[bicon(src)] [src] beeps: \"No records in User DB\"")
/obj/machinery/pros_fabricator/proc/update_busy()
if(queue.len)
diff --git a/code/game/mecha/mech_sensor.dm b/code/game/mecha/mech_sensor.dm
index 72202788b9..33147e0ab1 100644
--- a/code/game/mecha/mech_sensor.dm
+++ b/code/game/mecha/mech_sensor.dm
@@ -6,7 +6,7 @@
anchored = 1
density = 1
throwpass = 1
- use_power = 1
+ use_power = USE_POWER_IDLE
layer = ON_WINDOW_LAYER
power_channel = EQUIP
var/on = 0
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index d78053d6b2..2df16caea6 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -259,7 +259,9 @@
/obj/mecha/proc/check_for_support()
- if(locate(/obj/structure/grille, orange(1, src)) || locate(/obj/structure/lattice, orange(1, src)) || locate(/turf/simulated, orange(1, src)) || locate(/turf/unsimulated, orange(1, src)))
+ var/list/things = orange(1, src)
+
+ if(locate(/obj/structure/grille in things) || locate(/obj/structure/lattice in things) || locate(/turf/simulated in things) || locate(/turf/unsimulated in things))
return 1
else
return 0
@@ -281,7 +283,7 @@
if(equipment && equipment.len)
to_chat(user, "It's equipped with:")
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
- to_chat(user, "\icon[ME] [ME]")
+ to_chat(user, "[bicon(ME)] [ME]")
return
@@ -397,21 +399,26 @@
/obj/mecha/relaymove(mob/user,direction)
if(user != src.occupant) //While not "realistic", this piece is player friendly.
if(istype(user,/mob/living/carbon/brain))
- to_chat(user, "You try to move, but you are not the pilot! The exosuit doesn't respond.")
+ to_chat(user, "You try to move, but you are not the pilot! The exosuit doesn't respond.")
return 0
user.forceMove(get_turf(src))
to_chat(user, "You climb out from [src]")
return 0
if(connected_port)
if(world.time - last_message > 20)
- src.occupant_message("Unable to move while connected to the air system port")
+ src.occupant_message("Unable to move while connected to the air system port")
last_message = world.time
return 0
if(state)
- occupant_message("Maintenance protocols in effect")
+ occupant_message("Maintenance protocols in effect")
return
return domove(direction)
+/obj/mecha/proc/can_ztravel()
+ for(var/obj/item/mecha_parts/mecha_equipment/tool/jetpack/jp in equipment)
+ return jp.equip_ready
+ return FALSE
+
/obj/mecha/proc/domove(direction)
return call((proc_res["dyndomove"]||src), "dyndomove")(direction)
@@ -423,20 +430,51 @@
return 0
if(!has_charge(step_energy_drain))
return 0
+
var/move_result = 0
+
if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
move_result = mechsteprand()
- else if(src.dir!=direction)
+ //Up/down zmove
+ else if(direction & UP || direction & DOWN)
+ if(!can_ztravel())
+ occupant_message("Your vehicle lacks the capacity to move in that direction!")
+ return FALSE
+
+ //We're using locs because some mecha are 2x2 turfs. So thicc!
+ var/result = TRUE
+
+ for(var/turf/T in locs)
+ if(!T.CanZPass(src,direction))
+ occupant_message("You can't move that direction from here!")
+ result = FALSE
+ break
+ var/turf/dest = direction & UP ? GetAbove(T) : GetBelow(T)
+ if(!dest)
+ occupant_message("There is nothing of interest in this direction.")
+ result = FALSE
+ break
+ if(!dest.CanZPass(src,direction))
+ occupant_message("There's something blocking your movement in that direction!")
+ result = FALSE
+ break
+ if(result)
+ move_result = mechstep(direction)
+ //Turning
+ else if(src.dir != direction)
move_result = mechturn(direction)
+ //Stepping
else
move_result = mechstep(direction)
+
+
if(move_result)
can_move = 0
use_power(step_energy_drain)
if(istype(src.loc, /turf/space))
if(!src.check_for_support())
src.pr_inertial_movement.start(list(src,direction))
- src.log_message("Movement control lost. Inertial movement started.")
+ src.log_message("Movement control lost. Inertial movement started.")
if(do_after(step_in))
can_move = 1
return 1
@@ -1222,26 +1260,32 @@
src.icon_state = src.reset_icon()
set_dir(dir_in)
playsound(src, 'sound/machines/windowdoor.ogg', 50, 1)
- if(!hasInternalDamage()) //Otherwise it's not nominal!
- switch(mech_faction)
- if(MECH_FACTION_NT)//The good guys category
- if(firstactivation)//First time = long activation sound
- firstactivation = 1
- src.occupant << sound('sound/mecha/LongNanoActivation.ogg',volume=50)
- else
- src.occupant << sound('sound/mecha/nominalnano.ogg',volume=50)
- if(MECH_FACTION_SYNDI)//Bad guys
- if(firstactivation)
- firstactivation = 1
- src.occupant << sound('sound/mecha/LongSyndiActivation.ogg',volume=50)
- else
- src.occupant << sound('sound/mecha/nominalsyndi.ogg',volume=50)
- else//Everyone else gets the normal noise
- src.occupant << sound('sound/mecha/nominal.ogg',volume=50)
+ if(occupant.client && cloaked_selfimage)
+ occupant.client.images += cloaked_selfimage
+ play_entered_noise(occupant)
return 1
else
return 0
+/obj/mecha/proc/play_entered_noise(var/mob/who)
+ if(!hasInternalDamage()) //Otherwise it's not nominal!
+ switch(mech_faction)
+ if(MECH_FACTION_NT)//The good guys category
+ if(firstactivation)//First time = long activation sound
+ firstactivation = 1
+ who << sound('sound/mecha/LongNanoActivation.ogg',volume=50)
+ else
+ who << sound('sound/mecha/nominalnano.ogg',volume=50)
+ if(MECH_FACTION_SYNDI)//Bad guys
+ if(firstactivation)
+ firstactivation = 1
+ who << sound('sound/mecha/LongSyndiActivation.ogg',volume=50)
+ else
+ who << sound('sound/mecha/nominalsyndi.ogg',volume=50)
+ else//Everyone else gets the normal noise
+ who << sound('sound/mecha/nominal.ogg',volume=50)
+
+
/obj/mecha/verb/view_stats()
set name = "View Stats"
set category = "Exosuit Interface"
@@ -1285,45 +1329,21 @@
else
return
if(mob_container.forceMove(src.loc))//ejecting mob container
- /*
- if(ishuman(occupant) && (return_pressure() > HAZARD_HIGH_PRESSURE))
- use_internal_tank = 0
- var/datum/gas_mixture/environment = get_turf_air()
- if(environment)
- var/env_pressure = environment.return_pressure()
- var/pressure_delta = (cabin.return_pressure() - env_pressure)
- //Can not have a pressure delta that would cause environment pressure > tank pressure
-
- var/transfer_moles = 0
- if(pressure_delta > 0)
- transfer_moles = pressure_delta*environment.volume/(cabin.return_temperature() * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = cabin.air_contents.remove(transfer_moles)
- loc.assume_air(removed)
-
- occupant.SetStunned(5)
- occupant.SetWeakened(5)
- to_chat(occupant, "You were blown out of the mech!")
- */
- src.log_message("[mob_container] moved out.")
+ log_message("[mob_container] moved out.")
occupant.reset_view()
- /*
- if(src.occupant.client)
- src.occupant.client.eye = src.occupant.client.mob
- src.occupant.client.perspective = MOB_PERSPECTIVE
- */
- src.occupant << browse(null, "window=exosuit")
+ occupant << browse(null, "window=exosuit")
+ if(occupant.client && cloaked_selfimage)
+ occupant.client.images -= cloaked_selfimage
if(istype(mob_container, /obj/item/device/mmi))
var/obj/item/device/mmi/mmi = mob_container
if(mmi.brainmob)
occupant.loc = mmi
mmi.mecha = null
- src.occupant.canmove = 0
- src.occupant = null
- src.icon_state = src.reset_icon()+"-open"
- src.set_dir(dir_in)
- src.verbs -= /obj/mecha/verb/eject
+ occupant.canmove = 0
+ occupant = null
+ icon_state = src.reset_icon()+"-open"
+ set_dir(dir_in)
+ verbs -= /obj/mecha/verb/eject
return
/////////////////////////
@@ -1604,7 +1624,7 @@
/obj/mecha/proc/occupant_message(message as text)
if(message)
if(src.occupant && src.occupant.client)
- to_chat(src.occupant, "\icon[src] [message]")
+ to_chat(src.occupant, "[bicon(src)] [message]")
return
/obj/mecha/proc/log_message(message as text,red=null)
@@ -1837,7 +1857,7 @@
O.aiRestorePowerRoutine = 0
O.control_disabled = 1 // Can't control things remotely if you're stuck in a card!
O.laws = AI.laws
- O.stat = AI.stat
+ O.set_stat(AI.stat)
O.oxyloss = AI.getOxyLoss()
O.fireloss = AI.getFireLoss()
O.bruteloss = AI.getBruteLoss()
@@ -2026,6 +2046,17 @@
/////////////
+/obj/mecha/cloak()
+ . = ..()
+ if(occupant && occupant.client && cloaked_selfimage)
+ occupant.client.images += cloaked_selfimage
+
+/obj/mecha/uncloak()
+ if(occupant && occupant.client && cloaked_selfimage)
+ occupant.client.images -= cloaked_selfimage
+ return ..()
+
+
//debug
/*
/obj/mecha/verb/test_int_damage()
diff --git a/code/game/mecha/space/hoverpod.dm b/code/game/mecha/space/hoverpod.dm
index 31558458d9..fc5fc1e739 100644
--- a/code/game/mecha/space/hoverpod.dm
+++ b/code/game/mecha/space/hoverpod.dm
@@ -26,11 +26,20 @@
max_universal_equip = 1
max_special_equip = 1
-/obj/mecha/working/hoverpod/New()
- ..()
+/obj/mecha/working/hoverpod/Initialize()
+ . = ..()
ion_trail = new /datum/effect/effect/system/ion_trail_follow()
ion_trail.set_up(src)
- ion_trail.start()
+
+/obj/mecha/working/hoverpod/moved_inside(var/mob/living/carbon/human/H as mob)
+ . = ..(H)
+ if(.)
+ ion_trail.start()
+
+/obj/mecha/working/hoverpod/go_out()
+ . = ..()
+ if(!occupant)
+ ion_trail.stop()
//Modified phazon code
/obj/mecha/working/hoverpod/Topic(href, href_list)
@@ -52,6 +61,9 @@
output += ..()
return output
+/obj/mecha/working/hoverpod/can_ztravel()
+ return (stabilization_enabled && has_charge(step_energy_drain))
+
// No space drifting
/obj/mecha/working/hoverpod/check_for_support()
//does the hoverpod have enough charge left to stabilize itself?
@@ -106,7 +118,7 @@
max_special_equip = 1
/obj/mecha/working/hoverpod/combatpod/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
@@ -117,7 +129,7 @@
desc = "Who knew a tiny ball could fit three people?"
/obj/mecha/working/hoverpod/shuttlepod/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tool/passenger
diff --git a/code/game/mecha/space/shuttle.dm b/code/game/mecha/space/shuttle.dm
index 7e361ece0c..bf9aec3476 100644
--- a/code/game/mecha/space/shuttle.dm
+++ b/code/game/mecha/space/shuttle.dm
@@ -41,44 +41,30 @@
max_universal_equip = 1
max_special_equip = 1
-/obj/mecha/working/hoverpod/Initialize()
- ..()
- ion_trail.stop()
-
-/obj/mecha/working/hoverpod/shuttlecraft/moved_inside(var/mob/living/carbon/human/H as mob)
- . = ..(H)
- if(.)
- ion_trail.start()
-
-/obj/mecha/working/hoverpod/shuttlecraft/go_out()
- . = ..()
- if(!occupant)
- ion_trail.stop()
-
/obj/mecha/working/hoverpod/shuttlecraft/update_icon()
- overlays.Cut()
+ cut_overlays()
..()
if(base_paint)
if(!base_paint_mask)
base_paint_mask = image(icon, "[initial_icon]-mask+base", src.layer + 1)
base_paint_mask.color = base_paint
- overlays |= base_paint_mask
+ add_overlay(base_paint_mask)
if(front_paint)
if(!front_paint_mask)
front_paint_mask = image(icon, "[initial_icon]-mask+front", src.layer + 1)
front_paint_mask.color = front_paint
- overlays |= front_paint_mask
+ add_overlay(front_paint_mask)
if(engine_paint)
if(!engine_paint_mask)
engine_paint_mask = image(icon, "[initial_icon]-mask+engine", src.layer + 1)
engine_paint_mask.color = engine_paint
- overlays |= engine_paint_mask
+ add_overlay(engine_paint_mask)
if(central_paint)
if(!engine_paint_mask)
central_paint_mask = image(icon, "[initial_icon]-mask+central", src.layer + 2)
central_paint_mask.color = central_paint
- overlays |= central_paint_mask
+ add_overlay(central_paint_mask)
/obj/mecha/working/hoverpod/shuttlecraft/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/device/multitool) && state == 1)
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 8a9220e87f..203b22c93c 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -44,3 +44,50 @@
icon_state = "explosionfast"
duration = 4
// VOREStation Add End
+
+/obj/effect/temp_visual/impact_effect
+ icon_state = "impact_bullet"
+ plane = PLANE_LIGHTING_ABOVE // So they're visible even in a shootout in maint.
+ duration = 5
+
+/obj/effect/temp_visual/impact_effect/Initialize(mapload, obj/item/projectile/P, x, y)
+ pixel_x = x
+ pixel_y = y
+ return ..()
+
+/obj/effect/temp_visual/impact_effect/red_laser
+ icon_state = "impact_laser"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/red_laser/wall
+ icon_state = "impact_laser_wall"
+ duration = 10
+
+/obj/effect/temp_visual/impact_effect/blue_laser
+ icon_state = "impact_laser_blue"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/green_laser
+ icon_state = "impact_laser_green"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/purple_laser
+ icon_state = "impact_laser_purple"
+ duration = 4
+
+// Colors itself based on the projectile.
+// Checks light_color and color.
+/obj/effect/temp_visual/impact_effect/monochrome_laser
+ icon_state = "impact_laser_monochrome"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/monochrome_laser/Initialize(mapload, obj/item/projectile/P, x, y)
+ if(P.light_color)
+ color = P.light_color
+ else if(P.color)
+ color = P.color
+ return ..()
+
+/obj/effect/temp_visual/impact_effect/ion
+ icon_state = "shieldsparkles"
+ duration = 6
\ No newline at end of file
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index ec178a7709..26a0a6478e 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -634,6 +634,8 @@ modules/mob/mob_movement.dm if you move you will be zoomed out
modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
*/
//Looking through a scope or binoculars should /not/ improve your periphereal vision. Still, increase viewsize a tiny bit so that sniping isn't as restricted to NSEW
+/obj/item/var/ignore_visor_zoom_restriction = FALSE
+
/obj/item/proc/zoom(var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view
var/devicename
@@ -661,7 +663,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
if(!zoom && !cannotzoom)
if(H.hud_used.hud_shown)
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
- H.client.view = viewsize
+ H.set_viewsize(viewsize)
zoom = 1
var/tilesize = 32
@@ -682,11 +684,12 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
H.client.pixel_y = 0
H.visible_message("[usr] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].")
- H.looking_elsewhere = TRUE
+ if(!ignore_visor_zoom_restriction)
+ H.looking_elsewhere = TRUE
H.handle_vision()
else
- H.client.view = world.view
+ H.set_viewsize() // Reset to default
if(!H.hud_used.hud_shown)
H.toggle_zoom_hud()
zoom = 0
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index e5acb5c4e7..69ca365690 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -655,8 +655,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
// auto update every Master Controller tick
ui.set_auto_update(auto_update)
-//NOTE: graphic resources are loaded on client login
/obj/item/device/pda/attack_self(mob/user as mob)
+ var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
+ assets.send(user)
user.set_machine(src)
@@ -1146,7 +1147,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (!beep_silent)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
- O.show_message(text("\icon[src] *[message_tone]*"))
+ O.show_message(text("[bicon(src)] *[message_tone]*"))
//Search for holder of the PDA.
var/mob/living/L = null
if(loc && isliving(loc))
@@ -1161,7 +1162,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
SSnanoui.update_user_uis(L, src) // Update the receiving user's PDA UI so that they can see the new message
/obj/item/device/pda/proc/new_news(var/message)
- new_info(news_silent, newstone, news_silent ? "" : "\icon[src] [message]")
+ new_info(news_silent, newstone, news_silent ? "" : "[bicon(src)] [message]")
if(!news_silent)
new_news = 1
@@ -1176,7 +1177,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_message(sending_device, sending_device.owner, sending_device.ownjob, message)
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message, var/reply = 1)
- var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" ([reply ? "Reply" : "Unable to Reply"])"
+ var/reception_message = "[bicon(src)] Message from [sender] ([sender_job]), \"[message]\" ([reply ? "Reply" : "Unable to Reply"])"
new_info(message_silent, ttone, reception_message)
log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]", usr)
@@ -1188,7 +1189,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(ismob(sending_unit.loc) && isAI(loc))
track = "(Follow)"
- var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]"
+ var/reception_message = "[bicon(src)] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]"
new_info(message_silent, newstone, reception_message)
log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]",usr)
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index e34d1180c9..2a662ea5ff 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -425,14 +425,14 @@ var/list/civilian_cartridges = list(
if(mode==47)
var/supplyData[0]
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (shuttle)
supplyData["shuttle_moving"] = shuttle.has_arrive_time()
supplyData["shuttle_eta"] = shuttle.eta_minutes()
supplyData["shuttle_loc"] = shuttle.at_station() ? "Station" : "Dock"
var/supplyOrderCount = 0
var/supplyOrderData[0]
- for(var/S in supply_controller.shoppinglist)
+ for(var/S in SSsupply.shoppinglist)
var/datum/supply_order/SO = S
supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.ordered_by, "Comment" = html_encode(SO.comment))
@@ -444,7 +444,7 @@ var/list/civilian_cartridges = list(
var/requestCount = 0
var/requestData[0]
- for(var/S in supply_controller.order_history)
+ for(var/S in SSsupply.order_history)
var/datum/supply_order/SO = S
if(SO.status != SUP_ORDER_REQUESTED)
continue
diff --git a/code/game/objects/items/devices/ai_detector.dm b/code/game/objects/items/devices/ai_detector.dm
index fde112706f..94d3a35912 100644
--- a/code/game/objects/items/devices/ai_detector.dm
+++ b/code/game/objects/items/devices/ai_detector.dm
@@ -94,22 +94,22 @@
if(new_state != old_state)
switch(new_state)
if(PROXIMITY_OFF_CAMERANET)
- to_chat(carrier, "\icon[src] Now outside of camera network.")
+ to_chat(carrier, "[bicon(src)] Now outside of camera network.")
carrier << 'sound/machines/defib_failed.ogg'
if(PROXIMITY_NONE)
- to_chat(carrier, "\icon[src] Now within camera network, AI and cameras unfocused.")
+ to_chat(carrier, "[bicon(src)] Now within camera network, AI and cameras unfocused.")
carrier << 'sound/machines/defib_safetyOff.ogg'
if(PROXIMITY_NEAR)
- to_chat(carrier, "\icon[src] Warning: AI focus at nearby location.")
+ to_chat(carrier, "[bicon(src)] Warning: AI focus at nearby location.")
carrier << 'sound/machines/defib_SafetyOn.ogg'
if(PROXIMITY_ON_SCREEN)
- to_chat(carrier, "\icon[src] Alert: AI or camera focused at current location!")
+ to_chat(carrier, "[bicon(src)] Alert: AI or camera focused at current location!")
carrier <<'sound/machines/defib_ready.ogg'
if(PROXIMITY_TRACKING)
- to_chat(carrier, "\icon[src] Danger: AI is actively tracking you!")
+ to_chat(carrier, "[bicon(src)] Danger: AI is actively tracking you!")
carrier << 'sound/machines/defib_success.ogg'
if(PROXIMITY_TRACKING_FAIL)
- to_chat(carrier, "\icon[src] Danger: AI is attempting to actively track you, but you are outside of the camera network!")
+ to_chat(carrier, "[bicon(src)] Danger: AI is attempting to actively track you, but you are outside of the camera network!")
carrier <<'sound/machines/defib_ready.ogg'
diff --git a/code/game/objects/items/devices/communicator/cartridge.dm b/code/game/objects/items/devices/communicator/cartridge.dm
index b5a46b4ebe..b1c3bd41f2 100644
--- a/code/game/objects/items/devices/communicator/cartridge.dm
+++ b/code/game/objects/items/devices/communicator/cartridge.dm
@@ -140,7 +140,7 @@
if(!reason)
return
- supply_controller.create_order(S, user, reason)
+ SSsupply.create_order(S, user, reason)
internal_data["supply_reqtime"] = (world.time + 5) % 1e5
if(href_list["order_ref"])
@@ -189,20 +189,20 @@
O.approved_at = new_val
if(href_list["approve"])
- supply_controller.approve_order(O, user)
+ SSsupply.approve_order(O, user)
if(href_list["deny"])
- supply_controller.deny_order(O, user)
+ SSsupply.deny_order(O, user)
if(href_list["delete"])
- supply_controller.delete_order(O, user)
+ SSsupply.delete_order(O, user)
if(href_list["clear_all_requests"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
- supply_controller.deny_all_pending(user)
+ SSsupply.deny_all_pending(user)
if(href_list["export_ref"])
var/datum/exported_crate/E = locate(href_list["export_ref"])
@@ -258,29 +258,29 @@
E.value = num
else if(href_list["delete"])
- supply_controller.delete_export(E, user)
+ SSsupply.delete_export(E, user)
else if(href_list["add_item"])
- supply_controller.add_export_item(E, user)
+ SSsupply.add_export_item(E, user)
- if(supply_controller && supply_controller.shuttle)
+ if(SSsupply && SSsupply.shuttle)
switch(href_list["send_shuttle"])
if("send_away")
- if(supply_controller.shuttle.forbidden_atoms_check())
+ if(SSsupply.shuttle.forbidden_atoms_check())
to_chat(usr, "For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.")
else
- supply_controller.shuttle.launch(src)
+ SSsupply.shuttle.launch(src)
to_chat(usr, "Initiating launch sequence.")
if("send_to_station")
- supply_controller.shuttle.launch(src)
- to_chat(usr, "The supply shuttle has been called and will arrive in approximately [round(supply_controller.movetime/600,1)] minutes.")
+ SSsupply.shuttle.launch(src)
+ to_chat(usr, "The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.")
if("cancel_shuttle")
- supply_controller.shuttle.cancel_launch(src)
+ SSsupply.shuttle.cancel_launch(src)
if("force_shuttle")
- supply_controller.shuttle.force_launch(src)
+ SSsupply.shuttle.force_launch(src)
// Status display
switch(href_list["stat_display"])
diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm
index af3ae77ef5..f34ca86c27 100644
--- a/code/game/objects/items/devices/communicator/communicator.dm
+++ b/code/game/objects/items/devices/communicator/communicator.dm
@@ -313,7 +313,7 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
/obj/item/device/communicator/Destroy()
for(var/mob/living/voice/voice in contents)
voice_mobs.Remove(voice)
- to_chat(voice, "\icon[src] Connection timed out with remote host.")
+ to_chat(voice, "[bicon(src)] Connection timed out with remote host.")
qdel(voice)
close_connection(reason = "Connection timed out")
diff --git a/code/game/objects/items/devices/communicator/helper.dm b/code/game/objects/items/devices/communicator/helper.dm
index 25db45b666..ec67686668 100644
--- a/code/game/objects/items/devices/communicator/helper.dm
+++ b/code/game/objects/items/devices/communicator/helper.dm
@@ -394,7 +394,7 @@
// code\game\machinery\computer\supply.dm, starting at line 55
/obj/item/weapon/commcard/proc/get_supply_shuttle_status()
var/shuttle_status[0]
- var/datum/shuttle/ferry/supply/shuttle = supply_controller.shuttle
+ var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
@@ -404,8 +404,8 @@
else
shuttle_status["time"] = 0
if(shuttle.at_station())
- if(shuttle.docking_controller)
- switch(shuttle.docking_controller.get_docking_status())
+ if(shuttle.shuttle_docking_controller)
+ switch(shuttle.shuttle_docking_controller.get_docking_status())
if("docked")
shuttle_status["location"] = "Docked"
shuttle_status["mode"] = SUP_SHUTTLE_DOCKED
@@ -454,7 +454,7 @@
// code\game\machinery\computer\supply.dm, starting at line 130
/obj/item/weapon/commcard/proc/get_supply_orders()
var/orders[0]
- for(var/datum/supply_order/S in supply_controller.order_history)
+ for(var/datum/supply_order/S in SSsupply.order_history)
orders[++orders.len] = list(
"ref" = "\ref[S]",
"status" = S.status,
@@ -477,7 +477,7 @@
// code\game\machinery\computer\supply.dm, starting at line 147
/obj/item/weapon/commcard/proc/get_supply_receipts()
var/receipts[0]
- for(var/datum/exported_crate/E in supply_controller.exported_crates)
+ for(var/datum/exported_crate/E in SSsupply.exported_crates)
receipts[++receipts.len] = list(
"ref" = "\ref[E]",
"contents" = E.contents,
@@ -495,8 +495,8 @@
// code\game\machinery\computer\supply.dm, starting at line 147
/obj/item/weapon/commcard/proc/get_supply_pack_list()
var/supply_packs[0]
- for(var/pack_name in supply_controller.supply_pack)
- var/datum/supply_pack/P = supply_controller.supply_pack[pack_name]
+ for(var/pack_name in SSsupply.supply_pack)
+ var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
if(P.group == internal_data["supply_category"])
var/list/pack = list(
"name" = P.name,
@@ -521,7 +521,7 @@
return list(
"shuttle_auth" = (internal_data["supply_controls"] & SUP_SEND_SHUTTLE),
"order_auth" = (internal_data["supply_controls"] & SUP_ACCEPT_ORDERS),
- "supply_points" = supply_controller.points,
+ "supply_points" = SSsupply.points,
"supply_categories" = all_supply_groups
)
diff --git a/code/game/objects/items/devices/communicator/messaging.dm b/code/game/objects/items/devices/communicator/messaging.dm
index 62e585c982..c6191ab21e 100644
--- a/code/game/objects/items/devices/communicator/messaging.dm
+++ b/code/game/objects/items/devices/communicator/messaging.dm
@@ -34,7 +34,7 @@
if(src in comm.voice_invites)
comm.open_connection(src)
return
- to_chat(src, "\icon[origin_atom] Receiving communicator request from [origin_atom]. To answer, use the Call Communicator \
+ to_chat(src, "[bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the Call Communicator \
verb, and select that name to answer the call.")
src << 'sound/machines/defib_SafetyOn.ogg'
comm.voice_invites |= src
@@ -44,7 +44,7 @@
random = random / 10
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
if(message == "text")
- to_chat(src, "\icon[origin_atom] Received text message from [origin_atom]: \"[text]\"")
+ to_chat(src, "[bicon(origin_atom)] Received text message from [origin_atom]: \"[text]\"")
src << 'sound/machines/defib_safetyOff.ogg'
exonet_messages.Add("From [origin_atom]: [text]")
return
@@ -78,7 +78,7 @@
if(ringer)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
- O.show_message(text("\icon[src] *beep*"))
+ O.show_message(text("[bicon(src)] *beep*"))
alert_called = 1
update_icon()
@@ -89,7 +89,7 @@
L = loc
if(L)
- to_chat(L, "\icon[src] Message from [who].")
+ to_chat(L, "[bicon(src)] Message from [who].")
// Verb: text_communicator()
// Parameters: None
diff --git a/code/game/objects/items/devices/communicator/phone.dm b/code/game/objects/items/devices/communicator/phone.dm
index 098fecf628..e06b17a244 100644
--- a/code/game/objects/items/devices/communicator/phone.dm
+++ b/code/game/objects/items/devices/communicator/phone.dm
@@ -39,15 +39,15 @@
comm.voice_requests.Remove(src)
if(user)
- comm.visible_message("\icon[src] Connecting to [src].")
- to_chat(user, "\icon[src] Attempting to call [comm].")
+ comm.visible_message("[bicon(src)] Connecting to [src].")
+ to_chat(user, "[bicon(src)] Attempting to call [comm].")
sleep(10)
- to_chat(user, "\icon[src] Dialing internally from [station_name()], [system_name()].")
+ to_chat(user, "[bicon(src)] Dialing internally from [station_name()], [system_name()].")
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
- to_chat(user, "\icon[src] Connection re-routed to [comm] at [comm.exonet.address].")
+ to_chat(user, "[bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].")
sleep(40)
- to_chat(user, "\icon[src] Connection to [comm] at [comm.exonet.address] established.")
- comm.visible_message("\icon[src] Connection to [src] at [exonet.address] established.")
+ to_chat(user, "[bicon(src)] Connection to [comm] at [comm.exonet.address] established.")
+ comm.visible_message("[bicon(src)] Connection to [src] at [exonet.address] established.")
sleep(20)
src.add_communicating(comm)
@@ -86,28 +86,28 @@
//Now for some connection fluff.
if(user)
- to_chat(user, "\icon[src] Connecting to [candidate].")
- to_chat(new_voice, "\icon[src] Attempting to call [src].")
+ to_chat(user, "[bicon(src)] Connecting to [candidate].")
+ to_chat(new_voice, "[bicon(src)] Attempting to call [src].")
sleep(10)
- to_chat(new_voice, "\icon[src] Dialing to [station_name()], Kara Subsystem, [system_name()].")
+ to_chat(new_voice, "[bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].")
sleep(20)
- to_chat(new_voice, "\icon[src] Connecting to [station_name()] telecommunications array.")
+ to_chat(new_voice, "[bicon(src)] Connecting to [station_name()] telecommunications array.")
sleep(40)
- to_chat(new_voice, "\icon[src] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].")
+ to_chat(new_voice, "[bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].")
sleep(20)
//We're connected, no need to hide everything.
new_voice.client.screen.Remove(blackness)
qdel(blackness)
- to_chat(new_voice, "\icon[src] Connection to [src] established.")
+ to_chat(new_voice, "[bicon(src)] Connection to [src] established.")
to_chat(new_voice, "To talk to the person on the other end of the call, just talk normally.")
to_chat(new_voice, "If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.")
to_chat(new_voice, "Remember, your character does not know anything you've learned from observing!")
if(new_voice.mind)
new_voice.mind.assigned_role = "Disembodied Voice"
if(user)
- to_chat(user, "\icon[src] Your communicator is now connected to [candidate]'s communicator.")
+ to_chat(user, "[bicon(src)] Your communicator is now connected to [candidate]'s communicator.")
// Proc: close_connection()
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
@@ -120,8 +120,8 @@
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
if(target && voice != target) //If no target is inputted, it deletes all of them.
continue
- to_chat(voice, "\icon[src] [reason].")
- visible_message("\icon[src] [reason].")
+ to_chat(voice, "[bicon(src)] [reason].")
+ visible_message("[bicon(src)] [reason].")
voice_mobs.Remove(voice)
qdel(voice)
update_icon()
@@ -131,8 +131,8 @@
continue
src.del_communicating(comm)
comm.del_communicating(src)
- comm.visible_message("\icon[src] [reason].")
- visible_message("\icon[src] [reason].")
+ comm.visible_message("[bicon(src)] [reason].")
+ visible_message("[bicon(src)] [reason].")
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
end_video()
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
@@ -163,7 +163,7 @@
if(ringer)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
- O.show_message(text("\icon[src] *beep*"))
+ O.show_message(text("[bicon(src)] *beep*"))
alert_called = 1
update_icon()
@@ -174,7 +174,7 @@
L = loc
if(L)
- to_chat(L, "\icon[src] Communications request from [who].")
+ to_chat(L, "[bicon(src)] Communications request from [who].")
// Proc: del_request()
// Parameters: 1 (candidate - the ghost or communicator to be declined)
@@ -197,13 +197,13 @@
us = loc
if(us)
- to_chat(us, "\icon[src] Declined request.")
+ to_chat(us, "[bicon(src)] Declined request.")
// Proc: see_emote()
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
// Description: Relays the emote to all linked communicators.
/obj/item/device/communicator/see_emote(mob/living/M, text)
- var/rendered = "\icon[src] [text]"
+ var/rendered = "[bicon(src)] [text]"
for(var/obj/item/device/communicator/comm in communicating)
var/turf/T = get_turf(comm)
if(!T) return
@@ -241,16 +241,16 @@
var/name_used = M.GetVoice()
var/rendered = null
if(speaking) //Language being used
- rendered = "\icon[src] [name_used] [speaking.format_message(text, verb)]"
+ rendered = "[bicon(src)] [name_used] [speaking.format_message(text, verb)]"
else
- rendered = "\icon[src] [name_used] [verb], \"[text]\""
+ rendered = "[bicon(src)] [name_used] [verb], \"[text]\""
mob.show_message(rendered, 2)
// Proc: show_message()
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
// Description: Relays the message to all linked communicators.
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
- var/rendered = "\icon[src] [msg]"
+ var/rendered = "[bicon(src)] [msg]"
for(var/obj/item/device/communicator/comm in communicating)
var/turf/T = get_turf(comm)
if(!T) return
@@ -331,14 +331,14 @@
to_chat(user, "You cannot see well enough to do that!")
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
- to_chat(user, "\icon[src]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.")
+ to_chat(user, "[bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.")
- to_chat(user, "\icon[src] Attempting to start video over existing call.")
+ to_chat(user, "[bicon(src)] Attempting to start video over existing call.")
sleep(30)
- to_chat(user, "\icon[src] Please wait...")
+ to_chat(user, "[bicon(src)] Please wait...")
video_source = comm.camera
- comm.visible_message("\icon[src] New video connection from [comm].")
+ comm.visible_message("[bicon(src)] New video connection from [comm].")
watch_video(user)
update_icon()
@@ -377,7 +377,7 @@
/obj/item/device/communicator/proc/end_video(var/reason)
video_source = null
- . = "\icon[src] [reason ? reason : "Video session ended"]."
+ . = "[bicon(src)] [reason ? reason : "Video session ended"]."
visible_message(.)
update_icon()
diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm
index 2b55ae5c51..eea822d646 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -384,7 +384,7 @@
if(!H.client && !H.teleop)
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == H.mind)
- to_chat(ghost, "Someone is attempting to resuscitate you. Re-enter your body if you want to be revived! (Verbs -> Ghost -> Re-enter corpse)")
+ ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg')
break
//beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
@@ -489,7 +489,7 @@
living_mob_list += M
M.timeofdeath = 0
- M.stat = UNCONSCIOUS //Life() can bring them back to consciousness if it needs to.
+ M.set_stat(UNCONSCIOUS) //Life() can bring them back to consciousness if it needs to.
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 c16102bc55..6c512650b6 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -78,8 +78,8 @@
var/obj/item/rig_module/module = src.loc
if(module.holder && module.holder.wearer)
var/mob/living/carbon/human/H = module.holder.wearer
- if(istype(H) && H.back)
- var/obj/item/weapon/rig/suit = H.back
+ if(istype(H) && H.get_rig())
+ var/obj/item/weapon/rig/suit = H.get_rig()
if(istype(suit))
return suit.cell
return null
diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm
index 92ff449855..c6f7c3f9f1 100644
--- a/code/game/objects/items/devices/geiger.dm
+++ b/code/game/objects/items/devices/geiger.dm
@@ -62,7 +62,7 @@
scanning = !scanning
update_icon()
update_sound()
- to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] \the [src].")
+ to_chat(user, "[bicon(src)] You switch [scanning ? "on" : "off"] \the [src].")
/obj/item/device/geiger/update_icon()
if(!scanning)
diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm
index f6fad2efb5..0b6d25f0c9 100644
--- a/code/game/objects/items/devices/hacktool.dm
+++ b/code/game/objects/items/devices/hacktool.dm
@@ -47,7 +47,7 @@
to_chat(user, "You are already hacking!")
return 0
if(!is_type_in_list(target, supported_types))
- to_chat(user, "\icon[src] Unable to hack this target!")
+ to_chat(user, "[bicon(src)] Unable to hack this target!")
return 0
var/found = known_targets.Find(target)
if(found)
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 4bc24cf1c5..a39e1d8a17 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -364,7 +364,7 @@ var/global/list/default_medbay_channels = list(
var/list/jamming = is_jammed(src)
if(jamming)
var/distance = jamming["distance"]
- to_chat(M, "\icon[src] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.")
+ to_chat(M, "[bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.")
return FALSE
// First, we want to generate a new radio signal
diff --git a/code/game/objects/items/devices/text_to_speech.dm b/code/game/objects/items/devices/text_to_speech.dm
index 47dfc256fc..f3feacd86e 100644
--- a/code/game/objects/items/devices/text_to_speech.dm
+++ b/code/game/objects/items/devices/text_to_speech.dm
@@ -25,4 +25,4 @@
var/message = sanitize(input(user,"Choose a message to relay to those around you.") as text|null)
if(message)
var/obj/item/device/text_to_speech/O = src
- audible_message("\icon[O] \The [O.name] states, \"[message]\"")
+ audible_message("[bicon(O)] \The [O.name] states, \"[message]\"")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index fe1685ec70..602f6e3a66 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -66,7 +66,7 @@
if(ghost.mind && ghost.mind.current == R)
R.key = ghost.key
- R.stat = CONSCIOUS
+ R.set_stat(CONSCIOUS)
dead_mob_list -= R
living_mob_list |= R
R.notify_ai(ROBOT_NOTIFICATION_NEW_UNIT)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index fa84ea780f..9760e2da8a 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -446,7 +446,7 @@
/obj/item/toy/waterflower/examine(mob/user)
if(..(user, 0))
- to_chat(user, "\icon[src] [src.reagents.total_volume] units of water left!")
+ to_chat(user, "[bicon(src)] [src.reagents.total_volume] units of water left!")
/*
* Bosun's whistle
@@ -902,7 +902,7 @@
/obj/structure/plushie/attack_hand(mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- if(stored_item && !searching)
+ if(stored_item && opened && !searching)
searching = TRUE
if(do_after(user, 10))
to_chat(user, "You find \icon[stored_item] [stored_item] in [src]!")
@@ -999,7 +999,7 @@
to_chat(user, "You can see something in there...")
/obj/item/toy/plushie/attack_self(mob/user as mob)
- if(stored_item && !searching)
+ if(stored_item && opened && !searching)
searching = TRUE
if(do_after(user, 10))
to_chat(user, "You find \icon[stored_item] [stored_item] in [src]!")
diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm
index 4d6b6eea03..4a160d05c8 100644
--- a/code/game/objects/items/weapons/AI_modules.dm
+++ b/code/game/objects/items/weapons/AI_modules.dm
@@ -106,6 +106,7 @@ AI MODULES
if(laws)
laws.sync(target, 0)
+ target.notify_of_law_change()
addAdditionalLaws(target, sender)
to_chat(target, "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ")
diff --git a/code/game/objects/items/weapons/canes.dm b/code/game/objects/items/weapons/canes.dm
new file mode 100644
index 0000000000..f7688fb2d1
--- /dev/null
+++ b/code/game/objects/items/weapons/canes.dm
@@ -0,0 +1,124 @@
+/obj/item/weapon/cane
+ name = "cane"
+ desc = "A cane used by a true gentleman."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "cane"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
+ )
+ force = 5.0
+ throwforce = 7.0
+ w_class = ITEMSIZE_NORMAL
+ matter = list(DEFAULT_WALL_MATERIAL = 50)
+ attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed")
+
+/obj/item/weapon/cane/crutch
+ name ="crutch"
+ desc = "A long stick with a crosspiece at the top, used to help with walking."
+ icon_state = "crutch"
+ item_state = "crutch"
+
+/obj/item/weapon/cane/concealed
+ var/concealed_blade
+
+/obj/item/weapon/cane/concealed/New()
+ ..()
+ var/obj/item/weapon/material/butterfly/switchblade/temp_blade = new(src)
+ concealed_blade = temp_blade
+ temp_blade.attack_self()
+
+/obj/item/weapon/cane/concealed/attack_self(var/mob/user)
+ var/datum/gender/T = gender_datums[user.get_visible_gender()]
+ if(concealed_blade)
+ user.visible_message("[user] has unsheathed \a [concealed_blade] from [T.his] [src]!", "You unsheathe \the [concealed_blade] from \the [src].")
+ // Calling drop/put in hands to properly call item drop/pickup procs
+ playsound(user.loc, 'sound/weapons/holster/sheathout.ogg', 50, 1)
+ user.drop_from_inventory(src)
+ user.put_in_hands(concealed_blade)
+ user.put_in_hands(src)
+ user.update_inv_l_hand(0)
+ user.update_inv_r_hand()
+ concealed_blade = null
+ else
+ ..()
+
+/obj/item/weapon/cane/concealed/attackby(var/obj/item/weapon/material/butterfly/W, var/mob/user)
+ if(!src.concealed_blade && istype(W))
+ var/datum/gender/T = gender_datums[user.get_visible_gender()]
+ user.visible_message("[user] has sheathed \a [W] into [T.his] [src]!", "You sheathe \the [W] into \the [src].")
+ playsound(user.loc, 'sound/weapons/holster/sheathin.ogg', 50, 1)
+ user.drop_from_inventory(W)
+ W.loc = src
+ src.concealed_blade = W
+ update_icon()
+ else
+ ..()
+
+/obj/item/weapon/cane/concealed/update_icon()
+ if(concealed_blade)
+ name = initial(name)
+ icon_state = initial(icon_state)
+ item_state = initial(icon_state)
+ else
+ name = "cane shaft"
+ icon_state = "nullrod"
+ item_state = "foldcane"
+
+/obj/item/weapon/cane/white
+ name = "white cane"
+ desc = "A white cane. They are commonly used by the blind or visually impaired as a mobility tool or as a courtesy to others."
+ icon_state = "whitecane"
+
+/obj/item/weapon/cane/white/attack(mob/M as mob, mob/user as mob)
+ if(user.a_intent == I_HELP)
+ user.visible_message("\The [user] has lightly tapped [M] on the ankle with their white cane!")
+ return TRUE
+ else
+ . = ..()
+
+
+//Code for Telescopic White Cane writen by Gozulio
+
+/obj/item/weapon/cane/white/collapsible
+ name = "telescopic white cane"
+ desc = "A telescopic white cane. They are commonly used by the blind or visually impaired as a mobility tool or as a courtesy to others."
+ icon_state = "whitecane1in"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
+ slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
+ )
+ slot_flags = SLOT_BELT
+ w_class = ITEMSIZE_SMALL
+ force = 3
+ var/on = 0
+
+/obj/item/weapon/cane/white/collapsible/attack_self(mob/user as mob)
+ on = !on
+ if(on)
+ user.visible_message("\The [user] extends the white cane.",\
+ "You extend the white cane.",\
+ "You hear an ominous click.")
+ icon_state = "whitecane1out"
+ item_state_slots = list(slot_r_hand_str = "whitecane", slot_l_hand_str = "whitecane")
+ w_class = ITEMSIZE_NORMAL
+ force = 5
+ attack_verb = list("smacked", "struck", "cracked", "beaten")
+ else
+ user.visible_message("\The [user] collapses the white cane.",\
+ "You collapse the white cane.",\
+ "You hear a click.")
+ icon_state = "whitecane1in"
+ item_state_slots = list(slot_r_hand_str = null, slot_l_hand_str = null)
+ w_class = ITEMSIZE_SMALL
+ force = 3
+ attack_verb = list("hit", "poked", "prodded")
+
+ if(istype(user,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_l_hand()
+ H.update_inv_r_hand()
+
+ playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1)
+ add_fingerprint(user)
+ return TRUE
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 624dbae6a1..f44abcb96b 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -41,7 +41,7 @@
/obj/item/weapon/extinguisher/examine(mob/user)
if(..(user, 0))
- to_chat(user, text("\icon[] [] contains [] units of water left!", src, src.name, src.reagents.total_volume))
+ to_chat(user, "[bicon(src)] [src.name] contains [src.reagents.total_volume] units of water left!")
/obj/item/weapon/extinguisher/attack_self(mob/user as mob)
safety = !safety
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 36725e6b15..c5f1fbc25e 100644
--- a/code/game/objects/items/weapons/id cards/station_ids.dm
+++ b/code/game/objects/items/weapons/id cards/station_ids.dm
@@ -91,8 +91,8 @@
return dat
/obj/item/weapon/card/id/attack_self(mob/user as mob)
- user.visible_message("\The [user] shows you: \icon[src] [src.name]. The assignment on the card: [src.assignment]",\
- "You flash your ID card: \icon[src] [src.name]. The assignment on the card: [src.assignment]")
+ user.visible_message("\The [user] shows you: [bicon(src)] [src.name]. The assignment on the card: [src.assignment]",\
+ "You flash your ID card: [bicon(src)] [src.name]. The assignment on the card: [src.assignment]")
src.add_fingerprint(user)
return
@@ -108,7 +108,7 @@
set category = "Object"
set src in usr
- to_chat(usr, "\icon[src] [src.name]: The current assignment on the card is [src.assignment].")
+ to_chat(usr, "[bicon(src)] [src.name]: The current assignment on the card is [src.assignment].")
to_chat(usr, "The blood type on the card is [blood_type].")
to_chat(usr, "The DNA hash on the card is [dna_hash].")
to_chat(usr, "The fingerprint hash on the card is [fingerprint_hash].")
diff --git a/code/game/objects/items/weapons/implants/implantaugment.dm b/code/game/objects/items/weapons/implants/implantaugment.dm
index 10873d1d06..be6c8721ee 100644
--- a/code/game/objects/items/weapons/implants/implantaugment.dm
+++ b/code/game/objects/items/weapons/implants/implantaugment.dm
@@ -75,12 +75,12 @@
var/obj/item/organ/external/E = setup_augment_slots(H, NewOrgan)
to_chat(H, "You feel a tingling sensation in your [part].")
- if(E && istype(E) && !(H.internal_organs_by_name[NewOrgan.organ_tag]))
+ NewOrgan.forceMove(H)
+ NewOrgan.owner = H
+ if(E && istype(E) && !(H.internal_organs_by_name[NewOrgan.organ_tag]) && NewOrgan.check_verb_compatability())
spawn(rand(1 SECONDS, 30 SECONDS))
to_chat(H, "You feel a pressure in your [E] as the tingling fades, the lump caused by the implant now gone.")
- NewOrgan.forceMove(H)
- NewOrgan.owner = H
if(E.internal_organs == null)
E.internal_organs = list()
E.internal_organs |= NewOrgan
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index 2db6fea0e6..29193b1c08 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -73,12 +73,14 @@
/obj/item/weapon/material/snow/snowball/attack_self(mob/user as mob)
if(user.a_intent == I_HURT)
- visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
+ //visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
+ to_chat(user, "You smash the snowball in your hand.")
var/atom/S = new /obj/item/stack/material/snow(user.loc)
del(src)
user.put_in_hands(S)
else
- visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
+ //visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
+ to_chat(user, "You start compacting the snowball.")
if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
del(src)
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 17d7bc4621..9145786d69 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -168,7 +168,7 @@
. = ..()
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "[icon_state]_blade")
blade_overlay.color = lcolor
- color = lcolor
+ color = lcolor
if(rainbow)
blade_overlay = mutable_appearance(icon, "[icon_state]_blade_rainbow")
blade_overlay.color = "FFFFFF"
@@ -211,6 +211,8 @@
desc = "An energised battle axe."
icon_state = "eaxe"
item_state = "eaxe"
+ colorable = FALSE
+ lcolor = null
//active_force = 150 //holy...
active_force = 60
active_throwforce = 35
diff --git a/code/game/objects/items/weapons/mop_deploy.dm b/code/game/objects/items/weapons/mop_deploy.dm
index 49836005fa..2e2ea6aebc 100644
--- a/code/game/objects/items/weapons/mop_deploy.dm
+++ b/code/game/objects/items/weapons/mop_deploy.dm
@@ -1,6 +1,7 @@
/obj/item/weapon/mop_deploy
name = "mop"
desc = "Deployable mop."
+ icon = 'icons/obj/janitor.dmi'
icon_state = "mop"
force = 3
anchored = 1 // Never spawned outside of inventory, should be fine.
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index 4e89372ec1..744a92e370 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -186,15 +186,22 @@
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "[icon_state]_blade")
if(lcolor)
blade_overlay.color = lcolor
+ color = lcolor
cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
if(active)
add_overlay(blade_overlay)
item_state = "[icon_state]_blade"
set_light(lrange, lpower, lcolor)
else
+ color = "FFFFFF"
set_light(0)
item_state = "[icon_state]"
+ if(istype(usr,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = usr
+ H.update_inv_l_hand()
+ H.update_inv_r_hand()
+
/obj/item/weapon/shield/energy/AltClick(mob/living/user)
if(!in_range(src, user)) //Basic checks to prevent abuse
return
@@ -204,7 +211,7 @@
if(alert("Are you sure you want to recolor your shield?", "Confirm Recolor", "Yes", "No") == "Yes")
var/energy_color_input = input(usr,"","Choose Energy Color",lcolor) as color|null
if(energy_color_input)
- lcolor = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ lcolor = sanitize_hexcolor(energy_color_input)
update_icon()
/obj/item/weapon/shield/energy/examine(mob/user)
diff --git a/code/game/objects/items/weapons/storage/quickdraw.dm b/code/game/objects/items/weapons/storage/quickdraw.dm
index 86d7c76ca2..a2094f50fd 100644
--- a/code/game/objects/items/weapons/storage/quickdraw.dm
+++ b/code/game/objects/items/weapons/storage/quickdraw.dm
@@ -77,4 +77,22 @@
/obj/item/weapon/reagent_containers/syringe,
/obj/item/weapon/reagent_containers/syringe,
/obj/item/weapon/reagent_containers/syringe
- )
\ No newline at end of file
+ )
+
+/obj/item/weapon/storage/quickdraw/syringe_case/clotting
+ desc = "A small case for safely carrying sharps around. This one is deluxe!"
+ max_w_class = ITEMSIZE_SMALL
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
+ )
+
+/obj/item/weapon/storage/quickdraw/syringe_case/bonemed
+ desc = "A small case for safely carrying sharps around. This one is deluxe!"
+ max_w_class = ITEMSIZE_SMALL
+ starts_with = list(
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed,
+ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed
+ )
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 2144a1e394..abae12ed8a 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -266,6 +266,37 @@
/obj/item/weapon/tool/screwdriver
)
+/obj/item/weapon/storage/box/syndie_kit/voidsuit
+ starts_with = list(
+ /obj/item/clothing/suit/space/void/merc,
+ /obj/item/clothing/head/helmet/space/void/merc,
+ /obj/item/clothing/shoes/magboots,
+ /obj/item/weapon/tank/jetpack/oxygen
+ )
+
+/obj/item/weapon/storage/box/syndie_kit/voidsuit/fire
+ starts_with = list(
+ /obj/item/clothing/suit/space/void/merc/fire,
+ /obj/item/clothing/head/helmet/space/void/merc/fire,
+ /obj/item/clothing/shoes/magboots,
+ /obj/item/weapon/tank/jetpack/oxygen
+ )
+
+/obj/item/weapon/storage/box/syndie_kit/concussion_grenade
+ starts_with = list(
+ /obj/item/weapon/grenade/concussion = 8
+ )
+
+/obj/item/weapon/storage/box/syndie_kit/deadliest_game
+ starts_with = list(
+ /obj/item/weapon/beartrap/hunting = 4
+ )
+
+/obj/item/weapon/storage/box/syndie_kit/viral
+ starts_with = list(
+ /obj/item/weapon/virusdish/random = 3
+ )
+
/obj/item/weapon/storage/secure/briefcase/rifle
name = "secure briefcase"
starts_with = list(
@@ -275,6 +306,15 @@
/obj/item/ammo_casing/a145 = 4
)
+/obj/item/weapon/storage/secure/briefcase/flamer
+ name = "secure briefcase"
+ starts_with = list(
+ /obj/item/weapon/gun/magnetic/gasthrower,
+ /obj/item/weapon/cell/super,
+ /obj/item/weapon/stock_parts/capacitor/adv,
+ /obj/item/weapon/tank/phoron/pressurized = 2
+ )
+
/obj/item/weapon/storage/secure/briefcase/fuelrod
name = "heavy briefcase"
desc = "A heavy, locked briefcase."
diff --git a/code/game/objects/items/weapons/syndie.dm b/code/game/objects/items/weapons/syndie.dm
index ee528cb6f8..c4e273deea 100644
--- a/code/game/objects/items/weapons/syndie.dm
+++ b/code/game/objects/items/weapons/syndie.dm
@@ -50,7 +50,7 @@
icon_state = "c-4[size]_1"
playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1)
for(var/mob/O in hearers(src, null))
- O.show_message("\icon[src] The [src.name] beeps! ")
+ O.show_message("[bicon(src)] The [src.name] beeps! ")
sleep(50)
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.
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index 9e984ba05f..6d6839a4a5 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -113,6 +113,19 @@
air_contents.adjust_gas("phoron", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
return
+/obj/item/weapon/tank/phoron/pressurized
+ name = "fuel can"
+ icon_state = "phoron_vox"
+ w_class = ITEMSIZE_NORMAL
+
+/obj/item/weapon/tank/phoron/pressurized/Initialize()
+ ..()
+
+ adjust_scale(0.8)
+
+ air_contents.adjust_gas("phoron", (7*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
+ return
+
/*
* Emergency Oxygen
*/
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 6230350851..ce99e7e837 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -329,6 +329,9 @@ var/list/global/tank_gauge_cache = list()
/obj/item/weapon/tank/remove_air(amount)
return air_contents.remove(amount)
+/obj/item/weapon/tank/proc/remove_air_by_flag(flag, amount)
+ return air_contents.remove_by_flag(flag, amount)
+
/obj/item/weapon/tank/return_air()
return air_contents
@@ -465,7 +468,7 @@ var/list/global/tank_gauge_cache = list()
return
T.assume_air(air_contents)
playsound(get_turf(src), 'sound/weapons/Gunshot_shotgun.ogg', 20, 1)
- visible_message("\icon[src] \The [src] flies apart!", "You hear a bang!")
+ visible_message("[bicon(src)] \The [src] flies apart!", "You hear a bang!")
T.hotspot_expose(air_contents.temperature, 70, 1)
@@ -510,7 +513,7 @@ var/list/global/tank_gauge_cache = list()
T.assume_air(leaked_gas)
if(!leaking)
- visible_message("\icon[src] \The [src] relief valve flips open with a hiss!", "You hear hissing.")
+ visible_message("[bicon(src)] \The [src] relief valve flips open with a hiss!", "You hear hissing.")
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
leaking = 1
#ifdef FIREDBG
diff --git a/code/game/objects/items/weapons/tools/combitool.dm b/code/game/objects/items/weapons/tools/combitool.dm
index 96b64d18f7..b154f059af 100644
--- a/code/game/objects/items/weapons/tools/combitool.dm
+++ b/code/game/objects/items/weapons/tools/combitool.dm
@@ -27,7 +27,7 @@
if(loc == usr && tools.len)
to_chat(usr, "It has the following fittings:")
for(var/obj/item/tool in tools)
- to_chat(usr, "\icon[tool] - [tool.name][tools[current_tool]==tool?" (selected)":""]")
+ to_chat(usr, "[bicon(tool)] - [tool.name][tools[current_tool]==tool?" (selected)":""]")
/obj/item/weapon/combitool/New()
..()
diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm
index 14bdfa3778..c4a4c59f6e 100644
--- a/code/game/objects/items/weapons/tools/weldingtool.dm
+++ b/code/game/objects/items/weapons/tools/weldingtool.dm
@@ -58,7 +58,7 @@
/obj/item/weapon/weldingtool/examine(mob/user)
if(..(user, 0))
if(max_fuel)
- to_chat(user, text("\icon[] The [] contains []/[] units of fuel!", src, src.name, get_fuel(),src.max_fuel ))
+ to_chat(user, "[bicon(src)] The [src.name] contains [get_fuel()]/[src.max_fuel] units of fuel!")
/obj/item/weapon/weldingtool/attack(atom/A, mob/living/user, def_zone)
if(ishuman(A) && user.a_intent == I_HELP)
@@ -560,9 +560,9 @@
to_chat(user, desc)
else
if(power_supply)
- to_chat(user, "\icon[src] The [src.name] has [get_fuel()] charge left.")
+ to_chat(user, "[bicon(src)] The [src.name] has [get_fuel()] charge left.")
else
- to_chat(user, "\icon[src] The [src.name] has no power cell!")
+ to_chat(user, "[bicon(src)] The [src.name] has no power cell!")
/obj/item/weapon/weldingtool/electric/get_fuel()
if(use_external_power)
diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm
index 1f9397e705..8e6667c759 100644
--- a/code/game/objects/items/weapons/traps.dm
+++ b/code/game/objects/items/weapons/traps.dm
@@ -105,6 +105,7 @@
L.Stun(stun_length)
to_chat(L, "The steel jaws of \the [src] bite into you, trapping you in place!")
deployed = 0
+ anchored = FALSE
can_buckle = initial(can_buckle)
/obj/item/weapon/beartrap/Crossed(atom/movable/AM as mob|obj)
diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm
index 856020e52a..2f946a5942 100644
--- a/code/game/objects/items/weapons/weldbackpack.dm
+++ b/code/game/objects/items/weapons/weldbackpack.dm
@@ -145,7 +145,7 @@
/obj/item/weapon/weldpack/examine(mob/user)
..(user)
- to_chat(user, "\icon[src] [src.reagents.total_volume] units of fuel left!")
+ to_chat(user, "[bicon(src)] [src.reagents.total_volume] units of fuel left!")
return
/obj/item/weapon/weldpack/survival
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index c7b8c07f8d..faafdb62f3 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -58,7 +58,7 @@
/obj/CanUseTopic(var/mob/user, var/datum/topic_state/state = default_state)
if(user.CanUseObjTopic(src))
return ..()
- to_chat(user, "\icon[src]Access Denied!")
+ to_chat(user, "[bicon(src)]Access Denied!")
return STATUS_CLOSE
/mob/living/silicon/CanUseObjTopic(var/obj/O)
diff --git a/code/game/objects/structures/holoplant.dm b/code/game/objects/structures/holoplant.dm
index bbd92b81ee..9a46b8ca15 100644
--- a/code/game/objects/structures/holoplant.dm
+++ b/code/game/objects/structures/holoplant.dm
@@ -48,13 +48,13 @@
plant = prepare_icon(emagged ? "emagged" : null)
overlays += plant
set_light(2)
- use_power = 2
+ use_power = USE_POWER_ACTIVE
/obj/machinery/holoplant/proc/deactivate()
overlays -= plant
QDEL_NULL(plant)
set_light(0)
- use_power = 0
+ use_power = USE_POWER_OFF
/obj/machinery/holoplant/power_change()
..()
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index 6e01e0035e..93c48fe8a9 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
/obj/structure/janitorialcart/examine(mob/user)
if(..(user, 1))
- to_chat(user, "[src] \icon[src] contains [reagents.total_volume] unit\s of liquid!")
+ to_chat(user, "[src] [bicon(src)] contains [reagents.total_volume] unit\s of liquid!")
//everything else is visible, so doesn't need to be mentioned
@@ -189,7 +189,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
if(!..(user, 1))
return
- to_chat(user, "\icon[src] This [callme] contains [reagents.total_volume] unit\s of water!")
+ to_chat(user, "[bicon(src)] This [callme] contains [reagents.total_volume] unit\s of water!")
if(mybag)
to_chat(user, "\A [mybag] is hanging on the [callme].")
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 714f2cbfc9..0fff00df19 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -18,7 +18,7 @@ GLOBAL_LIST_BOILERPLATE(all_mopbuckets, /obj/structure/mopbucket)
/obj/structure/mopbucket/examine(mob/user)
if(..(user, 1))
- to_chat(user, "[src] \icon[src] contains [reagents.total_volume] unit\s of water!")
+ to_chat(user, "[src] [bicon(src)] contains [reagents.total_volume] unit\s of water!")
/obj/structure/mopbucket/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/mop))
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 4b4d0e90cc..467579a225 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -124,7 +124,7 @@
icon_state = "shower"
density = 0
anchored = 1
- use_power = 0
+ use_power = USE_POWER_OFF
var/on = 0
var/obj/effect/mist/mymist = null
var/ismist = 0 //needs a var so we can make it linger~
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index c4facdaa20..353df5ecb8 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -192,7 +192,7 @@ obj/structure/windoor_assembly/Destroy()
if(src.electronics && istype(src.electronics, /obj/item/weapon/circuitboard/broken))
to_chat(usr,"The assembly has broken airlock electronics.")
return
- to_chat(usr,browse(null, "window=windoor_access")) //Not sure what this actually does... -Ner
+ usr << browse(null, "window=windoor_access") //Not sure what this actually does... -Ner
playsound(src, W.usesound, 100, 1)
user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame.")
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 9be335a84c..c6918beba9 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -116,26 +116,81 @@
/proc/get_sfx(soundin)
if(istext(soundin))
switch(soundin)
- 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 ("thunder") soundin = pick('sound/effects/thunder/thunder1.ogg', 'sound/effects/thunder/thunder2.ogg', 'sound/effects/thunder/thunder3.ogg', 'sound/effects/thunder/thunder4.ogg',
- 'sound/effects/thunder/thunder5.ogg', 'sound/effects/thunder/thunder6.ogg', 'sound/effects/thunder/thunder7.ogg', 'sound/effects/thunder/thunder8.ogg', 'sound/effects/thunder/thunder9.ogg',
- 'sound/effects/thunder/thunder10.ogg')
- if ("keyboard") soundin = pick('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg')
- if ("button") soundin = pick('sound/machines/button1.ogg','sound/machines/button2.ogg','sound/machines/button3.ogg','sound/machines/button4.ogg')
- if ("switch") soundin = pick('sound/machines/switch1.ogg','sound/machines/switch2.ogg','sound/machines/switch3.ogg','sound/machines/switch4.ogg')
- if ("casing_sound") soundin = pick('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg')
- if ("pickaxe") soundin = pick('sound/weapons/mine/pickaxe1.ogg', 'sound/weapons/mine/pickaxe2.ogg','sound/weapons/mine/pickaxe3.ogg','sound/weapons/mine/pickaxe4.ogg')
+ 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("thunder")
+ soundin = pick(
+ 'sound/effects/thunder/thunder1.ogg',
+ 'sound/effects/thunder/thunder2.ogg',
+ 'sound/effects/thunder/thunder3.ogg',
+ 'sound/effects/thunder/thunder4.ogg',
+ 'sound/effects/thunder/thunder5.ogg',
+ 'sound/effects/thunder/thunder6.ogg',
+ 'sound/effects/thunder/thunder7.ogg',
+ 'sound/effects/thunder/thunder8.ogg',
+ 'sound/effects/thunder/thunder9.ogg',
+ 'sound/effects/thunder/thunder10.ogg')
+ if("keyboard")
+ soundin = pick(
+ 'sound/effects/keyboard/keyboard1.ogg',
+ 'sound/effects/keyboard/keyboard2.ogg',
+ 'sound/effects/keyboard/keyboard3.ogg',
+ 'sound/effects/keyboard/keyboard4.ogg')
+ if("button")
+ soundin = pick('sound/machines/button1.ogg','sound/machines/button2.ogg','sound/machines/button3.ogg','sound/machines/button4.ogg')
+ if("switch")
+ soundin = pick('sound/machines/switch1.ogg','sound/machines/switch2.ogg','sound/machines/switch3.ogg','sound/machines/switch4.ogg')
+ if("casing_sound")
+ soundin = pick('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg')
+ if("ricochet")
+ soundin = pick(
+ 'sound/weapons/effects/ric1.ogg',
+ 'sound/weapons/effects/ric2.ogg',
+ 'sound/weapons/effects/ric3.ogg',
+ 'sound/weapons/effects/ric4.ogg',
+ 'sound/weapons/effects/ric5.ogg')
+ if("bullet_miss")
+ soundin = pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg')
+ if ("pickaxe")
+ soundin = pick(
+ 'sound/weapons/mine/pickaxe1.ogg',
+ 'sound/weapons/mine/pickaxe2.ogg',
+ 'sound/weapons/mine/pickaxe3.ogg',
+ 'sound/weapons/mine/pickaxe4.ogg')
return soundin
//Are these even used?
diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm
index 6c39e01798..3bae19db69 100644
--- a/code/game/turfs/simulated/dungeon/wall.dm
+++ b/code/game/turfs/simulated/dungeon/wall.dm
@@ -16,26 +16,55 @@
return
/turf/simulated/wall/solidrock //for more stylish anti-cheese.
- name = "solid rock"
- desc = "This rock seems dense, impossible to drill."
description_info = "Probably not going to be able to drill or bomb your way through this, best to try and find a way around."
- icon_state = "bedrock"
- var/base_state = "bedrock"
+ var/rock_side = "rock_side"
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/New(var/newloc)
+ ..(newloc,"bedrock")
/turf/simulated/wall/solidrock/Initialize()
- icon_state = base_state
+ . = ..()
update_icon(1)
+/turf/simulated/wall/solidrock/update_material()
+ name = "solid rock"
+ desc = "This rock seems dense, impossible to drill."
+
+/turf/simulated/wall/solidrock/proc/get_cached_border(var/cache_id, var/direction, var/icon_file, var/icon_state, var/offset = 32)
+ if(!mining_overlay_cache["[cache_id]_[direction]"])
+ var/image/new_cached_image = image(icon_state, dir = direction, layer = ABOVE_TURF_LAYER)
+ switch(direction)
+ if(NORTH)
+ new_cached_image.pixel_y = offset
+ if(SOUTH)
+ new_cached_image.pixel_y = -offset
+ if(EAST)
+ new_cached_image.pixel_x = offset
+ if(WEST)
+ new_cached_image.pixel_x = -offset
+ mining_overlay_cache["[cache_id]_[direction]"] = new_cached_image
+ return new_cached_image
+
+ return mining_overlay_cache["[cache_id]_[direction]"]
+
+/turf/simulated/wall/solidrock/update_icon(var/update_neighbors)
+ if(density)
+ var/image/I
+ for(var/i = 1 to 4)
+ I = image('icons/turf/wall_masks.dmi', "rock[wall_connections[i]]", dir = 1<<(i-1))
+ add_overlay(I)
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src,direction)
+ if(istype(T) && !T.density)
+ add_overlay(get_cached_border(rock_side,direction,icon,rock_side))
+
+ else if(update_neighbors)
+ for(var/direction in alldirs)
+ if(istype(get_step(src, direction), /turf/simulated/wall/solidrock))
+ var/turf/simulated/wall/solidrock/M = get_step(src, direction)
+ M.update_icon()
+
/turf/simulated/wall/solidrock/attackby()
return
@@ -43,4 +72,31 @@
return
/turf/simulated/wall/solidrock/take_damage() //These things are suppose to be unbreakable
- return
\ No newline at end of file
+ return
+
+
+//Mossy rocks for POI. Unbreakable, no teleport.
+
+/turf/simulated/wall/solidrock/mossyrockpoi // Version for POI labyrinths. No teleporting, no breaking.
+ desc = "An old, yet impressively durably rock wall."
+ var/mossyrock_side = "mossyrock_side"
+
+/turf/simulated/wall/solidrock/New(var/newloc)
+ ..(newloc,"mossyrock")
+
+/turf/simulated/wall/solidrock/mossyrockpoi/update_icon(var/update_neighbors)
+ if(density)
+ var/image/I
+ for(var/i = 1 to 4)
+ I = image('icons/turf/wall_masks.dmi', "mossyrock[wall_connections[i]]", dir = 1<<(i-1))
+ add_overlay(I)
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src,direction)
+ if(istype(T) && !T.density)
+ add_overlay(get_cached_border(mossyrock_side,direction,icon,mossyrock_side))
+
+ else if(update_neighbors)
+ for(var/direction in alldirs)
+ if(istype(get_step(src, direction), /turf/simulated/wall/solidrock/mossyrockpoi))
+ var/turf/simulated/wall/solidrock/mossyrockpoi/M = get_step(src, direction)
+ M.update_icon()
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index d670fc3a40..a91b5decc9 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -55,7 +55,7 @@
return new_dest
-/obj/landed_holder/proc/leave_turf()
+/obj/landed_holder/proc/leave_turf(var/turf/base_turf = null)
var/turf/new_source
//Change our source to whatever it was before
if(turf_type)
@@ -67,7 +67,7 @@
new_source.underlays = underlays
new_source.decals = decals
else
- new_source = my_turf.ChangeTurf(get_base_turf_by_area(my_turf),,1)
+ new_source = my_turf.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(my_turf),,1)
return new_source
@@ -83,11 +83,31 @@
var/turf/under_turf //Underlay override turf path.
var/join_flags = 0 //Bitstring to represent adjacency of joining walls
var/join_group = "shuttle" //A tag for what other walls to join with. Null if you don't want them to.
+ var/static/list/antilight_cache
+
+/turf/simulated/shuttle/New()
+ ..()
+ if(!antilight_cache)
+ antilight_cache = list()
+ for(var/diag in cornerdirs)
+ var/image/I = image(LIGHTING_ICON, null, icon_state = "diagonals", layer = 10, dir = diag)
+ I.plane = PLANE_LIGHTING
+ antilight_cache["[diag]"] = I
/turf/simulated/shuttle/Destroy()
landed_holder = null
..()
+// For joined corners touching static lighting turfs, add an overlay to cancel out that part of our lighting overlay.
+/turf/simulated/shuttle/proc/update_breaklights()
+ if(join_flags in cornerdirs) //We're joined at an angle
+ //Dynamic lighting dissolver
+ var/turf/T = get_step(src, turn(join_flags,180))
+ if(!T || !T.dynamic_lighting || !get_area(T).dynamic_lighting)
+ add_overlay(antilight_cache["[join_flags]"], TRUE)
+ return
+ cut_overlay(antilight_cache["[join_flags]"], TRUE)
+
/turf/simulated/shuttle/proc/underlay_update()
if(!takes_underlays)
//Basically, if it's not forced, and we don't care, don't do it.
@@ -103,11 +123,19 @@
//Well if this isn't our first rodeo, we know EXACTLY what we landed on, and it looks like this.
if(landed_holder && !interior_corner)
- var/mutable_appearance/landed_on = new(landed_holder)
- landed_on.layer = FLOAT_LAYER //Not turf
- landed_on.plane = FLOAT_PLANE //Not turf
- us.underlays = list(landed_on)
- appearance = us
+ //Space gets special treatment
+ if(ispath(landed_holder.turf_type, /turf/space))
+ var/image/spaceimage = image(landed_holder.icon, landed_holder.icon_state)
+ spaceimage.plane = SPACE_PLANE
+ underlays = list(spaceimage)
+ else
+ var/mutable_appearance/landed_on = new(landed_holder)
+ landed_on.layer = FLOAT_LAYER //Not turf
+ landed_on.plane = FLOAT_PLANE //Not turf
+ us.underlays = list(landed_on)
+ appearance = us
+
+ spawn update_breaklights() //So that we update the breaklight overlays only after turfs are connected
return
if(!under)
@@ -143,12 +171,15 @@
under_ma = new(under)
if(under_ma)
- if(ispath(under,/turf/space)) //Scramble space turfs
- under_ma.icon_state = "[rand(1,25)]"
+ if(ispath(under,/turf/space) || istype(under,/turf/space)) //Space gets weird treatment
+ under_ma.icon_state = "white"
+ under_ma.plane = SPACE_PLANE
us.underlays = list(under_ma)
appearance = us
+ spawn update_breaklights() //So that we update the breaklight overlays only after turfs are connected
+
return under
/turf/simulated/shuttle/floor
diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm
index f9ae1e7bc3..1ef11c40de 100644
--- a/code/game/turfs/simulated/wall_attacks.dm
+++ b/code/game/turfs/simulated/wall_attacks.dm
@@ -232,7 +232,7 @@
if(WT.remove_fuel(0,user))
to_chat(user, "You start repairing the damage to [src].")
- playsound(src.loc, WT.usesound, 100, 1)
+ playsound(src, WT.usesound, 100, 1)
if(do_after(user, max(5, damage / 5) * WT.toolspeed) && WT && WT.isOn())
to_chat(user, "You finish repairing the damage to [src].")
take_damage(-damage)
diff --git a/code/game/turfs/space/cracked_asteroid.dm b/code/game/turfs/space/cracked_asteroid.dm
index 75cf25fd3f..ca77a8cd2c 100644
--- a/code/game/turfs/space/cracked_asteroid.dm
+++ b/code/game/turfs/space/cracked_asteroid.dm
@@ -7,6 +7,7 @@
icon_state = "asteroid_cracked"
dynamic_lighting = TRUE
keep_sprite = TRUE
+ plane = TURF_PLANE //It's not really space
/turf/space/cracked_asteroid/is_space() // So people don't start floating when standing on it.
return FALSE
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index b72143e4c0..afdaab404b 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -1,20 +1,89 @@
/turf/space
icon = 'icons/turf/space.dmi'
name = "\proper space"
- icon_state = "0"
+ icon_state = "default"
dynamic_lighting = 0
+ plane = SPACE_PLANE
temperature = T20C
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
can_build_into_floor = TRUE
var/keep_sprite = FALSE
// heat_capacity = 700000 No.
+ var/static/list/dust_cache
+ var/static/list/speedspace_cache
+ var/static/list/phase_shift_by_x
+ var/static/list/phase_shift_by_y
+
+/turf/space/proc/build_dust_cache()
+ //Static
+ LAZYINITLIST(dust_cache)
+ for (var/i in 0 to 25)
+ var/image/im = image('icons/turf/space_dust.dmi', "[i]")
+ im.plane = DUST_PLANE
+ im.alpha = 128 //80
+ im.blend_mode = BLEND_ADD
+ dust_cache["[i]"] = im
+ //Moving
+ LAZYINITLIST(speedspace_cache)
+ for (var/i in 0 to 14)
+ // NORTH/SOUTH
+ var/image/im = image('icons/turf/space_dust_transit.dmi', "speedspace_ns_[i]")
+ im.plane = DUST_PLANE
+ im.blend_mode = BLEND_ADD
+ speedspace_cache["NS_[i]"] = im
+ // EAST/WEST
+ im = image('icons/turf/space_dust_transit.dmi', "speedspace_ew_[i]")
+ im.plane = DUST_PLANE
+ im.blend_mode = BLEND_ADD
+ speedspace_cache["EW_[i]"] = im
/turf/space/Initialize()
. = ..()
if(!keep_sprite)
- icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
+ icon_state = "white"
update_starlight()
+ if (!dust_cache)
+ build_dust_cache()
+ toggle_transit() //add static dust
+
+/turf/space/proc/toggle_transit(var/direction)
+ cut_overlays()
+
+ if(!direction)
+ add_overlay(dust_cache["[((x + y) ^ ~(x * y) + z) % 25]"])
+ return
+
+ if(direction & (NORTH|SOUTH))
+ if(!phase_shift_by_x)
+ phase_shift_by_x = get_cross_shift_list(15)
+ var/x_shift = phase_shift_by_x[src.x % (phase_shift_by_x.len - 1) + 1]
+ var/transit_state = ((direction & SOUTH ? world.maxy - src.y : src.y) + x_shift)%15
+ add_overlay(speedspace_cache["NS_[transit_state]"])
+ else if(direction & (EAST|WEST))
+ if(!phase_shift_by_y)
+ phase_shift_by_y = get_cross_shift_list(15)
+ var/y_shift = phase_shift_by_y[src.y % (phase_shift_by_y.len - 1) + 1]
+ var/transit_state = ((direction & WEST ? world.maxx - src.x : src.x) + y_shift)%15
+ add_overlay(speedspace_cache["EW_[transit_state]"])
+
+ for(var/atom/movable/AM in src)
+ if (AM.simulated && !AM.anchored)
+ AM.throw_at(get_step(src,reverse_direction(direction)), 5, 1)
+
+//generates a list used to randomize transit animations so they aren't in lockstep
+/turf/space/proc/get_cross_shift_list(var/size)
+ var/list/result = list()
+
+ result += rand(0, 14)
+ for(var/i in 2 to size)
+ var/shifts = list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
+ shifts -= result[i - 1] //consecutive shifts should not be equal
+ if(i == size)
+ shifts -= result[1] //because shift list is a ring buffer
+ result += pick(shifts)
+
+ return result
/turf/space/is_space()
return 1
@@ -24,6 +93,9 @@
for(var/obj/O in src)
O.hide(0)
+/turf/space/is_solid_structure()
+ return locate(/obj/structure/lattice, src) //counts as solid structure if it has a lattice
+
/turf/space/proc/update_starlight()
if(!config.starlight)
return
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 0bfcb4e0f6..02c589e966 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -1,5 +1,4 @@
/turf/space/transit
- keep_sprite = TRUE
can_build_into_floor = FALSE
var/pushdirection // push things that get caught in the transit tile this direction
@@ -7,87 +6,26 @@
/turf/space/transit/attackby(obj/O as obj, mob/user as mob)
return
-//generates a list used to randomize transit animations so they aren't in lockstep
-/turf/space/transit/proc/get_cross_shift_list(var/size)
- var/list/result = list()
-
- result += rand(0, 14)
- for(var/i in 2 to size)
- var/shifts = list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
- shifts -= result[i - 1] //consecutive shifts should not be equal
- if(i == size)
- shifts -= result[1] //because shift list is a ring buffer
- result += pick(shifts)
-
- return result
+/turf/space/transit/Initialize()
+ . = ..()
+ toggle_transit(reverse_dir[pushdirection])
//------------------------
/turf/space/transit/north // moving to the north
icon_state = "arrow-north"
pushdirection = SOUTH // south because the space tile is scrolling south
- var/static/list/phase_shift_by_x
-
-/turf/space/transit/north/New()
- ..()
- if(!phase_shift_by_x)
- phase_shift_by_x = get_cross_shift_list(15)
-
- var/x_shift = phase_shift_by_x[src.x % (phase_shift_by_x.len - 1) + 1]
- var/transit_state = (world.maxy - src.y + x_shift)%15 + 1
-
- icon_state = "speedspace_ns_[transit_state]"
-//------------------------
/turf/space/transit/south // moving to the south
icon_state = "arrow-south"
pushdirection = SOUTH // south because the space tile is scrolling south
- var/static/list/phase_shift_by_x
-
-/turf/space/transit/south/New()
- ..()
- if(!phase_shift_by_x)
- phase_shift_by_x = get_cross_shift_list(15)
-
- var/x_shift = phase_shift_by_x[src.x % (phase_shift_by_x.len - 1) + 1]
- var/transit_state = (world.maxy - src.y + x_shift)%15 + 1
-
- var/icon/I = new(icon, "speedspace_ns_[transit_state]")
- I.Flip(SOUTH)
- icon = I
-//------------------------
/turf/space/transit/east // moving to the east
icon_state = "arrow-east"
pushdirection = WEST
- var/static/list/phase_shift_by_y
-
-/turf/space/transit/east/New()
- ..()
- if(!phase_shift_by_y)
- phase_shift_by_y = get_cross_shift_list(15)
-
- var/y_shift = phase_shift_by_y[src.y % (phase_shift_by_y.len - 1) + 1]
- var/transit_state = (world.maxx - src.x + y_shift)%15 + 1
-
- icon_state = "speedspace_ew_[transit_state]"
-//------------------------
/turf/space/transit/west // moving to the west
icon_state = "arrow-west"
pushdirection = WEST
- var/static/list/phase_shift_by_y
-
-/turf/space/transit/west/New()
- ..()
- if(!phase_shift_by_y)
- phase_shift_by_y = get_cross_shift_list(15)
-
- var/y_shift = phase_shift_by_y[src.y % (phase_shift_by_y.len - 1) + 1]
- var/transit_state = (world.maxx - src.x + y_shift)%15 + 1
-
- var/icon/I = new(icon, "speedspace_ew_[transit_state]")
- I.Flip(WEST)
- icon = I
//------------------------
\ No newline at end of file
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 4d606bc3f2..8abd2f44fa 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -64,6 +64,10 @@
/turf/proc/is_intact()
return 0
+// Used by shuttle code to check if this turf is empty enough to not crush want it lands on.
+/turf/proc/is_solid_structure()
+ return 1
+
/turf/attack_hand(mob/user)
if(!(user.canmove) || user.restrained() || !(user.pulling))
return 0
diff --git a/code/game/verbs/advanced_who.dm b/code/game/verbs/advanced_who.dm
index bbde65fd07..9f067054f2 100644
--- a/code/game/verbs/advanced_who.dm
+++ b/code/game/verbs/advanced_who.dm
@@ -71,4 +71,5 @@
msg += "[line]\n"
msg += "Total Players: [length(Lines)]"
+ msg = "" + msg + ""
to_chat(src, msg)
\ No newline at end of file
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 978b1dddc1..5df51c1dd0 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -149,12 +149,12 @@
if(target in admins)
admin_stuff += "/([key])"
- to_chat(target, "" + create_text_tag("looc", "LOOC:", target) + " [display_name][admin_stuff]:[msg]")
+ to_chat(target, "" + create_text_tag("looc", "LOOC:", target) + " [display_name][admin_stuff]:[msg]")
for(var/client/target in r_receivers)
var/admin_stuff = "/([key])([admin_jump_link(mob, target.holder)])"
- to_chat(target, "" + create_text_tag("looc", "LOOC:", target) + " (R)[display_name][admin_stuff]:[msg]")
+ to_chat(target, "" + create_text_tag("looc", "LOOC:", target) + " (R)[display_name][admin_stuff]:[msg]")
/mob/proc/get_looc_source()
return src
diff --git a/code/game/world.dm b/code/game/world.dm
index e82bb00d33..1accb20916 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -2,13 +2,6 @@
#define RECOMMENDED_VERSION 501
/world/New()
to_world_log("Map Loading Complete")
- //logs
- log_path += time2text(world.realtime, "YYYY/MM-Month/DD-Day/round-hh-mm-ss")
- diary = file("[log_path].log")
- href_logfile = file("[log_path]-hrefs.htm")
- error_log = file("[log_path]-error.log")
- debug_log = file("[log_path]-debug.log")
- debug_log << "[log_end]\n[log_end]\nStarting up. [time_stamp()][log_end]\n---------------------[log_end]"
changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently
if(byond_version < RECOMMENDED_VERSION)
@@ -26,6 +19,7 @@
GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000
callHook("startup")
+ init_vchat()
//Emergency Fix
load_mods()
//end-emergency fix
@@ -638,4 +632,18 @@ proc/establish_old_db_connection()
maxz++
max_z_changed()
+// Call this to change world.fps, don't modify it directly.
+/world/proc/change_fps(new_value = 20)
+ if(new_value <= 0)
+ CRASH("change_fps() called with [new_value] new_value.")
+ if(fps == new_value)
+ return //No change required.
+
+ fps = new_value
+ on_tickrate_change()
+
+// Called whenver world.tick_lag or world.fps are changed.
+/world/proc/on_tickrate_change()
+ SStimer?.reset_buckets()
+
#undef FAILED_DB_CONNECTION_CUTOFF
diff --git a/code/global_init.dm b/code/global_init.dm
index c562209183..c3f8056d95 100644
--- a/code/global_init.dm
+++ b/code/global_init.dm
@@ -14,9 +14,15 @@ var/global/datum/global_init/init = new ()
Pre-map initialization stuff should go here.
*/
/datum/global_init/New()
-
- makeDatumRefLists()
+ //logs
+ log_path += time2text(world.realtime, "YYYY/MM-Month/DD-Day/round-hh-mm-ss")
+ diary = file("[log_path].log")
+ href_logfile = file("[log_path]-hrefs.htm")
+ error_log = file("[log_path]-error.log")
+ debug_log = file("[log_path]-debug.log")
+ debug_log << "[log_end]\n[log_end]\nStarting up. [time_stamp()][log_end]\n---------------------[log_end]"
load_configuration()
+ makeDatumRefLists()
initialize_integrated_circuits_list()
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 0a35eaae56..e2cab42b42 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -75,6 +75,7 @@ proc/admin_notice(var/message, var/rights)
if(M.client)
body += "| Prison | "
+ body += "\ Send back to Lobby | "
var/muted = M.client.prefs.muted
body += {" Mute:
\[IC |
@@ -128,6 +129,8 @@ proc/admin_notice(var/message, var/rights)
else
body += "Animalize | "
+ body += "Respawn | "
+
// DNA2 - Admin Hax
if(M.dna && iscarbon(M))
body += "
"
diff --git a/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm b/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm
index 4097632aa3..3767d21a8b 100644
--- a/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm
+++ b/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm
@@ -2,17 +2,17 @@
name = "Jump a Shuttle"
/datum/admin_secret_item/admin_secret/jump_shuttle/can_execute(var/mob/user)
- if(!shuttle_controller) return 0
+ if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/jump_shuttle/execute(var/mob/user)
. = ..()
if(!.)
return
- var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
+ var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
if (!shuttle_tag) return
- var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
+ var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
if (!origin_area) return
diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm
index 9d6ce44a2d..2f253a1a80 100644
--- a/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm
+++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm
@@ -2,7 +2,7 @@
name = "Launch a Shuttle"
/datum/admin_secret_item/admin_secret/launch_shuttle/can_execute(var/mob/user)
- if(!shuttle_controller) return 0
+ if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/launch_shuttle/execute(var/mob/user)
@@ -10,15 +10,15 @@
if(!.)
return
var/list/valid_shuttles = list()
- for (var/shuttle_tag in shuttle_controller.shuttles)
- if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
+ for (var/shuttle_tag in SSshuttles.shuttles)
+ if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
valid_shuttles += shuttle_tag
var/shuttle_tag = input(user, "Which shuttle do you want to launch?") as null|anything in valid_shuttles
if (!shuttle_tag)
return
- var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
+ var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
if (S.can_launch())
S.launch(user)
log_and_message_admins("launched the [shuttle_tag] shuttle", user)
diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm
index d1a86fec98..592a8da57c 100644
--- a/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm
+++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm
@@ -2,7 +2,7 @@
name = "Launch a Shuttle (Forced)"
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/can_execute(var/mob/user)
- if(!shuttle_controller) return 0
+ if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/launch_shuttle_forced/execute(var/mob/user)
@@ -10,15 +10,15 @@
if(!.)
return
var/list/valid_shuttles = list()
- for (var/shuttle_tag in shuttle_controller.shuttles)
- if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
+ for (var/shuttle_tag in SSshuttles.shuttles)
+ if (istype(SSshuttles.shuttles[shuttle_tag], /datum/shuttle/autodock))
valid_shuttles += shuttle_tag
var/shuttle_tag = input(user, "Which shuttle's launch do you want to force?") as null|anything in valid_shuttles
if (!shuttle_tag)
return
- var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
+ var/datum/shuttle/autodock/S = SSshuttles.shuttles[shuttle_tag]
if (S.can_force())
S.force_launch(user)
log_and_message_admins("forced the [shuttle_tag] shuttle", user)
diff --git a/code/modules/admin/secrets/admin_secrets/move_shuttle.dm b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm
index 5772bbed54..a79a2d7143 100644
--- a/code/modules/admin/secrets/admin_secrets/move_shuttle.dm
+++ b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm
@@ -2,7 +2,7 @@
name = "Move a Shuttle"
/datum/admin_secret_item/admin_secret/move_shuttle/can_execute(var/mob/user)
- if(!shuttle_controller) return 0
+ if(!SSshuttles) return 0
return ..()
/datum/admin_secret_item/admin_secret/move_shuttle/execute(var/mob/user)
@@ -13,16 +13,15 @@
if (confirm == "Cancel")
return
- var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
+ var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in SSshuttles.shuttles
if (!shuttle_tag) return
- var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
+ var/datum/shuttle/S = SSshuttles.shuttles[shuttle_tag]
- var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
- if (!origin_area) return
+ var/destination_tag = input(user, "Which landmark do you want to jump to? (IF YOU GET THIS WRONG THINGS WILL BREAK)") as null|anything in SSshuttles.registered_shuttle_landmarks
+ if (!destination_tag) return
+ var/destination_location = SSshuttles.get_landmark(destination_tag)
+ if (!destination_location) return
- var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
- if (!destination_area) return
-
- S.move(origin_area, destination_area)
+ S.attempt_move(destination_location)
log_and_message_admins("moved the [shuttle_tag] shuttle", user)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 6e81c6ae9d..d96b32e2df 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1035,6 +1035,29 @@
log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.")
message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1)
+ else if(href_list["sendbacktolobby"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ var/mob/M = locate(href_list["sendbacktolobby"])
+ if(!isobserver(M))
+ to_chat(usr, "You can only send ghost players back to the Lobby.")
+ return
+
+ if(!M.client)
+ to_chat(usr, "[M] doesn't seem to have an active client.")
+ return
+
+ if(alert(usr, "Send [key_name(M)] back to Lobby?", "Message", "Yes", "No") != "Yes")
+ return
+
+ log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
+ message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
+
+ var/mob/new_player/NP = new()
+ NP.ckey = M.ckey
+ qdel(M)
+
else if(href_list["tdome1"])
if(!check_rights(R_FUN)) return
@@ -1193,6 +1216,15 @@
usr.client.cmd_admin_animalize(M)
+ else if(href_list["respawn"])
+ if(!check_rights(R_SPAWN))
+ return
+
+ var/client/C = locate(href_list["respawn"])
+ if(!istype(C))
+ return
+ usr.client.respawn_character_proper(C)
+
else if(href_list["togmutate"])
if(!check_rights(R_SPAWN)) return
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 2bf3a1f5cc..2bd7326b3b 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -6,7 +6,7 @@
set category = null
set name = "Admin PM Mob"
if(!holder)
- to_chat(src, "Error: Admin-PM-Context: Only administrators may use this command.")
+ to_chat(src, "Error: Admin-PM-Context: Only administrators may use this command.")
return
if( !ismob(M) || !M.client )
return
@@ -18,7 +18,7 @@
set category = "Admin"
set name = "Admin PM"
if(!holder)
- to_chat(src, "Error: Admin-PM-Panel: Only administrators may use this command.")
+ to_chat(src, "Error: Admin-PM-Panel: Only administrators may use this command.")
return
var/list/client/targets[0]
for(var/client/T)
@@ -37,7 +37,7 @@
/client/proc/cmd_ahelp_reply(whom)
if(prefs.muted & MUTE_ADMINHELP)
- to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
+ to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
return
var/client/C
if(istext(whom))
@@ -48,16 +48,16 @@
C = whom
if(!C)
if(holder)
- to_chat(src, "Error: Admin-PM: Client not found.")
+ to_chat(src, "Error: Admin-PM: Client not found.")
return
var/datum/admin_help/AH = C.current_ticket
if(AH)
- message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
+ message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.")
var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as text|null
if (!msg)
- message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
+ message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.")
return
cmd_admin_pm(whom, msg, AH)
@@ -65,12 +65,12 @@
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg, datum/admin_help/AH)
if(prefs.muted & MUTE_ADMINHELP)
- to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
+ to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
return
if(!holder && !current_ticket) //no ticket? https://www.youtube.com/watch?v=iHSPf6x1Fdo
- to_chat(src, "You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.")
- to_chat(src, "Message: [msg]")
+ to_chat(src, "You can no longer reply to this ticket, please open another one by using the Adminhelp verb if need be.")
+ to_chat(src, "Message: [msg]")
return
var/client/recipient
@@ -95,14 +95,14 @@
if(!msg)
return
if(holder)
- to_chat(src, "Error: Use the admin IRC channel, nerd.")
+ to_chat(src, "Error: Use the admin IRC channel, nerd.")
return
else
if(!recipient)
if(holder)
- to_chat(src, "Error: Admin-PM: Client not found.")
+ to_chat(src, "Error: Admin-PM: Client not found.")
to_chat(src, msg)
else
current_ticket.MessageNoRecipient(msg)
@@ -116,12 +116,12 @@
return
if(prefs.muted & MUTE_ADMINHELP)
- to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
+ to_chat(src, "Error: Admin-PM: You are unable to use admin PM-s (muted).")
return
if(!recipient)
if(holder)
- to_chat(src, "Error: Admin-PM: Client not found.")
+ to_chat(src, "Error: Admin-PM: Client not found.")
else
current_ticket.MessageNoRecipient(msg)
return
@@ -140,27 +140,27 @@
var/keywordparsedmsg = keywords_lookup(msg)
if(irc)
- to_chat(src, "PM to-Admins: [rawmsg]")
- admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to IRC: [keywordparsedmsg]")
+ to_chat(src, "PM to-Admins: [rawmsg]")
+ admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to IRC: [keywordparsedmsg]")
ircreplyamount--
send2irc("Reply: [ckey]",rawmsg)
else
if(recipient.holder)
if(holder) //both are admins
- to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]")
- to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]")
+ to_chat(recipient, "Admin PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]")
+ to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]")
//omg this is dumb, just fill in both their tickets
- var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]"
+ var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]"
admin_ticket_log(src, interaction_message)
if(recipient != src) //reeee
admin_ticket_log(recipient, interaction_message)
else //recipient is an admin but sender is not
- var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]"
+ var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]"
admin_ticket_log(src, replymsg)
to_chat(recipient, replymsg)
- to_chat(src, "PM to-Admins: [msg]")
+ to_chat(src, "PM to-Admins: [msg]")
//play the recieving admin the adminhelp sound (if they have them enabled)
if(recipient.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping))
@@ -171,12 +171,12 @@
if(!recipient.current_ticket)
new /datum/admin_help(msg, recipient, TRUE)
- to_chat(recipient, "-- Administrator private message --")
- to_chat(recipient, "Admin PM from-[key_name(src, recipient, 0)]: [msg]")
- to_chat(recipient, "Click on the administrator's name to reply.")
- to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [msg]")
+ to_chat(recipient, "-- Administrator private message --")
+ to_chat(recipient, "Admin PM from-[key_name(src, recipient, 0)]: [msg]")
+ to_chat(recipient, "Click on the administrator's name to reply.")
+ to_chat(src, "Admin PM to-[key_name(recipient, src, 1)]: [msg]")
- admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]")
+ admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]")
//always play non-admin recipients the adminhelp sound
recipient << 'sound/effects/adminhelp.ogg'
@@ -195,19 +195,19 @@
return
else //neither are admins
- to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.")
+ to_chat(src, "Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.")
return
if(irc)
log_admin("PM: [key_name(src)]->IRC: [rawmsg]")
for(var/client/X in admins)
- to_chat(X, "PM: [key_name(src, X, 0)]->IRC: [keywordparsedmsg]")
+ to_chat(X, "PM: [key_name(src, X, 0)]->IRC: [keywordparsedmsg]")
else
log_admin("PM: [key_name(src)]->[key_name(recipient)]: [rawmsg]")
//we don't use message_admins here because the sender/receiver might get it too
for(var/client/X in admins)
if(X.key!=key && X.key!=recipient.key) //check client/X is an admin and isn't the sender or recipient
- to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" )
+ to_chat(X, "PM: [key_name(src, X, 0)]->[key_name(recipient, X, 0)]: [keywordparsedmsg]" )
/proc/IrcPm(target,msg,sender)
var/client/C = GLOB.directory[target]
@@ -256,11 +256,11 @@
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
log_admin("IRC PM: [sender] -> [key_name(C)] : [msg]")
- to_chat(C, "-- Administrator private message --")
- to_chat(C, "Admin PM from-[adminname]: [msg]")
- to_chat(C, "Click on the administrator's name to reply.")
+ to_chat(C, "-- Administrator private message --")
+ to_chat(C, "Admin PM from-[adminname]: [msg]")
+ to_chat(C, "Click on the administrator's name to reply.")
- admin_ticket_log(C, "PM From [irc_tagged]: [msg]")
+ admin_ticket_log(C, "PM From [irc_tagged]: [msg]")
window_flash(C, ignorepref = TRUE)
//always play non-admin recipients the adminhelp sound
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index d14c37d97e..feebada82a 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -539,7 +539,7 @@
Pump.air2.gas["nitrogen"] = 3750 //The contents of 2 canisters.
Pump.air2.temperature = 50
Pump.air2.update_values()
- Pump.use_power=1
+ Pump.update_use_power(USE_POWER_IDLE)
Pump.target_pressure = 4500
Pump.update_icon()
diff --git a/code/modules/admin/verbs/fps.dm b/code/modules/admin/verbs/fps.dm
new file mode 100644
index 0000000000..fbafc004db
--- /dev/null
+++ b/code/modules/admin/verbs/fps.dm
@@ -0,0 +1,23 @@
+//Merged Doohl's and the existing ticklag as they both had good elements about them ~
+//Replaces the old Ticklag verb, fps is easier to understand
+/client/proc/set_server_fps()
+ set category = "Debug"
+ set name = "Set Server FPS"
+ set desc = "Sets game speed in frames-per-second. Can potentially break the game"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [config.fps])", "FPS", world.fps) as num|null)
+ if(new_fps <= 0)
+ to_chat(src, "Error: set_server_fps(): Invalid world.fps value. No changes made.")
+ return
+ if(new_fps > config.fps * 1.5)
+ if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [config.fps]", "Warning!", "Confirm", "ABORT-ABORT-ABORT") != "Confirm")
+ return
+
+ var/msg = "[key_name(src)] has modified world.fps to [new_fps]"
+ log_admin(msg, 0)
+ message_admins(msg, 0)
+ world.change_fps(new_fps)
+ feedback_add_details("admin_verb", "SETFPS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 26eeb37929..312aa20a6f 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -139,7 +139,7 @@ var/list/debug_verbs = list (
,/client/proc/cmd_assume_direct_control
,/client/proc/jump_to_dead_group
,/client/proc/startSinglo
- ,/client/proc/ticklag
+ ,/client/proc/set_server_fps
,/client/proc/cmd_admin_grantfullaccess
,/client/proc/kaboom
,/client/proc/cmd_admin_areatest
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index efd7f4a0b4..aec9db7e81 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -17,7 +17,7 @@
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
- msg = "\icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, src)]) (CA) (SC) (SMITE): [msg]"
+ msg = "[bicon(cross)] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, src)]) (CA) (SC) (SMITE): [msg]"
for(var/client/C in admins)
if(R_ADMIN|R_EVENT & C.holder.rights)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 1eb22f1201..10eac5839f 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -106,7 +106,9 @@
if (!holder)
return
- var/msg = sanitize(input("Message:", text("Enter the text you wish to appear to everyone:")) as text)
+ var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
+ if(!(msg[1] == "<" && msg[length(msg)] == ">")) //You can use HTML but only if the whole thing is HTML. Tries to prevent admin 'accidents'.
+ msg = sanitize(msg)
if (!msg)
return
@@ -128,7 +130,9 @@
if(!M)
return
- var/msg = sanitize(input("Message:", text("Enter the text you wish to appear to your target:")) as text)
+ var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text
+ if(!(msg[1] == "<" && msg[length(msg)] == ">")) //You can use HTML but only if the whole thing is HTML. Tries to prevent admin 'accidents'.
+ msg = sanitize(msg)
if( !msg )
return
@@ -365,12 +369,18 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!holder)
return
- //I frontload all the questions so we don't have a half-done process while you're reading.
var/client/picked_client = input(src, "Please specify which client's character to spawn.", "Client", "") as null|anything in GLOB.clients
if(!picked_client)
return
- var/location = alert(src,"Please specify where to spawn them.", "Location", "Right Here", "Arrivals", "Cancel")
+ respawn_character_proper(picked_client)
+
+/client/proc/respawn_character_proper(client/picked_client)
+ if(!istype(picked_client))
+ return
+
+ //I frontload all the questions so we don't have a half-done process while you're reading.
+ var/location = alert(src, "Please specify where to spawn them.", "Location", "Right Here", "Arrivals", "Cancel")
if(location == "Cancel" || !location)
return
@@ -812,10 +822,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!holder)
return
+ var/view = src.view
if(view == world.view)
view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
else
view = world.view
+ mob.set_viewsize(view)
log_admin("[key_name(usr)] changed their view range to [view].")
//message_admins("[key_name_admin(usr)] changed their view range to [view].", 1) //why? removed by order of XSI
diff --git a/code/modules/admin/verbs/ticklag.dm b/code/modules/admin/verbs/ticklag.dm
deleted file mode 100644
index 3c34f0f35a..0000000000
--- a/code/modules/admin/verbs/ticklag.dm
+++ /dev/null
@@ -1,24 +0,0 @@
-//Merged Doohl's and the existing ticklag as they both had good elements about them ~Carn
-
-/client/proc/ticklag()
- set category = "Debug"
- set name = "Set Ticklag"
- set desc = "Sets a new tick lag. Recommend you don't mess with this too much! Stable, time-tested ticklag value is 0.9"
-
- if(!check_rights(R_DEBUG)) return
-
- var/newtick = input("Sets a new tick lag. Please don't mess with this too much! The stable, time-tested ticklag value is 0.9","Lag of Tick", world.tick_lag) as num|null
- //I've used ticks of 2 before to help with serious singulo lags
- if(newtick && newtick <= 2 && newtick > 0)
- log_admin("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
- message_admins("[key_name(src)] has modified world.tick_lag to [newtick]", 0)
- world.tick_lag = newtick
- feedback_add_details("admin_verb","TICKLAG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
- switch(alert("Enable Tick Compensation?","Tick Comp is currently: [config.Tickcomp]","Yes","No"))
- if("Yes") config.Tickcomp = 1
- else config.Tickcomp = 0
- else
- to_chat(src, "Error: ticklag(): Invalid world.ticklag value. No changes made.")
-
-
diff --git a/code/modules/admin/view_variables/modify_variables.dm b/code/modules/admin/view_variables/modify_variables.dm
index 8878318fd6..1e3aef04bd 100644
--- a/code/modules/admin/view_variables/modify_variables.dm
+++ b/code/modules/admin/view_variables/modify_variables.dm
@@ -310,6 +310,13 @@ GLOBAL_PROTECT(VVpixelmovement)
if(!variable)
return
+ if(variable in GLOB.VVpixelmovement)
+ if(!check_rights(R_DEBUG))
+ return
+ var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
+ if (prompt != "Continue")
+ return
+
if(!O.can_vv_get(variable))
return
diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm
index cb510836ce..b524ade4b2 100644
--- a/code/modules/admin/view_variables/topic.dm
+++ b/code/modules/admin/view_variables/topic.dm
@@ -449,7 +449,7 @@
to_chat(usr, "This can only be done on mobs with clients")
return
- SSnanoui.send_resources(H.client)
+ H.client.send_resources()
to_chat(usr, "Resource files sent")
to_chat(H, "Your NanoUI Resource files have been refreshed")
diff --git a/code/modules/ai/_defines.dm b/code/modules/ai/_defines.dm
index e94d26b3c3..7b49f18ddb 100644
--- a/code/modules/ai/_defines.dm
+++ b/code/modules/ai/_defines.dm
@@ -20,6 +20,11 @@
#define MOVEMENT_FAILED 0 // Move() returned false for whatever reason and the mob didn't move.
#define MOVEMENT_SUCCESSFUL 1 // Move() returned true and the mob hopefully moved.
+// Results of pre-attack checks
+#define ATTACK_ON_COOLDOWN -1 // Recently attacked and needs to try again soon.
+#define ATTACK_FAILED 0 // Something else went wrong! Maybe they moved away!
+#define ATTACK_SUCCESSFUL 1 // We attacked (or tried to, misses count too)
+
// Reasons for targets to not be valid. Based on why, the AI responds differently.
#define AI_TARGET_VALID 0 // We can fight them.
#define AI_TARGET_INVIS 1 // They were in field of view but became invisible. Switch to STANCE_BLINDFIGHT if no other viable targets exist.
diff --git a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm
index 0d432e55b1..cdbd665047 100644
--- a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm
+++ b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm
@@ -133,7 +133,7 @@
return
rabid = TRUE
my_slime.update_mood()
- my_slime.visible_message(span("danger", "\The [src] enrages!"))
+ my_slime.visible_message(span("danger", "\The [my_slime] enrages!"))
// Called when using a pacification agent (or it's Kendrick being initalized).
/datum/ai_holder/simple_mob/xenobio_slime/proc/pacify()
diff --git a/code/modules/ai/ai_holder_combat.dm b/code/modules/ai/ai_holder_combat.dm
index 65fd1785b1..64dfa7d17e 100644
--- a/code/modules/ai/ai_holder_combat.dm
+++ b/code/modules/ai/ai_holder_combat.dm
@@ -70,21 +70,21 @@
/datum/ai_holder/proc/melee_attack(atom/A)
pre_melee_attack(A)
. = holder.IAttack(A)
- if(.)
+ if(. == ATTACK_SUCCESSFUL)
post_melee_attack(A)
// Ditto.
/datum/ai_holder/proc/ranged_attack(atom/A)
pre_ranged_attack(A)
. = holder.IRangedAttack(A)
- if(.)
+ if(. == ATTACK_SUCCESSFUL)
post_ranged_attack(A)
// Most mobs probably won't have this defined but we don't care.
/datum/ai_holder/proc/special_attack(atom/movable/AM)
pre_special_attack(AM)
. = holder.ISpecialAttack(AM)
- if(.)
+ if(. == ATTACK_SUCCESSFUL)
post_special_attack(AM)
// Called when within striking/shooting distance, however cooldown is not considered.
@@ -218,7 +218,6 @@
var/dir_to_target = get_dir(holder, target_atom)
holder.face_atom(target_atom)
- ai_log("breakthrough() : Exiting", AI_LOG_DEBUG)
// Sometimes the mob will try to hit something diagonally, and generally this fails.
// So instead we will try two more times with some adjustments if the attack fails.
@@ -274,32 +273,32 @@
for(var/obj/structure/window/W in problem_turf)
if(W.dir == reverse_dir[holder.dir]) // So that windows get smashed in the right order
ai_log("destroy_surroundings() : Attacking side window.", AI_LOG_INFO)
- return holder.IAttack(W)
+ return melee_attack(W)
else if(W.is_fulltile())
ai_log("destroy_surroundings() : Attacking full tile window.", AI_LOG_INFO)
- return holder.IAttack(W)
+ return melee_attack(W)
// Kill hull shields in the way.
for(var/obj/effect/energy_field/shield in problem_turf)
if(shield.density) // Don't attack shields that are already down.
ai_log("destroy_surroundings() : Attacking hull shield.", AI_LOG_INFO)
- return holder.IAttack(shield)
+ return melee_attack(shield)
// Kill common obstacle in the way like tables.
var/obj/structure/obstacle = locate(/obj/structure, problem_turf)
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
ai_log("destroy_surroundings() : Attacking generic structure.", AI_LOG_INFO)
- return holder.IAttack(obstacle)
+ return melee_attack(obstacle)
for(var/obj/machinery/door/D in problem_turf) // Required since firelocks take up the same turf.
if(D.density)
ai_log("destroy_surroundings() : Attacking closed door.", AI_LOG_INFO)
- return holder.IAttack(D)
+ return melee_attack(D)
ai_log("destroy_surroundings() : Exiting due to nothing to attack.", AI_LOG_INFO)
- return FALSE // Nothing to attack.
+ return ATTACK_FAILED // Nothing to attack.
// Override for special behaviour.
/datum/ai_holder/proc/can_violently_breakthrough()
- return violent_breakthrough
\ No newline at end of file
+ return violent_breakthrough
diff --git a/code/modules/ai/ai_holder_movement.dm b/code/modules/ai/ai_holder_movement.dm
index 58b8c9d5ee..eb465dec5d 100644
--- a/code/modules/ai/ai_holder_movement.dm
+++ b/code/modules/ai/ai_holder_movement.dm
@@ -9,13 +9,14 @@
var/home_low_priority = FALSE // If true, the mob will not go home unless it has nothing better to do, e.g. its following someone.
var/max_home_distance = 3 // How far the mob can go away from its home before being told to go_home().
// Note that there is a 'BYOND cap' of 14 due to limitations of get_/step_to().
-
// Wandering.
var/wander = FALSE // If true, the mob will randomly move in the four cardinal directions when idle.
var/wander_delay = 0 // How many ticks until the mob can move a tile in handle_wander_movement().
var/base_wander_delay = 2 // What the above var gets set to when it wanders. Note that a tick happens every half a second.
var/wander_when_pulled = FALSE // If the mob will refrain from wandering if someone is pulling it.
+ // Breakthrough
+ var/failed_breakthroughs = 0 // How many times we've failed to breakthrough something lately
/datum/ai_holder/proc/walk_to_destination()
ai_log("walk_to_destination() : Entering.",AI_LOG_TRACE)
@@ -90,7 +91,9 @@
// step_to(holder, A)
if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED)
ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO)
- breakthrough(A) // We failed to move, time to smash things.
+ if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things.
+ give_up_movement()
+ failed_breakthroughs = 0
return
if(move_once() == FALSE) // Start walking the path.
@@ -106,7 +109,9 @@
ai_log("walk_path() : Going to IMove().", AI_LOG_TRACE)
if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED )
ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO)
- breakthrough(A) // We failed to move, time to smash things.
+ if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things.
+ give_up_movement()
+ failed_breakthroughs = 0
ai_log("walk_path() : Exited.", AI_LOG_TRACE)
diff --git a/code/modules/ai/interfaces.dm b/code/modules/ai/interfaces.dm
index 59ffbeea72..b4323782d3 100644
--- a/code/modules/ai/interfaces.dm
+++ b/code/modules/ai/interfaces.dm
@@ -8,7 +8,7 @@
/mob/living/simple_mob/IAttack(atom/A)
if(!canClick()) // Still on cooldown from a "click".
- return FALSE
+ return ATTACK_ON_COOLDOWN
return attack_target(A) // This will set click cooldown.
/mob/living/proc/IRangedAttack(atom/A)
@@ -16,7 +16,7 @@
/mob/living/simple_mob/IRangedAttack(atom/A)
if(!canClick()) // Still on cooldown from a "click".
- return FALSE
+ return ATTACK_ON_COOLDOWN
return shoot_target(A)
// Test if the AI is allowed to attempt a ranged attack.
diff --git a/code/modules/artifice/deadringer.dm b/code/modules/artifice/deadringer.dm
index bdac793daf..3e95152528 100644
--- a/code/modules/artifice/deadringer.dm
+++ b/code/modules/artifice/deadringer.dm
@@ -67,7 +67,7 @@
if(timer > 0)
timer--
if(timer == 20)
- uncloak()
+ reveal()
if(corpse)
new /obj/effect/effect/smoke/chem(corpse.loc)
qdel(corpse)
@@ -86,7 +86,7 @@
makeacorpse(watchowner)
return
-/obj/item/weapon/deadringer/proc/uncloak()
+/obj/item/weapon/deadringer/proc/reveal()
if(watchowner)
watchowner.alpha = 255
playsound(get_turf(src), 'sound/effects/uncloak.ogg', 35, 1, -1)
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index 0636c9e5e9..d815fea765 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -199,7 +199,7 @@
/obj/item/device/assembly_holder/process_activation(var/obj/D, var/normal = 1, var/special = 1)
if(!D) return 0
if(!secured)
- visible_message("\icon[src] *beep* *beep*", "*beep* *beep*")
+ visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
if((normal) && (a_right) && (a_left))
if(a_right != D)
a_right.pulsed(0)
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 436f2741fd..1cac7f60c4 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -97,7 +97,7 @@
if((!secured)||(!on)||(cooldown > 0)) return 0
pulse(0)
if(!holder)
- visible_message("\icon[src] *beep* *beep*")
+ visible_message("[bicon(src)] *beep* *beep*")
cooldown = 2
spawn(10)
process_cooldown()
diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm
index a03130ea92..2ac1fdf90f 100644
--- a/code/modules/assembly/proximity.dm
+++ b/code/modules/assembly/proximity.dm
@@ -25,7 +25,7 @@
/obj/item/device/assembly/prox_sensor/toggle_secure()
secured = !secured
if(secured)
- START_PROCESSING(SSobj, src)
+ START_PROCESSING(SSobj, src)
else
scanning = 0
timing = 0
@@ -46,11 +46,11 @@
/obj/item/device/assembly/prox_sensor/proc/sense()
var/turf/mainloc = get_turf(src)
// if(scanning && cooldown <= 0)
-// mainloc.visible_message("\icon[src] *boop* *boop*", "*boop* *boop*")
+// mainloc.visible_message("[bicon(src)] *boop* *boop*", "*boop* *boop*")
if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0
pulse(0)
if(!holder)
- mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*")
+ mainloc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
cooldown = 2
spawn(10)
process_cooldown()
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index a8859e7c1c..448e0c9860 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -148,7 +148,7 @@ Code:
if(!holder)
for(var/mob/O in hearers(1, src.loc))
- O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
+ O.show_message("[bicon(src)] *beep* *beep*", 3, "*beep* *beep*", 2)
return
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index 488083d11a..543d7d1801 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -25,7 +25,7 @@
/obj/item/device/assembly/timer/toggle_secure()
secured = !secured
if(secured)
- START_PROCESSING(SSobj, src)
+ START_PROCESSING(SSobj, src)
else
timing = 0
STOP_PROCESSING(SSobj, src)
@@ -37,7 +37,7 @@
if(!secured) return 0
pulse(0)
if(!holder)
- visible_message("\icon[src] *beep* *beep*", "*beep* *beep*")
+ visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
cooldown = 2
spawn(10)
process_cooldown()
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 7e8c89cc79..0cf4b85665 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -12,7 +12,7 @@
recorded = msg
listening = 0
var/turf/T = get_turf(src) //otherwise it won't work in hand
- T.visible_message("\icon[src] beeps, \"Activation message is '[recorded]'.\"")
+ T.visible_message("[bicon(src)] beeps, \"Activation message is '[recorded]'.\"")
else
if(findtext(msg, recorded))
pulse(0)
@@ -22,7 +22,7 @@
if(!holder)
listening = !listening
var/turf/T = get_turf(src)
- T.visible_message("\icon[src] beeps, \"[listening ? "Now" : "No longer"] recording input.\"")
+ T.visible_message("[bicon(src)] beeps, \"[listening ? "Now" : "No longer"] recording input.\"")
/obj/item/device/assembly/voice/attack_self(mob/user)
diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm
index 123b653052..bd88744d70 100644
--- a/code/modules/awaymissions/gateway.dm
+++ b/code/modules/awaymissions/gateway.dm
@@ -26,7 +26,7 @@
/obj/machinery/gateway/centerstation
density = 1
icon_state = "offcenter"
- use_power = 1
+ use_power = USE_POWER_IDLE
//warping vars
var/list/linked = list()
@@ -142,7 +142,7 @@ obj/machinery/gateway/centerstation/process()
/obj/machinery/gateway/centeraway
density = 1
icon_state = "offcenter"
- use_power = 0
+ use_power = USE_POWER_OFF
var/calibrated = 1
var/list/linked = list() //a list of the connected gateway chunks
var/ready = 0
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
new file mode 100644
index 0000000000..ef64cd4acd
--- /dev/null
+++ b/code/modules/client/asset_cache.dm
@@ -0,0 +1,272 @@
+/*
+Asset cache quick users guide:
+
+Make a datum at the bottom of this file with your assets for your thing.
+The simple subsystem will most like be of use for most cases.
+Then call get_asset_datum() with the type of the datum you created and store the return
+Then call .send(client) on that stored return value.
+
+You can set verify to TRUE if you want send() to sleep until the client has the assets.
+*/
+
+
+// Amount of time(ds) MAX to send per asset, if this get exceeded we cancel the sleeping.
+// This is doubled for the first asset, then added per asset after
+#define ASSET_CACHE_SEND_TIMEOUT 7
+
+//When sending mutiple assets, how many before we give the client a quaint little sending resources message
+#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8
+
+//When passively preloading assets, how many to send at once? Too high creates noticable lag where as too low can flood the client's cache with "verify" files
+#define ASSET_CACHE_PRELOAD_CONCURRENT 3
+
+/client
+ var/list/cache = list() // List of all assets sent to this client by the asset cache.
+ var/list/completed_asset_jobs = list() // List of all completed jobs, awaiting acknowledgement.
+ var/list/sending = list()
+ var/last_asset_job = 0 // Last job done.
+
+//This proc sends the asset to the client, but only if it needs it.
+//This proc blocks(sleeps) unless verify is set to false
+/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE)
+ client = CLIENT_FROM_VAR(client) // Will get client from a mob, or accept a client, or return null
+ if(!istype(client))
+ return 0
+
+ if(client.cache.Find(asset_name) || client.sending.Find(asset_name))
+ return 0
+
+ client << browse_rsc(SSassets.cache[asset_name], asset_name)
+ if(!verify) // Can't access the asset cache browser, rip.
+ client.cache += asset_name
+ return 1
+
+ client.sending |= asset_name
+ var/job = ++client.last_asset_job
+
+ client << browse({"
+
+ "}, "window=asset_cache_browser")
+
+ var/t = 0
+ var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT
+ while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
+ sleep(1) // Lock up the caller until this is received.
+ t++
+
+ if(client)
+ client.sending -= asset_name
+ client.cache |= asset_name
+ client.completed_asset_jobs -= job
+
+ return 1
+
+//This proc blocks(sleeps) unless verify is set to false
+/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE)
+ client = CLIENT_FROM_VAR(client) // Will get client from a mob, or accept a client, or return null
+ if(!istype(client))
+ return 0
+
+ var/list/unreceived = asset_list - (client.cache + client.sending)
+ if(!unreceived || !unreceived.len)
+ return 0
+ if(unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
+ to_chat(client, "Sending Resources...")
+ for(var/asset in unreceived)
+ if(asset in SSassets.cache)
+ client << browse_rsc(SSassets.cache[asset], asset)
+
+ if(!verify) // Can't access the asset cache browser, rip.
+ client.cache += unreceived
+ return 1
+
+ client.sending |= unreceived
+ var/job = ++client.last_asset_job
+
+ client << browse({"
+
+ "}, "window=asset_cache_browser")
+
+ var/t = 0
+ var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len
+ while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
+ sleep(1) // Lock up the caller until this is received.
+ t++
+
+ if(client)
+ client.sending -= unreceived
+ client.cache |= unreceived
+ client.completed_asset_jobs -= job
+
+ return 1
+
+//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start.
+//The proc calls procs that sleep for long times.
+/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
+ var/concurrent_tracker = 1
+ for(var/file in files)
+ if(!client)
+ break
+ if(register_asset)
+ register_asset(file, files[file])
+ if(concurrent_tracker >= ASSET_CACHE_PRELOAD_CONCURRENT)
+ concurrent_tracker = 1
+ send_asset(client, file)
+ else
+ concurrent_tracker++
+ send_asset(client, file, verify = FALSE)
+ sleep(0) //queuing calls like this too quickly can cause issues in some client versions
+
+//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
+//if it's an icon or something be careful, you'll have to copy it before further use.
+/proc/register_asset(var/asset_name, var/asset)
+ SSassets.cache[asset_name] = asset
+
+//These datums are used to populate the asset cache, the proc "register()" does this.
+
+//all of our asset datums, used for referring to these later
+/var/global/list/asset_datums = list()
+
+//get a assetdatum or make a new one
+/proc/get_asset_datum(var/type)
+ if(!(type in asset_datums))
+ return new type()
+ return asset_datums[type]
+
+/datum/asset/New()
+ asset_datums[type] = src
+
+/datum/asset/proc/register()
+ return
+
+/datum/asset/proc/send(client)
+ return
+
+//If you don't need anything complicated.
+/datum/asset/simple
+ var/assets = list()
+ var/verify = FALSE
+
+/datum/asset/simple/register()
+ for(var/asset_name in assets)
+ register_asset(asset_name, assets[asset_name])
+/datum/asset/simple/send(client)
+ send_asset_list(client,assets,verify)
+
+
+//DEFINITIONS FOR ASSET DATUMS START HERE.
+/datum/asset/simple/pda
+ assets = list(
+ "pda_atmos.png" = 'icons/pda_icons/pda_atmos.png',
+ "pda_back.png" = 'icons/pda_icons/pda_back.png',
+ "pda_bell.png" = 'icons/pda_icons/pda_bell.png',
+ "pda_blank.png" = 'icons/pda_icons/pda_blank.png',
+ "pda_boom.png" = 'icons/pda_icons/pda_boom.png',
+ "pda_bucket.png" = 'icons/pda_icons/pda_bucket.png',
+ "pda_crate.png" = 'icons/pda_icons/pda_crate.png',
+ "pda_cuffs.png" = 'icons/pda_icons/pda_cuffs.png',
+ "pda_eject.png" = 'icons/pda_icons/pda_eject.png',
+ "pda_exit.png" = 'icons/pda_icons/pda_exit.png',
+ "pda_flashlight.png" = 'icons/pda_icons/pda_flashlight.png',
+ "pda_honk.png" = 'icons/pda_icons/pda_honk.png',
+ "pda_mail.png" = 'icons/pda_icons/pda_mail.png',
+ "pda_medical.png" = 'icons/pda_icons/pda_medical.png',
+ "pda_menu.png" = 'icons/pda_icons/pda_menu.png',
+ "pda_mule.png" = 'icons/pda_icons/pda_mule.png',
+ "pda_notes.png" = 'icons/pda_icons/pda_notes.png',
+ "pda_power.png" = 'icons/pda_icons/pda_power.png',
+ "pda_rdoor.png" = 'icons/pda_icons/pda_rdoor.png',
+ "pda_reagent.png" = 'icons/pda_icons/pda_reagent.png',
+ "pda_refresh.png" = 'icons/pda_icons/pda_refresh.png',
+ "pda_scanner.png" = 'icons/pda_icons/pda_scanner.png',
+ "pda_signaler.png" = 'icons/pda_icons/pda_signaler.png',
+ "pda_status.png" = 'icons/pda_icons/pda_status.png'
+ )
+
+/datum/asset/simple/generic
+ assets = list(
+ "search.js" = 'html/search.js',
+ "panels.css" = 'html/panels.css',
+ "loading.gif" = 'html/images/loading.gif',
+ "ntlogo.png" = 'html/images/ntlogo.png',
+ "sglogo.png" = 'html/images/sglogo.png',
+ "talisman.png" = 'html/images/talisman.png',
+ "paper_bg.png" = 'html/images/paper_bg.png',
+ "no_image32.png" = 'html/images/no_image32.png',
+ "sos_1.png" = 'icons/spideros_icons/sos_1.png',
+ "sos_2.png" = 'icons/spideros_icons/sos_2.png',
+ "sos_3.png" = 'icons/spideros_icons/sos_3.png',
+ "sos_4.png" = 'icons/spideros_icons/sos_4.png',
+ "sos_5.png" = 'icons/spideros_icons/sos_5.png',
+ "sos_6.png" = 'icons/spideros_icons/sos_6.png',
+ "sos_7.png" = 'icons/spideros_icons/sos_7.png',
+ "sos_8.png" = 'icons/spideros_icons/sos_8.png',
+ "sos_9.png" = 'icons/spideros_icons/sos_9.png',
+ "sos_10.png" = 'icons/spideros_icons/sos_10.png',
+ "sos_11.png" = 'icons/spideros_icons/sos_11.png',
+ "sos_12.png" = 'icons/spideros_icons/sos_12.png',
+ "sos_13.png" = 'icons/spideros_icons/sos_13.png',
+ "sos_14.png" = 'icons/spideros_icons/sos_14.png'
+ )
+
+/datum/asset/simple/changelog
+ assets = list(
+ "88x31.png" = 'html/88x31.png',
+ "bug-minus.png" = 'html/bug-minus.png',
+ "cross-circle.png" = 'html/cross-circle.png',
+ "hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
+ "image-minus.png" = 'html/image-minus.png',
+ "image-plus.png" = 'html/image-plus.png',
+ "map-pencil.png" = 'html/map-pencil.png',
+ "music-minus.png" = 'html/music-minus.png',
+ "music-plus.png" = 'html/music-plus.png',
+ "tick-circle.png" = 'html/tick-circle.png',
+ "wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
+ "spell-check.png" = 'html/spell-check.png',
+ "burn-exclamation.png" = 'html/burn-exclamation.png',
+ "chevron.png" = 'html/chevron.png',
+ "chevron-expand.png" = 'html/chevron-expand.png',
+ "changelog.css" = 'html/changelog.css',
+ "changelog.js" = 'html/changelog.js',
+ "changelog.html" = 'html/changelog.html'
+ )
+
+/datum/asset/nanoui
+ var/list/common = list()
+
+ var/list/common_dirs = list(
+ "nano/css/",
+ "nano/images/",
+ "nano/images/modular_computers/",
+ "nano/js/"
+ )
+ var/list/uncommon_dirs = list(
+ "nano/templates/"
+ )
+
+/datum/asset/nanoui/register()
+ // Crawl the directories to find files.
+ for(var/path in common_dirs)
+ var/list/filenames = flist(path)
+ for(var/filename in filenames)
+ if(copytext(filename, length(filename)) != "/") // Ignore directories.
+ if(fexists(path + filename))
+ common[filename] = fcopy_rsc(path + filename)
+ register_asset(filename, common[filename])
+ for(var/path in uncommon_dirs)
+ var/list/filenames = flist(path)
+ for(var/filename in filenames)
+ if(copytext(filename, length(filename)) != "/") // Ignore directories.
+ if(fexists(path + filename))
+ register_asset(filename, fcopy_rsc(path + filename))
+
+/datum/asset/nanoui/send(client, uncommon)
+ if(!islist(uncommon))
+ uncommon = list(uncommon)
+
+ send_asset_list(client, uncommon)
+ send_asset_list(client, common)
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index d95f1b0cea..ef942b1992 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -24,6 +24,8 @@
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
var/datum/tooltip/tooltips = null
+ var/datum/chatOutput/chatOutput
+ var/chatOutputLoadedAt
var/adminhelped = 0
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index d997733d8e..933729fa13 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -34,6 +34,11 @@
#endif
+ if(href_list["asset_cache_confirm_arrival"])
+ var/job = text2num(href_list["asset_cache_confirm_arrival"])
+ completed_asset_jobs += job
+ return
+
//search the href for script injection
if( findtext(href,"
+
+
+
+
+
+
+
You probably shouldn't see this page. This generally means chat is very broken.
+
You can wait a few seconds to see if it loads, or try OOC > Reload VChat.