diff --git a/_maps/shuttles/emergency_nature.dmm b/_maps/shuttles/emergency_nature.dmm
new file mode 100644
index 0000000000..9639e37852
--- /dev/null
+++ b/_maps/shuttles/emergency_nature.dmm
@@ -0,0 +1,2040 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"as" = (
+/obj/structure/flora/ausbushes/lavendergrass,
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"au" = (
+/obj/structure/sink/puddle,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"ay" = (
+/obj/structure/flora/ausbushes/leafybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"aA" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 6
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"aJ" = (
+/obj/structure/flora/ausbushes/stalkybush,
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"bd" = (
+/obj/structure/flora/rock/pile/largejungle,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"bg" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/toolbox/mechanical{
+ pixel_y = 8;
+ pixel_x = -2
+ },
+/obj/item/storage/toolbox/electrical,
+/obj/effect/turf_decal/stripes/line,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"bS" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/box/lights/mixed{
+ pixel_y = 9;
+ pixel_x = -5
+ },
+/obj/item/storage/box/matches{
+ pixel_y = 5
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 10
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"cm" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/machinery/portable_atmospherics/canister/oxygen,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"cL" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"cR" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 5
+ },
+/obj/structure/sign/warning/nosmoking{
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"cZ" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 1
+ },
+/obj/machinery/computer/emergency_shuttle,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"dj" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/obj/item/radio/intercom{
+ name = "Station Intercom (General)";
+ pixel_y = -31
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"dP" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/structure/extinguisher_cabinet{
+ pixel_y = 30
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"dT" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plating{
+ icon_state = "platingdmg3"
+ },
+/area/shuttle/escape)
+"eq" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plating{
+ icon_state = "platingdmg1"
+ },
+/area/shuttle/escape)
+"ev" = (
+/obj/effect/turf_decal/trimline/green/filled/corner,
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"ex" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 6
+ },
+/obj/structure/flora/ausbushes/leafybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"eB" = (
+/obj/item/rack_parts,
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/corner{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"eS" = (
+/obj/effect/turf_decal/trimline/red/filled/end{
+ dir = 1
+ },
+/obj/structure/table/reinforced,
+/obj/machinery/recharger,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"eY" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 9
+ },
+/obj/structure/table/reinforced,
+/obj/item/storage/toolbox/emergency{
+ pixel_y = 3
+ },
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"fD" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 1
+ },
+/obj/machinery/computer/security,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"fG" = (
+/obj/structure/flora/ausbushes/fullgrass,
+/obj/structure/flora/ausbushes/genericbush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"fJ" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 1
+ },
+/obj/machinery/computer/communications,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"fT" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 10
+ },
+/obj/machinery/door/window/westleft{
+ name = "Infirmary"
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"gg" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/obj/item/radio/intercom{
+ dir = 4;
+ name = "Station Intercom (General)";
+ pixel_y = 27
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"gj" = (
+/obj/machinery/door/airlock/maintenance_hatch,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"gl" = (
+/obj/structure/flora/junglebush/large,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"gu" = (
+/obj/structure/shuttle/engine/propulsion,
+/turf/open/floor/plating/airless,
+/area/shuttle/escape)
+"gx" = (
+/turf/open/floor/plating/airless,
+/area/shuttle/escape)
+"gI" = (
+/obj/item/shovel,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"gM" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 5
+ },
+/obj/structure/table/reinforced,
+/obj/item/storage/fancy/donut_box,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"gR" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/machinery/hydroponics/soil,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"ht" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 9
+ },
+/obj/structure/chair/comfy/shuttle,
+/obj/machinery/light{
+ dir = 8
+ },
+/obj/structure/reagent_dispensers/peppertank{
+ pixel_y = 28
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"hC" = (
+/obj/effect/turf_decal/trimline/red/filled/corner{
+ dir = 1
+ },
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 4
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"hJ" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 8
+ },
+/obj/structure/table/reinforced,
+/obj/item/storage/box/monkeycubes{
+ pixel_x = 6;
+ pixel_y = 5
+ },
+/obj/item/storage/box/monkeycubes{
+ pixel_x = -6;
+ pixel_y = 2
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"ib" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"it" = (
+/mob/living/carbon/monkey,
+/obj/structure/flora/grass/jungle/b{
+ icon_state = "bushb3"
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"iD" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 5
+ },
+/obj/structure/table/reinforced,
+/obj/item/restraints/handcuffs{
+ pixel_y = 3
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"iF" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/obj/structure/flora/ausbushes/brflowers,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"iO" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/machinery/space_heater,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"iV" = (
+/obj/effect/decal/cleanable/robot_debris,
+/obj/effect/turf_decal/stripes/corner{
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"jO" = (
+/obj/structure/table/reinforced,
+/obj/item/storage/box/stockparts{
+ pixel_y = 7
+ },
+/obj/effect/turf_decal/stripes/line,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"jX" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 9
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"jZ" = (
+/obj/effect/turf_decal/trimline/red/filled/corner{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"ke" = (
+/obj/item/shovel/spade,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"ku" = (
+/obj/effect/turf_decal/trimline/blue/filled/corner{
+ dir = 4
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"lo" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/obj/structure/flora/ausbushes/leafybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"lH" = (
+/obj/structure/reagent_dispensers/fueltank,
+/obj/effect/turf_decal/stripes/end{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"lN" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/structure/grille/broken,
+/turf/open/floor/plating{
+ icon_state = "panelscorched"
+ },
+/area/shuttle/escape)
+"lS" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 4
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"lT" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 8
+ },
+/obj/structure/table/reinforced,
+/obj/item/cigbutt{
+ pixel_x = 8
+ },
+/obj/machinery/recharger,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"lV" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 5
+ },
+/obj/structure/table/glass,
+/obj/item/reagent_containers/food/snacks/soup/monkeysdelight{
+ pixel_y = 4
+ },
+/obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy{
+ pixel_y = 5;
+ pixel_x = 6
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"me" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 9
+ },
+/obj/structure/sign/warning/nosmoking{
+ pixel_y = 32
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"mq" = (
+/mob/living/carbon/monkey,
+/obj/machinery/light/floor,
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"mw" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 10
+ },
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"nA" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 9
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"nD" = (
+/obj/structure/flora/ausbushes/fernybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"nQ" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"og" = (
+/obj/effect/turf_decal/trimline/blue/filled/corner{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"os" = (
+/obj/effect/turf_decal/trimline/green/filled/end{
+ dir = 8
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 8
+ },
+/obj/machinery/door/window/westleft{
+ name = "Nature pen"
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"oE" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 5
+ },
+/obj/structure/table/reinforced,
+/obj/item/storage/firstaid/regular,
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"qD" = (
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"rg" = (
+/obj/item/clothing/glasses/welding{
+ pixel_y = 8;
+ pixel_x = 3
+ },
+/obj/item/weldingtool/largetank{
+ pixel_x = -3
+ },
+/obj/structure/rack,
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"rI" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"sm" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/reagent_dispensers/watertank,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"su" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 6
+ },
+/obj/structure/table/optable,
+/obj/effect/decal/cleanable/blood/old,
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"sF" = (
+/obj/effect/turf_decal/trimline/blue/filled/line,
+/obj/item/storage/backpack/duffelbag/med/surgery{
+ pixel_y = 5
+ },
+/obj/structure/rack,
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"sN" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"sV" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 1
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"tL" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 8
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"uc" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 10
+ },
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"ui" = (
+/obj/structure/extinguisher_cabinet,
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/escape)
+"ur" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 8
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"uI" = (
+/obj/structure/flora/rock/jungle{
+ icon_state = "rock3"
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"vt" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 10
+ },
+/obj/structure/table/reinforced,
+/obj/item/restraints/handcuffs{
+ pixel_y = 7
+ },
+/obj/item/storage/fancy/donut_box,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"vx" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 6
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"vP" = (
+/obj/effect/turf_decal/trimline/red/filled/line,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"vW" = (
+/obj/effect/turf_decal/trimline/red/filled/line{
+ dir = 6
+ },
+/obj/structure/table/reinforced,
+/obj/item/storage/box/handcuffs{
+ pixel_y = 5
+ },
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"wg" = (
+/obj/effect/turf_decal/trimline/green/filled/end{
+ dir = 1
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/door/window/northleft,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"wX" = (
+/obj/effect/turf_decal/trimline/blue/filled/line,
+/obj/machinery/light,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"xA" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/obj/structure/flora/ausbushes/fernybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"xZ" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 10
+ },
+/obj/structure/tank_dispenser/oxygen{
+ layer = 2.7;
+ pixel_x = -1;
+ pixel_y = 2
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"yt" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"yI" = (
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"yR" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 6
+ },
+/obj/machinery/suit_storage_unit/standard_unit,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"yZ" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 6
+ },
+/obj/structure/sign/poster/official/pda_ad{
+ pixel_y = -32
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"zf" = (
+/obj/structure/flora/ausbushes/pointybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"zr" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 10
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"zs" = (
+/obj/machinery/light/floor,
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"zD" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 5
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"zE" = (
+/obj/machinery/door/airlock/security{
+ name = "Brig";
+ req_access_txt = "63; 42"
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"Ai" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 6
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Aw" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 4
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/obj/machinery/status_display/evac{
+ dir = 8;
+ pixel_x = 32
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"AM" = (
+/obj/structure/flora/ausbushes/ywflowers,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Bm" = (
+/obj/machinery/door/airlock/command/glass{
+ name = "Cockpit";
+ req_access_txt = "19"
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"Bo" = (
+/obj/structure/flora/ausbushes/sunnybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Bt" = (
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Bv" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"BA" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 9
+ },
+/obj/structure/table/glass,
+/obj/item/defibrillator/loaded{
+ pixel_y = 5
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"BG" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 10
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"BM" = (
+/obj/structure/flora/ausbushes/ppflowers,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Cb" = (
+/obj/structure/flora/rock/jungle{
+ icon_state = "bushc2"
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Co" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"CA" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 9
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"CE" = (
+/obj/structure/flora/tree/jungle/small,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"CQ" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 1
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/vending/cola/space_up,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Db" = (
+/obj/structure/sign/poster/official/help_others,
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/escape)
+"DD" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 9
+ },
+/obj/structure/window/reinforced{
+ dir = 8
+ },
+/mob/living/simple_animal/bot/medbot{
+ name = "\improper emergency medibot";
+ pixel_x = -3;
+ pixel_y = 2
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"DQ" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"EI" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 1
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/vending/snack/green,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Fo" = (
+/obj/item/cultivator,
+/mob/living/simple_animal/hostile/lizard,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Fp" = (
+/obj/structure/flora/ausbushes/grassybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Gf" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 8
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"GO" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 8
+ },
+/obj/structure/table/glass,
+/obj/item/storage/box/monkeycubes{
+ pixel_y = 10;
+ pixel_x = 5
+ },
+/obj/item/reagent_containers/food/snacks/cube/monkey{
+ pixel_x = 5
+ },
+/obj/item/paicard{
+ pixel_x = -6;
+ pixel_y = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"GV" = (
+/obj/structure/shuttle/engine/huge,
+/turf/open/floor/plating/airless,
+/area/shuttle/escape)
+"He" = (
+/obj/effect/turf_decal/trimline/blue/filled/corner{
+ dir = 1
+ },
+/turf/open/floor/plasteel{
+ icon_state = "floorscorched1"
+ },
+/area/shuttle/escape)
+"Hi" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plating{
+ icon_state = "platingdmg1"
+ },
+/area/shuttle/escape)
+"Hq" = (
+/obj/structure/flora/rock/pile,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"HV" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Ia" = (
+/mob/living/carbon/monkey,
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Io" = (
+/obj/effect/turf_decal/trimline/green/filled/corner,
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Iw" = (
+/obj/item/reagent_containers/glass/bucket,
+/mob/living/simple_animal/hostile/retaliate/frog,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Iz" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/vomit,
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"IB" = (
+/obj/effect/decal/cleanable/oil,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"Jw" = (
+/obj/structure/shuttle/engine/heater,
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/turf/open/floor/plating/airless,
+/area/shuttle/escape)
+"JD" = (
+/obj/effect/turf_decal/trimline/blue/filled/end{
+ dir = 1
+ },
+/obj/structure/table/glass,
+/obj/item/storage/firstaid/brute{
+ pixel_x = 4;
+ pixel_y = 2
+ },
+/obj/item/storage/firstaid/regular{
+ pixel_x = -3
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"JR" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 4
+ },
+/obj/machinery/suit_storage_unit/standard_unit,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"Ka" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/structure/flora/ausbushes/sparsegrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Kv" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/structure/sign/poster/contraband/tools{
+ pixel_y = 32
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"Kx" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"KT" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 5
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Lm" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/obj/structure/flora/ausbushes/pointybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"LG" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"LO" = (
+/obj/structure/flora/rock/jungle{
+ icon_state = "grassa4"
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"LW" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"LY" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"MJ" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/obj/structure/flora/ausbushes/leafybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"MS" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 6
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Nu" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/item/hatchet,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Ob" = (
+/obj/effect/turf_decal/trimline/green/filled/end,
+/obj/effect/turf_decal/stripes/line,
+/obj/machinery/door/window/southleft{
+ name = "Nature pen"
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"OS" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/obj/machinery/vending/coffee,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Ps" = (
+/obj/structure/flora/ausbushes/brflowers,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"PG" = (
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/green/filled/corner{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"PP" = (
+/obj/structure/flora/ausbushes/genericbush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"QC" = (
+/obj/structure/flora/ausbushes/lavendergrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"QM" = (
+/obj/item/bodypart,
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plating{
+ icon_state = "panelscorched"
+ },
+/area/shuttle/escape)
+"QO" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 4
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"QZ" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 4
+ },
+/obj/effect/turf_decal/trimline/blue/filled/corner{
+ dir = 1
+ },
+/obj/structure/chair,
+/obj/structure/sign/poster/contraband/busty_backdoor_xeno_babes_6{
+ pixel_x = 30
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"Ru" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 9
+ },
+/obj/machinery/vending/hydroseeds,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Sl" = (
+/obj/effect/turf_decal/trimline/blue/filled/line,
+/obj/machinery/computer/operating{
+ dir = 1
+ },
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"Sr" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 6
+ },
+/obj/structure/table/glass,
+/obj/item/clothing/suit/monkeysuit{
+ pixel_y = 4;
+ pixel_x = -2
+ },
+/obj/item/clothing/mask/gas/monkeymask{
+ pixel_x = 5;
+ pixel_y = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"SS" = (
+/obj/machinery/door/airlock/titanium{
+ name = "Emergency Shuttle Airlock"
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"ST" = (
+/obj/effect/turf_decal/weather/dirt,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Ti" = (
+/obj/structure/flora/rock/jungle{
+ icon_state = "busha3"
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Ts" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/obj/machinery/hydroponics/soil,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"TH" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 5
+ },
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/structure/chair/comfy/shuttle,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"TK" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 5
+ },
+/obj/item/hatchet,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"TT" = (
+/obj/effect/turf_decal/weather/dirt,
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Um" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"Uy" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"UE" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 5
+ },
+/obj/machinery/vending/hydronutrients,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"UO" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 8
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Vu" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/mob/living/carbon/monkey,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Vv" = (
+/mob/living/carbon/monkey,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"VI" = (
+/obj/effect/spawner/structure/window/shuttle,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"VM" = (
+/obj/structure/flora/tree/jungle,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"VU" = (
+/turf/closed/wall/mineral/titanium,
+/area/shuttle/escape)
+"Wa" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Wr" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 9
+ },
+/obj/structure/flora/ausbushes/reedbush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Wz" = (
+/obj/effect/turf_decal/stripes/line,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/recharge_station,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"WE" = (
+/turf/template_noop,
+/area/template_noop)
+"WH" = (
+/obj/structure/flora/ausbushes/fullgrass,
+/obj/structure/flora/ausbushes/sunnybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"WL" = (
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"Xm" = (
+/obj/structure/flora/rock,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"XK" = (
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"XY" = (
+/obj/effect/turf_decal/trimline/blue/filled/line{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel{
+ dir = 1
+ },
+/area/shuttle/escape)
+"Ym" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 1
+ },
+/obj/structure/flora/rock/pile,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Yp" = (
+/obj/machinery/door/airlock/titanium{
+ name = "Emergency Shuttle Airlock"
+ },
+/obj/docking_port/mobile/emergency,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Yu" = (
+/turf/closed/wall/mineral/titanium/nodiagonal,
+/area/shuttle/escape)
+"YH" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 9
+ },
+/obj/structure/flora/ausbushes/fullgrass,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"YP" = (
+/obj/effect/turf_decal/trimline/green/filled/end{
+ dir = 4
+ },
+/obj/effect/turf_decal/stripes/line{
+ dir = 4
+ },
+/obj/machinery/door/window/eastleft{
+ name = "Nature pen"
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"YW" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/obj/machinery/vending/wardrobe/hydro_wardrobe,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Zd" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 3
+ },
+/obj/machinery/light,
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"Zg" = (
+/obj/effect/turf_decal/trimline/blue/filled/line,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
+"Zl" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 5
+ },
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Zm" = (
+/obj/effect/turf_decal/weather/dirt{
+ dir = 10
+ },
+/obj/structure/flora/ausbushes/fernybush,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"Zt" = (
+/obj/effect/turf_decal/trimline/green/filled/line,
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"ZD" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 4
+ },
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+"ZL" = (
+/obj/machinery/hydroponics/soil,
+/obj/item/seeds/banana,
+/turf/open/floor/grass,
+/area/shuttle/escape)
+"ZT" = (
+/obj/effect/turf_decal/trimline/green/filled/line{
+ dir = 8
+ },
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/shuttle/escape)
+
+(1,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+SS
+Yu
+Yp
+Yu
+Yu
+Yu
+Yu
+Yu
+SS
+Yu
+SS
+Yu
+Yu
+Yu
+Yu
+Yu
+Yu
+VU
+WE
+WE
+WE
+"}
+(2,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+Yu
+nA
+UO
+yt
+ZT
+UO
+GO
+UO
+ZT
+yt
+UO
+zr
+Yu
+Yu
+lH
+eB
+lN
+bS
+Yu
+VU
+WE
+WE
+"}
+(3,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+Yu
+me
+Io
+Wa
+Wa
+Wa
+Wa
+ev
+Wa
+Wa
+Wa
+Wa
+Bv
+zr
+Yu
+Yu
+rg
+iV
+jO
+Jw
+gx
+gx
+GV
+"}
+(4,1,1) = {"
+WE
+WE
+VU
+VI
+VI
+VI
+VU
+Yu
+nA
+Io
+MS
+VI
+VI
+VI
+VI
+YP
+VI
+VI
+VI
+VI
+KT
+Bv
+zr
+Yu
+Yu
+eq
+bg
+Jw
+gx
+gx
+gx
+"}
+(5,1,1) = {"
+WE
+VU
+Yu
+jX
+tL
+vt
+Yu
+CA
+Io
+MS
+VI
+VI
+YH
+iF
+xA
+Gf
+lo
+Gf
+Zm
+VI
+VI
+KT
+Bv
+BG
+Yu
+Kv
+DQ
+Jw
+gx
+gx
+gx
+"}
+(6,1,1) = {"
+VU
+Yu
+ht
+jZ
+WL
+vP
+zE
+HV
+Zt
+VI
+VI
+Wr
+Vv
+Ti
+Fo
+PP
+Xm
+ZL
+LO
+mw
+VI
+VI
+HV
+Zd
+Yu
+IB
+iO
+Jw
+gu
+WE
+WE
+"}
+(7,1,1) = {"
+VI
+eS
+hC
+lS
+lS
+vW
+Yu
+Co
+Zt
+VI
+Ru
+zs
+Bt
+qD
+Bo
+aJ
+fG
+CE
+Vv
+zs
+uc
+VI
+HV
+Kx
+Yu
+dP
+dT
+Jw
+gu
+WE
+WE
+"}
+(8,1,1) = {"
+Yu
+Yu
+VI
+VI
+ui
+Yu
+Db
+Co
+Zt
+VI
+Ym
+XK
+au
+XK
+VM
+Hq
+QC
+XK
+BM
+Bt
+Ka
+VI
+HV
+YW
+Yu
+LY
+sm
+Jw
+gu
+WE
+WE
+"}
+(9,1,1) = {"
+VI
+eY
+hJ
+lT
+ur
+xZ
+Yu
+CQ
+Zt
+VI
+Ts
+WH
+XK
+XK
+Ps
+gl
+Bt
+it
+AM
+gI
+TT
+VI
+HV
+Zd
+Yu
+Um
+DQ
+Jw
+gx
+gx
+GV
+"}
+(10,1,1) = {"
+VI
+fD
+LW
+WL
+WL
+Zg
+Bm
+HV
+LG
+Ob
+Uy
+Xm
+Vv
+Fp
+qD
+zs
+XK
+XK
+PP
+Bt
+ST
+wg
+PG
+cL
+gj
+Um
+cm
+Jw
+gx
+gx
+gx
+"}
+(11,1,1) = {"
+VI
+cZ
+LW
+WL
+WL
+Zg
+VI
+EI
+Zt
+VI
+Lm
+as
+XK
+VM
+Iw
+au
+XK
+bd
+Bt
+XK
+Nu
+VI
+HV
+Zd
+Yu
+Um
+Hi
+Jw
+gx
+gx
+gx
+"}
+(12,1,1) = {"
+VI
+fJ
+LW
+WL
+WL
+Zg
+VI
+Co
+Zt
+VI
+Vu
+nD
+qD
+PP
+Bt
+yI
+QC
+Bt
+XK
+uI
+gR
+VI
+HV
+OS
+Yu
+Um
+Wz
+Jw
+gu
+WE
+WE
+"}
+(13,1,1) = {"
+VI
+gM
+ku
+WL
+WL
+wX
+Yu
+gg
+Zt
+VI
+UE
+zs
+zf
+ke
+zf
+ay
+XK
+ay
+AM
+mq
+ex
+VI
+HV
+dj
+Yu
+QM
+DQ
+Jw
+gu
+WE
+WE
+"}
+(14,1,1) = {"
+VU
+Yu
+iD
+og
+WL
+Zg
+ui
+Co
+Zt
+VI
+VI
+TK
+Cb
+Bt
+qD
+BM
+Bo
+Ia
+XK
+Ai
+VI
+VI
+HV
+Zd
+Yu
+zD
+vx
+Jw
+gu
+WE
+WE
+"}
+(15,1,1) = {"
+WE
+VU
+Yu
+oE
+JR
+yR
+Yu
+TH
+sN
+zr
+VI
+VI
+Zl
+QO
+MJ
+QO
+ib
+MJ
+Ai
+VI
+VI
+nA
+sV
+aA
+Yu
+DD
+fT
+Jw
+gx
+gx
+GV
+"}
+(16,1,1) = {"
+WE
+WE
+VU
+Yu
+Yu
+Yu
+VU
+Yu
+KT
+sN
+zr
+VI
+VI
+VI
+VI
+os
+VI
+VI
+VI
+VI
+nA
+sV
+MS
+Yu
+Yu
+XY
+sF
+Jw
+gx
+gx
+gx
+"}
+(17,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+Yu
+cR
+sN
+yt
+yt
+yt
+yt
+nQ
+yt
+yt
+yt
+yt
+sV
+yZ
+Yu
+Yu
+BA
+He
+Sl
+Jw
+gx
+gx
+gx
+"}
+(18,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+Yu
+lV
+rI
+ZD
+rI
+rI
+Aw
+rI
+rI
+ZD
+rI
+Sr
+Yu
+Yu
+JD
+QZ
+Iz
+su
+Yu
+VU
+WE
+WE
+"}
+(19,1,1) = {"
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+WE
+VU
+Yu
+VI
+VI
+VI
+VI
+Yu
+VI
+VI
+VI
+VI
+Yu
+Yu
+Yu
+Yu
+Yu
+Yu
+Yu
+VU
+WE
+WE
+WE
+"}
diff --git a/_maps/templates/hilbertshotel.dmm b/_maps/templates/hilbertshotel.dmm
index 4e4d8f8267..da5d13d93e 100644
--- a/_maps/templates/hilbertshotel.dmm
+++ b/_maps/templates/hilbertshotel.dmm
@@ -7,7 +7,7 @@
/area/hilbertshotel)
"c" = (
/obj/machinery/jukebox{
- req_access = null
+ req_one_access = null
},
/turf/open/indestructible/hotelwood,
/area/hilbertshotel)
diff --git a/code/__DEFINES/_flags/obj_flags.dm b/code/__DEFINES/_flags/obj_flags.dm
index a936a5cef5..ce1e126f12 100644
--- a/code/__DEFINES/_flags/obj_flags.dm
+++ b/code/__DEFINES/_flags/obj_flags.dm
@@ -9,8 +9,11 @@
#define UNIQUE_RENAME (1<<6) //can you customize the description/name of the thing?
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
#define FROZEN (1<<8)
-#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
-#define BLOCK_Z_FALL (1<<10)
+#define BLOCK_Z_OUT_DOWN (1<<9) // Should this object block z falling from loc?
+#define BLOCK_Z_OUT_UP (1<<10) // Should this object block z uprise from loc?
+#define BLOCK_Z_IN_DOWN (1<<11) // Should this object block z falling from above?
+#define BLOCK_Z_IN_UP (1<<12) // Should this object block z uprise from below?
+#define SHOVABLE_ONTO (1<<13) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
/// Integrity defines for clothing (not flags but close enough)
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
@@ -18,3 +21,6 @@
#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
+
+/// Flags for the pod_flags var on /obj/structure/closet/supplypod
+#define FIRST_SOUNDS (1<<0) // If it shouldn't play sounds the first time it lands, used for reverse mode
diff --git a/code/__DEFINES/actionspeed_modifiers.dm b/code/__DEFINES/actionspeed_modifiers.dm
new file mode 100644
index 0000000000..40fbd3fe26
--- /dev/null
+++ b/code/__DEFINES/actionspeed_modifiers.dm
@@ -0,0 +1,2 @@
+//ids
+#define ACTIONSPEED_ID_SANITY "sanity_component"
diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm
index bba5b5c5ed..ac5272057a 100644
--- a/code/__DEFINES/cargo.dm
+++ b/code/__DEFINES/cargo.dm
@@ -13,27 +13,43 @@
#define STYLE_GONDOLA 13
#define STYLE_SEETHROUGH 14
-#define POD_ICON_STATE 1
-#define POD_NAME 2
-#define POD_DESC 3
+#define POD_SHAPE 1
+#define POD_BASE 2
+#define POD_DOOR 3
+#define POD_DECAL 4
+#define POD_GLOW 5
+#define POD_RUBBLE_TYPE 6
+#define POD_NAME 7
+#define POD_DESC 8
-#define POD_STYLES list(\
- list("supplypod", "supply pod", "A Nanotrasen supply drop pod."),\
- list("bluespacepod", "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
- list("centcompod", "\improper Centcom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to Centcom after delivery."),\
- list("syndiepod", "blood-red supply pod", "A dark, intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
- list("squadpod", "\improper MK. II supply pod", "A Nanotrasen supply pod. This one has been marked the markings of some sort of elite strike team."),\
- list("cultpod", "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
- list("missilepod", "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
- list("smissilepod", "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
- list("boxpod", "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
- list("honkpod", "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
- list("fruitpod", "\improper Orange", "An angry orange."),\
- list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
- list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
- list("", "", "")\
-)
+#define RUBBLE_NONE 1
+#define RUBBLE_NORMAL 2
+#define RUBBLE_WIDE 3
+#define RUBBLE_THIN 4
+#define POD_SHAPE_NORML 1
+#define POD_SHAPE_OTHER 2
+
+#define SUPPLYPOD_X_OFFSET -16
+
+GLOBAL_LIST_EMPTY(supplypod_loading_bays)
+
+GLOBAL_LIST_INIT(podstyles, list(\
+ list(POD_SHAPE_NORML, "pod", TRUE, "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\
+ list(POD_SHAPE_NORML, "advpod", TRUE, "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
+ list(POD_SHAPE_NORML, "advpod", TRUE, "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\
+ list(POD_SHAPE_NORML, "darkpod", TRUE, "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
+ list(POD_SHAPE_NORML, "darkpod", TRUE, "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\
+ list(POD_SHAPE_NORML, "pod", TRUE, "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
+ list(POD_SHAPE_OTHER, "missile", FALSE, FALSE, FALSE, RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
+ list(POD_SHAPE_OTHER, "smissile", FALSE, FALSE, FALSE, RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
+ list(POD_SHAPE_OTHER, "box", TRUE, FALSE, FALSE, RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
+ list(POD_SHAPE_NORML, "clownpod", TRUE, "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
+ list(POD_SHAPE_OTHER, "orange", TRUE, FALSE, FALSE, RUBBLE_NONE, "\improper Orange", "An angry orange."),\
+ list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
+ list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
+ list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\
+))
#define PACK_GOODY_NONE 0
#define PACK_GOODY_PUBLIC 1 //can be bought by both privates and cargo
-#define PACK_GOODY_PRIVATE 2 //can be bought only by privates
\ No newline at end of file
+#define PACK_GOODY_PRIVATE 2 //can be bought only by privates
diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm
index 2273d34c82..fb461acfa4 100644
--- a/code/__DEFINES/colors.dm
+++ b/code/__DEFINES/colors.dm
@@ -1,54 +1,54 @@
// This is eventually for wjohn to add more color standardization stuff like I keep asking him >:(
-#define COLOR_INPUT_DISABLED "#F0F0F0"
-#define COLOR_INPUT_ENABLED "#D3B5B5"
-#define COLOR_FLOORTILE_GRAY "#8D8B8B"
-#define COLOR_ALMOST_BLACK "#333333"
-#define COLOR_BLACK "#000000"
-#define COLOR_RED "#FF0000"
-#define COLOR_RED_LIGHT "#FF3333"
-#define COLOR_MAROON "#800000"
-#define COLOR_YELLOW "#FFFF00"
-#define COLOR_OLIVE "#808000"
-#define COLOR_LIME "#32CD32"
-#define COLOR_GREEN "#008000"
-#define COLOR_CYAN "#00FFFF"
-#define COLOR_TEAL "#008080"
-#define COLOR_BLUE "#0000FF"
-#define COLOR_BLUE_LIGHT "#33CCFF"
-#define COLOR_NAVY "#000080"
-#define COLOR_PINK "#FFC0CB"
-#define COLOR_MAGENTA "#FF00FF"
-#define COLOR_PURPLE "#800080"
-#define COLOR_ORANGE "#FF9900"
-#define COLOR_BEIGE "#CEB689"
-#define COLOR_BLUE_GRAY "#75A2BB"
-#define COLOR_BROWN "#BA9F6D"
-#define COLOR_DARK_BROWN "#997C4F"
-#define COLOR_DARK_ORANGE "#C3630C"
-#define COLOR_GREEN_GRAY "#99BB76"
-#define COLOR_RED_GRAY "#B4696A"
-#define COLOR_PALE_BLUE_GRAY "#98C5DF"
-#define COLOR_PALE_GREEN_GRAY "#B7D993"
-#define COLOR_PALE_ORANGE "#FFC066"
-#define COLOR_PALE_RED_GRAY "#D59998"
-#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
-#define COLOR_PURPLE_GRAY "#AE8CA8"
+#define COLOR_INPUT_DISABLED "#F0F0F0"
+#define COLOR_INPUT_ENABLED "#D3B5B5"
+#define COLOR_FLOORTILE_GRAY "#8D8B8B"
+#define COLOR_ALMOST_BLACK "#333333"
+#define COLOR_BLACK "#000000"
+#define COLOR_RED "#FF0000"
+#define COLOR_RED_LIGHT "#FF3333"
+#define COLOR_MAROON "#800000"
+#define COLOR_YELLOW "#FFFF00"
+#define COLOR_OLIVE "#808000"
+#define COLOR_LIME "#32CD32"
+#define COLOR_GREEN "#008000"
+#define COLOR_CYAN "#00FFFF"
+#define COLOR_TEAL "#008080"
+#define COLOR_BLUE "#0000FF"
+#define COLOR_BLUE_LIGHT "#33CCFF"
+#define COLOR_NAVY "#000080"
+#define COLOR_PINK "#FFC0CB"
+#define COLOR_MAGENTA "#FF00FF"
+#define COLOR_PURPLE "#800080"
+#define COLOR_ORANGE "#FF9900"
+#define COLOR_BEIGE "#CEB689"
+#define COLOR_BLUE_GRAY "#75A2BB"
+#define COLOR_BROWN "#BA9F6D"
+#define COLOR_DARK_BROWN "#997C4F"
+#define COLOR_DARK_ORANGE "#C3630C"
+#define COLOR_GREEN_GRAY "#99BB76"
+#define COLOR_RED_GRAY "#B4696A"
+#define COLOR_PALE_BLUE_GRAY "#98C5DF"
+#define COLOR_PALE_GREEN_GRAY "#B7D993"
+#define COLOR_PALE_ORANGE "#FFC066"
+#define COLOR_PALE_RED_GRAY "#D59998"
+#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
+#define COLOR_PURPLE_GRAY "#AE8CA8"
-//Color defines used by the assembly detailer.
-#define COLOR_ASSEMBLY_BLACK "#545454"
-#define COLOR_ASSEMBLY_BGRAY "#9497AB"
-#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
-#define COLOR_ASSEMBLY_RED "#CC4242"
-#define COLOR_ASSEMBLY_ORANGE "#E39751"
-#define COLOR_ASSEMBLY_BEIGE "#AF9366"
-#define COLOR_ASSEMBLY_BROWN "#97670E"
-#define COLOR_ASSEMBLY_GOLD "#AA9100"
-#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
-#define COLOR_ASSEMBLY_GURKHA "#999875"
-#define COLOR_ASSEMBLY_LGREEN "#789876"
-#define COLOR_ASSEMBLY_GREEN "#44843C"
-#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
-#define COLOR_ASSEMBLY_BLUE "#38559E"
-#define COLOR_ASSEMBLY_PURPLE "#6F6192"
-#define COLOR_ASSEMBLY_PINK "#ff4adc"
+// Color defines used by the assembly detailer.
+#define COLOR_ASSEMBLY_BLACK "#545454"
+#define COLOR_ASSEMBLY_BGRAY "#9497AB"
+#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
+#define COLOR_ASSEMBLY_RED "#CC4242"
+#define COLOR_ASSEMBLY_ORANGE "#E39751"
+#define COLOR_ASSEMBLY_BEIGE "#AF9366"
+#define COLOR_ASSEMBLY_BROWN "#97670E"
+#define COLOR_ASSEMBLY_GOLD "#AA9100"
+#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
+#define COLOR_ASSEMBLY_GURKHA "#999875"
+#define COLOR_ASSEMBLY_LGREEN "#789876"
+#define COLOR_ASSEMBLY_GREEN "#44843C"
+#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
+#define COLOR_ASSEMBLY_BLUE "#38559E"
+#define COLOR_ASSEMBLY_PURPLE "#6F6192"
+#define COLOR_ASSEMBLY_PINK "#ff4adc"
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index cf669b905a..7b214df421 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -85,7 +85,7 @@
#define COMSIG_ATOM_EMP_ACT "atom_emp_act"
///from base of atom/fire_act(): (exposed_temperature, exposed_volume)
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act"
-///from base of atom/bullet_act(): (/obj/projectile, def_zone)
+///from base of atom/bullet_act(): (/obj/item/projectile, def_zone)
#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act"
///from base of atom/blob_act(): (/obj/structure/blob)
#define COMSIG_ATOM_BLOB_ACT "atom_blob_act"
@@ -381,6 +381,8 @@
#define COMSIG_MINE_TRIGGERED "minegoboom" ///from [/obj/effect/mine/proc/triggermine]:
// Uncovered information
#define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1
+///from [/obj/structure/closet/supplypod/proc/endlaunch]:
+#define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom"
// /obj/item/grenade signals
#define COMSIG_GRENADE_PRIME "grenade_prime" //called in /obj/item/gun/process_fire (user, target, params, zone_override)
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 66f741b2c7..21b66f5e37 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
-#define istransparentturf(A) (istype(A, /turf/open/transparent))
+#define istransparentturf(A) (istype(A, /turf/open/transparent)||istype(A, /turf/open/space/transparent))
//Mobs
#define isliving(A) (istype(A, /mob/living))
@@ -235,3 +235,5 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))
#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs))
+
+#define isProbablyWallMounted(O) (O.pixel_x > 20 || O.pixel_x < -20 || O.pixel_y > 20 || O.pixel_y < -20)
diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm
index 9188efacfd..8ab33689d3 100644
--- a/code/__DEFINES/layers_planes.dm
+++ b/code/__DEFINES/layers_planes.dm
@@ -37,7 +37,9 @@
#define FIELD_OF_VISION_VISUAL_RENDER_TARGET "FIELD_OF_VISION_VISUAL_PLANE"
#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV.
-#define CHAT_LAYER 12.1 //Legacy, it doesn't matter that much because we are displayed above the game plane anyway.
+
+#define CHAT_LAYER 12.0001 // Do not insert layers between these two values
+#define CHAT_LAYER_MAX 12.9999
#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
#define BLACKNESS_PLANE_RENDER_TARGET "BLACKNESS_PLANE"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 586fce3e0c..d39b8641ba 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -1,17 +1,17 @@
/*ALL MOB-RELATED DEFINES THAT DON'T BELONG IN ANOTHER FILE GO HERE*/
-//Misc mob defines
+// Misc mob defines
-//Ready states at roundstart for mob/dead/new_player
+// 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
+// movement intent defines for the m_intent var
#define MOVE_INTENT_WALK "walk"
#define MOVE_INTENT_RUN "run"
-//Blood levels
+// Blood levels
#define BLOOD_VOLUME_MAX_LETHAL 2150
#define BLOOD_VOLUME_EXCESS 2100
#define BLOOD_VOLUME_MAXIMUM 2000
@@ -22,34 +22,34 @@
#define BLOOD_VOLUME_BAD 224
#define BLOOD_VOLUME_SURVIVE 122
-//Sizes of mobs, used by mob/living/var/mob_size
+// Sizes of mobs, used by mob/living/var/mob_size
#define MOB_SIZE_TINY 0
#define MOB_SIZE_SMALL 1
#define MOB_SIZE_HUMAN 2
#define MOB_SIZE_LARGE 3
-//Ventcrawling defines
+// Ventcrawling defines
#define VENTCRAWLER_NONE 0
#define VENTCRAWLER_NUDE 1
#define VENTCRAWLER_ALWAYS 2
-//Bloodcrawling defines
+// Bloodcrawling defines
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
-//Mob bio-types flags
-#define MOB_ORGANIC (1 << 0)
+// Mob bio-types flags
+#define MOB_ORGANIC (1 << 0)
#define MOB_MINERAL (1 << 1)
-#define MOB_ROBOTIC (1 << 2)
+#define MOB_ROBOTIC (1 << 2)
#define MOB_UNDEAD (1 << 3)
-#define MOB_HUMANOID (1 << 4)
-#define MOB_BUG (1 << 5)
+#define MOB_HUMANOID (1 << 4)
+#define MOB_BUG (1 << 5)
#define MOB_BEAST (1 << 6)
-#define MOB_EPIC (1 << 7) //megafauna
+#define MOB_EPIC (1 << 7) // Megafauna
#define MOB_REPTILE (1 << 8)
#define MOB_SPIRIT (1 << 9)
-//Organ defines for carbon mobs
+// Organ defines for carbon mobs
#define ORGAN_ORGANIC 1
#define ORGAN_ROBOTIC 2
@@ -66,194 +66,194 @@
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
#define MONKEY_BODYPART "monkey"
-#define ALIEN_BODYPART "alien"
-#define LARVA_BODYPART "larva"
-#define DEVIL_BODYPART "devil"
+#define ALIEN_BODYPART "alien"
+#define LARVA_BODYPART "larva"
+#define DEVIL_BODYPART "devil"
/*see __DEFINES/inventory.dm for bodypart bitflag defines*/
// Health/damage defines for carbon mobs
#define HUMAN_MAX_OXYLOSS 3
#define HUMAN_CRIT_MAX_OXYLOSS (SSmobs.wait/30)
-#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
-#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
-#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
+#define HEAT_DAMAGE_LEVEL_1 2 // Amount of damage applied when your body temperature just passes the 360.15k safety point
+#define HEAT_DAMAGE_LEVEL_2 3 // Amount of damage applied when your body temperature passes the 400K point
+#define HEAT_DAMAGE_LEVEL_3 8 // Amount of damage applied when your body temperature passes the 460K point and you are on fire
-#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
-#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
-#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point
+#define COLD_DAMAGE_LEVEL_1 0.5 // Amount of damage applied when your body temperature just passes the 260.15k safety point
+#define COLD_DAMAGE_LEVEL_2 1.5 // Amount of damage applied when your body temperature passes the 200K point
+#define COLD_DAMAGE_LEVEL_3 3 // Amount of damage applied when your body temperature passes the 120K point
-//Note that gas heat damage is only applied once every FOUR ticks.
-#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point
-#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point
-#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point
+// Note that gas heat damage is only applied once every FOUR ticks.
+#define HEAT_GAS_DAMAGE_LEVEL_1 2 // Amount of damage applied when the current breath's temperature just passes the 360.15k safety point
+#define HEAT_GAS_DAMAGE_LEVEL_2 4 // Amount of damage applied when the current breath's temperature passes the 400K point
+#define HEAT_GAS_DAMAGE_LEVEL_3 8 // Amount of damage applied when the current breath's temperature passes the 1000K point
-#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
-#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
-#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
+#define COLD_GAS_DAMAGE_LEVEL_1 0.5 // Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
+#define COLD_GAS_DAMAGE_LEVEL_2 1.5 // Amount of damage applied when the current breath's temperature passes the 200K point
+#define COLD_GAS_DAMAGE_LEVEL_3 3 // Amount of damage applied when the current breath's temperature passes the 120K point
-//Brain Damage defines
-#define BRAIN_DAMAGE_MILD 20
+// Brain Damage defines
+#define BRAIN_DAMAGE_MILD 20
#define BRAIN_DAMAGE_SEVERE 100
-#define BRAIN_DAMAGE_DEATH 200
+#define BRAIN_DAMAGE_DEATH 200
#define BRAIN_TRAUMA_MILD /datum/brain_trauma/mild
#define BRAIN_TRAUMA_SEVERE /datum/brain_trauma/severe
#define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special
#define BRAIN_TRAUMA_MAGIC /datum/brain_trauma/magic
-#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
-#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
-#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
-#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
-#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
-#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
+#define TRAUMA_RESILIENCE_BASIC 1 // Curable with chems
+#define TRAUMA_RESILIENCE_SURGERY 2 // Curable with brain surgery
+#define TRAUMA_RESILIENCE_LOBOTOMY 3 // Curable with lobotomy
+#define TRAUMA_RESILIENCE_WOUND 4 // Curable by healing the head wound
+#define TRAUMA_RESILIENCE_MAGIC 5 // Curable only with magic
+#define TRAUMA_RESILIENCE_ABSOLUTE 6 // This is here to stay
-//Limit of traumas for each resilience tier
-#define TRAUMA_LIMIT_BASIC 3
-#define TRAUMA_LIMIT_SURGERY 2
-#define TRAUMA_LIMIT_WOUND 2
+// Limit of traumas for each resilience tier
+#define TRAUMA_LIMIT_BASIC 3
+#define TRAUMA_LIMIT_SURGERY 2
+#define TRAUMA_LIMIT_WOUND 2
#define TRAUMA_LIMIT_LOBOTOMY 3
-#define TRAUMA_LIMIT_MAGIC 3
+#define TRAUMA_LIMIT_MAGIC 3
#define TRAUMA_LIMIT_ABSOLUTE INFINITY
#define BRAIN_DAMAGE_INTEGRITY_MULTIPLIER 0.5
-//Surgery Defines
+// Surgery Defines
#define BIOWARE_GENERIC "generic"
#define BIOWARE_NERVES "nerves"
#define BIOWARE_CIRCULATION "circulation"
#define BIOWARE_LIGAMENTS "ligaments"
-//Health hud screws for carbon mobs
-#define SCREWYHUD_NONE 0
-#define SCREWYHUD_CRIT 1
-#define SCREWYHUD_DEAD 2
+// Health hud screws for carbon mobs
+#define SCREWYHUD_NONE 0
+#define SCREWYHUD_CRIT 1
+#define SCREWYHUD_DEAD 2
#define SCREWYHUD_HEALTHY 3
-//Threshold levels for beauty for humans
+// Threshold levels for beauty for humans
#define BEAUTY_LEVEL_HORRID -66
-#define BEAUTY_LEVEL_BAD -33
-#define BEAUTY_LEVEL_DECENT 33
-#define BEAUTY_LEVEL_GOOD 66
-#define BEAUTY_LEVEL_GREAT 100
+#define BEAUTY_LEVEL_BAD -33
+#define BEAUTY_LEVEL_DECENT 33
+#define BEAUTY_LEVEL_GOOD 66
+#define BEAUTY_LEVEL_GREAT 100
-//Moods levels for humans
-#define MOOD_LEVEL_HAPPY4 15
-#define MOOD_LEVEL_HAPPY3 10
-#define MOOD_LEVEL_HAPPY2 6
-#define MOOD_LEVEL_HAPPY1 2
-#define MOOD_LEVEL_NEUTRAL 0
-#define MOOD_LEVEL_SAD1 -3
-#define MOOD_LEVEL_SAD2 -12
-#define MOOD_LEVEL_SAD3 -18
-#define MOOD_LEVEL_SAD4 -25
+// Moods levels for humans
+#define MOOD_LEVEL_HAPPY4 15
+#define MOOD_LEVEL_HAPPY3 10
+#define MOOD_LEVEL_HAPPY2 6
+#define MOOD_LEVEL_HAPPY1 2
+#define MOOD_LEVEL_NEUTRAL 0
+#define MOOD_LEVEL_SAD1 -3
+#define MOOD_LEVEL_SAD2 -12
+#define MOOD_LEVEL_SAD3 -18
+#define MOOD_LEVEL_SAD4 -25
-//Sanity levels for humans
-#define SANITY_AMAZING 150
-#define SANITY_GREAT 125
-#define SANITY_NEUTRAL 100
+// Sanity levels for humans
+#define SANITY_AMAZING 150
+#define SANITY_GREAT 125
+#define SANITY_NEUTRAL 100
#define SANITY_DISTURBED 75
-#define SANITY_UNSTABLE 50
-#define SANITY_CRAZY 25
-#define SANITY_INSANE 0
+#define SANITY_UNSTABLE 50
+#define SANITY_CRAZY 25
+#define SANITY_INSANE 0
-//Nutrition levels for humans
-#define NUTRITION_LEVEL_FAT 600
-#define NUTRITION_LEVEL_FULL 550
+// Nutrition levels for humans
+#define NUTRITION_LEVEL_FAT 600
+#define NUTRITION_LEVEL_FULL 550
#define NUTRITION_LEVEL_WELL_FED 450
-#define NUTRITION_LEVEL_FED 350
-#define NUTRITION_LEVEL_HUNGRY 250
+#define NUTRITION_LEVEL_FED 350
+#define NUTRITION_LEVEL_HUNGRY 250
#define NUTRITION_LEVEL_STARVING 150
#define NUTRITION_LEVEL_START_MIN 250
#define NUTRITION_LEVEL_START_MAX 400
-//Disgust levels for humans
-#define DISGUST_LEVEL_MAXEDOUT 150
-#define DISGUST_LEVEL_DISGUSTED 75
-#define DISGUST_LEVEL_VERYGROSS 50
-#define DISGUST_LEVEL_GROSS 25
+// Disgust levels for humans
+#define DISGUST_LEVEL_MAXEDOUT 150
+#define DISGUST_LEVEL_DISGUSTED 75
+#define DISGUST_LEVEL_VERYGROSS 50
+#define DISGUST_LEVEL_GROSS 25
-//Charge levels for Ethereals
-#define ETHEREAL_CHARGE_NONE 0
-#define ETHEREAL_CHARGE_LOWPOWER 20
-#define ETHEREAL_CHARGE_NORMAL 50
+// Charge levels for Ethereals
+#define ETHEREAL_CHARGE_NONE 0
+#define ETHEREAL_CHARGE_LOWPOWER 20
+#define ETHEREAL_CHARGE_NORMAL 50
#define ETHEREAL_CHARGE_ALMOSTFULL 75
-#define ETHEREAL_CHARGE_FULL 100
-#define ETHEREAL_CHARGE_OVERLOAD 125
+#define ETHEREAL_CHARGE_FULL 100
+#define ETHEREAL_CHARGE_OVERLOAD 125
#define ETHEREAL_CHARGE_DANGEROUS 150
-//Slime evolution threshold. Controls how fast slimes can split/grow
+// Slime evolution threshold. Controls how fast slimes can split/grow
#define SLIME_EVOLUTION_THRESHOLD 10
-//Slime extract crossing. Controls how many extracts is required to feed to a slime to core-cross.
+// Slime extract crossing. Controls how many extracts is required to feed to a slime to core-cross.
#define SLIME_EXTRACT_CROSSING_REQUIRED 10
-//Slime commands defines
-#define SLIME_FRIENDSHIP_FOLLOW 3 //Min friendship to order it to follow
-#define SLIME_FRIENDSHIP_STOPEAT 5 //Min friendship to order it to stop eating someone
-#define SLIME_FRIENDSHIP_STOPEAT_NOANGRY 7 //Min friendship to order it to stop eating someone without it losing friendship
-#define SLIME_FRIENDSHIP_STOPCHASE 4 //Min friendship to order it to stop chasing someone (their target)
-#define SLIME_FRIENDSHIP_STOPCHASE_NOANGRY 6 //Min friendship to order it to stop chasing someone (their target) without it losing friendship
-#define SLIME_FRIENDSHIP_STAY 3 //Min friendship to order it to stay
-#define SLIME_FRIENDSHIP_ATTACK 8 //Min friendship to order it to attack
+// Slime commands defines
+#define SLIME_FRIENDSHIP_FOLLOW 3 // Min friendship to order it to follow
+#define SLIME_FRIENDSHIP_STOPEAT 5 // Min friendship to order it to stop eating someone
+#define SLIME_FRIENDSHIP_STOPEAT_NOANGRY 7 // Min friendship to order it to stop eating someone without it losing friendship
+#define SLIME_FRIENDSHIP_STOPCHASE 4 // Min friendship to order it to stop chasing someone (their target)
+#define SLIME_FRIENDSHIP_STOPCHASE_NOANGRY 6 // Min friendship to order it to stop chasing someone (their target) without it losing friendship
+#define SLIME_FRIENDSHIP_STAY 3 // Min friendship to order it to stay
+#define SLIME_FRIENDSHIP_ATTACK 8 // Min friendship to order it to attack
-//Sentience types, to prevent things like sentience potions from giving bosses sentience
-#define SENTIENCE_ORGANIC 1
+// Sentience types, to prevent things like sentience potions from giving bosses sentience
+#define SENTIENCE_ORGANIC 1
#define SENTIENCE_ARTIFICIAL 2
-// #define SENTIENCE_OTHER 3 unused
-#define SENTIENCE_MINEBOT 4
-#define SENTIENCE_BOSS 5
+//#define SENTIENCE_OTHER 3 // Unused
+#define SENTIENCE_MINEBOT 4
+#define SENTIENCE_BOSS 5
-//Mob AI Status
+// Mob AI Status
-//Hostile simple animals
-//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm
+// Hostile simple animals
+// If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm
#define AI_ON 1
#define AI_IDLE 2
#define AI_OFF 3
#define AI_Z_OFF 4
-//determines if a mob can smash through it
-#define ENVIRONMENT_SMASH_NONE 0
-#define ENVIRONMENT_SMASH_STRUCTURES (1<<0) //crates, lockers, ect
-#define ENVIRONMENT_SMASH_WALLS (1<<1) //walls
-#define ENVIRONMENT_SMASH_RWALLS (1<<2) //rwalls
+// determines if a mob can smash through it
+#define ENVIRONMENT_SMASH_NONE 0
+#define ENVIRONMENT_SMASH_STRUCTURES (1<<0) // crates, lockers, ect
+#define ENVIRONMENT_SMASH_WALLS (1<<1) // walls
+#define ENVIRONMENT_SMASH_RWALLS (1<<2) // rwalls
-#define NO_SLIP_WHEN_WALKING (1<<0)
-#define SLIDE (1<<1)
-#define GALOSHES_DONT_HELP (1<<2)
-#define FLYING_DOESNT_HELP (1<<3)
-#define SLIDE_ICE (1<<4)
-#define SLIP_WHEN_CRAWLING (1<<5) //clown planet ruin amongst others
-#define SLIP_WHEN_JOGGING (1<<6) //slips prevented by walking are also dodged if the mob is nor sprinting or fatigued... unless this flag is on.
+#define NO_SLIP_WHEN_WALKING (1<<0)
+#define SLIDE (1<<1)
+#define GALOSHES_DONT_HELP (1<<2)
+#define FLYING_DOESNT_HELP (1<<3)
+#define SLIDE_ICE (1<<4)
+#define SLIP_WHEN_CRAWLING (1<<5) // clown planet ruin amongst others
+#define SLIP_WHEN_JOGGING (1<<6) // slips prevented by walking are also dodged if the mob is nor sprinting or fatigued... unless this flag is on.
#define MAX_CHICKENS 50
-///Flags used by the flags parameter of electrocute act.
+// /Flags used by the flags parameter of electrocute act.
-///Makes it so that the shock doesn't take gloves into account.
-#define SHOCK_NOGLOVES (1 << 0)
-///Used when the shock is from a tesla bolt.
-#define SHOCK_TESLA (1 << 1)
-///Used when an illusion shocks something. Makes the shock deal stamina damage and not trigger certain secondary effects.
-#define SHOCK_ILLUSION (1 << 2)
-///The shock doesn't stun.
-#define SHOCK_NOSTUN (1 << 3)
+// /Makes it so that the shock doesn't take gloves into account.
+#define SHOCK_NOGLOVES (1 << 0)
+// /Used when the shock is from a tesla bolt.
+#define SHOCK_TESLA (1 << 1)
+// /Used when an illusion shocks something. Makes the shock deal stamina damage and not trigger certain secondary effects.
+#define SHOCK_ILLUSION (1 << 2)
+// /The shock doesn't stun.
+#define SHOCK_NOSTUN (1 << 3)
-#define INCORPOREAL_MOVE_BASIC 1
-#define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows
-#define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt
+#define INCORPOREAL_MOVE_BASIC 1
+#define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows
+#define INCORPOREAL_MOVE_JAUNT 3 // is blocked by holy water/salt
-//Secbot and ED209 judgement criteria bitflag values
+// Secbot and ED209 judgement criteria bitflag values
#define JUDGE_EMAGGED (1<<0)
#define JUDGE_IDCHECK (1<<1)
#define JUDGE_WEAPONCHECK (1<<2)
#define JUDGE_RECORDCHECK (1<<3)
-//ED209's ignore monkeys
+// ED209's ignore monkeys
#define JUDGE_IGNOREMONKEYS (1<<4)
#define MEGAFAUNA_DEFAULT_RECOVERY_TIME 5
@@ -262,45 +262,45 @@
// Offsets defines
-#define OFFSET_UNIFORM "uniform"
-#define OFFSET_ID "id"
-#define OFFSET_GLOVES "gloves"
-#define OFFSET_GLASSES "glasses"
-#define OFFSET_EARS "ears"
-#define OFFSET_SHOES "shoes"
-#define OFFSET_S_STORE "s_store"
-#define OFFSET_FACEMASK "mask"
-#define OFFSET_HEAD "head"
-#define OFFSET_EYES "eyes"
-#define OFFSET_LIPS "lips"
-#define OFFSET_BELT "belt"
-#define OFFSET_BACK "back"
-#define OFFSET_SUIT "suit"
-#define OFFSET_NECK "neck"
-#define OFFSET_HAIR "hair"
-#define OFFSET_FHAIR "fhair"
-#define OFFSET_MUTPARTS "mutantparts"
+#define OFFSET_UNIFORM "uniform"
+#define OFFSET_ID "id"
+#define OFFSET_GLOVES "gloves"
+#define OFFSET_GLASSES "glasses"
+#define OFFSET_EARS "ears"
+#define OFFSET_SHOES "shoes"
+#define OFFSET_S_STORE "s_store"
+#define OFFSET_FACEMASK "mask"
+#define OFFSET_HEAD "head"
+#define OFFSET_EYES "eyes"
+#define OFFSET_LIPS "lips"
+#define OFFSET_BELT "belt"
+#define OFFSET_BACK "back"
+#define OFFSET_SUIT "suit"
+#define OFFSET_NECK "neck"
+#define OFFSET_HAIR "hair"
+#define OFFSET_FHAIR "fhair"
+#define OFFSET_MUTPARTS "mutantparts"
-//MINOR TWEAKS/MISC
-#define AGE_MIN 18 //youngest a character can be //CITADEL EDIT - 17 --> 18
-#define AGE_MAX 85 //oldest a character can be
-#define WIZARD_AGE_MIN 30 //youngest a wizard can be
-#define APPRENTICE_AGE_MIN 29 //youngest an apprentice can be
-#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
-#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
-#define POCKET_STRIP_DELAY 40 //time taken (in deciseconds) to search somebody's pockets
-#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
+// MINOR TWEAKS/MISC
+#define AGE_MIN 18 // youngest a character can be // CITADEL EDIT - 17 --> 18
+#define AGE_MAX 85 // oldest a character can be
+#define WIZARD_AGE_MIN 30 // youngest a wizard can be
+#define APPRENTICE_AGE_MIN 29 // youngest an apprentice can be
+#define SHOES_SLOWDOWN 0 // How much shoes slow you down by default. Negative values speed you up
+#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
+#define POCKET_STRIP_DELAY 40 // time taken (in deciseconds) to search somebody's pockets
+#define DOOR_CRUSH_DAMAGE 15 // the amount of damage that airlocks deal when they crush you
-#define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases
-#define ETHEREAL_CHARGE_FACTOR 0.08 //factor at which ethereal's charge decreases
-#define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default.
+#define HUNGER_FACTOR 0.1 // factor at which mob nutrition decreases
+#define ETHEREAL_CHARGE_FACTOR 0.08 // factor at which ethereal's charge decreases
+#define REAGENTS_METABOLISM 0.4 // How many units of reagent are consumed per tick, by default.
#define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism
// Roundstart trait system
-#define MAX_QUIRKS 6 //The maximum amount of quirks one character can have at roundstart
+#define MAX_QUIRKS 6 // The maximum amount of quirks one character can have at roundstart
-#define MAX_REVIVE_FIRE_DAMAGE 180
+#define MAX_REVIVE_FIRE_DAMAGE 180
#define MAX_REVIVE_BRUTE_DAMAGE 180
// AI Toggles
@@ -308,28 +308,28 @@
#define AI_VOX // Comment out if you don't want VOX to be enabled and have players download the voice sounds.
// /obj/item/bodypart on_mob_life() retval flag
-#define BODYPART_LIFE_UPDATE_HEALTH (1<<0)
+#define BODYPART_LIFE_UPDATE_HEALTH (1<<0)
#define HUMAN_FIRE_STACK_ICON_NUM 3
#define TYPING_INDICATOR_TIMEOUT 20 MINUTES
-#define GRAB_PIXEL_SHIFT_PASSIVE 6
-#define GRAB_PIXEL_SHIFT_AGGRESSIVE 12
-#define GRAB_PIXEL_SHIFT_NECK 16
+#define GRAB_PIXEL_SHIFT_PASSIVE 6
+#define GRAB_PIXEL_SHIFT_AGGRESSIVE 12
+#define GRAB_PIXEL_SHIFT_NECK 16
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)
-/// Field of vision defines.
+// / Field of vision defines.
#define FOV_90_DEGREES 90
#define FOV_180_DEGREES 180
#define FOV_270_DEGREES 270
-/// How far away you can be to make eye contact with someone while examining
+// / How far away you can be to make eye contact with someone while examining
#define EYE_CONTACT_RANGE 5
-/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
+// / If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
#define EXAMINE_MORE_TIME 1 SECONDS
-#define SILENCE_RANGED_MESSAGE (1<<0)
+#define SILENCE_RANGED_MESSAGE (1<<0)
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 84eed5483a..aef77e7b57 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -40,6 +40,16 @@
#define PARALLAX_LOW 2
#define PARALLAX_DISABLE 3 //this option must be the highest number
+#define PIXEL_SCALING_AUTO 0
+#define PIXEL_SCALING_1X 1
+#define PIXEL_SCALING_1_2X 1.5
+#define PIXEL_SCALING_2X 2
+#define PIXEL_SCALING_3X 3
+
+#define SCALING_METHOD_NORMAL "normal"
+#define SCALING_METHOD_DISTORT "distort"
+#define SCALING_METHOD_BLUR "blur"
+
#define PARALLAX_DELAY_DEFAULT world.tick_lag
#define PARALLAX_DELAY_MED 1
#define PARALLAX_DELAY_LOW 2
diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm
index 80983b34be..a188bf8363 100644
--- a/code/__DEFINES/shuttles.dm
+++ b/code/__DEFINES/shuttles.dm
@@ -31,6 +31,11 @@
#define EARLY_LAUNCHED 2
#define ENDGAME_TRANSIT 3
+//positive value = cannot puchase
+#define SHUTTLEPURCHASE_PURCHASABLE 0 //station can buy a shuttle
+#define SHUTTLEPURCHASE_PURCHASED 1 //station has already bought a shuttle, so cannot
+#define SHUTTLEPURCHASE_FORCED 2 //station was given a new shuttle through events or other shenanigans
+
// Ripples, effects that signal a shuttle's arrival
#define SHUTTLE_RIPPLE_TIME 100
diff --git a/code/__DEFINES/species.dm b/code/__DEFINES/species.dm
new file mode 100644
index 0000000000..c6cc6a5037
--- /dev/null
+++ b/code/__DEFINES/species.dm
@@ -0,0 +1,50 @@
+
+// Species ID Defines ---------------------------
+
+#define SPECIES_ABDUCTOR "abductor"
+#define SPECIES_ANDROID "android"
+#define SPECIES_ANGEL "angel"
+#define SPECIES_MAMMAL "mammal"
+#define SPECIES_INSECT "insect"
+#define SPECIES_DULLAHAN "dullahan"
+#define SPECIES_DWARF "dwarf"
+#define SPECIES_ETHEREAL "ethereal"
+#define SPECIES_FELINID "felinid"
+#define SPECIES_FLY "fly"
+#define SPECIES_GOLEM "golem"
+#define SPECIES_HUMAN "human"
+#define SPECIES_IPC "ipc"
+#define SPECIES_JELLY "jelly"
+ #define SPECIES_SLIME "slime"
+ #define SPECIES_SLIME_HYBRID "slimeperson"
+ #define SPECIES_SLIME_LUMI "slimelumi"
+ #define SPECIES_STARGAZER "stargazer"
+#define SPECIES_LIZARD "lizard"
+ #define SPECIES_ASHWALKER "ashlizard"
+#define SPECIES_MUSHROOM "mush"
+#define SPECIES_PLASMAMAN "plasmaman"
+#define SPECIES_POD "pod"
+ #define SPECIES_POD_WEAK "podweak"
+#define SPECIES_SHADOW "shadow"
+ #define SPECIES_NIGHTMARE "nightmare"
+#define SPECIES_SKELETON "skeleton"
+ #define SPECIES_SKELETON_SPACE "spaceskeleton"
+#define SPECIES_SYNTH_LIZARD "synthliz"
+#define SPECIES_SYNTH "synth"
+ #define SPECIES_SYNTH_MIL "military_synth"
+#define SPECIES_VAMPIRE "vampire"
+#define SPECIES_XENOHYBRID "xeno"
+
+// Species Category Defines ---------------------
+
+#define SPECIES_CATEGORY_ALIEN "alien"
+#define SPECIES_CATEGORY_BASIC "human"
+#define SPECIES_CATEGORY_FURRY "furry" // Weird Category, but okay.
+#define SPECIES_CATEGORY_GOLEM "golem"
+#define SPECIES_CATEGORY_INSECT "insect"
+#define SPECIES_CATEGORY_PLANT "plant"
+#define SPECIES_CATEGORY_ROBOT "robotic"
+#define SPECIES_CATEGORY_JELLY "jelly"
+#define SPECIES_CATEGORY_SHADOW "shadow"
+#define SPECIES_CATEGORY_SKELETON "skeleton"
+#define SPECIES_CATEGORY_UNDEAD "undead"
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 9deddd4b46..b405db83b0 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -124,6 +124,7 @@
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
#define FIRE_PRIORITY_STATPANEL 390
#define FIRE_PRIORITY_CHAT 400
+#define FIRE_PRIORITY_RUNECHAT 410
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 441926e75a..520f205381 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -164,6 +164,7 @@
#define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events
#define TRAIT_PUGILIST "pugilist" //This guy punches people for a living
#define TRAIT_KI_VAMPIRE "ki-vampire" //when someone with this trait rolls maximum damage on a punch and stuns the target, they regain some stamina and do clone damage
+#define TRAIT_MAULER "mauler" // this guy punches the shit out of people to hurt them, not to drain their stamina
#define TRAIT_PASSTABLE "passtable"
#define TRAIT_GIANT "giant"
#define TRAIT_DWARF "dwarf"
@@ -223,6 +224,8 @@
#define TRAIT_MOBILITY_NOPICKUP "mobility_nopickup"
/// Disallow item use
#define TRAIT_MOBILITY_NOUSE "mobility_nouse"
+///Disallow resting/unresting
+#define TRAIT_MOBILITY_NOREST "mobility_norest"
#define TRAIT_SWIMMING "swimming" //only applied by /datum/element/swimming, for checking
@@ -315,6 +318,7 @@
#define CLOWNOP_TRAIT "clown-op"
#define MEGAFAUNA_TRAIT "megafauna"
#define DEATHSQUAD_TRAIT "deathsquad"
+#define SLIMEPUDDLE_TRAIT "slimepuddle"
/// This trait is added by the active directional block system.
#define ACTIVE_BLOCK_TRAIT "active_block"
/// This trait is added by the parry system.
diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm
index 30d40f3867..c65cd80394 100644
--- a/code/__HELPERS/do_after.dm
+++ b/code/__HELPERS/do_after.dm
@@ -38,11 +38,11 @@
return FALSE
if((do_after_flags & DO_AFTER_REQUIRES_USER_ON_TURF) && !isturf(user.loc))
return FALSE
+ if(!(do_after_flags & DO_AFTER_NO_COEFFICIENT) && living_user)
+ delay *= living_user.cached_multiplicative_actions_slowdown
var/starttime = world.time
var/endtime = world.time + delay
var/obj/item/initially_held_item = mob_redirect?.get_active_held_item()
- if(!(do_after_flags & DO_AFTER_NO_COEFFICIENT) && living_user)
- delay *= living_user.do_after_coefficent()
var/atom/movable/AM_user = ismovable(user) && user
var/drifting = AM_user?.Process_Spacemove(NONE) && AM_user.inertia_dir
var/initial_dx = targetturf.x - userturf.x
@@ -245,7 +245,7 @@
if(holding)
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
- delay *= user.do_after_coefficent()
+ delay *= user.cached_multiplicative_actions_slowdown
var/datum/progressbar/progbar
if (progress)
@@ -300,10 +300,6 @@
LAZYREMOVE(user.do_afters, target)
LAZYREMOVE(target.targeted_by, user)
-/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
- . = 1
- return
-
/proc/do_after_mob(mob/user, var/list/targets, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks)
if(!user || !targets)
return 0
@@ -326,6 +322,8 @@
if(progress)
progbar = new(user, time, targets[1])
+ time *= user.cached_multiplicative_actions_slowdown
+
var/endtime = world.time + time
var/starttime = world.time
. = 1
diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm
index 1570eededb..d527d0ac51 100644
--- a/code/__HELPERS/radiation.dm
+++ b/code/__HELPERS/radiation.dm
@@ -12,15 +12,17 @@
))
var/list/processing_list = list(location)
. = list()
- while(processing_list.len)
- var/atom/thing = processing_list[1]
- processing_list -= thing
+ var/i = 0
+ var/lim = 1
+ while(i < lim)
+ var/atom/thing = processing_list[++i]
if(ignored_things[thing.type])
continue
. += thing
if((thing.rad_flags & RAD_PROTECT_CONTENTS) || (SEND_SIGNAL(thing, COMSIG_ATOM_RAD_PROBE) & COMPONENT_BLOCK_RADIATION))
continue
processing_list += thing.contents
+ lim = processing_list.len
/proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE)
if(!SSradiation.can_fire)
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 92bd726641..794a495ae3 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -457,21 +457,23 @@ Turf and target are separate in case you want to teleport some distance from a t
/atom/proc/GetAllContents(var/T)
var/list/processing_list = list(src)
+ var/i = 0
+ var/lim = 1
if(T)
. = list()
- var/i = 0
- while(i < length(processing_list))
+ while(i < lim)
var/atom/A = processing_list[++i]
//Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
//This is also why we don't need to check against assembled as we go along
processing_list += A.contents
+ lim = processing_list.len
if(istype(A,T))
. += A
else
- var/i = 0
- while(i < length(processing_list))
+ while(i < lim)
var/atom/A = processing_list[++i]
processing_list += A.contents
+ lim = processing_list.len
return processing_list
/atom/proc/GetAllContentsIgnoring(list/ignore_typecache)
@@ -480,10 +482,12 @@ Turf and target are separate in case you want to teleport some distance from a t
var/list/processing = list(src)
. = list()
var/i = 0
- while(i < length(processing))
+ var/lim = 1
+ while(i < lim)
var/atom/A = processing[++i]
if(!ignore_typecache[A.type])
processing += A.contents
+ lim = processing.len
. += A
diff --git a/code/__HELPERS/view.dm b/code/__HELPERS/view.dm
index 48e68be20f..1c92971802 100644
--- a/code/__HELPERS/view.dm
+++ b/code/__HELPERS/view.dm
@@ -2,7 +2,7 @@
var/viewX
var/viewY
if(isnum(view))
- var/totalviewrange = 1 + 2 * view
+ var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view
viewX = totalviewrange
viewY = totalviewrange
else
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 44973327f0..a327b7fcde 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -267,24 +267,60 @@ GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARC
GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt"))
+//LANGUAGE CHARACTER CUSTOMIZATION
GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles"))
-
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc))
+//SPECIES BODYPART LISTS
//locked parts are those that your picked species requires to have
//unlocked parts are those that anyone can choose on customisation regardless
//parts not in unlocked, but in all, are thus locked
GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "body_markings" = "Body Markings", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns"))
GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff"))
+
//parts in either of the above two lists that require a second option that allows them to be coloured
GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color"))
//body ids that have greyscale sprites
-GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","lum","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic"))
+GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","slimelumi","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic"))
//body ids that have prosthetic sprites
GLOBAL_LIST_INIT(prosthetic_limb_types, list("xion","bishop","cybersolutions","grayson","hephaestus","nanotrasen","talon"))
+//FAMILY HEIRLOOM LIST
+//this works by using the first number for the species as a probability to choose one of the items in the following list for their family heirloom
+//if the probability fails, or the species simply isn't in the list, then it defaults to the next global list, which has its own list of items for each job
+//the first item in the list is for if your job isn't in that list
+
+//species-heirloom list (we categorise them by the species id var)
+GLOBAL_LIST_INIT(species_heirlooms, list(
+ "dwarf" = list(25, list(/obj/item/reagent_containers/food/drinks/dwarf_mug)), //example: 25% chance for dwarves to get a dwarf mug as their heirloom (normal container but has manly dorf icon)
+ "insect" = list(25, list(/obj/item/flashlight/lantern/heirloom_moth)),
+ "ipc" = list(25, list(/obj/item/stock_parts/cell/family)), //gives a broken powercell for flavor text!
+ "synthliz" = list(25, list(/obj/item/stock_parts/cell/family)), //they're also robots
+ "slimeperson" = list(25, list(/obj/item/toy/plush/slimeplushie)),
+ "lizard" = list(25, list(/obj/item/toy/plush/lizardplushie)),
+ ))
+
+//job-heirloom list
+GLOBAL_LIST_INIT(job_heirlooms, list(
+ "NO_JOB" = list(/obj/item/toy/cards/deck, /obj/item/lighter, /obj/item/dice/d20),
+ "Clown" = list(/obj/item/paint/anycolor, /obj/item/bikehorn/golden),
+ "Mime" = list(/obj/item/paint/anycolor, /obj/item/toy/dummy),
+ "Cook" = list(/obj/item/kitchen/knife/scimitar),
+ "Botanist" = list(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie),
+ "Medical Doctor" = list(/obj/item/healthanalyzer),
+ "Paramedic" = list(/obj/item/lighter), //..why?
+ "Station Engineer" = list(/obj/item/wirecutters/brass/family, /obj/item/crowbar/brass/family, /obj/item/screwdriver/brass/family, /obj/item/wrench/brass/family), //brass tools but without the tool speed modifier
+ "Atmospheric Technician" = list(/obj/item/extinguisher/mini/family),
+ "Lawyer" = list(/obj/item/storage/briefcase/lawyer/family),
+ "Janitor" = list(/obj/item/mop),
+ "Scientist" = list(/obj/item/toy/plush/slimeplushie),
+ "Assistant" = list(/obj/item/clothing/gloves/cut/family),
+ "Chaplain" = list(/obj/item/camera/spooky/family),
+ "Head of Personnel" = list(/obj/item/pinpointer/ian)
+ ))
+
//body ids that have non-gendered bodyparts
GLOBAL_LIST_INIT(nongendered_limb_types, list("fly", "zombie" ,"synth", "shadow", "cultgolem", "agent", "plasmaman", "clockgolem", "clothgolem"))
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 706a5ed955..9abc37c7e4 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -43,5 +43,4 @@ GLOBAL_LIST_EMPTY(ai_status_displays)
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert
-//list of everyone playing rock paper scissors
-GLOBAL_LIST_EMPTY(rockpaperscissors_players)
+GLOBAL_LIST_EMPTY(rockpaperscissors_players) // List of everyone playing rock paper scissors
diff --git a/code/_onclick/hud/map_popups.dm b/code/_onclick/hud/map_popups.dm
index 777ebb0718..2ecfe80ab5 100644
--- a/code/_onclick/hud/map_popups.dm
+++ b/code/_onclick/hud/map_popups.dm
@@ -1,30 +1,11 @@
-/client
- /**
- * Assoc list with all the active maps - when a screen obj is added to
- * a map, it's put in here as well.
- *
- * Format: list(
- Reverse Drop-off Location:
- {data.dropoff_turf ? data.dropoff_turf : 'None'}
-
- [Enable Reverse Mode for this feature]
- "+e+"
"
dat += "HUD Button Flash Color: Change
"
+/* CITADEL EDIT - We're using top menu instead
+ button_name = pixel_size
+ dat += "Pixel Scaling: [(button_name) ? "Pixel Perfect [button_name]x" : "Stretch to fit"]
"
+
+ switch(scaling_method)
+ if(SCALING_METHOD_NORMAL)
+ button_name = "Nearest Neighbor"
+ if(SCALING_METHOD_DISTORT)
+ button_name = "Point Sampling"
+ if(SCALING_METHOD_BLUR)
+ button_name = "Bilinear"
+ dat += "Scaling Method: [button_name]
"
+*/
+
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
var/p_map = preferred_map
if (!p_map)
@@ -2239,7 +2260,32 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["has_womb"] = !features["has_womb"]
if("widescreenpref")
widescreenpref = !widescreenpref
- user.client.change_view(CONFIG_GET(string/default_view))
+ user.client.view_size.setDefault(getScreenSize(widescreenpref))
+
+ if("pixel_size")
+ switch(pixel_size)
+ if(PIXEL_SCALING_AUTO)
+ pixel_size = PIXEL_SCALING_1X
+ if(PIXEL_SCALING_1X)
+ pixel_size = PIXEL_SCALING_1_2X
+ if(PIXEL_SCALING_1_2X)
+ pixel_size = PIXEL_SCALING_2X
+ if(PIXEL_SCALING_2X)
+ pixel_size = PIXEL_SCALING_3X
+ if(PIXEL_SCALING_3X)
+ pixel_size = PIXEL_SCALING_AUTO
+ user.client.view_size.apply() //Let's winset() it so it actually works
+
+ if("scaling_method")
+ switch(scaling_method)
+ if(SCALING_METHOD_NORMAL)
+ scaling_method = SCALING_METHOD_DISTORT
+ if(SCALING_METHOD_DISTORT)
+ scaling_method = SCALING_METHOD_BLUR
+ if(SCALING_METHOD_BLUR)
+ scaling_method = SCALING_METHOD_NORMAL
+ user.client.view_size.setZoomMode()
+
if("autostand")
autostand = !autostand
if("auto_ooc")
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 7d4ad08e6a..ab30e48b67 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -280,6 +280,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["parallax"] >> parallax
S["ambientocclusion"] >> ambientocclusion
S["auto_fit_viewport"] >> auto_fit_viewport
+ S["widescreenpref"] >> widescreenpref
+ S["pixel_size"] >> pixel_size
+ S["scaling_method"] >> scaling_method
S["hud_toggle_flash"] >> hud_toggle_flash
S["hud_toggle_color"] >> hud_toggle_color
S["menuoptions"] >> menuoptions
@@ -297,7 +300,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["arousable"] >> arousable
S["screenshake"] >> screenshake
S["damagescreenshake"] >> damagescreenshake
- S["widescreenpref"] >> widescreenpref
S["autostand"] >> autostand
S["cit_toggles"] >> cit_toggles
S["preferred_chaos"] >> preferred_chaos
@@ -333,6 +335,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
+ widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
+ pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
+ scaling_method = sanitize_text(scaling_method, initial(scaling_method))
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
hud_toggle_color = sanitize_hexcolor(hud_toggle_color, 6, 1, initial(hud_toggle_color))
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
@@ -346,7 +351,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
- widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles))
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 2fbe738acb..ea01b0c0ed 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -45,13 +45,12 @@
var/dynamic_fhair_suffix = ""//mask > head for facial hair
//basically a restriction list.
- var/list/species_restricted = null
+ var/list/species_restricted
//Basically syntax is species_restricted = list("Species Name","Species Name")
//Add a "exclude" string to do the opposite, making it only only species listed that can't wear it.
//You append this to clothing objects
-
// How much clothing damage has been dealt to each of the limbs of the clothing, assuming it covers more than one limb
var/list/damage_by_parts
// How much integrity is in a specific limb before that limb is disabled (for use in [/obj/item/clothing/proc/take_damage_zone], and only if we cover multiple zones.) Set to 0 to disable shredding.
@@ -477,7 +476,6 @@ BLIND // can't see anything
return TRUE
-
/// If we're a clothing with at least 1 shredded/disabled zone, give the wearer a periodic heads up letting them know their clothes are damaged
/obj/item/clothing/proc/bristle(mob/living/L)
if(!istype(L))
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index b5d92fb780..f9f587ae5b 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -20,8 +20,14 @@
body_parts_covered = ARMS
cold_protection = ARMS
strip_delay = 300 //you can't just yank them off
+ /// did you ever get around to wearing these or no
+ var/wornonce = FALSE
///Extra damage through the punch.
var/enhancement = 0 //it's a +0 to your punches because it isn't magical
+ ///extra wound bonus through the punch (MAYBE DON'T BE GENEROUS WITH THIS)
+ var/wound_enhancement = 0
+ /// do we give the flavortext for wearing them
+ var/silent = FALSE
///Main trait added by the gloves to the user on wear.
var/inherited_trait = TRAIT_NOGUNS //what are you, dishonoroable?
///Secondary trait added by the gloves to the user on wear.
@@ -29,7 +35,18 @@
/obj/item/clothing/gloves/fingerless/pugilist/equipped(mob/user, slot)
. = ..()
- if(slot == SLOT_GLOVES)
+ if(current_equipped_slot == SLOT_GLOVES)
+ use_buffs(user, TRUE)
+ wornonce = TRUE
+
+/obj/item/clothing/gloves/fingerless/pugilist/dropped(mob/user)
+ . = ..()
+ if(wornonce)
+ use_buffs(user, FALSE)
+ wornonce = FALSE
+
+/obj/item/clothing/gloves/fingerless/pugilist/proc/use_buffs(mob/user, buff)
+ if(buff) // tarukaja
if(ishuman(user))
var/mob/living/carbon/human/H = user
ADD_TRAIT(H, TRAIT_PUGILIST, GLOVE_TRAIT)
@@ -37,17 +54,20 @@
ADD_TRAIT(H, secondary_trait, GLOVE_TRAIT)
H.dna.species.punchdamagehigh += enhancement
H.dna.species.punchdamagelow += enhancement
-
-/obj/item/clothing/gloves/fingerless/pugilist/dropped(mob/user)
-
- REMOVE_TRAIT(user, TRAIT_PUGILIST, GLOVE_TRAIT)
- REMOVE_TRAIT(user, inherited_trait, GLOVE_TRAIT)
- REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- H.dna.species.punchdamagehigh -= enhancement
- H.dna.species.punchdamagelow -= enhancement
- return ..()
+ H.dna.species.punchwoundbonus += wound_enhancement
+ if(!silent)
+ to_chat(H, "With [src] on your arms, you feel ready to punch things.")
+ else // dekaja
+ REMOVE_TRAIT(user, TRAIT_PUGILIST, GLOVE_TRAIT)
+ REMOVE_TRAIT(user, inherited_trait, GLOVE_TRAIT)
+ REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.dna.species.punchdamagehigh -= enhancement
+ H.dna.species.punchdamagelow -= enhancement
+ H.dna.species.punchwoundbonus -= wound_enhancement
+ if(!silent)
+ to_chat(user, "With [src] off of your arms, you feel less ready to punch things.")
/obj/item/clothing/gloves/fingerless/pugilist/chaplain
name = "armwraps of unyielding resolve"
@@ -93,6 +113,7 @@
icon_state = "rapid"
item_state = "rapid"
enhancement = 10 //omae wa mou shindeiru
+ wound_enhancement = 10
var/warcry = "AT"
secondary_trait = TRAIT_NOSOFTCRIT //basically extra health
diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm
index f4b4140a1a..eda36ea12f 100644
--- a/code/modules/clothing/gloves/tacklers.dm
+++ b/code/modules/clothing/gloves/tacklers.dm
@@ -65,12 +65,14 @@
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
+ strip_mod = 1.2 // because apparently black gloves had this
/obj/item/clothing/gloves/tackler/combat/insulated
name = "guerrilla gloves"
desc = "Superior quality combative gloves, good for performing tackle takedowns as well as absorbing electrical shocks."
siemens_coefficient = 0
permeability_coefficient = 0.05
+ strip_mod = 1.5 // and combat gloves had this??
/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator
name = "insidious guerrilla gloves"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 11df38cfdd..5dd35788f1 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -355,7 +355,7 @@
/obj/item/clothing/mask/paper/Initialize(mapload)
- .=..()
+ . = ..()
papermask_designs = list(
"Blank" = image(icon = src.icon, icon_state = "plainmask"),
"Neutral" = image(icon = src.icon, icon_state = "neutralmask"),
@@ -384,7 +384,7 @@
"Vertical" = "verticalmask", "Horizontal" = "horizontalmask", "X" ="xmask",
"Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask")
- var/choice = show_radial_menu(user,src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
+ var/choice = show_radial_menu(user, src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
diff --git a/code/modules/events/shuttle_catastrophe b/code/modules/events/shuttle_catastrophe
new file mode 100644
index 0000000000..d948b39d3b
--- /dev/null
+++ b/code/modules/events/shuttle_catastrophe
@@ -0,0 +1,37 @@
+/datum/round_event_control/shuttle_catastrophe
+ name = "Shuttle Catastrophe"
+ typepath = /datum/round_event/shuttle_catastrophe
+ weight = 10
+ max_occurrences = 1
+
+/datum/round_event_control/shuttle_catastrophe/canSpawnEvent(players, gamemode)
+ if(SSshuttle.emergency.name == "Build your own shuttle kit")
+ return FALSE //don't undo manual player engineering, it also would unload people and ghost them, there's just a lot of problems
+ return ..()
+
+
+/datum/round_event/shuttle_catastrophe
+ var/datum/map_template/shuttle/new_shuttle
+
+/datum/round_event/shuttle_catastrophe/announce(fake)
+ var/cause = pick("was attacked by [syndicate_name()] Operatives", "mysteriously teleported away", "had its refuelling crew mutiny",
+ "was found with its engines stolen", "\[REDACTED\]", "flew into the sunset, and melted", "learned something from a very wise cow, and left on its own",
+ "had cloning devices on it", "had its shuttle inspector put the shuttle in reverse instead of park, causing the shuttle to crash into the hangar")
+
+ priority_announce("Your emergency shuttle [cause]. Your replacement shuttle will be the [new_shuttle.name] until further notice.", "CentCom Spacecraft Engineering")
+
+/datum/round_event/shuttle_catastrophe/setup()
+ var/list/valid_shuttle_templates = list()
+ for(var/shuttle_id in SSmapping.shuttle_templates)
+ var/datum/map_template/shuttle/template = SSmapping.shuttle_templates[shuttle_id]
+ if(template.can_be_bought && template.credit_cost < INFINITY) //if we could get it from the communications console, it's cool for us to get it here
+ valid_shuttle_templates += template
+ new_shuttle = pick(valid_shuttle_templates)
+
+/datum/round_event/shuttle_catastrophe/start()
+ SSshuttle.shuttle_purchased = SHUTTLEPURCHASE_FORCED
+ SSshuttle.unload_preview()
+ SSshuttle.load_template(new_shuttle)
+ SSshuttle.existing_shuttle = SSshuttle.emergency
+ SSshuttle.action_load(new_shuttle)
+ log_shuttle("Shuttle Catastrophe set a new shuttle, [new_shuttle.name].")
diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm
index 031642c875..aae39e28a4 100644
--- a/code/modules/events/stray_cargo.dm
+++ b/code/modules/events/stray_cargo.dm
@@ -55,7 +55,7 @@
crate.update_icon()
var/obj/structure/closet/supplypod/pod = make_pod()
crate.forceMove(pod)
- new /obj/effect/abstract/DPtarget(LZ, pod)
+ new /obj/effect/pod_landingzone(LZ, pod)
///Handles the creation of the pod, in case it needs to be modified beforehand
/datum/round_event/stray_cargo/proc/make_pod()
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index a3ee8c5228..140923c1ef 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -618,3 +618,9 @@
icon_state = "monkey_energy"
list_reagents = list(/datum/reagent/consumable/monkey_energy = 50)
foodtype = SUGAR | JUNKFOOD
+
+/obj/item/reagent_containers/food/drinks/dwarf_mug //dwarf family heirloom (just a cup that always has the manly dorf icon!)
+ name = "ale mug"
+ desc = "An old stained mug used for filling with dwarven ale."
+ icon_state = "manlydorfglass"
+ isGlass = FALSE //it's a wooden mug!
diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm
index eea7cdb87d..38a68ad364 100644
--- a/code/modules/food_and_drinks/food/snacks_soup.dm
+++ b/code/modules/food_and_drinks/food/snacks_soup.dm
@@ -291,3 +291,12 @@
tastes = list("creamy peas"= 2, "parsnip" = 1)
filling_color = "#9dc530"
foodtype = VEGETABLES
+
+/obj/item/reagent_containers/food/snacks/soup/facehuggerpot
+ name = "pot of face hugger jambalaya"
+ desc = "An entire pot of an extremely spicy dish made using extremely exotic ingredients. Highly recommend by an interdimensional businessman."
+ icon_state = "facehuggerpot"
+ bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
+ list_reagents = list(/datum/reagent/consumable/nutriment = 10, /datum/reagent/consumable/nutriment/vitamin = 4)
+ tastes = list("face huggers" = 1)
+ foodtype = MEAT
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
index 6372137edc..c52218c913 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm
@@ -291,3 +291,18 @@
)
result = /obj/item/reagent_containers/food/snacks/soup/peasoup
subcategory = CAT_SOUP
+
+/datum/crafting_recipe/food/facehuggerjambalayapot
+ name = "Facehugger jambalaya"
+ reqs = list(
+ /datum/reagent/bluespace = 10,
+ /datum/reagent/consumable/ethanol/booger =10,
+ /obj/item/organ/heart= 3,
+ /obj/item/clothing/mask/facehugger = 1,
+ /obj/item/reagent_containers/food/snacks/egg = 1,
+ /datum/reagent/consumable/blackpepper = 5,
+ /datum/reagent/toxin/acid = 5
+
+ )
+ result = /obj/item/reagent_containers/food/snacks/soup/facehuggerpot
+ subcategory = CAT_SOUP
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index aa8a7b60c2..a1a177c028 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -42,6 +42,14 @@
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "hydrotray3"
+/obj/machinery/hydroponics/constructable/ComponentInitialize()
+ . = ..()
+ AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
+ AddComponent(/datum/component/plumbing/simple_demand)
+
+/obj/machinery/hydroponics/constructable/proc/can_be_rotated(mob/user, rotation_type)
+ return !anchored
+
/obj/machinery/hydroponics/constructable/RefreshParts()
var/tmp_capacity = 0
for (var/obj/item/stock_parts/matter_bin/M in component_parts)
diff --git a/code/modules/keybindings/keybind/movement.dm b/code/modules/keybindings/keybind/movement.dm
index 176e6b9fb8..cc5798710c 100644
--- a/code/modules/keybindings/keybind/movement.dm
+++ b/code/modules/keybindings/keybind/movement.dm
@@ -154,7 +154,7 @@
/datum/keybinding/living/toggle_sprint/down(client/user)
var/mob/living/L = user.mob
- L.default_toggle_sprint(TRUE)
+ L.default_toggle_sprint()
return TRUE
/datum/keybinding/mob/toggle_move_intent
diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm
index 193106c294..b681c348e0 100644
--- a/code/modules/mapping/ruins.dm
+++ b/code/modules/mapping/ruins.dm
@@ -135,7 +135,12 @@
//That's done remove from priority even if it failed
if(forced)
//TODO : handle forced ruins with multiple variants
+ // this might work?
forced_ruins -= current_pick
+ if(!current_pick.allow_duplicates)
+ for(var/datum/map_template/ruin/R in forced_ruins)
+ if(R.id == current_pick.id)
+ forced_ruins -= R
forced = FALSE
if(failed_to_place)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index e1d078c632..0c57c13e3f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -408,7 +408,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mind.current.key && mind.current.key[1] != "@") //makes sure we don't accidentally kick any clients
to_chat(usr, "Another consciousness is in your body...It is resisting you.")
return
- client.change_view(CONFIG_GET(string/default_view))
+ client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))//Let's reset so people can't become allseeing gods
transfer_ckey(mind.current, FALSE)
SStgui.on_transfer(src, mind.current) // Transfer NanoUIs.
mind.current.client.init_verbs()
@@ -568,15 +568,15 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc = "Change your view range."
var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
- if(client.view == CONFIG_GET(string/default_view))
+ if(client.view_size.getView() == client.view_size.default)
var/list/views = list()
for(var/i in 7 to max_view)
views |= i
- var/new_view = input("Choose your new view", "Modify view range", 7) as null|anything in views
+ var/new_view = input("Choose your new view", "Modify view range", 0) as null|anything in views
if(new_view)
- client.change_view(clamp(new_view, 7, max_view))
+ client.view_size.setTo(clamp(new_view, 7, max_view) - 7)
else
- client.change_view(CONFIG_GET(string/default_view))
+ client.view_size.resetToDefault()
/mob/dead/observer/verb/add_view_range(input as num)
set name = "Add View Range"
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 54a4f23fd4..26486f255a 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -988,30 +988,15 @@
O.held_index = r_arm_index_next //2, 4, 6, 8...
hand_bodyparts += O
-/mob/living/carbon/do_after_coefficent()
- . = ..()
- var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) //Currently, only carbons or higher use mood, move this once that changes.
- if(mood)
- switch(mood.sanity) //Alters do_after delay based on how sane you are
- if(SANITY_INSANE to SANITY_DISTURBED)
- . *= 1.25
- if(SANITY_NEUTRAL to SANITY_GREAT)
- . *= 0.90
-
- for(var/i in status_effects)
- var/datum/status_effect/S = i
- . *= S.interact_speed_modifier()
-
-
/mob/living/carbon/proc/create_internal_organs()
for(var/X in internal_organs)
var/obj/item/organ/I = X
I.Insert(src)
-/mob/living/carbon/proc/update_disabled_bodyparts()
+/mob/living/carbon/proc/update_disabled_bodyparts(silent = FALSE)
for(var/B in bodyparts)
var/obj/item/bodypart/BP = B
- BP.update_disabled()
+ BP.update_disabled(silent)
/mob/living/carbon/vv_get_dropdown()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 1e221e7385..1b7ab81d59 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -254,10 +254,10 @@
if(href_list["pockets"])
var/strip_mod = 1
var/strip_silence = FALSE
- var/obj/item/clothing/gloves/g = gloves
- if (istype(g))
- strip_mod = g.strip_mod
- strip_silence = g.strip_silence
+ var/obj/item/clothing/gloves/G = gloves
+ if(istype(G))
+ strip_mod = G.strip_mod
+ strip_silence = G.strip_silence
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? SLOT_R_STORE : SLOT_L_STORE)
var/obj/item/pocket_item = (pocket_id == SLOT_R_STORE ? r_store : l_store)
@@ -1045,7 +1045,8 @@
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
return
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
- var/health_deficiency = ((maxHealth) - health + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
+ var/scaling = maxHealth / 100
+ var/health_deficiency = ((maxHealth / scaling) - (health / scaling) + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
if(health_deficiency >= 40)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
@@ -1056,11 +1057,6 @@
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
-
-/mob/living/carbon/human/do_after_coefficent()
- . = ..()
- . *= physiology.do_after_speed
-
/mob/living/carbon/human/is_bleeding()
if(NOBLOOD in dna.species.species_traits || bleedsuppress)
return FALSE
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 509633c0d5..97c40c96d7 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -100,3 +100,8 @@
if(dna.species.space_move(src))
return TRUE
return ..()
+
+/mob/living/carbon/human/CanPass(atom/movable/mover, turf/target)
+ if(dna.species.species_pass_check())
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm
index fd0df0bde9..22c197f7de 100644
--- a/code/modules/mob/living/carbon/human/physiology.dm
+++ b/code/modules/mob/living/carbon/human/physiology.dm
@@ -23,8 +23,6 @@
var/hunger_mod = 1 //% of hunger rate taken per tick.
- var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations.
-
/// footstep type override for both shoeless and not footstep sounds.
var/footstep_type
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 77b13c0bc9..50a725f8cf 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -64,7 +64,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/stunmod = 1 // multiplier for stun duration
var/punchdamagelow = 1 //lowest possible punch damage. if this is set to 0, punches will always miss
var/punchdamagehigh = 10 //highest possible punch damage
- var/punchstunthreshold = 10//damage at which punches from this race will stun //yes it should be to the attacked race but it's not useful that way even if it's logical
+ var/punchstunthreshold = 10 //damage at which punches from this race will stun //yes it should be to the attacked race but it's not useful that way even if it's logical
+ var/punchwoundbonus = 0 // additional wound bonus. generally zero.
var/siemens_coeff = 1 //base electrocution coefficient
var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded?
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
@@ -106,7 +107,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
var/icon_limbs //Overrides the icon used for the limbs of this species. Mainly for downstream, and also because hardcoded icons disgust me. Implemented and maintained as a favor in return for a downstream's implementation of synths.
- var/species_type
+ var/species_category
var/tail_type //type of tail i.e. mam_tail
var/wagging_type //type of wagging i.e. waggingtail_lizard
@@ -591,9 +592,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else
var/left_state = DEFAULT_LEFT_EYE_STATE
var/right_state = DEFAULT_RIGHT_EYE_STATE
- message_admins("okay so our eye type is [eye_type] and we can index it to know [GLOB.eye_types[eye_type]]")
if(eye_type in GLOB.eye_types)
- message_admins("to know that it's in!")
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)
@@ -1389,6 +1388,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
user.do_attack_animation(target, ATTACK_EFFECT_PUNCH)
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
+ var/punchwoundbonus = user.dna.species.punchwoundbonus
var/puncherstam = user.getStaminaLoss()
var/puncherbrute = user.getBruteLoss()
var/punchedstam = target.getStaminaLoss()
@@ -1404,6 +1404,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//END OF CITADEL CHANGES
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
+ if(HAS_TRAIT(user, TRAIT_PUGILIST))
+ affecting = target.get_bodypart(check_zone(user.zone_selected)) // if you're going the based unarmed route you won't miss
if(!affecting) //Maybe the bodypart is missing? Or things just went wrong..
affecting = target.get_bodypart(BODY_ZONE_CHEST) //target chest instead, as failsafe. Or hugbox? You decide.
@@ -1415,8 +1417,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(user.dna.species.punchdamagelow)
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
miss_chance = 0
- else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance
- miss_chance = 10
+ else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists, being good at Punching People, also never miss
+ miss_chance = 0
else
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
@@ -1430,12 +1432,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = target.run_armor_check(affecting, "melee")
+ if(HAS_TRAIT(user, TRAIT_MAULER)) // maulers get 15 armorpierce because if you're going to punch someone you might as well do a good job of it
+ armor_block = target.run_armor_check(affecting, "melee", armour_penetration = 15) // lot of good that sec jumpsuit did you
playsound(target.loc, user.dna.species.attack_sound, 25, 1, -1)
-
- target.visible_message("[user] [atk_verb]s [target]!", \
- "[user] [atk_verb]s you!", null, COMBAT_MESSAGE_RANGE, null, \
- user, "You [atk_verb] [target]!")
+ target.visible_message("[user] [atk_verb]ed [target]!", \
+ "[user] [atk_verb]ed you!", null, COMBAT_MESSAGE_RANGE, null, \
+ user, "You [atk_verb]ed [target]!")
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
@@ -1445,11 +1448,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.dismembering_strike(user, affecting.body_zone)
if(atk_verb == ATTACK_EFFECT_KICK)//kicks deal 1.5x raw damage + 0.5x stamina damage
- target.apply_damage(damage*1.5, attack_type, affecting, armor_block)
+ target.apply_damage(damage*1.5, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
target.apply_damage(damage*0.5, STAMINA, affecting, armor_block)
log_combat(user, target, "kicked")
- else//other attacks deal full raw damage + 2x in stamina damage
- target.apply_damage(damage, attack_type, affecting, armor_block)
+ else if(HAS_TRAIT(user, TRAIT_MAULER)) // mauler punches deal 1.3x raw damage + 1x stam damage, and have some armor pierce
+ target.apply_damage(damage*1.3, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
+ target.apply_damage(damage, STAMINA, affecting, armor_block)
+ log_combat(user, target, "punched (mauler)")
+ else //other attacks deal full raw damage + 2x in stamina damage
+ target.apply_damage(damage, attack_type, affecting, armor_block, wound_bonus = punchwoundbonus)
target.apply_damage(damage*2, STAMINA, affecting, armor_block)
log_combat(user, target, "punched")
@@ -1956,6 +1963,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HAS_BONE in species_traits)
. |= BIO_JUST_BONE
+//a check for if you should render any overlays or not
+/datum/species/proc/should_render(mob/living/carbon/human/H)
+ return TRUE
+
+//a check for if you want to forcibly make CanPass return TRUE for the mob with this species
+/datum/species/proc/species_pass_check()
+ return FALSE
+
/////////////
//BREATHING//
/////////////
diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductor.dm
similarity index 90%
rename from code/modules/mob/living/carbon/human/species_types/abductors.dm
rename to code/modules/mob/living/carbon/human/species_types/abductor.dm
index 38e10e8662..004ba267e8 100644
--- a/code/modules/mob/living/carbon/human/species_types/abductors.dm
+++ b/code/modules/mob/living/carbon/human/species_types/abductor.dm
@@ -1,12 +1,12 @@
/datum/species/abductor
name = "Abductor"
- id = "abductor"
+ id = SPECIES_ABDUCTOR
say_mod = "gibbers"
sexes = FALSE
species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutanttongue = /obj/item/organ/tongue/abductor
- species_type = "alien"
+ species_category = SPECIES_CATEGORY_ALIEN
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm
index 5d43d18429..7f755ce027 100644
--- a/code/modules/mob/living/carbon/human/species_types/android.dm
+++ b/code/modules/mob/living/carbon/human/species_types/android.dm
@@ -1,6 +1,6 @@
/datum/species/android
name = "Android"
- id = "android"
+ id = SPECIES_ANDROID
say_mod = "states"
species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT)
@@ -11,7 +11,7 @@
mutanttongue = /obj/item/organ/tongue/robot
species_language_holder = /datum/language_holder/synthetic
limbs_id = "synth"
- species_type = "robotic"
+ species_category = SPECIES_CATEGORY_ROBOT
/datum/species/android/on_species_gain(mob/living/carbon/C)
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index 3cae574a90..9c87f3ad5d 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -1,6 +1,6 @@
/datum/species/angel
name = "Angel"
- id = "angel"
+ id = SPECIES_ANGEL
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel")
@@ -9,7 +9,7 @@
blacklisted = 1
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
- species_type = "human" //they're a kind of human
+ species_category = SPECIES_CATEGORY_BASIC //they're a kind of human
var/datum/action/innate/flight/fly
diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/anthromorph.dm
similarity index 87%
rename from code/modules/mob/living/carbon/human/species_types/furrypeople.dm
rename to code/modules/mob/living/carbon/human/species_types/anthromorph.dm
index 534536d6e7..95aec26d9f 100644
--- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/anthromorph.dm
@@ -1,6 +1,6 @@
/datum/species/mammal
name = "Anthromorph"
- id = "mammal"
+ id = SPECIES_MAMMAL
default_color = "4B4B4B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST
@@ -15,6 +15,6 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "furry"
+ species_category = SPECIES_CATEGORY_FURRY
- allowed_limb_ids = list("mammal","aquatic","avian")
\ No newline at end of file
+ allowed_limb_ids = list("mammal","aquatic","avian")
diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
index 6eccde61a9..773651d464 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -1,6 +1,6 @@
/datum/species/insect
name = "Anthromorphic Insect"
- id = "insect"
+ id = SPECIES_INSECT
say_mod = "chitters"
default_color = "00FF00"
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
@@ -18,7 +18,7 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "insect"
+ species_category = SPECIES_CATEGORY_INSECT
allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale")
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index a2597ed286..e9baa786da 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -18,4 +18,4 @@
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
sexes = 0
gib_types = /obj/effect/gibspawner/robot
- species_type = "robotic"
\ No newline at end of file
+ species_category = SPECIES_CATEGORY_ROBOT
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
index f3b499093b..f756fd8816 100644
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
@@ -1,6 +1,6 @@
/datum/species/dullahan
name = "Dullahan"
- id = "dullahan"
+ id = SPECIES_DULLAHAN
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
@@ -14,7 +14,7 @@
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head.
- species_type = "undead"
+ species_category = SPECIES_CATEGORY_UNDEAD
var/pumpkin = FALSE
var/obj/item/dullahan_relay/myhead
diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
index a465e7c3a9..ce67a947de 100644
--- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
@@ -4,7 +4,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/datum/species/dwarf //not to be confused with the genetic manlets
name = "Dwarf"
- id = "dwarf" //Also called Homo sapiens pumilionis
+ id = SPECIES_DWARF //Also called Homo sapiens pumilionis
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB)
@@ -18,7 +18,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
mutant_organs = list(/obj/item/organ/dwarfgland) //Dwarven alcohol gland, literal gland warrior
mutantliver = /obj/item/organ/liver/dwarf //Dwarven super liver (Otherwise they r doomed)
species_language_holder = /datum/language_holder/dwarf
- species_type = "human" //a kind of human
+ species_category = SPECIES_CATEGORY_BASIC //a kind of human
/mob/living/carbon/human/species/dwarf //species admin spawn path
race = /datum/species/dwarf //and the race the path is set to.
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index c182defda4..d92f4ab14a 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -2,7 +2,7 @@
/datum/species/ethereal
name = "Ethereal"
- id = "ethereal"
+ id = SPECIES_ETHEREAL
attack_verb = "burn"
attack_sound = 'sound/weapons/etherealhit.ogg'
miss_sound = 'sound/weapons/etherealmiss.ogg'
diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm
index b760fd0aee..011b6b7642 100644
--- a/code/modules/mob/living/carbon/human/species_types/felinid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm
@@ -1,7 +1,7 @@
//Subtype of human
/datum/species/human/felinid
name = "Felinid"
- id = "felinid"
+ id = SPECIES_FELINID
limbs_id = "human"
mutant_bodyparts = list("mam_tail" = "Cat", "mam_ears" = "Cat", "deco_wings" = "None")
@@ -11,7 +11,7 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "furry"
+ species_category = SPECIES_CATEGORY_FURRY
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
index c56adaf1b0..c3e406244b 100644
--- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm
@@ -1,6 +1,6 @@
/datum/species/fly
name = "Anthromorphic Fly"
- id = "fly"
+ id = SPECIES_FLY
say_mod = "buzzes"
species_traits = list(NOEYES,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
@@ -12,7 +12,7 @@
liked_food = GROSS
exotic_bloodtype = "BUG"
exotic_blood_color = BLOOD_COLOR_BUG
- species_type = "insect"
+ species_category = SPECIES_CATEGORY_INSECT
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(istype(chem, /datum/reagent/toxin/pestkiller))
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 438eaf1eea..ff0287d7b9 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -1,7 +1,7 @@
/datum/species/golem
// Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck.
name = "Golem"
- id = "iron golem"
+ id = SPECIES_GOLEM
species_traits = list(NOBLOOD,MUTCOLORS,NO_UNDERWEAR,NOGENITALS,NOAROUSAL)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = MOB_HUMANOID|MOB_MINERAL
@@ -32,7 +32,7 @@
var/special_name_chance = 5
var/owner //dobby is a free golem
- species_type = "golem"
+ species_category = SPECIES_CATEGORY_GOLEM
/datum/species/golem/random_name(gender,unique,lastname)
var/golem_surname = pick(GLOB.golem_names)
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index f175ddb921..e8e0ff1a78 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -1,6 +1,6 @@
/datum/species/human
name = "Human"
- id = "human"
+ id = SPECIES_HUMAN
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,HAS_FLESH,HAS_BONE)
@@ -12,7 +12,7 @@
tail_type = "tail_human"
wagging_type = "waggingtail_human"
- species_type = "human"
+ species_category = SPECIES_CATEGORY_BASIC
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm
index 9bfe661f47..6353fd5184 100644
--- a/code/modules/mob/living/carbon/human/species_types/ipc.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm
@@ -1,6 +1,6 @@
/datum/species/ipc
name = "I.P.C."
- id = "ipc"
+ id = SPECIES_IPC
say_mod = "beeps"
default_color = "00FF00"
blacklisted = 0
@@ -28,7 +28,7 @@
exotic_bloodtype = "HF"
exotic_blood_color = BLOOD_COLOR_OIL
- species_type = "robotic"
+ species_category = SPECIES_CATEGORY_ROBOT
var/datum/action/innate/monitor_change/screen
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 a2c3248c6a..58a10fb08e 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -1,7 +1,7 @@
/datum/species/jelly
// Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them.
name = "Xenobiological Jelly Entity"
- id = "jelly"
+ id = SPECIES_JELLY
default_color = "00FF90"
say_mod = "chirps"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH)
@@ -16,7 +16,8 @@
exotic_blood_color = "BLOOD_COLOR_SLIME"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
- var/datum/action/innate/slime_change/slime_change //CIT CHANGE
+ var/datum/action/innate/slime_change/slime_change
+ var/datum/action/innate/slime_puddle/slime_puddle
liked_food = TOXIC | MEAT
disliked_food = null
toxic_food = ANTITOXIC
@@ -28,19 +29,22 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "jelly"
+ species_category = SPECIES_CATEGORY_JELLY
/obj/item/organ/brain/jelly
name = "slime nucleus"
desc = "A slimey membranous mass from a slime person"
icon_state = "brain-slime"
-
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
+ if(slime_puddle && slime_puddle.is_puddle)
+ slime_puddle.Activate()
if(regenerate_limbs)
regenerate_limbs.Remove(C)
- if(slime_change) //CIT CHANGE
- slime_change.Remove(C) //CIT CHANGE
+ if(slime_change)
+ slime_change.Remove(C)
+ if(slime_puddle)
+ slime_puddle.Remove(C)
C.faction -= "slime"
..()
C.faction -= "slime"
@@ -50,8 +54,10 @@
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
- slime_change = new //CIT CHANGE
- slime_change.Grant(C) //CIT CHANGE
+ slime_change = new
+ slime_change.Grant(C)
+ slime_puddle = new
+ slime_puddle.Grant(C)
C.faction |= "slime"
/datum/species/jelly/handle_body(mob/living/carbon/human/H)
@@ -59,6 +65,18 @@
//update blood color to body color
exotic_blood_color = "#" + H.dna.features["mcolor"]
+/datum/species/jelly/should_render()
+ if(slime_puddle && slime_puddle.is_puddle)
+ return FALSE
+ else
+ return ..()
+
+/datum/species/jelly/species_pass_check()
+ if(slime_puddle && slime_puddle.is_puddle)
+ return TRUE
+ else
+ return ..()
+
/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 blooduskers
return
@@ -140,7 +158,7 @@
/datum/species/jelly/slime
name = "Xenobiological Slime Entity"
- id = "slime"
+ id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
say_mod = "says"
@@ -449,7 +467,7 @@
/datum/species/jelly/roundstartslime
name = "Xenobiological Slime Hybrid"
- id = "slimeperson"
+ id = SPECIES_SLIME_HYBRID
limbs_id = "slime"
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
@@ -670,6 +688,88 @@
else
return
+/datum/action/innate/slime_puddle
+ name = "Puddle Transformation"
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "slimepuddle"
+ icon_icon = 'icons/mob/actions/actions_slime.dmi'
+ background_icon_state = "bg_alien"
+ required_mobility_flags = MOBILITY_STAND
+ var/is_puddle = FALSE
+ var/in_transformation_duration = 12
+ var/out_transformation_duration = 7
+ var/puddle_into_effect = /obj/effect/temp_visual/slime_puddle
+ var/puddle_from_effect = /obj/effect/temp_visual/slime_puddle/reverse
+ var/puddle_icon = 'icons/mob/mob.dmi'
+ var/puddle_state = "puddle"
+ var/tracked_overlay
+ var/datum/component/squeak/squeak
+ var/transforming = FALSE
+ var/last_use
+
+/datum/action/innate/slime_puddle/IsAvailable()
+ if(!transforming)
+ return ..()
+ else
+ return FALSE
+
+/datum/action/innate/slime_puddle/Activate()
+ if(isjellyperson(owner) && IsAvailable())
+ transforming = TRUE
+ UpdateButtonIcon()
+ var/mob/living/carbon/human/H = owner
+ var/mutcolor = "#" + H.dna.features["mcolor"]
+ if(!is_puddle)
+ if(CHECK_MOBILITY(H, MOBILITY_USE))
+ is_puddle = TRUE
+ owner.cut_overlays()
+ var/obj/effect/puddle_effect = new puddle_into_effect(get_turf(owner), owner.dir)
+ puddle_effect.color = mutcolor
+ H.Stun(in_transformation_duration, ignore_canstun = TRUE)
+ ADD_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
+ ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
+ H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
+ H.update_disabled_bodyparts(silent = TRUE)
+ H.layer -= 1 //go one layer down so people go over you
+ ENABLE_BITFIELD(H.pass_flags, PASSMOB)
+ squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg'))
+ sleep(in_transformation_duration)
+ var/mutable_appearance/puddle_overlay = mutable_appearance(icon = puddle_icon, icon_state = puddle_state)
+ puddle_overlay.color = mutcolor
+ tracked_overlay = puddle_overlay
+ owner.add_overlay(puddle_overlay)
+ transforming = FALSE
+ UpdateButtonIcon()
+ else
+ owner.cut_overlay(tracked_overlay)
+ var/obj/effect/puddle_effect = new puddle_from_effect(get_turf(owner), owner.dir)
+ puddle_effect.color = mutcolor
+ H.Stun(out_transformation_duration, ignore_canstun = TRUE)
+ sleep(out_transformation_duration)
+ REMOVE_TRAIT(H, TRAIT_PARALYSIS_L_ARM, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_PARALYSIS_R_ARM, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
+ H.update_disabled_bodyparts(silent = TRUE)
+ H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
+ H.layer += 1 //go one layer back above!
+ DISABLE_BITFIELD(H.pass_flags, PASSMOB)
+ is_puddle = FALSE
+ if(squeak)
+ squeak.RemoveComponent()
+ owner.regenerate_icons()
+ transforming = FALSE
+ UpdateButtonIcon()
+ else
+ to_chat(owner, "You need to be standing up to do this!") //just assume they're a slime because it's such a weird edgecase to have it and not be one (it shouldn't even be possible)
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
@@ -677,7 +777,7 @@
/datum/species/jelly/luminescent
name = "Luminescent Slime Entity"
- id = "lum"
+ id = SPECIES_SLIME_LUMI
say_mod = "says"
var/glow_intensity = LUMINESCENT_DEFAULT_GLOW
var/obj/effect/dummy/luminescent_glow/glow
@@ -844,7 +944,7 @@
/datum/species/jelly/stargazer
name = "Stargazer Slime Entity"
- id = "stargazer"
+ id = SPECIES_STARGAZER
var/datum/action/innate/project_thought/project_thought
var/datum/action/innate/link_minds/link_minds
var/list/mob/living/linked_mobs = list()
diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
index a8e3f89957..c37a24a93a 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -1,7 +1,7 @@
/datum/species/lizard
// Reptilian humanoids with scaled skin and tails.
name = "Anthromorphic Lizard"
- id = "lizard"
+ id = SPECIES_LIZARD
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
@@ -28,7 +28,7 @@
tail_type = "tail_lizard"
wagging_type = "waggingtail_lizard"
- species_type = "lizard"
+ species_category = "lizard"
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
@@ -46,7 +46,7 @@
*/
/datum/species/lizard/ashwalker
name = "Ash Walker"
- id = "ashlizard"
+ id = SPECIES_ASHWALKER
limbs_id = "lizard"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
index f91c3518a3..dcbdf91485 100644
--- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm
@@ -1,6 +1,6 @@
/datum/species/mush //mush mush codecuck
name = "Anthromorphic Mushroom"
- id = "mush"
+ id = SPECIES_MUSHROOM
mutant_bodyparts = list("caps" = "Round")
fixed_mut_color = "DBBF92"
@@ -21,7 +21,7 @@
burnmod = 1.25
heatmod = 1.5
- species_type = "plant"
+ species_category = SPECIES_CATEGORY_PLANT
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
var/datum/martial_art/mushpunch/mush
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 8c30adb8f9..12a520b463 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -1,6 +1,6 @@
/datum/species/plasmaman
name = "Plasmaman"
- id = "plasmaman"
+ id = SPECIES_PLASMAMAN
say_mod = "rattles"
sexes = 0
meat = /obj/item/stack/sheet/mineral/plasma
@@ -22,7 +22,7 @@
liked_food = VEGETABLES
outfit_important_for_life = /datum/outfit/plasmaman
- species_type = "skeleton"
+ species_category = SPECIES_CATEGORY_SKELETON
/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/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
index 0f62953e6c..fae8ebfb0d 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -1,7 +1,7 @@
/datum/species/pod
// A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness.
name = "Anthromorphic Plant"
- id = "pod"
+ id = SPECIES_POD
default_color = "59CE00"
species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE)
attack_verb = "slash"
@@ -19,7 +19,7 @@
var/light_burnheal = -1
var/light_bruteheal = -1
- species_type = "plant"
+ species_category = SPECIES_CATEGORY_PLANT
allowed_limb_ids = list("pod","mush")
@@ -66,7 +66,7 @@
/datum/species/pod/pseudo_weak
name = "Anthromorphic Plant"
- id = "podweak"
+ id = SPECIES_POD_WEAK
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
limbs_id = "pod"
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index a7d9ce4473..7dc8083264 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -4,7 +4,7 @@
/datum/species/shadow
// Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light.
name = "???"
- id = "shadow"
+ id = SPECIES_SHADOW
sexes = 0
blacklisted = 1
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
@@ -15,7 +15,7 @@
dangerous_existence = 1
mutanteyes = /obj/item/organ/eyes/night_vision
- species_type = "shadow"
+ species_category = SPECIES_CATEGORY_SHADOW
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -32,7 +32,7 @@
/datum/species/shadow/nightmare
name = "Nightmare"
- id = "nightmare"
+ id = SPECIES_NIGHTMARE
limbs_id = "shadow"
burnmod = 1.5
blacklisted = TRUE
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 1b6bef9dc6..b0673a7df4 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -1,6 +1,6 @@
/datum/species/skeleton
name = "Skeleton"
- id = "skeleton"
+ id = SPECIES_SKELETON
say_mod = "rattles"
blacklisted = 0
sexes = 0
@@ -15,7 +15,7 @@
brutemod = 1.25
burnmod = 1.25
- species_type = "skeleton" //they have their own category that's disassociated from undead, paired with plasmapeople
+ species_category = SPECIES_CATEGORY_SKELETON //they have their own category that's disassociated from undead, paired with plasmapeople
/datum/species/skeleton/New()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!
@@ -31,7 +31,7 @@
/datum/species/skeleton/space
name = "Spooky Spacey Skeleton"
- id = "spaceskeleton"
+ id = SPECIES_SKELETON_SPACE
limbs_id = "skeleton"
blacklisted = 1
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT, TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
index b446e3796e..88781532d3 100644
--- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm
@@ -1,6 +1,6 @@
/datum/species/synthliz
name = "Synthetic Lizardperson"
- id = "synthliz"
+ id = SPECIES_SYNTH_LIZARD
say_mod = "beeps"
default_color = "00FF00"
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE)
@@ -27,4 +27,4 @@
tail_type = "mam_tail"
wagging_type = "mam_waggingtail"
- species_type = "robotic"
+ species_category = SPECIES_CATEGORY_ROBOT
diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm
index 3d55ce1027..5d2b6f4c77 100644
--- a/code/modules/mob/living/carbon/human/species_types/synths.dm
+++ b/code/modules/mob/living/carbon/human/species_types/synths.dm
@@ -1,6 +1,6 @@
/datum/species/synth
name = "Synthetic" //inherited from the real species, for health scanners and things
- id = "synth"
+ id = SPECIES_SYNTH
say_mod = "beep boops" //inherited from a user's real species
sexes = 0
species_traits = list(NOTRANSSTING,NOGENITALS,NOAROUSAL) //all of these + whatever we inherit from the real species
@@ -17,11 +17,11 @@
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
species_language_holder = /datum/language_holder/synthetic
- species_type = "robotic"
+ species_category = SPECIES_CATEGORY_ROBOT
/datum/species/synth/military
name = "Military Synth"
- id = "military_synth"
+ id = SPECIES_SYNTH_MIL
armor = 25
punchdamagelow = 10
punchdamagehigh = 19
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 857fb6d8ed..4125d3beab 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -1,6 +1,6 @@
/datum/species/vampire
name = "Vampire"
- id = "vampire"
+ id = SPECIES_VAMPIRE
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH)
@@ -14,7 +14,7 @@
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
- species_type = "undead"
+ species_category = SPECIES_CATEGORY_UNDEAD
/datum/species/vampire/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
diff --git a/code/modules/mob/living/carbon/human/species_types/xeno.dm b/code/modules/mob/living/carbon/human/species_types/xeno.dm
index ddd1c86f0a..2757c624e7 100644
--- a/code/modules/mob/living/carbon/human/species_types/xeno.dm
+++ b/code/modules/mob/living/carbon/human/species_types/xeno.dm
@@ -1,7 +1,7 @@
/datum/species/xeno
// A cloning mistake, crossing human and xenomorph DNA
name = "Xenomorph Hybrid"
- id = "xeno"
+ id = SPECIES_XENOHYBRID
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
@@ -15,4 +15,4 @@
exotic_bloodtype = "X*"
damage_overlay_type = "xeno"
liked_food = MEAT
- species_type = "alien"
+ species_category = SPECIES_CATEGORY_ALIEN
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index 8d86ad2fa9..f1c0b8e7c0 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -15,7 +15,7 @@
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
liked_food = GROSS | MEAT | RAW
- species_type = "undead"
+ species_category = SPECIES_CATEGORY_UNDEAD
/datum/species/zombie/notspaceproof
id = "notspaceproofzombie"
@@ -98,7 +98,7 @@
// Your skin falls off
/datum/species/krokodil_addict
- name = "Human"
+ name = SPECIES_HUMAN
id = "goofzombies"
limbs_id = "zombie" //They look like zombies
sexes = 0
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index b83a6f9039..71833d22a3 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -50,19 +50,21 @@ There are several things that need to be remembered:
//HAIR OVERLAY
/mob/living/carbon/human/update_hair()
- dna.species.handle_hair(src)
+ if(dna.species.should_render())
+ dna.species.handle_hair(src)
//used when putting/removing clothes that hide certain mutant body parts to just update those and not update the whole body.
/mob/living/carbon/human/proc/update_mutant_bodyparts()
- dna.species.handle_mutant_bodyparts(src)
-
+ if(dna.species.should_render())
+ dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/update_body(update_genitals = FALSE)
- remove_overlay(BODY_LAYER)
- dna.species.handle_body(src)
- ..()
- if(update_genitals)
- update_genitals()
+ if(dna.species.should_render())
+ remove_overlay(BODY_LAYER)
+ dna.species.handle_body(src)
+ ..()
+ if(update_genitals)
+ update_genitals()
/mob/living/carbon/human/update_fire()
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
@@ -71,381 +73,385 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
-
- if(!..())
- icon_render_key = null //invalidate bodyparts cache
- update_body(TRUE)
- update_hair()
- update_inv_w_uniform()
- update_inv_wear_id()
- update_inv_gloves()
- update_inv_glasses()
- update_inv_ears()
- update_inv_shoes()
- update_inv_s_store()
- update_inv_wear_mask()
- update_inv_head()
- update_inv_belt()
- update_inv_back()
- update_inv_wear_suit()
- update_inv_pockets()
- update_inv_neck()
- update_transform()
- //mutations
- update_mutations_overlay()
- //damage overlays
- update_damage_overlays()
+ if(dna.species.should_render())
+ if(!..())
+ icon_render_key = null //invalidate bodyparts cache
+ update_body(TRUE)
+ update_hair()
+ update_inv_w_uniform()
+ update_inv_wear_id()
+ update_inv_gloves()
+ update_inv_glasses()
+ update_inv_ears()
+ update_inv_shoes()
+ update_inv_s_store()
+ update_inv_wear_mask()
+ update_inv_head()
+ update_inv_belt()
+ update_inv_back()
+ update_inv_wear_suit()
+ update_inv_pockets()
+ update_inv_neck()
+ update_transform()
+ //mutations
+ update_mutations_overlay()
+ //damage overlays
+ update_damage_overlays()
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform()
- remove_overlay(UNIFORM_LAYER)
+ if(dna.species.should_render())
+ remove_overlay(UNIFORM_LAYER)
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
- inv.update_icon()
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
+ inv.update_icon()
- if(istype(w_uniform, /obj/item/clothing/under))
- var/obj/item/clothing/under/U = w_uniform
- U.screen_loc = ui_iclothing
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += w_uniform
- update_observer_view(w_uniform,1)
+ if(istype(w_uniform, /obj/item/clothing/under))
+ var/obj/item/clothing/under/U = w_uniform
+ U.screen_loc = ui_iclothing
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown)
+ client.screen += w_uniform
+ update_observer_view(w_uniform,1)
- if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
- return
+ if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
+ return
- var/target_overlay = U.icon_state
- if(U.adjusted == ALT_STYLE)
- target_overlay = "[target_overlay]_d"
+ var/target_overlay = U.icon_state
+ if(U.adjusted == ALT_STYLE)
+ target_overlay = "[target_overlay]_d"
- var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi'
- var/variant_flag = NONE
+ var/alt_worn = U.mob_overlay_icon || 'icons/mob/clothing/uniform.dmi'
+ var/variant_flag = NONE
- if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE && !(U.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
- alt_worn = U.anthro_mob_worn_overlay || 'icons/mob/clothing/uniform_digi.dmi'
- variant_flag |= STYLE_DIGITIGRADE
+ if((DIGITIGRADE in dna.species.species_traits) && U.mutantrace_variation & STYLE_DIGITIGRADE && !(U.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
+ alt_worn = U.anthro_mob_worn_overlay || 'icons/mob/clothing/uniform_digi.dmi'
+ variant_flag |= STYLE_DIGITIGRADE
- var/mask
- if(dna.species.mutant_bodyparts["taur"])
- var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
- var/clip_flag = U.mutantrace_variation & T?.hide_legs
- if(clip_flag)
- variant_flag |= clip_flag
- mask = T.alpha_mask_state
+ var/mask
+ if(dna.species.mutant_bodyparts["taur"])
+ var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
+ var/clip_flag = U.mutantrace_variation & T?.hide_legs
+ if(clip_flag)
+ variant_flag |= clip_flag
+ mask = T.alpha_mask_state
- var/mutable_appearance/uniform_overlay
+ var/mutable_appearance/uniform_overlay
- var/gendered = (dna?.species.sexes && dna.features["body_model"] == FEMALE) ? U.fitted : NO_FEMALE_UNIFORM
- uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, gendered, target_overlay, variant_flag, FALSE, mask)
+ var/gendered = (dna?.species.sexes && dna.features["body_model"] == FEMALE) ? U.fitted : NO_FEMALE_UNIFORM
+ uniform_overlay = U.build_worn_icon( UNIFORM_LAYER, alt_worn, FALSE, gendered, target_overlay, variant_flag, FALSE, mask)
- if(OFFSET_UNIFORM in dna.species.offset_features)
- uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
- uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
- overlays_standing[UNIFORM_LAYER] = uniform_overlay
-
- apply_overlay(UNIFORM_LAYER)
- update_mutant_bodyparts()
+ if(OFFSET_UNIFORM in dna.species.offset_features)
+ uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
+ uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
+ overlays_standing[UNIFORM_LAYER] = uniform_overlay
+ apply_overlay(UNIFORM_LAYER)
+ update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
- remove_overlay(ID_LAYER)
+ if(dna.species.should_render())
+ remove_overlay(ID_LAYER)
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
- inv.update_icon()
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
+ inv.update_icon()
- var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
+ var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
- if(wear_id)
- wear_id.screen_loc = ui_id
- if(client && hud_used && hud_used.hud_shown)
- client.screen += wear_id
- update_observer_view(wear_id)
+ if(wear_id)
+ wear_id.screen_loc = ui_id
+ if(client && hud_used && hud_used.hud_shown)
+ client.screen += wear_id
+ update_observer_view(wear_id)
- //TODO: add an icon file for ID slot stuff, so it's less snowflakey
- id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state)
- if(OFFSET_ID in dna.species.offset_features)
- id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
- id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
- overlays_standing[ID_LAYER] = id_overlay
- apply_overlay(ID_LAYER)
+ //TODO: add an icon file for ID slot stuff, so it's less snowflakey
+ id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi', override_state = wear_id.item_state)
+ if(OFFSET_ID in dna.species.offset_features)
+ id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
+ id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
+ overlays_standing[ID_LAYER] = id_overlay
+ apply_overlay(ID_LAYER)
/mob/living/carbon/human/update_inv_gloves()
- remove_overlay(GLOVES_LAYER)
+ if(dna.species.should_render())
+ remove_overlay(GLOVES_LAYER)
- if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
- inv.update_icon()
+ if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
+ 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())
- if(get_num_arms(FALSE) < 2)
- if(has_left_hand(FALSE))
- bloody_overlay.icon_state = "bloodyhands_left"
- else if(has_right_hand(FALSE))
- bloody_overlay.icon_state = "bloodyhands_right"
+ if(!gloves && bloody_hands)
+ var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
+ if(get_num_arms(FALSE) < 2)
+ if(has_left_hand(FALSE))
+ bloody_overlay.icon_state = "bloodyhands_left"
+ else if(has_right_hand(FALSE))
+ bloody_overlay.icon_state = "bloodyhands_right"
- overlays_standing[GLOVES_LAYER] = bloody_overlay
+ overlays_standing[GLOVES_LAYER] = bloody_overlay
- var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
- if(gloves)
- gloves.screen_loc = ui_gloves
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += gloves
- update_observer_view(gloves,1)
- overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
- gloves_overlay = overlays_standing[GLOVES_LAYER]
- if(OFFSET_GLOVES in dna.species.offset_features)
- gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
- gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
- overlays_standing[GLOVES_LAYER] = gloves_overlay
- apply_overlay(GLOVES_LAYER)
+ var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
+ if(gloves)
+ gloves.screen_loc = ui_gloves
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown)
+ client.screen += gloves
+ update_observer_view(gloves,1)
+ overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/clothing/hands.dmi')
+ gloves_overlay = overlays_standing[GLOVES_LAYER]
+ if(OFFSET_GLOVES in dna.species.offset_features)
+ gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
+ gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
+ overlays_standing[GLOVES_LAYER] = gloves_overlay
+ apply_overlay(GLOVES_LAYER)
/mob/living/carbon/human/update_inv_glasses()
- remove_overlay(GLASSES_LAYER)
+ if(dna.species.should_render())
+ remove_overlay(GLASSES_LAYER)
- if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
- return
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
- inv.update_icon()
-
- if(glasses)
- glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open ...
- client.screen += glasses //Either way, add the item to the HUD
- update_observer_view(glasses,1)
- if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
- overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state)
- var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
- if(glasses_overlay)
- if(OFFSET_GLASSES in dna.species.offset_features)
- glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
- glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
- overlays_standing[GLASSES_LAYER] = glasses_overlay
- apply_overlay(GLASSES_LAYER)
-
-
-/mob/living/carbon/human/update_inv_ears()
- remove_overlay(EARS_LAYER)
-
- if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
- return
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
- inv.update_icon()
-
- if(ears)
- ears.screen_loc = ui_ears //move the item to the appropriate screen loc
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open
- client.screen += ears //add it to the client's screen
- update_observer_view(ears,1)
-
- overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
- var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
- if(OFFSET_EARS in dna.species.offset_features)
- ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
- ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
- overlays_standing[EARS_LAYER] = ears_overlay
- apply_overlay(EARS_LAYER)
-
-
-/mob/living/carbon/human/update_inv_shoes()
- remove_overlay(SHOES_LAYER)
-
- if(get_num_legs(FALSE) <2)
- return
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
- inv.update_icon()
-
- if(dna.species.mutant_bodyparts["taur"])
- var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
- if(T?.hide_legs) //If only they actually made shoes unwearable. Please don't making cosmetics, guys.
+ if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
return
- if(shoes)
- var/obj/item/clothing/shoes/S = shoes
- shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown) //if the inventory is open
- client.screen += shoes //add it to client's screen
- update_observer_view(shoes,1)
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
+ inv.update_icon()
- var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi'
- var/variation_flag = NONE
- if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
- alt_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/feet_digi.dmi'
- variation_flag |= STYLE_DIGITIGRADE
+ if(glasses)
+ glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown) //if the inventory is open ...
+ client.screen += glasses //Either way, add the item to the HUD
+ update_observer_view(glasses,1)
+ if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
+ overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/clothing/eyes.dmi', override_state = glasses.icon_state)
+ var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
+ if(glasses_overlay)
+ if(OFFSET_GLASSES in dna.species.offset_features)
+ glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
+ glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
+ overlays_standing[GLASSES_LAYER] = glasses_overlay
+ apply_overlay(GLASSES_LAYER)
- overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, S.icon_state, variation_flag, FALSE)
- var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
- if(OFFSET_SHOES in dna.species.offset_features)
- shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
- shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
- overlays_standing[SHOES_LAYER] = shoes_overlay
- apply_overlay(SHOES_LAYER)
+/mob/living/carbon/human/update_inv_ears()
+ if(dna.species.should_render())
+ remove_overlay(EARS_LAYER)
-/mob/living/carbon/human/update_inv_s_store()
- remove_overlay(SUIT_STORE_LAYER)
+ if(!get_bodypart(BODY_ZONE_HEAD)) //decapitated
+ return
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
- inv.update_icon()
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
+ inv.update_icon()
- if(s_store)
- s_store.screen_loc = ui_sstore1
- if(client && hud_used && hud_used.hud_shown)
- client.screen += s_store
- update_observer_view(s_store)
- var/t_state = s_store.item_state
- if(!t_state)
- t_state = s_store.icon_state
- overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
- var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
- if(OFFSET_S_STORE in dna.species.offset_features)
- s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
- s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
- overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
- apply_overlay(SUIT_STORE_LAYER)
+ if(ears)
+ ears.screen_loc = ui_ears //move the item to the appropriate screen loc
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown) //if the inventory is open
+ client.screen += ears //add it to the client's screen
+ update_observer_view(ears,1)
+ overlays_standing[EARS_LAYER] = ears.build_worn_icon(default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
+ var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
+ if(OFFSET_EARS in dna.species.offset_features)
+ ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
+ ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
+ overlays_standing[EARS_LAYER] = ears_overlay
+ apply_overlay(EARS_LAYER)
-/mob/living/carbon/human/update_inv_head()
- remove_overlay(HEAD_LAYER)
+/mob/living/carbon/human/update_inv_shoes()
+ if(dna.species.should_render())
+ remove_overlay(SHOES_LAYER)
- if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
- return
+ if(get_num_legs(FALSE) <2)
+ return
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
- inv.update_icon()
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
+ inv.update_icon()
- if(head)
- head.screen_loc = ui_head
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += head
- update_observer_view(head,1)
- remove_overlay(HEAD_LAYER)
- var/obj/item/clothing/head/H = head
- var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
- var/muzzled = FALSE
- var/variation_flag = NONE
- if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
- muzzled = TRUE
- else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
- muzzled = TRUE
- if(muzzled && H.mutantrace_variation & STYLE_MUZZLE && !(H.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
- alt_icon = H.anthro_mob_worn_overlay || 'icons/mob/clothing/head_muzzled.dmi'
- variation_flag |= STYLE_MUZZLE
-
- overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE)
- var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
-
- if(OFFSET_HEAD in dna.species.offset_features)
- head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
- head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
- overlays_standing[HEAD_LAYER] = head_overlay
- apply_overlay(HEAD_LAYER)
- update_mutant_bodyparts()
-
-/mob/living/carbon/human/update_inv_belt()
- remove_overlay(BELT_LAYER)
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
- inv.update_icon()
-
- if(belt)
- belt.screen_loc = ui_belt
- if(client && hud_used && hud_used.hud_shown)
- client.screen += belt
- update_observer_view(belt)
-
- overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi')
- var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
- if(OFFSET_BELT in dna.species.offset_features)
- belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
- belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
- overlays_standing[BELT_LAYER] = belt_overlay
- apply_overlay(BELT_LAYER)
-
-
-/mob/living/carbon/human/update_inv_wear_suit()
- remove_overlay(SUIT_LAYER)
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
- inv.update_icon()
-
- if(wear_suit)
- var/obj/item/clothing/suit/S = wear_suit
- wear_suit.screen_loc = ui_oclothing
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += wear_suit
- update_observer_view(wear_suit,1)
-
- var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi'
- var/worn_state = wear_suit.icon_state
- var/center = FALSE
- var/dimension_x = 32
- var/dimension_y = 32
- var/variation_flag = NONE
- var/datum/sprite_accessory/taur/T
if(dna.species.mutant_bodyparts["taur"])
- T = GLOB.taur_list[dna.features["taur"]]
+ var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
+ if(T?.hide_legs) //If only they actually made shoes unwearable. Please don't making cosmetics, guys.
+ return
- if(S.mutantrace_variation)
+ if(shoes)
+ var/obj/item/clothing/shoes/S = shoes
+ shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown) //if the inventory is open
+ client.screen += shoes //add it to client's screen
+ update_observer_view(shoes,1)
- if(T?.taur_mode)
- var/init_worn_icon = worn_icon
- variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode
- switch(variation_flag)
- if(STYLE_HOOF_TAURIC)
- worn_icon = 'icons/mob/clothing/taur_hooved.dmi'
- if(STYLE_SNEK_TAURIC)
- worn_icon = 'icons/mob/clothing/taur_naga.dmi'
- if(STYLE_PAW_TAURIC)
- worn_icon = 'icons/mob/clothing/taur_canine.dmi'
- if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied.
- if(S.taur_mob_worn_overlay) //not going to make several new variables for all taur types. Nope.
- var/static/list/icon_to_state = list('icons/mob/clothing/taur_hooved.dmi' = "_hooved", 'icons/mob/clothing/taur_naga.dmi' = "_naga", 'icons/mob/clothing/taur_canine.dmi' = "_paws")
- worn_state += icon_to_state[worn_icon]
- worn_icon = S.taur_mob_worn_overlay
- center = T.center
- dimension_x = T.dimension_x
- dimension_y = T.dimension_y
-
- else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON)) //not a taur, but digitigrade legs.
- worn_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/suit_digi.dmi'
+ var/alt_icon = S.mob_overlay_icon || 'icons/mob/clothing/feet.dmi'
+ var/variation_flag = NONE
+ if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
+ alt_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/feet_digi.dmi'
variation_flag |= STYLE_DIGITIGRADE
- overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, worn_state, variation_flag, FALSE)
- var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
- if(OFFSET_SUIT in dna.species.offset_features)
- suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
- suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
- if(center)
- suit_overlay = center_image(suit_overlay, dimension_x, dimension_y)
- overlays_standing[SUIT_LAYER] = suit_overlay
- update_hair()
- update_mutant_bodyparts()
+ overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(SHOES_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, S.icon_state, variation_flag, FALSE)
+ var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
+ if(OFFSET_SHOES in dna.species.offset_features)
+ shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
+ shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
+ overlays_standing[SHOES_LAYER] = shoes_overlay
+ apply_overlay(SHOES_LAYER)
- apply_overlay(SUIT_LAYER)
+/mob/living/carbon/human/update_inv_s_store()
+ if(dna.species.should_render())
+ remove_overlay(SUIT_STORE_LAYER)
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
+ inv.update_icon()
+
+ if(s_store)
+ s_store.screen_loc = ui_sstore1
+ if(client && hud_used && hud_used.hud_shown)
+ client.screen += s_store
+ update_observer_view(s_store)
+ var/t_state = s_store.item_state
+ if(!t_state)
+ t_state = s_store.icon_state
+ overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.mob_overlay_icon) ? s_store.mob_overlay_icon : 'icons/mob/clothing/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
+ var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
+ if(OFFSET_S_STORE in dna.species.offset_features)
+ s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
+ s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
+ overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
+ apply_overlay(SUIT_STORE_LAYER)
+
+/mob/living/carbon/human/update_inv_head()
+ if(dna.species.should_render())
+ remove_overlay(HEAD_LAYER)
+
+ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
+ return
+
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
+ inv.update_icon()
+
+ if(head)
+ head.screen_loc = ui_head
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown)
+ client.screen += head
+ update_observer_view(head,1)
+ remove_overlay(HEAD_LAYER)
+ var/obj/item/clothing/head/H = head
+ var/alt_icon = H.mob_overlay_icon || 'icons/mob/clothing/head.dmi'
+ var/muzzled = FALSE
+ var/variation_flag = NONE
+ if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
+ muzzled = TRUE
+ else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
+ muzzled = TRUE
+ if(muzzled && H.mutantrace_variation & STYLE_MUZZLE && !(H.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
+ alt_icon = H.anthro_mob_worn_overlay || 'icons/mob/clothing/head_muzzled.dmi'
+ variation_flag |= STYLE_MUZZLE
+
+ overlays_standing[HEAD_LAYER] = H.build_worn_icon(HEAD_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, H.icon_state, variation_flag, FALSE)
+ var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
+
+ if(OFFSET_HEAD in dna.species.offset_features)
+ head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
+ head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
+ overlays_standing[HEAD_LAYER] = head_overlay
+ apply_overlay(HEAD_LAYER)
+ update_mutant_bodyparts()
+
+/mob/living/carbon/human/update_inv_belt()
+ if(dna.species.should_render())
+ remove_overlay(BELT_LAYER)
+
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
+ inv.update_icon()
+
+ if(belt)
+ belt.screen_loc = ui_belt
+ if(client && hud_used && hud_used.hud_shown)
+ client.screen += belt
+ update_observer_view(belt)
+
+ overlays_standing[BELT_LAYER] = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = 'icons/mob/clothing/belt.dmi')
+ var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
+ if(OFFSET_BELT in dna.species.offset_features)
+ belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
+ belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
+ overlays_standing[BELT_LAYER] = belt_overlay
+ apply_overlay(BELT_LAYER)
+
+/mob/living/carbon/human/update_inv_wear_suit()
+ if(dna.species.should_render())
+ remove_overlay(SUIT_LAYER)
+
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
+ inv.update_icon()
+
+ if(wear_suit)
+ var/obj/item/clothing/suit/S = wear_suit
+ wear_suit.screen_loc = ui_oclothing
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown)
+ client.screen += wear_suit
+ update_observer_view(wear_suit,1)
+
+ var/worn_icon = wear_suit.mob_overlay_icon || 'icons/mob/clothing/suit.dmi'
+ var/worn_state = wear_suit.icon_state
+ var/center = FALSE
+ var/dimension_x = 32
+ var/dimension_y = 32
+ var/variation_flag = NONE
+ var/datum/sprite_accessory/taur/T
+ if(dna.species.mutant_bodyparts["taur"])
+ T = GLOB.taur_list[dna.features["taur"]]
+
+ if(S.mutantrace_variation)
+
+ if(T?.taur_mode)
+ var/init_worn_icon = worn_icon
+ variation_flag |= S.mutantrace_variation & T.taur_mode || S.mutantrace_variation & T.alt_taur_mode
+ switch(variation_flag)
+ if(STYLE_HOOF_TAURIC)
+ worn_icon = 'icons/mob/clothing/taur_hooved.dmi'
+ if(STYLE_SNEK_TAURIC)
+ worn_icon = 'icons/mob/clothing/taur_naga.dmi'
+ if(STYLE_PAW_TAURIC)
+ worn_icon = 'icons/mob/clothing/taur_canine.dmi'
+ if(worn_icon != init_worn_icon) //worn icon sprite was changed, taur offsets will have to be applied.
+ if(S.taur_mob_worn_overlay) //not going to make several new variables for all taur types. Nope.
+ var/static/list/icon_to_state = list('icons/mob/clothing/taur_hooved.dmi' = "_hooved", 'icons/mob/clothing/taur_naga.dmi' = "_naga", 'icons/mob/clothing/taur_canine.dmi' = "_paws")
+ worn_state += icon_to_state[worn_icon]
+ worn_icon = S.taur_mob_worn_overlay
+ center = T.center
+ dimension_x = T.dimension_x
+ dimension_y = T.dimension_y
+
+ else if((DIGITIGRADE in dna.species.species_traits) && S.mutantrace_variation & STYLE_DIGITIGRADE && !(S.mutantrace_variation & STYLE_NO_ANTHRO_ICON)) //not a taur, but digitigrade legs.
+ worn_icon = S.anthro_mob_worn_overlay || 'icons/mob/clothing/suit_digi.dmi'
+ variation_flag |= STYLE_DIGITIGRADE
+
+ overlays_standing[SUIT_LAYER] = S.build_worn_icon(SUIT_LAYER, worn_icon, FALSE, NO_FEMALE_UNIFORM, worn_state, variation_flag, FALSE)
+ var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
+ if(OFFSET_SUIT in dna.species.offset_features)
+ suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
+ suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
+ if(center)
+ suit_overlay = center_image(suit_overlay, dimension_x, dimension_y)
+ overlays_standing[SUIT_LAYER] = suit_overlay
+ update_hair()
+ update_mutant_bodyparts()
+
+ apply_overlay(SUIT_LAYER)
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
@@ -471,55 +477,57 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_wear_mask()
- remove_overlay(FACEMASK_LAYER)
-
- if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
- return
-
- if(client && hud_used)
- var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
- inv.update_icon()
-
- if(wear_mask)
- wear_mask.screen_loc = ui_mask
- if(client && hud_used && hud_used.hud_shown)
- if(hud_used.inventory_shown)
- client.screen += wear_mask
- update_observer_view(wear_mask,1)
- var/obj/item/clothing/mask/M = wear_mask
+ if(dna.species.should_render())
remove_overlay(FACEMASK_LAYER)
- var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
- var/muzzled = FALSE
- var/variation_flag = NONE
- if(head && (head.flags_inv & HIDEMASK))
+
+ if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
- if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
- muzzled = TRUE
- else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
- muzzled = TRUE
- if(muzzled && M.mutantrace_variation & STYLE_MUZZLE && !(M.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
- alt_icon = M.anthro_mob_worn_overlay || 'icons/mob/clothing/mask_muzzled.dmi'
- variation_flag |= STYLE_MUZZLE
- var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE)
+ if(client && hud_used)
+ var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
+ inv.update_icon()
- if(OFFSET_FACEMASK in dna.species.offset_features)
- mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
- mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
- overlays_standing[FACEMASK_LAYER] = mask_overlay
- apply_overlay(FACEMASK_LAYER)
- update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
+ if(wear_mask)
+ wear_mask.screen_loc = ui_mask
+ if(client && hud_used && hud_used.hud_shown)
+ if(hud_used.inventory_shown)
+ client.screen += wear_mask
+ update_observer_view(wear_mask,1)
+ var/obj/item/clothing/mask/M = wear_mask
+ remove_overlay(FACEMASK_LAYER)
+ var/alt_icon = M.mob_overlay_icon || 'icons/mob/clothing/mask.dmi'
+ var/muzzled = FALSE
+ var/variation_flag = NONE
+ if(head && (head.flags_inv & HIDEMASK))
+ return
+ if(dna.species.mutant_bodyparts["mam_snouts"] && dna.features["mam_snouts"] != "None")
+ muzzled = TRUE
+ else if(dna.species.mutant_bodyparts["snout"] && dna.features["snout"] != "None")
+ muzzled = TRUE
+ if(muzzled && M.mutantrace_variation & STYLE_MUZZLE && !(M.mutantrace_variation & STYLE_NO_ANTHRO_ICON))
+ alt_icon = M.anthro_mob_worn_overlay || 'icons/mob/clothing/mask_muzzled.dmi'
+ variation_flag |= STYLE_MUZZLE
+
+ var/mutable_appearance/mask_overlay = M.build_worn_icon(FACEMASK_LAYER, alt_icon, FALSE, NO_FEMALE_UNIFORM, wear_mask.icon_state, variation_flag, FALSE)
+
+ if(OFFSET_FACEMASK in dna.species.offset_features)
+ mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
+ mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
+ overlays_standing[FACEMASK_LAYER] = mask_overlay
+ apply_overlay(FACEMASK_LAYER)
+ update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
- ..()
- var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
- if(back_overlay)
- remove_overlay(BACK_LAYER)
- if(OFFSET_BACK in dna.species.offset_features)
- back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
- back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
- overlays_standing[BACK_LAYER] = back_overlay
- apply_overlay(BACK_LAYER)
+ if(dna.species.should_render())
+ ..()
+ var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
+ if(back_overlay)
+ remove_overlay(BACK_LAYER)
+ if(OFFSET_BACK in dna.species.offset_features)
+ back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
+ back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
+ overlays_standing[BACK_LAYER] = back_overlay
+ apply_overlay(BACK_LAYER)
/proc/wear_alpha_masked_version(state, icon, layer, female, alpha_mask)
var/mask = "-[alpha_mask]"
@@ -710,8 +718,6 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
..()
update_hair()
-
-
/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory)
if(observers && observers.len)
for(var/M in observers)
@@ -729,15 +735,17 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
// Only renders the head of the human
/mob/living/carbon/human/proc/update_body_parts_head_only()
- if (!dna)
+ if(!dna)
return
- if (!dna.species)
+ if(!dna.species)
+ return
+
+ if(dna.species.should_render())
return
var/obj/item/bodypart/HD = get_bodypart("head")
-
- if (!istype(HD))
+ if(!istype(HD))
return
HD.update_limb()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index d34073ea24..57d688bde3 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -844,12 +844,12 @@
return
var/strip_mod = 1
var/strip_silence = FALSE
- if (ishuman(src)) //carbon doesn't actually wear gloves
+ if(ishuman(src)) //carbon doesn't actually wear gloves
var/mob/living/carbon/C = src
- var/obj/item/clothing/gloves/g = C.gloves
- if (istype(g))
- strip_mod = g.strip_mod
- strip_silence = g.strip_silence
+ var/obj/item/clothing/gloves/G = C.gloves
+ if(istype(G))
+ strip_mod = G.strip_mod
+ strip_silence = G.strip_silence
if (!strip_silence)
who.visible_message("[src] tries to remove [who]'s [what.name].", \
"[src] tries to remove your [what.name].", target = src,
diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm
index 1d8815d007..db472df388 100644
--- a/code/modules/mob/living/living_active_block.dm
+++ b/code/modules/mob/living/living_active_block.dm
@@ -237,6 +237,7 @@
active_block_do_stamina_damage(owner, object, stamina_cost, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = damage - final_damage
block_return[BLOCK_RETURN_SET_DAMAGE_TO] = final_damage
+ block_return[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(1 - (final_damage / damage), 0, 1)
. = BLOCK_SHOULD_CHANGE_DAMAGE
if((final_damage <= 0) || (damage <= 0))
. |= BLOCK_SUCCESS //full block
diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm
index 782da69248..8c6cf9d207 100644
--- a/code/modules/mob/living/living_mobility.dm
+++ b/code/modules/mob/living/living_mobility.dm
@@ -5,12 +5,15 @@
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
+ RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
//Stuff like mobility flag updates, resting updates, etc.
//Force-set resting variable, without needing to resist/etc.
/mob/living/proc/set_resting(new_resting, silent = FALSE, updating = TRUE)
if(new_resting != resting)
+ if(resting && HAS_TRAIT(src, TRAIT_MOBILITY_NOREST)) //forcibly block resting from all sources - BE CAREFUL WITH THIS TRAIT
+ return
resting = new_resting
if(!silent)
to_chat(src, "You are now [resting? "resting" : "getting up"].")
@@ -87,7 +90,7 @@
var/canstand_involuntary = conscious && !stat_softcrit && !knockdown && !chokehold && !paralyze && (ignore_legs || has_legs) && !(buckled && buckled.buckle_lying) && !(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)
var/canstand = canstand_involuntary && !resting
- var/should_be_lying = !canstand
+ var/should_be_lying = !canstand && !HAS_TRAIT(src, TRAIT_MOBILITY_NOREST)
if(buckled)
if(buckled.buckle_lying != -1)
should_be_lying = buckled.buckle_lying
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 186fe36a10..37eb9b7f67 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -52,6 +52,19 @@
var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach
var/lose_patience_timeout = 300 //30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever
+ ///When a target is found, will the mob attempt to charge at it's target?
+ var/charger = FALSE
+ ///Tracks if the target is actively charging.
+ var/charge_state = FALSE
+ ///In a charge, how many tiles will the charger travel?
+ var/charge_distance = 3
+ ///How often can the charging mob actually charge? Effects the cooldown between charges.
+ var/charge_frequency = 6 SECONDS
+ ///If the mob is charging, how long will it stun it's target on success, and itself on failure?
+ var/knockdown_time = 3 SECONDS
+ ///Declares a cooldown for potential charges right off the bat.
+ COOLDOWN_DECLARE(charge_cooldown)
+
/mob/living/simple_animal/hostile/Initialize()
. = ..()
@@ -292,6 +305,9 @@
if(ranged) //We ranged? Shoot at em
if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown
OpenFire(target)
+ if(charger && (target_distance > minimum_distance) && (target_distance <= charge_distance))//Attempt to close the distance with a charge.
+ enter_charge(target)
+ return TRUE
if(!Process_Spacemove()) //Drifting
walk(src,0)
return 1
@@ -599,3 +615,64 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
. += M
else if (M.loc.type in hostile_machines)
. += M.loc
+
+
+/**
+ * Proc that handles a charge attack windup for a mob.
+ */
+/mob/living/simple_animal/hostile/proc/enter_charge(var/atom/target)
+ if((mobility_flags & (MOBILITY_MOVE | MOBILITY_STAND)) != (MOBILITY_MOVE | MOBILITY_STAND) || charge_state)
+ return FALSE
+
+ if(!(COOLDOWN_FINISHED(src, charge_cooldown)) || !has_gravity() || !target.has_gravity())
+ return FALSE
+ Shake(15, 15, 1 SECONDS)
+ addtimer(CALLBACK(src, .proc/handle_charge_target, target), 1.5 SECONDS, TIMER_STOPPABLE)
+
+/**
+ * Proc that throws the mob at the target after the windup.
+ */
+/mob/living/simple_animal/hostile/proc/handle_charge_target(var/atom/target)
+ charge_state = TRUE
+ throw_at(target, charge_distance, 1, src, FALSE, TRUE, callback = CALLBACK(src, .proc/charge_end))
+ COOLDOWN_START(src, charge_cooldown, charge_frequency)
+ return TRUE
+
+/**
+ * Proc that handles a charge attack after it's concluded.
+ */
+/mob/living/simple_animal/hostile/proc/charge_end()
+ charge_state = FALSE
+
+/**
+ * Proc that handles the charge impact of the charging mob.
+ */
+/mob/living/simple_animal/hostile/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ if(!charge_state)
+ return ..()
+
+ if(hit_atom)
+ if(isliving(hit_atom))
+ var/mob/living/L = hit_atom
+ var/blocked = FALSE
+ if(ishuman(hit_atom))
+ var/mob/living/carbon/human/H = hit_atom
+ var/list/return_list = list()
+ if(H.mob_run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src, null, return_list) & BLOCK_SUCCESS)
+ blocked = TRUE
+ if(!blocked)
+ blocked = return_list[BLOCK_RETURN_MITIGATION_PERCENT]
+ if(!blocked)
+ L.visible_message("[src] charges on [L]!", "[src] charges into you!")
+ L.Knockdown(knockdown_time)
+ else
+ Stun((knockdown_time * 2), 1, 1)
+ charge_end()
+ else if(hit_atom.density && !hit_atom.CanPass(src))
+ visible_message("[src] smashes into [hit_atom]!")
+ Stun((knockdown_time * 2), 1, 1)
+
+ if(charge_state)
+ charge_state = FALSE
+ update_icons()
+ update_mobility()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobsterosity.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobsterosity.dm
new file mode 100644
index 0000000000..140042024d
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobsterosity.dm
@@ -0,0 +1,42 @@
+/**
+ * Lobstrosities, the poster boy of charging AI mobs. Drops crab meat and bones.
+ * Outside of charging, it's intended behavior is that it is generally slow moving, but makes up for that with a knockdown attack to score additional hits.
+ */
+/mob/living/simple_animal/hostile/asteroid/lobstrosity
+ name = "arctic lobstrosity"
+ desc = "A marvel of evolution gone wrong, the frosty ice produces underground lakes where these ill tempered seafood gather. Beware its charge."
+ icon = 'icons/mob/icemoon/icemoon_monsters.dmi'
+ icon_state = "arctic_lobstrosity"
+ icon_living = "arctic_lobstrosity"
+ icon_dead = "arctic_lobstrosity_dead"
+ mob_biotypes = MOB_ORGANIC|MOB_BEAST
+ mouse_opacity = MOUSE_OPACITY_ICON
+ friendly_verb_continuous = "chitters at"
+ friendly_verb_simple = "chits at"
+ speak_emote = list("chitters")
+ speed = 3
+ move_to_delay = 20
+ maxHealth = 150
+ health = 150
+ obj_damage = 15
+ melee_damage_lower = 15
+ melee_damage_upper = 19
+ attack_verb_continuous = "snips"
+ attack_verb_simple = "snip"
+ attack_sound = 'sound/weapons/bite.ogg'
+ weather_immunities = list("snow")
+ vision_range = 5
+ aggro_vision_range = 7
+ charger = TRUE
+ charge_distance = 4
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/crab = 2, /obj/item/stack/sheet/bone = 2)
+ robust_searching = TRUE
+ footstep_type = FOOTSTEP_MOB_CLAW
+ gold_core_spawnable = HOSTILE_SPAWN
+
+/mob/living/simple_animal/hostile/asteroid/lobstrosity/lava
+ name = "tropical lobstrosity"
+ desc = "A marvel of evolution gone wrong, the sulfur lakes of lavaland have given them a vibrant, red hued shell. Beware its charge."
+ icon_state = "lobstrosity"
+ icon_living = "lobstrosity"
+ icon_dead = "lobstrosity_dead"
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index b192182c71..5fa6a0c22d 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -6,6 +6,7 @@
gender = PLURAL //placeholder
///How much blud it has for bloodsucking
blood_volume = 550
+ rad_flags = RAD_NO_CONTAMINATE
status_flags = CANPUSH
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 0d4afd0915..2ed0bfa9d2 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -39,8 +39,7 @@
update_client_colour()
update_mouse_pointer()
if(client)
- client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed.
-
+ client.view_size?.resetToDefault()
if(client.player_details && istype(client.player_details))
if(client.player_details.player_actions.len)
for(var/datum/action/A in client.player_details.player_actions)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index e1a4ac6118..ab2556abb5 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -39,6 +39,7 @@
. = ..()
update_config_movespeed()
update_movespeed(TRUE)
+ initialize_actionspeed()
hook_vr("mob_new",list(src))
/mob/GenerateTag()
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 03a3ab1001..8c6b722140 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -58,6 +58,13 @@
var/list/movespeed_mod_immunities //Lazy list, see mob_movespeed.dm
/// The calculated mob speed slowdown based on the modifiers list
var/cached_multiplicative_slowdown
+ /// List of action speed modifiers applying to this mob
+ var/list/actionspeed_modification //Lazy list, see mob_movespeed.dm
+ /// List of action speed modifiers ignored by this mob. List -> List (id) -> List (sources)
+ var/list/actionspeed_mod_immunities //Lazy list, see mob_movespeed.dm
+ /// The calculated mob action speed slowdown based on the modifiers list
+ var/cached_multiplicative_actions_slowdown
+
/////////////////
var/name_archive //For admin things like possession
diff --git a/code/modules/movespeed/modifiers/innate.dm b/code/modules/movespeed/modifiers/innate.dm
index a0357ddf0f..946d93e96b 100644
--- a/code/modules/movespeed/modifiers/innate.dm
+++ b/code/modules/movespeed/modifiers/innate.dm
@@ -18,3 +18,7 @@
blacklisted_movetypes = (FLOATING|CRAWLING)
variable = TRUE
flags = IGNORE_NOSLOW
+
+/datum/movespeed_modifier/slime_puddle
+ multiplicative_slowdown = 2
+ flags = IGNORE_NOSLOW
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
index 0e553ced35..25b5cfb51b 100644
--- a/code/modules/paperwork/ticketmachine.dm
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -160,8 +160,7 @@
/obj/machinery/ticket_machine/proc/reset_cooldown()
ready = TRUE
-/obj/machinery/ticket_machine/attack_hand(mob/living/carbon/user)
- . = ..()
+/obj/machinery/ticket_machine/on_attack_hand(mob/living/carbon/user)
INVOKE_ASYNC(src, .proc/attempt_ticket, user)
/obj/machinery/ticket_machine/proc/attempt_ticket(mob/living/carbon/user)
diff --git a/code/modules/plumbing/plumbers/autohydro.dm b/code/modules/plumbing/plumbers/autohydro.dm
index 20b8e6012a..9c358d8d6e 100644
--- a/code/modules/plumbing/plumbers/autohydro.dm
+++ b/code/modules/plumbing/plumbers/autohydro.dm
@@ -30,20 +30,8 @@
. = ..()
START_PROCESSING(SSobj, src)
create_reagents(100 , AMOUNT_VISIBLE)
- AddComponent(/datum/component/plumbing/simple_demand)
-
-/obj/machinery/hydroponics/constructable/automagic/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
-
-
-/obj/machinery/hydroponics/constructable/proc/can_be_rotated(mob/user, rotation_type)
- return !anchored
/obj/machinery/hydroponics/constructable/automagic/process()
- if(reagents)
- reagents.add_reagent(reagents)
- reagents.clear_reagents()
if(dead)
dead = 0
qdel(myseed)
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index fe05365dd9..a4daeb6a33 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -407,3 +407,10 @@
/obj/item/stock_parts/cell/toymagburst
name = "toy mag burst rifle power supply"
maxcharge = 4000
+
+/obj/item/stock_parts/cell/family
+ name = "broken power cell"
+ desc = "An old faulty power cell. You can see your family name faintly etched onto it."
+ maxcharge = 100
+ self_recharge = -5 //it loses power over time instead of gaining
+ rating = 1
diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm
index b558031fab..c19927e84c 100644
--- a/code/modules/power/rtg.dm
+++ b/code/modules/power/rtg.dm
@@ -53,6 +53,33 @@
power_gen = 1250 // 2500 on T1, 10000 on T4.
circuit = /obj/item/circuitboard/machine/rtg/advanced
+/obj/machinery/power/rtg/advanced/fullupgrade //fully ugpraded stock parts
+ desc = "An advanced RTG capable of moderating isotope decay, increasing power output but reducing lifetime. It uses plasma-fueled radiation collectors to increase output even further. This model is fully upgraded with the latest tech available in this quadrant."
+
+/obj/machinery/power/rtg/advanced/fullupgrade/Initialize()
+ . = ..()
+ //This looks terrifying. And apparently instancing vars and modifying the amount variable causes runtime errors. Guess we're sticking to copy pasta, thanks, byond.
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/machine/rtg/advanced(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/uranium(null)
+ component_parts += new /obj/item/stack/sheet/mineral/plasma(null)
+ component_parts += new /obj/item/stack/sheet/mineral/plasma(null)
+ component_parts += new /obj/item/stack/sheet/mineral/plasma(null)
+ component_parts += new /obj/item/stack/sheet/mineral/plasma(null)
+ component_parts += new /obj/item/stack/sheet/mineral/plasma(null)
+ component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
+ component_parts += new /obj/item/stock_parts/micro_laser/quadultra(null)
+ RefreshParts()
+
// Void Core, power source for Abductor ships and bases.
// Provides a lot of power, but tends to explode when mistreated.
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 50dae7d6bb..6961ec54bb 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -364,7 +364,7 @@
icon_state_on = "protoemitter_+a"
can_buckle = TRUE
buckle_lying = FALSE
- var/view_range = 12
+ var/view_range = 4.5
var/datum/action/innate/protoemitter/firing/auto
//BUCKLE HOOKS
@@ -379,7 +379,7 @@
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
- buckled_mob.client.change_view(CONFIG_GET(string/default_view))
+ buckled_mob.client.view_size.resetToDefault()
auto.Remove(buckled_mob)
. = ..()
@@ -395,7 +395,7 @@
M.pixel_y = 14
layer = 4.1
if(M.client)
- M.client.change_view(view_range)
+ M.client.view_size.setTo(view_range)
if(!auto)
auto = new()
auto.Grant(M, src)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 70d262cd15..1c3a0d230f 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -134,7 +134,7 @@
/obj/item/gun/equipped(mob/living/user, slot)
. = ..()
if(zoomed && user.get_active_held_item() != src)
- zoom(user, FALSE) //we can only stay zoomed in if it's in our hands //yeah and we only unzoom if we're actually zoomed using the gun!!
+ zoom(user, user.dir, FALSE) //we can only stay zoomed in if it's in our hands //yeah and we only unzoom if we're actually zoomed using the gun!!
//called after the gun has successfully fired its chambered ammo.
/obj/item/gun/proc/process_chamber(mob/living/user)
@@ -439,7 +439,7 @@
/obj/item/gun/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/toggle_scope_zoom))
- zoom(user)
+ zoom(user, user.dir)
else if(istype(action, alight))
toggle_gunlight()
@@ -554,14 +554,19 @@
. = ..()
if(!.)
var/obj/item/gun/G = target
- G.zoom(owner, FALSE)
+ G.zoom(owner, owner.dir)
/datum/action/item_action/toggle_scope_zoom/Remove(mob/living/L)
var/obj/item/gun/G = target
- G.zoom(L, FALSE)
+ G.zoom(L, L.dir)
return ..()
-/obj/item/gun/proc/zoom(mob/living/user, forced_zoom)
+/obj/item/gun/proc/rotate(atom/thing, old_dir, new_dir)
+ if(ismob(thing))
+ var/mob/lad = thing
+ lad.client.view_size.zoomOut(zoom_out_amt, zoom_amt, new_dir)
+
+/obj/item/gun/proc/zoom(mob/living/user, direct, forced_zoom)
if(!(user?.client))
return
@@ -573,25 +578,11 @@
zoomed = !zoomed
if(zoomed)
- var/_x = 0
- var/_y = 0
- switch(user.dir)
- if(NORTH)
- _y = zoom_amt
- if(EAST)
- _x = zoom_amt
- if(SOUTH)
- _y = -zoom_amt
- if(WEST)
- _x = -zoom_amt
-
- user.client.change_view(zoom_out_amt)
- user.client.pixel_x = world.icon_size*_x
- user.client.pixel_y = world.icon_size*_y
+ RegisterSignal(user, COMSIG_ATOM_DIR_CHANGE, .proc/rotate)
+ user.client.view_size.zoomOut(zoom_out_amt, zoom_amt, direct)
else
- user.client.change_view(CONFIG_GET(string/default_view))
- user.client.pixel_x = 0
- user.client.pixel_y = 0
+ UnregisterSignal(user, COMSIG_ATOM_DIR_CHANGE)
+ user.client.view_size.zoomIn()
/obj/item/gun/handle_atom_del(atom/A)
if(A == chambered)
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 9210e66f22..00e59d09f8 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -374,7 +374,7 @@
inaccuracy_modifier = 0.5
zoomable = TRUE
zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you.
- zoom_out_amt = 13
+ zoom_out_amt = 5
slot_flags = ITEM_SLOT_BACK
automatic_burst_overlay = FALSE
actions_types = list()
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index 5e250d44e2..9d9f6aeb83 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -69,7 +69,8 @@
//ZOOMING
var/zoom_current_view_increase = 0
- var/zoom_target_view_increase = 10
+ ///The radius you want to zoom by
+ var/zoom_target_view_increase = 9.5
var/zooming = FALSE
var/zoom_lock = ZOOM_LOCK_OFF
var/zooming_angle
@@ -133,7 +134,7 @@
if(zoom_lock == ZOOM_LOCK_OFF)
return
zooming = TRUE
- current_user.client.change_view(world.view + zoom_target_view_increase)
+ current_user.client.view_size.setTo(zoom_target_view_increase)
zoom_current_view_increase = zoom_target_view_increase
/obj/item/gun/energy/beam_rifle/proc/stop_zooming(mob/user)
@@ -146,9 +147,8 @@
user = current_user
if(!user || !user.client)
return FALSE
- animate(user.client, pixel_x = 0, pixel_y = 0, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW)
+ user.client.view_size.zoomIn()
zoom_current_view_increase = 0
- user.client.change_view(CONFIG_GET(string/default_view))
zooming_angle = 0
current_zoom_x = 0
current_zoom_y = 0
diff --git a/code/modules/projectiles/projectile/special/rocket.dm b/code/modules/projectiles/projectile/special/rocket.dm
index df417ad734..b3737a8388 100644
--- a/code/modules/projectiles/projectile/special/rocket.dm
+++ b/code/modules/projectiles/projectile/special/rocket.dm
@@ -73,4 +73,4 @@
explosion(target, 0, 1, 1, 2)
return BULLET_ACT_HIT
//if(istype(target, /turf/closed) || ismecha(target))
- new /obj/item/broken_missile(get_turf(src), 1)
\ No newline at end of file
+ new /obj/item/broken_missile(get_turf(src), 1)
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index c2bb678904..86f6460ff7 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -2283,7 +2283,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
boozepwr = 50
/datum/reagent/consumable/ethanol/species_drink/on_mob_life(mob/living/carbon/C)
- if(C.dna.species && C.dna.species.species_type == species_required) //species have a species_type variable that refers to one of the drinks
+ if(C.dna.species && C.dna.species.species_category == species_required) //species have a species_category variable that refers to one of the drinks
quality = RACE_DRINK
else
C.adjust_disgust(disgust)
diff --git a/code/modules/research/designs/biogenerator_designs.dm b/code/modules/research/designs/biogenerator_designs.dm
index bdaf39732f..ed12d4945e 100644
--- a/code/modules/research/designs/biogenerator_designs.dm
+++ b/code/modules/research/designs/biogenerator_designs.dm
@@ -181,6 +181,14 @@
build_path = /obj/item/storage/belt/janitor
category = list("initial","Organic Materials")
+/datum/design/plantbelt
+ name = "Botanical Belt"
+ id = "plantbelt"
+ build_type = BIOGENERATOR
+ materials = list(/datum/material/biomass= 300)
+ build_path = /obj/item/storage/belt/plant
+ category = list("initial","Organic Materials")
+
/datum/design/s_holster
name = "Shoulder Holster"
id = "s_holster"
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 7013412e6d..b178f936b7 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -32,7 +32,7 @@
materials = list(/datum/material/glass = 3000, /datum/material/plasma = 3000, /datum/material/diamond = 250, /datum/material/bluespace = 250)
build_path = /obj/item/reagent_containers/glass/beaker/bluespace
category = list("Medical Designs")
- departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_SERVICE
/datum/design/noreactbeaker
name = "Cryostasis Beaker"
@@ -973,6 +973,10 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+/////////////////////////////////////////
+//////////// Plumbing //////////
+/////////////////////////////////////////
+
/datum/design/acclimator
name = "Plumbing Acclimator"
desc = "A heating and cooling device for pipes!"
@@ -1126,3 +1130,14 @@
build_path = /obj/item/construction/plumbing
category = list("Misc","Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/rplunger
+ name = "Reinforced Plunger"
+ desc = "A plunger designed for heavy duty clogs."
+ id = "rplunger"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/plasma = 1000, /datum/material/iron = 1000, /datum/material/glass = 1000)
+ construction_time = 15
+ build_path = /obj/item/plunger/reinforced
+ category = list ("Misc","Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_CARGO
diff --git a/code/modules/research/techweb/nodes/medical_nodes.dm b/code/modules/research/techweb/nodes/medical_nodes.dm
index 150e420c09..7b9b2f2923 100644
--- a/code/modules/research/techweb/nodes/medical_nodes.dm
+++ b/code/modules/research/techweb/nodes/medical_nodes.dm
@@ -38,7 +38,7 @@
display_name = "Advanced Plumbing Technology"
description = "Plumbing RCD."
prereq_ids = list("plumbing", "adv_engi")
- design_ids = list("plumb_rcd", "autohydrotray")
+ design_ids = list("plumb_rcd", "autohydrotray", "rplunger")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
//////////////////////Cybernetics/////////////////////
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index ed43576a61..cbfbbe2a36 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -335,15 +335,11 @@ datum/status_effect/rebreathing/tick()
duration = 600
/datum/status_effect/timecookie/on_apply()
- if(ishuman(owner))
- var/mob/living/carbon/human/H
- H.physiology.do_after_speed *= 0.95
+ owner.add_actionspeed_modifier(/datum/actionspeed_modifier/timecookie)
return ..()
/datum/status_effect/timecookie/on_remove()
- if(ishuman(owner))
- var/mob/living/carbon/human/H
- H.physiology.do_after_speed /= 0.95
+ owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/timecookie)
return ..()
/datum/status_effect/lovecookie
diff --git a/code/modules/ruins/spaceruin_code/caravanambush.dm b/code/modules/ruins/spaceruin_code/caravanambush.dm
index a7d89f3324..740850524c 100644
--- a/code/modules/ruins/spaceruin_code/caravanambush.dm
+++ b/code/modules/ruins/spaceruin_code/caravanambush.dm
@@ -68,7 +68,7 @@
lock_override = NONE
shuttlePortId = "caravantrade1_custom"
jumpto_ports = list("whiteship_away" = 1, "whiteship_home" = 1, "whiteship_z4" = 1, "caravantrade1_ambush" = 1)
- view_range = 14
+ view_range = 6.5
x_offset = -5
y_offset = -5
designate_time = 100
@@ -92,7 +92,7 @@
lock_override = NONE
shuttlePortId = "caravanpirate_custom"
jumpto_ports = list("caravanpirate_ambush" = 1)
- view_range = 14
+ view_range = 6.5
x_offset = 3
y_offset = -6
@@ -116,7 +116,7 @@
lock_override = NONE
shuttlePortId = "caravansyndicate1_custom"
jumpto_ports = list("caravansyndicate1_ambush" = 1, "caravansyndicate1_listeningpost" = 1)
- view_range = 7
+ view_range = 0
x_offset = 2
y_offset = 0
@@ -140,7 +140,7 @@
lock_override = NONE
shuttlePortId = "caravansyndicate2_custom"
jumpto_ports = list("caravansyndicate2_ambush" = 1, "caravansyndicate1_listeningpost" = 1)
- view_range = 7
+ view_range = 0
x_offset = 0
y_offset = 2
@@ -164,6 +164,6 @@
lock_override = NONE
shuttlePortId = "caravansyndicate3_custom"
jumpto_ports = list("caravansyndicate3_ambush" = 1, "caravansyndicate3_listeningpost" = 1)
- view_range = 10
+ view_range = 2.5
x_offset = -1
y_offset = -3
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index 195e87720c..21a9c6c5d7 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -2,6 +2,7 @@
name = "navigation computer"
desc = "Used to designate a precise transit location for a spacecraft."
jump_action = null
+ should_supress_view_changes = FALSE
var/datum/action/innate/shuttledocker_rotate/rotate_action = new
var/datum/action/innate/shuttledocker_place/place_action = new
var/shuttleId = ""
@@ -10,7 +11,7 @@
var/list/jumpto_ports = list() //hashset of ports to jump to and ignore for collision purposes
var/obj/docking_port/stationary/my_port //the custom docking port placed by this console
var/obj/docking_port/mobile/shuttle_port //the mobile docking port of the connected shuttle
- var/view_range = 7
+ var/view_range = 0
var/x_offset = 0
var/y_offset = 0
var/list/whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava)
@@ -88,7 +89,7 @@
to_add += SSshuttle.hidden_shuttle_turf_images
user.client.images += to_add
- user.client.change_view(view_range)
+ user.client.view_size.setTo(view_range)
/obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user)
..()
@@ -101,7 +102,7 @@
to_remove += SSshuttle.hidden_shuttle_turf_images
user.client.images -= to_remove
- user.client.change_view(CONFIG_GET(string/default_view))
+ user.client.view_size.resetToDefault()
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot()
if(designating_target_loc || !current_user)
diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm
index bdbdc08c6f..794f2bcd44 100644
--- a/code/modules/shuttle/syndicate.dm
+++ b/code/modules/shuttle/syndicate.dm
@@ -60,7 +60,7 @@
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "syndicate_custom"
jumpto_ports = list("syndicate_ne" = 1, "syndicate_nw" = 1, "syndicate_n" = 1, "syndicate_se" = 1, "syndicate_sw" = 1, "syndicate_s" = 1)
- view_range = 13
+ view_range = 5.5
x_offset = -7
y_offset = -1
space_turfs_only = FALSE
diff --git a/code/modules/shuttle/white_ship.dm b/code/modules/shuttle/white_ship.dm
index f25fe30f36..66146edea1 100644
--- a/code/modules/shuttle/white_ship.dm
+++ b/code/modules/shuttle/white_ship.dm
@@ -25,7 +25,7 @@
lock_override = NONE
shuttlePortId = "whiteship_custom"
jumpto_ports = list("whiteship_away" = 1, "whiteship_home" = 1, "whiteship_z4" = 1)
- view_range = 18
+ view_range = 10
x_offset = -6
y_offset = -10
designate_time = 100
@@ -36,7 +36,7 @@
shuttleId = "whiteship_pod"
shuttlePortId = "whiteship_pod_custom"
jumpto_ports = list("whiteship_pod_home" = 1)
- view_range = 7
+ view_range = 0
x_offset = -2
y_offset = 0
designate_time = 0
diff --git a/code/modules/spells/spell_types/devil_boons.dm b/code/modules/spells/spell_types/devil_boons.dm
index 8ba106d77b..cf11466d19 100644
--- a/code/modules/spells/spell_types/devil_boons.dm
+++ b/code/modules/spells/spell_types/devil_boons.dm
@@ -43,7 +43,7 @@
for(var/mob/C in targets)
if(!C.client)
continue
- C.client.change_view(input("Select view range:", "Range", 4) in ranges)
+ C.client.view_size.setTo((input("Select view range:", "Range", 4) in ranges) - 7)
/obj/effect/proc_holder/spell/targeted/summon_friend
name = "Summon Friend"
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 90f2185ce6..80740ee6f7 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -483,12 +483,12 @@
//Checks disabled status thresholds
//Checks disabled status thresholds
-/obj/item/bodypart/proc/update_disabled()
+/obj/item/bodypart/proc/update_disabled(silent = FALSE)
if(!owner)
return
- set_disabled(is_disabled())
+ set_disabled(is_disabled(silent), silent)
-/obj/item/bodypart/proc/is_disabled()
+/obj/item/bodypart/proc/is_disabled(silent = FALSE)
if(!owner)
return
if(HAS_TRAIT(owner, TRAIT_PARALYSIS))
@@ -500,7 +500,7 @@
if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER))
. = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled
if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0%
- if(!last_maxed)
+ if(!last_maxed && !silent)
owner.emote("scream")
last_maxed = TRUE
if(!is_organic_limb() || stamina_dam >= max_damage)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 3038e32733..481bafbb3d 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -434,8 +434,8 @@
var/datum/scar/scaries = new
var/datum/wound/loss/phantom_loss = new // stolen valor, really
scaries.generate(L, phantom_loss)
- if(HAS_TRAIT(src, ROBOTIC_LIMBS)) //Snowflake trait moment, but needed.
+ L.attach_limb(src, 1)
+ if(ROBOTIC_LIMBS in dna.species.species_traits) //Snowflake trait moment, but needed.
L.render_like_organic = TRUE
L.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE) //Haha what if IPC-lings actually regenerated the right limbs instead of organic ones? That'd be pretty cool, right?
- L.attach_limb(src, 1)
return TRUE
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index 5a887ee6b7..86288564ae 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -75,11 +75,11 @@
return BODYPART_DISABLED_PARALYSIS
return ..()
-/obj/item/bodypart/l_arm/set_disabled(new_disabled)
+/obj/item/bodypart/l_arm/set_disabled(new_disabled, silent = FALSE)
. = ..()
if(!.)
return
- if(owner.stat < UNCONSCIOUS)
+ if(owner.stat < UNCONSCIOUS && !silent)
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
@@ -136,11 +136,11 @@
return BODYPART_DISABLED_PARALYSIS
return ..()
-/obj/item/bodypart/r_arm/set_disabled(new_disabled)
+/obj/item/bodypart/r_arm/set_disabled(new_disabled, silent = FALSE)
. = ..()
if(!.)
return
- if(owner.stat < UNCONSCIOUS)
+ if(owner.stat < UNCONSCIOUS && !silent)
switch(disabled)
if(BODYPART_DISABLED_DAMAGE)
owner.emote("scream")
@@ -196,16 +196,17 @@
return BODYPART_DISABLED_PARALYSIS
return ..()
-/obj/item/bodypart/l_leg/set_disabled(new_disabled)
+/obj/item/bodypart/l_leg/set_disabled(new_disabled, silent = FALSE)
. = ..()
if(!. || owner.stat >= UNCONSCIOUS)
return
- switch(disabled)
- if(BODYPART_DISABLED_DAMAGE)
- owner.emote("scream")
- to_chat(owner, "Your [name] is too damaged to function!")
- if(BODYPART_DISABLED_PARALYSIS)
- to_chat(owner, "You can't feel your [name]!")
+ if(!silent)
+ switch(disabled)
+ if(BODYPART_DISABLED_DAMAGE)
+ owner.emote("scream")
+ to_chat(owner, "Your [name] is too damaged to function!")
+ if(BODYPART_DISABLED_PARALYSIS)
+ to_chat(owner, "You can't feel your [name]!")
/obj/item/bodypart/l_leg/digitigrade
name = "left digitigrade leg"
@@ -253,16 +254,17 @@
return BODYPART_DISABLED_PARALYSIS
return ..()
-/obj/item/bodypart/r_leg/set_disabled(new_disabled)
+/obj/item/bodypart/r_leg/set_disabled(new_disabled, silent = FALSE)
. = ..()
if(!. || owner.stat >= UNCONSCIOUS)
return
- switch(disabled)
- if(BODYPART_DISABLED_DAMAGE)
- owner.emote("scream")
- to_chat(owner, "Your [name] is too damaged to function!")
- if(BODYPART_DISABLED_PARALYSIS)
- to_chat(owner, "You can't feel your [name]!")
+ if(!silent)
+ switch(disabled)
+ if(BODYPART_DISABLED_DAMAGE)
+ owner.emote("scream")
+ to_chat(owner, "Your [name] is too damaged to function!")
+ if(BODYPART_DISABLED_PARALYSIS)
+ to_chat(owner, "You can't feel your [name]!")
/obj/item/bodypart/r_leg/digitigrade
name = "right digitigrade leg"
diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html
index 3cab68da6a..60bd358031 100644
--- a/code/modules/tooltip/tooltip.html
+++ b/code/modules/tooltip/tooltip.html
@@ -120,12 +120,17 @@
window.location = 'byond://winset?id='+tooltip.control+';anchor1=0,0;size=999x999';
//Get the real icon size according to the client view
+ //FYI, this bit is even more borrowed from goon, our widescreen broke tooltips so I took a look at how they do it
+ //To improve our code. Thanks gooncoders, very cool
var mapWidth = map['view-size'].x,
mapHeight = map['view-size'].y,
- tilesShown = tooltip.client_view_h
- realIconSize = mapHeight / tilesShown,
- resizeRatio = realIconSize / tooltip.tileSize,
- //Calculate letterboxing offsets
+ tilesShownX = tooltip.client_view_w
+ tilesShownY = tooltip.client_view_h
+ realIconSizeX = mapWidth / tilesShownX,
+ realIconSizeY = mapHeight / tilesShownY,
+ resizeRatioX = realIconSizeX / tooltip.tileSize,
+ resizeRatioY = realIconSizeY / tooltip.tileSize,
+ //Calculate letterboxing offsets
leftOffset = (map.size.x - mapWidth) / 2,
topOffset = (map.size.y - mapHeight) / 2;
@@ -168,7 +173,7 @@
if ((iconX + westOffset) !== enteredX) { //Cursor entered on the offset tile
left = left + (westOffset < 0 ? 1 : -1);
}
- leftOffset = leftOffset + (westOffset * resizeRatio);
+ leftOffset = leftOffset + (westOffset * resizeRatioX);
}
}
@@ -179,13 +184,13 @@
if (northOffset !== 0) {
if ((iconY + northOffset) === enteredY) { //Cursor entered on the original tile
top--;
- topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatio);
+ topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatioY);
} else { //Cursor entered on the offset tile
if (northOffset < 0) { //Offset southwards
- topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatio);
+ topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatioY);
} else { //Offset northwards
top--;
- topOffset = topOffset - (northOffset * resizeRatio);
+ topOffset = topOffset - (northOffset * resizeRatioY);
}
}
}
@@ -198,12 +203,12 @@
}
//Clamp values
- left = (left < 0 ? 0 : (left > tilesShown ? tilesShown : left));
- top = (top < 0 ? 0 : (top > tilesShown ? tilesShown : top));
+ left = (left < 0 ? 0 : (left > tilesShownX ? tilesShownX : left));
+ top = (top < 0 ? 0 : (top > tilesShownY ? tilesShownY : top));
//Calculate where on the screen the popup should appear (below the hovered tile)
- var posX = Math.round(((left - 1) * realIconSize) + leftOffset + tooltip.padding); //-1 to position at the left of the target tile
- var posY = Math.round(((tilesShown - top + 1) * realIconSize) + topOffset + tooltip.padding); //+1 to position at the bottom of the target tile
+ var posX = Math.round(((left - 1) * realIconSizeX) + leftOffset + tooltip.padding); //-1 to position at the left of the target tile
+ var posY = Math.round(((tilesShownY - top + 1) * realIconSizeY) + topOffset + tooltip.padding); //+1 to position at the bottom of the target tile
//alert(mapWidth+' | '+mapHeight+' | '+tilesShown+' | '+realIconSize+' | '+leftOffset+' | '+topOffset+' | '+left+' | '+top+' | '+posX+' | '+posY); //DEBUG
@@ -221,7 +226,7 @@
docHeight = $wrap.outerHeight();
if (posY + docHeight > map.size.y) { //Is the bottom edge below the window? Snap it up if so
- posY = (posY - docHeight) - realIconSize - tooltip.padding;
+ posY = (posY - docHeight) - realIconSizeY - tooltip.padding;
}
//Actually size, move and show the tooltip box
diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm
index 745eddcc07..6163e5722a 100644
--- a/code/modules/uplink/uplink_items/uplink_clothing.dm
+++ b/code/modules/uplink/uplink_items/uplink_clothing.dm
@@ -92,8 +92,8 @@
cost = 6
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
-/datum/uplink_item/device_tools/guerillagloves
- name = "Guerilla Gloves"
+/datum/uplink_item/device_tools/guerrillagloves
+ name = "Guerrilla Gloves"
desc = "A pair of highly robust combat gripper gloves that excels at performing takedowns at close range, with an added lining of insulation. Careful not to hit a wall!"
item = /obj/item/clothing/gloves/tackler/combat/insulated
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
diff --git a/code/modules/uplink/uplink_items/uplink_implants.dm b/code/modules/uplink/uplink_items/uplink_implants.dm
index bb4e0c7960..4839c96a2d 100644
--- a/code/modules/uplink/uplink_items/uplink_implants.dm
+++ b/code/modules/uplink/uplink_items/uplink_implants.dm
@@ -31,7 +31,7 @@
/datum/uplink_item/implants/warp
name = "Warp Implant"
- desc = "An implant injected into the body and later activated at the user's will. It will inject eigenstasium which saves the user's location and teleports them there after five seconds. Lasts only fifteen times."
+ desc = "An implant injected into the body and later activated at the user's will. Allows the user to teleport to where they were 10 seconds ago. Has a 10 second cooldown."
item = /obj/item/storage/box/syndie_kit/imp_warp
cost = 6
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
diff --git a/html/changelog.html b/html/changelog.html
index 0de57ebe79..8a1401744e 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -324,272 +324,11 @@
12 September 2020
+ 01 October 2020
BlueWildrose updated:
-
- DeltaFire15 updated:
-
-
- Putnam3145 updated:
-
-
- Sonic121x updated:
-
-
- TheObserver-sys updated:
-
-
- Trilbyspaceclone updated:
-
-
- Tupinambis updated:
-
-
- lolman360 updated:
-
-
- zeroisthebiggay updated:
-
-
-
- 11 September 2020
- Putnam3145 updated:
-
-
-
- 09 September 2020
- Putnam3145 updated:
-
-
- timothyteakettle updated:
-
-
-
- 08 September 2020
- Ghommie updated:
-
-
- KeRSedChaplain updated:
-
-
- silicons updated:
-
-
-
- 07 September 2020
- DeltaFire15 updated:
-
-
- Putnam for debugging ammo loading! Thx!! updated:
-
-
-
- 06 September 2020
- Putnam3145 updated:
-
-
- lolman360, NecromancerAnne updated:
-
-
- raspy-on-osu updated:
-
-
-
- 05 September 2020
- Bhijn updated:
-
-
- Putnam3145 updated:
-
-
- raspy-on-osu updated:
-
-
-
- 04 September 2020
- timothyteakettle updated:
-
-
-
- 03 September 2020
- Ghommie updated:
-
-
-
- 02 September 2020
- Putnam3145 updated:
-
-
- Tupinambis updated:
-
-
- raspy-on-osu updated:
-
-
- timothyteakettle updated:
-
-
-
- 01 September 2020
- BlueWildrose updated:
-
-
-
- 31 August 2020
- Arturlang updated:
-
-
- Chiirno updated:
-
-
- Couls, ported by NecromancerAnne updated:
-
-
- DeltaFire15 updated:
-
-
- Detective-Google updated:
-
-
- EmeraldSundisk updated:
-
-
- ForrestWick updated:
-
-
- Ghommie updated:
-
-
- LetterN updated:
-
-
- Lynxless updated:
-
-
- Putnam3145 updated:
-
-
- Sonic121x updated:
-
-
- kappa-sama updated:
-
-
- lolman360 updated:
-
-
- raspy-on-osu updated:
-
-
- silicons updated:
-
-
- timothyteakettle updated:
-
-
- zeroisthebiggay updated:
-
-
30 August 2020
diff --git a/html/changelogs/AutoChangeLog-pr-13014.yml b/html/changelogs/AutoChangeLog-pr-13014.yml
new file mode 100644
index 0000000000..861e797669
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13014.yml
@@ -0,0 +1,4 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - rscadd: "The wastes of Lavaland and the icy caverns of Snow Taxi rumble in unison."
diff --git a/html/changelogs/AutoChangeLog-pr-13233.yml b/html/changelogs/AutoChangeLog-pr-13233.yml
new file mode 100644
index 0000000000..4366abec64
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13233.yml
@@ -0,0 +1,6 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - rscadd: "Changeling bone gauntlets! They punch the shit out of people really good."
+ - tweak: "Guerilla gloves and gorilla gloves inherit the strip modifiers of their predecessors, because apparently they had those."
+ - balance: "Pugilists now always hit the targeted limb and never miss."
diff --git a/html/changelogs/AutoChangeLog-pr-13405.yml b/html/changelogs/AutoChangeLog-pr-13405.yml
new file mode 100644
index 0000000000..176e886b0d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13405.yml
@@ -0,0 +1,4 @@
+author: "silicons"
+delete-after: True
+changes:
+ - tweak: "the warp implant now actually warps you back 10 seconds. leaves a trail, though. now unlimited us."
diff --git a/html/changelogs/AutoChangeLog-pr-13444.yml b/html/changelogs/AutoChangeLog-pr-13444.yml
new file mode 100644
index 0000000000..d24babda2e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13444.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - tweak: "you can now get a family heirlooms based off your species instead of job"
diff --git a/html/changelogs/AutoChangeLog-pr-13472.yml b/html/changelogs/AutoChangeLog-pr-13472.yml
new file mode 100644
index 0000000000..8e8d043de6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13472.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscadd: "roundstart slimes can turn into puddles now"
diff --git a/html/changelogs/AutoChangeLog-pr-13497.yml b/html/changelogs/AutoChangeLog-pr-13497.yml
new file mode 100644
index 0000000000..c5f569bad3
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13497.yml
@@ -0,0 +1,5 @@
+author: "Zandario"
+delete-after: True
+changes:
+ - code_imp: "Added some framework for future species expansions, including clothing refitting."
+ - refactor: "Made majority of the relevant Species IDs and Categories pre-defined, also for easier expansion and use."
diff --git a/html/changelogs/AutoChangeLog-pr-13517.yml b/html/changelogs/AutoChangeLog-pr-13517.yml
new file mode 100644
index 0000000000..8f29517058
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13517.yml
@@ -0,0 +1,4 @@
+author: "silicons"
+delete-after: True
+changes:
+ - bugfix: "simple mobs are now immune to radioactive contamination"
diff --git a/html/changelogs/AutoChangeLog-pr-13525.yml b/html/changelogs/AutoChangeLog-pr-13525.yml
new file mode 100644
index 0000000000..eb441f04c3
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13525.yml
@@ -0,0 +1,4 @@
+author: "Detective-Google"
+delete-after: True
+changes:
+ - bugfix: "Hilbert's jukebox works"
diff --git a/html/changelogs/AutoChangeLog-pr-13527.yml b/html/changelogs/AutoChangeLog-pr-13527.yml
new file mode 100644
index 0000000000..7e65116e83
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13527.yml
@@ -0,0 +1,4 @@
+author: "ArchieBeepBoop"
+delete-after: True
+changes:
+ - rscadd: "Upgraded Advanced RTG Machine Preset"
diff --git a/html/changelogs/AutoChangeLog-pr-13531.yml b/html/changelogs/AutoChangeLog-pr-13531.yml
new file mode 100644
index 0000000000..3c138ef98d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13531.yml
@@ -0,0 +1,4 @@
+author: "DeltaFire15"
+delete-after: True
+changes:
+ - bugfix: "A certain lizard (totally not me) being stupid is no longer going to break regenerate_bodyparts"
diff --git a/html/changelogs/AutoChangeLog-pr-13533.yml b/html/changelogs/AutoChangeLog-pr-13533.yml
new file mode 100644
index 0000000000..1ba14c689c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13533.yml
@@ -0,0 +1,4 @@
+author: "shellspeed1"
+delete-after: True
+changes:
+ - rscadd: "A new recipe for a spicy has been given to us by a strange business man."
diff --git a/html/changelogs/AutoChangeLog-pr-13535.yml b/html/changelogs/AutoChangeLog-pr-13535.yml
new file mode 100644
index 0000000000..b020587eb8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13535.yml
@@ -0,0 +1,7 @@
+author: "Hatterhat"
+delete-after: True
+changes:
+ - rscadd: "Energy sabre reskin for the energy sword - access via alt-click."
+ - bugfix: "Alt-click reskins are fixed."
+ - tweak: "Defibrillators and their many, many overlays were moved to another .dmi."
+ - tweak: "You can now change the color of an energy sword via multitool. Not deswords. Yet."
diff --git a/html/changelogs/AutoChangeLog-pr-13539.yml b/html/changelogs/AutoChangeLog-pr-13539.yml
new file mode 100644
index 0000000000..a1f3df4fd0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13539.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscdel: "removes two debug messages left in from my prior eye customization pr"
diff --git a/html/changelogs/AutoChangeLog-pr-13540.yml b/html/changelogs/AutoChangeLog-pr-13540.yml
new file mode 100644
index 0000000000..0d7d9b8d2c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-13540.yml
@@ -0,0 +1,6 @@
+author: "ArcaneMusic, The0bserver-sys"
+delete-after: True
+changes:
+ - rscadd: "New from Hydrowear LLC: The Botanical Belt! This handy yellow belt lets you hold most of your botany gear, and a few beakers for reduced bag and floor clutter!"
+ - tweak: "Gives Hydrotrays plumbing pipes automatically, allowing you to make a self sustaining tray via plumbing."
+ - tweak: "Gives Service access to Bluespace Beakers, at last, gives Cargo, Science, and Medical the ability to construct reinforced plungers for use on lavaland."
diff --git a/icons/mob/actions/actions_changeling.dmi b/icons/mob/actions/actions_changeling.dmi
index ce6b81e13b..2f384c6119 100644
Binary files a/icons/mob/actions/actions_changeling.dmi and b/icons/mob/actions/actions_changeling.dmi differ
diff --git a/icons/mob/actions/actions_slime.dmi b/icons/mob/actions/actions_slime.dmi
index acf7a31c6e..59840650a5 100644
Binary files a/icons/mob/actions/actions_slime.dmi and b/icons/mob/actions/actions_slime.dmi differ
diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi
index 4ac82ca299..a25752c1d0 100644
Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index 44499649f9..b95c377e12 100644
Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ
diff --git a/icons/mob/icemoon/icemoon_monsters.dmi b/icons/mob/icemoon/icemoon_monsters.dmi
index 4f0b5df64a..02b39cc3c7 100644
Binary files a/icons/mob/icemoon/icemoon_monsters.dmi and b/icons/mob/icemoon/icemoon_monsters.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi
index 23d80af9ef..5ff248de68 100644
Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi
index 702c0299b5..0332e60fb5 100644
Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 23f0e2cc13..10b733bae4 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi
index 1c22a0ad1b..cdb2567268 100644
Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ
diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi
index 1a98872463..75fd20b856 100644
Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index c0f78ee604..0feb6a75db 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 8fbb2abe1e..4f650f8561 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/defibrillators.dmi b/icons/obj/defibrillators.dmi
new file mode 100644
index 0000000000..f838f40030
Binary files /dev/null and b/icons/obj/defibrillators.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 5a9e1e54b6..34f9867ee9 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/food/soupsalad.dmi b/icons/obj/food/soupsalad.dmi
index ca9c150480..c4d7c184b6 100644
Binary files a/icons/obj/food/soupsalad.dmi and b/icons/obj/food/soupsalad.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index c5aca2394f..9b73fa706b 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/supplypods.dmi b/icons/obj/supplypods.dmi
index d21da6d53a..68674c4006 100644
Binary files a/icons/obj/supplypods.dmi and b/icons/obj/supplypods.dmi differ
diff --git a/icons/obj/supplypods_32x32.dmi b/icons/obj/supplypods_32x32.dmi
new file mode 100644
index 0000000000..855132f649
Binary files /dev/null and b/icons/obj/supplypods_32x32.dmi differ
diff --git a/icons/radials/taperecorder.dmi b/icons/radials/taperecorder.dmi
new file mode 100644
index 0000000000..6230ab1363
Binary files /dev/null and b/icons/radials/taperecorder.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index ef738288f5..e8c764345e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -22,6 +22,7 @@
#include "code\__DEFINES\_protect.dm"
#include "code\__DEFINES\_tick.dm"
#include "code\__DEFINES\access.dm"
+#include "code\__DEFINES\actionspeed_modifiers.dm"
#include "code\__DEFINES\admin.dm"
#include "code\__DEFINES\antagonists.dm"
#include "code\__DEFINES\atmospherics.dm"
@@ -107,6 +108,7 @@
#include "code\__DEFINES\sight.dm"
#include "code\__DEFINES\sound.dm"
#include "code\__DEFINES\spaceman_dmm.dm"
+#include "code\__DEFINES\species.dm"
#include "code\__DEFINES\stat.dm"
#include "code\__DEFINES\stat_tracking.dm"
#include "code\__DEFINES\status_effects.dm"
@@ -327,6 +329,7 @@
#include "code\controllers\subsystem\materials.dm"
#include "code\controllers\subsystem\medals.dm"
#include "code\controllers\subsystem\minimaps.dm"
+#include "code\controllers\subsystem\minimum_spawns.dm"
#include "code\controllers\subsystem\minor_mapping.dm"
#include "code\controllers\subsystem\mobs.dm"
#include "code\controllers\subsystem\nightshift.dm"
@@ -340,6 +343,7 @@
#include "code\controllers\subsystem\radiation.dm"
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\research.dm"
+#include "code\controllers\subsystem\runechat.dm"
#include "code\controllers\subsystem\server_maint.dm"
#include "code\controllers\subsystem\shuttle.dm"
#include "code\controllers\subsystem\sounds.dm"
@@ -412,6 +416,7 @@
#include "code\datums\spawners_menu.dm"
#include "code\datums\tgs_event_handler.dm"
#include "code\datums\verbs.dm"
+#include "code\datums\view.dm"
#include "code\datums\weakrefs.dm"
#include "code\datums\world_topic.dm"
#include "code\datums\actions\beam_rifle.dm"
@@ -1349,6 +1354,10 @@
#include "code\game\turfs\simulated\wall\reinf_walls.dm"
#include "code\game\turfs\space\space.dm"
#include "code\game\turfs\space\transit.dm"
+#include "code\modules\actionspeed\_actionspeed_modifier.dm"
+#include "code\modules\actionspeed\modifiers\base.dm"
+#include "code\modules\actionspeed\modifiers\mood.dm"
+#include "code\modules\actionspeed\modifiers\status_effects.dm"
#include "code\modules\admin\admin.dm"
#include "code\modules\admin\admin_investigate.dm"
#include "code\modules\admin\admin_ranks.dm"
@@ -2541,9 +2550,10 @@
#include "code\modules\mob\living\carbon\human\status_procs.dm"
#include "code\modules\mob\living\carbon\human\typing_indicator.dm"
#include "code\modules\mob\living\carbon\human\update_icons.dm"
-#include "code\modules\mob\living\carbon\human\species_types\abductors.dm"
+#include "code\modules\mob\living\carbon\human\species_types\abductor.dm"
#include "code\modules\mob\living\carbon\human\species_types\android.dm"
#include "code\modules\mob\living\carbon\human\species_types\angel.dm"
+#include "code\modules\mob\living\carbon\human\species_types\anthromorph.dm"
#include "code\modules\mob\living\carbon\human\species_types\bugmen.dm"
#include "code\modules\mob\living\carbon\human\species_types\corporate.dm"
#include "code\modules\mob\living\carbon\human\species_types\dullahan.dm"
@@ -2551,7 +2561,6 @@
#include "code\modules\mob\living\carbon\human\species_types\ethereal.dm"
#include "code\modules\mob\living\carbon\human\species_types\felinid.dm"
#include "code\modules\mob\living\carbon\human\species_types\flypeople.dm"
-#include "code\modules\mob\living\carbon\human\species_types\furrypeople.dm"
#include "code\modules\mob\living\carbon\human\species_types\golems.dm"
#include "code\modules\mob\living\carbon\human\species_types\humans.dm"
#include "code\modules\mob\living\carbon\human\species_types\ipc.dm"
@@ -2749,6 +2758,7 @@
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\hivelord.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\ice_demon.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\ice_whelp.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\lobsterosity.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\polarbear.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\wolf.dm"
diff --git a/tgui/packages/tgui/interfaces/CentcomPodLauncher.js b/tgui/packages/tgui/interfaces/CentcomPodLauncher.js
index 05982b2fbf..a0d507e154 100644
--- a/tgui/packages/tgui/interfaces/CentcomPodLauncher.js
+++ b/tgui/packages/tgui/interfaces/CentcomPodLauncher.js
@@ -1,518 +1,1135 @@
+import { toFixed } from 'common/math';
+import { classes } from 'common/react';
+import { storage } from 'common/storage';
import { multiline } from 'common/string';
-import { Fragment } from 'inferno';
-import { useBackend } from '../backend';
-import { Button, LabeledList, NoticeBox, Section } from '../components';
+import { createUuid } from 'common/uuid';
+import { Component } from 'inferno';
+import { useBackend, useLocalState } from '../backend';
+import { Box, Button, ByondUi, Divider, Flex, Fragment, Input, Knob, LabeledControls, NumberInput, Section } from '../components';
import { Window } from '../layouts';
-export const CentcomPodLauncher = () => {
+const pod_grey = {
+ color: 'grey',
+};
+
+const useCompact = context => {
+ const [compact, setCompact] = useLocalState(context, 'compact', false);
+ const toggleCompact = () => setCompact(!compact);
+ return [compact, toggleCompact];
+};
+
+export const CentcomPodLauncher = (props, context) => {
+ const [compact] = useCompact(context);
return (
+ blueprint pod and edit vars directly
+
+
+ NOTE: Custom sounds from outside the base game files will not save! :(
+
+
/gi,"\n").replace(/<\/?[a-z0-9-_]+[^>]*>/gi,"").replace(/&(nbsp|amp|quot|lt|gt|apos);/g,(function(e,n){return t[n]})).replace(/?([0-9]+);/gi,(function(e,t){var n=parseInt(t,10);return String.fromCharCode(n)})).replace(/?([0-9a-f]+);/gi,(function(e,t){var n=parseInt(t,16);return String.fromCharCode(n)}))};t.buildQueryString=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,n){"use strict";var r={}.hasOwnProperty;e.exports=function(e,t){return r.call(e,t)}},function(e,t,n){"use strict";var r=n(53),o=n(66),i=n(18),a=n(12),c=n(72),u=[].push,s=function(e){var t=1==e,n=2==e,s=3==e,l=4==e,f=6==e,d=5==e||f;return function(p,h,g,v){for(var m,y,b=i(p),x=o(b),w=r(h,g,3),_=a(x.length),E=0,k=v||c,S=t?k(p,_):n?k(p,0):undefined;_>E;E++)if((d||E in x)&&(y=w(m=x[E],E,b),e))if(t)S[E]=y;else if(y)switch(e){case 3:return!0;case 5:return m;case 6:return E;case 2:u.call(S,m)}else if(l)return!1;return f?-1:s||l?l:S}};e.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6)}},function(e,t,n){"use strict";t.__esModule=!0,t.useSelector=t.useDispatch=t.createAction=t.combineReducers=t.applyMiddleware=t.createStore=void 0;n(0);var r=n(35);function o(e,t){var n;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return i(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return i(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(n=e[Symbol.iterator]()).next.bind(n)}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nu||n!=n?l*Infinity:l*n}},function(e,t,n){"use strict";var r=n(7).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&r(e)}},function(e,t,n){"use strict";var r=n(7),o=n(62).trim,i=n(92),a=r.parseFloat,c=1/a(i+"-0")!=-Infinity;e.exports=c?function(e){var t=o(String(e)),n=a(t);return 0===n&&"-"==t.charAt(0)?-0:n}:a},function(e,t,n){"use strict";var r=n(36);e.exports=function(e){if("number"!=typeof e&&"Number"!=r(e))throw TypeError("Incorrect invocation");return+e}},function(e,t,n){"use strict";var r=n(9),o=n(5),i=n(71),a=n(115),c=n(82),u=n(18),s=n(66),l=Object.assign,f=Object.defineProperty;e.exports=!l||o((function(){if(r&&1!==l({b:1},l(f({},"a",{enumerable:!0,get:function(){f(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol();return e[n]=7,"abcdefghijklmnopqrst".split("").forEach((function(e){t[e]=e})),7!=l({},e)[n]||"abcdefghijklmnopqrst"!=i(l({},t)).join("")}))?function(e,t){for(var n=u(e),o=arguments.length,l=1,f=a.f,d=c.f;o>l;)for(var p,h=s(arguments[l++]),g=f?i(h).concat(f(h)):i(h),v=g.length,m=0;v>m;)p=g[m++],r&&!d.call(h,p)||(n[p]=h[p]);return n}:l},function(e,t,n){"use strict";var r=n(121),o=n(85);e.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},function(e,t,n){"use strict";var r=n(7);e.exports=function(e,t){var n=r.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},function(e,t,n){"use strict";var r=n(37);e.exports=function(e){var t=r(e);if(t<0)throw RangeError("The argument can't be less than 0");return t}},function(e,t,n){"use strict";t.__esModule=!0,t._CI=Ae,t._HI=B,t._M=Te,t._MCCC=Le,t._ME=Ie,t._MFCC=Ve,t._MP=Ce,t._MR=ye,t.__render=je,t.createComponentVNode=function(e,t,n,r,o){var a=new T(1,null,null,e=function(e,t){if(12&e)return e;if(t.prototype&&t.prototype.render)return 4;if(t.render)return 32776;return 8}(e,t),r,function(e,t,n){var r=(32768&e?t.render:t).defaultProps;if(i(r))return n;if(i(n))return l(r,null);return N(n,r)}(e,t,n),function(e,t,n){if(4&e)return n;var r=(32768&e?t.render:t).defaultHooks;if(i(r))return n;if(i(n))return r;return N(n,r)}(e,t,o),t);k.createVNode&&k.createVNode(a);return a},t.createFragment=M,t.createPortal=function(e,t){var n=B(e);return O(1024,1024,null,n,0,null,n.key,t)},t.createRef=function(){return{current:null}},t.createRenderer=function(e){return function(t,n,r,o){e||(e=t),Fe(n,e,r,o)}},t.createTextVNode=I,t.createVNode=O,t.directClone=L,t.findDOMfromVNode=b,t.forwardRef=function(e){return{render:e}},t.getFlagsForElementVnode=function(e){switch(e){case"svg":return 32;case"input":return 64;case"select":return 256;case"textarea":return 128;case"$F":return 8192;default:return 1}},t.linkEvent=function(e,t){if(c(t))return{data:e,event:t};return null},t.normalizeProps=function(e){var t=e.props;if(t){var n=e.flags;481&n&&(void 0!==t.children&&i(e.children)&&P(e,t.children),void 0!==t.className&&(e.className=t.className||null,t.className=undefined)),void 0!==t.key&&(e.key=t.key,t.key=undefined),void 0!==t.ref&&(e.ref=8&n?l(e.ref,t.ref):t.ref,t.ref=undefined)}return e},t.render=Fe,t.rerender=He,t.version=t.options=t.Fragment=t.EMPTY_OBJ=t.Component=void 0;var r=Array.isArray;function o(e){var t=typeof e;return"string"===t||"number"===t}function i(e){return null==e}function a(e){return null===e||!1===e||!0===e||void 0===e}function c(e){return"function"==typeof e}function u(e){return"string"==typeof e}function s(e){return null===e}function l(e,t){var n={};if(e)for(var r in e)n[r]=e[r];if(t)for(var o in t)n[o]=t[o];return n}function f(e){return!s(e)&&"object"==typeof e}var d={};t.EMPTY_OBJ=d;function p(e){return e.substr(2).toLowerCase()}function h(e,t){e.appendChild(t)}function g(e,t,n){s(n)?h(e,t):e.insertBefore(t,n)}function v(e,t){e.removeChild(t)}function m(e){for(var t=0;t
\n":"'+(n?e:Y(e,!0))+"
\n"},t.blockquote=function(e){return""+(n?e:Y(e,!0))+"\n"+e+"
\n"},t.html=function(e){return e},t.heading=function(e,t,n,r){return this.options.headerIds?"
\n":"
\n"},t.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+""+r+">\n"},t.listitem=function(e){return"\n\n"+e+"\n"+t+"
\n"},t.tablerow=function(e){return"\n"+e+" \n"},t.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+""+n+">\n"},t.strong=function(e){return""+e+""},t.em=function(e){return""+e+""},t.codespan=function(e){return""+e+""},t.br=function(){return this.options.xhtml?"
":"
"},t.del=function(e){return""+e+""},t.link=function(e,t,n){if(null===(e=z(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"+n+""},t.image=function(e,t,n){if(null===(e=z(this.options.sanitize,this.options.baseUrl,e)))return n;var r='":">"},t.text=function(e){return e},e}(),$=function(){function e(){}var t=e.prototype;return t.strong=function(e){return e},t.em=function(e){return e},t.codespan=function(e){return e},t.del=function(e){return e},t.html=function(e){return e},t.text=function(e){return e},t.link=function(e,t,n){return""+n},t.image=function(e,t,n){return""+n},t.br=function(){return""},e}(),H=function(){function e(){this.seen={}}return e.prototype.slug=function(e){var t=e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+"-"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t},e}(),W=r.defaults,q=w.unescape,G=function(){function e(e){this.options=e||W,this.options.renderer=this.options.renderer||new U,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new $,this.slugger=new H}e.parse=function(t,n){return new e(n).parse(t)};var t=e.prototype;return t.parse=function(e,t){void 0===t&&(t=!0);var n,r,o,i,a,c,u,s,l,f,d,p,h,g,v,m,y,b,x="",w=e.length;for(n=0;n
"+Q(u.message+"",!0)+"";throw u}}return ne.options=ne.setOptions=function(e){return X(ne.defaults,e),ee(ne.defaults),ne},ne.getDefaults=J,ne.defaults=te,ne.use=function(e){var t=X({},e);if(e.renderer&&function(){var n=ne.defaults.renderer||new U,r=function(t){var r=n[t];n[t]=function(){for(var o=arguments.length,i=new Array(o),a=0;a
'+(n?e:Y(e,!0))+"\n":""+(n?e:Y(e,!0))+"\n"},t.blockquote=function(e){return"\n"+e+"\n"},t.html=function(e){return e},t.heading=function(e,t,n,r){return this.options.headerIds?"
"+e+"
\n"},t.table=function(e,t){return t&&(t=""+t+""),""+e+""},t.br=function(){return this.options.xhtml?""+Q(u.message+"",!0)+"";throw u}}return ne.options=ne.setOptions=function(e){return X(ne.defaults,e),ee(ne.defaults),ne},ne.getDefaults=J,ne.defaults=te,ne.use=function(e){var t=X({},e);if(e.renderer&&function(){var n=ne.defaults.renderer||new U,r=function(t){var r=n[t];n[t]=function(){for(var o=arguments.length,i=new Array(o),a=0;a
'+(n?e:Y(e,!0))+"\n":""+(n?e:Y(e,!0))+"\n"},t.blockquote=function(e){return"\n"+e+"\n"},t.html=function(e){return e},t.heading=function(e,t,n,r){return this.options.headerIds?"
"+e+"
\n"},t.table=function(e,t){return t&&(t=""+t+""),""+e+""},t.br=function(){return this.options.xhtml?""+Q(u.message+"",!0)+"";throw u}}return ne.options=ne.setOptions=function(e){return X(ne.defaults,e),ee(ne.defaults),ne},ne.getDefaults=J,ne.defaults=te,ne.use=function(e){var t=X({},e);if(e.renderer&&function(){var n=ne.defaults.renderer||new U,r=function(t){var r=n[t];n[t]=function(){for(var o=arguments.length,i=new Array(o),a=0;a