diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index dcd0717e29..1ef76788eb 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -24665,7 +24665,7 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"bgp" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on,
/turf/open/floor/plasteel/white,
@@ -26862,7 +26862,7 @@
dir = 4
},
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"blh" = (
/obj/structure/table/reinforced,
/obj/machinery/door/window/eastright{
@@ -26940,7 +26940,7 @@
dir = 4
},
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"blp" = (
/obj/machinery/power/apc{
dir = 8;
@@ -26974,7 +26974,7 @@
dir = 4
},
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"blr" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 4
@@ -29030,7 +29030,7 @@
},
/obj/structure/disposalpipe/segment,
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"bpR" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/structure/disposalpipe/segment{
@@ -60163,7 +60163,7 @@
icon_state = "2-4"
},
/turf/open/floor/plating,
-/area/maintenance/aft)
+/area/maintenance/department/medical/morgue)
"cHE" = (
/obj/machinery/door/airlock/maintenance{
name = "Mech Bay Maintenance";
@@ -63862,6 +63862,167 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"cTJ" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
+ },
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTK" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTL" = (
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/structure/cable{
+ d1 = 2;
+ d2 = 4;
+ icon_state = "2-4"
+ },
+/turf/open/floor/plasteel/black,
+/area/medical/morgue)
+"cTM" = (
+/obj/machinery/power/apc{
+ dir = 4;
+ name = "Morgue Maintenance APC";
+ areastring = "/area/maintenance/department/medical/morgue";
+ pixel_x = 26
+ },
+/obj/structure/cable{
+ d2 = 8;
+ icon_state = "0-8"
+ },
+/turf/open/floor/plasteel/black,
+/area/medical/morgue)
+"cTN" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTO" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTP" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTQ" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTR" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/cable{
+ d1 = 4;
+ d2 = 8;
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTS" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTT" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTU" = (
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"cTV" = (
+/obj/machinery/door/airlock/maintenance{
+ req_access_txt = "12"
+ },
+/obj/structure/disposalpipe/segment,
+/obj/structure/cable{
+ d1 = 1;
+ d2 = 2;
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
(1,1,1) = {"
aaa
@@ -103574,7 +103735,7 @@ bfL
bhp
biB
biB
-biB
+cTL
bkU
bmX
bpE
@@ -103831,7 +103992,7 @@ bfL
bhq
bhm
bkb
-bhm
+cTM
bla
bmZ
bpH
@@ -104346,7 +104507,7 @@ bfS
biC
bkd
bfS
-bKH
+cTO
bmZ
bpJ
brc
@@ -104860,7 +105021,7 @@ bfS
biE
bkf
bfS
-bKH
+cTP
bmZ
bpL
bre
@@ -105117,7 +105278,7 @@ bfS
biD
bke
bfS
-bKH
+cTQ
bmZ
bpK
brd
@@ -105374,7 +105535,7 @@ bfS
bfS
bfS
bfS
-bKH
+cTR
bmZ
bon
bon
@@ -105626,17 +105787,17 @@ aYV
baR
bcb
bdl
-bdO
+cTJ
cHD
bgo
-bPv
-bPv
+cTK
+cTN
blq
-bna
-bPv
+cTS
+cTT
bpQ
-bPv
-bdO
+cTU
+cTV
btm
buy
bvz
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 5809176275..efae305c74 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -91795,7 +91795,7 @@
"dwO" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dwP" = (
/obj/machinery/door/firedoor,
/obj/structure/cable/white{
@@ -91815,7 +91815,7 @@
dir = 1
},
/turf/open/floor/plasteel,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dwQ" = (
/obj/structure/table/glass,
/obj/item/clipboard,
@@ -92448,7 +92448,7 @@
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dyb" = (
/obj/structure/bed/roller,
/obj/machinery/iv_drip,
@@ -92456,12 +92456,12 @@
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dyc" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dyd" = (
/obj/structure/cable/white{
d1 = 1;
@@ -92470,7 +92470,7 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dye" = (
/obj/structure/table/glass,
/obj/item/folder/white,
@@ -92923,12 +92923,12 @@
"dzf" = (
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel/neutral,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dzg" = (
/obj/effect/decal/cleanable/blood/old,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dzh" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -92938,14 +92938,14 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dzi" = (
/obj/structure/table,
/obj/effect/decal/cleanable/dirt,
/obj/item/storage/backpack/duffelbag/med,
/obj/item/device/flashlight/pen,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dzj" = (
/turf/closed/wall,
/area/crew_quarters/heads/cmo)
@@ -93674,7 +93674,7 @@
dir = 4
},
/turf/open/floor/plasteel,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAw" = (
/obj/structure/cable/white{
d1 = 4;
@@ -93687,7 +93687,7 @@
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAx" = (
/obj/structure/cable/white{
d1 = 4;
@@ -93699,7 +93699,7 @@
dir = 1
},
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAy" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -93712,7 +93712,7 @@
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAz" = (
/obj/structure/cable/white{
d1 = 1;
@@ -93733,14 +93733,14 @@
dir = 4
},
/turf/open/floor/plasteel/neutral,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAA" = (
/obj/structure/table,
/obj/item/clothing/gloves/color/latex/nitrile,
/obj/item/clothing/suit/apron/surgical,
/obj/item/clothing/mask/breath/medical,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dAB" = (
/obj/structure/closet/secure_closet/CMO,
/obj/item/clothing/under/rank/nursesuit,
@@ -94324,7 +94324,7 @@
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dBP" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
@@ -94334,13 +94334,13 @@
dir = 4
},
/turf/open/floor/plasteel/neutral,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dBQ" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dBR" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -94350,7 +94350,7 @@
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/neutral,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dBS" = (
/obj/structure/rack,
/obj/effect/decal/cleanable/dirt,
@@ -94359,7 +94359,7 @@
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dBT" = (
/obj/machinery/light{
dir = 8
@@ -95032,15 +95032,15 @@
/obj/structure/closet/secure_closet/medical3,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dDe" = (
/obj/structure/closet/wardrobe/white/medical,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dDf" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plating,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dDg" = (
/obj/structure/cable/white{
d1 = 1;
@@ -95048,10 +95048,15 @@
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/structure/cable/white{
+ d1 = 2;
+ d2 = 4;
+ icon_state = "2-4"
+ },
/turf/open/floor/plasteel/vault{
dir = 5
},
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dDh" = (
/obj/machinery/suit_storage_unit/cmo,
/obj/effect/turf_decal/stripes/line{
@@ -95603,7 +95608,7 @@
dir = 1
},
/turf/open/floor/plasteel,
-/area/medical/morgue)
+/area/maintenance/department/medical/morgue)
"dEn" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall,
@@ -113090,6 +113095,50 @@
/obj/structure/ore_box,
/turf/open/floor/plating,
/area/shuttle/auxillary_base)
+"esz" = (
+/turf/closed/wall/r_wall,
+/area/maintenance/department/medical/morgue)
+"esA" = (
+/turf/closed/wall/r_wall,
+/area/maintenance/department/medical/morgue)
+"esB" = (
+/turf/closed/wall,
+/area/maintenance/department/medical/morgue)
+"esC" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel/vault{
+ dir = 5
+ },
+/area/maintenance/department/medical/morgue)
+"esD" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/maintenance/department/medical/morgue)
+"esE" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/power/apc{
+ dir = 2;
+ name = "Morgue Maintenance APC";
+ areastring = "/area/maintenance/department/medical/morgue";
+ pixel_y = -26
+ },
+/obj/structure/cable/white{
+ d2 = 8;
+ icon_state = "0-8"
+ },
+/turf/open/floor/plasteel/vault{
+ dir = 5
+ },
+/area/maintenance/department/medical/morgue)
+"esF" = (
+/turf/closed/wall,
+/area/maintenance/department/medical/morgue)
+"esG" = (
+/turf/closed/wall,
+/area/maintenance/department/medical/morgue)
+"esH" = (
+/turf/closed/wall,
+/area/maintenance/department/medical/morgue)
(1,1,1) = {"
aaa
@@ -155932,13 +155981,13 @@ drr
dsR
dur
dvw
-dwN
+esz
dya
-dyY
+esD
dAw
dBO
dDd
-dwK
+esF
dFd
dGE
dHP
@@ -156189,13 +156238,13 @@ drs
dsS
drs
dvx
-dwN
+esA
dyb
dzf
dAx
dBP
dDe
-dwK
+esG
dFe
dGF
dHP
@@ -156960,13 +157009,13 @@ drv
dlO
dus
dvA
-dwK
-dxS
+esB
+esC
dzi
dAA
dBS
-dxS
-dwK
+esE
+esH
dEY
dGA
dHP
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 35b70bdb84..d33eaa35da 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -6,7 +6,8 @@
#define PLANE_SPACE -95
#define PLANE_SPACE_PARALLAX -90
-#define GAME_PLANE 0
+#define GAME_PLANE -1
+#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#define SPACE_LAYER 1.8
#define ABOVE_SPACE_LAYER 1.9
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm
index 6d7c9568a9..819abd032f 100644
--- a/code/__DEFINES/lighting.dm
+++ b/code/__DEFINES/lighting.dm
@@ -70,6 +70,8 @@
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
+#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
+
#define LIGHTING_PLANE_ALPHA_VISIBLE 255
#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 128 //For lighting alpha, small amounts lead to big changes. even at 128 its hard to figure out what is dark and what is light, at 64 you almost can't even tell.
diff --git a/code/__DEFINES/server_tools.dm b/code/__DEFINES/server_tools.dm
index b86a54959f..2773965d9c 100644
--- a/code/__DEFINES/server_tools.dm
+++ b/code/__DEFINES/server_tools.dm
@@ -1,4 +1,4 @@
-// /tg/station 13 server tools API v3.1
+// /tg/station 13 server tools API v3.1.0.1
//CONFIGURATION
//use this define if you want to do configuration outside of this file
@@ -21,6 +21,8 @@
#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]")
//Notify current in-game administrators of a string `event`
#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event)
+//The current amount of connected clients
+#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len
#endif
//Required hooks:
@@ -62,7 +64,7 @@
//IMPLEMENTATION
-#define SERVICE_API_VERSION_STRING "3.1.0.0"
+#define SERVICE_API_VERSION_STRING "3.1.0.1"
#define REBOOT_MODE_NORMAL 0
#define REBOOT_MODE_HARD 1
@@ -78,12 +80,13 @@
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce"
#define SERVICE_CMD_LIST_CUSTOM "list_custom_commands"
+#define SERVICE_CMD_API_COMPATIBLE "api_compat"
+#define SERVICE_CMD_PLAYER_COUNT "client_count"
#define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
#define SERVICE_CMD_PARAM_COMMAND "command"
#define SERVICE_CMD_PARAM_SENDER "sender"
#define SERVICE_CMD_PARAM_CUSTOM "custom"
-#define SERVICE_CMD_API_COMPATIBLE "api_compat"
#define SERVICE_JSON_PARAM_HELPTEXT "help_text"
#define SERVICE_JSON_PARAM_ADMINONLY "admin_only"
diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm
index 522ff84ff0..d855c7f141 100644
--- a/code/_globalvars/lists/names.dm
+++ b/code/_globalvars/lists/names.dm
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(carp_names, world.file2list("strings/names/carp.txt"))
GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt"))
GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt"))
GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
+GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt"))
GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 1d36f7d31e..4d1ca2c778 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -313,11 +313,15 @@
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
+
+ update_locked_slots()
/datum/hud/human/update_locked_slots()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
+ if(!istype(H) || !H.dna.species)
+ return
var/datum/species/S = H.dna.species
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index 49ccb411fc..a9807a599c 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -74,6 +74,10 @@ GLOBAL_PROTECT(config_dir)
if(copytext(L, 1, 2) == "#")
continue
+ var/lockthis = copytext(L, 1, 2) == "@"
+ if(lockthis)
+ L = copytext(L, 2)
+
var/pos = findtext(L, " ")
var/entry = null
var/value = null
@@ -96,6 +100,9 @@ GLOBAL_PROTECT(config_dir)
log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
continue
+ if(lockthis)
+ E.protection |= CONFIG_ENTRY_LOCKED
+
var/validated = E.ValidateAndSet(value)
if(!validated)
log_config("Failed to validate setting \"[value]\" for [entry]")
diff --git a/code/controllers/configuration/entries/config.dm b/code/controllers/configuration/entries/config.dm
index 62919afd06..ec96e88553 100644
--- a/code/controllers/configuration/entries/config.dm
+++ b/code/controllers/configuration/entries/config.dm
@@ -8,10 +8,8 @@ CONFIG_DEF(string/autoadmin_rank) // the rank for autoadmins
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/servername) // server name (the name of the game window)
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/serversqlname) // short form server name used for the DB
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/stationname) // station name (the name of the station in-game)
@@ -24,52 +22,38 @@ CONFIG_DEF(number/round_end_countdown) // Post round murder death kill countdown
min_val = 0
CONFIG_DEF(flag/hub) // if the game appears on the hub or not
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_ooc) // log OOC channel
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_access) // log login/logout
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_say) // log client say
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_admin) // log admin actions
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_prayer) // log prayers
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_law) // log lawchanges
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_game) // log game events
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_vote) // log voting
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_whisper) // log client whisper
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_attack) // log attack messages
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_emote) // log emotes
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_adminchat) // log admin chat messages
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_pda) // log pda messages
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour
protection = CONFIG_ENTRY_LOCKED
@@ -85,14 +69,12 @@ CONFIG_DEF(number/vote_delay) // minimum time between voting sessions (decisecon
CONFIG_DEF(number/vote_period) // length of voting period (deciseconds, default 1 minute)
value = 600
min_val = 0
-
+
CONFIG_DEF(flag/default_no_vote) // vote does not default to nochange/norestart
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/no_dead_vote) // dead people can't vote
CONFIG_DEF(flag/allow_metadata) // Metadata is supported.
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/popup_admin_pm) // adminPMs to non-admins show in a pop-up 'reply' window when set
@@ -140,14 +122,12 @@ CONFIG_DEF(flag/admin_legacy_system) //Defines whether the server uses the legac
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/hostedby)
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/norespawn)
CONFIG_DEF(flag/guest_jobban)
CONFIG_DEF(flag/usewhitelist)
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/ban_legacy_system) //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
protection = CONFIG_ENTRY_LOCKED
@@ -171,29 +151,22 @@ CONFIG_DEF(flag/use_exp_restrictions_other)
CONFIG_DEF(flag/use_exp_restrictions_admin_bypass)
CONFIG_DEF(string/server)
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/banappeals)
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(string/wikiurl)
- protection = CONFIG_ENTRY_LOCKED
value = "http://www.tgstation13.org/wiki"
CONFIG_DEF(string/forumurl)
- protection = CONFIG_ENTRY_LOCKED
value = "http://tgstation13.org/phpBB/index.php"
CONFIG_DEF(string/rulesurl)
- protection = CONFIG_ENTRY_LOCKED
value = "http://www.tgstation13.org/wiki/Rules"
CONFIG_DEF(string/githuburl)
- protection = CONFIG_ENTRY_LOCKED
value = "https://www.github.com/tgstation/-tg-station"
CONFIG_DEF(number/githubrepoid)
- protection = CONFIG_ENTRY_LOCKED
value = null
min_val = 0
@@ -233,7 +206,6 @@ CONFIG_DEF(flag/useircbot) //tgs2 support
CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention
CONFIG_DEF(string/panic_server_name)
- protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
return str_val != "\[Put the name here\]" && ..()
@@ -290,7 +262,6 @@ CONFIG_DEF(string/extreme_popcap_message)
value = "The server is currently serving a high number of users, find alternative servers."
CONFIG_DEF(flag/panic_bunker) // prevents people the server hasn't seen before from connecting
- protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(number/notify_new_player_age) // how long do we notify admins of a new player
min_val = -1
@@ -303,7 +274,6 @@ CONFIG_DEF(flag/irc_first_connection_alert) // do we notify the irc channel when
CONFIG_DEF(flag/check_randomizer)
CONFIG_DEF(string/ipintel_email)
- protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
return str_val != "ch@nge.me" && ..()
@@ -315,17 +285,14 @@ CONFIG_DEF(number/ipintel_rating_bad)
max_val = 1
CONFIG_DEF(number/ipintel_save_good)
- protection = CONFIG_ENTRY_LOCKED
value = 12
min_val = 0
CONFIG_DEF(number/ipintel_save_bad)
- protection = CONFIG_ENTRY_LOCKED
value = 1
min_val = 0
CONFIG_DEF(string/ipintel_domain)
- protection = CONFIG_ENTRY_LOCKED
value = "check.getipintel.net"
CONFIG_DEF(flag/aggressive_changelog)
diff --git a/code/datums/action.dm b/code/datums/action.dm
index b0ee243978..60a0722f0f 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -591,7 +591,4 @@
var/mob/M = owner
var/datum/language_holder/H = M.get_language_holder()
H.open_language_menu(usr)
-<<<<<<< HEAD
-=======
->>>>>>> 380413f... Ports dash weapons to the dash datum (#31222)
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index c790dcc1aa..d4b75e3892 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -17,6 +17,7 @@
var/show_on_examine
var/list/allowed_typecache
var/last_inserted_type
+ var/last_inserted_id
var/last_amount_inserted
var/last_insert_success
var/datum/callback/precondition
@@ -116,7 +117,7 @@
if(!amt)
return 0
- insert_materials(S,amt)
+ last_inserted_id = insert_materials(S,amt)
last_inserted_type = S.type
S.use(amt)
last_amount_inserted = amt
@@ -133,17 +134,22 @@
if(!material_amount || !has_space(material_amount))
return 0
- insert_materials(I, multiplier)
+ last_inserted_id = insert_materials(I, multiplier)
last_inserted_type = I.type
last_amount_inserted = material_amount
return material_amount
/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
var/datum/material/M
+ var/primary_mat
+ var/max_mat_value = 0
for(var/MAT in materials)
M = materials[MAT]
M.amount += I.materials[MAT] * multiplier
total_amount += I.materials[MAT] * multiplier
+ if(I.materials[MAT] > max_mat_value)
+ primary_mat = MAT
+ return primary_mat
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index a3bfa7d497..093e828452 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -63,6 +63,7 @@
var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems)
var/datum/language_holder/language_holder
+ var/unconvertable = FALSE
/datum/mind/New(var/key)
src.key = key
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 25b04b4312..20d218f767 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -384,3 +384,31 @@
if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"])
owner.stun_absorption -= "blooddrunk"
+/datum/status_effect/sword_spin
+ id = "Bastard Sword Spin"
+ duration = 50
+ tick_interval = 8
+ alert_type = null
+
+
+/datum/status_effect/sword_spin/on_apply()
+ owner.visible_message("[owner] begins swinging the sword with inhuman strength!")
+ var/oldcolor = owner.color
+ owner.color = "#ff0000"
+ owner.add_stun_absorption("bloody bastard sword", duration, 2, "doesn't even flinch as the sword's power courses through them!", "You shrug off the stun!", " glowing with a blazing red aura!")
+ owner.spin(duration,1)
+ animate(owner, color = oldcolor, time = duration, easing = EASE_IN)
+ addtimer(CALLBACK(owner, /atom/proc/update_atom_colour), duration)
+ playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0)
+ return ..()
+
+
+/datum/status_effect/sword_spin/tick()
+ playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0)
+ var/obj/item/slashy
+ slashy = owner.get_active_held_item()
+ for(var/mob/living/M in orange(1,owner))
+ slashy.attack(M, owner)
+
+/datum/status_effect/sword_spin/on_remove()
+ owner.visible_message("[owner]'s inhuman strength dissipates and the sword's runes grow cold!")
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index 4846cc2bc2..c4b5c5caae 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -151,7 +151,11 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/maintenance/department/medical
name = "Medbay Maintenance"
- icon_state = "asmaint"
+ icon_state = "medbay_maint"
+
+/area/maintenance/department/medical/morgue
+ name = "Morgue Maintenance"
+ icon_state = "morgue_maint"
/area/maintenance/department/science
name = "Science Maintenance"
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 0e72fe93aa..7d6f9bcdd1 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -53,6 +53,8 @@ Credit where due:
return FALSE
if(M.mind.enslaved_to && !is_servant_of_ratvar(M.mind.enslaved_to))
return FALSE
+ if(M.mind.unconvertable)
+ return FALSE
else
return FALSE
if(iscultist(M) || isconstruct(M) || M.isloyal() || ispAI(M))
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 868e02589b..01773f1ea6 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -21,6 +21,8 @@
return FALSE
if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to))
return FALSE
+ if(M.mind.unconvertable)
+ return FALSE
else
return FALSE
if(M.isloyal() || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M))
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index b6f25fc746..62fe64ecee 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -72,8 +72,6 @@
if(is_servant_of_ratvar(C) && C.reagents)
C.reagents.add_reagent("heparin", 1)
-<<<<<<< HEAD
-=======
/obj/item/twohanded/required/cult_bastard
name = "bloody bastard sword"
desc = "An enormous sword used by Nar-Sien cultists to rapidly harvest the souls of non-believers."
@@ -100,7 +98,6 @@
var/datum/action/innate/cult/spin2win/linked_action
var/spinning = FALSE
var/spin_cooldown = 250
- var/list/shards = list()
var/dash_toggled = TRUE
/obj/item/twohanded/required/cult_bastard/Initialize()
@@ -176,11 +173,12 @@
if(H.stat != CONSCIOUS)
var/obj/item/device/soulstone/SS = new /obj/item/device/soulstone(src)
SS.attack(H, user)
- shards += SS
- return
+ if(!LAZYLEN(SS.contents))
+ qdel(SS)
if(istype(target, /obj/structure/constructshell) && contents.len)
var/obj/item/device/soulstone/SS = contents[1]
- if(istype(SS) && SS.transfer_soul("CONSTRUCT",target,user))
+ if(istype(SS))
+ SS.transfer_soul("CONSTRUCT",target,user)
qdel(SS)
/datum/action/innate/dash/cult
@@ -238,7 +236,6 @@
sword.slowdown -= 1.5
sleep(sword.spin_cooldown)
holder.update_action_buttons_icon()
->>>>>>> 380413f... Ports dash weapons to the dash datum (#31222)
/obj/item/restraints/legcuffs/bola/cult
name = "nar'sien bola"
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index c1ccf9a368..8140dffe53 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -100,15 +100,21 @@
if(cooldowntime > world.time)
to_chat(user, "The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].")
return
- var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit")
+ var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword")
var/pickedtype
switch(choice)
if("Shielded Robe")
pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield
if("Flagellant's Robe")
pickedtype = /obj/item/clothing/suit/hooded/cultrobes/berserker
- if("Nar-Sien Hardsuit")
- pickedtype = /obj/item/clothing/suit/space/hardsuit/cult
+ if("Bastard Sword")
+ if((world.time - SSticker.round_start_time) >= 12000)
+ pickedtype = /obj/item/twohanded/required/cult_bastard
+ else
+ cooldowntime = 12000 - (world.time - SSticker.round_start_time)
+ to_chat(user, "The forge fires are not yet hot enough for this weapon, give it another [DisplayTimeText(cooldowntime)].")
+ cooldowntime = 0
+ return
if(src && !QDELETED(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time)
cooldowntime = world.time + 2400
var/obj/item/N = new pickedtype(get_turf(src))
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index add016dd8f..c1b6d13456 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -253,12 +253,14 @@
/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind)
if(rev_mind.assigned_role in GLOB.command_positions)
- return 0
+ return FALSE
var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted
if(H.isloyal())
- return 0
+ return FALSE
if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries))
- return 0
+ return FALSE
+ if(rev_mind.unconvertable)
+ return FALSE
revolutionaries += rev_mind
if(iscarbon(rev_mind.current))
var/mob/living/carbon/carbon_mob = rev_mind.current
@@ -271,7 +273,7 @@
update_rev_icons_added(rev_mind)
if(jobban_isbanned(rev_mind.current, ROLE_REV))
INVOKE_ASYNC(src, .proc/replace_jobbaned_player, rev_mind.current, ROLE_REV, ROLE_REV)
- return 1
+ return TRUE
//////////////////////////////////////////////////////////////////////////////
//Deals with players being converted from the revolution (Not a rev anymore)// // Modified to handle borged MMIs. Accepts another var if the target is being borged at the time -- Polymorph.
//////////////////////////////////////////////////////////////////////////////
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index df57ded774..149c2ae912 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -199,7 +199,6 @@
SSticker.mode.cult -= A.mind
SSticker.mode.update_cult_icons_removed(A.mind)
qdel(T)
- user.drop_item()
qdel(src)
else
to_chat(user, "Creation failed!: The soul stone is empty! Go kill someone!")
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 9fa53765ed..4894952a69 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -134,12 +134,11 @@
if(ispath(lit, /obj/item/ore/bluespace_crystal))
use_power(max(500,M.last_amount_inserted/10))
else
- var/obj/item/stack/S = lit
- var/list/initmats = initial(S.materials)
- if (initmats[MAT_METAL])
- flick("autolathe_o",src)//plays metal insertion animation
- if (initmats[MAT_GLASS])
- flick("autolathe_r",src)//plays glass insertion animation
+ switch(M.last_inserted_id)
+ if (MAT_METAL)
+ flick("autolathe_o",src)//plays metal insertion animation
+ if (MAT_GLASS)
+ flick("autolathe_r",src)//plays glass insertion animation
use_power(M.last_amount_inserted*100)
updateUsrDialog()
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 8efc14d966..747647b1a5 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -420,13 +420,7 @@
var/datum/component/material_container/M = C
if(!M.last_insert_success)
return
- var/lit = M.last_inserted_type
- var/stack_name
- if(ispath(lit, /obj/item/ore/bluespace_crystal))
- stack_name = "bluespace"
- else
- var/obj/item/stack/S = lit
- stack_name = material2name(initial(S.materials)[1])
+ var/stack_name = material2name(M.last_inserted_id)
add_overlay("fab-load-[stack_name]")
addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[stack_name]"), 10)
updateUsrDialog()
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 8b2d95f373..dfc5fb94d5 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -213,7 +213,7 @@
/obj/effect/temp_visual/fire
icon = 'icons/effects/fire.dmi'
icon_state = "3"
- light_range = 3
+ light_range = LIGHT_RANGE_FIRE
light_color = LIGHT_COLOR_FIRE
duration = 10
diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm
index 8b27659ada..513ffb8d2b 100644
--- a/code/game/objects/items/devices/radio/electropack.dm
+++ b/code/game/objects/items/devices/radio/electropack.dm
@@ -143,4 +143,82 @@ Code:
"}
user << browse(dat, "window=radio")
onclose(user, "radio")
- return
\ No newline at end of file
+ return
+
+/obj/item/device/electropack/shockcollar
+ name = "shock collar"
+ desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.."
+ icon = 'icons/obj/clothing/neck.dmi'
+ icon_state = "shockcollar"
+ item_state = "shockcollar"
+ body_parts_covered = NECK
+ slot_flags = SLOT_NECK
+ w_class = WEIGHT_CLASS_SMALL
+ strip_delay = 60
+ equip_delay_other = 60
+ materials = list(MAT_METAL=5000, MAT_GLASS=2000)
+ var/tagname = null
+
+/obj/item/device/electropack/shockcollar/attack_hand(mob/user)
+ if(loc == user)
+ if(slot_flags == SLOT_NECK)
+ to_chat(user, "The collar is fastened tight! You'll need help taking this off!")
+ return
+ ..()
+
+/obj/item/device/electropack/shockcollar/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption != code)
+ return
+
+ if(isliving(loc) && on)
+ if(shock_cooldown != 0)
+ return
+ shock_cooldown = 1
+ spawn(100)
+ shock_cooldown = 0
+ var/mob/living/L = loc
+ step(L, pick(GLOB.cardinals))
+
+ to_chat(L, "You feel a sharp shock from the collar!")
+ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
+ s.set_up(3, 1, L)
+ s.start()
+
+ L.Knockdown(100)
+
+ if(master)
+ master.receive_signal()
+ return
+
+/obj/item/device/electropack/shockcollar/attack_self(mob/user) //Turns out can't fully source this from the parent item, spritepath gets confused if power toggled. Will come back to this when I know how to code better and readd powertoggle..
+ var/option = "Change Name"
+ option = input(user, "What do you want to do?", "[src]", option) as null|anything in list("Change Name", "Change Frequency")
+ switch(option)
+ if("Change Name")
+ var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
+ if(t)
+ tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
+ name = "[initial(name)] - [tagname]"
+ if("Change Frequency")
+ if(!ishuman(user))
+ return
+ user.set_machine(src)
+ var/dat = {"
+ Frequency/Code for shock collar:
+ Frequency:
+ -
+ - [format_frequency(frequency)]
+ +
+ +
+
+ Code:
+ -
+ - [code]
+ +
+ +
+ "}
+
+ user << browse(dat, "window=radio")
+ onclose(user, "radio")
+ return
+
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index e9a622365a..e55c728121 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -73,6 +73,7 @@ MASS SPECTROMETER
origin_tech = "magnets=1;biotech=1"
var/mode = 1
var/scanmode = 0
+ var/advanced = FALSE
/obj/item/device/healthanalyzer/attack_self(mob/user)
if(!scanmode)
@@ -97,7 +98,7 @@ MASS SPECTROMETER
user.visible_message("[user] has analyzed [M]'s vitals.")
if(scanmode == 0)
- healthscan(user, M, mode)
+ healthscan(user, M, mode, advanced)
else if(scanmode == 1)
chemscan(user, M)
@@ -105,7 +106,7 @@ MASS SPECTROMETER
// Used by the PDA medical scanner too
-/proc/healthscan(mob/living/user, mob/living/M, mode = 1)
+/proc/healthscan(mob/living/user, mob/living/M, mode = 1, advanced = FALSE)
if(user.incapacitated() || user.eye_blind)
return
//Damage specifics
@@ -115,8 +116,8 @@ MASS SPECTROMETER
var/brute_loss = M.getBruteLoss()
var/mob_status = (M.stat == DEAD ? "Deceased" : "[round(M.health/M.maxHealth,0.01)*100] % healthy")
- if(M.status_flags & FAKEDEATH)
- mob_status = "Deceased"
+ if(M.status_flags & FAKEDEATH && !advanced)
+ mob_status = "Deceased"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
if(ishuman(M))
@@ -141,19 +142,77 @@ MASS SPECTROMETER
if(oxy_loss > 10)
to_chat(user, "\t[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.")
if(tox_loss > 10)
- to_chat(user, "\t[tox_loss > 50 ? "Critical" : "Dangerous"] amount of toxins detected.")
+ to_chat(user, "\t[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.")
if(M.getStaminaLoss())
to_chat(user, "\tSubject appears to be suffering from fatigue.")
+ if(advanced)
+ to_chat(user, "\tFatigue Level: [M.getStaminaLoss()]%.")
if (M.getCloneLoss())
to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.")
- if (M.reagents && M.reagents.get_reagent_amount("epinephrine"))
- to_chat(user, "\tBloodstream analysis located [M.reagents.get_reagent_amount("epinephrine")] units of rejuvenation chemicals.")
+ if(advanced)
+ to_chat(user, "\tCellular Damage Level: [M.getCloneLoss()].")
if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain))
to_chat(user, "\tSubject brain function is non-existent.")
else if (M.getBrainLoss() >= 60)
to_chat(user, "\tSevere brain damage detected. Subject likely to have mental retardation.")
else if (M.getBrainLoss() >= 10)
to_chat(user, "\tBrain damage detected. Subject may have had a concussion.")
+ if(advanced)
+ to_chat(user, "\tBrain Activity Level: [100 - M.getBrainLoss()]%.")
+ if (M.radiation)
+ to_chat(user, "\tSubject is irradiated.")
+ if(advanced)
+ to_chat(user, "\tRadiation Level: [M.radiation]%.")
+
+ if(advanced && M.hallucinating())
+ to_chat(user, "\tSubject is hallucinating.")
+
+ //Eyes and ears
+ if(advanced)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ var/obj/item/organ/ears/ears = C.getorganslot("ears")
+ to_chat(user, "\t==EAR STATUS==")
+ if(istype(ears))
+ var/healthy = TRUE
+ if(C.disabilities & DEAF)
+ healthy = FALSE
+ to_chat(user, "\tSubject is genetically deaf.")
+ else
+ if(ears.ear_damage)
+ to_chat(user, "\tSubject has [ears.ear_damage > UNHEALING_EAR_DAMAGE? "permanent ": "temporary "]hearing damage.")
+ healthy = FALSE
+ if(ears.deaf)
+ to_chat(user, "\tSubject is [ears.ear_damage > UNHEALING_EAR_DAMAGE ? "permanently ": "temporarily "] deaf.")
+ healthy = FALSE
+ if(healthy)
+ to_chat(user, "\tHealthy.")
+ else
+ to_chat(user, "\tSubject does not have ears.")
+ var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight")
+ to_chat(user, "\t==EYE STATUS==")
+ if(istype(eyes))
+ var/healthy = TRUE
+ if(C.disabilities & BLIND)
+ to_chat(user, "\tSubject is blind.")
+ healthy = FALSE
+ if(C.disabilities & NEARSIGHT)
+ to_chat(user, "\tSubject is nearsighted.")
+ healthy = FALSE
+ if(eyes.eye_damage > 30)
+ to_chat(user, "\tSubject has severe eye damage.")
+ healthy = FALSE
+ else if(eyes.eye_damage > 20)
+ to_chat(user, "\tSubject has significant eye damage.")
+ healthy = FALSE
+ else if(eyes.eye_damage)
+ to_chat(user, "\tSubject has minor eye damage.")
+ healthy = FALSE
+ if(healthy)
+ to_chat(user, "\tHealthy.")
+ else
+ to_chat(user, "\tSubject does not have eyes.")
+
if(ishuman(M))
var/mob/living/carbon/human/H = M
@@ -177,7 +236,7 @@ MASS SPECTROMETER
to_chat(user, "Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)")
// Time of death
- if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
+ if(M.tod && (M.stat == DEAD || ((M.status_flags & FAKEDEATH) && !advanced)))
to_chat(user, "Time of Death: [M.tod]")
var/tdelta = round(world.time - M.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
@@ -251,6 +310,12 @@ MASS SPECTROMETER
if(0)
to_chat(usr, "The scanner no longer shows limb damage.")
+/obj/item/device/healthanalyzer/advanced
+ name = "advanced health analyzer"
+ icon_state = "health_adv"
+ desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy."
+ origin_tech = "magnets=3;biotech=3"
+ advanced = TRUE
/obj/item/device/analyzer
desc = "A hand-held environmental scanner which reports current gas levels."
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 1badef90cf..634fbee9d2 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -335,8 +335,8 @@
/obj/item/nullrod/carp
name = "carp-sie plushie"
desc = "An adorable stuffed toy that resembles the god of all carp. The teeth look pretty sharp. Activate it to receive the blessing of Carp-Sie."
- icon = 'icons/obj/toy.dmi'
- icon_state = "carpplushie"
+ icon = 'icons/obj/plushes.dmi'
+ icon_state = "carpplush"
item_state = "carp_plushie"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
diff --git a/code/game/objects/items/implants/implant_loyality.dm b/code/game/objects/items/implants/implant_loyality.dm
index a1e9a0e4d5..ffaebf5a63 100644
--- a/code/game/objects/items/implants/implant_loyality.dm
+++ b/code/game/objects/items/implants/implant_loyality.dm
@@ -19,12 +19,12 @@
/obj/item/implant/mindshield/implant(mob/living/target, mob/user, silent = 0)
if(..())
- if((target.mind in (SSticker.mode.head_revolutionaries)))
+ if((target.mind in (SSticker.mode.head_revolutionaries)) || target.mind.unconvertable)
if(!silent)
target.visible_message("[target] seems to resist the implant!", "You feel something interfering with your mental conditioning, but you resist it!")
removed(target, 1)
qdel(src)
- return 0
+ return FALSE
if(target.mind in SSticker.mode.revolutionaries)
SSticker.mode.remove_revolutionary(target.mind, FALSE, user)
if(!silent)
@@ -32,8 +32,8 @@
to_chat(target, "You feel something interfering with your mental conditioning, but you resist it!")
else
to_chat(target, "You feel a sense of peace and security. You are now protected from brainwashing.")
- return 1
- return 0
+ return TRUE
+ return FALSE
/obj/item/implant/mindshield/removed(mob/target, silent = 0, special = 0)
if(..())
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index dc6993cdbe..28856e17d8 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -156,6 +156,24 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
var/unholy2clean = A.reagents.get_reagent_amount("unholywater")
A.reagents.del_reagent("unholywater")
A.reagents.add_reagent("holywater",unholy2clean)
+ if(istype(A, /obj/item/twohanded/required/cult_bastard))
+ var/obj/item/twohanded/required/cult_bastard/sword = A
+ to_chat(user, "You begin to exorcise [sword].")
+ playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1)
+ if(do_after(user, 40, target = sword))
+ playsound(src,'sound/effects/pray_chaplain.ogg',60,1)
+ for(var/obj/item/device/soulstone/SS in sword.shards)
+ SS.usability = TRUE
+ for(var/mob/living/simple_animal/shade/EX in SS)
+ SSticker.mode.remove_cultist(EX.mind, 1, 0)
+ EX.icon_state = "ghost1"
+ EX.name = "Purified [EX.name]"
+ SS.release_shades(user)
+ qdel(SS)
+ new /obj/item/nullrod/claymore(get_turf(sword))
+ user.visible_message("[user] has purified the [sword]!!")
+ qdel(sword)
+
/obj/item/storage/book/bible/booze
desc = "To be applied to the head repeatedly."
diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm
index 935b62f46a..5c36c5a6ba 100644
--- a/code/game/objects/structures/beds_chairs/bed.dm
+++ b/code/game/objects/structures/beds_chairs/bed.dm
@@ -21,6 +21,10 @@
var/buildstacktype = /obj/item/stack/sheet/metal
var/buildstackamount = 2
+/obj/structure/bed/examine(mob/user)
+ ..()
+ to_chat(user, "It's held together by a couple of bolts.")
+
/obj/structure/bed/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(buildstacktype)
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index aed1679322..9d6985c620 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -1,6 +1,6 @@
/obj/structure/chair
name = "chair"
- desc = "You sit in this. Either by will or force.\nDrag your sprite to sit in the chair. Alt-click to rotate it clockwise."
+ desc = "You sit in this. Either by will or force."
icon = 'icons/obj/chairs.dmi'
icon_state = "chair"
anchored = TRUE
@@ -14,6 +14,14 @@
var/item_chair = /obj/item/chair // if null it can't be picked up
layer = OBJ_LAYER
+/obj/structure/chair/examine(mob/user)
+ ..()
+ to_chat(user, "It's held together by a couple of bolts.")
+ if(!has_buckled_mobs())
+ to_chat(user, "Drag your sprite to sit in it. Alt-click to rotate.")
+ else
+ to_chat(user, "Alt-click to rotate.")
+
/obj/structure/chair/Initialize()
. = ..()
if(!anchored) //why would you put these on the shuttle?
@@ -140,7 +148,7 @@
/obj/structure/chair/comfy
name = "comfy chair"
- desc = "It looks comfy.\nAlt-click to rotate it clockwise."
+ desc = "It looks comfy."
icon_state = "comfychair"
color = rgb(255,255,255)
resistance_flags = FLAMMABLE
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index c7b63be32b..3d77be1bb5 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -76,8 +76,12 @@
/obj/structure/closet/examine(mob/user)
..()
+ if(welded)
+ to_chat(user, "It's welded shut.")
if(anchored)
- to_chat(user, "It is anchored to the ground.")
+ to_chat(user, "It is bolted to the ground.")
+ if(opened)
+ to_chat(user, "The parts are welded together.")
else if(secure && !opened)
to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].")
@@ -453,4 +457,4 @@
/obj/structure/closet/return_temperature()
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index a2a055f464..ee9ecfc908 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -1,93 +1,94 @@
-/obj/structure/closet/secure_closet/medical1
- name = "medicine closet"
- desc = "Filled to the brim with medical junk."
- icon_state = "med"
+/obj/structure/closet/secure_closet/medical1
+ name = "medicine closet"
+ desc = "Filled to the brim with medical junk."
+ icon_state = "med"
req_access = list(ACCESS_MEDICAL)
-
-/obj/structure/closet/secure_closet/medical1/PopulateContents()
- ..()
- new /obj/item/reagent_containers/glass/beaker(src)
- new /obj/item/reagent_containers/glass/beaker(src)
- new /obj/item/reagent_containers/dropper(src)
- new /obj/item/reagent_containers/dropper(src)
- new /obj/item/storage/belt/medical(src)
- new /obj/item/storage/box/syringes(src)
- new /obj/item/reagent_containers/glass/bottle/toxin(src)
- new /obj/item/reagent_containers/glass/bottle/morphine(src)
- new /obj/item/reagent_containers/glass/bottle/morphine(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/glass/bottle/epinephrine(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/glass/bottle/charcoal(src)
- new /obj/item/storage/box/rxglasses(src)
-
-/obj/structure/closet/secure_closet/medical2
- name = "anesthetic closet"
- desc = "Used to knock people out."
+
+/obj/structure/closet/secure_closet/medical1/PopulateContents()
+ ..()
+ new /obj/item/reagent_containers/glass/beaker(src)
+ new /obj/item/reagent_containers/glass/beaker(src)
+ new /obj/item/reagent_containers/dropper(src)
+ new /obj/item/reagent_containers/dropper(src)
+ new /obj/item/storage/belt/medical(src)
+ new /obj/item/storage/box/syringes(src)
+ new /obj/item/reagent_containers/glass/bottle/toxin(src)
+ new /obj/item/reagent_containers/glass/bottle/morphine(src)
+ new /obj/item/reagent_containers/glass/bottle/morphine(src)
+ for(var/i in 1 to 3)
+ new /obj/item/reagent_containers/glass/bottle/epinephrine(src)
+ for(var/i in 1 to 3)
+ new /obj/item/reagent_containers/glass/bottle/charcoal(src)
+ new /obj/item/storage/box/rxglasses(src)
+
+/obj/structure/closet/secure_closet/medical2
+ name = "anesthetic closet"
+ desc = "Used to knock people out."
req_access = list(ACCESS_SURGERY)
-
-/obj/structure/closet/secure_closet/medical2/PopulateContents()
- ..()
- for(var/i in 1 to 3)
- new /obj/item/tank/internals/anesthetic(src)
- for(var/i in 1 to 3)
- new /obj/item/clothing/mask/breath/medical(src)
-
-/obj/structure/closet/secure_closet/medical3
- name = "medical doctor's locker"
+
+/obj/structure/closet/secure_closet/medical2/PopulateContents()
+ ..()
+ for(var/i in 1 to 3)
+ new /obj/item/tank/internals/anesthetic(src)
+ for(var/i in 1 to 3)
+ new /obj/item/clothing/mask/breath/medical(src)
+
+/obj/structure/closet/secure_closet/medical3
+ name = "medical doctor's locker"
req_access = list(ACCESS_SURGERY)
- icon_state = "med_secure"
-
-/obj/structure/closet/secure_closet/medical3/PopulateContents()
- ..()
- new /obj/item/device/radio/headset/headset_med(src)
- new /obj/item/defibrillator/loaded(src)
- new /obj/item/clothing/gloves/color/latex/nitrile(src)
- new /obj/item/storage/belt/medical(src)
- new /obj/item/clothing/glasses/hud/health(src)
- return
-
-/obj/structure/closet/secure_closet/CMO
- name = "\proper chief medical officer's locker"
+ icon_state = "med_secure"
+
+/obj/structure/closet/secure_closet/medical3/PopulateContents()
+ ..()
+ new /obj/item/device/radio/headset/headset_med(src)
+ new /obj/item/defibrillator/loaded(src)
+ new /obj/item/clothing/gloves/color/latex/nitrile(src)
+ new /obj/item/storage/belt/medical(src)
+ new /obj/item/clothing/glasses/hud/health(src)
+ return
+
+/obj/structure/closet/secure_closet/CMO
+ name = "\proper chief medical officer's locker"
req_access = list(ACCESS_CMO)
- icon_state = "cmo"
-
-/obj/structure/closet/secure_closet/CMO/PopulateContents()
- ..()
- new /obj/item/clothing/neck/cloak/cmo(src)
- new /obj/item/storage/backpack/duffelbag/med(src)
- new /obj/item/clothing/suit/bio_suit/cmo(src)
- new /obj/item/clothing/head/bio_hood/cmo(src)
- new /obj/item/clothing/suit/toggle/labcoat/cmo(src)
- new /obj/item/clothing/under/rank/chief_medical_officer(src)
- new /obj/item/clothing/shoes/sneakers/brown (src)
- new /obj/item/cartridge/cmo(src)
- new /obj/item/device/radio/headset/heads/cmo(src)
- new /obj/item/device/megaphone/command(src)
- new /obj/item/defibrillator/compact/loaded(src)
- new /obj/item/clothing/gloves/color/latex/nitrile(src)
- new /obj/item/storage/belt/medical(src)
- new /obj/item/device/assembly/flash/handheld(src)
- new /obj/item/reagent_containers/hypospray/CMO(src)
- new /obj/item/device/autosurgeon/cmo(src)
- new /obj/item/door_remote/chief_medical_officer(src)
-
-/obj/structure/closet/secure_closet/animal
- name = "animal control"
+ icon_state = "cmo"
+
+/obj/structure/closet/secure_closet/CMO/PopulateContents()
+ ..()
+ new /obj/item/clothing/neck/cloak/cmo(src)
+ new /obj/item/storage/backpack/duffelbag/med(src)
+ new /obj/item/clothing/suit/bio_suit/cmo(src)
+ new /obj/item/clothing/head/bio_hood/cmo(src)
+ new /obj/item/clothing/suit/toggle/labcoat/cmo(src)
+ new /obj/item/clothing/under/rank/chief_medical_officer(src)
+ new /obj/item/clothing/shoes/sneakers/brown (src)
+ new /obj/item/cartridge/cmo(src)
+ new /obj/item/device/radio/headset/heads/cmo(src)
+ new /obj/item/device/megaphone/command(src)
+ new /obj/item/defibrillator/compact/loaded(src)
+ new /obj/item/clothing/gloves/color/latex/nitrile(src)
+ new /obj/item/storage/belt/medical(src)
+ new /obj/item/device/healthanalyzer/advanced(src)
+ new /obj/item/device/assembly/flash/handheld(src)
+ new /obj/item/reagent_containers/hypospray/CMO(src)
+ new /obj/item/device/autosurgeon/cmo(src)
+ new /obj/item/door_remote/chief_medical_officer(src)
+
+/obj/structure/closet/secure_closet/animal
+ name = "animal control"
req_access = list(ACCESS_SURGERY)
-
-/obj/structure/closet/secure_closet/animal/PopulateContents()
- ..()
- new /obj/item/device/assembly/signaler(src)
- for(var/i in 1 to 3)
- new /obj/item/device/electropack(src)
-
-/obj/structure/closet/secure_closet/chemical
- name = "chemical closet"
- desc = "Store dangerous chemicals in here."
- icon_door = "chemical"
-
-/obj/structure/closet/secure_closet/chemical/PopulateContents()
- ..()
- new /obj/item/storage/box/pillbottles(src)
- new /obj/item/storage/box/pillbottles(src)
+
+/obj/structure/closet/secure_closet/animal/PopulateContents()
+ ..()
+ new /obj/item/device/assembly/signaler(src)
+ for(var/i in 1 to 3)
+ new /obj/item/device/electropack(src)
+
+/obj/structure/closet/secure_closet/chemical
+ name = "chemical closet"
+ desc = "Store dangerous chemicals in here."
+ icon_door = "chemical"
+
+/obj/structure/closet/secure_closet/chemical/PopulateContents()
+ ..()
+ new /obj/item/storage/box/pillbottles(src)
+ new /obj/item/storage/box/pillbottles(src)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 914be24cfd..1683ac00e6 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -1,5 +1,5 @@
/obj/structure/grille
- desc = "A flimsy lattice of metal rods, with screws to secure it to the floor."
+ desc = "A flimsy framework of metal rods."
name = "grille"
icon = 'icons/obj/structures.dmi'
icon_state = "grille"
@@ -17,6 +17,13 @@
var/grille_type = null
var/broken_type = /obj/structure/grille/broken
+/obj/structure/grille/examine(mob/user)
+ ..()
+ if(anchored)
+ to_chat(user, "It's secured in place with screws. The rods look like they could be cut through.")
+ if(!anchored)
+ to_chat(user, "The anchoring screws are unscrewed. The rods look like they could be cut through.")
+
/obj/structure/grille/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
switch(the_rcd.mode)
if(RCD_DECONSTRUCT)
diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm
index d578b307db..c0dcd866d8 100644
--- a/code/game/objects/structures/lattice.dm
+++ b/code/game/objects/structures/lattice.dm
@@ -16,6 +16,13 @@
smooth = SMOOTH_MORE
// flags_1 = CONDUCT_1
+/obj/structure/lattice/examine(mob/user)
+ ..()
+ deconstruction_hints(user)
+
+/obj/structure/lattice/proc/deconstruction_hints(mob/user)
+ to_chat(user, "The rods look like they could be cut. There's space for more rods or a tile.")
+
/obj/structure/lattice/Initialize(mapload)
. = ..()
for(var/obj/structure/lattice/LAT in loc)
@@ -79,6 +86,9 @@
smooth = SMOOTH_TRUE
canSmoothWith = null
+/obj/structure/lattice/catwalk/deconstruction_hints(mob/user)
+ to_chat(user, "The supporting rods look like they could be cut.")
+
/obj/structure/lattice/catwalk/ratvar_act()
new /obj/structure/lattice/catwalk/clockwork(loc)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 116ced183f..c54661066a 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -34,6 +34,13 @@
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/table, /obj/structure/table/reinforced)
+/obj/structure/table/examine(mob/user)
+ ..()
+ deconstruction_hints(user)
+
+/obj/structure/table/proc/deconstruction_hints(mob/user)
+ to_chat(user, "The top is screwed on, but the main bolts are also visible.")
+
/obj/structure/table/Initialize()
. = ..()
for(var/obj/structure/table/T in src.loc)
@@ -285,7 +292,7 @@
*/
/obj/structure/table/reinforced
name = "reinforced table"
- desc = "A reinforced version of the four legged table, much harder to simply deconstruct."
+ desc = "A reinforced version of the four legged table."
icon = 'icons/obj/smooth_structures/reinforced_table.dmi'
icon_state = "r_table"
deconstruction_ready = 0
@@ -295,6 +302,12 @@
integrity_failure = 50
armor = list(melee = 10, bullet = 30, laser = 30, energy = 100, bomb = 20, bio = 0, rad = 0, fire = 80, acid = 70)
+/obj/structure/table/reinforced/deconstruction_hints(mob/user)
+ if(deconstruction_ready)
+ to_chat(user, "The top cover has been welded loose and the main frame's bolts are exposed.")
+ else
+ to_chat(user, "The top cover is firmly welded on.")
+
/obj/structure/table/reinforced/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
@@ -405,6 +418,10 @@
pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.
max_integrity = 20
+/obj/structure/rack/examine(mob/user)
+ ..()
+ to_chat(user, "It's held together by a couple of bolts.")
+
/obj/structure/rack/CanPass(atom/movable/mover, turf/target)
if(src.density == 0) //Because broken racks -Agouri |TODO: SPRITE!|
return 1
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 02206646d2..97634f7629 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -161,10 +161,10 @@
broken = 0
burnt = 0
if(user && !silent)
- to_chat(user, "You remove the broken plating.")
+ to_chat(user, "You remove the broken plating.")
else
if(user && !silent)
- to_chat(user, "You remove the floor tile.")
+ to_chat(user, "You remove the floor tile.")
if(floor_tile && make_tile)
new floor_tile(src)
return make_plating()
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index a24642c735..428c965197 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -8,10 +8,15 @@
*/
/turf/open/floor/wood
+ desc = "Stylish dark wood."
icon_state = "wood"
floor_tile = /obj/item/stack/tile/wood
broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7")
+/turf/open/floor/wood/examine(mob/user)
+ ..()
+ to_chat(user, "There's a few screws and a small crack visible.")
+
/turf/open/floor/wood/attackby(obj/item/C, mob/user, params)
if(..())
return
@@ -42,16 +47,16 @@
broken = 0
burnt = 0
if(user && !silent)
- to_chat(user, "You remove the broken planks.")
+ to_chat(user, "You remove the broken planks.")
else
if(make_tile)
if(user && !silent)
- to_chat(user, "You unscrew the planks.")
+ to_chat(user, "You unscrew the planks.")
if(floor_tile)
new floor_tile(src)
else
if(user && !silent)
- to_chat(user, "You forcefully pry off the planks, destroying them in the process.")
+ to_chat(user, "You forcefully pry off the planks, destroying them in the process.")
return make_plating()
/turf/open/floor/wood/cold
@@ -78,7 +83,7 @@
if(istype(C, /obj/item/shovel) && params)
new ore_type(src)
new ore_type(src) //Make some sand if you shovel grass
- user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].")
+ user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
make_plating()
if(..())
@@ -143,6 +148,10 @@
canSmoothWith = list(/turf/open/floor/carpet)
flags_1 = NONE
+/turf/open/floor/carpet/examine(mob/user)
+ ..()
+ to_chat(user, "There's a small crack on the edge of it.")
+
/turf/open/floor/carpet/Initialize()
. = ..()
update_icon()
diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm
index 247382d03c..0dd3673f6a 100644
--- a/code/game/turfs/simulated/floor/light_floor.dm
+++ b/code/game/turfs/simulated/floor/light_floor.dm
@@ -12,6 +12,10 @@
var/can_modify_colour = TRUE
+/turf/open/floor/light/examine(mob/user)
+ ..()
+ to_chat(user, "There's a small crack on the edge of it.")
+
/turf/open/floor/light/Initialize()
. = ..()
update_icon()
diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm
index 63c883f88c..b194127de8 100644
--- a/code/game/turfs/simulated/floor/plasteel_floor.dm
+++ b/code/game/turfs/simulated/floor/plasteel_floor.dm
@@ -4,6 +4,10 @@
broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
burnt_states = list("floorscorched1", "floorscorched2")
+/turf/open/floor/plasteel/examine(mob/user)
+ ..()
+ to_chat(user, "There's a small crack on the edge of it.")
+
/turf/open/floor/plasteel/update_icon()
if(!..())
return 0
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 8ad6657784..3e16da8b9f 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -12,6 +12,13 @@
icon_state = "plating"
intact = FALSE
+/turf/open/floor/plating/examine(mob/user)
+ ..()
+ if(broken || burnt)
+ to_chat(user, "It looks like the dents could be welded smooth.")
+ return
+ to_chat(user, "There are few attachment holes for a new tile or reinforcement rods.")
+
/turf/open/floor/plating/Initialize()
if (!broken_states)
broken_states = list("platingdmg1", "platingdmg2", "platingdmg3")
diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm
index 2649a3a14d..848a7e8219 100644
--- a/code/game/turfs/simulated/floor/plating/asteroid.dm
+++ b/code/game/turfs/simulated/floor/plating/asteroid.dm
@@ -193,7 +193,7 @@
var/list/L = list(45)
if(IsOdd(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels.
- L += -45
+ L -= 45
// Expand the edges of our tunnel
for(var/edge_angle in L)
diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm
index 04c97aa7d5..74354e78c7 100644
--- a/code/game/turfs/simulated/floor/reinf_floor.dm
+++ b/code/game/turfs/simulated/floor/reinf_floor.dm
@@ -1,11 +1,16 @@
/turf/open/floor/engine
name = "reinforced floor"
+ desc = "Extremely sturdy."
icon_state = "engine"
thermal_conductivity = 0.025
heat_capacity = INFINITY
floor_tile = /obj/item/stack/rods
+/turf/open/floor/engine/examine(mob/user)
+ ..()
+ to_chat(user, "The reinforcement rods are wrenched firmly in place.")
+
/turf/open/floor/engine/airless
initial_gas_mix = "TEMP=2.7"
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
index a39a9059f3..93862f16b4 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -49,7 +49,7 @@
icon = 'icons/effects/fire.dmi'
icon_state = "1"
layer = ABOVE_OPEN_TURF_LAYER
- light_range = 3
+ light_range = LIGHT_RANGE_FIRE
light_color = LIGHT_COLOR_FIRE
var/volume = 125
@@ -175,3 +175,15 @@
..()
if(isliving(L))
L.fire_act(temperature, volume)
+
+/obj/effect/dummy/fire
+ name = "fire"
+ desc = "OWWWWWW. IT BURNS. Tell a coder if you're seeing this."
+ icon_state = "nothing"
+ light_color = LIGHT_COLOR_FIRE
+ light_range = LIGHT_RANGE_FIRE
+
+/obj/effect/dummy/fire/Initialize()
+ . = ..()
+ if(!isliving(loc))
+ qdel(src)
diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm
index 7c8db01bcc..11426a4e04 100644
--- a/code/modules/food_and_drinks/food/snacks_meat.dm
+++ b/code/modules/food_and_drinks/food/snacks_meat.dm
@@ -185,7 +185,9 @@
/obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand()
visible_message("[src] expands!")
- new /mob/living/carbon/monkey(get_turf(src))
+ var/mob/spammer = get_mob_by_key(src.fingerprintslast)
+ var/mob/living/carbon/monkey/bananas = new(get_turf(src))
+ bananas.log_message("Spawned via [src] at [COORD(src)], Last attached mob: [key_name(spammer)].", INDIVIDUAL_ATTACK_LOG)
qdel(src)
/obj/item/reagent_containers/food/snacks/enchiladas
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index ae5f5c2fbb..33f02bc759 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -25,6 +25,21 @@
var/list/allowed_books = list(/obj/item/book, /obj/item/spellbook, /obj/item/storage/book) //Things allowed in the bookcase
+/obj/structure/bookcase/examine(mob/user)
+ ..()
+ if(!anchored)
+ to_chat(user, "The bolts on the bottom are unsecured.")
+ if(anchored)
+ to_chat(user, "It's secured in place with bolts.")
+ switch(state)
+ if(0)
+ to_chat(user, "There's a small crack visible on the back panel.")
+ if(1)
+ to_chat(user, "There's space inside for a wooden shelf.")
+ if(2)
+ to_chat(user, "There's a small crack visible on the shelf.")
+
+
/obj/structure/bookcase/Initialize(mapload)
. = ..()
if(!mapload)
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index cc98fd827e..831fde141e 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -59,6 +59,7 @@
if(previewJob && !nude)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
+ mannequin.compile_overlays()
CHECK_TICK
preview_icon = icon('icons/effects/effects.dmi', "nothing")
preview_icon.Scale(48+32, 16+32)
diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm
index 13a34b6bae..aa15e28e66 100644
--- a/code/modules/mob/living/brain/brain_item.dm
+++ b/code/modules/mob/living/brain/brain_item.dm
@@ -18,12 +18,12 @@
vital = FALSE
decoy_override = TRUE
-/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0)
+/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0,no_id_transfer = FALSE)
..()
name = "brain"
- if(C.mind && C.mind.changeling) //congrats, you're trapped in a body you don't control
+ if(C.mind && C.mind.changeling && !no_id_transfer) //congrats, you're trapped in a body you don't control
if(brainmob && !(C.stat == DEAD || (C.status_flags & FAKEDEATH)))
to_chat(brainmob, "You can't feel your body! You're still just a brain!")
loc = C
@@ -44,13 +44,9 @@
//Update the body's icon so it doesnt appear debrained anymore
C.update_hair()
-/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0)
+/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
..()
- if(!special)
- if(C.has_brain_worms())
- var/mob/living/simple_animal/borer/B = C.has_brain_worms()
- B.leave_victim() //Should remove borer if the brain is removed - RR
- if(!gc_destroyed || (owner && !owner.gc_destroyed))
+ if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer)
transfer_identity(C)
C.update_hair()
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 6068ef2d66..d90db23679 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -250,6 +250,9 @@
if(health >= 0 && !(status_flags & FAKEDEATH))
if(lying)
+ if(buckled)
+ to_chat(M, "You need to unbuckle [src] first to do that!")
+ return
M.visible_message("[M] shakes [src] trying to get [p_them()] up!", \
"You shake [src] trying to get [p_them()] up!")
else if(check_zone(M.zone_selected) == "head")
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 74ccdab19c..0ca0bed9fc 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -277,9 +277,11 @@
if(!appears_dead)
if(stat == UNCONSCIOUS)
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n"
- else if(getBrainLoss() >= 60)
- msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
-
+ else
+ if(getBrainLoss() >= 60)
+ msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n"
+ if(InCritical())
+ msg += "[t_He] is barely concious.\n"
if(getorgan(/obj/item/organ/brain))
if(istype(src, /mob/living/carbon/human/interactive))
var/mob/living/carbon/human/interactive/auto = src
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index d66e6f808a..63b84b9cf3 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -4,6 +4,7 @@
voice_name = "Unknown"
icon = 'icons/mob/human.dmi'
icon_state = "caucasian_m"
+ appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
@@ -21,41 +22,12 @@
set_species(dna.species.type)
//initialise organs
- create_internal_organs()
+ create_internal_organs() //most of it is done in set_species now, this is only for parent call
handcrafting = new()
. = ..()
-/mob/living/carbon/human/create_internal_organs()
- if(!(NOHUNGER in dna.species.species_traits))
- internal_organs += new /obj/item/organ/appendix
- if(!(NOBREATH in dna.species.species_traits))
- if(dna.species.mutantlungs)
- internal_organs += new dna.species.mutantlungs()
- else
- internal_organs += new /obj/item/organ/lungs()
- if(!(NOBLOOD in dna.species.species_traits))
- internal_organs += new /obj/item/organ/heart
-
- if(!(NOLIVER in dna.species.species_traits))
- if(dna.species.mutantliver)
- internal_organs += new dna.species.mutantliver()
- else
- internal_organs += new /obj/item/organ/liver()
-
- if(!(NOSTOMACH in dna.species.species_traits))
- if(dna.species.mutantstomach)
- internal_organs += new dna.species.mutantstomach()
- else
- internal_organs += new /obj/item/organ/stomach()
-
- internal_organs += new dna.species.mutanteyes
- internal_organs += new dna.species.mutantears
- internal_organs += new dna.species.mutanttongue
- internal_organs += new /obj/item/organ/brain
- ..()
-
/mob/living/carbon/human/OpenCraftingMenu()
handcrafting.ui_interact(src)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 07f3acea48..34d4ae8e51 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -68,7 +68,8 @@
//Flight and floating
var/override_float = 0
-
+
+ var/obj/item/organ/brain/mutant_brain = /obj/item/organ/brain
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
var/obj/item/mutanthands
@@ -123,6 +124,113 @@
return 0
return 1
+//Will regenerate missing organs
+/datum/species/proc/regenerate_organs(mob/living/carbon/C,datum/species/old_species,replace_current=TRUE)
+ var/obj/item/organ/brain/brain = C.getorganslot("brain")
+ var/obj/item/organ/heart/heart = C.getorganslot("heart")
+ var/obj/item/organ/lungs/lungs = C.getorganslot("lungs")
+ var/obj/item/organ/appendix/appendix = C.getorganslot("appendix")
+ var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight")
+ var/obj/item/organ/ears/ears = C.getorganslot("ears")
+ var/obj/item/organ/tongue/tongue = C.getorganslot("tongue")
+ var/obj/item/organ/liver/liver = C.getorganslot("liver")
+ var/obj/item/organ/stomach/stomach = C.getorganslot("stomach")
+
+ var/should_have_brain = TRUE
+ var/should_have_heart = !(NOBLOOD in species_traits)
+ var/should_have_lungs = !(NOBREATH in species_traits)
+ var/should_have_appendix = !(NOHUNGER in species_traits)
+ var/should_have_eyes = TRUE
+ var/should_have_ears = TRUE
+ var/should_have_tongue = TRUE
+ var/should_have_liver = !(NOLIVER in species_traits)
+ var/should_have_stomach = !(NOSTOMACH in species_traits)
+
+ if(brain && (replace_current || !should_have_brain))
+ if(!brain.decoy_override)//Just keep it if it's fake
+ brain.Remove(C,TRUE,TRUE)
+ QDEL_NULL(brain)
+ if(should_have_brain && !brain)
+ brain = new mutant_brain()
+ brain.Insert(C, TRUE, TRUE)
+
+ if(heart && (!should_have_heart || replace_current))
+ heart.Remove(C,1)
+ QDEL_NULL(heart)
+ if(should_have_heart && !heart)
+ heart = new()
+ heart.Insert(C)
+
+ if(lungs && (replace_current || !should_have_lungs))
+ lungs.Remove(C,1)
+ QDEL_NULL(lungs)
+ if(should_have_lungs && !lungs)
+ if(mutantlungs)
+ lungs = new mutantlungs()
+ else
+ lungs = new()
+ lungs.Insert(C)
+
+ if(liver && (!should_have_liver || replace_current))
+ liver.Remove(C,1)
+ QDEL_NULL(liver)
+ if(should_have_liver && !liver)
+ if(mutantliver)
+ liver = new mutantliver()
+ else
+ liver = new()
+ liver.Insert(C)
+
+ if(stomach && (!should_have_stomach || replace_current))
+ stomach.Remove(C,1)
+ QDEL_NULL(stomach)
+ if(should_have_stomach && !stomach)
+ if(mutantstomach)
+ stomach = new mutantstomach()
+ else
+ stomach = new()
+ stomach.Insert(C)
+
+ if(appendix && (!should_have_appendix || replace_current))
+ appendix.Remove(C,1)
+ QDEL_NULL(appendix)
+ if(should_have_appendix && !appendix)
+ appendix = new()
+ appendix.Insert(C)
+
+ if(C.get_bodypart("head"))
+ if(eyes && (replace_current || !should_have_eyes))
+ eyes.Remove(C,1)
+ QDEL_NULL(eyes)
+ if(should_have_eyes && !eyes)
+ eyes = new mutanteyes
+ eyes.Insert(C)
+
+ if(ears && (replace_current || !should_have_ears))
+ ears.Remove(C,1)
+ QDEL_NULL(ears)
+ if(should_have_ears && !ears)
+ ears = new mutantears
+ ears.Insert(C)
+
+ if(tongue && (replace_current || !should_have_tongue))
+ tongue.Remove(C,1)
+ QDEL_NULL(tongue)
+ if(should_have_tongue && !tongue)
+ tongue = new mutanttongue
+ tongue.Insert(C)
+
+ if(old_species)
+ for(var/mutantorgan in old_species.mutant_organs)
+ var/obj/item/organ/I = C.getorgan(mutantorgan)
+ if(I)
+ I.Remove(C)
+ QDEL_NULL(I)
+
+ for(var/path in mutant_organs)
+ var/obj/item/organ/I = new path()
+ I.Insert(C)
+
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species)
// Drop the items the new species can't wear
for(var/slot_id in no_equip)
@@ -138,79 +246,7 @@
if(DIGITIGRADE in species_traits)
C.Digitigrade_Leg_Swap(FALSE)
- var/obj/item/organ/heart/heart = C.getorganslot("heart")
- var/obj/item/organ/lungs/lungs = C.getorganslot("lungs")
- var/obj/item/organ/appendix/appendix = C.getorganslot("appendix")
- var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight")
- var/obj/item/organ/ears/ears = C.getorganslot("ears")
- var/obj/item/organ/tongue/tongue = C.getorganslot("tongue")
-
- var/obj/item/organ/liver/liver = C.getorganslot("liver")
- var/obj/item/organ/stomach/stomach = C.getorganslot("stomach")
-
-
-
- if((NOBLOOD in species_traits) && heart)
- heart.Remove(C)
- qdel(heart)
- else if((!(NOBLOOD in species_traits)) && (!heart))
- heart = new()
- heart.Insert(C)
-
- if(lungs)
- qdel(lungs)
- lungs = null
-
- QDEL_NULL(liver)
-
- QDEL_NULL(stomach)
-
- if(C.get_bodypart("head"))
- if(eyes)
- qdel(eyes)
- eyes = new mutanteyes
- eyes.Insert(C)
-
- if(ears)
- qdel(ears)
- ears = new mutantears
- ears.Insert(C)
-
- if(tongue)
- qdel(tongue)
- tongue = new mutanttongue
- tongue.Insert(C)
-
- if((!(NOBREATH in species_traits)) && !lungs)
- if(mutantlungs)
- lungs = new mutantlungs()
- else
- lungs = new()
- lungs.Insert(C)
-
- if((!(NOLIVER in species_traits)) && (!liver))
- if(mutantliver)
- liver = new mutantliver()
- else
- liver = new()
- liver.Insert(C)
-
- if((!(NOSTOMACH in species_traits)) && (!stomach))
- if(mutantstomach)
- stomach = new mutantstomach()
- else
- stomach = new()
- stomach.Insert(C)
-
- if((NOHUNGER in species_traits) && appendix)
- qdel(appendix)
- else if((!(NOHUNGER in species_traits)) && (!appendix))
- appendix = new()
- appendix.Insert(C)
-
- for(var/path in mutant_organs)
- var/obj/item/organ/I = new path()
- I.Insert(C)
+ regenerate_organs(C,old_species)
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
C.dna.blood_type = exotic_bloodtype
diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index ef044e462b..84bf5bdf80 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -37,7 +37,7 @@
if(H.nutrition > NUTRITION_LEVEL_FULL)
H.nutrition = NUTRITION_LEVEL_FULL
if(light_amount > 0.2) //if there's enough light, heal
- H.heal_overall_damage(0.05,0)
+ H.heal_overall_damage(0.75,0)
H.adjustOxyLoss(-0.5)
if(H.nutrition < NUTRITION_LEVEL_STARVING + 55)
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 5c635fb870..4347a8331c 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -1,3 +1,5 @@
+#define HEART_RESPAWN_THRESHHOLD 40
+
/datum/species/shadow
// Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light.
name = "???"
@@ -32,31 +34,21 @@
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform, slot_s_store)
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR,NOHUNGER,NO_DNA_COPY,NOTRANSSTING)
mutanteyes = /obj/item/organ/eyes/night_vision/nightmare
- var/obj/effect/proc_holder/spell/targeted/shadowwalk/shadowwalk
+ mutant_organs = list(/obj/item/organ/heart/nightmare)
+ mutant_brain = /obj/item/organ/brain/nightmare
- var/info_text = "You are a Nightmare. The ability shadow walk allows unlimited, unrestricted movement in the dark using. \
- Your light eater will destroy any light producing objects you attack, as well as destroy any lights a living creature may be holding. You will automatically dodge gunfire and melee attacks when on a dark tile."
+ var/info_text = "You are a Nightmare. The ability shadow walk allows unlimited, unrestricted movement in the dark while activated. \
+ Your light eater will destroy any light producing objects you attack, as well as destroy any lights a living creature may be holding. You will automatically dodge gunfire and melee attacks when on a dark tile. If killed, you will eventually revive if left in darkness."
/datum/species/shadow/nightmare/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
- var/obj/effect/proc_holder/spell/targeted/shadowwalk/SW = new
- C.AddSpell(SW)
- shadowwalk = SW
- var/obj/item/light_eater/blade = new
- C.put_in_hands(blade)
-
to_chat(C, "[info_text]")
- C.real_name = "Nightmare"
- C.name = "Nightmare"
+ C.real_name = "[pick(GLOB.nightmare_names)]"
+ C.name = C.real_name
if(C.mind)
- C.mind.name = "Nightmare"
- C.dna.real_name = "Nightmare"
-
-/datum/species/shadow/nightmare/on_species_loss(mob/living/carbon/C)
- . = ..()
- if(shadowwalk)
- C.RemoveSpell(shadowwalk)
+ C.mind.name = C.real_name
+ C.dna.real_name = C.real_name
/datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
var/turf/T = H.loc
@@ -68,6 +60,93 @@
return -1
return 0
+
+
+//Organs
+
+/obj/item/organ/brain/nightmare
+ name = "tumorous mass"
+ desc = "A fleshy growth that was dug out of the skull of a Nightmare."
+ icon_state = "brain-x-d"
+ var/obj/effect/proc_holder/spell/targeted/shadowwalk/shadowwalk
+
+/obj/item/organ/brain/nightmare/Insert(mob/living/carbon/M, special = 0)
+ ..()
+ if(M.dna.species.id != "nightmare")
+ M.set_species(/datum/species/shadow/nightmare)
+ visible_message("[M] thrashes as [src] takes root in their body!")
+ var/obj/effect/proc_holder/spell/targeted/shadowwalk/SW = new
+ M.AddSpell(SW)
+ shadowwalk = SW
+
+
+/obj/item/organ/brain/nightmare/Remove(mob/living/carbon/M, special = 0)
+ if(shadowwalk)
+ M.RemoveSpell(shadowwalk)
+ ..()
+
+
+/obj/item/organ/heart/nightmare
+ name = "heart of darkness"
+ desc = "An alien organ that twists and writhes when exposed to light."
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "demon_heart-on"
+ color = "#1C1C1C"
+ var/respawn_progress = 0
+ var/obj/item/light_eater/blade
+
+
+/obj/item/organ/heart/nightmare/attack(mob/M, mob/living/carbon/user, obj/target)
+ if(M != user)
+ return ..()
+ user.visible_message("[user] raises [src] to their mouth and tears into it with their teeth!", \
+ "[src] feels unnaturally cold in your hands. You raise [src] your mouth and devour it!")
+ playsound(user, 'sound/magic/demon_consume.ogg', 50, 1)
+
+
+ user.visible_message("Blood erupts from [user]'s arm as it reforms into a weapon!", \
+ "Icy blood pumps through your veins as your arm reforms itself!")
+ user.temporarilyRemoveItemFromInventory(src, TRUE)
+ Insert(user)
+
+/obj/item/organ/heart/nightmare/Insert(mob/living/carbon/M, special = 0)
+ ..()
+ blade = new/obj/item/light_eater
+ M.put_in_hands(blade)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
+ STOP_PROCESSING(SSobj, src)
+ respawn_progress = 0
+ if(blade)
+ QDEL_NULL(blade)
+ M.visible_message("\The [blade] disintegrates!")
+ ..()
+
+/obj/item/organ/heart/nightmare/Stop()
+ return 0
+
+/obj/item/organ/heart/nightmare/update_icon()
+ return //always beating visually
+
+/obj/item/organ/heart/nightmare/process()
+ if(QDELETED(owner) || owner.stat != DEAD)
+ respawn_progress = 0
+ return
+ var/turf/T = get_turf(owner)
+ if(istype(T))
+ var/light_amount = T.get_lumcount()
+ if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD)
+ respawn_progress++
+ playsound(owner,'sound/effects/singlebeat.ogg',40,1)
+ if(respawn_progress >= HEART_RESPAWN_THRESHHOLD)
+ owner.revive(full_heal = TRUE)
+ owner.visible_message("[owner] staggers to their feet!")
+ playsound(owner, 'sound/hallucinations/far_noise.ogg', 50, 1)
+ respawn_progress = 0
+
+//Weapon
+
/obj/item/light_eater
name = "light eater"
icon_state = "arm_blade"
@@ -113,3 +192,5 @@
visible_message("[O] is disintegrated by [src]!")
O.burn()
playsound(src, 'sound/items/welder.ogg', 50, 1)
+
+#undef HEART_RESPAWN_THRESHHOLD
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 4302c43ff8..be03e591aa 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -1,13 +1,13 @@
-/datum/species/skeleton
- // 2spooky
- name = "Spooky Scary Skeleton"
- id = "skeleton"
- say_mod = "rattles"
- blacklisted = 1
- sexes = 0
- meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
- species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYDISMEMBER,EASYLIMBATTACHMENT)
- mutant_organs = list(/obj/item/organ/tongue/bone)
- damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
- disliked_food = NONE
- liked_food = NONE
+/datum/species/skeleton
+ // 2spooky
+ name = "Spooky Scary Skeleton"
+ id = "skeleton"
+ say_mod = "rattles"
+ blacklisted = 1
+ sexes = 0
+ meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
+ species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYDISMEMBER,EASYLIMBATTACHMENT)
+ mutanttongue = /obj/item/organ/tongue/bone
+ damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
+ disliked_food = NONE
+ liked_food = NONE
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 04123102c0..016a3635ef 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -9,7 +9,7 @@
blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT,NOTRANSSTING)
- mutant_organs = list(/obj/item/organ/tongue/zombie)
+ mutanttongue = /obj/item/organ/tongue/zombie
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
liked_food = NONE
@@ -37,6 +37,7 @@
C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
if(regen_cooldown < world.time)
C.heal_overall_damage(4,4)
+ C.adjustToxLoss(-4)
if(prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
if(C.InCritical())
@@ -64,6 +65,6 @@
limbs_id = "zombie" //They look like zombies
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
- mutant_organs = list(/obj/item/organ/tongue/zombie)
+ mutanttongue = /obj/item/organ/tongue/zombie
#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e1d854c0c8..f4e85e40fb 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -884,7 +884,7 @@
on_fire = 1
src.visible_message("[src] catches fire!", \
"You're set on fire!")
- src.set_light(3)
+ new/obj/effect/dummy/fire(src)
throw_alert("fire", /obj/screen/alert/fire)
update_fire()
return TRUE
@@ -894,7 +894,8 @@
if(on_fire)
on_fire = 0
fire_stacks = 0
- src.set_light(0)
+ for(var/obj/effect/dummy/fire/F in src)
+ qdel(F)
clear_alert("fire")
update_fire()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
index 259ca4327d..325b971171 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
@@ -86,7 +86,7 @@
if(istype(head, /obj/item/clothing/mask))
used_head_icon = 'icons/mob/mask.dmi'
var/mutable_appearance/head_overlay = head.build_worn_icon(state = head.icon_state, default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon)
- head_overlay.pixel_y += -15
+ head_overlay.pixel_y -= 15
drone_overlays[DRONE_HEAD_LAYER] = head_overlay
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 144f7081e0..592679d35b 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -180,10 +180,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
new /obj/effect/temp_visual/guardian/phase(loc)
/mob/living/simple_animal/hostile/guardian/canSuicide()
- return 0
+ return FALSE
+
+/mob/living/simple_animal/hostile/guardian/proc/is_deployed()
+ return loc != summoner
/mob/living/simple_animal/hostile/guardian/AttackingTarget()
- if(loc == summoner)
+ if(!is_deployed())
to_chat(src, "You must be manifested to attack!")
return FALSE
else
diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm
index db1581d8cb..a8a31ad89c 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/support.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm
@@ -28,7 +28,7 @@
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
. = ..()
- if(. && toggle && iscarbon(target))
+ if(is_deployed() && toggle && iscarbon(target))
var/mob/living/carbon/C = target
C.adjustBruteLoss(-5)
C.adjustFireLoss(-5)
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index f2d29d3660..9f7a7d1bbf 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -105,22 +105,22 @@
/mob/living/simple_animal/hostile/poison/bees/CanAttack(atom/the_target)
. = ..()
if(!.)
- return 0
+ return FALSE
if(isliving(the_target))
var/mob/living/H = the_target
return !H.bee_friendly()
/mob/living/simple_animal/hostile/poison/bees/Found(atom/A)
+ if(isliving(A))
+ var/mob/living/H = A
+ return !H.bee_friendly()
if(istype(A, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = A
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
- return 1
- if(isliving(A))
- var/mob/living/H = A
- return !H.bee_friendly()
- return 0
+ return TRUE
+ return FALSE
/mob/living/simple_animal/hostile/poison/bees/AttackingTarget()
@@ -187,7 +187,7 @@
if(loc == beehome)
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
- forceMove(get_turf(beehome))
+ forceMove(beehome.drop_location())
else
idle = max(0, --idle)
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
@@ -200,6 +200,7 @@
continue
BB.bees |= src
beehome = BB
+ break // End loop after the first compatible find.
/mob/living/simple_animal/hostile/poison/bees/toxin/Initialize()
. = ..()
@@ -215,7 +216,7 @@
//the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
/mob/living/simple_animal/hostile/poison/bees/queen/Found(atom/A)
- return 0
+ return FALSE
//leave pollination for the peasent bees
@@ -234,10 +235,10 @@
/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
if(!B)
- return 0
+ return FALSE
if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
- return 1
- return 0
+ return TRUE
+ return FALSE
/obj/item/queen_bee
@@ -255,7 +256,7 @@
if(S.reagents.has_reagent("royal_bee_jelly")) //checked twice, because I really don't want royal bee jelly to be duped
if(S.reagents.has_reagent("royal_bee_jelly",5))
S.reagents.remove_reagent("royal_bee_jelly", 5)
- var/obj/item/queen_bee/qb = new(get_turf(user))
+ var/obj/item/queen_bee/qb = new(user.drop_location())
qb.queen = new(qb)
if(queen && queen.beegent)
qb.queen.assign_reagent(queen.beegent) //Bees use the global singleton instances of reagents, so we don't need to worry about one bee being deleted and her copies losing their reagents.
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 2b29283c28..d4c9632a03 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -115,7 +115,11 @@
if(can_see(targets_from, HM, vision_range))
. += HM
else
- . = oview(vision_range, targets_from)
+ . = list() // The following code is only very slightly slower than just returning oview(vision_range, targets_from), but it saves us much more work down the line, particularly when bees are involved
+ for (var/obj/A in oview(vision_range, targets_from))
+ . += A
+ for (var/mob/A in oview(vision_range, targets_from))
+ . += A
/mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about
. = list()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
index dda0b3abad..04282d12fd 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
@@ -62,6 +62,9 @@
return TRUE
+ if(isobj(the_target) && is_type_in_typecache(the_target, wanted_objects))
+ return TRUE
+
return FALSE
/mob/living/simple_animal/hostile/asteroid/gutlunch/Destroy()
diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm
index 62b8cee415..8eaaa40097 100644
--- a/code/modules/ninja/suit/gloves.dm
+++ b/code/modules/ninja/suit/gloves.dm
@@ -63,7 +63,7 @@
if(isnum(.)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking)
if(.)
- to_chat(H, "Gained [.] energy from \the [A].")
+ to_chat(H, "Gained [DisplayPower(.)] of energy from [A].")
else
to_chat(H, "\The [A] has run dry of power, you must find another source!")
else
diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm
index 4519835c1f..f04c61426b 100644
--- a/code/modules/power/singularity/particle_accelerator/particle.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle.dm
@@ -1,62 +1,65 @@
-/obj/effect/accelerated_particle
- name = "Accelerated Particles"
- desc = "Small things moving very fast."
- icon = 'icons/obj/machines/particle_accelerator.dmi'
- icon_state = "particle"
+/obj/effect/accelerated_particle
+ name = "Accelerated Particles"
+ desc = "Small things moving very fast."
+ icon = 'icons/obj/machines/particle_accelerator.dmi'
+ icon_state = "particle"
anchored = TRUE
density = FALSE
- var/movement_range = 10
- var/energy = 10
- var/speed = 1
-
-/obj/effect/accelerated_particle/weak
- movement_range = 8
- energy = 5
-
-/obj/effect/accelerated_particle/strong
- movement_range = 15
- energy = 15
-
-/obj/effect/accelerated_particle/powerful
- movement_range = 20
- energy = 50
-
-
-/obj/effect/accelerated_particle/New(loc)
- ..()
-
- addtimer(CALLBACK(src, .proc/move), 1)
-
-
+ var/movement_range = 10
+ var/energy = 10
+ var/speed = 1
+
+/obj/effect/accelerated_particle/weak
+ movement_range = 8
+ energy = 5
+
+/obj/effect/accelerated_particle/strong
+ movement_range = 15
+ energy = 15
+
+/obj/effect/accelerated_particle/powerful
+ movement_range = 20
+ energy = 50
+
+
+/obj/effect/accelerated_particle/New(loc)
+ ..()
+
+ addtimer(CALLBACK(src, .proc/move), 1)
+
+
/obj/effect/accelerated_particle/Collide(atom/A)
- if(A)
- if(isliving(A))
- toxmob(A)
- else if(istype(A, /obj/machinery/the_singularitygen))
- var/obj/machinery/the_singularitygen/S = A
- S.energy += energy
- else if(istype(A, /obj/singularity))
- var/obj/singularity/S = A
- S.energy += energy
-
-
-/obj/effect/accelerated_particle/Crossed(atom/A)
- if(isliving(A))
- toxmob(A)
-
-
-/obj/effect/accelerated_particle/ex_act(severity, target)
- qdel(src)
-
-/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
- M.rad_act(energy*6)
-
-/obj/effect/accelerated_particle/proc/move()
- if(!step(src,dir))
- forceMove(get_step(src,dir))
- movement_range--
- if(movement_range == 0)
- qdel(src)
- else
- sleep(speed)
- move()
+ if(A)
+ if(isliving(A))
+ toxmob(A)
+ else if(istype(A, /obj/machinery/the_singularitygen))
+ var/obj/machinery/the_singularitygen/S = A
+ S.energy += energy
+ else if(istype(A, /obj/singularity))
+ var/obj/singularity/S = A
+ S.energy += energy
+ else if(istype(A, /obj/structure/blob))
+ var/obj/structure/blob/B = A
+ B.take_damage(energy*0.6)
+ movement_range = 0
+
+/obj/effect/accelerated_particle/Crossed(atom/A)
+ if(isliving(A))
+ toxmob(A)
+
+
+/obj/effect/accelerated_particle/ex_act(severity, target)
+ qdel(src)
+
+/obj/effect/accelerated_particle/proc/toxmob(mob/living/M)
+ M.rad_act(energy*6)
+
+/obj/effect/accelerated_particle/proc/move()
+ if(!step(src,dir))
+ forceMove(get_step(src,dir))
+ movement_range--
+ if(movement_range == 0)
+ qdel(src)
+ else
+ sleep(speed)
+ move()
diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm
index 603f8843ca..5ee2ecec05 100644
--- a/code/modules/projectiles/guns/misc/blastcannon.dm
+++ b/code/modules/projectiles/guns/misc/blastcannon.dm
@@ -12,21 +12,17 @@
randomspread = FALSE
var/obj/item/device/transfer_valve/bomb
- var/datum/gas_mixture/air1
- var/datum/gas_mixture/air2
/obj/item/gun/blastcannon/New()
if(!pin)
pin = new
- . = ..()
+ return ..()
/obj/item/gun/blastcannon/Destroy()
if(bomb)
qdel(bomb)
bomb = null
- air1 = null
- air2 = null
- . = ..()
+ return ..()
/obj/item/gun/blastcannon/attack_self(mob/user)
if(bomb)
@@ -35,7 +31,7 @@
user.visible_message("[user] detaches the [bomb] from the [src]")
bomb = null
update_icon()
- . = ..(user)
+ return ..()
/obj/item/gun/blastcannon/update_icon()
if(bomb)
@@ -46,7 +42,6 @@
icon_state = initial(icon_state)
name = initial(name)
desc = initial(desc)
- . = ..()
/obj/item/gun/blastcannon/attackby(obj/O, mob/user)
if(istype(O, /obj/item/device/transfer_valve))
@@ -59,20 +54,17 @@
return FALSE
user.visible_message("[user] attaches the [O] to the [src]!")
bomb = O
- O.loc = src
+ O.forceMove(src)
update_icon()
return TRUE
- . = ..()
+ return ..()
/obj/item/gun/blastcannon/proc/calculate_bomb()
if(!istype(bomb)||!istype(bomb.tank_one)||!istype(bomb.tank_two))
return 0
- air1 = bomb.tank_one.air_contents
- air2 = bomb.tank_two.air_contents
- var/datum/gas_mixture/temp
- temp.volume = air1.volume + air2.volume
- temp.merge(air1)
- temp.merge(air2)
+ var/datum/gas_mixture/temp = new(60) //directional buff.
+ temp.merge(bomb.tank_one.air_contents.remove_ratio(1))
+ temp.merge(bomb.tank_two.air_contents.remove_ratio(2))
for(var/i in 1 to 6)
temp.react()
var/pressure = temp.return_pressure()
@@ -82,7 +74,7 @@
return (pressure/TANK_FRAGMENT_SCALE)
/obj/item/gun/blastcannon/afterattack(atom/target, mob/user, flag, params)
- if((!bomb) || (target == user) || (target.loc == user) || (!target) || (target.loc == user.loc) || (target.loc in range(user, 2)) || (target in range(user, 2)))
+ if((!bomb) || (!target) || (get_dist(get_turf(target), get_turf(user)) <= 2))
return ..()
var/power = calculate_bomb()
qdel(bomb)
@@ -90,13 +82,17 @@
var/heavy = power * 0.2
var/medium = power * 0.5
var/light = power
- user.visible_message("[user] opens \the [bomb] on \his [src.name] and fires a blast wave at \the [target]!","You open \the [bomb] on your [src.name] and fire a blast wave at \the [target]!")
+ user.visible_message("[user] opens \the [bomb] on \his [name] and fires a blast wave at \the [target]!","You open \the [bomb] on your [name] and fire a blast wave at \the [target]!")
playsound(user, "explosion", 100, 1)
var/turf/starting = get_turf(user)
+ var/turf/targturf = get_turf(target)
var/area/A = get_area(user)
- var/log_str = "Blast wave fired at [ADMIN_COORDJMP(starting)] ([A.name]) by [user.name]([user.ckey]) with power [heavy]/[medium]/[light]."
+ var/log_str = "Blast wave fired from [ADMIN_COORDJMP(starting)] ([A.name]) at [ADMIN_COORDJMP(targturf)] ([target.name]) by [user.name]([user.ckey]) with power [heavy]/[medium]/[light]."
message_admins(log_str)
log_game(log_str)
+ var/obj/item/projectile/blastwave/BW = new(loc, heavy, medium, light)
+ BW.preparePixelProjectile(target, get_turf(target), user, params, 0)
+ BW.fire()
/obj/item/projectile/blastwave
name = "blast wave"
@@ -109,6 +105,12 @@
var/lightr = 0
range = 150
+/obj/item/projectile/blastwave/Initialize(mapload, _h, _m, _l)
+ heavyr = _h
+ mediumr = _m
+ lightr = _l
+ return ..()
+
/obj/item/projectile/blastwave/Range()
..()
if(heavyr)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 3aba80fe64..937326a60b 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -90,8 +90,6 @@
new impact_effect_type(target_loca, target, src)
return 0
var/mob/living/L = target
- if(L.buckled && ismob(L.buckled))
- L = L.buckled
if(blocked != 100) // not completely blocked
if(damage && L.blood_volume && damage_type == BRUTE)
var/splatter_dir = dir
@@ -178,6 +176,8 @@
var/mob/living/picked_mob = pick(mobs_list)
if(!prehit(picked_mob))
return FALSE
+ if(ismob(picked_mob.buckled))
+ picked_mob = picked_mob.buckled
picked_mob.bullet_act(src, def_zone)
qdel(src)
return TRUE
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 6f4ae50243..8395ef4d83 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -10,7 +10,7 @@
/obj/item/projectile/bullet/pellet/Range()
..()
- damage += -0.75
+ damage -= 0.75
if(damage < 0)
qdel(src)
@@ -66,7 +66,7 @@
/obj/item/projectile/bullet/c38
name = ".38 bullet"
damage = 15
- knockdown = 30
+ knockdown = 60
stamina = 50
// 10mm (Stechkin)
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index 5d089739d1..946ec70d38 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -608,6 +608,14 @@
build_path = /obj/item/device/electropack
category = list("hacked", "Tools")
+/datum/design/shock_collar
+ name = "Shock Collar"
+ id = "shock_collar"
+ build_type = AUTOLATHE
+ materials = list(MAT_METAL = 5000, MAT_GLASS = 2000)
+ build_path = /obj/item/device/electropack/shockcollar
+ category = list("hacked", "Security")
+
/datum/design/large_welding_tool
name = "Industrial Welding Tool"
id = "large_welding_tool"
diff --git a/code/modules/server_tools/st_interface.dm b/code/modules/server_tools/st_interface.dm
index 12fb5a85c2..10b7f920e8 100644
--- a/code/modules/server_tools/st_interface.dm
+++ b/code/modules/server_tools/st_interface.dm
@@ -89,6 +89,8 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
return "No message set!"
SERVER_TOOLS_WORLD_ANNOUNCE(msg)
return "SUCCESS"
+ if(SERVICE_CMD_PLAYER_COUNT)
+ return "[SERVER_TOOLS_CLIENT_COUNT]"
if(SERVICE_CMD_LIST_CUSTOM)
return json_encode(ListServiceCustomCommands(FALSE))
else
diff --git a/code/modules/spells/spell_types/shadow_walk.dm b/code/modules/spells/spell_types/shadow_walk.dm
index 45ea521098..9f9b4ac223 100644
--- a/code/modules/spells/spell_types/shadow_walk.dm
+++ b/code/modules/spells/spell_types/shadow_walk.dm
@@ -25,8 +25,9 @@
if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD)
playsound(get_turf(user), 'sound/magic/ethereal_enter.ogg', 50, 1, -1)
visible_message("[user] melts into the shadows!")
- user.AdjustStun(-20, 0)
- user.AdjustKnockdown(-20, 0)
+ user.SetStun(0, FALSE)
+ user.SetKnockdown(0, FALSE)
+ user.setStaminaLoss(0, 0)
var/obj/effect/dummy/shadow/S2 = new(get_turf(user.loc))
user.forceMove(S2)
S2.jaunter = user
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 4b939bf4f1..3b83dd8e62 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -44,9 +44,11 @@
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
actions_types = list(/datum/action/item_action/organ_action/use)
+ sight_flags = SEE_BLACKNESS
var/night_vision = TRUE
/obj/item/organ/eyes/night_vision/ui_action_click()
+ sight_flags = initial(sight_flags)
switch(lighting_alpha)
if (LIGHTING_PLANE_ALPHA_VISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
@@ -56,6 +58,7 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
else
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
+ sight_flags &= ~SEE_BLACKNESS
owner.update_sight()
/obj/item/organ/eyes/night_vision/alien
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index f5a00d24cb..4fdda7a7bc 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -10,6 +10,8 @@
var/slot
// DO NOT add slots with matching names to different zones - it will break internal_organs_slot list!
var/vital = 0
+ //Was this organ implanted/inserted/etc, if true will not be removed during species change.
+ var/external = FALSE
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
diff --git a/config/config.txt b/config/config.txt
index d5d2725714..72f168dcce 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -1,3 +1,11 @@
+# You can use the @ character at the beginning of a config option to lock it from being edited in-game
+# Example usage:
+# @SERVERNAME tgstation
+# Which sets the SERVERNAME, and disallows admins from being able to change it using View Variables.
+# @LOG_TWITTER 0
+# Which explicitly disables LOG_TWITTER, as well as locking it.
+# There are various options which are hard-locked for security reasons.
+
## Server name: This appears at the top of the screen in-game and in the BYOND hub. Uncomment and replace 'tgstation' with the name of your choice.
# SERVERNAME tgstation
diff --git a/html/changelogs/AutoChangeLog-pr-3041.yml b/html/changelogs/AutoChangeLog-pr-3041.yml
new file mode 100644
index 0000000000..872bbc4b99
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3041.yml
@@ -0,0 +1,5 @@
+author: "Robustin"
+delete-after: True
+changes:
+ - rscadd: "Blood cultists can now create a unique bastard sword at their forge"
+ - rscdel: "Blood cultists can no longer obtain a hardsuit from the forge"
diff --git a/html/changelogs/AutoChangeLog-pr-3093.yml b/html/changelogs/AutoChangeLog-pr-3093.yml
new file mode 100644
index 0000000000..bc2a009a41
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3093.yml
@@ -0,0 +1,6 @@
+author: "Shock Collars"
+delete-after: True
+changes:
+ - rscadd: "Added Shock Collars to hacked autolathes."
+ - imageadd: "On character sprites, credit to Toriate"
+ - imageadd: "Object sprite, credit to Toriate"
diff --git a/html/changelogs/AutoChangeLog-pr-3096.yml b/html/changelogs/AutoChangeLog-pr-3096.yml
new file mode 100644
index 0000000000..4031580453
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3096.yml
@@ -0,0 +1,4 @@
+author: "Kor"
+delete-after: True
+changes:
+ - bugfix: "You can now tell when someone is in soft crit by examining them."
diff --git a/html/changelogs/AutoChangeLog-pr-3102.yml b/html/changelogs/AutoChangeLog-pr-3102.yml
new file mode 100644
index 0000000000..bc737b6a13
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3102.yml
@@ -0,0 +1,4 @@
+author: "Naksu"
+delete-after: True
+changes:
+ - bugfix: "Bees now come with reduced amounts of free lag"
diff --git a/html/changelogs/AutoChangeLog-pr-3104.yml b/html/changelogs/AutoChangeLog-pr-3104.yml
new file mode 100644
index 0000000000..e6f9d22374
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3104.yml
@@ -0,0 +1,4 @@
+author: "More Robust Than You"
+delete-after: True
+changes:
+ - balance: "Blobs now take damage from particle accelerators"
diff --git a/html/changelogs/AutoChangeLog-pr-3105.yml b/html/changelogs/AutoChangeLog-pr-3105.yml
new file mode 100644
index 0000000000..b48644c148
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3105.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - balance: "The detectives gun has been restored from a system change that nerfed knockdown in general. We need to have a serious discussion about anti revolver hate in this community."
diff --git a/html/changelogs/AutoChangeLog-pr-3108.yml b/html/changelogs/AutoChangeLog-pr-3108.yml
new file mode 100644
index 0000000000..f1e03db19a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3108.yml
@@ -0,0 +1,4 @@
+author: "XDTM"
+delete-after: True
+changes:
+ - rscadd: "The CMO now has an advanced health analyzer in his closet! It can give more precise readings on the non-standard damage types."
diff --git a/html/changelogs/AutoChangeLog-pr-3110.yml b/html/changelogs/AutoChangeLog-pr-3110.yml
new file mode 100644
index 0000000000..7d06447f99
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3110.yml
@@ -0,0 +1,4 @@
+author: "Kor"
+delete-after: True
+changes:
+ - rscadd: "Nightmares now have mutant hearts and brains, with their own special properties when consumed or implanted in mobs. Experiment!"
diff --git a/html/changelogs/AutoChangeLog-pr-3114.yml b/html/changelogs/AutoChangeLog-pr-3114.yml
new file mode 100644
index 0000000000..abe6380887
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3114.yml
@@ -0,0 +1,4 @@
+author: "Daniel0Mclovin"
+delete-after: True
+changes:
+ - tweak: "Modify health regeneration from 0.05 to 0.75"
diff --git a/html/changelogs/AutoChangeLog-pr-3115.yml b/html/changelogs/AutoChangeLog-pr-3115.yml
new file mode 100644
index 0000000000..c3a194f971
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3115.yml
@@ -0,0 +1,4 @@
+author: "Naksu"
+delete-after: True
+changes:
+ - bugfix: "Gutlunches will now once again look for gibs to eat."
diff --git a/html/changelogs/AutoChangeLog-pr-3127.yml b/html/changelogs/AutoChangeLog-pr-3127.yml
new file mode 100644
index 0000000000..050e9cb4d7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3127.yml
@@ -0,0 +1,4 @@
+author: "Raeschen"
+delete-after: True
+changes:
+ - rscadd: "FTL Milky Way added to music"
diff --git a/html/changelogs/AutoChangeLog-pr-3133.yml b/html/changelogs/AutoChangeLog-pr-3133.yml
new file mode 100644
index 0000000000..ac49ae1821
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3133.yml
@@ -0,0 +1,4 @@
+author: "CitadelStationBot"
+delete-after: True
+changes:
+ - spellcheck: "Beds, chairs, closets, grilles, lattices, catwalks, tables, racks, floors, plating and bookcases now show hints about constructing/deconstructing them."
diff --git a/html/changelogs/AutoChangeLog-pr-3134.yml b/html/changelogs/AutoChangeLog-pr-3134.yml
new file mode 100644
index 0000000000..5b8bcf21b6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3134.yml
@@ -0,0 +1,4 @@
+author: "ShizCalev"
+delete-after: True
+changes:
+ - bugfix: "You now have to unbuckle a player PRIOR to shaking them up off a bed or resin nest."
diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi
index a9a952733a..1b450ab3e0 100644
Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index bff96a991b..bbeddf9152 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/neck.dmi b/icons/mob/neck.dmi
index fb43ae85ec..17f9d3ade4 100644
Binary files a/icons/mob/neck.dmi and b/icons/mob/neck.dmi differ
diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi
index 21ab5cf9f5..64a877c2a1 100644
Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ
diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi
index 40c4aa03bc..c41db68326 100644
Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 79f0a207d4..71ce7d6df5 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 94c0c03835..b5ac65c2a8 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index ae61dc2852..cb5499487d 100644
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/interface/interface.dm b/interface/interface.dm
index 9d420e9821..a67cc5d290 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -65,7 +65,9 @@
message += GLOB.revdata.GetTestMergeInfo(FALSE)
if(tgalert(src, message, "Report Issue","Yes","No")=="No")
return
- src << link("[githuburl]/issues/new")
+ var/static/issue_template = file2text(".github/ISSUE_TEMPLATE.md")
+ var/servername = CONFIG_GET(string/servername)
+ src << link("[githuburl]/issues/new[GLOB.round_id ? "?body=[url_encode("Issue reported from Round ID: [GLOB.round_id][servername ? " ([servername])" : ""]\n\n[issue_template]")]" : ""]")
else
to_chat(src, "The Github URL is not set in the server configuration.")
return
diff --git a/sound/music/milkyway.ogg b/sound/music/milkyway.ogg
new file mode 100644
index 0000000000..59d9ba63f4
Binary files /dev/null and b/sound/music/milkyway.ogg differ
diff --git a/sound/weapons/fwoosh.wav b/sound/weapons/fwoosh.wav
new file mode 100644
index 0000000000..1723c4e9b8
Binary files /dev/null and b/sound/weapons/fwoosh.wav differ
diff --git a/sound/weapons/parry.ogg b/sound/weapons/parry.ogg
new file mode 100644
index 0000000000..1f86716337
Binary files /dev/null and b/sound/weapons/parry.ogg differ
diff --git a/strings/names/nightmare.txt b/strings/names/nightmare.txt
new file mode 100644
index 0000000000..b8798b734d
--- /dev/null
+++ b/strings/names/nightmare.txt
@@ -0,0 +1,10 @@
+U'ruan
+Y`shej
+Nex
+Hel-uae
+Noaey'gief
+Mii`mahza
+Amerziox
+Gyrg-mylin
+Kanet'pruunance
+Vigistaezian
\ No newline at end of file
diff --git a/strings/round_start_sounds.txt b/strings/round_start_sounds.txt
index 01323a6120..177f612ee1 100644
--- a/strings/round_start_sounds.txt
+++ b/strings/round_start_sounds.txt
@@ -20,3 +20,4 @@ sound/music/oceanman.ogg
sound/music/indeep.ogg
sound/music/goodbyemoonmen.ogg
sound/music/flytothemoon_otomatone.ogg
+sound/music/milkyway.ogg
\ No newline at end of file