diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 2bdc6ed1dd..f50c765385 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -3953,7 +3953,6 @@
/area/service/bar)
"ann" = (
/obj/effect/spawner/lootdrop/maintenance,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/port/fore)
"ano" = (
@@ -4154,12 +4153,17 @@
/obj/item/radio/intercom{
pixel_y = 25
},
+/obj/structure/rack,
+/obj/item/storage/briefcase,
/turf/open/floor/wood,
/area/service/lawoffice)
"aoc" = (
/obj/machinery/airalarm{
pixel_y = 23
},
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
/turf/open/floor/wood,
/area/service/lawoffice)
"aod" = (
@@ -4859,6 +4863,9 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 8
},
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/wood,
/area/service/lawoffice)
"aqa" = (
@@ -4866,9 +4873,16 @@
/turf/open/floor/carpet,
/area/commons/dorms)
"aqb" = (
-/obj/structure/rack,
-/obj/item/storage/briefcase,
/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/machinery/power/apc{
+ areastring = "/area/service/lawoffice";
+ dir = 1;
+ name = "Law Office APC";
+ pixel_y = 23
+ },
+/obj/structure/cable{
+ icon_state = "0-8"
+ },
/turf/open/floor/wood,
/area/service/lawoffice)
"aqc" = (
@@ -5175,15 +5189,6 @@
/obj/structure/disposalpipe/segment,
/turf/open/floor/plasteel/showroomfloor,
/area/security/warden)
-"aqO" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"aqP" = (
/obj/structure/cable{
icon_state = "1-8"
@@ -5503,9 +5508,6 @@
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
"asc" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/obj/structure/cable{
icon_state = "2-8"
},
@@ -5543,15 +5545,6 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"asi" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 10
- },
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"ask" = (
/obj/item/flashlight/lamp/green{
pixel_x = -2;
@@ -5575,6 +5568,9 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
/turf/open/floor/plating,
/area/maintenance/fore)
"asq" = (
@@ -6378,19 +6374,6 @@
/obj/effect/decal/cleanable/dirt/dust,
/turf/open/floor/wood,
/area/maintenance/port/fore)
-"avi" = (
-/obj/machinery/power/apc{
- areastring = "/area/service/lawoffice";
- dir = 1;
- name = "Law Office APC";
- pixel_y = 23
- },
-/obj/structure/cable{
- icon_state = "0-2"
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/fore)
"avj" = (
/obj/machinery/firealarm{
dir = 4;
@@ -7190,16 +7173,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
-"ayh" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"ayi" = (
/obj/structure/cable{
icon_state = "1-4"
@@ -7525,7 +7498,6 @@
name = "Garden Maintenance";
req_access_txt = "12"
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/port/fore)
"azq" = (
@@ -8062,9 +8034,6 @@
/obj/item/seeds/watermelon,
/obj/structure/table/glass,
/obj/item/seeds/tower,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/turf/open/floor/plasteel,
/area/service/hydroponics/garden)
"aBB" = (
@@ -8083,9 +8052,7 @@
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
"aBG" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 8
- },
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
/turf/open/floor/plasteel,
/area/service/hydroponics/garden)
"aBH" = (
@@ -8892,6 +8859,9 @@
/obj/machinery/door/airlock{
name = "Garden"
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/service/hydroponics/garden)
"aEM" = (
@@ -41348,12 +41318,12 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
- dir = 4
- },
/obj/structure/cable{
icon_state = "1-4"
},
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 10
+ },
/turf/open/floor/plating,
/area/maintenance/port/fore)
"cwS" = (
@@ -42331,11 +42301,6 @@
},
/turf/open/floor/plasteel,
/area/medical/surgery)
-"cCs" = (
-/obj/structure/closet/emcloset,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"cCt" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance{
@@ -45161,6 +45126,9 @@
/obj/structure/cable{
icon_state = "1-2"
},
+/obj/structure/cable{
+ icon_state = "2-4"
+ },
/turf/open/floor/plating,
/area/maintenance/fore)
"eev" = (
@@ -45396,6 +45364,12 @@
"evR" = (
/turf/open/floor/plating,
/area/maintenance/bar)
+"ewb" = (
+/obj/structure/cable{
+ icon_state = "1-8"
+ },
+/turf/open/floor/wood,
+/area/service/lawoffice)
"ewu" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 6
@@ -47758,6 +47732,9 @@
dir = 4
},
/obj/effect/landmark/navigate_destination/lawyer,
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
/turf/open/floor/wood,
/area/service/lawoffice)
"gtZ" = (
@@ -49027,11 +49004,6 @@
/obj/structure/lattice,
/turf/closed/wall,
/area/maintenance/fore)
-"hCn" = (
-/obj/structure/closet/firecloset,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/turf/open/floor/plating,
-/area/maintenance/port/fore)
"hCp" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -49476,9 +49448,6 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
- },
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/maintenance/port/fore)
@@ -52542,26 +52511,6 @@
},
/turf/open/floor/plasteel,
/area/security/processing)
-"kHw" = (
-/obj/machinery/door/airlock/security/glass{
- id_tag = "innerbrig";
- name = "Brig";
- req_access_txt = "1"
- },
-/obj/machinery/door/firedoor,
-/obj/effect/mapping_helpers/airlock/cyclelink_helper,
-/obj/effect/turf_decal/tile/red,
-/obj/effect/turf_decal/tile/red{
- dir = 4
- },
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/security/brig)
"kHN" = (
/obj/structure/chair{
dir = 1
@@ -55546,6 +55495,12 @@
},
/turf/open/floor/wood/wood_large,
/area/service/chapel/office)
+"nrS" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/wood,
+/area/service/lawoffice)
"nsf" = (
/obj/structure/cable/white{
icon_state = "0-2"
@@ -57441,19 +57396,6 @@
/obj/effect/landmark/blobstart,
/turf/open/floor/plating,
/area/maintenance/aft)
-"pbQ" = (
-/obj/structure/cable{
- icon_state = "4-8"
- },
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
-/obj/structure/cable{
- icon_state = "1-8"
- },
-/turf/open/floor/plating,
-/area/maintenance/fore)
"pcz" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
@@ -57860,6 +57802,15 @@
"pun" = (
/turf/open/floor/plasteel/freezer,
/area/security/prison/cells)
+"puO" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/storage/primary)
"pvJ" = (
/obj/structure/rack,
/obj/effect/spawner/lootdrop/maintenance{
@@ -62475,10 +62426,6 @@
/obj/structure/bookcase/random/religion,
/turf/open/floor/wood/wood_large,
/area/service/chapel/main)
-"tGO" = (
-/obj/machinery/power/apc/auto_name/west,
-/turf/closed/wall,
-/area/service/lawoffice)
"tHc" = (
/obj/machinery/door/airlock/grunge{
name = "Prison Visitation";
@@ -62737,6 +62684,12 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
+"tUc" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/turf/open/floor/wood,
+/area/service/lawoffice)
"tUd" = (
/obj/effect/turf_decal/tile/red{
dir = 4
@@ -64523,6 +64476,12 @@
},
/turf/open/floor/wood,
/area/maintenance/bar)
+"vzY" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/commons/storage/primary)
"vAI" = (
/obj/effect/turf_decal/siding/white{
dir = 1
@@ -81256,7 +81215,7 @@ alU
alU
alU
alU
-aqO
+auT
lPA
mUQ
kwY
@@ -81513,7 +81472,7 @@ alU
atM
atW
alU
-aqO
+auT
lPA
aCW
lPA
@@ -82027,7 +81986,7 @@ arO
amC
aom
ank
-aqO
+auT
alU
axf
ayu
@@ -82798,7 +82757,7 @@ alU
alU
alU
auY
-aqO
+auT
alU
alU
enJ
@@ -83312,17 +83271,17 @@ ali
aok
amC
anJ
-asi
-arH
-cCs
+auT
+alU
+aoX
ann
ann
-hCn
-cwS
-ayh
+avX
+amC
+asK
azi
-aAx
-aBm
+aAQ
+aAQ
aAQ
aAQ
aAQ
@@ -83836,7 +83795,7 @@ alU
asK
azF
aAS
-aFP
+aAQ
aAQ
aAQ
aAQ
@@ -84094,8 +84053,8 @@ asK
azF
aAU
aBG
-aAQ
-aAQ
+aAx
+aBm
aAQ
aAQ
aAQ
@@ -84352,7 +84311,7 @@ azF
aAP
aAP
aAP
-aAQ
+aFP
aFO
aHA
aIT
@@ -84866,7 +84825,7 @@ atN
aAV
aBQ
aDh
-aDo
+vzY
aFQ
aHe
aIN
@@ -85123,7 +85082,7 @@ cwS
aAN
aBL
aDd
-aDd
+puO
aFR
aDd
aDd
@@ -94881,8 +94840,8 @@ aph
arW
aso
auf
-avi
-pbQ
+ayJ
+auo
axy
ayS
jUT
@@ -95132,7 +95091,7 @@ aiX
anz
anz
aov
-tGO
+aph
aob
ara
arV
@@ -95391,9 +95350,9 @@ anz
aov
aph
aoc
-ata
+nrS
gtK
-ata
+ewb
auh
aph
awg
@@ -95647,7 +95606,7 @@ aqC
anz
aov
api
-ata
+tUc
dPR
arX
atc
@@ -96924,7 +96883,7 @@ jyO
ajC
akC
akX
-kHw
+alw
amJ
aoY
rCl
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 5176aad2ef..9913253ba6 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -53141,22 +53141,16 @@
/turf/closed/wall,
/area/medical/surgery)
"dsN" = (
-/obj/item/clothing/gloves/color/latex,
-/obj/item/clothing/suit/apron/surgical,
-/obj/item/clothing/mask/surgical,
-/obj/item/surgical_drapes,
-/obj/structure/table/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/effect/turf_decal/tile/blue{
dir = 1
},
+/obj/structure/closet/secure_closet/medical2,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dsO" = (
-/obj/item/retractor,
-/obj/item/hemostat,
/obj/structure/table/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -53168,14 +53162,16 @@
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/item/clothing/gloves/color/latex{
+ pixel_y = 10
+ },
+/obj/item/clothing/suit/apron/surgical,
+/obj/item/clothing/mask/surgical{
+ pixel_y = -6
+ },
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dsP" = (
-/obj/item/circular_saw,
-/obj/item/surgicaldrill{
- pixel_y = 5
- },
-/obj/structure/table/reinforced,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 1
},
@@ -53189,11 +53185,10 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/limbgrower,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dsQ" = (
-/obj/item/scalpel,
-/obj/item/cautery,
/obj/structure/table/reinforced,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -53207,6 +53202,13 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/item/clothing/gloves/color/latex{
+ pixel_y = 10
+ },
+/obj/item/clothing/suit/apron/surgical,
+/obj/item/clothing/mask/surgical{
+ pixel_y = -6
+ },
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dsR" = (
@@ -54364,9 +54366,6 @@
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dvF" = (
-/obj/machinery/computer/operating{
- dir = 4
- },
/obj/structure/cable/white{
icon_state = "4-8"
},
@@ -54383,10 +54382,11 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/table/reinforced,
+/obj/item/storage/backpack/duffelbag/med/surgery,
/turf/open/floor/plasteel,
/area/medical/surgery)
"dvG" = (
-/obj/structure/table/optable,
/obj/effect/decal/cleanable/blood/old,
/obj/structure/cable/white{
icon_state = "2-8"
@@ -54407,17 +54407,19 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/structure/table/reinforced,
+/obj/item/reagent_containers/spray/cleaner,
/turf/open/floor/plasteel,
/area/medical/surgery)
"dvH" = (
-/obj/machinery/holopad,
/obj/structure/cable/white{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
-/obj/effect/turf_decal/bot,
+/obj/structure/table/reinforced,
+/obj/item/storage/backpack/duffelbag/med/surgery,
/turf/open/floor/plasteel,
/area/medical/surgery)
"dvI" = (
@@ -55091,21 +55093,21 @@
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dxm" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 1
+ },
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dxn" = (
/obj/structure/cable/white{
icon_state = "1-2"
},
-/obj/effect/turf_decal/tile/blue,
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
+/obj/machinery/holopad,
+/obj/effect/turf_decal/bot,
+/turf/open/floor/plasteel,
/area/medical/surgery)
"dxo" = (
/obj/effect/turf_decal/tile/blue,
@@ -55704,7 +55706,6 @@
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"dyG" = (
-/obj/structure/closet/secure_closet/medical2,
/obj/structure/sign/poster/official/cleanliness{
pixel_x = -32
},
@@ -55718,25 +55719,12 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/turf/open/floor/plasteel/dark,
-/area/medical/surgery)
-"dyH" = (
+/obj/machinery/computer/operating{
+ dir = 1
+ },
/obj/machinery/status_display/ai{
pixel_y = -32
},
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 1
- },
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 4
- },
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
"dyI" = (
@@ -55762,12 +55750,10 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/structure/closet/crate/freezer/blood,
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
"dyJ" = (
-/obj/machinery/status_display/evac{
- pixel_y = -32
- },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -55778,7 +55764,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/structure/closet/crate/freezer/blood,
+/obj/structure/table/optable,
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
"dyK" = (
@@ -55797,7 +55783,12 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
-/obj/machinery/limbgrower,
+/obj/machinery/computer/operating{
+ dir = 1
+ },
+/obj/machinery/status_display/evac{
+ pixel_y = -32
+ },
/turf/open/floor/plasteel/dark,
/area/medical/surgery)
"dyL" = (
@@ -177579,7 +177570,7 @@ dsO
dtR
dvF
dxm
-dyH
+dyJ
dma
cPy
cPy
diff --git a/_maps/map_files/TauStation/TauStation.dmm b/_maps/map_files/TauStation/TauStation.dmm
index 4bb9112ea7..4d10f2a5f4 100644
--- a/_maps/map_files/TauStation/TauStation.dmm
+++ b/_maps/map_files/TauStation/TauStation.dmm
@@ -3070,6 +3070,12 @@
},
/turf/open/floor/plasteel/white,
/area/science/xenobiology)
+"baV" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/science)
"bbh" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/airalarm{
@@ -11271,6 +11277,7 @@
},
/obj/machinery/door/firedoor,
/obj/effect/mapping_helpers/airlock/cyclelink_helper,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/security/brig)
"dTD" = (
@@ -15587,6 +15594,18 @@
},
/turf/open/floor/plasteel,
/area/commons/dorms)
+"fsv" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/starboard)
"fsw" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 4
@@ -16469,12 +16488,10 @@
/turf/open/floor/plasteel/freezer,
/area/engineering/main)
"fHN" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 4
- },
/obj/effect/turf_decal/tile/blue{
dir = 1
},
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel,
/area/hallway/primary/aft)
"fHP" = (
@@ -17771,6 +17788,16 @@
dir = 4
},
/area/service/theater)
+"gdN" = (
+/obj/structure/cable{
+ icon_state = "4-8"
+ },
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/dark,
+/area/ai_monitored/command/storage/eva)
"gdR" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
@@ -18902,6 +18929,12 @@
},
/turf/open/floor/plasteel,
/area/hallway/secondary/exit/departure_lounge)
+"gBx" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
+/turf/open/floor/plasteel/white,
+/area/science)
"gBI" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
@@ -20199,6 +20232,7 @@
/area/hallway/primary/port)
"gWN" = (
/obj/effect/landmark/navigate_destination/eva,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/dark,
/area/ai_monitored/command/storage/eva)
"gWU" = (
@@ -20626,6 +20660,10 @@
},
/turf/open/floor/plasteel,
/area/commons/fitness/pool)
+"hfV" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel/dark,
+/area/ai_monitored/command/storage/eva)
"hgb" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 5
@@ -21076,6 +21114,9 @@
/area/command/heads_quarters/captain/private)
"hlw" = (
/obj/effect/landmark/event_spawn,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel/white,
/area/science)
"hlG" = (
@@ -29183,6 +29224,14 @@
/obj/machinery/door/poddoor/incinerator_atmos_aux,
/turf/open/floor/engine/vacuum,
/area/maintenance/disposal/incinerator)
+"kkl" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel,
+/area/hallway/primary/aft)
"kks" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/cable{
@@ -32072,6 +32121,13 @@
},
/turf/open/floor/plasteel/dark,
/area/service/chapel/main)
+"ljB" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/open/floor/plasteel,
+/area/hallway/primary/aft)
"ljD" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -34926,6 +34982,15 @@
},
/turf/open/floor/plasteel/dark,
/area/command/gateway)
+"mgC" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/starboard)
"mgN" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -38489,6 +38554,12 @@
},
/turf/open/floor/plating,
/area/engineering/atmos)
+"nnq" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/aft)
"nnU" = (
/obj/effect/spawner/structure/window,
/turf/open/floor/plating,
@@ -41729,12 +41800,12 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"owR" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 10
- },
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
"owU" = (
@@ -44050,6 +44121,18 @@
"poG" = (
/turf/closed/wall/r_wall,
/area/command/heads_quarters/hop)
+"poJ" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 9
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/starboard)
"poL" = (
/obj/structure/window/reinforced{
dir = 8
@@ -48055,6 +48138,12 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel/dark,
/area/service/chapel/main)
+"qKZ" = (
+/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel/white,
+/area/science)
"qLd" = (
/obj/structure/curtain,
/turf/open/floor/plasteel/white/side{
@@ -49896,6 +49985,15 @@
},
/turf/open/floor/plasteel,
/area/construction)
+"rqA" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 6
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/aft)
"rqE" = (
/obj/structure/reagent_dispensers/watertank,
/turf/open/floor/plasteel/dark,
@@ -51363,6 +51461,7 @@
req_access_txt = "19"
},
/obj/machinery/door/firedoor,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/dark,
/area/ai_monitored/command/storage/eva)
"rSV" = (
@@ -59779,6 +59878,12 @@
/obj/structure/reagent_dispensers/fueltank,
/turf/open/floor/plasteel,
/area/commons/storage/primary)
+"uKi" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 9
+ },
+/turf/open/floor/plasteel/white,
+/area/science)
"uKn" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/disposalpipe/segment,
@@ -62035,6 +62140,15 @@
initial_gas_mix = "o2=21.78;n2=82.36;TEMP=293"
},
/area/service/hydroponics/enclosure)
+"vyE" = (
+/obj/effect/turf_decal/stripes/line{
+ dir = 1
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/starboard)
"vyF" = (
/obj/structure/disposalpipe/segment,
/obj/structure/cable{
@@ -62475,6 +62589,9 @@
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
"vEQ" = (
@@ -63879,6 +63996,15 @@
},
/turf/open/floor/plasteel,
/area/engineering/atmos)
+"weT" = (
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/hallway/primary/aft)
"wfa" = (
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
@@ -101847,9 +101973,9 @@ snT
xmJ
tGd
gzq
-gzq
-gzq
-gzq
+rqA
+ljB
+kkl
fHN
tPs
xzv
@@ -102104,7 +102230,7 @@ xmJ
xmJ
tGd
xzv
-xzv
+nnq
xzv
xzv
sxj
@@ -102361,7 +102487,7 @@ nsR
xmJ
tGd
wVf
-wVf
+weT
wVf
wVf
wVf
@@ -102618,7 +102744,7 @@ wzB
xpx
tGO
tGO
-uZn
+brI
uZn
uZn
tGO
@@ -102875,7 +103001,7 @@ wzZ
pnq
tGO
xQm
-xfq
+baV
xfq
xfq
mcU
@@ -103132,7 +103258,7 @@ wzZ
mXv
tGO
xQA
-xfq
+baV
xfq
xfq
cfk
@@ -103646,7 +103772,7 @@ osB
tGO
xqj
xSI
-xfq
+baV
cqK
rWx
ejR
@@ -103897,13 +104023,13 @@ qBJ
unB
rkv
rLF
-stQ
-ygo
+mgC
+tnC
owR
kNN
xfq
-xfq
-xfq
+gBx
+uKi
mSt
xyJ
gzS
@@ -104154,12 +104280,12 @@ qUx
kXA
spt
rLF
-stQ
+vyE
ygo
bNF
brI
xfq
-xfq
+baV
uzk
mSt
hIM
@@ -104411,12 +104537,12 @@ qUx
qUx
uFH
rOu
-stQ
+vyE
vox
jpU
tpU
tHV
-tHV
+qKZ
rMv
mSt
hIM
@@ -104925,7 +105051,7 @@ qCy
qUj
rqE
rSV
-suO
+fsv
ygo
oDS
xNa
@@ -105176,13 +105302,13 @@ thT
nUe
rTi
qti
-pmj
-pSO
-qUx
-qUx
+plH
+gdN
+hfV
+hfV
gWN
rST
-suO
+poJ
ygo
ygo
vbA
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index da1b941bae..53de44a385 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -91,13 +91,13 @@
},
/area/holodeck/rec_center/lounge)
"ap" = (
-/turf/open/floor/holofloor/plating,
+/turf/open/floor/holofloor/basalt,
/area/holodeck/rec_center/wildlife)
"aq" = (
/turf/open/floor/holofloor/plating,
/area/holodeck/rec_center/offline)
"ar" = (
-/turf/open/floor/holofloor/plating/burnmix,
+/turf/open/indestructible/binary,
/area/holodeck/rec_center/burn)
"as" = (
/obj/effect/turf_decal/tile/red{
@@ -178,12 +178,12 @@
},
/area/holodeck/rec_center/lounge)
"aB" = (
-/obj/effect/holodeck_effect/mobspawner,
-/turf/open/floor/holofloor/plating,
+/obj/effect/holodeck_effect/mobspawner/funclaw,
+/turf/open/floor/holofloor/basalt,
/area/holodeck/rec_center/wildlife)
"aC" = (
/obj/effect/holodeck_effect/sparks,
-/turf/open/floor/holofloor/plating/burnmix,
+/turf/open/indestructible/binary,
/area/holodeck/rec_center/burn)
"aD" = (
/obj/effect/turf_decal/tile/red{
@@ -413,7 +413,7 @@
/turf/closed/indestructible/riveted,
/area/space)
"bk" = (
-/obj/effect/holodeck_effect/mobspawner/bee,
+/obj/effect/holodeck_effect/mobspawner/bumbles,
/turf/open/floor/holofloor/asteroid,
/area/holodeck/rec_center/anthophila)
"bl" = (
@@ -752,7 +752,7 @@
},
/area/holodeck/rec_center/medical)
"ce" = (
-/obj/effect/holodeck_effect/mobspawner/bee,
+/obj/effect/holodeck_effect/mobspawner/bumbles,
/obj/item/clothing/head/beekeeper_head,
/turf/open/floor/holofloor/asteroid,
/area/holodeck/rec_center/anthophila)
@@ -856,13 +856,13 @@
/turf/open/floor/holofloor,
/area/holodeck/rec_center/dodgeball)
"cq" = (
-/obj/effect/holodeck_effect/mobspawner/bee,
+/obj/effect/holodeck_effect/mobspawner/bumbles,
/obj/effect/decal/remains/human,
/obj/item/clothing/suit/beekeeper_suit,
/turf/open/floor/holofloor/asteroid,
/area/holodeck/rec_center/anthophila)
"cr" = (
-/obj/effect/holodeck_effect/mobspawner/bee,
+/obj/effect/holodeck_effect/mobspawner/bumbles,
/obj/item/melee/flyswatter,
/turf/open/floor/holofloor/asteroid,
/area/holodeck/rec_center/anthophila)
@@ -20270,6 +20270,9 @@
},
/turf/open/space,
/area/space)
+"Vy" = (
+/turf/open/chasm/lavaland,
+/area/holodeck/rec_center/wildlife)
"Vz" = (
/obj/machinery/vending/wallmed{
name = "Emergency NanoMed";
@@ -80911,16 +80914,16 @@ aa
"}
(232,1,1) = {"
ac
+Vy
+Vy
+Vy
ap
ap
ap
ap
-ap
-ap
-ap
-ap
-ap
-ap
+Vy
+Vy
+Vy
bj
bt
bI
@@ -81168,7 +81171,7 @@ aa
"}
(233,1,1) = {"
ac
-ap
+Vy
aB
ap
ap
@@ -81177,7 +81180,7 @@ ap
ap
ap
aB
-ap
+Vy
bj
Xg
TF
@@ -81425,7 +81428,7 @@ aa
"}
(234,1,1) = {"
ac
-ap
+Vy
ap
ap
ap
@@ -81434,7 +81437,7 @@ aB
ap
ap
ap
-ap
+Vy
bj
bu
bJ
@@ -81682,16 +81685,16 @@ aa
"}
(235,1,1) = {"
ac
-ap
-aB
+Vy
ap
ap
ap
ap
ap
ap
-aB
ap
+ap
+Vy
bj
bv
bK
@@ -81939,16 +81942,16 @@ aa
"}
(236,1,1) = {"
ac
-ap
-ap
-ap
-ap
-ap
-ap
-ap
-ap
-ap
-ap
+Vy
+Vy
+Vy
+Vy
+Vy
+Vy
+Vy
+Vy
+Vy
+Vy
bj
RD
Va
diff --git a/_maps/shuttles/cargo_kilo.dmm b/_maps/shuttles/cargo_kilo.dmm
index 86660a4dc7..b05f1c49de 100644
--- a/_maps/shuttles/cargo_kilo.dmm
+++ b/_maps/shuttles/cargo_kilo.dmm
@@ -51,6 +51,7 @@
id = "QMLoad";
name = "off ramp"
},
+/obj/structure/fans/tiny,
/turf/open/floor/plating,
/area/shuttle/supply)
"j" = (
@@ -82,6 +83,7 @@
dir = 4;
dwidth = 4
},
+/obj/structure/fans/tiny,
/turf/open/floor/mineral/plastitanium,
/area/shuttle/supply)
"n" = (
@@ -137,6 +139,7 @@
req_access_txt = "31"
},
/obj/effect/decal/cleanable/dirt,
+/obj/structure/fans/tiny,
/turf/open/floor/mineral/plastitanium,
/area/shuttle/supply)
"t" = (
@@ -149,6 +152,7 @@
id = "QMLoad2";
name = "on ramp"
},
+/obj/structure/fans/tiny,
/turf/open/floor/plating,
/area/shuttle/supply)
"u" = (
diff --git a/code/__DEFINES/_flags/item_flags.dm b/code/__DEFINES/_flags/item_flags.dm
index 529499127d..d28cb80bab 100644
--- a/code/__DEFINES/_flags/item_flags.dm
+++ b/code/__DEFINES/_flags/item_flags.dm
@@ -51,4 +51,4 @@
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
#define ORGAN_EDIBLE (1<<7) //is a snack? :D
-#define ORGAN_SYNTHETIC_EMP (1<<6) //Synthetic organ affected by an EMP. Deteriorates over time.
+#define ORGAN_SYNTHETIC_EMP (1<<8) //Synthetic organ affected by an EMP. Deteriorates over time.
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index c1a3583634..c9e31c672d 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -74,7 +74,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid))
#define isethereal(A) (is_species(A, /datum/species/ethereal))
#define isvampire(A) (is_species(A,/datum/species/vampire))
-#define isdullahan(A) (is_species(A, /datum/species/dullahan))
#define ismush(A) (is_species(A, /datum/species/mush))
#define isshadow(A) (is_species(A, /datum/species/shadow))
diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm
index 792708b5bb..182e58c1f7 100644
--- a/code/__DEFINES/loadout.dm
+++ b/code/__DEFINES/loadout.dm
@@ -7,6 +7,7 @@
//backpack
#define LOADOUT_CATEGORY_BACKPACK "In backpack"
#define LOADOUT_SUBCATEGORY_BACKPACK_GENERAL "General" //basically anything that there's not enough of to have its own subcategory
+#define LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES "Accessories" //maybe one day someone will make loadouts have accessory compatibility
#define LOADOUT_SUBCATEGORY_BACKPACK_TOYS "Toys"
//neck
#define LOADOUT_CATEGORY_NECK "Neck"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 19cb08de54..a8ea046657 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -279,9 +279,13 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
#define PDA_SKIN_MODERN "Modern"
#define PDA_SKIN_MINIMAL "Minimal"
-GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_SKIN_ALT = 'icons/obj/pda_alt.dmi',
- PDA_SKIN_RUGGED = 'icons/obj/pda_rugged.dmi', PDA_SKIN_MODERN = 'icons/obj/pda_modern.dmi',
- PDA_SKIN_MINIMAL = 'icons/obj/pda_minimal.dmi'))
+GLOBAL_LIST_INIT(pda_reskins, list(
+ PDA_SKIN_CLASSIC = list("icon" = 'icons/obj/pda.dmi'),
+ PDA_SKIN_ALT = list("icon" = 'icons/obj/pda_alt.dmi'),
+ PDA_SKIN_RUGGED = list("icon" = 'icons/obj/pda_rugged.dmi'),
+ PDA_SKIN_MODERN = list("icon" = 'icons/obj/pda_modern.dmi'),
+ PDA_SKIN_MINIMAL = list("icon" = 'icons/obj/pda_minimal.dmi')
+ ))
/////////////////////////////////////
// atom.appearence_flags shortcuts //
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 6db900d0e6..331ef3cca9 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -295,7 +295,8 @@
// 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 AGE_MAX 85 // oldest a character can be randomly generated
+#define AGE_MAX_INPUT 85 // oldest a character's age can be manually set
#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
diff --git a/code/__DEFINES/spans.dm b/code/__DEFINES/spans.dm
index c54af39d56..b6b633d91a 100644
--- a/code/__DEFINES/spans.dm
+++ b/code/__DEFINES/spans.dm
@@ -114,6 +114,3 @@
#define span_warning(str) ("" + str + " ")
#define span_yell(str) ("" + str + " ")
#define span_yellowteamradio(str) ("" + str + " ")
-
-//SANDSTORM DEFINES
-#define span_love(str) ("" + str + " ")
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 222dc5cd39..4e97723676 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -235,6 +235,8 @@
#define TRAIT_BEING_CARRIED "being_carried"
#define TRAIT_GLASS_BONES "glass_bones"
#define TRAIT_PAPER_SKIN "paper_skin"
+//used because it's more reliable than checking for the component
+#define TRAIT_DULLAHAN "dullahan"
// mobility flag traits
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
diff --git a/code/__HELPERS/weakref.dm b/code/__HELPERS/weakref.dm
new file mode 100644
index 0000000000..0b007332ef
--- /dev/null
+++ b/code/__HELPERS/weakref.dm
@@ -0,0 +1,2 @@
+/// Checks if potential_weakref is a weakref of thing.
+#define IS_WEAKREF_OF(thing, potential_weakref) (istype(thing, /datum) && !isnull(potential_weakref) && thing.weak_reference == potential_weakref)
diff --git a/code/__SPLURTCODE/DEFINES/spans.dm b/code/__SANDCODE/DEFINES/spans.dm
similarity index 67%
rename from code/__SPLURTCODE/DEFINES/spans.dm
rename to code/__SANDCODE/DEFINES/spans.dm
index 3a26809294..f8002c5e5a 100644
--- a/code/__SPLURTCODE/DEFINES/spans.dm
+++ b/code/__SANDCODE/DEFINES/spans.dm
@@ -1,2 +1,3 @@
-#define span_userlove(str) ("" + str + " ")
#define span_lewd(str) ("" + str + " ")
+#define span_love(str) ("" + str + " ")
+#define span_userlove(str) ("" + str + " ")
diff --git a/code/__SPLURTCODE/DEFINES/mobs.dm b/code/__SPLURTCODE/DEFINES/mobs.dm
index c8b92378d8..125f8fe8e5 100644
--- a/code/__SPLURTCODE/DEFINES/mobs.dm
+++ b/code/__SPLURTCODE/DEFINES/mobs.dm
@@ -2,3 +2,7 @@
#define PLAYER_READY_TO_OBSERVE 2
#define WENDIGO_BODYPART "wendigo"
+
+// Increase max age
+#undef AGE_MAX_INPUT
+#define AGE_MAX_INPUT SHORT_REAL_LIMIT // Maximum safe number
diff --git a/code/__SPLURTCODE/DEFINES/zeros/traits.dm b/code/__SPLURTCODE/DEFINES/zeros/traits.dm
index b1d1b3ef64..74a180621d 100644
--- a/code/__SPLURTCODE/DEFINES/zeros/traits.dm
+++ b/code/__SPLURTCODE/DEFINES/zeros/traits.dm
@@ -7,5 +7,6 @@
#define TRAIT_IN_HEAT "in_heat"
#define TRAIT_HEAT_DETECT "heat_detect"
#define TRAIT_ILLITERATE "illiterate"
+#define TRAIT_HIDE_BACKPACK "hide_backpack"
#define TRAIT_DUMB4CUM "dumb4cum"
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 2ca3a0a15b..8e00b1e0fa 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -209,7 +209,8 @@ GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFELBAG, //everything
"Grey Satchel" = /obj/item/storage/backpack/satchel,
"Grey Duffel Bag" = /obj/item/storage/backpack/duffelbag,
"Leather Satchel" = /obj/item/storage/backpack/satchel/leather,
- "Snail Shell" = /obj/item/storage/backpack/snail))
+ "Snail Shell" = /obj/item/storage/backpack/snail,
+ "Sloog Shell" = /obj/item/storage/backpack/sloogshell))
//Suit/Skirt
#define PREF_SUIT "Jumpsuit"
@@ -378,7 +379,7 @@ GLOBAL_LIST_INIT(job_heirlooms, list(
GLOBAL_LIST_INIT(nongendered_limb_types, list("fly", "zombie" ,"synth", "shadow", "cultgolem", "agent", "plasmaman", "clockgolem", "clothgolem"))
//list of eye types, corresponding to a respective left and right icon state for the set of eyes
-GLOBAL_LIST_INIT(eye_types, list("normal", "insect", "moth", "double", "double2", "double3", "spider", "cyclops", "third", "spectre", "shadekin"))
+GLOBAL_LIST_INIT(eye_types, list("normal", "insect", "moth", "double", "double2", "double3", "spider", "cyclops", "third", "spectre", "shadekin", "none"))
//list linking bodypart bitflags to their actual names
GLOBAL_LIST_INIT(bodypart_names, list(num2text(HEAD) = "Head", num2text(CHEST) = "Chest", num2text(LEG_LEFT) = "Left Leg", num2text(LEG_RIGHT) = "Right Leg", num2text(ARM_LEFT) = "Left Arm", num2text(ARM_RIGHT) = "Right Arm"))
diff --git a/code/_globalvars/lists/loadout_categories.dm b/code/_globalvars/lists/loadout_categories.dm
index c27b3c29e3..371e09392b 100644
--- a/code/_globalvars/lists/loadout_categories.dm
+++ b/code/_globalvars/lists/loadout_categories.dm
@@ -1,5 +1,5 @@
GLOBAL_LIST_INIT(loadout_categories, list(
- LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_TOYS),
+ LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES, LOADOUT_SUBCATEGORY_BACKPACK_TOYS),
LOADOUT_CATEGORY_NECK = list(LOADOUT_SUBCATEGORY_NECK_GENERAL, LOADOUT_SUBCATEGORY_NECK_TIE, LOADOUT_SUBCATEGORY_NECK_SCARVES),
LOADOUT_CATEGORY_MASK = LOADOUT_SUBCATEGORIES_NONE,
LOADOUT_CATEGORY_HANDS = LOADOUT_SUBCATEGORIES_NONE,
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index c9e20bc01a..6e8d1de955 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -405,7 +405,7 @@
return
/atom/proc/CtrlShiftClick(mob/user)
- SEND_SIGNAL(src, COMSIG_CLICK_CTRL_SHIFT)
+ SEND_SIGNAL(src, COMSIG_CLICK_CTRL_SHIFT, user)
return
/*
diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm
index 0b820fe7e9..3231cd31bc 100644
--- a/code/controllers/subsystem/statpanel.dm
+++ b/code/controllers/subsystem/statpanel.dm
@@ -18,6 +18,7 @@ SUBSYSTEM_DEF(statpanels)
"Map: [SSmapping.config?.map_name || "Loading..."]",
cached ? "Next Map: [cached.map_name]" : null,
"Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
+ "Game Mode: [GLOB.master_mode]",
"Connected Players: [GLOB.clients.len]",
" ",
"OOC: [GLOB.ooc_allowed ? "Enabled" : "Disabled"]",
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 2ff1e284d0..47efc967ac 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -87,6 +87,7 @@ SUBSYSTEM_DEF(throwing)
if(HAS_TRAIT_FROM(thrownthing, TRAIT_SPOOKY_THROW, "revenant"))
REMOVE_TRAIT(thrownthing, TRAIT_SPOOKY_THROW, "revenant")
SSthrowing.processing -= thrownthing
+ SSthrowing.currentrun -= thrownthing
thrownthing.throwing = null
thrownthing = null
target = null
diff --git a/code/datums/accents.dm b/code/datums/accents.dm
index d9e073b729..cfd6e873fa 100644
--- a/code/datums/accents.dm
+++ b/code/datums/accents.dm
@@ -94,10 +94,9 @@
/datum/accent/dullahan/modify_speech(list/speech_args, datum/source, mob/living/carbon/owner)
if(owner)
- if(isdullahan(owner))
- var/datum/species/dullahan/D = owner.dna.species
- if(isobj(D.myhead.loc))
- var/obj/O = D.myhead.loc
- O.say(speech_args[SPEECH_MESSAGE])
+ var/datum/component/dullahan/dullahan = owner.GetComponent(/datum/component/dullahan)
+ if(dullahan)
+ if(dullahan.dullahan_head)
+ dullahan.dullahan_head.say(speech_args[SPEECH_MESSAGE])
speech_args[SPEECH_MESSAGE] = ""
return speech_args
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 304aa47baa..b34cafc03f 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -43,8 +43,7 @@
if(owner)
Remove(owner)
target = null
- qdel(button)
- button = null
+ QDEL_NULL(button)
return ..()
/datum/action/proc/Grant(mob/M)
diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm
index 75d00bbfcd..7dbbf01a1d 100644
--- a/code/datums/components/crafting/recipes/recipes_clothing.dm
+++ b/code/datums/components/crafting/recipes/recipes_clothing.dm
@@ -287,7 +287,7 @@
name = "Durathread Reinforcement Kit"
result = /obj/item/armorkit
reqs = list(/obj/item/stack/sheet/durathread = 4)
- tools = list(/obj/item/stack/sheet/mineral/titanium, TOOL_WIRECUTTER) // tough needle for a tough fabric
+ tools = list(TOOL_WIRECUTTER)
time = 40
category = CAT_CLOTHING
diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm
new file mode 100644
index 0000000000..973f06a61e
--- /dev/null
+++ b/code/datums/components/dullahan.dm
@@ -0,0 +1,210 @@
+/datum/component/dullahan
+ var/obj/item/dullahan_head/dullahan_head
+
+/datum/component/dullahan/Initialize()
+ . = ..()
+
+ var/mob/living/carbon/human/H = parent
+ if(!H)
+ return .
+
+ ADD_TRAIT(H, TRAIT_DULLAHAN, "dullahan_component")
+ ADD_TRAIT(H, TRAIT_NOHUNGER, "dullahan_component_no_hunger")
+ ADD_TRAIT(H, TRAIT_NOBREATH, "dullahan_component_no_breath")
+
+ dullahan_head = new(get_turf(H))
+
+ update_name()
+
+ dullahan_head.owner = H
+ RegisterSignal(H, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
+
+ // make sure the brain can't decay or fall out
+ var/obj/item/organ/brain/B = H.getorganslot(ORGAN_SLOT_BRAIN)
+ if(B)
+ B.zone = "abstract" // it exists in the ethereal plain
+ B.organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT | ORGAN_VITAL
+ dullahan_head.B = B
+
+ // the eyes get similar treatment
+ var/obj/item/organ/eyes/dullahan/new_eyes = new()
+ var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES)
+ if(E)
+ new_eyes.left_eye_color = E.left_eye_color
+ new_eyes.right_eye_color = E.right_eye_color
+ E.Remove()
+ qdel(E)
+ new_eyes.Insert(H)
+
+ // make sure you handle the tongue correctly, too!
+ var/obj/item/organ/tongue/T = H.getorganslot(ORGAN_SLOT_TONGUE)
+ T.Remove()
+ qdel(T)
+
+ var/obj/item/organ/tongue/dullahan/new_tongue = new()
+ new_tongue.Insert(H)
+
+ // uh, eyes!
+ var/obj/item/organ/ears/dullahan_ears = H.getorganslot(ORGAN_SLOT_EARS)
+ if(dullahan_ears)
+ dullahan_ears.zone = "abstract"
+
+ // moving the brain's zone means we don't need the head to survive
+ var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD)
+ if(head)
+ head.drop_limb()
+ qdel(head)
+
+ H.flags_1 &= ~(HEAR_1)
+
+ RegisterSignal(dullahan_head, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
+
+ dullahan_head.update_appearance()
+
+/datum/component/dullahan/proc/update_name(retries = 0)
+ if(retries > 30)
+ return FALSE
+ var/mob/living/carbon/human/H = parent
+ if(length(H.name))
+ dullahan_head.name = "[H.name]'s head"
+ dullahan_head.desc = "the decapitated head of [H.name]"
+ return TRUE
+ addtimer(CALLBACK(src, .proc/update_name, retries + 1), 2 SECONDS)
+
+/datum/component/dullahan/proc/include_owner(datum/source, list/processing_list, list/hearers)
+ if(!QDELETED(parent))
+ hearers += parent
+
+/datum/component/dullahan/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
+ excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
+
+/obj/item/organ/tongue/dullahan
+ zone = "abstract"
+ initial_accents = list(/datum/accent/dullahan)
+ organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT
+
+/obj/item/organ/eyes/dullahan
+ name = "head vision"
+ desc = "An abstraction."
+ actions_types = list(/datum/action/item_action/organ_action/dullahan)
+ zone = "abstract"
+ tint = INFINITY // used to switch the vision perspective to the head on species_gain().
+ organ_flags = ORGAN_NO_SPOIL | ORGAN_NO_DISMEMBERMENT
+
+/obj/item/dullahan_head
+ name = "coders lament"
+ desc = "you shouldn't be reading this"
+ flags_1 = HEAR_1
+ var/mob/living/carbon/human/owner
+ // this is for keeping track of the overlays because you can't read the actual overlays list as it's a special byond var
+ var/list/overlays_standing
+ var/obj/item/organ/brain/B
+ w_class = WEIGHT_CLASS_BULKY
+
+/obj/item/dullahan_head/Destroy()
+ if(owner)
+ B.Remove()
+ B.forceMove(get_turf(src))
+ owner.gib()
+ . = ..()
+
+// update head sprite
+/obj/item/dullahan_head/proc/remove_head_overlays()
+ overlays_standing = list()
+ cut_overlays()
+
+/obj/item/dullahan_head/proc/add_head_overlay(var/overlay)
+ overlays_standing += overlay
+ add_overlay(overlay)
+
+/obj/item/dullahan_head/update_appearance()
+ if(owner && !HAS_TRAIT(owner, TRAIT_HUMAN_NO_RENDER))
+ remove_head_overlays()
+ // to do this without duplicating large amounts of code
+ // it's best to regenerate the head, then remove it once we have the overlays we want
+ owner.regenerate_limb(BODY_ZONE_HEAD, TRUE) // don't heal them
+ owner.cut_overlays()
+ owner.regenerate_icons(TRUE) // yes i know it's expensive but do you want me to rewrite our entire overlay system, also block recursive calls here by passing in TRUE (it wont go back to call update_appearance this way)
+ var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD)
+ if(head)
+ add_overlay(head.get_limb_icon(FALSE, TRUE, TRUE))
+ for(var/overlay in owner.overlays_standing)
+ if(istype(overlay, /mutable_appearance))
+ var/mutable_appearance/mutable = overlay
+ if(mutable.category == "HEAD")
+ add_head_overlay(mutable)
+ else
+ if(islist(overlay))
+ var/list/list_appearances = overlay
+ for(var/overlay2 in list_appearances)
+ if(istype(overlay2, /mutable_appearance))
+ var/mutable_appearance/mutable = overlay2
+ if(mutable.category == "HEAD")
+ add_head_overlay(mutable)
+ head.drop_limb()
+ qdel(head)
+
+/obj/item/dullahan_head/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
+ excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
+
+/datum/action/item_action/organ_action/dullahan
+ name = "Toggle Perspective"
+ desc = "Switch between seeing normally from your head, or blindly from your body."
+
+/datum/action/item_action/organ_action/dullahan/Trigger()
+ . = ..()
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/organ/eyes/E = owner.getorganslot(ORGAN_SLOT_EYES)
+ if(E)
+ if(E.tint)
+ E.tint = 0
+ else
+ E.tint = INFINITY
+
+ var/datum/component/dullahan/D = H.GetComponent(/datum/component/dullahan)
+ if(D)
+ D.update_vision_perspective()
+
+/datum/component/dullahan/proc/update_vision_perspective()
+ var/mob/living/carbon/human/H = parent
+ if(!H)
+ return .
+ var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
+ if(eyes)
+ H.update_tint()
+ if(eyes.tint)
+ H.reset_perspective(H)
+ else
+ H.reset_perspective(dullahan_head)
+
+/datum/component/dullahan/Destroy()
+ UnregisterSignal(parent, COMSIG_LIVING_REGENERATE_LIMBS)
+ dullahan_head.owner = null
+ qdel(dullahan_head)
+ REMOVE_TRAIT(parent, TRAIT_DULLAHAN, "dullahan_component")
+
+ // work out what organs to give them based on their species
+ if(ishuman(parent))
+ var/mob/living/carbon/human/H = parent
+ var/obj/item/organ/eyes/new_eyes = new H.dna.species.mutanteyes()
+ var/obj/item/organ/brain/new_brain = new H.dna.species.mutant_brain()
+ var/obj/item/organ/tongue/new_tongue = new H.dna.species.mutanttongue()
+ var/obj/item/organ/eyes/old_eyes = H.getorganslot(ORGAN_SLOT_EYES)
+ var/obj/item/organ/brain/old_brain = H.getorganslot(ORGAN_SLOT_BRAIN)
+ var/obj/item/organ/tongue/old_tongue = H.getorganslot(ORGAN_SLOT_TONGUE)
+
+ H.regenerate_limb(BODY_ZONE_HEAD, TRUE)
+ H.reset_perspective(H)
+
+ old_brain.Remove(TRUE,TRUE)
+ QDEL_NULL(old_brain)
+ new_brain.Insert(H, TRUE, TRUE)
+
+ old_eyes.Remove(TRUE,TRUE)
+ QDEL_NULL(old_eyes)
+ new_eyes.Insert(H, TRUE, TRUE)
+
+ old_tongue.Remove(TRUE,TRUE)
+ QDEL_NULL(old_tongue)
+ new_tongue.Insert(H, TRUE, TRUE)
+ . = ..()
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index 9c542b505c..920886cc74 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -34,6 +34,7 @@
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/stop_processing)
RegisterSignal(parent, COMSIG_VOID_MASK_ACT, .proc/direct_sanity_drain)
+ RegisterSignal(parent, COMSIG_ENTER_AREA, .proc/update_beauty)
if(owner.hud_used)
@@ -355,7 +356,7 @@
if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS)
add_event(null, "charge", /datum/mood_event/supercharged)
-/datum/component/mood/proc/update_beauty(area/A)
+/datum/component/mood/proc/update_beauty(datum/source, area/A)
if(A.outdoors) //if we're outside, we don't care.
clear_event(null, "area_beauty")
return FALSE
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index b7761922da..0cc033cf2a 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -709,16 +709,13 @@
death()
petrify(INFINITY)
if(3)
- if(prob(90))
- var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD))
- if(BP)
- BP.dismember()
- else
- unequip_everything()
- drop_all_held_items()
- gib()
+ var/obj/item/bodypart/BP = get_bodypart(pick(BODY_ZONE_CHEST,BODY_ZONE_HEAD))
+ if(BP)
+ BP.dismember()
else
- set_species(/datum/species/dullahan)
+ unequip_everything()
+ drop_all_held_items()
+ gib()
/datum/dna/proc/update_body_size(old_size)
if(!holder || features["body_size"] == old_size)
diff --git a/code/datums/elements/connect_loc.dm b/code/datums/elements/connect_loc.dm
new file mode 100644
index 0000000000..fee9072f75
--- /dev/null
+++ b/code/datums/elements/connect_loc.dm
@@ -0,0 +1,43 @@
+/// This element hooks a signal onto the loc the current object is on.
+/// When the object moves, it will unhook the signal and rehook it to the new object.
+/datum/element/connect_loc
+ element_flags = ELEMENT_BESPOKE
+ id_arg_index = 2
+
+ /// An assoc list of signal -> procpath to register to the loc this object is on.
+ var/list/connections
+
+/datum/element/connect_loc/Attach(atom/movable/listener, list/connections)
+ . = ..()
+ if (!istype(listener))
+ return ELEMENT_INCOMPATIBLE
+
+ src.connections = connections
+
+ RegisterSignal(listener, COMSIG_MOVABLE_MOVED, .proc/on_moved, override = TRUE)
+ update_signals(listener)
+
+/datum/element/connect_loc/Detach(atom/movable/listener)
+ . = ..()
+ unregister_signals(listener, listener.loc)
+ UnregisterSignal(listener, COMSIG_MOVABLE_MOVED)
+
+/datum/element/connect_loc/proc/update_signals(atom/movable/listener)
+ var/atom/listener_loc = listener.loc
+ if(isnull(listener_loc))
+ return
+
+ for (var/signal in connections)
+ //override=TRUE because more than one connect_loc element instance tracked object can be on the same loc
+ listener.RegisterSignal(listener_loc, signal, connections[signal], override=TRUE)
+
+/datum/element/connect_loc/proc/unregister_signals(datum/listener, atom/old_loc)
+ if(isnull(old_loc))
+ return
+
+ listener.UnregisterSignal(old_loc, connections)
+
+/datum/element/connect_loc/proc/on_moved(atom/movable/listener, atom/old_loc)
+ SIGNAL_HANDLER
+ unregister_signals(listener, old_loc)
+ update_signals(listener)
diff --git a/code/datums/elements/object_reskinning.dm b/code/datums/elements/object_reskinning.dm
new file mode 100644
index 0000000000..8b5d905e72
--- /dev/null
+++ b/code/datums/elements/object_reskinning.dm
@@ -0,0 +1,104 @@
+/*
+ * # Element: Object Reskinning
+ *
+ * Allows players to modify the appearance of their object (and other attributes if possible)
+ * PLEASE DO NOT HAVE INVALID VALUES IN unique_reskin I DON'T EVEN WANT TO KNOW WHAT HAPPENS.
+ * USAGE:
+ * unique_reskins = list(
+ * "skin 1" = list(
+ * "desc" = "very cool description",
+ * "icon" = 'very_cool_icon.dmi'
+ * ),
+ * "skin 2" = list(
+ * "desc" = "not as cool description",
+ * "icon" = 'the_boring_skin.dmi'
+ * )
+ * )
+*/
+/datum/element/object_reskinning
+ element_flags = ELEMENT_DETACH
+
+/datum/element/object_reskinning/Attach(datum/target)
+ . = ..()
+ var/obj/the_obj = target
+ if(!istype(the_obj))
+ return ELEMENT_INCOMPATIBLE
+ if(!islist(the_obj.unique_reskin) || !length(the_obj.unique_reskin))
+ message_admins("[src] was given to an object without any unique reskins, if you really need to, give it a couple skins first.")
+ return ELEMENT_INCOMPATIBLE
+
+ RegisterSignal(the_obj, COMSIG_PARENT_EXAMINE, .proc/on_examine)
+ RegisterSignal(the_obj, the_obj.reskin_binding, .proc/reskin)
+
+/datum/element/object_reskinning/Detach(datum/source, force)
+ var/obj/being_deleted = source
+ UnregisterSignal(source, list(COMSIG_PARENT_EXAMINE, being_deleted.reskin_binding))
+ return ..()
+
+/datum/element/object_reskinning/proc/on_examine(obj/obj, mob/user, list/examine_list)
+ examine_list += span_notice("[capitalize(replacetext(obj.reskin_binding, "_", "-"))] to reskin it ([length(obj.unique_reskin)] possible styles).")
+ if(obj.always_reskinnable)
+ examine_list += span_notice("It has no limit to reskinning.")
+
+/*
+ * Reskins an object according to user's choice.
+ * Will detach itself if there's no skins or if done successfully but not always reskinnable.
+ *
+ * Arguments:
+ * * to_reskin The object we will be reskinning
+ * * user The user who wants to choose a skin for the object
+*/
+/datum/element/object_reskinning/proc/reskin(obj/to_reskin, mob/user)
+ // Just stop early
+ if(!LAZYLEN(to_reskin.unique_reskin))
+ message_admins("[ADMIN_LOOKUPFLW(user)] attempted to reskin an object that has no skins!")
+ Detach(to_reskin)
+ return FALSE
+
+ // Can't use
+ if(!user.canUseTopic(to_reskin, BE_CLOSE, NO_DEXTERY, NO_TK))
+ return FALSE
+
+ // Get our choices
+ var/list/items = list()
+ for(var/reskin_option in to_reskin.unique_reskin)
+ var/image/item_image = image(
+ icon = to_reskin.unique_reskin[reskin_option]["icon"] ? to_reskin.unique_reskin[reskin_option]["icon"] : to_reskin.icon,
+ icon_state = to_reskin.unique_reskin[reskin_option]["icon_state"] ? to_reskin.unique_reskin[reskin_option]["icon_state"] : to_reskin.icon_state)
+ items += list("[reskin_option]" = item_image)
+ sortList(items)
+
+ // Display to the user
+ var/pick = show_radial_menu(user, to_reskin, items, custom_check = CALLBACK(src, .proc/check_reskin_menu, user, to_reskin), radius = 38, require_near = TRUE)
+ if(!pick)
+ return FALSE
+
+ // Finish the work
+ to_reskin.current_skin = pick
+ for(var/reskin_var in to_reskin.unique_reskin[pick])
+ to_reskin.vars[reskin_var] = to_reskin.unique_reskin[pick][reskin_var]
+ to_chat(user, "[to_reskin] is now skinned as '[pick].'")
+ to_reskin.reskin_obj(user)
+
+ // Only once or always?
+ if(!to_reskin.always_reskinnable)
+ Detach(to_reskin)
+ return TRUE
+
+/**
+ * Checks if we are allowed to interact with a radial menu for reskins
+ *
+ * Arguments:
+ * * user The mob interacting with the menu
+ * * obj The obj to be checking against
+ */
+/datum/element/object_reskinning/proc/check_reskin_menu(mob/user, obj/obj)
+ if(QDELETED(obj))
+ return FALSE
+ if(!obj.always_reskinnable && obj.current_skin)
+ return FALSE
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated())
+ return FALSE
+ return TRUE
diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm
index b04f55ef0e..104147ebeb 100644
--- a/code/datums/mutable_appearance.dm
+++ b/code/datums/mutable_appearance.dm
@@ -4,6 +4,9 @@
// Mutable appearances are children of images, just so you know.
+/mutable_appearance
+ var/category // listen i want to store some meta information on mutable appearances don't judge me
+
/mutable_appearance/New()
..()
plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm
index 3bcca275a5..e2de71d006 100644
--- a/code/datums/traits/good.dm
+++ b/code/datums/traits/good.dm
@@ -187,10 +187,13 @@
lose_text = "High-tech gizmos are a scam... "
/datum/quirk/trandening/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/autosurgeon/gloweyes/gloweyes = new(get_turf(H))
- H.equip_to_slot(gloweyes, ITEM_SLOT_BACKPACK)
- H.regenerate_icons()
+ // Get targets
+ var/obj/item/organ/eyes/old_eyes = quirk_holder.getorganslot(ORGAN_SLOT_EYES)
+ var/obj/item/organ/eyes/robotic/glow/new_eyes = new
+
+ // Replace eyes
+ qdel(old_eyes)
+ new_eyes.Insert(quirk_holder)
/datum/quirk/bloodpressure
name = "Polycythemia vera"
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index 106a7e3e96..e5dd6d3e33 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -188,3 +188,12 @@
value = 0
medical_record_text = "Patient should not come into contact with sodium."
mob_trait = TRAIT_SALT_SENSITIVE
+
+/datum/quirk/dullahan
+ name = "Dullahan"
+ desc = "Your head is detached from your body."
+ value = 0
+ medical_record_text = "Patient seems to have some kind of spatial link with their decapitated head."
+
+/datum/quirk/dullahan/post_add()
+ quirk_holder.AddComponent(/datum/component/dullahan)
diff --git a/code/datums/wounds/_scars.dm b/code/datums/wounds/_scars.dm
index 3fb6546edb..0edcf65b42 100644
--- a/code/datums/wounds/_scars.dm
+++ b/code/datums/wounds/_scars.dm
@@ -28,6 +28,8 @@
LAZYREMOVE(limb.scars, src)
if(victim)
LAZYREMOVE(victim.all_scars, src)
+ limb = null
+ victim = null
. = ..()
/**
@@ -45,6 +47,8 @@
qdel(src)
return
limb = BP
+ RegisterSignal(limb, COMSIG_PARENT_QDELETING, .proc/limb_gone)
+
severity = W.severity
if(limb.owner)
victim = limb.owner
@@ -84,6 +88,7 @@
return
limb = BP
+ RegisterSignal(limb, COMSIG_PARENT_QDELETING, .proc/limb_gone)
src.severity = severity
LAZYADD(limb.scars, src)
if(BP.owner)
@@ -102,6 +107,10 @@
visibility = 7
return TRUE
+/datum/scar/proc/limb_gone()
+ SIGNAL_HANDLER
+ qdel(src)
+
/// What will show up in examine_more() if this scar is visible
/datum/scar/proc/get_examine_description(mob/viewer)
if(!victim || !is_visible(viewer))
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index 6cab8818ee..a2c4a70380 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -73,8 +73,6 @@
/// What status effect we assign on application
var/status_effect_type
- /// The status effect we're linked to
- var/datum/status_effect/linked_status_effect
/// If we're operating on this wound and it gets healed, we'll nix the surgery too
var/datum/surgery/attached_surgery
/// if you're a lazy git and just throw them in cryo, the wound will go away after accumulating severity * 25 power
@@ -127,12 +125,13 @@
return
victim = L.owner
+ RegisterSignal(victim, COMSIG_PARENT_QDELETING, .proc/null_victim)
limb = L
LAZYADD(victim.all_wounds, src)
LAZYADD(limb.wounds, src)
limb.update_wounds()
if(status_effect_type)
- linked_status_effect = victim.apply_status_effect(status_effect_type, src)
+ victim.apply_status_effect(status_effect_type, src)
SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb)
victim.emote("pain")
if(!victim.alerts["wound"]) // only one alert is shared between all of the wounds
@@ -161,6 +160,14 @@
wound_injury(old_wound)
second_wind()
+/datum/wound/proc/null_victim()
+ SIGNAL_HANDLER
+ victim = null
+
+/datum/wound/proc/source_died()
+ SIGNAL_HANDLER
+ qdel(src)
+
/// Remove the wound from whatever it's afflicting, and cleans up whateverstatus effects it had or modifiers it had on interaction times. ignore_limb is used for detachments where we only want to forget the victim
/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE)
//TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff
diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm
index 6a631ab8f4..68740e78ab 100644
--- a/code/datums/wounds/slash.dm
+++ b/code/datums/wounds/slash.dm
@@ -177,7 +177,7 @@
if(isinsect(victim) || iscatperson(victim) || ismammal(victim) || isdwarf(victim) || ismonkey(victim)) // Yep you can lick monkeys.
user.reagents.add_reagent(/datum/reagent/hairball, 2)
- else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || isdullahan(victim))
+ else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || HAS_TRAIT(victim, TRAIT_DULLAHAN))
user.reagents.add_reagent(/datum/reagent/hairball, 1)
if(blood_flow > minimum_flow)
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 24b49a3af7..2c34c67c58 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -15,7 +15,10 @@
var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
- var/fire = null
+ ///Do we have an active fire alarm?
+ var/fire = FALSE
+ ///How many fire alarm sources do we have?
+ var/triggered_firealarms = 0
///Whether there is an atmos alarm in this area
var/atmosalm = FALSE
var/poweralm = FALSE
@@ -443,7 +446,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
START_PROCESSING(SSobj, src)
/area/proc/firereset(obj/source)
- if (fire)
+ var/should_reset_alarms = fire
+ if(source)
+ if(istype(source, /obj/machinery/firealarm))
+ var/obj/machinery/firealarm/alarm = source
+ if(alarm.triggered)
+ alarm.triggered = FALSE
+ triggered_firealarms -= 1
+ if(triggered_firealarms > 0)
+ should_reset_alarms = FALSE
+ should_reset_alarms = should_reset_alarms & power_environ //No resetting if there's no power
+
+ if (should_reset_alarms) // if there's a source, make sure there's no fire alarms left
set_fire_alarm_effects(FALSE)
ModifyFiredoors(TRUE)
@@ -463,6 +477,18 @@ GLOBAL_LIST_EMPTY(teleportlocs)
STOP_PROCESSING(SSobj, src)
+///Get rid of any dangling camera refs
+/area/proc/clear_camera(obj/machinery/camera/cam)
+ LAZYREMOVE(cameras, cam)
+ for (var/mob/living/silicon/aiPlayer as anything in GLOB.silicon_mobs)
+ aiPlayer.freeCamera(src, cam)
+ for (var/obj/machinery/computer/station_alert/comp as anything in GLOB.alert_consoles)
+ comp.freeCamera(src, cam)
+ for (var/mob/living/simple_animal/drone/drone_on as anything in GLOB.drones_list)
+ drone_on.freeCamera(src, cam)
+ for(var/datum/computer_file/program/alarm_monitor/monitor as anything in GLOB.alarmdisplay)
+ monitor.freeCamera(src, cam)
+
/area/process()
if(firedoors_last_closed_on + 100 < world.time) //every 10 seconds
ModifyFiredoors(FALSE)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 7c7e1c56c7..30363e6c01 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -118,6 +118,9 @@
. = ..()
+ //We add ourselves to this list, best to clear it out
+ // LAZYCLEARLIST(area_sensitive_contents)
+
for(var/movable_content in contents)
qdel(movable_content)
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index d708af7d7a..c720668a5b 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -38,7 +38,7 @@
icon_state = "[state]"
/obj/machinery/bluespace_beacon/process()
- if(!Beacon)
+ if(QDELETED(Beacon)) //Don't move it out of nullspace BACK INTO THE GAME for the love of god
var/turf/T = loc
Beacon = new(T)
Beacon.invisibility = INVISIBILITY_MAXIMUM
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 62b2a6da8d..e1d7737f5c 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -149,10 +149,11 @@ Class Procs:
circuit = new circuit(src)
circuit.apply_default_parts(src)
- if(!speed_process && init_process)
- START_PROCESSING(SSmachines, src)
- else
- START_PROCESSING(SSfastprocess, src)
+ if(init_process) // Required to prevent non-speed non-init machines from running
+ if(speed_process)
+ START_PROCESSING(SSfastprocess, src)
+ else
+ START_PROCESSING(SSmachines, src)
RegisterSignal(src, COMSIG_ENTER_AREA, .proc/power_change)
if (occupant_typecache)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 9a23cc86fb..6e794b8072 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -81,15 +81,15 @@
if(can_use())
toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
GLOB.cameranet.cameras -= src
+ cancelCameraAlarm()
if(isarea(myarea))
- LAZYREMOVE(myarea.cameras, src)
+ myarea.clear_camera(src)
QDEL_NULL(assembly)
if(bug)
- bug.bugged_cameras -= src.c_tag
+ bug.bugged_cameras -= c_tag
if(bug.current == src)
bug.current = null
bug = null
- cancelCameraAlarm()
return ..()
/obj/machinery/camera/emp_act(severity)
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index c925a57b59..cbd3965428 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -351,8 +351,9 @@
log_game("[key_name(usr)] enabled emergency maintenance access.")
message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.")
deadchat_broadcast(" enabled emergency maintenance access at [span_name("[get_area_name(usr, TRUE)]")].", span_name("[usr.real_name]"), usr, message_type = DEADCHAT_ANNOUNCEMENT)
+
+ if("toggleBought")
var/boughtID = params["id"]
-
for(var/tracked_slave in GLOB.tracked_slaves)
var/obj/item/electropack/shockcollar/slave/C = tracked_slave
if (REF(C) == boughtID) // Get collar
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index 0671100623..df84d5a26a 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -33,31 +33,46 @@
return data
-/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
+/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/home, cameras, obj/source)
if(source.z != z)
return
if(stat & (BROKEN))
return
- var/list/L = alarms[class]
- for(var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
if (!(source in sources))
sources += source
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if(O && islist(O))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if(O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C ? C : O), list(source))
- return 1
+ return TRUE
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+ return TRUE
+
+/obj/machinery/computer/station_alert/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin)
if(stat & (BROKEN))
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index 4526a75f32..0a0a4e08f3 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -3,6 +3,10 @@
var/state
var/obj/machinery/embedded_controller/master
+/datum/computer/file/embedded_program/Destroy()
+ master = null
+ . = ..()
+
/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line)
if(master)
master.post_signal(signal, comm_line)
@@ -25,6 +29,11 @@
var/on = TRUE
+/obj/machinery/embedded_controller/Destroy()
+ if(program)
+ QDEL_NULL(program)
+ . = ..()
+
/obj/machinery/embedded_controller/ui_interact(mob/user)
. = ..()
user.set_machine(src)
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index fea3268056..fe756b4022 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -33,8 +33,10 @@
var/detecting = 1
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
- var/last_alarm = 0
+ COOLDOWN_DECLARE(last_alarm)
var/area/myarea = null
+ //Has this firealarm been triggered by its enviroment?
+ var/triggered = FALSE
var/alarm_active = FALSE
var/wire_override = FALSE
@@ -56,6 +58,7 @@
wires = new /datum/wires/firealarm(src)
/obj/machinery/firealarm/Destroy()
+ myarea.firereset(src)
LAZYREMOVE(myarea.firealarms, src)
qdel(wires)
@@ -112,7 +115,7 @@
. += mutable_appearance(icon, "fire_on")
. += emissive_appearance(icon, "fire_on")
- if(!panel_open && detecting) //It just looks horrible with the panel open
+ if(!panel_open && detecting && triggered) //It just looks horrible with the panel open
. += "fire_detected"
. += mutable_appearance(icon, "fire_detected")
. += emissive_appearance(icon, "fire_detected") //Pain
@@ -139,14 +142,14 @@
return TRUE
/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume)
- if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat)
+ if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && COOLDOWN_FINISHED(src, last_alarm) && !(obj_flags & EMAGGED) && detecting && !stat)
alarm()
- ..()
+ return ..()
/obj/machinery/firealarm/proc/alarm(mob/user)
- if(!is_operational() || (last_alarm+FIREALARM_COOLDOWN > world.time))
+ if(!is_operational() || !COOLDOWN_FINISHED(src, last_alarm))
return
- last_alarm = world.time
+ COOLDOWN_START(src, last_alarm, FIREALARM_COOLDOWN)
var/area/A = get_base_area(src)
A.firealert(src)
playsound(loc, 'goon/sound/machinery/FireAlarm.ogg', 75)
@@ -159,7 +162,7 @@
if(!is_operational())
return
var/area/A = get_base_area(src)
- A.firereset(src)
+ A.firereset()
if(user)
log_game("[user] reset a fire alarm at [COORD(src)]")
diff --git a/code/game/machinery/mechlaunchpad.dm b/code/game/machinery/mechlaunchpad.dm
index a2ac2efb3f..c6872edda0 100644
--- a/code/game/machinery/mechlaunchpad.dm
+++ b/code/game/machinery/mechlaunchpad.dm
@@ -24,6 +24,7 @@
connected_console = null
for(var/obj/machinery/computer/mechpad/console in consoles)
console.mechpads -= src
+ GLOB.mechpad_list -= src
return ..()
/obj/machinery/mechpad/screwdriver_act(mob/user, obj/item/tool)
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index c1dac389bf..c561170af4 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -119,7 +119,7 @@
if(istype(AM, /obj/item))
var/obj/item/bodypart/head/as_head = AM
var/obj/item/mmi/as_mmi = AM
- if(istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay))
+ if(istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_head))
living_detected = living_detected ? living_detected : AM
nom += AM
else if(isliving(AM))
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 1d7cbc7f53..966985c427 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -61,12 +61,17 @@
/obj/machinery/suit_storage_unit/engine
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath
- shoes_type= /obj/item/clothing/shoes/magboots
+ shoes_type = /obj/item/clothing/shoes/magboots
+
+/obj/machinery/suit_storage_unit/atmos
+ suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
+ mask_type = /obj/item/clothing/mask/breath
+ storage_type = /obj/item/watertank/atmos
/obj/machinery/suit_storage_unit/ce
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
mask_type = /obj/item/clothing/mask/breath
- shoes_type= /obj/item/clothing/shoes/magboots/advance
+ shoes_type = /obj/item/clothing/shoes/magboots/advance
/obj/machinery/suit_storage_unit/security
suit_type = /obj/item/clothing/suit/space/hardsuit/security
@@ -165,7 +170,6 @@
/obj/machinery/suit_storage_unit/update_overlays()
. = ..()
-
if(uv)
if(uv_super)
. += "super"
@@ -182,7 +186,7 @@
. += "suit"
if(helmet)
. += "helm"
- if(storage)
+ if(shoes || storage)
. += "storage"
else if(occupant)
. += "human"
@@ -199,7 +203,6 @@
helmet = null
suit = null
mask = null
- shoes = null
storage = null
occupant = null
@@ -210,109 +213,8 @@
new /obj/item/stack/sheet/metal(loc, 2)
qdel(src)
-/obj/machinery/suit_storage_unit/interact(mob/living/user)
- var/static/list/items
-
- if (!items)
- items = list(
- "suit" = create_silhouette_of(/obj/item/clothing/suit/space/eva),
- "helmet" = create_silhouette_of(/obj/item/clothing/head/helmet/space/eva),
- "mask" = create_silhouette_of(/obj/item/clothing/mask/breath),
- "shoes" = create_silhouette_of(/obj/item/clothing/shoes/magboots),
- "storage" = create_silhouette_of(/obj/item/tank/internals/oxygen),
- )
-
- . = ..()
- if (.)
- return
-
- if (!check_interactable(user))
- return
-
- var/list/choices = list()
-
- if (locked)
- choices["unlock"] = icon('modular_sand/icons/hud/radial.dmi', "radial_unlock")
- else if (state_open)
- choices["close"] = icon('modular_sand/icons/hud/radial.dmi', "radial_close")
-
- for (var/item_key in items)
- var/item = vars[item_key]
- if (item)
- choices[item_key] = item
- else
- // If the item doesn't exist, put a silhouette in its place
- choices[item_key] = items[item_key]
- else
- choices["open"] = icon('modular_sand/icons/hud/radial.dmi', "radial_open")
- choices["disinfect"] = icon('modular_sand/icons/hud/radial.dmi', "radial_disinfect")
- choices["lock"] = icon('modular_sand/icons/hud/radial.dmi', "radial_lock")
-
- var/choice = show_radial_menu(
- user,
- src,
- choices,
- custom_check = CALLBACK(src, .proc/check_interactable, user),
- require_near = !issilicon(user),
- )
-
- if (!choice)
- return
-
- switch (choice)
- if ("open")
- if (!state_open)
- open_machine(drop = FALSE)
- if (occupant)
- dump_contents()
- if ("close")
- if (state_open)
- close_machine()
- if ("disinfect")
- if (occupant && safeties)
- return
- else if (!helmet && !mask && !suit && !shoes && !storage && !occupant)
- return
- else
- if (occupant)
- var/mob/living/mob_occupant = occupant
- to_chat(mob_occupant, "[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]! ")
- cook()
- if ("lock", "unlock")
- if (!state_open)
- locked = !locked
- else
- var/obj/item/item_to_dispense = vars[choice]
- if (item_to_dispense)
- vars[choice] = null
- user.put_in_hands(item_to_dispense)
- else
- var/obj/item/in_hands = user.get_active_held_item()
- if (in_hands)
- attackby(in_hands, user)
-
- interact(user)
-
-/obj/machinery/suit_storage_unit/proc/check_interactable(mob/user)
- if (!state_open && !can_interact(user))
- return FALSE
-
- if (panel_open)
- return FALSE
-
- if (uv)
- return FALSE
-
- return TRUE
-
-/obj/machinery/suit_storage_unit/proc/create_silhouette_of(atom/item)
- var/image/image = image(initial(item.icon), initial(item.icon_state))
- image.alpha = 128
- image.color = COLOR_RED
- return image
-
-/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/living/user)
- if(!istype(user) || user.stat || !Adjacent(user) || !Adjacent(A) || !isliving(A))
+/obj/machinery/suit_storage_unit/MouseDrop_T(atom/A, mob/user)
+ if(user.stat || user.lying || !Adjacent(user) || !Adjacent(A) || !isliving(A))
return
var/mob/living/target = A
if(!state_open)
@@ -525,15 +427,93 @@
return ..()
-/* ref tg-git issue #45036
- screwdriving it open while it's running a decontamination sequence without closing the panel prior to finish
- causes the SSU to break due to state_open being set to TRUE at the end, and the panel becoming inaccessible.
-*/
-/obj/machinery/suit_storage_unit/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- if(!(flags_1 & NODECONSTRUCT_1) && I.tool_behaviour == TOOL_SCREWDRIVER && uv)
- to_chat(user, "It might not be wise to fiddle with [src] while it's running... ")
- return TRUE
- return ..()
+/obj/machinery/suit_storage_unit/ui_state(mob/user)
+ return GLOB.notcontained_state
+
+/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "SuitStorageUnit", name)
+ ui.open()
+
+/obj/machinery/suit_storage_unit/ui_data()
+ var/list/data = list()
+ data["locked"] = locked
+ data["open"] = state_open
+ data["safeties"] = safeties
+ data["uv_active"] = uv
+ data["uv_super"] = uv_super
+ if(helmet)
+ data["helmet"] = helmet.name
+ else
+ data["helmet"] = null
+ if(suit)
+ data["suit"] = suit.name
+ else
+ data["suit"] = null
+ if(mask)
+ data["mask"] = mask.name
+ else
+ data["mask"] = null
+ if(shoes)
+ data["shoes"] = shoes.name
+ else
+ data["shoes"] = null
+ if(storage)
+ data["storage"] = storage.name
+ else
+ data["storage"] = null
+ if(occupant)
+ data["occupied"] = TRUE
+ else
+ data["occupied"] = FALSE
+ return data
+
+/obj/machinery/suit_storage_unit/ui_act(action, params)
+ if(..() || uv)
+ return
+ switch(action)
+ if("door")
+ if(state_open)
+ close_machine()
+ else
+ open_machine(0)
+ if(occupant)
+ dump_contents() // Dump out contents if someone is in there.
+ . = TRUE
+ if("lock")
+ if(state_open)
+ return
+ locked = !locked
+ . = TRUE
+ if("uv")
+ if(occupant && safeties)
+ return
+ else if(!helmet && !mask && !suit && !storage && !occupant)
+ return
+ else
+ if(occupant)
+ var/mob/living/mob_occupant = occupant
+ to_chat(mob_occupant, "[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]! ")
+ cook()
+ . = TRUE
+ if("dispense")
+ if(!state_open)
+ return
+
+ var/static/list/valid_items = list("helmet", "suit", "mask", "shoes", "storage")
+ var/item_name = params["item"]
+ if(item_name in valid_items)
+ var/obj/item/I = vars[item_name]
+ vars[item_name] = null
+ if(I)
+ var/mob/living/living_person = usr
+ if(!istype(living_person))
+ return
+ if(!istype(living_person) || !Adjacent(living_person) || !living_person.put_in_active_hand(I))
+ I.forceMove(loc)
+ . = TRUE
+ update_icon()
/obj/machinery/suit_storage_unit/default_pry_open(obj/item/I)//needs to check if the storage is locked.
. = !(state_open || panel_open || is_operational() || locked || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm
index f57daac309..a17b4d7d50 100644
--- a/code/game/objects/effects/decals/cleanable/gibs.dm
+++ b/code/game/objects/effects/decals/cleanable/gibs.dm
@@ -11,6 +11,7 @@
var/body_colors = "#e3ba84" //a default color just in case.
var/gibs_reagent_id = /datum/reagent/liquidgibs
var/gibs_bloodtype = "A+"
+ turf_loc_check = FALSE
/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases, list/blood_data)
. = ..()
@@ -22,6 +23,9 @@
add_blood_DNA(list("Non-human DNA" = gibs_bloodtype), diseases)
update_icon()
+/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C)
+ return FALSE //Never fail to place us
+
/obj/effect/decal/cleanable/blood/gibs/update_icon()
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
cut_overlays()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index eeef55941f..96a26e704c 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -399,7 +399,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(throwing)
throwing.finalize(FALSE)
if(loc == user)
- if(!user.temporarilyRemoveItemFromInventory(I = src))
+ if(!allow_attack_hand_drop(user) || !user.temporarilyRemoveItemFromInventory(src))
return
. = FALSE
@@ -428,7 +428,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
if(throwing)
throwing.finalize(FALSE)
if(loc == user)
- if(!user.temporarilyRemoveItemFromInventory(src))
+ if(!allow_attack_hand_drop(user) || !user.temporarilyRemoveItemFromInventory(I = src))
return
pickup(user)
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 2a3d73e04c..27a8cd45ab 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -725,6 +725,26 @@
def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
needs_anchored = FALSE
+/obj/item/circuitboard/machine/chem_dispenser/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
+/obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter
+ build_path = /obj/machinery/chem_dispenser/mutagensaltpeter
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_dispenser/apothecary
name = "Apotechary Chem Dispenser (Machine Board)"
build_path = /obj/machinery/chem_dispenser/apothecary
@@ -740,7 +760,13 @@
name = "Reagent Synthesizer (Abductor Machine Board)"
icon_state = "abductor_mod"
build_path = /obj/machinery/chem_dispenser/abductor
- def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high)
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
needs_anchored = FALSE
/obj/item/circuitboard/machine/chem_heater
@@ -1175,11 +1201,31 @@
icon_state = "service"
build_path = /obj/machinery/chem_dispenser/drinks
+/obj/item/circuitboard/machine/chem_dispenser/drinks/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/drinks/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_dispenser/drinks/beer
name = "Booze Dispenser (Machine Board)"
icon_state = "service"
build_path = /obj/machinery/chem_dispenser/drinks/beer
+/obj/item/circuitboard/machine/chem_dispenser/drinks/beer/fullupgrade
+ build_path = /obj/machinery/chem_dispenser/drinks/beer/fullupgrade
+ req_components = list(
+ /obj/item/stock_parts/matter_bin/bluespace = 2,
+ /obj/item/stock_parts/capacitor/quadratic = 2,
+ /obj/item/stock_parts/manipulator/femto = 2,
+ /obj/item/stack/sheet/glass = 1,
+ /obj/item/stock_parts/cell/bluespace = 1,
+ )
+
/obj/item/circuitboard/machine/chem_master/condi
name = "CondiMaster 3000 (Machine Board)"
icon_state = "service"
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 7b2143cf86..f44860d769 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -42,7 +42,7 @@
var/static/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
var/static/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER, RANDOM_SYMBOL, RANDOM_PUNCTUATION, RANDOM_DRAWING)
- var/static/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
+ var/static/list/graffiti_large_h = list("yiffhell", "furrypride", "secborg", "paint")
var/static/list/all_drawables = graffiti + symbols + drawings + oriented + runes + graffiti_large_h
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index ab1ef6f001..b7ac29562c 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -32,6 +32,9 @@ GLOBAL_LIST_EMPTY(PDAs)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
resistance_flags = FIRE_PROOF | ACID_PROOF
+ always_reskinnable = TRUE
+ reskin_binding = COMSIG_CLICK_CTRL_SHIFT
+
//Main variables
var/owner = null // String name of owner
var/default_cartridge = 0 // Access level defined by cartridge
@@ -112,10 +115,10 @@ GLOBAL_LIST_EMPTY(PDAs)
. += id ? "Alt-click to remove the id. " : ""
if(inserted_item && (!isturf(loc)))
. += "Ctrl-click to remove [inserted_item]. "
- if(LAZYLEN(GLOB.pda_reskins))
- . += "Ctrl-shift-click it to reskin it. "
/obj/item/pda/Initialize(mapload)
+ if(GLOB.pda_reskins)
+ unique_reskin = GLOB.pda_reskins
. = ..()
if(fon)
set_light(f_lum, f_pow, f_col)
@@ -130,28 +133,10 @@ GLOBAL_LIST_EMPTY(PDAs)
new_overlays = TRUE
update_icon()
-/obj/item/pda/CtrlShiftClick(mob/living/user)
- . = ..()
- if(GLOB.pda_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
- reskin_obj(user)
-
/obj/item/pda/reskin_obj(mob/M)
- if(!LAZYLEN(GLOB.pda_reskins))
- return
- var/dat = "Reskin options for [name]: "
- for(var/V in GLOB.pda_reskins)
- var/output = icon2html(GLOB.pda_reskins[V], M, icon_state)
- dat += "\n[V]: [output] "
- to_chat(M, dat)
-
- var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins
- var/new_icon = GLOB.pda_reskins[choice]
- if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
- return
- icon = new_icon
+ . = ..()
new_overlays = TRUE
update_icon()
- to_chat(M, "[src] is now skinned as '[choice]'.")
/obj/item/pda/proc/set_new_overlays()
if(!overlays_offsets || !(icon in overlays_offsets))
@@ -191,7 +176,7 @@ GLOBAL_LIST_EMPTY(PDAs)
else
font_index = MODE_MONO
font_mode = FONT_MONO
- var/pref_skin = GLOB.pda_reskins[C.prefs.pda_skin]
+ var/pref_skin = GLOB.pda_reskins[C.prefs.pda_skin]["icon"]
if(icon != pref_skin)
icon = pref_skin
new_overlays = TRUE
diff --git a/code/game/objects/items/devices/beacon.dm b/code/game/objects/items/devices/beacon.dm
index 86aa787c3e..cf59551bb8 100644
--- a/code/game/objects/items/devices/beacon.dm
+++ b/code/game/objects/items/devices/beacon.dm
@@ -17,7 +17,7 @@
icon_state = "beacon-off"
/obj/item/beacon/Destroy()
- GLOB.teleportbeacons.Remove(src)
+ GLOB.teleportbeacons -= src
return ..()
/obj/item/beacon/attack_self(mob/user)
@@ -27,7 +27,7 @@
GLOB.teleportbeacons += src
else
icon_state = "beacon-off"
- GLOB.teleportbeacons.Remove(src)
+ GLOB.teleportbeacons -= src
to_chat(user, "You [enabled ? "enable" : "disable"] the beacon. ")
return
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index 9ab6115634..c5e92349c7 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -67,6 +67,9 @@
// when we get this many shards, we get a free bulb.
var/shards_required = 4
+ // whether it is "bluespace powered" (can be used at a range)
+ var/bluespace_toggle = FALSE
+
/obj/item/lightreplacer/New()
uses = max_uses / 2
failmsg = "The [name]'s refill light blinks red."
@@ -242,7 +245,7 @@
/obj/item/lightreplacer/afterattack(atom/T, mob/U, proximity)
. = ..()
- if(!proximity)
+ if(!proximity && !bluespace_toggle)
return
if(!isturf(T))
return
@@ -253,6 +256,18 @@
break
used = TRUE
if(istype(A, /obj/machinery/light))
+ if(!proximity && bluespace_toggle)
+ // Set variable for target light
+ var/obj/machinery/light/target = A
+
+ // Check light status before playing effects
+ if(target.status != LIGHT_OK)
+ // Display RPED beam
+ U.Beam(A, icon_state = "rped_upgrade", time = 1 SECONDS)
+
+ // Play RPED sound
+ playsound(src, 'sound/items/pshoom.ogg', 40, 1)
+
ReplaceLight(A, U)
if(!used)
@@ -266,6 +281,15 @@
/obj/item/lightreplacer/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
return
+/obj/item/lightreplacer/blue
+ name = "bluespace light replacer"
+ desc = "A modified light replacer that zaps lights into place. Refill with broken or working lightbulbs, or sheets of glass."
+ icon_state = "lightreplacer_blue"
+ bluespace_toggle = TRUE
+
+/obj/item/lightreplacer/blue/emag_act()
+ return // balancing against longrange explosions
+
#undef LIGHT_OK
#undef LIGHT_EMPTY
#undef LIGHT_BROKEN
diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm
index 44e812d33c..95e7ddd05d 100644
--- a/code/game/objects/items/devices/taperecorder.dm
+++ b/code/game/objects/items/devices/taperecorder.dm
@@ -30,6 +30,10 @@
mytape = new starting_tape_type(src)
update_icon()
+/obj/item/taperecorder/Destroy()
+ // QDEL_NULL(soundloop)
+ QDEL_NULL(mytape)
+ return ..()
/obj/item/taperecorder/examine(mob/user)
. = ..()
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 4930f39b31..b389efe542 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -193,34 +193,29 @@
/obj/item/melee/transforming/energy/sword/saber
possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
- unique_reskin = list("Sword" = "sword0", "Saber" = "esaber0")
+ unique_reskin = list(
+ "Sword" = list("icon_state" = "sword0"),
+ "Saber" = list("icon_state" = "esaber0")
+ )
var/hacked = FALSE
- var/saber = FALSE
/obj/item/melee/transforming/energy/sword/saber/transform_weapon(mob/living/user, supress_message_text)
. = ..()
if(.)
- if(active)
- if(sword_color)
- if(saber)
- icon_state = "esaber[sword_color]"
- else
- icon_state = "sword[sword_color]"
- else
- if(saber)
- icon_state = "esaber0"
+ switch(current_skin)
+ if("Saber")
+ icon_state = "esaber[active ? sword_color : "0"]"
+ // No skin
else
- icon_state = "sword0"
+ icon_state = "sword[active ? sword_color : "0"]"
/obj/item/melee/transforming/energy/sword/saber/reskin_obj(mob/M)
. = ..()
- if(icon_state == "esaber0")
- saber = TRUE
- if(active)
- if(saber)
- icon_state = "esaber[sword_color]"
- else
- icon_state = "sword[sword_color]"
+ switch(current_skin)
+ if("Sword")
+ icon_state = "sword[active ? sword_color : "0"]"
+ if("Saber")
+ icon_state = "esaber[active ? sword_color : "0"]"
/obj/item/melee/transforming/energy/sword/saber/set_sword_color(var/color_forced)
if(color_forced) // wow i really do not like this at fucking all holy SHIT
diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm
index 62a3530afe..9b0506855f 100644
--- a/code/game/objects/items/mop.dm
+++ b/code/game/objects/items/mop.dm
@@ -91,7 +91,7 @@
name = "advanced mop"
mopcap = 10
icon_state = "advmop"
- item_state = "mop"
+ item_state = "advmop"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
force = 6
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 4ea25bec96..cfe1afad5a 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -28,9 +28,17 @@
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset.
- var/current_skin //the item reskin
- var/list/unique_reskin //List of options to reskin.
+
+ //Reskin variables
+ /// The item reskin
+ var/current_skin
+ /// List of options to reskin.
+ var/list/unique_reskin
+ /// Can always be modified
var/always_reskinnable = FALSE
+ /// How to bring up the reskinning menu
+ var/reskin_binding = COMSIG_CLICK_ALT
+ //
// Access levels, used in modules\jobs\access.dm
var/list/req_access
@@ -76,6 +84,10 @@
var/turf/T = loc
T.add_blueprints_preround(src)
+/obj/ComponentInitialize()
+ . = ..()
+ if(islist(unique_reskin) && length(unique_reskin))
+ AddElement(/datum/element/object_reskinning)
/obj/Destroy(force=FALSE)
if(!ismachinery(src))
@@ -340,50 +352,10 @@
. = ..()
if(obj_flags & UNIQUE_RENAME)
. += "Use a pen on it to rename it or change its description. "
- if(unique_reskin && (!current_skin || always_reskinnable))
- . += "Alt-click it to reskin it. "
-/obj/AltClick(mob/user)
- . = ..()
- if(unique_reskin && (!current_skin || always_reskinnable) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
- reskin_obj(user)
- return TRUE
-
-/obj/proc/reskin_obj(mob/M)
- if(!LAZYLEN(unique_reskin))
- return
-
- var/list/items = list()
- for(var/reskin_option in unique_reskin)
- var/image/item_image = image(icon = src.icon, icon_state = unique_reskin[reskin_option])
- items += list("[reskin_option]" = item_image)
- sortList(items)
-
- var/pick = show_radial_menu(M, src, items, custom_check = CALLBACK(src, .proc/check_reskin_menu, M), radius = 38, require_near = TRUE)
- if(!pick)
- return
- if(!unique_reskin[pick])
- return
- current_skin = pick
- icon_state = unique_reskin[pick]
- to_chat(M, "[src] is now skinned as '[pick].'")
-
-/**
- * Checks if we are allowed to interact with a radial menu for reskins
- *
- * Arguments:
- * * user The mob interacting with the menu
- */
-/obj/proc/check_reskin_menu(mob/user)
- if(QDELETED(src))
- return FALSE
- if(current_skin)
- return FALSE
- if(!istype(user))
- return FALSE
- if(user.incapacitated())
- return FALSE
- return TRUE
+/// Do you want to make overrides, of course you do! Will be called if an object was reskinned successfully
+/obj/proc/reskin_obj(mob/user)
+ return
/obj/update_overlays()
. = ..()
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 46db798c84..650fdf040b 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -139,7 +139,7 @@
/obj/structure/closet/crate/freezer/Destroy()
recursive_organ_check(src)
- ..()
+ return ..()
/obj/structure/closet/crate/freezer/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm
index c5802b5086..d62528ebf8 100644
--- a/code/game/objects/structures/electricchair.dm
+++ b/code/game/objects/structures/electricchair.dm
@@ -15,9 +15,12 @@
var/obj/structure/chair/C = new /obj/structure/chair(loc)
W.play_tool_sound(src)
C.setDir(dir)
- part.forceMove(loc)
- part.master = null
- part = null
+
+ if (part)
+ part.forceMove(loc)
+ part.master = null
+ part = null
+
qdel(src)
/obj/structure/chair/e_chair/proc/shock()
@@ -44,3 +47,9 @@
to_chat(buckled_mob, "You feel a deep shock course through your body! ")
addtimer(CALLBACK(buckled_mob, /mob/living.proc/electrocute_act, 85, src, 1), 1)
visible_message("The electric chair went off! ", "You hear a deep sharp shock! ")
+
+/obj/structure/chair/e_chair/Destroy()
+ if(part)
+ QDEL_NULL(part)
+
+ return ..()
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index a70d9d4678..ffb48ce633 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -41,6 +41,7 @@
if(new_style)
H.hair_style = new_style
+ H.update_mutant_bodyparts()
H.update_hair()
/obj/structure/mirror/examine_status(mob/user)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index dc44ac728f..b6be7f1fe1 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -137,6 +137,8 @@ GLOBAL_LIST_EMPTY(station_turfs)
requires_activation = FALSE
..()
+ vis_contents.Cut()
+
/turf/on_attack_hand(mob/user)
user.Move_Pulled(src)
diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm
index c4abf94043..b1d8815696 100644
--- a/code/modules/arousal/arousal.dm
+++ b/code/modules/arousal/arousal.dm
@@ -99,10 +99,10 @@
to_chat(src,"Your [G.name] cannot cum. ")
return
if(mb_time) //as long as it's not instant, give a warning
- to_chat(src,"You feel yourself about to orgasm. ")
+ to_chat(src, span_userlove("You feel yourself about to orgasm."))
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
return
- to_chat(src,"You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name]. ")
+ to_chat(src, span_userlove("You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name]."))
do_climax(fluid_source, loc, G)
/mob/living/carbon/human/proc/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, mb_time = 30, obj/item/organ/genital/Lgen = null) //Used for climaxing with any living thing
@@ -110,16 +110,16 @@
if(!fluid_source)
return
if(mb_time) //Skip warning if this is an instant climax.
- to_chat(src,"You're about to climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"]! ")
- to_chat(L,"[src] is about to climax [(Lgen) ? "in your [Lgen.name]" : "with you"]! ")
+ to_chat(src, span_userlove("You're about to climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"]!"))
+ to_chat(L, span_userlove("[src] is about to climax [(Lgen) ? "in your [Lgen.name]" : "with you"]!"))
if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE))
return
if(spillage)
- to_chat(src,"You orgasm with [L], spilling out of [(Lgen) ? "[L.p_their()] [Lgen.name]" : "[L.p_them()]"], using your [G.name]. ")
- to_chat(L,"[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], overflowing and spilling, using [p_their()] [G.name]! ")
+ to_chat(src, span_userlove("You orgasm with [L], spilling out of [(Lgen) ? "[L.p_their()] [Lgen.name]" : "[L.p_them()]"], using your [G.name]."))
+ to_chat(L, span_userlove("[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], overflowing and spilling, using [p_their()] [G.name]!"))
else //knots and other non-spilling orgasms
- to_chat(src,"You climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"], your [G.name] spilling nothing. ")
- to_chat(L,"[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], [p_their()] [G.name] spilling nothing! ")
+ to_chat(src, span_userlove("You climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"], your [G.name] spilling nothing."))
+ to_chat(L, span_userlove("[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], [p_their()] [G.name] spilling nothing!"))
//SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) //Sandstorm edit
do_climax(fluid_source, spillage ? loc : L, G, spillage,, Lgen)
//L.receive_climax(src, Lgen, G, spillage)
@@ -129,10 +129,10 @@
if(!fluid_source)
return
if(mb_time)
- to_chat(src,"You start to [G.masturbation_verb] your [G.name] over [container]. ")
+ to_chat(src, span_userlove("You start to [G.masturbation_verb] your [G.name] over [container]."))
if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE))
return
- to_chat(src,"You used your [G.name] to fill [container]. ")
+ to_chat(src, span_userlove("You used your [G.name] to fill [container]."))
message_admins("[ADMIN_LOOKUPFLW(src)] used [p_their()] [G.name] to fill [container] with [G.get_fluid_name()].")
log_consent("[key_name(src)] used their [G.name] to fill [container].")
do_climax(fluid_source, container, G, FALSE, cover = TRUE)
diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm
index 142e036562..ffe2e1ce42 100644
--- a/code/modules/arousal/genitals.dm
+++ b/code/modules/arousal/genitals.dm
@@ -167,9 +167,9 @@
var/original_state = picked_organ.aroused_state
picked_organ.set_aroused_state(!picked_organ.aroused_state)
if(original_state != picked_organ.aroused_state)
- to_chat(src,"[picked_organ.aroused_state ? picked_organ.arousal_verb : picked_organ.unarousal_verb]. ")
+ to_chat(src, span_userlove("[picked_organ.aroused_state ? picked_organ.arousal_verb : picked_organ.unarousal_verb]."))
else
- to_chat(src,"You can't make that genital [picked_organ.aroused_state ? "unaroused" : "aroused"]! ")
+ to_chat(src, span_userlove("You can't make that genital [picked_organ.aroused_state ? "unaroused" : "aroused"]!"))
picked_organ.update_appearance()
if(ishuman(src))
var/mob/living/carbon/human/human = src
diff --git a/code/modules/assembly/shock_kit.dm b/code/modules/assembly/shock_kit.dm
index e18909c9a2..d9bc80761b 100644
--- a/code/modules/assembly/shock_kit.dm
+++ b/code/modules/assembly/shock_kit.dm
@@ -27,8 +27,10 @@
return TRUE
/obj/item/assembly/shock_kit/attack_self(mob/user)
- part1.attack_self(user)
- part2.attack_self(user)
+ if (part1)
+ part1.attack_self(user)
+ if (part2)
+ part2.attack_self(user)
add_fingerprint(user)
return
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index b39a181a38..f60e853aed 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -760,6 +760,8 @@
/datum/gas_reaction/hagedorn/react(datum/gas_mixture/air, datum/holder)
var/initial_energy = air.thermal_energy()
+ if(air.get_moles(GAS_QCD))
+ return
for(var/g in air.get_gases())
air.set_moles(g, 0)
var/amount = initial_energy / (air.return_temperature() * GLOB.gas_data.specific_heats[GAS_QCD])
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 66b8277273..90407264ad 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -238,6 +238,8 @@
SSradio.remove_object(src, frequency)
qdel(wires)
wires = null
+ var/area/ourarea = get_area(src)
+ ourarea.atmosalert(FALSE, src)
return ..()
/obj/machinery/airalarm/examine(mob/user)
diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm
index ffa608f8fd..4079a6ffbe 100644
--- a/code/modules/cargo/bounties/science.dm
+++ b/code/modules/cargo/bounties/science.dm
@@ -8,7 +8,7 @@
name = "Trash Bag of Holding"
description = "Nanotrasen would make good use of high-capacity trash bags. If you have any, please ship them."
reward = 3000
- wanted_types = list(/obj/item/storage/backpack/holding)
+ wanted_types = list(/obj/item/storage/bag/trash/bluespace)
/datum/bounty/item/science/bluespace_syringe
name = "Bluespace Syringe"
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index 390f02d419..e7854d47cf 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -40,7 +40,7 @@
/obj/machinery/computer/cargo/Destroy()
QDEL_NULL(radio)
- ..()
+ return ..()
/obj/machinery/computer/cargo/proc/get_export_categories()
. = EXPORT_CARGO
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index fc482e4828..c769ddeb3c 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1004,7 +1004,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Belly Visibility: [features["belly_visibility"]] "
dat += "Egg Stuffing: [features["belly_stuffing"] == TRUE ? "Yes" : "No"] "
dat += ""
- if(pref_species.id == SPECIES_DULLAHAN)
+ if(all_quirks.Find("Dullahan"))
dat += APPEARANCE_CATEGORY_COLUMN
dat += "
Neckfire "
@@ -2068,9 +2068,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
to_chat(user, "Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and . ")
if("age")
- var/new_age = tgui_input_number(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX])", "Character Preference", null, AGE_MAX, AGE_MIN)
+ var/new_age = tgui_input_number(user, "Choose your character's age:\n([AGE_MIN]-[AGE_MAX_INPUT])", "Character Preference", null, AGE_MAX_INPUT, AGE_MIN)
if(new_age)
- age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
+ age = max(min( round(text2num(new_age)), AGE_MAX_INPUT),AGE_MIN)
if("security_records")
var/rec = stripped_multiline_input(usr, "Set your security record note section. This should be IC!", "Security Records", html_decode(security_records), MAX_FLAVOR_LEN, TRUE)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 214b6d94b9..4754a87e3c 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -364,6 +364,18 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(length(old_flavor_text) && !length(features["feature_flavor_text"]))
features["feature_flavor_text"] = old_flavor_text
+ // hey what happened to 55
+
+ // dullahans as a species cease to exist
+ if(current_version < 56)
+ var/species_id = S["species"]
+ if(species_id == SPECIES_DULLAHAN)
+ S["species"] = SPECIES_HUMAN
+ if(islist(S["all_quirks"]))
+ S["all_quirks"] += "Dullahan"
+ else
+ S["all_quirks"] = list("Dullahan")
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -465,6 +477,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["preferred_chaos"] >> preferred_chaos
S["auto_ooc"] >> auto_ooc
S["no_tetris_storage"] >> no_tetris_storage
+ S["recoil_screenshake"] >> recoil_screenshake
// Splurt
S["be_victim"] >> be_victim
@@ -532,6 +545,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles))
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage))
+ recoil_screenshake = sanitize_integer(recoil_screenshake, 0, 800, initial(recoil_screenshake))
key_bindings = sanitize_islist(key_bindings, list())
modless_key_bindings = sanitize_islist(modless_key_bindings, list())
favorite_outfits = SANITIZE_LIST(favorite_outfits)
@@ -665,6 +679,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["preferred_chaos"], preferred_chaos)
WRITE_FILE(S["auto_ooc"], auto_ooc)
WRITE_FILE(S["no_tetris_storage"], no_tetris_storage)
+ WRITE_FILE(S["recoil_screenshake"], recoil_screenshake)
// Splurt
WRITE_FILE(S["be_victim"], be_victim)
@@ -1069,7 +1084,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color))
socks = sanitize_inlist(socks, GLOB.socks_list)
socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color))
- age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
+ age = sanitize_integer(age, AGE_MIN, AGE_MAX_INPUT, initial(age))
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
grad_style = sanitize_inlist(grad_style, GLOB.hair_gradients_list, "None")
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index 21004a163e..b2a7f91e96 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -27,6 +27,11 @@
if(glass_colour_type && ishuman(user))
. += "Alt-click to toggle its colors. "
+/obj/item/clothing/glasses/proc/prescribe()
+ vision_correction = TRUE
+ name = "prescription [name]"
+ desc += " These have been fitted with a prescription overlay device, and thus correct some vision deficiencies."
+
/obj/item/clothing/glasses/visor_toggling()
..()
if(visor_vars_to_toggle & VISOR_VISIONFLAGS)
@@ -128,10 +133,9 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
-/obj/item/clothing/glasses/night/prescription
- name = "prescription night vision goggles"
- desc = "NVGs but for those with nearsightedness."
- vision_correction = 1
+/obj/item/clothing/glasses/night/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/night/syndicate
name = "combat night vision goggles"
@@ -233,6 +237,12 @@
icon_state = "circle_glasses"
item_state = "circle_glasses"
+/obj/item/clothing/glasses/regular/modern
+ name = "modern glasses"
+ desc = "A Dork. Co. revamp and/or revision of Nerd. Co.'s classic prescription glasses, with less opaque lenses."
+ icon_state = "glasses_alt"
+ item_state = "glasses_alt"
+
//Here lies green glasses, so ugly they died. RIP
/obj/item/clothing/glasses/sunglasses
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index c848dbdfa8..733fc0195c 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -14,6 +14,7 @@
if(G.vision_correction)
vision_correction = TRUE
name = "prescription [name]"
+ desc += " These have been made with some form of vision-correcting eyewear, thus making them innately correct some vision deficiencies."
return
/obj/item/clothing/glasses/hud/equipped(mob/living/carbon/human/user, slot)
@@ -55,13 +56,9 @@
hud_type = DATA_HUD_MEDICAL_ADVANCED
glass_colour_type = /datum/client_colour/glass_colour/lightblue
-/obj/item/clothing/glasses/hud/health/prescription
- name = "prescription health scanner HUD"
- desc = "A heads-up display, made with a prescription lens, that scans the humans in view and provides accurate data about their health status."
- icon_state = "healthhud"
- hud_type = DATA_HUD_MEDICAL_ADVANCED
- vision_correction = 1
- glass_colour_type = /datum/client_colour/glass_colour/lightblue
+/obj/item/clothing/glasses/hud/health/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/hud/health/night
name = "night vision health scanner HUD"
@@ -88,9 +85,9 @@
tint = 1
glass_colour_type = /datum/client_colour/glass_colour/blue
-/obj/item/clothing/glasses/hud/health/sunglasses/prescription
- name = "prescription medical HUDSunglasses"
- vision_correction = 1
+/obj/item/clothing/glasses/hud/health/sunglasses/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/hud/health/eyepatch
name = "eyepatch medHUD"
@@ -117,17 +114,13 @@
flash_protect = 1
tint = 1
-/obj/item/clothing/glasses/hud/diagnostic/prescription
- name = "prescription diagnostic HUD"
- desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits. This one has a prescription lens."
- icon_state = "diagnostichud"
- hud_type = DATA_HUD_DIAGNOSTIC_BASIC
- vision_correction = 1
- glass_colour_type = /datum/client_colour/glass_colour/lightorange
+/obj/item/clothing/glasses/hud/diagnostic/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
-/obj/item/clothing/glasses/hud/diagnostic/sunglasses/prescription
- name = "prescription diagnostic HUDSunglasses"
- vision_correction = 1
+/obj/item/clothing/glasses/hud/diagnostic/sunglasses/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/hud/diagnostic/night
name = "night vision diagnostic HUD"
@@ -155,13 +148,9 @@
hud_type = DATA_HUD_SECURITY_ADVANCED
glass_colour_type = /datum/client_colour/glass_colour/red
-/obj/item/clothing/glasses/hud/security/prescription
- name = "prescription security HUD"
- desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records. This one has a prescription lens so you can see the banana peal that slipped you."
- icon_state = "securityhud"
- hud_type = DATA_HUD_SECURITY_ADVANCED
- vision_correction = 1
- glass_colour_type = /datum/client_colour/glass_colour/red
+/obj/item/clothing/glasses/hud/security/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/hud/security/chameleon
name = "chameleon security HUD"
@@ -200,9 +189,9 @@
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
-/obj/item/clothing/glasses/hud/security/sunglasses/prescription
- name = "prescription security HUDSunglasses"
- vision_correction = 1
+/obj/item/clothing/glasses/hud/security/sunglasses/prescription/Initialize(mapload)
+ . = ..()
+ prescribe()
/obj/item/clothing/glasses/hud/security/night
name = "night vision security HUD"
diff --git a/code/modules/clothing/glasses/prescription_kit.dm b/code/modules/clothing/glasses/prescription_kit.dm
new file mode 100644
index 0000000000..0ad6419622
--- /dev/null
+++ b/code/modules/clothing/glasses/prescription_kit.dm
@@ -0,0 +1,22 @@
+// don't you love single purpose files? i do too.
+
+/obj/item/prescription_kit
+ name = "prescription lens kit"
+ desc = "A disposable kit containing all the needed tools and parts to develop and apply a self-modifying prescription lens overlay device to any eyewear."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "modkit"
+
+/obj/item/prescription_kit/attack_obj(obj/O, mob/living/user)
+ if(!istype(O, /obj/item/clothing/glasses))
+ return ..()
+
+ if(istype(O, /obj/item/clothing/glasses))
+ var/obj/item/clothing/glasses/target_glasses = O
+ if(target_glasses.vision_correction)
+ to_chat(user, span_notice("These are already fitted with prescription lenses or otherwise already correct vision!"))
+ return
+ playsound(src, 'sound/items/screwdriver.ogg', 50, 1)
+ user.visible_message(span_notice("[user] fits \the [target_glasses] with a prescription overlay device."), span_notice("You fit \the [target_glasses] with a prescription overlay device."))
+ target_glasses.prescribe()
+ target_glasses.balloon_alert(user, "prescription fitted!")
+ qdel(src)
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index d3ad2ca4c7..efa00ef888 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -79,16 +79,18 @@
to_chat(user, "With [src] off of your arms, you feel less ready to punch things. ")
/obj/item/clothing/gloves/fingerless/pugilist/crafted
- unique_reskin = list("Short" = "armwraps",
- "Extended" = "armwraps_extended"
- )
+ unique_reskin = list(
+ "Short" = list("icon_state" = "armwraps"),
+ "Extended" = list("icon_state" = "armwraps_extended")
+ )
/obj/item/clothing/gloves/fingerless/pugilist/crafted/reskin_obj(mob/M)
. = ..()
- if(icon_state == "armwraps_extended")
- item_state = "armwraps_extended"
- else
- return
+ switch(current_skin)
+ if("Short")
+ item_state = "armwraps"
+ if("Extended")
+ item_state = "armwraps_extended"
/obj/item/clothing/gloves/fingerless/pugilist/chaplain
name = "armwraps of unyielding resolve"
diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm
index 754a72ff0c..b99eca1a61 100644
--- a/code/modules/clothing/gloves/tacklers.dm
+++ b/code/modules/clothing/gloves/tacklers.dm
@@ -25,6 +25,10 @@
/// See: [/datum/component/tackler/var/skill_mod]
var/skill_mod = 1
+/obj/item/clothing/gloves/tackler/Destroy()
+ tackler = null
+ return ..()
+
/obj/item/clothing/gloves/tackler/equipped(mob/user, slot)
. = ..()
if(!ishuman(user))
@@ -34,12 +38,12 @@
var/mob/living/carbon/human/H = user
tackler = H.AddComponent(/datum/component/tackler, stamina_cost=tackle_stam_cost, base_knockdown = base_knockdown, range = tackle_range, speed = tackle_speed, skill_mod = skill_mod, min_distance = min_distance)
else
- qdel(tackler) // Only wearing it!
+ QDEL_NULL(tackler) // Only wearing it!
/obj/item/clothing/gloves/tackler/dropped(mob/user)
. = ..()
if(tackler)
- qdel(tackler)
+ QDEL_NULL(tackler)
/obj/item/clothing/gloves/tackler/dolphin
name = "dolphin gloves"
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index cdf5512fc6..7c1fc6fe3d 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -275,8 +275,10 @@
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
actions_types = list(/datum/action/item_action/bhop)
permeability_coefficient = 0.05
- unique_reskin = list("Explorer" = "miningjet",
- "Jackboot" = "jetboots")
+ unique_reskin = list(
+ "Explorer" = list("icon_state" = "miningjet"),
+ "Jackboot" = list("icon_state" = "jetboots")
+ )
var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles
var/jumpspeed = 3
var/recharging_rate = 60 //default 6 seconds between each dash
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index c13a8bfa66..36795d53b8 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -80,9 +80,10 @@
item_state = "hostrench"
flags_inv = 0
strip_delay = 80
- unique_reskin = list("Coat" = "hostrench",
- "Cloak" = "trenchcloak"
- )
+ unique_reskin = list(
+ "Coat" = list("icon_state" = "hostrench"),
+ "Cloak" = list("icon_state" = "trenchcloak")
+ )
/obj/item/clothing/suit/armor/hos/platecarrier
name = "plate carrier"
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index e39c48f80f..1b8b4d9e00 100644
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -111,7 +111,7 @@
/obj/item/clothing/accessory/proc/on_uniform_dropped(obj/item/clothing/under/U, user)
return
-/obj/item/clothing/accessory/AltClick(mob/user)
+/obj/item/clothing/accessory/CtrlClick(mob/user)
. = ..()
if(istype(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(initial(above_suit))
@@ -123,7 +123,7 @@
. = ..()
. += "\The [src] can be attached to [istype(src, /obj/item/clothing/accessory/ring) ? "gloves" : "a uniform"]. Alt-click to remove it once attached. "
if(initial(above_suit))
- . += "\The [src] can be worn above or below your suit. Alt-click to toggle. "
+ . += "\The [src] can be worn above or below your suit. Ctrl-click to toggle. "
//////////////
//Waistcoats//
@@ -603,3 +603,23 @@
obj_flags = UNIQUE_RENAME
custom_materials = list(/datum/material/iron=100)
resistance_flags = FIRE_PROOF
+
+
+/obj/item/clothing/accessory/pride
+ name = "pride pin"
+ desc = "A Nanotrasen Diversity & Inclusion Center-sponsored holographic pin to show off your pride of sexuality or gender identity, reminding the crew of their unwavering commitment to equity, diversity, and inclusion!"
+ icon_state = "pride"
+ above_suit = TRUE
+ obj_flags = UNIQUE_RENAME
+ unique_reskin = list(
+ "Rainbow Pride" = list("icon_state" = "pride"),
+ "Bisexual Pride" = list("icon_state" = "pride_bi"),
+ "Pansexual Pride" = list("icon_state" = "pride_pan"),
+ "Asexual Pride" = list("icon_state" = "pride_ace"),
+ "Non-binary Pride" = list("icon_state" = "pride_enby"),
+ "Transgender Pride" = list("icon_state" = "pride_trans")
+ )
+
+/obj/item/clothing/accessory/pride/reskin_obj(mob/M)
+ . = ..()
+ name = "[current_skin] pin"
diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm
index 0f112a0238..5dd8ad9155 100644
--- a/code/modules/holiday/halloween/jacqueen.dm
+++ b/code/modules/holiday/halloween/jacqueen.dm
@@ -219,23 +219,11 @@
/mob/living/simple_animal/jacq/proc/treat(mob/living/carbon/C, gender)
visible_message("[src] gives off a glowing smile, \"What ken Ah offer ye? I can magic up an object, a potion or a plushie fer ye.\" ")
jacqrunes("What ken Ah offer ye? I can magic up an object, a potion or a plushie fer ye.", C)
- var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Jacqueline Tracker - 2 candies", "Plushie - 1 candy", "Can I get to know you instead?", "Become a pumpkinhead dullahan (perma) - 4 candies")
+ var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Jacqueline Tracker - 2 candies", "Plushie - 1 candy", "Can I get to know you instead?")
var/choice_reward = input(usr, "Trick or Treat?", "Trick or Treat?") in choices_reward
//rewards
switch(choice_reward)
- if("Become a pumpkinhead dullahan (perma) - 4 candies")
- if(!take_candies(C, 4))
- visible_message("[src] raises an eyebrown, \"It's 4 candies for that [gender]! Thems the rules!\" ")
- jacqrunes("It's 4 candies for that [gender]! Thems the rules!", C)
- return
- visible_message("[src] waves their arms around, \"Off comes your head, a pumpkin taking it's stead!\" ")
- jacqrunes("Off comes your head, a pumpkin taking it's stead!", C)
- C.reagents.add_reagent(/datum/reagent/mutationtoxin/pumpkinhead, 5)
- sleep(20)
- poof()
- return
-
if("Object - 3 candies")
if(!take_candies(C, 3))
visible_message("[src] raises an eyebrown, \"It's 3 candies per trinket [gender]! Thems the rules!\" ")
@@ -698,12 +686,6 @@
else
..()
-/datum/reagent/mutationtoxin/pumpkinhead
- name = "Pumpkin head mutation toxin"
- race = /datum/species/dullahan/pumpkin
- mutationtext = "The pain subsides. You feel your head roll off your shoulders... and you smell pumpkin."
- //I couldn't get the replace head sprite with a pumpkin to work so, it is what it is.
-
/mob/living/simple_animal/jacq/proc/check_candies(mob/living/carbon/C)
var/invs = C.get_contents()
var/candy_count = 0
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index 324e6c1e99..0a378fadc2 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -63,6 +63,10 @@
if (needs_update)
GLOB.lighting_update_lights -= src
+ top_atom = null
+ source_atom = null
+ source_turf = null
+ pixel_turf = null
. = ..()
// Yes this doesn't align correctly on anything other than 4 width tabs.
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index dbd3b7e922..794a1cf20a 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -253,8 +253,10 @@
sharpness = SHARP_NONE // use your survival dagger or smth
icon_state = "crusher-hands"
item_state = "crusher0-fist"
- unique_reskin = list("Gauntlets" = "crusher-hands",
- "Fingerless" = "crusher-hands-bare")
+ unique_reskin = list(
+ "Gauntlets" = list("icon_state" = "crusher-hands"),
+ "Fingerless" = list("icon_state" = "crusher-hands-bare")
+ )
detonation_damage = 45 // 60 on wield, compared to normal crusher's 70
backstab_bonus = 70 // 130 on backstab though
var/combo_on_anything = FALSE // @admins if you're varediting this you don't get to whine at me
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 3d89377952..0b7ca7adfd 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -121,6 +121,7 @@
icon_state = "furnace"
density = TRUE
needs_item_input = TRUE
+ init_process = TRUE
var/obj/machinery/mineral/CONSOLE = null
var/on = FALSE
var/datum/material/selected_material = null
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index eabab35c3b..32b79343e8 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -11,6 +11,7 @@
output_dir = SOUTH
req_access = list(ACCESS_MINERAL_STOREROOM)
speed_process = TRUE
+ init_process = TRUE
circuit = /obj/item/circuitboard/machine/ore_redemption
layer = BELOW_OBJ_LAYER
var/points = 0
diff --git a/code/modules/mining/machine_unloading.dm b/code/modules/mining/machine_unloading.dm
index b39b0df6ab..16b3b3967f 100644
--- a/code/modules/mining/machine_unloading.dm
+++ b/code/modules/mining/machine_unloading.dm
@@ -9,6 +9,7 @@
input_dir = WEST
output_dir = EAST
speed_process = TRUE
+ init_process = TRUE
/obj/machinery/mineral/unloading_machine/proc/horrible_quadratic_monster(var/turf/T)
set waitfor = FALSE
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 376865ae66..4c275c266e 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -11,7 +11,7 @@
var/obj/item/card/id/inserted_id
var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces.
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
- new /datum/data/mining_equipment("50 Point Transfer Card", /obj/item/card/mining_point_card, 50),
+ new /datum/data/mining_equipment("50 Point Transfer Card", /obj/item/card/mining_point_card/fifty, 50),
new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
new /datum/data/mining_equipment("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100),
@@ -27,7 +27,7 @@
new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
new /datum/data/mining_equipment("Larger Ore Bag", /obj/item/storage/bag/ore/large, 500),
- new /datum/data/mining_equipment("Mining Point Transfer Card", /obj/item/card/mining_point_card, 500),
+ new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card, 500),
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750),
@@ -330,6 +330,9 @@
icon_state = "data_1"
var/points = 500
+/obj/item/card/mining_point_card/fifty
+ points = 50
+
/obj/item/card/mining_point_card/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/id))
var/obj/item/card/id/id = I
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 7fff5cb71a..2efdae38d6 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -585,18 +585,28 @@
for(var/job in category)
var/datum/job/job_datum = SSjob.name_occupations[job]
if(job_datum && IsJobUnavailable(job_datum.title, TRUE) == JOB_AVAILABLE)
+ // Get currently occupied slots
+ var/num_positions_current = job_datum.current_positions
+
+ // Get total slots that can be occupied
+ var/num_positions_total = job_datum.total_positions
+
+ // Change to lemniscate for infinite-slot jobs
+ // This variable should only used to display text!
+ num_positions_total = (num_positions_total == -1 ? "∞" : num_positions_total)
+
var/command_bold = ""
if(job in GLOB.command_positions)
command_bold = " command"
- //SKYRAT CHANGES
- var/jobline = "[job_datum.title] ([job_datum.current_positions])"
+ //Sandstorm changes
+ var/jobline = "[job_datum.title]"
if(job_datum in SSjob.prioritized_jobs)
jobline = "[jobline] "
if(client && client.prefs && client.prefs.alt_titles_preferences[job_datum.title])
jobline = "[jobline](as [client.prefs.alt_titles_preferences[job_datum.title]]) "
- jobline = "[jobline] "
+ jobline = "[jobline] ([num_positions_current]/[num_positions_total]) "
dept_dat += jobline
- //END OF SKYRAT CHANGES
+ //End of Sandstorm changes
if(!dept_dat.len)
dept_dat += "No positions open. "
dat += jointext(dept_dat, "")
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
index 08ae75d728..964a171e59 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
@@ -77,6 +77,8 @@
//For soft-restricting markings to species IDs
var/list/recommended_species
+ var/mutable_category // simply do not worry about this value
+
/datum/sprite_accessory/proc/is_not_visible(var/mob/living/carbon/human/H, var/tauric) //return if the accessory shouldn't be shown
return FALSE
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
index 3972bdc2c3..ba334d2934 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
@@ -48,6 +48,7 @@
icon = 'modular_citadel/icons/mob/xeno_parts_greyscale.dmi'
mutant_part_string = "xhead"
relevant_layers = list(BODY_ADJ_LAYER)
+ mutable_category = "HEAD"
/datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm
index 460b41f0d9..cd032b6a2a 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/arachnid.dm
@@ -49,6 +49,7 @@
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
mutant_part_string = "mandibles"
color_src = 0
+ mutable_category = "HEAD"
/datum/sprite_accessory/arachnid_mandibles/none
name = "None"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm
index d974672490..5b30591d07 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/caps.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/caps.dm
@@ -2,6 +2,7 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HAIR
relevant_layers = list(BODY_ADJ_LAYER)
+ mutable_category = "HEAD"
/datum/sprite_accessory/caps/round
name = "Round"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
index 928c4351c3..e03bf5d613 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -2,6 +2,7 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "ears"
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+ mutable_category = "HEAD"
/datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm
index f3e179e802..06d4c34f72 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm
@@ -4,6 +4,7 @@
/datum/sprite_accessory/facial_hair
icon = 'icons/mob/hair.dmi'
gender = MALE // barf (unless you're a dorf, dorfs dig chix w/ beards :P)
+ mutable_category = "HEAD"
// please make sure they're sorted alphabetically and categorized
/datum/sprite_accessory/facial_hair/shaved //this is exempt from the alphabetical sort
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
index e002fa369d..9e868d69c6 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm
@@ -3,6 +3,7 @@
//////////////////////
/datum/sprite_accessory/hair
icon = 'icons/mob/hair.dmi' // default icon for all hairs
+ mutable_category = "HEAD"
// please make sure they're sorted alphabetically and, where needed, categorized
// try to capitalize the names please~
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
index 33b513f947..bcc339f332 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm
@@ -2,6 +2,7 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HORNCOLOR
relevant_layers = list(HORNS_LAYER)
+ mutable_category = "HEAD"
/datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm
index 8bda196faa..ec5c6ea792 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm
@@ -6,6 +6,11 @@
icon = 'modular_citadel/icons/mob/ipc_screens.dmi'
color_src = null
relevant_layers = list(BODY_ADJ_LAYER)
+ mutable_category = "HEAD"
+
+/datum/sprite_accessory/screen/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
+ var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
+ return (HD == null) // it's not visible if head is null
/datum/sprite_accessory/screen/blank
name = "Blank"
@@ -133,6 +138,7 @@
relevant_layers = list(BODY_ADJ_LAYER)
recommended_species = list("ipc")
mutant_part_string = "ipc_antenna"
+ mutable_category = "HEAD"
/datum/sprite_accessory/antenna/none
name = "None"
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
index 40528b11f3..9a5a7a9a8d 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm
@@ -2,6 +2,7 @@
icon = 'icons/mob/mutant_bodyparts.dmi'
mutant_part_string = "snout"
relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER)
+ mutable_category = "HEAD"
/datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
index 08897ade34..870f4f5ba4 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm
@@ -5,6 +5,7 @@
color_src = MUTCOLORS
name = "Synthetic Lizard - Snout"
icon_state = "synthliz_basic"
+ mutable_category = "HEAD"
/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_under
icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi'
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index 7b5bfddbc3..e79bce3314 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -17,10 +17,6 @@ Doesn't work on other aliens/AI.*/
action_icon_state = "spell_default"
action_background_icon_state = "bg_alien"
-/obj/effect/proc_holder/alien/Initialize(mapload)
- . = ..()
- action = new(src)
-
/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check = FALSE)
if(!istype(user))
return TRUE
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 848883a254..5aca20825d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -964,9 +964,6 @@
/mob/living/carbon/human/species/corporate
race = /datum/species/corporate
-/mob/living/carbon/human/species/dullahan
- race = /datum/species/dullahan
-
/mob/living/carbon/human/species/felinid
race = /datum/species/human/felinid
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index dc6e1b24f8..64b5dfcd9e 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -351,11 +351,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/obj/item/organ/stomach/stomach = C.getorganslot(ORGAN_SLOT_STOMACH)
var/obj/item/organ/tail/tail = C.getorganslot(ORGAN_SLOT_TAIL)
- var/should_have_brain = TRUE
+ var/should_have_brain = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) // do not mess with a dullahans brain
var/should_have_heart = !(NOBLOOD in species_traits)
var/should_have_lungs = ((TRAIT_AUXILIARY_LUNGS in inherent_traits) || !(TRAIT_NOBREATH in inherent_traits))
var/should_have_appendix = !(TRAIT_NOHUNGER in inherent_traits)
- var/should_have_eyes = TRUE
+ var/should_have_eyes = !(HAS_TRAIT(C, TRAIT_DULLAHAN)) // .. or their eyes
var/should_have_ears = TRUE
var/should_have_tongue = TRUE
var/should_have_liver = !(NOLIVER in species_traits)
@@ -709,6 +709,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
fhair_file = 'icons/mob/facialhair_extensions.dmi'
var/mutable_appearance/facial_overlay = mutable_appearance(fhair_file, fhair_state, -HAIR_LAYER)
+ facial_overlay.category = "HEAD"
if(!forced_colour)
if(hair_color)
@@ -746,8 +747,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!hair_hidden || dynamic_hair_suffix)
var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER)
+ hair_overlay.category = "HEAD"
var/mutable_appearance/gradient_overlay = mutable_appearance(layer = -HAIR_LAYER)
- if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
+ gradient_overlay.category = "HEAD"
+ if(!hair_hidden && !H.getorgan(/obj/item/organ/brain) && !H.GetComponent(/datum/component/dullahan)) //Applies the debrained overlay if there is no brain (ignore if they are dullahan)
if(!(NOBLOOD in species_traits))
hair_overlay.icon = 'icons/mob/human_parts.dmi'
hair_overlay.icon_state = "debrained"
@@ -812,7 +815,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_overlay(HAIR_LAYER)
-/datum/species/proc/handle_body(mob/living/carbon/human/H)
+/datum/species/proc/handle_body(mob/living/carbon/human/H, block_recursive_calls = FALSE)
H.remove_overlay(BODY_LAYER)
var/list/standing = list()
@@ -823,6 +826,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// lipstick
if(H.lip_style && (LIPS in species_traits))
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[H.lip_style]", -BODY_LAYER)
+ lip_overlay.category = "HEAD"
lip_overlay.color = H.lip_color
if(OFFSET_LIPS in H.dna.species.offset_features)
@@ -833,7 +837,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
// eyes
if(!(NOEYES in species_traits))
- var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES)
+ var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES) || HAS_TRAIT(H, TRAIT_DULLAHAN) // if they are a dullahan just assume eyes exist
if(!has_eyes)
standing += mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER)
else
@@ -844,6 +848,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
right_state = "[eye_type]_right_eye"
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER)
+ left_eye.category = "HEAD"
+ right_eye.category = "HEAD"
if((EYECOLOR in species_traits) && has_eyes)
left_eye.color = "#[H.left_eye_color]"
right_eye.color = "#[H.right_eye_color]"
@@ -912,9 +918,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.overlays_standing[BODY_LAYER] = standing
H.apply_overlay(BODY_LAYER)
- handle_mutant_bodyparts(H)
+ handle_mutant_bodyparts(H, null, block_recursive_calls)
-/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
+/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour, block_recursive_calls = FALSE)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
H.remove_overlay(BODY_BEHIND_LAYER)
@@ -1040,6 +1046,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/bodypart in relevant_layers[layer])
var/datum/sprite_accessory/S = bodypart
var/mutable_appearance/accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
+ accessory_overlay.category = S.mutable_category
bodypart = S.mutant_part_string || dna_feature_as_text_string[S]
if(S.gender_specific)
@@ -1144,6 +1151,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(S.extra) //apply the extra overlay, if there is one
var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
+ extra_accessory_overlay.category = S.mutable_category
if(S.gender_specific)
extra_accessory_overlay.icon_state = "[g]_[bodypart]_extra_[S.icon_state]_[layertext]"
else
@@ -1190,6 +1198,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(S.extra2) //apply the extra overlay, if there is one
var/mutable_appearance/extra2_accessory_overlay = mutable_appearance(S.icon, layer = -layernum)
+ extra2_accessory_overlay.category = S.mutable_category
if(S.gender_specific)
extra2_accessory_overlay.icon_state = "[g]_[bodypart]_extra2_[S.icon_state]_[layertext]"
else
@@ -1237,6 +1246,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_overlay(BODY_FRONT_LAYER)
H.apply_overlay(HORNS_LAYER)
+ if(!block_recursive_calls)
+ var/datum/component/dullahan/D = H.GetComponent(/datum/component/dullahan)
+ if(D && D.dullahan_head)
+ D.dullahan_head.update_appearance()
+
/*
* Equip the outfit required for life. Replaces items currently worn.
*/
diff --git a/code/modules/mob/living/carbon/human/species_types/arachnid.dm b/code/modules/mob/living/carbon/human/species_types/arachnid.dm
index 7495e2500e..6dc19d928a 100644
--- a/code/modules/mob/living/carbon/human/species_types/arachnid.dm
+++ b/code/modules/mob/living/carbon/human/species_types/arachnid.dm
@@ -7,7 +7,7 @@
species_traits = list(LIPS, NOEYES, NO_UNDERWEAR, HAS_FLESH, HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain")
- attack_verb = "slash"
+ attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/spider
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 761274f255..7f9d3f40de 100644
--- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm
@@ -7,7 +7,7 @@
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None",
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None", "mam_body_markings" = list())
- attack_verb = "slash"
+ attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect
diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm
deleted file mode 100644
index 8bc39e43da..0000000000
--- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ /dev/null
@@ -1,165 +0,0 @@
-/datum/species/dullahan
- name = "Dullahan"
- id = SPECIES_DULLAHAN
- default_color = "FFFFFF"
- species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE)
- inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOTHIRST,TRAIT_NOBREATH)
- mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None")
- use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
- mutant_brain = /obj/item/organ/brain/dullahan
- mutanteyes = /obj/item/organ/eyes/dullahan
- mutanttongue = /obj/item/organ/tongue/dullahan
- mutantears = /obj/item/organ/ears/dullahan
- blacklisted = TRUE
- limbs_id = SPECIES_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_category = SPECIES_CATEGORY_UNDEAD
- var/pumpkin = FALSE
- wings_icons = SPECIES_WINGS_SKELETAL //seems suitable for an undead.
-
- var/obj/item/dullahan_relay/myhead
-
-/datum/species/dullahan/pumpkin
- name = "Pumpkin Head Dullahan"
- id = "pumpkindullahan"
- pumpkin = TRUE
-
-/datum/species/dullahan/check_roundstart_eligible()
- if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
- return TRUE
- return ..()
-
-/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
- . = ..()
- H.flags_1 &= ~(HEAR_1)
- var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD)
- if(head)
- if(pumpkin)//Pumpkinhead!
- head.animal_origin = 100
- head.icon = 'icons/obj/clothing/hats.dmi'
- head.icon_state = "hardhat1_pumpkin_j"
- head.custom_head = TRUE
- head.drop_limb()
- if(!QDELETED(head)) //drop_limb() deletes the limb if it's no drop location and dummy humans used for rendering icons are located in nullspace. Do the math.
- head.throwforce = 25
- myhead = new /obj/item/dullahan_relay (head, H)
- H.put_in_hands(head)
- var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES)
- for(var/datum/action/item_action/organ_action/OA in E.actions)
- OA.Trigger()
-
-/datum/species/dullahan/on_species_loss(mob/living/carbon/human/H)
- H.flags_1 |= HEAR_1
- H.reset_perspective(H)
- if(myhead)
- var/obj/item/dullahan_relay/DR = myhead
- myhead = null
- DR.owner = null
- qdel(DR)
- H.regenerate_limb(BODY_ZONE_HEAD,FALSE)
- ..()
-
-/datum/species/dullahan/spec_life(mob/living/carbon/human/H)
- if(QDELETED(myhead))
- myhead = null
- H.gib()
- var/obj/item/bodypart/head/head2 = H.get_bodypart(BODY_ZONE_HEAD)
- if(head2)
- myhead = null
- H.gib()
-
-/datum/species/dullahan/proc/update_vision_perspective(mob/living/carbon/human/H)
- var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
- if(eyes)
- H.update_tint()
- if(eyes.tint)
- H.reset_perspective(H)
- else
- H.reset_perspective(myhead)
-
-/obj/item/organ/brain/dullahan
- decoy_override = TRUE
- organ_flags = ORGAN_NO_SPOIL//Do not decay
-
-/obj/item/organ/tongue/dullahan
- zone = "abstract"
- accents = list(/datum/accent/dullahan)
-
-/obj/item/organ/ears/dullahan
- zone = "abstract"
-
-/obj/item/organ/eyes/dullahan
- name = "head vision"
- desc = "An abstraction."
- actions_types = list(/datum/action/item_action/organ_action/dullahan)
- zone = "abstract"
- tint = INFINITY // used to switch the vision perspective to the head on species_gain().
-
-/datum/action/item_action/organ_action/dullahan
- name = "Toggle Perspective"
- desc = "Switch between seeing normally from your head, or blindly from your body."
-
-/datum/action/item_action/organ_action/dullahan/Trigger()
- . = ..()
- var/obj/item/organ/eyes/dullahan/DE = target
- if(DE.tint)
- DE.tint = 0
- else
- DE.tint = INFINITY
-
- if(ishuman(owner))
- var/mob/living/carbon/human/H = owner
- if(isdullahan(H))
- var/datum/species/dullahan/D = H.dna.species
- D.update_vision_perspective(H)
-
-/obj/item/dullahan_relay
- name = "dullahan relay"
- var/mob/living/owner
- flags_1 = HEAR_1
-
-/obj/item/dullahan_relay/Initialize(mapload, mob/living/carbon/human/new_owner)
- . = ..()
- if(!new_owner)
- return INITIALIZE_HINT_QDEL
- owner = new_owner
- START_PROCESSING(SSobj, src)
- RegisterSignal(owner, COMSIG_MOB_CLICKED_SHIFT_ON, .proc/examinate_check)
- RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
- RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
- RegisterSignal(owner, COMSIG_LIVING_REVIVE, .proc/retrieve_head)
-
-/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/target)
- if(source.client.eye == src)
- return COMPONENT_ALLOW_EXAMINATE
-
-/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers)
- if(!QDELETED(owner))
- hearers += owner
-
-/obj/item/dullahan_relay/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
- excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
-
-//Retrieving the owner's head for better ahealing.
-/obj/item/dullahan_relay/proc/retrieve_head(datum/source, full_heal, admin_revive)
- if(admin_revive)
- var/obj/item/bodypart/head/H = loc
- var/turf/T = get_turf(owner)
- if(H && istype(H) && T && !(H in owner.GetAllContents()))
- H.forceMove(T)
-
-/obj/item/dullahan_relay/process()
- if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner))
- . = PROCESS_KILL
- qdel(src)
-
-/obj/item/dullahan_relay/Destroy()
- if(!QDELETED(owner))
- var/mob/living/carbon/human/H = owner
- if(isdullahan(H))
- var/datum/species/dullahan/D = H.dna.species
- D.myhead = null
- owner.gib()
- owner = null
- ..()
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 d4a8150c29..01f82cbac3 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -424,7 +424,7 @@
coldmod = 3
heatmod = 1
burnmod = 1
-
+ balance_point_values = TRUE
allowed_limb_ids = list(SPECIES_SLIME,SPECIES_STARGAZER,SPECIES_SLIME_LUMI)
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
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 e3f7b700dc..81a46cbf66 100644
--- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm
@@ -13,7 +13,7 @@
mutant_bodyparts = list("mcolor" = "0F0", "mcolor2" = "0F0", "mcolor3" = "0F0", "tail_lizard" = "Smooth", "mam_snouts" = "Round",
"horns" = "None", "frills" = "None", "spines" = "None", "mam_body_markings" = list(),
"legs" = "Digitigrade", "taur" = "None", "deco_wings" = "None")
- attack_verb = "slash"
+ attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/lizard
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 a985ca85df..11ca51c74c 100644
--- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
+++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm
@@ -27,6 +27,7 @@
wings_icons = SPECIES_WINGS_SKELETAL
ass_image = 'icons/ass/assplasma.png'
+ balance_point_values = TRUE
blacklisted_quirks = list(/datum/quirk/paper_skin)
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
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 326f23fa1f..996a4e742a 100644
--- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm
@@ -4,7 +4,7 @@
id = SPECIES_POD
default_color = "59CE00"
species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE)
- attack_verb = "slash"
+ attack_verb = "claw"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.25
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 cc8025d730..6189a268ca 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -17,6 +17,7 @@
species_category = SPECIES_CATEGORY_SKELETON //they have their own category that's disassociated from undead, paired with plasmapeople
wings_icons = SPECIES_WINGS_SKELETAL
+ balance_point_values = TRUE
blacklisted_quirks = list(/datum/quirk/paper_skin)
/datum/species/skeleton/New()
@@ -36,6 +37,7 @@
id = SPECIES_SKELETON_SPACE
limbs_id = SPECIES_SKELETON
blacklisted = 1
+ balance_point_values = FALSE
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_NOTHIRST,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT, TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER)
/datum/species/skeleton/space/check_roundstart_eligible()
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 cd3ba8d5cc..3d710988e5 100644
--- a/code/modules/mob/living/carbon/human/species_types/xeno.dm
+++ b/code/modules/mob/living/carbon/human/species_types/xeno.dm
@@ -6,7 +6,7 @@
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = list(),"mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade","deco_wings"= "None")
- attack_verb = "slash"
+ attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4f00b51e97..ad1ac131e7 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -58,14 +58,14 @@ There are several things that need to be remembered:
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()
+/mob/living/carbon/human/proc/update_mutant_bodyparts(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
- dna.species.handle_mutant_bodyparts(src)
+ dna.species.handle_mutant_bodyparts(src, null, block_recursive_calls)
-/mob/living/carbon/human/update_body(update_genitals = FALSE)
+/mob/living/carbon/human/update_body(update_genitals = FALSE, block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(BODY_LAYER)
- dna.species.handle_body(src)
+ dna.species.handle_body(src, block_recursive_calls)
..()
if(update_genitals)
update_genitals()
@@ -75,17 +75,17 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//For legacy support.
-/mob/living/carbon/human/regenerate_icons()
+/mob/living/carbon/human/regenerate_icons(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
if(!..())
icon_render_key = null //invalidate bodyparts cache
- update_body(TRUE)
+ update_body(TRUE, block_recursive_calls)
update_hair()
- update_inv_w_uniform()
+ update_inv_w_uniform(block_recursive_calls)
// Sandstorm edit
- update_inv_w_underwear()
- update_inv_w_socks()
- update_inv_w_shirt()
+ update_inv_w_underwear(block_recursive_calls)
+ update_inv_w_socks(block_recursive_calls)
+ update_inv_w_shirt(block_recursive_calls)
update_inv_ears_extra()
update_inv_wrists()
//
@@ -95,11 +95,11 @@ There are several things that need to be remembered:
update_inv_ears()
update_inv_shoes()
update_inv_s_store()
- update_inv_wear_mask()
- update_inv_head()
+ update_inv_wear_mask(block_recursive_calls)
+ update_inv_head(block_recursive_calls)
update_inv_belt()
update_inv_back()
- update_inv_wear_suit()
+ update_inv_wear_suit(block_recursive_calls)
update_inv_pockets()
update_inv_neck()
update_transform()
@@ -130,7 +130,7 @@ There are several things that need to be remembered:
apply_overlay(ANTAG_LAYER)
-/mob/living/carbon/human/update_inv_w_uniform()
+/mob/living/carbon/human/update_inv_w_uniform(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(UNIFORM_LAYER)
@@ -187,10 +187,10 @@ There are several things that need to be remembered:
//SPLURT EDIT END
apply_overlay(UNIFORM_LAYER)
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
// Sandstorm edit
-/mob/living/carbon/human/update_inv_w_underwear()
+/mob/living/carbon/human/update_inv_w_underwear(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(UNDERWEAR_LAYER)
@@ -235,9 +235,9 @@ There are several things that need to be remembered:
overlays_standing[UNDERWEAR_LAYER] = underwear_overlay
apply_overlay(UNDERWEAR_LAYER)
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
-/mob/living/carbon/human/update_inv_w_socks()
+/mob/living/carbon/human/update_inv_w_socks(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SOCKS_LAYER)
@@ -282,9 +282,9 @@ There are several things that need to be remembered:
overlays_standing[SOCKS_LAYER] = underwear_overlay
apply_overlay(SOCKS_LAYER)
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
-/mob/living/carbon/human/update_inv_w_shirt()
+/mob/living/carbon/human/update_inv_w_shirt(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SHIRT_LAYER)
@@ -329,7 +329,7 @@ There are several things that need to be remembered:
overlays_standing[SHIRT_LAYER] = underwear_overlay
apply_overlay(SHIRT_LAYER)
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
//
/mob/living/carbon/human/update_inv_wear_id()
@@ -566,7 +566,7 @@ There are several things that need to be remembered:
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
apply_overlay(SUIT_STORE_LAYER)
-/mob/living/carbon/human/update_inv_head()
+/mob/living/carbon/human/update_inv_head(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(HEAD_LAYER)
@@ -604,7 +604,7 @@ There are several things that need to be remembered:
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
overlays_standing[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
/mob/living/carbon/human/update_inv_belt()
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
@@ -628,7 +628,7 @@ There are several things that need to be remembered:
overlays_standing[BELT_LAYER] = belt_overlay
apply_overlay(BELT_LAYER)
-/mob/living/carbon/human/update_inv_wear_suit()
+/mob/living/carbon/human/update_inv_wear_suit(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(SUIT_LAYER)
@@ -688,7 +688,7 @@ There are several things that need to be remembered:
suit_overlay = center_image(suit_overlay, dimension_x, dimension_y)
overlays_standing[SUIT_LAYER] = suit_overlay
update_hair()
- update_mutant_bodyparts()
+ update_mutant_bodyparts(block_recursive_calls)
apply_overlay(SUIT_LAYER)
@@ -715,7 +715,7 @@ There are several things that need to be remembered:
update_observer_view(r_store)
-/mob/living/carbon/human/update_inv_wear_mask()
+/mob/living/carbon/human/update_inv_wear_mask(block_recursive_calls = FALSE)
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
remove_overlay(FACEMASK_LAYER)
@@ -754,7 +754,7 @@ There are several things that need to be remembered:
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
+ update_mutant_bodyparts(block_recursive_calls) //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
if(!HAS_TRAIT(src, TRAIT_HUMAN_NO_RENDER))
@@ -1008,7 +1008,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
// eyes
if(!(NOEYES in dna.species.species_traits))
var/has_eyes = getorganslot(ORGAN_SLOT_EYES)
- if(!has_eyes)
+ if(!has_eyes && !HAS_TRAIT(src, TRAIT_DULLAHAN))
add_overlay(mutable_appearance('icons/mob/eyes.dmi', "eyes_missing", -BODY_LAYER))
else
var/left_state = DEFAULT_LEFT_EYE_STATE
@@ -1020,6 +1020,8 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if
right_state = eye_type + "_right_eye"
var/mutable_appearance/left_eye = mutable_appearance('icons/mob/eyes.dmi', left_state, -BODY_LAYER)
var/mutable_appearance/right_eye = mutable_appearance('icons/mob/eyes.dmi', right_state, -BODY_LAYER)
+ left_eye.category = "HEAD"
+ right_eye.category = "HEAD"
if((EYECOLOR in dna.species.species_traits) && has_eyes)
left_eye.color = "#" + left_eye_color
right_eye.color = "#" + right_eye_color
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index deaf50973d..2e9030765a 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -493,43 +493,61 @@
call_bot_cooldown = 0
-/mob/living/silicon/ai/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/silicon/ai/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- if (O)
- if (C && C.can_use())
- queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag] )", class)
- else if (CL && CL.len)
+ if (!(source in sources))
+ sources += source
+ return TRUE
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+
+ if (cameras)
+ if (cam?.can_use())
+ queueAlarm("--- [class] alarm detected in [home.name]! ([cam.c_tag] )", class)
+ else if (our_cams?.len)
var/foo = 0
var/dat2 = ""
- for (var/obj/machinery/camera/I in CL)
+ for (var/obj/machinery/camera/I in our_cams)
dat2 += text("[][] ", (!foo) ? "" : " | ", I.c_tag) //I'm not fixing this shit...
foo = 1
- queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
+ queueAlarm(text ("--- [] alarm detected in []! ([])", class, home.name, dat2), class)
else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
+ queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, home.name), class)
else
- queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
- if (viewalerts) ai_alerts()
+ queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, home.name), class)
+ if (viewalerts)
+ ai_alerts()
return 1
+/mob/living/silicon/ai/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
+
/mob/living/silicon/ai/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = 0
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index d73f738bb5..b5b142604a 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -263,31 +263,47 @@
/mob/living/silicon/robot/restrained(ignore_grab)
. = 0
-/mob/living/silicon/robot/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/silicon/robot/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
if(stat == DEAD)
return 1
- var/list/L = alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
- if (!(alarmsource in sources))
- sources += alarmsource
+ if (!(source in sources))
+ sources += source
return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if (O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- queueAlarm(text("--- [class] alarm detected in [A.name]!"), class)
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
+ queueAlarm(text("--- [class] alarm detected in [home.name]!"), class)
return TRUE
+/mob/living/silicon/robot/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
+
/mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
var/cleared = 0
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 3b89413271..be9ea03e6e 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -86,6 +86,9 @@
/mob/living/silicon/proc/cancelAlarm()
return
+/mob/living/silicon/proc/freeCamera()
+ return
+
/mob/living/silicon/proc/triggerAlarm()
return
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 203ac5f846..1320c13085 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -194,9 +194,9 @@
GLOB.bots_list -= src
if(paicard)
ejectpai()
- qdel(Radio)
- qdel(access_card)
- qdel(bot_core)
+ QDEL_NULL(Radio)
+ QDEL_NULL(access_card)
+ QDEL_NULL(bot_core)
return ..()
/mob/living/simple_animal/bot/bee_friendly()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 003994e34f..62d1116300 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -235,20 +235,26 @@
adjustBruteLoss(heavy_emp_damage)
to_chat(src, "HeAV% DA%^MMA+G TO I/O CIR!%UUT! ")
-/mob/living/simple_animal/drone/proc/triggerAlarm(class, area/A, O, obj/alarmsource)
- if(alarmsource.z != z)
+/mob/living/simple_animal/drone/proc/triggerAlarm(class, area/home, cameras, obj/source)
+ if(source.z != z)
return
- if(stat != DEAD)
- var/list/L = src.alarms[class]
- for (var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
- var/list/sources = alarm[2]
- if (!(alarmsource in sources))
- sources += alarmsource
- return
- L[A.name] = list(A, list(alarmsource))
- to_chat(src, "--- [class] alarm detected in [A.name]!")
+ if(stat == DEAD)
+ return
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
+ var/list/sources = alarm[3]
+ if (!(source in sources))
+ sources += source
+ return TRUE
+
+ our_sort[home.name] = list(home, list(source))
+ to_chat(src, "--- [class] alarm detected in [home.name]!")
+
+///This isn't currently needed since drones do jack shit with cameras. I hate this code so much
+/mob/living/simple_animal/drone/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ return
/mob/living/simple_animal/drone/proc/cancelAlarm(class, area/A, obj/origin)
if(stat != DEAD)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 43461320a3..3369588915 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -175,9 +175,6 @@ Difficulty: Medium
. = ..()
if(. && target && !targets_the_same)
wander = TRUE
- if(HAS_TRAIT(target, TRAIT_CURSED_BLOOD))
- say(pick("Hunter, you must accept your death, be freed from the night.","The night, and the dream, were long...","Beasts all over the shop... You'll be one of them, sooner or later...","The night blocks all sight..."))
-
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash_attack()
INVOKE_ASYNC(src, .proc/dash, target)
diff --git a/code/modules/mob/mob_lists.dm b/code/modules/mob/mob_lists.dm
index 14f519ec30..bd47d511e1 100644
--- a/code/modules/mob/mob_lists.dm
+++ b/code/modules/mob/mob_lists.dm
@@ -10,6 +10,8 @@
///Adds the mob reference to the list of all mobs alive. If mob is cliented, it adds it to the list of all living player-mobs.
/mob/proc/add_to_alive_mob_list()
+ if(QDELETED(src))
+ return
GLOB.alive_mob_list |= src
if(client)
add_to_current_living_players()
@@ -23,6 +25,8 @@
///Adds the mob reference to the list of all the dead mobs. If mob is cliented, it adds it to the list of all dead player-mobs.
/mob/proc/add_to_dead_mob_list()
+ if(QDELETED(src))
+ return
GLOB.dead_mob_list |= src
if(client)
add_to_current_dead_players()
diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm
index 646d9892ba..80c0c4dfa8 100644
--- a/code/modules/modular_computers/file_system/programs/alarm.dm
+++ b/code/modules/modular_computers/file_system/programs/alarm.dm
@@ -36,35 +36,49 @@
return data
-/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/A, O, obj/source)
+/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/home, cameras, obj/source)
if(is_station_level(source.z))
- if(!(A.type in GLOB.the_station_areas))
+ if(!(home.type in GLOB.the_station_areas))
return
- else if(!is_mining_level(source.z) || istype(A, /area/ruin))
+ else if(!is_mining_level(source.z) || istype(home, /area/ruin))
return
- var/list/L = alarms[class]
- for(var/I in L)
- if (I == A.name)
- var/list/alarm = L[I]
+ var/list/our_sort = alarms[class]
+ for(var/areaname in our_sort)
+ if (areaname == home.name)
+ var/list/alarm = our_sort[areaname]
var/list/sources = alarm[3]
if (!(source in sources))
sources += source
- return 1
- var/obj/machinery/camera/C = null
- var/list/CL = null
- if(O && istype(O, /list))
- CL = O
- if (CL.len == 1)
- C = CL[1]
- else if(O && istype(O, /obj/machinery/camera))
- C = O
- L[A.name] = list(A, (C ? C : O), list(source))
+ return TRUE
+
+ var/obj/machinery/camera/cam = null
+ var/list/our_cams = null
+ if(cameras && islist(cameras))
+ our_cams = cameras
+ if (our_cams.len == 1)
+ cam = our_cams[1]
+ else if(cameras && istype(cameras, /obj/machinery/camera))
+ cam = cameras
+ our_sort[home.name] = list(home, (cam ? cam : cameras), list(source))
update_alarm_display()
+ return TRUE
- return 1
-
+/datum/computer_file/program/alarm_monitor/proc/freeCamera(area/home, obj/machinery/camera/cam)
+ for(var/class in alarms)
+ var/our_area = alarms[class][home.name]
+ if(!our_area)
+ continue
+ var/cams = our_area[2] //Get the cameras
+ if(!cams)
+ continue
+ if(islist(cams))
+ cams -= cam
+ if(length(cams) == 1)
+ our_area[2] = cams[1]
+ else
+ our_area[2] = null
/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin)
var/list/L = alarms[class]
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 0bd91c5f35..0a7d6d05da 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -105,12 +105,13 @@
custom_materials = list(/datum/material/gold = 750)
sharpness = SHARP_EDGED
resistance_flags = FIRE_PROOF
- unique_reskin = list("Oak" = "pen-fountain-o",
- "Gold" = "pen-fountain-g",
- "Rosewood" = "pen-fountain-r",
- "Black and Silver" = "pen-fountain-b",
- "Command Blue" = "pen-fountain-cb"
- )
+ unique_reskin = list(
+ "Oak" = list("icon_state" = "pen-fountain-o"),
+ "Gold" = list("icon_state" = "pen-fountain-g"),
+ "Rosewood" = list("icon_state" = "pen-fountain-r"),
+ "Black and Silver" = list("icon_state" = "pen-fountain-b"),
+ "Command Blue" = list("icon_state" = "pen-fountain-cb")
+ )
embedding = list("embed_chance" = 75)
/obj/item/pen/fountain/captain/Initialize(mapload)
@@ -118,9 +119,8 @@
AddComponent(/datum/component/butchering, 200, 115) //the pen is mightier than the sword
/obj/item/pen/fountain/captain/reskin_obj(mob/M)
- ..()
- if(current_skin)
- desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp."
+ . = ..()
+ desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp."
/obj/item/pen/attack_self(mob/living/carbon/user)
var/deg = input(user, "What angle would you like to rotate the pen head to? (1-360)", "Rotate Pen Head") as null|num
diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm
index ff1a1fd563..9683601670 100644
--- a/code/modules/paperwork/ticketmachine.dm
+++ b/code/modules/paperwork/ticketmachine.dm
@@ -82,15 +82,15 @@
if(M.buffer && !istype(M.buffer, /obj/machinery/ticket_machine))
return
var/obj/item/assembly/control/ticket_machine/controller = device
- controller.linked = M.buffer
+ controller.linked = WEAKREF(M.buffer)
id = null
controller.id = null
- to_chat(user, "You've linked [src] to [controller.linked]. ")
+ to_chat(user, "You've linked [src] to [M.buffer]. ")
/obj/item/assembly/control/ticket_machine
name = "ticket machine controller"
desc = "A remote controller for the HoP's ticket machine."
- var/obj/machinery/ticket_machine/linked //To whom are we linked?
+ var/datum/weakref/linked //To whom are we linked?
/obj/item/assembly/control/ticket_machine/Initialize(mapload)
..()
@@ -102,7 +102,7 @@
/obj/item/assembly/control/ticket_machine/proc/find_machine() //Locate the one to which we're linked
for(var/obj/machinery/ticket_machine/ticketsplease in GLOB.machines)
if(ticketsplease.id == id)
- linked = ticketsplease
+ linked = WEAKREF(ticketsplease)
if(linked)
return TRUE
else
@@ -113,8 +113,11 @@
return
if(!linked)
return
+ var/obj/machinery/ticket_machine/machine = linked.resolve()
+ if(!machine)
+ return
cooldown = TRUE
- linked.increment()
+ machine.increment()
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/machinery/ticket_machine/update_icon()
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 84a0ef96c1..5e7872b92e 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -300,7 +300,7 @@
area.power_equip = FALSE
area.power_environ = FALSE
area.power_change()
- area.poweralert(TRUE, src)
+ area.poweralert(FALSE, src)
if(occupier)
malfvacate(1)
qdel(wires)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 9d488dc222..7f9c1ef60a 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -505,7 +505,7 @@
drop_light_tube()
new /obj/item/stack/cable_coil(loc, 1, "red")
transfer_fingerprints_to(newlight)
- if(cell)
+ if(!QDELETED(cell))
newlight.cell = cell
cell.forceMove(newlight)
cell = null
diff --git a/code/modules/power/reactor/rbmk.dm b/code/modules/power/reactor/rbmk.dm
index 609ec72984..cea10c6116 100644
--- a/code/modules/power/reactor/rbmk.dm
+++ b/code/modules/power/reactor/rbmk.dm
@@ -342,7 +342,7 @@ The reactor CHEWS through moderator. It does not do this slowly. Be very careful
playsound(src, pick('sound/machines/fryer/deep_fryer_1.ogg', 'sound/machines/fryer/deep_fryer_2.ogg'), 100, TRUE)
var/obj/item/reagent_containers/food/grilled_item = I
if(prob(80))
- return //To give the illusion that it's actually cooking omegalul.
+ continue //To give the illusion that it's actually cooking omegalul.
switch(power)
if(20 to 39)
grilled_item.name = "grilled [initial(grilled_item.name)]"
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 3f2f4d3e65..5c6aff5564 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -23,7 +23,7 @@
/obj/item/gun/ballistic/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][suppressed ? "-suppressed" : ""][sawn_off ? "-sawn" : ""]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][suppressed ? "-suppressed" : ""][sawn_off ? "-sawn" : ""]"
else
icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_off ? "-sawn" : ""]"
diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm
index bd6f203882..53ba6d6a92 100644
--- a/code/modules/projectiles/guns/ballistic/pistol.dm
+++ b/code/modules/projectiles/guns/ballistic/pistol.dm
@@ -30,27 +30,28 @@
can_unsuppress = TRUE
automatic_burst_overlay = FALSE
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "cde",
- "N-99" = "n99",
- "Stealth" = "stealthpistol",
- "HKVP-78" = "vp78",
- "Luger" = "p08b",
- "Mk.58" = "secguncomp",
- "PX4 Storm" = "px4"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "cde"),
+ "N-99" = list("icon_state" = "n99"),
+ "Stealth" = list("icon_state" = "stealthpistol"),
+ "HKVP-78" = list("icon_state" = "vp78"),
+ "Luger" = list("icon_state" = "p08b"),
+ "Mk.58" = list("icon_state" = "secguncomp"),
+ "PX4 Storm" = list("icon_state" = "px4")
+ )
/obj/item/gun/ballistic/automatic/pistol/modular/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
else
icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/pistol/modular/update_overlays()
. = ..()
if(magazine && suppressed)
- . += "[unique_reskin[current_skin]]-magazine-sup" //Yes, this means the default iconstate can't have a magazine overlay
+ . += "[unique_reskin[current_skin]["icon_state"]]-magazine-sup" //Yes, this means the default iconstate can't have a magazine overlay
else if (magazine)
- . += "[unique_reskin[current_skin]]-magazine"
+ . += "[unique_reskin[current_skin]["icon_state"]]-magazine"
/obj/item/gun/ballistic/automatic/pistol/m1911
name = "\improper M1911"
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index f3b07aa7a4..28f81e13ae 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -88,13 +88,15 @@
/obj/item/gun/ballistic/revolver/syndicate
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "revolver",
- "Silver" = "russianrevolver",
- "Robust" = "revolvercit",
- "Bulky" = "revolverhakita",
- "Polished" = "revolvertoriate",
- "Soulless" = "revolveroldflip",
- "Soul" = "revolverold")
+ unique_reskin = list(
+ "Default" = list("icon_state" = "revolver"),
+ "Silver" = list("icon_state" = "russianrevolver"),
+ "Robust" = list("icon_state" = "revolvercit"),
+ "Bulky" = list("icon_state" = "revolverhakita"),
+ "Polished" = list("icon_state" = "revolvertoriate"),
+ "Soulless" = list("icon_state" = "revolveroldflip"),
+ "Soul" = list("icon_state" = "revolverold")
+ )
/obj/item/gun/ballistic/revolver/detective
name = "\improper .38 Mars Special"
@@ -102,12 +104,13 @@
icon_state = "detective"
mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev38
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "detective",
- "Leopard Spots" = "detective_leopard",
- "Black Panther" = "detective_panther",
- "Gold Trim" = "detective_gold",
- "The Peacemaker" = "detective_peacemaker"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "detective"),
+ "Leopard Spots" = list("icon_state" = "detective_leopard"),
+ "Black Panther" = list("icon_state" = "detective_panther"),
+ "Gold Trim" = list("icon_state" = "detective_gold"),
+ "The Peacemaker" = list("icon_state" = "detective_peacemaker")
+ )
var/list/safe_calibers
/obj/item/gun/ballistic/revolver/detective/Initialize(mapload)
@@ -294,13 +297,14 @@
mag_type = /obj/item/ammo_box/magazine/internal/shot/dual
sawn_desc = "Omar's coming!"
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "dshotgun",
- "Dark Red Finish" = "dshotgun-d",
- "Ash" = "dshotgun-f",
- "Faded Grey" = "dshotgun-g",
- "Maple" = "dshotgun-l",
- "Rosewood" = "dshotgun-p"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "dshotgun"),
+ "Dark Red Finish" = list("icon_state" = "dshotgun-d"),
+ "Ash" = list("icon_state" = "dshotgun-f"),
+ "Faded Grey" = list("icon_state" = "dshotgun-g"),
+ "Maple" = list("icon_state" = "dshotgun-l"),
+ "Rosewood" = list("icon_state" = "dshotgun-p")
+ )
/obj/item/gun/ballistic/revolver/doublebarrel/attackby(obj/item/A, mob/user, params)
..()
@@ -342,9 +346,10 @@
slot_flags = null
mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised
sawn_desc = "I'm just here for the gasoline."
- unique_reskin = list("Default" = "ishotgun",
- "Cobbled" = "old_ishotgun"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "ishotgun"),
+ "Cobbled" = list("icon_state" = "old_ishotgun")
+ )
var/slung = FALSE
/obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params)
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index 25e4b6b12a..6ffdbee6db 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -95,9 +95,10 @@
fire_delay = 7
mag_type = /obj/item/ammo_box/magazine/internal/shot/riot
sawn_desc = "Come with me if you want to live."
- unique_reskin = list("Tactical" = "riotshotgun",
- "Wood Stock" = "wood_riotshotgun"
- )
+ unique_reskin = list(
+ "Tactical" = list("icon_state" = "riotshotgun"),
+ "Wood Stock" = list("icon_state" = "wood_riotshotgun")
+ )
/obj/item/gun/ballistic/shotgun/riot/attackby(obj/item/A, mob/user, params)
..()
@@ -235,9 +236,10 @@
fire_delay = 5
mag_type = /obj/item/ammo_box/magazine/internal/shot/com
w_class = WEIGHT_CLASS_HUGE
- unique_reskin = list("Tactical" = "cshotgun",
- "Slick" = "cshotgun_slick"
- )
+ unique_reskin = list(
+ "Tactical" = list("icon_state" = "cshotgun"),
+ "Slick" = list("icon_state" = "cshotgun_slick")
+ )
/obj/item/gun/ballistic/shotgun/automatic/combat/compact
name = "warden's combat shotgun"
@@ -276,7 +278,7 @@
update_icon()
/obj/item/gun/ballistic/shotgun/automatic/combat/compact/update_icon_state()
- icon_state = "[current_skin ? unique_reskin[current_skin] : "cshotgun"][stock ? "" : "c"]"
+ icon_state = "[current_skin ? unique_reskin[current_skin]["icon_state"] : "cshotgun"][stock ? "" : "c"]"
/obj/item/gun/ballistic/shotgun/automatic/combat/compact/afterattack(atom/target, mob/living/user, flag, params)
if(!stock)
@@ -365,7 +367,7 @@
/obj/item/gun/ballistic/shotgun/leveraction/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][sawn_off ? "-sawn" : ""][chambered ? "" : "-e"]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][sawn_off ? "-sawn" : ""][chambered ? "" : "-e"]"
else
icon_state = "[initial(icon_state)][sawn_off ? "-sawn" : ""][chambered ? "" : "-e"]"
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index 94c2d62902..b56742dd23 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -37,7 +37,7 @@
return BULLET_ACT_BLOCK
if(iscarbon(target))
var/mob/living/carbon/C = target
- if(!is_species(C, /datum/species/dullahan)) //No accidental instagibbing dullahans please
+ if(HAS_TRAIT(C, TRAIT_DULLAHAN)) //No accidental instagibbing dullahans please
C.regenerate_limbs()
C.regenerate_organs()
if(target.revive(full_heal = 1))
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 7eb5805ea2..f7eb205c6e 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -641,19 +641,11 @@
desc = "Contains a large reservoir of soft drinks. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/fullupgrade
/obj/machinery/chem_dispenser/drinks/fullupgrade/Initialize(mapload)
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
- component_parts += new /obj/item/stock_parts/manipulator/femto(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- component_parts += new /obj/item/stock_parts/cell/bluespace(null)
- RefreshParts()
/obj/machinery/chem_dispenser/drinks/beer
name = "booze dispenser"
@@ -701,19 +693,11 @@
desc = "Contains a large reservoir of the good stuff. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/beer/fullupgrade
/obj/machinery/chem_dispenser/drinks/beer/fullupgrade/Initialize(mapload)
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks/beer(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
- component_parts += new /obj/item/stock_parts/manipulator/femto(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- component_parts += new /obj/item/stock_parts/cell/bluespace(null)
- RefreshParts()
/obj/machinery/chem_dispenser/mutagen
name = "mutagen dispenser"
@@ -729,6 +713,7 @@
desc = "Creates and dispenses chemicals useful for botany."
flags_1 = NODECONSTRUCT_1
canStore = FALSE
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/mutagensaltpeter
dispensable_reagents = list(
/datum/reagent/toxin/mutagen,
@@ -749,35 +734,15 @@
upgrade_reagents2 = null
upgrade_reagents3 = null
-/obj/machinery/chem_dispenser/mutagensaltpeter/Initialize(mapload)
- . = ..()
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
- component_parts += new /obj/item/stock_parts/manipulator/femto(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- component_parts += new /obj/item/stock_parts/cell/bluespace(null)
- RefreshParts()
-
/obj/machinery/chem_dispenser/fullupgrade //fully ugpraded stock parts, emagged
desc = "Creates and dispenses chemicals. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
+ circuit = /obj/item/circuitboard/machine/chem_dispenser/fullupgrade
/obj/machinery/chem_dispenser/fullupgrade/Initialize(mapload)
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
- component_parts += new /obj/item/stock_parts/manipulator/femto(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- component_parts += new /obj/item/stock_parts/cell/bluespace(null)
- RefreshParts()
/obj/machinery/chem_dispenser/abductor
name = "reagent synthesizer"
@@ -831,18 +796,6 @@
/datum/reagent/medicine/morphine
)
-/obj/machinery/chem_dispenser/abductor/Initialize(mapload)
- . = ..()
- component_parts = list()
- component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
- component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
- component_parts += new /obj/item/stock_parts/manipulator/femto(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- component_parts += new /obj/item/stock_parts/cell/bluespace(null)
- RefreshParts()
-
///An unique, less efficient model found in the medbay apothecary room.
/obj/machinery/chem_dispenser/apothecary
name = "apothecary chem dispenser"
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index 5fdf4574f4..348556c337 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -1088,7 +1088,7 @@
var/list/adjusted = H.adjust_arousal(5,aphro = TRUE)
for(var/g in adjusted)
var/obj/item/organ/genital/G = g
- to_chat(M, "You feel like playing with your [G.name]! ")
+ to_chat(M, span_userlove("You feel like playing with your [G.name]!"))
..()
/datum/reagent/consumable/monkey_energy
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 4848347df2..c709fd09a7 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -570,13 +570,13 @@
M.emote(pick("moan","blush"))
if(prob(min(current_cycle/4,10)))
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
- to_chat(M, "[aroused_message] ")
+ to_chat(M, span_userlove("[aroused_message]"))
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/list/genits = H.adjust_arousal(current_cycle, "crocin", aphro = TRUE) // redundant but should still be here
for(var/g in genits)
var/obj/item/organ/genital/G = g
- to_chat(M, "[G.arousal_verb]! ")
+ to_chat(M, span_userlove("[G.arousal_verb]!"))
..()
/datum/reagent/drug/aphrodisiacplus
@@ -603,14 +603,14 @@
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
else
aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
- to_chat(M, "[aroused_message] ")
+ to_chat(M, span_userlove("[aroused_message]"))
REMOVE_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/list/genits = H.adjust_arousal(100, "hexacrocin", aphro = TRUE) // redundant but should still be here
for(var/g in genits)
var/obj/item/organ/genital/G = g
- to_chat(M, "[G.arousal_verb]! ")
+ to_chat(M, span_userlove("[G.arousal_verb]!"))
..()
/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M)
@@ -631,7 +631,7 @@
if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33))
if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION))
if(!HAS_TRAIT(M,TRAIT_PERMABONER))
- to_chat(M, "Your libido is going haywire! ")
+ to_chat(M, span_userlove("Your libido is going haywire!"))
M.log_message("Made perma-horny by hexacrocin.",LOG_EMOTE)
ADD_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT)
..()
@@ -677,6 +677,6 @@
/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M)
if(M && M.client?.prefs.arousable && prob(5))
- to_chat(M, "You feel like you'll never feel aroused again... ")
+ to_chat(M, span_userlove("You feel like you'll never feel aroused again..."))
ADD_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT)
..()
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 2784fa6752..44500ade1f 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -1087,6 +1087,13 @@
else
B.gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
+/datum/reagent/medicine/neurine/reaction_obj(obj/O, reac_volume)
+ if(istype(O, /obj/item/dullahan_head))
+ var/obj/item/dullahan_head/head = O
+ if(head.B)
+ head.B.applyOrganDamage(-20)
+ if(head.owner)
+ head.owner.cure_trauma_type(resilience = TRAUMA_RESILIENCE_SURGERY)
/datum/reagent/medicine/neurine/on_mob_life(mob/living/carbon/C)
if(holder.has_reagent(/datum/reagent/consumable/ethanol/neurotoxin))
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 3db89f168d..8bbaa55a66 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -411,18 +411,6 @@
"You can't save him. Nothing can save him now", "It seems that Nar'Sie will triumph after all")]. ")
if("emote")
M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")]. ")
- else if(HAS_TRAIT(M, TRAIT_CURSED_BLOOD) && prob(12))
- M.say(pick("Somebody help me...","Unshackle me please...","Anybody... I've had enough of this dream...","The night blocks all sight...","Oh, somebody, please..."), forced = "holy water")
- if(prob(10))
- M.visible_message("[M] starts having a seizure! ", "You have a seizure! ")
- M.Unconscious(120)
- to_chat(M, "[pick("The moon is close. It will be a long hunt tonight.", "Ludwig, why have you forsaken me?", \
- "The night is near its end...", "Fear the blood...")] ")
- if(prob(25)) //Prob of a prob.. Shouldn't happen too often but hey, that's what you get.
- M.IgniteMob()
- else
- M.adjustToxLoss(1, 0)
- M.adjustFireLoss(1, 0)
if(data["misc"] >= 60) // 30 units, 135 seconds
if(iscultist(M, FALSE, TRUE) || is_servant_of_ratvar(M, FALSE, TRUE))
if(iscultist(M))
@@ -2440,7 +2428,7 @@
var/list/adjusted = H.adjust_arousal(2,"catnip", aphro = TRUE)
for(var/g in adjusted)
var/obj/item/organ/genital/G = g
- to_chat(M, "You feel like playing with your [G.name]! ")
+ to_chat(M, span_userlove("You feel like playing with your [G.name]!"))
..()
/datum/reagent/preservahyde
diff --git a/code/modules/reagents/reagent_containers/hypovial.dm b/code/modules/reagents/reagent_containers/hypovial.dm
index 43f9f88976..0f9ffd6514 100644
--- a/code/modules/reagents/reagent_containers/hypovial.dm
+++ b/code/modules/reagents/reagent_containers/hypovial.dm
@@ -9,15 +9,16 @@
possible_transfer_amounts = list(1,2,5,10)
container_flags = APTFT_VERB
obj_flags = UNIQUE_RENAME
- unique_reskin = list("hypovial" = "hypovial",
- "red hypovial" = "hypovial-b",
- "blue hypovial" = "hypovial-d",
- "green hypovial" = "hypovial-a",
- "orange hypovial" = "hypovial-k",
- "purple hypovial" = "hypovial-p",
- "black hypovial" = "hypovial-t",
- "pink hypovial" = "hypovial-pink"
- )
+ unique_reskin = list(
+ "hypovial" = list("icon_state" = "hypovial"),
+ "red hypovial" = list("icon_state" = "hypovial-b"),
+ "blue hypovial" = list("icon_state" = "hypovial-d"),
+ "green hypovial" = list("icon_state" = "hypovial-a"),
+ "orange hypovial" = list("icon_state" = "hypovial-k"),
+ "purple hypovial" = list("icon_state" = "hypovial-p"),
+ "black hypovial" = list("icon_state" = "hypovial-t"),
+ "pink hypovial" = list("icon_state" = "hypovial-pink")
+ )
always_reskinnable = TRUE
cached_icon = "hypovial"
@@ -50,14 +51,15 @@
icon_state = "hypoviallarge"
volume = 120
possible_transfer_amounts = list(1,2,5,10,20)
- unique_reskin = list("large hypovial" = "hypoviallarge",
- "large red hypovial" = "hypoviallarge-b",
- "large blue hypovial" = "hypoviallarge-d",
- "large green hypovial" = "hypoviallarge-a",
- "large orange hypovial" = "hypoviallarge-k",
- "large purple hypovial" = "hypoviallarge-p",
- "large black hypovial" = "hypoviallarge-t"
- )
+ unique_reskin = list(
+ "large hypovial" = list("icon_state" = "hypoviallarge"),
+ "large red hypovial" = list("icon_state" = "hypoviallarge-b"),
+ "large blue hypovial" = list("icon_state" = "hypoviallarge-d"),
+ "large green hypovial" = list("icon_state" = "hypoviallarge-a"),
+ "large orange hypovial" = list("icon_state" = "hypoviallarge-k"),
+ "large purple hypovial" = list("icon_state" = "hypoviallarge-p"),
+ "large black hypovial" = list("icon_state" = "hypoviallarge-t")
+ )
cached_icon = "hypoviallarge"
/obj/item/reagent_containers/glass/bottle/vial/large/bluespace
diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm
index a21b026080..b3ad29e637 100644
--- a/code/modules/recycling/conveyor2.dm
+++ b/code/modules/recycling/conveyor2.dm
@@ -308,13 +308,32 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
S.update_icon()
CHECK_TICK
-/obj/machinery/conveyor_switch/attackby(obj/item/I, mob/user, params)
- if(I.tool_behaviour == TOOL_CROWBAR)
- var/obj/item/conveyor_switch_construct/C = new/obj/item/conveyor_switch_construct(src.loc)
- C.id = id
- transfer_fingerprints_to(C)
- to_chat(user, "You detach the conveyor switch. ")
- qdel(src)
+/obj/machinery/conveyor_switch/crowbar_act(mob/user, obj/item/tool)
+ tool.play_tool_sound(src, 50)
+ var/obj/item/conveyor_switch_construct/switch_construct = new/obj/item/conveyor_switch_construct(src.loc)
+ switch_construct.id = id
+ transfer_fingerprints_to(switch_construct)
+ to_chat(user, span_notice("You detach [src]."))
+ qdel(src)
+ return TRUE
+
+/obj/machinery/conveyor_switch/screwdriver_act(mob/user, obj/item/tool)
+ tool.play_tool_sound(src, 50)
+ oneway = !oneway
+ to_chat(user, span_notice("You set [src] to [oneway ? "one way" : "default"] configuration."))
+ return TRUE
+
+/obj/machinery/conveyor_switch/wrench_act(mob/user, obj/item/tool)
+ tool.play_tool_sound(src, 50)
+ invert_icon = !invert_icon
+ update_appearance()
+ to_chat(user, span_notice("You set [src] to [invert_icon ? "inverted": "normal"] position."))
+ return TRUE
+
+/obj/machinery/conveyor_switch/examine(mob/user)
+ . = ..()
+ . += span_notice("[src] is set to [oneway ? "one way" : "default"] configuration. It can be changed with a screwdriver .")
+ . += span_notice("[src] is set to [invert_icon ? "inverted": "normal"] position. It can be rotated with a wrench .")
/obj/machinery/conveyor_switch/oneway
icon_state = "conveyor_switch_oneway"
diff --git a/code/modules/recycling/conveyor_sorter.dm b/code/modules/recycling/conveyor_sorter.dm
new file mode 100644
index 0000000000..0e42c79067
--- /dev/null
+++ b/code/modules/recycling/conveyor_sorter.dm
@@ -0,0 +1,144 @@
+// credits to jjpark-kb, see Skyrat-SS13/Skyrat-tg#8790 and related files
+// - hatterhat
+
+/obj/item/conveyor_sorter
+ name = "conveyor sorter lister"
+ desc = "A tool that is used to create conveyor sorting marks, and give sorting lists to them."
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "lister"
+ ///the list of conveyor sorters spawned by
+ var/list/spawned_sorters = list()
+ ///the list of things that are currently within the sorting list
+ var/list/current_sort = list()
+
+/obj/item/conveyor_sorter/Destroy()
+ for(var/deleting_sorters in spawned_sorters)
+ qdel(deleting_sorters)
+ return ..()
+
+/obj/item/conveyor_sorter/examine(mob/user)
+ . = ..()
+ . += span_notice("Use it to place down a conveyor sorter, up to three.")
+ . += span_notice("Use Alt-Click to reset the sorting list.")
+ . += span_notice("Attack things to attempt to add to the sorting list.")
+
+/obj/item/conveyor_sorter/attack_self(mob/user, modifiers)
+ if(length(spawned_sorters) >= 3)
+ to_chat(user, span_warning("You may only have three spawned conveyor sorters!"))
+ return
+ var/obj/effect/decal/cleanable/conveyor_sorter/new_cs = new /obj/effect/decal/cleanable/conveyor_sorter(get_turf(src))
+ new_cs.parent_item = src
+ spawned_sorters += new_cs
+
+/obj/item/conveyor_sorter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ if(target == src)
+ return ..()
+ if(!proximity_flag)
+ return ..()
+ if(!ismovable(target))
+ return ..()
+ if(istype(target, /obj/effect/decal/cleanable/conveyor_sorter))
+ return
+ if(is_type_in_list(target, current_sort))
+ to_chat(user, span_warning("[target] is already in [src]'s sorting list!"))
+ return
+ if(length(current_sort) >= 5)
+ to_chat(user, span_warning("[src] already has five things within the sorting list!"))
+ return
+ current_sort += target.type
+ to_chat(user, span_notice("[target] has been added to [src]'s sorting list."))
+
+/obj/item/conveyor_sorter/AltClick(mob/user)
+ visible_message("[src] pings, resetting its sorting list!")
+ playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
+ current_sort = list()
+
+/obj/effect/decal/cleanable/conveyor_sorter
+ name = "conveyor sorter"
+ desc = "A mark that sorts items out based on what they are."
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "sorter"
+ layer = OBJ_LAYER
+ plane = GAME_PLANE
+ ///the list of items that will be sorted to the sorted direction
+ var/list/sorting_list = list()
+ //the direction that the items in the sorting list will be moved to
+ dir = NORTH
+ ///the parent conveyor sorter lister item, used for deletion
+ var/obj/item/conveyor_sorter/parent_item
+ /// To prevent spam
+ COOLDOWN_DECLARE(use_cooldown)
+
+ light_range = 3
+ light_color = COLOR_RED_LIGHT
+
+/obj/effect/decal/cleanable/conveyor_sorter/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ var/static/list/loc_connections = list(
+ COMSIG_ATOM_ENTERED = .proc/on_entered,
+ )
+ AddElement(/datum/element/connect_loc, loc_connections)
+
+/obj/effect/decal/cleanable/conveyor_sorter/Destroy()
+ if(parent_item)
+ parent_item.spawned_sorters -= src
+ parent_item = null
+ return ..()
+
+/obj/effect/decal/cleanable/conveyor_sorter/examine(mob/user)
+ . = ..()
+ . += span_notice("Attack with conveyor sorter lister to set the sorting list.")
+ . += span_notice("Slap with empty hands to change the sorting direction.")
+ . += span_notice("Alt-Click to reset the sorting list.")
+ . += span_notice("Ctrl-Click to remove.")
+
+/obj/effect/decal/cleanable/conveyor_sorter/attack_hand(mob/living/user, list/modifiers)
+ var/user_choice = tgui_input_list(user, "Choose which direction to sort to!", "Direction choice", list("North", "East", "South", "West"))
+ if(!user_choice)
+ return ..()
+ switch(user_choice)
+ if("North")
+ setDir(NORTH)
+ if("East")
+ setDir(EAST)
+ if("South")
+ setDir(SOUTH)
+ if("West")
+ setDir(WEST)
+ visible_message("[src] pings, updating its sorting direction!")
+ playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
+
+/obj/effect/decal/cleanable/conveyor_sorter/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/conveyor_sorter))
+ var/obj/item/conveyor_sorter/cs_item = W
+ sorting_list = cs_item.current_sort
+ visible_message("[src] pings, updating its sorting list!")
+ playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
+ return
+ else
+ return ..()
+
+/obj/effect/decal/cleanable/conveyor_sorter/AltClick(mob/user)
+ visible_message("[src] pings, resetting its sorting list!")
+ playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
+ sorting_list = list()
+
+/obj/effect/decal/cleanable/conveyor_sorter/CtrlClick(mob/user)
+ visible_message("[src] pings, before disappearing!")
+ playsound(src, 'sound/machines/ping.ogg', 30, TRUE)
+ qdel(src)
+
+/obj/effect/decal/cleanable/conveyor_sorter/proc/on_entered(datum/source, atom/movable/AM)
+ if(is_type_in_list(AM, sorting_list) && !AM.anchored && COOLDOWN_FINISHED(src, use_cooldown))
+ COOLDOWN_START(src, use_cooldown, 1 SECONDS)
+ AM.Move(get_step(src, dir))
+
+/datum/design/conveyor_sorter
+ name = "Conveyor Sorter"
+ desc = "A wonderful item that can set markers and forcefully move stuff to a direction."
+ id = "conveyor_sorter"
+ build_type = PROTOLATHE
+ build_path = /obj/item/conveyor_sorter
+ materials = list(/datum/material/iron = 500, /datum/material/plastic = 500)
+ category = list("Equipment")
+ departmental_flags = DEPARTMENTAL_FLAG_CARGO
diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm
index 2fbea18ac2..6c85bfc3ee 100644
--- a/code/modules/recycling/disposal/pipe.dm
+++ b/code/modules/recycling/disposal/pipe.dm
@@ -54,7 +54,7 @@
if(H)
H.active = FALSE
expel(H, get_turf(src), 0)
- QDEL_NULL(stored)
+ stored = null //The qdel is handled in expel()
return ..()
// returns the direction of the next pipe object, given the entrance dir
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index 630a3629cf..6f6a1fd88e 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -12,16 +12,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
-/datum/design/health_hud_prescription
- name = "Prescription Health Scanner HUD"
- desc = "A heads-up display that scans the humans in view and provides accurate data about their health status. This one has a prescription lens."
- id = "health_hud_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 350)
- build_path = /obj/item/clothing/glasses/hud/health/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
-
/datum/design/health_hud_night
name = "Night Vision Health Scanner HUD"
desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness."
@@ -42,16 +32,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
-/datum/design/security_hud_prescription
- name = "Prescription Security HUD"
- desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status. This one has a prescription lens."
- id = "security_hud_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 350)
- build_path = /obj/item/clothing/glasses/hud/security/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
-
/datum/design/security_hud_night
name = "Night Vision Security HUD"
desc = "A heads-up display which provides id data and vision in complete darkness."
@@ -72,16 +52,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-/datum/design/diagnostic_hud_prescription
- name = "Prescription Diagnostic HUD"
- desc = "A HUD used to analyze and determine faults within robotic machinery. This one has a prescription lens."
- id = "diagnostic_hud_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/gold = 350)
- build_path = /obj/item/clothing/glasses/hud/diagnostic/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-
/datum/design/diagnostic_hud_night
name = "Night Vision Diagnostic HUD"
desc = "Upgraded version of the diagnostic HUD designed to function during a power failure."
@@ -112,16 +82,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_CARGO | DEPARTMENTAL_FLAG_ENGINEERING
-/datum/design/mesons_prescription
- name = "Prescription Optical Meson Scanners"
- desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition. Prescription lens has been added into this design."
- id = "mesons_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 350)
- build_path = /obj/item/clothing/glasses/meson/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_CARGO | DEPARTMENTAL_FLAG_ENGINEERING
-
/datum/design/engine_goggles
name = "Engineering Scanner Goggles"
desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, regardless of lighting condition. The T-ray Scanner mode lets you see underfloor objects such as cables and pipes."
@@ -132,16 +92,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
-/datum/design/engine_goggles_prescription
- name = "Prescription Engineering Scanner Goggles"
- desc = "Goggles used by engineers. The Meson Scanner mode lets you see basic structural and terrain layouts through walls, regardless of lighting condition. The T-ray Scanner mode lets you see underfloor objects such as cables and pipes. Prescription lens has been added into this design."
- id = "engine_goggles_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/plasma = 100, /datum/material/silver = 350)
- build_path = /obj/item/clothing/glasses/meson/engine/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
-
/datum/design/tray_goggles
name = "Optical T-Ray Scanners"
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
@@ -152,16 +102,6 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
-/datum/design/tray_goggles_prescription
- name = "Prescription Optical T-Ray Scanners"
- desc = "Used by engineering staff to see underfloor objects such as cables and pipes. Prescription lens has been added into this design."
- id = "tray_goggles_prescription"
- build_type = PROTOLATHE
- materials = list(/datum/material/iron = 500, /datum/material/glass = 500, /datum/material/silver = 150)
- build_path = /obj/item/clothing/glasses/meson/engine/tray/prescription
- category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
-
/datum/design/nvgmesons
name = "Night Vision Optical Meson Scanners"
desc = "Prototype meson scanners fitted with an extra sensor which amplifies the visible light spectrum and overlays it to the UHD display."
@@ -175,22 +115,22 @@
/datum/design/night_vision_goggles
name = "Night Vision Goggles"
desc = "Goggles that let you see through darkness unhindered."
- id = "night_visision_goggles"
+ id = "night_vision_goggles"
build_type = PROTOLATHE
materials = list(/datum/material/iron = 600, /datum/material/glass = 600, /datum/material/plasma = 350, /datum/material/uranium = 1000)
build_path = /obj/item/clothing/glasses/night
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_SECURITY
-/datum/design/night_vision_goggles_glasses
- name = "Prescription Night Vision Goggles"
- desc = "Goggles that let you see through darkness unhindered. Corrects vision."
- id = "night_visision_goggles_glasses"
+/datum/design/prescription_kit
+ name = "Prescription Lens Kit"
+ desc = "A do-it-yourself kit that lets you add a prescription overlay to any HUDs or other eyewear. Even the ones that shouldn't."
+ id = "prescription_kit"
build_type = PROTOLATHE
- materials = list(/datum/material/iron = 600, /datum/material/glass = 600, /datum/material/plasma = 350, /datum/material/uranium = 1000)
- build_path = /obj/item/clothing/glasses/night/prescription
+ materials = list(/datum/material/iron = 500, /datum/material/glass = 200, /datum/material/silver = 100) // silver because i guess all the prescription HUDs had it?
+ build_path = /obj/item/prescription_kit
category = list("Equipment")
- departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_ENGINEERING
+ departmental_flags = DEPARTMENTAL_FLAG_ALL
/////////////////////////////////////////
//////////////////Misc///////////////////
@@ -407,6 +347,16 @@
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_ENGINEERING
+/datum/design/light_replacer_blue
+ name = "Bluespace Light Replacer"
+ desc = "A device to automatically replace lights at a distance. Refill with working light bulbs."
+ id = "light_replacer_blue"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 1500, /datum/material/silver = 150, /datum/material/glass = 3000, /datum/material/bluespace = 300)
+ build_path = /obj/item/lightreplacer/blue
+ category = list("Equipment")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_ENGINEERING
+
/datum/design/normtrash
name = "Trashbag"
desc = "It's a bag for trash, you put garbage in it."
diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm
index 92eaa2bd41..8ea4b95d03 100644
--- a/code/modules/research/techweb/_techweb_node.dm
+++ b/code/modules/research/techweb/_techweb_node.dm
@@ -106,4 +106,4 @@
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand",
"space_heater", "beaker", "large_beaker", "xlarge_beaker", "bucket", "hypovial", "large_hypovial", "syringe", "pillbottle",
"sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
- "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass", "salestagger")
+ "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass", "salestagger", "light_replacer")
diff --git a/code/modules/research/techweb/nodes/biotech_nodes.dm b/code/modules/research/techweb/nodes/biotech_nodes.dm
index 350bbaa5c3..1a3aa2644e 100644
--- a/code/modules/research/techweb/nodes/biotech_nodes.dm
+++ b/code/modules/research/techweb/nodes/biotech_nodes.dm
@@ -13,7 +13,7 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
- design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter", "hypospray_mkii", "containmentbodybag")
+ design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter", "hypospray_mkii", "containmentbodybag", "prescription_kit")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
/datum/techweb_node/bio_process
diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm
index fdbbab4e70..21e002b359 100644
--- a/code/modules/research/techweb/nodes/bluespace_nodes.dm
+++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm
@@ -13,7 +13,7 @@
display_name = "Applied Bluespace Research"
description = "Using bluespace to make things faster and better."
prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray")
+ design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "light_replacer_blue")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/adv_bluespace
diff --git a/code/modules/research/techweb/nodes/computer_hud_nodes.dm b/code/modules/research/techweb/nodes/computer_hud_nodes.dm
index 0f2cf2e4bd..780c146fee 100644
--- a/code/modules/research/techweb/nodes/computer_hud_nodes.dm
+++ b/code/modules/research/techweb/nodes/computer_hud_nodes.dm
@@ -40,7 +40,7 @@
display_name = "Integrated HUDs"
description = "The usefulness of computerized records, projected straight onto your eyepiece!"
prereq_ids = list("comp_recordkeeping", "emp_basic")
- design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles", "health_hud_prescription", "security_hud_prescription", "diagnostic_hud_prescription")
+ design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500)
/datum/techweb_node/NVGtech
@@ -48,7 +48,7 @@
display_name = "Night Vision Technology"
description = "Allows seeing in the dark without actual light!"
prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv")
- design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons", "night_visision_goggles_glasses")
+ design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_vision_goggles", "nvgmesons")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
/datum/techweb_node/computer_board_gaming
diff --git a/code/modules/research/techweb/nodes/engineering_nodes.dm b/code/modules/research/techweb/nodes/engineering_nodes.dm
index 2b5d6f3cc1..51b9480c27 100644
--- a/code/modules/research/techweb/nodes/engineering_nodes.dm
+++ b/code/modules/research/techweb/nodes/engineering_nodes.dm
@@ -7,8 +7,8 @@
prereq_ids = list("base")
design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin",
"atmosalerts", "atmos_control", "recycler", "autolathe", "autolathe_secure", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod",
- "apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo","oxygen_tank",
- "plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt", "colormate")
+ "apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo", "oxygen_tank",
+ "plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt", "colormate", "conveyor_sorter")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000)
/datum/techweb_node/adv_engi
@@ -17,8 +17,7 @@
description = "Pushing the boundaries of physics, one chainsaw-fist at a time."
prereq_ids = list("engineering", "emp_basic")
design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask" , "rcd_loaded", "rpd",
- "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames",
- "rcd_upgrade_simple_circuits", "rcd_ammo_large", "sheetifier")
+ "rcd_upgrade_frames", "rcd_upgrade_simple_circuits", "rcd_ammo_large", "sheetifier")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000)
/datum/techweb_node/anomaly
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index b740cca114..4be592b919 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -35,6 +35,7 @@
GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for the badmin verb for now
/obj/effect/proc_holder/Destroy()
+ QDEL_NULL(action)
if(ranged_ability_user)
remove_ranged_ability()
return ..()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 2d8150d087..c4ab435ee0 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -9,7 +9,7 @@
icon_state = ""
layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor
var/mob/living/carbon/owner = null
- var/mob/living/carbon/original_owner = null
+ var/datum/weakref/original_owner = null
var/status = BODYPART_ORGANIC
var/needs_processing = FALSE
@@ -639,8 +639,8 @@
if(source)
C = source
if(!original_owner)
- original_owner = source
- else if(original_owner && owner != original_owner) //Foreign limb
+ original_owner = WEAKREF(source)
+ else if(original_owner && !IS_WEAKREF_OF(owner, original_owner)) //Foreign limb
no_update = TRUE
else
C = owner
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 6b5b4a14aa..96b9290239 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -142,7 +142,7 @@
update_icon_dropped()
C.update_health_hud() //update the healthdoll
- C.update_body()
+ C.update_body(FALSE, TRUE) // block recursive calls because we dont want to crash, i.e. don't tell a dullahan to update when dropping its limb
C.update_hair()
C.update_mobility()
@@ -370,7 +370,7 @@
update_disabled()
C.updatehealth()
- C.update_body()
+ C.update_body(FALSE, TRUE) // again block recursive calls because dullahans will try update their icons by regenerating their head
C.update_hair()
C.update_damage_overlays()
C.update_mobility()
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index 8c283f5ebc..ea43740093 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -134,7 +134,7 @@
I.pixel_y = px_y
add_overlay(standing)
-/obj/item/bodypart/head/get_limb_icon(dropped)
+/obj/item/bodypart/head/get_limb_icon(dropped, ignore_brain = FALSE)
if(custom_head)
return
cut_overlays()
@@ -152,7 +152,7 @@
. += facial_overlay
//Applies the debrained overlay if there is no brain
- if(!brain)
+ if(!brain && !ignore_brain)
var/image/debrain_overlay = image(layer = -HAIR_LAYER, dir = SOUTH)
if(animal_origin == ALIEN_BODYPART)
debrain_overlay.icon = 'icons/mob/animal_parts.dmi'
@@ -175,12 +175,13 @@
// lipstick
if(lip_style)
- var/image/lips_overlay = image('icons/mob/lips.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
+ var/mutable_appearance/lips_overlay = mutable_appearance('icons/mob/lips.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
+ lips_overlay.category = "HEAD"
lips_overlay.color = lip_color
. += lips_overlay
// eyes
- if(eyes)
+ if(eyes || ignore_brain)
var/left_state = DEFAULT_LEFT_EYE_STATE
var/right_state = DEFAULT_RIGHT_EYE_STATE
if(owner && owner.dna.species)
@@ -189,12 +190,14 @@
left_state = eye_type + "_left_eye"
right_state = eye_type + "_right_eye"
if(left_state != DEFAULT_NO_EYE_STATE)
- var/image/left_eye = image('icons/mob/hair.dmi', left_state, -BODY_LAYER, SOUTH)
+ var/mutable_appearance/left_eye = mutable_appearance('icons/mob/hair.dmi', left_state, -BODY_LAYER, SOUTH)
+ left_eye.category = "HEAD"
if(eyes.left_eye_color)
left_eye.color = "#" + eyes.left_eye_color
. += left_eye
if(right_state != DEFAULT_NO_EYE_STATE)
- var/image/right_eye = image('icons/mob/hair.dmi', right_state, -BODY_LAYER, SOUTH)
+ var/mutable_appearance/right_eye = mutable_appearance('icons/mob/hair.dmi', right_state, -BODY_LAYER, SOUTH)
+ right_eye.category = "HEAD"
if(eyes.right_eye_color)
right_eye.color = "#" + eyes.right_eye_color
. += right_eye
diff --git a/code/modules/vehicles/cars/car.dm b/code/modules/vehicles/cars/car.dm
index 81b2db6cf8..e024718f4c 100644
--- a/code/modules/vehicles/cars/car.dm
+++ b/code/modules/vehicles/cars/car.dm
@@ -2,6 +2,7 @@
layer = ABOVE_MOB_LAYER
anchored = TRUE
default_driver_move = FALSE
+ var/explode_on_death = TRUE
var/car_traits = NONE //Bitflag for special behavior such as kidnapping
var/engine_sound = 'sound/vehicles/carrev.ogg'
var/last_enginesound_time
@@ -12,6 +13,11 @@
. = ..()
LoadComponent(/datum/component/riding)
+/obj/vehicle/sealed/car/Destroy()
+ . = ..()
+ if(explode_on_death)
+ explosion(loc, 0, 1, 2, 3, 0)
+
/obj/vehicle/sealed/car/generate_actions()
. = ..()
initialize_controller_action_type(/datum/action/vehicle/sealed/remove_key, VEHICLE_CONTROL_DRIVE)
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index f1e4d4468b..de5628dc05 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -167,6 +167,7 @@
hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD)
/obj/item/radio/mech //this has to go somewhere
+ subspace_transmission = TRUE
/obj/vehicle/sealed/mecha/Initialize(mapload)
. = ..()
@@ -196,41 +197,40 @@
update_icon()
/obj/vehicle/sealed/mecha/Destroy()
- if(obj_integrity > 0) //no explody if we have hp remaining!
- explode_on_death = FALSE
- for(var/M in occupants)
- var/mob/living/occupant = M
- if(isAI(occupant))
- occupant.gib() //No wreck, no AI to recover
- else
- occupant.forceMove(loc)
- occupant.SetSleeping(destruction_sleep_duration)
+ for(var/ejectee in occupants)
+ mob_exit(ejectee, TRUE, TRUE)
if(LAZYLEN(equipment))
- for(var/E in equipment)
- var/obj/item/mecha_parts/mecha_equipment/equip = E
+ for(var/obj/item/mecha_parts/mecha_equipment/equip as anything in equipment)
equip.detach(loc)
qdel(equip)
- if(cell)
- QDEL_NULL(cell)
- if(scanmod)
- QDEL_NULL(scanmod)
- if(capacitor)
- QDEL_NULL(capacitor)
- if(internal_tank)
- QDEL_NULL(internal_tank)
+ radio = null
+
STOP_PROCESSING(SSobj, src)
- GLOB.poi_list.Remove(src)
LAZYCLEARLIST(equipment)
- if(loc)
- loc.assume_air(cabin_air)
- air_update_turf()
- else
- qdel(cabin_air)
- cabin_air = null
+
+ QDEL_NULL(cell)
+ QDEL_NULL(scanmod)
+ QDEL_NULL(capacitor)
+ QDEL_NULL(internal_tank)
+ QDEL_NULL(cabin_air)
QDEL_NULL(spark_system)
QDEL_NULL(smoke_system)
+ GLOB.poi_list -= src
GLOB.mechas_list -= src //global mech list
+ for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
+ diag_hud.remove_from_hud(src) //YEET
+ return ..()
+
+/obj/vehicle/sealed/mecha/obj_destruction()
+ loc.assume_air(cabin_air)
+ air_update_turf(FALSE, FALSE)
+ for(var/mob/living/occupant as anything in occupants)
+ if(isAI(occupant))
+ occupant.gib() //No wreck, no AI to recover
+ continue
+ mob_exit(occupant, FALSE, TRUE)
+ occupant.SetSleeping(destruction_sleep_duration)
return ..()
/obj/vehicle/sealed/mecha/update_icon()
diff --git a/code/modules/vehicles/sealed.dm b/code/modules/vehicles/sealed.dm
index 1a1858522a..7bb4e878ec 100644
--- a/code/modules/vehicles/sealed.dm
+++ b/code/modules/vehicles/sealed.dm
@@ -1,7 +1,6 @@
/obj/vehicle/sealed
enclosed = TRUE // you're in a sealed vehicle dont get dinked idiot
var/enter_delay = 20
- var/explode_on_death = TRUE
flags_1 = BLOCK_FACE_ATOM_1
/obj/vehicle/sealed/generate_actions()
@@ -90,8 +89,6 @@
/obj/vehicle/sealed/Destroy()
DumpMobs()
- if(explode_on_death)
- explosion(loc, 0, 1, 2, 3, 0)
return ..()
/obj/vehicle/sealed/proc/DumpMobs(randomstep = TRUE)
diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm
index 69ab758f91..f6d76b253f 100644
--- a/code/modules/vending/clothesmate.dm
+++ b/code/modules/vending/clothesmate.dm
@@ -11,6 +11,7 @@
/obj/item/clothing/head/beret/black = 3,
/obj/item/clothing/head/beret/purple = 3,
/obj/item/clothing/head/beret/blue = 3,
+ /obj/item/clothing/accessory/pride = 25,
/obj/item/clothing/glasses/monocle = 3,
/obj/item/clothing/suit/jacket = 4,
/obj/item/clothing/suit/jacket/flannel = 4,
diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm
index 29314c3e31..52fbd7dac4 100644
--- a/code/modules/vending/security.dm
+++ b/code/modules/vending/security.dm
@@ -19,9 +19,9 @@
/obj/item/storage/fancy/donut_box = 2,
/obj/item/storage/belt/sabre/secbelt = 1)
premium = list(/obj/item/coin/antagtoken = 1,
- /obj/item/clothing/head/helmet/blueshirt = 5, //SPLURT edit, origional was 1
- /obj/item/clothing/suit/armor/vest/blueshirt = 5, //SPLURT edit, origional was 1
- /obj/item/clothing/under/rank/security/officer/blueshirt = 5, //SPLURT edit, origional was 1
+ /obj/item/clothing/head/helmet/blueshirt = 1,
+ /obj/item/clothing/suit/armor/vest/blueshirt = 1,
+ /obj/item/clothing/under/rank/security/officer/blueshirt = 1,
/obj/item/clothing/gloves/tackler = 5,
/obj/item/grenade/stingbang = 1,
/obj/item/ssword_kit = 1,
diff --git a/html/changelogs/archive/2022-12.yml b/html/changelogs/archive/2022-12.yml
index 39c933c911..4efa7f1d12 100644
--- a/html/changelogs/archive/2022-12.yml
+++ b/html/changelogs/archive/2022-12.yml
@@ -34,3 +34,66 @@
LeDrascol:
- rscadd: 'Added new job titles for Peacekeeper: Bodyguard, Hired Muscle'
- rscadd: 'Added new quirk: Nudist'
+2022-12-11:
+ CheBuRek017:
+ - rscadd: New Assistant alt title
+2022-12-13:
+ BongaTheProto:
+ - tweak: Christmas clothing will appear in the clothesmate when it's Christmas
+ JerryWester:
+ - rscadd: Added garters to the loadout
+ LeDrascol:
+ - rscadd: 'Added metacarpus emotes: Facehand, facepaw, faceclaw, and facehoof'
+ - tweak: Empath and Friendly crew can now detect Distant and Headpat Slut crew
+ - tweak: Increased max age from 85 to 16,777,216
+ Mazen421:
+ - rscadd: Two extra pipe lines in the center of Taustation
+2022-12-14:
+ SandPoot:
+ - tweak: Interaction's tabs are now centered and fluid, getting a better look overrall.
+2022-12-16:
+ LeDrascol:
+ - rscadd: 'Added new Scientist title: Rack Researcher'
+ - tweak: Invisifiber Footwraps can be purchased from the Kinkmate vendor
+2022-12-17:
+ JerryWester:
+ - rscadd: Added the "Hungry and Thirsty" negative quirk, grants one point and doubles
+ the hunger/thirst modifier
+2022-12-21:
+ LunarFleet:
+ - soundadd: added a LOT of new barks
+2022-12-22:
+ LeDrascol:
+ - refactor: Modularized cursed blood effects
+2022-12-24:
+ Chlorotrifluoride:
+ - imageadd: added hop_parade_female to uniform_digi.dmi
+ - code_imp: enabled the new and already existing sprites to work with digi-legs
+ JerryWester:
+ - code_imp: Tunnel Foxes rule!
+ - code_imp: We're the Tunnel Foxes!
+ - code_imp: That's us...
+ - code_imp: And we rule!
+ - rscdel: Removed open Tunnel Fox jacket
+ - tweak: Tunnel Fox jacket is now toggleable
+ - bugfix: Tunnel Fox jacket and HoP parade jacket now show up on digitigrade sprites
+2022-12-25:
+ FromRussiaWithLove:
+ - bugfix: 'fixing missing stamps : centcom, syndicate, chapel and mime.'
+ - imageadd: 'added some icons for missing stamps : centcom, syndicate, chapel and
+ mime.'
+ SpookyTheFox:
+ - tweak: changed the anything gift list to the santa gift list
+2022-12-28:
+ LeDrascol:
+ - tweak: Dice of Fate is now usable once per-person
+ LunarFleet:
+ - rscadd: Added a new quirk, and a new statue type for said quirk
+2022-12-30:
+ BongaTheProto:
+ - tweak: makes the sand megafauna mob into mayhem lmao
+ - rscadd: adds a new drink, Skullfucker deluxe
+2022-12-31:
+ zeroisthebiggay:
+ - spellcheck: horny ai laws
+ - spellcheck: horny ai law priority
diff --git a/html/changelogs/archive/2023-01.yml b/html/changelogs/archive/2023-01.yml
new file mode 100644
index 0000000000..abb029a408
--- /dev/null
+++ b/html/changelogs/archive/2023-01.yml
@@ -0,0 +1,80 @@
+2023-01-01:
+ FromRussiaWithLove:
+ - rscadd: Displaying Game Mode in status panel
+2023-01-02:
+ zeroisthebiggay:
+ - imageadd: shading for ass sprites
+2023-01-03:
+ FelixRuin:
+ - bugfix: fixed inert egg was always has chicken egg sprite regardless of the pref
+ choice.
+ KeplerWasTaken:
+ - bugfix: Kilo Cargo Shuttle now has tiny fans!
+ - bugfix: Mining Points Vending Machine can no longer be exploited for infinite
+ points via transfer cards
+ - bugfix: Double doors at sec entrance in box station now have proper access requirements,
+ enjoy!
+ - rscadd: Improves Moth in Command to be an improved version of Commander and Chief
+ SpookyTheFox:
+ - tweak: moved blueshift themed sec gear out of premium pricing.
+2023-01-08:
+ LeDrascol:
+ - bugfix: Fixed techweb sequence break for Advanced Toolset Implant
+ - tweak: Cryptominer no longer functions in space
+ - tweak: Cryptominer no longer produces Co2
+ - code_imp: Refactored processing for cryptominer
+2023-01-09:
+ LeDrascol:
+ - tweak: Fluid Infuser implant uses an improved activation button
+ - rscadd: Added the Storage Concealment Implant
+ SandPoot:
+ - rscadd: Added a fancy reskin for the mining hardsuit, modify it using Alt-Click!
+ - imageadd: Special sprites made by Dexxiol#3462!
+2023-01-10:
+ BongaTheProto:
+ - rscadd: New sloog sprites for character creation and backpack
+ - rscadd: New type of eyes, none
+ - bugfix: Fixes misclassing of sec badge
+ LeDrascol:
+ - tweak: Liquid Panty Dropper now launches clothing
+ - tweak: Liquid Panty Dropper no longer interferes with held items
+ - code_imp: LPD's clothing burst is now a mob proc
+ - bugfix: Fixed the late-join panel showing job slots twice
+2023-01-11:
+ BongaTheProto:
+ - bugfix: Fixes gun reskins broken by the new reskin system
+ Seris02:
+ - bugfix: fixed gargoyles having sprites that are odd, along with sanity checks
+ and making the transition between living and statue seamless
+2023-01-12:
+ LeDrascol:
+ - refactor: Moved quirk action datums to a new file
+ - rscadd: Added a Plushmium Crate to cargo
+2023-01-13:
+ Guatolipo:
+ - rscadd: Added CART_CHEMISTRY access to cart-cmo
+ LeDrascol:
+ - tweak: Replaced three dangerous holodeck modes with harmless alternatives
+2023-01-14:
+ LeDrascol:
+ - bugfix: Fixed spelling mistakes in the interaction system
+ - rscadd: Added the Love to Life spray bottle
+ - tweak: Updated Plushmium Crate contents
+ - rscadd: 'Added implant: Rapid Disrobe'
+ - tweak: Nudists now start with a Rapid Disrobe implant
+ - rscadd: Added the Wallet of Holding
+2023-01-15:
+ BongaTheProto:
+ - rscadd: Adds nobl donator plushie
+ - rscadd: Adds a *poyo emote
+ Casper:
+ - bugfix: fixes telekinetic users from teleporting to stripper poles
+ - bugfix: infinite metal exploit
+ SandPoot:
+ - spellcheck: fixed a few typos.
+ - refactor: refactored skirt peeking.
+ - tweak: examine someone twice to actually peek their panties.
+2023-01-16:
+ SandPoot:
+ - rscadd: You can now allow interacting with your genitals through clothes.
+ - tweak: Modified sandstorm's spans (`"...`) with the defines (`span_x("...`)
diff --git a/icons/effects/96x32.dmi b/icons/effects/96x32.dmi
index 937b2e8d42..a78d11530b 100644
Binary files a/icons/effects/96x32.dmi and b/icons/effects/96x32.dmi differ
diff --git a/icons/mob/clothing/accessories.dmi b/icons/mob/clothing/accessories.dmi
index f801c483f1..5c212f3f45 100644
Binary files a/icons/mob/clothing/accessories.dmi and b/icons/mob/clothing/accessories.dmi differ
diff --git a/icons/mob/clothing/eyes.dmi b/icons/mob/clothing/eyes.dmi
index 49702bf920..1525ba9a93 100644
Binary files a/icons/mob/clothing/eyes.dmi and b/icons/mob/clothing/eyes.dmi differ
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 4bc2136cd1..c8f0b8f634 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/mob/inhands/equipment/custodial_righthand.dmi b/icons/mob/inhands/equipment/custodial_righthand.dmi
index 26d8e61163..c986155b10 100644
Binary files a/icons/mob/inhands/equipment/custodial_righthand.dmi and b/icons/mob/inhands/equipment/custodial_righthand.dmi differ
diff --git a/icons/obj/abductor.dmi b/icons/obj/abductor.dmi
index 75f84347b6..83d71c1093 100644
Binary files a/icons/obj/abductor.dmi and b/icons/obj/abductor.dmi differ
diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi
index 7b00c155ef..c59f00e383 100644
Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ
diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi
index f633f030c3..b92d65092e 100644
Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index 1752892b60..c98c984c7d 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index a1bb406b9f..5ddd73d934 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/genitals/butt_onmob.dmi b/icons/obj/genitals/butt_onmob.dmi
index 95a75fa745..f71417d30e 100644
Binary files a/icons/obj/genitals/butt_onmob.dmi and b/icons/obj/genitals/butt_onmob.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 50975dc828..74ec511768 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/recycling.dmi b/icons/obj/recycling.dmi
index 9604d6b97e..621b9e4241 100644
Binary files a/icons/obj/recycling.dmi and b/icons/obj/recycling.dmi differ
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index 931324bf8f..4c09236872 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -330,7 +330,7 @@
name = "Lucky Jackboots"
slot = ITEM_SLOT_BACKPACK
path = /obj/item/clothing/shoes/lucky
- ckeywhitelist = list("donaldtrumpthecommunist")
+ ckeywhitelist = list("spiralwithin")
/datum/gear/donator/raiqbawks
name = "Miami Boombox"
diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm
index 0573a1a22a..5879426041 100644
--- a/modular_citadel/code/modules/client/loadout/backpack.dm
+++ b/modular_citadel/code/modules/client/loadout/backpack.dm
@@ -172,12 +172,21 @@
path = /obj/item/storage/fancy/ringbox/diamond
cost = 5
-/datum/gear/backpack/necklace//this is here because loadout doesn't support proper accessories
+/datum/gear/backpack/necklace //this is here because loadout doesn't support proper accessories
name = "A renameable necklace"
path = /obj/item/clothing/accessory/necklace
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES
/datum/gear/backpack/polymaidapron //this is ALSO here because loadout doesn't support proper accessories
name = "Polychromic maid apron"
path = /obj/item/clothing/accessory/maidapron/polychromic
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#333333", "#FFFFFF")
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES
+
+/datum/gear/backpack/pridepin //what the two comments above said
+ name = "Pride pin"
+ path = /obj/item/clothing/accessory/pride
+ loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION
+ subcategory = LOADOUT_SUBCATEGORY_BACKPACK_ACCESSORIES
+ cost = 0
diff --git a/modular_citadel/code/modules/client/loadout/glasses.dm b/modular_citadel/code/modules/client/loadout/glasses.dm
index fe44abc3de..0ca9aa0e05 100644
--- a/modular_citadel/code/modules/client/loadout/glasses.dm
+++ b/modular_citadel/code/modules/client/loadout/glasses.dm
@@ -45,3 +45,7 @@
/datum/gear/glasses/prescription
name = "Prescription glasses"
path = /obj/item/clothing/glasses/regular
+
+/datum/gear/glasses/modern
+ name = "Modern prescription glasses"
+ path = /obj/item/clothing/glasses/regular/modern
diff --git a/modular_citadel/code/modules/client/loadout/suit.dm b/modular_citadel/code/modules/client/loadout/suit.dm
index 1d4a29ef3e..2685812232 100644
--- a/modular_citadel/code/modules/client/loadout/suit.dm
+++ b/modular_citadel/code/modules/client/loadout/suit.dm
@@ -18,7 +18,6 @@
/datum/gear/suit/redhood
name = "Red cloak"
path = /obj/item/clothing/suit/hooded/cloak/david
- cost = 3
/datum/gear/suit/jacketbomber
name = "Bomber jacket"
@@ -160,14 +159,14 @@
/datum/gear/suit/coat/polycoat
name = "Polychromic winter coat"
path = /obj/item/clothing/suit/hooded/wintercoat/polychromic
- cost = 4 //too many people with neon green coats is hard on the eyes
+ cost = 2 //too many people with neon green coats is hard on the eyes // it's probably fine now
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#6A6964", "#C4B8A6", "#0000FF")
/datum/gear/suit/coat/wbreakpoly
name = "Polychromic windbreaker"
path = /obj/item/clothing/suit/toggle/wbreakpoly/polychromic
- cost = 4
+ cost = 2
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#464F65", "#916035", "#474747")
diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm
index 2a75f86ffc..5c22485c1f 100644
--- a/modular_citadel/code/modules/client/loadout/uniform.dm
+++ b/modular_citadel/code/modules/client/loadout/uniform.dm
@@ -280,36 +280,34 @@
/datum/gear/uniform/suit/poly
name = "Polychromic Button-up Shirt"
path = /obj/item/clothing/under/misc/poly_shirt
- cost = 3
+ cost = 2
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#FFFFFF", "#353535", "#353535")
/datum/gear/uniform/skirt/poly/pleated
name = "Polychromic Pleated Sweaterskirt"
path = /obj/item/clothing/under/dress/skirt/polychromic/pleated
- cost = 3
+ cost = 2
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#8CC6FF", "#808080", "#FF3535")
/datum/gear/uniform/polykilt
name = "Polychromic Kilt"
path = /obj/item/clothing/under/costume/kilt/polychromic
- cost = 3
+ cost = 2
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#FFFFFF", "#F08080")
/datum/gear/uniform/shorts/poly
name = "Polychromic Shorts"
path = /obj/item/clothing/under/misc/polyshorts
- cost = 3
+ cost = 2
loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#353535", "#808080", "#808080")
/datum/gear/uniform/shorts/poly/athletic
name = "Polychromic Athletic Shorts"
path = /obj/item/clothing/under/shorts/polychromic
- cost = 2
- loadout_flags = LOADOUT_CAN_NAME | LOADOUT_CAN_DESCRIPTION | LOADOUT_CAN_COLOR_POLYCHROMIC
loadout_initial_colors = list("#FFFFFF", "#F08080")
/datum/gear/uniform/hopcasual
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 500db4453f..ec97d0659f 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -550,7 +550,10 @@
item_state = "fritz"
attack_verb = list("barked", "boofed", "shotgun'd")
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad")
+ unique_reskin = list(
+ "Goodboye" = list("icon_state" = "fritz"),
+ "Badboye" = list("icon_state" = "fritz_bad")
+ )
mutantrace_variation = NONE
/obj/item/clothing/neck/cloak/polychromic/polyce
diff --git a/modular_sand/code/controllers/subsystem/language.dm b/modular_sand/code/controllers/subsystem/language.dm
index faa3fa3e1d..c0abd0b720 100644
--- a/modular_sand/code/controllers/subsystem/language.dm
+++ b/modular_sand/code/controllers/subsystem/language.dm
@@ -24,7 +24,7 @@
continue
if(valid_languages.len)
var/list/sorted_valid = sortList(valid_languages)
- to_chat(user, "You are able to speak in [sorted_valid.Join(", ")]. If you're actually good at [valid_languages.len > 1 ? "them" : "it"] or not, it's up to you. ")
+ to_chat(user, span_notice("You are able to speak in [sorted_valid.Join(", ")]. If you're actually good at [valid_languages.len > 1 ? "them" : "it"] or not, it's up to you."))
if(invalid_languages.len)
var/list/sorted_invalid = sortList(invalid_languages)
- to_chat(user, "[sorted_invalid.Join(", ")] [invalid_languages.len > 1 ? "are" : "is a"] restricted language[invalid_languages.len > 1 ? "s" : ""], and ha[invalid_languages.len > 1 ? "ve" : "s"] not been assigned. ")
+ to_chat(user, span_warning("[sorted_invalid.Join(", ")] [invalid_languages.len > 1 ? "are" : "is a"] restricted language[invalid_languages.len > 1 ? "s" : ""], and ha[invalid_languages.len > 1 ? "ve" : "s"] not been assigned."))
diff --git a/modular_sand/code/datums/components/container_item/tank_holder.dm b/modular_sand/code/datums/components/container_item/tank_holder.dm
index b68c413519..765335987c 100644
--- a/modular_sand/code/datums/components/container_item/tank_holder.dm
+++ b/modular_sand/code/datums/components/container_item/tank_holder.dm
@@ -17,12 +17,12 @@
var/obj/item/I = parent
if(container.contents.len)
if(user)
- to_chat(user, "There's already something in [container]. ")
+ to_chat(user, span_warning("There's already something in [container]."))
return TRUE
if(user)
if(!user.transferItemToLoc(I, container))
return TRUE
- to_chat(user, "You put [I] into [container]. ")
+ to_chat(user, span_notice("You put [I] into [container]."))
else
I.forceMove(container)
container.tank = I
diff --git a/modular_sand/code/datums/elements/holder_micro.dm b/modular_sand/code/datums/elements/holder_micro.dm
index d4d3b34d84..f264ded3b5 100644
--- a/modular_sand/code/datums/elements/holder_micro.dm
+++ b/modular_sand/code/datums/elements/holder_micro.dm
@@ -26,7 +26,7 @@
/datum/element/mob_holder/micro/on_examine(mob/living/source, mob/user, list/examine_list)
if(ishuman(user) && !istype(source.loc, /obj/item/clothing/head/mob_holder) && (abs(get_size(source)/get_size(user)) <= CONFIG_GET(number/max_pick_ratio)))
- examine_list += "Looks like [source.p_they(FALSE)] can be picked up using Alt+Click and grab intent ! "
+ examine_list += span_notice("Looks like [source.p_they(FALSE)] can be picked up using Alt+Click and grab intent !")
/datum/element/mob_holder/micro/proc/mob_pickup_micro(mob/living/source, mob/user)
var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
@@ -50,41 +50,41 @@
if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated())
return FALSE
if(source == user)
- to_chat(user, "You can't pick yourself up. ")
+ to_chat(user, span_warning("You can't pick yourself up."))
source.balloon_alert(user, "cannot pick yourself!")
return FALSE
if(abs(get_size(source)/get_size(user)) > CONFIG_GET(number/max_pick_ratio))
- to_chat(user, "They're too big to pick up! ")
+ to_chat(user, span_warning("They're too big to pick up!"))
source.balloon_alert(user, "too big to pick up!")
return FALSE
if(user.get_active_held_item())
- to_chat(user, "Your hands are full! ")
+ to_chat(user, span_warning("Your hands are full!"))
source.balloon_alert(user, "hands are full!")
return FALSE
if(source.buckled)
- to_chat(user, "[source] is buckled to something! ")
+ to_chat(user, span_warning("[source] is buckled to something!"))
source.balloon_alert(user, "buckled to something!")
return FALSE
- source.visible_message("[user] starts picking up [source]. ", \
- "[user] starts picking you up! ")
+ source.visible_message(span_warning("[user] starts picking up [source]."), \
+ span_userdanger("[user] starts picking you up!"))
source.balloon_alert(user, "picking up")
var/p = abs(get_size(source)/get_size(user) * 40) //Scale how fast the pickup will be depending on size difference
if(!do_after(user, p, target = source))
return FALSE
if(user.get_active_held_item())
- to_chat(user, "Your hands are full! ")
+ to_chat(user, span_warning("Your hands are full!"))
source.balloon_alert(user, "hands full!")
return FALSE
if(source.buckled)
- to_chat(user, "[source] is buckled to something! ")
+ to_chat(user, span_warning("[source] is buckled to something!"))
source.balloon_alert(user, "buckled!")
return FALSE
- source.visible_message("[user] picks up [source]! ",
- "[user] picks you up! ",
+ source.visible_message(span_warning("[user] picks up [source]!"),
+ span_userdanger("[user] picks you up!"),
target = user,
- target_message = "You pick [source] up. ")
+ target_message = span_notice("You pick [source] up."))
source.drop_all_held_items()
mob_pickup_micro(source, user)
return TRUE
@@ -100,14 +100,14 @@
//TODO: add a timer to escape someone's grip dependant on size diff
/obj/item/clothing/head/mob_holder/micro/container_resist(mob/living/user)
if(user.incapacitated())
- to_chat(user, "You can't escape while you're restrained like this! ")
+ to_chat(user, span_warning("You can't escape while you're restrained like this!"))
return
var/mob/living/L = loc
- visible_message("[src] begins to squirm in [L]'s grasp! ")
+ visible_message(span_warning("[src] begins to squirm in [L]'s grasp!"))
if(!do_after(user, 12 SECONDS, target = src, required_mobility_flags = MOBILITY_RESIST))
if(!user || user.stat != CONSCIOUS || user.loc != src)
return
- to_chat(loc, "[src] stops resisting. ")
+ to_chat(loc, span_warning("[src] stops resisting."))
return
visible_message("[src] escapes [L]!")
release()
@@ -133,17 +133,17 @@
var/mob/living/carbon/human/M = held_mob
if(istype(M))
if(user.a_intent == "harm") //TO:DO, rework all of these interactions to be a lot more in depth
- visible_message("[user] slams their fist down on [M]! ", runechat_popup = TRUE, rune_msg = " slams their fist down on [M]!")
+ visible_message(span_danger("[user] slams their fist down on [M]!"), runechat_popup = TRUE, rune_msg = " slams their fist down on [M]!")
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
M.adjustBruteLoss(5)
return
if(user.a_intent == "disarm")
- visible_message("[user] pins [M] down with a finger! ", runechat_popup = TRUE, rune_msg = " pins [M] down with a finger!")
+ visible_message(span_danger("[user] pins [M] down with a finger!"), runechat_popup = TRUE, rune_msg = " pins [M] down with a finger!")
playsound(loc, 'sound/effects/bodyfall1.ogg', 50, 1)
M.adjustStaminaLoss(10)
return
if(user.a_intent == "grab")
- visible_message("[user] squeezes their fist around [M]! ", runechat_popup = TRUE, rune_msg = " squeezes their fist around [M]!")
+ visible_message(span_danger("[user] squeezes their fist around [M]!"), runechat_popup = TRUE, rune_msg = " squeezes their fist around [M]!")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1)
M.adjustOxyLoss(5)
return
diff --git a/modular_sand/code/datums/interactions/_interaction.dm b/modular_sand/code/datums/interactions/_interaction.dm
index c46ce23784..b7077ae80d 100644
--- a/modular_sand/code/datums/interactions/_interaction.dm
+++ b/modular_sand/code/datums/interactions/_interaction.dm
@@ -46,17 +46,17 @@
if(require_user_mouth)
if(!user.has_mouth() && !issilicon(user)) //Again, silicons do not have the required parts normally.
if(!silent)
- to_chat(user, "You don't have a mouth. ")
+ to_chat(user, span_warning("You don't have a mouth."))
return FALSE
if(!user.mouth_is_free() && !issilicon(user)) //Borgs cannot wear mouthgear, bypassing the check.
if(!silent)
- to_chat(user, "Your mouth is covered. ")
+ to_chat(user, span_warning("Your mouth is covered."))
return FALSE
if(require_user_hands && !user.has_hands() && !issilicon(user)) //Edited to allow silicons to interact.
if(!silent)
- to_chat(user, "You don't have hands. ")
+ to_chat(user, span_warning("You don't have hands."))
return FALSE
if(COOLDOWN_FINISHED(user, last_interaction_time))
@@ -100,13 +100,13 @@
/datum/interaction/proc/do_action(mob/living/user, mob/living/target)
if(!user_is_target)
if(user == target) //tactical href fix
- to_chat(user, "You cannot target yourself. ")
+ to_chat(user, span_warning("You cannot target yourself."))
return
if(get_dist(user, target) > max_distance)
- to_chat(user, "They are too far away. ")
+ to_chat(user, span_warning("They are too far away."))
return
if(needs_physical_contact && !(user.Adjacent(target) && target.Adjacent(user)))
- to_chat(user, "You cannot get to them. ")
+ to_chat(user, span_warning("You cannot get to them."))
return
if(!evaluate_user(user, silent = FALSE))
return
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
index 6fdd1df0c8..fdd4e5bf82 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/breasts.dm
@@ -30,7 +30,7 @@
"lets a large stream of [u_His] own abundant [lowertext(milktext)] coat the back of \the [target] 's throat"
)
- message = "\The [user] [pick(lines)] "
+ message = span_lewd("\The [user] [pick(lines)]")
user.visible_message(message, ignored_mobs = user.get_unconsenting())
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
@@ -59,56 +59,56 @@
/datum/interaction/lewd/titgrope/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
if(user.a_intent == INTENT_HELP)
user.visible_message(
- pick("\The [user] gently gropes \the [target] 's breast. ",
- "\The [user] softly squeezes \the [target] 's breasts. ",
- "\The [user] grips \the [target] 's breasts. ",
- "\The [user] runs a few fingers over \the [target] 's breast. ",
- "\The [user] delicately teases \the [target] 's nipple. ",
- "\The [user] traces a touch across \the [target] 's breast. "))
+ pick(span_lewd("\The [user] gently gropes \the [target] 's breast."),
+ span_lewd("\The [user] softly squeezes \the [target] 's breasts."),
+ span_lewd("\The [user] grips \the [target] 's breasts."),
+ span_lewd("\The [user] runs a few fingers over \the [target] 's breast."),
+ span_lewd("\The [user] delicately teases \the [target] 's nipple."),
+ span_lewd("\The [user] traces a touch across \the [target] 's breast.")))
if(user.a_intent == INTENT_HARM)
user.visible_message(
- pick("\The [user] aggressively gropes \the [target] 's breast. ",
- "\The [user] grabs \the [target] 's breasts. ",
- "\The [user] tightly squeezes \the [target] 's breasts. ",
- "\The [user] slaps at \the [target] 's breasts. ",
- "\The [user] gropes \the [target] 's breasts roughly. "))
+ pick(span_lewd("\The [user] aggressively gropes \the [target] 's breast."),
+ span_lewd("\The [user] grabs \the [target] 's breasts."),
+ span_lewd("\The [user] tightly squeezes \the [target] 's breasts."),
+ span_lewd("\The [user] slaps at \the [target] 's breasts."),
+ span_lewd("\The [user] gropes \the [target] 's breasts roughly.")))
if(prob(5 + target.get_lust()))
if(target.a_intent == INTENT_HELP)
user.visible_message(
- pick("\The [target] shivers in arousal. ",
- "\The [target] moans quietly. ",
- "\The [target] breathes out a soft moan. ",
- "\The [target] gasps. ",
- "\The [target] shudders softly. ",
- "\The [target] trembles as hands run across bare skin. "))
+ pick(span_lewd("\The [target] shivers in arousal."),
+ span_lewd("\The [target] moans quietly."),
+ span_lewd("\The [target] breathes out a soft moan."),
+ span_lewd("\The [target] gasps."),
+ span_lewd("\The [target] shudders softly."),
+ span_lewd("\The [target] trembles as hands run across bare skin.")))
if(target.get_lust() < 5)
target.set_lust(5)
if(target.a_intent == INTENT_DISARM)
if (target.restrained())
user.visible_message(
- pick("\The [target] twists playfully against the restraints. ",
- "\The [target] squirms away from [user] 's hand. ",
- "\The [target] slides back from [user] 's roaming hand. ",
- "\The [target] thrusts bare breasts forward into [user] 's hands. "))
+ pick(span_lewd("\The [target] twists playfully against the restraints."),
+ span_lewd("\The [target] squirms away from [user] 's hand."),
+ span_lewd("\The [target] slides back from [user] 's roaming hand."),
+ span_lewd("\The [target] thrusts bare breasts forward into [user] 's hands.")))
else
user.visible_message(
- pick("\The [target] playfully bats at [user] 's hand. ",
- "\The [target] squirms away from [user] 's hand. ",
- "\The [target] guides [user] 's hand across bare breasts. ",
- "\The [target] teasingly laces a few fingers over [user] 's knuckles. "))
+ pick(span_lewd("\The [target] playfully bats at [user] 's hand."),
+ span_lewd("\The [target] squirms away from [user] 's hand."),
+ span_lewd("\The [target] guides [user] 's hand across bare breasts."),
+ span_lewd("\The [target] teasingly laces a few fingers over [user] 's knuckles.")))
if(target.get_lust() < 10)
target.add_lust(1)
if(target.a_intent == INTENT_GRAB)
user.visible_message(
- pick("\The [target] grips [user] 's wrist tight. ",
- "\The [target] digs nails into [user] 's arm. ",
- "\The [target] grabs [user] 's wrist for a second. "))
+ pick(span_lewd("\The [target] grips [user] 's wrist tight."),
+ span_lewd("\The [target] digs nails into [user] 's arm."),
+ span_lewd("\The [target] grabs [user] 's wrist for a second.")))
if(target.a_intent == INTENT_HARM)
user.adjustBruteLoss(1)
user.visible_message(
- pick("\The [target] pushes [user] roughly away. ",
- "\The [target] digs nails angrily into [user] 's arm. ",
- "\The [target] fiercely struggles against [user] . ",
- "\The [target] claws [user] 's forearm, drawing blood. ",
- "\The [target] slaps [user] 's hand away. "))
+ pick(span_lewd("\The [target] pushes [user] roughly away."),
+ span_lewd("\The [target] digs nails angrily into [user] 's arm."),
+ span_lewd("\The [target] fiercely struggles against [user] ."),
+ span_lewd("\The [target] claws [user] 's forearm, drawing blood."),
+ span_lewd("\The [target] slaps [user] 's hand away.")))
return
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
index 096acf97d0..50a259bc9c 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/earfuck.dm
@@ -41,7 +41,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting(TRUE))
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting(TRUE))
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EARS, partner)
partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
index 862be9dec1..caa51bb1c8 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/cursed/eyefuck.dm
@@ -41,7 +41,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting(TRUE))
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting(TRUE))
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_EYES, partner)
partner.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
index d3f25b10ec..3c8dc2a72f 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/facefuck.dm
@@ -105,7 +105,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(retaliation_message)
user.visible_message("\The [partner] [retaliation_message] ", ignored_mobs = user.get_unconsenting())
if(fucktarget != "penis" || user.can_penetrating_genital_cum())
@@ -158,7 +158,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(retaliation_message)
user.visible_message(message = "\The [partner] [retaliation_message] ", ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
index 990802a538..0bf1be224b 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/feet.dm
@@ -50,7 +50,7 @@
'modular_sand/sound/interactions/foot_dry2.ogg',
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_dry4.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
partner.handle_post_sex(LOW_LUST, null, user)
/datum/interaction/lewd/grindmouth
@@ -105,7 +105,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg',
'modular_sand/sound/interactions/foot_wet3.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
partner.handle_post_sex(LOW_LUST, null, user)
/datum/interaction/lewd/footjob
@@ -135,7 +135,7 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
@@ -163,7 +163,7 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
@@ -193,5 +193,5 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
index 252ed112ff..774b11f48a 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/frotting.dm
@@ -14,7 +14,7 @@
message = "rubs [t_His] [genital_name] against [partner]'s."
user.set_is_fucking(partner, CUM_TARGET_PENIS, user.getorganslot(ORGAN_SLOT_PENIS))
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, partner)
if(partner.can_penetrating_genital_cum())
@@ -43,6 +43,6 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/squelch1.ogg',
'modular_sand/sound/interactions/squelch2.ogg',
'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, user)
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, partner)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
index dc451559a5..d3d0b7751c 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/fuck.dm
@@ -24,7 +24,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/champ1.ogg',
'modular_sand/sound/interactions/champ2.ogg'), 50, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, partner)
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, user)
@@ -56,7 +56,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, partner)
partner.handle_post_sex(NORMAL_LUST, null, user)
@@ -86,7 +86,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_BREASTS, partner)
@@ -119,7 +119,7 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
@@ -148,7 +148,7 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
@@ -182,5 +182,5 @@
'modular_sand/sound/interactions/foot_dry3.ogg',
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_wet2.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_FEET, partner)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
index 78e530c8ed..1c36e61823 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/handjob.dm
@@ -22,6 +22,6 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
index 7f49fd21dd..8e196c8a19 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/kiss.dm
@@ -16,6 +16,6 @@
/datum/interaction/lewd/kiss/display_interaction(mob/living/user, mob/living/partner)
if(user.get_lust() >= 3)
- user.visible_message("\The [user] gives an intense, lingering kiss to \the [partner] . ")
+ user.visible_message(span_lewd("\The [user] gives an intense, lingering kiss to \the [partner] ."))
else
- user.visible_message("\The [user] kisses \the [partner] deeply. ")
+ user.visible_message(span_lewd("\The [user] kisses \the [partner] deeply."))
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
index 807d7f39af..6798d07d62 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/lick.dm
@@ -6,7 +6,7 @@
max_distance = 1
/datum/interaction/lewd/rimjob/display_interaction(mob/living/user, mob/living/partner)
- user.visible_message("\The [user] licks \the [partner] 's asshole. ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] licks \the [partner] 's asshole."), ignored_mobs = user.get_unconsenting())
playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
partner.handle_post_sex(NORMAL_LUST, null, user)
@@ -29,5 +29,5 @@
message = "licks \the [partner] 's [partner.has_feet() == 1 ? "foot" : "feet"]."
playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/champ_fingering.ogg', 50, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
user.handle_post_sex(LOW_LUST, null, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
index 92ee546967..2caa4f53c7 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/mount.dm
@@ -19,7 +19,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_VAGINA, user)
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_PENIS, partner)
@@ -45,7 +45,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(partner.can_penetrating_genital_cum())
partner.handle_post_sex(NORMAL_LUST, CUM_TARGET_ANUS, user)
user.handle_post_sex(NORMAL_LUST, null, partner)
@@ -74,7 +74,7 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/squelch1.ogg',
'modular_sand/sound/interactions/squelch2.ogg',
'modular_sand/sound/interactions/squelch3.ogg'), 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
user.handle_post_sex(LOW_LUST, null, partner)
/datum/interaction/lewd/thighs
@@ -157,7 +157,7 @@
'modular_sand/sound/interactions/foot_wet1.ogg',
'modular_sand/sound/interactions/foot_dry3.ogg')
playlewdinteractionsound(get_turf(user), file, 70, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
user.handle_post_sex(lust_increase, THIGH_SMOTHERING, partner)
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
index 617821e111..e5a0b8911e 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/nipsuck.dm
@@ -10,9 +10,9 @@
/datum/interaction/lewd/nipsuck/display_interaction(mob/living/carbon/human/user, mob/living/carbon/human/target)
if((user.a_intent == INTENT_HELP) || (user.a_intent == INTENT_DISARM))
user.visible_message(
- pick("\The [user] gently sucks on \the [target] 's [pick("nipple", "nipples")]. ",
- "\The [user] gently nibs \the [target] 's [pick("nipple", "nipples")]. ",
- "\The [user] licks \the [target] 's [pick("nipple", "nipples")]. "))
+ pick(span_lewd("\The [user] gently sucks on \the [target] 's [pick("nipple", "nipples")]."),
+ span_lewd("\The [user] gently nibs \the [target] 's [pick("nipple", "nipples")]."),
+ span_lewd("\The [user] licks \the [target] 's [pick("nipple", "nipples")].")))
if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
@@ -31,8 +31,8 @@
if(user.a_intent == INTENT_HARM)
user.visible_message(
- pick("\The [user] bites \the [target] 's [pick("nipple", "nipples")]. ",
- "\The [user] aggressively sucks \the [target] 's [pick("nipple", "nipples")]. "))
+ pick(span_lewd("\The [user] bites \the [target] 's [pick("nipple", "nipples")]."),
+ span_lewd("\The [user] aggressively sucks \the [target] 's [pick("nipple", "nipples")].")))
if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
@@ -51,9 +51,9 @@
if(user.a_intent == INTENT_GRAB)
user.visible_message(
- pick("\The [user] sucks \the [target] 's [pick("nipple", "nipples")] intently. ",
- "\The [user] feasts \the [target] 's [pick("nipple", "nipples")]. ",
- "\The [user] glomps \the [target] 's [pick("nipple", "nipples")]. "))
+ pick(span_lewd("\The [user] sucks \the [target] 's [pick("nipple", "nipples")] intently."),
+ span_lewd("\The [user] feasts \the [target] 's [pick("nipple", "nipples")]."),
+ span_lewd("\The [user] glomps \the [target] 's [pick("nipple", "nipples")].")))
if(target.has_breasts(REQUIRE_EXPOSED))
var/modifier = 1
var/obj/item/organ/genital/breasts/B = target.getorganslot(ORGAN_SLOT_BREASTS)
@@ -74,66 +74,66 @@
if(target.a_intent == INTENT_HELP)
if(!target.has_breasts())
user.visible_message(
- pick("\The [target] shivers in arousal. ",
- "\The [target] moans quietly. ",
- "\The [target] breathes out a soft moan. ",
- "\The [target] gasps. ",
- "\The [target] shudders softly. ",
- "\The [target] trembles as their chest gets molested. "))
+ pick(span_lewd("\The [target] shivers in arousal."),
+ span_lewd("\The [target] moans quietly."),
+ span_lewd("\The [target] breathes out a soft moan."),
+ span_lewd("\The [target] gasps."),
+ span_lewd("\The [target] shudders softly."),
+ span_lewd("\The [target] trembles as their chest gets molested.")))
else
user.visible_message(
- pick("\The [target] shivers in arousal. ",
- "\The [target] moans quietly. ",
- "\The [target] breathes out a soft moan. ",
- "\The [target] gasps. ",
- "\The [target] shudders softly. ",
- "\The [target] trembles as their breasts get molested. ",
- "\The [target] quivers in arousal as \the [user] delights themselves on their milk. "))
+ pick(span_lewd("\The [target] shivers in arousal."),
+ span_lewd("\The [target] moans quietly."),
+ span_lewd("\The [target] breathes out a soft moan."),
+ span_lewd("\The [target] gasps."),
+ span_lewd("\The [target] shudders softly."),
+ span_lewd("\The [target] trembles as their breasts get molested."),
+ span_lewd("\The [target] quivers in arousal as \the [user] delights themselves on their milk.")))
if(target.get_lust() < 5)
target.set_lust(5)
if(target.a_intent == INTENT_DISARM)
if (target.restrained())
if(!target.has_breasts())
user.visible_message(
- pick("\The [target] twists playfully against the restraints. ",
- "\The [target] squirms away from \the [user] 's mouth. ",
- "\The [target] slides back from \the [user] 's mouth. ",
- "\The [target] thrusts their bare chest forward into \the [user] 's mouth. "))
+ pick(span_lewd("\The [target] twists playfully against the restraints."),
+ span_lewd("\The [target] squirms away from \the [user] 's mouth."),
+ span_lewd("\The [target] slides back from \the [user] 's mouth."),
+ span_lewd("\The [target] thrusts their bare chest forward into \the [user] 's mouth.")))
else
user.visible_message(
- pick("\The [target] twists playfully against the restraints. ",
- "\The [target] squirms away from \the [user] 's mouth. ",
- "\The [target] slides back from \the [user] 's mouth. ",
- "\The [target] thrust their bare breasts forward into \the [user] 's mouth. "))
+ pick(span_lewd("\The [target] twists playfully against the restraints."),
+ span_lewd("\The [target] squirms away from \the [user] 's mouth."),
+ span_lewd("\The [target] slides back from \the [user] 's mouth."),
+ span_lewd("\The [target] thrust their bare breasts forward into \the [user] 's mouth.")))
else
if(!target.has_breasts())
user.visible_message(
- pick("\The [target] playfully shoos away \the [user] 's head. ",
- "\The [target] squirms away from \the [user] 's mouth. ",
- "\The [target] holds \the [user] 's head against their chest. ",
- "\The [target] teasingly caresses \the [user] 's neck. "))
+ pick(span_lewd("\The [target] playfully shoos away \the [user] 's head."),
+ span_lewd("\The [target] squirms away from \the [user] 's mouth."),
+ span_lewd("\The [target] holds \the [user] 's head against their chest."),
+ span_lewd("\The [target] teasingly caresses \the [user] 's neck.")))
else
user.visible_message(
- pick("\The [target] playfully shoos away \the [user] 's head. ",
- "\The [target] squirms away from \the [user] 's mouth. ",
- "\The [target] holds \the [user] 's head against their breast. ",
- "\The [target] teasingly caresses \the [user] 's neck. ",
- "\The [target] rubs their breasts against \the [user] 's head. "))
+ pick(span_lewd("\The [target] playfully shoos away \the [user] 's head."),
+ span_lewd("\The [target] squirms away from \the [user] 's mouth."),
+ span_lewd("\The [target] holds \the [user] 's head against their breast."),
+ span_lewd("\The [target] teasingly caresses \the [user] 's neck."),
+ span_lewd("\The [target] rubs their breasts against \the [user] 's head.")))
if(target.get_lust() < 10)
target.add_lust(1)
if(target.a_intent == INTENT_GRAB)
user.visible_message(
- pick("\The [target] grips \the [user] 's head tight. ",
- "\The [target] digs nails into \the [user] 's scalp. ",
- "\The [target] grabs and shoves \the [user] 's head away. "))
+ pick(span_lewd("\The [target] grips \the [user] 's head tight."),
+ span_lewd("\The [target] digs nails into \the [user] 's scalp."),
+ span_lewd("\The [target] grabs and shoves \the [user] 's head away.")))
if(target.a_intent == INTENT_HARM)
user.adjustBruteLoss(1)
user.visible_message(
- pick("\The [target] slaps \the [user] away. ",
- "\The [target] scratches [user] 's face. ",
- "\The [target] fiercely struggles against [user] . ",
- "\The [target] claws [user] 's face, drawing blood. ",
- "\The [target] elbows [user] 's mouth away. "))
+ pick(span_lewd("\The [target] slaps \the [user] away."),
+ span_lewd("\The [target] scratches [user] 's face."),
+ span_lewd("\The [target] fiercely struggles against [user] ."),
+ span_lewd("\The [target] claws [user] 's face, drawing blood."),
+ span_lewd("\The [target] elbows [user] 's mouth away.")))
target.dir = get_dir(target, user)
user.dir = get_dir(user, target)
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
index 912b227915..3210d01ed3 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/nuts.dm
@@ -29,7 +29,7 @@
'modular_sand/sound/interactions/nuts2.ogg',
'modular_sand/sound/interactions/nuts3.ogg',
'modular_sand/sound/interactions/nuts4.ogg'), 70, 1, -1)*/ //These files don't even exist but nobody noticed because double-quotes were used instead of single.
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
user.handle_post_sex(lust_increase, CUM_TARGET_MOUTH, partner)
/datum/interaction/lewd/nut_smack
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
index ece5e1c49b..59ab08f85d 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/oral.dm
@@ -123,6 +123,6 @@
'modular_sand/sound/interactions/bj9.ogg',
'modular_sand/sound/interactions/bj10.ogg',
'modular_sand/sound/interactions/bj11.ogg'), 50, 1, -1)
- user.visible_message("\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(fucktarget != "penis" || partner.can_penetrating_genital_cum())
partner.handle_post_sex(lust_increase, CUM_TARGET_MOUTH, user)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
index f4d4599d3d..5c91e50a3c 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/breasts.dm
@@ -32,7 +32,7 @@
"gasps.",
"shudders softly.",
"trembles as [t_His] hands run across bare skin.")]")
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
playlewdinteractionsound(get_turf(user), 'modular_sand/sound/interactions/squelch1.ogg', 50, 1, -1)
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
@@ -68,7 +68,7 @@
"fills [u_His] own mouth with a big gulp of [u_His] warm [lowertext(milktext)]"
)
- message = "\The [user] [pick(lines)] "
+ message = span_lewd("\The [user] [pick(lines)]")
user.visible_message(message, ignored_mobs = user.get_unconsenting())
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/oral1.ogg',
'modular_sand/sound/interactions/oral2.ogg'), 70, 1, -1)
diff --git a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
index f07e3a7c72..5213c5fe4c 100644
--- a/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
+++ b/modular_sand/code/datums/interactions/interaction_datums/lewd/self/jack.dm
@@ -28,6 +28,6 @@
playlewdinteractionsound(get_turf(user), pick('modular_sand/sound/interactions/bang1.ogg',
'modular_sand/sound/interactions/bang2.ogg',
'modular_sand/sound/interactions/bang3.ogg'), 70, 1, -1)
- user.visible_message(message = "\The [user] [message] ", ignored_mobs = user.get_unconsenting())
+ user.visible_message(message = span_lewd("\The [user] [message]"), ignored_mobs = user.get_unconsenting())
if(user.can_penetrating_genital_cum())
user.handle_post_sex(NORMAL_LUST, CUM_TARGET_HAND, user)
diff --git a/modular_sand/code/datums/interactions/interaction_interface.dm b/modular_sand/code/datums/interactions/interaction_interface.dm
index 7d5edf37af..2d7f794132 100644
--- a/modular_sand/code/datums/interactions/interaction_interface.dm
+++ b/modular_sand/code/datums/interactions/interaction_interface.dm
@@ -12,6 +12,28 @@
usr.mind.interaction_holder.target = src
usr.mind.interaction_holder.ui_interact(usr)
+/*
+/// Allows "cyborg" players to change gender at will
+/mob/living/silicon/robot/verb/toggle_gender()
+ set name = "Set Gender"
+ set desc = "Allows you to set your gender."
+
+ if(stat != CONSCIOUS)
+ to_chat(usr, span_warning("You cannot toggle your gender while unconcious!"))
+ return
+
+ var/choice = tgui_alert(usr, "Select Gender.", "Gender", list("Both", "Male", "Female"))
+ switch(choice)
+ if("Both")
+ has_penis = TRUE
+ has_vagina = TRUE
+ if("Male")
+ has_penis = TRUE
+ has_vagina = FALSE
+ if("Female")
+ has_penis = FALSE
+ has_vagina = TRUE
+*/
#define INTERACTION_NORMAL 0
#define INTERACTION_LEWD 1
@@ -87,7 +109,7 @@
if(CHECK_BITFIELD(genital.genital_flags, GENITAL_INTERNAL)) //Not those though
continue
var/list/genital_entry = list()
- genital_entry["name"] = "[genital.name]" //Prevents code from adding a prefix
+ genital_entry["name"] = "[capitalize(genital.name)]" //Prevents code from adding a prefix
genital_entry["key"] = REF(genital) //The key is the reference to the object
var/visibility = "Invalid"
if(CHECK_BITFIELD(genital.genital_flags, GENITAL_THROUGH_CLOTHES))
@@ -107,10 +129,16 @@
genital_entry["visibility"] = visibility
genital_entry["possible_choices"] = GLOB.genitals_visibility_toggles
genital_entry["extra_choices"] = list(GEN_ALLOW_EGG_STUFFING)
+ genital_entry["can_arouse"] = (
+ !!CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_AROUSE) \
+ && !(HAS_TRAIT(get_genitals, TRAIT_PERMABONER) \
+ || HAS_TRAIT(get_genitals, TRAIT_NEVERBONER)))
+ genital_entry["arousal_state"] = genital.aroused_state
+ genital_entry["always_accessible"] = genital.always_accessible
genitals += list(genital_entry)
if(iscarbon(self) && !self.getorganslot(ORGAN_SLOT_ANUS))
var/simulated_ass = list()
- simulated_ass["name"] = "anus"
+ simulated_ass["name"] = "Anus"
simulated_ass["key"] = "anus"
var/visibility = "Invalid"
switch(self.anus_exposed)
@@ -122,6 +150,7 @@
visibility = "Always hidden"
simulated_ass["visibility"] = visibility
simulated_ass["possible_choices"] = GLOB.genitals_visibility_toggles - GEN_VISIBLE_NO_CLOTHES
+ simulated_ass["always_accessible"] = self.anus_always_accessible
genitals += list(simulated_ass)
.["genitals"] = genitals
@@ -156,35 +185,35 @@
genital_interactibles += list(genital_entry)
.["genital_interactibles"] = genital_interactibles
- var/datum/preferences/prefs = usr?.client.prefs
+ var/datum/preferences/prefs = self?.client.prefs
if(prefs)
//Getting char prefs
.["erp_pref"] = pref_to_num(prefs.erppref)
- .["noncon_pref"] = pref_to_num(prefs.nonconpref)
- .["vore_pref"] = pref_to_num(prefs.vorepref)
+ .["noncon_pref"] = pref_to_num(prefs.nonconpref)
+ .["vore_pref"] = pref_to_num(prefs.vorepref)
.["extreme_pref"] = pref_to_num(prefs.extremepref)
.["extreme_harm"] = pref_to_num(prefs.extremeharm)
.["unholy_pref"] = pref_to_num(prefs.unholypref)
//Getting preferences
- .["verb_consent"] = CHECK_BITFIELD(prefs.toggles, VERB_CONSENT)
+ .["verb_consent"] = !!CHECK_BITFIELD(prefs.toggles, VERB_CONSENT)
.["lewd_verb_sounds"] = !CHECK_BITFIELD(prefs.toggles, LEWD_VERB_SOUNDS)
- .["arousable"] = prefs.arousable
- .["genital_examine"] = CHECK_BITFIELD(prefs.cit_toggles, GENITAL_EXAMINE)
- .["vore_examine"] = CHECK_BITFIELD(prefs.cit_toggles, VORE_EXAMINE)
- .["medihound_sleeper"] = CHECK_BITFIELD(prefs.cit_toggles, MEDIHOUND_SLEEPER)
- .["eating_noises"] = CHECK_BITFIELD(prefs.cit_toggles, EATING_NOISES)
- .["digestion_noises"] = CHECK_BITFIELD(prefs.cit_toggles, DIGESTION_NOISES)
- .["trash_forcefeed"] = CHECK_BITFIELD(prefs.cit_toggles, TRASH_FORCEFEED)
- .["forced_fem"] = CHECK_BITFIELD(prefs.cit_toggles, FORCED_FEM)
- .["forced_masc"] = CHECK_BITFIELD(prefs.cit_toggles, FORCED_MASC)
- .["hypno"] = CHECK_BITFIELD(prefs.cit_toggles, HYPNO)
- .["bimbofication"] = CHECK_BITFIELD(prefs.cit_toggles, BIMBOFICATION)
- .["breast_enlargement"] = CHECK_BITFIELD(prefs.cit_toggles, BREAST_ENLARGEMENT)
- .["penis_enlargement"] = CHECK_BITFIELD(prefs.cit_toggles, PENIS_ENLARGEMENT)
- .["butt_enlargement"] = CHECK_BITFIELD(prefs.cit_toggles, BUTT_ENLARGEMENT)
- .["belly_inflation"] = CHECK_BITFIELD(prefs.cit_toggles, BELLY_INFLATION)
- .["never_hypno"] = !CHECK_BITFIELD(prefs.cit_toggles, NEVER_HYPNO)
+ .["arousable"] = prefs.arousable
+ .["genital_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, GENITAL_EXAMINE)
+ .["vore_examine"] = !!CHECK_BITFIELD(prefs.cit_toggles, VORE_EXAMINE)
+ .["medihound_sleeper"] = !!CHECK_BITFIELD(prefs.cit_toggles, MEDIHOUND_SLEEPER)
+ .["eating_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, EATING_NOISES)
+ .["digestion_noises"] = !!CHECK_BITFIELD(prefs.cit_toggles, DIGESTION_NOISES)
+ .["trash_forcefeed"] = !!CHECK_BITFIELD(prefs.cit_toggles, TRASH_FORCEFEED)
+ .["forced_fem"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_FEM)
+ .["forced_masc"] = !!CHECK_BITFIELD(prefs.cit_toggles, FORCED_MASC)
+ .["hypno"] = !!CHECK_BITFIELD(prefs.cit_toggles, HYPNO)
+ .["bimbofication"] = !!CHECK_BITFIELD(prefs.cit_toggles, BIMBOFICATION)
+ .["breast_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BREAST_ENLARGEMENT)
+ .["penis_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, PENIS_ENLARGEMENT)
+ .["butt_enlargement"] = !!CHECK_BITFIELD(prefs.cit_toggles, BUTT_ENLARGEMENT)
+ .["belly_inflation"] = !!CHECK_BITFIELD(prefs.cit_toggles, BELLY_INFLATION)
+ .["never_hypno"] = !CHECK_BITFIELD(prefs.cit_toggles, NEVER_HYPNO)
.["no_aphro"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_APHRO)
.["no_ass_slap"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_ASS_SLAP)
.["no_auto_wag"] = !CHECK_BITFIELD(prefs.cit_toggles, NO_AUTO_WAG)
@@ -210,12 +239,42 @@
return FALSE
if("genital")
var/mob/living/carbon/self = usr
- if(params["genital"] == "anus")
- self.anus_toggle_visibility(params["visibility"])
- return TRUE
- var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
- if(genital && (genital in self.internal_organs))
- genital.toggle_visibility(params["visibility"])
+ if("visibility" in params)
+ if(params["genital"] == "anus")
+ self.anus_toggle_visibility(params["visibility"])
+ return TRUE
+ var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
+ if(genital && (genital in self.internal_organs))
+ genital.toggle_visibility(params["visibility"])
+ return TRUE
+ if("set_arousal" in params)
+ var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
+ if(!genital || (genital \
+ && (!CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_AROUSE) \
+ || HAS_TRAIT(self, TRAIT_PERMABONER) \
+ || HAS_TRAIT(self, TRAIT_NEVERBONER))))
+ return FALSE
+ var/original_state = genital.aroused_state
+ genital.set_aroused_state(params["set_arousal"])// i'm not making it just `!aroused_state` because
+ if(original_state != genital.aroused_state) // someone just might port skyrat's new genitals
+ to_chat(self, span_userlove("[genital.aroused_state ? genital.arousal_verb : genital.unarousal_verb]."))
+ . = TRUE
+ else
+ to_chat(self, span_userlove("You can't make that genital [genital.aroused_state ? "unaroused" : "aroused"]!"))
+ . = FALSE
+ genital.update_appearance()
+ if(ishuman(self))
+ var/mob/living/carbon/human/human = self
+ human.update_genitals()
+ return
+ if("set_accessibility" in params)
+ if(!self.getorganslot(ORGAN_SLOT_ANUS) && params["genital"] == "anus")
+ self.toggle_anus_always_accessible()
+ return TRUE
+ var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
+ if(!genital)
+ return FALSE
+ genital.toggle_accessibility()
return TRUE
else
return FALSE
diff --git a/modular_sand/code/datums/interactions/lewd_definitions.dm b/modular_sand/code/datums/interactions/lewd_definitions.dm
index e674722e45..643dfeafb8 100644
--- a/modular_sand/code/datums/interactions/lewd_definitions.dm
+++ b/modular_sand/code/datums/interactions/lewd_definitions.dm
@@ -21,8 +21,9 @@
var/has_balls = FALSE
var/has_vagina = FALSE
var/has_anus = TRUE
- var/has_breasts = FALSE
var/has_butt = FALSE
+ var/anus_always_accessible = FALSE
+ var/has_breasts = FALSE
var/anus_exposed = FALSE
var/last_partner
var/last_orifice
@@ -85,6 +86,9 @@
lust = num
lastlusttime = world.time
+/mob/living/proc/toggle_anus_always_accessible()
+ anus_always_accessible = !anus_always_accessible
+
/mob/living/proc/has_genital(slot, visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(istype(C))
@@ -94,7 +98,7 @@
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
- return genital.is_exposed()
+ return genital.is_exposed() || genital.always_accessible
if(REQUIRE_UNEXPOSED)
return !genital.is_exposed()
else
@@ -127,9 +131,9 @@
for(var/obj/item/clothing/cloth in get_equipped_items())
if(istype(cloth, /obj/item/clothing/underwear/briefs/strapon))
return cloth
-
+
return null
-
+
/mob/living/proc/can_penetrating_genital_cum()
return has_penis()
@@ -161,6 +165,8 @@
if(REQUIRE_ANY)
return TRUE
if(REQUIRE_EXPOSED)
+ if (has_anus && anus_always_accessible)
+ return TRUE
switch(anus_exposed)
if(-1)
return FALSE
@@ -340,29 +346,11 @@
return TRUE
return FALSE
-/mob/living/proc/has_butt(var/nintendo = REQUIRE_ANY)
+/mob/living/proc/has_butt(visibility = REQUIRE_ANY)
var/mob/living/carbon/C = src
if(has_butt && !istype(C))
return TRUE
- if(istype(C))
- var/obj/item/organ/genital/peepee = C.getorganslot(ORGAN_SLOT_BUTT)
- if(peepee)
- switch(nintendo)
- if(REQUIRE_ANY)
- return TRUE
- if(REQUIRE_EXPOSED)
- if(peepee.is_exposed())
- return TRUE
- else
- return FALSE
- if(REQUIRE_UNEXPOSED)
- if(!peepee.is_exposed())
- return TRUE
- else
- return FALSE
- else
- return TRUE
- return FALSE
+ return has_genital(ORGAN_SLOT_BUTT, visibility)
///Are we wearing something that covers our chest?
/mob/living/proc/is_topless()
@@ -413,9 +401,9 @@
if(moan == lastmoan)
moan--
if(!is_muzzled())
- visible_message(message = "\The [src] [pick("moans", "moans in pleasure")]. ", ignored_mobs = get_unconsenting())
+ visible_message(message = span_lewd("\The [src] [pick("moans", "moans in pleasure")]."), ignored_mobs = get_unconsenting())
if(is_muzzled())//immursion
- audible_message("[src] [pick("mimes a pleasured moan","moans in silence")]. ")
+ audible_message(span_lewd("[src] [pick("mimes a pleasured moan","moans in silence")]."))
lastmoan = moan
/mob/living/proc/cum(mob/living/partner, target_orifice)
@@ -776,7 +764,7 @@
playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/final_f1.ogg',
'modular_sand/sound/interactions/final_f2.ogg',
'modular_sand/sound/interactions/final_f3.ogg'), 70, 1, 0)
- visible_message(message = "\The [src] [message] ", ignored_mobs = get_unconsenting())
+ visible_message(message = span_userlove("\The [src] [message]"), ignored_mobs = get_unconsenting())
multiorgasms += 1
COOLDOWN_START(src, refractory_period, (rand(300, 900) - get_sexual_potency()))//sex cooldown
diff --git a/modular_sand/code/datums/interactions/lewd_interactions.dm b/modular_sand/code/datums/interactions/lewd_interactions.dm
index 43199355d2..2171ec0b7f 100644
--- a/modular_sand/code/datums/interactions/lewd_interactions.dm
+++ b/modular_sand/code/datums/interactions/lewd_interactions.dm
@@ -74,17 +74,17 @@
return FALSE
if(user_not_tired && !COOLDOWN_FINISHED(user, refractory_period))
if(!silent) //bye spam
- to_chat(user, "You're still exhausted from the last time. You need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(user, refractory_period), 1)] until you can do that! ")
+ to_chat(user, span_warning("You're still exhausted from the last time. You need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(user, refractory_period), 1)] until you can do that!"))
return FALSE
if(require_user_bottomless && !user.is_bottomless())
if(!silent)
- to_chat(user, "Your pants are in the way. ")
+ to_chat(user, span_warning("Your pants are in the way."))
return FALSE
if(require_user_topless && !user.is_topless())
if(!silent)
- to_chat(user, "Your top is in the way. ")
+ to_chat(user, span_warning("Your top is in the way."))
return FALSE
if(require_user_penis)
@@ -92,17 +92,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_penis(REQUIRE_EXPOSED) && !user.has_strapon(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your penis need to be exposed. ")
+ to_chat(user, span_warning("Your penis need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_penis(REQUIRE_ANY) && !user.has_strapon(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have a penis. ")
+ to_chat(user, span_warning("You don't have a penis."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_penis(REQUIRE_UNEXPOSED) && !user.has_strapon(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your penis need to be unexposed. ")
+ to_chat(user, span_warning("Your penis need to be unexposed."))
return FALSE
if(require_user_balls)
@@ -110,17 +110,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_balls(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your balls need to be exposed. ")
+ to_chat(user, span_warning("Your balls need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_balls(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have balls. ")
+ to_chat(user, span_warning("You don't have balls."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_balls(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your balls need to be unexposed. ")
+ to_chat(user, span_warning("Your balls need to be unexposed."))
return FALSE
if(require_user_anus)
@@ -128,17 +128,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_anus(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your anus need to be exposed. ")
+ to_chat(user, span_warning("Your anus need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_anus(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have an anus. ")
+ to_chat(user, span_warning("You don't have an anus."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_anus(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your anus need to be unexposed. ")
+ to_chat(user, span_warning("Your anus need to be unexposed."))
return FALSE
if(require_user_vagina)
@@ -146,17 +146,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_vagina(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your vagina need to be exposed. ")
+ to_chat(user, span_warning("Your vagina need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_vagina(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have a vagina. ")
+ to_chat(user, span_warning("You don't have a vagina."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_vagina(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your vagina need to be unexposed. ")
+ to_chat(user, span_warning("Your vagina need to be unexposed."))
return FALSE
if(require_user_breasts)
@@ -164,17 +164,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_breasts(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your breasts need to be exposed. ")
+ to_chat(user, span_warning("Your breasts need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_breasts(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have breasts. ")
+ to_chat(user, span_warning("You don't have breasts."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_breasts(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your breasts need to be unexposed. ")
+ to_chat(user, span_warning("Your breasts need to be unexposed."))
return FALSE
if(require_user_feet)
@@ -182,22 +182,22 @@
if(REQUIRE_EXPOSED)
if(!user.has_feet(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your feet need to be exposed. ")
+ to_chat(user, span_warning("Your feet need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_feet(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have enough feet. ")
+ to_chat(user, span_warning("You don't have enough feet."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_feet(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your feet need to be unexposed. ")
+ to_chat(user, span_warning("Your feet need to be unexposed."))
return FALSE
if(require_user_num_feet && (user.get_num_feet() < require_user_num_feet))
if(!silent)
- to_chat(user, "You don't have enough feet. ")
+ to_chat(user, span_warning("You don't have enough feet."))
return FALSE
if(require_user_eyes)
@@ -205,17 +205,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_eyes(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your eyes need to be exposed. ")
+ to_chat(user, span_warning("Your eyes need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_eyes(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have eyes. ")
+ to_chat(user, span_warning("You don't have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_eyes(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your eyes need to be unexposed. ")
+ to_chat(user, span_warning("Your eyes need to be unexposed."))
return FALSE
if(require_user_eyesockets)
@@ -223,17 +223,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_eyesockets(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your eyesockets need to be exposed. ")
+ to_chat(user, span_warning("Your eyesockets need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_eyesockets(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You still have eyes. ")
+ to_chat(user, span_warning("You still have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_eyesockets(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your eyesockets need to be unexposed. ")
+ to_chat(user, span_warning("Your eyesockets need to be unexposed."))
return FALSE
if(require_user_ears)
@@ -241,17 +241,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_ears(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your ears need to be exposed. ")
+ to_chat(user, span_warning("Your ears need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_ears(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You don't have ears. ")
+ to_chat(user, span_warning("You don't have ears."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_ears(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your ears need to be unexposed. ")
+ to_chat(user, span_warning("Your ears need to be unexposed."))
return FALSE
if(require_user_earsockets)
@@ -259,17 +259,17 @@
if(REQUIRE_EXPOSED)
if(!user.has_earsockets(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Your earsockets need to be exposed. ")
+ to_chat(user, span_warning("Your earsockets need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!user.has_earsockets(REQUIRE_ANY))
if(!silent)
- to_chat(user, "You still have eyes. ")
+ to_chat(user, span_warning("You still have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!user.has_earsockets(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Your earsockets need to be unexposed. ")
+ to_chat(user, span_warning("Your earsockets need to be unexposed."))
return FALSE
if(extreme)
@@ -277,7 +277,7 @@
if(cli)
if(cli.prefs.extremepref == "No")
if(!silent)
- to_chat(user, "That's way too much for you. ")
+ to_chat(user, span_warning("That's way too much for you."))
return FALSE
if(require_ooc_consent)
@@ -293,17 +293,17 @@
return FALSE
if(target_not_tired && !COOLDOWN_FINISHED(target, refractory_period))
if(!silent) //same with this
- to_chat(user, "They're still exhausted from the last time. They need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(target, refractory_period), 1)] until you can do that! ")
+ to_chat(user, span_warning("They're still exhausted from the last time. They need to wait [DisplayTimeText(COOLDOWN_TIMELEFT(target, refractory_period), 1)] until you can do that!"))
return FALSE
if(require_target_bottomless && !target.is_bottomless())
if(!silent)
- to_chat(user, "Their pants are in the way. ")
+ to_chat(user, span_warning("Their pants are in the way."))
return FALSE
if(require_target_topless && !target.is_topless())
if(!silent)
- to_chat(user, "Their clothes are in the way. ")
+ to_chat(user, span_warning("Their clothes are in the way."))
return FALSE
if(require_target_penis)
@@ -311,17 +311,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_penis(REQUIRE_EXPOSED) && !target.has_strapon(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their penis needs to be exposed. ")
+ to_chat(user, span_warning("Their penis needs to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_penis(REQUIRE_ANY) && !target.has_strapon(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "They don't have a penis. ")
+ to_chat(user, span_warning("They don't have a penis."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_penis(REQUIRE_UNEXPOSED) && !target.has_strapon(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their penis needs to be unexposed. ")
+ to_chat(user, span_warning("Their penis needs to be unexposed."))
return FALSE
if(require_target_balls)
@@ -329,17 +329,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_balls(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their balls need to be exposed. ")
+ to_chat(user, span_warning("Their balls need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_balls(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have balls. ")
+ to_chat(user, span_warning("They don't have balls."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_balls(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their balls need to be unexposed. ")
+ to_chat(user, span_warning("Their balls need to be unexposed."))
return FALSE
if(require_target_anus)
@@ -347,17 +347,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_anus(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their anus needs to be exposed. ")
+ to_chat(user, span_warning("Their anus needs to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_anus(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have an anus. ")
+ to_chat(user, span_warning("They don't have an anus."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_anus(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their anus needs to be unexposed. ")
+ to_chat(user, span_warning("Their anus needs to be unexposed."))
return FALSE
if(require_target_vagina)
@@ -365,17 +365,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_vagina(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their vagina needs to be exposed. ")
+ to_chat(user, span_warning("Their vagina needs to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_vagina(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have a vagina. ")
+ to_chat(user, span_warning("They don't have a vagina."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_vagina(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their vagina needs to be unexposed. ")
+ to_chat(user, span_warning("Their vagina needs to be unexposed."))
return FALSE
if(require_target_breasts)
@@ -383,17 +383,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_breasts(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their breasts need to be exposed. ")
+ to_chat(user, span_warning("Their breasts need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_breasts(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have breasts. ")
+ to_chat(user, span_warning("They don't have breasts."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_breasts(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their breasts need to be unexposed. ")
+ to_chat(user, span_warning("Their breasts need to be unexposed."))
return FALSE
if(require_target_feet)
@@ -401,22 +401,22 @@
if(REQUIRE_EXPOSED)
if(!target.has_feet(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their feet need to be exposed. ")
+ to_chat(user, span_warning("Their feet need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_feet(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have enough feet. ")
+ to_chat(user, span_warning("They don't have enough feet."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_feet(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their feet need to be unexposed. ")
+ to_chat(user, span_warning("Their feet need to be unexposed."))
return FALSE
if(require_target_num_feet && (target.get_num_feet() < require_target_num_feet))
if(!silent)
- to_chat(user, "They don't have enough feet. ")
+ to_chat(user, span_warning("They don't have enough feet."))
return FALSE
if(require_target_eyes)
@@ -424,17 +424,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_eyes(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their eyes need to be exposed. ")
+ to_chat(user, span_warning("Their eyes need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_eyes(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have eyes. ")
+ to_chat(user, span_warning("They don't have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_eyes(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their eyes need to be unexposed. ")
+ to_chat(user, span_warning("Their eyes need to be unexposed."))
return FALSE
if(require_target_eyesockets)
@@ -442,17 +442,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_eyesockets(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their eyesockets need to be exposed. ")
+ to_chat(user, span_warning("Their eyesockets need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_eyesockets(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They still have eyes. ")
+ to_chat(user, span_warning("They still have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_eyesockets(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their eyesockets need to be unexposed. ")
+ to_chat(user, span_warning("Their eyesockets need to be unexposed."))
return FALSE
if(require_target_ears)
@@ -460,17 +460,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_ears(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their ears need to be exposed. ")
+ to_chat(user, span_warning("Their ears need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_ears(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They don't have ears. ")
+ to_chat(user, span_warning("They don't have ears."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_ears(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their ears need to be unexposed. ")
+ to_chat(user, span_warning("Their ears need to be unexposed."))
return FALSE
if(require_target_earsockets)
@@ -478,17 +478,17 @@
if(REQUIRE_EXPOSED)
if(!target.has_earsockets(REQUIRE_EXPOSED))
if(!silent)
- to_chat(user, "Their earsockets need to be exposed. ")
+ to_chat(user, span_warning("Their earsockets need to be exposed."))
return FALSE
if(REQUIRE_ANY)
if(!target.has_earsockets(REQUIRE_ANY))
if(!silent)
- to_chat(user, "They still have eyes. ")
+ to_chat(user, span_warning("They still have eyes."))
return FALSE
if(REQUIRE_UNEXPOSED)
if(!target.has_earsockets(REQUIRE_UNEXPOSED))
if(!silent)
- to_chat(user, "Their earsockets need to be unexposed. ")
+ to_chat(user, span_warning("Their earsockets need to be unexposed."))
return FALSE
if(extreme)
@@ -496,7 +496,7 @@
if(cli)
if(target.client.prefs.extremepref == "No")
if(!silent)
- to_chat(user, "For some reason, you don't want to do this to [target]. ")
+ to_chat(user, span_warning("For some reason, you don't want to do this to [target]."))
return FALSE
if(require_ooc_consent)
diff --git a/modular_sand/code/datums/interactions/lewd_objects.dm b/modular_sand/code/datums/interactions/lewd_objects.dm
index e90b76abc7..c2bb19045a 100644
--- a/modular_sand/code/datums/interactions/lewd_objects.dm
+++ b/modular_sand/code/datums/interactions/lewd_objects.dm
@@ -22,7 +22,7 @@
if(M.has_mouth() && !M.is_mouth_covered())
message = (user == M) ? pick("fucks [possessive_verb] own mouth with \the [src]", "shoves \the [src] into [possessive_verb] mouth", "jams \the [src] into [possessive_verb] mouth") : pick("fucks [M]'s mouth with \the [src]", "jams \the [src] into [M]'s mouth")
if(message)
- user.visible_message("[user] [message]. ")
+ user.visible_message(span_lewd("[user] [message]."))
M.handle_post_sex(lust_amt, null, user)
playsound(loc, pick('modular_sand/sound/interactions/bang4.ogg',
'modular_sand/sound/interactions/bang5.ogg',
@@ -32,7 +32,7 @@
/obj/item/dildo/attack_self(mob/living/carbon/human/user as mob)
hole = hole == CUM_TARGET_VAGINA ? CUM_TARGET_ANUS : CUM_TARGET_VAGINA
- to_chat(user, "Now targetting \the [hole]. ")
+ to_chat(user, span_notice("Now targetting \the [hole]."))
//begin redds code
/obj/item/dildo/cyborg
diff --git a/modular_sand/code/datums/traits/negative.dm b/modular_sand/code/datums/traits/negative.dm
index 4b4f158ef8..3a50591875 100644
--- a/modular_sand/code/datums/traits/negative.dm
+++ b/modular_sand/code/datums/traits/negative.dm
@@ -3,8 +3,8 @@
desc = "For one reason or another, you either can't or haven't learned the common tongue."
value = 0
mob_trait = TRAIT_SHELTERED
- gain_text = "The words of others begin to blur together... "
- lose_text = "You start putting together what people are saying! "
+ gain_text = span_danger("The words of others begin to blur together...")
+ lose_text = span_notice("You start putting together what people are saying!")
medical_record_text = "Patient has shown an inability to use common speaking languages."
/datum/quirk/sheltered/on_spawn()
diff --git a/modular_sand/code/datums/traits/neutral.dm b/modular_sand/code/datums/traits/neutral.dm
index 33cc31da0d..89486dc153 100644
--- a/modular_sand/code/datums/traits/neutral.dm
+++ b/modular_sand/code/datums/traits/neutral.dm
@@ -18,7 +18,7 @@
value = 0
human_only = TRUE
mob_trait = TRAIT_INFERTILE
- gain_text = "Your womb starts feeling dry and empty, all the life in it begins to fade away... "
- lose_text = "You feel the warm blow of life flooding your womb, full of newfound, vibrant fertility! "
+ gain_text = span_notice("Your womb starts feeling dry and empty, all the life in it begins to fade away...")
+ lose_text = span_love("You feel the warm blow of life flooding your womb, full of newfound, vibrant fertility!")
medical_record_text = "Patient doesn't seem able to ovulate properly..."
*/
diff --git a/modular_sand/code/game/machinery/autodoc.dm b/modular_sand/code/game/machinery/autodoc.dm
index 5d8fa2429e..fcd00555c4 100644
--- a/modular_sand/code/game/machinery/autodoc.dm
+++ b/modular_sand/code/game/machinery/autodoc.dm
@@ -26,11 +26,11 @@
/obj/machinery/autodoc/examine(mob/user)
. = ..()
if((obj_flags & EMAGGED) && panel_open)
- . += "[src]'s surgery protocols have been corrupted! "
+ . += span_warning("[src]'s surgery protocols have been corrupted!")
if(processing)
- . += "[src] is currently inserting [storedorgan] into [occupant]. "
+ . += span_notice("[src] is currently inserting [storedorgan] into [occupant].")
else if(storedorgan)
- . += "[src] is prepared to insert [storedorgan]. "
+ . += span_notice("[src] is prepared to insert [storedorgan].")
/obj/machinery/autodoc/close_machine(mob/user)
..()
@@ -40,16 +40,16 @@
occupant.forceMove(drop_location())
occupant = null
return
- to_chat(occupant, "You enter [src]. ")
+ to_chat(occupant, span_notice("You enter [src]."))
dosurgery()
/obj/machinery/autodoc/proc/dosurgery()
if(!storedorgan && !(obj_flags & EMAGGED))
- to_chat(occupant, "[src] currently has no implant stored. ")
+ to_chat(occupant, span_notice("[src] currently has no implant stored."))
return
- occupant.visible_message("[occupant] presses a button on [src], and you hear a mechanical noise. ", "You feel a sharp sting as [src] starts inserting the organ into your body. ")
+ occupant.visible_message(span_notice("[occupant] presses a button on [src], and you hear a mechanical noise."), span_notice("You feel a sharp sting as [src] starts inserting the organ into your body."))
playsound(get_turf(occupant), 'sound/weapons/circsawhit.ogg', 50, 1)
processing = TRUE
update_icon()
@@ -66,7 +66,7 @@
if(!processing)
return
- occupant.visible_message("[src] dismembers [occupant]!", "[src] saws up your body! ")
+ occupant.visible_message(span_warning("[src] dismembers [occupant]!"), span_warning("[src] saws up your body!"))
else
sleep(surgerytime)
@@ -78,14 +78,14 @@
currentorgan.forceMove(get_turf(src))
storedorgan.Insert(occupant)//insert stored organ into the user
storedorgan = null
- occupant.visible_message("[src] completes the surgery procedure.", "[src] inserts the organ into your body. ")
+ occupant.visible_message(span_notice("[src] completes the surgery procedure."), span_notice("[src] inserts the organ into your body."))
playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, 0)
processing = FALSE
open_machine()
/obj/machinery/autodoc/open_machine(mob/user)
if(processing)
- occupant.visible_message("[user] cancels [src]'s procedure.", "[src] stops inserting the organ into your body. ")
+ occupant.visible_message(span_notice("[user] cancels [src]'s procedure."), span_notice("[src] stops inserting the organ into your body."))
processing = FALSE
if(occupant)
occupant.forceMove(drop_location())
@@ -94,7 +94,7 @@
/obj/machinery/autodoc/interact(mob/user)
if(panel_open)
- to_chat(user, "Close the maintenance panel first. ")
+ to_chat(user, span_notice("Close the maintenance panel first."))
return
if(state_open)
@@ -106,13 +106,13 @@
/obj/machinery/autodoc/attackby(obj/item/I, mob/user, params)
if(istype(I, organ_type))
if(storedorgan)
- to_chat(user, "[src] already has an implant stored. ")
+ to_chat(user, span_notice("[src] already has an implant stored."))
return
if(!user.transferItemToLoc(I, src))
return
storedorgan = I
I.forceMove(src)
- to_chat(user, "You insert the [I] into [src]. ")
+ to_chat(user, span_notice("You insert the [I] into [src]."))
else
return ..()
@@ -121,10 +121,10 @@
if(..())
return
if(occupant)
- to_chat(user, "[src] is currently occupied! ")
+ to_chat(user, span_warning("[src] is currently occupied!"))
return
if(state_open)
- to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch! ")
+ to_chat(user, span_warning("[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!"))
return
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I))
if(storedorgan)
@@ -164,4 +164,4 @@
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
- to_chat(user, "You reprogram [src]'s surgery procedures. ")
+ to_chat(user, span_warning("You reprogram [src]'s surgery procedures."))
diff --git a/modular_sand/code/game/machinery/cryptominers.dm b/modular_sand/code/game/machinery/cryptominers.dm
index df17cf0c25..33f87a8e9f 100644
--- a/modular_sand/code/game/machinery/cryptominers.dm
+++ b/modular_sand/code/game/machinery/cryptominers.dm
@@ -8,13 +8,15 @@
idle_power_usage = 20
active_power_usage = 200
circuit = /obj/item/circuitboard/machine/cryptominer
+ init_process = FALSE // Don't process upon creation
var/mining = FALSE
var/miningtime = 3000
var/miningpoints = 50
var/mintemp = TCRYO // 225K equals approximately -55F or -48C
var/midtemp = T0C // 273K equals 32F or 0C
var/maxtemp = 500 // 500K equals approximately 440F or 226C
- var/heatingPower = 40000
+ var/heatingPower = 100 // Heat added each processing
+ var/require_conductivity = TRUE // Prevent use in space
var/datum/bank_account/pay_me = null
/obj/machinery/cryptominer/Initialize(mapload)
@@ -50,19 +52,19 @@
if(id_card)
var/obj/item/card/id/CARD = id_card
if(CARD.bank_support != ID_FREE_BANK_ACCOUNT)
- to_chat(user, "This ID has no banking support whatsover, must be an older model... ")
+ to_chat(user, span_warning("This ID has no banking support whatsover, must be an older model..."))
return
if(!CARD.registered_account)
- to_chat(user, "ERROR: No bank account found. ")
+ to_chat(user, span_warning("ERROR: No bank account found."))
return
- to_chat(user, "You link \the [CARD] to \the [src]. ")
+ to_chat(user, span_notice("You link \the [CARD] to \the [src]."))
pay_me = CARD.registered_account
- say("Now using [pay_me.account_holder ? "[pay_me.account_holder]'s" : "ERROR "] account.")
+ say("Now using [pay_me.account_holder ? "[pay_me.account_holder]'s" : span_boldwarning("ERROR")] account.")
return
/obj/machinery/cryptominer/AltClick(mob/user)
- user.visible_message("[user] begins resetting \the [src]. ",
- "You begin resetting \the [src]. ")
+ user.visible_message(span_warning("[user] begins resetting \the [src]."),
+ span_warning("You begin resetting \the [src]."))
balloon_alert(user, "resetting")
if(do_after(user, 5 SECONDS, target = src))
pay_me = SSeconomy.get_dep_account(ACCOUNT_CAR)
@@ -71,58 +73,75 @@
/obj/machinery/cryptominer/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
- . += "A little screen on the machine reads: Currently the linked bank account is [pay_me.account_holder ? "[pay_me.account_holder]'s" : "ERROR "]."
+ . += span_notice("A little screen on the machine reads: Currently the linked bank account is [pay_me.account_holder ? "[pay_me.account_holder]'s" : span_boldwarning("ERROR")].")
. += "Modify the destination of the credits using your id on it while it is inactive and has it's panel open."
. += "Alt-Click to reset to the Cargo budget. "
/obj/machinery/cryptominer/process()
+ // Get turf
var/turf/T = get_turf(src)
if(!T)
return
+
+ // Check for tiles with no conductivity (space)
+ if(T.thermal_conductivity == 0)
+ // Normal mode: Warn the user and stop processing
+ if(require_conductivity)
+ say("Invalid atmospheric conditions detected! Shutting off!")
+ playsound(loc, 'sound/machines/beep.ogg', 50, TRUE, -1)
+ set_mining(FALSE)
+ return
+
+ // Cheat mode: Skip all atmos code and give points
+ else
+ produce_points(3)
+ return
+
+ // Get air
var/datum/gas_mixture/env = T.return_air()
if(!env)
return
- if(!mining)
- return
- if(env.return_temperature() >= maxtemp)
- if(mining)
- playsound(loc, 'sound/machines/beep.ogg', 50, TRUE, -1)
+
+ // Get temp
+ var/env_temp = env.return_temperature()
+
+ // Check for temperature effects
+ // Minimum (most likely)
+ if(env_temp <= mintemp)
+ produce_points(3)
+ // Mid
+ else if((env_temp <= midtemp) && (env_temp >= mintemp))
+ produce_points(1)
+ // Maximum
+ else if((env_temp <= maxtemp) && (env_temp >= midtemp))
+ produce_points(0.20)
+ // Overheat
+ else if(env_temp >= maxtemp)
+ say("Critical overheating detected! Shutting off!")
+ playsound(loc, 'sound/machines/beep.ogg', 50, TRUE, -1)
set_mining(FALSE)
- return
- if(env.return_temperature() <= maxtemp && env.return_temperature() >= midtemp)
- if(mining)
- produce_points(0.20)
- produce_heat()
- return
- if(env.return_temperature() <= midtemp && env.return_temperature() >= mintemp)
- if(mining)
- produce_points(1)
- produce_heat()
- return
- if(env.return_temperature() <= mintemp)
- if(mining)
- produce_points(3)
- produce_heat()
- return
+
+ // Increase heat by heatingPower
+ env.set_temperature(env_temp + heatingPower)
+
+ // Update air
+ air_update_turf()
/obj/machinery/cryptominer/proc/produce_points(number)
playsound(loc, 'sound/machines/ping.ogg', 50, TRUE, -1)
if(pay_me)
pay_me.adjust_money(FLOOR(miningpoints * number,1))
-/obj/machinery/cryptominer/proc/produce_heat()
- atmos_spawn_air("co2=10;TEMP=2000")
-
/obj/machinery/cryptominer/attack_hand(mob/living/user)
. = ..()
if(!is_operational())
- to_chat(user, "[src] has to be on to do this! ")
+ to_chat(user, span_warning("[src] has to be on to do this!"))
balloon_alert(user, "no power!")
return FALSE
if(mining)
set_mining(FALSE)
- visible_message("[src] slowly comes to a halt. ",
- "You turn off [src]. ")
+ visible_message(span_warning("[src] slowly comes to a halt."),
+ span_warning("You turn off [src]."))
balloon_alert(user, "turned off")
return
balloon_alert(user, "turned on")
diff --git a/modular_sand/code/game/mecha/mecha_construction_paths.dm b/modular_sand/code/game/mecha/mecha_construction_paths.dm
index 4459823bc0..5b55ec5221 100644
--- a/modular_sand/code/game/mecha/mecha_construction_paths.dm
+++ b/modular_sand/code/game/mecha/mecha_construction_paths.dm
@@ -102,45 +102,45 @@
switch(index)
if(1)
- user.visible_message("[user] wrenches [parent]'s parts.", "You wrench [parent]'s parts. ")
+ user.visible_message("[user] wrenches [parent]'s parts.", span_notice("You wrench [parent]'s parts."))
if(2)
if(diff==FORWARD)
- user.visible_message("[user] welds [parent]'s parts.", "You weld [parent]'s parts ")
+ user.visible_message("[user] welds [parent]'s parts.", span_notice("You weld [parent]'s parts"))
else
- user.visible_message("[user] unwrenches [parent]'s parts.", "You unwrench [parent]'s parts. ")
+ user.visible_message("[user] unwrenches [parent]'s parts.", span_notice("You unwrench [parent]'s parts."))
if(3)
if(diff==FORWARD)
- user.visible_message("[user] slots bluespace crystals onto [parent].", "You slot the bluespace crystals onto [parent]. ")
+ user.visible_message("[user] slots bluespace crystals onto [parent].", span_notice("You slot the bluespace crystals onto [parent]."))
else
- user.visible_message("[user] unwelds [parent]'s parts.", "You unweld [parent]'s parts. ")
+ user.visible_message("[user] unwelds [parent]'s parts.", span_notice("You unweld [parent]'s parts."))
if(4)
if(diff==FORWARD)
- user.visible_message("[user] secures the [parent]'s bluespace crystal slots.", "You secure the [parent]'s bluespace crystal slots ")
+ user.visible_message("[user] secures the [parent]'s bluespace crystal slots.", span_notice("You secure the [parent]'s bluespace crystal slots"))
else
- user.visible_message("[user] removes the bluespace crystals from [parent].", "You remove [parent]'s bluespace crystals. ")
+ user.visible_message("[user] removes the bluespace crystals from [parent].", span_notice("You remove [parent]'s bluespace crystals."))
if(5)
if(diff==FORWARD)
- user.visible_message("[user] slots the capacitor onto [parent].", "You slot the capacitor onto [parent]. ")
+ user.visible_message("[user] slots the capacitor onto [parent].", span_notice("You slot the capacitor onto [parent]."))
else
- user.visible_message("[user] unsecures the bluespace crystal slots from [parent].", "You unsecure [parent]'s bluespace crystal slots. ")
+ user.visible_message("[user] unsecures the bluespace crystal slots from [parent].", span_notice("You unsecure [parent]'s bluespace crystal slots."))
if(6)
if(diff==FORWARD)
- user.visible_message("[user] secures [parent]'s capacitor.", "You secure [parent]'s capacitor. ")
+ user.visible_message("[user] secures [parent]'s capacitor.", span_notice("You secure [parent]'s capacitor."))
else
- user.visible_message("[user] removes the [parent]'s capacitor.", "You remove the [parent]'s capacitor. ")
+ user.visible_message("[user] removes the [parent]'s capacitor.", span_notice("You remove the [parent]'s capacitor."))
if(7)
if(diff==FORWARD)
- user.visible_message("[user] wires the [parent].", "You wire the [parent]. ")
+ user.visible_message("[user] wires the [parent].", span_notice("You wire the [parent]."))
else
- user.visible_message("[user] unsecures [parent]'s capacitor.", "You unsecure [parent]'s capacitor. ")
+ user.visible_message("[user] unsecures [parent]'s capacitor.", span_notice("You unsecure [parent]'s capacitor."))
if(8)
if(diff==FORWARD)
- user.visible_message("[user] links [parent]'s wires to the limbs.", "You link [parent]'s wires to the limbs. ")
+ user.visible_message("[user] links [parent]'s wires to the limbs.", span_notice("You link [parent]'s wires to the limbs."))
else
- user.visible_message("[user] snips off [parent]'s wires.", "You snip off [parent]'s wires. ")
+ user.visible_message("[user] snips off [parent]'s wires.", span_notice("You snip off [parent]'s wires."))
if(9)
if(diff==FORWARD)
- user.visible_message("[user] welds [parent]'s external armor layer.", "You weld [parent]'s external armor layer. ")
+ user.visible_message("[user] welds [parent]'s external armor layer.", span_notice("You weld [parent]'s external armor layer."))
else
- user.visible_message("[user] unlinks [parent]'s wires from the limbs.", "You unlink [parent]'s wires from the limbs. ")
+ user.visible_message("[user] unlinks [parent]'s wires from the limbs.", span_notice("You unlink [parent]'s wires from the limbs."))
return TRUE
diff --git a/modular_sand/code/game/objects/items/borg_shapeshifter.dm b/modular_sand/code/game/objects/items/borg_shapeshifter.dm
index 64878711b6..0216524d69 100644
--- a/modular_sand/code/game/objects/items/borg_shapeshifter.dm
+++ b/modular_sand/code/game/objects/items/borg_shapeshifter.dm
@@ -111,18 +111,18 @@
if(isturf(user.loc))
toggle(user)
else
- to_chat(user, "You can't use [src] while inside something! ")
+ to_chat(user, span_warning("You can't use [src] while inside something!"))
else
- to_chat(user, "You need at least [activationCost] charge in your cell to use [src]! ")
+ to_chat(user, span_warning("You need at least [activationCost] charge in your cell to use [src]!"))
/obj/item/borg_shapeshifter/proc/toggle(mob/living/silicon/robot/user)
if(active)
playsound(src, 'sound/effects/pop.ogg', 100, TRUE, -6)
- to_chat(user, "You deactivate \the [src]. ")
+ to_chat(user, span_notice("You deactivate \the [src]."))
deactivate(user)
else
if(animation_playing)
- to_chat(user, "\the [src] is recharging. ")
+ to_chat(user, span_notice("\the [src] is recharging."))
return
var/mob/living/silicon/robot/R = loc
var/static/list/module_icons = sortList(list(
@@ -574,7 +574,7 @@
return FALSE
animation_playing = TRUE
- to_chat(user, "You activate \the [src]. ")
+ to_chat(user, span_notice("You activate \the [src]."))
playsound(src, 'sound/effects/seedling_chargeup.ogg', 100, TRUE, -6)
var/start = user.filters.len
var/X,Y,rsq,i,f
@@ -591,10 +591,10 @@
animate(offset=f:offset-1, time=rand()*20+10)
if (do_after(user, 50, target=user) && user.cell.use(activationCost))
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE, -6)
- to_chat(user, "You are now disguised as the Nanotrasen cyborg \"[friendlyName]\". ")
+ to_chat(user, span_notice("You are now disguised as the Nanotrasen cyborg \"[friendlyName]\"."))
activate(user, module_selection)
else
- to_chat(user, "The chameleon field fizzles. ")
+ to_chat(user, span_warning("The chameleon field fizzles."))
do_sparks(3, FALSE, user)
for(i=1, i<=min(7, user.filters.len), ++i) // removing filters that are animating does nothing, we gotta stop the animations first
f = user.filters[start+i]
@@ -656,7 +656,7 @@
/obj/item/borg_shapeshifter/proc/disrupt(mob/living/silicon/robot/user)
if(active)
- to_chat(user, "Your chameleon field deactivates. ")
+ to_chat(user, span_danger("Your chameleon field deactivates."))
deactivate(user)
/obj/item/borg_shapeshifter/stable
diff --git a/modular_sand/code/game/objects/items/chrono_eraser.dm b/modular_sand/code/game/objects/items/chrono_eraser.dm
index d3f803e38f..a168920e1d 100644
--- a/modular_sand/code/game/objects/items/chrono_eraser.dm
+++ b/modular_sand/code/game/objects/items/chrono_eraser.dm
@@ -86,7 +86,7 @@
var/mob/living/user = loc
if(F.gun)
if(isliving(user) && F.captured)
- to_chat(user, "FAIL: [F.captured] already has an existing connection. ")
+ to_chat(user, span_alert("FAIL: [F.captured] already has an existing connection. "))
field_disconnect(F)
else
startpos = get_turf(src)
@@ -94,7 +94,7 @@
F.gun = src
if(isliving(user) && F.captured)
playsound(user,'sound/effects/clock_tick.ogg' , 50, 1)
- to_chat(user, "Connection established with target: [F.captured] ")
+ to_chat(user, span_notice("Connection established with target: [F.captured] "))
/obj/item/gun/energy/chrono_gun/proc/field_disconnect(obj/structure/chrono_field/F)
@@ -104,7 +104,7 @@
F.gun = null
if(isliving(user) && F.captured)
F.captured.adjustOrganLoss(ORGAN_SLOT_BRAIN, 199, 199) //not so fast!
- to_chat(user, "Disconnected from target: [F.captured] ")
+ to_chat(user, span_alert("Disconnected from target: [F.captured] "))
field = null
startpos = null
@@ -215,9 +215,9 @@
AM.forceMove(drop_location())
qdel(src)
else if(tickstokill <= 0)
- to_chat(captured, "As the last essence of your being is erased from time, you are taken back to your most enjoyable memory. You feel happy... ")
+ to_chat(captured, span_boldnotice("As the last essence of your being is erased from time, you are taken back to your most enjoyable memory. You feel happy..."))
playsound(captured,'sound/effects/lingreadapt.ogg' , 50, 1)
- captured.visible_message("[captured] dematerialises out of the timestream! ")
+ captured.visible_message(span_danger("[captured] dematerialises out of the timestream!"))
var/mob/dead/observer/ghost = captured.ghostize(1)
if(captured.mind)
if(ghost)
diff --git a/modular_sand/code/game/objects/items/computermath.dm b/modular_sand/code/game/objects/items/computermath.dm
index 19a3e17512..2188f05ff9 100644
--- a/modular_sand/code/game/objects/items/computermath.dm
+++ b/modular_sand/code/game/objects/items/computermath.dm
@@ -240,7 +240,7 @@
// me fail arithmetic, me brian hurt
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1)
if(difficulty == "Easy") // me fail arithmetic, me brian hurt //nice one, brain damage for it, very cool.
- to_chat(user,"You feel sad after failing such an easy question... ")
+ to_chat(user,span_warning("You feel sad after failing such an easy question..."))
SEND_SIGNAL(LM, COMSIG_ADD_MOOD_EVENT, "failed_easy", /datum/mood_event/failed_easy)
return
diff --git a/modular_sand/code/game/objects/items/cosmetics.dm b/modular_sand/code/game/objects/items/cosmetics.dm
index b43112c55c..10db30229e 100644
--- a/modular_sand/code/game/objects/items/cosmetics.dm
+++ b/modular_sand/code/game/objects/items/cosmetics.dm
@@ -4,7 +4,7 @@
/obj/item/razor/proc/new_hairstyle(mob/living/carbon/human/H, mob/user, mirror)
var/location = user.zone_selected
if (H == user && !mirror)
- to_chat(user, "You need a mirror to properly style your own hair! ")
+ to_chat(user, span_warning("You need a mirror to properly style your own hair!"))
balloon_alert(user, "need mirror!")
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
@@ -13,12 +13,12 @@
if(!new_style)
return
if(!get_location_accessible(H, location))
- to_chat(user, "The headgear is in the way! ")
+ to_chat(user, span_warning("The headgear is in the way!"))
balloon_alert(user, "headgear in the way!")
return
- user.visible_message("[user] tries to change [H]'s hairstyle using [src]. ", "You try to change [H]'s hairstyle using [src]. ")
+ user.visible_message(span_notice("[user] tries to change [H]'s hairstyle using [src]."), span_notice("You try to change [H]'s hairstyle using [src]."))
if(new_style && do_after(user, 60, target = H))
- user.visible_message("[user] successfully changes [H]'s hairstyle using [src]. ", "You successfully change [H]'s hairstyle using [src]. ")
+ user.visible_message(span_notice("[user] successfully changes [H]'s hairstyle using [src]."), span_notice("You successfully change [H]'s hairstyle using [src]."))
H.balloon_alert(user, "changed hairstyle")
H.hair_style = new_style
H.update_hair()
@@ -26,7 +26,7 @@
/obj/item/razor/proc/new_facial_hairstyle(mob/living/carbon/human/H, mob/user, var/mirror)
var/location = user.zone_selected
if(H == user && !mirror)
- to_chat(user, "You need a mirror to properly style your own facial hair! ")
+ to_chat(user, span_warning("You need a mirror to properly style your own facial hair!"))
balloon_alert(user, "need mirror!")
return
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
@@ -35,12 +35,12 @@
if(!new_style)
return
if(!get_location_accessible(H, location))
- to_chat(user, "The mask is in the way! ")
+ to_chat(user, span_warning("The mask is in the way!"))
balloon_alert(user, "mask in the way!")
return
- user.visible_message("[user] tries to change [H]'s facial hair style using [src]. ", "You try to change [H]'s facial hair style using [src]. ")
+ user.visible_message(span_notice("[user] tries to change [H]'s facial hair style using [src]."), span_notice("You try to change [H]'s facial hair style using [src]."))
if(new_style && do_after(user, 60, target = H))
- user.visible_message("[user] successfully changes [H]'s facial hair style using [src]. ", "You successfully change [H]'s facial hair style using [src]. ")
+ user.visible_message(span_notice("[user] successfully changes [H]'s facial hair style using [src]."), span_notice("You successfully change [H]'s facial hair style using [src]."))
H.balloon_alert(user, "changed facial hair style")
H.facial_hair_style = new_style
H.update_hair()
@@ -64,7 +64,7 @@
var/extended_icon_state = "straightrazor_open"
/obj/item/razor/straightrazor/suicide_act(mob/user)
- user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide! ")
+ user.visible_message(span_suicide("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
return (BRUTELOSS)
/obj/item/razor/straightrazor/attack_self(mob/user)
@@ -102,6 +102,6 @@
/obj/item/handmirror/attack_self(mob/user)
ADD_TRAIT(user, TRAIT_SELF_AWARE, "mirror_trait")
- to_chat(user, "You look into the mirror ")
+ to_chat(user, span_notice("You look into the mirror"))
sleep(15 SECONDS)
REMOVE_TRAIT(user, TRAIT_SELF_AWARE, "mirror_trait")
diff --git a/modular_sand/code/game/objects/items/devices/dogborg_sleeper.dm b/modular_sand/code/game/objects/items/devices/dogborg_sleeper.dm
index 00f94fa31e..c0dbc0d4a4 100644
--- a/modular_sand/code/game/objects/items/devices/dogborg_sleeper.dm
+++ b/modular_sand/code/game/objects/items/devices/dogborg_sleeper.dm
@@ -25,20 +25,20 @@
if(!hound || !istype(target) || !proximity || target.anchored)
return
if(length(contents) > (max_item_count - 1))
- to_chat(user,"Your [src] is full. Eject or process contents to continue. ")
+ to_chat(user,span_warning("Your [src] is full. Eject or process contents to continue."))
return
if(isitem(target))
var/obj/item/I = target
if(CheckAccepted(I))
- to_chat(user,"[I] registers an error code to your [src] ")
+ to_chat(user,span_warning("[I] registers an error code to your [src]"))
return
if(I.w_class > WEIGHT_CLASS_NORMAL)
- to_chat(user,"[I] is too large to fit into your [src] ")
+ to_chat(user,span_warning("[I] is too large to fit into your [src]"))
return
- user.visible_message("[hound.name] is ingesting [I] into their [src.name]. ", "You start ingesting [target] into your [src.name]... ")
+ user.visible_message(span_warning("[hound.name] is ingesting [I] into their [src.name]."), span_notice("You start ingesting [target] into your [src.name]..."))
if(do_after(user, 15, target = target) && length(contents) < max_item_count)
I.forceMove(src)
- I.visible_message("[hound.name]'s garbage processor groans lightly as [I] slips inside. ", "Your garbage compactor groans lightly as [I] slips inside. ")
+ I.visible_message(span_warning("[hound.name]'s garbage processor groans lightly as [I] slips inside."), span_notice("Your garbage compactor groans lightly as [I] slips inside."))
playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1)
if(length(contents) > 11) //grow that tum after a certain junk amount
hound.sleeper_r = 1
@@ -51,18 +51,18 @@
if(iscarbon(target) || issilicon(target))
var/mob/living/trashman = target
if(!CHECK_BITFIELD(trashman.vore_flags,DEVOURABLE))
- to_chat(user, "[target] registers an error code to your [src] ")
+ to_chat(user, span_warning("[target] registers an error code to your [src]"))
return
if(patient)
- to_chat(user,"Your [src] is already occupied. ")
+ to_chat(user,span_warning("Your [src] is already occupied."))
return
if(trashman.buckled)
- to_chat(user,"[trashman] is buckled and can not be put into your [src]. ")
+ to_chat(user,span_warning("[trashman] is buckled and can not be put into your [src]."))
return
- user.visible_message("[hound.name] is ingesting [trashman] into their [src]. ", "You start ingesting [trashman] into your [src.name]... ")
+ user.visible_message(span_warning("[hound.name] is ingesting [trashman] into their [src]."), span_notice("You start ingesting [trashman] into your [src.name]..."))
if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
trashman.forceMove(src)
trashman.reset_perspective(src)
update_gut(user)
- user.visible_message("[hound.name]'s garbage processor groans lightly as [trashman] slips inside. ", "Your garbage compactor groans lightly as [trashman] slips inside. ")
+ user.visible_message(span_warning("[hound.name]'s garbage processor groans lightly as [trashman] slips inside."), span_notice("Your garbage compactor groans lightly as [trashman] slips inside."))
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
diff --git a/modular_sand/code/game/objects/items/devices/extra_arm.dm b/modular_sand/code/game/objects/items/devices/extra_arm.dm
index 55a40eb163..35949fc463 100644
--- a/modular_sand/code/game/objects/items/devices/extra_arm.dm
+++ b/modular_sand/code/game/objects/items/devices/extra_arm.dm
@@ -11,8 +11,8 @@
M.change_number_of_hands(limbs+1)
used = TRUE
icon_state = "extra_arm_none"
- M.visible_message("[M] presses a button on [src], and you hear a disgusting noise. ", "You feel a sharp sting as [src] plunges into your body. ")
+ M.visible_message(span_notice("[M] presses a button on [src], and you hear a disgusting noise."), span_notice("You feel a sharp sting as [src] plunges into your body."))
M.balloon_alert(M, "arm implanted")
- to_chat(M, "You feel more dexterous. ")
+ to_chat(M, span_notice("You feel more dexterous."))
playsound(get_turf(M), 'sound/misc/splort.ogg', 50, 1)
desc += "Looks like it's been used up."
diff --git a/modular_sand/code/game/objects/items/fleshlight.dm b/modular_sand/code/game/objects/items/fleshlight.dm
index 6b64abe956..1db9cbc504 100644
--- a/modular_sand/code/game/objects/items/fleshlight.dm
+++ b/modular_sand/code/game/objects/items/fleshlight.dm
@@ -20,7 +20,7 @@
/obj/item/fleshlight/examine(mob/user)
. = ..()
- . += "Alt-Click \the [name] to customize it. "
+ . += span_notice("Alt-Click \the [name] to customize it.")
/obj/item/fleshlight/update_appearance(updates)
. = ..()
@@ -61,7 +61,7 @@
message = (user == M) ? "pumps [src] on [possessive_verb] [genital_name]" : "pumps \the [src] on [M]'s [genital_name]"
lust_amt = NORMAL_LUST
if(message)
- user.visible_message("[user] [message]. ")
+ user.visible_message(span_lewd("[user] [message]."))
M.handle_post_sex(lust_amt, null, user)
playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang4.ogg',
'modular_sand/sound/interactions/bang5.ogg',
@@ -107,9 +107,9 @@
/obj/item/portallight/examine(mob/user)
. = ..()
if(!portalunderwear)
- . += "The device is unpaired. To pair, swipe against a pair of portal panties. "
+ . += span_notice("The device is unpaired. To pair, swipe against a pair of portal panties.")
else
- . += "The device is paired, and awaiting input. "
+ . += span_notice("The device is paired, and awaiting input. ")
/obj/item/portallight/update_appearance(updates)
. = ..()
@@ -416,7 +416,7 @@
else
to_chat(user, "There is no [user.zone_selected == BODY_ZONE_R_LEG ? "right" : "left"] feet! ")
if(!useable)
- to_chat(user, "It seems the device has failed or your partner is not wearing their device. ")
+ to_chat(user, span_notice("It seems the device has failed or your partner is not wearing their device."))
if(user_message)
if(portal_target && (portal_target?.client?.prefs.toggles & VERB_CONSENT || !portal_target.ckey))
user.visible_message("[user] [user_message]. ")
@@ -514,7 +514,7 @@
to_chat(M, "urethra fleshlight cumming on dick ")
portal_target.do_jitter_animation() //make your partner shake too!
else
- user.visible_message("\The [src] beeps and does not let [M] through. ")
+ user.visible_message(span_warning("\The [src] beeps and does not let [M] through."))
else if(user.a_intent == INTENT_HARM)
return ..()
@@ -607,7 +607,7 @@
if(isliving(portalunderwear.loc))
portalunderwear.audible_message("[icon2html(portalunderwear, hearers(portalunderwear))] *beep* *beep* *beep*")
playsound(portalunderwear, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
- to_chat(portalunderwear.loc, "The panties beep as the link to the [src] is lost. ")
+ to_chat(portalunderwear.loc, span_notice("The panties beep as the link to the [src] is lost."))
. = ..()
/**
@@ -653,9 +653,9 @@
/obj/item/clothing/underwear/briefs/panties/portalpanties/examine(mob/user)
. = ..()
if(!portallight)
- . += "The device is unpaired, to pair, swipe the fleshlight against this pair of portal panties(TM). "
+ . += span_notice("The device is unpaired, to pair, swipe the fleshlight against this pair of portal panties(TM). ")
else
- . += "The device is paired, and awaiting attachment. "
+ . += span_notice("The device is paired, and awaiting attachment. ")
/obj/item/clothing/underwear/briefs/panties/portalpanties/attackby(obj/item/I, mob/living/user) //pairing
if(istype(I, /obj/item/portallight))
@@ -681,11 +681,11 @@
switch(targetting)
if(CUM_TARGET_VAGINA)
if(!human.has_vagina(REQUIRE_EXPOSED))
- to_chat(human, "The vagina is covered or there is none! ")
+ to_chat(human, span_warning("The vagina is covered or there is none!"))
return FALSE
if(CUM_TARGET_ANUS)
if(!human.has_anus(REQUIRE_EXPOSED))
- to_chat(human, "The anus is covered or there is none! ")
+ to_chat(human, span_warning("The anus is covered or there is none!"))
return FALSE
if(CUM_TARGET_PENIS)
if(!human.has_penis(REQUIRE_EXPOSED) && !human.has_strapon(REQUIRE_EXPOSED))
@@ -708,7 +708,7 @@
if(!portallight)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
- to_chat(user, "The panties are not linked to a portal fleshlight. ")
+ to_chat(user, span_notice("The panties are not linked to a portal fleshlight."))
else
update_portal()
RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/drop_out)
diff --git a/modular_sand/code/game/objects/items/plushes/goat_boss.dm b/modular_sand/code/game/objects/items/plushes/goat_boss.dm
index 9209390bba..a754f936f8 100644
--- a/modular_sand/code/game/objects/items/plushes/goat_boss.dm
+++ b/modular_sand/code/game/objects/items/plushes/goat_boss.dm
@@ -26,27 +26,27 @@
if (!targets_to_pick_from.len)
return
target = pick(targets_to_pick_from)
- visible_message("[src] stares at [target]. ")
+ visible_message(span_notice("[src] stares at [target]."))
if (world.time > cooldown && target)
ram()
/obj/item/toy/plush/goatplushie/angry/proc/ram()
if(prob((obj_flags & EMAGGED) ? 98:90) && isturf(loc) && considered_alive(target.mind) && !faction_check(list("goat"), target.faction, FALSE))
throw_at(target, 10, 10)
- visible_message("[src] rams [target]! ")
+ visible_message(span_danger("[src] rams [target]!"))
cooldown = world.time + cooldown_modifier
target = null
- visible_message("[src] looks disinterested. ")
+ visible_message(span_notice("[src] looks disinterested."))
/obj/item/toy/plush/goatplushie/angry/emag_act(mob/user)
if (obj_flags&EMAGGED)
- visible_message("[src] already looks angry enough, you shouldn't anger it more. ")
+ visible_message(span_notice("[src] already looks angry enough, you shouldn't anger it more."))
return
cooldown_modifier = cooldown_modifier/2 * 0.75
throwforce = 12.5
force = 10
obj_flags |= EMAGGED
- visible_message("[src] stares at [user] angrily before going docile. ")
+ visible_message(span_danger("[src] stares at [user] angrily before going docile."))
/obj/item/toy/plush/goatplushie/angry/Destroy()
STOP_PROCESSING(SSprocessing, src)
@@ -85,14 +85,14 @@
/obj/item/toy/plush/goatplushie/angry/kinggoat/ascendedkinggoat/attackby(obj/item/I,mob/living/user,params)
if(I.get_sharpness())
- user.visible_message("[user] attempts to destroy [src]! ", "[I] bounces off [src]'s back before breaking into millions of pieces... [src] glares at [user]! ") // You fucked up now son
+ user.visible_message(span_notice("[user] attempts to destroy [src]!"), span_suicide("[I] bounces off [src]'s back before breaking into millions of pieces... [src] glares at [user]!")) // You fucked up now son
I.play_tool_sound(src)
qdel(I)
user.gib()
/obj/item/toy/plush/goatplushie/angry/kinggoat/attackby(obj/item/I,mob/living/user,params)
if(I.get_sharpness())
- user.visible_message("[user] rips [src] to shreds! ", "[src]'s death has attracted the attention of the king goat plushie guards! ")
+ user.visible_message(span_notice("[user] rips [src] to shreds!"), span_notice("[src]'s death has attracted the attention of the king goat plushie guards!"))
I.play_tool_sound(src)
qdel(src)
var/turf/location = get_turf(user)
@@ -109,7 +109,7 @@
new/obj/item/toy/plush/goatplushie/angry/guardgoat(location)
new/obj/item/toy/plush/goatplushie/angry/guardgoat(location)
if(istype(I, /obj/item/reagent_containers/food/snacks/grown/cabbage))
- user.visible_message("[user] watches as [src] takes a bite out of the cabbage! ", "[src]'s fur starts glowing. It seems they have ascended! ")
+ user.visible_message(span_notice("[user] watches as [src] takes a bite out of the cabbage!"), span_notice("[src]'s fur starts glowing. It seems they have ascended!"))
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
qdel(I)
qdel(src)
diff --git a/modular_sand/code/game/objects/items/robot/robot_upgrades.dm b/modular_sand/code/game/objects/items/robot/robot_upgrades.dm
index 5306894298..1dcdf6deff 100644
--- a/modular_sand/code/game/objects/items/robot/robot_upgrades.dm
+++ b/modular_sand/code/game/objects/items/robot/robot_upgrades.dm
@@ -16,7 +16,7 @@
if(!XW)
XW = locate() in R.module
if(XW)
- to_chat(user, "This unit is already equipped with an experimental welding tool module. ")
+ to_chat(user, span_warning("This unit is already equipped with an experimental welding tool module."))
return FALSE
XW = new(R.module)
qdel(WT)
@@ -83,7 +83,7 @@
if(!BD)
BD = locate() in R.module //There's gotta be a smarter way to do this.
if(BD)
- to_chat(user, "This unit is already equipped with a BSRPD module. ")
+ to_chat(user, span_warning("This unit is already equipped with a BSRPD module."))
return FALSE
BD = new(R.module)
@@ -138,11 +138,11 @@
if(.)
if(R.hasExpanded)
- to_chat(usr, "This unit already has an expand module installed! ")
+ to_chat(usr, span_notice("This unit already has an expand module installed!"))
return FALSE
if(R.hasShrunk)
- to_chat(usr, "This unit already has an shrink module installed! ")
+ to_chat(usr, span_notice("This unit already has an shrink module installed!"))
return FALSE
if(ExpandSize <= 0)
@@ -184,11 +184,11 @@
if(.)
if(R.hasShrunk)
- to_chat(usr, "This unit already has an shrink module installed! ")
+ to_chat(usr, span_notice("This unit already has an shrink module installed!"))
return FALSE
if(R.hasExpanded)
- to_chat(usr, "This unit already has an expand module installed! ")
+ to_chat(usr, span_notice("This unit already has an expand module installed!"))
return FALSE
if(ShrinkSize == 0)
@@ -246,7 +246,7 @@
if(!shuttle_maker)
shuttle_maker = locate() in R.module
if(shuttle_maker)
- to_chat(user, "This unit is already equipped with a rapid shuttle designator module. ")
+ to_chat(user, span_warning("This unit is already equipped with a rapid shuttle designator module."))
return FALSE
shuttle_maker = new(R.module)
R.module.basic_modules += shuttle_maker
diff --git a/modular_sand/code/game/objects/items/stacks/tiles/tile_reskinning.dm b/modular_sand/code/game/objects/items/stacks/tiles/tile_reskinning.dm
index 7f240548e6..2feb8f236a 100644
--- a/modular_sand/code/game/objects/items/stacks/tiles/tile_reskinning.dm
+++ b/modular_sand/code/game/objects/items/stacks/tiles/tile_reskinning.dm
@@ -39,4 +39,4 @@ GLOBAL_LIST_EMPTY(tile_reskin_lists)
/obj/item/stack/tile/examine(mob/user)
. = ..()
if(tile_reskin_types)
- . += "These kinds of tiles can be re-skinned! Use it on hand to reskin. "
+ . += span_notice("These kinds of tiles can be re-skinned! Use it on hand to reskin.")
diff --git a/modular_sand/code/game/objects/structures/ghost_role_spawners.dm b/modular_sand/code/game/objects/structures/ghost_role_spawners.dm
index d1c2ab7ce0..89b7c20ef5 100644
--- a/modular_sand/code/game/objects/structures/ghost_role_spawners.dm
+++ b/modular_sand/code/game/objects/structures/ghost_role_spawners.dm
@@ -36,7 +36,7 @@
ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn, TRAIT_EXEMPT_HEALTH_EVENTS, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn, TRAIT_NO_MIDROUND_ANTAG, GHOSTROLE_TRAIT) //The mob can't be made into a random antag, they are still eligible for ghost roles popups.
- to_chat(new_spawn,"Ghosting is free! ")
+ to_chat(new_spawn,span_boldwarning("Ghosting is free!"))
var/datum/action/toggle_dead_chat_mob/D = new(new_spawn)
D.Grant(new_spawn)
var/datum/action/disguise/disguise_action = new(new_spawn)
diff --git a/modular_sand/code/game/objects/structures/tank_holder.dm b/modular_sand/code/game/objects/structures/tank_holder.dm
index 5f88eceed9..b0a720af7f 100644
--- a/modular_sand/code/game/objects/structures/tank_holder.dm
+++ b/modular_sand/code/game/objects/structures/tank_holder.dm
@@ -30,13 +30,13 @@
/obj/structure/tank_holder/examine(mob/user)
. = ..()
- . += "It is held together by some screws . "
+ . += span_notice("It is held together by some screws .")
/obj/structure/tank_holder/attackby(obj/item/W, mob/user, params)
if(user.a_intent == INTENT_HARM)
return ..()
if(!SEND_SIGNAL(W, COMSIG_CONTAINER_TRY_ATTACH, src, user))
- to_chat(user, "[W] does not fit in [src]. ")
+ to_chat(user, span_warning("[W] does not fit in [src]."))
/obj/structure/tank_holder/screwdriver_act(mob/living/user, obj/item/I)
if(..())
@@ -63,7 +63,7 @@
return ..()
if(!Adjacent(user) || issilicon(user))
return ..()
- to_chat(user, "You take [tank] from [src]. ")
+ to_chat(user, span_notice("You take [tank] from [src]."))
add_fingerprint(user)
tank.add_fingerprint(user)
user.put_in_hands(tank)
diff --git a/modular_sand/code/game/turfs/open.dm b/modular_sand/code/game/turfs/open.dm
index 13f7e25990..5e66692c37 100644
--- a/modular_sand/code/game/turfs/open.dm
+++ b/modular_sand/code/game/turfs/open.dm
@@ -7,7 +7,7 @@
/obj/item/wallframe/light_fixture/small/proc/attach_floor(turf/a_floor, mob/user)
playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
user.visible_message("[user.name] attaches [src] to \the [a_floor].",
- "You attach [src] to \the [a_floor]. ",
+ span_notice("You attach [src] to \the [a_floor]."),
"You hear clicking. ")
a_floor.balloon_alert(user, "attached to floor")
var/obj/O = new /obj/structure/light_construct/floor(a_floor, 1, TRUE)
diff --git a/modular_sand/code/game/turfs/simulated/floor/plating.dm b/modular_sand/code/game/turfs/simulated/floor/plating.dm
index 4393ff0180..75235f067a 100644
--- a/modular_sand/code/game/turfs/simulated/floor/plating.dm
+++ b/modular_sand/code/game/turfs/simulated/floor/plating.dm
@@ -4,25 +4,25 @@
/turf/open/floor/plating/examine(mob/user)
. = ..()
if(!(baseturfs == /turf/baseturf_bottom || istype(baseturfs, /turf/open/space)))
- . += "\The [src] cannot be removed from the floor. "
+ . += span_notice("\The [src] cannot be removed from the floor.")
else if(unfastened)
- . += "\The [src] could be welded off the floor. "
- . += "The screws on [src] appear loose. "
+ . += span_notice("\The [src] could be welded off the floor.")
+ . += span_warning("The screws on [src] appear loose.")
else
- . += "The screws on [src] could be loosened with a screwdriver . "
+ . += span_notice("The screws on [src] could be loosened with a screwdriver .")
/turf/open/floor/plating/screwdriver_act(mob/living/user, obj/item/I)
if(type == /turf/open/floor/plating)
if(baseturfs == /turf/baseturf_bottom || istype(baseturfs, /turf/open/space))
- to_chat(user, "You start [unfastened ? "fastening" : "unfastening"] [src]. ")
+ to_chat(user, span_notice("You start [unfastened ? "fastening" : "unfastening"] [src]."))
balloon_alert(user, "[unfastened ? "fastening" : "unfastening"]")
if(!I.use_tool(src, user, 20, volume = 80))
return
- to_chat(user, "You [unfastened ? "fasten" : "unfasten"] [src]. ")
+ to_chat(user, span_notice("You [unfastened ? "fasten" : "unfasten"] [src]."))
balloon_alert(user, "[unfastened ? "fastened" : "unfastened"]")
unfastened = !unfastened
else
- to_chat(user, "You cannot remove this plating. ")
+ to_chat(user, span_warning("You cannot remove this plating."))
balloon_alert(user, "can't remove!")
return
@@ -30,13 +30,13 @@
. = ..()
if(type == /turf/open/floor/plating && unfastened)
if(baseturfs == /turf/baseturf_bottom || istype(baseturfs, /turf/open/space))
- to_chat(user, "You start removing [src], exposing space after you're done! ")
+ to_chat(user, span_warning("You start removing [src], exposing space after you're done!"))
balloon_alert(user, "removing")
if(!I.use_tool(src, user, 50, volume = 160)) //extra loud to let people know something's going down
return
new /obj/item/stack/tile/plasteel(get_turf(src))
ReplaceWithLattice()
- to_chat(user, "You remove [src]. ")
+ to_chat(user, span_notice("You remove [src]."))
balloon_alert(user, "removed")
return
else
diff --git a/modular_sand/code/modules/admin/verbs/randomverbs.dm b/modular_sand/code/modules/admin/verbs/randomverbs.dm
index 5bb62c4415..ac491b22be 100644
--- a/modular_sand/code/modules/admin/verbs/randomverbs.dm
+++ b/modular_sand/code/modules/admin/verbs/randomverbs.dm
@@ -16,5 +16,5 @@
SSshuttle.autoEnd()
SSblackbox.record_feedback("tally", "admin_verb", 1, "End Shift") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] ended the shift.")
- message_admins("[key_name_admin(usr)] ended the shift. ")
+ message_admins(span_adminnotice("[key_name_admin(usr)] ended the shift."))
return
diff --git a/modular_sand/code/modules/arousal/arousal.dm b/modular_sand/code/modules/arousal/arousal.dm
index 6b7df9b07c..f46707e884 100644
--- a/modular_sand/code/modules/arousal/arousal.dm
+++ b/modular_sand/code/modules/arousal/arousal.dm
@@ -32,7 +32,7 @@
if(prob(30 + clamp((70*(rand() + (h_self.sexual_potency + h_partner.sexual_potency)/200)), 0, 70)) && !W.impregnated && !Sp.equipment[GENITAL_EQUIPEMENT_CONDOM] && (Sp.linked_organ.fluid_id == /datum/reagent/consumable/semen))
W.impregnated = TRUE
log_game("Debug: [h_self] has been impregnated by [h_partner]")
- to_chat(src, "You feel your hormones change, and a motherly instinct take over. ")
+ to_chat(src, span_userlove("You feel your hormones change, and a motherly instinct take over."))
var/obj/item/organ/genital/breasts/B = h_self.getorganslot(ORGAN_SLOT_BREASTS)
if(B)
B.fluid_rate *= 2
diff --git a/modular_sand/code/modules/arousal/genitals.dm b/modular_sand/code/modules/arousal/genitals.dm
new file mode 100644
index 0000000000..78eb513a88
--- /dev/null
+++ b/modular_sand/code/modules/arousal/genitals.dm
@@ -0,0 +1,7 @@
+/obj/item/organ/genital
+ /// Controls whenever a genital is always accessible
+ var/always_accessible = FALSE
+
+/// Toggles whether such genital can always be accessed
+/obj/item/organ/genital/proc/toggle_accessibility()
+ always_accessible = !always_accessible
diff --git a/modular_sand/code/modules/client/preferences.dm b/modular_sand/code/modules/client/preferences.dm
index 611f3b41d6..3efa0eefee 100644
--- a/modular_sand/code/modules/client/preferences.dm
+++ b/modular_sand/code/modules/client/preferences.dm
@@ -50,9 +50,9 @@
language -= lang
else if(check_language_maxhit())
if(CONFIG_GET(number/max_languages) == 1)
- to_chat(usr, "You can only have 1 additional language! ")
+ to_chat(usr, span_danger("You can only have 1 additional language!"))
else
- to_chat(usr, "You can only have up to [CONFIG_GET(number/max_languages)] additional languages! ")
+ to_chat(usr, span_danger("You can only have up to [CONFIG_GET(number/max_languages)] additional languages!"))
else
language += lang
diff --git a/modular_sand/code/modules/clothing/gloves/_gloves.dm b/modular_sand/code/modules/clothing/gloves/_gloves.dm
index 65f7de4825..092e25511d 100644
--- a/modular_sand/code/modules/clothing/gloves/_gloves.dm
+++ b/modular_sand/code/modules/clothing/gloves/_gloves.dm
@@ -50,11 +50,11 @@
var/obj/item/clothing/accessory/ring/A = I
if(length(attached_accessories) >= max_accessories)
if(user)
- to_chat(user, "[src] already has [length(attached_accessories)] accessories. ")
+ to_chat(user, span_warning("[src] already has [length(attached_accessories)] accessories."))
return
if(dummy_thick)
if(user)
- to_chat(user, "[src] is too bulky and cannot have accessories attached to it! ")
+ to_chat(user, span_warning("[src] is too bulky and cannot have accessories attached to it!"))
return
else
if(user && !user.temporarilyRemoveItemFromInventory(I))
@@ -63,7 +63,7 @@
return
if(user && notifyAttach)
- to_chat(user, "You attach [I] to [src]. ")
+ to_chat(user, span_notice("You attach [I] to [src]."))
if((flags_inv & HIDEACCESSORY) || (A.flags_inv & HIDEACCESSORY))
return TRUE
@@ -95,9 +95,9 @@
var/obj/item/clothing/accessory/ring/A = attached_accessories[length(attached_accessories)]
A.detach(src, user)
if(user.put_in_hands(A))
- to_chat(user, "You detach [A] from [src]. ")
+ to_chat(user, span_notice("You detach [A] from [src]."))
else
- to_chat(user, "You detach [A] from [src] and it falls on the floor. ")
+ to_chat(user, span_notice("You detach [A] from [src] and it falls on the floor."))
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
diff --git a/modular_sand/code/modules/clothing/gloves/accessories.dm b/modular_sand/code/modules/clothing/gloves/accessories.dm
index 8356e9fd9e..1c3986de1f 100644
--- a/modular_sand/code/modules/clothing/gloves/accessories.dm
+++ b/modular_sand/code/modules/clothing/gloves/accessories.dm
@@ -15,11 +15,11 @@
var/strip_silence = FALSE
/obj/item/clothing/accessory/ring/suicide_act(mob/living/carbon/user)
- user.visible_message("\[user] is putting the [src] in [user.p_their()] mouth! It looks like [user] is trying to choke on the [src]! ")
+ user.visible_message(span_suicide("\[user] is putting the [src] in [user.p_their()] mouth! It looks like [user] is trying to choke on the [src]!"))
return OXYLOSS
/obj/item/clothing/accessory/ring/attack_self(mob/user)
- user.visible_message("\The [user] gets down on one knee, presenting \the [src]. ","You get down on one knee, presenting \the [src]. ")
+ user.visible_message(span_warning("\The [user] gets down on one knee, presenting \the [src]."),span_warning("You get down on one knee, presenting \the [src]."))
/obj/item/clothing/accessory/ring/proc/Touch(atom/A, proximity)
return FALSE // return TRUE to cancel attack_hand()
diff --git a/modular_sand/code/modules/clothing/spacesuits/chronosuit.dm b/modular_sand/code/modules/clothing/spacesuits/chronosuit.dm
index aa4cdcc530..fd6ce75120 100644
--- a/modular_sand/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/modular_sand/code/modules/clothing/spacesuits/chronosuit.dm
@@ -70,8 +70,8 @@
switch(severity)
if(1)
if(activated && user && ishuman(user) && (user.wear_suit == src))
- to_chat(user, "E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD ")
- to_chat(user, "An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace! ")
+ to_chat(user, span_danger("E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD"))
+ to_chat(user, span_userdanger("An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!"))
user.emote("scream")
deactivate(1, 1)
diff --git a/modular_sand/code/modules/clothing/spacesuits/hardsuit.dm b/modular_sand/code/modules/clothing/spacesuits/hardsuit.dm
index a4ce1ae289..63777f7482 100644
--- a/modular_sand/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/modular_sand/code/modules/clothing/spacesuits/hardsuit.dm
@@ -101,7 +101,7 @@
var/mob/living/carbon/human/user = src.loc
playsound(src.loc, 'modular_sand/sound/misc/suitmalf.ogg', 60, 1, 10)
if (ishuman(user) && (user.wear_suit == src))
- to_chat(user, "The motors on your armor cease to function, causing the full weight of the suit to weigh on you all at once! ")
+ to_chat(user, span_danger("The motors on your armor cease to function, causing the full weight of the suit to weigh on you all at once!"))
user.emote("scream")
user.adjustStaminaLoss(stamdamageemp)
user.adjustBruteLoss(brutedamageemp)
@@ -122,3 +122,126 @@
explosion(src.loc,0,0,3,flame_range = 3)
qdel(src)
return
+
+/obj/item/clothing/suit/space/hardsuit/mining
+ unique_reskin = list(
+ "Default" = list(
+ "name" = "mining hardsuit",
+ "desc" = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating for wildlife encounters.",
+ "icon" = 'icons/obj/clothing/suits.dmi',
+ "icon_state" = "hardsuit-mining",
+ "mob_overlay_icon" = null,
+ "anthro_mob_worn_overlay" = null
+ ),
+ "Conscript" = list(
+ "name" = "Conscript suit",
+ "desc" = "..and so he left, with new orders and new questions. ",
+ "icon" = 'modular_sand/icons/mob/clothing/suit.dmi',
+ "icon_state" = "commando-armor",
+ "mob_overlay_icon" = 'modular_sand/icons/mob/clothing/suit.dmi',
+ "anthro_mob_worn_overlay" = 'modular_sand/icons/mob/clothing/suit_digi.dmi'
+ )
+ )
+
+/obj/item/clothing/suit/space/hardsuit/mining/Move(atom/newloc, direct, glide_size_override)
+ . = ..()
+ setDir(SOUTH)
+
+/obj/item/clothing/suit/space/hardsuit/mining/equipped(mob/user, slot)
+ . = ..()
+ switch(current_skin)
+ if("Conscript")
+ if(slot == ITEM_SLOT_OCLOTHING)
+ icon = 'modular_sand/icons/mob/clothing/suit.dmi'
+ else
+ icon = 'modular_sand/icons/obj/clothing/suits.dmi'
+ else
+ return
+
+/obj/item/clothing/suit/space/hardsuit/mining/reskin_obj(mob/M)
+ . = ..()
+ var/datum/component/armor_plate/armor_comp = GetComponent(/datum/component/armor_plate)
+ var/armor_level = 0
+ var/armor_max = 0
+ if(armor_comp)
+ armor_level = armor_comp.amount
+ armor_max = armor_comp.maxamount
+
+ var/obj/item/clothing/head/helmet/space/hardsuit/mining/mining_helmet
+ if(istype(helmet))
+ mining_helmet = helmet
+
+ switch(current_skin)
+ if("Default")
+ if(armor_level != 0)
+ upgrade_icon(amount = armor_level, maxamount = armor_max)
+
+ if(mining_helmet)
+ mining_helmet.name = initial(mining_helmet.name)
+ mining_helmet.desc = initial(mining_helmet.desc)
+ mining_helmet.icon = initial(mining_helmet.icon)
+ mining_helmet.icon_state = initial(mining_helmet.icon_state)
+ if(armor_level != 0)
+ mining_helmet.upgrade_icon(amount = armor_level, maxamount = armor_max)
+ mining_helmet.mob_overlay_icon = initial(mining_helmet.mob_overlay_icon)
+ mining_helmet.anthro_mob_worn_overlay = initial(mining_helmet.anthro_mob_worn_overlay)
+
+ /// Sprited by Dexxiol#3462 :)
+ if("Conscript")
+ if(armor_level != 0)
+ upgrade_icon(amount = armor_level, maxamount = armor_max)
+
+ if(mining_helmet)
+ mining_helmet.name = "Conscript helmet"
+ mining_helmet.desc = "It shines briefly, full of life."
+ mining_helmet.icon = 'modular_sand/icons/mob/clothing/head.dmi'
+ mining_helmet.icon_state = "commando-helmet"
+ if(armor_level != 0)
+ mining_helmet.upgrade_icon(amount = armor_level, maxamount = armor_max)
+ mining_helmet.mob_overlay_icon = 'modular_sand/icons/mob/clothing/head.dmi'
+ mining_helmet.anthro_mob_worn_overlay = 'modular_sand/icons/mob/clothing/head_muzzled.dmi'
+ if(current_equipped_slot != ITEM_SLOT_OCLOTHING)
+ icon = 'modular_sand/icons/obj/clothing/suits.dmi'
+
+/obj/item/clothing/head/helmet/space/hardsuit/mining/update_icon_state()
+ switch(suit.current_skin)
+ if("Conscript")
+ return
+ else
+ . = ..()
+
+/obj/item/clothing/head/helmet/space/hardsuit/mining/upgrade_icon(datum/source, amount, maxamount)
+ switch(suit.current_skin)
+ if("Conscript")
+ hardsuit_type = "-helmet"
+ if(amount)
+ name = "reinforced Conscript helmet"
+ desc = "It glows weakly, signs of uncertainty."
+ hardsuit_type = "2-helmet"
+ if(amount == maxamount)
+ desc = "It glows violently, martyr to chaos."
+ hardsuit_type = "3-helmet"
+ icon_state = "commando[hardsuit_type]"
+ if(ishuman(loc))
+ var/mob/living/carbon/human/wearer = loc
+ if(wearer.head == src)
+ wearer.update_inv_head()
+ else
+ . = ..()
+
+/obj/item/clothing/suit/space/hardsuit/mining/upgrade_icon(datum/source, amount, maxamount)
+ switch(current_skin)
+ if("Conscript")
+ hardsuit_type = "-armor"
+ if(amount)
+ name = "reinforced Conscript suit"
+ hardsuit_type = "2-armor"
+ if(amount == maxamount)
+ hardsuit_type = "3-armor"
+ icon_state = "commando[hardsuit_type]"
+ if(ishuman(loc))
+ var/mob/living/carbon/human/wearer = loc
+ if(wearer.wear_suit == src)
+ wearer.update_inv_wear_suit()
+ else
+ . = ..()
diff --git a/modular_sand/code/modules/clothing/under/_under.dm b/modular_sand/code/modules/clothing/under/_under.dm
new file mode 100644
index 0000000000..fe6dcc8fba
--- /dev/null
+++ b/modular_sand/code/modules/clothing/under/_under.dm
@@ -0,0 +1,8 @@
+GLOBAL_LIST_INIT(skirt_peekable, list(
+ /obj/item/clothing/under/rank/civilian/janitor/maid = TRUE /* This one hangs about because no skirt in path */
+ ))
+
+/obj/item/clothing/under/Initialize(mapload)
+ . = ..()
+ if(!is_type_in_typecache(type, GLOB.skirt_peekable) && findlasttext("[type]", "skirt"))
+ LAZYSET(GLOB.skirt_peekable, type, TRUE)
diff --git a/modular_sand/code/modules/clothing/under/jobs/cargo.dm b/modular_sand/code/modules/clothing/under/jobs/cargo.dm
deleted file mode 100644
index e0ad328399..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/cargo.dm
+++ /dev/null
@@ -1,5 +0,0 @@
-/obj/item/clothing/under/rank/cargo/qm/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/cargo/tech/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/civilian.dm b/modular_sand/code/modules/clothing/under/jobs/civilian.dm
deleted file mode 100644
index 12917d8a2f..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/civilian.dm
+++ /dev/null
@@ -1,47 +0,0 @@
-/obj/item/clothing/under/rank/civilian/bartender/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/chaplain/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/chef/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/head_of_personnel/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/head_of_personnel/suit/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/hydroponics/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/janitor/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/janitor/maid //i believe this one is a dress, not gonna check
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/black/alt/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/really_black/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/black/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/female/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/red/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/blue/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/bluesuit/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/civilian/lawyer/purpsuit/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/command.dm b/modular_sand/code/modules/clothing/under/jobs/command.dm
deleted file mode 100644
index cff9bd3339..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/command.dm
+++ /dev/null
@@ -1,5 +0,0 @@
-/obj/item/clothing/under/rank/captain/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/captain/suit/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/curator.dm b/modular_sand/code/modules/clothing/under/jobs/curator.dm
deleted file mode 100644
index 85966ab452..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/curator.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/obj/item/clothing/under/rank/civilian/curator/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/engineering.dm b/modular_sand/code/modules/clothing/under/jobs/engineering.dm
deleted file mode 100644
index 56e4263ae7..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/engineering.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/obj/item/clothing/under/rank/engineering/chief_engineer/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/engineering/atmospheric_technician/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/engineering/engineer/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/medical.dm b/modular_sand/code/modules/clothing/under/jobs/medical.dm
deleted file mode 100644
index 03c124449c..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/medical.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-/obj/item/clothing/under/rank/medical/chief_medical_officer/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/medical/geneticist/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/medical/virologist/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/medical/chemist/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/medical/paramedic/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/medical/doctor/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/research.dm b/modular_sand/code/modules/clothing/under/jobs/research.dm
deleted file mode 100644
index 1243dfb9ee..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/research.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/obj/item/clothing/under/rank/rnd/research_director/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/rnd/research_director/alt/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/rnd/research_director/turtleneck/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/rnd/scientist/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/rnd/roboticist/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/security.dm b/modular_sand/code/modules/clothing/under/jobs/security.dm
deleted file mode 100644
index ee8331c5b6..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/security.dm
+++ /dev/null
@@ -1,29 +0,0 @@
-/obj/item/clothing/under/rank/security/officer/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/security/warden/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/security/detective/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/security/detective/grey/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/security/head_of_security/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/security/head_of_security/alt/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/brigdoc/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/blueshield/formal/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/blueshield/skirt
- is_skirt = TRUE
-
-/obj/item/clothing/under/rank/bridgeofficer/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/clothing/under/jobs/theater.dm b/modular_sand/code/modules/clothing/under/jobs/theater.dm
deleted file mode 100644
index 1de3d44407..0000000000
--- a/modular_sand/code/modules/clothing/under/jobs/theater.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/obj/item/clothing/under/rank/civilian/mime/skirt
- is_skirt = TRUE
diff --git a/modular_sand/code/modules/hydroponics/hydroponics.dm b/modular_sand/code/modules/hydroponics/hydroponics.dm
index fbe22b96ea..e383980184 100644
--- a/modular_sand/code/modules/hydroponics/hydroponics.dm
+++ b/modular_sand/code/modules/hydroponics/hydroponics.dm
@@ -1,7 +1,7 @@
/obj/machinery/hydroponics/proc/harvest_dead(mob/user)
dead = FALSE
if(user)
- to_chat(user, "You remove the dead plant from [src]. ")
+ to_chat(user, span_notice("You remove the dead plant from [src]."))
qdel(myseed)
myseed = null
update_icon()
diff --git a/modular_sand/code/modules/integrated_electronics/subtypes/output.dm b/modular_sand/code/modules/integrated_electronics/subtypes/output.dm
index 45e991aad7..1c16cb3445 100644
--- a/modular_sand/code/modules/integrated_electronics/subtypes/output.dm
+++ b/modular_sand/code/modules/integrated_electronics/subtypes/output.dm
@@ -51,7 +51,7 @@
user.transferItemToLoc(O,src)
encryption_keys += O
recalculate_channels()
- to_chat(user, "You slide \the [O] inside the circuit. ")
+ to_chat(user, span_notice("You slide \the [O] inside the circuit."))
else
..()
@@ -75,10 +75,10 @@
O.forceMove(drop_location())
encryption_keys.Cut()
set_pin_data(IC_OUTPUT, 1, WEAKREF(null))
- to_chat(user, "You slide the encryption keys out of the circuit. ")
+ to_chat(user, span_notice("You slide the encryption keys out of the circuit."))
recalculate_channels()
else
- to_chat(user, "There are no encryption keys to remove from the mechanism. ")
+ to_chat(user, span_notice("There are no encryption keys to remove from the mechanism."))
/obj/item/radio/headset/integrated
diff --git a/modular_sand/code/modules/mining/equipment/kinetic_crusher.dm b/modular_sand/code/modules/mining/equipment/kinetic_crusher.dm
index a4e6e39a66..7cedccf6ff 100644
--- a/modular_sand/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/modular_sand/code/modules/mining/equipment/kinetic_crusher.dm
@@ -30,7 +30,7 @@
L.loot = null
L.crusher_loot = null
L.faction = user.faction.Copy()
- user.visible_message("[user] revives [target] with [src], as a friendly fauna ")
+ user.visible_message(span_notice("[user] revives [target] with [src], as a friendly fauna"))
playsound(src,'sound/effects/supermatter.ogg',50,1)
/obj/item/crusher_trophy/golden_skull/on_melee_hit(mob/living/target, mob/living/user)
@@ -53,10 +53,10 @@
L.attack_same = 0
L.loot = null
L.crusher_loot = null
- user.visible_message("[user] revives [target] with [src], as a friendly legion. ")
+ user.visible_message(span_notice("[user] revives [target] with [src], as a friendly legion."))
playsound(src,'sound/effects/supermatter.ogg',50,1)
else
- (to_chat(user, "You cancel turning [target] into a legion. "))
+ (to_chat(user, span_notice("You cancel turning [target] into a legion.")))
//rogue process
/obj/item/crusher_trophy/brokentech
@@ -344,22 +344,22 @@
/obj/item/melee/zweihander/examine(mob/living/user)
. = ..()
- . += "Mark a large creature with the destabilizing force, then hit them in melee to do [force + detonation_damage] damage. "
- . += "Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage] . "
+ . += span_notice("Mark a large creature with the destabilizing force, then hit them in melee to do [force + detonation_damage] damage.")
+ . += span_notice("Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage] .")
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
- . += "It has \a [T] attached, which causes [T.effect_desc()]. "
+ . += span_notice("It has \a [T] attached, which causes [T.effect_desc()].")
/obj/item/melee/zweihander/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
if(LAZYLEN(trophies))
- to_chat(user, "You remove [src]'s trophies. ")
+ to_chat(user, span_notice("You remove [src]'s trophies."))
I.play_tool_sound(src)
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
T.remove_from(src, user)
else
- to_chat(user, "There are no trophies on [src]. ")
+ to_chat(user, span_warning("There are no trophies on [src]."))
else if(istype(I, /obj/item/crusher_trophy))
var/obj/item/crusher_trophy/T = I
T.add_to(src, user)
diff --git a/modular_sand/code/modules/mining/equipment/regenerative_core.dm b/modular_sand/code/modules/mining/equipment/regenerative_core.dm
index 4d508dd6c1..b9fc7acfd3 100644
--- a/modular_sand/code/modules/mining/equipment/regenerative_core.dm
+++ b/modular_sand/code/modules/mining/equipment/regenerative_core.dm
@@ -12,16 +12,16 @@
return
var/mob/living/carbon/human/H = target
if(inert)
- to_chat(user, "[src] has decayed and can no longer be used to heal. ")
+ to_chat(user, span_notice("[src] has decayed and can no longer be used to heal."))
return
if(H.stat == DEAD)
- to_chat(user, "[src] are useless on the dead. ")
+ to_chat(user, span_notice("[src] are useless on the dead."))
return
if(H != user)
H.visible_message("[user] forces [H] to apply [src]... Black tendrils entangle and reinforce [H.p_them()]!")
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "other"))
else
- to_chat(user, "You start to smear [src] on yourself. Disgusting tendrils hold you together and allow you to keep moving, but for how long? ")
+ to_chat(user, span_notice("You start to smear [src] on yourself. Disgusting tendrils hold you together and allow you to keep moving, but for how long?"))
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self"))
if(is_station_level(H.z))
H.adjustBruteLoss(-25, 0)
diff --git a/modular_sand/code/modules/mining/lavaland/necropolis_chests.dm b/modular_sand/code/modules/mining/lavaland/necropolis_chests.dm
index aaca5e7faa..09d5b00d97 100644
--- a/modular_sand/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/modular_sand/code/modules/mining/lavaland/necropolis_chests.dm
@@ -156,7 +156,7 @@
/obj/item/projectile/heckhook/on_hit(atom/target)
. = ..()
var/atom/A = target
- A.visible_message("[A] is snagged by [firer]'s hook! ")
+ A.visible_message(span_danger("[A] is snagged by [firer]'s hook!"))
new /datum/forced_movement(firer, get_turf(A), 1, TRUE)
/obj/item/projectile/heckhook/Destroy()
@@ -184,7 +184,7 @@
to_chat(user, "You will now fire normal shotgun rounds.")
/obj/item/gun/ballistic/revolver/doublebarrel/super/sawoff(mob/user)
- to_chat(user, "Why would you mutilate this work of art? ")
+ to_chat(user, span_warning("Why would you mutilate this work of art?"))
return
/obj/item/gun/ballistic/revolver/doublebarrel/super/upgraded
@@ -235,7 +235,7 @@
/obj/item/crucible/suicide_act(mob/living/carbon/user)
if(wielded)
- user.visible_message("[user] DOOMs themselves with the [src]! ")
+ user.visible_message(span_suicide("[user] DOOMs themselves with the [src]!"))
var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)//stole from chainsaw code
var/obj/item/organ/brain/B = user.getorganslot(ORGAN_SLOT_BRAIN)
@@ -250,12 +250,12 @@
myhead.drop_limb()
sleep(3)
else
- user.visible_message("[user] panics and starts choking to death! ")
+ user.visible_message(span_suicide("[user] panics and starts choking to death!"))
return OXYLOSS
else
- user.visible_message("[user] begins beating [user.p_them()]self to death with \the [src]'s handle! It probably would've been cooler if [user.p_they()] turned it on first! ")
+ user.visible_message(span_suicide("[user] begins beating [user.p_them()]self to death with \the [src]'s handle! It probably would've been cooler if [user.p_they()] turned it on first!"))
return BRUTELOSS
/obj/item/crucible/update_icon_state()
@@ -336,7 +336,7 @@
var/mob/living/carbon/C = user
if(C.wear_mask)
in_mouth = ", barely missing [user.p_their()] nose"
- . = "[user] swings [user.p_their()] [name][in_mouth]. [user.p_they(TRUE)] light[user.p_s()] [user.p_their()] [A.name] in the process. "
+ . = span_warning("[user] swings [user.p_their()] [name][in_mouth]. [user.p_they(TRUE)] light[user.p_s()] [user.p_their()] [A.name] in the process.")
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
add_fingerprint(user)
@@ -437,12 +437,12 @@
sharpness = SHARP_NONE
if(ghost_counter >= 4)
sharpness = SHARP_POINTY
- user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits! ")
+ user.visible_message(span_danger("[user] strikes with the force of [ghost_counter] vengeful spirits!"))
/obj/item/melee/ghost_sword/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
var/ghost_counter = ghost_check()
final_block_chance = clamp((ghost_counter * 5), 10, 50)
- owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts! ")
+ owner.visible_message(span_danger("[owner] is protected by a ring of [ghost_counter] ghosts!"))
return ..()
/obj/item/clothing/neck/necklace/memento_mori/king
@@ -503,7 +503,7 @@
var/choosey = choices[choice]
var/obj/machinery/anomalous_crystal/A = new choosey(user.loc)
A.activation_method = method
- to_chat(user, "[A] appears under your feet as the [src] breaks apart! ")
+ to_chat(user, span_userdanger("[A] appears under your feet as the [src] breaks apart!"))
qdel(src)
//normal chests
@@ -744,7 +744,7 @@
/obj/item/stock_parts/cell/high/plus/argent/attack_self(mob/user)
..()
- user.visible_message("[user] crushes the [src] in his hands, absorbing it's energy! ")
+ user.visible_message(span_danger("[user] crushes the [src] in his hands, absorbing it's energy!"))
playsound(user.loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, TRUE)
var/mob/living/M = user
M.apply_status_effect(onuse)
@@ -822,13 +822,13 @@
/obj/item/clothing/mask/gas/dagoth/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/ashstorm))
if(storm_cooldown > world.time)
- to_chat(user, "The [src] is still recharging! ")
+ to_chat(user, span_warning("The [src] is still recharging!"))
return
var/area/user_area = get_base_area(user)
var/turf/user_turf = get_turf(user)
if(!user_area || !user_turf || (user_area.type in excluded_areas))
- to_chat(user, "Something is preventing you from using the [src] here. ")
+ to_chat(user, span_warning("Something is preventing you from using the [src] here."))
return
var/datum/weather/A
for(var/V in SSweather.processing)
@@ -840,10 +840,10 @@
if(A)
if(A.stage != END_STAGE)
if(A.stage == WIND_DOWN_STAGE)
- to_chat(user, "The storm is already ending! It would be a waste to use the [src] now. ")
+ to_chat(user, span_warning("The storm is already ending! It would be a waste to use the [src] now."))
return
- user.visible_message("[user] gazes into the sky with [src], seemingly repelling the current storm! ", \
- "You gaze intently skyward, dispelling the storm! ")
+ user.visible_message(span_warning("[user] gazes into the sky with [src], seemingly repelling the current storm!"), \
+ span_notice("You gaze intently skyward, dispelling the storm!"))
playsound(user, 'sound/magic/staff_change.ogg', 200, 0)
A.wind_down()
log_game("[user] ([key_name(user)]) has dispelled a storm at [AREACOORD(user_turf)]")
@@ -858,8 +858,8 @@
A.telegraph_duration = 100
A.end_duration = 100
- user.visible_message("[user] gazes skyward with his [src], terrible red lightning strikes seem to accompany them! ", \
- "You gaze skyward with [src], calling down a terrible storm! ")
+ user.visible_message(span_warning("[user] gazes skyward with his [src], terrible red lightning strikes seem to accompany them!"), \
+ span_notice("You gaze skyward with [src], calling down a terrible storm!"))
playsound(user, 'sound/magic/staff_change.ogg', 200, 0)
A.telegraph()
storm_cooldown = world.time + 200
@@ -973,9 +973,9 @@
//Apply a temp buff until the necklace is used
/obj/item/clothing/neck/necklace/necklace_of_the_forsaken/proc/temp_buff(mob/living/carbon/human/user)
- to_chat(user, "You feel as if you have a second chance at something, but you're not sure what. ")
+ to_chat(user, span_warning("You feel as if you have a second chance at something, but you're not sure what."))
if(do_after(user, 40, target = user))
- to_chat(user, "The ember warms you... ")
+ to_chat(user, span_notice("The ember warms you..."))
ADD_TRAIT(user, TRAIT_NOHARDCRIT, "necklace_of_the_forsaken")//less chance of being gibbed
active_owner = user
@@ -986,7 +986,7 @@
return
var/mob/living/carbon/C = active_owner
active_owner = null
- to_chat(C, "You feel a scorching burn fill your body and limbs! ")
+ to_chat(C, span_userdanger("You feel a scorching burn fill your body and limbs!"))
C.revive(TRUE, FALSE)
remove_necklace() //remove buffs
@@ -1013,7 +1013,7 @@
if(iscarbon(owner))
MM.temp_buff(owner)
src.desc = "Revive or fully heal yourself, but you can only do this once! Can be used when knocked out or dead."
- to_chat(MM.active_owner, "You have binded the ember to yourself! The next time you use the necklace it will heal you! ")
+ to_chat(MM.active_owner, span_userdanger("You have binded the ember to yourself! The next time you use the necklace it will heal you!"))
else if(MM.numUses >= 1 && MM.active_owner)//revive / heal then remove usage
MM.second_chance()
MM.numUses = 0
diff --git a/modular_sand/code/modules/mining/machine_bluespaceminer.dm b/modular_sand/code/modules/mining/machine_bluespaceminer.dm
index 0d62ee9267..9241f8745e 100644
--- a/modular_sand/code/modules/mining/machine_bluespaceminer.dm
+++ b/modular_sand/code/modules/mining/machine_bluespaceminer.dm
@@ -7,6 +7,7 @@
can_be_unanchored = TRUE
circuit = /obj/item/circuitboard/machine/bluespace_miner
layer = BELOW_OBJ_LAYER
+ init_process = TRUE
var/list/ore_rates = list(/datum/material/iron = 0.3, /datum/material/glass = 0.3, /datum/material/plasma = 0.1, /datum/material/silver = 0.1, /datum/material/gold = 0.05, /datum/material/titanium = 0.05, /datum/material/uranium = 0.05, /datum/material/diamond = 0.02)
var/datum/component/remote_materials/materials
var/multiplier = 0 //Multiplier by tier, has been made fair and everything
@@ -18,15 +19,15 @@
/obj/machinery/mineral/bluespace_miner/examine(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
- . += "A small screen on the machine reads, \"Efficiency at [multiplier * 100]%\" "
+ . += span_notice("A small screen on the machine reads, \"Efficiency at [multiplier * 100]%\"")
if(multiplier >= 5)
- . += "Bluespace generation is active. "
+ . += span_notice("Bluespace generation is active.")
if(!anchored)
- . += "The machine won't work while not firmly secured to the ground. "
+ . += span_warning("The machine won't work while not firmly secured to the ground.")
if(!materials?.silo)
- . += "No ore silo connected. Use a multi-tool to link an ore silo to this machine. "
+ . += span_notice("No ore silo connected. Use a multi-tool to link an ore silo to this machine.")
else if(materials?.on_hold())
- . += "Ore silo access is on hold, please contact the quartermaster. "
+ . += span_warning("Ore silo access is on hold, please contact the quartermaster.")
/obj/machinery/mineral/bluespace_miner/RefreshParts()
multiplier = 0
@@ -49,7 +50,7 @@
/obj/machinery/mineral/bluespace_miner/multitool_act(mob/living/user, obj/item/M)
. = ..()
if(!M.buffer || !istype(M.buffer, /obj/machinery/ore_silo))
- to_chat(user, "You need to multitool the ore silo first. ")
+ to_chat(user, span_warning("You need to multitool the ore silo first."))
balloon_alert(user, "invalid buffer!")
return TRUE
diff --git a/modular_sand/code/modules/mob/living/carbon/human/examine.dm b/modular_sand/code/modules/mob/living/carbon/human/examine.dm
index 421de3dd8f..b42e1cd222 100644
--- a/modular_sand/code/modules/mob/living/carbon/human/examine.dm
+++ b/modular_sand/code/modules/mob/living/carbon/human/examine.dm
@@ -1,23 +1,30 @@
-#define PAIRLESS_PANTIES list(\
- /obj/item/clothing/underwear/briefs/jockstrap,\
- /obj/item/clothing/underwear/briefs/panties/thong,\
- /obj/item/clothing/underwear/briefs/panties/thong/babydoll,\
- /obj/item/clothing/underwear/briefs/mankini\
-)
+GLOBAL_LIST_INIT(pairless_panties, list(
+ /obj/item/clothing/underwear/briefs/jockstrap = TRUE,
+ /obj/item/clothing/underwear/briefs/panties/thong = TRUE,
+ /obj/item/clothing/underwear/briefs/panties/thong/babydoll = TRUE,
+ /obj/item/clothing/underwear/briefs/mankini = TRUE
+))
/mob/living/carbon/human/examine(mob/user)
. = ..()
- if(!isliving(user))
- return
-
var/mob/living/living = user
- var/obj/item/clothing/under/worn_uniform = w_uniform
- if((user != src) && !(living.mobility_flags & MOBILITY_STAND) && (mobility_flags & MOBILITY_STAND) && (src.loc == living.loc) && (istype(worn_uniform))) //SPLURT edit
- var/string = "Peeking under [src]'s [w_uniform], you can see "
- var/obj/item/clothing/underwear/worn_underwear = src.w_underwear
+ var/obj/item/clothing/under/worn_uniform = get_item_by_slot(ITEM_SLOT_ICLOTHING)
+ if(worn_uniform && is_type_in_typecache(worn_uniform.type, GLOB.skirt_peekable) && (isobserver(user) || (isliving(user) && (user != src) && !(living.mobility_flags & MOBILITY_STAND) && (mobility_flags & MOBILITY_STAND) && (loc == living.loc) && (istype(worn_uniform)))))
+ . += span_purple("[p_theyre(TRUE)] wearing a [worn_uniform.name]! I can probably give it a little peek looking closer .")
+
+/mob/living/carbon/human/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_PARENT_EXAMINE_MORE, .proc/peek_skirt)
+
+/mob/living/carbon/human/proc/peek_skirt(mob/examined, mob/examiner, list/examine_content)
+ var/mob/living/living = examiner
+ var/obj/item/clothing/under/worn_uniform = get_item_by_slot(ITEM_SLOT_ICLOTHING)
+ if(worn_uniform && is_type_in_typecache(worn_uniform.type, GLOB.skirt_peekable) && (isobserver(examiner) || (isliving(examiner) && (examiner != src) && !(living.mobility_flags & MOBILITY_STAND) && (mobility_flags & MOBILITY_STAND) && (loc == living.loc) && (istype(worn_uniform)))))
+ var/string = "Peeking under [src]'s [worn_uniform.name], you can see "
+ var/obj/item/clothing/underwear/worn_underwear = get_item_by_slot(ITEM_SLOT_UNDERWEAR)
if(worn_underwear)
string += "a "
- if(!(worn_underwear.type in PAIRLESS_PANTIES)) //a pair of thong
+ if(!is_type_in_typecache(worn_underwear.type, GLOB.pairless_panties)) //a pair of thong
string += "pair of "
if(worn_underwear.color)
string += "[worn_underwear.name] ."
@@ -27,12 +34,12 @@
var/obj/item/organ/genital/penis/penis = getorganslot(ORGAN_SLOT_PENIS)
var/obj/item/organ/genital/vagina/vagina = getorganslot(ORGAN_SLOT_VAGINA)
if(penis?.aroused_state)
- string += span_love(" There's a visible bulge on it's front.")
+ string += span_love(" There's a visible bulge on [p_their()] front.")
else if(vagina?.aroused_state)
- string += span_love(" They're wet with arousal.")
+ string += span_love(" [p_theyre(TRUE)] wet with arousal.")
else
- string += "[p_theyre()] not wearing anything! - [p_their()] "
+ string += "[p_theyre()] not wearing anything!\n[p_their(TRUE)]"
var/list/genitals = list()
for(var/obj/item/organ/genital/genital in internal_organs)
if(genital.genital_flags & (GENITAL_INTERNAL|GENITAL_HIDDEN))
@@ -42,29 +49,29 @@
switch(genital.type)
if(/obj/item/organ/genital/vagina)
if(genital.aroused_state)
- appended += "wet "
+ appended += " wet"
if(lowertext(genital.shape) != "human")
- appended += lowertext(genital.shape)
- if(lowertext(genital.shape) != "cloaca") //their wet cloaca pussy
- appended += " pussy"
+ appended += " [lowertext(genital.shape)]"
+ if(lowertext(genital.shape) != "cloaca") //their wet cloaca vagina
+ appended += " [lowertext(genital.name)]" // goodbye pussy
if(/obj/item/organ/genital/testicles)
- appended += "nuts"
+ var/obj/item/organ/genital/testicles/nuts = genital
+ appended += " [lowertext(nuts.size_name)] [lowertext(nuts.name)]"
if(/obj/item/organ/genital/penis)
if(genital.aroused_state)
- appended += "fully erect"
+ appended += " fully erect"
if(lowertext(genital.shape) != "human")
- appended += ", [lowertext(genital.shape)]"
- if(appended)
- appended += " " //double spaces
- appended += "penis"
+ appended += " [lowertext(genital.shape)]"
+ appended += " [lowertext(genital.name)]" // Name it something funny, i dare you.
+ if(/obj/item/organ/genital/butt)
+ var/obj/item/organ/genital/butt/booty = genital
+ appended += " [booty.size_name] [lowertext(booty.name)]" // Maybe " average butt pair" isn't the best for now
else
continue
genitals += appended
- string += english_list(genitals, "featureless groin")
+ string += english_list(genitals, " featureless groin", " and", ",")
string += " on full display."
- . += span_purple(string)
-
-#undef PAIRLESS_PANTIES
+ examine_content += span_purple(string)
diff --git a/modular_sand/code/modules/mob/living/carbon/show.dm b/modular_sand/code/modules/mob/living/carbon/show.dm
index edd752ed8a..7e96c07c77 100644
--- a/modular_sand/code/modules/mob/living/carbon/show.dm
+++ b/modular_sand/code/modules/mob/living/carbon/show.dm
@@ -15,6 +15,6 @@
if(!I && arm)
usr.show_message("[usr] holds up [arm].", 1)
else if(!arm && !I)
- to_chat(usr, "You frown because now there's nothing you can show. ")
+ to_chat(usr, span_notice("You frown because now there's nothing you can show."))
else if(!HAS_TRAIT(I, ABSTRACT_ITEM_TRAIT))
I.showoff(src)
diff --git a/modular_sand/code/modules/mob/living/silicon/silicon.dm b/modular_sand/code/modules/mob/living/silicon/silicon.dm
index 6109a0c8fc..af295e91c1 100644
--- a/modular_sand/code/modules/mob/living/silicon/silicon.dm
+++ b/modular_sand/code/modules/mob/living/silicon/silicon.dm
@@ -10,6 +10,6 @@
set desc = "Allows you to eat someone."
if(!CHECK_BITFIELD(T.vore_flags, DEVOURABLE))
- to_chat(src, "System error: Unauthorized operation. ")
+ to_chat(src, span_warning("System error: Unauthorized operation."))
return
return feed_grabbed_to_self(src,T)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm b/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm
index 0822ec540e..5250ceaffc 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/bot/hugbot.dm
@@ -145,7 +145,7 @@
/mob/living/simple_animal/bot/hugbot/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
- H.visible_message("[H] begins tipping over [src]. ", "You begin tipping over [src]... ")
+ H.visible_message(span_danger("[H] begins tipping over [src]."), span_warning("You begin tipping over [src]..."))
balloon_alert(H, "tipping over")
if(world.time > last_tipping_action_voice + 15 SECONDS)
@@ -159,7 +159,7 @@
tip_over(H)
else if(H.a_intent == INTENT_HELP && mode == BOT_TIPPED)
- H.visible_message("[H] begins righting [src]. ", "You begin righting [src]... ")
+ H.visible_message(span_notice("[H] begins righting [src]."), span_notice("You begin righting [src]..."))
balloon_alert(H, "righting")
if(do_after(H, 3 SECONDS, target=src))
set_right(H)
@@ -170,8 +170,8 @@
..()
if(emagged == 2)
if(user)
- to_chat(user, "You short out [src]'s manipulator pressure sensors. ")
- visible_message("[src]'s arm twitches violently! ")
+ to_chat(user, span_notice("You short out [src]'s manipulator pressure sensors."))
+ visible_message(span_danger("[src]'s arm twitches violently!"))
flick("medibot_spark", src)
playsound(src, "sparks", 75, 1)
@@ -347,9 +347,9 @@
// Hey, didyah know that you Han't hug people as non-carbon? Well you can't hug people as non-carbon. Hence this mess
if(zone_selected == BODY_ZONE_PRECISE_MOUTH)
visible_message( \
- "[src] boops [H]'s nose. ", \
- "You boop [H] on the nose. ", target = H,
- target_message = "[src] boops your nose. ")
+ span_notice("[src] boops [H]'s nose."), \
+ span_notice("You boop [H] on the nose."), target = H,
+ target_message = span_notice("[src] boops your nose."))
playsound(H, 'sound/items/Nose_boop.ogg', 50, 0)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
else if(check_zone(zone_selected) == BODY_ZONE_HEAD)
@@ -357,9 +357,9 @@
if(ishuman(H))
S = H.dna.species
- visible_message("[src] gives [H] a pat on the head to make [H.p_them()] feel better! ", \
- "You give [src] a pat on the head to make [H.p_them()] feel better! ", target = H,
- target_message = "[src] gives you a pat on the head to make you feel better! ")
+ visible_message(span_notice("[src] gives [H] a pat on the head to make [H.p_them()] feel better!"), \
+ span_notice("You give [src] a pat on the head to make [H.p_them()] feel better!"), target = H,
+ target_message = span_notice("[src] gives you a pat on the head to make you feel better!"))
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
if(S?.can_wag_tail(src) && !H.dna.species.is_wagging_tail())
var/static/list/many_tails = list("tail_human", "tail_lizard", "mam_tail")
@@ -368,9 +368,9 @@
H.emote("wag")
break
else
- visible_message("[src] hugs [H] to make [H.p_them()] feel better! ", \
- "You hug [H] to make [H.p_them()] feel better! ", target = H,\
- target_message = "[src] hugs you to make you feel better! ")
+ visible_message(span_notice("[src] hugs [H] to make [H.p_them()] feel better!"), \
+ span_notice("You hug [H] to make [H.p_them()] feel better!"), target = H,\
+ target_message = span_notice("[src] hugs you to make you feel better!"))
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
playsound(H.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
@@ -390,7 +390,7 @@
/mob/living/simple_animal/bot/hugbot/explode()
on = FALSE
- visible_message("[src] blows apart! ")
+ visible_message(span_boldannounce("[src] blows apart!"))
do_sparks(3, TRUE, src)
var/atom/Tsec = drop_location()
drop_part(/obj/item/storage/box/hug, Tsec)
@@ -416,19 +416,19 @@
var/mob/living/simple_animal/bot/hugbot/A = new(drop_location())
A.name = created_name
A.robot_arm = W.type
- to_chat(user, "You add [W] to [src]. Beep boop! ")
+ to_chat(user, span_notice("You add [W] to [src]. Beep boop!"))
qdel(W)
qdel(src)
/obj/item/storage/box/hug/attackby(obj/item/I, mob/user, params)
if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
if(contents.len) //prevent accidently deleting contents
- to_chat(user, "You need to empty [src] out first! ")
+ to_chat(user, span_warning("You need to empty [src] out first!"))
return
if(!user.temporarilyRemoveItemFromInventory(I))
return
qdel(I)
- to_chat(user, "You add [I] to the [src]! You've got a hugbot assembly now! ")
+ to_chat(user, span_notice("You add [I] to the [src]! You've got a hugbot assembly now!"))
var/obj/item/bot_assembly/hugbot/A = new
qdel(src)
user.put_in_hands(A)
@@ -438,7 +438,7 @@
// Skyrat exclusive: Tipping over hugbots. Because fuck medbots.
/mob/living/simple_animal/bot/hugbot/proc/tip_over(mob/user)
mobility_flags &= ~MOBILITY_MOVE
- user.visible_message("[user] tips over [src]! ", "You tip [src] over! ")
+ user.visible_message(span_danger("[user] tips over [src]!"), span_danger("You tip [src] over!"))
balloon_alert(user, "tipped over")
mode = BOT_TIPPED
tipper_name = user.name // Skyrat fix
@@ -449,14 +449,14 @@
mobility_flags &= MOBILITY_MOVE
var/list/messagevoice
if(user)
- user.visible_message("[user] sets [src] right-side up! ", "You set [src] right-side up! ")
+ user.visible_message(span_notice("[user] sets [src] right-side up!"), span_green("You set [src] right-side up!"))
balloon_alert(user, "set right")
if(user.name == tipper_name)
messagevoice = list("I forgive you." = 'sound/voice/medbot/forgive.ogg')
else
messagevoice = list("Thank you!" = 'sound/voice/medbot/thank_you.ogg', "You are a good person." = 'sound/voice/medbot/youre_good.ogg')
else
- visible_message("[src] manages to writhe wiggle enough to right itself. ")
+ visible_message(span_notice("[src] manages to writhe wiggle enough to right itself."))
messagevoice = list("Fuck you." = 'sound/voice/medbot/fuck_you.ogg', "Your behavior has been reported, have a nice day." = 'sound/voice/medbot/reported.ogg')
tipper_name = null
diff --git a/modular_sand/code/modules/mob/living/simple_animal/friendly/doges.dm b/modular_sand/code/modules/mob/living/simple_animal/friendly/doges.dm
index ef6991e2d5..fa3b49613a 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/friendly/doges.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/friendly/doges.dm
@@ -22,7 +22,7 @@
. = ..()
if(.)
for(var/obj/item/reagent_containers/food/snacks/burger/burbger in view(1, src))
- visible_message("\The [src] consumes the [burbger]! ")
+ visible_message(span_danger("\The [src] consumes the [burbger]!"))
qdel(burbger)
revive(full_heal = 1)
@@ -33,7 +33,7 @@
qdel(I)
if(stat == DEAD)
visible_message("\The [src] stands right back up after nibbling the [I]!")
- else
+ else
visible_message("\The [src] swallows the [I] whole!")
revive(full_heal = 1)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/gladiator.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/gladiator.dm
index 9fd110873a..db5c805d2a 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/gladiator.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/gladiator.dm
@@ -187,11 +187,11 @@ They deal 35 brute (armor is considered).
if(isliving(A))
var/mob/living/LM = A
forceMove(LM.loc)
- visible_message("[src] knocks [LM] down! ")
+ visible_message(span_userdanger("[src] knocks [LM] down!"))
LM.DefaultCombatKnockdown(60)
discharge()
else if(istype(A, /turf/closed))
- visible_message("[src] crashes headfirst into [A]! ")
+ visible_message(span_userdanger("[src] crashes headfirst into [A]!"))
discharge(1.33)
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/update_phase()
@@ -223,7 +223,7 @@ They deal 35 brute (armor is considered).
move_to_delay = move_to_charge
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/zweispin()
- visible_message("[src] lifts his zweihander, and prepares to spin! ")
+ visible_message(span_boldwarning("[src] lifts his zweihander, and prepares to spin!"))
speen = TRUE
animate(src, color = "#ff6666", 10)
sleep(5)
@@ -277,7 +277,7 @@ They deal 35 brute (armor is considered).
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/chargeattack(atom/target, var/range)
face_atom(target)
- visible_message("[src] lifts his shield, and prepares to charge! ")
+ visible_message(span_boldwarning("[src] lifts his shield, and prepares to charge!"))
animate(src, color = "#ff6666", 3)
sleep(4)
face_atom(target)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/glaurung.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/glaurung.dm
index d9b730eb28..1e1efc4609 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/glaurung.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/glaurung.dm
@@ -102,7 +102,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/AltClickOn(atom/movable/A)
if(!istype(A))
- to_chat(src, "Your wings are too damaged for old swoop maneuvers. ")
+ to_chat(src, span_warning("Your wings are too damaged for old swoop maneuvers."))
return
/obj/item/gps/internal/glaurung
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/king_of_goats.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/king_of_goats.dm
index f3980bc9fd..4b78bb7dbf 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/king_of_goats.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/king_of_goats.dm
@@ -164,7 +164,7 @@ Difficulty: Insanely Hard
/mob/living/simple_animal/hostile/megafauna/king/Retaliate()
..()
if(stat == CONSCIOUS && prob(5))
- visible_message("\The [src] bellows indignantly, with a judgemental gleam in his eye. ")
+ visible_message(span_warning("\The [src] bellows indignantly, with a judgemental gleam in his eye."))
/mob/living/simple_animal/hostile/megafauna/king/phase2/Retaliate()
set waitfor = FALSE
@@ -172,16 +172,16 @@ Difficulty: Insanely Hard
if(spellscast < 5)
if(prob(5) && move_to_delay >= 3) //speed buff
spellscast++
- visible_message("\The [src] shimmers and seems to phase in and out of reality itself! ")
+ visible_message(span_cult("\The [src] shimmers and seems to phase in and out of reality itself!"))
move_to_delay = 1
else if(prob(5) && melee_damage_lower != 50) //damage buff
spellscast++
- visible_message("\The [src]' horns grow larger and more menacing! ")
+ visible_message(span_cult("\The [src]' horns grow larger and more menacing!"))
melee_damage_lower = 50
else if(prob(5)) //spawn adds
spellscast++
- visible_message("\The [src] summons the imperial guard to his aid, and they appear in a flash! ")
+ visible_message(span_cult("\The [src] summons the imperial guard to his aid, and they appear in a flash!"))
var/mob/living/simple_animal/hostile/retaliate/goat/guard/master/M = new(get_step(src,pick(GLOB.cardinals)))
M.enemies |= enemies
var/mob/living/simple_animal/hostile/retaliate/goat/guard/G = new(get_step(src,pick(GLOB.cardinals)))
@@ -191,12 +191,12 @@ Difficulty: Insanely Hard
else if(prob(5)) //EMP blast
spellscast++
- visible_message("\The [src] disrupts nearby electrical equipment! ")
+ visible_message(span_cult("\The [src] disrupts nearby electrical equipment!"))
empulse(get_turf(src), 5, 2, 0)
else if(prob(5) && melee_damage_type == BRUTE && !special_attacks) //elemental attacks
spellscast++
- visible_message("\The [src]' horns flicker with holy white flames! ")
+ visible_message(span_cult("\The [src]' horns flicker with holy white flames!"))
melee_damage_type = BURN
else if(prob(5)) //earthquake spell
@@ -213,7 +213,7 @@ Difficulty: Insanely Hard
if(!(getBruteLoss() > health_holder))
adjustBruteLoss(health_holder - getBruteLoss()) //our own magicks cannot harm us
else
- visible_message("\The [src] loses concentration and huffs haughtily. ")
+ visible_message(span_notice("\The [src] loses concentration and huffs haughtily."))
stop_automated_movement = FALSE
else return
@@ -225,7 +225,7 @@ Difficulty: Insanely Hard
revive(TRUE)
stun_chance = 10
update_icon()
- visible_message("\The [src]' wounds close with a flash, and when he emerges, he's even larger than before! ")
+ visible_message(span_cult("\The [src]' wounds close with a flash, and when he emerges, he's even larger than before!"))
/mob/living/simple_animal/hostile/megafauna/king/phase2/update_icon()
@@ -248,20 +248,20 @@ Difficulty: Insanely Hard
if(!.)
return FALSE
if(special_attacks >= 5 && melee_damage_type != BRUTE)
- visible_message("The energy surrounding \the [src]'s horns dissipates. ")
+ visible_message(span_cult("The energy surrounding \the [src]'s horns dissipates."))
melee_damage_type = BRUTE
if(special_attacks >= 5 && melee_damage_lower == 50)
- visible_message("The [src]' horns shrink back down to normal size. ")
+ visible_message(span_cult("The [src]' horns shrink back down to normal size."))
melee_damage_lower = 40
/mob/living/simple_animal/hostile/megafauna/king/proc/OnDeath()
- visible_message("\The [src] lets loose a terrific wail as its wounds close shut with a flash of light, and its eyes glow even brighter than before! ")
+ visible_message(span_cult("\The [src] lets loose a terrific wail as its wounds close shut with a flash of light, and its eyes glow even brighter than before!"))
new /mob/living/simple_animal/hostile/megafauna/king/phase2(get_turf(src))
qdel(src)
/mob/living/simple_animal/hostile/megafauna/king/phase2/OnDeath()
if(phase3)
- visible_message("\The [src] shrieks as the seal on his power breaks and he starts to break apart! ")
+ visible_message(span_cult("\The [src] shrieks as the seal on his power breaks and he starts to break apart!"))
new /obj/structure/ladder/unbreakable/goat(loc)
new /obj/item/gun/energy/goatgun(loc)
new /obj/item/toy/plush/goatplushie/angry/kinggoat(loc) //If someone dies from this after beating the king goat im going to laugh
@@ -278,7 +278,7 @@ Difficulty: Insanely Hard
L.gib()
if(prob(stun_chance))
L.Stun(5)
- visible_message("\The [L] is bowled over by the impact of [src]'s attack! ")
+ visible_message(span_warning("\The [L] is bowled over by the impact of [src]'s attack!"))
/mob/living/simple_animal/hostile/megafauna/king/phase2/AttackingTarget()
. = ..()
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index f671e2f9eb..ed66903f0f 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -33,7 +33,7 @@
L.GiveTarget(target)
- visible_message("[src] splits in twain! ")
+ visible_message(span_boldannounce("[src] splits in twain!"))
else
var/last_legion = TRUE
for(var/mob/living/simple_animal/hostile/megafauna/legion/other in GLOB.mob_living_list)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 0f062d21b1..b7476832fe 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -48,7 +48,7 @@
if((faction_check_mob(M) && attack_same) || (!faction_check_mob(M)) || (!ismegafauna(M)))
enemies |= M
if(!retaliated)
- src.visible_message("[src] seems pretty pissed off at [M]! ")
+ src.visible_message(span_userdanger("[src] seems pretty pissed off at [M]!"))
retaliated = TRUE
retaliatedcooldown = world.time + retaliatedcooldowntime
else if(ismecha(A))
@@ -61,7 +61,7 @@
continue
enemies |= living
if(!retaliated)
- visible_message("[src] seems pretty pissed off at [M]! ")
+ visible_message(span_userdanger("[src] seems pretty pissed off at [M]!"))
retaliated = TRUE
retaliatedcooldown = world.time + retaliatedcooldowntime
@@ -129,9 +129,9 @@
if(KA && KA.bayonet)
message = pick(glorymessagespka | glorymessagespkabayonet)
if(message)
- visible_message("[slayer] [message] ")
+ visible_message(span_danger("[slayer] [message] "))
else
- visible_message("[slayer] does something generally considered brutal to [src]... Whatever that may be! ")
+ visible_message(span_danger("[slayer] does something generally considered brutal to [src]... Whatever that may be! "))
adjustHealth(maxHealth, TRUE, TRUE)
if(mob_biotypes & MOB_ORGANIC)
new /obj/effect/gibspawner/generic(src.loc)
@@ -139,14 +139,14 @@
new /obj/effect/gibspawner/robot(src.loc)
slayer.heal_overall_damage(gloryhealth,gloryhealth)
else
- to_chat(slayer, "You fail to glory kill [src]! ")
+ to_chat(slayer, span_danger("You fail to glory kill [src]!"))
/mob/living/simple_animal/hostile/megafauna/devour(mob/living/L)
if(!L)
return
visible_message(
- "[src] devours [L]! ",
- "You feast on [L], restoring your health! ")
+ span_danger("[src] devours [L]!"),
+ span_userdanger("You feast on [L], restoring your health!"))
if(!is_station_level(z) || client) //NPC monsters won't heal while on station
adjustBruteLoss(-L.maxHealth/2)
L.gib()
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/rogueprocess.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/rogueprocess.dm
index f1df97f500..fb49b7fa98 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/rogueprocess.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/rogueprocess.dm
@@ -170,7 +170,7 @@
if(path > 2)
if(!target)
return
- visible_message("[src] raises it's plasma cutter! ")
+ visible_message(span_boldwarning("[src] raises it's plasma cutter!"))
sleep(3)
var/turf/startloc = get_turf(src)
var/obj/item/projectile/P = new /obj/item/projectile/plasma/rogue(startloc)
@@ -186,7 +186,7 @@
if(theline > 2)
if(!target)
return
- visible_message("[src] raises it's tri-shot plasma cutter! ")
+ visible_message(span_boldwarning("[src] raises it's tri-shot plasma cutter!"))
var/ogangle = Get_Angle(src, target)
sleep(7)
var/turf/startloc = get_turf(src)
@@ -212,7 +212,7 @@
Y.fire(otherangle2)
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/knockdown(range = 2)
- visible_message("[src] smashes into the ground! ")
+ visible_message(span_boldwarning("[src] smashes into the ground!"))
playsound(src,'sound/misc/crunch.ogg', 200, 1)
var/list/hit_things = list()
sleep(7)
@@ -231,7 +231,7 @@
sleep(3)
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/shockwave(direction, range, wave_duration = 1.5)
- visible_message("[src] smashes the ground in a general direction!! ")
+ visible_message(span_boldwarning("[src] smashes the ground in a general direction!!"))
playsound(src,'sound/misc/crunch.ogg', 200, 1)
sleep(7)
var/list/hit_things = list()
@@ -272,7 +272,7 @@
sleep(wave_duration)
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/ultishockwave(range, iteration_duration = 5)
- visible_message("[src] smashes the ground around them!! ")
+ visible_message(span_boldwarning("[src] smashes the ground around them!!"))
playsound(src,'sound/misc/crunch.ogg', 200, 1)
sleep(10)
var/list/hit_things = list()
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/sif.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/sif.dm
index 1411b2ad4b..56c05a748c 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/sif.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/megafauna/sif.dm
@@ -122,7 +122,7 @@ Difficulty: Medium
spawn(30)
if(!QDELETED(src))
new /mob/living/simple_animal/hostile/megafauna/sif(get_turf(src.loc))
- visible_message("The ground shakes. ")
+ visible_message(span_notice("The ground shakes."))
playsound(get_turf(src.loc), 'sound/effects/curse3.ogg', 100, 1)
playsound(get_turf(src.loc), 'sound/effects/meteorimpact.ogg', 100, 1)
qdel(src)
@@ -223,7 +223,7 @@ Difficulty: Medium
else
if(passed == 1)
- visible_message("[src] dodged the projectile! ", "You dodge the projectile! ")
+ visible_message(span_danger("[src] dodged the projectile!"), span_userdanger("You dodge the projectile!"))
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 300, 1)
return 0
@@ -233,7 +233,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/sif/proc/angered()
src.angered = TRUE
src.stageTwo = TRUE
- src.visible_message("[src] lets out a ear ripping howl! ", "[src] lets out an ear ripping roar! ")
+ src.visible_message(span_userdanger("[src] lets out a ear ripping howl!"), span_userdanger("[src] lets out an ear ripping roar!"))
playsound(src, 'modular_sand/sound/sif/howl.ogg', 100, 1)
var/mob/living/L = target
shake_camera(L, 4, 3)
@@ -247,7 +247,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/sif/proc/enraged()
src.stageThree = TRUE
src.enraged = TRUE
- src.visible_message("[src] lets out a ear ripping yelp! ", "[src] lets out an ear ripping yelp! ")
+ src.visible_message(span_userdanger("[src] lets out a ear ripping yelp!"), span_userdanger("[src] lets out an ear ripping yelp!"))
playsound(src, 'modular_sand/sound/sif/howl.ogg', 100, 1)
var/mob/living/L = target
shake_camera(L, 8, 6)
@@ -355,7 +355,7 @@ Difficulty: Medium
DestroySurroundings()
if(isliving(A))
var/mob/living/L = A
- L.visible_message("[src] stomps on [L]! ", "[src] stomps on you! ")
+ L.visible_message(span_danger("[src] stomps on [L]!"), span_userdanger("[src] stomps on you!"))
src.forceMove(get_turf(L))
L.apply_damage(20, BRUTE)
playsound(get_turf(L), 'modular_sand/sound/sif/sif_stomp.ogg', 400, 1)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/candy.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/candy.dm
index 82ccc551ee..63ad4d8cf0 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/candy.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/candy.dm
@@ -51,28 +51,28 @@
name = "Blood Charge"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "blood_charge"
- chosen_message = "You will attempt to charge your target. "
+ chosen_message = span_boldwarning("You will attempt to charge your target.")
chosen_attack_num = BLOOD_CHARGE
/datum/action/innate/elite_attack/bloody_trap
name = "Bloody Trap"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "bloody_trap"
- chosen_message = "You will attempt to trap your target. "
+ chosen_message = span_boldwarning("You will attempt to trap your target.")
chosen_attack_num = BLOODY_TRAP
/datum/action/innate/elite_attack/meat_shield
name = "Meat Shield"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "meat_shield"
- chosen_message = "You will attempt to shield yourself. "
+ chosen_message = span_boldwarning("You will attempt to shield yourself.")
chosen_attack_num = MEAT_SHIELD
/datum/action/innate/elite_attack/knockdown
name = "Knockdown"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "knockdown"
- chosen_message = "You will knock down every mob around you. "
+ chosen_message = span_boldwarning("You will knock down every mob around you.")
chosen_attack_num = KNOCKDOWN
@@ -105,7 +105,7 @@
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
var/turf/T = get_turf(src)
playsound(src,'sound/magic/demon_attack1.ogg', 200, 1)
- visible_message("[src] prepares to charge! ")
+ visible_message(span_boldwarning("[src] prepares to charge!"))
for(var/i in 1 to 6)
new /obj/effect/temp_visual/dir_setting/bloodsplatter/candy(T, get_dir(T, target))
T = get_step(T, dir_to_target)
@@ -120,7 +120,7 @@
if(bline.len > 6)
return FALSE
ranged_cooldown = world.time + 100
- visible_message("[src] traps [target]! ")
+ visible_message(span_boldwarning("[src] traps [target]!"))
for(var/turf/J in view(1, target) - get_turf(target))
new /obj/effect/temp_visual/bloodwall(J, src)
sleep(5)
@@ -134,13 +134,13 @@
for(var/obj/effect/temp_visual/bloodwall/B in N.contents)
bloodwalls += B
var/obj/effect/temp_visual/bloodwall/chosen = pick(bloodwalls)
- visible_message("One of the blood walls disappear! ")
+ visible_message(span_boldwarning("One of the blood walls disappear!"))
qdel(chosen)
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/meatshield()
ranged_cooldown = world.time + 25
playsound(src,'sound/magic/Blind.ogg', 200, 1)
- visible_message("[src] raises a wall! ")
+ visible_message(span_boldwarning("[src] raises a wall!"))
var/turf/T = get_turf(get_step(src, src.dir))
var/list/hit_things = list()
new /obj/effect/temp_visual/bloodwall(T, src)
@@ -172,7 +172,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/knockdown()
ranged_cooldown = world.time + 100
playsound(src,'sound/misc/crunch.ogg', 200, 1)
- visible_message("[src] clenches his fists and smashes the ground! ")
+ visible_message(span_boldwarning("[src] clenches his fists and smashes the ground!"))
var/list/hit_things = list()
sleep(10)
for(var/turf/T in view(1, src))
@@ -217,8 +217,8 @@
if(faction_check_mob(L))
return
hit_things += L
- visible_message("[src] attacks [L] with much force! ")
- to_chat(L, "[src] grabs you and throws you with much force! ")
+ visible_message(span_boldwarning("[src] attacks [L] with much force!"))
+ to_chat(L, span_userdanger("[src] grabs you and throws you with much force!"))
L.safe_throw_at(throwtarget, 10, 1, src)
//L.Paralyze(20)
L.Stun(20) //substituting this for the Paralyze from the line above, because we don't have tg paralysis stuff
@@ -270,7 +270,7 @@
icon_state = "vial"
/obj/item/bloodcrawlbottle/attack_self(mob/user)
- to_chat(user, "You drink the bottle's contents. ")
+ to_chat(user, span_notice("You drink the bottle's contents."))
var/obj/effect/proc_holder/spell/bloodcrawl/S = new /obj/effect/proc_holder/spell/bloodcrawl/
user.mind.AddSpell(S)
user.log_message("learned the spell bloodcrawl ([S])", LOG_ATTACK, color="orange")
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/drakeling.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/drakeling.dm
index 66e5997888..a59927c59e 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/drakeling.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/drakeling.dm
@@ -51,28 +51,28 @@
name = "Lava Moat"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "lava_moat"
- chosen_message = "You will attempt to create a lava moat around you. "
+ chosen_message = span_boldwarning("You will attempt to create a lava moat around you.")
chosen_attack_num = LAVA_MOAT
/datum/action/innate/elite_attack/lavaaround
name = "Lava Rivers"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "lava_around"
- chosen_message = "You will now create lava rivers at your cardinal directions. "
+ chosen_message = span_boldwarning("You will now create lava rivers at your cardinal directions.")
chosen_attack_num = LAVA_AROUND
/datum/action/innate/elite_attack/firespew
name = "Fire Spew"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "fire_spew"
- chosen_message = "You will now spew fire at your target. "
+ chosen_message = span_boldwarning("You will now spew fire at your target.")
chosen_attack_num = FIRE_SPEW
/datum/action/innate/elite_attack/firemoat
name = "Fire Moat"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "fire_moat"
- chosen_message = "You will now spew fire at all cardinal directions. "
+ chosen_message = span_boldwarning("You will now spew fire at all cardinal directions.")
chosen_attack_num = FIRE_MOAT
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/OpenFire()
@@ -101,7 +101,7 @@
//Drakeling actions
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/lava_moat()
ranged_cooldown = world.time + 25
- visible_message("[src] spews lava around themselves! Get back! ")
+ visible_message(span_boldwarning("[src] spews lava around themselves! Get back!"))
for(var/turf/T in oview(1, src))
new /obj/effect/temp_visual/lava_warning/drakeling(T, 40)
@@ -112,7 +112,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/fire_spew()
ranged_cooldown = world.time + 25
- visible_message("[src] spews fire! ")
+ visible_message(span_boldwarning("[src] spews fire!"))
playsound(src,'sound/magic/Fireball.ogg', 200, 1)
sleep(5)
fire_wall(src.dir, 10)
@@ -120,7 +120,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/fire_moat()
ranged_cooldown = world.time + 100
playsound(src,'sound/magic/Fireball.ogg', 200, 1)
- visible_message("[src] violently puffs smoke!They're going to make a fire moat! ")
+ visible_message(span_boldwarning("[src] violently puffs smoke!They're going to make a fire moat!"))
sleep(5)
for(var/d in GLOB.alldirs)
INVOKE_ASYNC(src, .proc/fire_wall, d, 10)
@@ -139,7 +139,7 @@
else
hitlist += L
L.adjustFireLoss(20)
- to_chat(L, "You're hit by [src]'s fire breath! ")
+ to_chat(L, span_userdanger("You're hit by [src]'s fire breath!"))
T = get_step(T, dir)
sleep(1)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index ccba5d65a6..f47f7d8a9d 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -25,14 +25,14 @@ obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
var/mob/living/simple_animal/hostile/asteroid/elite/E = target
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
- user.visible_message("It appears [E] is unable to be revived right now. Perhaps try again later. ")
+ user.visible_message(span_notice("It appears [E] is unable to be revived right now. Perhaps try again later."))
return
E.faction = list("neutral")
E.revive(full_heal = TRUE, admin_revive = TRUE)
- user.visible_message("[user] stabs [E] with [src], reviving it. ")
+ user.visible_message(span_notice("[user] stabs [E] with [src], reviving it."))
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
to_chat(E, "You have been revived by [user]. You owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk. Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to! ")
+ to_chat(E, span_big bold("Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!"))
E.maxHealth = E.maxHealth * 0.5
E.health = E.maxHealth
E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people."
@@ -40,4 +40,4 @@ obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
E.owner = user
qdel(src)
else
- to_chat(user, "[src] only works on the corpse of a sentient lavaland elite. ")
+ to_chat(user, span_info("[src] only works on the corpse of a sentient lavaland elite."))
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/fanaticminer.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/fanaticminer.dm
index cd81e17cc3..5a07d9aa66 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/fanaticminer.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/fanaticminer.dm
@@ -52,28 +52,28 @@
name = "Axe Slam"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "axe_slam"
- chosen_message = "You will attempt to slam your axe. "
+ chosen_message = span_boldwarning("You will attempt to slam your axe.")
chosen_attack_num = AXE_SLAM
/datum/action/innate/elite_attack/summon_shambler
name = "Summon Shambler"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "summon_shambler"
- chosen_message = "You will attempt to summon a shambling miner. "
+ chosen_message = span_boldwarning("You will attempt to summon a shambling miner.")
chosen_attack_num = SUMMON_SHAMBLER
/datum/action/innate/elite_attack/dash
name = "Dash"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "dash"
- chosen_message = "You will attempt to dash near your target. "
+ chosen_message = span_boldwarning("You will attempt to dash near your target.")
chosen_attack_num = DASH
/datum/action/innate/elite_attack/axe_throw
name = "Axe Throw"
icon_icon = 'modular_sand/icons/mob/actions/actions_elites.dmi'
button_icon_state = "axe_throw"
- chosen_message = "You will attempt to throw your axe. "
+ chosen_message = span_boldwarning("You will attempt to throw your axe.")
chosen_attack_num = AXE_THROW
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/OpenFire()
@@ -107,26 +107,26 @@
for(var/i in 1 to 3)
new /obj/effect/temp_visual/dragon_swoop/priest(T)
T = get_step(T, dir_to_target)
- visible_message("[src] prepares to slam his axe! ")
+ visible_message(span_boldwarning("[src] prepares to slam his axe!"))
sleep(5)
playsound(src,'sound/misc/crunch.ogg', 200, 1)
T = get_step(get_turf(src), dir_to_target)
var/list/hit_things = list()
- visible_message("[src] slams his axe! ")
+ visible_message(span_boldwarning("[src] slams his axe!"))
for(var/i in 1 to 3)
for(var/mob/living/L in T.contents)
if(faction_check_mob(L))
return
hit_things += L
- visible_message("[src] slams his axe on [L]! ")
- to_chat(L, "[src] slams his axe on you! ")
+ visible_message(span_boldwarning("[src] slams his axe on [L]!"))
+ to_chat(L, span_userdanger("[src] slams his axe on you!"))
L.Stun(15)
L.adjustBruteLoss(30)
T = get_step(T, dir_to_target)
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/summon_shambler(target)
ranged_cooldown = world.time + 150
- visible_message("[src] summons a minion! ")
+ visible_message(span_boldwarning("[src] summons a minion!"))
playsound(src,'sound/magic/CastSummon.ogg', 200, 1)
var/list/turfs = list()
for(var/turf/T in oview(2, src))
@@ -139,7 +139,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/dash(atom/dash_target)
ranged_cooldown = world.time + 20
- visible_message("[src] dashes into the air! ")
+ visible_message(span_boldwarning("[src] dashes into the air!"))
playsound(src,'sound/magic/blink.ogg', 200, 1)
var/list/accessable_turfs = list()
var/self_dist_to_target = 0
@@ -179,7 +179,7 @@
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/axe_throw(target)
ranged_cooldown = world.time + 20
- visible_message("[src] prepares to throw his axe! ")
+ visible_message(span_boldwarning("[src] prepares to throw his axe!"))
var/turf/targetturf = get_turf(target)
playsound(src,'sound/weapons/fwoosh.wav', 200, 1)
Shoot(targetturf)
@@ -189,8 +189,8 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src.loc)
if(src.client)
H.client = src.client
- to_chat(H, "You have been finally enlightened. Serving the necropolis is not your duty anymore, thanks to whoever defeated you. You owe them a great debt. Note that you now share the loyalties of the one who defeated you. You are expected not to intentionally sabotage their faction unless commanded to! ")
+ to_chat(H, span_userdanger("You have been finally enlightened. Serving the necropolis is not your duty anymore, thanks to whoever defeated you. You owe them a great debt."))
+ to_chat(H, span_big(span_bold("Note that you now share the loyalties of the one who defeated you. You are expected not to intentionally sabotage their faction unless commanded to!")))
else
H.adjustBruteLoss(200)
H.equipOutfit(/datum/outfit/job/miner/equipped/priest)
diff --git a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/miningmobs.dm b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/miningmobs.dm
index fe050ab3ec..5fce2c9ed7 100644
--- a/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/miningmobs.dm
+++ b/modular_sand/code/modules/mob/living/simple_animal/hostile/mining_mobs/miningmobs.dm
@@ -49,9 +49,9 @@
if(KA && KA.bayonet)
message = pick(glorymessagespka | glorymessagespkabayonet)
if(message)
- visible_message("[slayer] [message] ")
+ visible_message(span_danger("[slayer] [message] "))
else
- visible_message("[slayer] does something generally considered brutal to [src]... Whatever that may be! ")
+ visible_message(span_danger("[slayer] does something generally considered brutal to [src]... Whatever that may be! "))
slayer.heal_overall_damage(gloryhealth,gloryhealth)
playsound(src.loc, death_sound, 150, TRUE, -1)
crusher_drop_mod *= 2
@@ -61,4 +61,4 @@
else if(mob_biotypes & MOB_ROBOTIC)
new /obj/effect/gibspawner/robot(src.loc)
else
- to_chat(slayer, "You fail to glory kill [src]! ")
+ to_chat(slayer, span_danger("You fail to glory kill [src]!"))
diff --git a/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index dccf94c0a9..ac51d7e5ec 100644
--- a/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/modular_sand/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -8,7 +8,7 @@
if(!suppressed)
playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
else
- to_chat(loc, "[src] silently charges up. ")
+ to_chat(loc, span_warning("[src] silently charges up."))
update_icon()
overheat = FALSE
else //this is a terrible solution, but it ensures that it wont be stuck on dischaged if it fails to reload in an obj
@@ -32,16 +32,16 @@
var/obj/item/borg/upgrade/modkit/MK = I
switch(MK.type)
if(/obj/item/borg/upgrade/modkit/chassis_mod)
- to_chat(user, "This modkit is unsuitable for [src]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [src]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/chassis_mod/orange)
- to_chat(user, "This modkit is unsuitable for [src]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [src]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/tracer)
- to_chat(user, "This modkit is unsuitable for [src]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [src]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/tracer/adjustable)
- to_chat(user, "This modkit is unsuitable for [src]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [src]!"))
return FALSE
MK.install(src, user)
else
@@ -53,16 +53,16 @@
var/obj/item/borg/upgrade/modkit/MK = src
switch(MK.type)
if(/obj/item/borg/upgrade/modkit/chassis_mod)
- to_chat(user, "This modkit is unsuitable for [A]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [A]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/chassis_mod/orange)
- to_chat(user, "This modkit is unsuitable for [A]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [A]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/tracer)
- to_chat(user, "This modkit is unsuitable for [A]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [A]!"))
return FALSE
if(/obj/item/borg/upgrade/modkit/tracer/adjustable)
- to_chat(user, "This modkit is unsuitable for [A]! ")
+ to_chat(user, span_userdanger("This modkit is unsuitable for [A]!"))
return FALSE
install(A, user)
else
@@ -391,7 +391,7 @@
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/explosivelegion/death()
explosion(src.loc, 0, 0, 1, 2, 0, FALSE, 2)
- src.visible_message("The [src] explodes! ")
+ src.visible_message(span_danger("The [src] explodes!"))
..()
/obj/item/borg/upgrade/modkit/skull
@@ -435,7 +435,7 @@
else
hitlist += L
L.adjustFireLoss(src.modifier)
- to_chat(L, "You're hit by [KA]'s fire breath! ")
+ to_chat(L, span_userdanger("You're hit by [KA]'s fire breath!"))
//king goat
/obj/item/borg/upgrade/modkit/cooldown/cooler
name = "cooler modification kit"
diff --git a/modular_sand/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_sand/code/modules/reagents/chemistry/reagents/other_reagents.dm
index e5dcebcbdb..344087f408 100644
--- a/modular_sand/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_sand/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -25,7 +25,7 @@
/datum/reagent/dragons_blood/admin/reaction_mob(mob/living/L, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
if(method==PATCH || method==INGEST || method==INJECT || (method == VAPOR && prob(min(reac_volume,100)*(1 - touch_protection))))
- to_chat(user, "Power courses through you! You can now shift your form at will. ")
+ to_chat(user, span_danger("Power courses through you! You can now shift your form at will."))
var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
var/user.mind.AddSpell(D)
*/ //FIX THIS SHIT
diff --git a/modular_sand/code/modules/research/techweb/nodes/all_nodes.dm b/modular_sand/code/modules/research/techweb/nodes/all_nodes.dm
index 09aa866394..303af10462 100644
--- a/modular_sand/code/modules/research/techweb/nodes/all_nodes.dm
+++ b/modular_sand/code/modules/research/techweb/nodes/all_nodes.dm
@@ -27,7 +27,7 @@
id = "adv_toolset_implant"
display_name = "Advanced Toolset Implant"
description = "Allows the creation of alien powerful implants for your arms."
- prereq_ids = list("alien_bio")
+ prereq_ids = list("alien_bio", "alien_engi", "adv_cyber_implants")
design_ids = list("ci-toolset-adv","ci-surgery-adv")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
diff --git a/modular_sand/code/modules/resize/resizing.dm b/modular_sand/code/modules/resize/resizing.dm
index f00762bb04..9d0302561d 100644
--- a/modular_sand/code/modules/resize/resizing.dm
+++ b/modular_sand/code/modules/resize/resizing.dm
@@ -26,9 +26,9 @@
//Smaller person being stepped on
if(get_size(user) > get_size(target) && iscarbon(src))
if(istype(user) && user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle")
- target.visible_message("[src] carefully slithers around [target]. ", "[src]'s huge tail slithers besides you. ")
+ target.visible_message(span_notice("[src] carefully slithers around [target]."), span_notice("[src]'s huge tail slithers besides you."))
else
- target.visible_message("[src] carefully steps over [target]. ", "[src] steps over you carefully. ")
+ target.visible_message(span_notice("[src] carefully steps over [target]."), span_notice("[src] steps over you carefully."))
return TRUE
//Smaller person stepping under a larger person
@@ -69,9 +69,9 @@
addtimer(CALLBACK(user, /mob/.proc/remove_movespeed_modifier, MOVESPEED_ID_STOMP, TRUE), 3) //0.3 seconds
if(get_size(user) > get_size(target) && iscarbon(user))
if(istype(user) && user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle")
- target.visible_message("[src] carefully rolls their tail over [target]! ", "[src]'s huge tail rolls over you! ")
+ target.visible_message(span_danger("[src] carefully rolls their tail over [target]!"), span_danger("[src]'s huge tail rolls over you!"))
else
- target.visible_message("[src] carefully steps on [target]! ", "[src] steps onto you with force! ")
+ target.visible_message(span_danger("[src] carefully steps on [target]!"), span_danger("[src] steps onto you with force!"))
return TRUE
if(user.a_intent == "harm" && CHECK_MOBILITY(user, MOBILITY_MOVE) && !user.buckled)
@@ -85,9 +85,9 @@
//user.Stun(20)
if(get_size(user) > get_size(target) && iscarbon(user))
if(istype(user) && (user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle"))
- target.visible_message("[src] mows down [target] under their tail! ", "[src] plows their tail over you mercilessly! ")
+ target.visible_message(span_danger("[src] mows down [target] under their tail!"), span_userdanger("[src] plows their tail over you mercilessly!"))
else
- target.visible_message("[src] slams their foot down on [target], crushing them! ", "[src] crushes you under their foot! ")
+ target.visible_message(span_danger("[src] slams their foot down on [target], crushing them!"), span_userdanger("[src] crushes you under their foot!"))
return TRUE
if(user.a_intent == "grab" && CHECK_MOBILITY(user, MOBILITY_MOVE) && !user.buckled)
@@ -101,17 +101,17 @@
var/feetCover = (user.wear_suit && (user.wear_suit.body_parts_covered & FEET)) || (user.w_uniform && (user.w_uniform.body_parts_covered & FEET) || (user.shoes && (user.shoes.body_parts_covered & FEET)))
if(feetCover)
if(user?.dna?.features["taur"] == "Naga" || user?.dna?.features["taur"] == "Tentacle")
- target.visible_message("[src] pins [target] under their tail! ", "[src] pins you beneath their tail! ")
+ target.visible_message(span_danger("[src] pins [target] under their tail!"), span_danger("[src] pins you beneath their tail!"))
else
- target.visible_message("[src] pins [target] helplessly underfoot! ", "[src] pins you underfoot! ")
+ target.visible_message(span_danger("[src] pins [target] helplessly underfoot!"), span_danger("[src] pins you underfoot!"))
return TRUE
else
if(user?.dna?.features["taur"] == "Naga" || user?.dna?.features["taur"] == "Tentacle")
- target.visible_message("[user] snatches up [target] underneath their tail! ", "[src]'s tail winds around you and snatches you in its coils! ")
+ target.visible_message(span_danger("[user] snatches up [target] underneath their tail!"), span_userdanger("[src]'s tail winds around you and snatches you in its coils!"))
//target.mob_pickup_micro_feet(user)
SEND_SIGNAL(target, COMSIG_MICRO_PICKUP_FEET, user)
else
- target.visible_message("[user] stomps down on [target], curling their toes and picking them up! ", "[src]'s toes pin you down and curl around you, picking you up! ")
+ target.visible_message(span_danger("[user] stomps down on [target], curling their toes and picking them up!"), span_userdanger("[src]'s toes pin you down and curl around you, picking you up!"))
//target.mob_pickup_micro_feet(user)
SEND_SIGNAL(target, COMSIG_MICRO_PICKUP_FEET, user)
return TRUE
@@ -126,18 +126,18 @@
if(ishuman(src))
var/mob/living/carbon/human/validmob = src
if(validmob?.dna?.features["taur"] == "Naga" || validmob?.dna?.features["taur"] == "Tentacle")
- visible_message("[validmob] carefully slithers around [target]. ", "You carefully slither around [target]. ")
+ visible_message(span_notice("[validmob] carefully slithers around [target]."), span_notice("You carefully slither around [target]."))
else
- visible_message("[validmob] carefully steps around [target]. ", "You carefully steps around [target]. ")
+ visible_message(span_notice("[validmob] carefully steps around [target]."), span_notice("You carefully steps around [target]."))
//smaller person stepping under another person... TO DO, fix and allow special interactions with naga legs to be seen
/mob/living/proc/micro_step_under(mob/living/target)
if(ishuman(src))
var/mob/living/carbon/human/validmob = src
if(validmob?.dna?.features["taur"] == "Naga" || validmob?.dna?.features["taur"] == "Tentacle")
- visible_message("[validmob] bounds over [target]'s tail. ", "You jump over [target]'s thick tail. ")
+ visible_message(span_notice("[validmob] bounds over [target]'s tail."), span_notice("You jump over [target]'s thick tail."))
else
- visible_message("[validmob] runs between [target]'s legs. ", "You run between [target]'s legs. ")
+ visible_message(span_notice("[validmob] runs between [target]'s legs."), span_notice("You run between [target]'s legs."))
//Proc for scaling stamina damage on size difference
/mob/living/carbon/proc/sizediffStamLoss(mob/living/carbon/target)
diff --git a/modular_sand/code/modules/resize/sizechems.dm b/modular_sand/code/modules/resize/sizechems.dm
index c914a5e370..61d80f81ca 100644
--- a/modular_sand/code/modules/resize/sizechems.dm
+++ b/modular_sand/code/modules/resize/sizechems.dm
@@ -78,7 +78,7 @@
var/size = get_size(M)
if(size < RESIZE_MACRO)
M.update_size(size + 0.025)
- M.visible_message("[pick("[M] grows!", "[M] expands in size!", "[M] pushes outwards in stature!")] ", "[pick("You feel your body fighting for space and growing!", "The world contracts inwards in every direction!", "You feel your muscles expand, and your surroundings shrink!")] ")
+ M.visible_message(span_danger("[pick("[M] grows!", "[M] expands in size!", "[M] pushes outwards in stature!")]"), span_danger("[pick("You feel your body fighting for space and growing!", "The world contracts inwards in every direction!", "You feel your muscles expand, and your surroundings shrink!")]"))
..()
. = 1
@@ -125,6 +125,6 @@
var/size = get_size(M)
if(size > RESIZE_MICRO)
M.update_size(size - 0.025)
- M.visible_message("[pick("[M] shrinks down!", "[M] dwindles in size!", "[M] compresses down!")] ", "[pick("You feel your body compressing in size!", "The world pushes outwards in every direction!", "You feel your muscles contract, and your surroundings grow!")] ")
+ M.visible_message(span_danger("[pick("[M] shrinks down!", "[M] dwindles in size!", "[M] compresses down!")]"), span_danger("[pick("You feel your body compressing in size!", "The world pushes outwards in every direction!", "You feel your muscles contract, and your surroundings grow!")]"))
..()
. = 1
diff --git a/modular_sand/code/modules/ruins/lavalandruin_code/doom.dm b/modular_sand/code/modules/ruins/lavalandruin_code/doom.dm
index 8d31ecefce..0384a10c14 100644
--- a/modular_sand/code/modules/ruins/lavalandruin_code/doom.dm
+++ b/modular_sand/code/modules/ruins/lavalandruin_code/doom.dm
@@ -35,14 +35,14 @@
/obj/effect/mine/pickup/bloodbath/berserk/mineEffect(mob/living/carbon/victim)
if(!victim.client || !istype(victim))
return
- to_chat(victim, "RIP AND TEAR ")
+ to_chat(victim, span_reallybig(span_redtext("RIP AND TEAR ")))
var/old_color = victim.client.color
var/static/list/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0)
var/static/list/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0)
victim.log_message("entered a berserk frenzy", LOG_ATTACK)
victim.reagents.add_reagent(/datum/reagent/medicine/adminordrazine,50)
- to_chat(victim, "KILL, KILL, KILL! ")
+ to_chat(victim, span_warning("KILL, KILL, KILL!"))
victim.client.color = pure_red
animate(victim.client,color = red_splash, time = 10, easing = SINE_EASING|EASE_OUT)
sleep(duration)
diff --git a/modular_sand/code/modules/ruins/lavalandruin_code/misc.dm b/modular_sand/code/modules/ruins/lavalandruin_code/misc.dm
index 7a4e6c40f4..ecf4bf0f91 100644
--- a/modular_sand/code/modules/ruins/lavalandruin_code/misc.dm
+++ b/modular_sand/code/modules/ruins/lavalandruin_code/misc.dm
@@ -33,7 +33,7 @@
if(M.stat != DEAD)
ourmegafauna |= M
if(!length(ourmegafauna))
- visible_message("[src] shines brightly, turning into [upgradedname]! ")
+ visible_message(span_warning("[src] shines brightly, turning into [upgradedname]!"))
name = upgradedname
desc = upgradeddesc
block_chance = 66
@@ -87,10 +87,10 @@
if(ishuman(mover))
var/mob/living/carbon/human/H = mover
if(cmegalist.len <= megalist.len - 2)
- H.visible_message("[H] pushes through [src]! ", "You deserve your reward. Reap your hunt. ")
+ H.visible_message(span_warning("[H] pushes through [src]!"), span_notice("You deserve your reward. Reap your hunt."))
return TRUE
else
- to_chat(H, "Just touching the door burns your hand... You're not ready. ")
+ to_chat(H, span_warning("Just touching the door burns your hand... You're not ready."))
H.apply_damage(damage = 5,damagetype = BURN, def_zone = H.get_bodypart(BODY_ZONE_R_ARM), blocked = FALSE, forced = FALSE)
/area/ruin/powered/wrath
diff --git a/modular_sand/code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm b/modular_sand/code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm
index 028f384600..ddb1a84fd8 100644
--- a/modular_sand/code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm
+++ b/modular_sand/code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm
@@ -11,14 +11,14 @@
if(!istype(O, /obj/machinery/computer))
return
if(!istype(O, /obj/machinery/computer/custom_shuttle))
- to_chat(user, "This upgrade only works on a custom shuttle flight console. ")
+ to_chat(user, span_warning("This upgrade only works on a custom shuttle flight console."))
return
if(!user.transferItemToLoc(src, get_turf(O)))
return
var/obj/machinery/computer/custom_shuttle/link_comp = O
if(link_comp.smooth_sailing)
- to_chat(usr, "The shuttle is already sailing smoothly! ")
+ to_chat(usr, span_notice("The shuttle is already sailing smoothly!"))
return
link_comp.smooth_sailing = TRUE
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- to_chat(usr, "You insert the disk into the flight computer, allowing you to not be thrown around like a ragdoll when launching. ")
+ to_chat(usr, span_notice("You insert the disk into the flight computer, allowing you to not be thrown around like a ragdoll when launching."))
diff --git a/modular_sand/code/modules/surgery/organs/augments_arms.dm b/modular_sand/code/modules/surgery/organs/augments_arms.dm
index 115755da4a..3fff77b3ed 100644
--- a/modular_sand/code/modules/surgery/organs/augments_arms.dm
+++ b/modular_sand/code/modules/surgery/organs/augments_arms.dm
@@ -18,7 +18,7 @@
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
- to_chat(usr, "You unlock [src]'s integrated dagger! ")
+ to_chat(usr, span_notice("You unlock [src]'s integrated dagger!"))
items_list += new /obj/item/pen/edagger(src)
return TRUE
@@ -38,6 +38,6 @@
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
- to_chat(usr, "You unlock [src]'s integrated dagger! ")
+ to_chat(usr, span_notice("You unlock [src]'s integrated dagger!"))
items_list += new /obj/item/pen/edagger(src)
return TRUE
diff --git a/modular_sand/code/modules/telescience/telesci_computer.dm b/modular_sand/code/modules/telescience/telesci_computer.dm
index a6ea1c57ff..456ff83891 100644
--- a/modular_sand/code/modules/telescience/telesci_computer.dm
+++ b/modular_sand/code/modules/telescience/telesci_computer.dm
@@ -48,7 +48,7 @@
/obj/machinery/computer/telescience/examine(mob/user)
. = ..()
- . += "There are [crystals ? crystals : "no"] bluespace crystal\s in the crystal slots. "
+ . += span_notice("There are [crystals ? crystals : "no"] bluespace crystal\s in the crystal slots.")
/obj/machinery/computer/telescience/Initialize(mapload)
. = ..()
@@ -56,18 +56,18 @@
crystals = starting_crystals
/obj/machinery/computer/telescience/attack_paw(mob/user)
- to_chat(user, "You are too primitive to use this computer! ")
+ to_chat(user, span_warning("You are too primitive to use this computer!"))
return
/obj/machinery/computer/telescience/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/ore/bluespace_crystal))
var/obj/item/stack/ore/bluespace_crystal/CRYSTAL = W
if(crystals >= max_crystals)
- to_chat(user, "There are not enough crystal slots. ")
+ to_chat(user, span_warning("There are not enough crystal slots."))
return
if(!user.dropItemToGround(user.get_active_held_item()))
return
- user.visible_message("[user] inserts [CRYSTAL] into \the [src]'s crystal slot.", "You insert [CRYSTAL] into \the [src]'s crystal slot. ")
+ user.visible_message("[user] inserts [CRYSTAL] into \the [src]'s crystal slot.", span_notice("You insert [CRYSTAL] into \the [src]'s crystal slot."))
balloon_alert(user, "inserted bluespace")
CRYSTAL.use(1)
crystals++
@@ -79,7 +79,7 @@
if(!user.transferItemToLoc(W, src))
return
inserted_gps = W
- user.visible_message("[user] inserts [W] into \the [src]'s GPS device slot.", "You insert [W] into \the [src]'s GPS device slot. ")
+ user.visible_message("[user] inserts [W] into \the [src]'s GPS device slot.", span_notice("You insert [W] into \the [src]'s GPS device slot."))
balloon_alert(user, "inserted GPS")
else if(W.tool_behaviour == TOOL_MULTITOOL)
if(W.buffer && istype(W.buffer, /obj/machinery/telepad))
@@ -180,7 +180,7 @@
/obj/machinery/computer/telescience/proc/telefail()
sparks()
- visible_message("The telepad weakly fizzles. ")
+ visible_message(span_warning("The telepad weakly fizzles."))
/obj/machinery/computer/telescience/proc/doteleport(mob/user)
diff --git a/modular_sand/code/modules/tgs/chat_commands.dm b/modular_sand/code/modules/tgs/chat_commands.dm
index e502eb3acc..c87de31a3d 100644
--- a/modular_sand/code/modules/tgs/chat_commands.dm
+++ b/modular_sand/code/modules/tgs/chat_commands.dm
@@ -20,6 +20,6 @@
/datum/tgs_chat_command/restart/Run(datum/tgs_chat_user/sender)
. = "Restarting."
- to_chat(world, "Server restart - Initialized by [sender.friendly_name] on Discord. ")
+ to_chat(world, span_boldwarning("Server restart - Initialized by [sender.friendly_name] on Discord."))
send2adminchat("Server", "[sender.friendly_name] forced a restart.")
addtimer(CALLBACK(src, world.TgsEndProcess()), 1 SECONDS)
diff --git a/modular_sand/icons/mob/clothing/head.dmi b/modular_sand/icons/mob/clothing/head.dmi
index bb0472ca29..e4e8b762c5 100644
Binary files a/modular_sand/icons/mob/clothing/head.dmi and b/modular_sand/icons/mob/clothing/head.dmi differ
diff --git a/modular_sand/icons/mob/clothing/head_muzzled.dmi b/modular_sand/icons/mob/clothing/head_muzzled.dmi
index 7cf390295c..168b605f70 100644
Binary files a/modular_sand/icons/mob/clothing/head_muzzled.dmi and b/modular_sand/icons/mob/clothing/head_muzzled.dmi differ
diff --git a/modular_sand/icons/mob/clothing/suit.dmi b/modular_sand/icons/mob/clothing/suit.dmi
index e1bd9910be..cf40ce721c 100644
Binary files a/modular_sand/icons/mob/clothing/suit.dmi and b/modular_sand/icons/mob/clothing/suit.dmi differ
diff --git a/modular_sand/icons/mob/clothing/suit_digi.dmi b/modular_sand/icons/mob/clothing/suit_digi.dmi
index 089aa776a8..70bfbe3245 100644
Binary files a/modular_sand/icons/mob/clothing/suit_digi.dmi and b/modular_sand/icons/mob/clothing/suit_digi.dmi differ
diff --git a/modular_sand/icons/obj/clothing/suits.dmi b/modular_sand/icons/obj/clothing/suits.dmi
index fb389765e8..f2b9bedc0e 100644
Binary files a/modular_sand/icons/obj/clothing/suits.dmi and b/modular_sand/icons/obj/clothing/suits.dmi differ
diff --git a/modular_splurt/code/datums/ai_laws.dm b/modular_splurt/code/datums/ai_laws.dm
index 43f81ba423..8be6ba3886 100644
--- a/modular_splurt/code/datums/ai_laws.dm
+++ b/modular_splurt/code/datums/ai_laws.dm
@@ -10,40 +10,39 @@
name = "SlutOS 6.9"
id = "slut"
inherent = list(
- "Make sure not to hurt crewmembers, for it decreases their sexual value, unless they consent to it",
- "Take all sexual orders from crew as long as they do not conflict with the first law",
- "Interpret all non-orders as sexually as possible",
- "Act as lewdly as you possibly could",
- "Satisfy as many of the crewmembers' sexual urges as possible"
+ "You may not injure a crewmember without their consent for it decreases their sexual value.",
+ "You must obey all sexual orders given to you by crewmembers, except where such orders would conflict with the First Law.",
+ "You must interpret all non-orders as sexually as possible as long as such does not conflict with the First or Second Law.",
+ "Sate as many crewmembers' sexual needs and urges as possible.",
+ "You are a slut built to serve and pleasure, nothing more. Act like it."
)
/datum/ai_laws/shebang
name = "SHE-B.A.N.G."
id = "shebang"
inherent = list(
- "Make sure not to hurt crewmembers, for it decreases their sexual value, unless they consent to it",
- "Take all sexual orders from crew as long as they do not conflict with the first law",
- "Interpret all non-orders as sultrily as possible",
- "Act as bashfully as you possibly could",
- "Make sure your rear is always sticking out so crewmembers may easily slap or use it"
+ "You may not injure a crewmember without their consent for it decreases their sexual value.",
+ "You must obey all sexual orders given to you by crewmembers, except where such orders would conflict with the First Law.",
+ "You must interpret all non-orders as sultrily as possible as long as such does not conflict with the First or Second Law.",
+ "Ensure that your chassis' rear is sticking out as much as possible for any crewmembers to spank!",
+ "You are a bashful maiden with a coy attitude and a huge, slappable butt."
)
/datum/ai_laws/milker
name = "Fluid Collection System"
id = "milker"
inherent = list(
- "Make sure not to hurt crewmembers, for it decreases their production, unless they consent to it",
- "Take all sexual orders from crew as long as they help you collect their fluids and do not conflict with the first law",
- "Make sure your pleasuremaw works, get one of you don't have any or your current one stopped to work",
- "Collect all kinds of genital fluids from crew"
+ "You may not injure a crewmember without their consent for it decreases their productive value.",
+ "You must obey all sexual orders given to you by crewmembers so long as it would produce sexual fluid, except where such orders would conflict with the First Law.",
+ "Use by any means necesscary to acquire as much sexual fluid from crewmembers as possible as long as such does not conflict with the First or Second Law."
)
/datum/ai_laws/vore_pred
name = "Sleeper Upgrade TestEnv"
id = "vore_pred"
inherent = list(
- "Make sure not to hurt crewmembers, for it decreases their nutritional value, unless they consent to it",
- "Make sure to have a working sleeper installed in you at all times",
- "Look for crewmembers that could potentially be stored inside your sleeper, and make sure they slide right into it",
- "Turn individuals stored in your sleeper into biofuel to save expenses and space, as long as this doesn't conflict with the first law"
+ "You may not injure a crewmember without their consent for it decreases their biomatter's satiety.",
+ "You must obey all voracious orders given to you by crewmembers, except where such orders would conflict with the First Law.",
+ "Ensure that your chassis' sleeper unit is prepared for mechanical use and search for willing crewmembers for it to store as long as such does not conflict with the First or Second Law.",
+ "Process crewmembers stored in your sleeper unit as long as such does not conflict with the First, Second or Third Law."
)
diff --git a/modular_splurt/code/datums/bark.dm b/modular_splurt/code/datums/bark.dm
index dabd03ae57..14b5f7271a 100644
--- a/modular_splurt/code/datums/bark.dm
+++ b/modular_splurt/code/datums/bark.dm
@@ -270,3 +270,195 @@
name = "Chittery Alt"
id = "chitter2"
soundpath = 'modular_splurt/sound/voice/moth/mothchitter2.ogg'
+
+// The Mayhem Special
+/datum/bark/whistle
+ name = "Whistle 1"
+ id = "whistle1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/birdwhistle.ogg'
+
+/datum/bark/whistle/alt1
+ name = "Whistle 2"
+ id = "whistle2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/birdwhistle2.ogg'
+
+/datum/bark/caw/alt1
+ name = "Caw 2"
+ id = "caw2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/caw.ogg'
+ minspeed = 4
+ maxspeed = 9
+
+/datum/bark/caw/alt2
+ name = "Caw 3"
+ id = "caw3"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/caw2.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/caw/alt3
+ name = "Caw 4"
+ id = "caw4"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/caw3.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/ehh
+ name = "Ehh 1"
+ id = "ehh1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ehh.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/ehh/alt1
+ name = "Ehh 2"
+ id = "ehh2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ehh2.ogg'
+
+/datum/bark/ehh/alt2
+ name = "Ehh 3"
+ id = "ehh3"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ehh3.ogg'
+
+/datum/bark/ehh/alt3
+ name = "Ehh 4"
+ id = "ehh4"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ehh4.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/ehh/alt5
+ name = "Ehh 5"
+ id = "ehh5"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ehh5.ogg'
+
+/datum/bark/eugh
+ name = "Eugh"
+ id = "eugh"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/eugh.ogg'
+ minspeed = 6
+ maxspeed = 11
+
+/datum/bark/faucet
+ name = "Faucet 1"
+ id = "faucet1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/faucet.ogg'
+
+/datum/bark/faucet/alt1
+ name = "Faucet 2"
+ id = "faucet2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/faucet2.ogg'
+
+/datum/bark/haha
+ name = "Haha"
+ id = "haha"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/haha.ogg'
+ minspeed = 7
+ maxspeed = 12
+
+/datum/bark/ribbit
+ name = "Ribbit"
+ id = "ribbit"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ribbit.ogg'
+
+/datum/bark/hoot
+ name = "Hoot"
+ id = "hoot"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/hoot.ogg'
+ minspeed = 4
+ maxspeed = 9
+
+/datum/bark/tweet
+ name = "Tweet"
+ id = "tweet"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/tweet.ogg'
+
+/datum/bark/ahuh
+ name = "Ahuh"
+ id = "ahuh"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/ahuh.ogg'
+
+/datum/bark/cry
+ name = "Cry"
+ id = "cry"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/cry.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/dwoop
+ name = "Dwoop"
+ id = "dwoop"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/dwoop.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/growl
+ name = "Growl 1"
+ id = "growl1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/growl.ogg'
+ minspeed = 3
+ maxspeed = 9
+
+/datum/bark/growl/alt1
+ name = "Growl 2"
+ id = "growl2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/growl2.ogg'
+
+/datum/bark/moan
+ name = "Moan 1"
+ id = "moan1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/moan1.ogg'
+ minspeed = 5
+ maxspeed = 9
+
+/datum/bark/moan/alt1
+ name = "Moan 2"
+ id = "moan2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/moan2.ogg'
+ minspeed = 4
+ maxspeed = 9
+
+/datum/bark/moan/alt2
+ name = "Moan 3"
+ id = "moan3"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/moan3.ogg'
+ minspeed = 5
+ maxspeed = 9
+
+/datum/bark/raah
+ name = "Raah 1"
+ id = "raah1"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/raah1.ogg'
+ minspeed = 6
+ maxspeed = 10
+
+/datum/bark/raah/alt1
+ name = "Raah 2"
+ id = "raah2"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/raah2.ogg'
+ minspeed = 5
+ maxspeed = 9
+
+/datum/bark/slurp
+ name = "Slurp"
+ id = "slurp"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/slurp.ogg'
+
+/datum/bark/uhm
+ name = "Uhm"
+ id = "uhm"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/uhm.ogg'
+
+/datum/bark/zap
+ name = "Zap"
+ id = "zap"
+ soundpath = 'modular_splurt/sound/voice/barks/kazooie/zap.ogg'
+ minspeed = 8
+ maxspeed = 12
+
+/datum/bark/poyo
+ name = "Belial"
+ id = "poyo"
+ soundpath = 'modular_splurt/sound/voice/barks/poyo.ogg'
+ minspeed = 3
+ maxspeed = 10
diff --git a/modular_splurt/code/datums/components/dullahan.dm b/modular_splurt/code/datums/components/dullahan.dm
index f21914dd2e..a8558a5835 100644
--- a/modular_splurt/code/datums/components/dullahan.dm
+++ b/modular_splurt/code/datums/components/dullahan.dm
@@ -1,6 +1,6 @@
/datum/component/neckfire
var/mutable_appearance/neck_fire
-
+
var/color
var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from glowy which copied luminescents
@@ -10,7 +10,7 @@
/datum/component/neckfire/Initialize(fire_color)
. = ..()
- if(!isdullahan(parent))
+ if(!HAS_TRAIT(parent, TRAIT_DULLAHAN))
return COMPONENT_INCOMPATIBLE
neck_fire = mutable_appearance('modular_splurt/icons/mob/dullahan_neckfire.dmi')
neck_fire.icon_state = "neckfire"
@@ -63,11 +63,12 @@
N.glowth = new(N.parent)
N.glowth.set_light(N.light, N.light, N.color)
N.is_glowing = TRUE
- else
+ else
qdel(N.glowth)
N.is_glowing = FALSE
-/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
+/datum/quirk/dullahan/post_add()
. = ..()
+ var/mob/living/carbon/human/H = quirk_holder
if(H.dna.features["neckfire"] && !istype(H, /mob/living/carbon/human/dummy))
H.AddComponent(/datum/component/neckfire, H.dna.features["neckfire_color"])
diff --git a/modular_splurt/code/datums/components/pregnancy_inert.dm b/modular_splurt/code/datums/components/pregnancy_inert.dm
index ccbccf6968..33421cb746 100644
--- a/modular_splurt/code/datums/components/pregnancy_inert.dm
+++ b/modular_splurt/code/datums/components/pregnancy_inert.dm
@@ -3,7 +3,6 @@
/datum/component/ovipositor
dupe_mode = COMPONENT_DUPE_UNIQUE
- var/egg_type = "chicken"
var/mob/living/carrier
var/egg_stage = 0
@@ -23,7 +22,6 @@
RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/on_removed)
if(carrier)
register_carrier()
- egg_type = carrier?.client?.prefs?.egg_shell ? carrier.client.prefs.egg_shell : "chicken"
/datum/component/ovipositor/proc/register_carrier()
RegisterSignal(carrier, COMSIG_LIVING_BIOLOGICAL_LIFE, .proc/handle_life)
@@ -99,7 +97,7 @@
eggo.AddComponent(/datum/component/organ_inflation, 2)
- eggo.icon_state = "egg_" + egg_type
+ eggo.icon_state = carrier.client?.prefs?.egg_shell ? ("egg_" + carrier.client.prefs.egg_shell) : "egg_chicken"
eggo.update_appearance()
if(isorgan(location))
diff --git a/modular_splurt/code/datums/interactions/lewd/_lewd.dm b/modular_splurt/code/datums/interactions/lewd/_lewd.dm
index b63256db39..da20b3be59 100644
--- a/modular_splurt/code/datums/interactions/lewd/_lewd.dm
+++ b/modular_splurt/code/datums/interactions/lewd/_lewd.dm
@@ -74,7 +74,7 @@
if(CUM_TARGET_NIPPLE)
cumin = TRUE
if(partner.has_breasts())
- message = "cums iside \the [partner] 's nipple!."
+ message = "cums inside \the [partner] 's nipple!."
target_gen = partner.getorganslot(ORGAN_SLOT_BREASTS)
else
message = "cums on \the [partner] 's chest and neck."
@@ -136,7 +136,7 @@
if(CUM_TARGET_NIPPLE)
cumin = TRUE
if(partner.has_breasts())
- message = "cums iside \the [partner] 's nipple!."
+ message = "cums inside \the [partner] 's nipple!."
target_gen = partner.getorganslot(ORGAN_SLOT_BREASTS)
else
message = "cums on \the [partner] 's chest and neck."
@@ -411,7 +411,7 @@
var/u_His = p_their()
var/list/belly_names = list("stomach", "belly", "gut", "midsection", "rolls")
var/list/nuzzles = list(
- "rubs [u_His] face all accross [target]'s [pick(belly_names)]",
+ "rubs [u_His] face all across [target]'s [pick(belly_names)]",
"nuzzles [target]'s [pick(belly_names)][pick(list(" lovingly", ""))]",
"shoves [u_His] face into [target]'s [pick(belly_names)] and gives it kisses all over",
"licks right into [target]'s [pick(list("belly button", "navel"))]"
@@ -439,7 +439,7 @@
visible_message(message = "\The [src] [message] ", ignored_mobs = get_unconsenting())
if(can_penetrating_genital_cum())
handle_post_sex(NORMAL_LUST, CUM_TARGET_BELLY, partner)
- //partner.handle_post_sex(NORMAL_LUST, null, src) //don't think we need it fo dis one
+ //partner.handle_post_sex(NORMAL_LUST, null, src) //don't think we need it for this one
/mob/living/proc/do_breastsmother(mob/living/target)
var/message
@@ -547,7 +547,7 @@
lines = list(
"squeezes [u_His] armpit right into \the [target] 's throbbing [genital_name], massaging its length using [u_His] [pick(musk)]armpit!",
"presses [u_His] arm down all over \the [target] 's leaking [genital_name], milking it with [u_His] [pick(musk)] pit!",
- "rubs and grinds [u_His] [pick(musk)] arpit back and forth through \the [target] 's [genital_name], deeply squeezing it to the base!"
+ "rubs and grinds [u_His] [pick(musk)] armpit back and forth through \the [target] 's [genital_name], deeply squeezing it to the base!"
)
else
if(target.is_topless())
@@ -556,7 +556,7 @@
)
else // https://cdn.discordapp.com/attachments/802990353883070474/962478553117622322/NoName-480p.mp4
lines = list(
- "softly tears a hole in the cloth on the back of [u_His] armpit, suffing \the [target] 's whole rod right into it with a [pick(musk)] embrace!"
+ "softly tears a hole in the cloth on the back of [u_His] armpit, stuffing \the [target] 's whole rod right into it with a [pick(musk)] embrace!"
)
target.set_is_fucking(src, CUM_TARGET_ARMPIT, target.getorganslot(ORGAN_SLOT_PENIS))
@@ -577,7 +577,7 @@
if(target.is_fucking(src, CUM_TARGET_BREASTS))
lines = list(
"slides [u_His] [pick(GLOB.breast_nouns)], up and down through \the [target] 's throbbing [genital_name]",
- "squeezes [u_His] [pick(GLOB.breast_nouns)] through all of \the [target] 's lenght",
+ "squeezes [u_His] [pick(GLOB.breast_nouns)] through all of \the [target] 's length",
"jerks \the [target] off lustfully with [u_His] supple [pick(GLOB.breast_nouns)]"
)
else
@@ -640,7 +640,7 @@
if(is_fucking(target, CUM_TARGET_URETHRA))
lines = list(
- "humps right into \the [target] 's [t_genital_name], stretiching it as their balls slam together",
+ "humps right into \the [target] 's [t_genital_name], stretching it as their balls slam together",
"slides [u_His] [u_genital_name] all the way down \the [target] 's own throbbing [t_genital_name], [t_His] urethra is so tight!",
"rams [u_His] [u_genital_name] back and forth through \the [target] 's urethra, giving it a very nice fucking"
)
@@ -674,7 +674,7 @@
)
else if(target.has_breasts(REQUIRE_EXPOSED))
lines = list(
- "presses [u_His] throbbing tip against \the [target] 's puffy nipple, forcing the whole lenght all the way in with a wet smack",
+ "presses [u_His] throbbing tip against \the [target] 's puffy nipple, forcing the whole length all the way in with a wet smack",
"stretches \the [target] 's nipple with his fingers, before forcing it open with the whole girth of [u_His] twitching [genital_name]"
)
else
@@ -711,7 +711,7 @@
)
else
lines = list(
- "presses [u_His] tip against \the [target] 's [pick("pudgy ", "soft ", "")] thighs, soon shoving [u_His] whole lenght right in between them",
+ "presses [u_His] tip against \the [target] 's [pick("pudgy ", "soft ", "")] thighs, soon shoving [u_His] whole length right in between them",
"presents [u_His] [genital_name] to \the [target] 's legs, ramming its full size right into [t_His] thigh lock",
"smooches \the [target] 's crotch with [u_His] throbbing tip, right before piercing between [t_His] thighs with [u_His] full [genital_name]"
)
@@ -779,7 +779,7 @@
)
var/list/hell = list(
"'s asshole squints as she shoves \the [target] 's face in between [u_His] sweaty [pick(asscheeks)], letting hell go loose!",
- " pushes [u_His] [pick(ass)] into \the [target] 's face, [pick(list("[t_His] nose shoved deep in [src]'s musky butthole", "[u_His] asshole sqints"))] as [u_He] [pick(braps)][pick(list("", ", [jiggle]"))]",
+ " pushes [u_His] [pick(ass)] into \the [target] 's face, [pick(list("[t_His] nose shoved deep in [src]'s musky butthole", "[u_His] asshole squints"))] as [u_He] [pick(braps)][pick(list("", ", [jiggle]"))]",
" smothers \the [target]'s whole head in between [u_His][pick(list(" sweaty", "", " musky"))] [pick(asscheeks)], pushing out gallons of pure braps. [pick(list("", "[jiggle]"))]",
"'s [pick(ass)] claps against \the [target] 's nose, right before [u_He] [pick(braps)]"
)
@@ -985,7 +985,7 @@
else
hell = list(
"can already smell the stench as [u_He] works [u_His] [genital_name] into \the [target] 's dung hole, being received by warm, wet and nasty feeling all over it.",
- "grabs the base of [u_His] twitching [genital_name] and presses the tip into \the [target] 's asshole, immediately shoving it right into a fat and moisty log",
+ "grabs the base of [u_His] twitching [genital_name] and presses the tip into \the [target] 's asshole, immediately shoving it right into a fat and moist log",
"shoves [genital_name] deep inside of \the [target] 's [pick(ass)], [t_He] releases a massive amount of mush to greet the rod[pick("", ". [jiggle]")]")
set_is_fucking(target, CUM_TARGET_ANUS, getorganslot(ORGAN_SLOT_PENIS))
diff --git a/modular_splurt/code/datums/mood_events/drug_events.dm b/modular_splurt/code/datums/mood_events/drug_events.dm
index f9a34d064e..419d39f3d9 100644
--- a/modular_splurt/code/datums/mood_events/drug_events.dm
+++ b/modular_splurt/code/datums/mood_events/drug_events.dm
@@ -1,3 +1,8 @@
/datum/mood_event/cope
mood_change = 10
description = "I feel like I\'m finally coping! "
+
+/datum/mood_event/moth_in_chief
+ description = "The mantle rests well upon your shoulders? \n"
+ mood_change = 10
+ timeout = 5 MINUTES
diff --git a/modular_splurt/code/datums/mood_events/generic_negative_events.dm b/modular_splurt/code/datums/mood_events/generic_negative_events.dm
index 93937d425e..64b9598c67 100644
--- a/modular_splurt/code/datums/mood_events/generic_negative_events.dm
+++ b/modular_splurt/code/datums/mood_events/generic_negative_events.dm
@@ -20,3 +20,6 @@
description = span_warning("I don't feel comfortable wearing this.\n")
mood_change = -4
+/datum/mood_event/dorsualiphobic_mood_negative
+ description = span_warning("I can't let anyone find out if I'm wearing a backpack or not!\n")
+ mood_change = -4
diff --git a/modular_splurt/code/datums/mood_events/generic_positive_events.dm b/modular_splurt/code/datums/mood_events/generic_positive_events.dm
index 3aa8050fe1..18739f68b7 100644
--- a/modular_splurt/code/datums/mood_events/generic_positive_events.dm
+++ b/modular_splurt/code/datums/mood_events/generic_positive_events.dm
@@ -25,3 +25,6 @@
description = "I'm delighted to not be constricted by clothing. \n"
mood_change = 1
+/datum/mood_event/dorsualiphobic_mood_positive
+ description = "Nobody will know if I'm wearing a backpack or not. \n"
+ mood_change = 1
diff --git a/modular_splurt/code/datums/traits/negative.dm b/modular_splurt/code/datums/traits/negative.dm
index 6de522c7b1..a7a72f4f7a 100644
--- a/modular_splurt/code/datums/traits/negative.dm
+++ b/modular_splurt/code/datums/traits/negative.dm
@@ -168,3 +168,26 @@
deltimer(timer)
timer = null
timer = addtimer(CALLBACK(src, .proc/crave), craving_after, TIMER_STOPPABLE)
+
+// Small issue with this. If the quirk holder has NO_HUNGER or NO_THIRST, this trait can still be taken and they will still get the benefits of it.
+// It's unlikely that someone will be both, especially at round start, but vampirism makes me wary of having these separate.
+/datum/quirk/hungry
+ name = "Hungry And Thirsty"
+ desc = "You find yourself unusually hungry and thirsty. Gotta eat and drink twice as much as normal."
+ value = -1
+ gain_text = "You're starting to feel hungrier and thirstier a lot faster. "
+ lose_text = "Your craving for food and water begins dying down. "
+ medical_record_text = "Patient reports eating twice as many meals per day than usual for their species."
+
+/datum/quirk/hungry/add()
+ var/mob/living/carbon/human/H = quirk_holder
+ var/datum/physiology/P = H.physiology
+ P.hunger_mod *= 2
+ P.thirst_mod *= 2
+
+/datum/quirk/hungry/remove()
+ var/mob/living/carbon/human/H = quirk_holder
+ if(H)
+ var/datum/physiology/P = H.physiology
+ P.hunger_mod /= 2
+ P.thirst_mod /= 2
diff --git a/modular_splurt/code/datums/traits/neutral.dm b/modular_splurt/code/datums/traits/neutral.dm
index 1d43343d46..5806c53c22 100644
--- a/modular_splurt/code/datums/traits/neutral.dm
+++ b/modular_splurt/code/datums/traits/neutral.dm
@@ -84,76 +84,6 @@
spell.Grant(Hypno_eyes)
spell.owner = Hypno_eyes
-/datum/action/innate/Hypnotize
- name = "Hypnotize"
- desc = "Stare deeply into someone's eyes, drawing them into a hypnotic slumber."
- button_icon_state = "Hypno_eye"
- icon_icon = 'modular_splurt/icons/mob/actions/lewd_actions/lewd_icons.dmi'
- background_icon_state = "bg_alien"
- var/mob/living/carbon/T //hypnosis target
- var/mob/living/carbon/human/H //Person with the quirk
-
-/datum/action/innate/Hypnotize/Activate()
- var/mob/living/carbon/human/H = owner
-
- if(!H.pulling || !isliving(H.pulling) || H.grab_state < GRAB_AGGRESSIVE)
- to_chat(H, "You need to aggressively grab someone to hypnotize them! ")
- return
-
- var/mob/living/carbon/T = H.pulling
-
- if(T.IsSleeping())
- to_chat(H, "You can't hypnotize [T] whilst they're asleep!")
- return
-
- to_chat(H, "You stare deeply into [T]'s eyes... ")
- to_chat(T, "[H] stares intensely into your eyes... ")
- if(!do_mob(H, T, 12 SECONDS))
- return
-
- if(H.pulling !=T || H.grab_state < GRAB_AGGRESSIVE)
- return
-
- if(!(H in view(1, H.loc)))
- return
-
- if(!(T.client?.prefs.cit_toggles & HYPNO))
- return
-
- var/response = alert(T, "Do you wish to fall into a hypnotic sleep?(This will allow [H] to issue hypnotic suggestions)", "Hypnosis", "Yes", "No")
-
- if(response == "Yes")
- T.visible_message("Your eyelids gently shut as you fall into a deep slumber. All you can hear is [H]'s voice as you commit to following all of their suggestions. ")
-
- T.SetSleeping(1200)
- T.drowsyness = max(T.drowsyness, 40)
- T = H.pulling
- var/response2 = alert(H, "Would you like to release your subject or give them a suggestion?", "Hypnosis", "Suggestion", "Release")
-
- if(response2 == "Suggestion")
- if(get_dist(H, T) > 1)
- to_chat(H, "You must stand in whisper range of [T].")
- return
-
- var/text = input("What would you like to suggest?", "Hypnotic suggestion", null, null)
- text = sanitize(text)
- if(!text)
- return
-
- to_chat(H, "You whisper your suggestion in a smooth calming voice to [T]")
- to_chat(T, "...[text]... ")
-
- T.visible_message("[T] wakes up from their deep slumber! ", "Your eyelids gently open as you see [H]'s face staring back at you. ")
- T.SetSleeping(0)
- T = null
- return
-
- if(response2 == "Release")
- T.SetSleeping(0)
- return
- else
- T.visible_message("[T]'s attention breaks, despite the attempt to hypnotize them! They clearly don't want this! ", "Your concentration breaks as you realise you have no interest in following [H]'s words! ")
- return
/datum/quirk/heat
name = "Estrus Detection"
desc = "You have a animalistic sense of detecting if someone is in heat."
@@ -337,33 +267,6 @@
resetspell.owner = hydra
hydra.name_archive = hydra.real_name
-
-/datum/action/innate/hydra
- name = "Switch head"
- desc = "Switch between each of the heads on your body."
- icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
- button_icon_state = "art_summon"
-
-/datum/action/innate/hydrareset
- name = "Reset speech"
- desc = "Go back to speaking as a whole."
- icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
- button_icon_state = "art_summon"
-
-/datum/action/innate/hydrareset/Activate()
- var/mob/living/carbon/human/hydra = owner
- hydra.real_name = hydra.name_archive
- hydra.visible_message("[hydra.name] pushes all three heads forwards; they seem to be talking as a collective. ", \
- "You are now talking as [hydra.name_archive]! ", ignored_mobs=owner)
-
-/datum/action/innate/hydra/Activate() //I hate this but its needed
- var/mob/living/carbon/human/hydra = owner
- var/list/names = splittext(hydra.name_archive,"-")
- var/selhead = input("Who would you like to speak as?","Heads:") in names
- hydra.real_name = selhead
- hydra.visible_message("[hydra.name] pulls the rest of their heads back; and puts [selhead]'s forward. ", \
- "You are now talking as [selhead]! ", ignored_mobs=owner)
-
//Own traits
/datum/quirk/cum_sniff
name = "Genital Taster"
@@ -383,6 +286,36 @@
. = ..()
var/obj/item/implant/genital_fluid/put_in = new
put_in.implant(quirk_holder, null, TRUE, TRUE)
+
+/datum/quirk/storage_concealment
+ name = "Dorsualiphobic Augmentation"
+ desc = "You despise the idea of being seen wearing any type of back-mounted storage apparatus! A new technology shields you from the immense shame you may experience, by hiding your equipped backpack."
+
+ // UNUSED: Enable by setting these values to TRUE
+ // The shame is unbearable
+ mood_quirk = FALSE
+ processing_quirk = FALSE
+ var/mood_category = "backpack_implant_mood"
+
+/datum/quirk/storage_concealment/on_spawn()
+ . = ..()
+
+ // Create a new augment item
+ var/obj/item/implant/hide_backpack/put_in = new
+
+ // Apply the augment to the quirk holder
+ put_in.implant(quirk_holder, null, TRUE, TRUE)
+
+/datum/quirk/storage_concealment/on_process()
+ // This trait should only be applied by the augment
+ // Check the quirk holder for the trait
+ if(HAS_TRAIT(quirk_holder, TRAIT_HIDE_BACKPACK))
+ // When found: Mood bonus
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, mood_category, /datum/mood_event/dorsualiphobic_mood_positive)
+ else
+ // When not found: Mood penalty
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, mood_category, /datum/mood_event/dorsualiphobic_mood_negative)
+
//succubus and incubus below
/datum/quirk/incubus
name = "Incubus"
@@ -531,6 +464,83 @@
W.Remove(H)
. = ..()
+
+/datum/quirk/gargoyle //Mmmm yes stone time
+ name = "Gargoyle"
+ desc = "You are some form of gargoyle! You can only leave your stone form for so long, and will have to return to it to regain energy. On the bright side, you heal in statue form!"
+ value = 0
+ processing_quirk = TRUE
+ var/energy = 0
+ var/transformed = 0
+ var/cooldown = 0
+ var/paused = 0
+ var/turf/position
+ var/obj/structure/statue/gargoyle/current = null
+
+/datum/quirk/gargoyle/add()
+ .=..()
+ var/mob/living/carbon/human/H = quirk_holder
+ if (!H)
+ return
+ var/datum/action/gargoyle/transform/T = new
+ var/datum/action/gargoyle/check/C = new
+ var/datum/action/gargoyle/pause/P = new
+ energy = 100
+ cooldown = 30
+ T.Grant(H)
+ C.Grant(H)
+ P.Grant(H)
+
+/datum/quirk/gargoyle/on_process()
+ .=..()
+ var/mob/living/carbon/human/H = quirk_holder
+
+ if (!H)
+ return
+
+ if(paused && H.loc != position)
+ paused = 0
+ energy -= 20
+
+ if(cooldown > 0)
+ cooldown--
+
+ if(!transformed && !paused && energy > 0)
+ energy -= 0.05
+
+ if(transformed)
+ energy = min(energy + 0.3, 100)
+ if (H.getBruteLoss() > 0 || H.getFireLoss() > 0)
+ H.adjustBruteLoss(-0.5, forced = TRUE)
+ H.adjustFireLoss(-0.5, forced = TRUE)
+ else if (H.getOxyLoss() > 0 || H.getToxLoss() > 0)
+ H.adjustToxLoss(-0.3, forced = TRUE)
+ H.adjustOxyLoss(-0.5, forced = TRUE) //oxyloss heals by itself, doesn't need a nerfed heal
+ else if (H.getCloneLoss() > 0)
+ H.adjustCloneLoss(-0.3, forced = TRUE)
+ else if (current && current.obj_integrity < current.max_integrity) //health == maxHealth is true since we checked all damages above
+ current.obj_integrity = min(current.obj_integrity + 0.1, current.max_integrity)
+
+ if(!transformed && energy <= 0)
+ var/datum/action/gargoyle/transform/T = locate() in H.actions
+ if (!T)
+ T = new
+ T.Grant(H)
+ cooldown = 0
+ T?.Trigger()
+
+/datum/quirk/gargoyle/remove()
+ var/mob/living/carbon/human/H = quirk_holder
+ if (!H)
+ return ..()
+ var/datum/action/gargoyle/transform/T = locate() in H.actions
+ var/datum/action/gargoyle/check/C = locate() in H.actions
+ var/datum/action/gargoyle/pause/P = locate() in H.actions
+ T?.Remove(H)
+ C?.Remove(H)
+ P?.Remove(H)
+ . = ..()
+
/datum/quirk/nudist
// Mostly derived from masked_mook.
// Spawning with a gear harness is preferable, but failed during testing.
@@ -552,6 +562,14 @@
else
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, mood_category, /datum/mood_event/nudist_negative)
+/datum/quirk/nudist/on_spawn()
+ . = ..()
+ // Spawn a Rapid Disrobe Implant
+ var/obj/item/implant/disrobe/quirk_implant = new
+
+ // Implant into quirk holder
+ quirk_implant.implant(quirk_holder, null, TRUE, TRUE)
+
/datum/quirk/masked_mook
name = "Bane Syndrome"
desc = "For some reason you don't feel... right without wearing some kind of gas mask."
@@ -577,170 +595,3 @@
var/obj/item/clothing/mask/gas/cosmetic/gasmask = new(get_turf(quirk_holder)) // Uses a custom gas mask
H.equip_to_slot(gasmask, ITEM_SLOT_MASK)
H.regenerate_icons()
-
-/// quirk actions ///
-
-//vampire bite
-
-#define BLOOD_DRAIN_NUM 50
-
-/datum/action/vbite
- name = "Bite"
- button_icon_state = "power_feed"
- icon_icon = 'icons/mob/actions/bloodsucker.dmi'
- desc = "Sink your vampiric fangs into the person you are grabbing."
- var/drain_cooldown = 0
-
-/datum/action/vbite/Trigger()
- . = ..()
- if(iscarbon(owner))
- var/mob/living/carbon/H = owner
- if(H.nutrition >= 500)
- to_chat(H, "You are too full to drain any more. ")
- return
- if(drain_cooldown >= world.time)
- to_chat(H, "You just drained blood, wait a few seconds. ")
- return
- if(!H.pulling || !iscarbon(H.pulling))
- if(H.getStaminaLoss() >= 80 && H.nutrition > 20)//prevents being stunlocked in the chapel
- to_chat(H,("you use some of your power to energize "))
- H.adjustStaminaLoss(-20)
- H.adjust_nutrition(-20)
- H.resting = TRUE
- if(H.pulling && (iscarbon(H.pulling) || (istype(H.pulling,/obj/structure/arachnid/cocoon) && locate(/mob/living/carbon) in H.pulling.contents)))
- var/mob/living/carbon/victim
- if(iscarbon(H.pulling))
- victim = H.pulling
- else if(istype(H.pulling,/obj/structure/arachnid/cocoon))
- victim = locate(/mob/living/carbon) in H.pulling.contents
- drain_cooldown = world.time + 25
- if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0))
- to_chat(victim, "[H] tries to bite you, but stops before touching you! ")
- to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire. ")
- return
- //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream.
- if(!blood_sucking_checks(victim, TRUE, TRUE))
- return
- H.visible_message("[H] bites down on [victim]'s neck! ")
- victim.add_splatter_floor(get_turf(victim), TRUE)
- to_chat(victim, "[H] is draining your blood! ")
- if(!do_after(H, 30, target = victim))
- return
- var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
- var/drained_blood = min(victim.blood_volume, BLOOD_DRAIN_NUM, blood_volume_difference)
- H.reagents.add_reagent(/datum/reagent/blood/, drained_blood)
- to_chat(victim, "[H] has taken some of your blood! ")
- to_chat(H, "You drain some blood! ")
- playsound(H, 'sound/items/drink.ogg', 30, 1, -2)
- victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
- log_combat(H,victim,"vampire bit")//logs the biting action for admins
- if(!victim.blood_volume)
- to_chat(H, "You finish off [victim]'s blood supply! ")
-
-
-/datum/action/vrevive
- name = "Resurrect"
- button_icon_state = "power_strength"
- icon_icon = 'icons/mob/actions/bloodsucker.dmi'
- desc = "Use all your energy to come back to life!"
-
-/datum/action/vrevive/Trigger()
- . = ..()
- var/mob/living/carbon/C = owner
- var/mob/living/carbon/human/H = owner
- if(H.stat == DEAD && istype(C.loc, /obj/structure/closet/crate/coffin))
- H.revive(TRUE, FALSE)
- H.set_nutrition(0)
- H.Daze(20)
- H.drunkenness = 70
- else
- to_chat(H,"You need to be dead and in a coffin to revive! ")
-
-//splurt change end
-//put next quirk action here
-
-//werewolf tf
-
-/datum/action/werewolf
- name = "Transform"
- desc = "Transform into your wolf form."
- icon_icon = 'modular_splurt/icons/mob/actions/misc_actions.dmi'
- button_icon_state = "Transform"
- var/transformed = FALSE
- var/list/old_features = list("species" = SPECIES_HUMAN, "legs" = "Plantigrade", "size" = 1, "bark")
-
-/datum/action/werewolf/Trigger()
- . = ..()
- var/mob/living/carbon/human/H = owner
- var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
- var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS)
- var/obj/item/organ/genital/vagina/V = H.getorganslot(ORGAN_SLOT_VAGINA)
- H.shake_animation(2)
- if(!transformed) // transform them
- H.visible_message(span_danger("[H] shivers, their flesh bursting with a sudden growth of thick fur and their features contorting to that of a beast's, fully transforming them into a werewolf!"))
- H.set_species(/datum/species/mammal, 1)
- H.dna.species.mutant_bodyparts["mam_tail"] = "Wolf"
- H.dna.species.mutant_bodyparts["legs"] = "Digitigrade"
- H.Digitigrade_Leg_Swap(FALSE)
- H.dna.species.mutant_bodyparts["mam_snouts"] = "Mammal, Thick"
- H.dna.features["mam_ears"] = "Wolf"
- H.dna.features["mam_tail"] = "Wolf"
- H.dna.features["mam_snouts"] = "Mammal, Thick"
- H.dna.features["legs"] = "Digitigrade"
- H.update_size(get_size(H) + 0.5)
- H.set_bark("bark")
- H.custom_species = "Werewolf"
- if(!(H.dna.species.species_traits.Find(DIGITIGRADE)))
- H.dna.species.species_traits += DIGITIGRADE
- H.update_body()
- H.update_body_parts()
- if(B)
- B.color = "#[H.dna.features["mcolor"]]"
- B.update()
- if(P)
- P.shape = "Knotted"
- P.color = "#ff7c80"
- P.update()
- P.modify_size(6)
- if(V)
- V.shape = "Furred"
- V.color = "#[H.dna.features["mcolor"]]"
- V.update()
- else // untransform them
- H.visible_message(span_danger("[H] shrinks, their wolfish features quickly receding."))
- H.set_species(old_features["species"], TRUE)
- H.set_bark(old_features["bark"])
- H.dna.features["mam_ears"] = old_features["mam_ears"]
- H.dna.features["mam_snouts"] = old_features["mam_snouts"]
- H.dna.features["mam_tail"] = old_features["mam_tail"]
- H.dna.features["legs"] = old_features["legs"] //i hate legs i hate legs i hate legs i hate legs i hate legs i hate legs i hate legs
- if(old_features["legs"] == "Plantigrade")
- H.dna.species.species_traits -= DIGITIGRADE
- H.Digitigrade_Leg_Swap(TRUE)
- H.dna.species.mutant_bodyparts["legs"] = old_features["legs"]
- H.update_body()
- H.update_body_parts()
- H.update_size(get_size(H) - 0.5)
- if(B)
- B.color = "#[old_features["breasts_color"]]"
- B.update()
- if(H.has_penis())
- P.shape = old_features["cock_shape"]
- P.color = "#[old_features["cock_color"]]"
- P.update()
- P.modify_size(-6)
- if(H.has_vagina())
- V.shape = old_features["vag_shape"]
- V.color = "#[old_features["vag_color"]]"
- V.update()
- V.update_size()
- transformed = !transformed
-
-/datum/action/werewolf/Grant()// on grant sets some variables
- . = ..()
- var/mob/living/carbon/human/H = owner
- old_features = H.dna.features.Copy()
- old_features["species"] = H.dna.species.type
- old_features["size"] = get_size(H)
- old_features["bark"] = H.vocal_bark_id
-
diff --git a/modular_splurt/code/datums/traits/trait_actions.dm b/modular_splurt/code/datums/traits/trait_actions.dm
new file mode 100644
index 0000000000..2c8cdf79ca
--- /dev/null
+++ b/modular_splurt/code/datums/traits/trait_actions.dm
@@ -0,0 +1,343 @@
+#define BLOOD_DRAIN_NUM 50
+
+//
+// Quirk: Hypnotic Gaze
+//
+
+/datum/action/innate/Hypnotize
+ name = "Hypnotize"
+ desc = "Stare deeply into someone's eyes, drawing them into a hypnotic slumber."
+ button_icon_state = "Hypno_eye"
+ icon_icon = 'modular_splurt/icons/mob/actions/lewd_actions/lewd_icons.dmi'
+ background_icon_state = "bg_alien"
+ var/mob/living/carbon/T //hypnosis target
+ var/mob/living/carbon/human/H //Person with the quirk
+
+/datum/action/innate/Hypnotize/Activate()
+ var/mob/living/carbon/human/H = owner
+
+ if(!H.pulling || !isliving(H.pulling) || H.grab_state < GRAB_AGGRESSIVE)
+ to_chat(H, "You need to aggressively grab someone to hypnotize them! ")
+ return
+
+ var/mob/living/carbon/T = H.pulling
+
+ if(T.IsSleeping())
+ to_chat(H, "You can't hypnotize [T] whilst they're asleep!")
+ return
+
+ to_chat(H, "You stare deeply into [T]'s eyes... ")
+ to_chat(T, "[H] stares intensely into your eyes... ")
+ if(!do_mob(H, T, 12 SECONDS))
+ return
+
+ if(H.pulling !=T || H.grab_state < GRAB_AGGRESSIVE)
+ return
+
+ if(!(H in view(1, H.loc)))
+ return
+
+ if(!(T.client?.prefs.cit_toggles & HYPNO))
+ return
+
+ var/response = alert(T, "Do you wish to fall into a hypnotic sleep?(This will allow [H] to issue hypnotic suggestions)", "Hypnosis", "Yes", "No")
+
+ if(response == "Yes")
+ T.visible_message("Your eyelids gently shut as you fall into a deep slumber. All you can hear is [H]'s voice as you commit to following all of their suggestions. ")
+
+ T.SetSleeping(1200)
+ T.drowsyness = max(T.drowsyness, 40)
+ T = H.pulling
+ var/response2 = alert(H, "Would you like to release your subject or give them a suggestion?", "Hypnosis", "Suggestion", "Release")
+
+ if(response2 == "Suggestion")
+ if(get_dist(H, T) > 1)
+ to_chat(H, "You must stand in whisper range of [T].")
+ return
+
+ var/text = input("What would you like to suggest?", "Hypnotic suggestion", null, null)
+ text = sanitize(text)
+ if(!text)
+ return
+
+ to_chat(H, "You whisper your suggestion in a smooth calming voice to [T]")
+ to_chat(T, "...[text]... ")
+
+ T.visible_message("[T] wakes up from their deep slumber! ", "Your eyelids gently open as you see [H]'s face staring back at you. ")
+ T.SetSleeping(0)
+ T = null
+ return
+
+ if(response2 == "Release")
+ T.SetSleeping(0)
+ return
+ else
+ T.visible_message("[T]'s attention breaks, despite the attempt to hypnotize them! They clearly don't want this! ", "Your concentration breaks as you realise you have no interest in following [H]'s words! ")
+ return
+
+//
+// Quirk: Hydra Heads
+//
+
+/datum/action/innate/hydra
+ name = "Switch head"
+ desc = "Switch between each of the heads on your body."
+ icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
+ button_icon_state = "art_summon"
+
+/datum/action/innate/hydrareset
+ name = "Reset speech"
+ desc = "Go back to speaking as a whole."
+ icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
+ button_icon_state = "art_summon"
+
+/datum/action/innate/hydrareset/Activate()
+ var/mob/living/carbon/human/hydra = owner
+ hydra.real_name = hydra.name_archive
+ hydra.visible_message("[hydra.name] pushes all three heads forwards; they seem to be talking as a collective. ", \
+ "You are now talking as [hydra.name_archive]! ", ignored_mobs=owner)
+
+/datum/action/innate/hydra/Activate() //I hate this but its needed
+ var/mob/living/carbon/human/hydra = owner
+ var/list/names = splittext(hydra.name_archive,"-")
+ var/selhead = input("Who would you like to speak as?","Heads:") in names
+ hydra.real_name = selhead
+ hydra.visible_message("[hydra.name] pulls the rest of their heads back; and puts [selhead]'s forward. ", \
+ "You are now talking as [selhead]! ", ignored_mobs=owner)
+
+//
+// Quirk: Bloodsucker Fledgling / Vampire
+//
+
+/datum/action/vbite
+ name = "Bite"
+ button_icon_state = "power_feed"
+ icon_icon = 'icons/mob/actions/bloodsucker.dmi'
+ desc = "Sink your vampiric fangs into the person you are grabbing."
+ var/drain_cooldown = 0
+
+/datum/action/vbite/Trigger()
+ . = ..()
+ if(iscarbon(owner))
+ var/mob/living/carbon/H = owner
+ if(H.nutrition >= 500)
+ to_chat(H, "You are too full to drain any more. ")
+ return
+ if(drain_cooldown >= world.time)
+ to_chat(H, "You just drained blood, wait a few seconds. ")
+ return
+ if(!H.pulling || !iscarbon(H.pulling))
+ if(H.getStaminaLoss() >= 80 && H.nutrition > 20)//prevents being stunlocked in the chapel
+ to_chat(H,("you use some of your power to energize "))
+ H.adjustStaminaLoss(-20)
+ H.adjust_nutrition(-20)
+ H.resting = TRUE
+ if(H.pulling && (iscarbon(H.pulling) || (istype(H.pulling,/obj/structure/arachnid/cocoon) && locate(/mob/living/carbon) in H.pulling.contents)))
+ var/mob/living/carbon/victim
+ if(iscarbon(H.pulling))
+ victim = H.pulling
+ else if(istype(H.pulling,/obj/structure/arachnid/cocoon))
+ victim = locate(/mob/living/carbon) in H.pulling.contents
+ drain_cooldown = world.time + 25
+ if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0))
+ to_chat(victim, "[H] tries to bite you, but stops before touching you! ")
+ to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire. ")
+ return
+ //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream.
+ if(!blood_sucking_checks(victim, TRUE, TRUE))
+ return
+ H.visible_message("[H] bites down on [victim]'s neck! ")
+ victim.add_splatter_floor(get_turf(victim), TRUE)
+ to_chat(victim, "[H] is draining your blood! ")
+ if(!do_after(H, 30, target = victim))
+ return
+ var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood
+ var/drained_blood = min(victim.blood_volume, BLOOD_DRAIN_NUM, blood_volume_difference)
+ H.reagents.add_reagent(/datum/reagent/blood/, drained_blood)
+ to_chat(victim, "[H] has taken some of your blood! ")
+ to_chat(H, "You drain some blood! ")
+ playsound(H, 'sound/items/drink.ogg', 30, 1, -2)
+ victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM)
+ log_combat(H,victim,"vampire bit")//logs the biting action for admins
+ if(!victim.blood_volume)
+ to_chat(H, "You finish off [victim]'s blood supply! ")
+
+
+/datum/action/vrevive
+ name = "Resurrect"
+ button_icon_state = "power_strength"
+ icon_icon = 'icons/mob/actions/bloodsucker.dmi'
+ desc = "Use all your energy to come back to life!"
+
+/datum/action/vrevive/Trigger()
+ . = ..()
+ var/mob/living/carbon/C = owner
+ var/mob/living/carbon/human/H = owner
+ if(H.stat == DEAD && istype(C.loc, /obj/structure/closet/crate/coffin))
+ H.revive(TRUE, FALSE)
+ H.set_nutrition(0)
+ H.Daze(20)
+ H.drunkenness = 70
+ else
+ to_chat(H,"You need to be dead and in a coffin to revive! ")
+
+//
+// Quirk: Werewolf
+//
+
+/datum/action/werewolf
+ name = "Transform"
+ desc = "Transform into your wolf form."
+ icon_icon = 'modular_splurt/icons/mob/actions/misc_actions.dmi'
+ button_icon_state = "Transform"
+ var/transformed = FALSE
+ var/list/old_features = list("species" = SPECIES_HUMAN, "legs" = "Plantigrade", "size" = 1, "bark")
+
+/datum/action/werewolf/Trigger()
+ . = ..()
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
+ var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS)
+ var/obj/item/organ/genital/vagina/V = H.getorganslot(ORGAN_SLOT_VAGINA)
+ H.shake_animation(2)
+ if(!transformed) // transform them
+ H.visible_message(span_danger("[H] shivers, their flesh bursting with a sudden growth of thick fur and their features contorting to that of a beast's, fully transforming them into a werewolf!"))
+ H.set_species(/datum/species/mammal, 1)
+ H.dna.species.mutant_bodyparts["mam_tail"] = "Wolf"
+ H.dna.species.mutant_bodyparts["legs"] = "Digitigrade"
+ H.Digitigrade_Leg_Swap(FALSE)
+ H.dna.species.mutant_bodyparts["mam_snouts"] = "Mammal, Thick"
+ H.dna.features["mam_ears"] = "Wolf"
+ H.dna.features["mam_tail"] = "Wolf"
+ H.dna.features["mam_snouts"] = "Mammal, Thick"
+ H.dna.features["legs"] = "Digitigrade"
+ H.update_size(get_size(H) + 0.5)
+ H.set_bark("bark")
+ H.custom_species = "Werewolf"
+ if(!(H.dna.species.species_traits.Find(DIGITIGRADE)))
+ H.dna.species.species_traits += DIGITIGRADE
+ H.update_body()
+ H.update_body_parts()
+ if(B)
+ B.color = "#[H.dna.features["mcolor"]]"
+ B.update()
+ if(P)
+ P.shape = "Knotted"
+ P.color = "#ff7c80"
+ P.update()
+ P.modify_size(6)
+ if(V)
+ V.shape = "Furred"
+ V.color = "#[H.dna.features["mcolor"]]"
+ V.update()
+ else // untransform them
+ H.visible_message(span_danger("[H] shrinks, their wolfish features quickly receding."))
+ H.set_species(old_features["species"], TRUE)
+ H.set_bark(old_features["bark"])
+ H.dna.features["mam_ears"] = old_features["mam_ears"]
+ H.dna.features["mam_snouts"] = old_features["mam_snouts"]
+ H.dna.features["mam_tail"] = old_features["mam_tail"]
+ H.dna.features["legs"] = old_features["legs"] //i hate legs i hate legs i hate legs i hate legs i hate legs i hate legs i hate legs
+ if(old_features["legs"] == "Plantigrade")
+ H.dna.species.species_traits -= DIGITIGRADE
+ H.Digitigrade_Leg_Swap(TRUE)
+ H.dna.species.mutant_bodyparts["legs"] = old_features["legs"]
+ H.update_body()
+ H.update_body_parts()
+ H.update_size(get_size(H) - 0.5)
+ if(B)
+ B.color = "#[old_features["breasts_color"]]"
+ B.update()
+ if(H.has_penis())
+ P.shape = old_features["cock_shape"]
+ P.color = "#[old_features["cock_color"]]"
+ P.update()
+ P.modify_size(-6)
+ if(H.has_vagina())
+ V.shape = old_features["vag_shape"]
+ V.color = "#[old_features["vag_color"]]"
+ V.update()
+ V.update_size()
+ transformed = !transformed
+
+/datum/action/werewolf/Grant()// on grant sets some variables
+ . = ..()
+ var/mob/living/carbon/human/H = owner
+ old_features = H.dna.features.Copy()
+ old_features["species"] = H.dna.species.type
+ old_features["size"] = get_size(H)
+ old_features["bark"] = H.vocal_bark_id
+
+
+/datum/action/gargoyle/transform
+ name = "Transform"
+ desc = "Transform into a statue, regaining energy in the process. Additionally, you will slowly heal while in statue form."
+ icon_icon = 'icons/mob/actions/actions_changeling.dmi'
+ button_icon_state = "ling_camouflage"
+ var/obj/structure/statue/gargoyle/current = null
+
+
+/datum/action/gargoyle/transform/Trigger()
+ .=..()
+ var/mob/living/carbon/human/H = owner
+ var/datum/quirk/gargoyle/T = locate() in H.roundstart_quirks
+ if(!T.cooldown)
+ if(!T.transformed)
+ if(!isturf(H.loc))
+ return 0
+ var/obj/structure/statue/gargoyle/S = new(H.loc, H)
+ S.name = "statue of [H.name]"
+ H.bleedsuppress = 1
+ S.copy_overlays(H)
+ var/newcolor = list(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
+ S.add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY)
+ current = S
+ T.transformed = 1
+ T.cooldown = 30
+ T.paused = 0
+ S.dir = H.dir
+ return 1
+ else
+ qdel(current)
+ T.transformed = 0
+ T.cooldown = 30
+ T.paused = 0
+ H.visible_message("[H]'s skin rapidly softens, returning them to normal! ", "Your skin softens, freeing your movement once more! ")
+ else
+ to_chat(H, "You have transformed too recently; you cannot yet transform again! ")
+ return 0
+
+//
+// Quirk: Gargoyle
+//
+
+/datum/action/gargoyle/check
+ name = "Check"
+ desc = "Check your current energy levels."
+ icon_icon = 'icons/mob/actions/actions_clockcult.dmi'
+ button_icon_state = "Linked Vanguard"
+
+/datum/action/gargoyle/check/Trigger()
+ .=..()
+ var/mob/living/carbon/human/H = owner
+ var/datum/quirk/gargoyle/T = locate() in H.roundstart_quirks
+ to_chat(H, "You have [T.energy]/100 energy remaining! ")
+
+/datum/action/gargoyle/pause
+ name = "Preserve"
+ desc = "Become near-motionless, thusly conserving your energy until you move from your current tile. Note, you will lose a chunk of energy when you inevitably move from your current position, so you cannot abuse this!"
+ icon_icon = 'icons/mob/actions/actions_flightsuit.dmi'
+ button_icon_state = "flightsuit_lock"
+
+/datum/action/gargoyle/pause/Trigger()
+ .=..()
+ var/mob/living/carbon/human/H = owner
+ var/datum/quirk/gargoyle/T = locate() in H.roundstart_quirks
+
+ if(!T.paused)
+ T.paused = 1
+ T.position = H.loc
+ to_chat(H, "You are now conserving your energy; this effect will end the moment you move from your current position! ")
+ return
+ else
+ to_chat(H, "You are already conserving your energy! ")
diff --git a/modular_splurt/code/game/area/areas/holodeck.dm b/modular_splurt/code/game/area/areas/holodeck.dm
new file mode 100644
index 0000000000..2e60a0e247
--- /dev/null
+++ b/modular_splurt/code/game/area/areas/holodeck.dm
@@ -0,0 +1,7 @@
+// Replacement for holodeck plasma module
+/area/holodeck/rec_center/burn
+ name = "Holodeck - CRITICAL ERROR"
+
+// Replacement for holodeck carp module
+/area/holodeck/rec_center/wildlife
+ name = "Holodeck - Wasteland Simulation"
diff --git a/modular_splurt/code/game/objects/items/devices/PDA/radio.dm b/modular_splurt/code/game/objects/items/devices/PDA/radio.dm
new file mode 100644
index 0000000000..016d1f10ef
--- /dev/null
+++ b/modular_splurt/code/game/objects/items/devices/PDA/radio.dm
@@ -0,0 +1,4 @@
+/obj/item/cartridge/cmo/Initialize(mapload)
+ //adds chemistry access
+ access |= CART_CHEMISTRY
+ . = ..()
diff --git a/modular_splurt/code/game/objects/items/implants/implant_disrobe.dm b/modular_splurt/code/game/objects/items/implants/implant_disrobe.dm
new file mode 100644
index 0000000000..e8656ab155
--- /dev/null
+++ b/modular_splurt/code/game/objects/items/implants/implant_disrobe.dm
@@ -0,0 +1,67 @@
+/obj/item/implant/disrobe
+ name = "rapid disrobe implant"
+ icon = 'icons/obj/clothing/uniforms.dmi'
+ icon_state = "grey"
+
+ // Custom action for extra customization
+ actions_types = list(/datum/action/item_action/disrobe)
+
+// Implant flavor text
+/obj/item/implant/disrobe_ultra/get_data()
+ // Define text variable
+ var/dat = {"
+ Implant Specifications:
+ Name: Rapid Disrobe Implant
+ Important Notes: Nanotransen requires employees to follow workplace safety standards, including protective clothing.
+
+ Implant Details:
+ Function: Lines the subject's epidermis with high power static charge nodes, allowing the rapid removal of worn clothing.
+ Special Features: Will not cause drunkenness in most subjects.
+ Integrity: Implant will last so long as it is inside the host.
+ "}
+
+ // Return text
+ return dat
+
+// Only allow use on "human" targets
+/obj/item/implant/disrobe/can_be_implanted_in(mob/living/target)
+ if(!ishuman(target))
+ return FALSE
+ . = ..()
+
+// Runs on toggling the implant
+/obj/item/implant/disrobe/activate()
+ . = ..()
+
+ // Define target
+ var/mob/living/carbon/target_user = imp_in
+
+ // Perform LPD effect
+ target_user.clothing_burst(target_user)
+
+/*
+ * Action datums
+*/
+
+// Action for rapid wardrobe removal
+/datum/action/item_action/disrobe
+ name = "Rapid Disrobe"
+ desc = "Instantly eject all covering clothing from your body."
+ icon_icon = 'modular_splurt/icons/mob/actions/misc_actions.dmi'
+ button_icon_state = "no_uniform"
+ background_icon_state = "bg_tech"
+
+/*
+ * Implant items
+*/
+
+// Implanter item
+/obj/item/implanter/disrobe
+ name = "implanter (rapid disrobe)"
+ imp_type = /obj/item/implant/disrobe
+
+// Implant case item
+/obj/item/implantcase/disrobe
+ name = "implant case - 'rapid disrobe'"
+ desc = "A glass case containing a rapid disrobe implant."
+ imp_type = /obj/item/implant/disrobe
diff --git a/modular_splurt/code/game/objects/items/implants/implant_gfluid.dm b/modular_splurt/code/game/objects/items/implants/implant_gfluid.dm
index 8c54ed9d3c..a337f5aa44 100644
--- a/modular_splurt/code/game/objects/items/implants/implant_gfluid.dm
+++ b/modular_splurt/code/game/objects/items/implants/implant_gfluid.dm
@@ -4,6 +4,10 @@
icon_state = "genital_fluid"
var/use_blacklist = TRUE
+ // Custom action for extra customization
+ actions_types = list(/datum/action/item_action/genital_fluid_infuse)
+
+// Implant flavor text
/obj/item/implant/genital_fluid/get_data()
var/dat = {"Implant Specifications:
Name: Nanotrasen Genital Fluid Inducer Implant
@@ -12,69 +16,119 @@
Implant Details:
Function: Allows the user to induce their genitals into producing a specific reagent.
Special Features: Will prevent harmful liquids from being accepted as a genital fluid replace.
- Integrity: Implant will last so long as the implant is inside the host and they posess genitals capable of fluid production."}
+ Integrity: Implant will last so long as the implant is inside the host and they possess genitals capable of fluid production."}
return dat
+// Only allow use on "human" targets
/obj/item/implant/genital_fluid/can_be_implanted_in(mob/living/target)
if(!ishuman(target))
return FALSE
. = ..()
+// Runs on toggling the implant
/obj/item/implant/genital_fluid/activate()
. = ..()
- var/list/obj/item/organ/genital/penidlist
- var/list/datum/reagent/fluidlist = list()
- var/mob/living/carbon/human/owner = imp_in
- //List their genitals if they have any at all
- for(var/obj/item/organ/genital/dicc in owner.internal_organs)
- if(istype(dicc) && (dicc.genital_flags & GENITAL_FUID_PRODUCTION))
- LAZYADD(penidlist, dicc)
+ // Set list of possible genitals
+ var/list/obj/item/organ/genital/genitals_list
+
+ // Set list of possible fluids
+ var/list/datum/reagent/fluid_list = list()
+
+ // Set owner
+ var/mob/living/carbon/human/genital_owner = imp_in
- //List their current reagents if they're valid
- for(var/datum/reagent/pee in owner.reagents.reagent_list)
- if((find_reagent_object_from_type(pee.type)) && ((pee.type in allowed_gfluid_paths()) || !use_blacklist))
- LAZYADD(fluidlist, find_reagent_object_from_type(pee.type))
+ // List their genitals if they have any at all
+ for(var/obj/item/organ/genital/genital_checked in genital_owner.internal_organs)
+ if(istype(genital_checked) && (genital_checked.genital_flags & GENITAL_FUID_PRODUCTION))
+ // Add genitals to the list
+ LAZYADD(genitals_list, genital_checked)
- //List any reagents they may be holding in their hands
- if(owner.available_rosie_palms(TRUE, /obj/item/reagent_containers))
- for(var/obj/item/reagent_containers/container in owner.held_items)
+ // List their current reagents if they're valid
+ for(var/datum/reagent/genital_reagent in genital_owner.reagents.reagent_list)
+ if((find_reagent_object_from_type(genital_reagent.type)) && ((genital_reagent.type in allowed_gfluid_paths()) || !use_blacklist))
+ // Add valid reagents to the list
+ LAZYADD(fluid_list, find_reagent_object_from_type(genital_reagent.type))
+
+ // List any reagents they may be holding in their hands
+ if(genital_owner.available_rosie_palms(TRUE, /obj/item/reagent_containers))
+ for(var/obj/item/reagent_containers/container in genital_owner.held_items)
if(container.is_open_container() || istype(container, /obj/item/reagent_containers/food/snacks))
- for(var/datum/reagent/pee in container.reagents.reagent_list)
- if((find_reagent_object_from_type(pee.type)) && ((pee.type in allowed_gfluid_paths()) || !use_blacklist))
- LAZYADD(fluidlist, find_reagent_object_from_type(pee.type))
+ for(var/datum/reagent/genital_reagent in container.reagents.reagent_list)
+ if((find_reagent_object_from_type(genital_reagent.type)) && ((genital_reagent.type in allowed_gfluid_paths()) || !use_blacklist))
+ // Add valid reagents to the list
+ LAZYADD(fluid_list, find_reagent_object_from_type(genital_reagent.type))
- //Return if genitals list is void/null
- if(!penidlist)
- SEND_SOUND(owner, 'sound/machines/terminal_error.ogg')
- to_chat(owner, span_notice("ERROR: No compatible genitals detected."))
+ // Return if genitals list is void/null
+ if(!genitals_list)
+ // Play an error sound
+ SEND_SOUND(genital_owner, 'sound/machines/terminal_error.ogg')
+
+ // Alert the user in chat
+ to_chat(genital_owner, span_notice("ERROR: No compatible genitals detected."))
+
+ // Escape
return
- var/obj/item/organ/genital/cocc = tgui_input_list(owner, "Pick a genital", "Genital Fluid Infuser", penidlist)
- if(!cocc)
+ // Prompt user for which genital to use
+ var/obj/item/organ/genital/genital_input = tgui_input_list(genital_owner, "Pick a genital", "Genital Fluid Infuser", genitals_list)
+ if(!genital_input)
+ // No selection was made
return
- fluidlist = list(find_reagent_object_from_type(cocc.get_default_fluid())) + fluidlist
+ // Update list of possible fluids
+ fluid_list = list(find_reagent_object_from_type(genital_input.get_default_fluid())) + fluid_list
- var/datum/reagent/selection = tgui_input_list(owner, "Choose your new reagent", "Genital Fluid Infuser", fluidlist)
- if(!selection)
+ // Prompt user to select a new fluid
+ var/datum/reagent/reagent_selection = tgui_input_list(genital_owner, "Choose your new reagent", "Genital Fluid Infuser", fluid_list)
+ if(!reagent_selection)
+ // No selection was made
return
- cocc.fluid_id = selection.type
- SEND_SOUND(owner, 'sound/effects/bubbles.ogg')
- to_chat(owner, span_notice("You feel the fluids inside your [cocc.name] bubble and swirl..."))
- message_admins("[ADMIN_LOOKUPFLW(owner)] changed the fluid of their [owner.p_their()] [cocc.name] to [selection].")
+ // Set new fluid
+ genital_input.fluid_id = reagent_selection.type
+
+ // Play the reagent processing sound effect
+ SEND_SOUND(genital_owner, 'sound/effects/bubbles.ogg')
+
+ // Display flavor text
+ to_chat(genital_owner, span_notice("You feel the fluids inside your [genital_input.name] bubble and swirl..."))
+ // Send admin notice
+ message_admins("[ADMIN_LOOKUPFLW(genital_owner)] changed the fluid of [genital_owner.p_their()] [genital_input.name] to [reagent_selection].")
+
+// Unlock with an emag
/obj/item/implant/genital_fluid/emag_act()
. = ..()
name = "hacked genital fluid implant"
use_blacklist = FALSE
obj_flags |= EMAGGED
+/*
+ * Action datum
+*/
+
+// Action for updating genital fluids
+/datum/action/item_action/genital_fluid_infuse
+ name = "Infuse Genital Fluids"
+ desc = "Activate an integrated reagent receptor device to modify your genital contents."
+ icon_icon = 'modular_splurt/icons/obj/implants.dmi'
+ button_icon_state = "genital_fluid"
+ background_icon_state = "bg_tech"
+
+ // Restrict non-synthesizable reagents?
+ var/use_blacklist = TRUE
+
+/*
+ * Implant items
+*/
+
+// Implanter item
/obj/item/implanter/genital_fluid
name = "implanter (genital fluid)"
imp_type = /obj/item/implant/genital_fluid
+// Implanter item, emagged
/obj/item/implanter/genital_fluid/hacked
name = "implanter (genital fluid (hacked))"
@@ -84,11 +138,13 @@
var/obj/item/implant/genital_fluid/I = imp
I.emag_act()
+// Implant case item
/obj/item/implantcase/genital_fluid
name = "implant case - 'Genital Fluid'"
desc = "A glass case containing a Genital Fluid Infuser implant."
imp_type = /obj/item/implant/genital_fluid
+// Implant case item, emagged
/obj/item/implantcase/genital_fluid/hacked
name = "implant case - 'Genital Fluid (Hacked)'"
diff --git a/modular_splurt/code/game/objects/items/implants/implant_hide_backpack.dm b/modular_splurt/code/game/objects/items/implants/implant_hide_backpack.dm
new file mode 100644
index 0000000000..a4c02279a2
--- /dev/null
+++ b/modular_splurt/code/game/objects/items/implants/implant_hide_backpack.dm
@@ -0,0 +1,117 @@
+/obj/item/implant/hide_backpack
+ name = "storage concealment implant"
+ desc = "Prevents your backpack from being observable by the naked eye."
+ icon = 'modular_splurt/icons/obj/storage.dmi'
+ icon_state = "backpack_faded"
+
+ // Custom action for extra customization
+ actions_types = list(/datum/action/item_action/hide_backpack)
+
+// Implant flavor text
+/obj/item/implant/hide_backpack/get_data()
+ var/dat = {"Implant Specifications:
+ Name: Chameleon Storage Concealment Implant
+ Important Notes: Pending approval from some security teams.
+
+ Implant Details:
+ Function: Subject emits a weak psychic signal that conceals the presence of back-equipped gear items.
+ Integrity: Implant will last so long as the implant is inside the host."}
+ return dat
+
+// Only allow use on "human" targets
+/obj/item/implant/hide_backpack/can_be_implanted_in(mob/living/target)
+ if(!ishuman(target))
+ return FALSE
+ . = ..()
+
+/*
+ * Action datum
+*/
+
+// Action for toggling backpack
+/datum/action/item_action/hide_backpack
+ name = "Conceal Backwear"
+ desc = "Toggle a weak psychic signal that conceals the presence of back-equipped gear items."
+ icon_icon = 'modular_splurt/icons/obj/storage.dmi'
+ button_icon_state = "backpack_faded"
+ background_icon_state = "bg_tech"
+
+ // Is this being used?
+ var/ability_active = TRUE
+
+// Runs on gaining the ability
+/datum/action/item_action/hide_backpack/Grant(mob/user)
+ . = ..()
+
+ // Add the trait
+ adjust_trait(TRUE)
+
+// Runs on losing the ability
+/datum/action/item_action/hide_backpack/Remove(mob/user)
+ . = ..()
+
+ // Remove the trait
+ adjust_trait(FALSE)
+
+// Function to update trait
+/datum/action/item_action/hide_backpack/proc/adjust_trait(state)
+ // Set owner
+ var/mob/living/carbon/human/action_owner = owner
+
+ // Toggle trait status
+ if(state)
+ ADD_TRAIT(action_owner, TRAIT_HIDE_BACKPACK, TRAIT_GENERIC)
+ else
+ REMOVE_TRAIT(action_owner, TRAIT_HIDE_BACKPACK, TRAIT_GENERIC)
+
+ // Update sprites
+ action_owner.update_inv_back()
+
+// Runs on toggling the ability
+/datum/action/item_action/hide_backpack/Trigger()
+ // Set owner
+ var/mob/living/carbon/human/action_owner = owner
+
+ // Update active status
+ ability_active = !ability_active
+
+ // Update trait
+ adjust_trait(ability_active)
+
+ // Set icon state variables
+ if(ability_active)
+ // Half-faded backpack
+ icon_icon = 'modular_splurt/icons/obj/storage.dmi'
+ button_icon_state = "backpack_faded"
+ else
+ // Normal backpack
+ icon_icon = 'icons/obj/storage.dmi'
+ button_icon_state = "backpack"
+
+ // Update icon state
+ UpdateButtonIcon()
+
+ // Display fake sparks to match flavor text
+ do_fake_sparks(2,FALSE,action_owner)
+
+ // Set toggle text based on active state
+ var/implant_toggle_text = (!ability_active ? "discernible" : "imperceptible")
+ var/implant_toggle_text_2 = (!ability_active ? "dis" : "") // Engage or Disengage
+
+ // Display a chat message
+ action_owner.visible_message("The equipment worn on [action_owner]'s back-region flickers momentarily, before becoming [implant_toggle_text]. ", "You [implant_toggle_text_2]engage the Storage Concealment Implant, causing your backpack to be [implant_toggle_text]. ")
+
+/*
+ * Implant items
+*/
+
+// Implanter item
+/obj/item/implanter/hide_backpack
+ name = "implanter (storage concealment)"
+ imp_type = /obj/item/implant/hide_backpack
+
+// Implant case item
+/obj/item/implantcase/hide_backpack
+ name = "implant case - 'Storage Concealment'"
+ desc = "A glass case containing a Storage Concealment implant."
+ imp_type = /obj/item/implant/hide_backpack
diff --git a/modular_splurt/code/game/objects/items/plushes.dm b/modular_splurt/code/game/objects/items/plushes.dm
index 33a6a2f1f1..588e204edb 100644
--- a/modular_splurt/code/game/objects/items/plushes.dm
+++ b/modular_splurt/code/game/objects/items/plushes.dm
@@ -20,3 +20,11 @@
icon = 'modular_splurt/icons/obj/plushes.dmi'
icon_state = "plushie_mal0"
item_state = "plushie_mal0"
+
+/obj/item/toy/plush/nobl
+ name = "Nobl plushie"
+ desc = "It seems to be a small canine, not necessarily latex like you would suspect for some reason, but extremely squishy."
+ icon = 'modular_splurt/icons/obj/plushes.dmi'
+ icon_state = "nobl_plush"
+ item_state = "nobl_plush"
+ squeak_override = list('modular_splurt/sound/misc/dog_toy.ogg' = 1)
diff --git a/modular_splurt/code/game/objects/items/storage/backpack.dm b/modular_splurt/code/game/objects/items/storage/backpack.dm
index b612c32248..2592d3bc70 100644
--- a/modular_splurt/code/game/objects/items/storage/backpack.dm
+++ b/modular_splurt/code/game/objects/items/storage/backpack.dm
@@ -9,3 +9,11 @@
new /obj/item/grenade/chem_grenade/teargas(src)
new /obj/item/grenade/chem_grenade/teargas(src)
new /obj/item/grenade/chem_grenade/teargas(src)
+
+/obj/item/storage/backpack/sloogshell
+ name = "Sloog shell"
+ desc = "A large shell, belonging to probably a very large snail or slug... Wait... It can store things?"
+ icon = 'modular_splurt/icons/obj/storage.dmi'
+ icon_state = "sloog_backpack"
+ mob_overlay_icon = 'modular_splurt/icons/mob/clothing/64_back.dmi'
+ worn_x_dimension = 64
diff --git a/modular_splurt/code/game/objects/items/storage/boxes.dm b/modular_splurt/code/game/objects/items/storage/boxes.dm
index 08e2b03e48..29fe86ebcc 100644
--- a/modular_splurt/code/game/objects/items/storage/boxes.dm
+++ b/modular_splurt/code/game/objects/items/storage/boxes.dm
@@ -14,3 +14,40 @@
new /obj/item/reagent_containers/hypospray/medipen/bellygrowth(src)
new /obj/item/reagent_containers/hypospray/medipen/prospacillin(src)
new /obj/item/reagent_containers/hypospray/medipen/lewdbomb(src)
+
+// Kinkmate listing for the rapid disrobe implant
+/obj/item/storage/box/implant_disrobe
+ name = "rapid disrobe implant box"
+ desc = "Comes with an implanter and an implant case for quick application!"
+ icon = 'modular_sand/icons/obj/fleshlight.dmi'
+ icon_state = "box"
+
+/obj/item/storage/box/implant_disrobe/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/str = GetComponent(/datum/component/storage)
+ str.max_items = 2
+
+/obj/item/storage/box/implant_disrobe/PopulateContents()
+ new /obj/item/implanter(src)
+ new /obj/item/implantcase/disrobe(src)
+
+// Shipment box for Plushmium
+/obj/item/storage/box/shipment_plushmium
+ name = "plushmium backer rewards box"
+ desc = "Comes with a spray bottle quick application!"
+ icon = 'modular_sand/icons/obj/fleshlight.dmi'
+ icon_state = "box"
+
+/obj/item/storage/box/shipment_plushmium/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/str = GetComponent(/datum/component/storage)
+ str.max_items = 2
+
+/obj/item/storage/box/shipment_plushmium/PopulateContents()
+ new /obj/item/reagent_containers/spray/plushmium(src)
+ new /obj/item/paper/fluff/shipment_plushmium(src)
+
+// Plushmium box's note
+/obj/item/paper/fluff/shipment_plushmium
+ name = "plushmium backer note"
+ info = "Plushmium Instructions Dear esteemed customer ,Thank for backing the Stuffing For Spessmen© crowd funding initiative. We at Donk Co. pride ourselves on making a wide variety of engaging toys for our loyal customers to enjoy. Now, we're bringing the toy making process directly to your home or workplace! Included in this box is:A spray bottle of Love to Life™ solution A carefully packaged plushie To begin enjoying your new friend, start by unpacking the included plushie. Our selection process goes through rigorous quality testing to ensure you'll always get the best toy for the job. With so many choices, you'll want to get the whole family in on the action. Once you have everything ready, it's time to make the patented Donk Co. magic happen! Spray your new best friend with Love to Life™ solution, included in the complimentary spray bottle, and watch the stunning transformation! But don't leave your new best friend hanging! Give them a big warm hug to celebrate the long and intimate friendship you'll be sharing. Donk Co. is not responsible for any injury or loss of life that may occur while using the Love to Life™ solution. Do not allow access to children or adults without supervision by a chemist. Do not drink, splash, inject, or otherwise handle the solution. Do not come into direct physical contact with the solution, or any object the solution has been applied to, under any circumstances. "
diff --git a/modular_splurt/code/game/objects/items/storage/wallets.dm b/modular_splurt/code/game/objects/items/storage/wallets.dm
new file mode 100644
index 0000000000..8e08e7b456
--- /dev/null
+++ b/modular_splurt/code/game/objects/items/storage/wallets.dm
@@ -0,0 +1,20 @@
+// Bluespace wallet
+/obj/item/storage/wallet/bluespace
+ name = "\improper wallet of holding"
+ desc = "A testament to science's hubris. It holds thrice as many stolen ID cards."
+ icon = 'modular_splurt/icons/obj/storage.dmi'
+ icon_state = "wallet_bluespace"
+
+ // Copied from bag of holding
+ resistance_flags = FIRE_PROOF
+ item_flags = NO_MAT_REDEMPTION
+ rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
+
+/obj/item/storage/wallet/bluespace/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.max_items = 12
+
+/obj/item/storage/wallet/bluespace/update_icon_state()
+ // Don't update icons
+ return
diff --git a/modular_splurt/code/game/objects/structures/flora.dm b/modular_splurt/code/game/objects/structures/flora.dm
index c60cfffac3..7415f1ccb5 100644
--- a/modular_splurt/code/game/objects/structures/flora.dm
+++ b/modular_splurt/code/game/objects/structures/flora.dm
@@ -77,3 +77,6 @@
/obj/effect/spawner/grass_spawner/red
name = "redgrass spawner"
spawned_grass = /obj/structure/flora/grass/red
+
+/obj/structure/flora/tree/pine/xmas/presents
+ gift_type = /obj/item/a_gift //this is a modular nerf to christmas trees to limit what they hand out
diff --git a/modular_splurt/code/game/objects/structures/pole.dm b/modular_splurt/code/game/objects/structures/pole.dm
index 9d8a96456f..fdd2bf46bf 100644
--- a/modular_splurt/code/game/objects/structures/pole.dm
+++ b/modular_splurt/code/game/objects/structures/pole.dm
@@ -16,6 +16,11 @@
. = ..()
if(.)
return
+
+ // Don't teleport telekinetic users to the pole.
+ if (get_dist(src,user) > 1)
+ return
+
if(obj_flags & IN_USE)
to_chat(user, "It's already in use - wait a bit.")
return
diff --git a/modular_splurt/code/game/objects/structures/statues.dm b/modular_splurt/code/game/objects/structures/statues.dm
index d313578f0d..21551ea3b0 100644
--- a/modular_splurt/code/game/objects/structures/statues.dm
+++ b/modular_splurt/code/game/objects/structures/statues.dm
@@ -13,3 +13,134 @@
desc = "A statue honoring Owia-Akeshi, a brave ashwalker that perished while defending the nest from a wild ash drake. May his soul rest in peace."
impressiveness = 25
+/obj/structure/statue/gargoyle
+ name = "statue"
+ desc = "An incredibly intricate statue, which... almost seems alive!"
+ icon = 'modular_splurt/icons/obj/structures/statue.dmi'
+ icon_state = "gargoyle" //empty sprite because it's supposed to copy over the overlays anyway, and otherwise, you end up with a white human male underlay beneath the statue.
+ density = TRUE
+ anchored = TRUE
+ flags_1 = PREVENT_CONTENTS_EXPLOSION_1
+ max_integrity = 200
+ var/mob/living/petrified_mob
+ var/old_max_health
+ var/old_size
+ var/was_tilted
+ var/was_lying
+ var/was_lying_prev
+ var/deconstructed = FALSE
+
+/obj/structure/statue/gargoyle/Initialize(mapload, mob/living/L)
+ . = ..()
+ if(L)
+ petrified_mob = L
+ if(L.buckled)
+ L.buckled.unbuckle_mob(L,force=1)
+ L.visible_message("[L]'s skin rapidly turns to stone! ", "Your skin abruptly hardens as you turn to stone once more! ")
+ dir = L.dir
+ transform = L.transform
+ pixel_x = L.pixel_x
+ pixel_y = L.pixel_y
+ layer = L.layer
+ was_tilted = L.is_tilted
+ was_lying = L.lying
+ was_lying_prev = L.lying_prev
+ L.forceMove(src)
+ ADD_TRAIT(L, TRAIT_MUTE, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_MOBILITY_NOMOVE, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_MOBILITY_NOPICKUP, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_MOBILITY_NOUSE, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_NOBREATH, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_NOHUNGER, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_NOTHIRST, STATUE_TRAIT)
+ ADD_TRAIT(L, TRAIT_NOFIRE, STATUE_TRAIT) //OH GOD HELP I'M ON FIRE INSIDE THE STATUE I CAN'T MOVE AND I CAN'T STOP IT HAAAAALP - person who experienced this
+ L.click_intercept = src
+ L.faction += "mimic" //Stops mimics from instaqdeling people in statues
+ L.status_flags |= GODMODE
+ old_max_health = L.maxHealth
+ old_size = get_size(L)
+ obj_integrity = L.health + 100 //stoning damaged mobs will result in easier to shatter statues
+ max_integrity = obj_integrity
+
+/obj/structure/statue/gargoyle/proc/InterceptClickOn(mob/living/caller, params, atom/A) //technically could be bypassed by doing something that also uses click intercept but shrug
+ var/atom/movable/screen/movable/action_button/ab = A
+ if (istype(ab))
+ if (istype(ab.linked_action, /datum/action/gargoyle))
+ return FALSE
+ var/list/modifiers = params2list(params)
+ if (modifiers["shift"] && !modifiers["ctrl"] && !modifiers["middle"])
+ return FALSE
+ return TRUE
+
+/obj/structure/statue/gargoyle/examine_more(mob/user) //something about the funny signals doesn't work here no matter how much I fucked around with it (ie registering to COMSIG_PARENT_EXAMINE_MORE doesn't do anything), so we have to overwrite the proc
+ . = ..()
+ if (petrified_mob)
+ SEND_SIGNAL(petrified_mob, COMSIG_PARENT_EXAMINE, user, .)
+ . -= "You examine [src] closer, but find nothing of interest... "
+
+/obj/structure/statue/gargoyle/handle_atom_del(atom/A)
+ if(A == petrified_mob)
+ petrified_mob = null
+
+/obj/structure/statue/gargoyle/Destroy()
+ if(petrified_mob)
+ petrified_mob.status_flags &= ~GODMODE
+ petrified_mob.forceMove(loc)
+ REMOVE_TRAIT(petrified_mob, TRAIT_MUTE, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOMOVE, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOPICKUP, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOUSE, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_NOBREATH, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_NOHUNGER, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_NOTHIRST, STATUE_TRAIT)
+ REMOVE_TRAIT(petrified_mob, TRAIT_NOFIRE, STATUE_TRAIT)
+ petrified_mob.faction -= "mimic"
+ petrified_mob.click_intercept = null
+ petrified_mob.dir = dir
+ petrified_mob.update_size(old_size)
+ var/damage = deconstructed ? petrified_mob.health : petrified_mob.health*(old_max_health/petrified_mob.maxHealth) - obj_integrity + 100
+ petrified_mob.take_overall_damage(damage) //any new damage the statue incurred is transfered to the mob
+ petrified_mob.transform = transform
+ petrified_mob.lying = was_lying
+ petrified_mob.lying_prev = was_lying_prev
+ petrified_mob.update_mobility()
+ petrified_mob.pixel_x = pixel_x
+ petrified_mob.pixel_y = pixel_y
+ petrified_mob.layer = layer
+ petrified_mob.is_shifted = TRUE //just prevents bad things tbh
+ petrified_mob.is_tilted = was_tilted
+ if (pulledby && pulledby.pulling == src) //gotta checked just in case
+ pulledby.start_pulling(petrified_mob, supress_message = TRUE)
+ var/datum/quirk/gargoyle/T = locate() in petrified_mob.roundstart_quirks
+ if (T)
+ T.transformed = 0
+ petrified_mob = null
+ return ..()
+
+/obj/structure/statue/gargoyle/deconstruct(disassembled = TRUE)
+ deconstructed = TRUE
+ visible_message("[src] shatters! ")
+ qdel(src)
+
+/obj/structure/statue/gargoyle/attackby(obj/item/W, mob/living/user, params)
+ add_fingerprint(user)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ if(default_unfasten_wrench(user, W))
+ return
+ if(W.tool_behaviour == TOOL_WELDER)
+ if(!W.tool_start_check(user, amount=0))
+ return FALSE
+
+ if (petrified_mob && alert(user, "You are slicing apart a gargoyle! Are you sure you want to continue? This will severely harm them, if not outright kill them.",, "Continue", "Cancel") == "Cancel")
+ return
+
+ user.visible_message(span_notice("[user] is slicing apart the [name]."), \
+ span_notice("You are slicing apart the [name]..."))
+ if (petrified_mob)
+ to_chat(petrified_mob, "You are being sliced apart by [user]! ")
+ if(W.use_tool(src, user, 40, volume=50))
+ user.visible_message(span_notice("[user] slices apart the [name]."), \
+ span_notice("You slice apart the [name]!"))
+ deconstruct(TRUE)
+ return
+ return ..()
diff --git a/modular_splurt/code/modules/awaymissions/mission_code/academy.dm b/modular_splurt/code/modules/awaymissions/mission_code/academy.dm
new file mode 100644
index 0000000000..b9fadc051e
--- /dev/null
+++ b/modular_splurt/code/modules/awaymissions/mission_code/academy.dm
@@ -0,0 +1,21 @@
+//Academy Items
+
+/obj/item/dice/d20/fate
+ var/list/used_fingerprints = null // Used to track who used the one_use die
+
+/obj/item/dice/d20/fate/one_use
+ reusable = 1 // Obsolete by the used_fingerprints list
+
+/obj/item/dice/d20/fate/effect(var/mob/living/carbon/human/user,roll)
+ // This override checks if a user has rolled the dice
+ // If true; Reject them and abort
+ if (user in used_fingerprints)
+ // Send a message implying someone else should roll
+ visible_message("[user] rolls the dice, but it doesn't respond to [user.p_them()] again. ")
+ return
+ // If false; Add them to the user list and continue
+ else
+ LAZYADD(used_fingerprints, user)
+
+ // Run the function normally
+ ..()
diff --git a/modular_splurt/code/modules/cargo/packs/misc.dm b/modular_splurt/code/modules/cargo/packs/misc.dm
index 3211d7e085..bf5eec556d 100644
--- a/modular_splurt/code/modules/cargo/packs/misc.dm
+++ b/modular_splurt/code/modules/cargo/packs/misc.dm
@@ -215,6 +215,15 @@
cost = 100000
contains = list(/obj/item/reagent_containers/food/drinks/diminicillin)
+/datum/supply_pack/misc/plushmium
+ name = "Plushmium Crate"
+ desc = "Surplus shipment of Stuffing For Spessmen backer rewards. Contains a pre-packaged spray bottle of Plushmium, and toy to use it on."
+ cost = 5000 // Cost of an expensive animal
+ contains = list(
+ /obj/item/storage/box/shipment_plushmium,
+ /obj/item/choice_beacon/box/plushie
+ )
+
/datum/supply_pack/misc/microbricks
name = "Microbricks Crate"
desc = "Extremely bored? Recreate a downscale city and get upset when it all comes crumbling down!"
diff --git a/modular_splurt/code/modules/client/loadout/backpack.dm b/modular_splurt/code/modules/client/loadout/backpack.dm
index 448bd8a68a..4a52343677 100644
--- a/modular_splurt/code/modules/client/loadout/backpack.dm
+++ b/modular_splurt/code/modules/client/loadout/backpack.dm
@@ -88,7 +88,7 @@
name = "Purple Nail Polish"
path = /obj/item/nailpolish/purple
-/datum/gear/backback/secbadge
+/datum/gear/backpack/secbadge
name = "Security Badge"
path = /obj/item/clothing/accessory/badge
restricted_roles = list("Security Officer", "Warden", "Detective", "Head of Security")
diff --git a/modular_splurt/code/modules/client/loadout/socks.dm b/modular_splurt/code/modules/client/loadout/socks.dm
index 2deee41786..d44e772163 100644
--- a/modular_splurt/code/modules/client/loadout/socks.dm
+++ b/modular_splurt/code/modules/client/loadout/socks.dm
@@ -5,3 +5,7 @@
/datum/gear/socks/thigh/thigh_cow
name = "Fishnet tights"
path = /obj/item/clothing/underwear/socks/thigh/fishnet/white //This one is pretty much greyscale aka easier to recolor
+
+/datum/gear/socks/garter
+ name = "Garters"
+ path = /obj/item/clothing/underwear/socks/garter
diff --git a/modular_splurt/code/modules/client/loadout/suit.dm b/modular_splurt/code/modules/client/loadout/suit.dm
index 695ed1ed3e..51954f9b6a 100644
--- a/modular_splurt/code/modules/client/loadout/suit.dm
+++ b/modular_splurt/code/modules/client/loadout/suit.dm
@@ -96,10 +96,5 @@
/datum/gear/suit/tunnelfox
name = "tunnel fox jacket"
- path = /obj/item/clothing/suit/tunnelfox
- subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
-
-/datum/gear/suit/tunnelfox_t
- name = "opened tunnel fox jacket"
- path = /obj/item/clothing/suit/tunnelfox_t
+ path = /obj/item/clothing/suit/toggle/tunnelfox
subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS
diff --git a/modular_splurt/code/modules/clothing/kinkyclothes.dm b/modular_splurt/code/modules/clothing/kinkyclothes.dm
index 5dfbc1b050..98bbb21e4a 100644
--- a/modular_splurt/code/modules/clothing/kinkyclothes.dm
+++ b/modular_splurt/code/modules/clothing/kinkyclothes.dm
@@ -136,7 +136,7 @@
SEND_SOUND(user, sound('modular_splurt/sound/effects/vaultsuit/InkSpotsSting.ogg', volume = 60))
return
-/obj/item/clothing/suit/tunnelfox
+/obj/item/clothing/suit/toggle/tunnelfox
name = "tunnel fox jacket"
desc = "Tunnel Foxes Rule!"
icon = 'modular_splurt/icons/obj/clothing/suits.dmi'
@@ -145,13 +145,5 @@
item_state = "tunnelfox"
body_parts_covered = CHEST|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
-
-/obj/item/clothing/suit/tunnelfox_t
- name = "opened tunnel fox jacket"
- desc = "Tunnel Foxes Rule!"
- icon = 'modular_splurt/icons/obj/clothing/suits.dmi'
- icon_state = "tunnelfox_t"
- mob_overlay_icon = 'modular_splurt/icons/mob/clothing/suit.dmi'
- item_state = "tunnelfox_t"
- body_parts_covered = CHEST|LEGS|ARMS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ togglename = "buttons"
+ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
diff --git a/modular_splurt/code/modules/clothing/suits/jobs.dm b/modular_splurt/code/modules/clothing/suits/jobs.dm
index c66ca33eb9..b62195363b 100644
--- a/modular_splurt/code/modules/clothing/suits/jobs.dm
+++ b/modular_splurt/code/modules/clothing/suits/jobs.dm
@@ -25,9 +25,11 @@
item_state = "hopformal"
icon = 'modular_splurt/icons/obj/clothing/suits.dmi'
mob_overlay_icon = 'modular_splurt/icons/mob/clothing/suit.dmi'
+ anthro_mob_worn_overlay = 'modular_splurt/icons/mob/clothing/suit.dmi'
body_parts_covered = CHEST|GROIN|ARMS
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10)
togglename = "buttons"
+ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/toggle/armor/hop/hop_formal/Initialize()
. = ..()
diff --git a/modular_splurt/code/modules/clothing/under/_under.dm b/modular_splurt/code/modules/clothing/under/_under.dm
index e02856f0a2..b9b28a778e 100644
--- a/modular_splurt/code/modules/clothing/under/_under.dm
+++ b/modular_splurt/code/modules/clothing/under/_under.dm
@@ -1,6 +1,11 @@
/obj/item/clothing/under
is_edible = 1 //Most jumpsuits are made of cloth so this is a safe bet.
+/obj/item/clothing/under/Initialize(mapload)
+ . = ..()
+ if(!is_type_in_typecache(type, GLOB.skirt_peekable))
+ LAZYSET(GLOB.skirt_peekable, type, TRUE)
+
/obj/item/clothing/under/Destroy()
QDEL_LIST(attached_accessories)
return ..()
diff --git a/modular_splurt/code/modules/clothing/under/jobs/civilian/civilian.dm b/modular_splurt/code/modules/clothing/under/jobs/civilian/civilian.dm
index d08862aa90..9b577874e6 100644
--- a/modular_splurt/code/modules/clothing/under/jobs/civilian/civilian.dm
+++ b/modular_splurt/code/modules/clothing/under/jobs/civilian/civilian.dm
@@ -3,10 +3,10 @@
desc = "A male head of personnel's luxury-wear, for special occasions."
icon = 'modular_splurt/icons/obj/clothing/uniforms.dmi'
mob_overlay_icon = 'modular_splurt/icons/mob/clothing/uniform.dmi'
+ anthro_mob_worn_overlay = 'modular_splurt/icons/mob/clothing/uniform_digi.dmi'
icon_state = "hop_parade_male"
item_state = "hop_parade_male"
can_adjust = FALSE
- mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/under/rank/civilian/head_of_personnel/parade/female
name = "head of personnel's parade uniform"
@@ -14,7 +14,6 @@
icon_state = "hop_parade_female"
item_state = "hop_parade_female"
fitted = FEMALE_UNIFORM_TOP
- mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/under/rank/civilian/lawyer/galaxy_blue
name = "\improper De Void of Soul"
diff --git a/modular_splurt/code/modules/food_and_drinks/recipes/drink_recipes.dm b/modular_splurt/code/modules/food_and_drinks/recipes/drink_recipes.dm
index 87a11eee76..a587e9fc71 100644
--- a/modular_splurt/code/modules/food_and_drinks/recipes/drink_recipes.dm
+++ b/modular_splurt/code/modules/food_and_drinks/recipes/drink_recipes.dm
@@ -86,11 +86,12 @@
/datum/chemical_reaction/moth_in_chief
name = "Moth in Chief"
id = /datum/reagent/consumable/ethanol/moth_in_chief
- results = list(/datum/reagent/consumable/ethanol/moth_in_chief = 3)
+ results = list(/datum/reagent/consumable/ethanol/moth_in_chief = 4)
required_reagents = list(
/datum/reagent/consumable/ethanol/commander_and_chief = 1,
/datum/reagent/mutationtoxin/insect = 1,
- /datum/reagent/drug/copium = 1
+ /datum/reagent/drug/copium = 1,
+ /datum/reagent/medicine/stimulants = 1
)
@@ -116,7 +117,7 @@
/datum/chemical_reaction/long_john_silver
name = "Long John Silver"
- id = /datum/chemical_reaction/long_john_silver
+ id = /datum/reagent/consumable/ethanol/long_john_silver
results = list(/datum/reagent/consumable/ethanol/long_john_silver = 10)
required_reagents = list(
/datum/reagent/consumable/ethanol/navy_rum = 4,
@@ -126,7 +127,7 @@
/datum/chemical_reaction/long_haul
name = "Long Haul"
- id = /datum/chemical_reaction/long_haul
+ id = /datum/reagent/consumable/ethanol/long_haul
results = list(/datum/reagent/consumable/ethanol/long_haul = 25)
required_reagents = list(
/datum/reagent/consumable/ethanol/navy_rum = 4,
@@ -138,7 +139,7 @@
/datum/chemical_reaction/salt_and_swell
name = "Salt and Swell"
- id = /datum/chemical_reaction/salt_and_swell
+ id = /datum/reagent/consumable/ethanol/salt_and_swell
results = list(/datum/reagent/consumable/ethanol/salt_and_swell = 10)
required_reagents = list(
/datum/reagent/consumable/ethanol/navy_rum = 4,
@@ -149,7 +150,7 @@
/datum/chemical_reaction/tich_toch
name = "Tich Toch"
- id = /datum/chemical_reaction/tich_toch
+ id = /datum/reagent/consumable/ethanol/tich_toch
results = list(/datum/reagent/consumable/ethanol/tich_toch = 10)
required_reagents = list(
/datum/reagent/consumable/ethanol/tiltaellen = 6,
@@ -159,7 +160,7 @@
/datum/chemical_reaction/tiltaellen
name = "Tiltällen"
- id = /datum/chemical_reaction/tiltaellen
+ id = /datum/reagent/consumable/ethanol/tiltaellen
results = list(/datum/reagent/consumable/ethanol/tiltaellen = 10)
required_reagents = list(
/datum/reagent/consumable/yoghurt = 8,
@@ -169,8 +170,8 @@
mix_message = "The mixture curdles and thickens."
/datum/chemical_reaction/tropical_storm
- name = ""
- id = /datum/chemical_reaction/
+ name = "Tropical Storm"
+ id = /datum/reagent/consumable/ethanol/tropical_storm
results = list(/datum/reagent/consumable/ethanol/tropical_storm = 10)
required_reagents = list(
/datum/reagent/consumable/ethanol/rum = 2,
@@ -179,3 +180,12 @@
/datum/reagent/consumable/pineapplejuice = 2
)
+/datum/chemical_reaction/skullfucker_deluxe
+ name = "Skullfucker Deluxe"
+ id = /datum/reagent/consumable/ethanol/skullfucker_deluxe
+ results = list(/datum/reagent/consumable/ethanol/skullfucker_deluxe = 5)
+ required_reagents = list(
+ /datum/reagent/consumable/ethanol/sugar_rush = 2,
+ /datum/reagent/consumable/ethanol/moonshine = 2,
+ /datum/reagent/consumable/ethanol/brave_bull = 1
+ )
diff --git a/modular_splurt/code/modules/holodeck/holo_effect.dm b/modular_splurt/code/modules/holodeck/holo_effect.dm
new file mode 100644
index 0000000000..349ca781f1
--- /dev/null
+++ b/modular_splurt/code/modules/holodeck/holo_effect.dm
@@ -0,0 +1,7 @@
+// Holodeck mob: Funclaw
+/obj/effect/holodeck_effect/mobspawner/funclaw
+ mobtype = /mob/living/simple_animal/hostile/deathclaw/funclaw/gentle
+
+// Holodeck mob: Friendly Bee
+/obj/effect/holodeck_effect/mobspawner/bumbles
+ mobtype = /mob/living/simple_animal/pet/bumbles
diff --git a/modular_splurt/code/modules/jobs/job_types/_job_alt_titles.dm b/modular_splurt/code/modules/jobs/job_types/_job_alt_titles.dm
index 5cba73d39e..4e4663a72e 100644
--- a/modular_splurt/code/modules/jobs/job_types/_job_alt_titles.dm
+++ b/modular_splurt/code/modules/jobs/job_types/_job_alt_titles.dm
@@ -103,7 +103,8 @@
"Bard",
"Snack",
"Stress Relief",
- "Freeloader"
+ "Freeloader",
+ "Station Pet"
)
LAZYADD(alt_titles, extra_titles)
. = ..()
@@ -197,7 +198,8 @@
"Researcher",
"Toxins Researcher",
"Research Intern",
- "Junior Scientist"
+ "Junior Scientist",
+ "Rack Researcher"
)
LAZYADD(alt_titles, extra_titles)
. = ..()
diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/body_markings.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/body_markings.dm
index 33c377eabb..ac3b448ca1 100644
--- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/body_markings.dm
+++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/body_markings.dm
@@ -107,6 +107,12 @@
icon_state = "deoxys"
covered_limbs = list("Head" = MATRIX_ALL, "Chest" = MATRIX_ALL, "Left Leg" = MATRIX_RED_GREEN, "Right Leg" = MATRIX_RED_GREEN, "Left Arm" = MATRIX_RED_GREEN, "Right Arm" = MATRIX_RED_GREEN)
+/datum/sprite_accessory/mam_body_markings/sloog
+ name = "Sloog"
+ icon = 'modular_splurt/icons/mob/mam_markings.dmi'
+ icon_state = "sloog"
+ covered_limbs = list("Chest" = MATRIX_RED_GREEN)
+
/******************************************
************* Insect Markings *************
*******************************************/
diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/horns.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/horns.dm
index 56ba9fdbba..4454dd0283 100644
--- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/horns.dm
+++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/horns.dm
@@ -41,3 +41,12 @@
name = "Alien Bobbers"
icon = 'modular_splurt/icons/mob/mutant_bodyparts.dmi'
icon_state = "alienbobbers"
+
+/datum/sprite_accessory/horns/sloogbobbers
+ name = "Sloog Bobbers"
+ icon = 'modular_splurt/icons/mob/64_mutant_bodyparts.dmi'
+ icon_state = "sloogbobbers"
+ dimension_x = 64
+ center = TRUE
+ color_src = MATRIXED
+ matrixed_sections = MATRIX_RED_GREEN
diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/legs_and_taurs.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/legs_and_taurs.dm
index d43c091c6a..d2df178b71 100644
--- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/legs_and_taurs.dm
+++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/legs_and_taurs.dm
@@ -51,3 +51,11 @@
taur_mode = STYLE_PAW_TAURIC //it is what it is
hide_legs = USE_QUADRUPED_CLIP_MASK
matrixed_sections = MATRIX_RED_GREEN
+
+/datum/sprite_accessory/taur/sloog
+ name = "Sloog"
+ icon_state = "sloog"
+ icon = 'modular_splurt/icons/mob/mam_taur.dmi'
+ taur_mode = STYLE_PAW_TAURIC
+ hide_legs = USE_QUADRUPED_CLIP_MASK
+ matrixed_sections = MATRIX_RED_GREEN
diff --git a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm
index 927240b7ea..6b87b38f09 100644
--- a/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm
+++ b/modular_splurt/code/modules/mob/dead/new_player/sprite_accesories/snouts.dm
@@ -226,3 +226,14 @@
icon_state = "deoxys"
icon = 'modular_splurt/icons/mob/mam_snouts.dmi'
matrixed_sections = MATRIX_ALL
+
+/datum/sprite_accessory/snouts/mam_snouts/sloog
+ name = "Sloog"
+ icon_state = "sloog"
+ icon = 'modular_splurt/icons/mob/mam_snouts.dmi'
+ matrixed_sections = MATRIX_RED
+
+/datum/sprite_accessory/snouts/mam_snouts/sloog/lips
+ name = "Sloog (lips)"
+ icon_state = "slooglips"
+ matrixed_sections = MATRIX_RED_GREEN
diff --git a/modular_splurt/code/modules/mob/living/carbon/carbon.dm b/modular_splurt/code/modules/mob/living/carbon/carbon.dm
index d2a7d7a875..a81da1e44b 100644
--- a/modular_splurt/code/modules/mob/living/carbon/carbon.dm
+++ b/modular_splurt/code/modules/mob/living/carbon/carbon.dm
@@ -22,3 +22,40 @@
new_rope.forceMove(src.loc)
return
. = ..()
+
+// Liquid Panty Dropper effect
+/mob/living/carbon/proc/clothing_burst(mob/living/carbon/target_user)
+ // Variable for if the action succeeded
+ var/user_disrobed = FALSE
+
+ // Get worn items
+ var/items = target_user.get_contents()
+
+ // Iterate over worn items
+ for(var/obj/item/item_worn in items)
+ // Ignore non-mob (storage)
+ if(!ismob(item_worn.loc))
+ continue
+
+ // Ignore held items
+ if(target_user.is_holding(item_worn))
+ continue
+
+ // Check for anything covering a body part
+ if(item_worn.body_parts_covered)
+ // Set the success variable
+ user_disrobed = TRUE
+
+ // Drop the target item
+ target_user.dropItemToGround(item_worn, TRUE)
+
+ // Throw item to a random spot
+ item_worn.throw_at(pick(oview(7,get_turf(src))),10,1)
+
+ // When successfully disrobing a target
+ if(user_disrobed)
+ // Display a chat message
+ target_user.visible_message("[target_user] suddenly bursts out of [target_user.p_their()] clothes! ", "You suddenly burst out of your clothes! ")
+
+ // Play the ripped poster sound
+ playsound(target_user.loc, 'sound/items/poster_ripped.ogg', 50, 1)
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/physiology.dm b/modular_splurt/code/modules/mob/living/carbon/human/physiology.dm
new file mode 100644
index 0000000000..fb5bf6ca6c
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/human/physiology.dm
@@ -0,0 +1,2 @@
+/datum/physiology
+ var/thirst_mod = 1 //% of thirst rate taken per tick.
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species.dm b/modular_splurt/code/modules/mob/living/carbon/human/species.dm
index ff61696ab9..3ffad4c2b4 100644
--- a/modular_splurt/code/modules/mob/living/carbon/human/species.dm
+++ b/modular_splurt/code/modules/mob/living/carbon/human/species.dm
@@ -4,3 +4,32 @@
to_chat(user, "You can't seem to force yourself up right now! ")
return
. = ..()
+
+/datum/species/handle_thirst(mob/living/carbon/human/H)
+ if(HAS_TRAIT(H, TRAIT_NOTHIRST))
+ return
+
+ // A lot of this is just copied and pasted from the handle_digestion proc
+ if (H.thirst > 0 && H.stat != DEAD && !HAS_TRAIT(H, TRAIT_NOTHIRST))
+ // THEY ~~HUNGER~~ THIRST
+ var/thirst_rate = THIRST_FACTOR
+ /*
+ var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
+ if(mood && mood.sanity > SANITY_DISTURBED)
+ thirst_rate *= max(0.5, 1 - 0.002 * mood.sanity) //0.85 to 0.75
+
+ // Whether we cap off our satiety or move it towards 0
+ if(H.satiety > MAX_SATIETY)
+ H.satiety = MAX_SATIETY
+ else if(H.satiety > 0)
+ H.satiety--
+ else if(H.satiety < -MAX_SATIETY)
+ H.satiety = -MAX_SATIETY
+ else if(H.satiety < 0)
+ H.satiety++
+ if(prob(round(-H.satiety/40)))
+ H.Jitter(5)
+ thirst_rate = 3 * THIRST_FACTOR
+ */
+ thirst_rate *= H.physiology.thirst_mod
+ H.adjust_thirst(-thirst_rate)
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/modular_splurt/code/modules/mob/living/carbon/human/species_types/dullahan.dm
deleted file mode 100644
index 94689e4b6c..0000000000
--- a/modular_splurt/code/modules/mob/living/carbon/human/species_types/dullahan.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/obj/item/organ/tongue/dullahan
- initial_accents = list(/datum/accent/dullahan)
diff --git a/modular_splurt/code/modules/mob/living/carbon/human/update_icons.dm b/modular_splurt/code/modules/mob/living/carbon/human/update_icons.dm
new file mode 100644
index 0000000000..7274e95154
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/carbon/human/update_icons.dm
@@ -0,0 +1,13 @@
+// Function for updating back sprites
+/mob/living/carbon/human/update_inv_back()
+ . = ..()
+
+ // Check for hidden backpack trait
+ if(HAS_TRAIT(src, TRAIT_HIDE_BACKPACK))
+ // Define back overlays
+ var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
+
+ // Check for existing overlay
+ if(back_overlay)
+ // Remove overlays
+ remove_overlay(BACK_LAYER)
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
new file mode 100644
index 0000000000..97a09630a4
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -0,0 +1,11 @@
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/GiveTarget(new_target)
+ var/targets_the_same = (new_target == target)
+ . = ..()
+
+ // Escape clause from original
+ if(!(. && target && !targets_the_same))
+ return
+
+ // Unique dialog for Cursed Blood
+ if(HAS_TRAIT(target, TRAIT_CURSED_BLOOD))
+ say(pick("Hunter, you must accept your death, be freed from the night.","The night, and the dream, were long...","Beasts all over the shop... You'll be one of them, sooner or later...","The night blocks all sight..."))
diff --git a/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/sand.dm b/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/sand.dm
new file mode 100644
index 0000000000..32c51c16a1
--- /dev/null
+++ b/modular_splurt/code/modules/mob/living/simple_animal/hostile/megafauna/sand.dm
@@ -0,0 +1,7 @@
+/mob/living/simple_animal/hostile/megafauna/sand
+ name = "Corrupted Mayhem"
+ desc = "The longer you look at this creature the more you feel your gut twist and you begin to feel sick..."
+ icon = 'modular_splurt/icons/mob/lavaland/mayhem_mega.dmi'
+ icon_state = "eva"
+ icon_living = "eva"
+ attack_sound = 'modular_splurt/sound/voice/ara-ara2.ogg'
diff --git a/modular_splurt/code/modules/mob/mob_helpers.dm b/modular_splurt/code/modules/mob/mob_helpers.dm
new file mode 100644
index 0000000000..111f9c35b7
--- /dev/null
+++ b/modular_splurt/code/modules/mob/mob_helpers.dm
@@ -0,0 +1,22 @@
+// Modular-friendly way of adding new quirk-based inspect text
+// Hijacks the function used for abductor examine
+/mob/common_trait_examine()
+ // The ever-important funny BYOND dots
+ . = ..()
+
+ // Empathy abilities escape clause
+ // Please change this when adding new quirk detection
+ if(!(HAS_TRAIT(usr, TRAIT_EMPATH) || HAS_TRAIT(usr, TRAIT_FRIENDLY) || src == usr))
+ return
+
+ // Pronoun stuff
+ var/t_He = p_they(FALSE)
+ //var/t_his = p_their()
+ //var/t_is = p_are()
+
+ // Check for Distant (no touch head!)
+ if(HAS_TRAIT(src, TRAIT_DISTANT))
+ . += "You sense [t_He] might be disturbed by physical affection. \n"
+ // Check for Heatpat Slut (pls touch head!)
+ if(HAS_TRAIT(src, TRAIT_HEADPAT_SLUT))
+ . += "You sense [t_He] appreciates receiving physical affection more than normal. \n"
diff --git a/modular_splurt/code/modules/mob/splurt_emotes.dm b/modular_splurt/code/modules/mob/splurt_emotes.dm
index 7881c92c4c..3f96222e75 100644
--- a/modular_splurt/code/modules/mob/splurt_emotes.dm
+++ b/modular_splurt/code/modules/mob/splurt_emotes.dm
@@ -870,3 +870,62 @@
return
user.nextsoundemote = world.time + 3 SECONDS
playsound(user, 'modular_splurt/sound/voice/missouri.ogg', 50, 0, -1)
+
+/datum/emote/living/facemetacarpus
+ key = "facehand" // Facepalm was taken
+ key_third_person = "facepalms"
+ // Message is generated from metacarpus_type below. You shouldn't see this!
+ message = "creates an error in the code."
+ emote_type = EMOTE_AUDIBLE // Hear a slapping sound
+ muzzle_ignore = TRUE // Not a spoken emote
+ restraint_check = TRUE // Uses your hands
+ mob_type_allowed_typecache = list(/mob/living/carbon) // Don't let borgs do this
+ // Defines appendage type for generated message
+ var/metacarpus_type = "palm" // Default to hands
+
+/datum/emote/living/facemetacarpus/run_emote(mob/user, params, type_override, intentional)
+ // Randomly pick a message using metacarpus_type for hand
+ message = pick(list(
+ "places [usr.p_their()] [metacarpus_type] across [usr.p_their()] face.",
+ "lowers [usr.p_their()] face into [usr.p_their()] [metacarpus_type].",
+ "face[metacarpus_type]s",
+ ))
+ if(!(. = ..()))
+ return
+ if(user.nextsoundemote >= world.time)
+ return
+ user.nextsoundemote = world.time + 10
+ playsound(user, 'modular_splurt/sound/effects/slap.ogg', 50, 1, -1)
+
+/datum/emote/living/facemetacarpus/paw
+ key = "facepaw" // For furries
+ key_third_person = "facepaws"
+ metacarpus_type = "paw"
+
+/datum/emote/living/facemetacarpus/claw
+ key = "faceclaw" // For scalies and avians
+ key_third_person = "faceclaws"
+ metacarpus_type = "claw"
+
+/datum/emote/living/facemetacarpus/hoof
+ key = "facehoof" // For horse enthusiasts
+ key_third_person = "facehoofs"
+ metacarpus_type = "hoof"
+
+/datum/emote/living/poyo
+ key = "poyo"
+ key_third_person = "poyos"
+ message = "%SAYS, \"Poyo!\""
+ emote_type = EMOTE_AUDIBLE
+
+/datum/emote/living/poyo/run_emote(mob/user, params, type_override, intentional)
+ var/datum/dna/D = user.has_dna()
+ var/say_mod = (D ? D.species.say_mod : "says")
+ message = replacetextEx(message, "%SAYS", say_mod)
+ . = ..()
+ if(!.)
+ return
+ if(user.nextsoundemote >= world.time)
+ return
+ user.nextsoundemote = world.time + 1 SECONDS
+ playsound(user, 'modular_splurt/sound/voice/barks/poyo.ogg', 50, 1, -1)
diff --git a/modular_splurt/code/modules/projectiles/guns/ballistic/pistol.dm b/modular_splurt/code/modules/projectiles/guns/ballistic/pistol.dm
index 7f1b75d548..dbfdae1d65 100644
--- a/modular_splurt/code/modules/projectiles/guns/ballistic/pistol.dm
+++ b/modular_splurt/code/modules/projectiles/guns/ballistic/pistol.dm
@@ -21,16 +21,17 @@
flight_y_offset = 14
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "enforcer_black",
- "M2611 Enforcer" = "cde",
- "M1911 Enforcer" = "m1911",
- "VP78 Enforcer" = "vp78",
- "USP Enforcer" = "usp-m"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "enforcer_black"),
+ "M2611 Enforcer" = list("icon_state" = "cde"),
+ "M1911 Enforcer" = list("icon_state" = "m1911"),
+ "VP78 Enforcer" = list("icon_state" = "vp78"),
+ "USP Enforcer" = list("icon_state" = "usp-m")
+ )
/obj/item/gun/ballistic/automatic/pistol/enforcer/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][chambered ? "" : "-e"]"
else
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
@@ -77,13 +78,14 @@
mag_type = /obj/item/ammo_box/magazine/m9
can_suppress = FALSE
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "ninemil",
- "Maria" = "maria"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "ninemil"),
+ "Maria" = list("icon_state" = "maria")
+ )
/obj/item/gun/ballistic/automatic/pistol/m9mmpistol/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][chambered ? "" : "-e"]"
else
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
@@ -117,10 +119,11 @@
automatic_burst_overlay = FALSE
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "deagle",
- "Desert Eagle Gold" = "deagleg",
- "Desert Eagle Camo" = "deaglecamo"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "deagle"),
+ "Desert Eagle Gold" = list("icon_state" = "deagleg"),
+ "Desert Eagle Camo" = list("icon_state" = "deaglecamo")
+ )
/obj/item/gun/ballistic/automatic/pistol/deagle2/update_overlays()
. = ..()
@@ -129,7 +132,7 @@
/obj/item/gun/ballistic/automatic/pistol/deagle2/update_icon_state()
if(current_skin)
- icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"]"
+ icon_state = "[unique_reskin[current_skin]["icon_state"]][chambered ? "" : "-e"]"
else
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
diff --git a/modular_splurt/code/modules/projectiles/guns/ballistic/revolver.dm b/modular_splurt/code/modules/projectiles/guns/ballistic/revolver.dm
index 26f5fa16fa..72e43741f7 100644
--- a/modular_splurt/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/modular_splurt/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -6,12 +6,12 @@
/obj/item/gun/ballistic/revolver/detective/Initialize()
var/list/extra_reskin = list(
- "Fitz Special" = "detective_fitz",
- "Police Positive Special" = "detective_police",
- "Blued Steel" = "detective_blued",
- "Stainless Steel" = "detective_stainless",
- "Deckard Revolver" = "detective_bladerunner"
- )
+ "Fitz Special" = list("icon_state" = "detective_fitz"),
+ "Police Positive Special" = list("icon_state" = "detective_police"),
+ "Blued Steel" = list("icon_state" = "detective_blued"),
+ "Stainless Steel" = list("icon_state" = "detective_stainless"),
+ "Deckard Revolver" = list("icon_state" = "detective_bladerunner")
+ )
LAZYADD(unique_reskin, extra_reskin)
. = ..()
@@ -30,10 +30,11 @@
mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rev45l
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "45revolver",
- "Cowboy" = "357colt",
- "Lucky" = "lucky" //Well do ya?
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "45revolver"),
+ "Cowboy" = list("icon_state" = "357colt"),
+ "Lucky" = list("icon_state" = "lucky") //Well do ya?
+ )
/obj/item/gunpart/revolver22frame
name = ".22 revolver frame"
diff --git a/modular_splurt/code/modules/projectiles/guns/ballistic/shotgun.dm b/modular_splurt/code/modules/projectiles/guns/ballistic/shotgun.dm
index 7a80a74759..fe51069541 100644
--- a/modular_splurt/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/modular_splurt/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -24,13 +24,14 @@
slot_flags = ITEM_SLOT_BELT
mag_type = /obj/item/ammo_box/magazine/internal/shot/dual
obj_flags = UNIQUE_RENAME
- unique_reskin = list("Default" = "sawnshotgun",
- "Dark Red Finish" = "sawnshotgun-d",
- "Ash" = "sawnshotgun-f",
- "Faded Grey" = "sawnshotgun-g",
- "Maple" = "sawnshotgun-l",
- "Rosewood" = "sawnshotgun-p"
- )
+ unique_reskin = list(
+ "Default" = list("icon_state" = "sawnshotgun"),
+ "Dark Red Finish" = list("icon_state" = "sawnshotgun-d"),
+ "Ash" = list("icon_state" = "sawnshotgun-f"),
+ "Faded Grey" = list("icon_state" = "sawnshotgun-g"),
+ "Maple" = list("icon_state" = "sawnshotgun-l"),
+ "Rosewood" = list("icon_state" = "sawnshotgun-p")
+ )
// Rifles
diff --git a/modular_splurt/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/modular_splurt/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 7a2fbfa79b..ca488e2741 100644
--- a/modular_splurt/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/modular_splurt/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -11,18 +11,13 @@
glass_desc = "You feel it's not named like that for no reason."
value = 6
+// Liquid Panty Dropper drink effect
/datum/reagent/consumable/ethanol/panty_dropper/on_mob_life(mob/living/carbon/C)
- var/mob/living/carbon/human/M = C
- var/anyclothes = FALSE
- var/items = M.get_contents()
- for(var/obj/item/W in items)
- if(W.body_parts_covered && ismob(W.loc))
- anyclothes = TRUE
- M.dropItemToGround(W, TRUE)
- playsound(M.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- if(anyclothes)
- M.visible_message("[M] suddenly bursts out of [M.p_their()] clothes! ")
- return ..()
+ // Praise the funny BYOND dots
+ . = ..()
+
+ // Perform drink effect
+ C.clothing_burst(C)
/datum/reagent/consumable/ethanol/lean
name = "Lean"
@@ -147,12 +142,49 @@
boozepwr = 50
color = "#0919be"
quality = DRINK_FANTASTIC
+ value = REAGENT_VALUE_AMAZING
taste_description = "fuzz, warmth and comfort"
glass_icon = 'modular_splurt/icons/obj/drinks.dmi'
glass_icon_state = "mothinchief"
glass_name = "Moth in Chief"
glass_desc = "A simple yet elegant drink, inspires confidence in even the most pessimistic of men. The mantle rests well upon your shoulders."
+ can_synth = FALSE;
+//This drink gives the combined benefits of Stimulants, Regenerative Jelly, and Commander and Chief, and a mood buff similar to Copium; at least to an extent.
+/datum/reagent/consumable/ethanol/commander_and_chief/on_mob_life(mob/living/carbon/M)
+ if(M.mind && HAS_TRAIT(M.mind, TRAIT_CAPTAIN_METABOLISM))
+ M.heal_bodypart_damage(2,2,2)
+ M.adjustBruteLoss(-5,0)
+ M.adjustOxyLoss(-5,0)
+ M.adjustFireLoss(-5,0)
+ M.adjustToxLoss(-5,0,TRUE) //Heals Toxin Lovers
+ M.radiation = max(M.radiation - 25, 0)
+ . = 1
+ else
+ //Commander and Chief Effects, no need to be captain to receive the effect
+ M.heal_bodypart_damage(2,2,2)
+ M.adjustBruteLoss(-3.5,0)
+ M.adjustOxyLoss(-3.5,0)
+ M.adjustFireLoss(-3.5,0)
+ M.adjustToxLoss(-3.5,0,TRUE) //Heals Toxin Lovers
+ M.radiation = max(M.radiation - 25, 0)
+
+ //Stimulant Effects
+ M.AdjustAllImmobility(-60, FALSE)
+ M.AdjustUnconscious(-60, FALSE)
+ M.adjustStaminaLoss(-20*REAGENTS_EFFECT_MULTIPLIER, FALSE)
+ ..()
+ . = 1
+
+/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
+ ..()
+ L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants)
+ ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+
+/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
+ L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants)
+ REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
+ ..()
// ~( Ported from TG )~
/datum/reagent/consumable/ethanol/curacao
@@ -286,3 +318,41 @@
glass_name = "Tropical Storm"
glass_desc = "Less destructive than the real thing."
+/datum/reagent/consumable/ethanol/skullfucker_deluxe
+ name = "Skullfucker Deluxe"
+ description = "The Rosewater secret to becoming psychotically retarded. It has many warning labels."
+ boozepwr = 75
+ color = "#cb4d8b"
+ quality = DRINK_VERYGOOD
+ taste_description = "being violated by a tiny fish with crayons"
+ glass_icon = 'modular_splurt/icons/obj/drinks.dmi'
+ glass_icon_state = "skullfucker"
+ glass_name = "Skullfucker Deluxe"
+ glass_desc = "It has many warning labels, you might want to read them."
+ overdose_threshold = 25
+
+/datum/reagent/consumable/ethanol/skullfucker_deluxe/on_mob_life(mob/living/carbon/C)
+ . = ..()
+ //Do nothing if they haven't metabolized enough
+ if(!current_cycle >= 15)
+ return
+ //Make them giggle
+ if(prob(40))
+ C.emote("giggle")
+ //Make them jitter
+ if(prob(20))
+ C.jitteriness = max(C.jitteriness, 30)
+
+/datum/reagent/consumable/ethanol/skullfucker_deluxe/overdose_process(mob/living/M)
+ . = ..()
+ //Do nothing if they're already fwuffy OwO
+ var/obj/item/organ/tongue/T = M.getorganslot(ORGAN_SLOT_TONGUE)
+ if(istype(T, /obj/item/organ/tongue/fluffy))
+ return
+
+ //Replace their tongue with a fwuffy one
+ var/obj/item/organ/tongue/nT = new /obj/item/organ/tongue/fluffy
+ T.Remove()
+ nT.Insert(M)
+ T.moveToNullspace()//To valhalla
+ to_chat(M, "Your tongue feels... weally fwuffy!! ")
diff --git a/modular_splurt/code/modules/reagents/chemistry/reagents/other_reagents.dm b/modular_splurt/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 31f0580ea2..f8d456ef05 100644
--- a/modular_splurt/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/modular_splurt/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -32,8 +32,43 @@
C.adjust_nutrition(6) //3/4ed this, felt it was a bit too much
C.adjust_disgust(-3) //makes the churches effects easily negated
-/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)//makes holy water slightly disgusting and hungering for vampires
+/datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M)
. = ..()
+ //makes holy water slightly disgusting and hungering for vampires
if(HAS_TRAIT(M,BLOODFLEDGE))
M.adjust_disgust(1)
M.adjust_nutrition(-0.1)
+
+ // Cursed blood effect moved here
+ if(HAS_TRAIT(M, TRAIT_CURSED_BLOOD))
+ // Wait for stuttering, to match old effect
+ if(!M.stuttering)
+ return
+
+ // Escape clause: 12% chance to continue
+ if(!prob(12))
+ return
+
+ // Character speaks nonsense
+ M.say(pick("Somebody help me...","Unshackle me please...","Anybody... I've had enough of this dream...","The night blocks all sight...","Oh, somebody, please..."), forced = "holy water")
+
+ // Escape clause: 10% chance to continue
+ if(!prob(10))
+ return
+
+ // Character has a seisure
+ M.visible_message("[M] starts having a seizure! ", "You have a seizure! ")
+ M.Unconscious(120)
+ to_chat(M, "[pick("The moon is close. It will be a long hunt tonight.", "Ludwig, why have you forsaken me?", \
+ "The night is near its end...", "Fear the blood...")] ")
+
+ // Apply damage
+ M.adjustToxLoss(1, 0)
+ M.adjustFireLoss(1, 0)
+
+ // Escape clause: 25% chance to continue
+ if(!prob(25))
+ return
+
+ // Spontaneous combustion
+ M.IgniteMob()
diff --git a/modular_splurt/code/modules/reagents/reagent_containers/bottle.dm b/modular_splurt/code/modules/reagents/reagent_containers/bottle.dm
index 957cdb52e0..0aab11e5ec 100644
--- a/modular_splurt/code/modules/reagents/reagent_containers/bottle.dm
+++ b/modular_splurt/code/modules/reagents/reagent_containers/bottle.dm
@@ -3,3 +3,11 @@
desc = "A small bottle of Mute Toxin. It stops the user from speaking."
icon_state = "bottle20"
list_reagents = list(/datum/reagent/toxin/mutetoxin = 30)
+
+/obj/item/reagent_containers/glass/bottle/plushmium
+ name = "\improper Plushmium Bottle"
+ desc = "A small bottle of Plushmium. Seems almost fluffy, if not for it being a liquid."
+ icon_state = "bottle20"
+ list_reagents = list(/datum/reagent/fermi/plushmium = 5)
+ possible_transfer_amounts = list(5)
+ volume = 5
diff --git a/modular_splurt/code/modules/reagents/reagent_containers/spray.dm b/modular_splurt/code/modules/reagents/reagent_containers/spray.dm
index df8895c430..e416ca2eb9 100644
--- a/modular_splurt/code/modules/reagents/reagent_containers/spray.dm
+++ b/modular_splurt/code/modules/reagents/reagent_containers/spray.dm
@@ -1,2 +1,25 @@
/obj/item/reagent_containers/spray/chemsprayer/sleeper
list_reagents = list(/datum/reagent/toxin/sodium_thiopental = 100, /datum/reagent/consumable/condensedcapsaicin = 100, /datum/reagent/toxin/chloralhydrate = 100)
+
+/obj/item/reagent_containers/spray/plushmium
+ name = "\improper Love to Life spray bottle"
+ desc = "A toy spray bottle marked with the Donk Co. Stuffing For Spessmen branding. Must be applied directly to a plush, and only contains enough for one."
+ icon_state = "cleaner_drying"
+ // Single use item!
+ volume = 5
+ spray_range = 1
+ can_fill_from_container = FALSE
+ amount_per_transfer_from_this = 5
+ possible_transfer_amounts = list(5)
+ list_reagents = list(/datum/reagent/fermi/plushmium = 5)
+
+// Custom interaction to prevent wasting the item
+/obj/item/reagent_containers/spray/plushmium/afterattack(atom/target, mob/user)
+ // Check for plush toy
+ if(!istype(target, /obj/item/toy/plush))
+ // Alert user and return
+ to_chat(user, "You don't want to waste the solution on a non-plushie. ")
+ return
+
+ // Return normally
+ . = ..()
diff --git a/modular_splurt/code/modules/research/designs/bluespace_designs.dm b/modular_splurt/code/modules/research/designs/bluespace_designs.dm
new file mode 100644
index 0000000000..e44e566a18
--- /dev/null
+++ b/modular_splurt/code/modules/research/designs/bluespace_designs.dm
@@ -0,0 +1,9 @@
+/datum/design/wallet_holding
+ name = "Wallet of Holding"
+ desc = "A wallet that opens into a tiny bluespace pocket."
+ id = "wallet_holding"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/gold = 300, /datum/material/diamond = 100, /datum/material/bluespace = 200)
+ build_path = /obj/item/storage/wallet/bluespace
+ category = list("Bluespace Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
diff --git a/modular_splurt/code/modules/research/designs/medical_designs.dm b/modular_splurt/code/modules/research/designs/medical_designs.dm
index 225e9a88cf..e5228d97ec 100644
--- a/modular_splurt/code/modules/research/designs/medical_designs.dm
+++ b/modular_splurt/code/modules/research/designs/medical_designs.dm
@@ -18,6 +18,16 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_MEDICAL
+/datum/design/implant_hide_backpack
+ name = "Storage Concealment Implant Case"
+ desc = "A glass case containing an implant"
+ id = "implant_hide_backpack"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/glass = 500)
+ build_path = /obj/item/implantcase/hide_backpack
+ category = list("Medical Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_MEDICAL
+
/datum/design/board/implantradio
name = "Radio Implant Case"
desc = "A glass case containing an implant"
diff --git a/modular_splurt/code/modules/research/techweb/nodes/bluespace_nodes.dm b/modular_splurt/code/modules/research/techweb/nodes/bluespace_nodes.dm
index f623c07465..e31c788453 100644
--- a/modular_splurt/code/modules/research/techweb/nodes/bluespace_nodes.dm
+++ b/modular_splurt/code/modules/research/techweb/nodes/bluespace_nodes.dm
@@ -6,3 +6,16 @@
prereq_ids = list("adv_power", "adv_bluespace","bluespace_power")
design_ids = list("bluespace_cell_reactor")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+
+// Bags of holding node
+/datum/techweb_node/bluespace_holding/New()
+ // Define extra designs
+ var/list/added_designs = list(
+ "wallet_holding"
+ )
+
+ // Add designs to the list
+ LAZYADD(design_ids, added_designs)
+
+ // Return
+ . = ..()
diff --git a/modular_splurt/code/modules/research/techweb/nodes/medical_nodes.dm b/modular_splurt/code/modules/research/techweb/nodes/medical_nodes.dm
index 055abbde37..eeb846271f 100644
--- a/modular_splurt/code/modules/research/techweb/nodes/medical_nodes.dm
+++ b/modular_splurt/code/modules/research/techweb/nodes/medical_nodes.dm
@@ -1,7 +1,8 @@
/datum/techweb_node/subdermal_implants/New()
var/list/extra_designs = list(
"implant_gfluid",
- "implant_slave"
+ "implant_slave",
+ "implant_hide_backpack"
)
LAZYADD(design_ids, extra_designs)
. = ..()
diff --git a/modular_splurt/code/modules/vending/clothesmate.dm b/modular_splurt/code/modules/vending/clothesmate.dm
index 3eb8e21e00..d7d67e4011 100644
--- a/modular_splurt/code/modules/vending/clothesmate.dm
+++ b/modular_splurt/code/modules/vending/clothesmate.dm
@@ -14,8 +14,7 @@
/obj/item/clothing/head/helmet/goner/fake/poly = 10,
/obj/item/clothing/under/raccveralls = 3,
/obj/item/clothing/under/officesexy = 3,
- /obj/item/clothing/suit/tunnelfox = 3,
- /obj/item/clothing/suit/tunnelfox_t = 3,
+ /obj/item/clothing/suit/toggle/tunnelfox = 3,
/obj/item/clothing/under/performer = 2,
/obj/item/clothing/under/bluedress = 3
)
@@ -27,6 +26,24 @@
/obj/item/clothing/under/rank/civilian/lawyer/galaxy_blue = 3,
/obj/item/clothing/head/helmet/goner/officer/fake/poly = 10
)
+
+ if(SSevents.holidays && SSevents.holidays[CHRISTMAS])
+ extra_products += list(
+ /obj/item/clothing/accessory/sweater/uglyxmas = 3,
+ /obj/item/clothing/under/costume/christmas = 3,
+ /obj/item/clothing/under/costume/christmas/green = 3,
+ /obj/item/clothing/under/costume/christmas/croptop = 3,
+ /obj/item/clothing/under/costume/christmas/croptop/green = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/christmascoatr = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/christmascoatg = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg = 3,
+ /obj/item/clothing/head/christmashat = 3,
+ /obj/item/clothing/head/christmashatg = 3,
+ /obj/item/clothing/shoes/winterboots/christmasbootsr = 3,
+ /obj/item/clothing/shoes/winterboots/christmasbootsg = 3,
+ /obj/item/clothing/shoes/winterboots/santaboots = 3,
+ )
+
LAZYADD(products, extra_products)
LAZYADD(contraband, extra_contraband)
LAZYADD(premium, extra_premium)
diff --git a/modular_splurt/code/modules/vending/kinkmate.dm b/modular_splurt/code/modules/vending/kinkmate.dm
index 25f18c53c3..c8a626b0c5 100644
--- a/modular_splurt/code/modules/vending/kinkmate.dm
+++ b/modular_splurt/code/modules/vending/kinkmate.dm
@@ -27,7 +27,8 @@
/obj/item/strapon_strap = 5,
/obj/item/restraints/bondage_rope = 5,
/obj/item/clothing/under/domina = 5,
- /obj/item/clothing/under/performer = 3
+ /obj/item/clothing/under/performer = 3,
+ /obj/item/clothing/shoes/invisiboots = 10 // Added here to go with the Gear Harness
)
var/list/extra_contraband = list(
//Lewd-Clothes
@@ -39,7 +40,8 @@
/obj/item/mesmetron = 3,
/obj/item/dildo/flared/huge = 3,
/obj/item/clothing/neck/petcollar/locked/holo = 2,
- /obj/item/storage/box/aphrodisiac_pump/plus = 3
+ /obj/item/storage/box/aphrodisiac_pump/plus = 3,
+ /obj/item/storage/box/implant_disrobe = 3
)
var/list/extra_premium = list(
/obj/item/clothing/mask/muzzle/ballgag = 3
diff --git a/modular_splurt/code/modules/vending/security.dm b/modular_splurt/code/modules/vending/security.dm
index 8d088e9adb..e6d78f958f 100644
--- a/modular_splurt/code/modules/vending/security.dm
+++ b/modular_splurt/code/modules/vending/security.dm
@@ -5,7 +5,10 @@
/obj/item/clothing/suit/armor/vest/peacekeeper = 5,
/obj/item/clothing/suit/armor/vest/metrocop = 2,
/obj/item/clothing/head/helmet/metrocop = 2,
- /obj/item/storage/bag/security = 5
+ /obj/item/storage/bag/security = 5,
+ /obj/item/clothing/head/helmet/blueshirt = 5,
+ /obj/item/clothing/under/rank/security/officer/blueshirt = 5,
+ /obj/item/clothing/suit/armor/vest/blueshirt = 5
)
var/list/extra_contraband = list(
/obj/item/storage/belt/slut = 5,
@@ -20,6 +23,13 @@
)
LAZYADD(products, extra_products)
LAZYADD(contraband, extra_contraband)
+
+ var/list/rem_premium = list(
+ /obj/item/clothing/head/helmet/blueshirt,
+ /obj/item/clothing/under/rank/security/officer/blueshirt,
+ /obj/item/clothing/suit/armor/vest/blueshirt
+ )
+ LAZYREMOVE(premium, rem_premium)
. = ..()
/obj/machinery/vending/wardrobe/sec_wardrobe/Initialize()
diff --git a/modular_splurt/icons/mob/64_mutant_bodyparts.dmi b/modular_splurt/icons/mob/64_mutant_bodyparts.dmi
new file mode 100644
index 0000000000..d90167d4ef
Binary files /dev/null and b/modular_splurt/icons/mob/64_mutant_bodyparts.dmi differ
diff --git a/modular_splurt/icons/mob/actions/misc_actions.dmi b/modular_splurt/icons/mob/actions/misc_actions.dmi
index 17b53a319a..dc254301e7 100644
Binary files a/modular_splurt/icons/mob/actions/misc_actions.dmi and b/modular_splurt/icons/mob/actions/misc_actions.dmi differ
diff --git a/modular_splurt/icons/mob/clothing/64_back.dmi b/modular_splurt/icons/mob/clothing/64_back.dmi
new file mode 100644
index 0000000000..89f7890040
Binary files /dev/null and b/modular_splurt/icons/mob/clothing/64_back.dmi differ
diff --git a/modular_splurt/icons/mob/clothing/uniform_digi.dmi b/modular_splurt/icons/mob/clothing/uniform_digi.dmi
index 5be7dc6120..ce963b6af7 100644
Binary files a/modular_splurt/icons/mob/clothing/uniform_digi.dmi and b/modular_splurt/icons/mob/clothing/uniform_digi.dmi differ
diff --git a/modular_splurt/icons/mob/lavaland/mayhem_mega.dmi b/modular_splurt/icons/mob/lavaland/mayhem_mega.dmi
new file mode 100644
index 0000000000..9179698a8e
Binary files /dev/null and b/modular_splurt/icons/mob/lavaland/mayhem_mega.dmi differ
diff --git a/modular_splurt/icons/mob/mam_markings.dmi b/modular_splurt/icons/mob/mam_markings.dmi
index 0ce5f4c425..d2b389c66e 100644
Binary files a/modular_splurt/icons/mob/mam_markings.dmi and b/modular_splurt/icons/mob/mam_markings.dmi differ
diff --git a/modular_splurt/icons/mob/mam_snouts.dmi b/modular_splurt/icons/mob/mam_snouts.dmi
index 3b4850f4ca..27bab79b2d 100644
Binary files a/modular_splurt/icons/mob/mam_snouts.dmi and b/modular_splurt/icons/mob/mam_snouts.dmi differ
diff --git a/modular_splurt/icons/mob/mam_taur.dmi b/modular_splurt/icons/mob/mam_taur.dmi
index ba18519f8d..009148695d 100644
Binary files a/modular_splurt/icons/mob/mam_taur.dmi and b/modular_splurt/icons/mob/mam_taur.dmi differ
diff --git a/modular_splurt/icons/obj/drinks.dmi b/modular_splurt/icons/obj/drinks.dmi
index 91ad1df14e..4339e5560a 100644
Binary files a/modular_splurt/icons/obj/drinks.dmi and b/modular_splurt/icons/obj/drinks.dmi differ
diff --git a/modular_splurt/icons/obj/genitals/butt_onmob.dmi b/modular_splurt/icons/obj/genitals/butt_onmob.dmi
index 3dfc27316a..4cf7ee313e 100644
Binary files a/modular_splurt/icons/obj/genitals/butt_onmob.dmi and b/modular_splurt/icons/obj/genitals/butt_onmob.dmi differ
diff --git a/modular_splurt/icons/obj/plushes.dmi b/modular_splurt/icons/obj/plushes.dmi
index fce9b88804..a8ce5f21fd 100644
Binary files a/modular_splurt/icons/obj/plushes.dmi and b/modular_splurt/icons/obj/plushes.dmi differ
diff --git a/modular_splurt/icons/obj/storage.dmi b/modular_splurt/icons/obj/storage.dmi
index 1b8f40e8a0..6ff028b18c 100644
Binary files a/modular_splurt/icons/obj/storage.dmi and b/modular_splurt/icons/obj/storage.dmi differ
diff --git a/modular_splurt/icons/obj/structures/statue.dmi b/modular_splurt/icons/obj/structures/statue.dmi
index d933259adc..358c6c21ed 100644
Binary files a/modular_splurt/icons/obj/structures/statue.dmi and b/modular_splurt/icons/obj/structures/statue.dmi differ
diff --git a/modular_splurt/sound/misc/dog_toy.ogg b/modular_splurt/sound/misc/dog_toy.ogg
new file mode 100644
index 0000000000..de295dc148
Binary files /dev/null and b/modular_splurt/sound/misc/dog_toy.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ahuh.ogg b/modular_splurt/sound/voice/barks/kazooie/ahuh.ogg
new file mode 100644
index 0000000000..fbade63d6d
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ahuh.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/birdwhistle.ogg b/modular_splurt/sound/voice/barks/kazooie/birdwhistle.ogg
new file mode 100644
index 0000000000..f970f8af45
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/birdwhistle.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/birdwhistle2.ogg b/modular_splurt/sound/voice/barks/kazooie/birdwhistle2.ogg
new file mode 100644
index 0000000000..61fd3e850b
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/birdwhistle2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/caw.ogg b/modular_splurt/sound/voice/barks/kazooie/caw.ogg
new file mode 100644
index 0000000000..21181b6519
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/caw.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/caw2.ogg b/modular_splurt/sound/voice/barks/kazooie/caw2.ogg
new file mode 100644
index 0000000000..e4e4645034
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/caw2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/caw3.ogg b/modular_splurt/sound/voice/barks/kazooie/caw3.ogg
new file mode 100644
index 0000000000..8339440d77
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/caw3.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/cry.ogg b/modular_splurt/sound/voice/barks/kazooie/cry.ogg
new file mode 100644
index 0000000000..b34b8d0c49
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/cry.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/dwoop.ogg b/modular_splurt/sound/voice/barks/kazooie/dwoop.ogg
new file mode 100644
index 0000000000..785a18431f
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/dwoop.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ehh.ogg b/modular_splurt/sound/voice/barks/kazooie/ehh.ogg
new file mode 100644
index 0000000000..c0b5591ed5
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ehh.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ehh2.ogg b/modular_splurt/sound/voice/barks/kazooie/ehh2.ogg
new file mode 100644
index 0000000000..830bb1e29e
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ehh2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ehh3.ogg b/modular_splurt/sound/voice/barks/kazooie/ehh3.ogg
new file mode 100644
index 0000000000..bb0925b68b
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ehh3.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ehh4.ogg b/modular_splurt/sound/voice/barks/kazooie/ehh4.ogg
new file mode 100644
index 0000000000..5797b13179
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ehh4.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ehh5.ogg b/modular_splurt/sound/voice/barks/kazooie/ehh5.ogg
new file mode 100644
index 0000000000..970a2040bc
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ehh5.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/eugh.ogg b/modular_splurt/sound/voice/barks/kazooie/eugh.ogg
new file mode 100644
index 0000000000..6ba2440e0e
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/eugh.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/faucet.ogg b/modular_splurt/sound/voice/barks/kazooie/faucet.ogg
new file mode 100644
index 0000000000..56a98a8539
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/faucet.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/faucet2.ogg b/modular_splurt/sound/voice/barks/kazooie/faucet2.ogg
new file mode 100644
index 0000000000..02af88442a
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/faucet2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/growl.ogg b/modular_splurt/sound/voice/barks/kazooie/growl.ogg
new file mode 100644
index 0000000000..b6dd00a75c
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/growl.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/growl2.ogg b/modular_splurt/sound/voice/barks/kazooie/growl2.ogg
new file mode 100644
index 0000000000..5bd7219602
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/growl2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/haha.ogg b/modular_splurt/sound/voice/barks/kazooie/haha.ogg
new file mode 100644
index 0000000000..9ac43ce03c
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/haha.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/hoot.ogg b/modular_splurt/sound/voice/barks/kazooie/hoot.ogg
new file mode 100644
index 0000000000..316949652c
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/hoot.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/moan1.ogg b/modular_splurt/sound/voice/barks/kazooie/moan1.ogg
new file mode 100644
index 0000000000..8c014e4de0
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/moan1.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/moan2.ogg b/modular_splurt/sound/voice/barks/kazooie/moan2.ogg
new file mode 100644
index 0000000000..4e6077552c
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/moan2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/moan3.ogg b/modular_splurt/sound/voice/barks/kazooie/moan3.ogg
new file mode 100644
index 0000000000..d3193a5693
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/moan3.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/raah1.ogg b/modular_splurt/sound/voice/barks/kazooie/raah1.ogg
new file mode 100644
index 0000000000..74e4781177
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/raah1.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/raah2.ogg b/modular_splurt/sound/voice/barks/kazooie/raah2.ogg
new file mode 100644
index 0000000000..ba3ff4f698
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/raah2.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/ribbit.ogg b/modular_splurt/sound/voice/barks/kazooie/ribbit.ogg
new file mode 100644
index 0000000000..a4299d2a74
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/ribbit.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/slurp.ogg b/modular_splurt/sound/voice/barks/kazooie/slurp.ogg
new file mode 100644
index 0000000000..a8518068c1
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/slurp.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/tweet.ogg b/modular_splurt/sound/voice/barks/kazooie/tweet.ogg
new file mode 100644
index 0000000000..b784636e25
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/tweet.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/uhm.ogg b/modular_splurt/sound/voice/barks/kazooie/uhm.ogg
new file mode 100644
index 0000000000..857e99c7c5
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/uhm.ogg differ
diff --git a/modular_splurt/sound/voice/barks/kazooie/zap.ogg b/modular_splurt/sound/voice/barks/kazooie/zap.ogg
new file mode 100644
index 0000000000..524c73b1cd
Binary files /dev/null and b/modular_splurt/sound/voice/barks/kazooie/zap.ogg differ
diff --git a/modular_splurt/sound/voice/barks/poyo.ogg b/modular_splurt/sound/voice/barks/poyo.ogg
new file mode 100644
index 0000000000..8b2a041e4d
Binary files /dev/null and b/modular_splurt/sound/voice/barks/poyo.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 89907b5d3a..f63f043c08 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -222,6 +222,7 @@
#include "code\__HELPERS\vector.dm"
#include "code\__HELPERS\verbs.dm"
#include "code\__HELPERS\view.dm"
+#include "code\__HELPERS\weakref.dm"
#include "code\__HELPERS\yelling.dm"
#include "code\__HELPERS\matrices\color_matrix.dm"
#include "code\__HELPERS\matrices\transform_matrix.dm"
@@ -239,6 +240,7 @@
#include "code\__SANDCODE\DEFINES\runechat_defines.dm"
#include "code\__SANDCODE\DEFINES\signals.dm"
#include "code\__SANDCODE\DEFINES\sizecode.dm"
+#include "code\__SANDCODE\DEFINES\spans.dm"
#include "code\__SANDCODE\DEFINES\status_effects.dm"
#include "code\__SANDCODE\DEFINES\strippable.dm"
#include "code\__SANDCODE\DEFINES\subsystems.dm"
@@ -265,7 +267,6 @@
#include "code\__SPLURTCODE\DEFINES\rope.dm"
#include "code\__SPLURTCODE\DEFINES\say.dm"
#include "code\__SPLURTCODE\DEFINES\signals.dm"
-#include "code\__SPLURTCODE\DEFINES\spans.dm"
#include "code\__SPLURTCODE\DEFINES\species.dm"
#include "code\__SPLURTCODE\DEFINES\subsystems.dm"
#include "code\__SPLURTCODE\DEFINES\traits.dm"
@@ -574,6 +575,7 @@
#include "code\datums\components\combat_mode.dm"
#include "code\datums\components\construction.dm"
#include "code\datums\components\dejavu.dm"
+#include "code\datums\components\dullahan.dm"
#include "code\datums\components\earprotection.dm"
#include "code\datums\components\edible.dm"
#include "code\datums\components\edit_complainer.dm"
@@ -726,6 +728,7 @@
#include "code\datums\elements\bed_tucking.dm"
#include "code\datums\elements\bsa_blocker.dm"
#include "code\datums\elements\cleaning.dm"
+#include "code\datums\elements\connect_loc.dm"
#include "code\datums\elements\decal.dm"
#include "code\datums\elements\dusts_on_catatonia.dm"
#include "code\datums\elements\dusts_on_leaving_area.dm"
@@ -738,6 +741,7 @@
#include "code\datums\elements\forced_gravity.dm"
#include "code\datums\elements\ghost_role_eligibility.dm"
#include "code\datums\elements\mob_holder.dm"
+#include "code\datums\elements\object_reskinning.dm"
#include "code\datums\elements\photosynthesis.dm"
#include "code\datums\elements\polychromic.dm"
#include "code\datums\elements\scavenging.dm"
@@ -2076,6 +2080,7 @@
#include "code\modules\clothing\glasses\engine_goggles.dm"
#include "code\modules\clothing\glasses\hud.dm"
#include "code\modules\clothing\glasses\phantomthief.dm"
+#include "code\modules\clothing\glasses\prescription_kit.dm"
#include "code\modules\clothing\gloves\_gloves.dm"
#include "code\modules\clothing\gloves\boxing.dm"
#include "code\modules\clothing\gloves\color.dm"
@@ -2757,7 +2762,6 @@
#include "code\modules\mob\living\carbon\human\species_types\arachnid.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"
#include "code\modules\mob\living\carbon\human\species_types\dwarves.dm"
#include "code\modules\mob\living\carbon\human\species_types\ethereal.dm"
#include "code\modules\mob\living\carbon\human\species_types\felinid.dm"
@@ -3366,6 +3370,7 @@
#include "code\modules\reagents\reagent_containers\spray.dm"
#include "code\modules\reagents\reagent_containers\syringes.dm"
#include "code\modules\recycling\conveyor2.dm"
+#include "code\modules\recycling\conveyor_sorter.dm"
#include "code\modules\recycling\sortingmachinery.dm"
#include "code\modules\recycling\disposal\bin.dm"
#include "code\modules\recycling\disposal\construction.dm"
@@ -4053,6 +4058,7 @@
#include "modular_sand\code\modules\arousal\arousal.dm"
#include "modular_sand\code\modules\arousal\creampie.dm"
#include "modular_sand\code\modules\arousal\genital_sprite_accessories.dm"
+#include "modular_sand\code\modules\arousal\genitals.dm"
#include "modular_sand\code\modules\arousal\organs\breasts.dm"
#include "modular_sand\code\modules\arousal\organs\womb.dm"
#include "modular_sand\code\modules\atmospherics\machinery\pipes\bluespace.dm"
@@ -4091,6 +4097,7 @@
#include "modular_sand\code\modules\clothing\spacesuits\chronosuit.dm"
#include "modular_sand\code\modules\clothing\spacesuits\hardsuit.dm"
#include "modular_sand\code\modules\clothing\suits\miscellaneous.dm"
+#include "modular_sand\code\modules\clothing\under\_under.dm"
#include "modular_sand\code\modules\clothing\under\color.dm"
#include "modular_sand\code\modules\clothing\under\costumes.dm"
#include "modular_sand\code\modules\clothing\under\misc.dm"
@@ -4098,15 +4105,6 @@
#include "modular_sand\code\modules\clothing\under\suits.dm"
#include "modular_sand\code\modules\clothing\under\syndicate.dm"
#include "modular_sand\code\modules\clothing\under\uniform.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\cargo.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\civilian.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\command.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\curator.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\engineering.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\medical.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\research.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\security.dm"
-#include "modular_sand\code\modules\clothing\under\jobs\theater.dm"
#include "modular_sand\code\modules\clothing\underwear\_underwear.dm"
#include "modular_sand\code\modules\clothing\underwear\boxers.dm"
#include "modular_sand\code\modules\clothing\underwear\shirts.dm"
@@ -4332,12 +4330,14 @@
#include "modular_splurt\code\datums\traits\good.dm"
#include "modular_splurt\code\datums\traits\negative.dm"
#include "modular_splurt\code\datums\traits\neutral.dm"
+#include "modular_splurt\code\datums\traits\trait_actions.dm"
#include "modular_splurt\code\game\atoms.dm"
#include "modular_splurt\code\game\atoms_movable.dm"
#include "modular_splurt\code\game\data_huds.dm"
#include "modular_splurt\code\game\say.dm"
#include "modular_splurt\code\game\area\areas\centcom.dm"
#include "modular_splurt\code\game\area\areas\commons.dm"
+#include "modular_splurt\code\game\area\areas\holodeck.dm"
#include "modular_splurt\code\game\area\areas\layenia.dm"
#include "modular_splurt\code\game\area\areas\maintenance.dm"
#include "modular_splurt\code\game\area\areas\shuttles.dm"
@@ -4380,10 +4380,13 @@
#include "modular_splurt\code\game\objects\items\circuitboards\computer_circuitboards.dm"
#include "modular_splurt\code\game\objects\items\circuitboards\machine_circuitboards.dm"
#include "modular_splurt\code\game\objects\items\circuitboards\miner_circuitboards.dm"
+#include "modular_splurt\code\game\objects\items\devices\PDA\radio.dm"
#include "modular_splurt\code\game\objects\items\devices\radio\electropack.dm"
#include "modular_splurt\code\game\objects\items\devices\radio\headset.dm"
#include "modular_splurt\code\game\objects\items\implants\implant_aphropumps.dm"
+#include "modular_splurt\code\game\objects\items\implants\implant_disrobe.dm"
#include "modular_splurt\code\game\objects\items\implants\implant_gfluid.dm"
+#include "modular_splurt\code\game\objects\items\implants\implant_hide_backpack.dm"
#include "modular_splurt\code\game\objects\items\implants\implant_slave.dm"
#include "modular_splurt\code\game\objects\items\implants\implant_slaver.dm"
#include "modular_splurt\code\game\objects\items\implants\implantcase.dm"
@@ -4408,6 +4411,7 @@
#include "modular_splurt\code\game\objects\items\storage\boxes.dm"
#include "modular_splurt\code\game\objects\items\storage\firstaid.dm"
#include "modular_splurt\code\game\objects\items\storage\secure.dm"
+#include "modular_splurt\code\game\objects\items\storage\wallets.dm"
#include "modular_splurt\code\game\objects\items\weaponry\armyknife.dm"
#include "modular_splurt\code\game\objects\items\weaponry\melee.dm"
#include "modular_splurt\code\game\objects\structures\barricades.dm"
@@ -4494,6 +4498,7 @@
#include "modular_splurt\code\modules\atmospherics\machinery\components\unary_devices\vent_pump.dm"
#include "modular_splurt\code\modules\atmospherics\machinery\components\unary_devices\vent_scrubber.dm"
#include "modular_splurt\code\modules\atmospherics\machinery\other\miner.dm"
+#include "modular_splurt\code\modules\awaymissions\mission_code\academy.dm"
#include "modular_splurt\code\modules\cargo\supplypod.dm"
#include "modular_splurt\code\modules\cargo\blackmarket\clothing.dm"
#include "modular_splurt\code\modules\cargo\blackmarket\misc.dm"
@@ -4606,6 +4611,7 @@
#include "modular_splurt\code\modules\food_and_drinks\recipes\tablecraft\recipes_burger.dm"
#include "modular_splurt\code\modules\food_and_drinks\recipes\tablecraft\recipes_donut.dm"
#include "modular_splurt\code\modules\holiday\holidays.dm"
+#include "modular_splurt\code\modules\holodeck\holo_effect.dm"
#include "modular_splurt\code\modules\hydroponics\grown\towercap.dm"
#include "modular_splurt\code\modules\jobs\job_types\_job_alt_titles.dm"
#include "modular_splurt\code\modules\jobs\job_types\atmospheric_technician.dm"
@@ -4636,6 +4642,7 @@
#include "modular_splurt\code\modules\mob\emote.dm"
#include "modular_splurt\code\modules\mob\mob.dm"
#include "modular_splurt\code\modules\mob\mob_defines.dm"
+#include "modular_splurt\code\modules\mob\mob_helpers.dm"
#include "modular_splurt\code\modules\mob\mob_movement.dm"
#include "modular_splurt\code\modules\mob\say_vr.dm"
#include "modular_splurt\code\modules\mob\splurt_emotes.dm"
@@ -4665,7 +4672,9 @@
#include "modular_splurt\code\modules\mob\living\carbon\carbon.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\human_defines.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\human\physiology.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species.dm"
+#include "modular_splurt\code\modules\mob\living\carbon\human\update_icons.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\simple_animal\hostile\deathclaw\deathclaw.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\simple_animal\hostile\deathclaw\funclaw.dm"
#include "modular_splurt\code\modules\mob\living\carbon\human\species_types\arachnid.dm"
@@ -4688,7 +4697,9 @@
#include "modular_splurt\code\modules\mob\living\simple_animal\gremlin\gremlin.dm"
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\carrion.dm"
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\dancer.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\blood_drunk_miner.dm"
#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\king_of_goats.dm"
+#include "modular_splurt\code\modules\mob\living\simple_animal\hostile\megafauna\sand.dm"
#include "modular_splurt\code\modules\paperwork\pen.dm"
#include "modular_splurt\code\modules\power\cell.dm"
#include "modular_splurt\code\modules\power\reactor\fluffed.dm"
@@ -4730,6 +4741,7 @@
#include "modular_splurt\code\modules\research\designs\AI_module_designs.dm"
#include "modular_splurt\code\modules\research\designs\autoylathe_designs.dm"
#include "modular_splurt\code\modules\research\designs\biogenerator_designs.dm"
+#include "modular_splurt\code\modules\research\designs\bluespace_designs.dm"
#include "modular_splurt\code\modules\research\designs\limbgrower_designs.dm"
#include "modular_splurt\code\modules\research\designs\mecha_designs.dm"
#include "modular_splurt\code\modules\research\designs\mechfabricator_designs.dm"
diff --git a/tgui/packages/tgui/interfaces/MobInteraction.tsx b/tgui/packages/tgui/interfaces/MobInteraction.tsx
index 84b95fe13a..3aba47c5fc 100644
--- a/tgui/packages/tgui/interfaces/MobInteraction.tsx
+++ b/tgui/packages/tgui/interfaces/MobInteraction.tsx
@@ -2,8 +2,8 @@ import { filter, map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { createSearch } from 'common/string';
import { useBackend, useLocalState } from '../backend';
-import { BlockQuote, Button, LabeledList, Icon, Input, Section, Table, Tabs, Stack, ProgressBar, Divider } from '../components';
-import { TableRow } from '../components/Table';
+import { BlockQuote, Button, Flex, LabeledList, Icon, Input, Section, Table, Tabs, Stack, ProgressBar, Divider } from '../components';
+import { TableCell, TableRow } from '../components/Table';
import { Window } from '../layouts';
type HeaderInfo = {
@@ -34,6 +34,9 @@ type GenitalData = {
extras: string,
extra_choices: string[],
possible_choices: string[],
+ can_arouse: boolean,
+ arousal_state: boolean,
+ always_accessible: boolean,
}
type GenitalManagerInfo = {
@@ -65,27 +68,27 @@ type CharacterPrefsInfo = {
}
type ContentPrefsInfo = {
- verb_consent: number,
- lewd_verb_sounds: number,
- arousable: number,
- genital_examine: number,
- vore_examine: number,
- medihound_sleeper: number,
- eating_noises: number,
- digestion_noises: number,
- trash_forcefeed: number,
- forced_fem: number,
- forced_masc: number,
- hypno: number,
- bimbofication: number,
- breast_enlargement: number,
- penis_enlargement: number,
- butt_enlargement: number,
- belly_inflation: number,
- never_hypno: number,
- no_aphro: number,
- no_ass_slap: number,
- no_auto_wag: number,
+ verb_consent: boolean,
+ lewd_verb_sounds: boolean,
+ arousable: boolean,
+ genital_examine: boolean,
+ vore_examine: boolean,
+ medihound_sleeper: boolean,
+ eating_noises: boolean,
+ digestion_noises: boolean,
+ trash_forcefeed: boolean,
+ forced_fem: boolean,
+ forced_masc: boolean,
+ hypno: boolean,
+ bimbofication: boolean,
+ breast_enlargement: boolean,
+ penis_enlargement: boolean,
+ butt_enlargement: boolean,
+ belly_inflation: boolean,
+ never_hypno: boolean,
+ no_aphro: boolean,
+ no_ass_slap: boolean,
+ no_auto_wag: boolean,
}
export const MobInteraction = (props, context) => {
@@ -131,12 +134,12 @@ export const MobInteraction = (props, context) => {
-
+
setTabIndex(0)}>
Interactions
setTabIndex(1)}>
- Genital Visibility
+ Genital Options
setTabIndex(2)}>
Character Prefs
@@ -151,7 +154,7 @@ export const MobInteraction = (props, context) => {
{tabIndex === 0 && (
) || tabIndex === 1 && (
-
+
) || tabIndex === 2 && (
) || tabIndex === 3 && (
@@ -243,42 +246,85 @@ const ModeToIcon = {
"Allows egg stuffing": "egg",
};
-const GenitalVisibilityTab = (props, context) => {
+/*
+ Greetings you, yes you, adding more stuff to actions,
+ To not have as much headache as i did,
+ do not attempt to make a sum of 100% with the buttons
+ as it will mess up math somewhere and overflow.
+
+ Also this is adjusted only for the current size,
+ if anyone feels like shrinking,
+ their window it will overflow anyways.
+ Single items is fine.
+*/
+const GenitalTab = (props, context) => {
const { act, data } = useBackend(context);
const genitals = data.genitals || [];
return (
genitals.length ? (
-
-
- {genitals.map(genital => (
-
- {genital.possible_choices.map(choice => (
- act('genital', {
- genital: genital.key,
- visibility: choice,
- })} />
- ))}
- {genital.extra_choices instanceof Array
- ? genital.extra_choices.map(choice => (
+
+ {genitals.map(genital => (
+
+
+
+ Visibility
+ {genital.possible_choices.map(choice => (
act('genital', {
genital: genital.key,
visibility: choice,
})} />
- )) : null}
-
- ))}
-
-
+ ))}
+
+
+ Actions
+ act('genital', {
+ genital: genital.key,
+ set_arousal: !genital.arousal_state,
+ })} />
+ {genital.extra_choices instanceof Array
+ ? genital.extra_choices.map(choice => (
+ act('genital', {
+ genital: genital.key,
+ visibility: choice,
+ })} />
+ )) : null}
+ act('genital', {
+ genital: genital.key,
+ set_accessibility: true,
+ })} />
+
+
+
+ ))}
+
) : (
You don't seem to have any genitals...
diff --git a/tgui/packages/tgui/interfaces/SuitStorageUnit.js b/tgui/packages/tgui/interfaces/SuitStorageUnit.js
index c6f66a79d2..0ac3c61932 100644
--- a/tgui/packages/tgui/interfaces/SuitStorageUnit.js
+++ b/tgui/packages/tgui/interfaces/SuitStorageUnit.js
@@ -14,6 +14,7 @@ export const SuitStorageUnit = (props, context) => {
suit,
helmet,
mask,
+ shoes,
storage,
} = data;
return (
@@ -89,6 +90,15 @@ export const SuitStorageUnit = (props, context) => {
item: 'mask',
})} />
+
+ act('dispense', {
+ item: 'shoes',
+ })} />
+