diff --git a/.vscode/settings.json b/.vscode/settings.json
index bfce9bda7c..8edb013566 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -13,7 +13,7 @@
"source.fixAll.eslint": true
},
"workbench.editorAssociations": {
- "*.dmi": "imagePreview.previewEditor"
+ "*.dmi": "dmiEditor.dmiEditor"
},
"files.eol": "\n",
"gitlens.advanced.blame.customArguments": ["-w"],
diff --git a/_maps/RandomZLevels/away_mission/SnowCabin.dmm b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
index e7f5341bea..7de2ed53f1 100644
--- a/_maps/RandomZLevels/away_mission/SnowCabin.dmm
+++ b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
@@ -99,7 +99,9 @@
/obj/machinery/door/airlock/command{
name = "Manager's Office"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"as" = (
@@ -134,7 +136,9 @@
/area/awaymission/cabin)
"aw" = (
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"ax" = (
@@ -185,17 +189,18 @@
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
"aD" = (
-/obj/machinery/power/smes/magical{
- desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. It seems to be powered just fine without our intervention.";
- name = "nanotrasen power storage unit"
- },
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
+/obj/machinery/power/smes/magical,
/turf/open/floor/plating,
/area/awaymission/cabin)
"aE" = (
/obj/effect/decal/cleanable/cobweb/cobweb2,
/obj/effect/baseturf_helper/asteroid/snow,
/obj/effect/decal/cleanable/dirt,
+/obj/machinery/power/port_gen/pacman,
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -207,7 +212,12 @@
pixel_y = 23
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"aG" = (
@@ -255,7 +265,9 @@
dir = 1
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -281,15 +293,6 @@
/turf/open/floor/carpet,
/area/awaymission/cabin)
"aQ" = (
-/obj/structure{
- anchored = 1;
- density = 1;
- desc = "Generates power from lava!";
- dir = 1;
- icon = 'icons/obj/atmospherics/pipes/simple.dmi';
- icon_state = "compressor";
- name = "geothermal generator"
- },
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating{
icon_state = "panelscorched"
@@ -366,7 +369,9 @@
/turf/open/floor/wood,
/area/awaymission/cabin)
"bb" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/carpet,
/area/awaymission/cabin)
"bc" = (
@@ -431,7 +436,9 @@
id_tag = "snowdorm5";
name = "Cabin 5"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"bn" = (
@@ -463,7 +470,9 @@
/obj/machinery/newscaster{
pixel_y = 32
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"bt" = (
@@ -492,7 +501,9 @@
"by" = (
/obj/structure/table,
/obj/machinery/reagentgrinder,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/plasteel/cafeteria,
/area/awaymission/cabin)
"bz" = (
@@ -611,7 +622,9 @@
/obj/machinery/door/airlock/maintenance{
name = "Garage"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"bW" = (
@@ -739,7 +752,9 @@
/obj/structure/sign/poster/official/soft_cap_pop_art{
pixel_y = 32
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"cu" = (
@@ -838,14 +853,18 @@
dir = 8
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"cM" = (
/obj/machinery/door/airlock/wood{
name = "Gateway"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"cN" = (
@@ -859,12 +878,16 @@
/turf/open/floor/carpet,
/area/awaymission/cabin)
"cP" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/plasteel/white,
/area/awaymission/cabin)
"cQ" = (
/obj/effect/landmark/awaystart,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/carpet,
/area/awaymission/cabin)
"cR" = (
@@ -898,7 +921,9 @@
/area/awaymission/cabin)
"cW" = (
/obj/item/shovel,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating{
icon_state = "platingdmg3"
},
@@ -957,7 +982,9 @@
/obj/structure/chair/wood{
dir = 4
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/carpet,
/area/awaymission/cabin)
"df" = (
@@ -1040,20 +1067,19 @@
/area/awaymission/cabin)
"du" = (
/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
/turf/open/floor/plating{
icon_state = "panelscorched"
},
/area/awaymission/cabin)
"dv" = (
-/obj/structure{
- anchored = 1;
- density = 1;
- desc = "Generates power from lava!";
- icon = 'icons/obj/atmospherics/pipes/simple.dmi';
- icon_state = "turbine";
- name = "geothermal generator"
- },
/obj/effect/decal/cleanable/dirt,
+/obj/machinery/power/rtg,
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -1269,7 +1295,9 @@
/turf/open/floor/wood/cold,
/area/awaymission/cabin/snowforest)
"eg" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"eh" = (
@@ -1279,7 +1307,9 @@
"ei" = (
/obj/effect/decal/cleanable/dirt/dust,
/obj/effect/decal/cleanable/glass,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"ej" = (
@@ -1350,7 +1380,9 @@
/area/awaymission/cabin/snowforest)
"et" = (
/obj/effect/decal/cleanable/dirt/dust,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"eu" = (
@@ -2724,11 +2756,15 @@
/obj/structure/sign/poster/official/fruit_bowl{
pixel_y = 32
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"hi" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
"hj" = (
@@ -2736,7 +2772,9 @@
dir = 8
},
/obj/effect/decal/cleanable/dirt/dust,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"hk" = (
@@ -2781,7 +2819,9 @@
/obj/effect/decal/cleanable/dirt/dust,
/obj/effect/decal/cleanable/oil,
/obj/effect/decal/cleanable/generic,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"hs" = (
@@ -2789,14 +2829,18 @@
/obj/structure/sign/poster/contraband/missing_gloves{
pixel_x = 32
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"ht" = (
/obj/structure/window{
dir = 4
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"hu" = (
@@ -2816,6 +2860,9 @@
pixel_y = 4
},
/obj/effect/decal/cleanable/dirt,
+/obj/item/stack/sheet/mineral/plasma{
+ amount = 26
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"hw" = (
@@ -2841,28 +2888,36 @@
/turf/open/floor/plating,
/area/awaymission/cabin)
"hz" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plasteel/cafeteria,
/area/awaymission/cabin)
"hA" = (
/obj/machinery/door/airlock/freezer{
name = "Freezer"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plasteel/freezer,
/area/awaymission/cabin)
"hB" = (
/obj/machinery/door/airlock{
name = "Backstage"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"hC" = (
/obj/structure/chair/wood{
dir = 8
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
/turf/open/floor/carpet,
/area/awaymission/cabin)
"hD" = (
@@ -2874,7 +2929,9 @@
/obj/machinery/door/airlock{
name = "Kitchen"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"hF" = (
@@ -2889,7 +2946,9 @@
/obj/structure/chair/wood{
dir = 1
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"hH" = (
@@ -3124,7 +3183,9 @@
/obj/structure/extinguisher_cabinet{
pixel_y = 32
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"io" = (
@@ -3321,7 +3382,9 @@
id_tag = "snowdorm1";
name = "Cabin 1"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"iW" = (
@@ -3329,7 +3392,9 @@
id_tag = "snowdorm2";
name = "Cabin 2"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"iX" = (
@@ -3337,7 +3402,9 @@
id_tag = "snowdorm3";
name = "Cabin 3"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"iY" = (
@@ -3345,7 +3412,9 @@
id_tag = "snowdorm4";
name = "Cabin 4"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/awaymission/cabin)
"iZ" = (
@@ -3518,7 +3587,9 @@
},
/obj/item/reagent_containers/glass/bottle/cryoxadone,
/obj/item/reagent_containers/glass/bottle/cryoxadone,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plasteel/white,
/area/awaymission/cabin)
"jr" = (
@@ -3649,7 +3720,9 @@
name = "Generator Room"
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"jD" = (
@@ -5450,7 +5523,9 @@
/turf/open/floor/wood,
/area/awaymission/cabin)
"nR" = (
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"nS" = (
@@ -5477,13 +5552,152 @@
/obj/machinery/door/airlock/maintenance{
name = "Maintenance"
},
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
+"nY" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/awaymission/cabin)
+"rn" = (
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/awaymission/cabin)
+"rV" = (
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"sn" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating,
+/area/awaymission/cabin)
+"uk" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/awaymission/cabin)
+"uD" = (
+/obj/structure/chair/wood{
+ dir = 4
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
+"ww" = (
+/obj/effect/landmark/awaystart,
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
+"wx" = (
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/awaymission/cabin)
+"zF" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"BB" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/plating,
+/area/awaymission/cabin)
+"Co" = (
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plasteel/cafeteria,
+/area/awaymission/cabin)
+"DU" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/plating,
+/area/awaymission/cabin)
+"Fj" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"FH" = (
+/obj/structure/cable{
+ icon_state = "0-4"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"Hb" = (
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
+"He" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"IG" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/white,
+/area/awaymission/cabin)
+"JZ" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
+"KS" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
+"MB" = (
+/obj/structure/chair/wood{
+ dir = 8
+ },
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/carpet,
+/area/awaymission/cabin)
"MS" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/oil,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating,
/area/awaymission/cabin)
"TZ" = (
@@ -5495,6 +5709,37 @@
/obj/item/clothing/shoes/winterboots/ice_boots,
/turf/open/floor/plating/ice/smooth,
/area/awaymission/cabin/caves)
+"UL" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plasteel/freezer,
+/area/awaymission/cabin)
+"WD" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
+"WX" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
+/turf/open/floor/plating,
+/area/awaymission/cabin)
+"WY" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/wood,
+/area/awaymission/cabin)
(1,1,1) = {"
ab
@@ -25696,21 +25941,21 @@ iZ
aN
jl
bb
-bb
-bb
+JZ
+JZ
eg
bm
-eg
+Fj
nS
an
-eg
+rV
eg
eg
eg
eg
eg
hB
-eg
+Fj
aq
an
cT
@@ -25957,7 +26202,7 @@ az
az
aq
an
-eg
+He
bh
an
cA
@@ -25967,7 +26212,7 @@ an
an
hx
an
-eg
+He
aq
an
cU
@@ -26214,7 +26459,7 @@ az
az
aq
an
-eg
+He
aq
an
aq
@@ -26224,7 +26469,7 @@ aq
aq
aq
an
-eg
+He
aq
an
cV
@@ -26481,11 +26726,11 @@ aq
aq
bh
an
-eg
+He
bh
an
aL
-nR
+BB
aL
ed
an
@@ -26728,17 +26973,17 @@ an
an
aR
an
-eg
+He
aq
an
aq
aq
-eg
+FH
aq
aq
aq
an
-eg
+He
aq
an
cU
@@ -26985,21 +27230,21 @@ aH
an
an
an
-eg
+He
aq
an
cz
aq
-eg
+He
aq
aq
bh
an
-eg
+He
aq
an
ed
-nR
+BB
aL
kE
an
@@ -27242,7 +27487,7 @@ an
an
aS
hg
-eg
+He
bh
an
nT
@@ -27252,11 +27497,11 @@ bo
bo
cB
an
-eg
+WD
eg
bV
-aw
-aw
+sn
+DU
gM
an
an
@@ -27499,17 +27744,17 @@ aH
an
an
an
-eg
+He
aq
an
aO
aO
hC
-hC
-hC
-bb
-bb
-eg
+MB
+MB
+JZ
+JZ
+WY
aq
an
eb
@@ -27756,7 +28001,7 @@ an
an
aT
an
-eg
+He
aq
an
az
@@ -27766,7 +28011,7 @@ az
aq
aq
cO
-eg
+He
bh
an
an
@@ -28270,7 +28515,7 @@ az
az
aq
an
-eg
+He
aq
an
aP
@@ -28280,7 +28525,7 @@ nB
hd
az
aO
-eg
+He
aq
aq
an
@@ -28527,7 +28772,7 @@ az
az
aq
an
-eg
+He
bh
an
bq
@@ -28537,7 +28782,7 @@ hc
hd
az
az
-eg
+He
aq
aq
aN
@@ -28780,11 +29025,11 @@ ja
bp
jm
bb
-bb
-bb
+JZ
+JZ
eg
iY
-eg
+WY
aq
an
bt
@@ -28794,7 +29039,7 @@ jx
hd
az
cO
-eg
+He
aq
aq
iR
@@ -29041,7 +29286,7 @@ aI
aA
jj
an
-eg
+He
aq
an
cN
@@ -29308,7 +29553,7 @@ az
aq
aq
aO
-eg
+He
aq
aq
an
@@ -29555,17 +29800,17 @@ ju
au
ji
an
-eg
+He
aq
an
de
-de
-de
-de
-de
-bb
-bb
-eg
+uD
+uD
+uD
+uD
+JZ
+JZ
+WY
bh
an
an
@@ -29808,11 +30053,11 @@ jb
aN
jn
bb
-bb
-bb
+JZ
+JZ
eg
iX
-eg
+WY
bh
an
hb
@@ -29822,7 +30067,7 @@ eu
cK
cD
an
-eg
+He
aq
aq
an
@@ -30069,7 +30314,7 @@ az
az
aq
an
-eg
+He
aq
an
hn
@@ -30079,7 +30324,7 @@ aq
aq
aq
an
-eg
+He
aq
aq
aN
@@ -30326,7 +30571,7 @@ az
az
aq
an
-eg
+He
aq
an
bv
@@ -30336,7 +30581,7 @@ aq
ap
aq
an
-eg
+He
aq
aq
iU
@@ -30593,7 +30838,7 @@ bu
an
eo
an
-eg
+He
aq
aq
bp
@@ -30840,7 +31085,7 @@ an
an
aU
an
-eg
+He
aq
an
bw
@@ -30848,9 +31093,9 @@ bO
bO
bO
bO
-hz
+Co
hE
-eg
+WY
aq
aq
an
@@ -31097,7 +31342,7 @@ aH
an
an
an
-eg
+He
aq
an
bx
@@ -31105,9 +31350,9 @@ bO
cJ
cF
cJ
-hz
+nY
an
-eg
+He
bh
an
an
@@ -31354,7 +31599,7 @@ an
an
hf
hy
-eg
+He
aq
an
by
@@ -31362,9 +31607,9 @@ hz
hz
hz
hz
-hz
+rn
an
-eg
+He
aq
aq
an
@@ -31611,7 +31856,7 @@ aH
an
an
an
-eg
+He
bh
an
bz
@@ -31619,9 +31864,9 @@ bO
bW
ck
cj
-hz
+nY
an
-eg
+He
aq
aq
aN
@@ -31868,7 +32113,7 @@ an
an
aW
an
-eg
+He
aq
an
an
@@ -31878,7 +32123,7 @@ an
an
hA
an
-eg
+He
aq
aq
iS
@@ -32133,9 +32378,9 @@ bB
bX
cl
cl
-hi
+uk
an
-eg
+He
aq
aq
bp
@@ -32382,15 +32627,15 @@ az
az
aq
an
-eg
+He
aq
an
hi
-hi
-hi
-hi
-hi
-hi
+UL
+UL
+UL
+UL
+wx
an
hh
aq
@@ -32639,7 +32884,7 @@ az
az
aq
an
-eg
+He
aq
an
bC
@@ -32649,7 +32894,7 @@ is
dt
cG
an
-eg
+He
bh
an
an
@@ -32892,11 +33137,11 @@ jc
bp
jo
bb
-bb
-bb
+JZ
+JZ
eg
iW
-eg
+WY
aq
an
an
@@ -32906,7 +33151,7 @@ an
an
an
an
-eg
+He
aq
aq
an
@@ -33153,7 +33398,7 @@ aI
aA
jg
an
-eg
+He
aq
an
aJ
@@ -33163,7 +33408,7 @@ cv
hq
cv
an
-eg
+He
aq
aq
aN
@@ -33420,7 +33665,7 @@ bE
bE
lz
an
-eg
+He
aq
aq
iT
@@ -33667,7 +33912,7 @@ jw
au
jh
an
-eg
+He
aq
an
bD
@@ -33677,7 +33922,7 @@ cI
hD
bE
nM
-eg
+He
aq
aq
bp
@@ -33920,21 +34165,21 @@ jd
aN
jp
bb
-bb
-bb
+JZ
+JZ
eg
iV
-eg
+WY
aq
an
cP
-cP
-cP
-cP
+IG
+IG
+IG
jq
-cP
-cP
-eg
+IG
+IG
+WY
aq
aq
an
@@ -34181,7 +34426,7 @@ az
az
aq
an
-eg
+He
aq
an
bF
@@ -34191,7 +34436,7 @@ ho
bE
lz
an
-eg
+He
aq
an
an
@@ -34438,7 +34683,7 @@ az
az
aq
an
-eg
+He
nS
an
bF
@@ -34448,7 +34693,7 @@ hp
js
hp
an
-eg
+He
aq
an
dB
@@ -34705,7 +34950,7 @@ an
an
an
an
-eg
+He
bh
an
dB
@@ -34952,7 +35197,7 @@ an
an
aU
an
-eg
+WD
eg
nV
ei
@@ -34962,7 +35207,7 @@ hr
hs
et
nV
-eg
+zF
aq
an
dB
@@ -35466,7 +35711,7 @@ an
an
aX
bf
-bb
+KS
an
bj
bH
@@ -35476,7 +35721,7 @@ aq
aq
aq
io
-bb
+KS
az
an
dB
@@ -35719,11 +35964,11 @@ ax
an
aF
cL
-aw
+sn
jC
-bb
-bb
-bb
+JZ
+JZ
+Hb
an
bk
bJ
@@ -35987,10 +36232,10 @@ an
an
aq
cp
+rV
eg
eg
-eg
-cQ
+ww
hI
an
dB
@@ -36230,8 +36475,8 @@ ac
ac
dB
ax
-ed
-aw
+WX
+DU
ed
hv
an
diff --git a/_maps/RandomZLevels/away_mission/jungleresort.dmm b/_maps/RandomZLevels/away_mission/jungleresort.dmm
index 4207080ac4..cb5334e855 100644
--- a/_maps/RandomZLevels/away_mission/jungleresort.dmm
+++ b/_maps/RandomZLevels/away_mission/jungleresort.dmm
@@ -1992,6 +1992,7 @@
dir = 8
},
/obj/effect/decal/cleanable/oil/streak,
+/obj/machinery/power/port_gen/pacman,
/turf/open/floor/plating,
/area/awaymission/jungleresort)
"BP" = (
@@ -2040,7 +2041,7 @@
/obj/structure/cable{
icon_state = "0-8"
},
-/obj/machinery/power/port_gen/pacman/super,
+/obj/machinery/power/rtg,
/turf/open/floor/plating,
/area/awaymission/jungleresort)
"CA" = (
@@ -2811,12 +2812,7 @@
/obj/structure/cable{
icon_state = "0-8"
},
-/obj/machinery/power/smes{
- charge = 1.5e+006;
- input_level = 30000;
- inputting = 0;
- output_level = 7000
- },
+/obj/machinery/power/smes/magical,
/turf/open/floor/plating,
/area/awaymission/jungleresort)
"LR" = (
@@ -3183,6 +3179,9 @@
/obj/item/stack/sheet/mineral/uranium,
/obj/item/clothing/glasses/meson/engine,
/obj/item/storage/belt/utility,
+/obj/item/stack/sheet/mineral/plasma{
+ amount = 26
+ },
/turf/open/floor/plating,
/area/awaymission/jungleresort)
"Rm" = (
@@ -3720,7 +3719,7 @@
/obj/structure/cable{
icon_state = "2-4"
},
-/obj/machinery/power/port_gen/pacman/super,
+/obj/machinery/power/rtg,
/turf/open/floor/plating,
/area/awaymission/jungleresort)
"Yb" = (
diff --git a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
index de2105e9d4..6eee9e9d9f 100644
--- a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
+++ b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
@@ -815,16 +815,16 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 351.9
+ initial_temperature = 351.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"bX" = (
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 351.9
+ initial_temperature = 351.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"bY" = (
@@ -2263,8 +2263,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"eK" = (
@@ -2634,8 +2634,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/central)
"fo" = (
@@ -2870,8 +2870,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/central)
"fK" = (
@@ -3049,8 +3049,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"gg" = (
@@ -3197,8 +3197,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"gC" = (
@@ -3411,8 +3411,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/research)
"he" = (
@@ -3422,8 +3422,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"hf" = (
@@ -3454,8 +3454,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"hi" = (
@@ -4789,8 +4789,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/gateway)
"jM" = (
@@ -4823,8 +4823,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/research)
"jR" = (
@@ -6221,6 +6221,7 @@
c_tag = "Engineering Secure Storage";
network = list("uo45")
},
+/obj/machinery/power/port_gen/pacman,
/turf/open/floor/plating{
heat_capacity = 1e+006
},
@@ -6606,8 +6607,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/gateway)
"mJ" = (
@@ -7751,12 +7752,7 @@
/area/awaymission/undergroundoutpost45/engineering)
"ou" = (
/obj/structure/cable,
-/obj/machinery/power/smes{
- charge = 1.5e+006;
- input_level = 30000;
- inputting = 0;
- output_level = 7000
- },
+/obj/machinery/power/smes/magical,
/turf/open/floor/plating{
heat_capacity = 1e+006
},
@@ -8072,12 +8068,10 @@
/obj/machinery/power/terminal{
dir = 1
},
-/obj/machinery/power/port_gen/pacman{
- name = "P.A.C.M.A.N.-type portable generator"
- },
/obj/structure/cable{
icon_state = "0-4"
},
+/obj/machinery/power/rtg,
/turf/open/floor/plating{
heat_capacity = 1e+006
},
@@ -8086,9 +8080,6 @@
/obj/machinery/power/terminal{
dir = 1
},
-/obj/machinery/power/port_gen/pacman/super{
- name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator"
- },
/obj/item/wrench,
/obj/structure/cable{
icon_state = "0-8"
@@ -8096,6 +8087,7 @@
/obj/structure/cable{
icon_state = "0-4"
},
+/obj/machinery/power/rtg,
/turf/open/floor/plating{
heat_capacity = 1e+006
},
@@ -8104,12 +8096,10 @@
/obj/machinery/power/terminal{
dir = 1
},
-/obj/machinery/power/port_gen/pacman{
- name = "P.A.C.M.A.N.-type portable generator"
- },
/obj/structure/cable{
icon_state = "0-8"
},
+/obj/machinery/power/rtg,
/turf/open/floor/plating{
heat_capacity = 1e+006
},
@@ -8356,8 +8346,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"pv" = (
@@ -8367,8 +8357,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"pw" = (
@@ -8379,8 +8369,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/engineering)
"px" = (
@@ -8670,8 +8660,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"qb" = (
@@ -8902,8 +8892,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"qA" = (
@@ -8913,8 +8903,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"qB" = (
@@ -8924,8 +8914,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"qC" = (
@@ -11106,8 +11096,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"uc" = (
@@ -11752,8 +11742,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"vm" = (
@@ -11978,8 +11968,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/research)
"vI" = (
@@ -12264,8 +12254,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/mining)
"wk" = (
@@ -13483,8 +13473,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/mining)
"yh" = (
@@ -13492,8 +13482,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yi" = (
@@ -13501,8 +13491,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yj" = (
@@ -13512,8 +13502,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yk" = (
@@ -13522,8 +13512,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yl" = (
@@ -13533,8 +13523,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"ym" = (
@@ -13543,8 +13533,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yn" = (
@@ -13552,8 +13542,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yo" = (
@@ -13562,8 +13552,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yp" = (
@@ -13572,8 +13562,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yq" = (
@@ -13581,8 +13571,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yr" = (
@@ -13590,8 +13580,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yt" = (
@@ -13600,8 +13590,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yu" = (
@@ -13610,8 +13600,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yw" = (
@@ -13620,8 +13610,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yz" = (
@@ -13629,8 +13619,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yA" = (
@@ -13639,8 +13629,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yB" = (
@@ -13648,8 +13638,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yC" = (
@@ -13658,8 +13648,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yD" = (
@@ -13669,8 +13659,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"yH" = (
@@ -13680,8 +13670,8 @@
/turf/open/floor/plating/asteroid{
heat_capacity = 1e+006;
initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9";
- name = "Cave Floor";
- initial_temperature = 363.9
+ initial_temperature = 363.9;
+ name = "Cave Floor"
},
/area/awaymission/undergroundoutpost45/caves)
"KE" = (
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 8fbb97bbdd..f1c58be502 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -2088,6 +2088,9 @@
},
/obj/machinery/suit_storage_unit/hos,
/obj/effect/turf_decal/delivery,
+/obj/machinery/status_display/ai{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/hos)
"aeE" = (
@@ -5400,6 +5403,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/status_display/ai{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel,
/area/security/brig)
"akp" = (
@@ -5684,6 +5690,9 @@
},
/obj/structure/table,
/obj/item/storage/box/donkpockets,
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel,
/area/security/office)
"akS" = (
@@ -13391,6 +13400,9 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/status_display/ai{
+ pixel_x = -32
+ },
/turf/open/floor/plasteel/cafeteria,
/area/command/heads_quarters/cmo)
"aFb" = (
@@ -19982,6 +19994,9 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel,
/area/command/bridge)
"aWV" = (
@@ -20707,12 +20722,20 @@
/turf/closed/wall/r_wall,
/area/ai_monitored/turret_protected/ai_upload)
"aYy" = (
-/obj/machinery/status_display/ai,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/machinery/status_display/ai{
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel,
+/area/commons/dorms)
"aYz" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
@@ -22940,6 +22963,9 @@
"beG" = (
/obj/machinery/door/firedoor,
/obj/effect/turf_decal/tile/red,
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel,
/area/hallway/secondary/exit)
"beH" = (
@@ -23223,12 +23249,11 @@
/turf/open/floor/plating,
/area/maintenance/port)
"bft" = (
-/obj/machinery/status_display/ai,
-/obj/structure/cable{
- icon_state = "4-8"
+/obj/machinery/status_display/ai{
+ pixel_x = -32
},
-/turf/closed/wall/r_wall,
-/area/ai_monitored/turret_protected/ai_upload)
+/turf/open/floor/plasteel,
+/area/commons/locker)
"bfu" = (
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
@@ -27013,6 +27038,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/machinery/status_display/ai{
+ pixel_x = -32
+ },
/turf/open/floor/plasteel/white,
/area/science/research)
"boB" = (
@@ -28442,6 +28470,9 @@
icon_state = "2-8"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/machinery/status_display/ai{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel,
/area/command/heads_quarters/hop)
"bsa" = (
@@ -31824,6 +31855,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 6
},
+/obj/machinery/status_display/ai{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/white,
/area/command/heads_quarters/rd)
"bzO" = (
@@ -32989,6 +33023,9 @@
pixel_x = 1;
pixel_y = 9
},
+/obj/machinery/status_display/ai{
+ pixel_x = -32
+ },
/turf/open/floor/plasteel,
/area/cargo/miningdock)
"bCp" = (
@@ -42889,7 +42926,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"cbr" = (
@@ -46784,6 +46821,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/machinery/status_display/ai{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel,
/area/engineering/main)
"clN" = (
@@ -47569,7 +47609,7 @@
/obj/structure/cable/yellow{
icon_state = "1-2"
},
-/obj/machinery/air_sensor{
+/obj/machinery/air_sensor/atmos/incinerator_tank{
pixel_x = -32;
pixel_y = -32
},
@@ -52812,6 +52852,14 @@
icon_state = "platingdmg3"
},
/area/commons/arcade)
+"dGh" = (
+/obj/machinery/door/firedoor,
+/obj/effect/turf_decal/delivery,
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
+/turf/open/floor/plasteel,
+/area/medical/medbay/central)
"dIu" = (
/obj/structure/chair/sofa{
dir = 8
@@ -53793,6 +53841,12 @@
},
/turf/open/floor/plasteel,
/area/cargo/miningdock)
+"eVW" = (
+/obj/machinery/status_display/ai{
+ pixel_x = -32
+ },
+/turf/open/floor/wood,
+/area/command/heads_quarters/captain)
"eWL" = (
/obj/machinery/door/firedoor,
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -54369,6 +54423,12 @@
/obj/effect/turf_decal/stripes/corner,
/turf/open/floor/plasteel,
/area/service/hydroponics)
+"fzx" = (
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
+/turf/open/floor/wood,
+/area/service/bar)
"fAj" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
@@ -54656,6 +54716,7 @@
/obj/structure/sign/poster/contraband/robust_softdrinks{
pixel_y = 32
},
+/obj/machinery/vending/snack/orange,
/turf/open/floor/wood,
/area/service/bar)
"fZm" = (
@@ -54952,6 +55013,12 @@
},
/turf/open/floor/plasteel/dark,
/area/commons/fitness)
+"grS" = (
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
+/turf/open/floor/circuit,
+/area/ai_monitored/turret_protected/ai_upload)
"gsM" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance,
@@ -56182,6 +56249,19 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"iyK" = (
+/obj/machinery/conveyor{
+ dir = 8;
+ id = "QMLoad"
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
+/turf/open/floor/plating,
+/area/cargo/storage)
"izg" = (
/obj/item/cigbutt/cigarbutt,
/turf/open/floor/plating,
@@ -57267,6 +57347,12 @@
},
/turf/open/floor/plasteel,
/area/security/prison/upper)
+"jYI" = (
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
+/turf/open/floor/plasteel/white,
+/area/science/robotics/lab)
"jZT" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -57444,10 +57530,10 @@
/turf/open/floor/plasteel/dark,
/area/security/prison/cells)
"kgB" = (
-/obj/machinery/vending/snack/orange,
/obj/machinery/light{
dir = 1
},
+/obj/machinery/jukebox,
/turf/open/floor/wood,
/area/service/bar)
"khb" = (
@@ -58686,6 +58772,12 @@
},
/turf/open/floor/plasteel,
/area/security/prison/upper)
+"lOe" = (
+/obj/machinery/status_display/ai{
+ pixel_y = 32
+ },
+/turf/open/floor/wood,
+/area/command/meeting_room)
"lOr" = (
/obj/structure/table,
/obj/machinery/light/floor,
@@ -58881,6 +58973,9 @@
dir = 4
},
/obj/effect/decal/cleanable/dirt,
+/obj/machinery/status_display/ai{
+ pixel_y = 32
+ },
/turf/open/floor/plasteel,
/area/security/prison/cells)
"maT" = (
@@ -84743,7 +84838,7 @@ aQN
aTB
aQN
aWq
-aQN
+bft
aWq
aUt
aQN
@@ -87074,7 +87169,7 @@ bjr
cBp
bjr
buB
-bvV
+iyK
bxu
bxu
bxx
@@ -93740,7 +93835,7 @@ aPR
aWL
aPR
aZM
-bbX
+lOe
bay
bbM
bcN
@@ -95542,8 +95637,8 @@ aZR
aZR
aZR
aZR
-aZR
-bft
+grS
+nVz
wZI
gDO
aBW
@@ -96565,7 +96660,7 @@ aSA
aTX
aVm
aWU
-aYy
+aYB
aZR
aZR
aZR
@@ -97600,7 +97695,7 @@ bch
bdi
bbw
bfy
-bbw
+eVW
bik
aZV
aZV
@@ -99885,7 +99980,7 @@ arf
arf
arf
arf
-ltK
+aYy
axP
azb
aAi
@@ -103524,7 +103619,7 @@ btX
bof
bwG
bxR
-bxR
+dGh
bof
bof
bzW
@@ -103762,7 +103857,7 @@ aSZ
aQc
qaY
acN
-aKR
+fzx
aJC
aYV
aYV
@@ -111229,7 +111324,7 @@ blG
biL
cHV
cIa
-biL
+jYI
box
buo
bvc
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index 1dcb97a647..6f1ec5682b 100644
--- a/_maps/map_files/CogStation/CogStation.dmm
+++ b/_maps/map_files/CogStation/CogStation.dmm
@@ -57320,7 +57320,7 @@
name = "Chief Engineer's RC";
pixel_y = -32
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel,
/area/command/heads_quarters/ce)
"csf" = (
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index d64abed5dc..776e50e9a5 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -2619,9 +2619,8 @@
/turf/closed/wall/r_wall,
/area/space/nearstation)
"ajs" = (
-/obj/structure/table,
-/obj/item/storage/briefcase,
/obj/effect/turf_decal/delivery,
+/obj/machinery/vending/kink,
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
"ajt" = (
@@ -2880,15 +2879,17 @@
"ajR" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/delivery,
-/obj/item/kirbyplants{
- icon_state = "plant-21"
- },
+/obj/structure/table,
+/obj/item/storage/briefcase,
/turf/open/floor/plasteel,
/area/hallway/secondary/entry)
"ajS" = (
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/item/kirbyplants{
+ icon_state = "plant-21"
+ },
/turf/open/floor/plasteel/cafeteria,
/area/hallway/secondary/entry)
"ajT" = (
@@ -75787,7 +75788,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"fLq" = (
@@ -96886,7 +96887,7 @@
/obj/item/folder/red,
/obj/item/toy/gun,
/obj/item/clothing/head/beret/sec{
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0);
+ armor = list("melee"=0,"bullet"=0,"laser"=0,"energy"=0,"bomb"=0,"bio"=0,"rad"=0);
desc = "A replica beret resembling that of a special operations officer under Nanotrasen.";
name = "replica officer's beret"
},
@@ -98957,7 +98958,7 @@
name = "Replica CentCom officer's jumpsuit"
},
/obj/item/clothing/head/centhat{
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0);
+ armor = list("melee"=0,"bullet"=0,"laser"=0,"energy"=0,"bomb"=0,"bio"=0,"rad"=0);
desc = "A replica hat of a Central Commander's attire. It has a small tag on it saying, 'It's good to be emperor.'";
name = "Replica CentCom hat"
},
@@ -114141,6 +114142,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
+/obj/machinery/vending/kink,
/turf/open/floor/plasteel,
/area/commons/fitness/recreation)
"sVM" = (
@@ -119427,7 +119429,7 @@
},
/obj/item/reagent_containers/food/drinks/beer{
desc = "Whatever it is, it reeks of foul, putrid froth.";
- list_reagents = list("bacchus_blessing" = 15);
+ list_reagents = list("bacchus_blessing"=15);
name = "Delta-Down";
pixel_x = 5;
pixel_y = 5
diff --git a/_maps/map_files/FestiveBall/FestiveStation.dmm b/_maps/map_files/FestiveBall/FestiveStation.dmm
index a559280263..353b298ceb 100644
--- a/_maps/map_files/FestiveBall/FestiveStation.dmm
+++ b/_maps/map_files/FestiveBall/FestiveStation.dmm
@@ -5069,7 +5069,7 @@
/area/command/heads_quarters/ce)
"ane" = (
/obj/structure/filingcabinet/chestdrawer,
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"anf" = (
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index fa3c32a418..37a0292f45 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -13429,7 +13429,7 @@
/obj/item/radio/intercom{
pixel_x = 28
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"awq" = (
diff --git a/_maps/map_files/LambdaStation/dorms.dmm b/_maps/map_files/LambdaStation/dorms.dmm
index d52c4e7870..99626ac667 100644
--- a/_maps/map_files/LambdaStation/dorms.dmm
+++ b/_maps/map_files/LambdaStation/dorms.dmm
@@ -5011,6 +5011,7 @@
dir = 1
},
/obj/machinery/light,
+/obj/machinery/jukebox,
/turf/open/floor/plasteel,
/area/service/bar)
"nb" = (
diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm
index 394f7fb7c1..97a17ff303 100644
--- a/_maps/map_files/LambdaStation/lambda.dmm
+++ b/_maps/map_files/LambdaStation/lambda.dmm
@@ -44859,7 +44859,7 @@
/obj/item/gps/engineering{
gpstag = "CE0"
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"bUH" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 3661b49684..52fe46984f 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -57489,7 +57489,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/ce)
"ixH" = (
@@ -65631,6 +65631,14 @@
},
/turf/open/floor/plasteel/dark,
/area/service/chapel/main)
+"mWS" = (
+/obj/effect/turf_decal/tile/bar,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/obj/machinery/jukebox,
+/turf/open/floor/plasteel,
+/area/service/bar)
"mXi" = (
/turf/open/floor/wood,
/area/command/heads_quarters/captain/private)
@@ -119802,7 +119810,7 @@ teZ
teZ
wbZ
hCA
-msI
+mWS
pzY
kPZ
upO
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index 68dfbe5bcf..8b4e4c38e6 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -6363,7 +6363,7 @@
c_tag = "Chief Engineer's Office";
network = list("ss13","engine")
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/obj/machinery/atmospherics/pipe/simple/orange/visible{
dir = 10
},
@@ -13604,14 +13604,7 @@
/turf/open/floor/plasteel,
/area/service/bar/atrium)
"ayN" = (
-/obj/item/storage/fancy/cigarettes/cigars{
- pixel_y = 6
- },
-/obj/item/storage/fancy/cigarettes/cigars/cohiba{
- pixel_y = 3
- },
-/obj/item/storage/fancy/cigarettes/cigars/havana,
-/obj/structure/table/reinforced,
+/obj/machinery/jukebox,
/turf/open/floor/plasteel/dark/corner{
dir = 4
},
@@ -13622,6 +13615,13 @@
pixel_x = 32
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/item/storage/fancy/cigarettes/cigars/havana,
+/obj/item/storage/fancy/cigarettes/cigars/cohiba{
+ pixel_y = 3
+ },
+/obj/item/storage/fancy/cigarettes/cigars{
+ pixel_y = 6
+ },
/turf/open/floor/plasteel/dark/side{
dir = 1
},
@@ -16379,9 +16379,8 @@
/area/hallway/secondary/exit)
"aEg" = (
/obj/effect/turf_decal/stripes/line,
-/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped/inverse{
- dir = 4;
- name = "air mixer"
+/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped{
+ dir = 4
},
/obj/structure/cable{
icon_state = "4-8"
@@ -23915,7 +23914,7 @@
c_tag = "Library 2";
dir = 4
},
-/obj/structure/sign/painting{
+/obj/structure/sign/painting/library{
pixel_y = 32
},
/turf/open/floor/plasteel/dark/side{
@@ -23926,6 +23925,9 @@
/obj/structure/table/wood,
/obj/item/folder,
/obj/item/pen,
+/obj/structure/sign/painting/library{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/dark,
/area/service/library)
"aRV" = (
@@ -23997,6 +23999,9 @@
/obj/machinery/newscaster{
pixel_x = 32
},
+/obj/structure/sign/painting/library{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/dark/side{
dir = 10
},
@@ -24956,6 +24961,9 @@
/area/maintenance/port/aft)
"aUj" = (
/obj/machinery/photocopier,
+/obj/structure/sign/painting/library{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/dark/side{
dir = 10
},
@@ -26435,7 +26443,7 @@
/turf/closed/wall,
/area/service/library)
"aXg" = (
-/obj/structure/sign/painting{
+/obj/structure/sign/painting/library{
pixel_y = -32
},
/turf/open/floor/plasteel/dark/side{
@@ -26444,6 +26452,9 @@
/area/service/library)
"aXh" = (
/obj/machinery/light,
+/obj/structure/sign/painting/library{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel/dark,
/area/service/library)
"aXi" = (
@@ -26461,7 +26472,7 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"aXj" = (
-/obj/structure/sign/painting{
+/obj/structure/sign/painting/library{
pixel_y = -32
},
/turf/open/floor/plasteel/dark,
@@ -26474,6 +26485,9 @@
c_tag = "Library 1";
dir = 8
},
+/obj/structure/sign/painting/library{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel/dark/side{
dir = 10
},
@@ -35444,7 +35458,7 @@
/obj/structure/table/wood,
/obj/item/folder,
/obj/item/pen,
-/obj/structure/sign/painting{
+/obj/structure/sign/painting/library{
pixel_x = -32
},
/turf/open/floor/plasteel/dark,
@@ -84771,7 +84785,7 @@ awp
awX
axR
ayN
-aue
+asg
blj
aCb
aCe
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 2c01f48150..d8d18c4407 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -42909,7 +42909,7 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel,
/area/command/heads_quarters/ce)
"bVE" = (
diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm
index 4def794b4f..1e3c094cf6 100644
--- a/_maps/map_files/Snaxi/Snaxi.dmm
+++ b/_maps/map_files/Snaxi/Snaxi.dmm
@@ -85,7 +85,7 @@
/obj/machinery/keycard_auth{
pixel_y = -28
},
-/mob/living/simple_animal/parrot/Poly,
+/mob/living/simple_animal/parrot/Polly,
/turf/open/floor/plasteel,
/area/command/heads_quarters/ce)
"aai" = (
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index a147773cd1..cb32e435ca 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -2280,7 +2280,7 @@
/turf/open/floor/plasteel,
/area/tdome/arena_source)
"fX" = (
-/turf/closed/indestructible/riveted,
+/turf/closed/indestructible/start_area,
/area/start)
"fY" = (
/obj/effect/landmark/start/new_player,
diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 5695995713..9cae56645f 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -80,7 +80,7 @@
//DNA - Because fuck you and your magic numbers being all over the codebase.
#define DNA_BLOCK_SIZE 3
-#define DNA_UNI_IDENTITY_BLOCKS 15
+#define DNA_UNI_IDENTITY_BLOCKS 19
#define DNA_HAIR_COLOR_BLOCK 1
#define DNA_FACIAL_HAIR_COLOR_BLOCK 2
#define DNA_SKIN_TONE_BLOCK 3
@@ -96,6 +96,10 @@
#define DNA_MUTANTEAR_BLOCK 13
#define DNA_MUTANTMARKING_BLOCK 14
#define DNA_TAUR_BLOCK 15
+#define DNA_BARK_SOUND_BLOCK 16
+#define DNA_BARK_SPEED_BLOCK 17
+#define DNA_BARK_PITCH_BLOCK 18
+#define DNA_BARK_VARIANCE_BLOCK 19
#define DNA_SEQUENCE_LENGTH 4
#define DNA_MUTATION_BLOCKS 8
diff --git a/code/__DEFINES/bitfields.dm b/code/__DEFINES/bitfields.dm
new file mode 100644
index 0000000000..19a962fbff
--- /dev/null
+++ b/code/__DEFINES/bitfields.dm
@@ -0,0 +1,4 @@
+#define DEFINE_BITFIELD(_variable, _flags) /datum/bitfield/##_variable { \
+ flags = ##_flags; \
+ variable = #_variable; \
+}
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 7ef6e8694d..2662caa63a 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -274,6 +274,8 @@
// #define HEARING_SPANS 6
#define HEARING_MESSAGE_MODE 7
// #define HEARING_SOURCE 8
+#define COMSIG_MOVABLE_BARK "movable_bark" //from base of atom/movable/proc/bark(): (list/hearers, distance, volume, pitch)
+#define COMSIG_MOVABLE_QUEUE_BARK "movable_queue_bark" //from base of atom/movable/proc/send_speech(): (list/hearers, message, range, atom/movable/source, bubble_type, list/spans, datum/language/message_language, message_mode)
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
#define COMSIG_MOVABLE_CHASM_DROP "movable_chasm_drop" //from base of /datum/component/chasm/drop() (/datum/component/chasm)
@@ -417,7 +419,7 @@
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
#define COMPONET_INTERRUPT_STATUS_EFFECTS 3 // interrupt status effects
-#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (seconds, times_fired)
+#define COMSIG_LIVING_BIOLOGICAL_LIFE "biological_life" //from base of mob/living/BiologicalLife() (delta_time, times_fired)
#define COMSIG_LIVING_PHYSICAL_LIFE "physical_life" //from base of mob/living/PhysicalLife() (seconds, times_fired)
@@ -569,7 +571,7 @@
#define COMSIG_MECHA_EQUIPMENT_CLICK "mecha_action_equipment_click"
/// Prevents click from happening.
#define COMPONENT_CANCEL_EQUIPMENT_CLICK (1<<0)
-
+
// /mob/living/carbon/human signals
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm
new file mode 100644
index 0000000000..cc6e5bd49a
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm
@@ -0,0 +1,3 @@
+/// Called from /mob/living/PushAM -- Called when this mob is about to push a movable, but before it moves
+/// (aotm/movable/being_pushed)
+#define COMSIG_LIVING_PUSHING_MOVABLE "living_pushing_movable"
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
new file mode 100644
index 0000000000..5d2a471c0a
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
@@ -0,0 +1,2 @@
+///From base of mob/living/MobBump() (mob/living)
+#define COMSIG_LIVING_MOB_BUMP "living_mob_bump"
diff --git a/code/__DEFINES/dcs/signals/signals_subsystem.dm b/code/__DEFINES/dcs/signals/signals_subsystem.dm
new file mode 100644
index 0000000000..c39b59262b
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_subsystem.dm
@@ -0,0 +1,25 @@
+// Subsystem signals. Format:
+// When the signal is called: (signal arguments)
+// All signals send the source datum of the signal as the first argument
+
+///Subsystem signals
+///From base of datum/controller/subsystem/Initialize: (start_timeofday)
+#define COMSIG_SUBSYSTEM_POST_INITIALIZE "subsystem_post_initialize"
+
+///Called when the ticker enters the pre-game phase
+#define COMSIG_TICKER_ENTER_PREGAME "comsig_ticker_enter_pregame"
+
+///Called when the ticker sets up the game for start
+#define COMSIG_TICKER_ENTER_SETTING_UP "comsig_ticker_enter_setting_up"
+
+///Called when the ticker fails to set up the game for start
+#define COMSIG_TICKER_ERROR_SETTING_UP "comsig_ticker_error_setting_up"
+
+/// Called when the round has started, but before GAME_STATE_PLAYING
+#define COMSIG_TICKER_ROUND_STARTING "comsig_ticker_round_starting"
+
+// Point of interest signals
+/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_added : (atom/new_poi)
+#define COMSIG_ADDED_POINT_OF_INTEREST "added_point_of_interest"
+/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed : (atom/old_poi)
+#define COMSIG_REMOVED_POINT_OF_INTEREST "removed_point_of_interest"
diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm
index 2550084207..fd841ba258 100644
--- a/code/__DEFINES/layers_planes.dm
+++ b/code/__DEFINES/layers_planes.dm
@@ -187,6 +187,9 @@
#define ABOVE_HUD_LAYER 30
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
+#define LOBBY_BACKGROUND_LAYER 3
+#define LOBBY_BUTTON_LAYER 4
+
#define SPLASHSCREEN_LAYER 90
#define SPLASHSCREEN_PLANE 90
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm
index f9b4c36c9c..792708b5bb 100644
--- a/code/__DEFINES/loadout.dm
+++ b/code/__DEFINES/loadout.dm
@@ -91,3 +91,8 @@
#define LOADOUT_TAB 4
#define CONTENT_PREFERENCES_TAB 5
#define KEYBINDINGS_TAB 6
+
+//quirks
+#define QUIRK_POSITIVE "Positive"
+#define QUIRK_NEGATIVE "Negative"
+#define QUIRK_NEUTRAL "Neutral"
diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 87e7fe3ce4..96201d71c2 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -42,6 +42,7 @@
#define LOG_MECHA (1 << 17)
#define LOG_SHUTTLE (1 << 18)
#define LOG_VICTIM (1 << 19)
+#define LOG_ECON (1 << 20)
//Individual logging panel pages
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
@@ -50,7 +51,7 @@
#define INDIVIDUAL_COMMS_LOG (LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS)
#define INDIVIDUAL_OOC_LOG (LOG_OOC | LOG_ADMIN)
#define INDIVIDUAL_OWNERSHIP_LOG (LOG_OWNERSHIP)
-#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM)
+#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM | LOG_ECON)
#define LOGSRC_CLIENT "Client"
#define LOGSRC_MOB "Mob"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index c8c084fc18..36f427a1bb 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -5,7 +5,6 @@
// Ready states at roundstart for mob/dead/new_player
#define PLAYER_NOT_READY 0
#define PLAYER_READY_TO_PLAY 1
-#define PLAYER_READY_TO_OBSERVE 2
// movement intent defines for the m_intent var
#define MOVE_INTENT_WALK "walk"
diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm
index 5bf7de8647..bccbd425dd 100644
--- a/code/__DEFINES/movement.dm
+++ b/code/__DEFINES/movement.dm
@@ -13,7 +13,7 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0)
/// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave.
/// The whole result is then clamped to within the range above.
/// Not very readable but it works
-#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))
+#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE))
/// Enables smooth movement
// #define SMOOTH_MOVEMENT
diff --git a/code/__DEFINES/pool.dm b/code/__DEFINES/pool.dm
index 1bf39dcb1d..86088fbb79 100644
--- a/code/__DEFINES/pool.dm
+++ b/code/__DEFINES/pool.dm
@@ -8,5 +8,6 @@
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
- /datum/reagent/consumable/semen //NO.
+ /datum/reagent/consumable/semen, //NO.
+ /datum/reagent/consumable/milk
))
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index d2aa2f6a91..5581d71080 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -15,6 +15,7 @@
#define DISABLE_DEATHRATTLE (1<<12)
#define DISABLE_ARRIVALRATTLE (1<<13)
#define COMBOHUD_LIGHTING (1<<14)
+#define SOUND_BARK (1<<15)
#define DEADMIN_ALWAYS (1<<0)
#define DEADMIN_ANTAGONIST (1<<1)
@@ -22,7 +23,7 @@
#define DEADMIN_POSITION_SECURITY (1<<3)
#define DEADMIN_POSITION_SILICON (1<<4)
-#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS)
+#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS|SOUND_BARK)
//Chat toggles
#define CHAT_OOC (1<<0)
diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm
index d1329060eb..061ac289d0 100644
--- a/code/__DEFINES/reactions.dm
+++ b/code/__DEFINES/reactions.dm
@@ -27,6 +27,7 @@
#define NOBLIUM_RESEARCH_AMOUNT 25
#define BZ_RESEARCH_SCALE 4
#define BZ_RESEARCH_MAX_AMOUNT 400
+#define QCD_RESEARCH_AMOUNT 0.2 // often made in absolutely massive quantities due to the simple nature of fusion
#define MIASMA_RESEARCH_AMOUNT 6
#define STIMULUM_RESEARCH_AMOUNT 50
//Plasma fusion properties
diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm
index e27489380c..b8b9b78bf3 100644
--- a/code/__DEFINES/research.dm
+++ b/code/__DEFINES/research.dm
@@ -73,7 +73,9 @@
TECHWEB_POINT_TYPE_GENERIC = "General Research"\
)
+#define LARGEST_BOMB "bomb"
+
#define BOMB_TARGET_POINTS 50000 //Adjust as needed. Actual hard cap is double this, but will never be reached due to hyperbolic curve.
-#define BOMB_TARGET_SIZE (world.system_type == MS_WINDOWS ? 240 : 50000) // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
+#define BOMB_TARGET_SIZE 300 // The shockwave radius required for a bomb to get TECHWEB_BOMB_MIDPOINT points.
// Linux still has old trit fires, so
#define BOMB_SUB_TARGET_EXPONENT 3 // The power of the points curve below the target size. Higher = less points for worse bombs, below target.
diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index b711837232..a4d0b6427d 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -37,6 +37,7 @@
#define MODE_ALIEN "alientalk"
#define MODE_HOLOPAD "holopad"
+#define MODE_STATUSDISPLAY "statusdisplay"
#define MODE_CHANGELING "changeling"
#define MODE_KEY_CHANGELING "g"
@@ -91,11 +92,32 @@
//ambition end
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
#define MAX_FLAVOR_LEN 4096
+#define MAX_FLAVOR_PREVIEW_LEN 40
#define MAX_TASTE_LEN 40 //lick... vore... ew...
#define MAX_NAME_LEN 42
#define MAX_BROADCAST_LEN 512
#define MAX_CHARTER_LEN 80
+//Bark defines
+#define BARK_DEFAULT_MINPITCH 0.6
+#define BARK_DEFAULT_MAXPITCH 1.4
+#define BARK_DEFAULT_MINVARY 0.1
+#define BARK_DEFAULT_MAXVARY 0.4
+#define BARK_DEFAULT_MINSPEED 2
+#define BARK_DEFAULT_MAXSPEED 8
+
+#define BARK_SPEED_BASELINE 4 //Used to calculate delay between barks, any bark speeds below this feature higher bark density, any speeds above feature lower bark density. Keeps barking length consistent
+
+#define BARK_MAX_BARKS 128
+#define BARK_MAX_TIME (10 SECONDS) // More or less the amount of time the above takes to process through with a bark speed of 2.
+
+#define BARK_PITCH_RAND(gend) ((gend == MALE ? rand(60, 120) : (gend == FEMALE ? rand(80, 140) : rand(60,140))) / 100) //Macro for determining random pitch based off gender
+#define BARK_VARIANCE_RAND (rand(BARK_DEFAULT_MINVARY * 100, BARK_DEFAULT_MAXVARY * 100) / 100) //Macro for randomizing bark variance to reduce the amount of copy-pasta necessary for that
+
+#define BARK_DO_VARY(pitch, variance) (rand(((pitch * 100) - (variance*50)), ((pitch*100) + (variance*50))) / 100)
+
+#define BARK_SOUND_FALLOFF_EXPONENT(distance) (distance/7) //At lower ranges, we want the exponent to be below 1 so that whispers don't sound too awkward. At higher ranges, we want the exponent fairly high to make yelling less obnoxious
+
// Is something in the IC chat filter? This is config dependent.
#define CHAT_FILTER_CHECK(T) (config.ic_filter_regex && findtext(T, config.ic_filter_regex))
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 986b9821b3..222dc5cd39 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -233,6 +233,8 @@
#define TRAIT_TRASHCAN "trashcan"
///Used for fireman carry to have mobe not be dropped when passing by a prone individual.
#define TRAIT_BEING_CARRIED "being_carried"
+#define TRAIT_GLASS_BONES "glass_bones"
+#define TRAIT_PAPER_SKIN "paper_skin"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 8a8ccd5023..58b7516be3 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -161,6 +161,10 @@
if (CONFIG_GET(flag/log_telecomms))
WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]")
+/proc/log_econ(text)
+ if (CONFIG_GET(flag/log_econ))
+ WRITE_LOG(GLOB.world_econ_log, "MONEY: [text]")
+
/proc/log_chat(text)
if (CONFIG_GET(flag/log_pda))
//same thing here
diff --git a/code/__HELPERS/clients.dm b/code/__HELPERS/clients.dm
new file mode 100644
index 0000000000..3b61cf1e1c
--- /dev/null
+++ b/code/__HELPERS/clients.dm
@@ -0,0 +1,12 @@
+///Returns whether or not a player is a guest using their ckey as an input
+/proc/is_guest_key(key)
+ if(findtext(key, "Guest-", 1, 7) != 1) //was findtextEx
+ return FALSE
+
+ var/i, ch, len = length(key)
+
+ for(i = 7, i <= len, ++i) //we know the first 6 chars are Guest-
+ ch = text2ascii(key, i)
+ if (ch < 48 || ch > 57) //0-9
+ return FALSE
+ return TRUE
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 3e5658fa00..8b8c05063e 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -79,6 +79,12 @@
var/datum/emote/E = new path()
E.emote_list[E.key] = E
+ for(var/path in subtypesof(/datum/bark))
+ var/datum/bark/B = new path()
+ GLOB.bark_list[B.id] = path
+ if(B.allow_random)
+ GLOB.bark_random_list[B.id] = path
+
// Hair Gradients - Initialise all /datum/sprite_accessory/hair_gradient into an list indexed by gradient-style name
for(var/path in subtypesof(/datum/sprite_accessory/hair_gradient))
var/datum/sprite_accessory/hair_gradient/H = new path()
diff --git a/code/__HELPERS/matrices/color_matrix.dm b/code/__HELPERS/matrices/color_matrix.dm
index e4a4a9bb48..bcc48b45f5 100644
--- a/code/__HELPERS/matrices/color_matrix.dm
+++ b/code/__HELPERS/matrices/color_matrix.dm
@@ -138,6 +138,25 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
+/**
+ * Builds a color matrix that transforms the hue, saturation, and value, all in one operation.
+ */
+/proc/color_matrix_hsv(hue, saturation, value)
+ hue = clamp(360 - hue, 0, 360)
+
+ // This is very much a rough approximation of hueshifting. This carries some artifacting, such as negative values that simply shouldn't exist, but it does get the job done, and that's what matters.
+ var/cos_a = cos(hue) // These have to be inverted from 360, otherwise the hue's inverted
+ var/sin_a = sin(hue)
+ var/rot_x = cos_a + (1 - cos_a) / 3
+ var/rot_y = (1 - cos_a) / 3 - 0.5774 * sin_a // 0.5774 is sqrt(1/3)
+ var/rot_z = (1 - cos_a) / 3 + 0.5774 * sin_a
+
+ return list(
+ round((((1-saturation) * LUMA_R) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_R) + (rot_z * saturation)) * value, 0.01),
+ round((((1-saturation) * LUMA_G) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_x * saturation)) * value, 0.01), round((((1-saturation) * LUMA_G) + (rot_y * saturation)) * value, 0.01),
+ round((((1-saturation) * LUMA_B) + (rot_y * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_z * saturation)) * value, 0.01), round((((1-saturation) * LUMA_B) + (rot_x * saturation)) * value, 0.01),
+ 0, 0, 0
+ )
//Returns a matrix addition of A with B
/proc/color_matrix_add(list/A, list/B)
diff --git a/code/__HELPERS/matrices/transform_matrix.dm b/code/__HELPERS/matrices/transform_matrix.dm
index 251ef8151f..8f8a67535e 100644
--- a/code/__HELPERS/matrices/transform_matrix.dm
+++ b/code/__HELPERS/matrices/transform_matrix.dm
@@ -19,7 +19,7 @@
speed /= segments
if(parallel)
- animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
+ animate(src, transform = matrices[1], time = speed, loops, flags = ANIMATION_PARALLEL)
else
animate(src, transform = matrices[1], time = speed, loops)
diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index 2f7dd7a64f..469f27926a 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -258,15 +258,24 @@
send2adminchat("Server", "A round of [mode.name] just ended[mode_result == "undefined" ? "." : " with a [mode_result]."] Survival rate: [survival_rate]")
- if(LAZYLEN(GLOB.round_end_notifiees))
- world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE)
-
if(length(CONFIG_GET(keyed_list/cross_server)))
send_news_report()
//tell the nice people on discord what went on before the salt cannon happens.
- world.TgsTargetedChatBroadcast("The current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!", FALSE)
- world.TgsTargetedChatBroadcast(send_news_report(), FALSE)
+ if(CONFIG_GET(string/chat_roundend_notice_tag))
+ var/broadcastmessage = ""
+
+ if(LAZYLEN(GLOB.round_end_notifiees))
+ broadcastmessage += "[GLOB.round_end_notifiees.Join(", ")], "
+
+
+ broadcastmessage += "[((broadcastmessage == "") ? "the" : "The")] current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!\n"
+ broadcastmessage += "```\n[send_news_report()]\n```"
+
+ if(CONFIG_GET(string/chat_reboot_role))
+ broadcastmessage += "\n\n<@&[CONFIG_GET(string/chat_reboot_role)]>, the server will reboot shortly!"
+
+ send2chat(broadcastmessage, CONFIG_GET(string/chat_roundend_notice_tag))
CHECK_TICK
@@ -370,6 +379,8 @@
parts += "[FOURSPACES]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]"
parts += "[FOURSPACES]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[popcount["station_integrity"]]%"]"
+ if(mode.station_was_nuked && SSevents.holidays && SSevents.holidays[PRIDE_MONTH])
+ parts += "[FOURSPACES]Gender revealed: [pick(500; "Male", 500; "Female", "Bigender", "Agender", "Demiboy", "Demigirl", "Genderfluid", "Pangender", "Xenogender", "Clown", 50; "What", 50; "Oh no.", 50; "Excuse me?")]"
var/total_players = GLOB.joined_player_list.len
if(total_players)
parts+= "[FOURSPACES]Total Population: [total_players]"
@@ -548,7 +559,7 @@
parts += "There were [station_vault] credits collected by crew this shift. "
if(total_players > 0)
parts += "An average of [station_vault/total_players] credits were collected. "
- // log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
+ log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
if(mr_moneybags)
parts += "The most affluent crew member at shift end was [mr_moneybags.account_holder] with [mr_moneybags.account_balance] cr!"
else
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index b415b4720f..428784e953 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1176,25 +1176,22 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
var/initialpixely = pixel_y
var/shiftx = rand(-pixelshiftx,pixelshiftx)
var/shifty = rand(-pixelshifty,pixelshifty)
- animate(src, pixel_x = pixel_x + shiftx, pixel_y = pixel_y + shifty, time = 0.2, loop = duration)
- pixel_x = initialpixelx
- pixel_y = initialpixely
+ animate(src, pixel_x = shiftx, pixel_y = shifty, time = 0.2, loop = duration, flags = ANIMATION_RELATIVE)
+ animate(pixel_x = initialpixelx, pixel_y = initialpixely, time = 0.2)
-/atom/proc/do_jiggle(targetangle = 45, timer = 20)
+/atom/proc/do_jiggle(targetangle = 25, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
- var/halftime = timer * 0.5
M.Turn(pick(-targetangle, targetangle))
- animate(src, transform = M, time = halftime, easing = ELASTIC_EASING)
- animate(src, transform = OM, time = halftime, easing = ELASTIC_EASING)
+ animate(src, transform = M, time = timer * 0.1, easing = BACK_EASING | EASE_IN)
+ animate(transform = OM, time = timer * 0.4, easing = ELASTIC_EASING)
/atom/proc/do_squish(squishx = 1.2, squishy = 0.6, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
- var/halftime = timer * 0.5
M.Scale(squishx, squishy)
- animate(src, transform = M, time = halftime, easing = BOUNCE_EASING)
- animate(src, transform = OM, time = halftime, easing = BOUNCE_EASING)
+ animate(src, transform = M, time = timer * 0.5, easing = ELASTIC_EASING)
+ animate(transform = OM, time = timer * 0.5, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
/proc/weightclass2text(var/w_class)
switch(w_class)
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index be1d95416b..8d06d9ecf3 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -1,329 +1,378 @@
-GLOBAL_LIST_INIT(bitfields, list(
- "appearance_flags" = list(
- "LONG_GLIDE" = LONG_GLIDE,
- "RESET_COLOR" = RESET_COLOR,
- "RESET_ALPHA" = RESET_ALPHA,
- "RESET_TRANSFORM" = RESET_TRANSFORM,
- "NO_CLIENT_COLOR" = NO_CLIENT_COLOR,
- "KEEP_TOGETHER" = KEEP_TOGETHER,
- "KEEP_APART" = KEEP_APART,
- "PLANE_MASTER" = PLANE_MASTER,
- "TILE_BOUND" = TILE_BOUND,
- "PIXEL_SCALE" = PIXEL_SCALE
- ),
- "area_flags" = list(
- "ABDUCTOR_PROOF" = ABDUCTOR_PROOF,
- "BLOBS_ALLOWED" = BLOBS_ALLOWED,
- "BLOCK_SUICIDE" = BLOCK_SUICIDE,
- "CULT_PERMITTED" = CULT_PERMITTED,
- "FLORA_ALLOWED" = FLORA_ALLOWED,
- "HIDDEN_AREA" = HIDDEN_AREA,
- "MEGAFAUNA_SPAWN_ALLOWED" = MEGAFAUNA_SPAWN_ALLOWED,
- "MOB_SPAWN_ALLOWED" = MOB_SPAWN_ALLOWED,
- "NO_ALERTS" = NO_ALERTS,
- "NOTELEPORT" = NOTELEPORT,
- "CAVES_ALLOWED" = CAVES_ALLOWED,
- "UNIQUE_AREA" = UNIQUE_AREA,
- "VALID_TERRITORY" = VALID_TERRITORY,
- "XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE,
- "NO_ALERTS" = NO_ALERTS,
- ) ,
- "sight" = list(
- "SEE_INFRA" = SEE_INFRA,
- "SEE_SELF" = SEE_SELF,
- "SEE_MOBS" = SEE_MOBS,
- "SEE_OBJS" = SEE_OBJS,
- "SEE_TURFS" = SEE_TURFS,
- "SEE_PIXELS" = SEE_PIXELS,
- "SEE_THRU" = SEE_THRU,
- "SEE_BLACKNESS" = SEE_BLACKNESS,
- "BLIND" = BLIND
- ),
- "obj_flags" = list(
- "EMAGGED" = EMAGGED,
- "IN_USE" = IN_USE,
- "CAN_BE_HIT" = CAN_BE_HIT,
- "BEING_SHOCKED" = BEING_SHOCKED,
- "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
- "ON_BLUEPRINTS" = ON_BLUEPRINTS,
- "UNIQUE_RENAME" = UNIQUE_RENAME,
- "USES_TGUI" = USES_TGUI,
- "FROZEN" = FROZEN,
- "SHOVABLE_ONTO" = SHOVABLE_ONTO,
- "BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN,
- "BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP,
- "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
- "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
- "EXAMINE_SKIP" = EXAMINE_SKIP
- ),
- "datum_flags" = list(
- "DF_USE_TAG" = DF_USE_TAG,
- "DF_VAR_EDITED" = DF_VAR_EDITED,
- "DF_ISPROCESSING" = DF_ISPROCESSING,
- ),
- "item_flags" = list(
- "BEING_REMOVED" = BEING_REMOVED,
- "IN_INVENTORY" = IN_INVENTORY,
- "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE,
- "NEEDS_PERMIT" = NEEDS_PERMIT,
- "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND,
- "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION,
- "DROPDEL" = DROPDEL,
- "NOBLUDGEON" = NOBLUDGEON,
- "ABSTRACT" = ABSTRACT,
- "IN_STORAGE" = IN_STORAGE,
- "ITEM_CAN_BLOCK" = ITEM_CAN_BLOCK,
- "ITEM_CAN_PARRY" = ITEM_CAN_PARRY
- ),
- "admin_flags" = list(
- "BUILDMODE" = R_BUILDMODE,
- "ADMIN" = R_ADMIN,
- "BAN" = R_BAN,
- "FUN" = R_FUN,
- "SERVER" = R_SERVER,
- "DEBUG" = R_DEBUG,
- "POSSESS" = R_POSSESS,
- "PERMISSIONS" = R_PERMISSIONS,
- "STEALTH" = R_STEALTH,
- "POLL" = R_POLL,
- "VAREDIT" = R_VAREDIT,
- "SOUNDS" = R_SOUNDS,
- "SPAWN" = R_SPAWN,
- "AUTOLOGIN" = R_AUTOLOGIN,
- "DBRANKS" = R_DBRANKS,
- "SENSITIVE" = R_SENSITIVE
- ),
- "interaction_flags_atom" = list(
- "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED,
- "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND,
- "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT,
- "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY,
- "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED,
- "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED,
- "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB,
- "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND,
- "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT
- ),
- "interaction_flags_machine" = list(
- "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN,
- "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
- "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
- "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
- "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON,
- "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
- "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE
- ),
- "interaction_flags_item" = list(
- "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP,
- ),
- "pass_flags" = list(
- "PASSTABLE" = PASSTABLE,
- "PASSGLASS" = PASSGLASS,
- "PASSGRILLE" = PASSGRILLE,
- "PASSBLOB" = PASSBLOB,
- "PASSMOB" = PASSMOB,
- "PASSCLOSEDTURF" = PASSCLOSEDTURF,
- "LETPASSTHROW" = LETPASSTHROW
- ),
- "movement_type" = list(
- "GROUND" = GROUND,
- "FLYING" = FLYING,
- "VENTCRAWLING" = VENTCRAWLING,
- "FLOATING" = FLOATING,
- "PHASING" = PHASING
- ),
- "resistance_flags" = list(
- "LAVA_PROOF" = LAVA_PROOF,
- "FIRE_PROOF" = FIRE_PROOF,
- "FLAMMABLE" = FLAMMABLE,
- "ON_FIRE" = ON_FIRE,
- "UNACIDABLE" = UNACIDABLE,
- "ACID_PROOF" = ACID_PROOF,
- "INDESTRUCTIBLE" = INDESTRUCTIBLE,
- "FREEZE_PROOF" = FREEZE_PROOF,
- "GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
- "GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS
- ),
- "flags_1" = list(
- "NOJAUNT_1" = NOJAUNT_1,
- "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
- "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
- "HEAR_1" = HEAR_1,
- "DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
- "CONDUCT_1" = CONDUCT_1,
- "NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
- "NODECONSTRUCT_1" = NODECONSTRUCT_1,
- "OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
- "ON_BORDER_1" = ON_BORDER_1,
- "NO_RUINS_1" = NO_RUINS_1,
- "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
- "HOLOGRAM_1" = HOLOGRAM_1,
- "SHOCKED_1" = SHOCKED_1,
- "INITIALIZED_1" = INITIALIZED_1,
- "NO_SCREENTIPS_1" = NO_SCREENTIPS_1,
- "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
- "BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
- "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1
- ),
- "flags_ricochet" = list(
- "RICOCHET_SHINY" = RICOCHET_SHINY,
- "RICOCHET_HARD" = RICOCHET_HARD
- ),
- "clothing_flags" = list(
- "LAVAPROTECT" = LAVAPROTECT,
- "STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE,
- "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT,
- "ALLOWINTERNALS" = ALLOWINTERNALS,
- "NOSLIP" = NOSLIP,
- "THICKMATERIAL" = THICKMATERIAL,
- "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
- "VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
- "IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
- "SCAN_REAGENTS" = SCAN_REAGENTS
- ),
- "zap_flags" = list(
- "ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE,
- "ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
- "ZAP_MOB_STUN" = ZAP_MOB_STUN,
- "ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES,
- "ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE,
- ),
- "smooth" = list(
- "SMOOTH_TRUE" = SMOOTH_TRUE,
- "SMOOTH_MORE" = SMOOTH_MORE,
- "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL,
- "SMOOTH_BORDER" = SMOOTH_BORDER,
- "SMOOTH_QUEUED" = SMOOTH_QUEUED,
- ),
- "reagents_holder_flags" = list(
- "INJECTABLE" = INJECTABLE,
- "DRAWABLE" = DRAWABLE,
- "REFILLABLE" = REFILLABLE,
- "DRAINABLE" = DRAINABLE,
- "TRANSPARENT" = TRANSPARENT,
- "AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
- "NO_REACT" = NO_REACT,
- ),
- "car_traits" = list(
- "CAN_KIDNAP" = CAN_KIDNAP,
- ),
- "rad_flags" = list(
- "RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
- "RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
- ),
- "disease_flags" = list(
- "CURABLE" = CURABLE,
- "CAN_CARRY" = CAN_CARRY,
- "CAN_RESIST" = CAN_RESIST
- ),
- "chemical_flags" = list(
- "REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
- "REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
- "REAGENT_ONLYINVERSE" = REAGENT_ONLYINVERSE,
- "REAGENT_ONMOBMERGE" = REAGENT_ONMOBMERGE,
- "REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
- "REAGENT_FORCEONNEW" = REAGENT_FORCEONNEW,
- "REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
- "REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL,
- "REAGENT_ORGANIC_PROCESS" = REAGENT_ORGANIC_PROCESS,
- "REAGENT_ROBOTIC_PROCESS" = REAGENT_ROBOTIC_PROCESS
- ),
- "clear_conversion" = list(
- "REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
- "REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
- ),
- "organ_flags" = list(
- "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
- "ORGAN_FROZEN" = ORGAN_FROZEN,
- "ORGAN_FAILING" = ORGAN_FAILING,
- "ORGAN_EXTERNAL" = ORGAN_EXTERNAL,
- "ORGAN_VITAL" = ORGAN_VITAL,
- "ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL
- ),
- "genital_flags" = list(
- "GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
- "GENITAL_INTERNAL" = GENITAL_INTERNAL,
- "GENITAL_HIDDEN" = GENITAL_HIDDEN,
- "GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
- "GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
- "CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
- "MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
- "CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH
+GLOBAL_LIST_INIT(bitfields, generate_bitfields())
- ),
- "mob_biotypes" = list (
- "MOB_ORGANIC" = MOB_ORGANIC,
- "MOB_MINERAL" = MOB_MINERAL,
- "MOB_ROBOTIC" = MOB_ROBOTIC,
- "MOB_UNDEAD" = MOB_UNDEAD,
- "MOB_HUMANOID" = MOB_HUMANOID,
- "MOB_BUG" = MOB_BUG,
- "MOB_BEAST" = MOB_BEAST,
- "MOB_EPIC" = MOB_EPIC,
- "MOB_REPTILE" = MOB_REPTILE,
- "MOB_SPIRIT" = MOB_SPIRIT
- ),
- "mobility_flags" = list(
- "MOBILITY_MOVE" = MOBILITY_MOVE,
- "MOBILITY_STAND" = MOBILITY_STAND,
- "MOBILITY_PICKUP" = MOBILITY_PICKUP,
- "MOBILITY_USE" = MOBILITY_USE,
- "MOBILITY_UI" = MOBILITY_UI,
- "MOBILITY_STORAGE" = MOBILITY_STORAGE,
- "MOBILITY_PULL" = MOBILITY_PULL,
- "MOBILITY_HOLD" = MOBILITY_HOLD,
- "MOBILITY_RESIST" = MOBILITY_RESIST
- ),
- "combat_flags" = list(
- "COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED,
- "COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE,
- "COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL,
- "COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT,
- "COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING,
- "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST,
- "COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED
- ),
- "shield_flags" = list(
- "SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
- "SHIELD_ENERGY_WEAK" = SHIELD_ENERGY_WEAK,
- "SHIELD_KINETIC_WEAK" = SHIELD_KINETIC_WEAK,
- "SHIELD_KINETIC_STRONG" = SHIELD_KINETIC_STRONG,
- "SHIELD_ENERGY_STRONG" = SHIELD_ENERGY_STRONG,
- "SHIELD_DISABLER_DISRUPTED" = SHIELD_DISABLER_DISRUPTED,
- "SHIELD_NO_RANGED" = SHIELD_NO_RANGED,
- "SHIELD_NO_MELEE" = SHIELD_NO_MELEE,
- "SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
- "SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
- "SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
- "SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
- "SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
- "SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
- "SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM
- ),
- "storage_flags" = list(
- "STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
- "STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
- "STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS,
- "STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME
- ),
- "mutantrace_variation" = list(
- "STYLE_DIGITIGRADE" = STYLE_DIGITIGRADE,
- "STYLE_MUZZLE" = STYLE_MUZZLE,
- "STYLE_SNEK_TAURIC" = STYLE_SNEK_TAURIC,
- "STYLE_PAW_TAURIC" = STYLE_PAW_TAURIC,
- "STYLE_HOOF_TAURIC" = STYLE_HOOF_TAURIC,
- "STYLE_NO_ANTHRO_ICON" = STYLE_NO_ANTHRO_ICON,
- "USE_SNEK_CLIP_MASK" = USE_SNEK_CLIP_MASK,
- "USE_QUADRUPED_CLIP_MASK" = USE_QUADRUPED_CLIP_MASK
- ),
- "vis_flags" = list(
- "VIS_INHERIT_ICON" = VIS_INHERIT_ICON,
- "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE,
- "VIS_INHERIT_DIR" = VIS_INHERIT_DIR,
- "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER,
- "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE,
- "VIS_INHERIT_ID" = VIS_INHERIT_ID,
- "VIS_UNDERLAY" = VIS_UNDERLAY,
- "VIS_HIDE" = VIS_HIDE
- )
- ))
+/// Specifies a bitfield for smarter debugging
+/datum/bitfield
+ /// The variable name that contains the bitfield
+ var/variable
+
+ /// An associative list of the readable flag and its true value
+ var/list/flags
+
+/// Turns /datum/bitfield subtypes into a list for use in debugging
+/proc/generate_bitfields()
+ var/list/bitfields = list()
+ for (var/_bitfield in subtypesof(/datum/bitfield))
+ var/datum/bitfield/bitfield = new _bitfield
+ bitfields[bitfield.variable] = bitfield.flags
+ return bitfields
+
+DEFINE_BITFIELD(admin_flags, list(
+ "ADMIN" = R_ADMIN,
+ "AUTOLOGIN" = R_AUTOLOGIN,
+ "BAN" = R_BAN,
+ "BUILDMODE" = R_BUILDMODE,
+ "DBRANKS" = R_DBRANKS,
+ "DEBUG" = R_DEBUG,
+ "FUN" = R_FUN,
+ "PERMISSIONS" = R_PERMISSIONS,
+ "POLL" = R_POLL,
+ "POSSESS" = R_POSSESS,
+ "SENSITIVE" = R_SENSITIVE,
+ "SERVER" = R_SERVER,
+ "SOUNDS" = R_SOUNDS,
+ "SPAWN" = R_SPAWN,
+ "STEALTH" = R_STEALTH,
+ "VAREDIT" = R_VAREDIT,
+))
+
+DEFINE_BITFIELD(appearance_flags, list(
+ "KEEP_APART" = KEEP_APART,
+ "KEEP_TOGETHER" = KEEP_TOGETHER,
+ "LONG_GLIDE" = LONG_GLIDE,
+ "NO_CLIENT_COLOR" = NO_CLIENT_COLOR,
+ "PASS_MOUSE" = PASS_MOUSE,
+ "PIXEL_SCALE" = PIXEL_SCALE,
+ "PLANE_MASTER" = PLANE_MASTER,
+ "RESET_ALPHA" = RESET_ALPHA,
+ "RESET_COLOR" = RESET_COLOR,
+ "RESET_TRANSFORM" = RESET_TRANSFORM,
+ "TILE_BOUND" = TILE_BOUND,
+ "TILE_MOVER" = TILE_MOVER,
+))
+
+DEFINE_BITFIELD(area_flags, list(
+ "ABDUCTOR_PROOF" = ABDUCTOR_PROOF,
+ "BLOBS_ALLOWED" = BLOBS_ALLOWED,
+ "BLOCK_SUICIDE" = BLOCK_SUICIDE,
+ "CULT_PERMITTED" = CULT_PERMITTED,
+ "FLORA_ALLOWED" = FLORA_ALLOWED,
+ "HIDDEN_AREA" = HIDDEN_AREA,
+ "MEGAFAUNA_SPAWN_ALLOWED" = MEGAFAUNA_SPAWN_ALLOWED,
+ "MOB_SPAWN_ALLOWED" = MOB_SPAWN_ALLOWED,
+ "NO_ALERTS" = NO_ALERTS,
+ "NOTELEPORT" = NOTELEPORT,
+ "CAVES_ALLOWED" = CAVES_ALLOWED,
+ "UNIQUE_AREA" = UNIQUE_AREA,
+ "VALID_TERRITORY" = VALID_TERRITORY,
+ "XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE,
+ "NO_ALERTS" = NO_ALERTS,
+))
+
+DEFINE_BITFIELD(car_traits, list(
+ "CAN_KIDNAP" = CAN_KIDNAP,
+))
+
+DEFINE_BITFIELD(chemical_flags, list(
+ "REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
+ "REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
+ "REAGENT_FORCEONNEW" = REAGENT_FORCEONNEW,
+ "REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
+ "REAGENT_ONLYINVERSE" = REAGENT_ONLYINVERSE,
+ "REAGENT_ONMOBMERGE" = REAGENT_ONMOBMERGE,
+ "REAGENT_ORGANIC_PROCESS" = REAGENT_ORGANIC_PROCESS,
+ "REAGENT_ROBOTIC_PROCESS" = REAGENT_ROBOTIC_PROCESS,
+ "REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
+ "REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL,
+))
+
+DEFINE_BITFIELD(clear_conversion, list(
+ "REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
+ "REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
+))
+
+DEFINE_BITFIELD(clothing_flags, list(
+ "ALLOWINTERNALS" = ALLOWINTERNALS,
+ "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT,
+ "IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS,
+ "LAVAPROTECT" = LAVAPROTECT,
+ "NOSLIP" = NOSLIP,
+ "SCAN_REAGENTS" = SCAN_REAGENTS,
+ "STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE,
+ "THICKMATERIAL" = THICKMATERIAL,
+ "VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
+ "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
+))
+
+DEFINE_BITFIELD(combat_flags, list(
+ "COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL,
+ "COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT,
+ "COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING,
+ "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST,
+ "COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE,
+ "COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED,
+ "COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED,
+))
+
+DEFINE_BITFIELD(datum_flags, list(
+ "DF_USE_TAG" = DF_USE_TAG,
+ "DF_VAR_EDITED" = DF_VAR_EDITED,
+ "DF_ISPROCESSING" = DF_ISPROCESSING,
+))
+
+DEFINE_BITFIELD(disease_flags, list(
+ "CAN_CARRY" = CAN_CARRY,
+ "CAN_RESIST" = CAN_RESIST,
+ "CURABLE" = CURABLE,
+))
+
+DEFINE_BITFIELD(flags_1, list(
+ "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1,
+ "BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1,
+ "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
+ "CONDUCT_1" = CONDUCT_1,
+ "DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
+ "HEAR_1" = HEAR_1,
+ "HOLOGRAM_1" = HOLOGRAM_1,
+ "INITIALIZED_1" = INITIALIZED_1,
+ "NODECONSTRUCT_1" = NODECONSTRUCT_1,
+ "NOJAUNT_1" = NOJAUNT_1,
+ "NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
+ "NO_RUINS_1" = NO_RUINS_1,
+ "NO_SCREENTIPS_1" = NO_SCREENTIPS_1,
+ "OVERLAY_QUEUED_1" = OVERLAY_QUEUED_1,
+ "ON_BORDER_1" = ON_BORDER_1,
+ "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1,
+ "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1,
+ "SHOCKED_1" = SHOCKED_1,
+ "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
+))
+
+DEFINE_BITFIELD(flags_ricochet, list(
+ "RICOCHET_SHINY" = RICOCHET_SHINY,
+ "RICOCHET_HARD" = RICOCHET_HARD
+))
+
+DEFINE_BITFIELD(genital_flags, list(
+ "CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH,
+ "CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
+ "GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
+ "GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
+ "GENITAL_HIDDEN" = GENITAL_HIDDEN,
+ "GENITAL_INTERNAL" = GENITAL_INTERNAL,
+ "GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
+ "MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
+))
+
+DEFINE_BITFIELD(interaction_flags_atom, list(
+ "INTERACT_ATOM_ATTACK_HAND" = INTERACT_ATOM_ATTACK_HAND,
+ "INTERACT_ATOM_CHECK_GRAB" = INTERACT_ATOM_CHECK_GRAB,
+ "INTERACT_ATOM_IGNORE_INCAPACITATED" = INTERACT_ATOM_IGNORE_INCAPACITATED,
+ "INTERACT_ATOM_IGNORE_RESTRAINED" = INTERACT_ATOM_IGNORE_RESTRAINED,
+ "INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND" = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND,
+ "INTERACT_ATOM_NO_FINGERPRINT_INTERACT" = INTERACT_ATOM_NO_FINGERPRINT_INTERACT,
+ "INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED,
+ "INTERACT_ATOM_REQUIRES_DEXTERITY" = INTERACT_ATOM_REQUIRES_DEXTERITY,
+ "INTERACT_ATOM_UI_INTERACT" = INTERACT_ATOM_UI_INTERACT,
+))
+
+DEFINE_BITFIELD(interaction_flags_machine, list(
+ "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON,
+ "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE,
+ "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN,
+ "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON,
+ "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON,
+ "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE,
+ "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN,
+))
+
+DEFINE_BITFIELD(interaction_flags_item, list(
+ "INTERACT_ITEM_ATTACK_HAND_PICKUP" = INTERACT_ITEM_ATTACK_HAND_PICKUP,
+))
+
+DEFINE_BITFIELD(item_flags, list(
+ "ABSTRACT" = ABSTRACT,
+ "BEING_REMOVED" = BEING_REMOVED,
+ "DROPDEL" = DROPDEL,
+ "FORCE_STRING_OVERRIDE" = FORCE_STRING_OVERRIDE,
+ "IN_INVENTORY" = IN_INVENTORY,
+ "IN_STORAGE" = IN_STORAGE,
+ "ITEM_CAN_BLOCK" = ITEM_CAN_BLOCK,
+ "ITEM_CAN_PARRY" = ITEM_CAN_PARRY,
+ "NEEDS_PERMIT" = NEEDS_PERMIT,
+ "NOBLUDGEON" = NOBLUDGEON,
+ "NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION,
+ "SLOWS_WHILE_IN_HAND" = SLOWS_WHILE_IN_HAND,
+))
+
+DEFINE_BITFIELD(mob_biotypes, list(
+ "MOB_BEAST" = MOB_BEAST,
+ "MOB_BUG" = MOB_BUG,
+ "MOB_EPIC" = MOB_EPIC,
+ "MOB_HUMANOID" = MOB_HUMANOID,
+ "MOB_MINERAL" = MOB_MINERAL,
+ "MOB_ORGANIC" = MOB_ORGANIC,
+ "MOB_REPTILE" = MOB_REPTILE,
+ "MOB_ROBOTIC" = MOB_ROBOTIC,
+ "MOB_SPIRIT" = MOB_SPIRIT,
+ "MOB_UNDEAD" = MOB_UNDEAD,
+))
+
+DEFINE_BITFIELD(mobility_flags, list(
+ "MOBILITY_HOLD" = MOBILITY_HOLD,
+ "MOBILITY_MOVE" = MOBILITY_MOVE,
+ "MOBILITY_PICKUP" = MOBILITY_PICKUP,
+ "MOBILITY_PULL" = MOBILITY_PULL,
+ "MOBILITY_RESIST" = MOBILITY_RESIST,
+ "MOBILITY_STAND" = MOBILITY_STAND,
+ "MOBILITY_STORAGE" = MOBILITY_STORAGE,
+ "MOBILITY_UI" = MOBILITY_UI,
+ "MOBILITY_USE" = MOBILITY_USE,
+))
+
+DEFINE_BITFIELD(movement_type, list(
+ "FLOATING" = FLOATING,
+ "FLYING" = FLYING,
+ "GROUND" = GROUND,
+ "PHASING" = PHASING,
+ "VENTCRAWLING" = VENTCRAWLING,
+))
+
+DEFINE_BITFIELD(mutantrace_variation, list(
+ "STYLE_DIGITIGRADE" = STYLE_DIGITIGRADE,
+ "STYLE_HOOF_TAURIC" = STYLE_HOOF_TAURIC,
+ "STYLE_MUZZLE" = STYLE_MUZZLE,
+ "STYLE_NO_ANTHRO_ICON" = STYLE_NO_ANTHRO_ICON,
+ "STYLE_PAW_TAURIC" = STYLE_PAW_TAURIC,
+ "STYLE_SNEK_TAURIC" = STYLE_SNEK_TAURIC,
+ "USE_SNEK_CLIP_MASK" = USE_SNEK_CLIP_MASK,
+ "USE_QUADRUPED_CLIP_MASK" = USE_QUADRUPED_CLIP_MASK,
+))
+
+DEFINE_BITFIELD(obj_flags, list(
+ "BEING_SHOCKED" = BEING_SHOCKED,
+ "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN,
+ "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP,
+ "BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN,
+ "BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP,
+ "CAN_BE_HIT" = CAN_BE_HIT,
+ "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION,
+ "EMAGGED" = EMAGGED,
+ "EXAMINE_SKIP" = EXAMINE_SKIP,
+ "FROZEN" = FROZEN,
+ "IN_USE" = IN_USE,
+ "ON_BLUEPRINTS" = ON_BLUEPRINTS,
+ "SHOVABLE_ONTO" = SHOVABLE_ONTO,
+ "UNIQUE_RENAME" = UNIQUE_RENAME,
+ "USES_TGUI" = USES_TGUI,
+))
+
+DEFINE_BITFIELD(organ_flags, list(
+ "ORGAN_EXTERNAL" = ORGAN_EXTERNAL,
+ "ORGAN_FAILING" = ORGAN_FAILING,
+ "ORGAN_FROZEN" = ORGAN_FROZEN,
+ "ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL,
+ "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
+ "ORGAN_VITAL" = ORGAN_VITAL,
+))
+
+DEFINE_BITFIELD(pass_flags, list(
+ "LETPASSTHROW" = LETPASSTHROW,
+ "PASSBLOB" = PASSBLOB,
+ "PASSCLOSEDTURF" = PASSCLOSEDTURF,
+ "PASSGLASS" = PASSGLASS,
+ "PASSGRILLE" = PASSGRILLE,
+ "PASSMOB" = PASSMOB,
+ "PASSTABLE" = PASSTABLE,
+))
+
+DEFINE_BITFIELD(rad_flags, list(
+ "RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
+ "RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
+))
+
+DEFINE_BITFIELD(reagents_holder_flags, list(
+ "AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
+ "DRAINABLE" = DRAINABLE,
+ "DRAWABLE" = DRAWABLE,
+ "INJECTABLE" = INJECTABLE,
+ "NO_REACT" = NO_REACT,
+ "REFILLABLE" = REFILLABLE,
+ "TRANSPARENT" = TRANSPARENT,
+))
+
+DEFINE_BITFIELD(resistance_flags, list(
+ "ACID_PROOF" = ACID_PROOF,
+ "FIRE_PROOF" = FIRE_PROOF,
+ "FLAMMABLE" = FLAMMABLE,
+ "FREEZE_PROOF" = FREEZE_PROOF,
+ "GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
+ "GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS,
+ "INDESTRUCTIBLE" = INDESTRUCTIBLE,
+ "LAVA_PROOF" = LAVA_PROOF,
+ "ON_FIRE" = ON_FIRE,
+ "UNACIDABLE" = UNACIDABLE,
+))
+
+DEFINE_BITFIELD(shield_flags, list(
+ "SHIELD_BASH_ALWAYS_DISARM" = SHIELD_BASH_ALWAYS_DISARM,
+ "SHIELD_BASH_ALWAYS_KNOCKDOWN" = SHIELD_BASH_ALWAYS_KNOCKDOWN,
+ "SHIELD_BASH_GROUND_SLAM" = SHIELD_BASH_GROUND_SLAM,
+ "SHIELD_BASH_GROUND_SLAM_DISARM" = SHIELD_BASH_GROUND_SLAM_DISARM,
+ "SHIELD_BASH_WALL_DISARM" = SHIELD_BASH_WALL_DISARM,
+ "SHIELD_BASH_WALL_KNOCKDOWN" = SHIELD_BASH_WALL_KNOCKDOWN,
+ "SHIELD_CAN_BASH" = SHIELD_CAN_BASH,
+ "SHIELD_DISABLER_DISRUPTED" = SHIELD_DISABLER_DISRUPTED,
+ "SHIELD_ENERGY_STRONG" = SHIELD_ENERGY_STRONG,
+ "SHIELD_ENERGY_WEAK" = SHIELD_ENERGY_WEAK,
+ "SHIELD_KINETIC_STRONG" = SHIELD_KINETIC_STRONG,
+ "SHIELD_KINETIC_WEAK" = SHIELD_KINETIC_WEAK,
+ "SHIELD_NO_MELEE" = SHIELD_NO_MELEE,
+ "SHIELD_NO_RANGED" = SHIELD_NO_RANGED,
+ "SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT,
+))
+
+DEFINE_BITFIELD(sight, list(
+ "BLIND" = BLIND,
+ "SEE_BLACKNESS" = SEE_BLACKNESS,
+ "SEE_INFRA" = SEE_INFRA,
+ "SEE_MOBS" = SEE_MOBS,
+ "SEE_OBJS" = SEE_OBJS,
+ "SEE_PIXELS" = SEE_PIXELS,
+ "SEE_SELF" = SEE_SELF,
+ "SEE_THRU" = SEE_THRU,
+ "SEE_TURFS" = SEE_TURFS,
+))
+
+DEFINE_BITFIELD(smooth, list(
+ "SMOOTH_BORDER" = SMOOTH_BORDER,
+ "SMOOTH_DIAGONAL" = SMOOTH_DIAGONAL,
+ "SMOOTH_MORE" = SMOOTH_MORE,
+ "SMOOTH_QUEUED" = SMOOTH_QUEUED,
+ "SMOOTH_TRUE" = SMOOTH_TRUE,
+))
+
+DEFINE_BITFIELD(storage_flags, list(
+ "STORAGE_LIMIT_COMBINED_W_CLASS" = STORAGE_LIMIT_COMBINED_W_CLASS,
+ "STORAGE_LIMIT_MAX_ITEMS" = STORAGE_LIMIT_MAX_ITEMS,
+ "STORAGE_LIMIT_MAX_W_CLASS" = STORAGE_LIMIT_MAX_W_CLASS,
+ "STORAGE_LIMIT_VOLUME" = STORAGE_LIMIT_VOLUME,
+))
+
+DEFINE_BITFIELD(vis_flags, list(
+ "VIS_HIDE" = VIS_HIDE,
+ "VIS_INHERIT_DIR" = VIS_INHERIT_DIR,
+ "VIS_INHERIT_ICON" = VIS_INHERIT_ICON,
+ "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE,
+ "VIS_INHERIT_ID" = VIS_INHERIT_ID,
+ "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER,
+ "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE,
+ "VIS_UNDERLAY" = VIS_UNDERLAY,
+))
+
+DEFINE_BITFIELD(zap_flags, list(
+ "ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES,
+ "ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE,
+ "ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE,
+ "ZAP_MOB_STUN" = ZAP_MOB_STUN,
+ "ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
+))
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index da8b0ed3ee..ff5829ff73 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -43,6 +43,10 @@ GLOBAL_LIST_EMPTY(arachnid_spinneret_list)
GLOBAL_LIST_EMPTY(arachnid_mandibles_list)
GLOBAL_LIST_EMPTY(caps_list)
+ //Bark bits
+GLOBAL_LIST_EMPTY(bark_list)
+GLOBAL_LIST_EMPTY(bark_random_list)
+
//a way to index the right bodypart list given the type of bodypart
GLOBAL_LIST_INIT(mutant_reference_list, list(
"tail_lizard" = GLOB.tails_list_lizard,
diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm
index 3f3d9c5e25..e9c38546a7 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -49,6 +49,8 @@ GLOBAL_VAR(tgui_log)
GLOBAL_PROTECT(tgui_log)
GLOBAL_VAR(world_shuttle_log)
GLOBAL_PROTECT(world_shuttle_log)
+GLOBAL_VAR(world_econ_log)
+GLOBAL_PROTECT(world_econ_log)
GLOBAL_VAR(perf_log)
GLOBAL_PROTECT(perf_log)
diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm
index ae853a4e1a..58c182036d 100644
--- a/code/_onclick/drag_drop.dm
+++ b/code/_onclick/drag_drop.dm
@@ -101,14 +101,6 @@
..()
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
- var/list/L = params2list(params)
- if (L["middle"])
- if (src_object && src_location != over_location)
- middragtime = world.time
- middragatom = src_object
- else
- middragtime = 0
- middragatom = null
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
@@ -121,9 +113,3 @@
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
-
-/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
- if (middragatom == src_object)
- middragtime = 0
- middragatom = null
- ..()
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 53ad775954..5029d51452 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -60,7 +60,7 @@
if(client && hud_used)
hud_used.reorganize_alerts()
thealert.transform = matrix(32, 6, MATRIX_TRANSLATE)
- animate(thealert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
+ animate(thealert, transform = matrix(), time = 2.5, easing = BACK_EASING)
if(thealert.timeout)
addtimer(CALLBACK(src, .proc/alert_timeout, thealert, category), thealert.timeout)
diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm
new file mode 100644
index 0000000000..b426db1aac
--- /dev/null
+++ b/code/_onclick/hud/new_player.dm
@@ -0,0 +1,333 @@
+/datum/hud/new_player
+
+/datum/hud/new_player/proc/populate_buttons(mob/dead/new_player/owner)
+ var/list/buttons = subtypesof(/atom/movable/screen/lobby)
+ for(var/button_type in buttons)
+ var/atom/movable/screen/lobby/lobbyscreen = new button_type()
+ lobbyscreen.SlowInit()
+ lobbyscreen.hud = src
+ static_inventory += lobbyscreen
+ if(istype(lobbyscreen, /atom/movable/screen/lobby/button))
+ var/atom/movable/screen/lobby/button/lobby_button = lobbyscreen
+ lobby_button.owner = REF(owner)
+ show_hud(hud_version)
+
+/atom/movable/screen/lobby
+ plane = SPLASHSCREEN_PLANE
+ layer = LOBBY_BUTTON_LAYER
+ screen_loc = "TOP,CENTER"
+
+/// Run sleeping actions after initialize
+/atom/movable/screen/lobby/proc/SlowInit()
+ return
+
+/atom/movable/screen/lobby/background
+ layer = LOBBY_BACKGROUND_LAYER
+ icon = 'icons/hud/lobby/background.dmi'
+ icon_state = "background"
+ screen_loc = "TOP,CENTER:-61"
+
+/atom/movable/screen/lobby/button
+ ///Is the button currently enabled?
+ var/enabled = TRUE
+ ///Is the button currently being hovered over with the mouse?
+ var/highlighted = FALSE
+ /// The ref of the mob that owns this button. Only the owner can click on it.
+ var/owner
+
+/atom/movable/screen/lobby/button/Click(location, control, params)
+ if(owner != REF(usr))
+ return
+
+ . = ..()
+
+ if(!enabled)
+ return
+ flick("[base_icon_state]_pressed", src)
+ update_appearance(UPDATE_ICON)
+ return TRUE
+
+/atom/movable/screen/lobby/button/MouseEntered(location,control,params)
+ if(owner != REF(usr))
+ return
+
+ . = ..()
+ highlighted = TRUE
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/lobby/button/MouseExited()
+ if(owner != REF(usr))
+ return
+
+ . = ..()
+ highlighted = FALSE
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/lobby/button/update_icon(updates)
+ . = ..()
+ if(!enabled)
+ icon_state = "[base_icon_state]_disabled"
+ return
+ else if(highlighted)
+ icon_state = "[base_icon_state]_highlighted"
+ return
+ icon_state = base_icon_state
+
+/atom/movable/screen/lobby/button/proc/set_button_status(status)
+ if(status == enabled)
+ return FALSE
+ enabled = status
+ update_appearance(UPDATE_ICON)
+ return TRUE
+
+///Prefs menu
+/atom/movable/screen/lobby/button/character_setup
+ screen_loc = "TOP:-70,CENTER:-54"
+ icon = 'icons/hud/lobby/character_setup.dmi'
+ icon_state = "character_setup"
+ base_icon_state = "character_setup"
+
+/atom/movable/screen/lobby/button/character_setup/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ hud.mymob.client.prefs.current_tab = SETTINGS_TAB
+ hud.mymob.client.prefs.ShowChoices(hud.mymob)
+
+///Button that appears before the game has started
+/atom/movable/screen/lobby/button/ready
+ screen_loc = "TOP:-8,CENTER:-65"
+ icon = 'icons/hud/lobby/ready.dmi'
+ icon_state = "not_ready"
+ base_icon_state = "not_ready"
+ var/ready = FALSE
+
+/atom/movable/screen/lobby/button/ready/Initialize(mapload)
+ . = ..()
+ switch(SSticker.current_state)
+ if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
+ if(GAME_STATE_SETTING_UP)
+ set_button_status(FALSE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
+ else
+ set_button_status(FALSE)
+
+/atom/movable/screen/lobby/button/ready/proc/hide_ready_button()
+ SIGNAL_HANDLER
+ set_button_status(FALSE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
+
+/atom/movable/screen/lobby/button/ready/proc/show_ready_button()
+ SIGNAL_HANDLER
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
+
+/atom/movable/screen/lobby/button/ready/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ ready = !ready
+ if(ready)
+ new_player.ready = PLAYER_READY_TO_PLAY
+ base_icon_state = "ready"
+ else
+ new_player.ready = PLAYER_NOT_READY
+ base_icon_state = "not_ready"
+ update_appearance(UPDATE_ICON)
+
+///Shown when the game has started
+/atom/movable/screen/lobby/button/join
+ screen_loc = "TOP:-13,CENTER:-58"
+ icon = 'icons/hud/lobby/join.dmi'
+ icon_state = "" //Default to not visible
+ base_icon_state = "join_game"
+ enabled = FALSE
+
+/atom/movable/screen/lobby/button/join/Initialize(mapload)
+ . = ..()
+ switch(SSticker.current_state)
+ if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
+ if(GAME_STATE_SETTING_UP)
+ set_button_status(TRUE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
+ else
+ set_button_status(TRUE)
+
+/atom/movable/screen/lobby/button/join/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ if(!SSticker?.IsRoundInProgress())
+ to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished..."))
+ return
+
+ //Determines Relevent Population Cap
+ var/relevant_cap
+ var/hpc = CONFIG_GET(number/hard_popcap)
+ var/epc = CONFIG_GET(number/extreme_popcap)
+ if(hpc && epc)
+ relevant_cap = min(hpc, epc)
+ else
+ relevant_cap = max(hpc, epc)
+
+ var/mob/dead/new_player/new_player = hud.mymob
+
+ if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(new_player.key) in GLOB.admin_datums)))
+ to_chat(new_player, span_danger("[CONFIG_GET(string/hard_popcap_message)]"))
+
+ var/queue_position = SSticker.queued_players.Find(new_player)
+ if(queue_position == 1)
+ to_chat(new_player, span_notice("You are next in line to join the game. You will be notified when a slot opens up."))
+ else if(queue_position)
+ to_chat(new_player, span_notice("There are [queue_position-1] players in front of you in the queue to join the game."))
+ else
+ SSticker.queued_players += new_player
+ to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len]."))
+ return
+ new_player.LateChoices()
+
+/atom/movable/screen/lobby/button/join/proc/show_join_button()
+ SIGNAL_HANDLER
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
+
+/atom/movable/screen/lobby/button/join/proc/hide_join_button()
+ SIGNAL_HANDLER
+ set_button_status(FALSE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
+
+/atom/movable/screen/lobby/button/observe
+ screen_loc = "TOP:-40,CENTER:-54"
+ icon = 'icons/hud/lobby/observe.dmi'
+ icon_state = "observe_disabled"
+ base_icon_state = "observe"
+ enabled = FALSE
+
+/atom/movable/screen/lobby/button/observe/Initialize(mapload)
+ . = ..()
+ if(SSticker.current_state > GAME_STATE_STARTUP)
+ set_button_status(TRUE)
+ else
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
+
+/atom/movable/screen/lobby/button/observe/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.make_me_an_observer()
+
+/atom/movable/screen/lobby/button/observe/proc/enable_observing()
+ SIGNAL_HANDLER
+ flick("[base_icon_state]_enabled", src)
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
+
+/atom/movable/screen/lobby/button/settings
+ icon = 'icons/hud/lobby/bottom_buttons.dmi'
+ icon_state = "settings"
+ base_icon_state = "settings"
+ screen_loc = "TOP:-122,CENTER:+30"
+
+/atom/movable/screen/lobby/button/settings/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+
+ hud.mymob.client.prefs.current_tab = GAME_PREFERENCES_TAB
+ hud.mymob.client.prefs.ShowChoices(hud.mymob)
+
+/atom/movable/screen/lobby/button/changelog_button
+ icon = 'icons/hud/lobby/bottom_buttons.dmi'
+ icon_state = "changelog"
+ base_icon_state = "changelog"
+ screen_loc ="TOP:-122,CENTER:+58"
+
+
+/atom/movable/screen/lobby/button/crew_manifest
+ icon = 'icons/hud/lobby/bottom_buttons.dmi'
+ icon_state = "crew_manifest"
+ base_icon_state = "crew_manifest"
+ screen_loc = "TOP:-122,CENTER:+2"
+
+/atom/movable/screen/lobby/button/crew_manifest/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.ViewManifest()
+
+/atom/movable/screen/lobby/button/changelog_button/Click(location, control, params)
+ . = ..()
+ usr.client?.changelog()
+
+/atom/movable/screen/lobby/button/poll
+ icon = 'icons/hud/lobby/bottom_buttons.dmi'
+ icon_state = "poll"
+ base_icon_state = "poll"
+ screen_loc = "TOP:-122,CENTER:-26"
+
+ var/new_poll = FALSE
+
+/atom/movable/screen/lobby/button/poll/SlowInit(mapload)
+ . = ..()
+ if(!usr)
+ return
+ var/mob/dead/new_player/new_player = usr
+ if(is_guest_key(new_player.key))
+ set_button_status(FALSE)
+ return
+ if(!SSdbcore.Connect())
+ set_button_status(FALSE)
+ return
+ var/isadmin = FALSE
+ if(new_player.client?.holder)
+ isadmin = TRUE
+ var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
+ SELECT id FROM [format_table_name("poll_question")]
+ WHERE (adminonly = 0 OR :isadmin = 1)
+ AND Now() BETWEEN starttime AND endtime
+ AND deleted = 0
+ AND id NOT IN (
+ SELECT pollid FROM [format_table_name("poll_vote")]
+ WHERE ckey = :ckey
+ AND deleted = 0
+ )
+ AND id NOT IN (
+ SELECT pollid FROM [format_table_name("poll_textreply")]
+ WHERE ckey = :ckey
+ AND deleted = 0
+ )
+ "}, list("isadmin" = isadmin, "ckey" = new_player.ckey))
+ if(!query_get_new_polls.Execute())
+ qdel(query_get_new_polls)
+ set_button_status(FALSE)
+ return
+ if(query_get_new_polls.NextRow())
+ new_poll = TRUE
+ else
+ new_poll = FALSE
+ update_appearance(UPDATE_OVERLAYS)
+ qdel(query_get_new_polls)
+ if(QDELETED(new_player))
+ set_button_status(FALSE)
+ return
+
+/atom/movable/screen/lobby/button/poll/update_overlays()
+ . = ..()
+ if(new_poll)
+ . += mutable_appearance('icons/hud/lobby/poll_overlay.dmi', "new_poll")
+
+/atom/movable/screen/lobby/button/poll/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.handle_player_polling()
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm
index 0070362f8b..935379b721 100644
--- a/code/_onclick/hud/radial.dm
+++ b/code/_onclick/hud/radial.dm
@@ -178,7 +178,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
starting.Scale(0.1,0.1)
E.transform = starting
var/matrix/TM = matrix()
- animate(E,pixel_x = px,pixel_y = py, transform = TM, time = timing)
+ animate(E,pixel_x = px,pixel_y = py, transform = TM, time = timing, easing = SINE_EASING | EASE_OUT)
else
E.pixel_y = py
E.pixel_x = px
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 8f3a7ef02c..23486cac29 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -126,6 +126,8 @@
return DISCARD_LAST_ACTION
user.do_attack_animation(O)
O.attacked_by(src, user)
+ if(force >= 20)
+ shake_camera(user, ((force - 15) * 0.01 + 1), ((force - 15) * 0.01))
/atom/movable/proc/attacked_by()
return
diff --git a/code/_rendering/atom_huds/atom_hud.dm b/code/_rendering/atom_huds/atom_hud.dm
index 07b403284b..c89fe33db8 100644
--- a/code/_rendering/atom_huds/atom_hud.dm
+++ b/code/_rendering/atom_huds/atom_hud.dm
@@ -29,7 +29,9 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(),
ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(),
- ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden()
+ ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden(),
+ ANTAG_HUD_SPACECOP = new/datum/atom_hud/antag(),
+ ANTAG_HUD_GANGSTER = new/datum/atom_hud/antag/hidden()
))
/datum/atom_hud
diff --git a/code/_rendering/parallax/parallax_holder.dm b/code/_rendering/parallax/parallax_holder.dm
index cbe095c02b..1f7d84ae11 100644
--- a/code/_rendering/parallax/parallax_holder.dm
+++ b/code/_rendering/parallax/parallax_holder.dm
@@ -248,7 +248,7 @@
if(P.absolute)
continue
var/matrix/translate_matrix = matrix()
- translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
+ translate_matrix.Translate(sin(turn) * 480, cos(turn) * 480)
var/matrix/target_matrix = matrix()
var/move_speed = speed * P.speed
// do the first segment by shifting down one screen
@@ -282,7 +282,7 @@
continue
P.CancelAnimation()
var/matrix/translate_matrix = matrix()
- translate_matrix.Translate(cos(turn) * 480, sin(turn) * 480)
+ translate_matrix.Translate(sin(turn) * 480, cos(turn) * 480)
P.transform = translate_matrix
animate(P, transform = matrix(), time = time, easing = QUAD_EASING | EASE_OUT)
diff --git a/code/controllers/configuration/entries/bot.dm b/code/controllers/configuration/entries/bot.dm
new file mode 100644
index 0000000000..071406ad65
--- /dev/null
+++ b/code/controllers/configuration/entries/bot.dm
@@ -0,0 +1,14 @@
+/datum/config_entry/flag/irc_announce_new_game
+ deprecated_by = /datum/config_entry/string/chat_announce_new_game
+
+/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
+ return "" //default broadcast
+
+/datum/config_entry/string/chat_announce_new_game
+ config_entry_value = null
+
+/datum/config_entry/string/chat_reboot_role
+
+/datum/config_entry/string/chat_roundend_notice_tag
+
+/datum/config_entry/string/chat_squawk_tag
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 9966f90ce7..b7a92ee48f 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -39,16 +39,6 @@
/datum/config_entry/flag/show_irc_name
-/datum/config_entry/flag/irc_announce_new_game
- deprecated_by = /datum/config_entry/string/chat_announce_new_game
-
-/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
- return "" //default broadcast
-
-/datum/config_entry/string/chat_announce_new_game
-
- config_entry_value = null
-
/datum/config_entry/string/default_view
config_entry_value = "15x15"
diff --git a/code/controllers/configuration/entries/logging.dm b/code/controllers/configuration/entries/logging.dm
index 52e4743a22..81013d8030 100644
--- a/code/controllers/configuration/entries/logging.dm
+++ b/code/controllers/configuration/entries/logging.dm
@@ -79,6 +79,10 @@
/datum/config_entry/flag/log_telecomms
config_entry_value = TRUE
+/// log economy
+/datum/config_entry/flag/log_econ
+ config_entry_value = TRUE
+
/// log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_twitter
config_entry_value = TRUE
diff --git a/code/controllers/subsystem/autotransfer.dm b/code/controllers/subsystem/autotransfer.dm
index 0afa07939e..4b4405c8cf 100644
--- a/code/controllers/subsystem/autotransfer.dm
+++ b/code/controllers/subsystem/autotransfer.dm
@@ -31,7 +31,7 @@ SUBSYSTEM_DEF(autotransfer)
if(world.time < targettime)
return
if(maxvotes == NO_MAXVOTES_CAP || maxvotes > curvotes)
- SSvote.initiate_vote("transfer","server")
+ SSvote.initiate_vote("transfer","server", votesystem=APPROVAL_VOTING)
targettime = targettime + voteinterval
curvotes++
else
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 2153325940..643811368c 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -367,9 +367,14 @@ SUBSYSTEM_DEF(job)
JobDebug("DO, Handling unrejectable unassigned")
//Mop up people who can't leave.
for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
- if(!GiveRandomJob(player))
- if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them an assistant
- return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
+ if(player.client.prefs.joblessrole == BERANDOMJOB) //Gives the player a random role if their preferences are set to it
+ if(!GiveRandomJob(player))
+ if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them the overflow role
+ return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
+ else //If the player prefers to return to lobby or be an assistant, give them assistant
+ if(!AssignRole(player, SSjob.overflow_role))
+ if(!GiveRandomJob(player)) //The forced antagonist couldn't be assigned to overflow role (bans, client age) - give a random role
+ return FALSE //Somehow the forced antagonist couldn't be assigned to the overflow role or the a random role - reroll
return validate_required_jobs(required_jobs)
diff --git a/code/controllers/subsystem/jukeboxes.dm b/code/controllers/subsystem/jukeboxes.dm
index 7be6d44a7f..1e457703c2 100644
--- a/code/controllers/subsystem/jukeboxes.dm
+++ b/code/controllers/subsystem/jukeboxes.dm
@@ -1,3 +1,19 @@
+//As a brief warning to all those who dare tread upon these grounds:
+//The bulk of this code here was written years ago, back in the days of 512.
+//We were incredibly drunk back then. And nowadays, we've found that being drunk is a hard requirement for working with this code.
+//So if you're here to make changes? Brandish a glass. There are many sins here, but it's exactly as engineered as it needs to be.
+//We physically won't be able to tell you what half of this code does. The only thing that'll help you here is the ballmer peak.
+//Bottoms up, friend. And be sure to drink responsibly. Be sure to fetch some water, too; it eases the hangover. - Bhijn & Myr
+
+
+// Jukelist indices
+#define JUKE_TRACK 1
+#define JUKE_CHANNEL 2
+#define JUKE_BOX 3
+#define JUKE_FALLOFF 4
+#define JUKE_SOUND 5
+
+
SUBSYSTEM_DEF(jukeboxes)
name = "Jukeboxes"
wait = 5
@@ -25,27 +41,41 @@ SUBSYSTEM_DEF(jukeboxes)
var/channeltoreserve = pick(freejukeboxchannels)
if(!channeltoreserve)
return FALSE
+ var/sound/song_to_init = sound(T.song_path)
freejukeboxchannels -= channeltoreserve
- var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
+ var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff, song_to_init)
+
+ song_to_init.status = SOUND_MUTE
+ song_to_init.environment = 7
+ song_to_init.channel = channeltoreserve
+ song_to_init.volume = 1
+ song_to_init.falloff = jukefalloff
+ song_to_init.echo = list(0, null, -10000, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
+
activejukeboxes.len++
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
- //Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
- //Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
- var/sound/song_to_init = sound(T.song_path)
- song_to_init.status = SOUND_MUTE
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
continue
- M.playsound_local(M, null, 100, channel = youvegotafreejukebox[2], S = song_to_init)
+ SEND_SOUND(M, song_to_init)
return activejukeboxes.len
+
+//Updates jukebox by transferring to different object or modifying falloff.
+/datum/controller/subsystem/jukeboxes/proc/updatejukebox(IDtoupdate, obj/jukebox, jukefalloff)
+ if(islist(activejukeboxes[IDtoupdate]))
+ if(istype(jukebox))
+ activejukeboxes[IDtoupdate][JUKE_BOX] = jukebox
+ if(!isnull(jukefalloff))
+ activejukeboxes[IDtoupdate][JUKE_FALLOFF] = jukefalloff
+
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
if(islist(activejukeboxes[IDtoremove]))
- var/jukechannel = activejukeboxes[IDtoremove][2]
+ var/jukechannel = activejukeboxes[IDtoremove][JUKE_CHANNEL]
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
@@ -85,37 +115,74 @@ SUBSYSTEM_DEF(jukeboxes)
if(!jukeinfo.len)
stack_trace("Active jukebox without any associated metadata.")
continue
- var/datum/track/juketrack = jukeinfo[1]
+ var/datum/track/juketrack = jukeinfo[JUKE_TRACK]
if(!istype(juketrack))
stack_trace("Invalid jukebox track datum.")
continue
- var/obj/jukebox = jukeinfo[3]
+ var/obj/jukebox = jukeinfo[JUKE_BOX]
if(!istype(jukebox))
stack_trace("Nonexistant or invalid object associated with jukebox.")
continue
- var/sound/song_played = sound(juketrack.song_path)
+
+ var/list/audible_zlevels = get_multiz_accessible_levels(jukebox.z) //TODO - for multiz refresh, this should use the cached zlevel connections var in SSMapping. For now this is fine!
+
+ var/sound/song_played = jukeinfo[JUKE_SOUND]
var/turf/currentturf = get_turf(jukebox)
var/area/currentarea = get_area(jukebox)
var/list/hearerscache = hearers(7, jukebox)
+ var/targetfalloff = jukeinfo[JUKE_FALLOFF]
+ var/mixes = ((targetfalloff*250)-750)
+ var/inrange
+ var/pressure_factor
- song_played.falloff = jukeinfo[4]
+
+ var/datum/gas_mixture/source_env = (istype(currentturf) ? currentturf.return_air() : null)
+ var/datum/gas_mixture/hearer_env //We init this var outside of the mob loop for the sake of performance
+ var/turf/hearerturf //ditto
+
+ var/source_pressure = (istype(source_env) ? source_env.return_pressure() : 0)
+
+ song_played.falloff = targetfalloff
+ song_played.volume = min((targetfalloff * 50), 100)
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
- if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS) || !M.can_hear())
- M.stop_sound_channel(jukeinfo[2])
+ if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
+ M.stop_sound_channel(jukeinfo[JUKE_CHANNEL])
continue
- var/inrange = FALSE
- if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master
- song_played.status = SOUND_UPDATE
- if(get_area(M) == currentarea)
- inrange = TRUE
- else if(M in hearerscache)
- inrange = TRUE
- else
- song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame.
- M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000))
+ inrange = FALSE
+ song_played.status = SOUND_MUTE | SOUND_UPDATE
+
+ if(source_pressure)
+ hearerturf = get_turf(M)
+ hearer_env = (istype(hearerturf) ? hearerturf.return_air() : null)
+ if(istype(hearer_env))
+ pressure_factor = min(source_pressure, hearer_env.return_pressure())
+
+ if(pressure_factor && targetfalloff && M.can_hear() && (hearerturf.z in audible_zlevels))
+ if(get_area(hearerturf) == currentarea)
+ inrange = TRUE
+ else if(M in hearerscache)
+ inrange = TRUE
+
+ song_played.x = (currentturf.x - hearerturf.x) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
+ song_played.z = (currentturf.y - hearerturf.y) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
+ song_played.y = (((currentturf.z - hearerturf.z) * 10 * SOUND_DEFAULT_DISTANCE_MULTIPLIER) + ((currentturf.z < hearerturf.z) ? -5 : 5))
+
+ if(pressure_factor < ONE_ATMOSPHERE)
+ song_played.volume = (min((targetfalloff * 50), 100) * max((pressure_factor - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 1))
+
+ song_played.echo[1] = (inrange ? 0 : -10000)
+ song_played.echo[3] = (inrange ? mixes : max(mixes, 0))
+ song_played.status = SOUND_UPDATE
+ SEND_SOUND(M, song_played)
CHECK_TICK
return
+
+#undef JUKE_TRACK
+#undef JUKE_CHANNEL
+#undef JUKE_BOX
+#undef JUKE_FALLOFF
+#undef JUKE_SOUND
diff --git a/code/controllers/subsystem/persistence/polly_parrot.dm b/code/controllers/subsystem/persistence/polly_parrot.dm
new file mode 100644
index 0000000000..b0014c249a
--- /dev/null
+++ b/code/controllers/subsystem/persistence/polly_parrot.dm
@@ -0,0 +1,11 @@
+/**
+ * Persists polly messages across rounds
+ */
+/datum/controller/subsystem/persistence/LoadGamePersistence()
+ . = ..()
+ LoadPolly()
+
+/datum/controller/subsystem/persistence/proc/LoadPolly()
+ for(var/mob/living/simple_animal/parrot/Polly/P in GLOB.alive_mob_list)
+ twitterize(P.speech_buffer, "polytalk")
+ break //Who's been duping the bird?!
diff --git a/code/controllers/subsystem/persistence/poly_parrot.dm b/code/controllers/subsystem/persistence/poly_parrot.dm
deleted file mode 100644
index 64743e9623..0000000000
--- a/code/controllers/subsystem/persistence/poly_parrot.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Persists poly messages across rounds
- */
-/datum/controller/subsystem/persistence/LoadGamePersistence()
- . = ..()
- LoadPoly()
-
-/datum/controller/subsystem/persistence/proc/LoadPoly()
- for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list)
- twitterize(P.speech_buffer, "polytalk")
- break //Who's been duping the bird?!
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index d1b3236050..d755003f3b 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -164,8 +164,8 @@ SUBSYSTEM_DEF(ticker)
to_chat(world, "Welcome to [station_name()]!")
send2chat("New round starting on [SSmapping.config.map_name]!", CONFIG_GET(string/chat_announce_new_game))
current_state = GAME_STATE_PREGAME
- //Everyone who wants to be an observer is now spawned
- create_observers()
+ SEND_SIGNAL(src, COMSIG_TICKER_ENTER_PREGAME)
+
fire()
if(GAME_STATE_PREGAME)
//lobby stats for statpanels
@@ -203,6 +203,7 @@ SUBSYSTEM_DEF(ticker)
for(var/client/C in SSvote.voting)
C << browse(null, "window=vote;can_close=0")
SSvote.reset()
+ SEND_SIGNAL(src, COMSIG_TICKER_ENTER_SETTING_UP)
current_state = GAME_STATE_SETTING_UP
Master.SetRunLevel(RUNLEVEL_SETUP)
if(start_immediately)
@@ -215,6 +216,7 @@ SUBSYSTEM_DEF(ticker)
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
timeLeft = null
Master.SetRunLevel(RUNLEVEL_LOBBY)
+ SEND_SIGNAL(src, COMSIG_TICKER_ERROR_SETTING_UP)
if(GAME_STATE_PLAYING)
mode.process(wait * 0.1)
@@ -378,8 +380,6 @@ SUBSYSTEM_DEF(ticker)
LAZYOR(player.client.prefs.characters_joined_as, player.new_character.real_name)
else
stack_trace("WARNING: Either a player did not have a new_character, did not have a client, or did not have preferences. This is VERY bad.")
- else
- player.new_player_panel()
CHECK_TICK
/datum/controller/subsystem/ticker/proc/collect_minds()
@@ -612,7 +612,7 @@ SUBSYSTEM_DEF(ticker)
var/list/ded = SSblackbox.first_death
if(ded.len)
var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""
- news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
+ news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died.\nTheir name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
else
news_message += "\nNT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
@@ -633,13 +633,6 @@ SUBSYSTEM_DEF(ticker)
else
timeLeft = newtime
-//Everyone who wanted to be an observer gets made one now
-/datum/controller/subsystem/ticker/proc/create_observers()
- for(var/mob/dead/new_player/player in GLOB.player_list)
- if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind)
- //Break chain since this has a sleep input in it
- addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1)
-
/datum/controller/subsystem/ticker/proc/load_mode()
var/mode = trim(file2text("data/mode.txt"))
if(mode)
diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm
index 3cc3d9dd99..1dbfb1540c 100644
--- a/code/controllers/subsystem/title.dm
+++ b/code/controllers/subsystem/title.dm
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(title)
/datum/controller/subsystem/title/Initialize()
if(file_path && icon)
- return ..()
+ return
if(fexists("data/previous_title.dat"))
var/previous_path = file2text("data/previous_title.dat")
@@ -31,13 +31,16 @@ SUBSYSTEM_DEF(title)
if(length(title_screens))
file_path = "[global.config.directory]/title_screens/images/[pick(title_screens)]"
- if(!file_path || !fexists(file_path))
- file_path = "icons/default_title.dmi"
+ if(!file_path)
+ file_path = "icons/runtime/default_title.dmi"
- if(fexists(file_path))
- icon = new(fcopy_rsc(file_path))
- if(splash_turf)
- splash_turf.icon = icon
+ ASSERT(fexists(file_path))
+
+ icon = new(fcopy_rsc(file_path))
+
+ if(splash_turf)
+ splash_turf.icon = icon
+ splash_turf.handle_generic_titlescreen_sizes()
return ..()
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index edf10f89c4..7f1ece6937 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -169,7 +169,7 @@ SUBSYSTEM_DEF(traumas)
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver,
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
/obj/item/melee/transforming/energy/sword/saber, /obj/item/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
- /obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/vehicle/sealed/mecha/combat/gygax/dark, /obj/vehicle/sealed/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
+ /obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm712x82, /obj/item/antag_spawner/nuke_ops, /obj/vehicle/sealed/mecha/combat/gygax/dark, /obj/vehicle/sealed/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
/obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate,
/obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited,
/obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 772d7f7b8d..eb28d4b4f2 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -320,11 +320,11 @@ SUBSYSTEM_DEF(vote)
admintext += "\nIt should be noted that this is not a raw tally of votes but rather the median score plus a tiebreaker!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
- admintext += "\n[choices[i]]: [votes]"
+ admintext += "\n[choices[i]]: [votes ? votes : "0"]" //This is raw data, but the raw data is null by default. If ya don't compensate for it, then it'll look weird!
else
for(var/i=1,i<=scores.len,i++)
var/score = scores[scores[i]]
- admintext += "\n[scores[i]]: [score]"
+ admintext += "\n[scores[i]]: [score ? score : "0"]"
message_admins(admintext)
return .
diff --git a/code/datums/bark.dm b/code/datums/bark.dm
new file mode 100644
index 0000000000..2bf3d7c69a
--- /dev/null
+++ b/code/datums/bark.dm
@@ -0,0 +1,150 @@
+//Datums for barks and bark accessories
+
+/datum/bark
+ var/name = "Default"
+ var/id = "Default"
+ var/soundpath //Path for the actual sound file used for the bark
+
+ // Pitch vars. The actual range for a bark is [(pitch - (maxvariance*0.5)) to (pitch + (maxvariance*0.5))]
+ // Make absolutely sure to take variance into account when curating a sound for bark purposes.
+ var/minpitch = BARK_DEFAULT_MINPITCH
+ var/maxpitch = BARK_DEFAULT_MAXPITCH
+ var/minvariance = BARK_DEFAULT_MINVARY
+ var/maxvariance = BARK_DEFAULT_MAXVARY
+
+ // Speed vars. Speed determines the number of characters required for each bark, with lower speeds being faster with higher bark density
+ var/minspeed = BARK_DEFAULT_MINSPEED
+ var/maxspeed = BARK_DEFAULT_MAXSPEED
+
+ // Visibility vars. Regardless of what's set below, these can still be obtained via adminbus and genetics. Rule of fun.
+ var/list/ckeys_allowed
+ var/ignore = FALSE //Controls whether or not this can be chosen in chargen
+ var/allow_random = FALSE //Allows chargen randomization to use this. This is mainly to restrict the pool to sounds that fit well for most characters
+
+
+// So the basic jist of the sound design here: We make use primarily of shorter instrument samples for barks. We would've went with animalese instead, but doing so would've involved quite a bit of overhead to saycode.
+// Short instrument samples tend to sound surprisingly nice for barks, being able to be played in rapid succession without being outright obnoxious.
+// It isn't just instruments that work well here, however. Anything that works well as a stab? Short attack, no sustain, a decent amount of release? Also works extremely well for barks.
+
+/datum/bark/mutedc2
+ name = "Muted String (Low)"
+ id = "mutedc2"
+ soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg'
+ allow_random = TRUE
+
+/datum/bark/mutedc3
+ name = "Muted String (Medium)"
+ id = "mutedc3"
+ soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg'
+ allow_random = TRUE
+
+/datum/bark/mutedc4
+ name = "Muted String (High)"
+ id = "mutedc4"
+ soundpath = 'sound/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg'
+ allow_random = TRUE
+
+/datum/bark/banjoc3
+ name = "Banjo (Medium)"
+ id = "banjoc3"
+ soundpath = 'sound/instruments/banjo/Cn3.ogg'
+ allow_random = TRUE
+
+/datum/bark/banjoc4
+ name = "Banjo (High)"
+ id = "banjoc4"
+ soundpath = 'sound/instruments/banjo/Cn4.ogg'
+ allow_random = TRUE
+
+/datum/bark/squeaky
+ name = "Squeaky"
+ id = "squeak"
+ soundpath = 'sound/items/toysqueak1.ogg'
+ maxspeed = 4
+
+/datum/bark/beep
+ name = "Beepy"
+ id = "beep"
+ soundpath = 'sound/machines/terminal_select.ogg'
+ maxpitch = 1 //Bringing the pitch higher just hurts your ears :<
+ maxspeed = 4 //This soundbyte's too short for larger speeds to not sound awkward
+
+/datum/bark/chitter
+ name = "Chittery"
+ id = "chitter"
+ minspeed = 4 //Even with the sound being replaced with a unique, shorter sound, this is still a little too long for higher speeds
+ soundpath = 'sound/voice/barks/chitter.ogg'
+
+/datum/bark/synthetic_grunt
+ name = "Synthetic (Grunt)"
+ id = "synthgrunt"
+ soundpath = 'sound/misc/bloop.ogg'
+
+/datum/bark/synthetic
+ name = "Synthetic (Normal)"
+ id = "synth"
+ soundpath = 'sound/machines/uplinkerror.ogg'
+
+/datum/bark/bullet
+ name = "Windy"
+ id = "bullet"
+ maxpitch = 1.6 //This works well with higher pitches!
+ soundpath = 'sound/weapons/bulletflyby.ogg' //This works... Surprisingly well as a bark? It's neat!
+
+/datum/bark/coggers
+ name = "Brassy"
+ id = "coggers"
+ soundpath = 'sound/machines/clockcult/integration_cog_install.ogg' //Yet another unexpectedly good bark sound
+
+
+// Genetics-only/admin-only sounds. These either clash hard with the audio design of the above sounds, or have some other form of audio design issue, but aren't *too* awful as a sometimes thing.
+// Rule of fun very much applies to this section. Audio design is extremely important for the above section, but down here? No gods, no masters, pure anarchy.
+// The min/max variables simply don't apply to these, as only chargen cares about them. As such, there's no need to define those.
+
+/datum/bark/bikehorn
+ name = "Bikehorn"
+ id = "horn"
+ soundpath = 'sound/instruments/bikehorn/Cn4.ogg'
+ ignore = TRUE // This is an unusually quiet sound.
+
+/datum/bark/bwoink
+ name = "Bwoink"
+ id = "bwoink"
+ soundpath = 'sound/effects/adminhelp.ogg'
+ ignore = TRUE // Emergent heart attack generation
+
+/datum/bark/merp
+ name = "Merp"
+ id = "merp"
+ soundpath = 'modular_citadel/sound/voice/merp.ogg'
+ ignore = TRUE
+
+/datum/bark/bark
+ name = "Bark"
+ id = "bark"
+ soundpath = 'modular_citadel/sound/voice/bark1.ogg'
+ ignore = TRUE
+
+/datum/bark/nya
+ name = "Nya"
+ id = "nya"
+ soundpath = 'modular_citadel/sound/voice/nya.ogg'
+ ignore = TRUE
+
+/datum/bark/moff
+ name = "Moff"
+ id = "moff"
+ soundpath = 'modular_citadel/sound/voice/mothsqueak.ogg'
+ ignore = TRUE
+
+/datum/bark/weh
+ name = "Weh"
+ id = "weh"
+ soundpath = 'modular_citadel/sound/voice/weh.ogg'
+ ignore = TRUE
+
+/datum/bark/honk
+ name = "Annoying Honk"
+ id = "honk"
+ soundpath = 'sound/creatures/goose1.ogg'
+ ignore = TRUE
diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm
index 6b84e1362d..44a1a76b08 100644
--- a/code/datums/brain_damage/split_personality.dm
+++ b/code/datums/brain_damage/split_personality.dm
@@ -123,7 +123,7 @@
trauma = _trauma
return ..()
-/mob/living/split_personality/BiologicalLife(seconds, times_fired)
+/mob/living/split_personality/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(QDELETED(body))
diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm
index a3a9ed5898..e4648233de 100644
--- a/code/datums/chatmessage.dm
+++ b/code/datums/chatmessage.dm
@@ -164,6 +164,7 @@
message.maptext_height = mheight
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
message.maptext = MAPTEXT(complete_text)
+ message.pixel_x = -owner.pixel_x //Dogborgs and other wide boys have a pixel offset. This accounts for that
// View the message
LAZYADDASSOC(owned_by.seen_messages, message_loc, src)
@@ -174,10 +175,6 @@
scheduled_destruction = world.time + (lifespan - CHAT_MESSAGE_EOL_FADE)
enter_subsystem()
- var/mob/living/silicon/robot/R = target
- if(iscyborg(R))
- if((R.module.dogborg == TRUE || R.dogborg == TRUE) && isturf(R.loc)) //I hate whoever that thought that putting two types of dogborg that don't even sync up properly was good
- message.pixel_x = 16
/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion
diff --git a/code/datums/components/bouncy.dm b/code/datums/components/bouncy.dm
index fed603410e..3c4e228b59 100644
--- a/code/datums/components/bouncy.dm
+++ b/code/datums/components/bouncy.dm
@@ -32,7 +32,7 @@
var/atom/movable/A = parent
switch(rand(1, 3))
if(1)
- A.do_jiggle(45 + rand(-10, 10) * bouncy_mod, 14)
+ A.do_jiggle(25 + rand(-5, 5) * bouncy_mod, 14)
if(2)
var/min_b = 0.6/bouncy_mod
var/max_b = 1.2 * bouncy_mod
diff --git a/code/datums/components/crafting/glassware/glassware.dm b/code/datums/components/crafting/glassware/glassware.dm
index 50137733ee..f37efedc8a 100644
--- a/code/datums/components/crafting/glassware/glassware.dm
+++ b/code/datums/components/crafting/glassware/glassware.dm
@@ -39,7 +39,7 @@
name = "tea cup"
desc = "A glass cup made for sipping tea!"
icon = 'icons/obj/glass_ware.dmi'
- icon_state = "tea_plate"
+ icon_state = "tea_cup"
//////////////////////Chem Disk/////////////////////
//Two Steps //
@@ -145,7 +145,7 @@
qdel(src)
/obj/item/glasswork/glass_base/glass_lens_part5
- name = "unpolished glass lens"
+ name = "unpolished glass (lens)"
desc = "An unpolished glass lens. It needs to be polished with some dry cloth."
icon = 'icons/obj/glass_ware.dmi'
icon_state = "glass_optics"
@@ -159,7 +159,7 @@
qdel(src)
/obj/item/glasswork/glass_base/glass_lens_part6
- name = "unrefined glass lens"
+ name = "unrefined glass (lens)"
desc = "A polished glass lens. It needs to be refined with some sandstone."
icon = 'icons/obj/glass_ware.dmi'
icon_state = "glass_optics"
@@ -179,7 +179,7 @@
/obj/item/glasswork/glass_base/spouty
name = "Glass fodder sheet (spout)"
- desc = "A set of glass sheets set aside for glass working. This one is ideal for a spouty flask. It needs to heated with something very hot."
+ desc = "A set of glass sheets set aside for glass working. This one is ideal for a spouty flask. It needs to be cut with some glassworking tools."
next_step = /obj/item/glasswork/glass_base/spouty_part2
/obj/item/glasswork/glass_base/spouty/attackby(obj/item/I, mob/user, params)
@@ -413,7 +413,7 @@
qdel(src)
qdel(I)
-/obj/item/glasswork/glass_base/tea_cupe2
+/obj/item/glasswork/glass_base/tea_cup2
name = "glassblowing rod (tea cup)"
desc = "A hollow metal rod made for blowing glass. There is a blob of shapen glass at the end of it that needs to be cut off with some glassworking tools."
icon_state = "blowing_rods_inuse"
@@ -433,7 +433,7 @@
icon_state = "glass_base_half"
next_step = /obj/item/glasswork/glass_base/tea_cup4
-/obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params)
+/obj/item/glasswork/glass_base/tea_cup3/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/stack/sheet/cloth))
if(do_after(user,10, target = src))
@@ -446,7 +446,7 @@
icon_state = "glass_base_half"
next_step = /obj/item/tea_cup
-/obj/item/glasswork/glass_base/cup4/attackby(obj/item/I, mob/user, params)
+/obj/item/glasswork/glass_base/tea_cup4/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/stack/sheet/glass))
if(do_after(user,10, target = src))
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 1535c3f142..9bdb009962 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -346,9 +346,9 @@
/datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list)
if(harmful)
- examine_list += "\t There is \a [weapon] embedded in [parent]!"
+ examine_list += "There is \a [weapon] embedded in [parent]!"
else
- examine_list += "\t There is \a [weapon] stuck to [parent]!"
+ examine_list += "There is \a [weapon] stuck to [parent]!"
/// Someone is ripping out the item from the turf by hand
diff --git a/code/datums/components/identification.dm b/code/datums/components/identification.dm
index 59b98b57ac..cd47cfcbeb 100644
--- a/code/datums/components/identification.dm
+++ b/code/datums/components/identification.dm
@@ -61,7 +61,7 @@
if(identification_method_flags & ID_COMPONENT_EFFECT_NO_ACTIONS)
return COMPONENT_NO_GRANT_ACTIONS
-/datum/component/identification/proc/check_knowledge(mob/user)
+/datum/component/identification/proc/check_knowledge(datum/source, mob/user)
return ID_COMPONENT_KNOWLEDGE_NONE
/datum/component/identification/proc/on_identify(mob/user)
@@ -83,7 +83,7 @@
*/
/datum/component/identification/syndicate
-/datum/component/identification/syndicate/check_knowledge(mob/user)
+/datum/component/identification/syndicate/check_knowledge(datum/source, mob/user)
. = ..()
if(user?.mind?.has_antag_datum(/datum/antagonist/traitor))
. = max(., ID_COMPONENT_KNOWLEDGE_FULL)
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index e100326f7b..d5b988d983 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -50,7 +50,7 @@
STOP_PROCESSING(SSobj, src)
/datum/component/mood/proc/print_mood(mob/user)
- var/msg = "*---------*\nYour current mood\n"
+ var/msg = "
Your current mood\n"
msg += "My mental status: " //Long term
switch(sanity)
if(SANITY_GREAT to INFINITY)
@@ -69,23 +69,23 @@
msg += "My current mood: " //Short term
switch(mood_level)
if(1)
- msg += "I wish I was dead!\n"
+ msg += "I wish I was dead!\n"
if(2)
- msg += "I feel terrible...\n"
+ msg += "I feel terrible...\n"
if(3)
- msg += "I feel very upset.\n"
+ msg += "I feel very upset.\n"
if(4)
- msg += "I'm a bit sad.\n"
+ msg += "I'm a bit sad.\n"
if(5)
- msg += "I'm alright.\n"
+ msg += "I'm alright.\n"
if(6)
- msg += "I feel pretty okay.\n"
+ msg += "I feel pretty okay.\n"
if(7)
- msg += "I feel pretty good.\n"
+ msg += "I feel pretty good.\n"
if(8)
- msg += "I feel amazing!\n"
+ msg += "I feel amazing!\n"
if(9)
- msg += "I love life!\n"
+ msg += "I love life!\n"
msg += "Moodlets:\n"//All moodlets
if(mood_events.len)
@@ -93,7 +93,8 @@
var/datum/mood_event/event = mood_events[i]
msg += event.description
else
- msg += "I don't have much of a reaction to anything right now.\n"
+ msg += "I don't have much of a reaction to anything right now.\n"
+ msg += "
"
to_chat(user || parent, msg)
///Called after moodevent/s have been added/removed.
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index 00a58a75f8..c0101140d6 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -431,25 +431,26 @@
if(M.incapacitated() || !M.canUseStorage())
return
var/atom/A = parent
- A.add_fingerprint(M)
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M)
user_show_to_mob(M, trigger_on_found = TRUE)
if(isrevenant(M))
INVOKE_ASYNC(GLOBAL_PROC, .proc/RevenantThrow, over_object, M, source)
return
+ if(check_locked(null, M) || !M.CanReach(A) || (!M.CanReach(over_object) && !istype(over_object, /atom/movable/screen)))
+ return
+ playsound(A, "rustle", 50, TRUE, -5)
+ A.do_jiggle()
+ A.add_fingerprint(M)
if(!istype(over_object, /atom/movable/screen))
INVOKE_ASYNC(src, .proc/dump_content_at, over_object, M)
return
if(A.loc != M)
return
- playsound(A, "rustle", 50, TRUE, -5)
- A.do_jiggle()
if(istype(over_object, /atom/movable/screen/inventory/hand))
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(A, H.held_index)
return
- A.add_fingerprint(M)
/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE, trigger_on_found = FALSE)
var/atom/A = parent
diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm
index 820d7067d4..d41d82ae75 100644
--- a/code/datums/components/storage/ui.dm
+++ b/code/datums/components/storage/ui.dm
@@ -63,6 +63,8 @@
if(QDELETED(O))
continue
var/atom/movable/screen/storage/item_holder/D = new(null, src, O)
+ // SNOWFLAKE: make O opaque too, pending storage rewrite
+ O.mouse_opacity = MOUSE_OPACITY_OPAQUE
D.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
D.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
O.maptext = ""
@@ -138,6 +140,8 @@
I = i
var/percent = percentage_by_item[I]
var/atom/movable/screen/storage/volumetric_box/center/B = new /atom/movable/screen/storage/volumetric_box/center(null, src, I)
+ // SNOWFLAKE: force it to icon until we unfuck storage/click passing
+ I.mouse_opacity = MOUSE_OPACITY_ICON
var/pixels_to_use = overrun? MINIMUM_PIXELS_PER_ITEM : max(using_horizontal_pixels * percent, MINIMUM_PIXELS_PER_ITEM)
var/addrow = FALSE
if(CEILING(pixels_to_use, 1) >= FLOOR(horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING, 1))
diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm
index 56e06e3582..c0e6e9dba6 100644
--- a/code/datums/components/virtual_reality.dm
+++ b/code/datums/components/virtual_reality.dm
@@ -84,9 +84,9 @@
if(VR)
VR.level_below = src
level_above = VR
- M.transfer_ckey(vr_M, FALSE)
mastermind = M.mind
mastermind.current.audiovisual_redirect = parent
+ M.transfer_ckey(vr_M, FALSE)
RegisterSignal(mastermind, COMSIG_PRE_MIND_TRANSFER, .proc/switch_player)
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
RegisterSignal(M, COMSIG_MOB_PRE_PLAYER_CHANGE, .proc/player_hijacked)
diff --git a/code/datums/diseases/parrotpossession.dm b/code/datums/diseases/parrotpossession.dm
index 1a3346d565..2fb3a36459 100644
--- a/code/datums/diseases/parrotpossession.dm
+++ b/code/datums/diseases/parrotpossession.dm
@@ -13,7 +13,7 @@
severity = DISEASE_SEVERITY_MEDIUM
infectable_biotypes = MOB_ORGANIC|MOB_UNDEAD|MOB_ROBOTIC|MOB_MINERAL
bypasses_immunity = TRUE //2spook
- var/mob/living/simple_animal/parrot/Poly/ghost/parrot
+ var/mob/living/simple_animal/parrot/Polly/ghost/parrot
/datum/disease/parrot_possession/stage_act()
..()
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 43dad6cef8..5619a09f05 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -77,6 +77,7 @@
new_dna.species = new species.type
new_dna.species.say_mod = species.say_mod
new_dna.species.exotic_blood_color = species.exotic_blood_color //it can change from the default value
+ new_dna.species.exotic_blood_blend_mode = species.exotic_blood_blend_mode
new_dna.species.eye_type = species.eye_type
new_dna.species.limbs_id = species.limbs_id || species.id
new_dna.real_name = real_name
@@ -137,9 +138,9 @@
L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)
L[DNA_LEFT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.left_eye_color)
L[DNA_RIGHT_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.right_eye_color)
- L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6)
- L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6)
- L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6)
+ L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"])
+ L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"])
+ L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"])
if(!GLOB.mam_tails_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
@@ -152,6 +153,10 @@
if(!GLOB.taur_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list)
L[DNA_TAUR_BLOCK] = construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
+ L[DNA_BARK_SOUND_BLOCK] = construct_block(GLOB.bark_list.Find(H.vocal_bark_id), GLOB.bark_list.len)
+ L[DNA_BARK_SPEED_BLOCK] = construct_block(H.vocal_speed * 4, 16)
+ L[DNA_BARK_PITCH_BLOCK] = construct_block(H.vocal_pitch * 30, 48)
+ L[DNA_BARK_VARIANCE_BLOCK] = construct_block(H.vocal_pitch_range * 48, 48)
for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++)
if(L[i])
@@ -247,19 +252,19 @@
if(DNA_HAIR_STYLE_BLOCK)
setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len))
if(DNA_COLOR_ONE_BLOCK)
- sanitize_hexcolor(features["mcolor"], 6)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor"]))
if(DNA_COLOR_TWO_BLOCK)
- sanitize_hexcolor(features["mcolor2"], 6)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor2"]))
if(DNA_COLOR_THREE_BLOCK)
- sanitize_hexcolor(features["mcolor3"], 6)
+ setblock(uni_identity, blocknumber, sanitize_hexcolor(features["mcolor3"]))
if(DNA_MUTANTTAIL_BLOCK)
- construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
+ setblock(uni_identity, blocknumber, construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len))
if(DNA_MUTANTEAR_BLOCK)
- construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len)
+ setblock(uni_identity, blocknumber, construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len))
if(DNA_MUTANTMARKING_BLOCK)
- construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len)
+ setblock(uni_identity, blocknumber, construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len))
if(DNA_TAUR_BLOCK)
- construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
+ setblock(uni_identity, blocknumber, construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len))
if(species.mutant_bodyparts["taur"] && ishuman(holder))
var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]]
switch(T?.taur_mode)
@@ -271,6 +276,14 @@
H.physiology.footstep_type = FOOTSTEP_MOB_CRAWL
else
H.physiology.footstep_type = null
+ if(DNA_BARK_SOUND_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(GLOB.bark_list.Find(H.vocal_bark_id), GLOB.bark_list.len))
+ if(DNA_BARK_SPEED_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(H.vocal_speed * 4, 16))
+ if(DNA_BARK_PITCH_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(H.vocal_pitch * 30, 48))
+ if(DNA_BARK_VARIANCE_BLOCK)
+ setblock(uni_identity, blocknumber, construct_block(H.vocal_pitch_range * 48, 48))
//Please use add_mutation or activate_mutation instead
/datum/dna/proc/force_give(datum/mutation/human/HM)
@@ -490,6 +503,10 @@
update_body_parts()
if(mutations_overlay_update)
update_mutations_overlay()
+ set_bark(GLOB.bark_list[deconstruct_block(getblock(structure, DNA_BARK_SOUND_BLOCK), GLOB.bark_list.len)])
+ vocal_speed = (deconstruct_block(getblock(structure, DNA_BARK_SPEED_BLOCK), 16) / 4)
+ vocal_pitch = (deconstruct_block(getblock(structure, DNA_BARK_PITCH_BLOCK), 48) / 30)
+ vocal_pitch_range = (deconstruct_block(getblock(structure, DNA_BARK_VARIANCE_BLOCK), 48) / 48)
/mob/proc/domutcheck()
diff --git a/code/datums/elements/flavor_text.dm b/code/datums/elements/flavor_text.dm
index 6217665157..b61bacbd19 100644
--- a/code/datums/elements/flavor_text.dm
+++ b/code/datums/elements/flavor_text.dm
@@ -76,10 +76,10 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
if(examine_full_view)
examine_list += "[msg]"
return
- if(length_char(msg) <= 40)
+ if(length_char(msg) <= MAX_FLAVOR_PREVIEW_LEN)
examine_list += "[msg]"
else
- examine_list += "[copytext_char(msg, 1, 37)]... More..."
+ examine_list += "[copytext_char(msg, 1, (MAX_FLAVOR_PREVIEW_LEN - 3))]... More..."
/datum/element/flavor_text/Topic(href, href_list)
. = ..()
@@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
if(ismob(target))
add_verb(target, /mob/proc/set_pose)
-/datum/element/flavor_Text/carbon/temporary/Detach(datum/source, force)
+/datum/element/flavor_text/carbon/temporary/Detach(datum/source, force)
. = ..()
if(ismob(source))
remove_verb(source, /mob/proc/set_pose)
diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm
index e67120f254..85fea3533e 100644
--- a/code/datums/elements/strippable.dm
+++ b/code/datums/elements/strippable.dm
@@ -136,13 +136,19 @@
if (isnull(item))
return FALSE
- source.visible_message(
- span_warning("[user] tries to remove [source]'s [item.name]."),
- span_userdanger("[user] tries to remove your [item.name]."),
- ignored_mobs = user,
- )
+ var/strip_silence
+ var/obj/item/clothing/gloves/gloves = user.get_item_by_slot(ITEM_SLOT_GLOVES)
+ if(istype(gloves))
+ strip_silence = gloves.strip_silence
- to_chat(user, span_danger("You try to remove [source]'s [item]..."))
+ if(!strip_silence)
+ source.visible_message(
+ span_warning("[user] tries to remove [source]'s [item.name]."),
+ span_userdanger("[user] tries to remove your [item.name]."),
+ ignored_mobs = user,
+ )
+
+ to_chat(user, strip_silence ? span_danger("You try to remove [source]'s [item]...") : span_notice("You try to remove [source]'s [item]..."))
user.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_ATTACK, color="red")
source.log_message("[key_name(source)] is being stripped of [item] by [key_name(user)]", LOG_VICTIM, color="red", log_globally=FALSE)
item.add_fingerprint(source)
@@ -284,7 +290,12 @@
/// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob.
/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay)
- if (!do_mob(user, source, strip_delay || item.strip_delay, ignorehelditem = TRUE))
+ var/strip_mod = 1
+ var/obj/item/clothing/gloves/gloves = user.get_item_by_slot(ITEM_SLOT_GLOVES)
+ if(istype(gloves))
+ strip_mod = gloves.strip_mod
+
+ if (!do_mob(user, source, (strip_delay || item.strip_delay) / strip_mod, ignorehelditem = TRUE))
return FALSE
return TRUE
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index 968809747b..b04f55ef0e 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -10,7 +10,7 @@
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
// Helper similar to image()
-/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF")
+/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF", blend_mode = BLEND_DEFAULT)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
@@ -19,5 +19,6 @@
MA.alpha = alpha
MA.appearance_flags |= appearance_flags
MA.color = color
+ MA.blend_mode = blend_mode
return MA
diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm
index 3b6fae5aee..bd0537bac7 100644
--- a/code/datums/saymode.dm
+++ b/code/datums/saymode.dm
@@ -120,6 +120,17 @@
return FALSE
return TRUE
+/datum/saymode/statusdisplay
+ key = "q"
+ mode = MODE_STATUSDISPLAY
+
+/datum/saymode/statusdisplay/handle_message(mob/living/user, message, datum/language/language)
+ if(isAI(user))
+ var/mob/living/silicon/ai/AI = user
+ AI.statusdisplay_talk(message, language)
+ return FALSE
+ return TRUE
+
/datum/saymode/monkey
key = "k"
mode = MODE_MONKEY
diff --git a/code/datums/traits/_quirk.dm b/code/datums/traits/_quirk.dm
index 99fa6e73c5..ce1796346a 100644
--- a/code/datums/traits/_quirk.dm
+++ b/code/datums/traits/_quirk.dm
@@ -14,6 +14,7 @@
/// should we immediately call on_spawn or add a timer to trigger
var/on_spawn_immediate = TRUE
var/mob/living/quirk_holder
+ var/processing_quirk = FALSE
/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type))
@@ -25,7 +26,8 @@
quirk_holder.roundstart_quirks += src
if(mob_trait)
ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
- START_PROCESSING(SSquirks, src)
+ if(processing_quirk)
+ START_PROCESSING(SSquirks, src)
add()
if(spawn_effects)
if(on_spawn_immediate)
@@ -35,7 +37,8 @@
addtimer(CALLBACK(src, .proc/post_add), 30)
/datum/quirk/Destroy()
- STOP_PROCESSING(SSquirks, src)
+ if(processing_quirk)
+ STOP_PROCESSING(SSquirks, src)
remove()
if(quirk_holder)
to_chat(quirk_holder, lose_text)
diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm
index a0f62a32b8..3bcca275a5 100644
--- a/code/datums/traits/good.dm
+++ b/code/datums/traits/good.dm
@@ -72,6 +72,7 @@
mob_trait = TRAIT_JOLLY
mood_quirk = TRUE
medical_record_text = "Patient demonstrates constant euthymia irregular for environment. It's a bit much, to be honest."
+ processing_quirk = TRUE
/datum/quirk/jolly/on_process()
if(prob(0.05))
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index 8958226ff4..8d3acf0f6d 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -25,6 +25,7 @@
lose_text = "You no longer feel depressed." //if only it were that easy!
medical_record_text = "Patient has a severe mood disorder, causing them to experience acute episodes of depression."
mood_quirk = TRUE
+ processing_quirk = TRUE
/datum/quirk/depression/on_process()
if(prob(0.05))
@@ -38,6 +39,7 @@
medical_record_text = "Patient demonstrates an unnatural attachment to a family heirloom."
var/obj/item/heirloom
var/where
+ processing_quirk = TRUE
GLOBAL_LIST_EMPTY(family_heirlooms)
@@ -102,6 +104,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "You feel smooth."
lose_text = "You feel wrinkled again."
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
+ processing_quirk = TRUE
/datum/quirk/brainproblems/on_process()
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
@@ -129,25 +132,38 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
value = -1
medical_record_text = "Patient demonstrates a fear of the dark. (Seriously?)"
-/datum/quirk/nyctophobia/on_process()
- var/mob/living/carbon/human/H = quirk_holder
- if(H.dna.species.id in list("shadow", "nightmare"))
- return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese
- var/turf/T = get_turf(quirk_holder)
- var/lums = T.get_lumcount()
- if(lums <= 0.2)
- if(quirk_holder.m_intent == MOVE_INTENT_RUN)
- addtimer(CALLBACK(src, .proc/recheck),2) //0.2 seconds of being in the dark
- SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
- else
- SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
+/datum/quirk/nyctophobia/add()
+ RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
-/datum/quirk/nyctophobia/proc/recheck()
- var/turf/T = get_turf(quirk_holder)
- var/lums = T.get_lumcount()
- if(lums <= 0.2) //check again, did they remain in the dark for 0.2 seconds?
- to_chat(quirk_holder, "Easy, easy, take it slow... you're in the dark...")
+/datum/quirk/nyctophobia/remove()
+ UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
+
+/// Called when the quirk holder moves. Updates the quirk holder's mood.
+/datum/quirk/nyctophobia/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
+ if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
+ return
+
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
+ return
+
+ if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
+ return
+
+ var/turf/holder_turf = get_turf(quirk_holder)
+
+ var/lums = holder_turf.get_lumcount()
+
+ if(lums > 0.2)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
+ return
+
+ if(quirk_holder.m_intent == MOVE_INTENT_RUN)
+ to_chat(quirk_holder, span_warning("Easy, easy, take it slow... you're in the dark..."))
quirk_holder.toggle_move_intent()
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
/datum/quirk/lightless
name = "Light Sensitivity"
@@ -157,6 +173,36 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
lose_text = "Enlightening."
medical_record_text = "Despite my warnings, the patient refuses turn on the lights, only to end up rolling down a full flight of stairs and into the cellar."
+/datum/quirk/lightless/add()
+ RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
+
+/datum/quirk/lightless/remove()
+ UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
+
+/datum/quirk/lightless/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
+ if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
+ return
+
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
+ return
+
+ if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
+ return
+
+ var/turf/holder_turf = get_turf(quirk_holder)
+
+ var/lums = holder_turf.get_lumcount()
+
+ if(lums < 0.8)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
+ return
+
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "brightlight", /datum/mood_event/brightlight)
+
+
/datum/quirk/lightless/on_process()
var/turf/T = get_turf(quirk_holder)
var/lums = T.get_lumcount()
@@ -236,6 +282,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "..."
lose_text = "You feel in tune with the world again."
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
+ processing_quirk = TRUE
/datum/quirk/insanity/on_process()
if(quirk_holder.reagents.has_reagent(/datum/reagent/toxin/mindbreaker))
@@ -261,6 +308,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
lose_text = "You feel easier about talking again." //if only it were that easy!
medical_record_text = "Patient is usually anxious in social encounters and prefers to avoid them."
var/dumb_thing = TRUE
+ processing_quirk = TRUE
/datum/quirk/social_anxiety/add()
RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact)
@@ -425,3 +473,21 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
gain_text = "You can't smell anything!"
lose_text = "You can smell again!"
medical_record_text = "Patient suffers from anosmia and is incapable of smelling gases or particulates."
+
+/datum/quirk/paper_skin
+ name = "Paper Skin"
+ desc = "Your flesh is weaker, resulting in receiving cuts more easily."
+ value = -1
+ mob_trait = TRAIT_PAPER_SKIN
+ gain_text = "Your flesh feels weak!"
+ lose_text = "Your flesh feels more durable!"
+ medical_record_text = "Patient suffers from weak flesh, resulting in them receiving cuts far more easily."
+
+/datum/quirk/glass_bones
+ name = "Glass Bones"
+ desc = "Your bones are far more brittle, and more vulnerable to breakage."
+ value = -1
+ mob_trait = TRAIT_GLASS_BONES
+ gain_text = "Your bones feels weak!"
+ lose_text = "Your bones feels more durable!"
+ medical_record_text = "Patient suffers from brittle bones, resulting in them receiving breakages far more easily."
diff --git a/code/datums/wounds/_scars.dm b/code/datums/wounds/_scars.dm
index 3365fc359d..3fb6546edb 100644
--- a/code/datums/wounds/_scars.dm
+++ b/code/datums/wounds/_scars.dm
@@ -118,7 +118,7 @@
if(WOUND_SEVERITY_LOSS)
msg = "[victim.p_their(TRUE)] [limb.name] [description]." // different format
msg = "[msg]"
- return "\t[msg]"
+ return "[msg]"
/// Whether a scar can currently be seen by the viewer
/datum/scar/proc/is_visible(mob/viewer)
diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm
index f3e22807cf..c16be6005a 100644
--- a/code/datums/wounds/burns.dm
+++ b/code/datums/wounds/burns.dm
@@ -167,7 +167,7 @@
if(WOUND_INFECTION_SEPTIC to INFINITY)
. += "Infection Level: LOSS IMMINENT\n"
if(infestation > sanitization)
- . += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
+ . += "Surgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n"
if(flesh_damage > 0)
. += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n"
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index a5b9dd2fc7..b09731ab62 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -212,6 +212,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
// airlock_wires = /datum/wires/airlock/maint
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
+ minimap_color = "#454545"
//Maintenance - Departmental
@@ -435,6 +436,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway
nightshift_public_area = NIGHTSHIFT_AREA_PUBLIC
sound_environment = SOUND_AREA_STANDARD_STATION
+ minimap_color = "#aaaaaa"
/area/hallway/primary
name = "Primary Hallway"
@@ -490,6 +492,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/secondary/exit
name = "Escape Shuttle Hallway"
icon_state = "escape"
+ minimap_color = "#baa0a0"
/area/hallway/secondary/exit/departure_lounge
name = "Departure Lounge"
@@ -498,6 +501,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/hallway/secondary/entry
name = "Arrival Shuttle Hallway"
icon_state = "entry"
+ minimap_color = "#a0a0ba"
/area/hallway/secondary/service
name = "Service Hallway"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 44916cf1d2..24b49a3af7 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -124,6 +124,10 @@
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
+ var/minimap_color2 // if this isn't null, then this will show as a checkerboard pattern mixed in with the above. works even if the above is null (for better or worse)
+
+ var/minimap_show_walls = TRUE
+
/**
* These two vars allow for multiple unique areas to be linked to a master area
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
diff --git a/code/game/area/areas/ruins/_ruins.dm b/code/game/area/areas/ruins/_ruins.dm
index 6699e94129..f9af5c8ce4 100644
--- a/code/game/area/areas/ruins/_ruins.dm
+++ b/code/game/area/areas/ruins/_ruins.dm
@@ -9,6 +9,9 @@
ambientsounds = RUINS
sound_environment = SOUND_ENVIRONMENT_STONEROOM
var/valid_territory = FALSE // hey so what if we did not allow things like cult summons to appear on ruins
+ minimap_color = "#775940"
+ minimap_color2 = "#6b5d48"
+ minimap_show_walls = FALSE
/area/ruin/unpowered
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 242f3123e1..6bb6b444b0 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -518,7 +518,7 @@
. = list("[get_examine_string(user, TRUE)].")
if(desc)
- . += desc
+ . += "[desc]"
if(custom_materials)
var/list/materials_list = list()
@@ -702,7 +702,7 @@
var/blood_id = get_blood_id()
if(!(blood_id in GLOB.blood_reagent_types))
return
- return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
+ return list("color" = BLOOD_COLOR_HUMAN, "blendmode" = BLEND_MULTIPLY, "ANIMAL DNA" = "Y-")
/mob/living/carbon/get_blood_dna_list()
var/blood_id = get_blood_id()
@@ -711,14 +711,16 @@
var/list/blood_dna = list()
if(dna)
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
+ blood_dna["blendmode"] = dna.species.exotic_blood_blend_mode
blood_dna[dna.unique_enzymes] = dna.blood_type
else
blood_dna["color"] = BLOOD_COLOR_HUMAN
+ blood_dna["blendmode"] = BLEND_MULTIPLY
blood_dna["UNKNOWN DNA"] = "X*"
return blood_dna
/mob/living/carbon/alien/get_blood_dna_list()
- return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
+ return list("color" = BLOOD_COLOR_XENO, "blendmode" = BLEND_MULTIPLY, "UNKNOWN DNA" = "X*")
//to add a mob's dna info into an object's blood_DNA list.
/atom/proc/transfer_mob_blood_dna(mob/living/L)
@@ -737,6 +739,7 @@
var/old = blood_DNA["color"]
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
changed = old != blood_DNA["color"]
+ blood_DNA["blendmode"] = new_blood_dna["blendmode"]
if(blood_DNA.len == old_length)
return FALSE
return changed
@@ -756,6 +759,7 @@
blood_DNA["color"] = blood_dna["color"]
else
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
+ blood_DNA["blendmode"] = blood_dna["blendmode"]
//to add blood from a mob onto something, and transfer their dna info
/atom/proc/add_mob_blood(mob/living/M)
@@ -826,6 +830,11 @@
/atom/proc/blood_DNA_to_color()
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
+/atom/proc/blood_DNA_to_blend()
+ if(blood_DNA && !isnull(blood_DNA["blendmode"]))
+ return blood_DNA["blendmode"]
+ return BLEND_MULTIPLY
+
/atom/proc/clean_blood()
. = blood_DNA? TRUE : FALSE
blood_DNA = null
@@ -1192,6 +1201,8 @@
log_mecha(log_text)
if(LOG_SHUTTLE)
log_shuttle(log_text)
+ if(LOG_ECON)
+ log_econ(log_text)
else
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
log_game(log_text)
@@ -1295,7 +1306,7 @@
filters += filter(arglist(arguments))
UNSETEMPTY(filter_data)
-/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
+/atom/proc/transition_filter(name, time, list/new_params, easing, loop, parallel = TRUE)
var/filter = get_filter(name)
if(!filter)
return
@@ -1306,7 +1317,7 @@
for(var/thing in new_params)
params[thing] = new_params[thing]
- animate(filter, new_params, time = time, easing = easing, loop = loop)
+ animate(filter, new_params, time = time, easing = easing, loop = loop, flags = (parallel ? ANIMATION_PARALLEL : 0))
for(var/param in params)
filter_data[name][param] = params[param]
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 56c668a24b..bace332ef2 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -64,6 +64,16 @@
/// last time we yelled
var/last_yell = 0
+ // Text-to-bark sounds
+ var/sound/vocal_bark
+ var/vocal_bark_id
+ var/vocal_pitch = 1
+ var/vocal_pitch_range = 0.2 //Actual pitch is (pitch - (vocal_pitch_range*0.5)) to (pitch + (vocal_pitch_range*0.5))
+ var/vocal_volume = 70 //Baseline. This gets modified by yelling and other factors
+ var/vocal_speed = 4 //Lower values are faster, higher values are slower
+
+ var/vocal_current_bark //When barks are queued, this gets passed to the bark proc. If vocal_current_bark doesn't match the args passed to the bark proc (if passed at all), then the bark simply doesn't play. Basic curtailing of spam~
+
/atom/movable/Initialize(mapload)
. = ..()
switch(blocks_emissive)
@@ -217,6 +227,10 @@
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
+ if(NAMEOF(src, vocal_bark))
+ if(isfile(var_value))
+ vocal_bark = sound(var_value) //bark() expects vocal_bark to already be a sound datum, for performance reasons. adminbus QoL!
+ . = TRUE
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
@@ -604,11 +618,11 @@
if(throwing && !throw_override)
return
if(on && !(movement_type & FLOATING))
- animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+ animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+ animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if (!on && (movement_type & FLOATING))
- animate(src, pixel_y = initial(pixel_y), time = 10)
+ animate(src, pixel_z = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
floating_need_update = FALSE // assume it's done
@@ -696,6 +710,17 @@
var/datum/language_holder/LH = get_language_holder()
return LH.update_atom_languages(src)
+/// Sets the vocal bark for the atom, using the bark's ID
+/atom/movable/proc/set_bark(id)
+ if(!id)
+ return FALSE
+ var/datum/bark/B = GLOB.bark_list[id]
+ if(!B)
+ return FALSE
+ vocal_bark = sound(initial(B.soundpath))
+ vocal_bark_id = id
+ return vocal_bark
+
/* End language procs */
@@ -774,4 +799,4 @@
M.Turn(pick(-30, 30))
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
- animate(I, alpha = 0, transform = matrix(), time = 1)
+ animate(I, alpha = 0, transform = matrix(), time = 1, flags = ANIMATION_PARALLEL)
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index e9a1fb61e0..62b2a6da8d 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -104,6 +104,10 @@ Class Procs:
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
+ vocal_bark_id = "synth"
+ vocal_pitch = 0.6
+ vocal_volume = 40
+
var/stat = 0
var/use_power = IDLE_POWER_USE
//0 = dont run the auto
@@ -312,6 +316,36 @@ Class Procs:
return TRUE // If we passed all of those checks, woohoo! We can interact with this machine.
+/obj/machinery/proc/can_transact(obj/item/card/id/thecard, allowdepartment, silent)
+ if(!istype(thecard))
+ if(!silent)
+ say("No card found.")
+ return FALSE
+ else if (!thecard.registered_account)
+ if(!silent)
+ say("No account found.")
+ return FALSE
+ else if(!allowdepartment && !thecard.registered_account.account_job)
+ if(!silent)
+ say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
+ return FALSE
+ return TRUE
+
+/obj/machinery/proc/attempt_transact(obj/item/card/id/thecard, transaction_cost)
+ if(!istype(thecard))
+ return FALSE
+ var/datum/bank_account/account = thecard.registered_account
+ if(!istype(account))
+ return FALSE
+
+ if(transaction_cost)
+ if(!account.adjust_money(-transaction_cost))
+ return FALSE
+ var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
+ if(D)
+ D.adjust_money(transaction_cost)
+ return TRUE
+
/obj/machinery/proc/check_nap_violations()
if(!SSeconomy.full_ancap)
return TRUE
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 35f45818b6..4f876b97e1 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -62,14 +62,15 @@
if(!is_operational())
return
- if(shocked && !(stat & NOPOWER))
- shock(user,50)
-
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Autolathe", capitalize(src.name))
ui.open()
+ if(shocked && !(stat & NOPOWER))
+ if(shock(user,50))
+ ui.close() //close the window if they got zapped successfully as to prevent them from getting zapped infinitely.
+
/obj/machinery/autolathe/ui_data(mob/user)
var/list/data = list()
data["materials"] = list()
@@ -298,6 +299,16 @@
wires.interact(user)
return STOP_ATTACK_PROC_CHAIN
+/obj/machinery/autolathe/wirecutter_act(mob/living/user, obj/item/I)
+ . = ..()
+ if(busy)
+ balloon_alert(user, "it's busy!")
+ return STOP_ATTACK_PROC_CHAIN
+
+ if(panel_open)
+ wires.interact(user)
+ return STOP_ATTACK_PROC_CHAIN
+
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
use_power(MINERAL_MATERIAL_AMOUNT / 10)
diff --git a/code/game/machinery/colormate.dm b/code/game/machinery/colormate.dm
index 1528142a3b..a208fc0bd2 100644
--- a/code/game/machinery/colormate.dm
+++ b/code/game/machinery/colormate.dm
@@ -1,6 +1,10 @@
+#define COLORMATE_TINT 1
+#define COLORMATE_HSV 2
+#define COLORMATE_MATRIX 3
+
/obj/machinery/gear_painter
name = "\improper Color Mate"
- desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
+ desc = "A machine to give your apparel a fresh new color!"
icon = 'icons/obj/vending.dmi'
icon_state = "colormate"
// light_mask = "colormate-light-mask"
@@ -10,7 +14,11 @@
var/atom/movable/inserted
var/activecolor = "#FFFFFF"
var/list/color_matrix_last
- var/matrix_mode = FALSE
+ var/active_mode = COLORMATE_HSV
+
+ var/build_hue = 0
+ var/build_sat = 1
+ var/build_val = 1
/// Allow holder'd mobs
var/allow_mobs = TRUE
/// Minimum lightness for normal mode
@@ -71,8 +79,8 @@
return
if(!QDELETED(H))
H.release()
+
insert_mob(victim, user)
- temp = "[victim] has been inserted."
SStgui.update_uis(src)
if(is_type_in_list(I, allowed_types) && is_operational())
@@ -85,7 +93,6 @@
inserted = I
update_icon()
- temp = "[I] has been inserted."
SStgui.update_uis(src)
else
@@ -134,7 +141,7 @@
/obj/machinery/gear_painter/ui_data(mob/user)
. = list()
- .["matrixactive"] = matrix_mode
+ .["activemode"] = active_mode
.["matrixcolors"] = list(
"rr" = color_matrix_last[1],
"rg" = color_matrix_last[2],
@@ -149,6 +156,9 @@
"cg" = color_matrix_last[11],
"cb" = color_matrix_last[12]
)
+ .["buildhue"] = build_hue
+ .["buildsat"] = build_sat
+ .["buildval"] = build_val
if(temp)
.["temp"] = temp
if(inserted)
@@ -166,7 +176,7 @@
if(inserted)
switch(action)
if("switch_modes")
- matrix_mode = text2num(params["mode"])
+ active_mode = text2num(params["mode"])
return TRUE
if("choose_color")
var/chosen_color = input(usr, "Choose a color: ", "Colormate color picking", activecolor) as color|null
@@ -174,14 +184,11 @@
activecolor = chosen_color
return TRUE
if("paint")
- if(!check_valid_color(activecolor, usr))
- return TRUE
- inserted.add_atom_colour(activecolor, FIXED_COLOUR_PRIORITY)
- playsound(src, 'sound/effects/spray3.ogg', 50, 1)
+ do_paint(usr)
temp = "Painted Successfully!"
return TRUE
if("drop")
- temp = "Ejected \the [inserted]!"
+ temp = ""
drop_item()
return TRUE
if("clear")
@@ -192,76 +199,95 @@
if("set_matrix_color")
color_matrix_last[params["color"]] = params["value"]
return TRUE
- if("matrix_paint")
- var/list/cm = rgb_construct_color_matrix(
- text2num(color_matrix_last[1]),
- text2num(color_matrix_last[2]),
- text2num(color_matrix_last[3]),
- text2num(color_matrix_last[4]),
- text2num(color_matrix_last[5]),
- text2num(color_matrix_last[6]),
- text2num(color_matrix_last[7]),
- text2num(color_matrix_last[8]),
- text2num(color_matrix_last[9]),
- text2num(color_matrix_last[10]),
- text2num(color_matrix_last[11]),
- text2num(color_matrix_last[12])
- )
- if(!check_valid_color(cm, usr))
- return TRUE
- inserted.add_atom_colour(cm, FIXED_COLOUR_PRIORITY)
- playsound(src, 'sound/effects/spray3.ogg', 50, 1)
- temp = "Matrix Painted Successfully!"
+ if("set_hue")
+ build_hue = clamp(text2num(params["buildhue"]), 0, 360)
return TRUE
+ if("set_sat")
+ build_sat = clamp(text2num(params["buildsat"]), -10, 10)
+ return TRUE
+ if("set_val")
+ build_val = clamp(text2num(params["buildval"]), -10, 10)
+ return TRUE
+
+
+/obj/machinery/gear_painter/proc/do_paint(mob/user)
+ var/color_to_use
+ switch(active_mode)
+ if(COLORMATE_TINT)
+ color_to_use = activecolor
+ if(COLORMATE_MATRIX)
+ color_to_use = rgb_construct_color_matrix(
+ text2num(color_matrix_last[1]),
+ text2num(color_matrix_last[2]),
+ text2num(color_matrix_last[3]),
+ text2num(color_matrix_last[4]),
+ text2num(color_matrix_last[5]),
+ text2num(color_matrix_last[6]),
+ text2num(color_matrix_last[7]),
+ text2num(color_matrix_last[8]),
+ text2num(color_matrix_last[9]),
+ text2num(color_matrix_last[10]),
+ text2num(color_matrix_last[11]),
+ text2num(color_matrix_last[12])
+ )
+ if(COLORMATE_HSV)
+ color_to_use = color_matrix_hsv(build_hue, build_sat, build_val)
+ color_matrix_last = color_to_use
+ if(!color_to_use || !check_valid_color(color_to_use, user))
+ to_chat(user, "Invalid color.")
+ return FALSE
+ inserted.add_atom_colour(color_to_use, FIXED_COLOUR_PRIORITY)
+ playsound(src, 'sound/effects/spray3.ogg', 50, 1)
+ return TRUE
+
/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin.
/obj/machinery/gear_painter/proc/build_preview()
if(inserted) //sanity
- if(matrix_mode)
- var/list/cm = rgb_construct_color_matrix(
- text2num(color_matrix_last[1]),
- text2num(color_matrix_last[2]),
- text2num(color_matrix_last[3]),
- text2num(color_matrix_last[4]),
- text2num(color_matrix_last[5]),
- text2num(color_matrix_last[6]),
- text2num(color_matrix_last[7]),
- text2num(color_matrix_last[8]),
- text2num(color_matrix_last[9]),
- text2num(color_matrix_last[10]),
- text2num(color_matrix_last[11]),
- text2num(color_matrix_last[12])
- )
- if(!check_valid_color(cm, usr))
- temp = "Failed to generate preview: Invalid color!"
- return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
+ var/list/cm
+ switch(active_mode)
+ if(COLORMATE_MATRIX)
+ cm = rgb_construct_color_matrix(
+ text2num(color_matrix_last[1]),
+ text2num(color_matrix_last[2]),
+ text2num(color_matrix_last[3]),
+ text2num(color_matrix_last[4]),
+ text2num(color_matrix_last[5]),
+ text2num(color_matrix_last[6]),
+ text2num(color_matrix_last[7]),
+ text2num(color_matrix_last[8]),
+ text2num(color_matrix_last[9]),
+ text2num(color_matrix_last[10]),
+ text2num(color_matrix_last[11]),
+ text2num(color_matrix_last[12])
+ )
+ if(!check_valid_color(cm, usr))
+ return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
- var/cur_color = inserted.color
- inserted.color = null
- inserted.color = cm
- var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
- inserted.color = cur_color
+ if(COLORMATE_TINT)
+ if(!check_valid_color(activecolor, usr))
+ return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
- . = preview
+ if(COLORMATE_HSV)
+ cm = color_matrix_hsv(build_hue, build_sat, build_val)
+ color_matrix_last = cm
+ if(!check_valid_color(cm, usr))
+ return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
- else
- if(!check_valid_color(activecolor, usr))
- temp = "Failed to generate preview: Invalid color!"
- return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
+ var/cur_color = inserted.color
+ inserted.color = null
+ inserted.color = (active_mode == COLORMATE_TINT ? activecolor : cm)
+ var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
+ inserted.color = cur_color
+ temp = ""
- var/cur_color = inserted.color
- inserted.color = null
- inserted.color = activecolor
- var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
- inserted.color = cur_color
-
- . = preview
+ . = preview
/obj/machinery/gear_painter/proc/check_valid_color(list/cm, mob/user)
if(!islist(cm)) // normal
var/list/HSV = ReadHSV(RGBtoHSV(cm))
if(HSV[3] < minimum_normal_lightness)
- temp = "[cm] is far too dark (min lightness [minimum_normal_lightness]!"
+ temp = "[cm] is too dark (Minimum lightness: [minimum_normal_lightness])"
return FALSE
return TRUE
else // matrix
@@ -275,6 +301,6 @@
COLORTEST("FFFFFF", cm)
#undef COLORTEST
if(passed < minimum_matrix_tests)
- temp = "[english_list(color)] is not allowed (passed [passed] out of 4, minimum [minimum_matrix_tests], minimum lightness [minimum_matrix_lightness])."
+ temp = "Matrix is too dark. (passed [passed] out of [minimum_matrix_tests] required tests. Minimum lightness: [minimum_matrix_lightness])."
return FALSE
return TRUE
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 8b24a3804f..956b3e9c79 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -6,17 +6,22 @@
verb_say = "states"
density = TRUE
req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_ENGINE, ACCESS_CARGO, ACCESS_THEATRE)
+ payment_department = ACCOUNT_SRV
var/active = FALSE
var/list/rangers = list()
var/stop = 0
var/volume = 70
- var/datum/track/selection = null
+ var/queuecost = PRICE_CHEAP //Set to -1 to make this jukebox require access for queueing
+ var/datum/track/playing = null
+ var/datum/track/selectedtrack = null
+ var/list/queuedplaylist = list()
+ var/queuecooldown //This var exists solely to prevent accidental repeats of John Mulaney's 'What's New Pussycat?' incident. Intentional, however......
/obj/machinery/jukebox/disco
name = "radiant dance machine mark IV"
desc = "The first three prototypes were discontinued after mass casualty incidents."
icon_state = "disco"
- req_access = list(ACCESS_ENGINE)
+ req_one_access = list(ACCESS_ENGINE)
anchored = FALSE
var/list/spotlights = list()
var/list/sparkles = list()
@@ -24,7 +29,7 @@
/obj/machinery/jukebox/disco/indestructible
name = "radiant dance machine mark V"
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
- req_access = null
+ req_one_access = null
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = NODECONSTRUCT_1
@@ -46,6 +51,16 @@
return
return ..()
+/obj/machinery/jukebox/emag_act(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ return
+ obj_flags |= EMAGGED
+ queuecost = PRICE_FREE
+ req_one_access = null
+ to_chat(user, "You've bypassed [src]'s audio volume limiter, and enabled free play.")
+ return TRUE
+
/obj/machinery/jukebox/update_icon_state()
if(active)
icon_state = "[initial(icon_state)]-active"
@@ -56,7 +71,7 @@
if(!anchored)
to_chat(user,"This device must be anchored by a wrench!")
return UI_CLOSE
- if(!allowed(user) && !isobserver(user))
+ if((queuecost < 0 && !allowed(user)) && !isobserver(user))
to_chat(user,"Error: Access Denied.")
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return UI_CLOSE
@@ -77,18 +92,21 @@
data["active"] = active
data["songs"] = list()
for(var/datum/track/S in SSjukeboxes.songs)
- var/list/track_data = list(
- name = S.song_name
- )
+ var/list/track_data = list(name = S.song_name)
data["songs"] += list(track_data)
+ data["queued_tracks"] = list()
+ for(var/datum/track/S in queuedplaylist)
+ var/list/track_data = list(name = S.song_name)
+ data["queued_tracks"] += list(track_data)
data["track_selected"] = null
data["track_length"] = null
- data["track_beat"] = null
- if(selection)
- data["track_selected"] = selection.song_name
- data["track_length"] = DisplayTimeText(selection.song_length)
- data["track_beat"] = selection.song_beat
+ if(playing)
+ data["track_selected"] = playing.song_name
+ data["track_length"] = DisplayTimeText(playing.song_length)
data["volume"] = volume
+ data["is_emagged"] = (obj_flags & EMAGGED)
+ data["cost_for_play"] = queuecost
+ data["has_access"] = allowed(user)
return data
/obj/machinery/jukebox/ui_act(action, list/params)
@@ -100,57 +118,91 @@
if("toggle")
if(QDELETED(src))
return
- if(!active)
- if(stop > world.time)
- to_chat(usr, "Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].")
- playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
- return
+ if(!allowed(usr))
+ return
+ if(!active && !playing)
activate_music()
- START_PROCESSING(SSobj, src)
- return TRUE
else
stop = 0
- return TRUE
- if("select_track")
- if(active)
- to_chat(usr, "Error: You cannot change the song until the current one is over.")
+ return TRUE
+ if("add_to_queue")
+ if(QDELETED(src))
return
+ if(world.time < queuecooldown)
+ return
+ if(!istype(selectedtrack, /datum/track))
+ return
+ if(!allowed(usr) && queuecost)
+ var/obj/item/card/id/C
+ if(isliving(usr))
+ var/mob/living/L = usr
+ C = L.get_idcard(TRUE)
+ if(!can_transact(C))
+ queuecooldown = world.time + (1 SECONDS)
+ playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
+ return
+ if(!attempt_transact(C, queuecost))
+ say("Insufficient funds.")
+ queuecooldown = world.time + (1 SECONDS)
+ playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
+ return
+ to_chat(usr, "You spend [queuecost] credits to queue [selectedtrack.song_name].")
+ log_econ("[queuecost] credits were inserted into [src] by [key_name(usr)] (ID: [C.registered_name]) to queue [selectedtrack.song_name].")
+ queuedplaylist += selectedtrack
+ if(active)
+ say("[selectedtrack.song_name] has been added to the queue.")
+ else if(!playing)
+ activate_music()
+ playsound(src, 'sound/machines/ping.ogg', 50, TRUE)
+ queuecooldown = world.time + (3 SECONDS)
+ return TRUE
+ if("select_track")
var/list/available = list()
for(var/datum/track/S in SSjukeboxes.songs)
available[S.song_name] = S
var/selected = params["track"]
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return
- selection = available[selected]
+ selectedtrack = available[selected]
return TRUE
if("set_volume")
+ if(!allowed(usr))
+ return
var/new_volume = params["volume"]
if(new_volume == "reset")
volume = initial(volume)
- return TRUE
else if(new_volume == "min")
volume = 0
- return TRUE
else if(new_volume == "max")
- volume = 100
- return TRUE
+ volume = ((obj_flags & EMAGGED) ? 210 : 100)
else if(text2num(new_volume) != null)
- volume = text2num(new_volume)
- return TRUE
+ volume = clamp(0, text2num(new_volume), ((obj_flags & EMAGGED) ? 210 : 100))
+ var/wherejuke = SSjukeboxes.findjukeboxindex(src)
+ if(wherejuke)
+ SSjukeboxes.updatejukebox(wherejuke, jukefalloff = volume/35)
+ return TRUE
/obj/machinery/jukebox/proc/activate_music()
- var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
+ if(playing || !queuedplaylist.len)
+ return FALSE
+ playing = queuedplaylist[1]
+ var/jukeboxslottotake = SSjukeboxes.addjukebox(src, playing, volume/35)
if(jukeboxslottotake)
active = TRUE
update_icon()
START_PROCESSING(SSobj, src)
- stop = world.time + selection.song_length
+ stop = world.time + playing.song_length
+ queuedplaylist.Cut(1, 2)
+ say("Now playing: [playing.song_name]")
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, TRUE)
return TRUE
else
return FALSE
/obj/machinery/jukebox/disco/activate_music()
- ..()
+ . = ..()
+ if(!.)
+ return
dance_setup()
lights_spin()
@@ -243,7 +295,7 @@
S.pixel_y = 7
S.forceMove(get_turf(src))
sleep(7)
- if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
+ if(playing.song_name == "Engineering's Ultimate High-Energy Hustle")
sleep(280)
for(var/obj/reveal in sparkles)
reveal.alpha = 255
@@ -299,7 +351,7 @@
continue
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
INVOKE_ASYNC(src, .proc/hierofunk)
- sleep(selection.song_beat)
+ sleep(playing.song_beat)
#undef DISCO_INFENO_RANGE
@@ -431,6 +483,7 @@
return
SSjukeboxes.removejukebox(position)
STOP_PROCESSING(SSobj, src)
+ playing = null
rangers = list()
/obj/machinery/jukebox/disco/dance_over()
@@ -439,12 +492,21 @@
QDEL_LIST(sparkles)
/obj/machinery/jukebox/process()
- if(active && world.time >= stop)
- active = FALSE
- dance_over()
- playsound(src,'sound/machines/terminal_off.ogg',50,1)
- update_icon()
- stop = world.time + 100
+ if(active)
+ if(world.time >= stop)
+ active = FALSE
+ dance_over()
+ if(stop && queuedplaylist.len)
+ activate_music()
+ else
+ playsound(src,'sound/machines/terminal_off.ogg',50,1)
+ update_icon()
+ playing = null
+ stop = 0
+ else if(volume > 140) // BOOM BOOM BOOM BOOM
+ for(var/mob/living/carbon/C in hearers(round(volume/35), src)) // I WANT YOU IN MY ROOM
+ if(istype(C)) // LETS SPEND THE NIGHT TOGETHER
+ C.adjustEarDamage(max((((volume/35) - sqrt(get_dist(C, src) * 4)) - C.get_ear_protection())*0.1, 0)) // FROM NOW UNTIL FOREVER
/obj/machinery/jukebox/disco/process()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index ed62019824..84e7b93e1b 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1356,6 +1356,7 @@
/obj/machinery/door/airlock/proc/remove_electrify()
secondsElectrified = NOT_ELECTRIFIED
unelectrify_timerid = null
+ diag_hud_set_electrified()
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
secondsElectrified = seconds
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index 18ed5205be..458f231f4b 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -203,9 +203,13 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
point_gain = (BOMB_TARGET_POINTS * 2 * orig_light) / (orig_light + BOMB_TARGET_SIZE)
/*****The Point Capper*****/
- if(point_gain > linked_techweb.largest_bomb_value)
- var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
- linked_techweb.largest_bomb_value = point_gain
+
+ var/list/largest_values = linked_techweb.largest_values
+ if(!(LARGEST_BOMB in largest_values))
+ largest_values[LARGEST_BOMB] = 0
+ if(point_gain > largest_values[LARGEST_BOMB])
+ var/old_tech_largest_bomb_value = largest_values[LARGEST_BOMB] //held so we can pull old before we do math
+ linked_techweb.largest_values[LARGEST_BOMB] = point_gain
point_gain -= old_tech_largest_bomb_value
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
if(D)
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index ff6f96a29f..12b2ba08e4 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -230,13 +230,13 @@
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
- . += "\tAttached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.\n"
+ . += "Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.\n"
else
- . += "\tAttached is an empty [beaker.name].\n"
+ . += "Attached is an empty [beaker.name].\n"
else
- . += "\tNo chemicals are attached.\n"
+ . += "No chemicals are attached.\n"
- . += "\t[attached ? attached : "No one"] is attached."
+ . += "[attached ? attached : "No one"] is attached."
/obj/machinery/iv_drip/telescopic
name = "telescopic IV drip"
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 4a05885b70..f4a82cb883 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -13,6 +13,17 @@
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
+DEFINE_BITFIELD(turret_flags, list(
+ "TURRET_FLAG_AUTH_WEAPONS" = TURRET_FLAG_AUTH_WEAPONS,
+ "TURRET_FLAG_SHOOT_ALL" = TURRET_FLAG_SHOOT_ALL,
+ "TURRET_FLAG_SHOOT_ALL_REACT" = TURRET_FLAG_SHOOT_ALL_REACT,
+ "TURRET_FLAG_SHOOT_ANOMALOUS" = TURRET_FLAG_SHOOT_ANOMALOUS,
+ "TURRET_FLAG_SHOOT_BORGS" = TURRET_FLAG_SHOOT_BORGS,
+ "TURRET_FLAG_SHOOT_CRIMINALS" = TURRET_FLAG_SHOOT_CRIMINALS,
+ "TURRET_FLAG_SHOOT_HEADS" = TURRET_FLAG_SHOOT_HEADS,
+ "TURRET_FLAG_SHOOT_UNSHIELDED" = TURRET_FLAG_SHOOT_UNSHIELDED,
+))
+
/obj/machinery/porta_turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index 2438a6b66b..5aaed2a808 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -29,10 +29,12 @@
var/obj/effect/overlay/status_display_text/message1_overlay
var/obj/effect/overlay/status_display_text/message2_overlay
+ var/mutable_appearance/ai_vtuber_overlay
var/current_picture = ""
var/current_mode = SD_BLANK
var/message1 = ""
var/message2 = ""
+ var/mob/living/silicon/ai/master
/obj/item/wallframe/status_display
name = "status display frame"
@@ -122,6 +124,10 @@
if(overlay && message == overlay.message)
return null
+ // if an AI is controlling, we don't update the overlay
+ if(master)
+ return
+
if(overlay)
qdel(overlay)
@@ -147,6 +153,10 @@
remove_messages()
return
+ if(master)
+ remove_messages()
+ return
+
switch(current_mode)
if(SD_BLANK)
remove_messages()
@@ -493,6 +503,42 @@
user.emote(initial(emote.key))
break
+// ai vtuber moment
+/obj/machinery/status_display/AICtrlClick(mob/living/silicon/ai/user)
+ if(!isAI(user) || master || (user.current && !istype(user.current, /obj/machinery/status_display))) // don't let two AIs control the same one, don't let AI control two things at once
+ return
+
+ if(!user.client.prefs.custom_holoform_icon)
+ to_chat(user, span_notice("You have no custom holoform set!"))
+ return
+
+ // move AI to the location, set master, update overlays (removes messages)
+ user.current = src
+ user.eyeobj.setLoc(get_turf(src))
+ icon_state = initial(icon_state)
+ user.controlled_display = src
+ master = user
+ update_overlays()
+ update_appearance()
+
+ // we set the avatar here
+ var/icon/I = icon(user.client.prefs.custom_holoform_icon)
+ I.Crop(1,16,32,32)
+ ai_vtuber_overlay = mutable_appearance(I)
+ ai_vtuber_overlay.blend_mode = BLEND_ADD
+ ai_vtuber_overlay.pixel_y = 8
+ update_overlays()
+ add_overlay(ai_vtuber_overlay)
+
+ // tell the user how to speak
+ to_chat(user, span_notice("Use :q to relay messages through the status display."))
+
+// modified version of how holopads 'hear' and relay to AIs
+/obj/machinery/status_display/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
+ . = ..()
+ if(master && !radio_freq && master.controlled_display == src)
+ master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
+
/obj/machinery/status_display/ai/process()
if(stat & NOPOWER)
update_appearance()
diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm
index 2762416949..f57daac309 100644
--- a/code/game/objects/effects/decals/cleanable/gibs.dm
+++ b/code/game/objects/effects/decals/cleanable/gibs.dm
@@ -3,6 +3,7 @@
desc = "They look bloody and gruesome."
icon_state = "gibbl5"
layer = LOW_OBJ_LAYER
+ blend_mode = BLEND_DEFAULT
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
mergeable_decal = FALSE
bloodiness = 0 //This isn't supposed to be bloody.
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 8aea7047b6..04942a1253 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -3,6 +3,7 @@
desc = "It's gooey. Perhaps it's the chef's cooking?"
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
+ blend_mode = BLEND_MULTIPLY
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
blood_state = BLOOD_STATE_BLOOD
bloodiness = BLOOD_AMOUNT_PER_DECAL
@@ -33,16 +34,20 @@
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ blend_mode = blood_DNA_to_blend()
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
. = ..()
data["color"] = color
+ data["blendmode"] = blend_mode
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
. = ..()
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
+ if(data["blendmode"])
+ blend_mode = data["blendmode"]
name = "dried blood"
desc = "Looks like it's been here a while. Eew"
bloodiness = 0
@@ -82,8 +87,8 @@
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon = 'icons/effects/blood.dmi'
- icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
+ blend_mode = BLEND_MULTIPLY
random_icon_states = null
beauty = -50
persistent = TRUE
@@ -95,6 +100,7 @@
. = ..()
data["dir"] = dir
data["color"] = color
+ data["blendmode"] = blend_mode
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
. = ..()
@@ -103,11 +109,14 @@
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
+ if(data["blendmode"])
+ blend_mode = data["blendmode"]
/obj/effect/decal/cleanable/trail_holder/update_icon()
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ blend_mode = blood_DNA_to_blend()
/obj/effect/cleanable/trail_holder/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index be3f1709a9..0dcc23f3aa 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1,4 +1,5 @@
GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire"))
+GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons/effects/welding_effect.dmi', "welding_sparks", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE))
GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// if true, everyone item when created will have its name changed to be
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index f66a1bea24..f680d0034b 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -601,11 +601,12 @@
H.adjustOxyLoss(H.health - HALFWAYCRITDEATH, 0)
else
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
- var/mobhealth = H.health
- H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
- H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
- H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
- H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
+ if(overall_damage)
+ var/mobhealth = H.health
+ H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
+ H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
+ H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
+ H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually.
user.visible_message("[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.")
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 0ca2e40b45..69fc53c904 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -145,32 +145,29 @@ GENETICS SCANNER
mob_status = "Deceased"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
- var/msg = "*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]"
+ var/msg = "Analyzing results for [M]:\n
")
dat += "Enter your date of birth here, to confirm that you are over 18. "
@@ -152,6 +89,9 @@
if(!(client.prefs.db_flags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE)) //completed? Skip
return TRUE
+ if(!client)
+ return FALSE
+
var/age_verification = age_gate()
//ban them and kick them
if(age_verification != 1)
@@ -269,61 +209,12 @@
if(!age_verify())
return
- //Determines Relevent Population Cap
- var/relevant_cap
- var/hpc = CONFIG_GET(number/hard_popcap)
- var/epc = CONFIG_GET(number/extreme_popcap)
- if(hpc && epc)
- relevant_cap = min(hpc, epc)
- else
- relevant_cap = max(hpc, epc)
-
- if(href_list["show_preferences"])
- client.prefs.ShowChoices(src)
- return 1
-
- if(href_list["ready"])
- var/tready = text2num(href_list["ready"])
- //Avoid updating ready if we're after PREGAME (they should use latejoin instead)
- //This is likely not an actual issue but I don't have time to prove that this
- //no longer is required
- if(SSticker.current_state <= GAME_STATE_PREGAME)
- ready = tready
- //if it's post initialisation and they're trying to observe we do the needful
- if(!SSticker.current_state < GAME_STATE_PREGAME && tready == PLAYER_READY_TO_OBSERVE)
- ready = tready
- make_me_an_observer()
- return
-
- if(href_list["refresh"])
- src << browse(null, "window=playersetup") //closes the player setup window
- new_player_panel()
-
if(href_list["late_join"])
if(!SSticker || !SSticker.IsRoundInProgress())
to_chat(usr, "The round is either not ready, or has already finished...")
return
-
- if(href_list["late_join"] == "override")
- LateChoices()
- return
-
- if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in GLOB.admin_datums)))
- to_chat(usr, "[CONFIG_GET(string/hard_popcap_message)]")
-
- var/queue_position = SSticker.queued_players.Find(usr)
- if(queue_position == 1)
- to_chat(usr, "You are next in line to join the game. You will be notified when a slot opens up.")
- else if(queue_position)
- to_chat(usr, "There are [queue_position-1] players in front of you in the queue to join the game.")
- else
- SSticker.queued_players += usr
- to_chat(usr, "You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len].")
- return
LateChoices()
-
- if(href_list["manifest"])
- ViewManifest()
+ return
if(href_list["SelectedJob"])
if(!SSticker || !SSticker.IsRoundInProgress())
@@ -337,6 +228,17 @@
to_chat(usr, "There is an administrative lock on entering the game!")
return
+ //Determines Relevent Population Cap
+ var/relevant_cap
+ var/hpc = CONFIG_GET(number/hard_popcap)
+ var/epc = CONFIG_GET(number/extreme_popcap)
+ if(hpc && epc)
+ relevant_cap = min(hpc, epc)
+ else
+ relevant_cap = max(hpc, epc)
+
+
+
if(SSticker.queued_players.len && !(ckey(key) in GLOB.admin_datums))
if((living_player_count() >= relevant_cap) || (src != SSticker.queued_players[1]))
to_chat(usr, "Server is full.")
@@ -349,6 +251,15 @@
if(!GLOB.enter_allowed)
to_chat(usr, " There is an administrative lock on entering the game!")
+ //Determines Relevent Population Cap
+ var/relevant_cap
+ var/hpc = CONFIG_GET(number/hard_popcap)
+ var/epc = CONFIG_GET(number/extreme_popcap)
+ if(hpc && epc)
+ relevant_cap = min(hpc, epc)
+ else
+ relevant_cap = max(hpc, epc)
+
if(SSticker.queued_players.len && !(ckey(key) in GLOB.admin_datums))
if((living_player_count() >= relevant_cap) || (src != SSticker.queued_players[1]))
to_chat(usr, "Server is full.")
@@ -360,13 +271,6 @@
SSticker.queue_delay = 4
qdel(src)
- else if(!href_list["late_join"])
- new_player_panel()
-
- if(href_list["showpoll"])
- handle_player_polling()
- return
-
if(href_list["pollid"])
var/pollid = href_list["pollid"]
if(istext(pollid))
@@ -460,7 +364,6 @@
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
src << browse(null, "window=playersetup") //closes the player setup window
- new_player_panel()
return FALSE
var/mob/dead/observer/observer = new()
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index a9233938ab..378313311e 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -24,6 +24,9 @@
var/rando_race = pick(GLOB.roundstart_races)
pref_species = new rando_race()
features = random_features(pref_species?.id, gender)
+ bark_id = pick(GLOB.bark_random_list)
+ bark_pitch = BARK_PITCH_RAND(gender)
+ bark_variance = BARK_VARIANCE_RAND
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon(current_tab)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 4b228e1eb3..94917e4de0 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -121,7 +121,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
remove_verb(src, /mob/dead/observer/verb/boo)
remove_verb(src, /mob/dead/observer/verb/possess)
- animate(src, pixel_y = 2, time = 10, loop = -1)
+ animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+ animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
add_to_dead_mob_list()
@@ -534,8 +535,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/stop_orbit(datum/component/orbiter/orbits)
. = ..()
//restart our floating animation after orbit is done.
- pixel_y = 0
- animate(src, pixel_y = 2, time = 10, loop = -1)
+ pixel_z = 0
+ animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+ animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index eabf2e2d0e..8d5bd40acc 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -30,7 +30,7 @@
// Takes care blood loss and regeneration
-/mob/living/carbon/human/handle_blood()
+/mob/living/carbon/human/handle_blood(delta_time, times_fired)
if(NOBLOOD in dna.species.species_traits || bleedsuppress || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
return
@@ -39,56 +39,57 @@
return
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood.
- if(integrating_blood > 0)
- var/blood_integrated = max(integrating_blood - 1, 0)
- var/blood_diff = integrating_blood - blood_integrated
- integrating_blood = blood_integrated
- if(blood_volume < BLOOD_VOLUME_MAXIMUM)
- blood_volume += blood_diff
- if(blood_volume < BLOOD_VOLUME_NORMAL)
- var/nutrition_ratio = 0
- if(!HAS_TRAIT(src, TRAIT_NOHUNGER))
- switch(nutrition)
- if(0 to NUTRITION_LEVEL_STARVING)
- nutrition_ratio = 0.2
- if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
- nutrition_ratio = 0.4
- if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
- nutrition_ratio = 0.6
- if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
- nutrition_ratio = 0.8
- else
- nutrition_ratio = 1
- if(satiety > 80)
- nutrition_ratio *= 1.25
- adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR)
- blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
+ if(dna.species.handle_blood(src, delta_time, times_fired)) // if this returns TRUE, then the species is not handling blood itself and we can control everything
+ if(integrating_blood > 0)
+ var/blood_integrated = max(integrating_blood - 1, 0)
+ var/blood_diff = integrating_blood - blood_integrated
+ integrating_blood = blood_integrated
+ if(blood_volume < BLOOD_VOLUME_MAXIMUM)
+ blood_volume += blood_diff
+ if(blood_volume < BLOOD_VOLUME_NORMAL)
+ var/nutrition_ratio = 0
+ if(!HAS_TRAIT(src, TRAIT_NOHUNGER))
+ switch(nutrition)
+ if(0 to NUTRITION_LEVEL_STARVING)
+ nutrition_ratio = 0.2
+ if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
+ nutrition_ratio = 0.4
+ if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
+ nutrition_ratio = 0.6
+ if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
+ nutrition_ratio = 0.8
+ else
+ nutrition_ratio = 1
+ if(satiety > 80)
+ nutrition_ratio *= 1.25
+ adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR)
+ blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
- //Effects of bloodloss
- if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM)) //Synths are immune to direct consequences of bloodloss, instead suffering penalties to heat exchange.
- var/word = pick("dizzy","woozy","faint")
- var/blood_effect_volume = blood_volume + integrating_blood
- switch(blood_effect_volume)
- if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
- if(prob(10))
- to_chat(src, "You feel terribly bloated.")
- if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
- if(prob(5))
- to_chat(src, "You feel [word].")
- adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
- if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
- adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
- if(prob(5))
- blur_eyes(6)
- to_chat(src, "You feel very [word].")
- if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
- adjustOxyLoss(5)
- if(prob(15))
- Unconscious(rand(20,60))
- to_chat(src, "You feel extremely [word].")
- if(-INFINITY to BLOOD_VOLUME_SURVIVE)
- if(!HAS_TRAIT(src, TRAIT_NODEATH))
- death()
+ //Effects of bloodloss
+ if(!HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM)) //Synths are immune to direct consequences of bloodloss, instead suffering penalties to heat exchange.
+ var/word = pick("dizzy","woozy","faint")
+ var/blood_effect_volume = blood_volume + integrating_blood
+ switch(blood_effect_volume)
+ if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
+ if(prob(10))
+ to_chat(src, "You feel terribly bloated.")
+ if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
+ if(prob(5))
+ to_chat(src, "You feel [word].")
+ adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
+ if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
+ adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
+ if(prob(5))
+ blur_eyes(6)
+ to_chat(src, "You feel very [word].")
+ if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
+ adjustOxyLoss(5)
+ if(prob(15))
+ Unconscious(rand(20,60))
+ to_chat(src, "You feel extremely [word].")
+ if(-INFINITY to BLOOD_VOLUME_SURVIVE)
+ if(!HAS_TRAIT(src, TRAIT_NODEATH))
+ death()
var/temp_bleed = 0
//Bleeding out
@@ -193,6 +194,7 @@
blood_data["blood_DNA"] = dna.unique_enzymes
blood_data["bloodcolor"] = dna.species.exotic_blood_color
+ blood_data["bloodblend"] = dna.species.exotic_blood_blend_mode
if(disease_resistances && disease_resistances.len)
blood_data["resistances"] = disease_resistances.Copy()
var/list/temp_chem = list()
@@ -264,7 +266,7 @@
"O-" = list("O-","SY"),
"O+" = list("O-", "O+","SY"),
"L" = list("L","SY"),
- "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U","SY"),
+ "U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U","SY", "BUG"),
"HF" = list("HF", "SY"),
"X*" = list("X*", "SY"),
"SY" = list("SY"),
@@ -370,27 +372,6 @@
if(!B)
B = new(T)
-//This is a terrible way of handling it.
-/mob/living/proc/ResetBloodVol()
- if(ishuman(src))
- var/mob/living/carbon/human/H = src
- if (HAS_TRAIT(src, TRAIT_HIGH_BLOOD))
- blood_ratio = 1.2
- H.handle_blood()
- return
- blood_ratio = 1
- H.handle_blood()
- return
- blood_ratio = 1
-
-/mob/living/proc/AdjustBloodVol(value)
- if(blood_ratio == value)
- return
- blood_ratio = value
- if(ishuman(src))
- var/mob/living/carbon/human/H = src
- H.handle_blood()
-
/mob/living/proc/adjust_integration_blood(value, remove_actual_blood, force)
if(integrating_blood + value < 0 && remove_actual_blood)
blood_volume += value + integrating_blood
diff --git a/code/modules/mob/living/brain/life.dm b/code/modules/mob/living/brain/life.dm
index 823d47dee2..e42f82d5cd 100644
--- a/code/modules/mob/living/brain/life.dm
+++ b/code/modules/mob/living/brain/life.dm
@@ -1,5 +1,5 @@
-/mob/living/brain/BiologicalLife(seconds, times_fired)
+/mob/living/brain/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
handle_emp_damage()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
index 9563959ebc..ff4a7d2bba 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm
@@ -51,7 +51,7 @@
// update_icons() //Handled in update_transform(), leaving this here as a reminder
update_transform()
-/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that.
+/mob/living/carbon/alien/humanoid/update_transform(do_animate) //The old method of updating lying/standing was update_icons(). Aliens still expect that.
if(lying > 0)
lying = 90 //Anything else looks silly
..()
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index f0004b5ed9..b22ff68531 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/alien/larva/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/alien/larva/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
// GROW!
diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm
index e6e7e657e8..85416261c7 100644
--- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm
+++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm
@@ -21,7 +21,7 @@
else
icon_state = "larva[state]"
-/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
+/mob/living/carbon/alien/larva/update_transform(do_animate) //All this is handled in update_icons()
..()
return update_icons()
diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm
index 530d2acd63..b56c897b03 100644
--- a/code/modules/mob/living/carbon/alien/life.dm
+++ b/code/modules/mob/living/carbon/alien/life.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/alien/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/alien/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
findQueen()
diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm
index 1a159a56bb..85c188d2ab 100644
--- a/code/modules/mob/living/carbon/damage_procs.dm
+++ b/code/modules/mob/living/carbon/damage_procs.dm
@@ -90,10 +90,12 @@
/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER) && toxins_type != TOX_SYSCORRUPT) //damage becomes healing and healing becomes damage
amount = -amount
+ // don't allow toxinlover to push blood levels past BLOOD_VOLUME_MAXIMUM, but also don't set it back down to this if it's higher from something else
+ var/blood_cap = blood_volume > BLOOD_VOLUME_MAXIMUM ? blood_volume : BLOOD_VOLUME_MAXIMUM
if(amount > 0)
- blood_volume -= 3 * amount //5x was too much, this is punishing enough.
+ blood_volume = min((blood_volume - (3 * amount)), blood_cap) //5x was too much, this is punishing enough.
else
- blood_volume -= amount
+ blood_volume = min((blood_volume - amount), blood_cap)
return ..()
/mob/living/carbon/getStaminaLoss()
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 5eabae16f7..958a8b599a 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -6,7 +6,7 @@
var/t_has = p_have()
var/t_is = p_are()
- . = list("*---------*\nThis is [icon2html(src, user)] \a [src]!")
+ . = list("This is [icon2html(src, user)] \a [src]!")
if (handcuffed)
. += "[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!"
@@ -152,8 +152,11 @@
. += "[t_He] look[p_s()] very happy."
if(MOOD_LEVEL_HAPPY4 to INFINITY)
. += "[t_He] look[p_s()] ecstatic."
+
+ if(LAZYLEN(.) > 1)
+ .[2] = "[.[2]]"
+
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
- . += "*---------*"
/mob/living/carbon/examine_more(mob/user)
if(!all_scars)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 32a4fac90f..93bd4c4eba 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -13,7 +13,7 @@
if(HAS_TRAIT(L, TRAIT_PROSOPAGNOSIA))
obscure_name = TRUE
- . = list("*---------*\nThis is [!obscure_name ? name : "Unknown"]!")
+ . = list("This is [!obscure_name ? name : "Unknown"]!")
var/vampDesc = ReturnVampExamine(user) // Vamps recognize the names of other vamps.
var/vassDesc = ReturnVassalExamine(user) // Vassals recognize each other's marks.
@@ -442,9 +442,10 @@
else if(isobserver(user) && traitstring)
. += "Traits: [traitstring]"
- SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) //This also handles flavor texts now
+ if(LAZYLEN(.) > 2) //Want this to appear after species text
+ .[3] = "[.[3]]"
- . += "*---------*"
+ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) //This also handles flavor texts now
/mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects!
var/list/dat = list()
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 5b6fae8e1b..1de40ec80c 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -550,7 +550,7 @@
to_chat(src, "You succesfuly remove the durathread strand.")
remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
return
- var/to_send = ""
+ var/to_send = "
"
visible_message("[src] examines [p_them()]self.", \
"You check yourself for injuries.")
@@ -597,27 +597,27 @@
var/no_damage
if(status == "OK" || status == "no damage")
no_damage = TRUE
- to_send += "\t Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].\n"
+ to_send += "Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].\n"
for(var/thing in LB.wounds)
var/datum/wound/W = thing
var/msg
switch(W.severity)
if(WOUND_SEVERITY_TRIVIAL)
- msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]."
+ msg = "Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]."
if(WOUND_SEVERITY_MODERATE)
- msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!"
+ msg = "Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!"
if(WOUND_SEVERITY_SEVERE)
- msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!"
+ msg = "Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!"
if(WOUND_SEVERITY_CRITICAL)
- msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!"
+ msg = "Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!"
to_chat(src, msg)
for(var/obj/item/I in LB.embedded_objects)
if(I.isEmbedHarmless())
- to_chat(src, "\t There is \a [I] stuck to your [LB.name]!")
+ to_chat(src, "There is \a [I] stuck to your [LB.name]!")
else
- to_chat(src, "\t There is \a [I] embedded in your [LB.name]!")
+ to_chat(src, "There is \a [I] embedded in your [LB.name]!")
for(var/t in missing)
to_send += "Your [parse_zone(t)] is missing!\n"
@@ -724,6 +724,8 @@
if(roundstart_quirks.len)
to_send += "You have these quirks: [get_trait_string()].\n"
+ to_send += "
"
+
to_chat(src, to_send)
else
if(wear_suit)
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 54d6771c6c..141fbb89d7 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -85,6 +85,7 @@
FP.blood_DNA["color"] = S.last_blood_color
else
FP.blood_DNA["color"] = BlendRGB(FP.blood_DNA["color"], S.last_blood_color)
+ FP.blood_DNA["blendmode"] = S.last_blood_blend
FP.update_icon()
update_inv_shoes()
//End bloody footprints
diff --git a/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
index 52e2a87a7d..2cfbf9fb73 100644
--- a/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
+++ b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm
@@ -30,6 +30,10 @@
currently_coiled.pixel_x = 12
/datum/action/innate/ability/coiling/proc/coil_mob(var/mob/living/carbon/human/H)
+ if(currently_coiling)
+ to_chat(owner, span_warning("You are already coiling someone!"))
+ return
+
// begin the coiling action
H.visible_message("[owner] coils [H] with their tail!", \
"[owner] coils you with their tail!")
@@ -58,6 +62,9 @@
/datum/action/innate/ability/coiling/proc/cancel_coil()
var/mob/living/carbon/human/H = owner
+
+ if(!currently_coiling)
+ return
// cancel the coiling action by removing the overlay
currently_coiled.pixel_x = 0
diff --git a/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm b/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm
index ce36397c91..6f3809c232 100644
--- a/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm
+++ b/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm
@@ -25,25 +25,21 @@
/datum/action/innate/ability/limb_regrowth/Activate()
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
- if(limbs_to_heal.len < 1)
- to_chat(H, "You feel intact enough as it is.")
+ if(!length(limbs_to_heal))
+ to_chat(H, span_notice("You feel intact enough as it is."))
return
- to_chat(H, "You focus intently on your missing [limbs_to_heal.len >= 2 ? "limbs" : "limb"]...")
- var/mode = H.get_ability_property(INNATE_ABILITY_LIMB_REGROWTH, PROPERTY_LIMB_REGROWTH_USAGE_TYPE)
- switch(mode)
- if(REGROWTH_USES_BLOOD)
- if(H.blood_volume >= 40*limbs_to_heal.len+(BLOOD_VOLUME_OKAY*H.blood_ratio))
- H.regenerate_limbs()
- H.blood_volume -= 40*limbs_to_heal.len
- to_chat(H, "...and after a moment you finish reforming!")
- return
- else if(H.blood_volume >= 40)//We can partially heal some limbs
- while(H.blood_volume >= (BLOOD_VOLUME_OKAY*H.blood_ratio)+40)
- var/healed_limb = pick(limbs_to_heal)
- H.regenerate_limb(healed_limb)
- limbs_to_heal -= healed_limb
- H.blood_volume -= 40
- to_chat(H, "...but there is not enough of you to fix everything! You must attain more mass to heal completely!")
- return
- to_chat(H, "...but there is not enough of you to go around! You must attain more mass to heal!")
-
+ to_chat(H, span_notice("You focus intently on your missing [length(limbs_to_heal) >= 2 ? "limbs" : "limb"]..."))
+ if(H.blood_volume >= 40*length(limbs_to_heal)+BLOOD_VOLUME_OKAY)
+ H.regenerate_limbs()
+ H.blood_volume -= 40*length(limbs_to_heal)
+ to_chat(H, span_notice("...and after a moment you finish reforming!"))
+ return
+ else if(H.blood_volume >= 40)//We can partially heal some limbs
+ while(H.blood_volume >= BLOOD_VOLUME_OKAY+40)
+ var/healed_limb = pick(limbs_to_heal)
+ H.regenerate_limb(healed_limb)
+ limbs_to_heal -= healed_limb
+ H.blood_volume -= 40
+ to_chat(H, span_warning("...but there is not enough of you to fix everything! You must attain more mass to heal completely!"))
+ return
+ to_chat(H, span_warning("...but there is not enough of you to go around! You must attain more mass to heal!"))
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 1ea28211af..4221df31f6 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -18,7 +18,7 @@
#define THERMAL_PROTECTION_HAND_LEFT 0.025
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
-/mob/living/carbon/human/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/human/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
handle_active_genes()
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm
index ebf76eeafa..cccee4a7ef 100644
--- a/code/modules/mob/living/carbon/human/login.dm
+++ b/code/modules/mob/living/carbon/human/login.dm
@@ -7,8 +7,8 @@
return
var/list/print_msg = list()
- print_msg += "*---------*"
print_msg += "As you snap back to consciousness, you recall people messing with your stuff..."
+ print_msg += "
"
afk_thefts = reverseRange(afk_thefts)
@@ -22,13 +22,14 @@
var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
- print_msg += "\tSomeone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago."
+ print_msg += "Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago."
else
- print_msg += "\t[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago."
+ print_msg += "[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago."
+
+ print_msg += "
"
if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
print_msg += "There may have been more, but that's all you can remember..."
- print_msg += "*---------*"
to_chat(src, print_msg.Join("\n"))
LAZYNULL(afk_thefts)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 4eccbc62c7..afceabf2a6 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -65,6 +65,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/exotic_bloodtype = ""
/// Assume human as the default blood colour, override this default by species subtypes
var/exotic_blood_color = BLOOD_COLOR_HUMAN
+ /// Which blend mode should this species blood use?
+ var/exotic_blood_blend_mode = BLEND_MULTIPLY
///What the species drops when gibbed by a gibber machine.
var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
var/list/gib_types = list(/obj/effect/gibspawner/human, /obj/effect/gibspawner/human/bodypartless)
@@ -826,13 +828,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/left_state = DEFAULT_LEFT_EYE_STATE
var/right_state = DEFAULT_RIGHT_EYE_STATE
if(eye_type in GLOB.eye_types)
- left_state = eye_type + "_left_eye"
- right_state = eye_type + "_right_eye"
+ left_state = "[eye_type]_left_eye"
+ right_state = "[eye_type]_right_eye"
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER)
if((EYECOLOR in species_traits) && has_eyes)
- left_eye.color = "#" + H.left_eye_color
- right_eye.color = "#" + H.right_eye_color
+ left_eye.color = "#[H.left_eye_color]"
+ right_eye.color = "#[H.right_eye_color]"
if(OFFSET_EYES in offset_features)
left_eye.pixel_x += offset_features[OFFSET_EYES][1]
left_eye.pixel_y += offset_features[OFFSET_EYES][2]
@@ -2450,6 +2452,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
return TRUE
return FALSE
+////////////////
+//Blood Stuff///
+////////////////
+// true = handle blood normally, false = do not (and then handle blood in this proc instead please!!)
+/datum/species/proc/handle_blood(mob/living/carbon/human/H, delta_time, times_fired)
+ return TRUE
+
////////////////
//Tail Wagging//
////////////////
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 3b84752e1e..4712fe4475 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -17,6 +17,7 @@
exotic_blood = /datum/reagent/blood/jellyblood
exotic_bloodtype = "GEL"
exotic_blood_color = "BLOOD_COLOR_SLIME"
+ exotic_blood_blend_mode = BLEND_DEFAULT
damage_overlay_type = ""
liked_food = TOXIC | MEAT
disliked_food = null
@@ -31,6 +32,7 @@
species_category = SPECIES_CATEGORY_JELLY
wings_icons = SPECIES_WINGS_JELLY
ass_image = 'icons/ass/assslime.png'
+ blacklisted_quirks = list(/datum/quirk/glass_bones)
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
C.faction -= "slime"
@@ -53,38 +55,46 @@
//update blood color to body color
exotic_blood_color = "#" + H.dna.features["mcolor"]
-/datum/species/jelly/spec_life(mob/living/carbon/human/H)
- if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for bloodsuckers
- return
- if(!H.blood_volume)
- H.adjust_integration_blood(5)
- H.adjustBruteLoss(5)
- to_chat(H, "You feel empty!")
+/datum/species/jelly/handle_blood(mob/living/carbon/human/H, delta_time, times_fired)
+ if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
+ return TRUE // we dont handle blood when dead
- if(H.blood_volume < (BLOOD_VOLUME_NORMAL * H.blood_ratio))
+ if(H.blood_volume <= 0)
+ H.blood_volume += 2.5 * delta_time
+ H.adjustBruteLoss(2.5 * delta_time)
+ to_chat(H, span_danger("You feel empty!"))
+
+ if(H.blood_volume < BLOOD_VOLUME_NORMAL)
if(H.nutrition >= NUTRITION_LEVEL_STARVING)
- H.adjust_integration_blood(3)
- H.nutrition -= 2.5
- if(H.blood_volume < (BLOOD_VOLUME_OKAY*H.blood_ratio))
- if(prob(5))
- to_chat(H, "You feel drained!")
- if(H.blood_volume < (BLOOD_VOLUME_BAD*H.blood_ratio))
+ H.blood_volume += 1.5 * delta_time
+ H.adjust_nutrition(-1.25 * delta_time)
+
+ if(H.blood_volume < BLOOD_VOLUME_OKAY)
+ if(DT_PROB(2.5, delta_time))
+ to_chat(H, span_danger("You feel drained!"))
+
+ if(H.blood_volume < BLOOD_VOLUME_BAD)
Cannibalize_Body(H)
- ..()
+
+ var/datum/action/innate/ability/regrowth = H.ability_actions[INNATE_ABILITY_LIMB_REGROWTH]
+ if(regrowth)
+ regrowth.UpdateButtonIcon()
+
+ return FALSE // to let living/handle_blood know that the species is handling blood instead
/datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H)
var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs()
var/obj/item/bodypart/consumed_limb
- if(!limbs_to_consume.len)
+ if(!length(limbs_to_consume))
H.losebreath++
return
if(H.get_num_legs(FALSE)) //Legs go before arms
limbs_to_consume -= list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM)
consumed_limb = H.get_bodypart(pick(limbs_to_consume))
consumed_limb.drop_limb()
- to_chat(H, "Your [consumed_limb] is drawn back into your body, unable to maintain its shape!")
+ to_chat(H, span_userdanger("Your [consumed_limb] is drawn back into your body, unable to maintain its shape!"))
qdel(consumed_limb)
- H.adjust_integration_blood(20)
+ H.blood_volume += 20
////////////////////////////////////////////////////////SLIMEPEOPLE///////////////////////////////////////////////////////////////////
diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
index 9c29856084..5fb816867f 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -26,6 +26,7 @@
wings_icons = SPECIES_WINGS_SKELETAL
ass_image = 'icons/ass/assplasma.png'
+ blacklisted_quirks = list(/datum/quirk/paper_skin)
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
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 5a927397fb..9c52a6a9d1 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -17,6 +17,7 @@
species_category = SPECIES_CATEGORY_SKELETON //they have their own category that's disassociated from undead, paired with plasmapeople
wings_icons = SPECIES_WINGS_SKELETAL
+ blacklisted_quirks = list(/datum/quirk/paper_skin)
/datum/species/skeleton/New()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index cb2458e376..a0620c8990 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -209,7 +209,7 @@ There are several things that need to be remembered:
inv.update_icon()
if(!gloves && bloody_hands)
- var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
+ var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
if(get_num_arms(FALSE) < 2)
if(has_left_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_left"
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 27f795015e..dadf169c35 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,6 +1,6 @@
-/mob/living/carbon/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/BiologicalLife(delta_time, times_fired)
//Reagent processing needs to come before breathing, to prevent edge cases.
- handle_organs(seconds, times_fired)
+ handle_organs(delta_time, times_fired)
. = ..() // if . is false, we are dead.
if(stat == DEAD)
stop_sound_channel(CHANNEL_HEARTBEAT)
@@ -9,7 +9,7 @@
. = FALSE
if(!.)
return
- handle_blood()
+ handle_blood(delta_time, times_fired)
// handle_blood *could* kill us.
// we should probably have a better system for if we need to check for death or something in the future hmw
if(stat != DEAD)
@@ -23,7 +23,7 @@
handle_brain_damage()
if(stat != DEAD)
- handle_liver(seconds, times_fired)
+ handle_liver(delta_time, times_fired)
if(stat != DEAD)
handle_corruption()
@@ -375,7 +375,7 @@
miasma_turf.air_update_turf()
-/mob/living/carbon/proc/handle_blood()
+/mob/living/carbon/proc/handle_blood(delta_time, times_fired)
return
/mob/living/carbon/proc/handle_bodyparts(seconds, times_fired)
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index ffb0e329be..a7bc0c11d5 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -3,7 +3,7 @@
/mob/living/carbon/monkey
-/mob/living/carbon/monkey/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/monkey/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(client)
diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm
index c8b8dbbc9d..585a93f304 100644
--- a/code/modules/mob/living/carbon/monkey/punpun.dm
+++ b/code/modules/mob/living/carbon/monkey/punpun.dm
@@ -33,7 +33,7 @@
if(relic_mask)
equip_to_slot_or_del(new relic_mask, ITEM_SLOT_MASK)
-/mob/living/carbon/monkey/punpun/BiologicalLife(seconds, times_fired)
+/mob/living/carbon/monkey/punpun/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -46,6 +46,7 @@
..()
/mob/living/carbon/monkey/punpun/proc/Read_Memory()
+ var/saved_color
if(fexists("data/npc_saves/Punpun.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
S["ancestor_name"] >> ancestor_name
@@ -62,6 +63,9 @@
ancestor_chain = json["ancestor_chain"]
relic_hat = json["relic_hat"]
relic_mask = json["relic_hat"]
+ saved_color = json["color"]
+ if(!isnull(saved_color))
+ add_atom_colour(json_decode(saved_color), FIXED_COLOUR_PRIORITY)
/mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed)
var/json_file = file("data/npc_saves/Punpun.json")
@@ -71,10 +75,12 @@
file_data["ancestor_chain"] = null
file_data["relic_hat"] = null
file_data["relic_mask"] = null
+ file_data["color"] = null
else
file_data["ancestor_name"] = ancestor_name ? ancestor_name : name
file_data["ancestor_chain"] = dead ? ancestor_chain + 1 : ancestor_chain
file_data["relic_hat"] = head ? head.type : null
file_data["relic_mask"] = wear_mask ? wear_mask.type : null
+ file_data["color"] = color ? json_encode(color) : null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index 99396ca09e..d59978d993 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -518,6 +518,8 @@
/datum/emote/living/circle/run_emote(mob/user, params)
. = ..()
+ if(!.)
+ return
var/obj/item/circlegame/N = new(user)
if(user.put_in_hands(N))
to_chat(user, "You make a circle with your hand.")
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 447256cb69..f4f8060fb3 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -42,8 +42,8 @@
* Handles biological life processes like chemical metabolism, breathing, etc
* Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop.
*/
-/mob/living/proc/BiologicalLife(seconds, times_fired)
- SEND_SIGNAL(src,COMSIG_LIVING_BIOLOGICAL_LIFE, seconds, times_fired)
+/mob/living/proc/BiologicalLife(delta_time, times_fired)
+ SEND_SIGNAL(src,COMSIG_LIVING_BIOLOGICAL_LIFE, delta_time, times_fired)
handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
handle_wounds()
@@ -67,7 +67,7 @@
//stuff in the stomach
handle_stomach()
- handle_block_parry(seconds)
+ handle_block_parry(delta_time)
handle_traits() // eye, ear, brain damages
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 6f394c1135..779e949f79 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -81,6 +81,7 @@
//Called when we bump onto a mob
/mob/living/proc/MobBump(mob/M)
+ SEND_SIGNAL(src, COMSIG_LIVING_MOB_BUMP, M)
//Even if we don't push/swap places, we "touched" them, so spread fire
spreadFire(M)
@@ -88,6 +89,7 @@
return TRUE
var/they_can_move = TRUE
+
if(isliving(M))
var/mob/living/L = M
they_can_move = CHECK_MOBILITY(L, MOBILITY_MOVE)
@@ -105,16 +107,16 @@
//Should stop you pushing a restrained person out of the way
if(L.pulledby && L.pulledby != src && L.restrained())
if(!(world.time % 5))
- to_chat(src, "[L] is restrained, you cannot push past.")
- return 1
+ to_chat(src, span_warning("[L] is restrained, you cannot push past."))
+ return TRUE
if(L.pulling)
if(ismob(L.pulling))
var/mob/P = L.pulling
if(P.restrained())
if(!(world.time % 5))
- to_chat(src, "[L] is restraining [P], you cannot push past.")
- return 1
+ to_chat(src, span_warning("[L] is restraining [P], you cannot push past."))
+ return TRUE
//CIT CHANGES START HERE - makes it so resting stops you from moving through standing folks or over prone bodies without a short delay
if(!CHECK_MOBILITY(src, MOBILITY_STAND))
@@ -142,7 +144,7 @@
//END OF CIT CHANGES
if(moving_diagonally)//no mob swap during diagonal moves.
- return 1
+ return TRUE
if(!M.buckled && !M.has_buckled_mobs())
var/mob_swap = FALSE
@@ -151,7 +153,8 @@
if(!too_strong)
mob_swap = TRUE
else
- if(M.pulledby == src && a_intent == INTENT_GRAB)
+ //You can swap with the person you are dragging on grab intent, and restrained people in most cases
+ if(M.pulledby == src && !too_strong)
mob_swap = TRUE
//restrained people act if they were on 'help' intent to prevent a person being pulled from being separated from their puller
else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP))
@@ -159,8 +162,8 @@
if(mob_swap)
//switch our position with M
if(loc && !loc.Adjacent(M.loc))
- return 1
- now_pushing = 1
+ return TRUE
+ now_pushing = TRUE
var/oldloc = loc
var/oldMloc = M.loc
@@ -180,27 +183,31 @@
if(!M_passmob)
M.pass_flags &= ~PASSMOB
- now_pushing = 0
+ now_pushing = FALSE
if(!move_failed)
- return 1
+ return TRUE
//okay, so we didn't switch. but should we push?
//not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
- return 1
+ return TRUE
if(isliving(M))
var/mob/living/L = M
if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE))
- return 1
- //If they're a human, and they're not in help intent, block pushing
- if(ishuman(M) && (M.a_intent != INTENT_HELP))
- return TRUE
+ return TRUE
+ if(M.a_intent != INTENT_HELP)
+ //If they're a human, and they're not in help intent, block pushing
+ if(ishuman(M))
+ return TRUE
+ //if they are a cyborg, and they're alive and not in help intent, block pushing
+ if(iscyborg(M) && M.stat != DEAD)
+ return TRUE
//anti-riot equipment is also anti-push
for(var/obj/item/I in M.held_items)
if(!istype(M, /obj/item/clothing))
if(prob(I.block_chance*2))
- return 1
+ return TRUE
/mob/living/get_photo_description(obj/item/camera/camera)
var/list/mob_details = list()
@@ -231,21 +238,40 @@
if(!client && (mob_size < MOB_SIZE_SMALL))
return
now_pushing = TRUE
- var/t = get_dir(src, AM)
+ SEND_SIGNAL(src, COMSIG_LIVING_PUSHING_MOVABLE, AM)
+ var/dir_to_target = get_dir(src, AM)
+
+ // If there's no dir_to_target then the player is on the same turf as the atom they're trying to push.
+ // This can happen when a player is stood on the same turf as a directional window. All attempts to push
+ // the window will fail as get_dir will return 0 and the player will be unable to move the window when
+ // it should be pushable.
+ // In this scenario, we will use the facing direction of the /mob/living attempting to push the atom as
+ // a fallback.
+ if(!dir_to_target)
+ dir_to_target = dir
+
var/push_anchored = FALSE
if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force)
- if(move_crush(AM, move_force, t))
+ if(move_crush(AM, move_force, dir_to_target))
push_anchored = TRUE
- if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally
- if(force_push(AM, move_force, t, push_anchored))
+ if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally
+ if(force_push(AM, move_force, dir_to_target, push_anchored))
push_anchored = TRUE
+ if(ismob(AM))
+ var/mob/mob_to_push = AM
+ var/atom/movable/mob_buckle = mob_to_push.buckled
+ // If we can't pull them because of what they're buckled to, make sure we can push the thing they're buckled to instead.
+ // If neither are true, we're not pushing anymore.
+ if(mob_buckle && (mob_buckle.buckle_prevents_pull || (force < (mob_buckle.move_resist * MOVE_FORCE_PUSH_RATIO))))
+ now_pushing = FALSE
+ return
if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO)))
now_pushing = FALSE
return
- if (istype(AM, /obj/structure/window))
+ if(istype(AM, /obj/structure/window))
var/obj/structure/window/W = AM
if(W.fulltile)
- for(var/obj/structure/window/win in get_step(W,t))
+ for(var/obj/structure/window/win in get_step(W, dir_to_target))
now_pushing = FALSE
return
if(pulling == AM)
@@ -253,8 +279,9 @@
var/current_dir
if(isliving(AM))
current_dir = AM.dir
- if(step(AM, t) && Process_Spacemove(t))
- step(src, t)
+ if(AM.Move(get_step(AM.loc, dir_to_target), dir_to_target, glide_size))
+ AM.add_fingerprint(src)
+ Move(get_step(loc, dir_to_target), dir_to_target)
if(current_dir)
AM.setDir(current_dir)
now_pushing = FALSE
@@ -354,29 +381,33 @@
offset = GRAB_PIXEL_SHIFT_NECK
if(GRAB_KILL)
offset = GRAB_PIXEL_SHIFT_NECK
- M.setDir(get_dir(M, src))
- switch(M.dir)
- if(NORTH)
- animate(M, pixel_x = 0, pixel_y = offset, 3)
- if(SOUTH)
- animate(M, pixel_x = 0, pixel_y = -offset, 3)
- if(EAST)
- if(M.lying == 270) //update the dragged dude's direction if we've turned
- M.lying = 90
- M.update_transform() //force a transformation update, otherwise it'll take a few ticks for update_mobility() to do so
- M.lying_prev = M.lying
- animate(M, pixel_x = offset, pixel_y = 0, 3)
- if(WEST)
- if(M.lying == 90)
- M.lying = 270
- M.update_transform()
- M.lying_prev = M.lying
- animate(M, pixel_x = -offset, pixel_y = 0, 3)
+ var/target_dir = get_dir(M, src)
+ M.setDir(target_dir)
+ var/target_x
+ var/target_y
+ if(target_dir & NORTH)
+ target_y += offset
+ if(target_dir & SOUTH)
+ target_y -= offset
+ if(target_dir & EAST)
+ target_x += offset
+ if(target_dir & WEST)
+ target_x -= offset
+ if(target_x || target_y)
+ if(0 < target_x && M.lying == 270)
+ M.lying = 90
+ M.update_transform(FALSE) //force a transformation update, otherwise it'll take a few ticks for update_mobility() to do so
+ M.lying_prev = M.lying
+ if(0 > target_x && M.lying == 90)
+ M.lying = 270
+ M.update_transform(FALSE)
+ M.lying_prev = M.lying
+ animate(M, pixel_x = target_x, pixel_y = target_y, time = 3, flags = ANIMATION_PARALLEL)
/mob/living/proc/reset_pull_offsets(mob/living/M, override)
if(!override && M.buckled)
return
- animate(M, pixel_x = 0, pixel_y = 0, 1)
+ animate(M, pixel_x = 0, pixel_y = 0, time = 3, flags = ANIMATION_PARALLEL)
//mob verbs are a lot faster than object verbs
//for more info on why this is not atom/pull, see examinate() in mob.dm
@@ -885,12 +916,11 @@
if(anchored || (buckled && buckled.anchored))
fixed = 1
if(on && !(movement_type & FLOATING) && !fixed)
- animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
- sleep(10)
- animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
+ animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+ animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if(((!on || fixed) && (movement_type & FLOATING)))
- animate(src, pixel_y = get_standard_pixel_y_offset(lying), time = 10)
+ animate(src, pixel_z = get_standard_pixel_y_offset(lying), time = 10)
setMovetype(movement_type & ~FLOATING)
// The src mob is trying to strip an item from someone
@@ -989,7 +1019,7 @@
var/pixel_y_diff = rand(-amplitude/3, amplitude/3)
var/final_pixel_x = get_standard_pixel_x_offset(lying)
var/final_pixel_y = get_standard_pixel_y_offset(lying)
- animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
+ animate(src, pixel_x = pixel_x_diff, pixel_y = pixel_y_diff , time = 2, loop = 6, flags = ANIMATION_PARALLEL | ANIMATION_RELATIVE)
animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2)
floating_need_update = TRUE
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 3aeabd1d51..02a3e3684e 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -238,7 +238,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) //parent calls can't overwrite the current proc args.
- if(!client)
+ if(!client && !audiovisual_redirect)
return
var/deaf_message
var/deaf_type
@@ -297,8 +297,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
- if(client && !eavesdrop_range && say_test(message) == "2") // Yell hook
- process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
+ var/is_yell = (say_test(message) == "2")
+ if(client && !eavesdrop_range && is_yell) // Yell hook
+ listening |= process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
//speech bubble
var/list/speech_bubble_recipients = list()
@@ -309,6 +310,23 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
+ //Listening gets trimmed here if a vocal bark's present. If anyone ever makes this proc return listening, make sure to instead initialize a copy of listening in here to avoid wonkiness
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_QUEUE_BARK, listening, args) || vocal_bark || vocal_bark_id)
+ for(var/mob/M in listening)
+ if(!M.client)
+ continue
+ if(!(M.client.prefs.toggles & SOUND_BARK))
+ listening -= M
+ var/barks = min(round((LAZYLEN(message) / vocal_speed)) + 1, BARK_MAX_BARKS)
+ var/total_delay
+ vocal_current_bark = world.time
+ for(var/i in 1 to barks)
+ if(total_delay > BARK_MAX_TIME)
+ break
+ addtimer(CALLBACK(src, /atom/movable/proc/bark, listening, (message_range * (is_yell ? 4 : 1)), (vocal_volume * (is_yell ? 1.5 : 1)), BARK_DO_VARY(vocal_pitch, vocal_pitch_range), vocal_current_bark), total_delay)
+ total_delay += rand(DS2TICKS(vocal_speed / BARK_SPEED_BASELINE), DS2TICKS(vocal_speed / BARK_SPEED_BASELINE) + DS2TICKS((vocal_speed / BARK_SPEED_BASELINE) * (is_yell ? 0.5 : 1))) TICKS
+
+
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
if(last_yell > (world.time - 10))
to_chat(src, "Your voice doesn't project as far as you try to yell in such quick succession.") // yeah no, no spamming an expensive floodfill.
@@ -333,6 +351,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/atom/movable/AM = _AM
AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
+ return overhearing
+
/mob/proc/binarycheck()
return FALSE
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a822917aa4..deaf50973d 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -47,6 +47,7 @@
var/mob/living/simple_animal/bot/Bot
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
+ var/obj/machinery/status_display/controlled_display
//MALFUNCTION
var/datum/module_picker/malf_picker
@@ -660,7 +661,7 @@
"goat" = 'icons/mob/animal.dmi',
"cat" = 'icons/mob/pets.dmi',
"cat2" = 'icons/mob/pets.dmi',
- "poly" = 'icons/mob/animal.dmi',
+ "polly" = 'icons/mob/animal.dmi',
"pug" = 'icons/mob/pets.dmi',
"spider" = 'icons/mob/animal.dmi'
)
@@ -669,7 +670,7 @@
if(input)
qdel(holo_icon)
switch(input)
- if("poly")
+ if("polly")
holo_icon = getHologramIcon(icon(icon_list[input],"parrot_fly"))
if("chicken")
holo_icon = getHologramIcon(icon(icon_list[input],"chicken_brown"))
@@ -1043,3 +1044,14 @@
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
. = eyeobj.zMove(dir, feedback)
+
+/mob/living/silicon/ai/proc/stop_controlling_display()
+ if(!controlled_display)
+ return
+ controlled_display.master = null
+ controlled_display.cut_overlay(controlled_display.ai_vtuber_overlay)
+ controlled_display.ai_vtuber_overlay = null
+ if(current == controlled_display)
+ current = null
+ controlled_display.update_appearance()
+ controlled_display = null
diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm
index 4cf9b81592..86de4c7c60 100644
--- a/code/modules/mob/living/silicon/ai/examine.dm
+++ b/code/modules/mob/living/silicon/ai/examine.dm
@@ -1,5 +1,5 @@
/mob/living/silicon/ai/examine(mob/user)
- . = list("*---------*\nThis is [icon2html(src, user)] [src]!")
+ . = list("This is [icon2html(src, user)] [src]!")
if (stat == DEAD)
. += "It appears to be powered-down."
else
@@ -17,6 +17,8 @@
. += "The wireless networking light is blinking."
else if (!shunted && !client)
. += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem..."
- . += "*---------*"
+
+ if(LAZYLEN(.) > 1)
+ .[2] = "[.[2]]"
. += ..()
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index bc6ab7c34e..bce18462b2 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -92,6 +92,8 @@
ai.light_cameras()
if(ai.master_multicam)
ai.master_multicam.refresh_view()
+ if(ai.controlled_display)
+ ai.stop_controlling_display()
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
/mob/camera/aiEye/zMove(dir, feedback = FALSE)
@@ -168,6 +170,9 @@
if(!user.tracking)
user.cameraFollow = null
+ if(user.controlled_display)
+ user.stop_controlling_display()
+
// Return to the Core.
/mob/living/silicon/ai/proc/view_core()
if(istype(current,/obj/machinery/holopad))
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index f14f2edcd4..ed969e49fb 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -3,7 +3,7 @@
#define POWER_RESTORATION_SEARCH_APC 2
#define POWER_RESTORATION_APC_FOUND 3
-/mob/living/silicon/ai/BiologicalLife(seconds, times_fired)
+/mob/living/silicon/ai/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
//I'm not removing that shitton of tabs, unneeded as they are. -- Urist
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index 2b5d3d98f2..76eaa6ad0d 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -34,8 +34,6 @@
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(message, language)
-
-
message = trim(message)
if (!message)
@@ -56,6 +54,29 @@
to_chat(src, "No holopad connected.")
+//For status displays only. Usable by AI.
+/mob/living/silicon/ai/proc/statusdisplay_talk(message, language)
+ message = trim(message)
+
+ if (!message)
+ return
+
+ var/obj/machinery/status_display/T = controlled_display
+ if(T)
+ var/turf/padturf = get_turf(T)
+ var/padloc
+ if(padturf)
+ padloc = AREACOORD(padturf)
+ else
+ padloc = "(UNKNOWN)"
+ src.log_talk(message, LOG_SAY, tag="STATUS DISPLAY in [padloc]")
+ send_speech(message, 7, T, "robot", message_language = language)
+ to_chat(src, "Status Display message transmitted, [real_name]\"[message]\"")
+ else
+ to_chat(src, "No status display connected.")
+
+
+
// Make sure that the code compiles with AI_VOX undefined
#ifdef AI_VOX
#define VOX_DELAY 600
diff --git a/code/modules/mob/living/silicon/examine.dm b/code/modules/mob/living/silicon/examine.dm
index 7de281de5f..0840ea1191 100644
--- a/code/modules/mob/living/silicon/examine.dm
+++ b/code/modules/mob/living/silicon/examine.dm
@@ -1,5 +1,4 @@
/mob/living/silicon/examine(mob/user) //Displays a silicon's laws to ghosts
- . = ..()
if(laws && isobserver(user))
. += "[src] has the following laws:"
for(var/law in laws.get_law_list(include_zeroth = TRUE))
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index fdde445379..ffe88705e4 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -152,7 +152,7 @@
if(possible_chassis[chassis])
AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD)
-/mob/living/silicon/pai/BiologicalLife(seconds, times_fired)
+/mob/living/silicon/pai/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(hacking)
diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm
index d499c2abae..5563f47e61 100644
--- a/code/modules/mob/living/silicon/robot/emote.dm
+++ b/code/modules/mob/living/silicon/robot/emote.dm
@@ -8,7 +8,7 @@
var/unrestricted = TRUE
/datum/emote/sound/silicon/run_emote(mob/user, params)
- if(!unrestricted && !(issilicon(user) || isipcperson(user)))
+ if(!unrestricted && !(issilicon(user) || isrobotic(user)))
return
return ..()
diff --git a/code/modules/mob/living/silicon/robot/examine.dm b/code/modules/mob/living/silicon/robot/examine.dm
index 45a3d15635..4ebd4c3be8 100644
--- a/code/modules/mob/living/silicon/robot/examine.dm
+++ b/code/modules/mob/living/silicon/robot/examine.dm
@@ -1,5 +1,5 @@
/mob/living/silicon/robot/examine(mob/user)
- . = list("*---------*\nThis is [icon2html(src, user)] \a [src], a [src.module.name] unit!")
+ . = list("This is [icon2html(src, user)] \a [src], a [src.module.name] unit!")
if(desc)
. += "[desc]"
@@ -49,8 +49,9 @@
if(DEAD)
. += "It looks like its system is corrupted and requires a reset."
+ if(LAZYLEN(.) > 1)
+ .[2] = "[.[2]]"
+
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, usr, .)
- . += "*---------*"
-
. += ..()
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index d1eaeeacc5..e902d57ddd 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -1,4 +1,4 @@
-/mob/living/silicon/robot/BiologicalLife(seconds, times_fired)
+/mob/living/silicon/robot/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
adjustOxyLoss(-10) //we're a robot!
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index f2f1f8adbe..d7c6dfe479 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -421,8 +421,8 @@
if("Alina")
cyborg_base_icon = "alina-med"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
- special_light_key = "alina"
- sleeper_overlay = "alinasleeper"
+ special_light_key = "alina-med"
+ sleeper_overlay = "valemedsleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
dogborg = TRUE
@@ -536,9 +536,9 @@
dogborg = TRUE
if("Alina")
cyborg_base_icon = "alina-eng"
- special_light_key = "alina"
+ special_light_key = "alina-eng"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
- sleeper_overlay = "alinasleeper"
+ sleeper_overlay = "valeengsleeper"
dogborg = TRUE
else
return FALSE
@@ -620,8 +620,8 @@
dogborg = TRUE
if("Alina")
cyborg_base_icon = "alina-sec"
- special_light_key = "alina"
- sleeper_overlay = "alinasleeper"
+ special_light_key = "alina-sec"
+ sleeper_overlay = "valesecsleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
dogborg = TRUE
if("K9 Dark")
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index b97536b7a4..76bfcf6eba 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -50,6 +50,9 @@
typing_indicator_state = /obj/effect/overlay/typing_indicator/machine
+ vocal_bark_id = "synth"
+ vocal_pitch_range = 0.1
+
/mob/living/silicon/Initialize(mapload)
. = ..()
GLOB.silicon_mobs += src
@@ -413,7 +416,7 @@
src << browse(dat, "window=airoster")
onclose(src, "airoster")
-/mob/living/silicon/update_transform()
+/mob/living/silicon/update_transform(do_animate)
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/changed = 0
if(resize != RESIZE_DEFAULT_SIZE)
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index 0ad684ab4b..806fc60156 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -19,6 +19,7 @@
path_image_color = "#993299"
weather_immunities = list("lava","ash")
+ var/base_icon = "cleanbot"
var/clean_time = 50 //How long do we take to clean?
var/upgrades = 0
@@ -126,13 +127,21 @@
/mob/living/simple_animal/bot/cleanbot/turn_on()
..()
- icon_state = "cleanbot[on]"
bot_core.updateUsrDialog()
+ update_icon()
/mob/living/simple_animal/bot/cleanbot/turn_off()
..()
- icon_state = "cleanbot[on]"
bot_core.updateUsrDialog()
+ update_icon()
+
+/mob/living/simple_animal/bot/cleanbot/update_icon_state()
+ . = ..()
+ switch(mode)
+ if(BOT_CLEANING)
+ icon_state = "[base_icon]-c"
+ else
+ icon_state = "[base_icon][on]"
/mob/living/simple_animal/bot/cleanbot/bot_reset()
..()
@@ -381,6 +390,12 @@
target = null
mode = BOT_IDLE
icon_state = "cleanbot[on]"
+ else if(istype(A, /turf)) //for player-controlled cleanbots so they can clean unclickable messes like dirt
+ var/turf/T = A
+ for(var/atom/S in T.contents)
+ if(istype(S, /obj/effect/decal/cleanable)) //clean the first mess found
+ UnarmedAttack(S)
+ return
else if(istype(A, /obj/item) || istype(A, /obj/effect/decal/remains))
visible_message("[src] sprays hydrofluoric acid at [A]!")
playsound(src, 'sound/effects/spray2.ogg', 50, TRUE, -6)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 3e32712fb3..7d37039fa1 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -83,13 +83,12 @@
/mob/living/simple_animal/hostile/construct/examine(mob/user)
var/t_He = p_they(TRUE)
var/t_s = p_s()
- . = list("*---------*\nThis is [icon2html(src, user)] \a [src]!\n[desc]")
+ . = list("This is [icon2html(src, user)] \a [src]!\n[desc]")
if(health < maxHealth)
if(health >= maxHealth/2)
. += "[t_He] look[t_s] slightly dented."
else
. += "[t_He] look[t_s] severely dented!"
- . += "*---------*"
/mob/living/simple_animal/hostile/construct/attack_animal(mob/living/simple_animal/M)
if(isconstruct(M)) //is it a construct?
diff --git a/code/modules/mob/living/simple_animal/eldritch_demons.dm b/code/modules/mob/living/simple_animal/eldritch_demons.dm
index 6fb53d42a4..eafac41303 100644
--- a/code/modules/mob/living/simple_animal/eldritch_demons.dm
+++ b/code/modules/mob/living/simple_animal/eldritch_demons.dm
@@ -223,7 +223,7 @@
QDEL_NULL(back) // chain destruction baby
return ..()
-/mob/living/simple_animal/hostile/eldritch/armsy/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/eldritch/armsy/BiologicalLife(delta_time, times_fired)
adjustBruteLoss(-2)
/mob/living/simple_animal/hostile/eldritch/armsy/proc/heal()
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 0d04d4b562..9673857a1b 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -35,6 +35,9 @@
collar_type = "cat"
var/held_icon = "cat2"
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "mutedc4"
+ vocal_pitch = 1.4
+ vocal_pitch_range = 0.4
/mob/living/simple_animal/pet/cat/Initialize(mapload)
. = ..()
@@ -115,7 +118,7 @@
Read_Memory()
. = ..()
-/mob/living/simple_animal/pet/cat/Runtime/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/cat/Runtime/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP)
@@ -136,6 +139,7 @@
..()
/mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory()
+ var/saved_color
if(fexists("data/npc_saves/Runtime.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Runtime.sav")
S["family"] >> family
@@ -146,14 +150,21 @@
return
var/list/json = json_decode(file2text(json_file))
family = json["family"]
+ saved_color = json["color"]
if(isnull(family))
family = list()
+ if(!isnull(saved_color))
+ add_atom_colour(json_decode(saved_color), FIXED_COLOUR_PRIORITY)
/mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead)
var/json_file = file("data/npc_saves/Runtime.json")
var/list/file_data = list()
family = list()
if(!dead)
+ if(color)
+ file_data["color"] = json_encode(color)
+ else
+ file_data["color"] = null
for(var/mob/living/simple_animal/pet/cat/kitten/C in children)
if(istype(C,type) || C.stat || !C.z || !C.butcher_results) //That last one is a work around for hologram cats
continue
@@ -161,6 +172,8 @@
family[C.type] += 1
else
family[C.type] = 1
+ else
+ file_data["color"] = null
file_data["family"] = family
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -178,7 +191,7 @@
gold_core_spawnable = NO_SPAWN
unique_pet = TRUE
-/mob/living/simple_animal/pet/cat/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/cat/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && !buckled && !client)
@@ -272,7 +285,7 @@
to_chat(src, "Your name is now \"new_name\"!")
name = new_name
-/mob/living/simple_animal/pet/cat/cak/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/cat/cak/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(stat)
diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm
index 8fd97a465c..775ad05c11 100644
--- a/code/modules/mob/living/simple_animal/friendly/crab.dm
+++ b/code/modules/mob/living/simple_animal/friendly/crab.dm
@@ -30,7 +30,7 @@
. = ..()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
-/mob/living/simple_animal/crab/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/crab/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
//CRAB movement
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index a12b28ea77..e4d042a4cc 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -20,6 +20,9 @@
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "bullet"
+ vocal_speed = 6
+
/mob/living/simple_animal/pet/dog/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
@@ -424,7 +427,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
RemoveElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/mob_holder, "old_corgi")
-/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -438,6 +441,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory()
set waitfor = FALSE
+ var/saved_color
if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
S["age"] >> age
@@ -452,12 +456,15 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
age = json["age"]
record_age = json["record_age"]
saved_head = json["saved_head"]
+ saved_color = json["color"]
if(isnull(age))
age = 0
if(isnull(record_age))
record_age = 1
if(saved_head)
place_on_head(new saved_head)
+ if(!isnull(saved_color))
+ add_atom_colour(json_decode(saved_color), FIXED_COLOUR_PRIORITY)
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Write_Memory(dead)
var/json_file = file("data/npc_saves/Ian.json")
@@ -472,10 +479,15 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
file_data["saved_head"] = inventory_head.type
else
file_data["saved_head"] = null
+ if(color)
+ file_data["color"] = json_encode(color)
+ else
+ file_data["color"] = null
else
file_data["age"] = 0
file_data["record_age"] = record_age
file_data["saved_head"] = null
+ file_data["color"] = null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -553,7 +565,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
nofur = TRUE
unique_pet = TRUE
-/mob/living/simple_animal/pet/dog/corgi/narsie/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/dog/corgi/narsie/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
for(var/mob/living/simple_animal/pet/P in range(1, src))
@@ -632,6 +644,8 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
mob_size = MOB_SIZE_SMALL
collar_type = "puppy"
+ vocal_pitch = 1.6
+
//puppies cannot wear anything.
/mob/living/simple_animal/pet/dog/corgi/puppy/Topic(href, href_list)
if(href_list["remove_inv"] || href_list["add_inv"])
@@ -653,6 +667,8 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
maxbodytemp = T0C + 40
held_icon = "void_puppy"
+ vocal_pitch = 0.6
+
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -679,7 +695,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
return
..()
-/mob/living/simple_animal/pet/dog/corgi/Lisa/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/dog/corgi/Lisa/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
@@ -693,7 +709,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list(
setDir(i)
sleep(1)
-/mob/living/simple_animal/pet/dog/pug/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/dog/pug/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 9ecc60f7eb..d35f12b0f6 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -178,7 +178,7 @@
/mob/living/simple_animal/drone/examine(mob/user)
- . = list("*---------*\nThis is [icon2html(src, user)] \a [src]!")
+ . = list("This is [icon2html(src, user)] \a [src]!")
//Hands
for(var/obj/item/I in held_items)
@@ -214,7 +214,7 @@
. += "A message repeatedly flashes on its display: \"REBOOT -- REQUIRED\"."
else
. += "A message repeatedly flashes on its display: \"ERROR -- OFFLINE\"."
- . += "*---------*"
+ . += ""
/mob/living/simple_animal/drone/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //Secbots won't hunt maintenance drones.
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index c6dfc772c1..7893f7b26b 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -36,6 +36,7 @@
var/datum/reagent/milk_reagent = /datum/reagent/consumable/milk
footstep_type = FOOTSTEP_MOB_SHOE
+ vocal_bark_id = "banjoc3"
/mob/living/simple_animal/hostile/retaliate/goat/Initialize(mapload, /datum/reagent/milk_reagent)
udder = new (null, milk_reagent)
@@ -46,7 +47,7 @@
udder = null
return ..()
-/mob/living/simple_animal/hostile/retaliate/goat/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/retaliate/goat/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(stat == CONSCIOUS)
@@ -143,6 +144,8 @@
blood_volume = BLOOD_VOLUME_NORMAL
footstep_type = FOOTSTEP_MOB_SHOE
+ vocal_bark_id = "mutedc2"
+ vocal_pitch = 1.2
/mob/living/simple_animal/cow/Initialize(mapload)
udder = new(null, milk_reagent)
@@ -160,7 +163,7 @@
else
return ..()
-/mob/living/simple_animal/cow/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/cow/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(stat == CONSCIOUS)
@@ -247,6 +250,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "squeak"
+ vocal_pitch = 1.4
/mob/living/simple_animal/chick/Initialize(mapload)
. = ..()
@@ -254,7 +259,7 @@
pixel_y = rand(0, 10)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
-/mob/living/simple_animal/chick/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/chick/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && !ckey)
@@ -263,7 +268,7 @@
new /mob/living/simple_animal/chicken(src.loc)
qdel(src)
-/mob/living/simple_animal/chick/holo/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/chick/holo/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
amount_grown = 0
@@ -309,6 +314,9 @@
var/static/chicken_count = 0
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "synthgrunt"
+ vocal_pitch = 1.4
+ vocal_pitch_range = 0.4
/mob/living/simple_animal/chicken/Initialize(mapload)
. = ..()
@@ -339,7 +347,7 @@
else
..()
-/mob/living/simple_animal/chicken/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/chicken/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if((!stat && prob(3) && eggsleft > 0) && egg_type)
@@ -403,6 +411,8 @@
var/static/kiwi_count = 0
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "squeak"
+ vocal_pitch = 1.4
/mob/living/simple_animal/kiwi/Destroy()
--kiwi_count
@@ -414,7 +424,7 @@
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
-/mob/living/simple_animal/kiwi/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/kiwi/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if((!stat && prob(3) && eggsleft > 0) && egg_type)
@@ -481,6 +491,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "squeak"
+ vocal_pitch = 1.4
/mob/living/simple_animal/babyKiwi/Initialize(mapload)
. = ..()
@@ -489,7 +501,7 @@
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
-/mob/living/simple_animal/babyKiwi/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/babyKiwi/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && !ckey)
@@ -557,3 +569,4 @@
maxHealth = 75
blood_volume = BLOOD_VOLUME_NORMAL
footstep_type = FOOTSTEP_MOB_SHOE
+ vocal_bark_id = "mutedc4"
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index 4e4fd7ccfc..475b50d44a 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -23,6 +23,11 @@
gold_core_spawnable = FRIENDLY_SPAWN
footstep_type = FOOTSTEP_MOB_CLAW
+ vocal_bark_id = "bullet"
+ vocal_speed = 2
+ vocal_pitch = 1.6
+ vocal_pitch_range = 0.4
+
/mob/living/simple_animal/pet/fox/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "fox")
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index d49eb1251d..f67c5dcb97 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -29,6 +29,8 @@
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
faction = list("rat")
+ vocal_bark_id = "squeak"
+ vocal_pitch = 1.4
/mob/living/simple_animal/mouse/Initialize(mapload)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/plushie.dm b/code/modules/mob/living/simple_animal/friendly/plushie.dm
index ff95e8fe86..6a8e2565f1 100644
--- a/code/modules/mob/living/simple_animal/friendly/plushie.dm
+++ b/code/modules/mob/living/simple_animal/friendly/plushie.dm
@@ -29,6 +29,8 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
pressure_resistance = 200
+ vocal_bark_id = "squeak"
+ vocal_pitch_range = 0.4
/mob/living/simple_animal/pet/plushie/ComponentInitialize()
. = ..()
@@ -72,7 +74,7 @@
qdel(src)
//low regen over time
-/mob/living/simple_animal/pet/plushie/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/pet/plushie/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(health < maxHealth)
diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
index ee5a648067..9715d4f63c 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm
@@ -14,7 +14,7 @@
var/charging = 0
var/atom/movable/screen/alert/chargealert
-/mob/living/simple_animal/hostile/guardian/charger/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/guardian/charger/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(ranged_cooldown <= world.time)
diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
index 6d421d326e..1fd1e623db 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm
@@ -18,14 +18,14 @@
/mob/living/simple_animal/hostile/guardian/dextrous/examine(mob/user)
if(dextrous)
- . = list("*---------*\nThis is [icon2html(src)] \a [src]!\n[desc]")
+ . = list("This is [icon2html(src)] \a [src]!\n[desc]")
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
. += "It has [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))]."
if(internal_storage && !(internal_storage.item_flags & ABSTRACT))
. += "It is holding [internal_storage.get_examine_string(user)] in its internal storage."
- . += "*---------*"
+ . += ""
else
return ..()
diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
index a05cd517fb..68e05f3f8c 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm
@@ -13,7 +13,7 @@
tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
carp_fluff_string = "CARP CARP CARP! You caught one! OH GOD, EVERYTHING'S ON FIRE. Except you and the fish."
-/mob/living/simple_animal/hostile/guardian/fire/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/guardian/fire/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(summoner)
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index c7772f780d..ba81ad72da 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -129,7 +129,7 @@
attack_verb_continuous = "slaps"
attack_verb_simple = "slap"
-/mob/living/simple_animal/hostile/bear/butter/BiologicalLife(seconds, times_fired) //Heals butter bear really fast when he takes damage.
+/mob/living/simple_animal/hostile/bear/butter/BiologicalLife(delta_time, times_fired) //Heals butter bear really fast when he takes damage.
if(stat)
return
if(health < maxHealth)
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 98dddab7bd..7f7589dae4 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -46,7 +46,7 @@
if(regen_amount)
regen_cooldown = world.time + REGENERATION_DELAY
-/mob/living/simple_animal/hostile/carp/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/carp/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(regen_amount && regen_cooldown < world.time)
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 1b6f417b7b..89f27f067e 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -79,7 +79,7 @@
foes = null
return ..()
-/mob/living/simple_animal/hostile/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
walk(src, 0) //stops walking
return
diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm
index f561f0d43c..edefa028f9 100644
--- a/code/modules/mob/living/simple_animal/hostile/illusion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm
@@ -23,7 +23,7 @@
deathmessage = "vanishes into thin air! It was a fake!"
has_field_of_vision = FALSE //not meant to be played anyway.
-/mob/living/simple_animal/hostile/illusion/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/illusion/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(world.time > life_span)
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index a0528b4109..f3676e752a 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -165,7 +165,7 @@
if(!hopping)
Hop()
-/mob/living/simple_animal/hostile/jungle/leaper/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/jungle/leaper/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
update_icons()
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
index 31303bd7f1..1e0116f52c 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm
@@ -26,7 +26,7 @@
footstep_type = FOOTSTEP_MOB_CLAW
-/mob/living/simple_animal/hostile/jungle/mega_arachnid/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/jungle/mega_arachnid/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(target && ranged_cooldown > world.time && iscarbon(target))
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 04967f081d..efef46f2ef 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -89,7 +89,7 @@ Difficulty: Normal
/mob/living/simple_animal/hostile/megafauna/hierophant/spawn_crusher_loot()
new /obj/item/crusher_trophy/vortex_talisman(get_turf(spawned_beacon))
-/mob/living/simple_animal/hostile/megafauna/hierophant/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/megafauna/hierophant/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(spawned_beacon && !QDELETED(spawned_beacon) && !client)
@@ -500,6 +500,8 @@ Difficulty: Normal
var/obj/item/projectile/P = mover
if(P.firer == caster)
return TRUE
+ if(mover != caster)
+ return FALSE
if(mover == caster)
return TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
index 6ce43ed409..a8910f5104 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
@@ -74,7 +74,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
step(R, ddir) //Step the swarmers, instead of spawning them there, incase the turf is solid
-/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
var/createtype = GetUncappedAISwarmerType()
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index c2d05e43d9..6370fae0e3 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -118,7 +118,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
overlay_googly_eyes = FALSE
CopyObject(copy, creator, destroy_original)
-/mob/living/simple_animal/hostile/mimic/copy/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/mimic/copy/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(idledamage && !target && !ckey) //Objects eventually revert to normal if no one is around to terrorize
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index cda54e32f9..232bdb04c4 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -95,7 +95,7 @@
wanted_objects = list(/obj/item/pen/survival, /obj/item/stack/ore/diamond)
field_of_vision_type = FOV_270_DEGREES //Obviously, it's one eyeball.
-/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(stat == CONSCIOUS)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
index 5ee249c767..d7b7dc3dae 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm
@@ -98,7 +98,7 @@
if(CALL_CHILDREN)
call_children()
-/mob/living/simple_animal/hostile/asteroid/elite/broodmother/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(health < maxHealth * 0.5 && rand_tent < world.time)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
index 50b15933a9..5daeaff9e8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm
@@ -95,7 +95,7 @@
if(AOE_SQUARES)
aoe_squares(target)
-/mob/living/simple_animal/hostile/asteroid/elite/pandora/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(health >= maxHealth * 0.5)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
index 2b7943d130..115681a7d4 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
@@ -38,7 +38,7 @@
footstep_type = FOOTSTEP_MOB_HEAVY
-/mob/living/simple_animal/hostile/asteroid/goliath/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/goliath/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
handle_preattack()
@@ -129,7 +129,7 @@
var/turf/last_location
var/tentacle_recheck_cooldown = 100
-/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(isturf(loc))
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 d0aa25aabc..f08b52040b 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
@@ -114,7 +114,7 @@
name = "guthen"
gender = FEMALE
-/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(udder.reagents.total_volume == udder.reagents.maximum_volume) //Only breed when we're full.
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index 757272ca98..f2ffd54cbd 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -198,7 +198,7 @@
swarming = TRUE
var/can_infest_dead = FALSE
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(isturf(loc))
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm
index d40cd8636c..2cf96bf51b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm
@@ -62,7 +62,7 @@
SLEEP_CHECK_DEATH(8)
return ..()
-/mob/living/simple_animal/hostile/asteroid/ice_demon/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/ice_demon/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm
index 7214fd71e0..8ab61d2450 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm
@@ -43,7 +43,7 @@
var/list/burn_turfs = getline(src, T) - get_turf(src)
dragon_fire_line(src, burn_turfs)
-/mob/living/simple_animal/hostile/asteroid/ice_whelp/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/ice_whelp/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm
index de9464cc16..9a81d74dc8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm
@@ -44,7 +44,7 @@
aggressive_message_said = TRUE
rapid_melee = 2
-/mob/living/simple_animal/hostile/asteroid/polarbear/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/polarbear/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm
index 8c4db48434..148d71ecd8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm
@@ -51,7 +51,7 @@
retreat_message_said = TRUE
retreat_distance = 30
-/mob/living/simple_animal/hostile/asteroid/wolf/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/wolf/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
index 527fd51260..378dbefae7 100644
--- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
@@ -51,7 +51,7 @@
else
. += "It looks like it's been roughed up."
-/mob/living/simple_animal/hostile/mushroom/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/mushroom/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat)//Mushrooms slowly regenerate if conscious, for people who want to save them from being eaten
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index 06db07daf6..a1e135d038 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -45,7 +45,7 @@
var/chosen_sound = pick(migo_sounds)
playsound(src, chosen_sound, 100, TRUE)
-/mob/living/simple_animal/hostile/netherworld/migo/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/netherworld/migo/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(stat)
diff --git a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
index 7112740b39..73dace85cd 100644
--- a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
@@ -86,7 +86,7 @@ GLOBAL_LIST_EMPTY(plague_rats)
walk_to(src, entry_vent)
break
-/mob/living/simple_animal/hostile/plaguerat/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/plaguerat/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(isopenturf(loc))
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 0233cb9c5d..2919c6d070 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -56,7 +56,7 @@
..()
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE)
-/mob/living/simple_animal/hostile/retaliate/clown/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/retaliate/clown/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(banana_time && banana_time < world.time)
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 600d60eb4d..9356c962fd 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -81,7 +81,7 @@
return 0
return ..()
-/mob/living/simple_animal/hostile/statue/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/statue/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!client && target) // If we have a target and we're AI controlled
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 978d58339d..9f53c11df3 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -44,7 +44,7 @@
gold_core_spawnable = HOSTILE_SPAWN
del_on_death = 1
-/mob/living/simple_animal/hostile/tree/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/tree/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(isopenturf(loc))
diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
index 452138fa80..e724da5cc3 100644
--- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
+++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
@@ -100,7 +100,7 @@
/mob/living/simple_animal/hostile/venus_human_trap/ghost_playable
playable_plant = TRUE //For admins that want to buss some harmless plants
-/mob/living/simple_animal/hostile/venus_human_trap/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/venus_human_trap/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
pull_vines()
diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
index eb35606e0d..33b9be4757 100644
--- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
+++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm
@@ -47,7 +47,7 @@
QDEL_NULL(E)
return ..()
-/mob/living/simple_animal/hostile/asteroid/fugu/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/hostile/asteroid/fugu/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!wumbo)
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index fe479bb943..0c24dd36fa 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -44,6 +44,10 @@
emote_hear = list("squawks.","bawks!")
emote_see = list("flutters its wings.")
+ vocal_bark_id = "banjoc4"
+ vocal_pitch = 1.4
+ vocal_pitch_range = 0.4
+
speak_chance = 1 //1% (1 in 100) chance every tick; So about once per 150 seconds, assuming an average tick is 1.5s
turns_per_move = 5
butcher_results = list(/obj/item/reagent_containers/food/snacks/cracker/ = 1)
@@ -80,7 +84,7 @@
var/speech_shuffle_rate = 20
var/list/available_channels = list()
- //Headset for Poly to yell at engineers :)
+ //Headset for Polly to yell at engineers :)
var/obj/item/radio/headset/ears = null
/// spawns with headset
var/spawns_with_headset = FALSE
@@ -345,7 +349,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
parrot_state |= PARROT_FLEE
icon_state = icon_living
drop_held_item(0)
- else if(istype(O, /obj/item/reagent_containers/food/snacks/cracker)) //Poly wants a cracker.
+ else if(istype(O, /obj/item/reagent_containers/food/snacks/cracker)) //Polly wants a cracker.
qdel(O)
if(health < maxHealth)
adjustBruteLoss(-10)
@@ -372,7 +376,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
/*
* AI - Not really intelligent, but I'm calling it AI anyway.
*/
-/mob/living/simple_animal/parrot/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/parrot/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
//Sprite update for when a parrot gets pulled
@@ -890,10 +894,10 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
/*
* Sub-types
*/
-/mob/living/simple_animal/parrot/Poly
- name = "Poly"
- desc = "Poly the Parrot. An expert on quantum cracker theory."
- speak = list("Poly wanna cracker!", ":e Check the crystal, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS ABOUT TO DELAMINATE CALL THE SHUTTLE")
+/mob/living/simple_animal/parrot/Polly
+ name = "Polly"
+ desc = "Polly the Parrot. An expert on quantum cracker theory."
+ speak = list("Polly wanna cracker!", ":e Check the crystal, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS ABOUT TO DELAMINATE CALL THE SHUTTLE")
gold_core_spawnable = NO_SPAWN
speak_chance = 3
spawns_with_headset = TRUE
@@ -902,7 +906,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
var/longest_survival = 0
var/longest_deathstreak = 0
-/mob/living/simple_animal/parrot/Poly/Initialize(mapload)
+/mob/living/simple_animal/parrot/Polly/Initialize(mapload)
ears = new /obj/item/radio/headset/headset_eng(src)
available_channels = list(":e")
Read_Memory()
@@ -910,11 +914,13 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
speak += pick("...[longest_survival].", "The things I've seen!", "I have lived many lives!", "What are you before me?")
desc += " Old as sin, and just as loud. Claimed to be [rounds_survived]."
speak_chance = 20 //His hubris has made him more annoying/easier to justify killing
- add_atom_colour("#EEEE22", FIXED_COLOUR_PRIORITY)
+ if(!color)
+ add_atom_colour("#EEEE22", FIXED_COLOUR_PRIORITY)
else if(rounds_survived == longest_deathstreak)
speak += pick("What are you waiting for!", "Violence breeds violence!", "Blood! Blood!", "Strike me down if you dare!")
desc += " The squawks of [-rounds_survived] dead parrots ring out in your ears..."
- add_atom_colour("#BB7777", FIXED_COLOUR_PRIORITY)
+ if(!color)
+ add_atom_colour("#BB7777", FIXED_COLOUR_PRIORITY)
else if(rounds_survived > 0)
speak += pick("...again?", "No, It was over!", "Let me out!", "It never ends!")
desc += " Over [rounds_survived] shifts without a \"terrible\" \"accident\"!"
@@ -923,30 +929,31 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
. = ..()
-/mob/living/simple_animal/parrot/Poly/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
+/mob/living/simple_animal/parrot/Polly/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
. = ..()
- if(. && !client && prob(1) && prob(1)) //Only the one true bird may speak across dimensions.
- world.TgsTargetedChatBroadcast("A stray squawk is heard... \"[message]\"", FALSE)
+ if(. && !client && prob(1) && prob(1) && CONFIG_GET(string/chat_squawk_tag)) //Only the one true bird may speak across dimensions.
+ send2chat("A stray squawk is heard... \"[message]\"", CONFIG_GET(string/chat_squawk_tag))
-/mob/living/simple_animal/parrot/Poly/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/parrot/Polly/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(FALSE)
memory_saved = TRUE
-/mob/living/simple_animal/parrot/Poly/death(gibbed)
+/mob/living/simple_animal/parrot/Polly/death(gibbed)
if(!memory_saved)
Write_Memory(TRUE)
if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak || prob(0.666))
- var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc)
+ var/mob/living/simple_animal/parrot/Polly/ghost/G = new(loc)
if(mind)
mind.transfer_to(G)
else
transfer_ckey(G)
..(gibbed)
-/mob/living/simple_animal/parrot/Poly/proc/Read_Memory()
+/mob/living/simple_animal/parrot/Polly/proc/Read_Memory()
+ var/saved_color
if(fexists("data/npc_saves/Poly.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Poly.sav")
S["phrases"] >> speech_buffer
@@ -963,10 +970,13 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
rounds_survived = json["roundssurvived"]
longest_survival = json["longestsurvival"]
longest_deathstreak = json["longestdeathstreak"]
+ saved_color = json["color"]
if(!islist(speech_buffer))
speech_buffer = list()
+ if(!isnull(saved_color))
+ add_atom_colour(json_decode(saved_color), FIXED_COLOUR_PRIORITY)
-/mob/living/simple_animal/parrot/Poly/proc/Write_Memory(dead)
+/mob/living/simple_animal/parrot/Polly/proc/Write_Memory(dead)
var/json_file = file("data/npc_saves/Poly.json")
var/list/file_data = list()
if(islist(speech_buffer))
@@ -978,6 +988,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
file_data["longestdeathstreak"] = rounds_survived - 1
else
file_data["longestdeathstreak"] = longest_deathstreak
+ file_data["color"] = null
else
file_data["roundssurvived"] = rounds_survived + 1
if(rounds_survived + 1 > longest_survival)
@@ -985,17 +996,21 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
else
file_data["longestsurvival"] = longest_survival
file_data["longestdeathstreak"] = longest_deathstreak
+ if(color)
+ file_data["color"] = json_encode(color)
+ else
+ file_data["color"] = null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
-/mob/living/simple_animal/parrot/Poly/ratvar_act()
+/mob/living/simple_animal/parrot/Polly/ratvar_act()
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 75, TRUE)
var/mob/living/simple_animal/parrot/clock_hawk/H = new(loc)
H.setDir(dir)
qdel(src)
-/mob/living/simple_animal/parrot/Poly/ghost
- name = "The Ghost of Poly"
+/mob/living/simple_animal/parrot/Polly/ghost
+ name = "The Ghost of Polly"
desc = "Doomed to squawk the Earth."
color = "#FFFFFF"
alpha = 77
@@ -1004,16 +1019,16 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
incorporeal_move = INCORPOREAL_MOVE_BASIC
butcher_results = list(/obj/item/ectoplasm = 1)
-/mob/living/simple_animal/parrot/Poly/ghost/Initialize(mapload)
+/mob/living/simple_animal/parrot/Polly/ghost/Initialize(mapload)
memory_saved = TRUE //At this point nothing is saved
. = ..()
-/mob/living/simple_animal/parrot/Poly/ghost/handle_automated_speech()
+/mob/living/simple_animal/parrot/Polly/ghost/handle_automated_speech()
if(ismob(loc))
return
..()
-/mob/living/simple_animal/parrot/Poly/ghost/handle_automated_movement()
+/mob/living/simple_animal/parrot/Polly/ghost/handle_automated_movement()
if(isliving(parrot_interest))
if(!ishuman(parrot_interest))
parrot_interest = null
@@ -1022,7 +1037,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
Possess(parrot_interest)
..()
-/mob/living/simple_animal/parrot/Poly/ghost/proc/Possess(mob/living/carbon/human/H)
+/mob/living/simple_animal/parrot/Polly/ghost/proc/Possess(mob/living/carbon/human/H)
if(!ishuman(H))
return
var/datum/disease/parrot_possession/P = new
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 9cc82f6a1a..4d992f274e 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -225,7 +225,7 @@
length += emote_see.len
var/randomValue = rand(1,length)
if(randomValue <= speak.len)
- say(pick(speak), forced = "poly")
+ say(pick(speak), forced = "polly")
else
randomValue -= speak.len
if(emote_see && randomValue <= emote_see.len)
@@ -233,7 +233,7 @@
else
emote("me [pick(emote_hear)]", 2)
else
- say(pick(speak), forced = "poly")
+ say(pick(speak), forced = "polly")
else
if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len))
emote("me", EMOTE_VISIBLE, pick(emote_see))
@@ -482,7 +482,7 @@
update_action_buttons_icon()
return mobility_flags
-/mob/living/simple_animal/update_transform()
+/mob/living/simple_animal/update_transform(do_animate)
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/changed = 0
diff --git a/code/modules/mob/living/simple_animal/slime/emote.dm b/code/modules/mob/living/simple_animal/slime/emote.dm
index 94f054345d..ac0ce1c1e5 100644
--- a/code/modules/mob/living/simple_animal/slime/emote.dm
+++ b/code/modules/mob/living/simple_animal/slime/emote.dm
@@ -27,6 +27,8 @@
/datum/emote/slime/mood/run_emote(mob/user, params)
. = ..()
+ if(!.)
+ return
var/mob/living/simple_animal/slime/S = user
S.mood = mood
S.regenerate_icons()
diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm
index 2ce355a0ef..274af333fc 100644
--- a/code/modules/mob/living/simple_animal/slime/life.dm
+++ b/code/modules/mob/living/simple_animal/slime/life.dm
@@ -8,7 +8,7 @@
typing_indicator_state = /obj/effect/overlay/typing_indicator/slime
-/mob/living/simple_animal/slime/BiologicalLife(seconds, times_fired)
+/mob/living/simple_animal/slime/BiologicalLife(delta_time, times_fired)
if(!(. = ..()))
return
if(buckled)
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 9812307300..dc9d6ff6a3 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -421,7 +421,7 @@
return
/mob/living/simple_animal/slime/examine(mob/user)
- . = list("*---------*\nThis is [icon2html(src, user)] \a [src]!")
+ . = list("This is [icon2html(src, user)] \a [src]!")
if (src.stat == DEAD)
. += "It is limp and unresponsive."
else
@@ -446,7 +446,7 @@
if(10)
. += "It is radiating with massive levels of electrical activity!"
- . += "*---------*"
+ . += ""
/mob/living/simple_animal/slime/proc/discipline_slime(mob/user)
if(stat)
diff --git a/code/modules/mob/living/update_icons.dm b/code/modules/mob/living/update_icons.dm
index f8d5d7e0ba..9705be3ad0 100644
--- a/code/modules/mob/living/update_icons.dm
+++ b/code/modules/mob/living/update_icons.dm
@@ -1,5 +1,5 @@
//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
-/mob/living/update_transform()
+/mob/living/update_transform(do_animate = TRUE)
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/final_pixel_y = pixel_y
var/changed = 0
@@ -21,5 +21,9 @@
resize = RESIZE_DEFAULT_SIZE
if(changed)
- animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, easing = EASE_IN|EASE_OUT)
+ if(do_animate)
+ animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, easing = EASE_IN|EASE_OUT, flags = ANIMATION_PARALLEL)
+ else
+ transform = ntransform
+ pixel_y = final_pixel_y
floating_need_update = TRUE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f5c89312e3..7ef26c7818 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -138,7 +138,7 @@
return
hearers -= ignored_mobs
- if(target_message && target && istype(target) && target.client)
+ if(target_message && target && istype(target) && (target.client || target.audiovisual_redirect))
hearers -= target
if(omni)
target.show_message(target_message)
@@ -155,7 +155,7 @@
if(self_message)
hearers -= src
for(var/mob/M in hearers)
- if(!M.client)
+ if(!M.client && !M.audiovisual_redirect)
continue
if(omni)
M.show_message(message)
@@ -330,7 +330,7 @@
else
result = A.examine(src) // if a tree is examined but no client is there to see it, did the tree ever really exist?
- to_chat(src, result.Join("\n"))
+ to_chat(src, "
[result.Join("\n")]
")
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
/mob/proc/clear_from_recent_examines(atom/A)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 561425c710..90a7aae95e 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -229,22 +229,38 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return copytext_char(sanitize(.),1,MAX_MESSAGE_LEN)
/proc/shake_camera(mob/M, duration, strength=1)
- if(!M || !M.client || duration < 1)
+ set waitfor = FALSE
+ if(!M || !M.client || duration <= 0)
return
var/client/C = M.client
+ if (C.prefs.screenshake==0)
+ return
var/oldx = C.pixel_x
var/oldy = C.pixel_y
- var/max = strength*world.icon_size
- var/min = -(strength*world.icon_size)
+ var/clientscreenshake = (C.prefs.screenshake * 0.01)
+ var/max = (strength*clientscreenshake) * world.icon_size
+ var/min = -((strength*clientscreenshake) * world.icon_size)
+ var/roundedduration = -round(-duration) // round() with only one arg will always round down. so uh. this is Something all right
- for(var/i in 0 to duration-1)
+ for(var/i in 0 to roundedduration-1)
+ duration--
if (i == 0)
- animate(C, pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
+ animate(C, pixel_x=(rand(min,max)*duration), pixel_y=(rand(min,max)*duration), time=1)
else
animate(pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
animate(pixel_x=oldx, pixel_y=oldy, time=1)
-
+/proc/directional_recoil(mob/M, strength=1, angle = 0)
+ if(!M || !M.client)
+ return
+ var/client/C = M.client
+ var/client_screenshake = (C.prefs.recoil_screenshake * 0.01)
+ strength *= client_screenshake
+ var/recoil_x = -sin(angle)*4*strength + rand(-strength, strength)
+ var/recoil_y = -cos(angle)*4*strength + rand(-strength, strength)
+ animate(C, pixel_x=recoil_x, pixel_y=recoil_y, time=1, easing=SINE_EASING|EASE_OUT, flags=ANIMATION_PARALLEL|ANIMATION_RELATIVE)
+ animate(pixel_x=0, pixel_y=0, time=3, easing=SINE_EASING|EASE_IN) // according to bhjin this works on more recent byond versions
+ // if you havent updated uuh sucks to be you then
/proc/findname(msg)
if(!istext(msg))
diff --git a/code/modules/modular_computers/file_system/programs/signaler.dm b/code/modules/modular_computers/file_system/programs/signaler.dm
index b7bbcacaa0..ded70f7f37 100644
--- a/code/modules/modular_computers/file_system/programs/signaler.dm
+++ b/code/modules/modular_computers/file_system/programs/signaler.dm
@@ -15,40 +15,29 @@
/// Radio connection datum used by signalers.
var/datum/radio_frequency/radio_connection
-/datum/computer_file/program/signaler/run_program(mob/living/user)
- . = ..()
- if (!.)
- return
- if(!computer?.get_modular_computer_part(MC_SIGNALER)) //Giving a clue to users why the program is spitting out zeros.
- to_chat(user, span_warning("\The [computer] flashes an error: \"hardware\\signal_hardware\\startup.bin -- file not found\"."))
-
+/datum/computer_file/program/signaler/New()
+ set_frequency(signal_frequency)
+ return ..()
/datum/computer_file/program/signaler/ui_data(mob/user)
var/list/data = get_header_data()
- var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
- if(sensor?.check_functionality())
- data["frequency"] = signal_frequency
- data["code"] = signal_code
- data["minFrequency"] = MIN_FREE_FREQ
- data["maxFrequency"] = MAX_FREE_FREQ
+ data["frequency"] = signal_frequency
+ data["code"] = signal_code
+ data["minFrequency"] = MIN_FREE_FREQ
+ data["maxFrequency"] = MAX_FREE_FREQ
return data
/datum/computer_file/program/signaler/ui_act(action, list/params)
. = ..()
if(.)
return
- var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
- if(!(sensor?.check_functionality()))
- playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE)
- return
switch(action)
if("signal")
INVOKE_ASYNC(src, .proc/signal)
. = TRUE
if("freq")
- signal_frequency = unformat_frequency(params["freq"])
- signal_frequency = sanitize_frequency(signal_frequency, TRUE)
- set_frequency(signal_frequency)
+ var/new_signal_frequency = sanitize_frequency(unformat_frequency(params["freq"]), TRUE)
+ set_frequency(new_signal_frequency)
. = TRUE
if("code")
signal_code = text2num(params["code"])
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 0ad49e192d..cb9570e02f 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -173,7 +173,7 @@
O.renamedByPlayer = TRUE
if(penchoice == "Change description")
- var/input = stripped_input(user,"Describe [O] here:", ,"[O.desc]", 140)
+ var/input = stripped_input(user,"Describe [O] here:", ,"[O.desc]", 350)
var/olddesc = O.desc
if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE))
return
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm
index 16e49cd451..1052752c82 100644
--- a/code/modules/power/singularity/collector.dm
+++ b/code/modules/power/singularity/collector.dm
@@ -182,7 +182,7 @@
. = ..()
if(active)
if(!bitcoinmining)
- . += "[src]'s display states that it has stored [DisplayPower(stored_power)], and is processing [DisplayPower((RAD_COLLECTOR_OUTPUT)*((60 SECONDS)/SSmachines.wait))] per minute. The plasma within it's tank is being irradiated into tritium."
+ . += "[src]'s display states that it has stored [DisplayEnergy(stored_power)], and is processing [DisplayPower((RAD_COLLECTOR_OUTPUT)*((1 SECONDS)/SSmachines.wait))]. The plasma within it's tank is being irradiated into tritium."
else
. += "[src]'s display states that it's producing a total of [(last_push*RAD_COLLECTOR_MINING_CONVERSION_RATE)*((60 SECONDS)/SSmachines.wait)] research points per minute. The tritium and oxygen within it's tank is being combusted into carbon dioxide."
else
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index fad48b4854..27fb30a459 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -5,6 +5,7 @@
desc = "A solar panel. Generates electricity when in contact with sunlight."
icon = 'goon/icons/obj/power.dmi'
icon_state = "sp_base"
+ minimap_override_color = "#02026a"
density = TRUE
use_power = NO_POWER_USE
idle_power_usage = 0
diff --git a/code/modules/projectiles/ammunition/ballistic/lmg.dm b/code/modules/projectiles/ammunition/ballistic/lmg.dm
index bf8b4007bf..1c39a73f1f 100644
--- a/code/modules/projectiles/ammunition/ballistic/lmg.dm
+++ b/code/modules/projectiles/ammunition/ballistic/lmg.dm
@@ -1,36 +1,28 @@
-// 1.95x129mm (SAW)
+// 7.12x82mm (SAW)
-/obj/item/ammo_casing/mm195x129
- name = "1.95x129mm bullet casing"
- desc = "A 1.95x129mm bullet casing."
+/obj/item/ammo_casing/mm712x82
+ name = "7.12x82mm bullet casing"
+ desc = "A 7.12x82mm bullet casing."
icon_state = "762-casing"
- caliber = "mm195129"
- projectile_type = /obj/item/projectile/bullet/mm195x129
+ caliber = "mm71282"
+ projectile_type = /obj/item/projectile/bullet/mm712x82
-/obj/item/ammo_casing/mm195x129/ap
- name = "1.95x129mm armor-piercing bullet casing"
- desc = "A 1.95x129mm bullet casing designed with a hardened-tipped core to help penetrate armored targets."
- projectile_type = /obj/item/projectile/bullet/mm195x129_ap
+/obj/item/ammo_casing/mm712x82/ap
+ name = "7.12x82mm armor-piercing bullet casing"
+ desc = "A 7.12x82mm bullet casing designed with a hardened-tipped core to help penetrate armored targets."
+ projectile_type = /obj/item/projectile/bullet/mm712x82_ap
-/obj/item/ammo_casing/mm195x129/hollow
- name = "1.95x129mm hollow-point bullet casing"
- desc = "A 1.95x129mm bullet casing designed to cause more damage to unarmored targets."
- projectile_type = /obj/item/projectile/bullet/mm195x129_hp
+/obj/item/ammo_casing/mm712x82/hollow
+ name = "7.12x82mm hollow-point bullet casing"
+ desc = "A 7.12x82mm bullet casing designed to cause more damage to unarmored targets."
+ projectile_type = /obj/item/projectile/bullet/mm712x82_hp
-/obj/item/ammo_casing/mm195x129/incen
- name = "1.95x129mm incendiary bullet casing"
- desc = "A 1.95x129mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames."
- projectile_type = /obj/item/projectile/bullet/incendiary/mm195x129
+/obj/item/ammo_casing/mm712x82/incen
+ name = "7.12x82mm incendiary bullet casing"
+ desc = "A 7.12x82mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames."
+ projectile_type = /obj/item/projectile/bullet/incendiary/mm712x82
/obj/item/ammo_casing/mm712x82/match
name = "7.12x82mm match bullet casing"
desc = "A 7.12x82mm bullet casing manufactured to unfailingly high standards, you could pull off some cool trickshots with this."
- projectile_type = /obj/item/projectile/bullet/mm712x82_match
-
-/obj/item/projectile/bullet/mm712x82_match
- name = "7.12x82mm match bullet"
- damage = 40
- ricochets_max = 2
- ricochet_chance = 60
- ricochet_auto_aim_range = 4
- ricochet_incidence_leeway = 35
+ projectile_type = /obj/item/projectile/bullet/mm712x82/match
diff --git a/code/modules/projectiles/boxes_magazines/external/lmg.dm b/code/modules/projectiles/boxes_magazines/external/lmg.dm
index 95ba17c733..e8447950ce 100644
--- a/code/modules/projectiles/boxes_magazines/external/lmg.dm
+++ b/code/modules/projectiles/boxes_magazines/external/lmg.dm
@@ -1,23 +1,23 @@
-/obj/item/ammo_box/magazine/mm195x129
- name = "box magazine (1.95x129mm)"
+/obj/item/ammo_box/magazine/mm712x82
+ name = "box magazine (7.12x82mm)"
icon_state = "a762-50"
- ammo_type = /obj/item/ammo_casing/mm195x129
- caliber = "mm195129"
+ ammo_type = /obj/item/ammo_casing/mm712x82
+ caliber = "mm71282"
max_ammo = 50
-/obj/item/ammo_box/magazine/mm195x129/hollow
- name = "box magazine (Hollow-Point 1.95x129mm)"
- ammo_type = /obj/item/ammo_casing/mm195x129/hollow
+/obj/item/ammo_box/magazine/mm712x82/hollow
+ name = "box magazine (Hollow-Point 7.12x82mm)"
+ ammo_type = /obj/item/ammo_casing/mm712x82/hollow
-/obj/item/ammo_box/magazine/mm195x129/ap
- name = "box magazine (Armor Penetrating 1.95x129mm)"
- ammo_type = /obj/item/ammo_casing/mm195x129/ap
+/obj/item/ammo_box/magazine/mm712x82/ap
+ name = "box magazine (Armor Penetrating 7.12x82mm)"
+ ammo_type = /obj/item/ammo_casing/mm712x82/ap
-/obj/item/ammo_box/magazine/mm195x129/incen
- name = "box magazine (Incendiary 1.95x129mm)"
- ammo_type = /obj/item/ammo_casing/mm195x129/incen
+/obj/item/ammo_box/magazine/mm712x82/incen
+ name = "box magazine (Incendiary 7.12x82mm)"
+ ammo_type = /obj/item/ammo_casing/mm712x82/incen
-/obj/item/ammo_box/magazine/mm195x129/update_icon()
+/obj/item/ammo_box/magazine/mm712x82/update_icon()
..()
icon_state = "a762-[round(ammo_count(),10)]"
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 3210ad2d15..a4d3c3a63a 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -94,6 +94,9 @@
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
+ /// directional recoil multiplier
+ var/dir_recoil_amp = 10
+
/obj/item/gun/Initialize(mapload)
. = ..()
if(no_pin_required)
@@ -159,7 +162,7 @@
/obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
if(recoil)
- shake_camera(user, recoil + 1, recoil)
+ directional_recoil(user, recoil*dir_recoil_amp, Get_Angle(user, pbtarget))
if(stam_cost) //CIT CHANGE - makes gun recoil cause staminaloss
var/safe_cost = clamp(stam_cost, 0, user.stamina_buffer)*(firing && burst_size >= 2 ? 1/burst_size : 1)
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 836ed3b804..3f2f4d3e65 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -3,6 +3,7 @@
name = "projectile gun"
icon_state = "pistol"
w_class = WEIGHT_CLASS_NORMAL
+ recoil = 0.25
var/spawnwithmagazine = TRUE
var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info
var/obj/item/ammo_box/magazine/magazine
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index aa3ac20cb8..4b871d59b2 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -296,13 +296,13 @@
/obj/item/gun/ballistic/automatic/l6_saw
name = "\improper L6 SAW"
- desc = "A heavily modified 1.95x129mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
+ desc = "A heavily modified 7.12x82mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
icon_state = "l6closed100"
item_state = "l6closedmag"
fire_sound = "sound/weapons/lmgshot.ogg"
w_class = WEIGHT_CLASS_HUGE
slot_flags = 0
- mag_type = /obj/item/ammo_box/magazine/mm195x129
+ mag_type = /obj/item/ammo_box/magazine/mm712x82
weapon_weight = WEAPON_HEAVY
var/cover_open = FALSE
can_suppress = FALSE
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index afb30631e0..f3b07aa7a4 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -5,6 +5,7 @@
mag_type = /obj/item/ammo_box/magazine/internal/cylinder
fire_sound = "sound/weapons/revolvershot.ogg"
casing_ejector = FALSE
+ recoil = 0.5
/obj/item/gun/ballistic/revolver/Initialize(mapload)
. = ..()
@@ -166,6 +167,7 @@
icon_state = "goldrevolver"
fire_sound = 'sound/weapons/resonator_blast.ogg'
recoil = 8
+ dir_recoil_amp = 5 // 40 directional recoil is already really funny
pin = /obj/item/firing_pin
/obj/item/gun/ballistic/revolver/nagant
@@ -285,6 +287,7 @@
item_state = "shotgun"
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_MEDIUM
+ recoil = 1
force = 10
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BACK
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index f7d57b43a0..b52620e7e0 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -5,6 +5,7 @@
item_state = "shotgun"
fire_sound = "sound/weapons/gunshotshotgunshot.ogg"
w_class = WEIGHT_CLASS_BULKY
+ recoil = 1
force = 10
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BACK
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index dd759f9e3c..03dfc46713 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -16,6 +16,7 @@
name = "energy gun"
desc = "A basic energy-based gun."
icon = 'icons/obj/guns/energy.dmi'
+ recoil = 0.1
var/obj/item/stock_parts/cell/cell //What type of power cell this uses
var/cell_type = /obj/item/stock_parts/cell
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index a785e4e0e8..5fd158c028 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -8,6 +8,7 @@
item_flags = NONE
obj_flags = UNIQUE_RENAME
weapon_weight = WEAPON_LIGHT
+ recoil = 0.5
can_flashlight = 1
flight_x_offset = 15
flight_y_offset = 9
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 15acd40172..bb7b21596f 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -167,6 +167,11 @@
/obj/item/gun/energy/plasmacutter/use(amount)
return cell.use(amount * 100)
+/obj/item/gun/energy/plasmacutter/use_tool(atom/target, mob/living/user, delay, amount, volume, datum/callback/extra_checks, skill_gain_mult)
+ target.add_overlay(GLOB.welding_sparks)
+ . = ..()
+ target.cut_overlay(GLOB.welding_sparks)
+
/obj/item/gun/energy/plasmacutter/adv
name = "advanced plasma cutter"
icon_state = "adv_plasmacutter"
diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm
index 07066023b3..8de7633a79 100644
--- a/code/modules/projectiles/guns/misc/syringe_gun.dm
+++ b/code/modules/projectiles/guns/misc/syringe_gun.dm
@@ -4,6 +4,7 @@
icon_state = "syringegun"
item_state = "syringegun"
w_class = WEIGHT_CLASS_NORMAL
+ recoil = 0.1
throw_speed = 3
throw_range = 7
force = 4
diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm
index e3eff6dcb0..177a98201c 100644
--- a/code/modules/projectiles/projectile/bullets/lmg.dm
+++ b/code/modules/projectiles/projectile/bullets/lmg.dm
@@ -21,22 +21,22 @@
/obj/item/projectile/bullet/syndicate_turret
damage = 20
-// 1.95x129mm (SAW)
+// 7.12x82mm (SAW)
-/obj/item/projectile/bullet/mm195x129
- name = "1.95x129mm bullet"
+/obj/item/projectile/bullet/mm712x82
+ name = "7.12x82mm bullet"
damage = 40
armour_penetration = 5
wound_bonus = -50
wound_falloff_tile = 0
-/obj/item/projectile/bullet/mm195x129_ap
- name = "1.95x129mm armor-piercing bullet"
+/obj/item/projectile/bullet/mm712x82_ap
+ name = "7.12x82mm armor-piercing bullet"
damage = 40
armour_penetration = 75
-/obj/item/projectile/bullet/mm195x129_hp
- name = "1.95x129mm hollow-point bullet"
+/obj/item/projectile/bullet/mm712x82_hp
+ name = "7.12x82mm hollow-point bullet"
damage = 50
armour_penetration = -60
sharpness = SHARP_EDGED
@@ -44,7 +44,15 @@
bare_wound_bonus = 30
wound_falloff_tile = -8
-/obj/item/projectile/bullet/incendiary/mm195x129
- name = "1.95x129mm incendiary bullet"
+/obj/item/projectile/bullet/incendiary/mm712x82
+ name = "7.12x82mm incendiary bullet"
damage = 20
fire_stacks = 3
+
+/obj/item/projectile/bullet/mm712x82/match
+ name = "7.12x82mm match bullet"
+ damage = 40
+ ricochets_max = 2
+ ricochet_chance = 60
+ ricochet_auto_aim_range = 4
+ ricochet_incidence_leeway = 35
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index 4376805e2c..c0892ce1e2 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -1034,7 +1034,7 @@
M.update_transform()
..()
-/datum/reagent/consumable/pinkmilk
+/datum/reagent/consumable/milk/pinkmilk
name = "Strawberry Milk"
description = "A drink of a bygone era of milk and artificial sweetener back on a rock."
color = "#f76aeb"//rgb(247, 106, 235)
@@ -1045,13 +1045,13 @@
glass_desc = "Delicious flavored strawberry syrup mixed with milk."
value = REAGENT_VALUE_VERY_COMMON
-/datum/reagent/consumable/tea/pinkmilk/on_mob_life(mob/living/carbon/M)
+/datum/reagent/consumable/milk/pinkmilk/on_mob_life(mob/living/carbon/M)
if(prob(15))
to_chat(M, "[pick("You cant help to smile.","You feel nostalgia all of sudden.","You remember to relax.")]")
..()
. = 1
-/datum/reagent/consumable/pinktea //Tiny Tim song
+/datum/reagent/consumable/tea/pinktea //Tiny Tim song
name = "Strawberry Tea"
description = "A timeless classic!"
color = "#f76aeb"//rgb(247, 106, 235)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index abe3aef82d..9e49e8556b 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1,5 +1,5 @@
/datum/reagent/blood
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null)
name = "Blood"
chemical_flags = REAGENT_ALL_PROCESS
value = REAGENT_VALUE_UNCOMMON // $$$ blood ""donations"" $$$
@@ -81,6 +81,7 @@
B.blood_DNA["color"] = data["bloodcolor"]
else
B.blood_DNA["color"] = BlendRGB(B.blood_DNA["color"], data["bloodcolor"])
+ B.blood_DNA["blendmode"] = data["bloodblend"]
if(B.reagents)
B.reagents.add_reagent(type, reac_volume)
B.update_icon()
@@ -148,7 +149,7 @@
. += D
/datum/reagent/blood/synthetics
- data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
name = "Synthetic Blood"
description = "A synthetically produced imitation of blood."
taste_description = "oil"
@@ -156,7 +157,7 @@
value = REAGENT_VALUE_NONE
/datum/reagent/blood/jellyblood
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "bloodblend" = BLEND_DEFAULT, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
name = "Slime Jelly Blood"
description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
color = BLOOD_COLOR_SLIME
@@ -165,7 +166,7 @@
pH = 4
/datum/reagent/blood/tomato
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
name = "Tomato Blood"
description = "This highly resembles blood, but it doesnt actually function like it, resembling more ketchup, with a more blood-like consistency."
taste_description = "sap" //Like tree sap?
@@ -189,7 +190,7 @@
description = "You don't even want to think about what's in here."
taste_description = "gross iron"
shot_glass_icon_state = "shotglassred"
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 7.45
/datum/reagent/liquidgibs/xeno
@@ -197,7 +198,7 @@
color = BLOOD_COLOR_XENO
taste_description = "blended heresy"
shot_glass_icon_state = "shotglassgreen"
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "bloodblend" = BLEND_MULTIPLY, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 2.5
/datum/reagent/liquidgibs/slime
@@ -205,20 +206,20 @@
color = BLOOD_COLOR_SLIME
taste_description = "slime"
shot_glass_icon_state = "shotglassgreen"
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "bloodblend" = BLEND_DEFAULT, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 4
/datum/reagent/liquidgibs/synth
name = "Synthetic sludge"
color = BLOOD_COLOR_SYNTHETIC
taste_description = "jellied plastic"
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
/datum/reagent/liquidgibs/oil
name = "Hydraulic sludge"
color = BLOOD_COLOR_OIL
taste_description = "chunky burnt oil"
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "bloodblend" = BLEND_MULTIPLY, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 9.75
/datum/reagent/vaccine
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index c6df9ebb0c..87349058a4 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -13,7 +13,7 @@
/obj/item/reagent_containers/blood/Initialize(mapload)
. = ..()
if(blood_type != null)
- reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"bloodcolor"=bloodtype_to_color(blood_type), "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
+ reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"bloodcolor"=bloodtype_to_color(blood_type), "bloodblend" = BLEND_MULTIPLY, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
diff --git a/code/modules/research/bepis.dm b/code/modules/research/bepis.dm
index 7b36a614a7..93df1e2351 100644
--- a/code/modules/research/bepis.dm
+++ b/code/modules/research/bepis.dm
@@ -103,7 +103,7 @@
return
account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts.
SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value)
- //log_econ("[deposit_value] credits were inserted into [src] by [account.account_holder]")
+ log_econ("[deposit_value] credits were inserted into [src] by [key_name(usr)] (account: [account.account_holder])")
banked_cash += deposit_value
use_power(1000 * power_saver)
say("Cash deposit successful. There is [banked_cash] in the chamber.")
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index d542694236..dc07a5a184 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -17,7 +17,7 @@
var/list/obj/machinery/computer/rdconsole/consoles_accessing = list()
var/id = "generic"
var/list/research_logs = list() //IC logs.
- var/largest_bomb_value = 0
+ var/largest_values = list()
var/organization = "Third-Party" //Organization name, used for display.
var/list/next_income = list() //To be applied on the next passive techweb income
var/list/last_bitcoins = list() //Current per-second production, used for display only.
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index e51e4852e6..1c7951a2d6 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -603,14 +603,14 @@
return ..()
/datum/status_effect/stabilized/darkpurple/tick()
- var/obj/item/I = owner.get_active_held_item()
- var/obj/item/reagent_containers/food/snacks/F = I
- if(istype(F))
- if(F.cooked_type)
+ var/obj/item/item = owner.get_active_held_item()
+ if(item)
+ var/obj/item/reagent_containers/food/snacks/F = item
+ if(istype(F) && F.cooked_type)
to_chat(owner, "[linked_extract] flares up brightly, and your hands alone are enough cook [F]!")
F.microwave_act()
- else
- I.attackby(fire, owner)
+ else
+ item.attackby(fire, owner)
return ..()
/datum/status_effect/stabilized/darkpurple/on_remove()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index a89727d183..2d8150d087 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -228,6 +228,8 @@
var/mangled_state = get_mangled_state()
var/bio_state = owner.get_biological_state()
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
+ var/glass_bones = HAS_TRAIT(owner, TRAIT_GLASS_BONES)
+ var/paper_skin = HAS_TRAIT(owner, TRAIT_PAPER_SKIN)
if(wounding_type == WOUND_BLUNT)
if(sharpness == SHARP_EDGED)
@@ -242,22 +244,29 @@
if(wounding_type == WOUND_SLASH)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ wounding_dmg *= (glass_bones ? 1.5 : 1)
else if(wounding_type == WOUND_PIERCE)
wounding_type = WOUND_BLUNT
wounding_dmg *= (easy_dismember ? 1 : 0.75)
+ wounding_dmg *= (glass_bones ? 1.5 : 1)
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// if we're flesh only, all blunt attacks become weakened slashes in terms of wound damage
if(BIO_JUST_FLESH)
if(wounding_type == WOUND_BLUNT)
wounding_type = WOUND_SLASH
- wounding_dmg *= (easy_dismember ? 1 : 0.3)
+ wounding_dmg *= (easy_dismember ? 1 : 0.5)
+ wounding_dmg *= (paper_skin ? 1.5 : 1)
if((mangled_state & BODYPART_MANGLED_FLESH) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
return
// standard humanoids
if(BIO_FLESH_BONE)
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
// So a big sharp weapon is still all you need to destroy a limb
+ if(wounding_type == WOUND_SLASH || wounding_type == WOUND_PIERCE)
+ wounding_dmg *= (paper_skin ? 1.5 : 1)
+ else
+ wounding_dmg *= (glass_bones ? 1.5 : 1)
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
if(wounding_type == WOUND_SLASH && !easy_dismember)
diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm
index 80b7599ec3..d572deca73 100644
--- a/code/modules/surgery/organs/ears.dm
+++ b/code/modules/surgery/organs/ears.dm
@@ -18,10 +18,9 @@
// to hear anything.
var/deaf = 0
- // `ear_damage` measures long term damage to the ears, if too high,
+ // `damage` in this case measures long term damage to the ears, if too high,
// the person will not have either `deaf` or `ear_damage` decrease
// without external aid (earmuffs, drugs)
- var/ear_damage = 0
//Resistance against loud noises
var/bang_protect = 0
@@ -44,16 +43,22 @@
/obj/item/organ/ears/proc/restoreEars()
deaf = 0
- ear_damage = 0
+ damage = 0
+ prev_damage = 0
organ_flags &= ~ORGAN_FAILING
var/mob/living/carbon/C = owner
if(iscarbon(owner) && HAS_TRAIT(C, TRAIT_DEAF))
deaf = 1
+ var/mess = check_damage_thresholds()
+ if(mess && owner)
+ to_chat(owner, mess)
/obj/item/organ/ears/proc/adjustEarDamage(ddmg, ddeaf)
- ear_damage = max(ear_damage + (ddmg*damage_multiplier), 0)
+ if(owner.status_flags & GODMODE)
+ return
+ setOrganDamage(max(damage + (ddmg*damage_multiplier), 0))
deaf = max(deaf + (ddeaf*damage_multiplier), 0)
/obj/item/organ/ears/proc/minimumDeafTicks(value)
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm
index cb2c02fa7c..058de79d04 100644
--- a/code/modules/surgery/organs/lungs.dm
+++ b/code/modules/surgery/organs/lungs.dm
@@ -300,7 +300,7 @@
to_chat(H, "Your throat closes up!")
H.silent = max(H.silent, 3)
else
- H.adjustFireLoss(nitryl_pp/4)
+ H.adjustFireLoss(nitryl_pp/2)
gas_breathed = breath.get_moles(GAS_NITRYL)
if (gas_breathed > gas_stimulation_min)
H.reagents.add_reagent(/datum/reagent/nitryl,1)
diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm
index 289e9df9d4..8478ae5d27 100644
--- a/code/modules/surgery/organs/tails.dm
+++ b/code/modules/surgery/organs/tails.dm
@@ -13,6 +13,9 @@
owner.dna.species.stop_wagging_tail(owner)
return ..()
+/obj/item/organ/tail/on_life()
+ return
+
/obj/item/organ/tail/cat
name = "cat tail"
desc = "A severed cat tail. Who's wagging now?"
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index 06415e7685..a4eafc4b01 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -123,6 +123,8 @@
if(locate(/obj/structure/table/optable, T))
propability = 1
+ else if(locate(/obj/machinery/stasis))
+ propability = 0.9
else if(locate(/obj/structure/table, T))
propability = 0.8
else if(locate(/obj/structure/bed, T))
diff --git a/code/modules/tcg/pack_nuclear.dm b/code/modules/tcg/pack_nuclear.dm
index 96ec174a4b..cb82c98571 100644
--- a/code/modules/tcg/pack_nuclear.dm
+++ b/code/modules/tcg/pack_nuclear.dm
@@ -59,7 +59,7 @@
/datum/tcg_card/pack_nuclear/l6saw
name = "L6 Saw LMG"
- desc = "A heavily modified 1.95x129mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
+ desc = "A heavily modified 7.12x82mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
rules = "After equipped unit dies, this card goes to the bottom of draw deck"
icon_state = "l6saw"
diff --git a/code/modules/unit_tests/character_saving.dm b/code/modules/unit_tests/character_saving.dm
index 8d978a630d..cca17b81e4 100644
--- a/code/modules/unit_tests/character_saving.dm
+++ b/code/modules/unit_tests/character_saving.dm
@@ -1,18 +1,29 @@
+#define UNIT_TEST_SAVING_FLAVOR_TEXT "Space"
+#define UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT "Station"
+#define UNIT_TEST_SAVING_OOC_NOTES "Thirteen"
+
/datum/unit_test/character_saving/Run()
try
var/datum/preferences/P = new
P.load_path("test")
- P.features["flavor_text"] = "Foo"
- P.features["ooc_notes"] = "Bar"
+ P.features["flavor_text"] = UNIT_TEST_SAVING_FLAVOR_TEXT
+ P.features["silicon_flavor_text"] = UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT
+ P.features["ooc_notes"] = UNIT_TEST_SAVING_OOC_NOTES
P.save_character()
P.load_character()
- if(P.features["flavor_text"] != "Foo")
+ if(P.features["flavor_text"] != UNIT_TEST_SAVING_FLAVOR_TEXT)
Fail("Flavor text is failing to save.")
- if(P.features["ooc_notes"] != "Bar")
+ if(P.features["silicon_flavor_text"] != UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT)
+ Fail("Silicon flavor text is failing to save.")
+ if(P.features["ooc_notes"] != UNIT_TEST_SAVING_OOC_NOTES)
Fail("OOC text is failing to save.")
P.save_character()
P.load_character()
- if(P.features["flavor_text"] != "Foo")
+ if((P.features["flavor_text"] != UNIT_TEST_SAVING_FLAVOR_TEXT) || (P.features["silicon_flavor_text"] != UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT) || (P.features["ooc_notes"] != UNIT_TEST_SAVING_OOC_NOTES))
Fail("Repeated saving and loading possibly causing save deletion.")
catch(var/exception/e)
Fail("Failed to save and load character due to exception [e.file]:[e.line], [e.name]")
+
+#undef UNIT_TEST_SAVING_FLAVOR_TEXT
+#undef UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT
+#undef UNIT_TEST_SAVING_OOC_NOTES
diff --git a/code/modules/uplink/uplink_items/uplink_ammo.dm b/code/modules/uplink/uplink_items/uplink_ammo.dm
index a1c96d1082..1ce8b7914a 100644
--- a/code/modules/uplink/uplink_items/uplink_ammo.dm
+++ b/code/modules/uplink/uplink_items/uplink_ammo.dm
@@ -209,29 +209,29 @@
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/machinegun/basic
- name = "1.95x129mm Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use with the L6 SAW. \
+ name = "7.12x82mm Box Magazine"
+ desc = "A 50-round magazine of 7.12x82mm ammunition for use with the L6 SAW. \
By the time you need to use this, you'll already be standing on a pile of corpses"
- item = /obj/item/ammo_box/magazine/mm195x129
+ item = /obj/item/ammo_box/magazine/mm712x82
/datum/uplink_item/ammo/machinegun/ap
- name = "1.95x129mm (Armor Penetrating) Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with special properties \
+ name = "7.12x82mm (Armor Penetrating) Box Magazine"
+ desc = "A 50-round magazine of 7.12x82mm ammunition for use in the L6 SAW; equipped with special properties \
to puncture even the most durable armor."
- item = /obj/item/ammo_box/magazine/mm195x129/ap
+ item = /obj/item/ammo_box/magazine/mm712x82/ap
cost = 9
/datum/uplink_item/ammo/machinegun/hollow
- name = "1.95x129mm (Hollow-Point) Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
+ name = "7.12x82mm (Hollow-Point) Box Magazine"
+ desc = "A 50-round magazine of 7.12x82mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
with the unarmored masses of crew."
- item = /obj/item/ammo_box/magazine/mm195x129/hollow
+ item = /obj/item/ammo_box/magazine/mm712x82/hollow
/datum/uplink_item/ammo/machinegun/incen
- name = "1.95x129mm (Incendiary) Box Magazine"
- desc = "A 50-round magazine of 1.95x129mm ammunition for use in the L6 SAW; tipped with a special flammable \
+ name = "7.12x82mm (Incendiary) Box Magazine"
+ desc = "A 50-round magazine of 7.12x82mm ammunition for use in the L6 SAW; tipped with a special flammable \
mixture that'll ignite anyone struck by the bullet. Some men just want to watch the world burn."
- item = /obj/item/ammo_box/magazine/mm195x129/incen
+ item = /obj/item/ammo_box/magazine/mm712x82/incen
/datum/uplink_item/ammo/rocket
purchasable_from = UPLINK_NUKE_OPS
diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm
index dac426db2b..6bfe3f5bb8 100644
--- a/code/modules/uplink/uplink_items/uplink_dangerous.dm
+++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm
@@ -213,7 +213,7 @@
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
- This deadly weapon has a massive 50-round magazine of devastating 1.95x129mm ammunition."
+ This deadly weapon has a massive 50-round magazine of devastating 7.12x82mm ammunition."
item = /obj/item/gun/ballistic/automatic/l6_saw
cost = 18
surplus = 0
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 99020ec7df..f1e4d4468b 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -272,7 +272,7 @@
/obj/vehicle/sealed/mecha/proc/update_part_values() ///Updates the values given by scanning module and capacitor tier, called when a part is removed or inserted.
if(scanmod)
- normal_step_energy_drain = 20 - (5 * scanmod.rating) //10 is normal, so on lowest part its worse, on second its ok and on higher its real good up to 0 on best
+ normal_step_energy_drain = initial(normal_step_energy_drain) * (1.5 / (scanmod.rating - 0.5)) //movement power cost is 3x of default at T1, 1x at T2, 0.6x at T3 and 0.4x at T4
step_energy_drain = normal_step_energy_drain
else
normal_step_energy_drain = 500
@@ -641,6 +641,9 @@
if(!Process_Spacemove(direction))
return FALSE
if(!has_charge(step_energy_drain))
+ if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MESSAGE))
+ to_chat(occupants, "[icon2html(src, occupants)]Insufficient power to move!")
+ TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
return FALSE
if(zoom_mode)
to_chat(occupants, "[icon2html(src, occupants)]Unable to move while in zoom mode!")
@@ -651,7 +654,7 @@
if(!scanmod || !capacitor)
to_chat(occupants, "[icon2html(src, occupants)]Missing [scanmod? "capacitor" : "scanning module"].")
return FALSE
- if(lavaland_only && is_mining_level(z))
+ if(lavaland_only && !is_mining_level(z))
to_chat(occupants, "[icon2html(src, occupants)]Invalid Environment.")
return FALSE
@@ -683,6 +686,7 @@
return TRUE
set_glide_size(DELAY_TO_GLIDE_SIZE(movedelay))
+ use_power(step_energy_drain)
//Otherwise just walk normally
. = step(src,direction, dir)
diff --git a/code/modules/vehicles/mecha/combat/five_stars.dm b/code/modules/vehicles/mecha/combat/five_stars.dm
index 6a73c3adde..def8e94cc8 100644
--- a/code/modules/vehicles/mecha/combat/five_stars.dm
+++ b/code/modules/vehicles/mecha/combat/five_stars.dm
@@ -4,7 +4,6 @@
icon = 'icons/mecha/mecha_96x96.dmi'
icon_state = "five_stars"
armor = list(MELEE = 100, BULLET = 50, LASER = 35, ENERGY = 35, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
- step_in = 4
dir_in = 1 //Facing North.
max_integrity = 800
pixel_x = -32
diff --git a/code/modules/vehicles/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm
index 29746a5fc7..ae7f846142 100644
--- a/code/modules/vehicles/mecha/combat/gygax.dm
+++ b/code/modules/vehicles/mecha/combat/gygax.dm
@@ -9,12 +9,13 @@
deflect_chance = 5
armor = list(MELEE = 25, BULLET = 20, LASER = 30, ENERGY = 15, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
max_temperature = 25000
- leg_overload_coeff = 80
+ leg_overload_coeff = 300
+ overload_step_energy_drain_min = 300
force = 25
wreckage = /obj/structure/mecha_wreckage/gygax
internal_damage_threshold = 35
max_equip = 3
- step_energy_drain = 3
+ normal_step_energy_drain = 3
/obj/vehicle/sealed/mecha/combat/gygax/dark
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
@@ -24,7 +25,8 @@
deflect_chance = 20
armor = list(MELEE = 40, BULLET = 40, LASER = 50, ENERGY = 35, BOMB = 20, BIO = 0, RAD =20, FIRE = 100, ACID = 100)
max_temperature = 35000
- leg_overload_coeff = 70
+ leg_overload_coeff = 100
+ overload_step_energy_drain_min = 100
force = 30
operation_req_access = list(ACCESS_SYNDICATE)
internals_req_access = list(ACCESS_SYNDICATE)
diff --git a/code/modules/vehicles/mecha/combat/medigax.dm b/code/modules/vehicles/mecha/combat/medigax.dm
index 6b2f54a976..ec38dd37db 100644
--- a/code/modules/vehicles/mecha/combat/medigax.dm
+++ b/code/modules/vehicles/mecha/combat/medigax.dm
@@ -11,7 +11,7 @@
max_temperature = 25000
wreckage = /obj/structure/mecha_wreckage/odysseus
internal_damage_threshold = 35
- step_energy_drain = 6
+ normal_step_energy_drain = 6
infra_luminosity = 6
internals_req_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
diff --git a/code/modules/vehicles/mecha/combat/phazon.dm b/code/modules/vehicles/mecha/combat/phazon.dm
index c964b17e36..fad2b0783c 100644
--- a/code/modules/vehicles/mecha/combat/phazon.dm
+++ b/code/modules/vehicles/mecha/combat/phazon.dm
@@ -4,7 +4,7 @@
icon_state = "phazon"
movedelay = 2
dir_in = 2 //Facing South.
- step_energy_drain = 3
+ normal_step_energy_drain = 3
max_integrity = 200
deflect_chance = 30
armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 30, BIO = 0, RAD = 50, FIRE = 100, ACID = 100)
diff --git a/code/modules/vehicles/mecha/combat/reticence.dm b/code/modules/vehicles/mecha/combat/reticence.dm
index b0c8b07aaf..300023b7ab 100644
--- a/code/modules/vehicles/mecha/combat/reticence.dm
+++ b/code/modules/vehicles/mecha/combat/reticence.dm
@@ -14,7 +14,7 @@
mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
internal_damage_threshold = 25
max_equip = 2
- step_energy_drain = 3
+ normal_step_energy_drain = 3
color = "#87878715"
stepsound = null
turnsound = null
diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm
index 38224fbbdd..ff5ea13059 100644
--- a/code/modules/vehicles/mecha/mecha_control_console.dm
+++ b/code/modules/vehicles/mecha/mecha_control_console.dm
@@ -118,7 +118,12 @@
return ..()
/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
- if(!..())
+ for(var/obj/item/I in M.contents)
+ if(istype(I, src))
+ to_chat(user, "[M] already has a tracking beacon!")
+ return
+ . = ..()
+ if(!.)
return
M.trackers += src
M.diag_hud_set_mechtracking()
diff --git a/code/modules/vehicles/mecha/medical/odysseus.dm b/code/modules/vehicles/mecha/medical/odysseus.dm
index bd415cd64f..dd693f9dbb 100644
--- a/code/modules/vehicles/mecha/medical/odysseus.dm
+++ b/code/modules/vehicles/mecha/medical/odysseus.dm
@@ -9,7 +9,7 @@
wreckage = /obj/structure/mecha_wreckage/odysseus
internal_damage_threshold = 35
deflect_chance = 15
- step_energy_drain = 6
+ normal_step_energy_drain = 6
internals_req_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
/obj/vehicle/sealed/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H)
diff --git a/code/modules/vehicles/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm
index 965cdbedd9..40b2e61402 100644
--- a/code/modules/vehicles/mecha/working/ripley.dm
+++ b/code/modules/vehicles/mecha/working/ripley.dm
@@ -96,7 +96,7 @@
movedelay = 4
lights_power = 7
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
- step_energy_drain = 0
+ normal_step_energy_drain = 0
enclosed = TRUE
enter_delay = 40
silicon_icon_state = null
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index 700a2fea7e..f84ced508e 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -864,21 +864,10 @@ GLOBAL_LIST_EMPTY(vending_products)
if(isliving(usr))
var/mob/living/L = usr
C = L.get_idcard(TRUE)
- if(!C)
- say("No card found.")
+ if(!can_transact(C))
flick(icon_deny,src)
vend_ready = TRUE
return
- else if (!C.registered_account)
- say("No account found.")
- flick(icon_deny,src)
- vend_ready = TRUE
- return
- else if(!C.registered_account.account_job)
- say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
- flick(icon_deny, src)
- vend_ready = TRUE
- return
// else if(age_restrictions && R.age_restricted && (!C.registered_age || C.registered_age < AGE_MINOR))
// say("You are not of legal age to purchase [R.name].")
// if(!(usr in GLOB.narcd_underages))
@@ -901,16 +890,13 @@ GLOBAL_LIST_EMPTY(vending_products)
price_to_use = 0 // it's free shut up
if(coin_records.Find(R) || hidden_records.Find(R))
price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price
- if(price_to_use && !account.adjust_money(-price_to_use))
+ if(price_to_use && !attempt_transact(C, price_to_use))
say("You do not possess the funds to purchase [R.name].")
flick(icon_deny,src)
vend_ready = TRUE
return
- var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
- if(D)
- D.adjust_money(price_to_use)
- SSblackbox.record_feedback("amount", "vending_spent", price_to_use)
- // log_econ("[price_to_use] credits were inserted into [src] by [D.account_holder] to buy [R].")
+ SSblackbox.record_feedback("amount", "vending_spent", price_to_use)
+ log_econ("[price_to_use] credits were inserted into [src] by [key_name(usr)] (account: [account.account_holder]) to buy [R].")
if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
say("Thank you for shopping with [src]!")
purchase_message_cooldown = world.time + 5 SECONDS
@@ -1169,7 +1155,7 @@ GLOBAL_LIST_EMPTY(vending_products)
if(owner)
owner.adjust_money(S.custom_price)
SSblackbox.record_feedback("amount", "vending_spent", S.custom_price)
- // log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [owner.account_holder], owned by [private_a.account_holder].")
+ log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [key_name(usr)] (account: [owner.account_holder]), owned by [private_a.account_holder].")
vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
S.forceMove(drop_location())
loaded_items--
diff --git a/code/modules/wiremod/preset/speech_relay.dm b/code/modules/wiremod/preset/speech_relay.dm
index a1e66832c9..bc84568cc0 100644
--- a/code/modules/wiremod/preset/speech_relay.dm
+++ b/code/modules/wiremod/preset/speech_relay.dm
@@ -1,7 +1,7 @@
/**
* # Speech Relay preset
*
- * Acts like poly. Says whatever it hears.
+ * Acts like polly. Says whatever it hears.
*/
/obj/item/integrated_circuit/loaded/speech_relay
diff --git a/config/config.txt b/config/config.txt
index c0c683373d..63adaee716 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -15,6 +15,7 @@
$include entries/admin.txt
$include entries/alert.txt
$include entries/antag_rep.txt
+$include entries/bot.txt
$include entries/comms.txt
$include entries/connections.txt
$include entries/dbconfig.txt
diff --git a/config/entries/bot.txt b/config/entries/bot.txt
new file mode 100644
index 0000000000..eb9e8855e7
--- /dev/null
+++ b/config/entries/bot.txt
@@ -0,0 +1,17 @@
+## Chat Announce Options
+## Various messages to be sent to game chats
+## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4
+## If using TGS4, the string option can be set as a chat channel tag to limit the message to channels of that tag type (case-sensitive)
+## i.e. CHAT_ANNOUNCE_NEW_GAME chat_channel_tag
+
+## Announcements for when a new round begins.
+#CHAT_ANNOUNCE_NEW_GAME
+
+## Announcements for when the round ends, pending server reboot.
+#CHAT_ROUNDEND_NOTICE_TAG
+
+## For where should the one true bird speak?
+#CHAT_SQUAWK_TAG
+
+## Role ID that, when present, will be pinged every round end.
+#CHAT_REBOOT_ROLE
diff --git a/config/entries/general.txt b/config/entries/general.txt
index 7fef691006..3688b8197b 100644
--- a/config/entries/general.txt
+++ b/config/entries/general.txt
@@ -31,15 +31,6 @@ ALLOW_HOLIDAYS
## Uncomment to show the names of the admin sending a pm from IRC instead of showing as a stealthmin.
#SHOW_IRC_NAME
-## Chat Announce Options
-## Various messages to be sent to game chats
-## Uncommenting these will enable them, by default they will be broadcast to Game chat channels on TGS3 or non-admin channels on TGS4
-## If using TGS4, the string option can be set as a chat channel tag to limit the message to channels of that tag type (case-sensitive)
-## i.e. CHAT_ANNOUNCE_NEW_GAME chat_channel_tag
-
-## Send a message with the station name starting a new game
-#CHAT_ANNOUNCE_NEW_GAME
-
##Default screen resolution, in tiles.
## By default, this is 15x15, which gets simplified to 7 by BYOND, as it is a 1:1 screen ratio.
## For reference, Goonstation uses a resolution of 21x15 for it's widescreen mode.
diff --git a/config/entries/logging.txt b/config/entries/logging.txt
index 57588d7cd3..8da1ac4474 100644
--- a/config/entries/logging.txt
+++ b/config/entries/logging.txt
@@ -61,11 +61,14 @@ LOG_JOB_DEBUG
## Log shuttle related actions
LOG_SHUTTLE
+## Log economy-related actions
+LOG_ECON
+
## log all world.Topic() calls
LOG_WORLD_TOPIC
## enables use of the proc twitterize() that lets you take a large list of strings and turn it into a JSON file of tweet sized strings.
-## As an example of how this could be """useful""" look towards Poly (https://twitter.com/Poly_the_Parrot)
+## As an example of how this could be """useful""" look towards Polly (https://twitter.com/Poly_the_Parrot)
# LOG_TWITTER
## Enable logging pictures
diff --git a/goon/icons/obj/power.dmi b/goon/icons/obj/power.dmi
index bb787c0b3c..d2a623bf6c 100644
Binary files a/goon/icons/obj/power.dmi and b/goon/icons/obj/power.dmi differ
diff --git a/html/changelogs/archive/2022-05.yml b/html/changelogs/archive/2022-05.yml
index 92a19f4e1c..e55d2a3bca 100644
--- a/html/changelogs/archive/2022-05.yml
+++ b/html/changelogs/archive/2022-05.yml
@@ -38,3 +38,12 @@
2022-05-17:
timothyteakettle:
- rscadd: poly alt cloak can now be renamed/dedescriptioned in loadout
+2022-05-19:
+ timothyteakettle:
+ - rscadd: quirks are now organised into three tabs for positive, neutral and negative
+2022-05-21:
+ Bhijn & Myr:
+ - bugfix: Blood trails no longer have a duplicate directionless iconstate as their
+ base sprite, fixing the Wonkiness of blood trails going west/east.
+ SandPoot:
+ - bugfix: Silicon flavor texts are no longer broken... maybe?
diff --git a/html/changelogs/archive/2022-06.yml b/html/changelogs/archive/2022-06.yml
new file mode 100644
index 0000000000..9365a633b1
--- /dev/null
+++ b/html/changelogs/archive/2022-06.yml
@@ -0,0 +1,171 @@
+2022-06-01:
+ DeltaFire15:
+ - bugfix: Mechs now use power when moving.
+ - bugfix: The check for mining-only mechs is no longer inverted to only allow non-mining
+ z levels.
+ - bugfix: Reverted an accidental buff from the /tg/ mech code port and its adjustment
+ to citadel's mech state.
+ - bugfix: 'Mechs with different base movement power cost now actually have it apply
+ instead of immediately being overwritten. tweak: Adjusted part impact on movement
+ power use to make more sense.'
+ timothyteakettle:
+ - rscadd: 'optimises quirks somewhat tweak: nyctophobia will now stop run intent
+ when you try to move in darkness with it on, compared to the old behaviour of
+ automatically turning it off in darkness when it is on and you have been in
+ darkness for >= 0.2 seconds tweak: nyctophobia and lightless will both not update
+ your mood until you move now, as part of the optimisations made by changing
+ them to tg code'
+2022-06-02:
+ Bhijn & Myr:
+ - bugfix: You can no longer attach multiple tracking beacons to a single mech, fixing
+ an exploit where mechs can be nuked with minimal effort.
+ - bugfix: Omegastation's airmix filter is no longer inverted! The oxygen:nitrogen
+ levels of Omega later in the round should now be normal again.
+ - rscadd: 'The TGS bot is now capable of pinging the reboot role! Rejoice! tweak:
+ The TGS bot''s automated output can now be configured to define which channels
+ certain messages are output to.'
+ - rscadd: Jukeboxes now have a queue! You can pay 40 credits to have any song of
+ your choosing queued up for playback on the jukebox!
+ - rscadd: Jukeboxes can now be emagged, allowing you to boost their volume up to
+ 210%, along with removing all of its access restrictions. Additionally, a sufficiently
+ loud jukebox is fully capable of causing potentially permanent damage to your
+ ears.
+ - rscadd: 'Jukeboxes now support multi-z! This is self-explanatory. tweak: Volume
+ knobs now work on jukeboxes! tweak: Muffled jukeboxes have been given a buff.
+ tweak: Sounds now factor in the distance multiplier for their baseline z offset.
+ tweak: SOUND_UPDATE now bypasses the can_hear() check in playsound_local() (thanks
+ Azarak for helping figure this out!)'
+ - bugfix: 'Jukebox audio no longer uses playsound_local(), allowing falloff to properly
+ apply to jukeboxes (this fixes the bug where they were significantly quieter
+ than intended) tweak: When deaf, jukeboxes no longer mute the playing track
+ permanently.'
+ - bugfix: Ears are capable of taking damage again.
+ - rscadd: Jukeboxes have been added to Boxstation, Lambdastation, Metastation, and
+ Omegastation
+ - bugfix: Boxstation's incinerator sensor now properly reports to atmos's machinery
+ again
+ Putnam3145:
+ - balance: Nitryl is higher risk, can't be sold for as much
+ - refactor: Gas prices are now part of the gas data structure
+ TrojanCoyote:
+ - rscadd: sprites for muzzled and non muzzled mobs for the masks, along with the
+ adjusted versions, icons for the masks as well.
+ bunny232:
+ - rscadd: Universal blood type now accepts bug blood.
+2022-06-03:
+ Bhijn & Myr:
+ - bugfix: Solar panels now actually face the proper direction. This is achieved
+ by reducing the iconstate to only 1 dir.
+2022-06-06:
+ SandPoot:
+ - refactor: Completely replaces the new player panel *not the admin one* with TG's.
+ timothyteakettle:
+ - rscadd: adds paper skin and glass bones quirks
+2022-06-08:
+ Bhijn & Myr:
+ - bugfix: Audiovisual redirection now works exactly as it used to. In laymen's terms,
+ this means folks in VR sleepers are aware of the world around them again!
+ - rscadd: During pride month, station nukes are significantly more efficient at
+ revealing genders.
+ - rscadd: Station pets now retain their color between shifts!
+ - bugfix: The shake animation, jiggle animation, squish animation, jitter animation,
+ and float animation, have all been fixed.
+ - bugfix: This also means that storage animations are fully working again. It's
+ been a few years!
+ - bugfix: 'The pull animation no longer interrupts ongoing animations. tweak: The
+ pull animation now supports diagonal directions (currently only applies to the
+ initial grab! pull code is spaghetti)'
+ - bugfix: All screenshake sources now fully support the screenshake pref
+ - code_imp: cit_screenshake.dm has been fully merged into the base files.
+ - bugfix: You can no longer remotely apply fingerprints to storage objects by clicking
+ and dragging it around. Additionally, storage objects now rustle again when
+ clicking and dragging (only took like,, a year to fix)
+ - bugfix: 'The pickup animation now properly slides into your spaceman again, instead
+ of just kinda disappearing. tweak: When pulling a resting mob, they''ll now
+ skip the laying animation entirely, fixing a visual oddity where they shrink
+ and grow to flip. tweak: Alerts are now a little snappier and bouncier, as they''ve
+ been swapped from sine easing, to back easing. tweak: Radial menus now use sine
+ easing, rather than linear easing. This just looks a little prettier. tweak:
+ Runechat now properly respects an object''s X offset. Previously, it relied
+ on a hardcoded check for dogborgs. tweak: The float animation now uses pixel_z
+ instead of pixel_y, fixing issues where the Y offset gets wiped due to the float
+ animation. This also makes floating fully compatible with ctrl+WASD.'
+ - bugfix: Admin vote deobfuscation now properly displays votes as 0 if they were
+ simply never voted for.
+ SandPoot:
+ - refactor: Does some extremely minor touches on pulling/pushing code.
+ timothyteakettle:
+ - rscadd: updates existing poly maid outfit with tg sprite but polychromatic
+ - rscadd: adds polychromic maid apron, gloves, collar, headband
+ - rscadd: adds support for polychromic accessories
+2022-06-12:
+ Bhijn & Myr:
+ - rscadd: The station minimap now features higher detail! Instead of just windows
+ and grilles being outlined, all dense+anchored structures and machinery are
+ shown on the minimap.
+ - rscadd: The station minimap now supports obfuscating entire areas, via the minimap_show_walls
+ var.
+ - rscadd: 'The station minimap now supports defining two area colors, allowing for
+ a checkerboard pattern! tweak: Hallways and maint have been given white and
+ gray colors, respectively, for ease of readability. tweak: Ruins are now obfuscated
+ on the minimap, and have been given a subtle, yet distinct, color pattern!'
+ - bugfix: The station minimap no longer errors when you mouse over it
+ - rscadd: 'The station minimap now supports multiz! (However, due to bugginess,
+ multiz minimaps won''t display area tooltips.) tweak: The station minimap now
+ features pixel-perfect scaling.'
+ - code_imp: The station minimap can now support managing data for up to 16,581,374
+ areas without any conflicts at all! Before, BYOND's psuedorandom RNG meant that
+ it was somewhat common for areas to collide with each others' data.
+ - rscadd: Talking is now accompanied with fully-customizable sounds! You can modify
+ your character's speech under the speech tab in chargen, and you can toggle
+ these sounds via the "Hear/Silence Vocal Barks" verb under the preferences tab!
+ This also fully supports genetics.
+ - bugfix: Admittedly an unatomized change, but Cit's DNA blocks can now properly
+ be updated through genetics. Before, these required a complete genetics reset
+ to apply.
+ - rscadd: 'The chat now supports blockquotes! tweak: Examining, medical scanners,
+ self-checking, and mood checkups, have all been converted to make use of blockquotes.'
+ Bhijn & Myr (+ UI work and cleanup by Sandpoot!):
+ - rscadd: 'Colormates now have HSV coloration! tweak: Colormates have had their
+ "please use white clothing" message removed, as that recommendation''s now mostly
+ pointless tweak: The default mode for colormates is now HSV coloration tweak:
+ The temp messages in colormates have been tweaked slightly to be more user-friendly,
+ as they''re user-facing. tweak: The description for constants in the colormate
+ matrix mode has been fixed; the constant variables have nothing to do with contrast,
+ they simply add color tweak: Matrix mode has been made a lot more usable; it''s
+ now clamped between -10 and 10, and features a step of 0.01, making it much
+ easier to simply click and drag to adjust the values, rather than having to
+ punch them in manually'
+ Putnam3145:
+ - balance: QCD matter is now worth 10x as much and makes 2 research pointer per
+ mole
+ SandPoot:
+ - rscadd: Added a search box to all vending machine uis.
+ - qol: Vending machines have candystripes for better clarity.
+ - bugfix: Fixed items that use strip_mod and strip_silence (stripping people faster
+ or without giving them a message)
+ keronshb:
+ - bugfix: Families fixed from crashing
+2022-06-13:
+ Bhijn & Myr:
+ - bugfix: Jukebox audio is now audible within closets, crates, etc!
+2022-06-19:
+ IHOPMommyLich:
+ - rscdel: Removed the forced dynamic, allowing the standard game mode vote.
+ TripleShades:
+ - bugfix: Cannabis mutation variants now use the proper growth state icons
+ - bugfix: Picking to make tea cups will now give the right starting glasswork base
+ - bugfix: Picking to make tea plates will now give the right starting glasswork
+ base
+ - spellcheck: Fixed a state typo in tea cup glassworking
+ - spellcheck: Fixed an incorrect step displayed on spout glassworking
+ - code_imp: Enables the make priority announcement admin verb for admin use
+2022-06-21:
+ Bhijn & Myr:
+ - balance: Ling abilities now have a default loudness of 0.5. This change applies
+ to every single ability that used to have 0 loudness.
+ TrojanCoyote:
+ - rscadd: Adds a plate carrier to HoS loadout, sprites for such
+2022-06-29:
+ Putnam3145:
+ - bugfix: GAS_OXYGEN -> GAS_O2
diff --git a/html/changelogs/archive/2022-07.yml b/html/changelogs/archive/2022-07.yml
new file mode 100644
index 0000000000..99a1e1103e
--- /dev/null
+++ b/html/changelogs/archive/2022-07.yml
@@ -0,0 +1,103 @@
+2022-07-05:
+ Putnam3145:
+ - bugfix: Miasma is brown again
+2022-07-09:
+ Bhijn & Myr:
+ - code_imp: Barks can now be intercepted via component signals. Both bark queuing
+ and individual barks can be intercepted via signals!
+ - rscadd: The "Brassy" bark has been added, using the cog installation sound as
+ a sample! This works surprisingly well as a bark
+ - rscadd: 'Genetics can now give people goose1.ogg tweak: If new barks are queued
+ before the current barks are finished, this will interrupt all ongoing barks
+ tweak: Yelling no longer cuts the minimum bark time variance down to half, as
+ this proved to sound pretty awful with most barks. tweak: Chitter now uses a
+ completely unique audio sample, which is based on the original ratchet.ogg it
+ used to be. This new sample is shorter, and has significantly less harsh noise
+ on the higher frequencies, making it much easier on the ears. Additionally,
+ the minimum speed for chitter has been reduced from 6 to 4. tweak: Setting vocal_bark
+ to a file should now automatically turn it into a sound datum (in theory, at
+ least! as of writing i haven''t tested this at all)'
+ - bugfix: Barks and other DNA features after the first mob color now work exactly
+ as you'd expect. This was the cause for horrid eldritch bark sounds when the
+ wrong part of DNA gets hit. The first mob color has lost some genetics resolution
+ as an indirect result of this (the higher resolution is what caused this bug)
+ UDaV73rus, Tokoriso, dragomagol:
+ - rscadd: welding now has an animation!
+ timothyteakettle:
+ - rscadd: slimes no longer die from having no blood, properly consume limbs when
+ at low blood, and suffer brute damage and oxygen loss for having no blood and
+ no limbs left to consume respectably, they cannot go past BLOOD_VOLUME_MAXIMUM
+ from consuming toxin
+2022-07-16:
+ MediHound:
+ - rscdel: Removed old Alina sprites
+ - rscadd: Added new Alina sprites
+ SandPoot:
+ - bugfix: The tweak tag for changelogs should now work.
+2022-07-20:
+ Putnam3145:
+ - balance: quark matter is now worth 5% as much and gives 10% the research points
+ timothyteakettle:
+ - bugfix: makes brain trauma event respect canSpawnEvent conditions such as min
+ players
+2022-07-21:
+ SandPoot:
+ - bugfix: If you have a dark purple stabilized extract and are holding nothing in
+ your hand, no longer attempts to heat nothing, which caused immense amounts
+ of runtimes.
+ - bugfix: The syndicate has fixed the radiation health analyzer allowing you to
+ check on the ui again.
+2022-07-23:
+ TripleShades:
+ - rscdel: Snow Cabin turbine
+ - tweak: Snow Cabin, Jungle Resort, and Plasma Outpost gateways now use RTGs for
+ power generation
+ - balance: Snow Cabin SMES unit is now non-magical
+ - bugfix: Snow Cabin gateway wiring now connected properly
+2022-07-24:
+ Bhijn & Myr:
+ - tweak: The typo in Polly's name has been fixed, severing the decade-old reference
+ to a 2012-era TGstation coder. If you know, you know.
+ BlueWildrose:
+ - qol: Two new Kinkmates have been added to Deltastation in the dorms and arrivals
+ area.
+ - bugfix: Cleanbots will no longer go invisible when they get turned on or off.
+ - qol: Public library paintings have been added to Omegastation. You can now submit
+ paintings that will appear in later rounds on that station.
+2022-07-25:
+ BlueWildrose:
+ - bugfix: Fixes hierophant walls letting non-casters pass through them.
+ - qol: Player-controlled cleanbots can now clean messes that ordinarily wouldn't
+ be clickable as long as they are clicking the tile it's on.
+ - bugfix: The shocked autolathe will no longer infinitely zap you with the menu
+ open.
+ - bugfix: Using wirecutters on an autolathe with an open panel will now have appropriate
+ behavior of opening the wire menu.
+ - bugfix: Harvested grown inedibles now take their seed stats into account instead
+ of acting like they got adminspawned.
+ - bugfix: Tea now dispenses from dispensers again.
+ - bugfix: Pink tea and Pink milk are pathed correctly.
+ SandPoot:
+ - bugfix: Put arguments into handle_blood (it needs them).
+2022-07-27:
+ timothyteakettle:
+ - bugfix: slime limb regeneration ability fix
+2022-07-31:
+ Putnam3145:
+ - rscadd: Atmospheric flux event (properly)
+ - rscadd: Sandstorm event (was in files, just disabled; 10 space dusts all at once)
+ - tweak: Random brain trauma can now trigger if there's an AI, chemist, virologist,
+ captain, HoP or roboticist
+ - balance: Flux anomaly min player count 10->0
+ - balance: Pyroclastic anomaly min player count 0->5
+ - balance: Cat surgeon weight 8->5
+ - balance: Disease outbreak min player count 10->3, now requires medbay
+ - balance: Heart attack min player count 40->10, now requires medbay
+ - balance: Mass hallucination max occurrences 2->5
+ - balance: Supermatter surge max occurrences 2->5, now half as strong on CO2less
+ setups (lerping up to old value for 100% CO2)
+ - balance: Supernova max occurrences 2->1, weight 10->5
+ - balance: 'Vent Clog: Normal min players 25->0, random chem prob 1%->0%'
+ - balance: 'Vent Clog: Threatening min players 35->15'
+ - balance: 'Vent Clog: Catastrophic min players 45->25'
+ - rscadd: Random shoe untying
diff --git a/html/changelogs/archive/2022-08.yml b/html/changelogs/archive/2022-08.yml
new file mode 100644
index 0000000000..a5f7fa3e87
--- /dev/null
+++ b/html/changelogs/archive/2022-08.yml
@@ -0,0 +1,50 @@
+2022-08-01:
+ Putnam3145:
+ - bugfix: rad collectors display the right units now
+ - balance: Stasis beds are now 90% as good as surgery tables for surgery
+2022-08-02:
+ SandPoot:
+ - admin: Alphabetically ordered bitfields for admin editing.
+ - admin: It is now easier to change the flags of turrets.
+ - refactor: Allows for defining bitfields in other files.
+2022-08-03:
+ Putnam3145:
+ - balance: Research bomb "midpoint" at which it's worth exactly 50000 points from
+ 240->300
+ - code_imp: doesn't snowflake the bomb cap for linux anymore, servers that need
+ to tweak it can do it themselves (I didn't even put it down right, should be
+ 5000 instead of 50000, yikes)
+2022-08-04:
+ MrJWhit:
+ - rscadd: Adds more AI screens on box
+ TripleShades:
+ - qol: Three gateways will no longer lose power via Magical SMES Units
+ timothyteakettle:
+ - rscadd: lets AIs control status displays (vtuber mode)
+2022-08-05:
+ Hatterhat:
+ - tweak: The L6 Squad Automatic Weapon, as used by Syndicate nuclear operatives,
+ now fires 7.12x82mm, with no change in ballistic performance. This has the side
+ effect of making it now capable of utilizing match-grade ammunition, which some
+ would think are mutually incompatible concepts.
+ Putnam3145:
+ - tweak: Untied shoelaces probabilities rework
+ - balance: Miner boots are slightly harder to tie/untie now
+2022-08-08:
+ Hatterhat:
+ - tweak: Proto-kinetic crushers and variants can now be renamed via pen.
+ - tweak: Custom descriptions on items tagged with UNIQUE_RENAME can now go to 350
+ characters, up from 140.
+ - tweak: Recoil now pushes your screen in the opposite direction of where you're
+ shooting. It makes sense in context, I swear. Adjust the setting for this in
+ your client prefs, because it defaults to on.
+ Linzolle:
+ - bugfix: catwalk overlays behave properly, appearing on top of cables and such
+ Putnam3145:
+ - tweak: Various gases now have shortened names for filters
+ - balance: Nitric oxide now removes from the power mix like nitrogen/pluoxium do
+ - balance: Nitric oxide now becomes, at most, 20% nitrogen dioxide instead of 50%
+ SandPoot:
+ - bugfix: Fixed the lack of eyes making ERROR appear on people.
+ - qol: Set up for the dmi editor extension, very helpful as you can see the existant
+ states and their names opposed to only images in a huge spritesheet.
diff --git a/icons/blanks/32x32.dmi b/icons/blanks/32x32.dmi
new file mode 100644
index 0000000000..6c4f2b33e0
Binary files /dev/null and b/icons/blanks/32x32.dmi differ
diff --git a/icons/blanks/96x96.dmi b/icons/blanks/96x96.dmi
new file mode 100644
index 0000000000..d79e60c111
Binary files /dev/null and b/icons/blanks/96x96.dmi differ
diff --git a/icons/blanks/blank_title.png b/icons/blanks/blank_title.png
new file mode 100644
index 0000000000..387a21f03a
Binary files /dev/null and b/icons/blanks/blank_title.png differ
diff --git a/icons/default_title.dmi b/icons/default_title.dmi
deleted file mode 100644
index 633bd434b8..0000000000
Binary files a/icons/default_title.dmi and /dev/null differ
diff --git a/icons/effects/welding_effect.dmi b/icons/effects/welding_effect.dmi
new file mode 100644
index 0000000000..8b8db2dcae
Binary files /dev/null and b/icons/effects/welding_effect.dmi differ
diff --git a/icons/hud/lobby/background.dmi b/icons/hud/lobby/background.dmi
new file mode 100644
index 0000000000..baae06fc1b
Binary files /dev/null and b/icons/hud/lobby/background.dmi differ
diff --git a/icons/hud/lobby/bottom_buttons.dmi b/icons/hud/lobby/bottom_buttons.dmi
new file mode 100644
index 0000000000..d0aa1228c7
Binary files /dev/null and b/icons/hud/lobby/bottom_buttons.dmi differ
diff --git a/icons/hud/lobby/character_setup.dmi b/icons/hud/lobby/character_setup.dmi
new file mode 100644
index 0000000000..d3b94fb43e
Binary files /dev/null and b/icons/hud/lobby/character_setup.dmi differ
diff --git a/icons/hud/lobby/join.dmi b/icons/hud/lobby/join.dmi
new file mode 100644
index 0000000000..416f315770
Binary files /dev/null and b/icons/hud/lobby/join.dmi differ
diff --git a/icons/hud/lobby/observe.dmi b/icons/hud/lobby/observe.dmi
new file mode 100644
index 0000000000..f59252b3ea
Binary files /dev/null and b/icons/hud/lobby/observe.dmi differ
diff --git a/icons/hud/lobby/poll_overlay.dmi b/icons/hud/lobby/poll_overlay.dmi
new file mode 100644
index 0000000000..2fc9716260
Binary files /dev/null and b/icons/hud/lobby/poll_overlay.dmi differ
diff --git a/icons/hud/lobby/ready.dmi b/icons/hud/lobby/ready.dmi
new file mode 100644
index 0000000000..d2a45a883f
Binary files /dev/null and b/icons/hud/lobby/ready.dmi differ
diff --git a/icons/mob/clothing/accessories.dmi b/icons/mob/clothing/accessories.dmi
index 03849efa5a..f801c483f1 100644
Binary files a/icons/mob/clothing/accessories.dmi and b/icons/mob/clothing/accessories.dmi differ
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index ca8a7312fa..9bd206e04e 100644
Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ
diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi
index 2413b52d71..3c50e4d42d 100644
Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ
diff --git a/icons/mob/clothing/mask_muzzled.dmi b/icons/mob/clothing/mask_muzzled.dmi
index 9f483c8d47..5e0bb46c34 100644
Binary files a/icons/mob/clothing/mask_muzzled.dmi and b/icons/mob/clothing/mask_muzzled.dmi differ
diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi
index 20b8576277..2b317737d7 100644
Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ
diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi
index 8be696eb45..e99623dfc6 100644
Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ
diff --git a/icons/mob/clothing/suit_digi.dmi b/icons/mob/clothing/suit_digi.dmi
index 13840507a6..a7d419545c 100644
Binary files a/icons/mob/clothing/suit_digi.dmi and b/icons/mob/clothing/suit_digi.dmi differ
diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi
index 04d9b20a75..ce25963360 100644
Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 4b8dba160a..c4927ea06b 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi
index 79cb2bff77..f633f030c3 100644
Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index d4cd4b4f2f..17073805c9 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index f5bc9e7046..b86731babd 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi
index 8540b2f392..c9491af6b2 100644
Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 5493361129..a6e5e1f037 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index c16b416cd8..de7dd234b1 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/runtime/README.md b/icons/runtime/README.md
new file mode 100644
index 0000000000..804cb2f285
--- /dev/null
+++ b/icons/runtime/README.md
@@ -0,0 +1,5 @@
+# Runtime Loaded Icons
+
+These icons are not compiled into the .rsc or are otherwise loaded at runtime.
+
+Please keep all (non-config) icons that do this in this folder as it is needed by the [deploy.sh](../../tools/deploy.sh) script to minimize build output.
diff --git a/icons/runtime/default_title.dmi b/icons/runtime/default_title.dmi
new file mode 100644
index 0000000000..17f4787f84
Binary files /dev/null and b/icons/runtime/default_title.dmi differ
diff --git a/icons/runtime/tcg/default.dmi b/icons/runtime/tcg/default.dmi
new file mode 100644
index 0000000000..f42113f30e
Binary files /dev/null and b/icons/runtime/tcg/default.dmi differ
diff --git a/icons/runtime/tcg/xenos.dmi b/icons/runtime/tcg/xenos.dmi
new file mode 100644
index 0000000000..682b0a6966
Binary files /dev/null and b/icons/runtime/tcg/xenos.dmi differ
diff --git a/icons/turf/floors/catwalk_plating.dmi b/icons/turf/floors/catwalk_plating.dmi
index 24954e4a17..c9ad36653b 100644
Binary files a/icons/turf/floors/catwalk_plating.dmi and b/icons/turf/floors/catwalk_plating.dmi differ
diff --git a/modular_citadel/code/game/objects/cit_screenshake.dm b/modular_citadel/code/game/objects/cit_screenshake.dm
deleted file mode 100644
index 222de37f82..0000000000
--- a/modular_citadel/code/game/objects/cit_screenshake.dm
+++ /dev/null
@@ -1,51 +0,0 @@
-//we vlambeer now
-
-/obj/proc/shake_camera(mob/M, duration, strength=1)//byond's wonky with this shit
- set waitfor = FALSE
- if(!M || !M.client || duration <= 0)
- return
- var/client/C = M.client
- if (C.prefs.screenshake==0)
- return
- var/oldx = C.pixel_x
- var/oldy = C.pixel_y
- var/clientscreenshake = (C.prefs.screenshake * 0.01)
- var/max = (strength*clientscreenshake) * world.icon_size
- var/min = -((strength*clientscreenshake) * world.icon_size)
-
- for(var/i in 0 to duration-1)
- if (i == 0)
- animate(C, pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
- else
- animate(pixel_x=rand(min,max), pixel_y=rand(min,max), time=1)
- animate(pixel_x=oldx, pixel_y=oldy, time=1)
-
-/obj/item/gun/energy
- recoil = 0.1
-
-/obj/item/gun/energy/kinetic_accelerator
- recoil = 0.5
-
-/obj/item/gun/ballistic
- recoil = 0.25
-
-/obj/item/gun/ballistic/shotgun
- recoil = 1
-
-/obj/item/gun/ballistic/revolver
- recoil = 0.5
-
-/obj/item/gun/ballistic/revolver/doublebarrel
- recoil = 1
-
-/obj/item/gun/syringe
- recoil = 0.1
-
-/obj/item/pneumatic_cannon/fire_items(turf/target, mob/user)
- . = ..()
- shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75))
-
-/obj/item/attack_obj(obj/O, mob/living/user)
- . = ..()
- if(force >= 20)
- shake_camera(user, ((force - 15) * 0.01 + 1), ((force - 15) * 0.01))
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index fe53574470..931324bf8f 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -579,3 +579,9 @@
path = /obj/item/storage/box/pockerchips
ckeywhitelist = list("greed2323")
+/datum/gear/donator/psychedelicjumpsuit
+ name = "psychedelic jumpsuit"
+ slot = ITEM_SLOT_ICLOTHING
+ path = /obj/item/clothing/under/misc/psyche
+ ckeywhitelist = list("commandnotrecognized")
+
diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm
index 3824993009..0573a1a22a 100644
--- a/modular_citadel/code/modules/client/loadout/backpack.dm
+++ b/modular_citadel/code/modules/client/loadout/backpack.dm
@@ -175,3 +175,9 @@
/datum/gear/backpack/necklace//this is here because loadout doesn't support proper accessories
name = "A renameable necklace"
path = /obj/item/clothing/accessory/necklace
+
+/datum/gear/backpack/polymaidapron //this is ALSO here because loadout doesn't support proper accessories
+ name = "Polychromic maid apron"
+ path = /obj/item/clothing/accessory/maidapron/polychromic
+ loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
+ loadout_initial_colors = list("#333333", "#FFFFFF")
diff --git a/modular_citadel/code/modules/client/loadout/gloves.dm b/modular_citadel/code/modules/client/loadout/gloves.dm
index 2a80d43bb1..960be356e2 100644
--- a/modular_citadel/code/modules/client/loadout/gloves.dm
+++ b/modular_citadel/code/modules/client/loadout/gloves.dm
@@ -14,6 +14,12 @@
name = "Midnight gloves"
path = /obj/item/clothing/gloves/evening/black
+/datum/gear/gloves/maidpoly // WHAT DO YOU EVEN CALL THEM
+ name = "Polychromic maid gloves"
+ path = /obj/item/clothing/gloves/polymaid
+ loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
+ loadout_initial_colors = list("#333333", "#FFFFFF")
+
/datum/gear/gloves/goldring
name = "A gold ring"
path = /obj/item/clothing/gloves/ring
diff --git a/modular_citadel/code/modules/client/loadout/head.dm b/modular_citadel/code/modules/client/loadout/head.dm
index f2a7ead5be..d0563d2986 100644
--- a/modular_citadel/code/modules/client/loadout/head.dm
+++ b/modular_citadel/code/modules/client/loadout/head.dm
@@ -58,6 +58,12 @@
name = "Maid headband"
path= /obj/item/clothing/head/maid
+/datum/gear/head/maidband/poly
+ name = "Polychromic maid headband"
+ path= /obj/item/clothing/head/maid/polychromic
+ loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
+ loadout_initial_colors = list("#333333", "#FFFFFF")
+
/datum/gear/head/flakhelm
name = "Flak Helmet"
path = /obj/item/clothing/head/flakhelm
diff --git a/modular_citadel/code/modules/client/loadout/mask.dm b/modular_citadel/code/modules/client/loadout/mask.dm
index 16b47e60e7..f1cf2a5d9f 100644
--- a/modular_citadel/code/modules/client/loadout/mask.dm
+++ b/modular_citadel/code/modules/client/loadout/mask.dm
@@ -15,6 +15,16 @@
path = /obj/item/clothing/mask/joy
cost = 3
+/datum/gear/mask/kitsune
+ name = "White Kitsune Mask"
+ path = /obj/item/clothing/mask/kitsunewhi
+ cost = 2
+
+/datum/gear/mask/black_kitsune
+ name = "Black Kitsune Mask"
+ path = /obj/item/clothing/mask/kitsuneblk
+ cost = 2
+
/datum/gear/mask/gas
name = "Gas Mask"
path = /obj/item/clothing/mask/gas
diff --git a/modular_citadel/code/modules/client/loadout/neck.dm b/modular_citadel/code/modules/client/loadout/neck.dm
index dc7735de2b..64d1fcdc1f 100644
--- a/modular_citadel/code/modules/client/loadout/neck.dm
+++ b/modular_citadel/code/modules/client/loadout/neck.dm
@@ -106,3 +106,9 @@
path = /obj/item/clothing/neck/cloak/cancloak/polychromic
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#585858", "#373737", "#BEBEBE")
+
+/datum/gear/neck/maid
+ name = "Polychromatic Maid Collar"
+ path = /obj/item/clothing/neck/maid
+ loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
+ loadout_initial_colors = list("#333333", "#FFFFFF")
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index 2b2f3b53e4..d70d3d4fa1 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -52,7 +52,7 @@
name = "Polychromic maid costume"
path = /obj/item/clothing/under/rank/civilian/janitor/maid/polychromic
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
- loadout_initial_colors = list("#FFFFFF", "#000000")
+ loadout_initial_colors = list("#333333", "#FFFFFF")
/datum/gear/uniform/mailmanuniform
name = "Mailman's jumpsuit"
diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm
index 102ae41921..4942a1041f 100644
--- a/modular_citadel/code/modules/client/preferences_savefile.dm
+++ b/modular_citadel/code/modules/client/preferences_savefile.dm
@@ -35,5 +35,4 @@
WRITE_FILE(S["feature_xeno_head"], features["xenohead"])
//flavor text
WRITE_FILE(S["feature_flavor_text"], features["flavor_text"])
- WRITE_FILE(S["silicon_feature_flavor_text"], features["silicon_flavor_text"])
-
+ WRITE_FILE(S["feature_silicon_flavor_text"], features["silicon_flavor_text"])
diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm
index 0adb12e5a1..8a6643d239 100644
--- a/modular_citadel/code/modules/mob/cit_emotes.dm
+++ b/modular_citadel/code/modules/mob/cit_emotes.dm
@@ -77,7 +77,8 @@
restraint_check = TRUE
/datum/emote/living/snap/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -93,7 +94,8 @@
restraint_check = TRUE
/datum/emote/living/snap2/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -109,7 +111,8 @@
restraint_check = TRUE
/datum/emote/living/snap3/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -125,7 +128,8 @@
restraint_check = FALSE
/datum/emote/living/awoo/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -141,7 +145,8 @@
restraint_check = FALSE
/datum/emote/living/hiss/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -157,7 +162,8 @@
restraint_check = FALSE
/datum/emote/living/meow/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -173,7 +179,8 @@
restraint_check = FALSE
/datum/emote/living/purr/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -189,7 +196,8 @@
restraint_check = FALSE
/datum/emote/living/nya/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -205,7 +213,8 @@
restraint_check = FALSE
/datum/emote/living/weh/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -221,7 +230,8 @@
restraint_check = FALSE
/datum/emote/living/peep/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -244,7 +254,8 @@
restraint_check = FALSE
/datum/emote/living/mothsqueak/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -260,7 +271,8 @@
restraint_check = FALSE
/datum/emote/living/merp/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -276,7 +288,8 @@
restraint_check = FALSE
/datum/emote/living/bark/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -293,7 +306,8 @@
restraint_check = FALSE
/datum/emote/living/squish/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -310,7 +324,8 @@
restraint_check = FALSE
/datum/emote/living/pain/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
if(user.nextsoundemote >= world.time)
return
@@ -331,6 +346,7 @@
restraint_check = TRUE
/datum/emote/living/clap1/run_emote(mob/living/user, params)
- if(!(. = ..()))
+ . = ..()
+ if(!.)
return
playsound(user, 'modular_citadel/sound/voice/clap.ogg', 50, 1, -1)
diff --git a/modular_citadel/icons/mob/widerobot.dmi b/modular_citadel/icons/mob/widerobot.dmi
index 50c29bb75f..cc986cfa9d 100644
Binary files a/modular_citadel/icons/mob/widerobot.dmi and b/modular_citadel/icons/mob/widerobot.dmi differ
diff --git a/sound/voice/barks/chitter.ogg b/sound/voice/barks/chitter.ogg
new file mode 100644
index 0000000000..0d162fa303
Binary files /dev/null and b/sound/voice/barks/chitter.ogg differ
diff --git a/strings/cas_white.txt b/strings/cas_white.txt
index 3e229862a2..397c7febff 100644
--- a/strings/cas_white.txt
+++ b/strings/cas_white.txt
@@ -72,7 +72,7 @@ Supermatter undergarments.
A permaban.
Stealing all the miners' ore.
Bluespace artillery.
-Poly reading porn over the radio again.
+Polly reading porn over the radio again.
Mining the shaft.
Grab intent.
A blob zombie with an erection.
diff --git a/strings/phobia.json b/strings/phobia.json
index fc8fb31995..ee25cc62fa 100644
--- a/strings/phobia.json
+++ b/strings/phobia.json
@@ -250,6 +250,7 @@
"bird",
"beak",
"poly",
+ "polly",
"wing",
"claw",
"peck",
diff --git a/tgstation.dme b/tgstation.dme
index 00a8286bdc..6878f256e2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -28,6 +28,7 @@
#include "code\__DEFINES\admin.dm"
#include "code\__DEFINES\antagonists.dm"
#include "code\__DEFINES\atmospherics.dm"
+#include "code\__DEFINES\bitfields.dm"
#include "code\__DEFINES\blackmarket.dm"
#include "code\__DEFINES\botany.dm"
#include "code\__DEFINES\callbacks.dm"
@@ -154,6 +155,9 @@
#include "code\__DEFINES\dcs\flags.dm"
#include "code\__DEFINES\dcs\helpers.dm"
#include "code\__DEFINES\dcs\signals.dm"
+#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
+#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm"
+#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm"
#include "code\__DEFINES\mapping\maploader.dm"
#include "code\__DEFINES\material\worth.dm"
#include "code\__DEFINES\mobs\innate_abilities.dm"
@@ -174,6 +178,7 @@
#include "code\__HELPERS\angles.dm"
#include "code\__HELPERS\areas.dm"
#include "code\__HELPERS\chat.dm"
+#include "code\__HELPERS\clients.dm"
#include "code\__HELPERS\cmp.dm"
#include "code\__HELPERS\config.dm"
#include "code\__HELPERS\custom_holoforms.dm"
@@ -283,6 +288,7 @@
#include "code\_onclick\hud\map_popups.dm"
#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
+#include "code\_onclick\hud\new_player.dm"
#include "code\_onclick\hud\picture_in_picture.dm"
#include "code\_onclick\hud\plane_master.dm"
#include "code\_onclick\hud\radial.dm"
@@ -321,6 +327,7 @@
#include "code\controllers\configuration\entries\admin.dm"
#include "code\controllers\configuration\entries\alert.dm"
#include "code\controllers\configuration\entries\antag_rep.dm"
+#include "code\controllers\configuration\entries\bot.dm"
#include "code\controllers\configuration\entries\comms.dm"
#include "code\controllers\configuration\entries\connections.dm"
#include "code\controllers\configuration\entries\dbconfig.dm"
@@ -415,7 +422,7 @@
#include "code\controllers\subsystem\persistence\_persistence.dm"
#include "code\controllers\subsystem\persistence\cleanable_debris.dm"
#include "code\controllers\subsystem\persistence\panic_bunker.dm"
-#include "code\controllers\subsystem\persistence\poly_parrot.dm"
+#include "code\controllers\subsystem\persistence\polly_parrot.dm"
#include "code\controllers\subsystem\persistence\recent_votes_etc.dm"
#include "code\controllers\subsystem\persistence\secret_satchels.dm"
#include "code\controllers\subsystem\persistence\trophies.dm"
@@ -439,6 +446,7 @@
#include "code\datums\action.dm"
#include "code\datums\ai_laws.dm"
#include "code\datums\armor.dm"
+#include "code\datums\bark.dm"
#include "code\datums\beam.dm"
#include "code\datums\beepsky_fashion.dm"
#include "code\datums\browser.dm"
@@ -2114,6 +2122,7 @@
#include "code\modules\events\anomaly_grav.dm"
#include "code\modules\events\anomaly_pyro.dm"
#include "code\modules\events\anomaly_vortex.dm"
+#include "code\modules\events\atmos_speed.dm"
#include "code\modules\events\aurora_caelus.dm"
#include "code\modules\events\blob.dm"
#include "code\modules\events\brain_trauma.dm"
@@ -2160,6 +2169,7 @@
#include "code\modules\events\supermatter_surge.dm"
#include "code\modules\events\supernova.dm"
#include "code\modules\events\travelling_trader.dm"
+#include "code\modules\events\untie_shoes.dm"
#include "code\modules\events\vent_clog.dm"
#include "code\modules\events\wisdomcow.dm"
#include "code\modules\events\wormholes.dm"
@@ -3706,6 +3716,7 @@
#include "code\modules\vehicles\mecha\mecha_wreckage.dm"
#include "code\modules\vehicles\mecha\combat\combat.dm"
#include "code\modules\vehicles\mecha\combat\durand.dm"
+#include "code\modules\vehicles\mecha\combat\five_stars.dm"
#include "code\modules\vehicles\mecha\combat\gygax.dm"
#include "code\modules\vehicles\mecha\combat\honker.dm"
#include "code\modules\vehicles\mecha\combat\marauder.dm"
@@ -3776,7 +3787,6 @@
#include "interface\skin.dmf"
#include "modular_citadel\code\datums\components\souldeath.dm"
#include "modular_citadel\code\datums\status_effects\chems.dm"
-#include "modular_citadel\code\game\objects\cit_screenshake.dm"
#include "modular_citadel\code\game\objects\effects\temporary_visuals\souldeath.dm"
#include "modular_citadel\code\modules\admin\holder2.dm"
#include "modular_citadel\code\modules\admin\secrets.dm"
diff --git a/tgui/packages/tgui-panel/styles/components/Chat.scss b/tgui/packages/tgui-panel/styles/components/Chat.scss
index b439ace8c5..a199963fd0 100644
--- a/tgui/packages/tgui-panel/styles/components/Chat.scss
+++ b/tgui/packages/tgui-panel/styles/components/Chat.scss
@@ -98,3 +98,24 @@ $color-bg-section: base.$color-bg-section !default;
pointer-events: none;
}
}
+
+blockquote {
+ background-color: rgba($text-color, 0.05);
+ border-left: 0.15em solid;
+ border-color: $text-color;
+ padding-left: 0.3em;
+ padding-right: 0.3em;
+ margin-bottom: 0.15em;
+ margin-left: 0.3em;
+ margin-right: 0em;
+}
+
+hr {
+ background-color: rgba($text-color, 0.25);
+ height: 0.15em;
+ border-style: none;
+ margin-left: 1em;
+ margin-right: 2em;
+ margin-bottom: 0.3em;
+ margin-top: 0.3em;
+}
diff --git a/tgui/packages/tgui-panel/styles/goon/chat-dark.scss b/tgui/packages/tgui-panel/styles/goon/chat-dark.scss
index 4406d24015..aa75db6c0d 100644
--- a/tgui/packages/tgui-panel/styles/goon/chat-dark.scss
+++ b/tgui/packages/tgui-panel/styles/goon/chat-dark.scss
@@ -447,6 +447,10 @@ em {
font-style: italic;
}
+blockquote.warning {
+ border-color: #c51e1e;
+}
+
.alertwarning {
color: #FF0000;
font-weight: bold;
@@ -486,10 +490,18 @@ em {
color: #9ab0ff;
}
+blockquote.info {
+ border-color: #9ab0ff;
+}
+
.notice {
color: #6685f5;
}
+blockquote.notice {
+ border-color: #6685f5;
+}
+
.tinynotice {
color: #6685f5;
font-size: 85%;
@@ -545,18 +557,34 @@ em {
color: #059223;
}
+blockquote.green {
+ border-color: #059223;
+}
+
.red {
color: #FF0000;
}
+blockquote.red {
+ border-color: #FF0000;
+}
+
.blue {
color: #215cff;
}
+blockquote.blue {
+ border-color: #215cff;
+}
+
.nicegreen {
color: #059223;
}
+blockquote.nicegreen {
+ border-color: #059223;
+}
+
/* hornichems */
.userlove {
color: #ff42a6;
@@ -575,6 +603,10 @@ em {
color: #973e3b;
}
+blockquote.cult {
+ border-color: #973e3b;
+}
+
.cultitalic {
color: #973e3b;
font-style: italic;
@@ -630,6 +662,10 @@ em {
color: #9956d3;
}
+blockquote.purple {
+ border-color: #9956d3;
+}
+
.holoparasite {
color: #88809c;
}
@@ -693,6 +729,10 @@ em {
color: #BE8700;
}
+blockquote.brass {
+ border-color: #BE8700;
+}
+
.heavy_brass {
color: #BE8700;
font-weight: bold;
diff --git a/tgui/packages/tgui-panel/styles/goon/chat-light.scss b/tgui/packages/tgui-panel/styles/goon/chat-light.scss
index e94d2a4e4b..42e2e478ae 100644
--- a/tgui/packages/tgui-panel/styles/goon/chat-light.scss
+++ b/tgui/packages/tgui-panel/styles/goon/chat-light.scss
@@ -484,6 +484,10 @@ h1.alert, h2.alert {
font-style: italic;
}
+blockquote.warning {
+ border-color: #ff0000;
+}
+
.alertwarning {
color: #FF0000;
font-weight: bold;
@@ -522,11 +526,18 @@ h1.alert, h2.alert {
.info {
color: #0000CC;
}
+blockquote.info {
+ border-color: #0000CC;
+}
.notice {
color: #000099;
}
+blockquote.notice {
+ border-color: #000099;
+}
+
.tinynotice {
color: #000099;
font-size: 85%;
@@ -582,18 +593,33 @@ h1.alert, h2.alert {
color: #03ff39;
}
+blockquote.green {
+ border-color: #03ff39;
+}
+
.red {
color: #FF0000;
}
+blockquote.red {
+ border-color: #FF0000;
+}
.blue {
color: #0000FF;
}
+blockquote.blue {
+ border-color: #0000FF;
+}
+
.nicegreen {
color: #14a833;
}
+blockquote.nicegreen {
+ border-color: #14a833;
+}
+
.userlove {
color: #FF1493;
font-style: italic;
@@ -611,6 +637,10 @@ h1.alert, h2.alert {
color: #973e3b;
}
+blockquote.cult {
+ border-color: #973e3b;
+}
+
.cultitalic {
color: #973e3b;
font-style: italic;
@@ -666,6 +696,10 @@ h1.alert, h2.alert {
color: #5e2d79;
}
+blockquote.purple {
+ border-color: #5e2d79;
+}
+
.holoparasite {
color: #35333a;
}
@@ -730,6 +764,10 @@ h1.alert, h2.alert {
color: #BE8700;
}
+blockquote.brass {
+ border-color: #BE8700;
+}
+
.heavy_brass {
color: #BE8700;
font-weight: bold;
diff --git a/tgui/packages/tgui/constants.js b/tgui/packages/tgui/constants.js
index bc20e9ac9c..a5ac6aceb0 100644
--- a/tgui/packages/tgui/constants.js
+++ b/tgui/packages/tgui/constants.js
@@ -181,6 +181,12 @@ const GASES = [
'label': 'N₂O',
'color': 'red',
},
+ {
+ 'id': 'no',
+ 'name': 'Nitric Oxide',
+ 'label': 'NO',
+ 'color': 'red',
+ },
{
'id': 'no2',
'name': 'Nitryl',
@@ -223,6 +229,24 @@ const GASES = [
'label': 'H₂',
'color': 'white',
},
+ {
+ 'id': 'methane',
+ 'name': 'Methane',
+ 'label': 'CH₄',
+ 'color': 'grey',
+ },
+ {
+ 'id': 'methyl_bromide',
+ 'name': 'Methyl Bromide',
+ 'label': 'CH₃Br',
+ 'color': 'brown',
+ },
+ {
+ 'id': 'qcd',
+ 'name': 'Quark Matter',
+ 'label': 'QGP',
+ 'color': 'pink',
+ },
];
export const getGasLabel = (gasId, fallbackValue) => {
diff --git a/tgui/packages/tgui/interfaces/Colormate.js b/tgui/packages/tgui/interfaces/Colormate.js
index f376547102..02810f2943 100644
--- a/tgui/packages/tgui/interfaces/Colormate.js
+++ b/tgui/packages/tgui/interfaces/Colormate.js
@@ -1,115 +1,120 @@
import { useBackend } from '../backend';
-import { Button, Flex, Icon, NoticeBox, NumberInput, Section, Tabs } from '../components';
+import { Button, Icon, NoticeBox, NumberInput, Section, Table, Tabs, Slider } from '../components';
import { Window } from '../layouts';
export const Colormate = (props, context) => {
const { act, data } = useBackend(context);
- const { matrixactive, temp } = data;
+ const { activemode, temp } = data;
const item = data.item || [];
return (
- {temp ? (
- {temp}
- ) : (null)}
- {Object.keys(item).length ? (
- <>
-
-
-