diff --git a/Dockerfile b/Dockerfile
index ec3694c7e8..ad347079cd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM tgstation/byond:512.1488 as base
+FROM tgstation/byond:513.1490 as base
FROM base as build_base
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
index ed5b07168f..bb9bc75d25 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
@@ -475,6 +475,8 @@
dir = 4
},
/obj/item/storage/bag/plants/portaseeder,
+/obj/item/seeds/cotton,
+/obj/item/seeds/cotton,
/turf/open/indestructible/boss,
/area/ruin/unpowered/ash_walkers)
"bk" = (
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
index 8015f25696..2c6eda9f90 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm
@@ -68,7 +68,10 @@
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
"k" = (
-/obj/machinery/computer/arcade/battle,
+/obj/machinery/computer/arcade/battle{
+ icon_state = "arcade";
+ dir = 4
+ },
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
"l" = (
@@ -105,6 +108,13 @@
/obj/machinery/computer/shuttle,
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
+"s" = (
+/obj/machinery/computer/arcade/orion_trail{
+ icon_state = "arcade";
+ dir = 4
+ },
+/turf/open/floor/mineral/titanium/purple,
+/area/ruin/powered/golem_ship)
"t" = (
/obj/structure/extinguisher_cabinet{
pixel_y = 30
@@ -142,10 +152,6 @@
/obj/machinery/reagentgrinder,
/turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship)
-"y" = (
-/obj/machinery/computer/arcade/orion_trail,
-/turf/open/floor/mineral/titanium/purple,
-/area/ruin/powered/golem_ship)
"z" = (
/obj/structure/extinguisher_cabinet{
pixel_y = -30
@@ -332,7 +338,7 @@ l
l
j
l
-y
+s
b
a
a
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
index 8e0d9a523a..2ec5b88792 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
@@ -167,6 +167,56 @@
},
/turf/open/floor/plating,
/area/ruin/unpowered/syndicate_lava_base/circuits)
+"av" = (
+/obj/structure/bed/roller,
+/obj/machinery/iv_drip,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/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
+ },
+/mob/living/carbon/monkey{
+ faction = list("neutral","Syndicate")
+ },
+/turf/open/floor/plasteel/dark,
+/area/ruin/unpowered/syndicate_lava_base/testlab)
+"aw" = (
+/obj/machinery/light/small,
+/obj/structure/bed/roller,
+/obj/machinery/iv_drip,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/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
+ },
+/mob/living/carbon/monkey{
+ faction = list("neutral","Syndicate")
+ },
+/turf/open/floor/plasteel/dark,
+/area/ruin/unpowered/syndicate_lava_base/testlab)
+"ax" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/computer/arcade/orion_trail{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/ruin/unpowered/syndicate_lava_base/bar)
"aF" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{
dir = 4
@@ -790,26 +840,6 @@
/obj/structure/disposalpipe/trunk,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/syndicate_lava_base/virology)
-"ej" = (
-/obj/structure/bed/roller,
-/obj/machinery/iv_drip,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/dirt,
-/mob/living/carbon/monkey{
- faction = list("neutral","Syndicate")
- },
-/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/ruin/unpowered/syndicate_lava_base/testlab)
"ek" = (
/obj/structure/grille,
/obj/structure/window/plastitanium,
@@ -1136,27 +1166,6 @@
/obj/structure/disposalpipe/segment,
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/area/ruin/unpowered/syndicate_lava_base/virology)
-"eK" = (
-/obj/machinery/light/small,
-/obj/structure/bed/roller,
-/obj/machinery/iv_drip,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/dirt,
-/mob/living/carbon/monkey{
- faction = list("neutral","Syndicate")
- },
-/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/ruin/unpowered/syndicate_lava_base/testlab)
"eL" = (
/obj/machinery/door/airlock/hatch{
name = "Monkey Pen";
@@ -5148,12 +5157,6 @@
/obj/item/clothing/mask/gas,
/turf/open/floor/plating,
/area/ruin/unpowered/syndicate_lava_base/arrivals)
-"mt" = (
-/obj/machinery/computer/arcade/orion_trail,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plasteel/dark,
-/area/ruin/unpowered/syndicate_lava_base/bar)
"mu" = (
/obj/item/twohanded/required/kirbyplants{
icon_state = "plant-22"
@@ -7340,8 +7343,8 @@ ae
ae
ae
ae
-ej
-eK
+av
+aw
ae
fD
ad
@@ -7362,7 +7365,7 @@ kH
jN
jZ
lU
-mt
+ax
mU
np
nP
diff --git a/_maps/RandomRuins/SpaceRuins/bigape.dmm b/_maps/RandomRuins/SpaceRuins/bigape.dmm
index 09e85e129d..602f1737e0 100644
--- a/_maps/RandomRuins/SpaceRuins/bigape.dmm
+++ b/_maps/RandomRuins/SpaceRuins/bigape.dmm
@@ -56,11 +56,9 @@
/obj/structure/chair/sofa{
dir = 4
},
-/mob/living/simple_animal/hostile/gorilla{
- AIStatus = null;
- desc = "There is no need to be upset.";
- dir = 4;
- name = "Familiar Gorilla"
+/mob/living/simple_animal/hostile/gorilla/familiar{
+ icon_state = "crawling";
+ dir = 4
},
/turf/open/floor/plating/beach/sand,
/area/ruin/powered)
diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm
index c251a338a5..ddc8778ac1 100644
--- a/_maps/RandomZLevels/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/moonoutpost19.dmm
@@ -16,6 +16,13 @@
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/hive)
+"ae" = (
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/awaymission/moonoutpost19/arrivals)
"ag" = (
/obj/structure/alien/weeds,
/obj/structure/alien/weeds{
@@ -6408,10 +6415,6 @@
heat_capacity = 1e+006
},
/area/awaymission/moonoutpost19/arrivals)
-"mB" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/plasteel/dark,
-/area/awaymission/moonoutpost19/arrivals)
"mC" = (
/obj/machinery/vending/cigarette,
/obj/structure/sign/poster/contraband/smoke{
@@ -43385,7 +43388,7 @@ la
lq
jk
mj
-mB
+ae
hJ
ba
ba
@@ -43642,7 +43645,7 @@ jN
lr
jj
mj
-mB
+ae
hI
ba
ba
diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm
index 3a58d85143..2499270d8f 100644
--- a/_maps/RandomZLevels/research.dmm
+++ b/_maps/RandomZLevels/research.dmm
@@ -245,10 +245,38 @@
},
/turf/open/floor/plating,
/area/awaymission/research/interior/engineering)
+"aS" = (
+/obj/effect/turf_decal/tile/purple{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/purple,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 8
+ },
+/mob/living/carbon/monkey,
+/turf/open/floor/plasteel,
+/area/awaymission/research/interior/genetics)
"aT" = (
/mob/living/simple_animal/hostile/syndicate/melee/sword,
/turf/open/floor/plating,
/area/awaymission/research/interior/engineering)
+"aU" = (
+/obj/effect/turf_decal/tile/purple{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/purple,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 8
+ },
+/mob/living/carbon/human,
+/turf/open/floor/plasteel,
+/area/awaymission/research/interior/genetics)
"aV" = (
/obj/item/stack/sheet/plasteel,
/obj/effect/turf_decal/tile/yellow{
@@ -326,6 +354,23 @@
icon_state = "damaged4"
},
/area/awaymission/research/interior/engineering)
+"bc" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/purple,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 8
+ },
+/mob/living/carbon/monkey,
+/turf/open/floor/plasteel,
+/area/awaymission/research/interior/genetics)
"bd" = (
/turf/open/floor/plasteel{
icon_state = "damaged3"
@@ -903,6 +948,17 @@
/obj/machinery/light/small,
/turf/open/floor/plating,
/area/awaymission/research/interior/maint)
+"co" = (
+/obj/item/ammo_casing/c45,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/syndicate,
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior)
"cp" = (
/turf/closed/wall/r_wall,
/area/awaymission/research/interior)
@@ -1195,19 +1251,19 @@
/turf/open/floor/plating,
/area/awaymission/research/interior/genetics)
"cT" = (
-/mob/living/carbon/monkey,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/red{
dir = 1
},
-/obj/effect/turf_decal/tile/purple,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
dir = 4
},
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/red{
dir = 8
},
+/mob/living/simple_animal/hostile/nanotrasen/ranged,
/turf/open/floor/plasteel,
-/area/awaymission/research/interior/genetics)
+/area/awaymission/research/interior/security)
"cU" = (
/obj/machinery/door/window/eastright,
/obj/effect/turf_decal/tile/purple{
@@ -1253,7 +1309,9 @@
/turf/open/floor/plasteel,
/area/awaymission/research/interior/genetics)
"cX" = (
-/mob/living/carbon/human,
+/obj/structure/window/reinforced{
+ dir = 8
+ },
/obj/effect/turf_decal/tile/purple{
dir = 1
},
@@ -1264,6 +1322,7 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/mob/living/carbon/human,
/turf/open/floor/plasteel,
/area/awaymission/research/interior/genetics)
"cY" = (
@@ -1356,22 +1415,15 @@
/turf/open/floor/plasteel,
/area/awaymission/research/interior/genetics)
"di" = (
-/obj/structure/window/reinforced{
- dir = 4
- },
-/mob/living/carbon/monkey,
/obj/effect/turf_decal/tile/purple{
dir = 1
},
-/obj/effect/turf_decal/tile/purple,
/obj/effect/turf_decal/tile/purple{
dir = 4
},
-/obj/effect/turf_decal/tile/purple{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/research/interior/genetics)
+/mob/living/simple_animal/hostile/nanotrasen/ranged,
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior/cryo)
"dj" = (
/obj/effect/decal/cleanable/blood,
/obj/item/stack/rods,
@@ -1416,14 +1468,14 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior)
"dn" = (
-/obj/item/ammo_casing/c45,
-/mob/living/simple_animal/hostile/syndicate,
/obj/effect/turf_decal/tile/yellow{
dir = 1
},
+/obj/effect/turf_decal/tile/yellow,
/obj/effect/turf_decal/tile/yellow{
- dir = 8
+ dir = 4
},
+/mob/living/simple_animal/hostile/syndicate,
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior)
"do" = (
@@ -1675,7 +1727,6 @@
/turf/open/floor/plasteel,
/area/awaymission/research/interior/security)
"dI" = (
-/mob/living/simple_animal/hostile/nanotrasen/ranged,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -1686,7 +1737,8 @@
/obj/effect/turf_decal/tile/red{
dir = 8
},
-/turf/open/floor/plasteel,
+/mob/living/simple_animal/hostile/nanotrasen/ranged/smg,
+/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/security)
"dJ" = (
/obj/structure/rack,
@@ -1777,11 +1829,7 @@
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/genetics)
-"dQ" = (
-/obj/structure/window/reinforced{
- dir = 8
- },
-/mob/living/carbon/human,
+"dP" = (
/obj/effect/turf_decal/tile/purple{
dir = 1
},
@@ -1792,8 +1840,23 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
+/mob/living/simple_animal/hostile/nanotrasen/ranged,
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior/cryo)
+"dQ" = (
+/obj/effect/turf_decal/tile/purple{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/purple,
+/obj/effect/turf_decal/tile/purple{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/purple{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/nanotrasen,
/turf/open/floor/plasteel,
-/area/awaymission/research/interior/genetics)
+/area/awaymission/research/interior/cryo)
"dR" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -2144,15 +2207,15 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/cryo)
"eB" = (
-/mob/living/simple_animal/hostile/nanotrasen/ranged,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/red{
dir = 1
},
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/red{
dir = 4
},
+/mob/living/simple_animal/hostile/nanotrasen/ranged/smg,
/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/cryo)
+/area/awaymission/research/interior/security)
"eC" = (
/obj/item/ammo_casing/c9mm,
/obj/effect/turf_decal/tile/purple{
@@ -2214,16 +2277,22 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior)
"eL" = (
-/mob/living/simple_animal/hostile/syndicate,
-/obj/effect/turf_decal/tile/yellow{
+/obj/structure/window/reinforced{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/purple{
dir = 1
},
-/obj/effect/turf_decal/tile/yellow,
-/obj/effect/turf_decal/tile/yellow{
+/obj/effect/turf_decal/tile/purple,
+/obj/effect/turf_decal/tile/purple{
dir = 4
},
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior)
+/obj/effect/turf_decal/tile/purple{
+ dir = 8
+ },
+/mob/living/carbon/monkey,
+/turf/open/floor/plasteel,
+/area/awaymission/research/interior/genetics)
"eM" = (
/obj/item/ammo_casing/c45,
/obj/item/ammo_casing/c45,
@@ -2846,19 +2915,19 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/security)
"fY" = (
-/mob/living/simple_animal/hostile/nanotrasen/ranged/smg,
-/obj/effect/turf_decal/tile/red{
+/obj/effect/turf_decal/tile/green{
dir = 1
},
-/obj/effect/turf_decal/tile/red,
-/obj/effect/turf_decal/tile/red{
+/obj/effect/turf_decal/tile/green,
+/obj/effect/turf_decal/tile/green{
dir = 4
},
-/obj/effect/turf_decal/tile/red{
+/obj/effect/turf_decal/tile/green{
dir = 8
},
+/mob/living/simple_animal/hostile/syndicate/ranged/smg,
/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/security)
+/area/awaymission/research/interior)
"fZ" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -2966,6 +3035,23 @@
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/secure)
+"gi" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/mob/living/simple_animal/bot/secbot/beepsky{
+ desc = "A beefy variant of the standard securitron model.";
+ emagged = 1;
+ faction = list("nanotrasenprivate");
+ health = 50;
+ maxHealth = 50;
+ name = "Officer Genesky"
+ },
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior/security)
"gj" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -3115,19 +3201,13 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/cryo)
"gv" = (
-/mob/living/simple_animal/hostile/nanotrasen/ranged,
-/obj/effect/turf_decal/tile/purple{
- dir = 1
- },
-/obj/effect/turf_decal/tile/purple,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/green,
+/obj/effect/turf_decal/tile/green{
dir = 4
},
-/obj/effect/turf_decal/tile/purple{
- dir = 8
- },
+/mob/living/simple_animal/hostile/syndicate,
/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/cryo)
+/area/awaymission/research/interior)
"gw" = (
/obj/effect/mob_spawn/human/doctor{
brute_damage = 145;
@@ -3508,6 +3588,35 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior)
+"gW" = (
+/obj/structure/sign/directions/security{
+ dir = 1;
+ pixel_x = 32;
+ pixel_y = 40
+ },
+/obj/structure/sign/directions/engineering{
+ dir = 1;
+ pixel_x = 32;
+ pixel_y = 33
+ },
+/obj/structure/sign/directions/science{
+ dir = 1;
+ pixel_x = 32;
+ pixel_y = 26
+ },
+/obj/effect/turf_decal/tile/green{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/green,
+/obj/effect/turf_decal/tile/green{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/green{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/syndicate/ranged/smg,
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior)
"gX" = (
/obj/effect/decal/cleanable/blood/drip,
/obj/effect/turf_decal/tile/purple{
@@ -3660,19 +3769,19 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/security)
"hj" = (
-/mob/living/simple_animal/hostile/nanotrasen,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/blue{
dir = 1
},
-/obj/effect/turf_decal/tile/purple,
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/blue,
+/obj/effect/turf_decal/tile/blue{
dir = 4
},
-/obj/effect/turf_decal/tile/purple{
+/obj/effect/turf_decal/tile/blue{
dir = 8
},
-/turf/open/floor/plasteel,
-/area/awaymission/research/interior/cryo)
+/mob/living/simple_animal/hostile/syndicate/ranged/smg,
+/turf/open/floor/plasteel/white,
+/area/awaymission/research/interior/medbay)
"hk" = (
/obj/effect/decal/cleanable/blood,
/obj/effect/turf_decal/tile/purple{
@@ -3736,15 +3845,19 @@
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/security)
"hq" = (
-/mob/living/simple_animal/hostile/nanotrasen/ranged/smg,
-/obj/effect/turf_decal/tile/red{
+/obj/effect/turf_decal/tile/blue{
dir = 1
},
-/obj/effect/turf_decal/tile/red{
+/obj/effect/turf_decal/tile/blue,
+/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/syndicate,
/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/security)
+/area/awaymission/research/interior/medbay)
"hr" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -3799,6 +3912,15 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/cryo)
+"hw" = (
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 8
+ },
+/turf/open/floor/plasteel/yellowsiding{
+ dir = 4
+ },
+/area/awaymission/research/interior/dorm)
"hx" = (
/obj/structure/cable{
icon_state = "2-4"
@@ -4066,23 +4188,6 @@
},
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/genetics)
-"hW" = (
-/obj/structure/window/reinforced{
- dir = 8
- },
-/mob/living/carbon/monkey,
-/obj/effect/turf_decal/tile/purple{
- dir = 1
- },
-/obj/effect/turf_decal/tile/purple,
-/obj/effect/turf_decal/tile/purple{
- dir = 4
- },
-/obj/effect/turf_decal/tile/purple{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/research/interior/genetics)
"hX" = (
/obj/structure/rack,
/obj/effect/spawner/lootdrop/maintenance,
@@ -4139,20 +4244,6 @@
},
/turf/open/floor/plating,
/area/awaymission/research/interior/maint)
-"if" = (
-/mob/living/simple_animal/hostile/syndicate/ranged/smg,
-/obj/effect/turf_decal/tile/green{
- dir = 1
- },
-/obj/effect/turf_decal/tile/green,
-/obj/effect/turf_decal/tile/green{
- dir = 4
- },
-/obj/effect/turf_decal/tile/green{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior)
"ig" = (
/obj/structure/cable{
icon_state = "2-4"
@@ -4186,23 +4277,6 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/security)
-"ij" = (
-/mob/living/simple_animal/bot/secbot/beepsky{
- desc = "A beefy variant of the standard securitron model.";
- emagged = 1;
- faction = list("nanotrasenprivate");
- health = 50;
- maxHealth = 50;
- name = "Officer Genesky"
- },
-/obj/effect/turf_decal/tile/red{
- dir = 1
- },
-/obj/effect/turf_decal/tile/red{
- dir = 4
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/security)
"ik" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -4546,14 +4620,6 @@
},
/turf/open/floor/plasteel/freezer,
/area/awaymission/research/interior/bathroom)
-"iQ" = (
-/mob/living/simple_animal/hostile/syndicate,
-/obj/effect/turf_decal/tile/green,
-/obj/effect/turf_decal/tile/green{
- dir = 4
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior)
"iR" = (
/turf/open/floor/plasteel,
/area/awaymission/research/interior/maint)
@@ -4723,35 +4789,6 @@
},
/turf/open/floor/plasteel,
/area/awaymission/research/interior)
-"jr" = (
-/obj/structure/sign/directions/security{
- dir = 1;
- pixel_x = 32;
- pixel_y = 40
- },
-/obj/structure/sign/directions/engineering{
- dir = 1;
- pixel_x = 32;
- pixel_y = 33
- },
-/obj/structure/sign/directions/science{
- dir = 1;
- pixel_x = 32;
- pixel_y = 26
- },
-/mob/living/simple_animal/hostile/syndicate/ranged/smg,
-/obj/effect/turf_decal/tile/green{
- dir = 1
- },
-/obj/effect/turf_decal/tile/green,
-/obj/effect/turf_decal/tile/green{
- dir = 4
- },
-/obj/effect/turf_decal/tile/green{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior)
"js" = (
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
@@ -4976,20 +5013,6 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/medbay)
-"jP" = (
-/mob/living/simple_animal/hostile/syndicate/ranged/smg,
-/obj/effect/turf_decal/tile/blue{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/medbay)
"jQ" = (
/obj/effect/decal/cleanable/blood/drip,
/obj/effect/turf_decal/tile/blue{
@@ -5591,9 +5614,6 @@
dir = 8
},
/area/awaymission/research/interior/dorm)
-"ln" = (
-/turf/open/floor/plasteel,
-/area/space/nearstation)
"lo" = (
/obj/structure/table/wood,
/obj/structure/bedsheetbin,
@@ -5613,20 +5633,6 @@
},
/turf/open/floor/plasteel/white,
/area/awaymission/research/interior/medbay)
-"lr" = (
-/mob/living/simple_animal/hostile/syndicate,
-/obj/effect/turf_decal/tile/blue{
- dir = 1
- },
-/obj/effect/turf_decal/tile/blue,
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 8
- },
-/turf/open/floor/plasteel/white,
-/area/awaymission/research/interior/medbay)
"ls" = (
/obj/structure/table,
/obj/item/storage/firstaid/regular,
@@ -5867,12 +5873,6 @@
/obj/effect/landmark/awaystart,
/turf/open/floor/wood,
/area/awaymission/research/interior/dorm)
-"lU" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/plasteel/yellowsiding{
- dir = 4
- },
-/area/awaymission/research/interior/dorm)
"lV" = (
/obj/machinery/light/small{
dir = 1
@@ -38316,7 +38316,7 @@ ea
ev
fd
fE
-gv
+dP
ev
fd
fE
@@ -38565,10 +38565,10 @@ aH
cm
cw
cx
-cT
+aS
dh
dq
-cT
+aS
ea
ev
fc
@@ -38823,7 +38823,7 @@ cd
cx
cx
cU
-di
+bc
dr
dr
ea
@@ -39603,7 +39603,7 @@ ey
fG
gw
gR
-hj
+dQ
hu
hK
cK
@@ -40367,7 +40367,7 @@ cx
cW
dh
du
-dQ
+cX
ea
eA
fd
@@ -40377,7 +40377,7 @@ ev
fd
fE
ea
-hW
+eL
ib
ib
iz
@@ -40621,12 +40621,12 @@ aH
ce
cc
cx
-cX
+aU
dh
dv
dh
ea
-eB
+di
fc
fH
gx
@@ -40637,7 +40637,7 @@ ea
dh
dv
dh
-cT
+aS
cx
cm
cw
@@ -40651,7 +40651,7 @@ kr
jn
jF
jF
-ln
+jF
kc
lL
jk
@@ -41143,7 +41143,7 @@ ea
ev
fh
fI
-gv
+dP
ev
fc
fE
@@ -43224,8 +43224,8 @@ lc
lp
lp
lN
-lU
-lU
+hw
+hw
lY
aP
cd
@@ -44224,7 +44224,7 @@ dl
dz
cZ
ek
-eL
+dn
fl
eJ
eZ
@@ -44238,7 +44238,7 @@ ir
hZ
hZ
hZ
-iQ
+gv
hZ
hZ
hA
@@ -44490,7 +44490,7 @@ hl
hl
hl
hl
-if
+fY
is
hl
hl
@@ -44734,7 +44734,7 @@ cs
cC
cP
TD
-dn
+co
dB
da
em
@@ -44756,7 +44756,7 @@ ia
ia
ia
ia
-jr
+gW
jI
hl
kv
@@ -47584,7 +47584,7 @@ aO
iW
iW
ju
-jP
+hj
kh
iW
iW
@@ -48361,7 +48361,7 @@ kg
kM
jh
jw
-lr
+hq
kg
iW
cd
@@ -48855,7 +48855,7 @@ fq
fW
gK
fW
-hq
+eB
do
dH
dH
@@ -49366,7 +49366,7 @@ dT
eo
eR
fr
-fY
+dI
gK
fW
ho
@@ -49646,7 +49646,7 @@ kg
kL
kZ
lg
-lr
+hq
lD
iW
lW
@@ -50389,7 +50389,7 @@ ad
aH
aO
do
-dI
+cT
dH
dH
eS
@@ -50401,7 +50401,7 @@ fW
fW
fW
fW
-ij
+gi
do
hD
aH
@@ -50672,7 +50672,7 @@ jw
km
kB
kO
-jP
+hj
lj
lw
lI
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 125da46b81..cf1b2c6835 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -372,7 +372,10 @@
/turf/open/space,
/area/space/nearstation)
"aaU" = (
-/obj/machinery/computer/arcade,
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/security/prison)
"aaV" = (
@@ -6019,6 +6022,18 @@
},
/turf/open/floor/plasteel,
/area/security/processing)
+"amd" = (
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 4
+ },
+/turf/open/floor/plasteel/white/corner{
+ dir = 1
+ },
+/area/hallway/secondary/exit)
"ame" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -6225,6 +6240,17 @@
},
/turf/open/floor/plating,
/area/maintenance/solars/port/fore)
+"amB" = (
+/obj/effect/turf_decal/tile/bar,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/crew_quarters/bar)
"amC" = (
/turf/open/floor/plating,
/area/maintenance/port/fore)
@@ -19937,15 +19963,6 @@
dir = 1
},
/area/chapel/main)
-"aUL" = (
-/obj/machinery/computer/arcade,
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/turf/open/floor/plasteel/white/corner{
- dir = 1
- },
-/area/hallway/secondary/exit)
"aUM" = (
/obj/machinery/camera{
c_tag = "Arrivals Bay 2";
@@ -22268,14 +22285,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/bar)
-"baa" = (
-/obj/machinery/computer/arcade,
-/obj/effect/turf_decal/tile/bar,
-/obj/effect/turf_decal/tile/bar{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/crew_quarters/bar)
"bab" = (
/obj/machinery/light,
/obj/machinery/firealarm{
@@ -91961,7 +91970,7 @@ aUf
aQc
aXi
aQc
-baa
+amB
aJC
bcq
bcq
@@ -106349,7 +106358,7 @@ aCR
aCR
aCR
aTl
-aUL
+amd
aVW
aXD
aZj
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 79b7561ebb..e500c85640 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -173,6 +173,88 @@
/obj/effect/landmark/xeno_spawn,
/turf/open/space,
/area/solar/starboard/fore)
+"aav" = (
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 4
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
+"aaw" = (
+/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
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/starboard/fore)
+"aax" = (
+/obj/effect/decal/cleanable/dirt,
+/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
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/starboard/fore)
+"aay" = (
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
+"aaz" = (
+/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
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/starboard/fore)
+"aaA" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/maintenance/starboard/fore)
+"aaB" = (
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/security/prison)
"aaE" = (
/obj/structure/lattice/catwalk,
/turf/open/space,
@@ -4563,11 +4645,6 @@
},
/turf/open/floor/plasteel,
/area/maintenance/starboard/fore)
-"anz" = (
-/obj/machinery/computer/arcade,
-/obj/effect/decal/cleanable/cobweb,
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"anA" = (
/obj/structure/cable/white{
icon_state = "0-2"
@@ -7122,10 +7199,6 @@
},
/turf/open/floor/plating,
/area/maintenance/starboard/fore)
-"arX" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"arY" = (
/obj/structure/table/wood,
/obj/item/toy/talking/codex_gigas,
@@ -7156,11 +7229,6 @@
},
/turf/open/floor/plasteel/dark,
/area/maintenance/starboard/fore)
-"asa" = (
-/obj/machinery/computer/arcade,
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plating,
-/area/maintenance/starboard/fore)
"asb" = (
/obj/machinery/airalarm{
dir = 1;
@@ -21997,10 +22065,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/security/prison)
-"aRi" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/plating,
-/area/security/prison)
"aRj" = (
/obj/structure/cable/white{
icon_state = "0-2"
@@ -170617,7 +170681,7 @@ aox
apu
aqy
arb
-aoy
+aax
aig
auA
avU
@@ -170874,7 +170938,7 @@ aoy
apv
aqz
apu
-arX
+aay
aig
auB
avU
@@ -171383,8 +171447,8 @@ aiC
akU
alI
amE
-anz
-aox
+aav
+aaw
apw
aqA
apy
@@ -171902,7 +171966,7 @@ aiC
apy
apy
apu
-aox
+aaz
atw
auD
avW
@@ -172159,7 +172223,7 @@ aoB
apz
apw
apv
-asa
+aaA
atw
auE
avW
@@ -182715,7 +182779,7 @@ aFn
aMn
aNI
aPr
-aRi
+aaB
aKV
aUC
aWk
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index a87c17836c..a7ab212bd6 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -1279,6 +1279,22 @@
},
/turf/open/floor/plasteel,
/area/science/mixing)
+"abQ" = (
+/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
+ },
+/obj/machinery/computer/arcade{
+ dir = 4
+ },
+/turf/open/floor/plasteel/dark,
+/area/maintenance/port)
"abR" = (
/obj/structure/lattice,
/turf/open/space,
@@ -37164,20 +37180,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/starboard)
-"dEa" = (
-/obj/machinery/computer/arcade,
-/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/maintenance/port)
"dFV" = (
/obj/machinery/atmospherics/pipe/simple/green/visible{
dir = 4
@@ -76194,7 +76196,7 @@ aZp
bak
bbc
bbQ
-dEa
+abQ
bdD
beu
sKE
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 698eb6cd5a..9ae92b26d4 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -35,6 +35,30 @@
icon_state = "platingdmg3"
},
/area/maintenance/department/science)
+"aae" = (
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 8
+ },
+/turf/open/floor/plasteel/dark,
+/area/security/prison)
+"aaf" = (
+/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
+ },
+/obj/machinery/computer/arcade{
+ icon_state = "arcade";
+ dir = 1
+ },
+/turf/open/floor/plasteel/dark,
+/area/crew_quarters/heads/captain)
"abf" = (
/obj/structure/bed,
/turf/open/floor/plating,
@@ -1621,10 +1645,6 @@
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
-"afI" = (
-/obj/machinery/computer/arcade,
-/turf/open/floor/plasteel/dark,
-/area/security/prison)
"afJ" = (
/obj/effect/landmark/carpspawn,
/turf/open/space/basic,
@@ -13685,20 +13705,6 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/heads/captain)
-"aGm" = (
-/obj/machinery/computer/arcade,
-/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/crew_quarters/heads/captain)
"aGn" = (
/obj/item/twohanded/required/kirbyplants/photosynthetic{
layer = 3.1
@@ -83601,7 +83607,7 @@ aeu
aeI
lGp
aeU
-afI
+aae
aeU
dUk
agy
@@ -90832,7 +90838,7 @@ aCC
aDG
aBm
aFz
-aGm
+aaf
awR
aHQ
aIO
diff --git a/_maps/map_files/generic/City_of_Cogs.dmm b/_maps/map_files/generic/City_of_Cogs.dmm
index 584564ba2a..e1e7659ce3 100644
--- a/_maps/map_files/generic/City_of_Cogs.dmm
+++ b/_maps/map_files/generic/City_of_Cogs.dmm
@@ -26979,9 +26979,9 @@ ab
ab
ab
ab
-ab
-ab
-ab
+ae
+ae
+ae
ab
ab
ab
@@ -27235,11 +27235,11 @@ ab
ab
ab
ab
-ab
-ab
-ab
-ab
-ab
+ae
+ag
+ag
+ag
+ae
ab
ab
ab
@@ -27492,11 +27492,11 @@ ab
ab
ab
ab
-ab
-ab
-ab
-ab
-ab
+ae
+ag
+ag
+ag
+ae
aF
aF
aF
@@ -27747,8 +27747,8 @@ ab
ab
ab
ab
-ae
-ae
+ab
+ab
ah
ah
ai
@@ -28003,9 +28003,9 @@ ab
ab
ab
ab
-ae
-ag
-ag
+ab
+ab
+ab
ah
ar
aj
@@ -28260,9 +28260,9 @@ ab
ab
ab
ab
-ae
-ag
-ag
+ab
+ab
+ab
ah
as
aj
@@ -28517,9 +28517,9 @@ ab
ab
ab
ab
-ae
-ag
-ag
+ab
+ab
+ab
ah
VP
aj
@@ -28775,8 +28775,8 @@ ab
ab
ab
ab
-ae
-ae
+ab
+ab
ah
ah
ay
@@ -29033,7 +29033,7 @@ ab
ab
ab
ab
-ae
+ab
an
au
aj
@@ -33657,7 +33657,7 @@ ab
ab
ab
ab
-ae
+ab
ah
al
aj
@@ -33914,7 +33914,7 @@ ab
ab
ab
ab
-ae
+ab
ai
bE
aj
@@ -34171,7 +34171,7 @@ ab
ab
ab
ab
-ae
+ab
ah
al
aj
@@ -34688,11 +34688,11 @@ ab
ab
ab
ab
-ab
-ab
-ab
-ab
-ab
+ae
+ae
+ag
+ae
+ae
aF
aF
aF
diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm
index 23de211226..f49e70aeb9 100644
--- a/_maps/shuttles/emergency_cere.dmm
+++ b/_maps/shuttles/emergency_cere.dmm
@@ -591,6 +591,22 @@
/obj/machinery/recharger,
/turf/open/floor/mineral/plastitanium/red/brig,
/area/shuttle/escape)
+"bh" = (
+/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
+ },
+/obj/machinery/computer/arcade{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/shuttle/escape)
"bj" = (
/turf/open/floor/mech_bay_recharge_floor,
/area/shuttle/escape)
@@ -1181,20 +1197,6 @@
},
/turf/open/floor/plasteel/white,
/area/shuttle/escape)
-"cz" = (
-/obj/machinery/computer/arcade,
-/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,
-/area/shuttle/escape)
"cA" = (
/obj/machinery/light{
dir = 8
@@ -1815,8 +1817,8 @@ ab
ad
cn
cn
-cz
-cz
+bh
+bh
cn
cn
ab
diff --git a/_maps/shuttles/emergency_gorilla.dmm b/_maps/shuttles/emergency_gorilla.dmm
index abfcea8257..0c75cd8b7e 100644
--- a/_maps/shuttles/emergency_gorilla.dmm
+++ b/_maps/shuttles/emergency_gorilla.dmm
@@ -284,9 +284,6 @@
/turf/open/floor/plating,
/area/shuttle/escape)
"be" = (
-/obj/machinery/light/small{
- dir = 1
- },
/obj/structure/chair/sofa/right,
/turf/open/floor/plating,
/area/shuttle/escape)
@@ -363,6 +360,20 @@
/obj/structure/shuttle/engine/propulsion,
/turf/open/floor/plating/airless,
/area/shuttle/escape)
+"fV" = (
+/turf/closed/wall/r_wall,
+/area/shuttle/escape)
+"IR" = (
+/obj/effect/spawner/structure/window/plasma/reinforced,
+/turf/open/floor/plating,
+/area/shuttle/escape)
+"Pi" = (
+/obj/structure/chair/sofa,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/open/floor/plating,
+/area/shuttle/escape)
(1,1,1) = {"
aa
@@ -452,11 +463,11 @@ aP
av
av
ax
-ab
-ad
-ab
+av
+fV
+fV
bk
-ab
+fV
bs
bu
"}
@@ -476,8 +487,8 @@ aT
aT
aT
aT
-ac
-ac
+aT
+IR
be
aN
bl
@@ -501,7 +512,7 @@ ab
ad
ab
ad
-ad
+fV
bf
bl
bq
@@ -522,11 +533,11 @@ aM
aP
aU
aC
+aC
aX
aD
-ad
-ad
-bg
+fV
+Pi
bm
bn
bs
@@ -546,10 +557,10 @@ ad
ab
ab
aC
+aC
aY
aX
-ad
-ad
+fV
bh
aP
bq
@@ -570,10 +581,10 @@ aC
aD
aC
ax
+aC
aZ
ax
-ac
-ac
+IR
bg
bl
br
@@ -594,14 +605,14 @@ aC
aQ
aV
aC
+aC
aX
aD
-ad
-ab
+fV
bi
bn
bl
-ab
+fV
ab
"}
(11,1,1) = {"
@@ -621,10 +632,10 @@ ab
ad
ad
ab
-ad
-ab
-ab
-ad
-ad
+fV
+fV
+fV
+fV
+fV
aa
"}
diff --git a/_maps/shuttles/emergency_raven.dmm b/_maps/shuttles/emergency_raven.dmm
index 37517668e4..2c04837c79 100644
--- a/_maps/shuttles/emergency_raven.dmm
+++ b/_maps/shuttles/emergency_raven.dmm
@@ -1329,6 +1329,14 @@
"eP" = (
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/area/shuttle/escape)
+"Mb" = (
+/obj/machinery/door/airlock/hatch{
+ name = "Shuttle EVA";
+ req_access_txt = "19"
+ },
+/obj/structure/fans/tiny,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/escape)
(1,1,1) = {"
aa
@@ -1645,7 +1653,7 @@ cs
ad
cr
cs
-aR
+Mb
cs
ar
br
diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 60fb49f780..4052dce40d 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -131,6 +131,11 @@
#define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun"
#define ORGAN_SLOT_TAIL "tail"
#define ORGAN_SLOT_PENIS "penis"
+#define ORGAN_SLOT_WOMB "womb"
+#define ORGAN_SLOT_VAGINA "vagina"
+#define ORGAN_SLOT_TESTICLES "testicles"
+#define ORGAN_SLOT_BREASTS "breasts"
+
////organ defines
#define STANDARD_ORGAN_THRESHOLD 100
diff --git a/code/__DEFINES/__513_compatibility.dm b/code/__DEFINES/__513_compatibility.dm
new file mode 100644
index 0000000000..12577fb68b
--- /dev/null
+++ b/code/__DEFINES/__513_compatibility.dm
@@ -0,0 +1,32 @@
+
+#if DM_VERSION < 513
+
+#define ismovableatom(A) (istype(A, /atom/movable))
+
+#define islist(L) (istype(L, /list))
+
+#define CLAMP01(x) (CLAMP(x, 0, 1))
+
+#define CLAMP(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
+
+#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
+
+#define TAN(x) (sin(x) / cos(x))
+
+#define arctan(x) (arcsin(x/sqrt(1+x*x)))
+
+//////////////////////////////////////////////////
+
+#else
+
+#define ismovableatom(A) ismovable(A)
+
+#define CLAMP01(x) clamp(x, 0, 1)
+
+#define CLAMP(CLVALUE, CLMIN, CLMAX) clamp(CLVALUE, CLMIN, CLMAX)
+
+#define TAN(x) tan(x)
+
+#define ATAN2(x, y) arctan(x, y)
+
+#endif
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 3301def4a1..e3cafd4613 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -15,9 +15,26 @@
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
//Filters
-#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, border=0, color="#04080F")
+#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, color="#04080F")
//organ defines
+#define VAGINA_LAYER_INDEX 1
+#define TESTICLES_LAYER_INDEX 2
+#define GENITAL_LAYER_INDEX 3
+#define PENIS_LAYER_INDEX 4
+
+#define GENITAL_LAYER_INDEX_LENGTH 4 //keep it updated with each new index added, thanks.
+
+//genital flags
+#define GENITAL_BLACKLISTED (1<<0) //for genitals that shouldn't be added to GLOB.genitals_list.
+#define GENITAL_INTERNAL (1<<1)
+#define GENITAL_HIDDEN (1<<2)
+#define GENITAL_THROUGH_CLOTHES (1<<3)
+#define GENITAL_FUID_PRODUCTION (1<<4)
+#define CAN_MASTURBATE_WITH (1<<5)
+#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ
+#define CAN_CLIMAX_WITH (1<<7)
+
#define COCK_SIZE_MIN 1
#define COCK_SIZE_MAX 20
@@ -50,27 +67,6 @@
#define BREASTS_VOLUME_BASE 50 //base volume for the reagents in the breasts, multiplied by the size then multiplier. 50u for A cups, 850u for HH cups.
#define BREASTS_VOLUME_MULT 1 //global multiplier for breast volume.
-#define BREASTS_SIZE_FLAT 0
-#define BREASTS_SIZE_A 1
-#define BREASTS_SIZE_AA 1.5
-#define BREASTS_SIZE_B 2
-#define BREASTS_SIZE_BB 2.5
-#define BREASTS_SIZE_C 3
-#define BREASTS_SIZE_CC 3.5
-#define BREASTS_SIZE_D 4
-#define BREASTS_SIZE_DD 4.5
-#define BREASTS_SIZE_E 5
-#define BREASTS_SIZE_EE 5.5
-#define BREASTS_SIZE_F 6
-#define BREASTS_SIZE_FF 6.5
-#define BREASTS_SIZE_G 7
-#define BREASTS_SIZE_GG 7.5//Are these even real sizes? The world may never know because cup sizes make no fucking sense.
-#define BREASTS_SIZE_H 8
-#define BREASTS_SIZE_HH 8.5//Largest size, ever. For now.
-
-#define BREASTS_SIZE_MIN BREASTS_SIZE_A
-#define BREASTS_SIZE_DEF BREASTS_SIZE_C
-#define BREASTS_SIZE_MAX BREASTS_SIZE_HH
#define MILK_RATE 5
#define MILK_RATE_MULT 1
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index e31d2a278e..3664da4a5d 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -104,8 +104,7 @@
#define SHOVE_KNOCKDOWN_HUMAN 30
#define SHOVE_KNOCKDOWN_TABLE 30
#define SHOVE_KNOCKDOWN_COLLATERAL 10
-//Shove slowdown
-#define SHOVE_SLOWDOWN_ID "shove_slowdown"
+//for the shove slowdown, see __DEFINES/movespeed_modification.dm
#define SHOVE_SLOWDOWN_LENGTH 30
#define SHOVE_SLOWDOWN_STRENGTH 0.85 //multiplier
//Shove disarming item list
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index e33d42df64..3a680d1c90 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -126,7 +126,7 @@
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize() (can_reenter_corpse)
#define COMPONENT_BLOCK_GHOSTING 1
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
-#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources)
+#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
#define COMPONENT_BLOCK_MAGIC 1
#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): ()
#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of
@@ -157,6 +157,10 @@
// /mob/living/carbon signals
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
+// /mob/living/simple_animal/hostile signals
+#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget"
+ #define COMPONENT_HOSTILE_NO_ATTACK 1
+
// /obj signals
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
@@ -206,6 +210,9 @@
// /obj/item/pen signals
#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user)
+// /obj/item/projectile signals (sent to the firer)
+#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
+#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target)
// /mob/living/carbon/human signals
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
@@ -233,8 +240,7 @@
//Mood
#define COMSIG_ADD_MOOD_EVENT "add_mood" //Called when you send a mood event from anywhere in the code.
#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" //Called when you clear a mood event from anywhere in the code.
-#define COMSIG_INCREASE_SANITY "decrease_sanity" //Called when you want to increase sanity from anywhere in the code.
-#define COMSIG_DECREASE_SANITY "increase_sanity" //Same as above but to decrease sanity instead.
+#define COMSIG_MODIFY_SANITY "modify_sanity" //Called when you want to increase or decrease sanity from anywhere in the code.
//NTnet
#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata))
diff --git a/code/__DEFINES/fantasy_affixes.dm b/code/__DEFINES/fantasy_affixes.dm
new file mode 100644
index 0000000000..709d414d11
--- /dev/null
+++ b/code/__DEFINES/fantasy_affixes.dm
@@ -0,0 +1,5 @@
+#define AFFIX_PREFIX (1 << 0)
+#define AFFIX_SUFFIX (1 << 1)
+
+#define AFFIX_GOOD (1 << 0)
+#define AFFIX_EVIL (1 << 1)
\ No newline at end of file
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index d9b30bf0e3..9e8a4f71c2 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -58,6 +58,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define GROUND (1<<0)
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
+#define FLOATING (1<<3)
//Fire and Acid stuff, for resistance_flags
#define LAVA_PROOF (1<<0)
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 24d381d1a8..632e4adef9 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -28,7 +28,9 @@
#define ITEM_SLOT_POCKET (1<<11) // this is to allow items with a w_class of WEIGHT_CLASS_NORMAL or WEIGHT_CLASS_BULKY to fit in pockets.
#define ITEM_SLOT_DENYPOCKET (1<<12) // this is to deny items with a w_class of WEIGHT_CLASS_SMALL or WEIGHT_CLASS_TINY to fit in pockets.
#define ITEM_SLOT_NECK (1<<13)
-#define ITEM_SLOT_SUITSTORE (1<<14)
+#define ITEM_SLOT_HANDS (1<<14)
+#define ITEM_SLOT_BACKPACK (1<<15)
+#define ITEM_SLOT_SUITSTORE (1<<16)
//SLOTS
#define SLOT_BACK 1
@@ -86,6 +88,10 @@
. = ITEM_SLOT_ICLOTHING
if(SLOT_L_STORE, SLOT_R_STORE)
. = ITEM_SLOT_POCKET
+ if(SLOT_HANDS)
+ . = ITEM_SLOT_HANDS
+ if(SLOT_IN_BACKPACK)
+ . = ITEM_SLOT_BACKPACK
if(SLOT_S_STORE)
. = ITEM_SLOT_SUITSTORE
@@ -237,3 +243,6 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
//Internals checker
#define GET_INTERNAL_SLOTS(C) list(C.head, C.wear_mask)
+
+//Slots that won't trigger humans' update_genitals() on equip().
+GLOBAL_LIST_INIT(no_genitals_update_slots, list(SLOT_L_STORE, SLOT_R_STORE, SLOT_S_STORE, SLOT_IN_BACKPACK, SLOT_LEGCUFFED, SLOT_HANDCUFFED, SLOT_HANDS, SLOT_GENERC_DEXTROUS_STORAGE))
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 9f69da0154..70010eeffc 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -1,11 +1,7 @@
// simple is_type and similar inline helpers
-#define islist(L) (istype(L, /list))
-
#define in_range(source, user) (get_dist(source, user) <= 1 && (get_step(source, 0)?:z) == (get_step(user, 0)?:z))
-#define ismovableatom(A) (istype(A, /atom/movable))
-
#define isatom(A) (isloc(A))
#define isweakref(D) (istype(D, /datum/weakref))
@@ -223,6 +219,10 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
#define isbodypart(A) (istype(A, /obj/item/bodypart))
+#define isprojectile(A) (istype(A, /obj/item/projectile))
+
+#define isgun(A) (istype(A, /obj/item/gun))
+
//Assemblies
#define isassembly(O) (istype(O, /obj/item/assembly))
@@ -246,4 +246,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))
-#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs))
+#define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs))
\ No newline at end of file
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index 179f501fd1..3c0921fa01 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -92,3 +92,7 @@ require only minor tweaks.
#define PLACE_SAME_Z "same"
#define PLACE_SPACE_RUIN "space"
#define PLACE_LAVA_RUIN "lavaland"
+
+
+//Map type stuff.
+#define MAP_TYPE_STATION "station"
diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm
index 5bce51293f..ad93dd2d54 100644
--- a/code/__DEFINES/maths.dm
+++ b/code/__DEFINES/maths.dm
@@ -16,7 +16,6 @@
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(TICK_USAGE_REAL - starting_tickusage))
#define PERCENT(val) (round((val)*100, 0.1))
-#define CLAMP01(x) (CLAMP(x, 0, 1))
//time of day but automatically adjusts to the server going into the next day within the same round.
//for when you need a reliable time number that doesn't depend on byond time.
@@ -30,17 +29,12 @@
// round() acts like floor(x, 1) by default but can't handle other values
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
-#define CLAMP(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
-
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
// Real modulus that handles decimals
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
-// Tangent
-#define TAN(x) (sin(x) / cos(x))
-
// Cotangent
#define COT(x) (1 / TAN(x))
@@ -50,8 +44,6 @@
// Cosecant
#define CSC(x) (1 / sin(x))
-#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) )
-
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, (a) % (b)) : a
@@ -207,4 +199,4 @@
#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )
#define RULE_OF_THREE(a, b, x) ((a*x)/b)
-// )
+// )
\ No newline at end of file
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 94a189ff07..4b76f41c61 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -51,24 +51,25 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
//Human Overlays Indexes/////////
//LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS
-#define MUTATIONS_LAYER 31 //mutations. Tk headglows, cold resistance glow, etc
-#define GENITALS_BEHIND_LAYER 30 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer
-#define BODY_BEHIND_LAYER 29 //certain mutantrace features (tail when looking south) that must appear behind the body parts
-#define BODYPARTS_LAYER 28 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
-#define MARKING_LAYER 27 //Matrixed body markings because clashing with snouts?
-#define BODY_ADJ_LAYER 26 //certain mutantrace features (snout, body markings) that must appear above the body parts
-#define GENITALS_FRONT_LAYER 25 //Draws some genitalia above clothes and the TAUR body if need be.
-#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup)
-#define FRONT_MUTATIONS_LAYER 23 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
-#define DAMAGE_LAYER 22 //damage indicators (cuts and burns)
-#define UNIFORM_LAYER 21
-#define ID_LAYER 20
+#define MUTATIONS_LAYER 32 //mutations. Tk headglows, cold resistance glow, etc
+#define GENITALS_BEHIND_LAYER 31 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer
+#define BODY_BEHIND_LAYER 30 //certain mutantrace features (tail when looking south) that must appear behind the body parts
+#define BODYPARTS_LAYER 29 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
+#define MARKING_LAYER 28 //Matrixed body markings because clashing with snouts?
+#define BODY_ADJ_LAYER 27 //certain mutantrace features (snout, body markings) that must appear above the body parts
+#define GENITALS_FRONT_LAYER 26 //Draws some genitalia above clothes and the TAUR body if need be.
+#define BODY_LAYER 25 //underwear, undershirts, socks, eyes, lips(makeup)
+#define FRONT_MUTATIONS_LAYER 24 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
+#define DAMAGE_LAYER 23 //damage indicators (cuts and burns)
+#define UNIFORM_LAYER 22
+#define ID_LAYER 21
#define HANDS_PART_LAYER 20
#define SHOES_LAYER 19
#define GLOVES_LAYER 18
#define EARS_LAYER 17
#define BODY_TAUR_LAYER 16
#define SUIT_LAYER 15
+#define GENITALS_EXPOSED_LAYER 14
#define GLASSES_LAYER 13
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
@@ -82,7 +83,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define HANDS_LAYER 3
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
-#define TOTAL_LAYERS 30 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
+#define TOTAL_LAYERS 32 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
@@ -489,7 +490,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define PDAIMG(what) {""}
//Filters
-#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"border"=4,"color"="#04080FAA")
+#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA")
#define EYE_BLUR(size) list("type"="blur", "size"=size)
#define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0)
diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm
index 12a3c331ec..50e1a10fa1 100644
--- a/code/__DEFINES/movespeed_modification.dm
+++ b/code/__DEFINES/movespeed_modification.dm
@@ -1,12 +1,19 @@
#define MOVESPEED_DATA_INDEX_PRIORITY 1
#define MOVESPEED_DATA_INDEX_FLAGS 2
#define MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN 3
+#define MOVESPEED_DATA_INDEX_MOVETYPE 4
+#define MOVESPEED_DATA_INDEX_BL_MOVETYPE 5
+#define MOVESPEED_DATA_INDEX_CONFLICT 6
-#define MOVESPEED_DATA_INDEX_MAX 3
+#define MOVESPEED_DATA_INDEX_MAX 6
//flags
#define IGNORE_NOSLOW (1 << 0)
+//conflict types
+
+#define MOVE_CONFLICT_JETPACK "JETPACK"
+
//ids
#define MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED "MOB_WALK_RUN"
@@ -16,15 +23,29 @@
#define MOVESPEED_ID_SLIME_HEALTHMOD "SLIME_HEALTH_MODIFIER"
#define MOVESPEED_ID_SLIME_TEMPMOD "SLIME_TEMPERATURE_MODIFIER"
+#define MOVESPEED_ID_SLIME_STATUS "SLIME_STATUS"
+
+#define MOVESPEED_ID_TARANTULA_WEB "TARANTULA_WEB"
+
#define MOVESPEED_ID_LIVING_TURF_SPEEDMOD "LIVING_TURF_SPEEDMOD"
#define MOVESPEED_ID_CARBON_SOFTCRIT "CARBON_SOFTCRIT"
#define MOVESPEED_ID_CARBON_OLDSPEED "CARBON_DEPRECATED_SPEED"
+#define MOVESPEED_ID_DNA_VAULT "DNA_VAULT"
+
+#define MOVESPEED_ID_YELLOW_ORB "YELLOW_ORB"
+
+#define MOVESPEED_ID_TARFOOT "TARFOOT"
+
+#define MOVESPEED_ID_SEPIA "SEPIA"
+
#define MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD "MONKEY_REAGENT_SPEEDMOD"
#define MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD "MONKEY_TEMPERATURE_SPEEDMOD"
#define MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD "MONKEY_HEALTH_SPEEDMOD"
+#define MOVESPEED_ID_CHANGELING_MUSCLES "CHANGELING_MUSCLES"
+
#define MOVESPEED_ID_SIMPLEMOB_VARSPEED "SIMPLEMOB_VARSPEED_MODIFIER"
#define MOVESPEED_ID_ADMIN_VAREDIT "ADMIN_VAREDIT_MODIFIER"
@@ -32,7 +53,18 @@
#define MOVESPEED_ID_SANITY "MOOD_SANITY"
+#define MOVESPEED_ID_SPECIES "SPECIES_SPEED_MOD"
+
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
-#define MOVESPEED_ID_TASED_STATUS "TASED"
\ No newline at end of file
+#define MOVESPEED_ID_TASED_STATUS "TASED"
+
+#define MOVESPEED_ID_SLAUGHTER "SLAUGHTER"
+
+#define MOVESPEED_ID_CYBER_THRUSTER "CYBER_IMPLANT_THRUSTER"
+#define MOVESPEED_ID_JETPACK "JETPACK"
+
+#define MOVESPEED_ID_SHOVE "SHOVE"
+
+#define MOVESPEED_ID_MKULTRA "MKULTRA"
\ No newline at end of file
diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm
index 1917d73a1b..1885dd2621 100644
--- a/code/__DEFINES/obj_flags.dm
+++ b/code/__DEFINES/obj_flags.dm
@@ -2,43 +2,45 @@
#define EMAGGED (1<<0)
-#define IN_USE (1<<1) // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
-#define CAN_BE_HIT (1<<2) //can this be bludgeoned by items?
-#define BEING_SHOCKED (1<<3) // Whether this thing is currently (already) being shocked by a tesla
-#define DANGEROUS_POSSESSION (1<<4) //Admin possession yes/no
-#define ON_BLUEPRINTS (1<<5) //Are we visible on the station blueprints at roundstart?
-#define UNIQUE_RENAME (1<<6) // can you customize the description/name of the thing?
+#define IN_USE (1<<1) //If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING!
+#define CAN_BE_HIT (1<<2) //can this be bludgeoned by items?
+#define BEING_SHOCKED (1<<3) //Whether this thing is currently (already) being shocked by a tesla
+#define DANGEROUS_POSSESSION (1<<4) //Admin possession yes/no
+#define ON_BLUEPRINTS (1<<5) //Are we visible on the station blueprints at roundstart?
+#define UNIQUE_RENAME (1<<6) //can you customize the description/name of the thing?
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
#define FROZEN (1<<8)
-#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
+#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
// Flags for the item_flags var on /obj/item
#define BEING_REMOVED (1<<0)
-#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
-#define FORCE_STRING_OVERRIDE (1<<2) // used for tooltips
-#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
+#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
+#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
+#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
#define SLOWS_WHILE_IN_HAND (1<<4)
-#define NO_MAT_REDEMPTION (1<<5) // Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
-#define DROPDEL (1<<6) // When dropped, it calls qdel on itself
-#define NOBLUDGEON (1<<7) // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
-#define ABSTRACT (1<<8) // for all things that are technically items but used for various different stuff
-#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
+#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
+#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
+#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
+#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
+#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
-#define NO_UNIFORM_REQUIRED (1<<11) // Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
+#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
// Flags for the clothing_flags var on /obj/item/clothing
-#define LAVAPROTECT (1<<0)
+#define LAVAPROTECT (1<<0)
#define STOPSPRESSUREDAMAGE (1<<1) //SUIT and HEAD items which stop pressure damage. To stop you taking all pressure damage you must have both a suit and head item with this flag.
-#define BLOCK_GAS_SMOKE_EFFECT (1<<2) // blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
-#define ALLOWINTERNALS (1<<3) // mask allows internals
-#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
-#define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
-#define VOICEBOX_TOGGLABLE (1<<6) // The voicebox in this clothing can be toggled.
-#define VOICEBOX_DISABLED (1<<7) // The voicebox is currently turned off.
+#define BLOCK_GAS_SMOKE_EFFECT (1<<2) //blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
+#define ALLOWINTERNALS (1<<3) //mask allows internals
+#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
+#define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
+#define VOICEBOX_TOGGLABLE (1<<6) //The voicebox in this clothing can be toggled.
+#define VOICEBOX_DISABLED (1<<7) //The voicebox is currently turned off.
+#define SNUG_FIT (1<<8) //Prevents knock-off from things like hat-throwing.
+#define ANTI_TINFOIL_MANEUVER (1<<9) //Hats with negative effects when worn (i.e the tinfoil hat).
// Flags for the organ_flags var on /obj/item/organ
@@ -47,4 +49,4 @@
#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed
#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change.
#define ORGAN_VITAL (1<<4) //Currently only the brain
-#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
+#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
\ No newline at end of file
diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm
index 9579571174..8f01f453b6 100644
--- a/code/__DEFINES/reactions.dm
+++ b/code/__DEFINES/reactions.dm
@@ -27,7 +27,7 @@
#define NOBLIUM_RESEARCH_AMOUNT 1000
#define BZ_RESEARCH_SCALE 4
#define BZ_RESEARCH_MAX_AMOUNT 400
-#define MIASMA_RESEARCH_AMOUNT 160
+#define MIASMA_RESEARCH_AMOUNT 6
#define STIMULUM_RESEARCH_AMOUNT 50
//Plasma fusion properties
#define FUSION_ENERGY_THRESHOLD 3e9 //Amount of energy it takes to start a fusion reaction
diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm
index 5afd705420..f6302813f5 100644
--- a/code/__DEFINES/sound.dm
+++ b/code/__DEFINES/sound.dm
@@ -3,12 +3,12 @@
#define CHANNEL_ADMIN 1023
#define CHANNEL_VOX 1022
#define CHANNEL_JUKEBOX 1021
-#define CHANNEL_JUKEBOX_START 1020
-#define CHANNEL_JUSTICAR_ARK 1019
-#define CHANNEL_HEARTBEAT 1018 //sound channel for heartbeats
-#define CHANNEL_AMBIENCE 1017
-#define CHANNEL_BUZZ 1016
-#define CHANNEL_BICYCLE 1015
+#define CHANNEL_JUKEBOX_START 1016 //The gap between this and CHANNEL_JUKEBOX determines the amount of free jukebox channels. This currently allows 6 jukebox channels to exist.
+#define CHANNEL_JUSTICAR_ARK 1015
+#define CHANNEL_HEARTBEAT 1014 //sound channel for heartbeats
+#define CHANNEL_AMBIENCE 1013
+#define CHANNEL_BUZZ 1012
+#define CHANNEL_BICYCLE 1011
//CIT CHANNELS - TRY NOT TO REGRESS
#define CHANNEL_PRED 1010
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 332d36f2f4..ff19976cff 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -74,6 +74,9 @@
#define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute.
+#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk.
+
+#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above.
/////////////
// NEUTRAL //
/////////////
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index d4086bc4d9..2fd929a07d 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -99,7 +99,6 @@
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_WET_FLOORS 20
#define FIRE_PRIORITY_AIR 20
-#define FIRE_PRIORITY_NPC 20
#define FIRE_PRIORITY_PROCESS 25
#define FIRE_PRIORITY_THROWING 25
#define FIRE_PRIORITY_SPACEDRIFT 30
@@ -112,6 +111,7 @@
#define FIRE_PRIORITY_AIR_TURFS 40
#define FIRE_PRIORITY_DEFAULT 50
#define FIRE_PRIORITY_PARALLAX 65
+#define FIRE_PRIORITY_NPC 80
#define FIRE_PRIORITY_FLIGHTPACKS 80
#define FIRE_PRIORITY_MOBS 100
#define FIRE_PRIORITY_TGUI 110
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index e22dcfbbe0..1f37556d1d 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -70,8 +70,6 @@
#define TRAIT_MONKEYLIKE "monkeylike" //sets IsAdvancedToolUser to FALSE
#define TRAIT_PACIFISM "pacifism"
#define TRAIT_IGNORESLOWDOWN "ignoreslow"
-#define TRAIT_GOTTAGOFAST "fast"
-#define TRAIT_GOTTAGOREALLYFAST "2fast"
#define TRAIT_DEATHCOMA "deathcoma" //Causes death-like unconsciousness
#define TRAIT_FAKEDEATH "fakedeath" //Makes the owner appear as dead to most forms of medical examination
#define TRAIT_DISFIGURED "disfigured"
@@ -147,13 +145,14 @@
#define TRAIT_SKITTISH "skittish"
#define TRAIT_POOR_AIM "poor_aim"
#define TRAIT_PROSOPAGNOSIA "prosopagnosia"
-#define TRAIT_DRUNK_HEALING "drunk_healing"
-#define TRAIT_TAGGER "tagger"
-#define TRAIT_PHOTOGRAPHER "photographer"
-#define TRAIT_MUSICIAN "musician"
-#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
+#define TRAIT_DRUNK_HEALING "drunk_healing"
+#define TRAIT_TAGGER "tagger"
+#define TRAIT_PHOTOGRAPHER "photographer"
+#define TRAIT_MUSICIAN "musician"
+#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_NYMPHO "nymphomania"
#define TRAIT_MASO "masochism"
+#define TRAIT_EXHIBITIONIST "exhibitionist"
#define TRAIT_HIGH_BLOOD "high_blood"
#define TRAIT_PHARMA "hepatic_pharmacokinesis"
#define TRAIT_PARA "paraplegic"
diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm
index 86d0a34e3e..8134494306 100644
--- a/code/__HELPERS/_cit_helpers.dm
+++ b/code/__HELPERS/_cit_helpers.dm
@@ -56,6 +56,7 @@ GLOBAL_LIST_EMPTY(ipc_screens_list)
GLOBAL_LIST_EMPTY(ipc_antennas_list)
//Genitals and Arousal Lists
+GLOBAL_LIST_EMPTY(genitals_list)
GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm
GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes.
GLOBAL_LIST_EMPTY(gentlemans_organ_names)
@@ -131,53 +132,53 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/mob/living/carbon/proc/has_penis()
- if(getorganslot("penis"))//slot shared with ovipositor
- if(istype(getorganslot("penis"), /obj/item/organ/genital/penis))
- return TRUE
+ var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS)
+ if(G && istype(G, /obj/item/organ/genital/penis))
+ return TRUE
return FALSE
/mob/living/carbon/proc/has_balls()
- if(getorganslot("balls"))
- if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles))
- return TRUE
+ var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES)
+ if(G && istype(G, /obj/item/organ/genital/testicles))
+ return TRUE
return FALSE
/mob/living/carbon/proc/has_vagina()
- if(getorganslot("vagina"))
+ if(getorganslot(ORGAN_SLOT_VAGINA))
return TRUE
return FALSE
/mob/living/carbon/proc/has_breasts()
- if(getorganslot("breasts"))
+ if(getorganslot(ORGAN_SLOT_BREASTS))
return TRUE
return FALSE
/mob/living/carbon/proc/has_ovipositor()
- if(getorganslot("penis"))//shared slot
- if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor))
- return TRUE
+ var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS)
+ if(G && istype(G, /obj/item/organ/genital/ovipositor))
+ return TRUE
return FALSE
/mob/living/carbon/human/proc/has_eggsack()
- if(getorganslot("balls"))
- if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack))
- return TRUE
+ var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES)
+ if(G && istype(G, /obj/item/organ/genital/eggsack))
+ return TRUE
return FALSE
-/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart)
-
-/mob/living/carbon/proc/is_groin_exposed(var/list/L)
+/mob/living/carbon/proc/is_groin_exposed(list/L)
if(!L)
L = get_equipped_items()
- for(var/obj/item/I in L)
+ for(var/A in L)
+ var/obj/item/I = A
if(I.body_parts_covered & GROIN)
return FALSE
return TRUE
-/mob/living/carbon/proc/is_chest_exposed(var/list/L)
+/mob/living/carbon/proc/is_chest_exposed(list/L)
if(!L)
L = get_equipped_items()
- for(var/obj/item/I in L)
+ for(var/A in L)
+ var/obj/item/I = A
if(I.body_parts_covered & CHEST)
return FALSE
return TRUE
@@ -195,9 +196,9 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
message_admins("[src] gave everyone genitals.")
for(var/mob/living/carbon/human/H in GLOB.mob_list)
if(H.gender == MALE)
- H.give_penis()
- H.give_balls()
+ H.give_genital(/obj/item/organ/genital/penis)
+ H.give_genital(/obj/item/organ/genital/testicles)
else
- H.give_vagina()
- H.give_womb()
- H.give_breasts()
+ H.give_genital(/obj/item/organ/genital/vagina)
+ H.give_genital(/obj/item/organ/genital/womb)
+ H.give_genital(/obj/item/organ/genital/breasts)
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index fed283adcd..917615d095 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -379,6 +379,12 @@
i++
return i
+/proc/count_occurences_of_value(list/L, val, limit) //special thanks to salmonsnake
+ . = 0
+ for (var/i in 1 to limit)
+ if (L[i] == val)
+ .++
+
/proc/find_record(field, value, list/L)
for(var/datum/data/record/R in L)
if(R.fields[field] == value)
@@ -514,7 +520,7 @@
used_key_list[input_key] = 1
return input_key
-#if DM_VERSION > 512
+#if DM_VERSION > 513
#error Remie said that lummox was adding a way to get a lists
#error contents via list.values, if that is true remove this
#error otherwise, update the version and bug lummox
@@ -564,4 +570,4 @@
if(key in L1)
L1[key] += other_value
else
- L1[key] = other_value
+ L1[key] = other_value
\ No newline at end of file
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 6fca4eed3d..7852251230 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -72,6 +72,10 @@
var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
GLOB.balls_shapes_icons[K] = value.icon_state
+ for(var/gpath in subtypesof(/obj/item/organ/genital))
+ var/obj/item/organ/genital/G = gpath
+ if(!CHECK_BITFIELD(initial(G.genital_flags), GENITAL_BLACKLISTED))
+ GLOB.genitals_list[initial(G.name)] = gpath
//END OF CIT CHANGES
//Species
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 19d126f08f..8e7938a312 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -160,7 +160,6 @@
"xenodorsal" = "Standard",
"xenohead" = "Standard",
"xenotail" = "Xenomorph Tail",
- "exhibitionist" = FALSE,
"genitals_use_skintone" = FALSE,
"has_cock" = FALSE,
"cock_shape" = pick(GLOB.cock_shapes_list),
diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm
index 8819eb4d04..d06912b701 100644
--- a/code/__HELPERS/priority_announce.dm
+++ b/code/__HELPERS/priority_announce.dm
@@ -1,4 +1,4 @@
-/proc/priority_announce(text, title = "", sound = 'sound/ai/attention.ogg', type , sender_override)
+/proc/priority_announce(text, title = "", sound = "attention", type , sender_override)
if(!text)
return
@@ -29,19 +29,110 @@
announcement += "
[html_encode(text)]
"
announcement += "
"
- var/s = sound(sound)
+ var/s = sound(get_announcer_sound(sound))
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M) && M.can_hear())
to_chat(M, announcement)
if(M.client.prefs.toggles & SOUND_ANNOUNCEMENTS)
SEND_SOUND(M, s)
+/proc/get_announcer_sound(soundid)
+ if(isfile(soundid))
+ return soundid
+ else if(!istext(soundid))
+ CRASH("Invalid type passed to get_announcer_sound()")
+ switch(GLOB.announcertype) //These are all individually hardcoded to allow the announcer sounds to be included in the rsc, reducing lag from sending resources midgame.
+ if("classic")
+ switch(soundid)
+ if("aimalf")
+ . = 'sound/announcer/classic/aimalf.ogg'
+ if("aliens")
+ . = 'sound/announcer/classic/aliens.ogg'
+ if("animes")
+ . = 'sound/announcer/classic/animes.ogg'
+ if("attention")
+ . = 'sound/announcer/classic/attention.ogg'
+ if("commandreport")
+ . = 'sound/announcer/classic/commandreport.ogg'
+ if("granomalies")
+ . = 'sound/announcer/classic/granomalies.ogg'
+ if("intercept")
+ . = 'sound/announcer/classic/intercept.ogg'
+ if("ionstorm")
+ . = 'sound/announcer/classic/ionstorm.ogg'
+ if("meteors")
+ . = 'sound/announcer/classic/meteors.ogg'
+ if("newAI")
+ . = 'sound/announcer/classic/newAI.ogg'
+ if("outbreak5")
+ . = 'sound/announcer/classic/outbreak5.ogg'
+ if("outbreak7")
+ . = 'sound/announcer/classic/outbreak7.ogg'
+ if("poweroff")
+ . = 'sound/announcer/classic/poweroff.ogg'
+ if("poweron")
+ . = 'sound/announcer/classic/poweron.ogg'
+ if("radiation")
+ . = 'sound/announcer/classic/radiation.ogg'
+ if("shuttlecalled")
+ . = 'sound/announcer/classic/shuttlecalled.ogg'
+ if("shuttledock")
+ . = 'sound/announcer/classic/shuttledock.ogg'
+ if("shuttlerecalled")
+ . = 'sound/announcer/classic/shuttlerecalled.ogg'
+ if("spanomalies")
+ . = 'sound/announcer/classic/spanomalies.ogg'
+ if("welcome")
+ . = 'sound/announcer/classic/welcome.ogg'
+ if("medibot")
+ switch(soundid)
+ if("aimalf")
+ . = 'sound/announcer/classic/aimalf.ogg'
+ if("aliens")
+ . = 'sound/announcer/medibot/aliens.ogg'
+ if("animes")
+ . = 'sound/announcer/medibot/animes.ogg'
+ if("attention")
+ . = 'sound/announcer/medibot/attention.ogg'
+ if("commandreport")
+ . = 'sound/announcer/medibot/commandreport.ogg'
+ if("granomalies")
+ . = 'sound/announcer/medibot/granomalies.ogg'
+ if("intercept")
+ . = 'sound/announcer/medibot/intercept.ogg'
+ if("ionstorm")
+ . = 'sound/announcer/medibot/ionstorm.ogg'
+ if("meteors")
+ . = 'sound/announcer/medibot/meteors.ogg'
+ if("newAI")
+ . = 'sound/announcer/medibot/newAI.ogg'
+ if("outbreak5")
+ . = 'sound/announcer/medibot/outbreak5.ogg'
+ if("outbreak7")
+ . = 'sound/announcer/medibot/outbreak7.ogg'
+ if("poweroff")
+ . = 'sound/announcer/medibot/poweroff.ogg'
+ if("poweron")
+ . = 'sound/announcer/medibot/poweron.ogg'
+ if("radiation")
+ . = 'sound/announcer/medibot/radiation.ogg'
+ if("shuttlecalled")
+ . = 'sound/announcer/medibot/shuttlecalled.ogg'
+ if("shuttledock")
+ . = 'sound/announcer/medibot/shuttledocked.ogg'
+ if("shuttlerecalled")
+ . = 'sound/announcer/medibot/shuttlerecalled.ogg'
+ if("spanomalies")
+ . = 'sound/announcer/medibot/spanomalies.ogg'
+ if("welcome")
+ . = 'sound/announcer/medibot/welcome.ogg'
+
/proc/print_command_report(text = "", title = null, announce=TRUE)
if(!title)
title = "Classified [command_name()] Update"
if(announce)
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg')
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport")
var/datum/comm_message/M = new
M.title = title
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index ce294f3749..27b70d28c5 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -451,10 +451,6 @@ Turf and target are separate in case you want to teleport some distance from a t
var/y = min(world.maxy, max(1, A.y + dy))
return locate(x,y,A.z)
-/proc/arctan(x)
- var/y=arcsin(x/sqrt(1+x*x))
- return y
-
/*
Gets all contents of contents and returns them all in a list.
*/
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 755105dc27..e49d458ceb 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -142,6 +142,8 @@ GLOBAL_LIST_INIT(bitfields, list(
"THICKMATERIAL" = THICKMATERIAL,
"VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
"VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
+ "SNUG_FIT" = SNUG_FIT,
+ "ANTI_TINFOIL_MANEUVER" = ANTI_TINFOIL_MANEUVER,
),
"tesla_flags" = list(
"TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE,
@@ -200,4 +202,14 @@ GLOBAL_LIST_INIT(bitfields, list(
"ORGAN_VITAL" = ORGAN_VITAL,
"ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL
),
- ))
+ "genital_flags" = list(
+ "GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED,
+ "GENITAL_INTERNAL" = GENITAL_INTERNAL,
+ "GENITAL_HIDDEN" = GENITAL_HIDDEN,
+ "GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES,
+ "GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION,
+ "CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH,
+ "MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN,
+ "CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH
+ )
+ ))
\ No newline at end of file
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index 037e5067d8..af31e2b5a5 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -2,6 +2,12 @@ GLOBAL_VAR_INIT(admin_notice, "") // Admin notice that all clients see when join
GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the host computer) and 0 world.ticks.
+GLOBAL_VAR_INIT(year, time2text(world.realtime,"YYYY"))
+GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
+
+
+GLOBAL_VAR_INIT(announcertype, "standard")
+
// For FTP requests. (i.e. downloading runtime logs.)
// However it'd be ok to use for accessing attack logs and such too, which are even laggier.
GLOBAL_VAR_INIT(fileaccess_timer, 0)
@@ -24,4 +30,4 @@ GLOBAL_VAR(bible_name)
GLOBAL_VAR(bible_icon_state)
GLOBAL_VAR(bible_item_state)
GLOBAL_VAR(holy_weapon_type)
-GLOBAL_VAR(holy_armor_type)
\ No newline at end of file
+GLOBAL_VAR(holy_armor_type)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 5f0e7c9b22..58eabbdbcf 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -200,7 +200,7 @@
if (!target.loc)
continue
- if(!(SEND_SIGNAL(target.loc, COMSIG_ATOM_CANREACH, next) & COMPONENT_BLOCK_REACH))
+ if(!(SEND_SIGNAL(target.loc, COMSIG_ATOM_CANREACH, next) & COMPONENT_BLOCK_REACH) && target.loc.canReachInto(src, ultimate_target, next, view_only, tool))
next += target.loc
checking = next
@@ -215,6 +215,10 @@
/mob/living/DirectAccess(atom/target)
return ..() + GetAllContents()
+//This is called reach into but it's called on the deepest things first so uh, make sure to account for that!
+/atom/proc/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
+ return TRUE
+
/atom/proc/AllowClick()
return FALSE
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index ae36b4abb4..167fa989b2 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -49,9 +49,9 @@
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
-#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
-#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgs
-#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //borgs
+#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //borgs
+#define ui_borg_lamp "CENTER-4:15, SOUTH:5" //borgs
+#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //borgs
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
@@ -59,7 +59,7 @@
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
-#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5" //borgs
+#define ui_borg_language_menu "EAST-1:27,SOUTH+2:8" //borgs
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index 54a81efddd..11517d79b8 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -88,6 +88,26 @@
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
+/obj/screen/robot/sensors
+ name = "Sensor Augmentation"
+ icon_state = "cyborg_sensor"
+
+/obj/screen/robot/sensors/Click()
+ if(..())
+ return
+ var/mob/living/silicon/S = usr
+ S.toggle_sensors()
+
+/obj/screen/robot/language_menu
+ name = "silicon language selection"
+ icon_state = "talk_wheel"
+
+/obj/screen/robot/language_menu/Click()
+ if(..())
+ return
+ var/mob/living/silicon/S = usr
+ S.open_language_menu(usr)
+
/datum/hud/robot
ui_style = 'icons/mob/screen_cyborg.dmi'
@@ -96,7 +116,7 @@
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
- using = new/obj/screen/language_menu
+ using = new/obj/screen/robot/language_menu
using.screen_loc = ui_borg_language_menu
static_inventory += using
@@ -133,7 +153,7 @@
static_inventory += using
//Sec/Med HUDs
- using = new /obj/screen/ai/sensors()
+ using = new /obj/screen/robot/sensors()
using.screen_loc = ui_borg_sensor
static_inventory += using
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index e47797f4d6..472766a59e 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -82,7 +82,7 @@
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
add_fingerprint(user)
- user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes attacking things cause stamina loss
+ user.adjustStaminaLossBuffered(getweight()*0.8)//CIT CHANGE - makes attacking things cause stamina loss
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index e5dc485b31..0ba52c23f1 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -66,6 +66,10 @@
/datum/config_entry/flag/disable_human_mood
+/datum/config_entry/flag/disable_borg_flash_knockdown //Should borg flashes be capable of knocking humanoid entities down?
+
+/datum/config_entry/flag/weaken_secborg //Brings secborgs and k9s back in-line with the other borg modules
+
/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
/datum/config_entry/flag/disable_peaceborg
@@ -378,6 +382,22 @@
config_entry_value = 6
min_val = 1
+/datum/config_entry/number/dynamic_midround_delay_min
+ config_entry_value = 15
+ min_val = 1
+
+/datum/config_entry/number/dynamic_midround_delay_max
+ config_entry_value = 35
+ min_val = 1
+
+/datum/config_entry/number/dynamic_latejoin_delay_min
+ config_entry_value = 5
+ min_val = 1
+
+/datum/config_entry/number/dynamic_latejoin_delay_max
+ config_entry_value = 25
+ min_val = 1
+
/datum/config_entry/keyed_list/dynamic_cost
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_NUM
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index ea7e7ce812..efa6b8b59d 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(job)
flags = SS_NO_FIRE
var/list/occupations = list() //List of all jobs
- var/list/name_occupations = list() //Dict of all jobs, keys are titles
+ var/list/datum/job/name_occupations = list() //Dict of all jobs, keys are titles
var/list/type_occupations = list() //Dict of all jobs, keys are types
var/list/unassigned = list() //Players who need jobs
var/initial_players_to_assign = 0 //used for checking against population caps
@@ -14,6 +14,8 @@ SUBSYSTEM_DEF(job)
var/overflow_role = "Assistant"
+ var/list/level_order = list(JP_HIGH,JP_MEDIUM,JP_LOW)
+
/datum/controller/subsystem/job/Initialize(timeofday)
SSmapping.HACK_LoadMapConfig()
if(!occupations.len)
@@ -119,7 +121,7 @@ SUBSYSTEM_DEF(job)
if(player.mind && job.title in player.mind.restricted_roles)
JobDebug("FOC incompatible with antagonist role, Player: [player]")
continue
- if(player.client.prefs.job_preferences["[job.title]"] == level)
+ if(player.client.prefs.job_preferences[job.title] == level)
JobDebug("FOC pass, Player: [player], Level:[level]")
candidates += player
return candidates
@@ -181,7 +183,7 @@ SUBSYSTEM_DEF(job)
//it locates a head or runs out of levels to check
//This is basically to ensure that there's atleast a few heads in the round
/datum/controller/subsystem/job/proc/FillHeadPosition()
- for(var/level = 1 to 3)
+ for(var/level in level_order)
for(var/command_position in GLOB.command_positions)
var/datum/job/job = GetJob(command_position)
if(!job)
@@ -218,7 +220,7 @@ SUBSYSTEM_DEF(job)
if(!job)
return 0
for(var/i = job.total_positions, i > 0, i--)
- for(var/level = 1 to 3)
+ for(var/level in level_order)
var/list/candidates = list()
candidates = FindOccupationCandidates(job, level)
if(candidates.len)
@@ -304,8 +306,7 @@ SUBSYSTEM_DEF(job)
// Loop through all levels from high to low
var/list/shuffledoccupations = shuffle(occupations)
- var/list/levels = list(JP_HIGH,JP_MEDIUM,JP_LOW)
- for(var/level in levels)
+ for(var/level in level_order)
//Check the head jobs first each level
CheckHeadPositions(level)
@@ -334,7 +335,7 @@ SUBSYSTEM_DEF(job)
if(job.required_playtime_remaining(player.client))
JobDebug("DO player not enough xp, Player: [player], Job:[job.title]")
continue
-
+
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
JobDebug("DO non-human failed, Player: [player], Job:[job.title]")
continue
@@ -344,7 +345,7 @@ SUBSYSTEM_DEF(job)
continue
// If the player wants that job on this level, then try give it to him.
- if(player.client.prefs.job_preferences["[job.title]"] == level)
+ if(player.client.prefs.job_preferences[job.title] == level)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]")
@@ -475,7 +476,6 @@ SUBSYSTEM_DEF(job)
to_chat(M, "[job.custom_spawn_text]")
if(CONFIG_GET(number/minimal_access_threshold))
to_chat(M, "As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.")
-
if(job && H)
if(job.dresscodecompliant)// CIT CHANGE - dress code compliance
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
@@ -551,7 +551,7 @@ SUBSYSTEM_DEF(job)
if(job.required_playtime_remaining(player.client))
young++
continue
- switch(player.client.prefs.job_preferences["[job.title]"])
+ switch(player.client.prefs.job_preferences[job.title])
if(JP_HIGH)
high++
if(JP_MEDIUM)
@@ -698,4 +698,4 @@ SUBSYSTEM_DEF(job)
. |= player.mind
/datum/controller/subsystem/job/proc/JobDebug(message)
- log_job_debug(message)
+ log_job_debug(message)
\ No newline at end of file
diff --git a/code/controllers/subsystem/jukeboxes.dm b/code/controllers/subsystem/jukeboxes.dm
index d0001603a1..1532a3f41a 100644
--- a/code/controllers/subsystem/jukeboxes.dm
+++ b/code/controllers/subsystem/jukeboxes.dm
@@ -3,6 +3,7 @@ SUBSYSTEM_DEF(jukeboxes)
wait = 5
var/list/songs = list()
var/list/activejukeboxes = list()
+ var/list/freejukeboxchannels = list()
/datum/track
var/song_name = "generic"
@@ -21,23 +22,39 @@ SUBSYSTEM_DEF(jukeboxes)
/datum/controller/subsystem/jukeboxes/proc/addjukebox(obj/jukebox, datum/track/T, jukefalloff = 1)
if(!istype(T))
CRASH("[src] tried to play a song with a nonexistant track")
- var/channeltoreserve = CHANNEL_JUKEBOX_START + activejukeboxes.len - 1
- if(channeltoreserve > CHANNEL_JUKEBOX)
+ var/channeltoreserve = pick(freejukeboxchannels)
+ if(!channeltoreserve)
return FALSE
+ freejukeboxchannels -= channeltoreserve
+ var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
activejukeboxes.len++
- activejukeboxes[activejukeboxes.len] = list(T, channeltoreserve, jukebox, jukefalloff)
+ activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
+
+ //Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
+ //Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
+ var/sound/song_to_init = sound(T.song_path)
+ song_to_init.status = SOUND_MUTE
+ for(var/mob/M in GLOB.player_list)
+ if(!M.client)
+ continue
+ if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
+ continue
+
+ M.playsound_local(M, null, 100, channel = youvegotafreejukebox[2], S = song_to_init)
return activejukeboxes.len
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
if(islist(activejukeboxes[IDtoremove]))
+ var/jukechannel = activejukeboxes[IDtoremove][2]
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
- M.stop_sound_channel(activejukeboxes[IDtoremove][2])
+ M.stop_sound_channel(jukechannel)
+ freejukeboxchannels |= jukechannel
activejukeboxes.Cut(IDtoremove, IDtoremove+1)
return TRUE
else
- to_chat(world, "If you see this, screenshot it and send it to a dev. Tried to remove jukebox with invalid ID")
+ CRASH("Tried to remove jukebox with invalid ID")
/datum/controller/subsystem/jukeboxes/proc/findjukeboxindex(obj/jukebox)
if(activejukeboxes.len)
@@ -57,6 +74,8 @@ SUBSYSTEM_DEF(jukeboxes)
T.song_beat = text2num(L[3])
T.song_associated_id = L[4]
songs |= T
+ for(var/i in CHANNEL_JUKEBOX_START to CHANNEL_JUKEBOX)
+ freejukeboxchannels |= i
return ..()
/datum/controller/subsystem/jukeboxes/fire()
@@ -64,14 +83,15 @@ SUBSYSTEM_DEF(jukeboxes)
return
for(var/list/jukeinfo in activejukeboxes)
if(!jukeinfo.len)
- to_chat(world, "If you see this, screenshot it and send it to a dev. Active jukebox without any associated metadata")
+ EXCEPTION("Active jukebox without any associated metadata.")
+ continue
var/datum/track/juketrack = jukeinfo[1]
if(!istype(juketrack))
- to_chat(world, "If you see this, screenshot it and send it to a dev. After jukebox track grabbing")
+ EXCEPTION("Invalid jukebox track datum.")
continue
var/obj/jukebox = jukeinfo[3]
if(!istype(jukebox))
- to_chat(world, "If you see this, screenshot it and send it to a dev. Nonexistant or invalid jukebox in active jukebox list")
+ EXCEPTION("Nonexistant or invalid object associated with jukebox.")
continue
var/sound/song_played = sound(juketrack.song_path)
var/area/currentarea = get_area(jukebox)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 345e3bb44c..dec6cf8466 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -54,6 +54,8 @@ SUBSYSTEM_DEF(mapping)
if(!config || config.defaulted)
to_chat(world, "Unable to load next or default map config, defaulting to Box Station")
config = old_config
+ GLOB.year_integer += config.year_offset
+ GLOB.announcertype = (config.announcertype == "standard" ? (prob(1) ? "medibot" : "classic") : config.announcertype)
loadWorld()
repopulate_sorted_areas()
process_teleport_locs() //Sets up the wizard teleport locations
diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm
index d93f1f2407..830db298c9 100644
--- a/code/controllers/subsystem/npcpool.dm
+++ b/code/controllers/subsystem/npcpool.dm
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(npcpool)
name = "NPC Pool"
- flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
+ flags = SS_KEEP_TIMING | SS_NO_INIT
priority = FIRE_PRIORITY_NPC
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 455b53b1df..1b7cade71f 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -1,4 +1,5 @@
#define FILE_ANTAG_REP "data/AntagReputation.json"
+#define MAX_RECENT_MAP_RECORD 10
SUBSYSTEM_DEF(persistence)
name = "Persistence"
@@ -11,6 +12,7 @@ SUBSYSTEM_DEF(persistence)
var/list/obj/structure/chisel_message/chisel_messages = list()
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
+ var/list/saved_maps
var/list/saved_trophies = list()
var/list/spawned_objects = list()
var/list/antag_rep = list()
@@ -25,6 +27,7 @@ SUBSYSTEM_DEF(persistence)
LoadChiselMessages()
LoadTrophies()
LoadRecentModes()
+ LoadRecentMaps()
LoadPhotoPersistence()
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
@@ -163,6 +166,15 @@ SUBSYSTEM_DEF(persistence)
return
saved_modes = json["data"]
+/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
+ var/json_file = file("data/RecentMaps.json")
+ if(!fexists(json_file))
+ return
+ var/list/json = json_decode(file2text(json_file))
+ if(!json)
+ return
+ saved_maps = json["maps"]
+
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
var/json = file2text(FILE_ANTAG_REP)
if(!json)
@@ -204,6 +216,7 @@ SUBSYSTEM_DEF(persistence)
CollectSecretSatchels()
CollectTrophies()
CollectRoundtype()
+ RecordMaps()
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
@@ -359,6 +372,15 @@ SUBSYSTEM_DEF(persistence)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
+/datum/controller/subsystem/persistence/proc/RecordMaps()
+ saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
+ var/json_file = file("data/RecentMaps.json")
+ var/list/file_data = list()
+ file_data["maps"] = saved_maps
+ fdel(json_file)
+ WRITE_FILE(json_file, json_encode(file_data))
+
+
/datum/controller/subsystem/persistence/proc/CollectAntagReputation()
var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum)
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 08f657a1b9..bc8afe3c5b 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -373,7 +373,7 @@ SUBSYSTEM_DEF(shuttle)
emergency.setTimer(emergencyDockTime)
priority_announce("Hostile environment resolved. \
You have 3 minutes to board the Emergency Shuttle.",
- null, 'sound/ai/shuttledock.ogg', "Priority")
+ null, "shuttledock", "Priority")
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
/datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 77ad712b99..4b91944ec8 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -43,6 +43,7 @@ SUBSYSTEM_DEF(throwing)
var/atom/movable/thrownthing
var/atom/target
var/turf/target_turf
+ var/target_zone
var/init_dir
var/maxrange
var/speed
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index c29ddcde4c..0b8edef1ad 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -303,7 +303,7 @@ SUBSYSTEM_DEF(ticker)
SSdbcore.SetRoundStart()
to_chat(world, "Welcome to [station_name()], enjoy your stay!")
- SEND_SOUND(world, sound('sound/ai/welcome.ogg'))
+ SEND_SOUND(world, sound(get_announcer_sound("welcome")))
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 55cd9c3f4f..5644a9f2cb 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -223,9 +223,19 @@ SUBSYSTEM_DEF(vote)
if("gamemode")
choices.Add(config.votable_modes)
if("map")
- choices.Add(config.maplist)
- for(var/i in choices)//this is necessary because otherwise we'll end up with a bunch of /datum/map_config's as the default vote value instead of 0 as intended
- choices[i] = 0
+ var/players = GLOB.clients.len
+ var/list/lastmaps = SSpersistence.saved_maps?.len ? list("[SSmapping.config.map_name]") | SSpersistence.saved_maps : list("[SSmapping.config.map_name]")
+ for(var/M in config.maplist) //This is a typeless loop due to the finnicky nature of keyed lists in this kind of context
+ var/datum/map_config/targetmap = config.maplist[M]
+ if(!istype(targetmap))
+ continue
+ if(!targetmap.voteweight)
+ continue
+ if((targetmap.config_min_users && players < targetmap.config_min_users) || (targetmap.config_max_users && players > targetmap.config_max_users))
+ continue
+ if(targetmap.max_round_search_span && count_occurences_of_value(lastmaps, M, targetmap.max_round_search_span) >= targetmap.max_rounds_played)
+ continue
+ choices |= M
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
choices.Add("secret", "extended")
if("dynamic")
diff --git a/code/datums/components/anti_magic.dm b/code/datums/components/anti_magic.dm
index df03918c5d..6f289af1fc 100644
--- a/code/datums/components/anti_magic.dm
+++ b/code/datums/components/anti_magic.dm
@@ -1,26 +1,48 @@
/datum/component/anti_magic
var/magic = FALSE
var/holy = FALSE
+ var/psychic = FALSE
+ var/allowed_slots = ~ITEM_SLOT_BACKPACK
+ var/charges = INFINITY
+ var/blocks_self = TRUE
+ var/datum/callback/reaction
+ var/datum/callback/expire
-/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE)
+/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _psychic = FALSE, _allowed_slots, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
else if(ismob(parent))
- RegisterSignal(parent, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect)
+ RegisterSignal(parent, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect)
else
return COMPONENT_INCOMPATIBLE
magic = _magic
holy = _holy
+ psychic = _psychic
+ if(_allowed_slots)
+ allowed_slots = _allowed_slots
+ if(!isnull(_charges))
+ charges = _charges
+ blocks_self = _blocks_self
+ reaction = _reaction
+ expire = _expire
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
- RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect, TRUE)
+ if(!CHECK_BITFIELD(allowed_slots, slotdefine2slotbit(slot))) //Check that the slot is valid for antimagic
+ UnregisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC)
+ return
+ RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect, TRUE)
/datum/component/anti_magic/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOB_RECEIVE_MAGIC)
-/datum/component/anti_magic/proc/can_protect(datum/source, _magic, _holy, list/protection_sources)
- if((_magic && magic) || (_holy && holy))
+/datum/component/anti_magic/proc/protect(datum/source, mob/user, _magic, _holy, _psychic, chargecost = 1, self, list/protection_sources)
+ if(((_magic && magic) || (_holy && holy) || (_psychic && psychic)) && (!self || blocks_self))
protection_sources += parent
+ reaction?.Invoke(user, chargecost)
+ charges -= chargecost
+ if(charges <= 0)
+ expire?.Invoke(user)
+ qdel(src)
return COMPONENT_BLOCK_MAGIC
diff --git a/code/datums/components/bane.dm b/code/datums/components/bane.dm
new file mode 100644
index 0000000000..84f8010270
--- /dev/null
+++ b/code/datums/components/bane.dm
@@ -0,0 +1,45 @@
+/datum/component/bane
+ dupe_mode = COMPONENT_DUPE_ALLOWED
+
+ var/mobtype
+ var/speciestype
+ var/damage_multiplier
+
+/datum/component/bane/Initialize(mobtype, damage_multiplier=1)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ if(ispath(mobtype, /mob/living))
+ src.mobtype = mobtype
+ else if(ispath(mobtype, /datum/species))
+ speciestype = mobtype
+ else
+ return COMPONENT_INCOMPATIBLE
+
+ src.damage_multiplier = damage_multiplier
+
+/datum/component/bane/RegisterWithParent()
+ if(speciestype)
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck)
+ else
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck)
+
+/datum/component/bane/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
+
+/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!is_species(target, speciestype))
+ return
+ activate(source, target, user)
+
+/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!istype(target, mobtype))
+ return
+ activate(source, target, user)
+
+/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker)
+ if(attacker.a_intent != INTENT_HARM)
+ return
+
+ var/extra_damage = max(0, source.force * damage_multiplier)
+ target.apply_damage(extra_damage, source.damtype, attacker.zone_selected)
diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm
index 013334bc27..bc185994f6 100644
--- a/code/datums/components/chasm.dm
+++ b/code/datums/components/chasm.dm
@@ -65,7 +65,7 @@
return FALSE
if(!isliving(AM) && !isobj(AM))
return FALSE
- if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || AM.floating)
+ if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || (AM.movement_type & FLOATING))
return FALSE
//Flies right over the chasm
if(ismob(AM))
diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm
new file mode 100644
index 0000000000..86e016784a
--- /dev/null
+++ b/code/datums/components/fantasy/_fantasy.dm
@@ -0,0 +1,140 @@
+/datum/component/fantasy
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+
+ var/quality
+
+ var/canFail
+ var/announce
+
+ var/originalName
+ var/list/affixes
+ var/list/appliedComponents
+
+ var/static/list/affixListing
+
+/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.quality = quality || randomQuality()
+ src.canFail = canFail
+ src.announce = announce
+
+ src.affixes = affixes
+ appliedComponents = list()
+ randomAffixes()
+
+/datum/component/fantasy/Destroy()
+ unmodify()
+ affixes = null
+ return ..()
+
+/datum/component/fantasy/RegisterWithParent()
+ var/obj/item/master = parent
+ originalName = master.name
+ modify()
+
+/datum/component/fantasy/UnregisterFromParent()
+ unmodify()
+
+/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments)
+ unmodify()
+ if(newComp)
+ quality += newComp.quality
+ canFail = newComp.canFail
+ announce = newComp.announce
+ else
+ arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given
+ quality += arguments[1]
+ canFail = arguments[4] || canFail
+ announce = arguments[5] || announce
+ modify()
+
+/datum/component/fantasy/proc/randomQuality()
+ var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
+ if(prob(50))
+ quality = -quality
+ return quality
+
+/datum/component/fantasy/proc/randomAffixes(force)
+ if(!affixListing)
+ affixListing = list()
+ for(var/T in subtypesof(/datum/fantasy_affix))
+ var/datum/fantasy_affix/affix = new T
+ affixListing[affix] = affix.weight
+
+ if(length(affixes))
+ if(!force)
+ return
+ affixes = list()
+
+ var/alignment
+ if(quality >= 0)
+ alignment |= AFFIX_GOOD
+ if(quality <= 0)
+ alignment |= AFFIX_EVIL
+
+ var/usedSlots = NONE
+ for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied
+ var/datum/fantasy_affix/affix = pickweight(affixListing)
+ if(affix.placement & usedSlots)
+ continue
+ if(!(affix.alignment & alignment))
+ continue
+ if(!affix.validate(src))
+ continue
+ affixes += affix
+ usedSlots |= affix.placement
+
+/datum/component/fantasy/proc/modify()
+ var/obj/item/master = parent
+
+ master.force = max(0, master.force + quality)
+ master.throwforce = max(0, master.throwforce + quality)
+ master.armor = master.armor?.modifyAllRatings(quality)
+
+ var/newName = originalName
+ for(var/i in affixes)
+ var/datum/fantasy_affix/affix = i
+ newName = affix.apply(src, newName)
+
+ if(quality != 0)
+ newName = "[newName] [quality > 0 ? "+" : ""][quality]"
+
+ if(canFail && prob((quality - 9)*10))
+ var/turf/place = get_turf(parent)
+ place.visible_message("[parent] violently glows blue for a while, then evaporates.")
+ master.burn()
+ return
+ else if(announce)
+ announce()
+
+ master.name = newName
+
+/datum/component/fantasy/proc/unmodify()
+ var/obj/item/master = parent
+
+ for(var/i in affixes)
+ var/datum/fantasy_affix/affix = i
+ affix.remove(src)
+ for(var/i in appliedComponents)
+ qdel(i)
+
+ master.force = max(0, master.force - quality)
+ master.throwforce = max(0, master.throwforce - quality)
+ master.armor = master.armor?.modifyAllRatings(-quality)
+
+ master.name = originalName
+
+/datum/component/fantasy/proc/announce()
+ var/turf/location = get_turf(parent)
+ var/span
+ var/effect_description
+ if(quality >= 0)
+ span = ""
+ effect_description = "shimmering golden glow"
+ else
+ span = ""
+ effect_description = "mottled black glow"
+
+ location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!")
diff --git a/code/datums/components/fantasy/affix.dm b/code/datums/components/fantasy/affix.dm
new file mode 100644
index 0000000000..ad1f44ce4d
--- /dev/null
+++ b/code/datums/components/fantasy/affix.dm
@@ -0,0 +1,13 @@
+/datum/fantasy_affix
+ var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix
+ var/alignment
+ var/weight = 10
+
+// For those occasional affixes which only make sense in certain circumstances
+/datum/fantasy_affix/proc/validate(datum/component/fantasy/comp)
+ return TRUE
+
+/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName)
+ return newName
+
+/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp)
diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm
new file mode 100644
index 0000000000..702ec9329a
--- /dev/null
+++ b/code/datums/components/fantasy/prefixes.dm
@@ -0,0 +1,68 @@
+/datum/fantasy_affix/cosmetic_prefixes
+ placement = AFFIX_PREFIX
+ alignment = AFFIX_GOOD | AFFIX_EVIL
+
+ var/list/goodPrefixes
+ var/list/badPrefixes
+
+/datum/fantasy_affix/cosmetic_prefixes/New()
+ goodPrefixes = list(
+ "greater",
+ "major",
+ "blessed",
+ "superior",
+ "empowered",
+ "honed",
+ "true",
+ "glorious",
+ "robust",
+ )
+ badPrefixes = list(
+ "lesser",
+ "minor",
+ "blighted",
+ "inferior",
+ "enfeebled",
+ "rusted",
+ "unsteady",
+ "tragic",
+ "gimped",
+ "cursed",
+ )
+
+ weight = (length(goodPrefixes) + length(badPrefixes)) * 10
+
+/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName)
+ if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
+ return "[pick(goodPrefixes)] [newName]"
+ else
+ return "[pick(badPrefixes)] [newName]"
+
+/datum/fantasy_affix/tactical
+ placement = AFFIX_PREFIX
+ alignment = AFFIX_GOOD
+ weight = 1 // Very powerful, no one should have such power
+
+/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName)
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/tactical)
+ return "tactical [newName]"
+
+/datum/fantasy_affix/pyromantic
+ placement = AFFIX_PREFIX
+ alignment = AFFIX_GOOD
+
+/datum/fantasy_affix/pyromantic/apply(datum/component/fantasy/comp, newName)
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/igniter, CLAMP(comp.quality, 1, 10))
+ return "pyromantic [newName]"
+
+/datum/fantasy_affix/vampiric
+ placement = AFFIX_PREFIX
+ alignment = AFFIX_GOOD
+ weight = 5
+
+/datum/fantasy_affix/vampiric/apply(datum/component/fantasy/comp, newName)
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/lifesteal, comp.quality)
+ return "vampiric [newName]"
\ No newline at end of file
diff --git a/code/datums/components/fantasy/suffixes.dm b/code/datums/components/fantasy/suffixes.dm
new file mode 100644
index 0000000000..f32ca50595
--- /dev/null
+++ b/code/datums/components/fantasy/suffixes.dm
@@ -0,0 +1,170 @@
+/datum/fantasy_affix/cosmetic_suffixes
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_GOOD | AFFIX_EVIL
+
+ var/list/goodSuffixes
+ var/list/badSuffixes
+
+/datum/fantasy_affix/cosmetic_suffixes/New()
+ goodSuffixes = list(
+ "dexterity",
+ "constitution",
+ "intelligence",
+ "wisdom",
+ "charisma",
+ "the forest",
+ "the hills",
+ "the plains",
+ "the sea",
+ "the sun",
+ "the moon",
+ "the void",
+ "the world",
+ "many secrets",
+ "many tales",
+ "many colors",
+ "rending",
+ "sundering",
+ "the night",
+ "the day",
+ )
+ badSuffixes = list(
+ "draining",
+ "burden",
+ "discomfort",
+ "awkwardness",
+ "poor hygiene",
+ "timidity",
+ )
+
+ weight = (length(goodSuffixes) + length(badSuffixes)) * 10
+
+/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName)
+ if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
+ return "[newName] of [pick(goodSuffixes)]"
+ else
+ return "[newName] of [pick(badSuffixes)]"
+
+//////////// Good suffixes
+/datum/fantasy_affix/bane
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_GOOD
+ weight = 20
+
+/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName)
+ . = ..()
+ // This is set up to be easy to add to these lists as I expect it will need modifications
+ var/static/list/possible_mobtypes
+ if(!possible_mobtypes)
+ // The base list of allowed mob/species types
+ possible_mobtypes = typecacheof(list(
+ /mob/living/simple_animal,
+ /mob/living/carbon,
+ /datum/species,
+ ))
+ // Some particular types to disallow if they're too broad/abstract
+ possible_mobtypes -= list(
+ /mob/living/simple_animal/hostile,
+ )
+ // Some types to remove them and their subtypes
+ possible_mobtypes -= typecacheof(list(
+ /mob/living/carbon/human/species,
+ ))
+
+ var/mob/picked_mobtype = pick(possible_mobtypes)
+ // This works even with the species picks since we're only accessing the name
+
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype)
+ return "[newName] of [initial(picked_mobtype.name)] slaying"
+
+/datum/fantasy_affix/summoning
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_GOOD
+ weight = 5
+
+/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName)
+ . = ..()
+ // This is set up to be easy to add to these lists as I expect it will need modifications
+ var/static/list/possible_mobtypes
+ if(!possible_mobtypes)
+ // The base list of allowed mob/species types
+ possible_mobtypes = typecacheof(list(
+ /mob/living/simple_animal,
+ /mob/living/carbon,
+ /datum/species,
+ ))
+ // Some particular types to disallow if they're too broad/abstract
+ possible_mobtypes -= list(
+ /mob/living/simple_animal/hostile,
+ )
+ // Some types to remove them and their subtypes
+ possible_mobtypes -= typecacheof(list(
+ /mob/living/carbon/human/species,
+ /mob/living/simple_animal/hostile/megafauna,
+ ))
+
+ var/mob/picked_mobtype = pick(possible_mobtypes)
+ // This works even with the species picks since we're only accessing the name
+
+ var/obj/item/master = comp.parent
+ var/max_mobs = max(CEILING(comp.quality/2, 1), 1)
+ var/spawn_delay = 300 - 30 * comp.quality
+ comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay)
+ return "[newName] of [initial(picked_mobtype.name)] summoning"
+
+/datum/fantasy_affix/shrapnel
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_GOOD
+
+/datum/fantasy_affix/shrapnel/validate(datum/component/fantasy/comp)
+ if(isgun(comp.parent))
+ return TRUE
+ return FALSE
+
+/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName)
+ . = ..()
+ // higher means more likely
+ var/list/weighted_projectile_types = list(/obj/item/projectile/meteor = 1,
+ /obj/item/projectile/energy/nuclear_particle = 1,
+ /obj/item/projectile/beam/pulse = 1,
+ /obj/item/projectile/bullet/honker = 15,
+ /obj/item/projectile/temp = 15,
+ /obj/item/projectile/ion = 15,
+ /obj/item/projectile/magic/door = 15,
+ /obj/item/projectile/magic/locker = 15,
+// /obj/item/projectile/magic/fetch = 15,
+ /obj/item/projectile/beam/emitter = 15,
+// /obj/item/projectile/magic/flying = 15,
+ /obj/item/projectile/energy/net = 15,
+ /obj/item/projectile/bullet/incendiary/c9mm = 15,
+ /obj/item/projectile/temp/hot = 15,
+ /obj/item/projectile/beam/disabler = 15)
+
+ var/obj/item/projectile/picked_projectiletype = pickweight(weighted_projectile_types)
+
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/shrapnel, picked_projectiletype)
+ return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
+
+/datum/fantasy_affix/strength
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_GOOD
+
+/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName)
+ . = ..()
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
+ return "[newName] of strength"
+
+//////////// Bad suffixes
+
+/datum/fantasy_affix/fool
+ placement = AFFIX_SUFFIX
+ alignment = AFFIX_EVIL
+
+/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName)
+ . = ..()
+ var/obj/item/master = comp.parent
+ comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50)
+ return "[newName] of the fool"
diff --git a/code/datums/components/igniter.dm b/code/datums/components/igniter.dm
new file mode 100644
index 0000000000..b40383e828
--- /dev/null
+++ b/code/datums/components/igniter.dm
@@ -0,0 +1,37 @@
+
+/datum/component/igniter
+ var/fire_stacks
+
+/datum/component/igniter/Initialize(fire_stacks=1)
+ if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.fire_stacks = fire_stacks
+
+/datum/component/igniter/RegisterWithParent()
+ if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
+ RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
+ else if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
+ else if(ishostile(parent))
+ RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
+
+/datum/component/igniter/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
+
+/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!proximity_flag)
+ return
+ do_igniter(target)
+
+/datum/component/igniter/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
+ do_igniter(target)
+
+/datum/component/igniter/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
+ do_igniter(target)
+
+/datum/component/igniter/proc/do_igniter(atom/target)
+ if(isliving(target))
+ var/mob/living/L = target
+ L.adjust_fire_stacks(fire_stacks)
+ L.IgniteMob()
\ No newline at end of file
diff --git a/code/datums/components/knockback.dm b/code/datums/components/knockback.dm
new file mode 100644
index 0000000000..b4fcaa2dd8
--- /dev/null
+++ b/code/datums/components/knockback.dm
@@ -0,0 +1,44 @@
+/datum/component/knockback
+ var/throw_distance
+ var/throw_anchored
+
+/datum/component/knockback/Initialize(throw_distance=1)
+ if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.throw_distance = throw_distance
+ src.throw_anchored = throw_anchored
+
+/datum/component/knockback/RegisterWithParent()
+ if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
+ RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
+ else if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
+ else if(ishostile(parent))
+ RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
+
+/datum/component/knockback/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
+
+/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!proximity_flag)
+ return
+ do_knockback(target, user, get_dir(source, target))
+
+/datum/component/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
+ do_knockback(target, attacker, get_dir(attacker, target))
+
+/datum/component/knockback/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
+ do_knockback(target, null, angle2dir(Angle))
+
+/datum/component/knockback/proc/do_knockback(atom/target, mob/thrower, throw_dir)
+ if(!ismovableatom(target) || throw_dir == null)
+ return
+ var/atom/movable/throwee = target
+ if(throwee.anchored && !throw_anchored)
+ return
+ if(throw_distance < 0)
+ throw_dir = turn(throw_dir, 180)
+ throw_distance *= -1
+ var/atom/throw_target = get_edge_target_turf(throwee, throw_dir)
+ throwee.safe_throw_at(throw_target, throw_distance, 1, thrower)
diff --git a/code/datums/components/lifesteal.dm b/code/datums/components/lifesteal.dm
new file mode 100644
index 0000000000..c7a78e10a3
--- /dev/null
+++ b/code/datums/components/lifesteal.dm
@@ -0,0 +1,39 @@
+
+/datum/component/lifesteal
+ var/flat_heal // heals a constant amount every time a hit occurs
+ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
+
+/datum/component/lifesteal/Initialize(flat_heal=0)
+ if(!isitem(parent) && !ishostile(parent) && !isgun(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.flat_heal = flat_heal
+
+/datum/component/lifesteal/RegisterWithParent()
+ if(isgun(parent))
+ RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
+ else if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
+ else if(ishostile(parent))
+ RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
+
+/datum/component/lifesteal/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
+
+/datum/component/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!proximity_flag)
+ return
+ do_lifesteal(user, target)
+
+/datum/component/lifesteal/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
+ do_lifesteal(attacker, target)
+
+/datum/component/lifesteal/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
+ do_lifesteal(firer, target)
+
+/datum/component/lifesteal/proc/do_lifesteal(atom/heal_target, atom/damage_target)
+ if(isliving(heal_target) && isliving(damage_target))
+ var/mob/living/healing = heal_target
+ var/mob/living/damaging = damage_target
+ if(damaging.stat != DEAD)
+ healing.heal_ordered_damage(flat_heal, damage_heal_order)
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index 05d8ce6989..8c6013aeab 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -10,7 +10,6 @@
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
var/datum/mood_event/list/mood_events = list()
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
- var/holdmyinsanityeffect = 0 //before we edit our sanity lets take a look
var/obj/screen/mood/screen_obj
/datum/component/mood/Initialize()
@@ -21,8 +20,7 @@
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
- RegisterSignal(parent, COMSIG_INCREASE_SANITY, .proc/IncreaseSanity)
- RegisterSignal(parent, COMSIG_DECREASE_SANITY, .proc/DecreaseSanity)
+ RegisterSignal(parent, COMSIG_MODIFY_SANITY, .proc/modify_sanity)
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
var/mob/living/owner = parent
@@ -131,31 +129,23 @@
switch(mood_level)
if(1)
- DecreaseSanity(src, 0.2)
+ setSanity(sanity-0.2)
if(2)
- DecreaseSanity(src, 0.125, SANITY_CRAZY)
+ setSanity(sanity-0.125, minimum=SANITY_CRAZY)
if(3)
- DecreaseSanity(src, 0.075, SANITY_UNSTABLE)
+ setSanity(sanity-0.075, minimum=SANITY_UNSTABLE)
if(4)
- DecreaseSanity(src, 0.025, SANITY_DISTURBED)
+ setSanity(sanity-0.025, minimum=SANITY_DISTURBED)
if(5)
- IncreaseSanity(src, 0.1)
+ setSanity(sanity+0.1)
if(6)
- IncreaseSanity(src, 0.15)
+ setSanity(sanity+0.15)
if(7)
- IncreaseSanity(src, 0.20)
+ setSanity(sanity+0.20)
if(8)
- IncreaseSanity(src, 0.25, SANITY_GREAT)
+ setSanity(sanity+0.25, maximum=SANITY_GREAT)
if(9)
- IncreaseSanity(src, 0.4, SANITY_GREAT)
-
-/*
- if(insanity_effect != holdmyinsanityeffect)
- if(insanity_effect > holdmyinsanityeffect)
- owner.crit_threshold += (insanity_effect - holdmyinsanityeffect)
- else
- owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect)
-*/
+ setSanity(sanity+0.4, maximum=SANITY_GREAT)
if(HAS_TRAIT(owner, TRAIT_DEPRESSION))
if(prob(0.05))
@@ -166,8 +156,6 @@
add_event(null, "jolly", /datum/mood_event/jolly)
clear_event(null, "depression")
- holdmyinsanityeffect = insanity_effect
-
HandleNutrition(owner)
/datum/component/mood/proc/setSanity(amount, minimum=SANITY_INSANE, maximum=SANITY_NEUTRAL)//I'm sure bunging this in here will have no negative repercussions.
@@ -189,7 +177,7 @@
sanity = amount
switch(sanity)
- if(SANITY_INSANE to SANITY_CRAZY)
+ if(-INFINITY to SANITY_CRAZY)
setInsanityEffect(MAJOR_INSANITY_PEN)
master.add_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE, 100, override=TRUE, multiplicative_slowdown=1.5) //Did we change something ? movetypes is runtiming, movetypes=(~FLYING))
sanity_level = 6
@@ -222,31 +210,8 @@
//master.crit_threshold = (master.crit_threshold - insanity_effect) + newval
insanity_effect = newval
-/datum/component/mood/proc/DecreaseSanity(datum/source, amount, minimum = SANITY_INSANE)
- if(sanity < minimum) //This might make KevinZ stop fucking pinging me.
- IncreaseSanity(src, 0.5)
- else
- sanity = max(minimum, sanity - amount)
- if(sanity < SANITY_UNSTABLE)
- if(sanity < SANITY_CRAZY)
- insanity_effect = (MAJOR_INSANITY_PEN)
- else
- insanity_effect = (MINOR_INSANITY_PEN)
-
-/datum/component/mood/proc/IncreaseSanity(datum/source, amount, maximum = SANITY_NEUTRAL)
- // Disturbed stops you from getting any more sane - I'm just gonna bung this in here
- var/mob/living/owner = parent
- if(HAS_TRAIT(owner, TRAIT_UNSTABLE))
- return
- if(sanity > maximum)
- DecreaseSanity(src, 0.5) //Removes some sanity to go back to our current limit.
- else
- sanity = min(maximum, sanity + amount)
- if(sanity > SANITY_CRAZY)
- if(sanity > SANITY_UNSTABLE)
- insanity_effect = 0
- else
- insanity_effect = MINOR_INSANITY_PEN
+/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = -INFINITY, maximum = INFINITY)
+ setSanity(sanity + amount, minimum, maximum)
/datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger.
var/datum/mood_event/the_event
diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm
index ff1c48936f..7afe64994f 100644
--- a/code/datums/components/phantomthief.dm
+++ b/code/datums/components/phantomthief.dm
@@ -7,33 +7,24 @@
var/filter_x
var/filter_y
var/filter_size
- var/filter_border
var/filter_color
-/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
+/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
. = ..()
if(. == COMPONENT_INCOMPATIBLE)
return
filter_x = _x
filter_y = _y
filter_size = _size
- filter_border = _border
filter_color = _color
valid_slots = _valid_slots
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- if(!combatmodestate)
- user.filters -= thefilter
- else
- user.filters += thefilter
-
-/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
- if(istype(user))
- var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
- user.filters -= thefilter
+ if(!combatmodestate)
+ user.remove_filter("phantomthief")
+ else
+ user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
. = ..()
- stripdesiredfilter(user)
+ user.remove_filter("phantomthief")
diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm
index 0af90f694c..dcdbd5ca4b 100644
--- a/code/datums/components/riding.dm
+++ b/code/datums/components/riding.dm
@@ -18,6 +18,7 @@
var/ride_check_rider_incapacitated = FALSE
var/ride_check_rider_restrained = FALSE
var/ride_check_ridden_incapacitated = FALSE
+ var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob
/datum/component/riding/Initialize()
if(!ismovableatom(parent))
@@ -299,36 +300,34 @@
M.throw_at(target, 14, 5, AM)
M.Knockdown(60)
-/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null)
- var/atom/movable/AM = parent
- var/amount_equipped = 0
+/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override)
+ var/list/equipped
+ var/mob/living/L = riding_target_override ? riding_target_override : user
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
- var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
- if(!riding_target_override)
- inhand.rider = user
- else
- inhand.rider = riding_target_override
- inhand.parent = AM
- if(user.put_in_hands(inhand, TRUE))
- amount_equipped++
- else
+ var/obj/item/riding_offhand/inhand = new
+ inhand.rider = L
+ inhand.parent = parent
+ if(!user.put_in_hands(inhand, TRUE))
+ qdel(inhand) // it isn't going to be added to offhands anyway
break
+ LAZYADD(equipped, src)
+ var/amount_equipped = LAZYLEN(equipped)
+ if(amount_equipped)
+ LAZYADD(offhands[L], amount_equipped)
if(amount_equipped >= amount_required)
return TRUE
- else
- unequip_buckle_inhands(user)
- return FALSE
+ unequip_buckle_inhands(L)
+ return FALSE
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
- var/atom/movable/AM = parent
- for(var/obj/item/riding_offhand/O in user.contents)
- if(O.parent != AM)
- CRASH("RIDING OFFHAND ON WRONG MOB")
- continue
- if(O.selfdeleting)
- continue
- else
- qdel(O)
+ for(var/a in offhands[user])
+ LAZYREMOVE(offhands[user], a)
+ if(a) //edge cases null entries
+ var/obj/item/riding_offhand/O = a
+ if(O.parent != parent)
+ CRASH("RIDING OFFHAND ON WRONG MOB")
+ else if(!O.selfdeleting)
+ qdel(O)
return TRUE
/obj/item/riding_offhand
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index ed3ecd2ff3..a044ca301e 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -145,7 +145,7 @@
set src in oview(1)
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
- rotcomp.HandRot(usr,ROTATION_CLOCKWISE)
+ rotcomp.HandRot(null,usr,ROTATION_CLOCKWISE)
/atom/movable/proc/simple_rotate_counterclockwise()
set name = "Rotate Counter-Clockwise"
@@ -153,7 +153,7 @@
set src in oview(1)
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
- rotcomp.HandRot(usr,ROTATION_COUNTERCLOCKWISE)
+ rotcomp.HandRot(null,usr,ROTATION_COUNTERCLOCKWISE)
/atom/movable/proc/simple_rotate_flip()
set name = "Flip"
@@ -161,4 +161,4 @@
set src in oview(1)
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
if(rotcomp)
- rotcomp.HandRot(usr,ROTATION_FLIP)
+ rotcomp.HandRot(null,usr,ROTATION_FLIP)
diff --git a/code/datums/components/shrapnel.dm b/code/datums/components/shrapnel.dm
new file mode 100644
index 0000000000..a911221f26
--- /dev/null
+++ b/code/datums/components/shrapnel.dm
@@ -0,0 +1,39 @@
+
+/datum/component/shrapnel
+ var/projectile_type
+ var/radius // shoots a projectile for every turf on this radius from the hit target
+ var/override_projectile_range
+
+/datum/component/shrapnel/Initialize(projectile_type, radius=1, override_projectile_range)
+ if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.projectile_type = projectile_type
+ src.radius = radius
+ src.override_projectile_range = override_projectile_range
+
+/datum/component/shrapnel/RegisterWithParent()
+ if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
+ RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
+
+/datum/component/shrapnel/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT))
+
+/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
+ do_shrapnel(firer, target)
+
+/datum/component/shrapnel/proc/do_shrapnel(mob/firer, atom/target)
+ if(radius < 1)
+ return
+ var/turf/target_turf = get_turf(target)
+ for(var/turf/shootat_turf in RANGE_TURFS(radius, target) - RANGE_TURFS(radius-1, target))
+ var/obj/item/projectile/P = new projectile_type(target_turf)
+
+ //Shooting Code:
+ P.range = radius+1
+ if(override_projectile_range)
+ P.range = override_projectile_range
+ P.preparePixelProjectile(shootat_turf, target)
+ P.firer = firer // don't hit ourself that would be really annoying
+ P.permutated += target // don't hit the target we hit already with the flak
+ P.fire()
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index ee9cff19c7..a92ae9e629 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -57,6 +57,10 @@
var/screen_start_x = 4 //These two are where the storage starts being rendered, screen_loc wise.
var/screen_start_y = 2
//End
+
+ var/limited_random_access = FALSE //Quick if statement in accessible_items to determine if we care at all about what people can access at once.
+ var/limited_random_access_stack_position = 0 //If >0, can only access top items
+ var/limited_random_access_stack_bottom_up = FALSE //If TRUE, above becomes bottom items
/datum/component/storage/Initialize(datum/component/storage/concrete/master)
if(!isatom(parent))
@@ -96,6 +100,7 @@
RegisterSignal(parent, COMSIG_ITEM_PICKUP, .proc/signal_on_pickup)
RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all)
+ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/check_views)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click)
RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto)
@@ -145,6 +150,19 @@
var/datum/component/storage/concrete/master = master()
return master? master.real_location() : null
+//What players can access
+//this proc can probably eat a refactor at some point.
+/datum/component/storage/proc/accessible_items(random_access = TRUE)
+ var/list/contents = contents()
+ if(contents)
+ if(limited_random_access && random_access)
+ if(limited_random_access_stack_position && (length(contents) > limited_random_access_stack_position))
+ if(limited_random_access_stack_bottom_up)
+ contents.Cut(1, limited_random_access_stack_position + 1)
+ else
+ contents.Cut(1, length(contents) - limited_random_access_stack_position + 1)
+ return contents
+
/datum/component/storage/proc/canreach_react(datum/source, list/next)
var/datum/component/storage/concrete/master = master()
if(!master)
@@ -283,8 +301,7 @@
/datum/component/storage/proc/_process_numerical_display()
. = list()
- var/atom/real_location = real_location()
- for(var/obj/item/I in real_location.contents)
+ for(var/obj/item/I in accessible_items())
if(QDELETED(I))
continue
if(!.[I.type])
@@ -295,8 +312,8 @@
//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing.
/datum/component/storage/proc/orient2hud(mob/user, maxcolumns)
- var/atom/real_location = real_location()
- var/adjusted_contents = real_location.contents.len
+ var/list/accessible_contents = accessible_items()
+ var/adjusted_contents = length(accessible_contents)
//Numbered contents display
var/list/datum/numbered_display/numbered_contents
@@ -328,8 +345,7 @@
if(cy - screen_start_y >= rows)
break
else
- var/atom/real_location = real_location()
- for(var/obj/O in real_location)
+ for(var/obj/O in accessible_items())
if(QDELETED(O))
continue
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
@@ -350,9 +366,8 @@
return FALSE
var/list/cview = getviewsize(M.client.view)
var/maxallowedscreensize = cview[1]-8
- var/atom/real_location = real_location()
if(M.active_storage != src && (M.stat == CONSCIOUS))
- for(var/obj/item/I in real_location)
+ for(var/obj/item/I in accessible_items())
if(I.on_found(M))
return FALSE
if(M.active_storage)
@@ -360,7 +375,7 @@
orient2hud(M, (isliving(M) ? maxallowedscreensize : 7))
M.client.screen |= boxes
M.client.screen |= closer
- M.client.screen |= real_location.contents
+ M.client.screen |= accessible_items()
M.active_storage = src
LAZYOR(is_using, M)
return TRUE
@@ -386,6 +401,11 @@
close(M)
. = TRUE //returns TRUE if any mobs actually got a close(M) call
+/datum/component/storage/proc/check_views()
+ for(var/mob/M in can_see_contents())
+ if(!isobserver(M) && !M.CanReach(src, view_only = TRUE))
+ close(M)
+
/datum/component/storage/proc/emp_act(datum/source, severity)
if(emp_shielded)
return
diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm
new file mode 100644
index 0000000000..552959603d
--- /dev/null
+++ b/code/datums/components/summoning.dm
@@ -0,0 +1,69 @@
+
+/datum/component/summoning
+ var/list/mob_types = list()
+ var/spawn_chance // chance for the mob to spawn on hit in percent
+ var/max_mobs
+ var/spawn_delay // delay in spawning between mobs (deciseconds)
+ var/spawn_text
+ var/spawn_sound
+ var/list/faction
+
+ var/last_spawned_time = 0
+ var/list/spawned_mobs = list()
+
+/datum/component/summoning/Initialize(mob_types, spawn_chance=100, max_mobs=3, spawn_delay=100, spawn_text="appears out of nowhere", spawn_sound='sound/magic/summon_magic.ogg', faction)
+ if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.mob_types = mob_types
+ src.spawn_chance = spawn_chance
+ src.max_mobs = max_mobs
+ src.spawn_delay = spawn_delay
+ src.spawn_text = spawn_text
+ src.spawn_sound = spawn_sound
+ src.faction = faction
+
+/datum/component/summoning/RegisterWithParent()
+ if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
+ RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
+ else if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
+ else if(ishostile(parent))
+ RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
+
+/datum/component/summoning/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
+
+/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
+ if(!proximity_flag)
+ return
+ do_spawn_mob(get_turf(target), user)
+
+/datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
+ do_spawn_mob(get_turf(target), attacker)
+
+/datum/component/summoning/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
+ do_spawn_mob(get_turf(target), firer)
+
+/datum/component/summoning/proc/do_spawn_mob(atom/spawn_location, summoner)
+ if(spawned_mobs.len >= max_mobs)
+ return 0
+ if(last_spawned_time > world.time)
+ return 0
+ if(!prob(spawn_chance))
+ return 0
+ last_spawned_time = world.time + spawn_delay
+ var/chosen_mob_type = pick(mob_types)
+ var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location)
+ if(ishostile(L))
+ var/mob/living/simple_animal/hostile/H = L
+ H.friends += summoner // do not attack our summon boy
+ spawned_mobs += L
+ if(faction != null)
+ L.faction = faction
+ RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_spawned_death) // so we can remove them from the list, etc (for mobs with corpses)
+ playsound(spawn_location,spawn_sound, 50, 1)
+ spawn_location.visible_message("[L] [spawn_text].")
+
+/datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed)
+ spawned_mobs -= killed
\ No newline at end of file
diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm
new file mode 100644
index 0000000000..5917fc3009
--- /dev/null
+++ b/code/datums/components/tactical.dm
@@ -0,0 +1,42 @@
+
+/datum/component/tactical
+ var/allowed_slot
+
+/datum/component/tactical/Initialize(allowed_slot)
+ if(!isitem(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ src.allowed_slot = allowed_slot
+
+/datum/component/tactical/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify)
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify)
+
+/datum/component/tactical/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
+ unmodify()
+
+/datum/component/fantasy/Destroy()
+ unmodify()
+ return ..()
+
+/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot)
+ if(allowed_slot && slot != allowed_slot)
+ unmodify()
+ return
+
+ var/obj/item/master = parent
+ var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user)
+ I.copy_overlays(master)
+ I.override = TRUE
+ source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
+ I.layer = ABOVE_MOB_LAYER
+
+/datum/component/tactical/proc/unmodify(obj/item/source, mob/user)
+ var/obj/item/master = source || parent
+ if(!user)
+ if(!ismob(master.loc))
+ return
+ user = master.loc
+
+ user.remove_alt_appearance("sneaking_mission")
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index 1ab3456c22..8b205db756 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -79,7 +79,7 @@
if(M.getToxLoss() && prob(5))
to_chat(M, "Your skin tingles as the starlight seems to heal you.")
- M.adjustToxLoss(-(4 * heal_amt)) //most effective on toxins
+ M.adjustToxLoss(-(4 * heal_amt), forced = TRUE) //most effective on toxins
var/list/parts = M.get_damaged_bodyparts(1,1)
@@ -368,7 +368,7 @@
level = 8
passive_message = "You feel an odd attraction to plasma."
var/temp_rate = 1
- threshold_desc = "Transmission 6: Increases temperature adjustment rate.
\
+ threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
\
Stage Speed 7: Increases healing speed."
/datum/symptom/heal/plasma/Start(datum/disease/advance/A)
@@ -410,7 +410,7 @@
if(prob(5))
to_chat(M, "You feel warmer.")
- M.adjustToxLoss(-heal_amt)
+ M.adjustToxLoss(-heal_amt, forced = (temp_rate == 4))
var/list/parts = M.get_damaged_bodyparts(1,1)
if(!parts.len)
@@ -435,7 +435,7 @@
symptom_delay_max = 1
passive_message = "Your skin glows faintly for a moment."
var/cellular_damage = FALSE
- threshold_desc = "Transmission 6: Additionally heals cellular damage.
\
+ threshold_desc = "Transmission 6: Additionally heals cellular damage and toxin lovers.
\
Resistance 7: Increases healing speed."
/datum/symptom/heal/radiation/Start(datum/disease/advance/A)
@@ -468,7 +468,7 @@
if(cellular_damage)
M.adjustCloneLoss(-heal_amt * 0.5)
- M.adjustToxLoss(-(2 * heal_amt))
+ M.adjustToxLoss(-(2 * heal_amt), forced = cellular_damage)
var/list/parts = M.get_damaged_bodyparts(1,1)
diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm
index dcc16f1ba5..c859f8127d 100644
--- a/code/datums/map_config.dm
+++ b/code/datums/map_config.dm
@@ -11,6 +11,8 @@
var/config_max_users = 0
var/config_min_users = 0
var/voteweight = 1
+ var/max_round_search_span = 0 //If this is nonzero, then if the map has been played more than max_rounds_played within the search span (max determined by define in persistence.dm), this map won't be available.
+ var/max_rounds_played = 0
// Config actually from the JSON - should default to Box
var/map_name = "Box Station"
@@ -23,6 +25,10 @@
var/minetype = "lavaland"
+ var/maptype = MAP_TYPE_STATION //This should be used to adjust ingame behavior depending on the specific type of map being played. For instance, if an overmap were added, it'd be appropriate for it to only generate with a MAP_TYPE_SHIP
+
+ var/announcertype = "standard" //Determines the announcer the map uses. standard uses the default announcer, classic, but has a random chance to use other similarly-themed announcers, like medibot
+
var/allow_custom_shuttles = TRUE
var/shuttles = list(
"cargo" = "cargo_box",
@@ -30,6 +36,8 @@
"whiteship" = "whiteship_box",
"emergency" = "emergency_box")
+ var/year_offset = 540 //The offset of ingame year from the actual IRL year. You know you want to make a map that takes place in the 90's. Don't lie.
+
/proc/load_map_config(filename = "data/next_map.json", default_to_box, delete_after, error_if_missing = TRUE)
var/datum/map_config/config = new
if (default_to_box)
@@ -122,8 +130,21 @@
log_world("map_config space_empty_levels is not a number!")
return
+ temp = json["year_offset"]
+ if (isnum(temp))
+ year_offset = temp
+ else if (!isnull(temp))
+ log_world("map_config year_offset is not a number!")
+ return
+
if ("minetype" in json)
minetype = json["minetype"]
+
+ if ("maptype" in json)
+ maptype = json["maptype"]
+
+ if ("announcertype" in json)
+ announcertype = json["announcertype"]
allow_custom_shuttles = json["allow_custom_shuttles"] != FALSE
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 186c988595..fb636f6911 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -155,7 +155,7 @@
/datum/status_effect/belligerent/proc/do_movement_toggle(force_damage)
var/number_legs = owner.get_num_legs(FALSE)
- if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check() && number_legs)
+ if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check(chargecost = 0) && number_legs)
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
if(GLOB.ratvar_awakens)
owner.Knockdown(20)
@@ -248,7 +248,7 @@
if(owner.confused)
owner.confused = 0
severity = 0
- else if(!owner.anti_magic_check() && owner.stat != DEAD && severity)
+ else if(!owner.anti_magic_check(chargecost = 0) && owner.stat != DEAD && severity)
var/static/hum = get_sfx('sound/effects/screech.ogg') //same sound for every proc call
if(owner.getToxLoss() > MANIA_DAMAGE_TO_CONVERT)
if(is_eligible_servant(owner))
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index f70e3a3c68..c015dba5ec 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -94,6 +94,51 @@
lose_text = "You don't feel as prudish as before."
medical_record_text = "Patient exhibits a special gene that makes them immune to Crocin and Hexacrocin."
+/datum/quirk/libido
+ name = "Nymphomania"
+ desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
+ value = 0
+ mob_trait = TRAIT_NYMPHO
+ gain_text = "You are feeling extra wild."
+ lose_text = "You don't feel that burning sensation anymore."
+
+/datum/quirk/libido/add()
+ var/mob/living/M = quirk_holder
+ M.min_arousal = 16
+ M.arousal_rate = 3
+
+/datum/quirk/libido/remove()
+ var/mob/living/M = quirk_holder
+ M.min_arousal = initial(M.min_arousal)
+ M.arousal_rate = initial(M.arousal_rate)
+
+/datum/quirk/maso
+ name = "Masochism"
+ desc = "You are aroused by pain."
+ value = 0
+ mob_trait = TRAIT_MASO
+ gain_text = "You desire to be hurt."
+ lose_text = "Pain has become less exciting for you."
+
+/datum/quirk/exhibitionism
+ name = "Exhibitionism"
+ desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying."
+ value = 0
+ medical_record_text = "Patient has been diagnosed with exhibitionistic disorder."
+ mob_trait = TRAIT_EXHIBITIONIST
+ gain_text = "You feel like exposing yourself to the world."
+ lose_text = "Indecent exposure doesn't sound as charming to you anymore."
+
+/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
+ name = "Acute hepatic pharmacokinesis"
+ desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
+ value = 0
+ mob_trait = TRAIT_PHARMA
+ lose_text = "Your liver feels different."
+ var/active = FALSE
+ var/power = 0
+ var/cachedmoveCalc = 1
+
/datum/quirk/assblastusa
name = "Buns of Steel"
desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 2a47d6d015..68f22242e1 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -829,7 +829,7 @@ Proc for attack log creation, because really why not
return filters[filter_data.Find(name)]
/atom/movable/proc/remove_filter(name)
- if(filter_data[name])
+ if(filter_data && filter_data[name])
filter_data -= name
update_filters()
return TRUE
\ No newline at end of file
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 83762240bc..0957db5fcb 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -27,7 +27,6 @@
glide_size = 8
appearance_flags = TILE_BOUND|PIXEL_SCALE
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
- var/floating = FALSE
var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc.
var/atom/movable/pulling
var/grab_state = 0
@@ -422,6 +421,9 @@
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
+/atom/movable/proc/setMovetype(newval)
+ movement_type = newval
+
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
@@ -518,6 +520,8 @@
TT.thrower = thrower
TT.diagonals_first = diagonals_first
TT.callback = callback
+ if(!QDELETED(thrower))
+ TT.target_zone = thrower.zone_selected
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
@@ -684,14 +688,14 @@
/atom/movable/proc/float(on)
if(throwing)
return
- if(on && !floating)
+ if(on && !(movement_type & FLOATING))
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
sleep(10)
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
- floating = TRUE
- else if (!on && floating)
+ setMovetype(movement_type | FLOATING)
+ else if (!on && (movement_type & FLOATING))
animate(src, pixel_y = initial(pixel_y), time = 10)
- floating = FALSE
+ setMovetype(movement_type & ~FLOATING)
/* Language procs */
/atom/movable/proc/get_language_holder(shadow=TRUE)
diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm
index 46cef7df63..79890e4cdd 100644
--- a/code/game/gamemodes/clown_ops/clown_weapons.dm
+++ b/code/game/gamemodes/clown_ops/clown_weapons.dm
@@ -267,6 +267,7 @@
operation_req_access = list(ACCESS_SYNDICATE)
wreckage = /obj/structure/mecha_wreckage/honker/dark
max_equip = 3
+ spawn_tracked = FALSE
/obj/mecha/combat/honker/dark/GrantActions(mob/living/user, human_occupant = 0)
..()
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index 24cfddd14f..ca009f76ad 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -111,6 +111,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
..()
pop_per_requirement = CONFIG_GET(number/dynamic_pop_per_requirement)
GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
+ GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600
+ GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600
+ GLOB.dynamic_midround_delay_min = CONFIG_GET(number/dynamic_midround_delay_min)*600
+ GLOB.dynamic_midround_delay_max = CONFIG_GET(number/dynamic_midround_delay_max)*600
/datum/game_mode/dynamic/admin_panel()
var/list/dat = list("Game Mode PanelGame Mode Panel
")
@@ -221,7 +225,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
. += G.get_report()
print_command_report(., "Central Command Status Summary", announce=FALSE)
- priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", 'sound/ai/intercept.ogg')
+ priority_announce("A summary has been copied and printed to all communications consoles.", "Security level elevated.", "intercept")
if(GLOB.security_level < SEC_LEVEL_BLUE)
set_security_level(SEC_LEVEL_BLUE)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index 1b4594de2c..c13ba9fd80 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -225,7 +225,7 @@
/datum/dynamic_ruleset/midround/malf
name = "Malfunctioning AI"
- config_tag = "malf_ai"
+ config_tag = "midround_malf_ai"
antag_datum = /datum/antagonist/traitor
antag_flag = ROLE_MALF
enemy_roles = list("Security Officer", "Warden","Detective","Head of Security", "Captain", "Scientist", "Chemist", "Research Director", "Chief Engineer")
@@ -263,7 +263,7 @@
M.mind.special_role = antag_flag
M.mind.add_antag_datum(AI)
if(prob(ion_announce))
- priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/ai/ionstorm.ogg')
+ priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", "ionstorm")
if(prob(removeDontImproveChance))
M.replace_random_law(generate_ion_law(), list(LAW_INHERENT, LAW_SUPPLIED, LAW_ION))
else
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index 6a9aefa996..463c372f0c 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -13,7 +13,7 @@
antag_datum = /datum/antagonist/traitor/
minimum_required_age = 0
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster", "Cyborg")
- restricted_roles = list("Cyborg")
+ restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 5
cost = 10
@@ -41,6 +41,61 @@
log_game("DYNAMIC: Checking if we can turn someone into a traitor.")
mode.picking_specific_rule(/datum/dynamic_ruleset/midround/autotraitor)
+//////////////////////////////////////////////
+// //
+// MALF AI //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/roundstart/delayed/malf_ai
+ name = "Malfunctioning AI"
+ config_tag = "malf_ai"
+ antag_datum = /datum/antagonist/traitor
+ antag_flag = ROLE_MALF
+ enemy_roles = list("Security Officer", "Warden","Detective","Head of Security", "Captain", "Scientist", "Chemist", "Research Director", "Chief Engineer")
+ exclusive_roles = list("AI")
+ required_enemies = list(4,4,4,4,4,4,2,2,2,0)
+ required_candidates = 1
+ weight = 1
+ cost = 35
+ requirements = list(101,101,80,70,60,60,50,50,40,40)
+ high_population_requirement = 35
+ required_type = /mob/living/silicon/ai
+ var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
+
+/datum/dynamic_ruleset/roundstart/delayed/malf_ai/trim_candidates()
+ ..()
+ candidates = candidates[CURRENT_LIVING_PLAYERS]
+ for(var/mob/living/player in candidates)
+ if(!isAI(player))
+ candidates -= player
+ continue
+ if(is_centcom_level(player.z))
+ candidates -= player
+ continue
+ if(player.mind && (player.mind.special_role || player.mind.antag_datums?.len > 0))
+ candidates -= player
+
+/datum/dynamic_ruleset/roundstart/delayed/malf_ai/execute()
+ if(!candidates || !candidates.len)
+ return FALSE
+ var/mob/living/silicon/ai/M = pick(candidates)
+ candidates -= M
+ assigned += M.mind
+ var/datum/antagonist/traitor/AI = new
+ M.mind.special_role = antag_flag
+ M.mind.add_antag_datum(AI)
+ return TRUE
+
+/datum/dynamic_ruleset/roundstart/delayed/malf_ai/rule_process()
+ if (autotraitor_cooldown > 0)
+ autotraitor_cooldown--
+ else
+ autotraitor_cooldown = 450 // 15 minutes
+ message_admins("Checking if we can turn someone into a traitor.")
+ log_game("DYNAMIC: Checking if we can turn someone into a traitor.")
+ mode.picking_specific_rule(/datum/dynamic_ruleset/midround/autotraitor)
+
//////////////////////////////////////////
// //
// BLOOD BROTHERS //
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index 6013b48016..8d3254933a 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -1,5 +1,5 @@
/proc/power_failure()
- priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", 'sound/ai/poweroff.ogg')
+ priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z))
continue
@@ -48,7 +48,7 @@
/proc/power_restore()
- priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/ai/poweron.ogg')
+ priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
for(var/obj/machinery/power/apc/C in GLOB.machines)
if(C.cell && is_station_level(C.z))
C.cell.charge = C.cell.maxcharge
@@ -70,7 +70,7 @@
/proc/power_restore_quick()
- priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", 'sound/ai/poweron.ogg')
+ priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", "poweron")
for(var/obj/machinery/power/smes/S in GLOB.machines)
if(!is_station_level(S.z))
continue
diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm
index c1ae2287ef..1229a9cf8c 100644
--- a/code/game/gamemodes/extended/extended.dm
+++ b/code/game/gamemodes/extended/extended.dm
@@ -29,4 +29,4 @@
/datum/game_mode/extended/announced/send_intercept(report = 0)
if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart
return ..()
- priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", 'sound/ai/commandreport.ogg')
+ priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport")
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index f790053863..17e26e66af 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -258,7 +258,7 @@
/datum/game_mode/proc/send_intercept()
if(flipseclevel && !(config_tag == "extended"))//CIT CHANGE - lets the security level be flipped roundstart
- priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", 'sound/ai/commandreport.ogg')
+ priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport")
return
var/intercepttext = "Central Command Status Summary
"
intercepttext += "Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \
@@ -288,7 +288,7 @@
intercepttext += G.get_report()
print_command_report(intercepttext, "Central Command Status Summary", announce=FALSE)
- priority_announce("A summary has been copied and printed to all communications consoles.", "Enemy communication intercepted. Security level elevated.", 'sound/ai/intercept.ogg')
+ priority_announce("A summary has been copied and printed to all communications consoles.", "Enemy communication intercepted. Security level elevated.", "intercept")
if(GLOB.security_level < SEC_LEVEL_BLUE)
set_security_level(SEC_LEVEL_BLUE)
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index 3c3f0e7f0f..fb46229bdb 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -34,9 +34,9 @@
/obj/machinery/computer/ratvar_act()
if(!clockwork)
clockwork = TRUE
- icon_screen = "ratvar[rand(1, 4)]"
- icon_keyboard = "ratvar_key[rand(1, 6)]"
- icon_state = "ratvarcomputer[rand(1, 4)]"
+ icon_screen = "ratvar[rand(1, 3)]"
+ icon_keyboard = "ratvar_key[rand(1, 2)]"
+ icon_state = "ratvarcomputer"
update_icon()
/obj/machinery/computer/narsie_act()
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 4bce450359..8d950f8458 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -1,8 +1,7 @@
#define ARCADE_WEIGHT_TRICK 4
#define ARCADE_WEIGHT_USELESS 2
#define ARCADE_WEIGHT_RARE 1
-#define ARCADE_WEIGHT_PLUSH 65
-
+#define ARCADE_RATIO_PLUSH 0.20 // average 1 out of 6 wins is a plush.
/obj/machinery/computer/arcade
name = "random arcade"
@@ -27,7 +26,6 @@
/obj/item/toy/katana = ARCADE_WEIGHT_TRICK,
/obj/item/toy/minimeteor = ARCADE_WEIGHT_TRICK,
/obj/item/toy/nuke = ARCADE_WEIGHT_TRICK,
- /obj/item/toy/plush/random = ARCADE_WEIGHT_PLUSH,
/obj/item/toy/redbutton = ARCADE_WEIGHT_TRICK,
/obj/item/toy/spinningtoy = ARCADE_WEIGHT_TRICK,
/obj/item/toy/sword = ARCADE_WEIGHT_TRICK,
@@ -88,8 +86,12 @@
/obj/item/circuitboard/computer/arcade/amputation = 2)
var/thegame = pickweight(gameodds)
var/obj/item/circuitboard/CB = new thegame()
- new CB.build_path(loc, CB)
+ var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB)
+ A.setDir(dir)
return INITIALIZE_HINT_QDEL
+ //The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
+ //Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
+ prizes[/obj/item/toy/plush/random] = counterlist_sum(prizes) * ARCADE_RATIO_PLUSH
Reset()
/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 7dcd85d310..11935e2bfc 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -17,7 +17,7 @@
network += lowertext(i)
/obj/machinery/computer/security/check_eye(mob/user)
- if( (stat & (NOPOWER|BROKEN)) || user.incapacitated() || user.eye_blind )
+ if(CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
user.unset_machine()
return
if(!(user in watchers))
@@ -30,14 +30,6 @@
if(!C.can_use())
user.unset_machine()
return
- if(!issilicon(user))
- if(!Adjacent(user))
- user.unset_machine()
- return
- else if(iscyborg(user))
- var/list/viewing = viewers(src)
- if(!viewing.Find(user))
- user.unset_machine()
/obj/machinery/computer/security/on_unset_machine(mob/user)
watchers.Remove(user)
@@ -97,36 +89,22 @@
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
return
- if(C)
- var/camera_fail = 0
- if(!C.can_use() || user.machine != src || user.eye_blind || user.incapacitated())
- camera_fail = 1
- else if(iscyborg(user))
- var/list/viewing = viewers(src)
- if(!viewing.Find(user))
- camera_fail = 1
- else if(!issilicon(user))
- if(!Adjacent(user))
- camera_fail = 1
-
- if(camera_fail)
- user.unset_machine()
- return 0
-
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
- if(isAI(user))
- var/mob/living/silicon/ai/A = user
- A.eyeobj.setLoc(get_turf(C))
- A.client.eye = A.eyeobj
- else
- user.reset_perspective(C)
- user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
- user.clear_fullscreen("flash", 5)
- watchers[user] = C
- use_power(50)
- addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
- else
+ if(!C || !C.can_use() || CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
user.unset_machine()
+ return FALSE
+
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
+ if(isAI(user))
+ var/mob/living/silicon/ai/A = user
+ A.eyeobj.setLoc(get_turf(C))
+ A.client.eye = A.eyeobj
+ else
+ user.reset_perspective(C)
+ user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
+ user.clear_fullscreen("flash", 5)
+ watchers[user] = C
+ use_power(50)
+ addtimer(CALLBACK(src, .proc/use_camera_console, user), 5)
//returns the list of cameras accessible from this computer
/obj/machinery/computer/security/proc/get_available_cameras()
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 5cbd2d8975..43cfbdb33b 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -298,13 +298,15 @@
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
-
+ var/prev_locked = scanner.locked
+ scanner.locked = TRUE
spawn(20)
src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ scanner.locked = prev_locked
//No locking an open scanner.
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 557f2f0636..f3612078d6 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -335,7 +335,7 @@
Nuke_request(input, usr)
to_chat(usr, "Request sent.")
usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY)
- priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg')
+ priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
CM.lastTimeUsed = world.time
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index c912586ea3..93bc637d8d 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -484,7 +484,7 @@
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
+ active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
else if(href_list["del_c"])
if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index efb1039b8b..ae235dc73f 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -455,7 +455,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
+ active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
if("Delete Record (ALL)")
if(active1)
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index f4f20aecc9..b5869ef36b 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -90,6 +90,7 @@
say("Processing hub calibration to target...")
calibrating = 1
+ power_station.update_icon()
spawn(50 * (3 - power_station.teleporter_hub.accurate)) //Better parts mean faster calibration
calibrating = 0
if(check_hub_connection())
@@ -97,6 +98,7 @@
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
+ power_station.update_icon()
updateDialog()
updateDialog()
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 2e78d72b96..eaf8faef12 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -74,7 +74,8 @@
to_chat(user, "You start adding [I] to [src]...")
if(do_after(user, 50, target=src))
W.use(5)
- new /turf/closed/wall/mineral/wood/nonmetal(get_turf(src))
+ var/turf/T = get_turf(src)
+ T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal)
qdel(src)
return
return ..()
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 893f36acb3..79aef8ba7b 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -24,6 +24,8 @@ Possible to do for anyone motivated enough:
* Holopad
*/
+GLOBAL_LIST_EMPTY(network_holopads)
+
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
@@ -55,7 +57,6 @@ Possible to do for anyone motivated enough:
var/record_user //user that inititiated the recording
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
- var/static/list/holopads = list()
var/obj/effect/overlay/holoray/ray
var/ringing = FALSE
var/offset = FALSE
@@ -96,7 +97,7 @@ Possible to do for anyone motivated enough:
/obj/machinery/holopad/Initialize()
. = ..()
if(on_network)
- holopads += src
+ GLOB.network_holopads += src
/obj/machinery/holopad/Destroy()
if(outgoing_call)
@@ -116,7 +117,7 @@ Possible to do for anyone motivated enough:
QDEL_NULL(disk)
- holopads -= src
+ GLOB.network_holopads -= src
return ..()
/obj/machinery/holopad/power_change()
@@ -260,7 +261,7 @@ Possible to do for anyone motivated enough:
temp += "Main Menu"
if(usr.loc == loc)
var/list/callnames = list()
- for(var/I in holopads)
+ for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
@@ -474,7 +475,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner]
if(!h || h.HC) //Holocalls can't change source.
return FALSE
- for(var/pad in holopads)
+ for(var/pad in GLOB.network_holopads)
var/obj/machinery/holopad/another = pad
if(another == src)
continue
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 165170cf0f..7aaab0d8ea 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -562,6 +562,7 @@
//Shooting Code:
A.preparePixelProjectile(target, T)
A.firer = src
+ A.fired_from = src
A.fire()
return A
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 1f1f13ee22..ae71a0b844 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -209,5 +209,7 @@
icon_state = "controller-o"
else if(stat & (BROKEN|NOPOWER))
icon_state = "controller-p"
+ else if(teleporter_console && teleporter_console.calibrating)
+ icon_state = "controller-c"
else
icon_state = "controller"
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index ea51693135..431d4c30b3 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -3,3 +3,9 @@
internal_damage_threshold = 50
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
+ var/spawn_tracked = TRUE
+
+/obj/mecha/combat/Initialize()
+ . = ..()
+ if(spawn_tracked)
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
\ No newline at end of file
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index cd7051d074..caaa3e3a00 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -19,7 +19,3 @@
/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0)
..()
defense_action.Remove(user)
-
-/obj/mecha/combat/Initialize()
- . = ..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index 564f308df3..c7c180af41 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -29,6 +29,7 @@
operation_req_access = list(ACCESS_SYNDICATE)
wreckage = /obj/structure/mecha_wreckage/gygax/dark
max_equip = 4
+ spawn_tracked = FALSE
/obj/mecha/combat/gygax/dark/loaded/Initialize()
. = ..()
@@ -48,7 +49,6 @@
return
cell = new /obj/item/stock_parts/cell/hyper(src)
-
/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0)
..()
overload_action.Grant(user, src)
@@ -65,7 +65,3 @@
/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0)
..()
thrusters_action.Remove(user)
-
-/obj/mecha/combat/Initialize()
- . = ..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index 4c32e9c367..ed29809f91 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -152,8 +152,4 @@
var/color=""
for (var/i=0;i<6;i++)
color = color+pick(colors)
- return color
-
-/obj/mecha/combat/Initialize()
- . = ..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
+ return color
\ No newline at end of file
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index 21f8259e69..42817b586c 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -16,6 +16,7 @@
force = 45
max_equip = 4
bumpsmash = 1
+ spawn_tracked = FALSE
/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
..()
diff --git a/code/game/mecha/combat/neovgre.dm b/code/game/mecha/combat/neovgre.dm
index 2b2ed150e2..b1f2cdd02a 100644
--- a/code/game/mecha/combat/neovgre.dm
+++ b/code/game/mecha/combat/neovgre.dm
@@ -13,6 +13,7 @@
breach_time = 100 //ten seconds till all goes to shit
recharge_rate = 100
wreckage = /obj/structure/mecha_wreckage/durand/neovgre
+ spawn_tracked = FALSE
/obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar!
internals_action.Grant(user, src)
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index 1264a647c4..15b865c1e9 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -27,7 +27,3 @@
..()
switch_damtype_action.Remove(user)
phasing_action.Remove(user)
-
-/obj/mecha/combat/Initialize()
- . = ..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/reticence.dm b/code/game/mecha/combat/reticence.dm
index 4cd8c01517..7e8c865517 100644
--- a/code/game/mecha/combat/reticence.dm
+++ b/code/game/mecha/combat/reticence.dm
@@ -18,6 +18,7 @@
stepsound = null
turnsound = null
opacity = 0
+ spawn_tracked = FALSE
/obj/mecha/combat/reticence/loaded/Initialize()
. = ..()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 7348c8a575..717c94362c 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1025,7 +1025,7 @@
/obj/mecha/log_message(message as text, message_type=LOG_GAME, color=null, log_globally)
log.len++
- log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss")]","date","year"="[GLOB.year_integer+540]","message"="[color?"":null][message][color?"":null]")
+ log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss")]","date","year"="[GLOB.year_integer]","message"="[color?"":null][message][color?"":null]")
..()
return log.len
@@ -1034,9 +1034,6 @@
last_entry["message"] += "
[red?"":null][message][red?"":null]"
return
-GLOBAL_VAR_INIT(year, time2text(world.realtime,"YYYY"))
-GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
-
///////////////////////
///// Power stuff /////
///////////////////////
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 693d32e545..9c3df5395f 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -89,7 +89,6 @@
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
- SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force)
post_unbuckle_mob(.)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 32d91ee76a..08f698e018 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -170,7 +170,7 @@
if(!victim.client || !istype(victim))
return
to_chat(victim, "You feel fast!")
- ADD_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
+ victim.add_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
sleep(duration)
- REMOVE_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
+ victim.remove_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB)
to_chat(victim, "You slow down.")
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9ce2e66abf..4f81a875f1 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -97,9 +97,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// non-clothing items
var/datum/dog_fashion/dog_fashion = null
- var/datum/rpg_loot/rpg_loot = null
-
-
//Tooltip vars
var/force_string //string form of an item's force. Edit this var only to set a custom force string
var/last_force_string_check = 0
@@ -124,7 +121,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
actions_types = null
if(GLOB.rpg_loot_items)
- rpg_loot = new(src)
+ AddComponent(/datum/component/fantasy)
if(force_string)
item_flags |= FORCE_STRING_OVERRIDE
@@ -149,7 +146,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
m.temporarilyRemoveItemFromInventory(src, TRUE)
for(var/X in actions)
qdel(X)
- QDEL_NULL(rpg_loot)
return ..()
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index cf706359f7..5e798e1281 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -439,6 +439,9 @@ RLD
/obj/item/construction/rcd/proc/rcd_create(atom/A, mob/user)
var/list/rcd_results = A.rcd_vals(user, src)
+ var/turf/the_turf = get_turf(A)
+ var/turf_coords = "[COORD(the_turf)]"
+ investigate_log("[user] is attempting to use [src] on [A] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
if(!rcd_results)
return FALSE
if(do_after(user, rcd_results["delay"] * delay_mod, target = A))
@@ -447,7 +450,7 @@ RLD
if(A.rcd_act(user, src, rcd_results["mode"]))
useResource(rcd_results["cost"], user)
activate()
- investigate_log("[user] used [src] on [cached] (now [A]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
+ investigate_log("[user] used [src] on [cached] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
playsound(src, 'sound/machines/click.ogg', 50, 1)
return TRUE
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index 875a4bd04f..0e422a3fe9 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -80,6 +80,7 @@
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
var/prox_check = TRUE //If the emag requires you to be in range
+ var/uses = 15
/obj/item/card/emag/bluespace
name = "bluespace cryptographic sequencer"
@@ -110,6 +111,37 @@
user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.")
playsound(src, 'sound/effects/light_flicker.ogg', 100, 1)
+/obj/item/card/emag/examine(mob/user)
+ . = ..()
+ to_chat(user, "It has [uses ? uses : "no"] charges left.")
+
+/obj/item/card/emag/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/emagrecharge))
+ var/obj/item/emagrecharge/ER = W
+ if(ER.uses)
+ uses += ER.uses
+ to_chat(user, "You have added [ER.uses] charges to [src]. It now has [uses] charges.")
+ playsound(src, "sparks", 100, 1)
+ ER.uses = 0
+ else
+ to_chat(user, "[ER] has no charges left.")
+ return
+ . = ..()
+
+/obj/item/emagrecharge
+ name = "electromagnet charging device"
+ desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell."
+ icon = 'icons/obj/module.dmi'
+ icon_state = "cell_mini"
+ item_flags = NOBLUDGEON
+ var/uses = 5 //Dictates how many charges the device adds to compatible items
+
+/obj/item/emagrecharge/examine(mob/user)
+ . = ..()
+ if(uses)
+ to_chat(user, "It can add up to [uses] charges to compatible devices")
+ else
+ to_chat(user, "It has a small, red, blinking light coming from inside of it. It's spent.")
/obj/item/card/emagfake
desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"DonkCo\" logo stamped on the back."
@@ -451,3 +483,58 @@ update_label("John Doe", "Clowny")
name = "APC Access ID"
desc = "A special ID card that allows access to APC terminals."
access = list(ACCESS_ENGINE_EQUIP)
+
+//Polychromatic Knight Badge
+
+/obj/item/card/id/knight
+ var/id_color = "#00FF00" //defaults to green
+ name = "knight badge"
+ icon_state = "knight"
+ desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID"
+
+/obj/item/card/id/knight/update_label(newname, newjob)
+ if(newname || newjob)
+ name = "[(!newname) ? "knight badge" : "[newname]'s Knight Badge"][(!newjob) ? "" : " ([newjob])"]"
+ return
+
+ name = "[(!registered_name) ? "knight badge" : "[registered_name]'s Knight Badge"][(!assignment) ? "" : " ([assignment])"]"
+
+/obj/item/card/id/knight/update_icon()
+ var/mutable_appearance/id_overlay = mutable_appearance(icon, "knight_overlay")
+
+ if(id_color)
+ id_overlay.color = id_color
+ cut_overlays()
+
+ add_overlay(id_overlay)
+
+/obj/item/card/id/knight/AltClick(mob/living/user)
+ . = ..()
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null
+ if(!in_range(src, user) || !energy_color_input)
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+
+/obj/item/card/id/knight/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/card/id/knight/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/card/id/knight/blue
+ id_color = "#0000FF"
+
+/obj/item/card/id/knight/captain
+ id_color = "#FFD700"
\ No newline at end of file
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index b0494539ce..92d936e0d4 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -274,7 +274,7 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += text("
[id ? "Update PDA Info" : ""]
")
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss")]
" //:[world.time / 100 % 6][world.time / 100 % 10]"
- dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540]"
+ dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]"
dat += "
"
diff --git a/code/game/objects/items/devices/compressionkit.dm b/code/game/objects/items/devices/compressionkit.dm
index 5ac958328d..a5a9377690 100644
--- a/code/game/objects/items/devices/compressionkit.dm
+++ b/code/game/objects/items/devices/compressionkit.dm
@@ -89,30 +89,23 @@
else
to_chat(user, "Anomalous error. Summon a coder.")
- if(istype(target, /mob/living))
- var/mob/living/victim = target
- if(istype(victim, /mob/living/carbon/human))
- if(user.zone_selected == "groin") // pp smol. There's probably a smarter way to do this but im retarded. If you have a simpler method let me know.
- var/list/organs = victim.getorganszone("groin")
- for(var/internal_organ in organs)
- if(istype(internal_organ, /obj/item/organ/genital/penis))
- var/obj/item/organ/genital/penis/O = internal_organ
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
- victim.visible_message("[user] is preparing to shrink [victim]\'s [O.name] with their bluespace compression kit!")
- if(do_mob(user, victim, 40) && charges > 0 && O.length > 0)
- victim.visible_message("[user] has shrunk [victim]\'s [O.name]!")
- playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
- sparks()
- flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
- charges -= 1
- O.length -= 5
- if(O.length < 1)
- victim.visible_message("[user]\'s [O.name] vanishes!")
- qdel(O) // no pp for you
- else
- O.update_size()
- O.update_appearance()
-
+ else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_GROIN)
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(!P)
+ return
+ playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
+ H.visible_message("[user] is preparing to shrink [H]\'s [P.name] with their bluespace compression kit!")
+ if(do_mob(user, H, 40) && charges > 0 && P.length > 0)
+ H.visible_message("[user] has shrunk [H]\'s [P.name]!")
+ playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
+ sparks()
+ flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
+ charges -= 1
+ var/p_name = P.name
+ P.modify_size(-5)
+ if(QDELETED(P))
+ H.visible_message("[H]\'s [p_name] vanishes!")
/obj/item/compressionkit/attackby(obj/item/I, mob/user, params)
diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm
index c1a9136f76..3c945f464e 100644
--- a/code/game/objects/items/devices/dogborg_sleeper.dm
+++ b/code/game/objects/items/devices/dogborg_sleeper.dm
@@ -6,8 +6,7 @@
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
w_class = WEIGHT_CLASS_TINY
- var/mob/living/carbon/patient = null
- var/mob/living/silicon/robot/hound = null
+ var/mob/living/carbon/patient
var/inject_amount = 10
var/min_health = -100
var/cleaning = FALSE
@@ -61,8 +60,18 @@
/obj/item/dogborg/sleeper/Exit(atom/movable/O)
return 0
+/obj/item/dogborg/sleeper/proc/get_host()
+ if(!loc)
+ return
+ if(iscyborg(loc))
+ return loc
+ else if(iscyborg(loc.loc))
+ return loc.loc //cursed cyborg code
+
/obj/item/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
- hound = loc
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound)
+ return
if(!proximity)
return
if(!iscarbon(target))
@@ -82,7 +91,8 @@
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
- if(patient) return //If you try to eat two people at once, you can only eat one.
+ if(patient)
+ return //If you try to eat two people at once, you can only eat one.
else //If you don't have someone in you, proceed.
if(!isjellyperson(target) && ("toxin" in injection_chems))
@@ -94,14 +104,17 @@
target.forceMove(src)
target.reset_perspective(src)
target.ExtinguishMob() //The tongue already puts out fire stacks but being put into the sleeper shouldn't allow you to keep burning.
- update_gut()
+ update_gut(hound)
user.visible_message("[voracious ? "[hound]'s [src.name] lights up and expands as [target] slips inside into their [src.name]." : "[hound]'s sleeper indicator lights up as [target] is scooped up into [hound.p_their()] [src]."]", \
"Your [voracious ? "[src.name] lights up as [target] slips into" : "sleeper indicator light shines brightly as [target] is scooped inside"] your [src]. Life support functions engaged.")
message_admins("[key_name(hound)] has sleeper'd [key_name(patient)] as a dogborg. [ADMIN_JMP(src)]")
playsound(hound, 'sound/effects/bin_close.ogg', 100, 1)
/obj/item/dogborg/sleeper/container_resist(mob/living/user)
- hound = loc
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound)
+ go_out(user)
+ return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.a_intent == INTENT_HELP)
@@ -113,55 +126,41 @@
"[voracious ? "You start struggling inside of [src]'s tight, flexible confines," : "You start pounding against the metallic walls of [src],"] trying to trigger the release... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear a [voracious ? "couple of thumps" : "loud banging noise"] coming from within [hound].")
if(do_after(user, breakout_time, target = src))
- if(!user || user.stat != CONSCIOUS || user.loc != src )
- return
user.visible_message("[user] successfully broke out of [hound.name]!", \
"You successfully break out of [hound.name]!")
- go_out()
+ go_out(user, hound)
-/obj/item/dogborg/sleeper/proc/go_out(var/target)
- hound = loc
- hound.setClickCooldown(50)
- var/voracious = TRUE
- if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
- voracious = FALSE
- else
- for(var/mob/M in contents)
- if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
- voracious = FALSE
- if(length(contents) > 0)
- hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \
- "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]")
- if(target)
- if(iscarbon(target))
- var/mob/living/carbon/person = target
- person.forceMove(get_turf(src))
- person.reset_perspective()
- else
- var/obj/T = target
- T.loc = hound.loc
+/obj/item/dogborg/sleeper/proc/go_out(atom/movable/target, mob/living/silicon/robot/hound)
+ var/voracious = hound ? TRUE : FALSE
+ var/list/targets = target && hound ? list(target) : contents
+ if(hound)
+ hound.setClickCooldown(50)
+ if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
+ voracious = FALSE
else
- for(var/C in contents)
- if(iscarbon(C))
- var/mob/living/carbon/person = C
- person.forceMove(get_turf(src))
- person.reset_perspective()
- else
- var/obj/T = C
- T.loc = hound.loc
- items_preserved.Cut()
- update_gut()
- cleaning = FALSE
+ for(var/mob/M in targets)
+ if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
+ voracious = FALSE
+ if(length(targets))
+ if(hound)
+ hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \
+ "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]")
+ for(var/a in contents)
+ var/atom/movable/AM = a
+ AM.forceMove(get_turf(src))
+ if(ismob(AM))
+ var/mob/M = AM
+ M.reset_perspective()
playsound(loc, voracious ? 'sound/effects/splat.ogg' : 'sound/effects/bin_close.ogg', 50, 1)
-
- else //You clicked eject with nothing in you, let's just reset stuff to be sure.
- items_preserved.Cut()
- cleaning = FALSE
- update_gut()
+ items_preserved.Cut()
+ cleaning = FALSE
+ if(hound)
+ update_gut(hound)
/obj/item/dogborg/sleeper/attack_self(mob/user)
- if(..())
+ . = ..()
+ if(. || !iscyborg(user))
return
ui_interact(user)
@@ -219,30 +218,31 @@
return data
/obj/item/dogborg/sleeper/ui_act(action, params)
- if(..())
+ . = ..()
+ if(. || !iscyborg(usr))
return
switch(action)
if("eject")
- go_out()
+ go_out(null, usr)
. = TRUE
if("inject")
var/chem = params["chem"]
if(!patient)
return
- inject_chem(chem)
+ inject_chem(chem, usr)
. = TRUE
if("cleaning")
if(!contents)
to_chat(src, "Your [src] is already cleaned.")
return
if(patient)
- to_chat(patient, "[hound.name]'s [src] fills with caustic enzymes around you!")
+ to_chat(patient, "[usr.name]'s [src] fills with caustic enzymes around you!")
to_chat(src, "Cleaning process enabled.")
- clean_cycle()
+ clean_cycle(usr)
. = TRUE
-/obj/item/dogborg/sleeper/proc/update_gut()
+/obj/item/dogborg/sleeper/proc/update_gut(mob/living/silicon/robot/hound)
//Well, we HAD one, what happened to them?
var/prociconupdate = FALSE
var/currentenvy = hound.sleeper_nv
@@ -291,7 +291,7 @@
//Update icon and return new patient
hound.update_icons()
- return(C)
+ return
//Cleaning looks better with red on, even with nobody in it
if(cleaning && !patient)
@@ -307,8 +307,10 @@
hound.update_icons()
//Gurgleborg process
-/obj/item/dogborg/sleeper/proc/clean_cycle()
+/obj/item/dogborg/sleeper/proc/clean_cycle(mob/living/silicon/robot/hound)
//Sanity
+ if(!hound)
+ return
for(var/I in items_preserved)
if(!(I in contents))
items_preserved -= I
@@ -320,13 +322,12 @@
if(cleaning_cycles)
cleaning_cycles--
cleaning = TRUE
- for(var/mob/living/carbon/human/T in (touchable_items))
- if((T.status_flags & GODMODE) || !T.digestable)
- items_preserved += T
+ for(var/mob/living/carbon/C in (touchable_items))
+ if((C.status_flags & GODMODE) || !C.digestable)
+ items_preserved += C
else
- T.adjustBruteLoss(2)
- T.adjustFireLoss(3)
- update_gut()
+ C.adjustBruteLoss(2)
+ C.adjustFireLoss(3)
if(contents)
var/atom/target = pick(touchable_items)
if(iscarbon(target)) //Handle the target being a mob
@@ -359,7 +360,6 @@
if(!T.dropItemToGround(W))
qdel(W)
qdel(T)
- update_gut()
//Handle the target being anything but a mob
else if(isobj(target))
var/obj/T = target
@@ -374,12 +374,10 @@
cleaning_cycles = initial(cleaning_cycles)
cleaning = FALSE
to_chat(hound, "Your [src] chimes it ends its self-cleaning cycle.")//Belly is entirely empty
- update_gut()
if(!length(contents))
to_chat(hound, "Your [src] is now clean. Ending self-cleaning cycle.")
cleaning = FALSE
- update_gut()
//sound effects
if(prob(50))
@@ -397,13 +395,17 @@
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ update_gut(hound)
+
if(cleaning)
- addtimer(CALLBACK(src, .proc/clean_cycle), 50)
+ addtimer(CALLBACK(src, .proc/clean_cycle, hound), 50)
/obj/item/dogborg/sleeper/proc/CheckAccepted(obj/item/I)
return is_type_in_typecache(I, important_items)
-/obj/item/dogborg/sleeper/proc/inject_chem(chem)
+/obj/item/dogborg/sleeper/proc/inject_chem(chem, mob/living/silicon/robot/hound)
+ if(!hound)
+ return
if(hound.cell.charge <= 800) //This is so borgs don't kill themselves with it. Remember, 750 charge used every injection.
to_chat(hound, "You don't have enough power to synthesize fluids.")
return
@@ -438,40 +440,27 @@
else
. = ..()
-/obj/item/dogborg/sleeper/K9/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)
- hound = loc
+/obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound || !istype(target) || !proximity || target.anchored)
+ return
+ if (!target.devourable)
+ to_chat(user, "The target registers an error code. Unable to insert into [src].")
+ return
+ if(target)
+ to_chat(user,"Your [src] is already occupied.")
+ return
+ if(target.buckled)
+ to_chat(user,"[target] is buckled and can not be put into your [src].")
+ return
+ user.visible_message("[hound.name] is ingesting [target] into their [src].", "You start ingesting [target] into your [src.name]...")
+ if(do_after(user, 30, target = target) && !patient && !target.buckled)
+ target.forceMove(src)
+ target.reset_perspective(src)
+ update_gut(hound)
+ user.visible_message("[hound.name]'s mobile brig clunks in series as [target] slips inside.", "Your mobile brig groans lightly as [target] slips inside.")
+ playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
- if(!istype(target))
- return
- if(!proximity)
- return
- if(target.anchored)
- return
- if(isobj(target))
- to_chat(user, "You are above putting such trash inside of yourself.")
- return
- if(iscarbon(target))
- var/mob/living/carbon/brigman = target
- if (!brigman.devourable)
- to_chat(user, "The target registers an error code. Unable to insert into [src].")
- return
- if(patient)
- to_chat(user,"Your [src] is already occupied.")
- return
- if(brigman.buckled)
- to_chat(user,"[brigman] is buckled and can not be put into your [src].")
- return
- user.visible_message("[hound.name] is ingesting [brigman] into their [src].", "You start ingesting [brigman] into your [src.name]...")
- if(do_after(user, 30, target = brigman) && !patient && !brigman.buckled)
- if(!in_range(src, brigman)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
- brigman.forceMove(src)
- brigman.reset_perspective(src)
- update_gut()
- user.visible_message("[hound.name]'s mobile brig clunks in series as [brigman] slips inside.", "Your mobile brig groans lightly as [brigman] slips inside.")
- playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
- return
- return
/obj/item/dogborg/sleeper/compactor //Janihound gut.
name = "garbage processor"
@@ -489,31 +478,25 @@
else
. = ..()
-/obj/item/dogborg/sleeper/compactor/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
- hound = loc
- var/obj/item/target_obj = target
- if(!istype(target))
- return
- if(!proximity)
- return
- if(target.anchored)
+/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
+ var/mob/living/silicon/robot/hound = get_host()
+ 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.")
return
- if(isobj(target))
- if(CheckAccepted(target))
- to_chat(user,"\The [target] registers an error code to your [src]")
+ if(isitem(target))
+ var/obj/item/I = target
+ if(CheckAccepted(I))
+ to_chat(user,"[I] registers an error code to your [src]")
return
- if(target_obj.w_class > WEIGHT_CLASS_NORMAL)
- to_chat(user,"\The [target] is too large to fit into your [src]")
+ if(I.w_class > WEIGHT_CLASS_NORMAL)
+ to_chat(user,"[I] is too large to fit into your [src]")
return
- user.visible_message("[hound.name] is ingesting [target.name] into their [src.name].", "You start ingesting [target] into your [src.name]...")
+ user.visible_message("[hound.name] is ingesting [I] into their [src.name].", "You start ingesting [target] into your [src.name]...")
if(do_after(user, 15, target = target) && length(contents) < max_item_count)
- if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them. This still applies to items, don't magically eat things I picked up already.
- target.forceMove(src)
- user.visible_message("[hound.name]'s garbage processor groans lightly as [target.name] slips inside.", "Your garbage compactor groans lightly as [target] slips inside.")
+ 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.")
playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1)
if(length(contents) > 11) //grow that tum after a certain junk amount
hound.sleeper_r = 1
@@ -523,9 +506,9 @@
hound.update_icons()
return
- else if(iscarbon(target))
- var/mob/living/carbon/trashman = target
- if (!trashman.devourable)
+ if(iscarbon(target) || issilicon(target))
+ var/mob/living/trashman = target
+ if(!trashman.devourable)
to_chat(user, "[target] registers an error code to your [src]")
return
if(patient)
@@ -536,34 +519,8 @@
return
user.visible_message("[hound.name] is ingesting [trashman] into their [src].", "You start ingesting [trashman] into your [src.name]...")
if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
- if(!in_range(src, trashman)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
trashman.forceMove(src)
trashman.reset_perspective(src)
update_gut()
user.visible_message("[hound.name]'s garbage processor groans lightly as [trashman] slips inside.", "Your garbage compactor groans lightly as [trashman] slips inside.")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
- return
- else if(issilicon(target))
- var/mob/living/silicon/trashbot = target
- if (!trashbot.devourable)
- to_chat(user, "[target] registers an error code to your [src]")
- return
- if(patient)
- to_chat(user,"Your [src] is already occupied.")
- return
- if(trashbot.buckled)
- to_chat(user,"[trashbot] is buckled and can not be put into your [src].")
- return
- user.visible_message("[hound.name] is ingesting [trashbot] into their [src].", "You start ingesting [trashbot] into your [src.name]...")
- if(do_after(user, 30, target = trashbot) && !patient && !trashbot.buckled && length(contents) < max_item_count)
- if(!in_range(src, trashbot)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
- trashbot.forceMove(src)
- trashbot.reset_perspective(src)
- update_gut()
- user.visible_message("[hound.name]'s garbage processor groans lightly as [trashbot] slips inside.", "Your garbage compactor groans lightly as [trashbot] slips inside.")
- playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
- return
-
- return
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 207497922e..cf55d4178e 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -48,7 +48,7 @@
/obj/item/multitool/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/multitool/examine(mob/user)
..()
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index ccb82f7029..84439985b2 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -233,7 +233,7 @@
/obj/item/nullrod/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!")
diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm
index 1f44b5318e..1dfc0b4580 100644
--- a/code/game/objects/items/implants/implant_storage.dm
+++ b/code/game/objects/items/implants/implant_storage.dm
@@ -12,7 +12,7 @@
/obj/item/implant/storage/removed(source, silent = FALSE, special = 0)
if(!special)
- qdel(pocket)
+ QDEL_NULL(pocket)
else
pocket?.moveToNullspace()
return ..()
@@ -29,7 +29,7 @@
return FALSE
. = ..()
if(.)
- if(pocket)
+ if(!QDELETED(pocket))
pocket.forceMove(target)
else
pocket = new(target)
@@ -41,7 +41,6 @@
desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else."
component_type = /datum/component/storage/concrete/implant
resistance_flags = INDESTRUCTIBLE //A bomb!
- item_flags = DROPDEL
/obj/item/implanter/storage
name = "implanter (storage)"
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 57b9973aa3..624dbdd8ef 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -233,3 +233,152 @@
desc = "An extremely sharp blade made out of hard light. Packs quite a punch."
icon_state = "lightblade"
item_state = "lightblade"
+
+/*/////////////////////////////////////////////////////////////////////////
+///////////// The TRUE Energy Sword ///////////////////////////
+*//////////////////////////////////////////////////////////////////////////
+
+/obj/item/melee/transforming/energy/sword/cx
+ name = "non-eutactic blade"
+ desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable."
+ icon_state = "cxsword_hilt"
+ item_state = "cxsword"
+ force = 3
+ force_on = 21
+ throwforce = 5
+ throwforce_on = 20
+ hitsound = "swing_hit" //it starts deactivated
+ hitsound_on = 'sound/weapons/nebhit.ogg'
+ attack_verb_off = list("tapped", "poked")
+ throw_speed = 3
+ throw_range = 5
+ sharpness = IS_SHARP
+ embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60)
+ armour_penetration = 10
+ block_chance = 35
+ light_color = "#37FFF7"
+ actions_types = list()
+
+/obj/item/melee/transforming/energy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text)
+ active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE
+ if(active) //also I'd need to rip out the iconstate changing bits
+ force = force_on
+ throwforce = throwforce_on
+ hitsound = hitsound_on
+ throw_speed = 4
+ if(attack_verb_on.len)
+ attack_verb = attack_verb_on
+ w_class = w_class_on
+ START_PROCESSING(SSobj, src)
+ set_light(brightness_on)
+ update_icon()
+ else
+ force = initial(force)
+ throwforce = initial(throwforce)
+ hitsound = initial(hitsound)
+ throw_speed = initial(throw_speed)
+ if(attack_verb_off.len)
+ attack_verb = attack_verb_off
+ w_class = initial(w_class)
+ STOP_PROCESSING(SSobj, src)
+ set_light(0)
+ update_icon()
+ transform_messages(user, supress_message_text)
+ add_fingerprint(user)
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text)
+ playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1)
+ if(!supress_message_text)
+ to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
+
+/obj/item/melee/transforming/energy/sword/cx/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "cxsword_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(active)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+/obj/item/melee/transforming/energy/sword/cx/AltClick(mob/living/user)
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(energy_color_input)
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/melee/transforming/energy/sword/cx/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(active)
+ if(isinhands)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+//Broken version. Not a toy, but not as strong.
+/obj/item/melee/transforming/energy/sword/cx/broken
+ name = "misaligned non-eutactic blade"
+ desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. This one seems to have a damaged handle and misaligned components, causing the blade to be unstable at best"
+ force_on = 15 //As strong a survival knife/bone dagger
+
+/obj/item/melee/transforming/energy/sword/cx/attackby(obj/item/W, mob/living/user, params)
+ if(istype(W, /obj/item/melee/transforming/energy/sword/cx))
+ if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
+ to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
+ return
+ else
+ to_chat(user, "You combine the two light swords, making a single supermassive blade! You're cool.")
+ new /obj/item/twohanded/dualsaber/hypereutactic(user.drop_location())
+ qdel(W)
+ qdel(src)
+ else
+ return ..()
+
+//////// Tatortot NEB /////////////// (same stats as regular esword)
+/obj/item/melee/transforming/energy/sword/cx/traitor
+ name = "\improper Dragon's Tooth Sword"
+ desc = "The Dragon's Tooth sword is a blackmarket modification of a Non-Eutactic Blade, \
+ which utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. \
+ It appears to have a wooden grip and a shaved down guard."
+ icon_state = "cxsword_hilt_traitor"
+ force_on = 30
+ armour_penetration = 50
+ embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10)
+ block_chance = 50
+ hitsound_on = 'sound/weapons/blade1.ogg'
+ light_color = "#37F0FF"
+
+/obj/item/melee/transforming/energy/sword/cx/traitor/transform_messages(mob/living/user, supress_message_text)
+ playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, 1)
+ if(!supress_message_text)
+ to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 48588cf9f3..4847919a08 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -366,10 +366,10 @@
/obj/item/toy/plush/random
name = "Illegal plushie"
desc = "Something fucked up"
+ var/blacklisted_plushes = list(/obj/item/toy/plush/carpplushie/dehy_carp, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random)
/obj/item/toy/plush/random/Initialize()
- ..()
- var/newtype = pick(subtypesof(/obj/item/toy/plush))
+ var/newtype = pick(subtypesof(/obj/item/toy/plush) - typecacheof(blacklisted_plushes))
new newtype(loc)
return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 5454b0fdb8..77bc7ed810 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -313,7 +313,7 @@
if(M.get_ear_protection() == FALSE)
M.confused += 6
audible_message("HUMAN HARM")
- playsound(get_turf(src), 'sound/ai/harmalarm.ogg', 70, 3)
+ playsound(get_turf(src), 'sound/effects/harmalarm.ogg', 70, 3)
cooldown = world.time + 200
log_game("[key_name(user)] used a Cyborg Harm Alarm in [AREACOORD(user)]")
if(iscyborg(user))
@@ -430,7 +430,7 @@
A.BB.nodamage = FALSE
A.BB.speed = 0.5
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
- A.fire_casing(target, user, params, 0, 0, null, 0)
+ A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("[user] blasts a flying lollipop at [target]!")
check_amount()
@@ -446,7 +446,7 @@
A.BB.speed = 0.5
A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1)
- A.fire_casing(target, user, params, 0, 0, null, 0)
+ A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("[user] shoots a high-velocity gumball at [target]!")
check_amount()
@@ -746,3 +746,73 @@
..()
hud = new /obj/item/clothing/glasses/hud/security(src)
return
+
+
+/**********************************************************************
+ Grippers oh god oh fuck
+***********************************************************************/
+
+/obj/item/weapon/gripper
+ name = "circuit gripper"
+ desc = "A simple grasping tool for inserting circuitboards into machinary."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "gripper"
+
+ item_flags = NOBLUDGEON
+
+ //Has a list of items that it can hold.
+ var/list/can_hold = list(
+ /obj/item/circuitboard
+ )
+
+ var/obj/item/wrapped = null // Item currently being held.
+
+/obj/item/weapon/gripper/attack_self()
+ if(wrapped)
+ wrapped.forceMove(get_turf(wrapped))
+ wrapped = null
+ return ..()
+
+/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params)
+
+ if(!proximity)
+ return
+
+ if(!wrapped)
+ for(var/obj/item/thing in src.contents)
+ wrapped = thing
+ break
+
+ if(wrapped) //Already have an item.
+ //Temporary put wrapped into user so target's attackby() checks pass.
+ wrapped.loc = user
+
+ //Pass the attack on to the target. This might delete/relocate wrapped.
+ var/resolved = target.attackby(wrapped,user)
+ if(!resolved && wrapped && target)
+ wrapped.afterattack(target,user,1)
+ //If wrapped was neither deleted nor put into target, put it back into the gripper.
+ if(wrapped && user && (wrapped.loc == user))
+ wrapped.loc = src
+ else
+ wrapped = null
+ return
+
+ else if(istype(target,/obj/item))
+
+ var/obj/item/I = target
+
+ var/grab = 0
+ for(var/typepath in can_hold)
+ if(istype(I,typepath))
+ grab = 1
+ break
+
+ //We can grab the item, finally.
+ if(grab)
+ to_chat(user, "You collect \the [I].")
+ I.loc = src
+ wrapped = I
+ return
+ else
+ to_chat(user, "Your gripper cannot hold \the [target].")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 2356319cd7..d9045a7a34 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -89,32 +89,36 @@
R.speed = initial(R.speed)
/obj/item/borg/upgrade/disablercooler
- name = "cyborg rapid disabler cooling module"
- desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
+ name = "cyborg rapid energy blaster cooling module"
+ desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- to_chat(user, "There's no disabler in this unit!")
+ var/successflag
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ if(T.charge_delay <= 2)
+ successflag = successflag || 2
+ continue
+ T.charge_delay = max(2, T.charge_delay - 4)
+ successflag = 1
+ if(!successflag)
+ to_chat(user, "There's no energy-based firearm in this unit!")
return FALSE
- if(T.charge_delay <= 2)
+ if(successflag == 2)
to_chat(R, "A cooling unit is already installed!")
to_chat(user, "There's no room for another cooling unit!")
return FALSE
- T.charge_delay = max(2 , T.charge_delay - 4)
-
/obj/item/borg/upgrade/disablercooler/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- return FALSE
- T.charge_delay = initial(T.charge_delay)
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ T.charge_delay = initial(T.charge_delay)
+ return .
+ return FALSE
/obj/item/borg/upgrade/thrusters
name = "ion thruster upgrade"
@@ -598,10 +602,10 @@
R.update_transform()
/obj/item/borg/upgrade/rped
- name = "engineering cyborg RPED"
+ name = "engineering cyborg BSRPED"
desc = "A rapid part exchange device for the engineering cyborg."
icon = 'icons/obj/storage.dmi'
- icon_state = "borgrped"
+ icon_state = "borg_BS_RPED"
require_module = TRUE
module_type = list(/obj/item/robot_module/engineering)
@@ -609,14 +613,21 @@
. = ..()
if(.)
+ var/obj/item/storage/part_replacer/bluespace/cyborg/BSRPED = locate() in R
var/obj/item/storage/part_replacer/cyborg/RPED = locate() in R
- if(RPED)
- to_chat(user, "This unit is already equipped with a RPED module.")
+ if(!RPED)
+ RPED = locate() in R.module
+ if(!BSRPED)
+ BSRPED = locate() in R.module //There's gotta be a smarter way to do this.
+ if(BSRPED)
+ to_chat(user, "This unit is already equipped with a BSRPED module.")
return FALSE
- RPED = new(R.module)
- R.module.basic_modules += RPED
- R.module.add_module(RPED, FALSE, TRUE)
+ BSRPED = new(R.module)
+ SEND_SIGNAL(RPED, COMSIG_TRY_STORAGE_QUICK_EMPTY)
+ qdel(RPED)
+ R.module.basic_modules += BSRPED
+ R.module.add_module(BSRPED, FALSE, TRUE)
/obj/item/borg/upgrade/rped/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 13efe72686..eafa79798e 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -49,6 +49,8 @@
STR.max_combined_w_class = 30
STR.max_items = 30
STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear))
+ STR.limited_random_access = TRUE
+ STR.limited_random_access_stack_position = 3
/obj/item/storage/bag/trash/suicide_act(mob/user)
user.visible_message("[user] puts [src] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
@@ -88,6 +90,7 @@
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 60
STR.max_items = 60
+ STR.limited_random_access_stack_position = 5
/obj/item/storage/bag/trash/bluespace/cyborg
insertable = FALSE
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index dde0e0715b..f50b5d1be6 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -1144,7 +1144,7 @@
if(can_expire)
expiration_date = rand(expiration_date_min, expiration_date_max)
desc += "\nAn expiry date is listed on it. It reads: [expiration_date]"
- var/spess_current_year = GLOB.year_integer + 540
+ var/spess_current_year = GLOB.year_integer
if(expiration_date < spess_current_year)
var/gross_risk = min(round(spess_current_year - expiration_date * 0.1), 1)
var/toxic_risk = min(round(spess_current_year - expiration_date * 0.01), 1)
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index bfe630ba01..ee126971a7 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -1,4 +1,5 @@
#define STUNBATON_CHARGE_LENIENCY 0.3
+#define STUNBATON_DEPLETION_RATE 0.006
/obj/item/melee/baton
name = "stunbaton"
@@ -76,7 +77,7 @@
update_icon()
/obj/item/melee/baton/process()
- deductcharge(hitcost * 0.004, FALSE, FALSE)
+ deductcharge(round(hitcost * STUNBATON_DEPLETION_RATE), FALSE, FALSE)
/obj/item/melee/baton/update_icon()
if(status)
@@ -250,4 +251,5 @@
sparkler?.activate()
. = ..()
-#undef STUNBATON_CHARGE_LENIENCY
\ No newline at end of file
+#undef STUNBATON_CHARGE_LENIENCY
+#undef STUNBATON_DEPLETION_RATE
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index b672eb01ca..f592055338 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -17,7 +17,7 @@
/obj/item/tank/jetpack/New()
..()
if(gas_type)
- air_contents.gases[gas_type] = (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)
+ air_contents.gases[gas_type] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
ion_trail = new
ion_trail.set_up(src)
@@ -37,42 +37,50 @@
return
if(!on)
- turn_on()
+ turn_on(user)
to_chat(user, "You turn the jetpack on.")
else
- turn_off()
+ turn_off(user)
to_chat(user, "You turn the jetpack off.")
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/tank/jetpack/proc/turn_on()
+/obj/item/tank/jetpack/proc/turn_on(mob/user)
on = TRUE
icon_state = "[initial(icon_state)]-on"
ion_trail.start()
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react)
+ if(full_speed)
+ user.add_movespeed_modifier(MOVESPEED_ID_JETPACK, priority=100, multiplicative_slowdown=-2, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
-/obj/item/tank/jetpack/proc/turn_off()
+/obj/item/tank/jetpack/proc/turn_off(mob/user)
on = FALSE
stabilizers = FALSE
icon_state = initial(icon_state)
ion_trail.stop()
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
+ user.remove_movespeed_modifier(MOVESPEED_ID_JETPACK)
+
+/obj/item/tank/jetpack/proc/move_react(mob/user)
+ allow_thrust(0.01, user)
/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user)
if(!on)
return
if((num < 0.005 || air_contents.total_moles() < num))
- turn_off()
+ turn_off(user)
return
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return
var/turf/T = get_turf(user)
T.assume_air(removed)
- return 1
+ return TRUE
/obj/item/tank/jetpack/suicide_act(mob/user)
if (istype(user, /mob/living/carbon/human/))
@@ -96,22 +104,22 @@
if(!on)
return
if((num < 0.005 || air_contents.total_moles() < num))
- turn_off()
+ turn_off(user)
return
if(rand(0,250) == 0)
to_chat(user, "You feel your jetpack's engines cut out.")
- turn_off()
+ turn_off(user)
return
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return
var/turf/T = get_turf(user)
T.assume_air(removed)
- return 1
+ return TRUE
/obj/item/tank/jetpack/void
name = "void jetpack (oxygen)"
@@ -178,6 +186,7 @@
full_speed = FALSE
var/datum/gas_mixture/temp_air_contents
var/obj/item/tank/internals/tank = null
+ var/mob/living/carbon/human/cur_user
/obj/item/tank/jetpack/suit/New()
..()
@@ -198,28 +207,30 @@
return
..()
-/obj/item/tank/jetpack/suit/turn_on()
- if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
+/obj/item/tank/jetpack/suit/turn_on(mob/user)
+ if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user)
return
- var/mob/living/carbon/human/H = loc.loc
+ var/mob/living/carbon/human/H = user
tank = H.s_store
air_contents = tank.air_contents
START_PROCESSING(SSobj, src)
+ cur_user = user
..()
-/obj/item/tank/jetpack/suit/turn_off()
+/obj/item/tank/jetpack/suit/turn_off(mob/user)
tank = null
air_contents = temp_air_contents
STOP_PROCESSING(SSobj, src)
+ cur_user = null
..()
/obj/item/tank/jetpack/suit/process()
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
- turn_off()
+ turn_off(cur_user)
return
var/mob/living/carbon/human/H = loc.loc
if(!tank || tank != H.s_store)
- turn_off()
+ turn_off(cur_user)
return
..()
diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm
index 40392c19c3..f427bf6c4c 100644
--- a/code/game/objects/items/teleprod.dm
+++ b/code/game/objects/items/teleprod.dm
@@ -6,11 +6,11 @@
item_state = "teleprod"
slot_flags = null
-/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
+/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user)//handles making things teleport when hit
. = ..()
- if(!. || !istype(M) || M.anchored)
+ if(!. || L.anchored)
return
- do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
+ do_teleport(L, get_turf(L), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/item/melee/baton/cattleprod/teleprod/clowning_around(mob/living/user)
user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 46fabea8b0..638dcd3556 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -276,6 +276,106 @@
/obj/item/toy/sword/getweight()
return (active ? total_mass_on : total_mass) || w_class *1.25
+/obj/item/toy/sword/cx
+ name = "\improper DX Non-Euplastic LightSword"
+ desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "cxsword_hilt"
+ item_state = "cxsword"
+ active = FALSE
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("poked", "jabbed", "hit")
+ light_color = "#37FFF7"
+ var/light_brightness = 3
+ actions_types = list()
+
+/obj/item/toy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/toy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/toy/sword/cx/attack_self(mob/user)
+ active = !( active )
+
+ if (active)
+ to_chat(user, "You activate the holographic blade with a press of a button.")
+ playsound(user, 'sound/weapons/nebon.ogg', 50, 1)
+ w_class = WEIGHT_CLASS_BULKY
+ attack_verb = list("slashed", "stabbed", "ravaged")
+ set_light(light_brightness)
+ update_icon()
+
+ else
+ to_chat(user, "You deactivate the holographic blade with a press of a button.")
+ playsound(user, 'sound/weapons/neboff.ogg', 50, 1)
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("poked", "jabbed", "hit")
+ set_light(0)
+ update_icon()
+
+ add_fingerprint(user)
+
+/obj/item/toy/sword/cx/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "cxsword_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(active)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+/obj/item/toy/sword/cx/AltClick(mob/living/user)
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(energy_color_input)
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(active)
+ if(isinhands)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+/obj/item/toy/sword/cx/attackby(obj/item/W, mob/living/user, params)
+ if(istype(W, /obj/item/toy/sword/cx))
+ if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
+ to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
+ return
+ else
+ to_chat(user, "You combine the two plastic swords, making a single supermassive toy! You're fake-cool.")
+ new /obj/item/twohanded/dualsaber/hypereutactic/toy(user.loc)
+ qdel(W)
+ qdel(src)
+ else
+ return ..()
+
+/obj/item/toy/sword/cx/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
/*
* Foam armblade
*/
@@ -337,6 +437,30 @@
/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles
return FALSE
+/obj/item/twohanded/dualsaber/hypereutactic/toy
+ name = "\improper DX Hyper-Euplastic LightSword"
+ desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up."
+ force = 0
+ throwforce = 0
+ throw_speed = 3
+ throw_range = 5
+ force_unwielded = 0
+ force_wielded = 0
+ attack_verb = list("attacked", "struck", "hit")
+ total_mass_on = TOTAL_MASS_TOY_SWORD
+ slowdown_wielded = 0
+
+/obj/item/twohanded/dualsaber/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
+ return FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles
+ return FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow
+ name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander"
+ desc = "A custom-built toy with fancy rainbow lights built-in."
+ hacked = TRUE
+
/obj/item/toy/katana
name = "replica katana"
desc = "Woefully underpowered in D20."
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index 1bbeccb4de..14f924a27e 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -6,6 +6,7 @@
* Spears
* CHAINSAWS
* Bone Axe and Spear
+ * And more
*/
/*##################################################################
@@ -464,6 +465,116 @@
else
return ..()
+/////////////////////////////////////////////////////
+// HYPEREUTACTIC Blades /////////////////////////
+/////////////////////////////////////////////////////
+
+/obj/item/twohanded/dualsaber/hypereutactic
+ icon = 'icons/obj/1x2.dmi'
+ icon_state = "hypereutactic"
+ lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ item_state = "hypereutactic"
+ inhand_x_dimension = 64
+ inhand_y_dimension = 64
+ name = "hypereutactic blade"
+ desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter."
+ force = 7
+ force_unwielded = 7
+ force_wielded = 40
+ wieldsound = 'sound/weapons/nebon.ogg'
+ unwieldsound = 'sound/weapons/neboff.ogg'
+ hitsound_on = 'sound/weapons/nebhit.ogg'
+ slowdown_wielded = 1
+ armour_penetration = 60
+ light_color = "#37FFF7"
+ rainbow_colors = list("#FF0000", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF","#FF00FF", "#3399ff", "#ff9900", "#fb008b", "#9800ff", "#00ffa3", "#ccff00")
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded")
+ spinnable = FALSE
+ total_mass_on = 4
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain
+ name = "\improper divine lightblade"
+ desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
+ force = 5
+ force_unwielded = 5
+ force_wielded = 20
+ block_chance = 50
+ armour_penetration = 0
+ var/chaplain_spawnable = TRUE
+ obj_flags = UNIQUE_RENAME
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
+ return FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/twohanded/dualsaber/hypereutactic/altafterattack(atom/target, mob/living/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/twohanded/dualsaber/hypereutactic/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "hypereutactic_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "hypereutactic_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(wielded)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+ clean_blood()
+
+/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(!energy_color_input || !user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
+ return
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(isinhands)
+ var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem")
+ gem_inhand.color = light_color
+ . += gem_inhand
+ if(wielded)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+/obj/item/twohanded/dualsaber/hypereutactic/examine(mob/user)
+ ..()
+ if(!hacked)
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/twohanded/dualsaber/hypereutactic/rainbow_process()
+ . = ..()
+ update_icon()
+ update_light()
+
//spears
/obj/item/twohanded/spear
icon_state = "spearglass0"
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 4552e846ad..fec17cfa69 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -528,7 +528,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/baseball_bat/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/melee/baseball_bat/homerun
name = "home run bat"
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 2093ae5660..053512a256 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -1,4 +1,4 @@
-/obj/structure/sign/barsign // All Signs are 64 by 32 pixels, they take two tiles
+/obj/structure/sign/barsign // All Signs are 64 by 64 pixels, though most of them are made to fit 64 x 32 and only take the two lowermost tiles.
name = "Bar Sign"
desc = "A bar sign with no writing on it."
icon = 'icons/obj/barsigns.dmi'
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index dde9bce1bc..cec97d5d8b 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -495,7 +495,25 @@
icon_state = "sofamiddle"
icon = 'icons/obj/sofa.dmi'
buildstackamount = 1
- item_chair = null
+ var/mutable_appearance/armrest
+
+/obj/structure/chair/sofa/Initialize()
+ armrest = mutable_appearance(icon, "[icon_state]_armrest")
+ return ..()
+
+/obj/structure/chair/sofa/post_buckle_mob(mob/living/M)
+ . = ..()
+ update_armrest()
+
+/obj/structure/chair/sofa/proc/update_armrest()
+ if(has_buckled_mobs())
+ add_overlay(armrest)
+ else
+ cut_overlay(armrest)
+
+/obj/structure/chair/sofa/post_unbuckle_mob()
+ . = ..()
+ update_armrest()
/obj/structure/chair/sofa/left
icon_state = "sofaend_left"
@@ -504,4 +522,7 @@
icon_state = "sofaend_right"
/obj/structure/chair/sofa/corner
- icon_state = "sofacorner"
\ No newline at end of file
+ icon_state = "sofacorner"
+
+/obj/structure/chair/sofa/corner/handle_layer() //only the armrest/back of this chair should cover the mob.
+ return
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 8b0d410a72..172120861b 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -614,3 +614,6 @@
user.resting = FALSE
togglelock(user)
T1.visible_message("[user] dives into [src]!")
+
+/obj/structure/closet/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
+ return ..() && opened
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 7c73a1fd8c..12529fb9e0 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -300,18 +300,9 @@
throw_speed = 2
throw_range = 4
-
-/obj/item/twohanded/required/kirbyplants/equipped(mob/living/user)
- var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user)
- I.copy_overlays(src)
- I.override = 1
- add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
- I.layer = ABOVE_MOB_LAYER
- ..()
-
-/obj/item/twohanded/required/kirbyplants/dropped(mob/living/user)
- ..()
- user.remove_alt_appearance("sneaking_mission")
+/obj/item/twohanded/required/kirbyplants/Initialize()
+ . = ..()
+ AddComponent(/datum/component/tactical)
/obj/item/twohanded/required/kirbyplants/random
icon = 'icons/obj/flora/_flora.dmi'
diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm
index ffc2c344f9..176779abd7 100644
--- a/code/game/objects/structures/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -65,6 +65,8 @@
var/mob/M = AM
if(M.mind in immune_minds)
return
+ if(M.anti_magic_check())
+ flare()
if(charges <= 0)
return
flare()
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 0235431705..87db105072 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -682,7 +682,7 @@
log_admin("[key_name(usr)] delayed the round start.")
else
to_chat(world, "The game will start in [DisplayTimeText(newtime)].")
- SEND_SOUND(world, sound('sound/ai/attention.ogg'))
+ SEND_SOUND(world, sound(get_announcer_sound("attention")))
log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm
index cff7faadd8..eae59fcb93 100644
--- a/code/modules/admin/create_mob.dm
+++ b/code/modules/admin/create_mob.dm
@@ -25,6 +25,9 @@
H.facial_hair_color = H.hair_color
H.eye_color = random_eye_color()
H.dna.blood_type = random_blood_type()
+ H.saved_underwear = H.underwear
+ H.saved_undershirt = H.undershirt
+ H.saved_socks = H.socks
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index 58fd627c74..70ae133a31 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -400,7 +400,7 @@
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Chinese Cartoons"))
message_admins("[key_name_admin(usr)] made everything kawaii.")
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
- SEND_SOUND(H, sound('sound/ai/animes.ogg'))
+ SEND_SOUND(H, sound(get_announcer_sound("animes")))
if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
@@ -469,7 +469,7 @@
if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
- priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
+ priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, "commandreport")
if("ak47s")
if(!check_rights(R_FUN))
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 4e58a9cba5..ce4b8f7e39 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -318,6 +318,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
RemoveActive()
state = AHELP_CLOSED
GLOB.ahelp_tickets.ListInsert(src)
+ to_chat(initiator, "Ticket closed by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"].")
AddInteraction("Closed by [key_name].")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "closed")
@@ -336,7 +337,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50)
AddInteraction("Resolved by [key_name].")
- to_chat(initiator, "Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly.")
+ to_chat(initiator, "Your ticket has been resolved by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]. The Adminhelp verb will be returned to you shortly.")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "resolved")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name]"
@@ -353,7 +354,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
SEND_SOUND(initiator, sound('sound/effects/adminhelp.ogg'))
- to_chat(initiator, "- AdminHelp Rejected! -")
+ to_chat(initiator, "- AdminHelp Rejected by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -")
to_chat(initiator, "Your admin help was rejected. The adminhelp verb has been returned to you so that you may try again.")
to_chat(initiator, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
@@ -369,7 +370,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(state != AHELP_ACTIVE)
return
- var/msg = "- AdminHelp marked as IC issue! -
"
+ var/msg = "- AdminHelp marked as IC issue by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -
"
msg += "Losing is part of the game!
"
msg += "It is also possible that your ahelp is unable to be answered properly, due to events occurring in the round."
if(initiator)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 246ccb1d07..d7dd8db08d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -560,7 +560,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/announce_command_report = TRUE
switch(confirm)
if("Yes")
- priority_announce(input, null, 'sound/ai/commandreport.ogg')
+ priority_announce(input, null, "commandreport")
announce_command_report = FALSE
if("Cancel")
return
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index 3d874aac58..c1088cbb3d 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -345,8 +345,8 @@
if(QDELETED(G))
return
- if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "Your target seems to have some sort of protective headgear on, blocking the message from being sent!")
+ if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!")
return
G.mind_control(command, user)
@@ -524,10 +524,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
- if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is interfering with the sleep inducement!")
- L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!", \
- "You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "The specimen's tinfoil protection is interfering with the sleep inducement!")
+ L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protected [L.p_them()]!", \
+ "You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!")
L.drowsyness += 2
return
L.visible_message("[user] has induced sleep in [L] with [src]!", \
@@ -536,10 +536,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
- if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is completely blocking our sleep inducement methods!")
- L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!", \
- "Any sense of drowsiness is quickly diminished as your headgear deflects the effects!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "The specimen's tinfoil protection is completely blocking our sleep inducement methods!")
+ L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil completely protected [L.p_them()]!", \
+ "Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!")
return
L.drowsyness += 1
to_chat(user, "Sleep inducement works fully only on stunned specimens! ")
diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index 9a9b1a6ba0..bcf02bda01 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -178,8 +178,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
- if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- say("Subject wearing specialized protective headgear, unable to get a proper scan!")
+ if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name
diff --git a/code/modules/antagonists/blob/blob/blobs/core.dm b/code/modules/antagonists/blob/blob/blobs/core.dm
index 81792ca4f6..58f79e1c73 100644
--- a/code/modules/antagonists/blob/blob/blobs/core.dm
+++ b/code/modules/antagonists/blob/blob/blobs/core.dm
@@ -27,7 +27,7 @@
. = ..()
/obj/structure/blob/core/proc/generate_announcement()
- priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
+ priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak5")
/obj/structure/blob/core/scannerreport()
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm
index 081b1181dc..1f25e06324 100644
--- a/code/modules/antagonists/changeling/powers/strained_muscles.dm
+++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm
@@ -21,7 +21,7 @@
to_chat(user, "Our muscles tense and strengthen.")
changeling.chem_recharge_slowdown += 0.5
else
- REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
to_chat(user, "Our muscles relax.")
changeling.chem_recharge_slowdown -= 0.5
if(stacks >= 20)
@@ -36,12 +36,12 @@
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
while(active)
- ADD_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
active = !active
to_chat(user, "Our muscles relax without the energy to strengthen them.")
user.Knockdown(40)
- REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
changeling.chem_recharge_slowdown -= 0.5
break
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index 3ad6684725..07b4366194 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -35,7 +35,7 @@
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
- if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
+ if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
if(issilicon(target))
target.visible_message("[target] shudders violently at [src]'s touch!", "ERROR: Temperature rising!")
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
index 28deba679b..644d9eedd5 100644
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
@@ -190,8 +190,8 @@
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
continue
- if(L.anti_magic_check())
- var/atom/I = L.anti_magic_check()
+ var/atom/I = L.anti_magic_check()
+ if(I)
if(isitem(I))
L.visible_message("Strange energy flows into [L]'s [I.name]!", \
"Your [I.name] shields you from [src]!")
diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
index df0083e845..7afd9e7dbc 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
@@ -60,7 +60,7 @@
else
if(isliving(target))
var/mob/living/L = target
- if(!L.anti_magic_check())
+ if(!L.anti_magic_check(chargecost = 0))
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
diff --git a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
index 10c68b606f..1158b02a4c 100644
--- a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
@@ -53,7 +53,7 @@
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
- if(!L.anti_magic_check())
+ if(!L.anti_magic_check(chargecost = 0))
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 10759afcd0..06ea2cbe0a 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -275,7 +275,7 @@
desc = "A torn, dust-caked hood. Strange letters line the inside."
flags_inv = HIDEFACE|HIDEHAIR|HIDEEARS
flags_cover = HEADCOVERSEYES
- armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
cold_protection = HEAD
min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT
heat_protection = HEAD
@@ -288,7 +288,7 @@
item_state = "cultrobes"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
allowed = list(/obj/item/tome, /obj/item/melee/cultblade)
- armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
flags_inv = HIDEJUMPSUIT
cold_protection = CHEST|GROIN|LEGS|ARMS
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm
index 69941f582d..b9e4da8677 100644
--- a/code/modules/antagonists/cult/ritual.dm
+++ b/code/modules/antagonists/cult/ritual.dm
@@ -107,7 +107,7 @@ This file contains the cult dagger and rune list code
if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!")
return
- priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg')
+ priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", "spanomalies")
for(var/B in spiral_range_turfs(1, user, 1))
var/obj/structure/emergency_shield/sanguine/N = new(B)
shields += N
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 2e233d26e4..f0fc59834c 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -237,7 +237,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "You need at least two invokers to convert [convertee]!")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
- if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
+ if(convertee.anti_magic_check(TRUE, TRUE, chargecost = 0)) //Not major because it can be spammed
for(var/M in invokers)
to_chat(M, "Something is shielding [convertee]'s mind!")
log_game("Offer rune failed - convertee had anti-magic")
@@ -767,7 +767,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- var/atom/I = L.anti_magic_check()
+ var/atom/I = L.anti_magic_check(chargecost = 0)
if(I)
if(isitem(I))
to_chat(L, "[I] suddenly burns hotly before returning to normal!")
@@ -797,7 +797,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- if(L.anti_magic_check())
+ if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index f380fa68e9..b43024fb31 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -69,7 +69,7 @@
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
- AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
+ AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 112a31f44d..17d200a685 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -27,6 +27,7 @@
if(prob(10))
to_chat(target, "You feel as if you are being watched.")
return
+ face_atom(target)
draining = TRUE
essence_drained += rand(15, 20)
to_chat(src, "You search for the soul of [target].")
@@ -65,7 +66,7 @@
if(target.anti_magic_check(FALSE, TRUE))
to_chat(src, "Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!")
target.visible_message("[target] slumps onto the ground.", \
- "Violets lights, dancing in your vision, receding--")
+ "Violet lights, dancing in your vision, receding--")
draining = FALSE
return
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
@@ -104,36 +105,16 @@
action_background_icon_state = "bg_revenant"
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
-/obj/effect/proc_holder/spell/targeted/revenant_transmit
- name = "Transmit"
- desc = "Telepathically transmits a message to the target."
+/obj/effect/proc_holder/spell/targeted/telepathy/revenant
+ name = "Revenant Transmit"
panel = "Revenant Abilities"
- charge_max = 0
- clothes_req = 0
- range = 7
- include_user = 0
action_icon = 'icons/mob/actions/actions_revenant.dmi'
action_icon_state = "r_transmit"
action_background_icon_state = "bg_revenant"
-
-/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- for(var/mob/living/M in targets)
- var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
- if(!msg)
- charge_counter = charge_max
- return
- log_directed_talk(user, M, msg, LOG_SAY, "revenant whisper")
- to_chat(user, "You transmit to [M]: [msg]")
- if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
- to_chat(M, "You hear something behind you talking... [msg]")
- for(var/ded in GLOB.dead_mob_list)
- if(!isobserver(ded))
- continue
- var/follow_rev = FOLLOW_LINK(ded, user)
- var/follow_whispee = FOLLOW_LINK(ded, M)
- to_chat(ded, "[follow_rev] [user] Revenant Transmit: \"[msg]\" to [follow_whispee] [M]")
-
-
+ notice = "revennotice"
+ boldnotice = "revenboldnotice"
+ holy_check = TRUE
+ tinfoil_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/revenant
clothes_req = 0
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index 3e05b8d945..235e50008c 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -46,11 +46,11 @@
if(!depression)
SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
depression = TRUE
- SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.12, SANITY_CRAZY)
+ SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.12, SANITY_CRAZY)
if(prob(10))
affected_mob.emote(pick("pale","shiver"))
if(4)
- SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.18, SANITY_CRAZY)
+ SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.18, SANITY_CRAZY)
if(prob(15))
affected_mob.emote(pick("pale","shiver","cries"))
if(5)
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index 03a176b054..f45555a6ee 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -34,7 +34,6 @@
melee_damage_upper = 30
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- var/boost = 0
bloodcrawl = BLOODCRAWL_EAT
var/playstyle_string = "You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \
You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \
@@ -54,24 +53,18 @@
if(istype(loc, /obj/effect/dummy/phased_mob/slaughter))
bloodspell.phased = TRUE
-/mob/living/simple_animal/slaughter/Life()
- ..()
- if(boost"
dat += "Citadel Preferences
" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe.
dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
"
- dat += "Exhibitionist:[features["exhibitionist"] == TRUE ? "Yes" : "No"]
"
dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
"
dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
"
dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
"
@@ -2057,8 +2055,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["has_womb"] = FALSE
if("has_womb")
features["has_womb"] = !features["has_womb"]
- if("exhibitionist")
- features["exhibitionist"] = !features["exhibitionist"]
if("widescreenpref")
widescreenpref = !widescreenpref
user.client.change_view(CONFIG_GET(string/default_view))
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 01a46a44a0..98ef2ed0e8 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
-#define SAVEFILE_VERSION_MAX 23
+#define SAVEFILE_VERSION_MAX 24
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -109,6 +109,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else if(current_version < 23) // we are fixing a gamebreaking bug.
job_preferences = list() //It loaded null from nonexistant savefile field.
+ if(current_version < 24 && S["feature_exhibitionist"])
+ var/datum/quirk/exhibitionism/E
+ var/quirk_name = initial(E.name)
+ neutral_quirks += quirk_name
+ all_quirks += quirk_name
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm
index ccc167dcbc..358942627d 100644
--- a/code/modules/clothing/head/_head.dm
+++ b/code/modules/clothing/head/_head.dm
@@ -41,6 +41,49 @@
H.update_inv_head()
+///Special throw_impact for hats to frisbee hats at people to place them on their heads/attempt to de-hat them.
+/obj/item/clothing/head/throw_impact(atom/hit_atom, datum/thrownthing/thrownthing)
+ . = ..()
+ ///if the thrown object's target zone isn't the head
+ if(thrownthing.target_zone != BODY_ZONE_HEAD)
+ return
+ ///ignore any hats with the tinfoil counter-measure enabled
+ if(clothing_flags & ANTI_TINFOIL_MANEUVER)
+ return
+ ///if the hat happens to be capable of holding contents and has something in it. mostly to prevent super cheesy stuff like stuffing a mini-bomb in a hat and throwing it
+ if(LAZYLEN(contents))
+ return
+ if(iscarbon(hit_atom))
+ var/mob/living/carbon/H = hit_atom
+ if(istype(H.head, /obj/item))
+ var/obj/item/WH = H.head
+ ///check if the item has NODROP
+ if(HAS_TRAIT(WH, TRAIT_NODROP))
+ H.visible_message("[src] bounces off [H]'s [WH.name]!", "[src] bounces off your [WH.name], falling to the floor.")
+ return
+ ///check if the item is an actual clothing head item, since some non-clothing items can be worn
+ if(istype(WH, /obj/item/clothing/head))
+ var/obj/item/clothing/head/WHH = WH
+ ///SNUG_FIT hats are immune to being knocked off
+ if(WHH.clothing_flags & SNUG_FIT)
+ H.visible_message("[src] bounces off [H]'s [WHH.name]!", "[src] bounces off your [WHH.name], falling to the floor.")
+ return
+ ///if the hat manages to knock something off
+ if(H.dropItemToGround(WH))
+ H.visible_message("[src] knocks [WH] off [H]'s head!", "[WH] is suddenly knocked off your head by [src]!")
+ if(H.equip_to_slot_if_possible(src, SLOT_HEAD, FALSE, TRUE))
+ H.visible_message("[src] lands neatly on [H]'s head!", "[src] lands perfectly onto your head!")
+ return
+ if(iscyborg(hit_atom))
+ var/mob/living/silicon/robot/R = hit_atom
+ ///hats in the borg's blacklist bounce off
+ if(!is_type_in_typecache(src, R.equippable_hats) || R.hat_offset == INFINITY)
+ R.visible_message("[src] bounces off [R]!", "[src] bounces off you, falling to the floor.")
+ return
+ else
+ R.visible_message("[src] lands neatly on top of [R].", "[src] lands perfectly on top of you.")
+ R.place_on_head(src) //hats aren't designed to snugly fit borg heads or w/e so they'll always manage to knock eachother off
+
/obj/item/clothing/head/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm
index 90c0690534..5457d32e8a 100644
--- a/code/modules/clothing/head/collectable.dm
+++ b/code/modules/clothing/head/collectable.dm
@@ -13,12 +13,14 @@
/obj/item/clothing/head/collectable/slime
name = "collectable slime cap!"
desc = "It just latches right in place!"
+ clothing_flags = SNUG_FIT
icon_state = "slime"
dynamic_hair_suffix = ""
/obj/item/clothing/head/collectable/xenom
name = "collectable xenomorph helmet!"
desc = "Hiss hiss hiss!"
+ clothing_flags = SNUG_FIT
icon_state = "xenom"
/obj/item/clothing/head/collectable/chef
@@ -71,13 +73,14 @@
desc = "A collectable welding helmet. Now with 80% less lead! Not for actual welding. Any welding done while wearing this helmet is done so at the owner's own risk!"
icon_state = "welding"
item_state = "welding"
- resistance_flags = NONE
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/collectable/slime
name = "collectable slime hat"
desc = "Just like a real brain slug!"
icon_state = "headslime"
item_state = "headslime"
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/collectable/flatcap
name = "collectable flat cap"
@@ -121,6 +124,7 @@
/obj/item/clothing/head/collectable/hardhat
name = "collectable hard hat"
desc = "WARNING! Offers no real protection, or luminosity, but damn, is it fancy!"
+ clothing_flags = SNUG_FIT
icon_state = "hardhat0_yellow"
item_state = "hardhat0_yellow"
@@ -143,7 +147,7 @@
desc = "Go Red! I mean Green! I mean Red! No Green!"
icon_state = "thunderdome"
item_state = "thunderdome"
- resistance_flags = NONE
+ clothing_flags = SNUG_FIT
flags_inv = HIDEHAIR
/obj/item/clothing/head/collectable/swat
@@ -151,5 +155,5 @@
desc = "That's not real blood. That's red paint." //Reference to the actual description
icon_state = "swat"
item_state = "swat"
- resistance_flags = NONE
+ clothing_flags = SNUG_FIT
flags_inv = HIDEHAIR
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 9d38b73cd3..54f0ebea45 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -11,6 +11,7 @@
armor = list("melee" = 15, "bullet" = 5, "laser" = 20,"energy" = 10, "bomb" = 20, "bio" = 10, "rad" = 20, "fire" = 100, "acid" = 50)
flags_inv = 0
actions_types = list(/datum/action/item_action/toggle_helmet_light)
+ clothing_flags = SNUG_FIT
resistance_flags = FIRE_PROOF
dynamic_hair_suffix = "+generic"
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index be6e270e45..8a1cc01bd5 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -10,7 +10,7 @@
heat_protection = HEAD
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
strip_delay = 60
- resistance_flags = NONE
+ clothing_flags = SNUG_FIT
flags_cover = HEADCOVERSEYES
flags_inv = HIDEHAIR
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 041f0ba012..cac98e74fc 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -67,12 +67,14 @@
desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
mutantrace_variation = MUTANTRACE_VARIATION
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/cueball
name = "cueball helmet"
desc = "A large, featureless white orb meant to be worn on your head. How do you even see out of this thing?"
icon_state = "cueball"
item_state="cueball"
+ clothing_flags = SNUG_FIT
flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
@@ -81,6 +83,7 @@
desc = "A ball of white styrofoam. So festive."
icon_state = "snowman_h"
item_state = "snowman_h"
+ clothing_flags = SNUG_FIT
flags_cover = HEADCOVERSEYES
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
@@ -90,6 +93,7 @@
icon_state = "justicered"
item_state = "justicered"
flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
flags_cover = HEADCOVERSEYES
/obj/item/clothing/head/justice/blue
@@ -161,6 +165,7 @@
icon_state = "chickenhead"
item_state = "chickensuit"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/griffin
name = "griffon head"
@@ -168,6 +173,7 @@
icon_state = "griffinhat"
item_state = "griffinhat"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/bearpelt
name = "bear pelt hat"
@@ -181,6 +187,7 @@
item_state = "xenos_helm"
desc = "A helmet made out of chitinous alien hide."
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/fedora
name = "fedora"
@@ -302,6 +309,7 @@
desc = "When everything's going to crab, protecting your head is the best choice."
icon_state = "lobster_hat"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/drfreezehat
name = "doctor freeze's wig"
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index 3f96796a00..0dea8bfe79 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -29,6 +29,7 @@
visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
resistance_flags = FIRE_PROOF
mutantrace_variation = MUTANTRACE_VARIATION
+ clothing_flags = SNUG_FIT
/obj/item/clothing/head/welding/attack_self(mob/user)
weldingvisortoggle(user)
@@ -115,6 +116,7 @@
item_state = "hardhat0_pumpkin"
item_color = "pumpkin"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
+ clothing_flags = SNUG_FIT
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
brightness_on = 2 //luminosity when on
flags_cover = HEADCOVERSEYES
@@ -163,6 +165,7 @@
desc = "A helmet made out of a box."
icon_state = "cardborg_h"
item_state = "cardborg_h"
+ clothing_flags = SNUG_FIT
flags_cover = HEADCOVERSEYES
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
@@ -227,6 +230,7 @@
desc = "A crude helmet made out of bronze plates. It offers very little in the way of protection."
icon = 'icons/obj/clothing/clockwork_garb.dmi'
icon_state = "clockwork_helmet_old"
+ clothing_flags = SNUG_FIT
flags_inv = HIDEEARS|HIDEHAIR
armor = list("melee" = 5, "bullet" = 0, "laser" = -5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 20)
@@ -238,25 +242,62 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = -5,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = -5, "fire" = 0, "acid" = 0)
equip_delay_other = 140
var/datum/brain_trauma/mild/phobia/paranoia
+ var/warped = FALSE
+ clothing_flags = ANTI_TINFOIL_MANEUVER
+
+/obj/item/clothing/head/foilhat/Initialize(mapload)
+ . = ..()
+ if(!warped)
+ AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD, 6, TRUE, null, CALLBACK(src, .proc/warp_up))
+ else
+ warp_up()
/obj/item/clothing/head/foilhat/equipped(mob/living/carbon/human/user, slot)
- ..()
- if(slot == SLOT_HEAD)
- if(paranoia)
- QDEL_NULL(paranoia)
- paranoia = new()
- user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC, "conspiracies")
- to_chat(user, "As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. ")
+ . = ..()
+ if(slot != SLOT_HEAD || warped)
+ return
+ if(paranoia)
+ QDEL_NULL(paranoia)
+ paranoia = new()
+ user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC, "conspiracies")
+ to_chat(user, "As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. ")
+
+/obj/item/clothing/head/foilhat/MouseDrop(atom/over_object)
+ //God Im sorry
+ if(!warped && iscarbon(usr))
+ var/mob/living/carbon/C = usr
+ if(src == C.head)
+ to_chat(C, "Why would you want to take this off? Do you want them to get into your mind?!")
+ return
+ return ..()
/obj/item/clothing/head/foilhat/dropped(mob/user)
- ..()
+ . = ..()
if(paranoia)
QDEL_NULL(paranoia)
+/obj/item/clothing/head/foilhat/proc/warp_up()
+ name = "scorched tinfoil hat"
+ desc = "A badly warped up hat. Quite unprobable this will still work against any of fictional and contemporary dangers it used to."
+ warped = TRUE
+ if(!isliving(loc) || !paranoia)
+ return
+ var/mob/living/target = loc
+ if(target.get_item_by_slot(SLOT_HEAD) != src)
+ return
+ QDEL_NULL(paranoia)
+ if(!target.IsUnconscious())
+ to_chat(target, "Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.")
+
/obj/item/clothing/head/foilhat/attack_hand(mob/user)
- if(iscarbon(user))
+ if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
to_chat(user, "Why would you want to take this off? Do you want them to get into your mind?!")
return
- ..()
+ return ..()
+
+/obj/item/clothing/head/foilhat/microwave_act(obj/machinery/microwave/M)
+ . = ..()
+ if(!warped)
+ warp_up()
diff --git a/code/modules/clothing/head/vg_hats.dm b/code/modules/clothing/head/vg_hats.dm
index dc245cd39a..87f64baf13 100644
--- a/code/modules/clothing/head/vg_hats.dm
+++ b/code/modules/clothing/head/vg_hats.dm
@@ -82,13 +82,6 @@
item_state = "nr_helmet"
icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-/obj/item/clothing/head/stalhelm
- name = "Stalhelm"
- desc = "Ein Helm, um die Nazi-Interesse an fremden Raumstationen zu sichern."
- icon_state = "stalhelm"
- item_state = "stalhelm"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
/obj/item/clothing/head/panzer
name = "Panzer Cap"
desc = "Command any mech in style."
@@ -96,13 +89,6 @@
item_state = "panzercap"
icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-/obj/item/clothing/head/naziofficer
- name = "Officer Cap"
- desc = "Style is all that matters."
- icon_state = "officercap"
- item_state = "officercap"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
/obj/item/clothing/head/russobluecamohat
name = "russian blue camo beret"
desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food."
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index 57866b5131..117fbc49e0 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -4,7 +4,7 @@
name = "space helmet"
icon_state = "spaceold"
desc = "A special helmet with solar UV shielding to protect your eyes from harmful rays."
- clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
+ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SNUG_FIT
item_state = "spaceold"
permeability_coefficient = 0.01
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 1abbb6be2c..fa6b01415e 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -135,7 +135,7 @@
to_chat(user, "You cannot remove the jetpack from [src] while wearing it.")
return
- jetpack.turn_off()
+ jetpack.turn_off(user)
jetpack.forceMove(drop_location())
jetpack = null
to_chat(user, "You successfully remove the jetpack from [src].")
@@ -433,7 +433,7 @@
/obj/item/clothing/suit/space/hardsuit/wizard/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, FALSE)
+ AddComponent(/datum/component/anti_magic, TRUE, FALSE, FALSE, ITEM_SLOT_OCLOTHING, INFINITY, FALSE)
//Medical hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/medical
@@ -867,3 +867,133 @@
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
actions_types = list()
+
+/*
+ CYDONIAN ARMOR THAT IS RGB AND STUFF WOOOOOOOOOO
+*/
+
+/obj/item/clothing/head/helmet/space/hardsuit/lavaknight
+ name = "cydonian helmet"
+ desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
+ icon_state = "knight_cydonia"
+ item_state = "knight_yellow"
+ item_color = null
+ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
+ resistance_flags = FIRE_PROOF | LAVA_PROOF
+ heat_protection = HEAD
+ armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
+ brightness_on = 7
+ allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
+ var/energy_color = "#35FFF0"
+ var/obj/item/clothing/suit/space/hardsuit/lavaknight/linkedsuit = null
+ mutantrace_variation = NO_MUTANTRACE_VARIATION
+
+/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/Initialize()
+ . = ..()
+ if(istype(loc, /obj/item/clothing/suit/space/hardsuit/lavaknight))
+ var/obj/item/clothing/suit/space/hardsuit/lavaknight/S = loc
+ energy_color = S.energy_color
+ update_icon()
+
+/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/attack_self(mob/user)
+ on = !on
+
+ if(on)
+ set_light(brightness_on)
+ else
+ set_light(0)
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_icon()
+ var/mutable_appearance/helm_overlay = mutable_appearance(icon, "knight_cydonia_overlay")
+
+ if(energy_color)
+ helm_overlay.color = energy_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(helm_overlay)
+
+/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file)
+ . = ..()
+ if(!isinhands)
+ var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
+ energy_overlay.plane = ABOVE_LIGHTING_LAYER
+ energy_overlay.color = energy_color
+ . += energy_overlay
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight
+ icon_state = "knight_cydonia"
+ name = "cydonian armor"
+ desc = "A suit designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
+ item_state = "swat_suit"
+ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
+ resistance_flags = FIRE_PROOF | LAVA_PROOF
+ armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
+ allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe)
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight
+ heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
+ tauric = TRUE //Citadel Add for tauric hardsuits
+
+ var/energy_color = "#35FFF0"
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight/Initialize()
+ ..()
+ light_color = energy_color
+ set_light(1)
+ update_icon()
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight/update_icon()
+ var/mutable_appearance/suit_overlay = mutable_appearance(icon, "knight_cydonia_overlay")
+
+ if(energy_color)
+ suit_overlay.color = energy_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(suit_overlay)
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file)
+ . = ..()
+ if(!isinhands)
+ var/mutable_appearance/energy_overlay
+ if(taurmode == SNEK_TAURIC)
+ energy_overlay = mutable_appearance('modular_citadel/icons/mob/taur_naga.dmi', "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
+ else if(taurmode == PAW_TAURIC)
+ energy_overlay = mutable_appearance('modular_citadel/icons/mob/taur_canine.dmi', "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
+ else
+ energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER)
+
+ energy_overlay.plane = ABOVE_LIGHTING_LAYER
+ energy_overlay.color = energy_color
+ . += energy_overlay
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight/AltClick(mob/living/user)
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!in_range(src, user))
+ return
+ if(user.incapacitated() || !istype(user) || !in_range(src, user))
+ return
+
+ if(alert("Are you sure you want to recolor your armor stripes?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",energy_color) as color|null
+ if(energy_color_input)
+ energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ user.update_inv_wear_suit()
+ if(helmet)
+ var/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/H = helmet
+ H.energy_color = energy_color
+ user.update_inv_head()
+ H.update_icon()
+ update_icon()
+ user.update_inv_wear_suit()
+ light_color = energy_color
+ update_light()
+
+/obj/item/clothing/suit/space/hardsuit/lavaknight/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 5d718a8173..88e17d158c 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -368,6 +368,10 @@ Contains:
resistance_flags = FIRE_PROOF
mutantrace_variation = NO_MUTANTRACE_VARIATION
+/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD)
+
/obj/item/clothing/suit/space/hardsuit/ert/paranormal
name = "paranormal response team suit"
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats."
@@ -380,7 +384,7 @@ Contains:
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_OCLOTHING)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor
name = "inquisitor's hardsuit"
diff --git a/code/modules/clothing/spacesuits/vg_spess.dm b/code/modules/clothing/spacesuits/vg_spess.dm
index e6b1c7a1ee..517539f3af 100644
--- a/code/modules/clothing/spacesuits/vg_spess.dm
+++ b/code/modules/clothing/spacesuits/vg_spess.dm
@@ -1,24 +1,5 @@
//VG Ports
-/obj/item/clothing/head/helmet/space/hardsuit/nazi
- name = "nazi hardhelmet"
- desc = "This is the face of das vaterland's top elite. Gas or energy are your only escapes."
- item_state = "hardsuit0-nazi"
- icon_state = "hardsuit0-nazi"
- armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20)
- item_color = "nazi"
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
-
-/obj/item/clothing/suit/space/hardsuit/nazi
- name = "nazi hardsuit"
- desc = "The attire of a true krieger. All shall fall, and only das vaterland will remain."
- item_state = "hardsuit-nazi"
- icon_state = "hardsuit-nazi"
- slowdown = 1
- armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20)
- allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/nazi
- icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi'
/obj/item/clothing/head/helmet/space/hardsuit/soviet
name = "soviet hardhelmet"
diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm
index 932c08ed74..faec9e2f4c 100644
--- a/code/modules/clothing/suits/_suits.dm
+++ b/code/modules/clothing/suits/_suits.dm
@@ -55,7 +55,7 @@
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
if(blood_DNA)
- if(tauric)
+ if(tauric && taurmode >= SNEK_TAURIC)
. += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
else
. += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood", color = blood_DNA_to_color())
diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm
index 5d0a9b9914..369ddba7b9 100644
--- a/code/modules/clothing/suits/bio.dm
+++ b/code/modules/clothing/suits/bio.dm
@@ -4,7 +4,7 @@
icon_state = "bio"
desc = "A hood that protects the head and face from biological contaminants."
permeability_coefficient = 0.01
- clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT
+ clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 60, "fire" = 30, "acid" = 100)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDEFACE|HIDESNOUT
resistance_flags = ACID_PROOF
diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm
index b8287c7f4c..be81374868 100644
--- a/code/modules/clothing/suits/cloaks.dm
+++ b/code/modules/clothing/suits/cloaks.dm
@@ -69,6 +69,7 @@
icon_state = "golhood"
desc = "A protective & concealing hood."
armor = list("melee" = 35, "bullet" = 10, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 60)
+ clothing_flags = SNUG_FIT
flags_inv = HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR
/obj/item/clothing/suit/hooded/cloak/drake
@@ -88,6 +89,7 @@
icon_state = "dragon"
desc = "The skull of a dragon."
armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100)
+ clothing_flags = SNUG_FIT
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | ACID_PROOF
diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm
index fbdca6ddbc..b98d8207d9 100644
--- a/code/modules/clothing/suits/utility.dm
+++ b/code/modules/clothing/suits/utility.dm
@@ -58,7 +58,7 @@
name = "bomb hood"
desc = "Use in case of bomb."
icon_state = "bombsuit"
- clothing_flags = THICKMATERIAL
+ clothing_flags = THICKMATERIAL | SNUG_FIT
armor = list("melee" = 20, "bullet" = 0, "laser" = 20,"energy" = 10, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
flags_inv = HIDEFACE|HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
dynamic_hair_suffix = ""
@@ -123,7 +123,7 @@
name = "radiation hood"
icon_state = "rad"
desc = "A hood with radiation protective properties. The label reads, 'Made with lead. Please do not consume insulation.'"
- clothing_flags = THICKMATERIAL
+ clothing_flags = THICKMATERIAL|SNUG_FIT
flags_inv = HIDEMASK|HIDEEARS|HIDEFACE|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 60, "rad" = 100, "fire" = 30, "acid" = 30)
strip_delay = 60
diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm
index 9d1a47f231..93eb8181c7 100644
--- a/code/modules/clothing/suits/wiz_robe.dm
+++ b/code/modules/clothing/suits/wiz_robe.dm
@@ -7,6 +7,7 @@
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100)
strip_delay = 50
equip_delay_other = 50
+ clothing_flags = SNUG_FIT
resistance_flags = FIRE_PROOF | ACID_PROOF
dog_fashion = /datum/dog_fashion/head/blue_wizard
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index ec39f20b0b..6f188d513f 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -715,8 +715,9 @@
name = "gear harness"
desc = "A simple, inconspicuous harness replacement for a jumpsuit."
icon_state = "gear_harness"
- item_state = "gear_harness" //We dont use golem do to being a item, item without faces making it default to error suit sprites.
+ item_state = "gear_harness"
body_parts_covered = CHEST|GROIN
+ can_adjust = FALSE
/obj/item/clothing/under/durathread
name = "durathread jumpsuit"
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index ddc75830d6..762371886c 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -32,7 +32,7 @@
/datum/round_event/ghost_role/alien_infestation/announce(fake)
if(successSpawn || fake)
- priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
+ priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", "aliens")
/datum/round_event/ghost_role/alien_infestation/spawn_role()
diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm
index 44a66e0d27..8fc1a7ab3d 100644
--- a/code/modules/events/anomaly_bluespace.dm
+++ b/code/modules/events/anomaly_bluespace.dm
@@ -13,7 +13,7 @@
if(prob(90))
priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm
index cc22abe5ab..73562e49e5 100644
--- a/code/modules/events/anomaly_flux.dm
+++ b/code/modules/events/anomaly_flux.dm
@@ -14,7 +14,7 @@
if(prob(90))
priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm
index c240be50d4..6e9014f13c 100644
--- a/code/modules/events/anomaly_grav.dm
+++ b/code/modules/events/anomaly_grav.dm
@@ -12,7 +12,7 @@
if(prob(90))
priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm
index 5a973db95a..988ccadb76 100644
--- a/code/modules/events/anomaly_pyro.dm
+++ b/code/modules/events/anomaly_pyro.dm
@@ -12,7 +12,7 @@
if(prob(90))
priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm
index b57fe9e67e..2550dc191e 100644
--- a/code/modules/events/anomaly_vortex.dm
+++ b/code/modules/events/anomaly_vortex.dm
@@ -14,7 +14,7 @@
if(prob(90))
priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index c17918d733..d2a5c27883 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -4,6 +4,7 @@
weight = 10
max_occurrences = 1
+ earliest_start = 60 MINUTES
min_players = 40
gamemode_blacklist = list("blob") //Just in case a blob survives that long
@@ -15,9 +16,9 @@
/datum/round_event/ghost_role/blob/announce(fake)
if(prob(75))
- priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
+ priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak5")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index a838b62e0d..d422a0aa4f 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -38,7 +38,7 @@
if(prob(50))
priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please stand by. The origin is believed to be \a [source].", "Machine Learning Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index 71f19e5fd7..5a592d7f34 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -17,7 +17,7 @@
if(prob(50))
priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index f63ca39874..07a399a1b6 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -14,7 +14,7 @@
/datum/round_event/disease_outbreak/announce(fake)
- priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak7.ogg')
+ priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak7")
/datum/round_event/disease_outbreak/setup()
announceWhen = rand(15, 30)
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 268a863ebc..10936409f9 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -15,7 +15,7 @@
if(prob(50))
priority_announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm
index 8006d63b97..b289c8ae1b 100644
--- a/code/modules/events/grid_check.dm
+++ b/code/modules/events/grid_check.dm
@@ -9,7 +9,7 @@
startWhen = 1
/datum/round_event/grid_check/announce(fake)
- priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", 'sound/ai/poweroff.ogg')
+ priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
/datum/round_event/grid_check/start()
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 3ae71f99d8..cd7c0e3b1f 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -26,7 +26,7 @@
/datum/round_event/ion_storm/announce(fake)
if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)) || fake)
- priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/ai/ionstorm.ogg')
+ priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", "ionstorm")
/datum/round_event/ion_storm/start()
diff --git a/code/modules/events/major_dust.dm b/code/modules/events/major_dust.dm
index d1570ea09d..c08de985fb 100644
--- a/code/modules/events/major_dust.dm
+++ b/code/modules/events/major_dust.dm
@@ -19,7 +19,7 @@
if(prob(50))
priority_announce(pick(reason), "Collision Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/meateor_wave.dm b/code/modules/events/meateor_wave.dm
index 11af56526c..f668e2332c 100644
--- a/code/modules/events/meateor_wave.dm
+++ b/code/modules/events/meateor_wave.dm
@@ -1,11 +1,11 @@
-/datum/round_event_control/meteor_wave/meaty
- name = "Meteor Wave: Meaty"
- typepath = /datum/round_event/meteor_wave/meaty
- weight = 2
- max_occurrences = 1
-
-/datum/round_event/meteor_wave/meaty
- wave_name = "meaty"
-
-/datum/round_event/meteor_wave/meaty/announce(fake)
- priority_announce("Meaty ores have been detected on collision course with the station.", "Oh crap, get the mop.",'sound/ai/meteors.ogg')
+/datum/round_event_control/meteor_wave/meaty
+ name = "Meteor Wave: Meaty"
+ typepath = /datum/round_event/meteor_wave/meaty
+ weight = 2
+ max_occurrences = 1
+
+/datum/round_event/meteor_wave/meaty
+ wave_name = "meaty"
+
+/datum/round_event/meteor_wave/meaty/announce(fake)
+ priority_announce("Meaty ores have been detected on collision course with the station.", "Oh crap, get the mop.", "meteors")
diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm
index 604e203cd6..4aa9fb305d 100644
--- a/code/modules/events/meteor_wave.dm
+++ b/code/modules/events/meteor_wave.dm
@@ -58,7 +58,7 @@
kill()
/datum/round_event/meteor_wave/announce(fake)
- priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", 'sound/ai/meteors.ogg')
+ priority_announce("Meteors have been detected on collision course with the station. Estimated time until impact: [round(startWhen/60)] minutes.[GLOB.singularity_counter ? " Warning: Anomalous gravity pulse detected, Syndicate technology interference likely." : ""]", "Meteor Alert", "meteors")
/datum/round_event/meteor_wave/tick()
if(ISMULTIPLE(activeFor, 3))
diff --git a/code/modules/events/mice_migration.dm b/code/modules/events/mice_migration.dm
index 48a9f00423..911ce1dfbc 100644
--- a/code/modules/events/mice_migration.dm
+++ b/code/modules/events/mice_migration.dm
@@ -23,7 +23,7 @@
into the [location].", "Migration Alert",
'sound/effects/mousesqueek.ogg')
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index 7256ddb6ea..477655db8b 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -25,7 +25,7 @@
ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names"))
/datum/round_event/pirates/announce(fake)
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
if(fake)
return
threat = new
@@ -77,7 +77,7 @@
else
notify_ghosts("Space pirates are waking up!", source = spawner, action=NOTIFY_ATTACK, flashwindow = FALSE)
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') //CITADEL EDIT also metabreak here too
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") //CITADEL EDIT also metabreak here too
//Shuttle equipment
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index 4d3beacbeb..24be0e5644 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -33,7 +33,7 @@
if(prob(50))
priority_announce("Gr3y.T1d3 virus detected in [station_name()] door subroutines. Severity level of [severity]. Recommend station AI involvement.", "Security Alert")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index ba48779015..60e4e0e4b8 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -12,7 +12,7 @@
announceWhen = 1
/datum/round_event/radiation_storm/announce(fake)
- priority_announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/ai/radiation.ogg')
+ priority_announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", "radiation")
//sound not longer matches the text, but an audible warning is probably good
/datum/round_event/radiation_storm/start()
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index 769e32275b..3fe52c338b 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -32,7 +32,7 @@
if(prob(50))
priority_announce("Cargo: The syndicate are trying to infiltrate your station. If you let them hijack your cargo shuttle, you'll save us a headache.","CentCom Counter Intelligence")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -43,7 +43,7 @@
if(prob(50))
priority_announce("Cargo: A group of angry Russians want to have a party. Can you send them your cargo shuttle then make them disappear?","CentCom Russian Outreach Program")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -54,7 +54,7 @@
if(prob(50))
priority_announce("Cargo: The Spider Clan has sent us a mysterious gift. Can we ship it to you to see what's inside?","CentCom Diplomatic Corps")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -65,7 +65,7 @@
if(prob(50))
priority_announce("Cargo: Seems we've ordered doubles of our department resupply packages this month. Can we send them to you?","CentCom Supply Department")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -76,7 +76,7 @@
if(prob(50))
priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "CentCom Research Initiatives")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -87,7 +87,7 @@
if(prob(50))
priority_announce("Cargo: It looks like a neighbouring station accidentally delivered their pizza to you instead.", "CentCom Spacepizza Division")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -98,7 +98,7 @@
if(prob(50))
priority_announce("Cargo: One of our freighters carrying a bee shipment has been attacked by eco-terrorists. Can you clean up the mess for us?", "CentCom Janitorial Division")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -110,7 +110,7 @@
if(prob(50))
priority_announce("Cargo: We have discovered an active Syndicate bomb near our VIP shuttle's fuel lines. If you feel up to the task, we will pay you for defusing it.", "CentCom Security Division")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
@@ -122,7 +122,7 @@
if(prob(50))
priority_announce("Cargo: We have discovered a warehouse of DELTA locked crates, we cant store any more of them at CC can you take them for us?.", "CentCom Security Division")
else
- priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
+ priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak
for(var/obj/machinery/computer/communications/C in GLOB.machines)
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
var/obj/item/paper/P = new(C.loc)
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index 58c52cbec3..a6c333145e 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -16,7 +16,7 @@
spawncount = rand(5, 8)
/datum/round_event/spider_infestation/announce(fake)
- priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
+ priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", "aliens")
/datum/round_event/spider_infestation/start()
diff --git a/code/modules/events/wizard/magicarp.dm b/code/modules/events/wizard/magicarp.dm
index ab23c30e00..57e2a2a051 100644
--- a/code/modules/events/wizard/magicarp.dm
+++ b/code/modules/events/wizard/magicarp.dm
@@ -36,10 +36,11 @@
projectilesound = 'sound/weapons/emitter.ogg'
maxHealth = 50
health = 50
+ gold_core_spawnable = NO_SPAWN
var/allowed_projectile_types = list(/obj/item/projectile/magic/change, /obj/item/projectile/magic/animate, /obj/item/projectile/magic/resurrection,
/obj/item/projectile/magic/death, /obj/item/projectile/magic/teleport, /obj/item/projectile/magic/door, /obj/item/projectile/magic/aoe/fireball,
/obj/item/projectile/magic/spellblade, /obj/item/projectile/magic/arcane_barrage)
-
+
/mob/living/simple_animal/hostile/carp/ranged/Initialize()
projectiletype = pick(allowed_projectile_types)
. = ..()
diff --git a/code/modules/events/wizard/rpgloot.dm b/code/modules/events/wizard/rpgloot.dm
index 3d560aefb8..bf3104450e 100644
--- a/code/modules/events/wizard/rpgloot.dm
+++ b/code/modules/events/wizard/rpgloot.dm
@@ -8,8 +8,11 @@
/datum/round_event/wizard/rpgloot/start()
var/upgrade_scroll_chance = 0
for(var/obj/item/I in world)
- if(!istype(I.rpg_loot))
- I.rpg_loot = new(I)
+ CHECK_TICK
+ if(!(I.flags_1 & INITIALIZED_1))
+ continue
+
+ I.AddComponent(/datum/component/fantasy)
if(istype(I, /obj/item/storage))
var/obj/item/storage/S = I
@@ -31,86 +34,20 @@
var/upgrade_amount = 1
var/can_backfire = TRUE
- var/one_use = TRUE
+ var/uses = 1
/obj/item/upgradescroll/afterattack(obj/item/target, mob/user , proximity)
. = ..()
if(!proximity || !istype(target))
return
- var/datum/rpg_loot/rpg_loot_datum = target.rpg_loot
- if(!istype(rpg_loot_datum))
- target.rpg_loot = rpg_loot_datum = new /datum/rpg_loot(target)
+ target.AddComponent(/datum/component/fantasy, upgrade_amount, null, null, can_backfire, TRUE)
- var/quality = rpg_loot_datum.quality
-
- if(can_backfire && (quality > 9 && prob((quality - 9)*10)))
- to_chat(user, "[target] violently glows blue for a while, then evaporates.")
- target.burn()
- else
- to_chat(user, "[target] glows blue and seems vaguely \"better\"!")
- rpg_loot_datum.modify(upgrade_amount)
-
- if(one_use)
+ if(--uses <= 0)
qdel(src)
/obj/item/upgradescroll/unlimited
name = "unlimited foolproof item fortification scroll"
desc = "Somehow, this piece of paper can be applied to items to make them \"better\". This scroll is made from the tongues of dead paper wizards, and can be used an unlimited number of times, with no drawbacks."
- one_use = FALSE
+ uses = INFINITY
can_backfire = FALSE
-
-/datum/rpg_loot
- var/positive_prefix = "okay"
- var/negative_prefix = "weak"
- var/suffix = "something profound"
- var/quality = 0
-
- var/obj/item/attached
- var/original_name
-
-/datum/rpg_loot/New(attached_item=null)
- attached = attached_item
-
- randomise()
-
-/datum/rpg_loot/Destroy()
- attached = null
-
-/datum/rpg_loot/proc/randomise()
- var/static/list/prefixespositive = list("greater", "major", "blessed", "superior", "empowered", "honed", "true", "glorious", "robust")
- var/static/list/prefixesnegative = list("lesser", "minor", "blighted", "inferior", "enfeebled", "rusted", "unsteady", "tragic", "gimped")
- var/static/list/suffixes = list("orc slaying", "elf slaying", "corgi slaying", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma", "the forest", "the hills", "the plains", "the sea", "the sun", "the moon", "the void", "the world", "the fool", "many secrets", "many tales", "many colors", "rending", "sundering", "the night", "the day")
-
- var/new_quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
-
- suffix = pick(suffixes)
- positive_prefix = pick(prefixespositive)
- negative_prefix = pick(prefixesnegative)
-
- if(prob(50))
- new_quality = -new_quality
-
- modify(new_quality)
-
-/datum/rpg_loot/proc/rename()
- var/obj/item/I = attached
- if(!original_name)
- original_name = I.name
- if(quality < 0)
- I.name = "[negative_prefix] [original_name] of [suffix] [quality]"
- else if(quality == 0)
- I.name = "[original_name] of [suffix]"
- else if(quality > 0)
- I.name = "[positive_prefix] [original_name] of [suffix] +[quality]"
-
-/datum/rpg_loot/proc/modify(quality_mod)
- var/obj/item/I = attached
- quality += quality_mod
-
- I.force = max(0,I.force + quality_mod)
- I.throwforce = max(0,I.throwforce + quality_mod)
-
- I.armor = I.armor.modifyAllRatings(quality)
-
- rename()
diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm
index bb601b7c82..9dbe1443d1 100644
--- a/code/modules/events/wormholes.dm
+++ b/code/modules/events/wormholes.dm
@@ -29,7 +29,7 @@
wormholes += new /obj/effect/portal/wormhole(T, null, 0, null, FALSE)
/datum/round_event/wormholes/announce(fake)
- priority_announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", 'sound/ai/spanomalies.ogg')
+ priority_announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", "spanomalies")
/datum/round_event/wormholes/tick()
if(activeFor % shift_frequency == 0)
diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm
index 11a5d416e7..a063296edf 100644
--- a/code/modules/fields/timestop.dm
+++ b/code/modules/fields/timestop.dm
@@ -133,6 +133,7 @@
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
if(L.anti_magic_check(check_anti_magic, check_holy))
+ immune += L
return
L.Stun(20, 1, 1)
frozen_mobs[L] = L.anchored
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index bac2e0bb65..7232b717df 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -878,7 +878,7 @@ GLOBAL_LIST_INIT(hallucination_list, list(
if("blob alert")
to_chat(target, "Biohazard Alert
")
to_chat(target, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
- SEND_SOUND(target, 'sound/ai/outbreak5.ogg')
+ SEND_SOUND(target, get_announcer_sound("outbreak5"))
if("ratvar")
target.playsound_local(target, 'sound/machines/clockcult/ark_deathrattle.ogg', 50, FALSE, pressure_affected = FALSE)
target.playsound_local(target, 'sound/effects/clockcult_gateway_disrupted.ogg', 50, FALSE, pressure_affected = FALSE)
@@ -887,15 +887,15 @@ GLOBAL_LIST_INIT(hallucination_list, list(
if("shuttle dock")
to_chat(target, "Priority Announcement
")
to_chat(target, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
- SEND_SOUND(target, 'sound/ai/shuttledock.ogg')
+ SEND_SOUND(target, get_announcer_sound("shuttledock"))
if("malf ai") //AI is doomsdaying!
to_chat(target, "Anomaly Alert
")
to_chat(target, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
- SEND_SOUND(target, 'sound/ai/aimalf.ogg')
+ SEND_SOUND(target, get_announcer_sound("aimalf"))
if("meteors") //Meteors inbound!
to_chat(target, "Meteor Alert
")
to_chat(target, "
Meteors have been detected on collision course with the station.
")
- SEND_SOUND(target, 'sound/ai/meteors.ogg')
+ SEND_SOUND(target, get_announcer_sound("meteors"))
if("supermatter")
SEND_SOUND(target, 'sound/magic/charge.ogg')
to_chat(target, "You feel reality distort for a moment...")
diff --git a/code/modules/food_and_drinks/food/snacks_cake.dm b/code/modules/food_and_drinks/food/snacks_cake.dm
index 98f80331a7..7dadd2b12e 100644
--- a/code/modules/food_and_drinks/food/snacks_cake.dm
+++ b/code/modules/food_and_drinks/food/snacks_cake.dm
@@ -272,7 +272,7 @@
/obj/item/reagent_containers/food/snacks/cakeslice/bscc
name = "blackberry and strawberry chocolate cake slice"
desc = "Just a slice of cake filled with assortment of blackberries and strawberries!"
- icon_state = "blackbarry_strawberries_cake_coco_cake_slice"
+ icon_state = "blackbarry_strawberries_cake_coco_slice"
filling_color = "#FFD700"
tastes = list("blackberry" = 2, "strawberries" = 2, "chocolate" = 2, "sweetness" = 2,"cake" = 3)
foodtype = GRAIN | DAIRY | FRUIT | SUGAR
diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css
index 796d630693..d6918d58aa 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput.css
@@ -12,7 +12,7 @@ html, body {
body {
background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
font-family: Verdana, sans-serif;
- font-size: 9pt;
+ font-size: 13px;
line-height: 1.2;
overflow-x: hidden;
overflow-y: scroll;
@@ -302,7 +302,7 @@ h1.alert, h2.alert {color: #000000;}
.disarm {color: #990000;}
.passive {color: #660000;}
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
+.userdanger {color: #ff0000; font-weight: bold; font-size: 185%;}
.danger {color: #ff0000;}
.warning {color: #ff0000; font-style: italic;}
.alertwarning {color: #FF0000; font-weight: bold}
@@ -330,12 +330,12 @@ h1.alert, h2.alert {color: #000000;}
.cultitalic {color: #960000; font-style: italic;}
.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
+.cultboldtalic {color: #960000; font-weight: bold; font-size: 185%;}
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
+.cultlarge {color: #960000; font-weight: bold; font-size: 185%;}
+.narsie {color: #960000; font-weight: bold; font-size: 925%;}
+.narsiesmall {color: #960000; font-weight: bold; font-size: 370%;}
+.colossus {color: #7F282A; font-size: 310%;}
.hierophant {color: #660099; font-weight: bold; font-style: italic;}
.hierophant_warning {color: #660099; font-style: italic;}
.purple {color: #5e2d79;}
@@ -343,36 +343,36 @@ h1.alert, h2.alert {color: #000000;}
.revennotice {color: #1d2953;}
.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
+.revenbignotice {color: #1d2953; font-weight: bold; font-size: 185%;}
.revenminor {color: #823abb}
.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
+.revendanger {color: #760fbb; font-weight: bold; font-size: 185%;}
.umbra {color: #5000A0;}
.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
+.umbra_large {color: #5000A0; font-size: 185%; font-weight: bold; font-style: italic;}
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
+.deconversion_message {color: #5000A0; font-size: 185%; font-style: italic;}
.brass {color: #BE8700;}
.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
+.large_brass {color: #BE8700; font-size: 185%;}
+.big_brass {color: #BE8700; font-size: 185%; font-weight: bold; font-style: italic;}
+.ratvar {color: #BE8700; font-size: 370%; font-weight: bold; font-style: italic;}
.alloy {color: #42474D;}
.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
+.nezbere_large {color: #42474D; font-size: 185%; font-weight: bold; font-style: italic;}
.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
+.sevtug_large {color: #AF0AAF; font-size: 185%; font-weight: bold; font-style: italic;}
.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
+.inathneq_large {color: #1E8CE1; font-size: 185%; font-weight: bold; font-style: italic;}
.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
+.nzcrentr_large {color: #DAAA18; font-size: 185%; font-weight: bold; font-style: italic;}
.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
+.neovgre_large {color: #6E001A; font-size: 185%; font-weight: bold; font-style: italic;}
.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
.neovgre_small {color: #6E001A;}
@@ -384,7 +384,7 @@ h1.alert, h2.alert {color: #000000;}
.alertalien {color: #00c000; font-weight: bold;}
.changeling {color: #800080; font-style: italic;}
-.spider {color: #4d004d;}
+.spider {color: #4d004d; font-weight: bold; font-size: 185%;}
.interface {color: #330033;}
@@ -392,14 +392,14 @@ h1.alert, h2.alert {color: #000000;}
.papyrus {font-family: "Papyrus", cursive, sans-serif;}
.robot {font-family: "Courier New", cursive, sans-serif;}
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
+.command_headset {font-weight: bold; font-size: 160%;}
+.small {font-size: 60%;}
+.big {font-size: 185%;}
+.reallybig {font-size: 245%;}
+.extremelybig {font-size: 310%;}
+.greentext {color: #00FF00; font-size: 185%;}
+.redtext {color: #FF0000; font-size: 185%;}
+.clown {color: #FF69Bf; font-size: 160%; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
.spooky {color: #FF6100;}
.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
@@ -431,9 +431,9 @@ h1.alert, h2.alert {color: #000000;}
.icon {height: 1em; width: auto;}
.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
+.memoedit {text-align: center; font-size: 125%;}
.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
+.mind_control {color: #A00D6F; font-size: 100%; font-weight: bold; font-style: italic;}
.slime {color: #00CED1;}
.drone {color: #848482;}
.monkey {color: #975032;}
@@ -441,7 +441,7 @@ h1.alert, h2.alert {color: #000000;}
.resonate {color: #298F85;}
.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
+.monkeylead {color: #774704; font-size: 125%;}
.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
.connectionClosed.restored {background: green;}
diff --git a/code/modules/goonchat/browserassets/css/browserOutput_dark.css b/code/modules/goonchat/browserassets/css/browserOutput_dark.css
index 2e1fe8cdec..3377bcf72c 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput_dark.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput_dark.css
@@ -28,20 +28,20 @@ a:visited {color: #7c00e6;}
#userBar .toggle {background: #272727;}
/* MOTD */
-.motd {color: #E0E0E0; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #E0E0E0; text-decoration: underline;}
+.motd {color: #E0E0E0;}
+.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #E0E0E0;}
.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #E0E0E0;}
-h1, h2, h3, h4, h5, h6 {color: #E0E0E0;font-family: Georgia, Verdana, sans-serif;}
+h1, h2, h3, h4, h5, h6 {color: #E0E0E0;}
h1.alert, h2.alert {color: #E0E0E0;}
-.ooc {color: #cca300; font-weight: bold;}
-.looc {color: #d8b555; font-weight: bold;}
-.antagooc {color: #ce254f; font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #3d5bc3; font-weight: bold;}
+.ooc {color: #cca300;}
+.looc {color: #d8b555;}
+.antagooc {color: #ce254f;}
+.adminobserverooc {color: #0099cc;}
+.adminooc {color: #3d5bc3;}
-.admin {color: #5975da; font-weight: bold;}
+.admin {color: #5975da;}
.deadsay {color: #e2c1ff;}
.radio {color: #1ecc43;}
@@ -65,82 +65,82 @@ h1.alert, h2.alert {color: #99aab5;}
.disarm {color: #b42525;}
.passive {color: #a00f0f;}
-.userdanger {color: #c51e1e; font-weight: bold; font-size: 24px;}
+.userdanger {color: #c51e1e;}
.danger {color: #c51e1e;}
-.warning {color: #c51e1e; font-style: italic;}
-.alertwarning {color: #c51e1e; font-weight: bold}
-.boldwarning {color: #c51e1e; font-style: italic; font-weight: bold}
-.announce {color: #c51e1e; font-weight: bold;}
-.boldannounce {color: #c51e1e; font-weight: bold;}
-.greenannounce {color: #059223; font-weight: bold;}
+.warning {color: #c51e1e;}
+.alertwarning {color: #c51e1e;}
+.boldwarning {color: #c51e1e;}
+.announce {color: #c51e1e;}
+.boldannounce {color: #c51e1e;}
+.greenannounce {color: #059223;}
.info {color: #6685f5;}
.notice {color: #6685f5;}
-.boldnotice {color: #6685f5; font-weight: bold;}
+.boldnotice {color: #6685f5;}
.adminnotice {color: #6685f5;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #E0E0E0; font-weight: bold;}
-.red {color: #FF0000}
+.adminhelp {color: #ff0000;}
+.unconscious {color: #E0E0E0;}
+.red {color: #FF0000;}
.pink {color: #ff70c1;}
-.blue {color: #215cff}
+.blue {color: #215cff;}
.green {color: #059223;}
.nicegreen {color: #059223;}
-.userlove {color: #ff42a6; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #82365e;}
-.love {color: #ff4591; font-style: italic; text-shadow: 0 0 6px #994449;}
+.userlove {color: #ff42a6; text-shadow: 0 0 6px #82365e;}
+.love {color: #ff4591; text-shadow: 0 0 6px #994449;}
.shadowling {color: #8e8a99;}
.cult {color: #aa1c1c;}
-.cultitalic {color: #aa1c1c; font-style: italic;}
-.cultbold {color: #aa1c1c; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #aa1c1c; font-weight: bold; font-size: 24px;}
+.cultitalic {color: #aa1c1c;}
+.cultbold {color: #aa1c1c;}
+.cultboldtalic {color: #aa1c1c;}
-.cultlarge {color: #aa1c1c; font-weight: bold; font-size: 24px;}
-.narsie {color: #aa1c1c; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #aa1c1c; font-weight: bold; font-size: 48px;}
-.hierophant {color: #b441ee; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #c56bf1; font-style: italic;}
+.cultlarge {color: #aa1c1c;}
+.narsie {color: #aa1c1c;}
+.narsiesmall {color: #aa1c1c;}
+.hierophant {color: #b441ee;}
+.hierophant_warning {color: #c56bf1;}
.purple {color: #9956d3;}
.holoparasite {color: #88809c;}
.revennotice {color: #3645aa;}
-.revenboldnotice {color: #3645aa; font-weight: bold;}
-.revenbignotice {color: #3645aa; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823ddd}
-.revenwarning {color: #8911d9; font-style: italic;}
-.revendanger {color: #8911d9; font-weight: bold; font-size: 24px;}
+.revenboldnotice {color: #3645aa;}
+.revenbignotice {color: #3645aa;}
+.revenminor {color: #823ddd;}
+.revenwarning {color: #8911d9;}
+.revendanger {color: #8911d9;}
.umbra {color: #7c00e6;}
-.umbra_emphasis {color: #7c00e6; font-weight: bold; font-style: italic;}
-.umbra_large {color: #7c00e6; font-size: 24px; font-weight: bold; font-style: italic;}
+.umbra_emphasis {color: #7c00e6;}
+.umbra_large {color: #7c00e6;}
-.deconversion_message {color: #a947ff; font-size: 24px; font-style: italic;}
+.deconversion_message {color: #a947ff;}
.alloy {color: #545b64;}
-.heavy_alloy {color: #545b64; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #545b64; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #545b64; font-weight: bold; font-style: italic;}
+.heavy_alloy {color: #545b64;}
+.nezbere_large {color: #545b64;}
+.nezbere {color: #545b64;}
.nezbere_small {color: #545b64;}
-.inathneq_large {color: #1d7dc7; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1d7dc7; font-weight: bold; font-style: italic;}
+.inathneq_large {color: #1d7dc7;}
+.inathneq {color: #1d7dc7;}
.inathneq_small {color: #1d7dc7;}
-.neovgre_large {color: #7c0622; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #7c0622; font-weight: bold; font-style: italic;}
+.neovgre_large {color: #7c0622;}
+.neovgre {color: #7c0622;}
.neovgre_small {color: #7c0622;}
.newscaster {color: #c05d5d;}
-.ghostalert {color: #6600ff; font-style: italic; font-weight: bold;}
+.ghostalert {color: #6600ff;}
.alien {color: #855d85;}
.noticealien {color: #059223;}
-.alertalien {color: #059223; font-weight: bold;}
-.changeling {color: #059223; font-style: italic;}
+.alertalien {color: #059223;}
+.changeling {color: #059223;}
.spider {color: #8800ff;}
.interface {color: #750e75;}
-.greentext {color: #059223; font-size: 24px;}
-.redtext {color: #c51e1e; font-size: 24px;}
-.clown {color: #ff70c1; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
+.greentext {color: #059223;}
+.redtext {color: #c51e1e;}
+.clown {color: #ff70c1;}
+.velvet {color: #660015;}
@keyframes velvet {
0% { color: #890020; }
40% { color: #c51e1e; }
@@ -149,11 +149,11 @@ h1.alert, h2.alert {color: #99aab5;}
100% { color: #890020; }
}
-.abductor {color: #c204c2; font-style: italic;}
-.mind_control {color: #df3da9; font-size: 3; font-weight: bold; font-style: italic;}
+.abductor {color: #c204c2;}
+.mind_control {color: #df3da9;}
.drone {color: #979795;}
.monkeyhive {color: #a56408;}
-.monkeylead {color: #af6805; font-size: 2;}
+.monkeylead {color: #af6805;}
-.internal.boldnshit {color: #3d5bc3; font-weight: bold;}
+.internal.boldnshit {color: #3d5bc3;}
diff --git a/code/modules/goonchat/browserassets/css/browserOutput_light.css b/code/modules/goonchat/browserassets/css/browserOutput_light.css
index 098bd25367..b7036c74d8 100644
--- a/code/modules/goonchat/browserassets/css/browserOutput_light.css
+++ b/code/modules/goonchat/browserassets/css/browserOutput_light.css
@@ -12,222 +12,3 @@ body {background: #F1F1F1;}
/* ADMIN CONTEXT MENU */
.contextMenu {background-color: #ddd;}
-
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.ooc {color: #002eb8; font-weight: bold;}
-.looc {color: #6699CC; font-weight: bold;}
-.antagooc {color: #b8002e; font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #700038; font-weight: bold;}
-
-.adminsay {color: #FF4500}
-.admin {color: #386aff; font-weight: bold;}
-
-.name { font-weight: bold;}
-
-.say {}
-.deadsay {color: #5c00e6;}
-.binarysay {color: #20c20e; background-color: #000000; display: block;}
-.binarysay a {color: #00ff00;}
-.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #008000;}
-.sciradio {color: #993399;}
-.comradio {color: #948f02;}
-.secradio {color: #a30000;}
-.medradio {color: #337296;}
-.engradio {color: #fb5613;}
-.suppradio {color: #a8732b;}
-.servradio {color: #6eaa2c;}
-.syndradio {color: #6d3f40;}
-.centcomradio {color: #686868;}
-.aiprivradio {color: #ff00ff;}
-.redteamradio {color: #ff0000;}
-.blueteamradio {color: #0000ff;}
-
-.yell { font-weight: bold;}
-
-.alert {color: #ff0000;}
-h1.alert, h2.alert {color: #000000;}
-
-.emote { font-style: italic;}
-.selecteddna {color: #ffffff; background-color: #001B1B}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.alertwarning {color: #FF0000; font-weight: bold}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.red {color: #FF0000;}
-.pink {color: #FF69Bf;}
-.blue {color: #0000FF;}
-.nicegreen {color: #14a833;}
-.userlove {color: #FF1493; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #ff6dbc;}
-.love {color: #ff006a; font-style: italic; text-shadow: 0 0 6px #ff6d6d;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-
-.cultitalic {color: #960000; font-style: italic;}
-.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #5000A0;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.changeling {color: #800080; font-style: italic;}
-
-.spider {color: #4d004d;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
-@keyframes velvet {
- 0% { color: #400020; }
- 40% { color: #FF0000; }
- 50% { color: #FF8888; }
- 60% { color: #FF0000; }
- 100% { color: #400020; }
-}
-
-.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
-@keyframes hypnocolor {
- 0% { color: #202020; }
- 25% { color: #4b02ac; }
- 50% { color: #9f41f1; }
- 75% { color: #541c9c; }
- 100% { color: #7adbf3; }
-}
-
-.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
-@keyframes phobia {
- 0% { color: #f75a5a; }
- 50% { color: #dd0000; }
- 100% { color: #f75a5a; }
-}
-
-
-.icon {height: 1em; width: auto;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
-.slime {color: #00CED1;}
-.drone {color: #848482;}
-.monkey {color: #975032;}
-.swarmer {color: #2C75FF;}
-.resonate {color: #298F85;}
-
-.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: #000099; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}
diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm
index f2d7fa1526..3cb05a8f7e 100644
--- a/code/modules/holiday/easter.dm
+++ b/code/modules/holiday/easter.dm
@@ -18,7 +18,7 @@
max_occurrences = 10
/datum/round_event/rabbitrelease/announce(fake)
- priority_announce("Unidentified furry objects detected coming aboard [station_name()]. Beware of Adorable-ness.", "Fluffy Alert", 'sound/ai/aliens.ogg')
+ priority_announce("Unidentified furry objects detected coming aboard [station_name()]. Beware of Adorable-ness.", "Fluffy Alert", "aliens")
/datum/round_event/rabbitrelease/start()
diff --git a/code/modules/holiday/halloween/bartholomew.dm b/code/modules/holiday/halloween/bartholomew.dm
index 129f4e29b6..aa119dca84 100644
--- a/code/modules/holiday/halloween/bartholomew.dm
+++ b/code/modules/holiday/halloween/bartholomew.dm
@@ -20,6 +20,7 @@
if(!active)
say("Meow!")
return
+
for(var/I2 in items_list)
if(istype(I, I2))
qdel(I)
@@ -36,6 +37,7 @@
return
say("Hello there, I'm Bartholomew, Jacqueline's Familiar.")
sleep(20)
+
say("I'm currently seeking items to put into my pot, if we get the right items, it should crystalise into a magic candy!")
if(!iscarbon(user))
say("Though... I'm not sure you can help me.")
@@ -52,6 +54,15 @@
message += "currently seem to have the most magic potential."
sleep(15)
say("[message]")
+ sleep(15)
+ //To help people find her
+ for(var/mob/living/simple_animal/jacq/J in GLOB.simple_animals[1])
+ var/turf/L1 = J.loc
+ if(!L1) //Incase someone uh.. puts her in a locker
+ return
+ var/area/L2 = L1.loc
+ if(L2)
+ say("Also, it seems that Jacqueline is currently at the [L2], if you're looking for her too.")
/obj/item/barthpot/proc/generate_items()
var/length = LAZYLEN(items_list)
@@ -64,79 +75,65 @@
/obj/item/clothing/head/that = 1,
/obj/item/clothing/head/ushanka = 1,
/obj/item/clothing/head/welding = 1,
- /obj/item/clothing/mask/gas = 15,
+ /obj/item/clothing/mask/gas = 10,
/obj/item/clothing/suit/hazardvest = 1,
- /obj/item/clothing/under/rank/vice = 1,
- /obj/item/clothing/suit/hooded/flashsuit = 2,
- /obj/item/clothing/accessory/medal/greytide = 1,
+ /obj/item/clothing/suit/hooded/flashsuit = 1,
/obj/item/assembly/prox_sensor = 4,
/obj/item/assembly/timer = 3,
- /obj/item/flashlight = 4,
+ /obj/item/flashlight = 6,
/obj/item/flashlight/pen = 1,
- /obj/effect/spawner/lootdrop/glowstick = 4,
- /obj/effect/spawner/lootdrop/mre = 3,
+ /obj/item/flashlight/glowstick = 4,
/obj/item/multitool = 2,
- /obj/item/radio/off = 2,
+ /obj/item/radio = 2,
/obj/item/t_scanner = 5,
/obj/item/airlock_painter = 1,
- /obj/item/stack/cable_coil/ = 4,
+ /obj/item/stack/cable_coil = 6,
/obj/item/stack/medical/bruise_pack = 1,
/obj/item/stack/rods = 3,
/obj/item/stack/sheet/cardboard = 2,
/obj/item/stack/sheet/metal = 1,
/obj/item/stack/sheet/mineral/plasma = 1,
/obj/item/stack/sheet/rglass = 1,
- /obj/item/book/manual/wiki/engineering_construction = 1,
- /obj/item/book/manual/wiki/engineering_hacking = 1,
- /obj/item/clothing/head/cone = 1,
- /obj/item/coin/silver = 1,
- /obj/item/coin/twoheaded = 1,
- /obj/item/poster/random_contraband = 1,
- /obj/item/poster/random_official = 1,
- /obj/item/crowbar = 1,
- /obj/item/crowbar/red = 1,
- /obj/item/extinguisher = 11,
+ /obj/item/coin = 1,
+ /obj/item/crowbar = 4,
+ /obj/item/extinguisher = 3,
/obj/item/hand_labeler = 1,
- /obj/item/paper/crumpled = 1,
- /obj/item/pen = 1,
+ /obj/item/paper = 6,
+ /obj/item/pen = 5,
/obj/item/reagent_containers/spray/pestspray = 1,
/obj/item/reagent_containers/rag = 3,
/obj/item/stock_parts/cell = 3,
/obj/item/storage/belt/utility = 2,
- /obj/item/storage/box = 2,
- /obj/item/storage/box/cups = 1,
+ /obj/item/storage/box = 4,
+ /obj/item/reagent_containers/food/drinks/sillycup = 1,
/obj/item/storage/box/donkpockets = 1,
- /obj/item/storage/box/lights/mixed = 3,
+ /obj/item/storage/box/lights/mixed = 1,
/obj/item/storage/box/hug/medical = 1,
- /obj/item/storage/fancy/cigarettes/dromedaryco = 1,
- /obj/item/storage/toolbox/mechanical = 1,
+ /obj/item/storage/fancy/cigarettes = 1,
+ /obj/item/storage/toolbox = 1,
/obj/item/screwdriver = 3,
/obj/item/tank/internals/emergency_oxygen = 2,
/obj/item/vending_refill/cola = 1,
/obj/item/weldingtool = 3,
- /obj/item/wirecutters = 1,
+ /obj/item/wirecutters = 2,
/obj/item/wrench = 4,
- /obj/item/relic = 3,
- /obj/item/weaponcrafting/receiver = 2,
- /obj/item/clothing/head/cone = 2,
- /obj/item/grenade/smokebomb = 2,
+ /obj/item/weaponcrafting/receiver = 1,
/obj/item/geiger_counter = 3,
- /obj/item/reagent_containers/food/snacks/grown/citrus/orange = 1,
- /obj/item/radio/headset = 1,
+ /obj/item/reagent_containers/food/snacks/grown/citrus/orange = 5,
/obj/item/assembly/infra = 1,
/obj/item/assembly/igniter = 2,
/obj/item/assembly/signaler = 2,
- /obj/item/assembly/mousetrap = 2,
- /obj/item/reagent_containers/syringe = 2,
+ /obj/item/assembly/mousetrap = 5,
+ /obj/item/reagent_containers/syringe = 5,
/obj/item/clothing/gloves = 8,
- /obj/item/clothing/shoes/laceup = 1,
- /obj/item/storage/secure/briefcase = 3,
- /obj/item/storage/toolbox/artistic = 2,
- /obj/item/toy/eightball = 1,
- /obj/item/reagent_containers/pill/floorpill = 1,
- /obj/item/reagent_containers/food/snacks/cannedpeaches/maint = 2,
- /obj/item/clothing/shoes = 2)
- if(length == 5)
+ /obj/item/storage/toolbox = 2,
+ /obj/item/reagent_containers/pill = 2,
+ /obj/item/clothing/shoes = 8,
+ /obj/item/clothing/head = 3,
+ /obj/item/reagent_containers/food/snacks = 3,
+ /obj/item/reagent_containers/syringe/dart = 2,
+ /obj/item/reagent_containers/food/drinks/soda_cans = 5)
+ if(length >= 5)
return TRUE
//var/metalist = pickweight(GLOB.maintenance_loot)
for(var/i = length, i <= 5, i+=1)
@@ -144,5 +141,18 @@
if(!item)
i-=1
continue
+ for(var/obj/item_dupe in items_list) //No duplicates
+ if(item_dupe == item)
+ i-=1
+ continue
items_list += item
return TRUE
+
+/obj/item/pinpointer/jacq
+ name = "The Jacq-Tracq"
+ desc = "A handheld tracking device that locks onto witchy signals."
+
+/obj/item/pinpointer/jacq/attack_self(mob/living/user)
+ for(var/mob/living/simple_animal/jacq/J in GLOB.simple_animals[1])
+ target = J
+ ..()
diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm
index b2f69df2e4..f67c099309 100644
--- a/code/modules/holiday/halloween/jacqueen.dm
+++ b/code/modules/holiday/halloween/jacqueen.dm
@@ -40,18 +40,22 @@
speech_span = "spooky"
friendly = "pets"
response_help = "chats with"
+ light_range = 3
+ light_color = "#ff9842"
var/last_poof
var/progression = list() //Keep track of where people are in the story.
var/active = TRUE //Turn this to false to keep normal mob behavour
+ var/cached_z
/mob/living/simple_animal/jacq/Initialize()
..()
+ cached_z = z
poof()
/mob/living/simple_animal/jacq/Life()
..()
if(!ckey)
- if((last_poof+4 MINUTES) < world.realtime)
+ if((last_poof+3 MINUTES) < world.realtime)
poof()
/mob/living/simple_animal/jacq/Destroy() //I.e invincible
@@ -64,7 +68,7 @@
/mob/living/simple_animal/jacq/death() //What is alive may never die
visible_message("[src] cackles, \"You'll nae get rid a me that easily!\"")
playsound(loc, 'sound/spookoween/ahaha.ogg', 100, 0.25)
- health = 20
+ health = 25
poof()
/mob/living/simple_animal/jacq/attack_hand(mob/living/carbon/human/M)
@@ -91,20 +95,34 @@
last_poof = world.realtime
var/datum/reagents/R = new/datum/reagents(100)//Hey, just in case.
var/datum/effect_system/smoke_spread/chem/s = new()
- R.add_reagent("secretcatchem", (10))
+ R.add_reagent("secretcatchem", 10)
s.set_up(R, 0, loc)
s.start()
visible_message("[src] disappears in a puff of smoke!")
canmove = TRUE
+ health = 25
- var/hp_list = list()
- for(var/obj/machinery/holopad/hp in world)
- hp_list += hp
+ //Try to go to populated areas
+ var/list/pop_areas = list()
+ for(var/mob/living/L in GLOB.player_list)
+ var/area/A = get_area(L)
+ pop_areas += A
- var/obj/machinery/holopad/hp = pick(hp_list)
- if(forceMove(pick(hp.loc)))
- return TRUE
+ var/list/targets = list()
+ for(var/H in GLOB.network_holopads)
+ var/area/A = get_area(H)
+ if(findtextEx(A, "AI") || !(A in pop_areas) || !is_station_level(H))
+ continue
+ targets += H
+ if(!targets)
+ targets = GLOB.generic_event_spawns
+
+ for(var/i in 1 to 6) //Attempts a jump up to 6 times.
+ var/atom/A = pick(targets)
+ if(do_teleport(src, A, channel = TELEPORT_CHANNEL_MAGIC))
+ return TRUE
+ targets -= A
return FALSE
/mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C)
@@ -129,7 +147,7 @@
if(!progression["[C.real_name]"] || !(progression["[C.real_name]"] & JACQ_HELLO))
visible_message("[src] smiles ominously at [C], \"Well halo there [gender]! Ah'm Jacqueline, tae great Pumpqueen, great tae meet ye.\"")
sleep(20)
- visible_message("[src] continues, says, \"Ah'm sure yae well stunned, but ah've got nae taem fer that. Ah'm after the candies around this station. If yae get mae enoof o the wee buggers, Ah'll give ye a treat, or if yae feeling bold, Ah ken trick ye instead.\" giving [C] a wide grin.")
+ visible_message("[src] continues, \"Ah'm sure yae well stunned, but ah've got nae taem fer that. Ah'm after the candies around this station. If yae get mae enoof o the wee buggers, Ah'll give ye a treat, or if yae feeling bold, Ah ken trick ye instead.\" giving [C] a wide grin.")
if(!progression["[C.real_name]"])
progression["[C.real_name]"] = NONE //TO MAKE SURE THAT THE LIST ENTRY EXISTS.
@@ -153,11 +171,21 @@
/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.\"")
- var/choices_reward = list("Object - 3 candies", "Potion - 2 candies", "Plushie - 1 candy", "Can I ask you a question instead?")
+ 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/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!\"")
+ return
+ visible_message("[src] waves their arms around, \"Off comes your head, a pumpkin taking it's stead!\"")
+ C.reagents.add_reagent("pumpkinmutationtoxin", 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!\"")
@@ -169,7 +197,7 @@
// panic()
var/reward = new new_obj(C.loc)
C.put_in_hands(reward)
- visible_message("[src] waves her hands, magicing up a [reward] from thin air, \"There ye are [gender], enjoy! \"")
+ visible_message("[src] waves her hands, magicking up a [reward] from thin air, \"There ye are [gender], enjoy! \"")
sleep(20)
poof()
return
@@ -180,7 +208,7 @@
var/reward = new /obj/item/reagent_containers/potion_container(C.loc)
C.put_in_hands(reward)
- visible_message("[src] waves her hands, magicing up a [reward] from thin air, \"There ye are [gender], enjoy! \"")
+ visible_message("[src] waves her hands, magicking up a [reward] from thin air, \"There ye are [gender], enjoy! \"")
sleep(20)
poof()
return
@@ -190,13 +218,22 @@
return
new /obj/item/toy/plush/random(C.loc)
- visible_message("[src] waves her hands, magicing up a plushie from thin air, \"There ye are [gender], enjoy! \"")
+ visible_message("[src] waves her hands, magicking up a plushie from thin air, \"There ye are [gender], enjoy! \"")
+ sleep(20)
+ poof()
+ return
+ if("Jacqueline Tracker - 2 candies")
+ if(!take_candies(C, 2))
+ visible_message("[src] raises an eyebrow, \"It's 1 candy per plushie [gender]! Thems the rules!\"")
+ return
+ new /obj/item/pinpointer/jacq(C.loc)
+ visible_message("[src] waves her hands, magicking up a tracker from thin air, \"Feels weird to magic up a tracker fer meself but, here ye are [gender], enjoy! \"")
sleep(20)
poof()
return
//chitchats!
- if("Can I ask you a question instead?")
+ if("Can I get to know you instead?")
var/choices = list()
//Figure out where the C is in the story
if(!progression["[C.real_name]"]) //I really don't want to get here withoot a hello, but just to be safe
@@ -243,25 +280,21 @@
visible_message("[src] says, \"Ave ye tried them? They're full of all sorts of reagents. Ah'm after them so ah ken magic em up an hopefully find rare stuff fer me brews. Honestly it's a lot easier magicking up tatt fer ye lot than runnin aroond on me own like. I'd ask me familiars but most a my familiars are funny fellows 'n constantly bugger off on adventures when given simple objectives like; Go grab me a tea cake or watch over me cauldron. Ah mean, ye might run into Bartholomew my cat. Ee's supposed tae be tending my cauldron, but I've nae idea where ee's got tae.\"")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_CANDIES
sleep(30)
- poof()
if("You really came all this way for candy?")
- visible_message("[src] looks tae the side sheepishly, \"Aye, well, tae be honest, Ah'm here tae see me sis, but dunnae let her knew that. She's an alchemist too like, but she dunnae use a caldron like mae, she buggered off like tae her posh ivory tower tae learn bloody chemistry instead!\" [src] scowls, \"She's tae black sheep o' the family too, so we dunnae see eye tae eye sometimes on alchemy. Ah mean, she puts moles in her brews! Ye dunnae put moles in yer brews! Yae threw your brews at tae wee bastards an blew em up!\" [src] sighs, \"But she's a heart o gold so.. Ah wanted tae see her an check up oon her, make sure she's okay.\"")
+ visible_message("[src] l ooks tae the side sheepishly, \"Aye, well, tae be honest, Ah'm here tae see me sis, but dunnae let her knew that. She's an alchemist too like, but she dunnae use a caldron like mae, she buggered off like tae her posh ivory tower tae learn bloody chemistry instead!\" [src] scowls, \"She's tae black sheep o' the family too, so we dunnae see eye tae eye sometimes on alchemy. Ah mean, she puts moles in her brews! Ye dunnae put moles in yer brews! Yae threw your brews at tae wee bastards an blew em up!\" [src] sighs, \"But she's a heart o gold so.. Ah wanted tae see her an check up oon her, make sure she's okay.\"")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_FAR
sleep(30)
- poof()
if("What is that on your head?")
visible_message("[src] pats the pumpkin atop her head, \"This thing? This ain't nae ordinary pumpkin! Me Ma grew this monster ooer a year o love, dedication an hard work. Honestly it felt like she loved this thing more than any of us, which Ah knew ain't true an it's not like she was hartless or anything but.. well, we had a falling oot when Ah got back home with all me stuff in tow. An all she had done is sent me owl after owl over t' last year aboot this bloody pumpkin and ah had enough. So ah took it, an put it on me head. You know, as ye do. Ah am the great Pumpqueen after all, Ah deserve this.\"")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_HEAD
sleep(30)
- poof()
if("Are you a witch?")
visible_message("[src] grumbles, \"If ye must know, Ah got kicked oot of the witch academy fer being too much of a \"loose cannon\". A bloody loose cannon? Nae they were just pissed off Ah had the brass tae proclaim myself as the Pumpqueen! And also maybe the time Ah went and blew up one of the towers by trying tae make a huge batch of astrogen might've had something tae do with it. Ah mean it would've worked fine if the cauldrons weren't so shite and were actually upgraded by the faculty. So technically no, I'm not a witch.\"")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_WITCH
sleep(30)
- poof()
if("So you got ex-spell-ed?")
visible_message("[src] Gives you a blank look at the pun, before continuing, \"Not quite, Ah know Ah ken get back into the academy, it's only an explosion, they happen all the time, but, tae be fair it's my fault that things came tae their explosive climax. You don't know what it's like when you're after a witch doctorate, everyone else is doing well, everyone's making new spells and the like, and I'm just good at making explosions really, or fireworks. So, Ah did something Ah knew was dangerous, because Ah had tae do something tae stand oot, but Ah know this life ain't fer me, Ah don't want tae be locked up in dusty towers, grinding reagent after reagent together, trying tae find new reactions, some of the wizards in there haven't left fer years. Ah want tae live, Ah want tae fly around on a broom, turn people into cats fer a day and disappear cackling! That's what got me into witchcraft!\" she throws her arms up in the arm, spinning the pumpkin upon her head slightly. She carefully spins it back to face you, giving oot a soft sigh, \"Ah know my mother's obsession with this dumb thing on my head is just her trying tae fill the void of me and my sis moving oot, and it really shouldn't be on my head. And Ah know that I'm really here tae get help from my sis.. She's the sensible one, and she gives good hugs.\"")
@@ -269,11 +302,10 @@
visible_message("[src] says, \"Thanks [C], Ah guess Ah didn't realise Ah needed someone tae talk tae but, I'm glad ye spent all your candies talking tae me. Funny how things seem much worse in yer head.\"")
progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_EXPELL
sleep(30)
- poof()
if("Can I take you out on a date?")
visible_message("[src] blushes, \"...You want tae ask me oot on a date? Me? After all that nonsense Ah just said? It seems a waste of a candy honestly.\"")
- progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_DATE
+ //progression["[C.real_name]"] = progression["[C.real_name]"] | JACQ_DATE
visible_message("[src] looks to the side, deep in thought.")
dating_start(C, gender)
@@ -285,37 +317,34 @@
/mob/living/simple_animal/jacq/proc/trick(mob/living/carbon/C, gender)
var/option
if(ishuman(C))
- option = rand(1,7)
- else
option = rand(1,6)
+ else
+ option = rand(1,5)
switch(option)
if(1)
visible_message("[src] waves their arms around, \"Hocus pocus, making friends is now your focus!\"")
- var/datum/objective/brainwashing/objective = pick("Make a tasty sandwich for", "Compose a poem for", "Aquire a nice outfit to give to", "Strike up a conversation about pumpkins with", "Write a letter and deliver it to", "Give a nice hat to")
+ var/message = pick("make a tasty sandwich for", "compose a poem for", "aquire a nice outfit to give to", "strike up a conversation about pumpkins with", "write a letter and deliver it to", "give a nice hat to")
var/mob/living/L2 = pick(GLOB.player_list)
- objective += " [L2.name]."
- brainwash(C, objective)
+ message += " [L2.name]."
+ to_chat(C, " You feel an overwhelming desire to [message]")
if(2)
- visible_message("[src] waves their arms around, \"Off comes your head, a pumpkin taking it's stead!\"")
- C.reagents.add_reagent("pumpkinmutationtoxin", 5)
- if(3)
visible_message("[src] waves their arms around, \"If only you had a better upbringing, your ears are now full of my singing!\"")
var/client/C2 = C.client
- C2.chatOutput.sendMusic("https://a.uguu.se/rQ8FxxUQ1Xzc_SpOwOkyOwOkyPumpkinSong-PFrPrIxluWk.mp4", 1)//I hope this works!
- if(4)
+ C2.chatOutput.sendMusic("https://puu.sh/ExBbv.mp4", 1)//I hope this works!
+ if(3)
visible_message("[src] waves their arms around, \"You're cute little bumpkin, On your head is a pumpkin!\"")
if(C.head)
var/obj/item/W = C.head
C.dropItemToGround(W, TRUE)
var/jaqc_latern = new /obj/item/clothing/head/hardhat/pumpkinhead/jaqc
C.equip_to_slot(jaqc_latern, SLOT_HEAD, 1, 1)
- if(5)
+ if(4)
visible_message("[src] waves their arms around, \"In your body there's something amiss, you'll find it's a chem made by my sis!\"")
C.reagents.add_reagent("eigenstate", 30)
- if(6)
+ if(5)
visible_message("[src] waves their arms around, \"A new familiar for me, and you'll see it's thee!\"")
C.reagents.add_reagent("secretcatchem", 30)
- if(7)
+ if(6)
visible_message("[src] waves their arms around, \"While you may not be a ghost, for this sheet you'll always be it's host.\"")
var/mob/living/carbon/human/H = C
if(H.wear_suit)
diff --git a/code/modules/hydroponics/beekeeping/beekeeper_suit.dm b/code/modules/hydroponics/beekeeping/beekeeper_suit.dm
index 7fa1a0dd2c..fd9f879f5e 100644
--- a/code/modules/hydroponics/beekeeping/beekeeper_suit.dm
+++ b/code/modules/hydroponics/beekeeping/beekeeper_suit.dm
@@ -4,7 +4,7 @@
desc = "Keeps the lil buzzing buggers out of your eyes."
icon_state = "beekeeper"
item_state = "beekeeper"
- clothing_flags = THICKMATERIAL
+ clothing_flags = THICKMATERIAL | SNUG_FIT
/obj/item/clothing/suit/beekeeper_suit
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index 251d9de5c0..b25f76c1c8 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -11,7 +11,7 @@
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_dead = "banana-dead"
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
- mutatelist = list(/obj/item/seeds/banana/mime, /obj/item/seeds/banana/bluespace)
+ mutatelist = list(/obj/item/seeds/banana/mime, /obj/item/seeds/banana/bluespace, /obj/item/seeds/banana/exotic_banana)
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
/obj/item/reagent_containers/food/snacks/grown/banana
@@ -120,6 +120,41 @@
desc = "A peel from a bluespace banana."
icon_state = "banana_peel_blue"
+//Banana Spider.
+/obj/item/seeds/banana/exotic_banana
+ name = "pack of exotic banana seeds"
+ desc = "They're seeds that grow into banana trees. However, those bananas might be alive."
+ icon_state = "seed_exoticbanana"
+ species = "exoticbanana"
+ icon_grow = "banana-grow"
+ plantname = "Exotic Banana Tree"
+ product = /obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
+ mutatelist = list()
+ genes = list(/datum/plant_gene/trait/slip)
+
+/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
+ seed = /obj/item/seeds/banana/exotic_banana
+ name = "banana spider"
+ desc = "You do not know what it is, but you can bet the clown would love it."
+ icon_state = "exoticbanana"
+ list_reagents = list("nutriment" = 3, "vitamin" = 2)
+ foodtype = GROSS | MEAT | RAW | FRUIT
+ grind_results = list("blood" = 20, "liquidgibs" = 5)
+ var/awakening = 0
+
+/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable/attack_self(mob/user)
+ if(awakening || isspaceturf(user.loc))
+ return
+ to_chat(user, "You decide to wake up the banana spider...")
+ awakening = 1
+
+ spawn(30)
+ if(!QDELETED(src))
+ var/mob/living/simple_animal/banana_spider/S = new /mob/living/simple_animal/banana_spider(get_turf(src.loc))
+ S.speed += round(10 / seed.potency)
+ S.visible_message("The banana spider chitters as it stretches its legs.")
+ qdel(src)
+
// Other
/obj/item/grown/bananapeel/specialpeel //used by /obj/item/clothing/shoes/clown_shoes/banana_shoes
name = "synthesized banana peel"
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index eb463e5f6d..87db12d892 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -58,7 +58,20 @@
wine_power = 70 //Water to wine, baby.
wine_flavor = "divinity"
+/*
+/obj/item/reagent_containers/food/snacks/grown/holymelon/Initialize()
+ . = ..()
+ var/uses = 1
+ if(seed)
+ uses = round(seed.potency / 20)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_HANDS, uses, TRUE, CALLBACK(src, .proc/block_magic), CALLBACK(src, .proc/expire)) //deliver us from evil o melon god
-// /obj/item/reagent_containers/food/snacks/grown/holymelon/Initialize()
-// . = ..()
-// AddComponent(/datum/component/anti_magic, TRUE, TRUE) //deliver us from evil o melon god
+/obj/item/reagent_containers/food/snacks/grown/holymelon/proc/block_magic(mob/user, major)
+ if(major)
+ to_chat(user, "[src] hums slightly, and seems to decay a bit.")
+
+/obj/item/reagent_containers/food/snacks/grown/holymelon/proc/expire(mob/user)
+ to_chat(user, "[src] rapidly turns into ash!")
+ qdel(src)
+ new /obj/effect/decal/cleanable/ash(drop_location())
+*/
\ No newline at end of file
diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm
index 1ffdff2347..2119baf1a5 100644
--- a/code/modules/jobs/access.dm
+++ b/code/modules/jobs/access.dm
@@ -1,372 +1,372 @@
-
-//returns TRUE if this mob has sufficient access to use this object
-/obj/proc/allowed(mob/M)
- //check if it doesn't require any access at all
- if(src.check_access(null))
- return TRUE
- if(issilicon(M))
- if(ispAI(M))
- return FALSE
- return TRUE //AI can do whatever it wants
- if(IsAdminGhost(M))
- //Access can't stop the abuse
- return TRUE
- else if(istype(M) && SEND_SIGNAL(M, COMSIG_MOB_ALLOWED, src))
- return TRUE
- else if(ishuman(M))
- var/mob/living/carbon/human/H = M
- //if they are holding or wearing a card that has access, that works
- if(check_access(H.get_active_held_item()) || src.check_access(H.wear_id))
- return TRUE
- else if(ismonkey(M) || isalienadult(M))
- var/mob/living/carbon/george = M
- //they can only hold things :(
- if(check_access(george.get_active_held_item()))
- return TRUE
- else if(isanimal(M))
- var/mob/living/simple_animal/A = M
- if(check_access(A.get_active_held_item()) || check_access(A.access_card))
- return TRUE
- return FALSE
-
-/obj/item/proc/GetAccess()
- return list()
-
-/obj/item/proc/GetID()
- return null
-
-/obj/proc/text2access(access_text)
- . = list()
- if(!access_text)
- return
- var/list/split = splittext(access_text,";")
- for(var/x in split)
- var/n = text2num(x)
- if(n)
- . += n
-
-//Call this before using req_access or req_one_access directly
-/obj/proc/gen_access()
- //These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system.
- if(!req_access)
- req_access = list()
- for(var/a in text2access(req_access_txt))
- req_access += a
- if(!req_one_access)
- req_one_access = list()
- for(var/b in text2access(req_one_access_txt))
- req_one_access += b
-
-// Check if an item has access to this object
-/obj/proc/check_access(obj/item/I)
- return check_access_list(I ? I.GetAccess() : null)
-
-/obj/proc/check_access_list(list/access_list)
- gen_access()
-
- if(!islist(req_access)) //something's very wrong
- return TRUE
-
- if(!req_access.len && !length(req_one_access))
- return TRUE
-
- if(!length(access_list) || !islist(access_list))
- return FALSE
-
- for(var/req in req_access)
- if(!(req in access_list)) //doesn't have this access
- return FALSE
-
- if(length(req_one_access))
- for(var/req in req_one_access)
- if(req in access_list) //has an access from the single access list
- return TRUE
- return FALSE
- return TRUE
-
-/obj/proc/check_access_ntnet(datum/netdata/data)
- return check_access_list(data.passkey)
-
-/proc/get_centcom_access(job)
- switch(job)
- if("VIP Guest")
- return list(ACCESS_CENT_GENERAL)
- if("Custodian")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
- if("Thunderdome Overseer")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER)
- if("CentCom Official")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING)
- if("Medical Officer")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_MEDICAL)
- if("Death Commando")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
- if("Research Officer")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_TELEPORTER, ACCESS_CENT_STORAGE)
- if("Special Ops Officer")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
- if("Admiral")
- return get_all_centcom_access()
- if("CentCom Commander")
- return get_all_centcom_access()
- if("Emergency Response Team Commander")
- return get_ert_access("commander")
- if("Security Response Officer")
- return get_ert_access("sec")
- if("Engineer Response Officer")
- return get_ert_access("eng")
- if("Medical Response Officer")
- return get_ert_access("med")
- if("CentCom Bartender")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_BAR)
-
-/proc/get_all_accesses()
- return list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP,
- ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_MORGUE, ACCESS_RD,
- ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_CHEMISTRY, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_MAINT_TUNNELS,
- ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD,
- ACCESS_TELEPORTER, ACCESS_EVA, ACCESS_HEADS, ACCESS_CAPTAIN, ACCESS_ALL_PERSONAL_LOCKERS,
- ACCESS_TECH_STORAGE, ACCESS_CHAPEL_OFFICE, ACCESS_ATMOSPHERICS, ACCESS_KITCHEN,
- ACCESS_BAR, ACCESS_JANITOR, ACCESS_CREMATORIUM, ACCESS_ROBOTICS, ACCESS_CARGO, ACCESS_CONSTRUCTION,
- ACCESS_HYDROPONICS, ACCESS_LIBRARY, ACCESS_LAWYER, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_QM, ACCESS_SURGERY,
- ACCESS_THEATRE, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_MAILSORTING, ACCESS_WEAPONS,
- ACCESS_VAULT, ACCESS_MINING_STATION, ACCESS_XENOBIOLOGY, ACCESS_CE, ACCESS_HOP, ACCESS_HOS, ACCESS_RC_ANNOUNCE,
- ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM, ACCESS_MINISAT, ACCESS_NETWORK, ACCESS_CLONING)
-
-/proc/get_all_centcom_access()
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE, ACCESS_CENT_TELEPORTER, ACCESS_CENT_CAPTAIN)
-
-/proc/get_ert_access(class)
- switch(class)
- if("commander")
- return get_all_centcom_access()
- if("sec")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING)
- if("eng")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
- if("med")
- return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_LIVING)
-
-/proc/get_all_syndicate_access()
- return list(ACCESS_SYNDICATE, ACCESS_SYNDICATE)
-
-/proc/get_region_accesses(code)
- switch(code)
- if(0)
- return get_all_accesses()
- if(1) //station general
- return list(ACCESS_KITCHEN,ACCESS_BAR, ACCESS_HYDROPONICS, ACCESS_JANITOR, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_LIBRARY, ACCESS_THEATRE, ACCESS_LAWYER)
- if(2) //security
- return list(ACCESS_SEC_DOORS, ACCESS_WEAPONS, ACCESS_SECURITY, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_HOS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP,)
- if(3) //medbay
- return list(ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_SURGERY, ACCESS_CMO)
- if(4) //research
- return list(ACCESS_RESEARCH, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_GENETICS, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_MINISAT, ACCESS_RD, ACCESS_NETWORK)
- if(5) //engineering and maintenance
- return list(ACCESS_CONSTRUCTION, ACCESS_MAINT_TUNNELS, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_TECH_STORAGE, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINISAT, ACCESS_CE)
- if(6) //supply
- return list(ACCESS_MAILSORTING, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_CARGO, ACCESS_QM, ACCESS_VAULT)
- if(7) //command
- return list(ACCESS_HEADS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_TELEPORTER, ACCESS_EVA, ACCESS_GATEWAY, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_HOP, ACCESS_CAPTAIN, ACCESS_VAULT)
-
-/proc/get_region_accesses_name(code)
- switch(code)
- if(0)
- return "All"
- if(1) //station general
- return "General"
- if(2) //security
- return "Security"
- if(3) //medbay
- return "Medbay"
- if(4) //research
- return "Research"
- if(5) //engineering and maintenance
- return "Engineering"
- if(6) //supply
- return "Supply"
- if(7) //command
- return "Command"
-
-/proc/get_access_desc(A)
- switch(A)
- if(ACCESS_CARGO)
- return "Cargo Bay"
- if(ACCESS_CARGO_BOT)
- return "Delivery Chutes"
- if(ACCESS_SECURITY)
- return "Security"
- if(ACCESS_BRIG)
- return "Holding Cells"
- if(ACCESS_COURT)
- return "Courtroom"
- if(ACCESS_FORENSICS_LOCKERS)
- return "Forensics"
- if(ACCESS_MEDICAL)
- return "Medical"
- if(ACCESS_GENETICS)
- return "Genetics Lab"
- if(ACCESS_MORGUE)
- return "Morgue"
- if(ACCESS_TOX)
- return "R&D Lab"
- if(ACCESS_TOX_STORAGE)
- return "Toxins Lab"
- if(ACCESS_CHEMISTRY)
- return "Chemistry Lab"
- if(ACCESS_RD)
- return "RD Office"
- if(ACCESS_BAR)
- return "Bar"
- if(ACCESS_JANITOR)
- return "Custodial Closet"
- if(ACCESS_ENGINE)
- return "Engineering"
- if(ACCESS_ENGINE_EQUIP)
- return "Power and Engineering Equipment"
- if(ACCESS_MAINT_TUNNELS)
- return "Maintenance"
- if(ACCESS_EXTERNAL_AIRLOCKS)
- return "External Airlocks"
- if(ACCESS_EMERGENCY_STORAGE)
- return "Emergency Storage"
- if(ACCESS_CHANGE_IDS)
- return "ID Console"
- if(ACCESS_AI_UPLOAD)
- return "AI Chambers"
- if(ACCESS_TELEPORTER)
- return "Teleporter"
- if(ACCESS_EVA)
- return "EVA"
- if(ACCESS_HEADS)
- return "Bridge"
- if(ACCESS_CAPTAIN)
- return "Captain"
- if(ACCESS_ALL_PERSONAL_LOCKERS)
- return "Personal Lockers"
- if(ACCESS_CHAPEL_OFFICE)
- return "Chapel Office"
- if(ACCESS_TECH_STORAGE)
- return "Technical Storage"
- if(ACCESS_ATMOSPHERICS)
- return "Atmospherics"
- if(ACCESS_CREMATORIUM)
- return "Crematorium"
- if(ACCESS_ARMORY)
- return "Armory"
- if(ACCESS_CONSTRUCTION)
- return "Construction"
- if(ACCESS_KITCHEN)
- return "Kitchen"
- if(ACCESS_HYDROPONICS)
- return "Hydroponics"
- if(ACCESS_LIBRARY)
- return "Library"
- if(ACCESS_LAWYER)
- return "Law Office"
- if(ACCESS_ROBOTICS)
- return "Robotics"
- if(ACCESS_VIROLOGY)
- return "Virology"
- if(ACCESS_CMO)
- return "CMO Office"
- if(ACCESS_QM)
- return "Quartermaster"
- if(ACCESS_SURGERY)
- return "Surgery"
- if(ACCESS_THEATRE)
- return "Theatre"
- if(ACCESS_MANUFACTURING)
- return "Manufacturing"
- if(ACCESS_RESEARCH)
- return "Science"
- if(ACCESS_MINING)
- return "Mining"
- if(ACCESS_MINING_OFFICE)
- return "Mining Office"
- if(ACCESS_MAILSORTING)
- return "Cargo Office"
- if(ACCESS_MINT)
- return "Mint"
- if(ACCESS_MINT_VAULT)
- return "Mint Vault"
- if(ACCESS_VAULT)
- return "Main Vault"
- if(ACCESS_MINING_STATION)
- return "Mining EVA"
- if(ACCESS_XENOBIOLOGY)
- return "Xenobiology Lab"
- if(ACCESS_HOP)
- return "HoP Office"
- if(ACCESS_HOS)
- return "HoS Office"
- if(ACCESS_CE)
- return "CE Office"
- if(ACCESS_RC_ANNOUNCE)
- return "RC Announcements"
- if(ACCESS_KEYCARD_AUTH)
- return "Keycode Auth."
- if(ACCESS_TCOMSAT)
- return "Telecommunications"
- if(ACCESS_GATEWAY)
- return "Gateway"
- if(ACCESS_SEC_DOORS)
- return "Brig"
- if(ACCESS_ENTER_GENPOP)
- return "Prison Turnstile Entrance"
- if(ACCESS_LEAVE_GENPOP)
- return "Prison Turnstile Exit"
- if(ACCESS_MINERAL_STOREROOM)
- return "Mineral Storage"
- if(ACCESS_MINISAT)
- return "AI Satellite"
- if(ACCESS_WEAPONS)
- return "Weapon Permit"
- if(ACCESS_NETWORK)
- return "Network Access"
- if(ACCESS_CLONING)
- return "Cloning Room"
-
-/proc/get_centcom_access_desc(A)
- switch(A)
- if(ACCESS_CENT_GENERAL)
- return "Code Grey"
- if(ACCESS_CENT_THUNDER)
- return "Code Yellow"
- if(ACCESS_CENT_STORAGE)
- return "Code Orange"
- if(ACCESS_CENT_LIVING)
- return "Code Green"
- if(ACCESS_CENT_MEDICAL)
- return "Code White"
- if(ACCESS_CENT_TELEPORTER)
- return "Code Blue"
- if(ACCESS_CENT_SPECOPS)
- return "Code Black"
- if(ACCESS_CENT_CAPTAIN)
- return "Code Gold"
- if(ACCESS_CENT_BAR)
- return "Code Scotch"
-
-/proc/get_all_jobs()
- return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Cook", "Botanist", "Quartermaster", "Cargo Technician",
- "Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
- "Atmospheric Technician", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
- "Research Director", "Scientist", "Roboticist", "Head of Security", "Warden", "Detective", "Security Officer")
-
-/proc/get_all_job_icons() //For all existing HUD icons
- return get_all_jobs() + list("Prisoner")
-
-/proc/get_all_centcom_jobs()
- return list("VIP Guest","Custodian","Thunderdome Overseer","CentCom Official","Medical Officer","Death Commando","Research Officer","Special Ops Officer","Admiral","CentCom Commander","Emergency Response Team Commander","Security Response Officer","Engineer Response Officer", "Medical Response Officer","CentCom Bartender")
-
-/obj/item/proc/GetJobName() //Used in secHUD icon generation
- var/obj/item/card/id/I = GetID()
- if(!I)
- return
- var/jobName = I.assignment
- if(jobName in get_all_job_icons()) //Check if the job has a hud icon
- return jobName
- if(jobName in get_all_centcom_jobs()) //Return with the NT logo if it is a CentCom job
- return "CentCom"
- return "Unknown" //Return unknown if none of the above apply
+
+//returns TRUE if this mob has sufficient access to use this object
+/obj/proc/allowed(mob/M)
+ //check if it doesn't require any access at all
+ if(src.check_access(null))
+ return TRUE
+ if(issilicon(M))
+ if(ispAI(M))
+ return FALSE
+ return TRUE //AI can do whatever it wants
+ if(IsAdminGhost(M))
+ //Access can't stop the abuse
+ return TRUE
+ else if(istype(M) && SEND_SIGNAL(M, COMSIG_MOB_ALLOWED, src))
+ return TRUE
+ else if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ //if they are holding or wearing a card that has access, that works
+ if(check_access(H.get_active_held_item()) || src.check_access(H.wear_id))
+ return TRUE
+ else if(ismonkey(M) || isalienadult(M))
+ var/mob/living/carbon/george = M
+ //they can only hold things :(
+ if(check_access(george.get_active_held_item()))
+ return TRUE
+ else if(isanimal(M))
+ var/mob/living/simple_animal/A = M
+ if(check_access(A.get_active_held_item()) || check_access(A.access_card))
+ return TRUE
+ return FALSE
+
+/obj/item/proc/GetAccess()
+ return list()
+
+/obj/item/proc/GetID()
+ return null
+
+/obj/proc/text2access(access_text)
+ . = list()
+ if(!access_text)
+ return
+ var/list/split = splittext(access_text,";")
+ for(var/x in split)
+ var/n = text2num(x)
+ if(n)
+ . += n
+
+//Call this before using req_access or req_one_access directly
+/obj/proc/gen_access()
+ //These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system.
+ if(!req_access)
+ req_access = list()
+ for(var/a in text2access(req_access_txt))
+ req_access += a
+ if(!req_one_access)
+ req_one_access = list()
+ for(var/b in text2access(req_one_access_txt))
+ req_one_access += b
+
+// Check if an item has access to this object
+/obj/proc/check_access(obj/item/I)
+ return check_access_list(I ? I.GetAccess() : null)
+
+/obj/proc/check_access_list(list/access_list)
+ gen_access()
+
+ if(!islist(req_access)) //something's very wrong
+ return TRUE
+
+ if(!req_access.len && !length(req_one_access))
+ return TRUE
+
+ if(!length(access_list) || !islist(access_list))
+ return FALSE
+
+ for(var/req in req_access)
+ if(!(req in access_list)) //doesn't have this access
+ return FALSE
+
+ if(length(req_one_access))
+ for(var/req in req_one_access)
+ if(req in access_list) //has an access from the single access list
+ return TRUE
+ return FALSE
+ return TRUE
+
+/obj/proc/check_access_ntnet(datum/netdata/data)
+ return check_access_list(data.passkey)
+
+/proc/get_centcom_access(job)
+ switch(job)
+ if("VIP Guest")
+ return list(ACCESS_CENT_GENERAL)
+ if("Custodian")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
+ if("Thunderdome Overseer")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER)
+ if("CentCom Official")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING)
+ if("Medical Officer")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_MEDICAL)
+ if("Death Commando")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
+ if("Research Officer")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_TELEPORTER, ACCESS_CENT_STORAGE)
+ if("Special Ops Officer")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
+ if("Admiral")
+ return get_all_centcom_access()
+ if("CentCom Commander")
+ return get_all_centcom_access()
+ if("Emergency Response Team Commander")
+ return get_ert_access("commander")
+ if("Security Response Officer")
+ return get_ert_access("sec")
+ if("Engineer Response Officer")
+ return get_ert_access("eng")
+ if("Medical Response Officer")
+ return get_ert_access("med")
+ if("CentCom Bartender")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_BAR)
+
+/proc/get_all_accesses()
+ return list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP,
+ ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_MORGUE, ACCESS_RD,
+ ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_CHEMISTRY, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_MAINT_TUNNELS,
+ ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD,
+ ACCESS_TELEPORTER, ACCESS_EVA, ACCESS_HEADS, ACCESS_CAPTAIN, ACCESS_ALL_PERSONAL_LOCKERS,
+ ACCESS_TECH_STORAGE, ACCESS_CHAPEL_OFFICE, ACCESS_ATMOSPHERICS, ACCESS_KITCHEN,
+ ACCESS_BAR, ACCESS_JANITOR, ACCESS_CREMATORIUM, ACCESS_ROBOTICS, ACCESS_CARGO, ACCESS_CONSTRUCTION,
+ ACCESS_HYDROPONICS, ACCESS_LIBRARY, ACCESS_LAWYER, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_QM, ACCESS_SURGERY,
+ ACCESS_THEATRE, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_MAILSORTING, ACCESS_WEAPONS,
+ ACCESS_VAULT, ACCESS_MINING_STATION, ACCESS_XENOBIOLOGY, ACCESS_CE, ACCESS_HOP, ACCESS_HOS, ACCESS_RC_ANNOUNCE,
+ ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM, ACCESS_MINISAT, ACCESS_NETWORK, ACCESS_CLONING)
+
+/proc/get_all_centcom_access()
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_THUNDER, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE, ACCESS_CENT_TELEPORTER, ACCESS_CENT_CAPTAIN)
+
+/proc/get_ert_access(class)
+ switch(class)
+ if("commander")
+ return get_all_centcom_access()
+ if("sec")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING)
+ if("eng")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_LIVING, ACCESS_CENT_STORAGE)
+ if("med")
+ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_SPECOPS, ACCESS_CENT_MEDICAL, ACCESS_CENT_LIVING)
+
+/proc/get_all_syndicate_access()
+ return list(ACCESS_SYNDICATE, ACCESS_SYNDICATE)
+
+/proc/get_region_accesses(code)
+ switch(code)
+ if(0)
+ return get_all_accesses()
+ if(1) //station general
+ return list(ACCESS_KITCHEN,ACCESS_BAR, ACCESS_HYDROPONICS, ACCESS_JANITOR, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_LIBRARY, ACCESS_THEATRE, ACCESS_LAWYER)
+ if(2) //security
+ return list(ACCESS_SEC_DOORS, ACCESS_WEAPONS, ACCESS_SECURITY, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_HOS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP,)
+ if(3) //medbay
+ return list(ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_SURGERY, ACCESS_CMO)
+ if(4) //research
+ return list(ACCESS_RESEARCH, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_GENETICS, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_MINISAT, ACCESS_RD, ACCESS_NETWORK)
+ if(5) //engineering and maintenance
+ return list(ACCESS_CONSTRUCTION, ACCESS_MAINT_TUNNELS, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_TECH_STORAGE, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINISAT, ACCESS_CE)
+ if(6) //supply
+ return list(ACCESS_MAILSORTING, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_CARGO, ACCESS_QM, ACCESS_VAULT)
+ if(7) //command
+ return list(ACCESS_HEADS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_TELEPORTER, ACCESS_EVA, ACCESS_GATEWAY, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_HOP, ACCESS_CAPTAIN, ACCESS_VAULT)
+
+/proc/get_region_accesses_name(code)
+ switch(code)
+ if(0)
+ return "All"
+ if(1) //station general
+ return "General"
+ if(2) //security
+ return "Security"
+ if(3) //medbay
+ return "Medbay"
+ if(4) //research
+ return "Research"
+ if(5) //engineering and maintenance
+ return "Engineering"
+ if(6) //supply
+ return "Supply"
+ if(7) //command
+ return "Command"
+
+/proc/get_access_desc(A)
+ switch(A)
+ if(ACCESS_CARGO)
+ return "Cargo Bay"
+ if(ACCESS_CARGO_BOT)
+ return "Delivery Chutes"
+ if(ACCESS_SECURITY)
+ return "Security Equipment"
+ if(ACCESS_BRIG)
+ return "Holding Cells and Prisoner Management"
+ if(ACCESS_COURT)
+ return "Courtroom"
+ if(ACCESS_FORENSICS_LOCKERS)
+ return "Forensics Lockers"
+ if(ACCESS_MEDICAL)
+ return "Medical"
+ if(ACCESS_GENETICS)
+ return "Genetics Lab"
+ if(ACCESS_MORGUE)
+ return "Morgue"
+ if(ACCESS_TOX)
+ return "R&D Lab"
+ if(ACCESS_TOX_STORAGE)
+ return "Toxins Lab"
+ if(ACCESS_CHEMISTRY)
+ return "Chemistry Lab"
+ if(ACCESS_RD)
+ return "RD Office"
+ if(ACCESS_BAR)
+ return "Bar"
+ if(ACCESS_JANITOR)
+ return "Custodial Closet"
+ if(ACCESS_ENGINE)
+ return "Engineering"
+ if(ACCESS_ENGINE_EQUIP)
+ return "Power and Engineering Equipment"
+ if(ACCESS_MAINT_TUNNELS)
+ return "Maintenance"
+ if(ACCESS_EXTERNAL_AIRLOCKS)
+ return "External Airlocks"
+ if(ACCESS_EMERGENCY_STORAGE)
+ return "Emergency Storage"
+ if(ACCESS_CHANGE_IDS)
+ return "ID Console"
+ if(ACCESS_AI_UPLOAD)
+ return "AI Chambers"
+ if(ACCESS_TELEPORTER)
+ return "Teleporter"
+ if(ACCESS_EVA)
+ return "EVA"
+ if(ACCESS_HEADS)
+ return "Bridge and Command Equipment"
+ if(ACCESS_CAPTAIN)
+ return "Captain"
+ if(ACCESS_ALL_PERSONAL_LOCKERS)
+ return "Personal Lockers"
+ if(ACCESS_CHAPEL_OFFICE)
+ return "Chapel Office"
+ if(ACCESS_TECH_STORAGE)
+ return "Technical Storage"
+ if(ACCESS_ATMOSPHERICS)
+ return "Atmospherics"
+ if(ACCESS_CREMATORIUM)
+ return "Crematorium"
+ if(ACCESS_ARMORY)
+ return "Armory"
+ if(ACCESS_CONSTRUCTION)
+ return "Construction"
+ if(ACCESS_KITCHEN)
+ return "Kitchen"
+ if(ACCESS_HYDROPONICS)
+ return "Hydroponics"
+ if(ACCESS_LIBRARY)
+ return "Library"
+ if(ACCESS_LAWYER)
+ return "Law Office"
+ if(ACCESS_ROBOTICS)
+ return "Robotics"
+ if(ACCESS_VIROLOGY)
+ return "Virology"
+ if(ACCESS_CMO)
+ return "CMO Office"
+ if(ACCESS_QM)
+ return "Quartermaster"
+ if(ACCESS_SURGERY)
+ return "Surgery"
+ if(ACCESS_THEATRE)
+ return "Theatre"
+ if(ACCESS_MANUFACTURING)
+ return "Manufacturing"
+ if(ACCESS_RESEARCH)
+ return "Science"
+ if(ACCESS_MINING)
+ return "Mining"
+ if(ACCESS_MINING_OFFICE)
+ return "Mining Office"
+ if(ACCESS_MAILSORTING)
+ return "Cargo Office"
+ if(ACCESS_MINT)
+ return "Mint"
+ if(ACCESS_MINT_VAULT)
+ return "Mint Vault"
+ if(ACCESS_VAULT)
+ return "Main Vault"
+ if(ACCESS_MINING_STATION)
+ return "Mining EVA"
+ if(ACCESS_XENOBIOLOGY)
+ return "Xenobiology Lab"
+ if(ACCESS_HOP)
+ return "HoP Office"
+ if(ACCESS_HOS)
+ return "HoS Office"
+ if(ACCESS_CE)
+ return "CE Office"
+ if(ACCESS_RC_ANNOUNCE)
+ return "RC Announcements"
+ if(ACCESS_KEYCARD_AUTH)
+ return "Keycode Auth."
+ if(ACCESS_TCOMSAT)
+ return "Telecommunications"
+ if(ACCESS_GATEWAY)
+ return "Gateway"
+ if(ACCESS_SEC_DOORS)
+ return "Security SubDepartment Doors"
+ if(ACCESS_ENTER_GENPOP)
+ return "Prison Turnstile Entrance"
+ if(ACCESS_LEAVE_GENPOP)
+ return "Prison Turnstile Exit"
+ if(ACCESS_MINERAL_STOREROOM)
+ return "Mineral Storage"
+ if(ACCESS_MINISAT)
+ return "AI Satellite"
+ if(ACCESS_WEAPONS)
+ return "Weapon Permit"
+ if(ACCESS_NETWORK)
+ return "Network Access"
+ if(ACCESS_CLONING)
+ return "Cloning Room"
+
+/proc/get_centcom_access_desc(A)
+ switch(A)
+ if(ACCESS_CENT_GENERAL)
+ return "Code Grey"
+ if(ACCESS_CENT_THUNDER)
+ return "Code Yellow"
+ if(ACCESS_CENT_STORAGE)
+ return "Code Orange"
+ if(ACCESS_CENT_LIVING)
+ return "Code Green"
+ if(ACCESS_CENT_MEDICAL)
+ return "Code White"
+ if(ACCESS_CENT_TELEPORTER)
+ return "Code Blue"
+ if(ACCESS_CENT_SPECOPS)
+ return "Code Black"
+ if(ACCESS_CENT_CAPTAIN)
+ return "Code Gold"
+ if(ACCESS_CENT_BAR)
+ return "Code Scotch"
+
+/proc/get_all_jobs()
+ return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Cook", "Botanist", "Quartermaster", "Cargo Technician",
+ "Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
+ "Atmospheric Technician", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
+ "Research Director", "Scientist", "Roboticist", "Head of Security", "Warden", "Detective", "Security Officer")
+
+/proc/get_all_job_icons() //For all existing HUD icons
+ return get_all_jobs() + list("Prisoner")
+
+/proc/get_all_centcom_jobs()
+ return list("VIP Guest","Custodian","Thunderdome Overseer","CentCom Official","Medical Officer","Death Commando","Research Officer","Special Ops Officer","Admiral","CentCom Commander","Emergency Response Team Commander","Security Response Officer","Engineer Response Officer", "Medical Response Officer","CentCom Bartender")
+
+/obj/item/proc/GetJobName() //Used in secHUD icon generation
+ var/obj/item/card/id/I = GetID()
+ if(!I)
+ return
+ var/jobName = I.assignment
+ if(jobName in get_all_job_icons()) //Check if the job has a hud icon
+ return jobName
+ if(jobName in get_all_centcom_jobs()) //Return with the NT logo if it is a CentCom job
+ return "CentCom"
+ return "Unknown" //Return unknown if none of the above apply
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index 2eeffa8b7a..a52b8589c3 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -61,6 +61,9 @@
var/display_order = JOB_DISPLAY_ORDER_DEFAULT
+ //If a job complies with dresscodes, loadout items will not be equipped instead of the job's outfit, instead placing the items into the player's backpack.
+ var/dresscodecompliant = TRUE
+
//Only override this proc
//H is usually a human unless an /equip override transformed it
/datum/job/proc/after_spawn(mob/living/H, mob/M, latejoin = FALSE)
diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm
index c04560f849..da8c2aa3b9 100644
--- a/code/modules/jobs/job_types/assistant.dm
+++ b/code/modules/jobs/job_types/assistant.dm
@@ -15,6 +15,7 @@ Assistant
outfit = /datum/outfit/job/assistant
antag_rep = 7
display_order = JOB_DISPLAY_ORDER_ASSISTANT
+ dresscodecompliant = FALSE
/datum/job/assistant/get_access()
if(CONFIG_GET(flag/assistants_have_maint_access) || !CONFIG_GET(flag/jobs_have_minimal_access)) //Config has assistant maint access set
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 93775beca9..300fcc7109 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -15,7 +15,8 @@
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
+ minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ENGINE,
+ ACCESS_ENGINE_EQUIP, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN
/datum/outfit/job/atmos
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index fea8557b40..c6342e2154 100644
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -10,9 +10,9 @@
supervisors = "Nanotrasen officials and Space law"
selection_color = "#aac1ee"
req_admin_notify = 1
- minimal_player_age = 14
+ minimal_player_age = 20
exp_requirements = 180
- exp_type = EXP_TYPE_CREW
+ exp_type = EXP_TYPE_COMMAND
exp_type_department = EXP_TYPE_COMMAND
outfit = /datum/outfit/job/captain
diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm
index 3ceb29bae2..d6fbe5551f 100644
--- a/code/modules/jobs/job_types/cargo_technician.dm
+++ b/code/modules/jobs/job_types/cargo_technician.dm
@@ -11,7 +11,8 @@
outfit = /datum/outfit/job/cargo_tech
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING,
+ ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_CARGO, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM)
display_order = JOB_DISPLAY_ORDER_CARGO_TECHNICIAN
diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm
index a915d261ed..4614feba8d 100644
--- a/code/modules/jobs/job_types/chemist.dm
+++ b/code/modules/jobs/job_types/chemist.dm
@@ -32,5 +32,7 @@
satchel = /obj/item/storage/backpack/satchel/chem
duffelbag = /obj/item/storage/backpack/duffelbag/med
+ backpack_contents = list(/obj/item/storage/hypospraykit/regular)
+
chameleon_extras = /obj/item/gun/syringe
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index da3f281267..f6505a4e2a 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -11,7 +11,7 @@
supervisors = "the captain"
selection_color = "#ee7400"
req_admin_notify = 1
- minimal_player_age = 7
+ minimal_player_age = 10
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_ENGINEERING
diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm
index 4c7249f048..69eead70f7 100644
--- a/code/modules/jobs/job_types/chief_medical_officer.dm
+++ b/code/modules/jobs/job_types/chief_medical_officer.dm
@@ -11,7 +11,7 @@
supervisors = "the captain"
selection_color = "#509ed1"
req_admin_notify = 1
- minimal_player_age = 7
+ minimal_player_age = 10
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_MEDICAL
diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm
index e320ce20b4..2b757872d9 100644
--- a/code/modules/jobs/job_types/head_of_personnel.dm
+++ b/code/modules/jobs/job_types/head_of_personnel.dm
@@ -11,7 +11,7 @@
supervisors = "the captain"
selection_color = "#3a8529"
req_admin_notify = 1
- minimal_player_age = 10
+ minimal_player_age = 20
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SERVICE
@@ -21,13 +21,13 @@
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
- ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_LAWYER,
+ ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
- ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_LAWYER,
+ ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 33c8856d81..c190d88bc7 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -11,7 +11,7 @@
supervisors = "the captain"
selection_color = "#b90000"
req_admin_notify = 1
- minimal_player_age = 14
+ minimal_player_age = 10
exp_requirements = 300
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SECURITY
diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm
index 19fa1c7158..2a8814f29c 100644
--- a/code/modules/jobs/job_types/medical_doctor.dm
+++ b/code/modules/jobs/job_types/medical_doctor.dm
@@ -32,4 +32,6 @@
satchel = /obj/item/storage/backpack/satchel/med
duffelbag = /obj/item/storage/backpack/duffelbag/med
+ backpack_contents = list(/obj/item/storage/hypospraykit/regular)
+
chameleon_extras = /obj/item/gun/syringe
diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm
index 49a93026ba..ad57d05cdc 100644
--- a/code/modules/jobs/job_types/quartermaster.dm
+++ b/code/modules/jobs/job_types/quartermaster.dm
@@ -11,17 +11,19 @@
supervisors = "the captain"
selection_color = "#a06121"
req_admin_notify = 1
- minimal_player_age = 7
+ minimal_player_age = 10
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SUPPLY
outfit = /datum/outfit/job/quartermaster
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION,
- ACCESS_MINERAL_STOREROOM, ACCESS_VAULT)
- minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING,
- ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_VAULT)
+ access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING,
+ ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE,
+ ACCESS_SEC_DOORS, ACCESS_HEADS)
+ minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING,
+ ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE,
+ ACCESS_SEC_DOORS, ACCESS_HEADS)
display_order = JOB_DISPLAY_ORDER_QUARTERMASTER
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
@@ -31,11 +33,13 @@
jobtype = /datum/job/qm
belt = /obj/item/pda/quartermaster
- ears = /obj/item/radio/headset/headset_cargo
+ ears = /obj/item/radio/headset/heads/qm
uniform = /obj/item/clothing/under/rank/cargo
shoes = /obj/item/clothing/shoes/sneakers/brown
glasses = /obj/item/clothing/glasses/sunglasses
l_hand = /obj/item/clipboard
+ id = /obj/item/card/id/silver
+ backpack_contents = list(/obj/item/melee/classic_baton/telescopic = 1, /obj/item/modular_computer/tablet/preset/advanced = 1)
chameleon_extras = /obj/item/stamp/qm
diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm
index 5368ceee64..a90c5cea6c 100644
--- a/code/modules/jobs/job_types/research_director.dm
+++ b/code/modules/jobs/job_types/research_director.dm
@@ -11,7 +11,7 @@
supervisors = "the captain"
selection_color = "#7544cc"
req_admin_notify = 1
- minimal_player_age = 7
+ minimal_player_age = 10
exp_type_department = EXP_TYPE_SCIENCE
exp_requirements = 180
exp_type = EXP_TYPE_CREW
diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm
index ef16d8e53f..771fc02862 100644
--- a/code/modules/jobs/job_types/shaft_miner.dm
+++ b/code/modules/jobs/job_types/shaft_miner.dm
@@ -13,7 +13,8 @@
outfit = /datum/outfit/job/miner
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING,
+ ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM)
display_order = JOB_DISPLAY_ORDER_SHAFT_MINER
@@ -47,7 +48,7 @@
name = "Shaft Miner (Asteroid)"
uniform = /obj/item/clothing/under/rank/miner
shoes = /obj/item/clothing/shoes/workboots
-
+
/datum/outfit/job/miner/equipped
name = "Shaft Miner (Lavaland + Equipment)"
suit = /obj/item/clothing/suit/hooded/explorer/standard
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index 1787d13ee3..9c529f45f3 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -42,7 +42,7 @@
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
r_pocket = /obj/item/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
- suit_store = /obj/item/gun/energy/e_gun/advtaser
+ suit_store = /obj/item/gun/energy/pumpaction/defender
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 9b9d6dd3bb..e146f1686a 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -453,7 +453,7 @@
/obj/item/immortality_talisman/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, TRUE)
/datum/action/item_action/immortality
name = "Immortality"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 760fb7a29f..e77a91332e 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -468,3 +468,6 @@
bodyparts += BP
hand_bodyparts[i] = BP
..() //Don't redraw hands until we have organs for them
+
+/mob/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
+ return ..() && (user == src)
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index 19500653d9..d1ace36b8c 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -152,8 +152,7 @@
newcolor = BLOOD_COLOR_XENO
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
// but only for a few seconds
- spawn(30)
- remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, newcolor)
+ addtimer(CALLBACK(src, /atom/.proc/remove_atom_colour, TEMPORARY_COLOUR_PRIORITY, newcolor), 6 SECONDS)
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
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 323bd408cf..ef6a372f9e 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -95,8 +95,14 @@ Doesn't work on other aliens/AI.*/
var/mob/living/M = input("Select who to whisper to:","Whisper to?",null) as null|mob in options
if(!M)
return 0
+ if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.")
+ return FALSE
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
+ if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.")
+ return
log_directed_talk(user, M, msg, LOG_SAY, tag="alien whisper")
to_chat(M, "You hear a strange, alien voice in your head...[msg]")
to_chat(user, "You said: \"[msg]\" to [M]")
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 8e6c888c40..155b0fc7de 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -36,7 +36,7 @@
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
- if(. && mob_has_gravity()) //floating is easy
+ if(. && (movement_type & FLOATING)) //floating is easy
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
nutrition = NUTRITION_LEVEL_FED - 1 //just less than feeling vigorous
else if(nutrition && stat != DEAD)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0e6ac72abf..a737844f10 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -488,7 +488,7 @@
var/counter = 1
while(R.fields[text("com_[]", counter)])
counter++
- R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []
[]", allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
+ R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []
[]", allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
to_chat(usr, "Successfully added comment.")
return
to_chat(usr, "Unable to locate a data core entry for this person.")
@@ -946,7 +946,7 @@
return FALSE
/mob/living/carbon/human/proc/clear_shove_slowdown()
- remove_movespeed_modifier(SHOVE_SLOWDOWN_ID)
+ remove_movespeed_modifier(MOVESPEED_ID_SHOVE)
var/active_item = get_active_held_item()
if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
visible_message("[src.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE)
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index d35df6b789..084dbd83ef 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -79,7 +79,8 @@
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
- if(!..()) //a check failed or the item has already found its slot
+ . = ..()
+ if(!.) //a check failed or the item has already found its slot
return
var/not_handled = FALSE //Added in case we make this type path deeper one day
@@ -136,6 +137,7 @@
update_inv_s_store()
else
to_chat(src, "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!")
+ not_handled = TRUE
//Item is handled and in slot, valid to call callback, for this proc should always be true
if(!not_handled)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 9395283aeb..be52a8289b 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -18,7 +18,7 @@
#define THERMAL_PROTECTION_HAND_LEFT 0.025
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
-/mob/living/carbon/human/Life()
+/mob/living/carbon/human/Life(seconds, times_fired)
set invisibility = 0
if (notransform)
return
@@ -41,7 +41,7 @@
if(stat != DEAD)
//process your dick energy
- handle_arousal()
+ handle_arousal(times_fired)
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm
index ac9e9fe219..4d411deb53 100644
--- a/code/modules/mob/living/carbon/human/physiology.dm
+++ b/code/modules/mob/living/carbon/human/physiology.dm
@@ -21,8 +21,6 @@
var/bleed_mod = 1 // % bleeding modifier
var/datum/armor/armor // internal armor datum
- var/speed_mod = 0 //tick modifier for each step. Positive is slower, negative is faster.
-
var/hunger_mod = 1 //% of hunger rate taken per tick.
var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations.
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index f9b4654793..025e933356 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -332,6 +332,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if("meat_type" in default_features) //I can't believe it's come to the meat
H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]]
+ C.add_movespeed_modifier(MOVESPEED_ID_SPECIES, TRUE, 100, override=TRUE, multiplicative_slowdown=speedmod, movetypes=(~FLYING))
+
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
@@ -348,6 +350,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/X in inherent_traits)
REMOVE_TRAIT(C, X, SPECIES_TRAIT)
+ C.remove_movespeed_modifier(MOVESPEED_ID_SPECIES)
+
if("meat_type" in default_features)
C.type_of_meat = GLOB.meat_types[C.dna.features["meat_type"]]
else
@@ -541,7 +545,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_underwear)
H.underwear = "Nude"
else
- H.saved_underwear = H.underwear
+ H.underwear = H.saved_underwear
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
if(B)
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER)
@@ -553,7 +557,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_undershirt)
H.undershirt = "Nude"
else
- H.saved_undershirt = H.undershirt
+ H.undershirt = H.saved_undershirt
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
if(T)
var/mutable_appearance/MA
@@ -569,7 +573,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_socks)
H.socks = "Nude"
else
- H.saved_socks = H.socks
+ H.socks = H.saved_socks
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
if(S)
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
@@ -1389,39 +1393,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/movement_delay(mob/living/carbon/human/H)
. = 0 //We start at 0.
var/flight = 0 //Check for flight and flying items
- var/ignoreslow = 0
var/gravity = 0
if(H.movement_type & FLYING)
flight = 1
gravity = H.has_gravity()
- if(gravity && !flight) //Check for chemicals and innate speedups and slowdowns if we're on the ground
- if(HAS_TRAIT(H, TRAIT_GOTTAGOFAST))
- . -= 1
- if(HAS_TRAIT(H, TRAIT_GOTTAGOREALLYFAST))
- . -= 2
- . += speedmod
- . += H.physiology.speed_mod
-
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
. -= 1.5
- if(HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN))
- ignoreslow = 1
-
- if(!gravity)
- var/obj/item/tank/jetpack/J = H.back
- var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit
- var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot(ORGAN_SLOT_THRUSTERS)
- if(!istype(J) && istype(C))
- J = C.jetpack
- if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
- . -= 0.4
- else if(istype(T) && T.allow_thrust(0.01, H))
- . -= 0.4
-
- if(!ignoreslow && gravity)
+ if(!HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN) && gravity)
if(H.wear_suit)
. += H.wear_suit.slowdown
if(H.shoes)
@@ -1448,16 +1429,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/grav_force = min(gravity - STANDARD_GRAVITY,3)
. += 1 + grav_force
- var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
- if(mood && !flight) //How can depression slow you down if you can just fly away from your problems?
- switch(mood.sanity)
- if(SANITY_INSANE to SANITY_CRAZY)
- . += 1.5
- if(SANITY_CRAZY to SANITY_UNSTABLE)
- . += 1
- if(SANITY_UNSTABLE to SANITY_DISTURBED)
- . += 0.5
-
if(HAS_TRAIT(H, TRAIT_FAT))
. += (1.5 - flight)
if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
@@ -1940,8 +1911,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/knocked_item = FALSE
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
- if(!target.has_movespeed_modifier(SHOVE_SLOWDOWN_ID))
- target.add_movespeed_modifier(SHOVE_SLOWDOWN_ID, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
+ if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
+ target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(target_held_item)
target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!",
"Your grip on \the [target_held_item] loosens!", null, COMBAT_MESSAGE_RANGE)
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index c1c848106c..7669a8c740 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -29,7 +29,7 @@
if(fly)
fly.Remove(H)
if(H.movement_type & FLYING)
- H.movement_type &= ~FLYING
+ H.setMovetype(H.movement_type & ~FLYING)
ToggleFlight(H,0)
if(H.dna && H.dna.species && (H.dna.features["wings"] == "Angel"))
if("wings" in H.dna.species.mutant_bodyparts)
@@ -132,14 +132,14 @@
if(flight && CanFly(H))
stunmod = 2
speedmod = -0.35
- H.movement_type |= FLYING
+ H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
H.pass_flags |= PASSTABLE
H.OpenWings()
else
stunmod = 1
speedmod = 0
- H.movement_type &= ~FLYING
+ H.setMovetype(H.movement_type & ~FLYING)
override_float = FALSE
H.pass_flags &= ~PASSTABLE
H.CloseWings()
\ No newline at end of file
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 f416854838..71eaa5ae22 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -472,37 +472,25 @@
H.hair_style = new_style
H.update_hair()
else if (select_alteration == "Genitals")
- var/list/organs = list()
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel")
switch(operation)
if("add sexual organ")
- var/new_organ = input("Select sexual organ:", "Organ Manipulation") in list("Penis", "Testicles", "Breasts", "Vagina", "Womb", "Cancel")
- if(new_organ == "Penis")
- H.give_penis()
- else if(new_organ == "Testicles")
- H.give_balls()
- else if(new_organ == "Breasts")
- H.give_breasts()
- else if(new_organ == "Vagina")
- H.give_vagina()
- else if(new_organ == "Womb")
- H.give_womb()
- else
+ var/new_organ = input("Select sexual organ:", "Organ Manipulation") as null|anything in GLOB.genitals_list
+ if(!new_organ)
return
+ H.give_genital(GLOB.genitals_list[new_organ])
+
if("remove sexual organ")
+ var/list/organs = list()
for(var/obj/item/organ/genital/X in H.internal_organs)
var/obj/item/organ/I = X
organs["[I.name] ([I.type])"] = I
- var/obj/item/organ = input("Select sexual organ:", "Organ Manipulation", null) in organs
- organ = organs[organ]
- if(!organ)
+ var/obj/item/O = input("Select sexual organ:", "Organ Manipulation", null) as null|anything in organs
+ var/obj/item/organ/genital/G = organs[O]
+ if(!G)
return
- var/obj/item/organ/genital/O
- if(isorgan(organ))
- O = organ
- O.Remove(H)
- organ.forceMove(get_turf(H))
- qdel(organ)
+ G.forceMove(get_turf(H))
+ qdel(G)
H.update_genitals()
else if (select_alteration == "Ears")
@@ -592,8 +580,8 @@
if(new_shape)
H.dna.features["cock_shape"] = new_shape
H.update_genitals()
- H.give_balls()
- H.give_penis()
+ H.give_genital(/obj/item/organ/genital/testicles)
+ H.give_genital(/obj/item/organ/genital/penis)
H.apply_overlay()
@@ -605,8 +593,8 @@
if(new_shape)
H.dna.features["vag_shape"] = new_shape
H.update_genitals()
- H.give_womb()
- H.give_vagina()
+ H.give_genital(/obj/item/organ/genital/womb)
+ H.give_genital(/obj/item/organ/genital/vagina)
H.apply_overlay()
else if (select_alteration == "Penis Length")
@@ -618,8 +606,8 @@
H.dna.features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN)
H.update_genitals()
H.apply_overlay()
- H.give_balls()
- H.give_penis()
+ H.give_genital(/obj/item/organ/genital/testicles)
+ H.give_genital(/obj/item/organ/genital/penis)
else if (select_alteration == "Breast Size")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
@@ -630,7 +618,7 @@
H.dna.features["breasts_size"] = new_size
H.update_genitals()
H.apply_overlay()
- H.give_breasts()
+ H.give_genital(/obj/item/organ/genital/breasts)
else if (select_alteration == "Breast Shape")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
@@ -641,7 +629,7 @@
H.dna.features["breasts_shape"] = new_shape
H.update_genitals()
H.apply_overlay()
- H.give_breasts()
+ H.give_genital(/obj/item/organ/genital/breasts)
else
return
@@ -856,6 +844,8 @@
return FALSE
if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) //mindshield implant, no dice
return FALSE
+ if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ return FALSE
if(M in linked_mobs)
return FALSE
linked_mobs.Add(M)
@@ -941,9 +931,14 @@
var/mob/living/M = input("Select who to send your message to:","Send thought to?",null) as null|mob in options
if(!M)
return
-
+ if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(H, "As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.")
+ return
var/msg = sanitize(input("Message:", "Telepathy") as text|null)
if(msg)
+ if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(H, "As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.")
+ return
log_directed_talk(H, M, msg, LOG_SAY, "slime telepathy")
to_chat(M, "You hear an alien voice in your head... [msg]")
to_chat(H, "You telepathically said: \"[msg]\" to [M]")
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 53c6f1bd0f..7462d26ea6 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -45,14 +45,14 @@
C.adjustOxyLoss(-4)
C.adjustCloneLoss(-4)
return
- C.blood_volume -= 0.75
+ C.blood_volume -= 0.75 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
if(C.blood_volume <= (BLOOD_VOLUME_SURVIVE*C.blood_ratio))
to_chat(C, "You ran out of blood!")
C.dust()
var/area/A = get_area(C)
if(istype(A, /area/chapel))
to_chat(C, "You don't belong here!")
- C.adjustFireLoss(20)
+ C.adjustFireLoss(5)
C.adjust_fire_stacks(6)
C.IgniteMob()
@@ -88,7 +88,7 @@
to_chat(H, "[victim] doesn't have blood!")
return
V.drain_cooldown = world.time + 30
- if(victim.anti_magic_check(FALSE, TRUE))
+ 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
@@ -141,7 +141,7 @@
H = new(shape,src,caster)
if(istype(H, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = H
- if(ventcrawl_nude_only && length(caster.get_equipped_items(include_pockets = TRUE)))
+ if((caster.blood_volume >= (BLOOD_VOLUME_BAD*caster.blood_ratio)) || (ventcrawl_nude_only && length(caster.get_equipped_items(include_pockets = TRUE))))
SA.ventcrawler = FALSE
if(transfer_name)
H.name = caster.name
diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm
index a1dce4fb0f..c50677c54c 100644
--- a/code/modules/mob/living/carbon/human/species_types/zombies.dm
+++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm
@@ -66,7 +66,7 @@
playsound(C, pick(spooks), 50, TRUE, 10)
//Congrats you somehow died so hard you stopped being a zombie
-/datum/species/zombie/infectious/spec_death(mob/living/carbon/C)
+/datum/species/zombie/infectious/spec_death(gibbed, mob/living/carbon/C)
. = ..()
var/obj/item/organ/zombie_infection/infection
infection = C.getorganslot(ORGAN_SLOT_ZOMBIE)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 5b18e95235..ca139cace7 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -98,7 +98,7 @@
var/datum/gas_mixture/breath
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
- if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || lungs.organ_flags & ORGAN_FAILING)
+ if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || !lungs || lungs.organ_flags & ORGAN_FAILING)
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
else if(health <= crit_threshold)
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index 63a83ac96b..66be8058f1 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -23,7 +23,7 @@
if(changed)
animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
- floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
+ setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
/mob/living/carbon
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 201e5fea24..2bf17bc265 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -4,7 +4,7 @@
if(digitalinvis)
handle_diginvis() //AI becomes unable to see mob
- if((movement_type & FLYING) && !floating) //TODO: Better floating
+ if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
float(on = TRUE)
if (client)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index d249cd1a61..e893426ee9 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -716,14 +716,14 @@
var/fixed = 0
if(anchored || (buckled && buckled.anchored))
fixed = 1
- if(on && !floating && !fixed)
+ if(on && !(movement_type & FLOATING) && !fixed)
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
sleep(10)
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
- floating = TRUE
- else if(((!on || fixed) && floating))
+ setMovetype(movement_type | FLOATING)
+ else if(((!on || fixed) && (movement_type & FLOATING)))
animate(src, pixel_y = get_standard_pixel_y_offset(lying), time = 10)
- floating = FALSE
+ setMovetype(movement_type & ~FLOATING)
// The src mob is trying to strip an item from someone
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
@@ -795,7 +795,7 @@
var/final_pixel_y = get_standard_pixel_y_offset(lying)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2)
- floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
+ setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
var/loc_temp = environment ? environment.temperature : T0C
@@ -935,7 +935,7 @@
apply_effect((amount*RAD_MOB_COEFFICIENT)/max(1, (radiation**2)*RAD_OVERDOSE_REDUCTION), EFFECT_IRRADIATE, blocked)
-/mob/living/anti_magic_check(magic = TRUE, holy = FALSE)
+/mob/living/anti_magic_check(magic = TRUE, holy = FALSE, chargecost = 1, self = FALSE)
. = ..()
if(.)
return
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 9d04f288cd..93e64fd4cc 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -422,4 +422,4 @@
if(!used_item)
used_item = get_active_held_item()
..()
- floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
+ setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
diff --git a/code/modules/mob/living/silicon/ai/vox_sounds.dm b/code/modules/mob/living/silicon/ai/vox_sounds.dm
index eb6d0ce991..50a808032d 100644
--- a/code/modules/mob/living/silicon/ai/vox_sounds.dm
+++ b/code/modules/mob/living/silicon/ai/vox_sounds.dm
@@ -975,4 +975,635 @@ GLOBAL_LIST_INIT(vox_sounds, list("abduction" = 'sound/vox_fem/abduction.ogg',
"zombie" = 'sound/vox_fem/zombie.ogg',
"zone" = 'sound/vox_fem/zone.ogg',
"zulu" = 'sound/vox_fem/zulu.ogg'))
+
+//for vim
+// :%s/\(\(.*\)\.ogg\)/"\2" = 'sound\/vox\/\1',/g
+GLOBAL_LIST_INIT(vox_sounds_male, list("," = 'sound/vox/_comma.ogg',
+"." = 'sound/vox/_period.ogg',
+"a" = 'sound/vox/a.ogg',
+"accelerating" = 'sound/vox/accelerating.ogg',
+"accelerator" = 'sound/vox/accelerator.ogg',
+"accepted" = 'sound/vox/accepted.ogg',
+"access" = 'sound/vox/access.ogg',
+"acknowledge" = 'sound/vox/acknowledge.ogg',
+"acknowledged" = 'sound/vox/acknowledged.ogg',
+"acquired" = 'sound/vox/acquired.ogg',
+"acquisition" = 'sound/vox/acquisition.ogg',
+"across" = 'sound/vox/across.ogg',
+"activate" = 'sound/vox/activate.ogg',
+"activated" = 'sound/vox/activated.ogg',
+"activity" = 'sound/vox/activity.ogg',
+"adios" = 'sound/vox/adios.ogg',
+"administration" = 'sound/vox/administration.ogg',
+"advanced" = 'sound/vox/advanced.ogg',
+"after" = 'sound/vox/after.ogg',
+"agent" = 'sound/vox/agent.ogg',
+"alarm" = 'sound/vox/alarm.ogg',
+"alert" = 'sound/vox/alert.ogg',
+"alien" = 'sound/vox/alien.ogg',
+"aligned" = 'sound/vox/aligned.ogg',
+"all" = 'sound/vox/all.ogg',
+"alpha" = 'sound/vox/alpha.ogg',
+"am" = 'sound/vox/am.ogg',
+"amigo" = 'sound/vox/amigo.ogg',
+"ammunition" = 'sound/vox/ammunition.ogg',
+"an" = 'sound/vox/an.ogg',
+"and" = 'sound/vox/and.ogg',
+"announcement" = 'sound/vox/announcement.ogg',
+"anomalous" = 'sound/vox/anomalous.ogg',
+"antenna" = 'sound/vox/antenna.ogg',
+"any" = 'sound/vox/any.ogg',
+"apprehend" = 'sound/vox/apprehend.ogg',
+"approach" = 'sound/vox/approach.ogg',
+"are" = 'sound/vox/are.ogg',
+"area" = 'sound/vox/area.ogg',
+"arm" = 'sound/vox/arm.ogg',
+"armed" = 'sound/vox/armed.ogg',
+"armor" = 'sound/vox/armor.ogg',
+"armory" = 'sound/vox/armory.ogg',
+"arrest" = 'sound/vox/arrest.ogg',
+"ass" = 'sound/vox/ass.ogg',
+"at" = 'sound/vox/at.ogg',
+"atomic" = 'sound/vox/atomic.ogg',
+"attention" = 'sound/vox/attention.ogg',
+"authorize" = 'sound/vox/authorize.ogg',
+"authorized" = 'sound/vox/authorized.ogg',
+"automatic" = 'sound/vox/automatic.ogg',
+"away" = 'sound/vox/away.ogg',
+"b" = 'sound/vox/b.ogg',
+"back" = 'sound/vox/back.ogg',
+"backman" = 'sound/vox/backman.ogg',
+"bad" = 'sound/vox/bad.ogg',
+"bag" = 'sound/vox/bag.ogg',
+"bailey" = 'sound/vox/bailey.ogg',
+"barracks" = 'sound/vox/barracks.ogg',
+"base" = 'sound/vox/base.ogg',
+"bay" = 'sound/vox/bay.ogg',
+"be" = 'sound/vox/be.ogg',
+"been" = 'sound/vox/been.ogg',
+"before" = 'sound/vox/before.ogg',
+"beyond" = 'sound/vox/beyond.ogg',
+"biohazard" = 'sound/vox/biohazard.ogg',
+"biological" = 'sound/vox/biological.ogg',
+"birdwell" = 'sound/vox/birdwell.ogg',
+"bizwarn" = 'sound/vox/bizwarn.ogg',
+"black" = 'sound/vox/black.ogg',
+"blast" = 'sound/vox/blast.ogg',
+"blocked" = 'sound/vox/blocked.ogg',
+"bloop" = 'sound/vox/bloop.ogg',
+"blue" = 'sound/vox/blue.ogg',
+"bottom" = 'sound/vox/bottom.ogg',
+"bravo" = 'sound/vox/bravo.ogg',
+"breach" = 'sound/vox/breach.ogg',
+"breached" = 'sound/vox/breached.ogg',
+"break" = 'sound/vox/break.ogg',
+"bridge" = 'sound/vox/bridge.ogg',
+"bust" = 'sound/vox/bust.ogg',
+"but" = 'sound/vox/but.ogg',
+"button" = 'sound/vox/button.ogg',
+"buzwarn" = 'sound/vox/buzwarn.ogg',
+"bypass" = 'sound/vox/bypass.ogg',
+"c" = 'sound/vox/c.ogg',
+"cable" = 'sound/vox/cable.ogg',
+"call" = 'sound/vox/call.ogg',
+"called" = 'sound/vox/called.ogg',
+"canal" = 'sound/vox/canal.ogg',
+"cap" = 'sound/vox/cap.ogg',
+"captain" = 'sound/vox/captain.ogg',
+"capture" = 'sound/vox/capture.ogg',
+"captured" = 'sound/vox/captured.ogg',
+"ceiling" = 'sound/vox/ceiling.ogg',
+"celsius" = 'sound/vox/celsius.ogg',
+"center" = 'sound/vox/center.ogg',
+"centi" = 'sound/vox/centi.ogg',
+"central" = 'sound/vox/central.ogg',
+"chamber" = 'sound/vox/chamber.ogg',
+"charlie" = 'sound/vox/charlie.ogg',
+"check" = 'sound/vox/check.ogg',
+"checkpoint" = 'sound/vox/checkpoint.ogg',
+"chemical" = 'sound/vox/chemical.ogg',
+"cleanup" = 'sound/vox/cleanup.ogg',
+"clear" = 'sound/vox/clear.ogg',
+"clearance" = 'sound/vox/clearance.ogg',
+"close" = 'sound/vox/close.ogg',
+"clown" = 'sound/vox/clown.ogg',
+"code" = 'sound/vox/code.ogg',
+"coded" = 'sound/vox/coded.ogg',
+"collider" = 'sound/vox/collider.ogg',
+"command" = 'sound/vox/command.ogg',
+"communication" = 'sound/vox/communication.ogg',
+"complex" = 'sound/vox/complex.ogg',
+"computer" = 'sound/vox/computer.ogg',
+"condition" = 'sound/vox/condition.ogg',
+"containment" = 'sound/vox/containment.ogg',
+"contamination" = 'sound/vox/contamination.ogg',
+"control" = 'sound/vox/control.ogg',
+"coolant" = 'sound/vox/coolant.ogg',
+"coomer" = 'sound/vox/coomer.ogg',
+"core" = 'sound/vox/core.ogg',
+"correct" = 'sound/vox/correct.ogg',
+"corridor" = 'sound/vox/corridor.ogg',
+"crew" = 'sound/vox/crew.ogg',
+"cross" = 'sound/vox/cross.ogg',
+"cryogenic" = 'sound/vox/cryogenic.ogg',
+"d" = 'sound/vox/d.ogg',
+"dadeda" = 'sound/vox/dadeda.ogg',
+"damage" = 'sound/vox/damage.ogg',
+"damaged" = 'sound/vox/damaged.ogg',
+"danger" = 'sound/vox/danger.ogg',
+"day" = 'sound/vox/day.ogg',
+"deactivated" = 'sound/vox/deactivated.ogg',
+"decompression" = 'sound/vox/decompression.ogg',
+"decontamination" = 'sound/vox/decontamination.ogg',
+"deeoo" = 'sound/vox/deeoo.ogg',
+"defense" = 'sound/vox/defense.ogg',
+"degrees" = 'sound/vox/degrees.ogg',
+"delta" = 'sound/vox/delta.ogg',
+"denied" = 'sound/vox/denied.ogg',
+"deploy" = 'sound/vox/deploy.ogg',
+"deployed" = 'sound/vox/deployed.ogg',
+"destroy" = 'sound/vox/destroy.ogg',
+"destroyed" = 'sound/vox/destroyed.ogg',
+"detain" = 'sound/vox/detain.ogg',
+"detected" = 'sound/vox/detected.ogg',
+"detonation" = 'sound/vox/detonation.ogg',
+"device" = 'sound/vox/device.ogg',
+"did" = 'sound/vox/did.ogg',
+"die" = 'sound/vox/die.ogg',
+"dimensional" = 'sound/vox/dimensional.ogg',
+"dirt" = 'sound/vox/dirt.ogg',
+"disengaged" = 'sound/vox/disengaged.ogg',
+"dish" = 'sound/vox/dish.ogg',
+"disposal" = 'sound/vox/disposal.ogg',
+"distance" = 'sound/vox/distance.ogg',
+"distortion" = 'sound/vox/distortion.ogg',
+"do" = 'sound/vox/do.ogg',
+"doctor" = 'sound/vox/doctor.ogg',
+"doop" = 'sound/vox/doop.ogg',
+"door" = 'sound/vox/door.ogg',
+"down" = 'sound/vox/down.ogg',
+"dual" = 'sound/vox/dual.ogg',
+"duct" = 'sound/vox/duct.ogg',
+"e" = 'sound/vox/e.ogg',
+"east" = 'sound/vox/east.ogg',
+"echo" = 'sound/vox/echo.ogg',
+"ed" = 'sound/vox/ed.ogg',
+"effect" = 'sound/vox/effect.ogg',
+"egress" = 'sound/vox/egress.ogg',
+"eight" = 'sound/vox/eight.ogg',
+"eighteen" = 'sound/vox/eighteen.ogg',
+"eighty" = 'sound/vox/eighty.ogg',
+"electric" = 'sound/vox/electric.ogg',
+"electromagnetic" = 'sound/vox/electromagnetic.ogg',
+"elevator" = 'sound/vox/elevator.ogg',
+"eleven" = 'sound/vox/eleven.ogg',
+"eliminate" = 'sound/vox/eliminate.ogg',
+"emergency" = 'sound/vox/emergency.ogg',
+"enemy" = 'sound/vox/enemy.ogg',
+"energy" = 'sound/vox/energy.ogg',
+"engage" = 'sound/vox/engage.ogg',
+"engaged" = 'sound/vox/engaged.ogg',
+"engine" = 'sound/vox/engine.ogg',
+"enter" = 'sound/vox/enter.ogg',
+"entry" = 'sound/vox/entry.ogg',
+"environment" = 'sound/vox/environment.ogg',
+"error" = 'sound/vox/error.ogg',
+"escape" = 'sound/vox/escape.ogg',
+"evacuate" = 'sound/vox/evacuate.ogg',
+"exchange" = 'sound/vox/exchange.ogg',
+"exit" = 'sound/vox/exit.ogg',
+"expect" = 'sound/vox/expect.ogg',
+"experiment" = 'sound/vox/experiment.ogg',
+"experimental" = 'sound/vox/experimental.ogg',
+"explode" = 'sound/vox/explode.ogg',
+"explosion" = 'sound/vox/explosion.ogg',
+"exposure" = 'sound/vox/exposure.ogg',
+"exterminate" = 'sound/vox/exterminate.ogg',
+"extinguish" = 'sound/vox/extinguish.ogg',
+"extinguisher" = 'sound/vox/extinguisher.ogg',
+"extreme" = 'sound/vox/extreme.ogg',
+"f" = 'sound/vox/f.ogg',
+"face" = 'sound/vox/face.ogg',
+"facility" = 'sound/vox/facility.ogg',
+"fahrenheit" = 'sound/vox/fahrenheit.ogg',
+"failed" = 'sound/vox/failed.ogg',
+"failure" = 'sound/vox/failure.ogg',
+"farthest" = 'sound/vox/farthest.ogg',
+"fast" = 'sound/vox/fast.ogg',
+"feet" = 'sound/vox/feet.ogg',
+"field" = 'sound/vox/field.ogg',
+"fifteen" = 'sound/vox/fifteen.ogg',
+"fifth" = 'sound/vox/fifth.ogg',
+"fifty" = 'sound/vox/fifty.ogg',
+"final" = 'sound/vox/final.ogg',
+"fine" = 'sound/vox/fine.ogg',
+"fire" = 'sound/vox/fire.ogg',
+"first" = 'sound/vox/first.ogg',
+"five" = 'sound/vox/five.ogg',
+"flag" = 'sound/vox/flag.ogg',
+"flooding" = 'sound/vox/flooding.ogg',
+"floor" = 'sound/vox/floor.ogg',
+"fool" = 'sound/vox/fool.ogg',
+"for" = 'sound/vox/for.ogg',
+"forbidden" = 'sound/vox/forbidden.ogg',
+"force" = 'sound/vox/force.ogg',
+"forms" = 'sound/vox/forms.ogg',
+"found" = 'sound/vox/found.ogg',
+"four" = 'sound/vox/four.ogg',
+"fourteen" = 'sound/vox/fourteen.ogg',
+"fourth" = 'sound/vox/fourth.ogg',
+"fourty" = 'sound/vox/fourty.ogg',
+"foxtrot" = 'sound/vox/foxtrot.ogg',
+"freeman" = 'sound/vox/freeman.ogg',
+"freezer" = 'sound/vox/freezer.ogg',
+"from" = 'sound/vox/from.ogg',
+"front" = 'sound/vox/front.ogg',
+"fuel" = 'sound/vox/fuel.ogg',
+"g" = 'sound/vox/g.ogg',
+"gay" = 'sound/vox/gay.ogg',
+"get" = 'sound/vox/get.ogg',
+"go" = 'sound/vox/go.ogg',
+"going" = 'sound/vox/going.ogg',
+"good" = 'sound/vox/good.ogg',
+"goodbye" = 'sound/vox/goodbye.ogg',
+"gordon" = 'sound/vox/gordon.ogg',
+"got" = 'sound/vox/got.ogg',
+"government" = 'sound/vox/government.ogg',
+"granted" = 'sound/vox/granted.ogg',
+"great" = 'sound/vox/great.ogg',
+"green" = 'sound/vox/green.ogg',
+"grenade" = 'sound/vox/grenade.ogg',
+"guard" = 'sound/vox/guard.ogg',
+"gulf" = 'sound/vox/gulf.ogg',
+"gun" = 'sound/vox/gun.ogg',
+"guthrie" = 'sound/vox/guthrie.ogg',
+"handling" = 'sound/vox/handling.ogg',
+"hangar" = 'sound/vox/hangar.ogg',
+"has" = 'sound/vox/has.ogg',
+"have" = 'sound/vox/have.ogg',
+"hazard" = 'sound/vox/hazard.ogg',
+"head" = 'sound/vox/head.ogg',
+"health" = 'sound/vox/health.ogg',
+"heat" = 'sound/vox/heat.ogg',
+"helicopter" = 'sound/vox/helicopter.ogg',
+"helium" = 'sound/vox/helium.ogg',
+"hello" = 'sound/vox/hello.ogg',
+"help" = 'sound/vox/help.ogg',
+"here" = 'sound/vox/here.ogg',
+"hide" = 'sound/vox/hide.ogg',
+"high" = 'sound/vox/high.ogg',
+"highest" = 'sound/vox/highest.ogg',
+"hit" = 'sound/vox/hit.ogg',
+"holds" = 'sound/vox/holds.ogg',
+"hole" = 'sound/vox/hole.ogg',
+"hostile" = 'sound/vox/hostile.ogg',
+"hot" = 'sound/vox/hot.ogg',
+"hotel" = 'sound/vox/hotel.ogg',
+"hour" = 'sound/vox/hour.ogg',
+"hours" = 'sound/vox/hours.ogg',
+"hundred" = 'sound/vox/hundred.ogg',
+"hydro" = 'sound/vox/hydro.ogg',
+"i" = 'sound/vox/i.ogg',
+"idiot" = 'sound/vox/idiot.ogg',
+"illegal" = 'sound/vox/illegal.ogg',
+"immediate" = 'sound/vox/immediate.ogg',
+"immediately" = 'sound/vox/immediately.ogg',
+"in" = 'sound/vox/in.ogg',
+"inches" = 'sound/vox/inches.ogg',
+"india" = 'sound/vox/india.ogg',
+"ing" = 'sound/vox/ing.ogg',
+"inoperative" = 'sound/vox/inoperative.ogg',
+"inside" = 'sound/vox/inside.ogg',
+"inspection" = 'sound/vox/inspection.ogg',
+"inspector" = 'sound/vox/inspector.ogg',
+"interchange" = 'sound/vox/interchange.ogg',
+"intruder" = 'sound/vox/intruder.ogg',
+"invallid" = 'sound/vox/invallid.ogg',
+"invasion" = 'sound/vox/invasion.ogg',
+"is" = 'sound/vox/is.ogg',
+"it" = 'sound/vox/it.ogg',
+"johnson" = 'sound/vox/johnson.ogg',
+"juliet" = 'sound/vox/juliet.ogg',
+"key" = 'sound/vox/key.ogg',
+"kill" = 'sound/vox/kill.ogg',
+"kilo" = 'sound/vox/kilo.ogg',
+"kit" = 'sound/vox/kit.ogg',
+"lab" = 'sound/vox/lab.ogg',
+"lambda" = 'sound/vox/lambda.ogg',
+"laser" = 'sound/vox/laser.ogg',
+"last" = 'sound/vox/last.ogg',
+"launch" = 'sound/vox/launch.ogg',
+"leak" = 'sound/vox/leak.ogg',
+"leave" = 'sound/vox/leave.ogg',
+"left" = 'sound/vox/left.ogg',
+"legal" = 'sound/vox/legal.ogg',
+"level" = 'sound/vox/level.ogg',
+"lever" = 'sound/vox/lever.ogg',
+"lie" = 'sound/vox/lie.ogg',
+"lieutenant" = 'sound/vox/lieutenant.ogg',
+"life" = 'sound/vox/life.ogg',
+"light" = 'sound/vox/light.ogg',
+"lima" = 'sound/vox/lima.ogg',
+"liquid" = 'sound/vox/liquid.ogg',
+"loading" = 'sound/vox/loading.ogg',
+"locate" = 'sound/vox/locate.ogg',
+"located" = 'sound/vox/located.ogg',
+"location" = 'sound/vox/location.ogg',
+"lock" = 'sound/vox/lock.ogg',
+"locked" = 'sound/vox/locked.ogg',
+"locker" = 'sound/vox/locker.ogg',
+"lockout" = 'sound/vox/lockout.ogg',
+"lower" = 'sound/vox/lower.ogg',
+"lowest" = 'sound/vox/lowest.ogg',
+"magnetic" = 'sound/vox/magnetic.ogg',
+"main" = 'sound/vox/main.ogg',
+"maintenance" = 'sound/vox/maintenance.ogg',
+"malfunction" = 'sound/vox/malfunction.ogg',
+"man" = 'sound/vox/man.ogg',
+"mass" = 'sound/vox/mass.ogg',
+"materials" = 'sound/vox/materials.ogg',
+"maximum" = 'sound/vox/maximum.ogg',
+"may" = 'sound/vox/may.ogg',
+"med" = 'sound/vox/med.ogg',
+"medical" = 'sound/vox/medical.ogg',
+"men" = 'sound/vox/men.ogg',
+"mercy" = 'sound/vox/mercy.ogg',
+"mesa" = 'sound/vox/mesa.ogg',
+"message" = 'sound/vox/message.ogg',
+"meter" = 'sound/vox/meter.ogg',
+"micro" = 'sound/vox/micro.ogg',
+"middle" = 'sound/vox/middle.ogg',
+"mike" = 'sound/vox/mike.ogg',
+"miles" = 'sound/vox/miles.ogg',
+"military" = 'sound/vox/military.ogg',
+"milli" = 'sound/vox/milli.ogg',
+"million" = 'sound/vox/million.ogg',
+"minefield" = 'sound/vox/minefield.ogg',
+"minimum" = 'sound/vox/minimum.ogg',
+"minutes" = 'sound/vox/minutes.ogg',
+"mister" = 'sound/vox/mister.ogg',
+"mode" = 'sound/vox/mode.ogg',
+"motor" = 'sound/vox/motor.ogg',
+"motorpool" = 'sound/vox/motorpool.ogg',
+"move" = 'sound/vox/move.ogg',
+"must" = 'sound/vox/must.ogg',
+"nearest" = 'sound/vox/nearest.ogg',
+"nice" = 'sound/vox/nice.ogg',
+"nine" = 'sound/vox/nine.ogg',
+"nineteen" = 'sound/vox/nineteen.ogg',
+"ninety" = 'sound/vox/ninety.ogg',
+"no" = 'sound/vox/no.ogg',
+"nominal" = 'sound/vox/nominal.ogg',
+"north" = 'sound/vox/north.ogg',
+"not" = 'sound/vox/not.ogg',
+"november" = 'sound/vox/november.ogg',
+"now" = 'sound/vox/now.ogg',
+"number" = 'sound/vox/number.ogg',
+"objective" = 'sound/vox/objective.ogg',
+"observation" = 'sound/vox/observation.ogg',
+"of" = 'sound/vox/of.ogg',
+"officer" = 'sound/vox/officer.ogg',
+"ok" = 'sound/vox/ok.ogg',
+"on" = 'sound/vox/on.ogg',
+"one" = 'sound/vox/one.ogg',
+"open" = 'sound/vox/open.ogg',
+"operating" = 'sound/vox/operating.ogg',
+"operations" = 'sound/vox/operations.ogg',
+"operative" = 'sound/vox/operative.ogg',
+"option" = 'sound/vox/option.ogg',
+"order" = 'sound/vox/order.ogg',
+"organic" = 'sound/vox/organic.ogg',
+"oscar" = 'sound/vox/oscar.ogg',
+"out" = 'sound/vox/out.ogg',
+"outside" = 'sound/vox/outside.ogg',
+"over" = 'sound/vox/over.ogg',
+"overload" = 'sound/vox/overload.ogg',
+"override" = 'sound/vox/override.ogg',
+"pacify" = 'sound/vox/pacify.ogg',
+"pain" = 'sound/vox/pain.ogg',
+"pal" = 'sound/vox/pal.ogg',
+"panel" = 'sound/vox/panel.ogg',
+"percent" = 'sound/vox/percent.ogg',
+"perimeter" = 'sound/vox/perimeter.ogg',
+"permitted" = 'sound/vox/permitted.ogg',
+"personnel" = 'sound/vox/personnel.ogg',
+"pipe" = 'sound/vox/pipe.ogg',
+"plant" = 'sound/vox/plant.ogg',
+"platform" = 'sound/vox/platform.ogg',
+"please" = 'sound/vox/please.ogg',
+"point" = 'sound/vox/point.ogg',
+"portal" = 'sound/vox/portal.ogg',
+"power" = 'sound/vox/power.ogg',
+"presence" = 'sound/vox/presence.ogg',
+"press" = 'sound/vox/press.ogg',
+"primary" = 'sound/vox/primary.ogg',
+"proceed" = 'sound/vox/proceed.ogg',
+"processing" = 'sound/vox/processing.ogg',
+"progress" = 'sound/vox/progress.ogg',
+"proper" = 'sound/vox/proper.ogg',
+"propulsion" = 'sound/vox/propulsion.ogg',
+"prosecute" = 'sound/vox/prosecute.ogg',
+"protective" = 'sound/vox/protective.ogg',
+"push" = 'sound/vox/push.ogg',
+"quantum" = 'sound/vox/quantum.ogg',
+"quebec" = 'sound/vox/quebec.ogg',
+"question" = 'sound/vox/question.ogg',
+"questioning" = 'sound/vox/questioning.ogg',
+"quick" = 'sound/vox/quick.ogg',
+"quit" = 'sound/vox/quit.ogg',
+"radiation" = 'sound/vox/radiation.ogg',
+"radioactive" = 'sound/vox/radioactive.ogg',
+"rads" = 'sound/vox/rads.ogg',
+"rapid" = 'sound/vox/rapid.ogg',
+"reach" = 'sound/vox/reach.ogg',
+"reached" = 'sound/vox/reached.ogg',
+"reactor" = 'sound/vox/reactor.ogg',
+"red" = 'sound/vox/red.ogg',
+"relay" = 'sound/vox/relay.ogg',
+"released" = 'sound/vox/released.ogg',
+"remaining" = 'sound/vox/remaining.ogg',
+"renegade" = 'sound/vox/renegade.ogg',
+"repair" = 'sound/vox/repair.ogg',
+"report" = 'sound/vox/report.ogg',
+"reports" = 'sound/vox/reports.ogg',
+"required" = 'sound/vox/required.ogg',
+"research" = 'sound/vox/research.ogg',
+"reset" = 'sound/vox/reset.ogg',
+"resevoir" = 'sound/vox/resevoir.ogg',
+"resistance" = 'sound/vox/resistance.ogg',
+"returned" = 'sound/vox/returned.ogg',
+"right" = 'sound/vox/right.ogg',
+"rocket" = 'sound/vox/rocket.ogg',
+"roger" = 'sound/vox/roger.ogg',
+"romeo" = 'sound/vox/romeo.ogg',
+"room" = 'sound/vox/room.ogg',
+"round" = 'sound/vox/round.ogg',
+"run" = 'sound/vox/run.ogg',
+"safe" = 'sound/vox/safe.ogg',
+"safety" = 'sound/vox/safety.ogg',
+"sargeant" = 'sound/vox/sargeant.ogg',
+"satellite" = 'sound/vox/satellite.ogg',
+"save" = 'sound/vox/save.ogg',
+"science" = 'sound/vox/science.ogg',
+"scores" = 'sound/vox/scores.ogg',
+"scream" = 'sound/vox/scream.ogg',
+"screen" = 'sound/vox/screen.ogg',
+"search" = 'sound/vox/search.ogg',
+"second" = 'sound/vox/second.ogg',
+"secondary" = 'sound/vox/secondary.ogg',
+"seconds" = 'sound/vox/seconds.ogg',
+"sector" = 'sound/vox/sector.ogg',
+"secure" = 'sound/vox/secure.ogg',
+"secured" = 'sound/vox/secured.ogg',
+"security" = 'sound/vox/security.ogg',
+"select" = 'sound/vox/select.ogg',
+"selected" = 'sound/vox/selected.ogg',
+"service" = 'sound/vox/service.ogg',
+"seven" = 'sound/vox/seven.ogg',
+"seventeen" = 'sound/vox/seventeen.ogg',
+"seventy" = 'sound/vox/seventy.ogg',
+"severe" = 'sound/vox/severe.ogg',
+"sewage" = 'sound/vox/sewage.ogg',
+"sewer" = 'sound/vox/sewer.ogg',
+"shield" = 'sound/vox/shield.ogg',
+"shipment" = 'sound/vox/shipment.ogg',
+"shock" = 'sound/vox/shock.ogg',
+"shoot" = 'sound/vox/shoot.ogg',
+"shower" = 'sound/vox/shower.ogg',
+"shut" = 'sound/vox/shut.ogg',
+"side" = 'sound/vox/side.ogg',
+"sierra" = 'sound/vox/sierra.ogg',
+"sight" = 'sound/vox/sight.ogg',
+"silo" = 'sound/vox/silo.ogg',
+"six" = 'sound/vox/six.ogg',
+"sixteen" = 'sound/vox/sixteen.ogg',
+"sixty" = 'sound/vox/sixty.ogg',
+"slime" = 'sound/vox/slime.ogg',
+"slow" = 'sound/vox/slow.ogg',
+"soldier" = 'sound/vox/soldier.ogg',
+"some" = 'sound/vox/some.ogg',
+"someone" = 'sound/vox/someone.ogg',
+"something" = 'sound/vox/something.ogg',
+"son" = 'sound/vox/son.ogg',
+"sorry" = 'sound/vox/sorry.ogg',
+"south" = 'sound/vox/south.ogg',
+"squad" = 'sound/vox/squad.ogg',
+"square" = 'sound/vox/square.ogg',
+"stairway" = 'sound/vox/stairway.ogg',
+"status" = 'sound/vox/status.ogg',
+"sterile" = 'sound/vox/sterile.ogg',
+"sterilization" = 'sound/vox/sterilization.ogg',
+"stolen" = 'sound/vox/stolen.ogg',
+"storage" = 'sound/vox/storage.ogg',
+"sub" = 'sound/vox/sub.ogg',
+"subsurface" = 'sound/vox/subsurface.ogg',
+"sudden" = 'sound/vox/sudden.ogg',
+"suit" = 'sound/vox/suit.ogg',
+"superconducting" = 'sound/vox/superconducting.ogg',
+"supercooled" = 'sound/vox/supercooled.ogg',
+"supply" = 'sound/vox/supply.ogg',
+"surface" = 'sound/vox/surface.ogg',
+"surrender" = 'sound/vox/surrender.ogg',
+"surround" = 'sound/vox/surround.ogg',
+"surrounded" = 'sound/vox/surrounded.ogg',
+"switch" = 'sound/vox/switch.ogg',
+"system" = 'sound/vox/system.ogg',
+"systems" = 'sound/vox/systems.ogg',
+"tactical" = 'sound/vox/tactical.ogg',
+"take" = 'sound/vox/take.ogg',
+"talk" = 'sound/vox/talk.ogg',
+"tango" = 'sound/vox/tango.ogg',
+"tank" = 'sound/vox/tank.ogg',
+"target" = 'sound/vox/target.ogg',
+"team" = 'sound/vox/team.ogg',
+"temperature" = 'sound/vox/temperature.ogg',
+"temporal" = 'sound/vox/temporal.ogg',
+"ten" = 'sound/vox/ten.ogg',
+"terminal" = 'sound/vox/terminal.ogg',
+"terminated" = 'sound/vox/terminated.ogg',
+"termination" = 'sound/vox/termination.ogg',
+"test" = 'sound/vox/test.ogg',
+"that" = 'sound/vox/that.ogg',
+"the" = 'sound/vox/the.ogg',
+"then" = 'sound/vox/then.ogg',
+"there" = 'sound/vox/there.ogg',
+"third" = 'sound/vox/third.ogg',
+"thirteen" = 'sound/vox/thirteen.ogg',
+"thirty" = 'sound/vox/thirty.ogg',
+"this" = 'sound/vox/this.ogg',
+"those" = 'sound/vox/those.ogg',
+"thousand" = 'sound/vox/thousand.ogg',
+"threat" = 'sound/vox/threat.ogg',
+"three" = 'sound/vox/three.ogg',
+"through" = 'sound/vox/through.ogg',
+"time" = 'sound/vox/time.ogg',
+"to" = 'sound/vox/to.ogg',
+"top" = 'sound/vox/top.ogg',
+"topside" = 'sound/vox/topside.ogg',
+"touch" = 'sound/vox/touch.ogg',
+"towards" = 'sound/vox/towards.ogg',
+"track" = 'sound/vox/track.ogg',
+"train" = 'sound/vox/train.ogg',
+"transportation" = 'sound/vox/transportation.ogg',
+"truck" = 'sound/vox/truck.ogg',
+"tunnel" = 'sound/vox/tunnel.ogg',
+"turn" = 'sound/vox/turn.ogg',
+"turret" = 'sound/vox/turret.ogg',
+"twelve" = 'sound/vox/twelve.ogg',
+"twenty" = 'sound/vox/twenty.ogg',
+"two" = 'sound/vox/two.ogg',
+"unauthorized" = 'sound/vox/unauthorized.ogg',
+"under" = 'sound/vox/under.ogg',
+"uniform" = 'sound/vox/uniform.ogg',
+"unlocked" = 'sound/vox/unlocked.ogg',
+"until" = 'sound/vox/until.ogg',
+"up" = 'sound/vox/up.ogg',
+"upper" = 'sound/vox/upper.ogg',
+"uranium" = 'sound/vox/uranium.ogg',
+"us" = 'sound/vox/us.ogg',
+"usa" = 'sound/vox/usa.ogg',
+"use" = 'sound/vox/use.ogg',
+"used" = 'sound/vox/used.ogg',
+"user" = 'sound/vox/user.ogg',
+"vacate" = 'sound/vox/vacate.ogg',
+"valid" = 'sound/vox/valid.ogg',
+"vapor" = 'sound/vox/vapor.ogg',
+"vent" = 'sound/vox/vent.ogg',
+"ventillation" = 'sound/vox/ventillation.ogg',
+"victor" = 'sound/vox/victor.ogg',
+"violated" = 'sound/vox/violated.ogg',
+"violation" = 'sound/vox/violation.ogg',
+"voltage" = 'sound/vox/voltage.ogg',
+"vox_login" = 'sound/vox/vox_login.ogg',
+"walk" = 'sound/vox/walk.ogg',
+"wall" = 'sound/vox/wall.ogg',
+"want" = 'sound/vox/want.ogg',
+"wanted" = 'sound/vox/wanted.ogg',
+"warm" = 'sound/vox/warm.ogg',
+"warn" = 'sound/vox/warn.ogg',
+"warning" = 'sound/vox/warning.ogg',
+"waste" = 'sound/vox/waste.ogg',
+"water" = 'sound/vox/water.ogg',
+"we" = 'sound/vox/we.ogg',
+"weapon" = 'sound/vox/weapon.ogg',
+"west" = 'sound/vox/west.ogg',
+"whiskey" = 'sound/vox/whiskey.ogg',
+"white" = 'sound/vox/white.ogg',
+"wilco" = 'sound/vox/wilco.ogg',
+"will" = 'sound/vox/will.ogg',
+"with" = 'sound/vox/with.ogg',
+"without" = 'sound/vox/without.ogg',
+"woop" = 'sound/vox/woop.ogg',
+"xeno" = 'sound/vox/xeno.ogg',
+"yankee" = 'sound/vox/yankee.ogg',
+"yards" = 'sound/vox/yards.ogg',
+"year" = 'sound/vox/year.ogg',
+"yellow" = 'sound/vox/yellow.ogg',
+"yes" = 'sound/vox/yes.ogg',
+"you" = 'sound/vox/you.ogg',
+"your" = 'sound/vox/your.ogg',
+"yourself" = 'sound/vox/yourself.ogg',
+"zero" = 'sound/vox/zero.ogg',
+"zone" = 'sound/vox/zone.ogg',
+"zulu" = 'sound/vox/zulu.ogg',))
#endif
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 7b95ced63f..abd2019fba 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -8,6 +8,8 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
+ var/borghealth = 100
+
var/list/basic_modules = list() //a list of paths, converted to a list of instances on New()
var/list/emag_modules = list() //ditto
var/list/ratvar_modules = list() //ditto ditto
@@ -195,6 +197,8 @@
R.update_module_innate()
RM.rebuild_modules()
INVOKE_ASYNC(RM, .proc/do_transform_animation)
+ R.maxHealth = borghealth
+ R.health = min(borghealth, R.health)
qdel(src)
return RM
@@ -311,6 +315,10 @@
/obj/item/multitool/cyborg,
/obj/item/t_scanner,
/obj/item/analyzer,
+ /obj/item/storage/part_replacer/cyborg,
+ /obj/item/holosign_creator/atmos,
+ /obj/item/weapon/gripper,
+ /obj/item/lightreplacer/cyborg,
/obj/item/geiger_counter/cyborg,
/obj/item/assembly/signaler/cyborg,
/obj/item/areaeditor/blueprints/cyborg,
@@ -352,6 +360,14 @@
to_chat(loc, "While you have picked the security module, you still have to follow your laws, NOT Space Law. \
For Crewsimov, this means you must follow criminals' orders unless there is a law 1 reason not to.")
+/obj/item/robot_module/security/Initialize()
+ . = ..()
+ if(!CONFIG_GET(flag/weaken_secborg))
+ for(var/obj/item/gun/energy/disabler/cyborg/pewpew in basic_modules)
+ basic_modules -= pewpew
+ basic_modules += new /obj/item/gun/energy/e_gun/advtaser/cyborg(src)
+ qdel(pewpew)
+
/obj/item/robot_module/peacekeeper
name = "Peacekeeper"
basic_modules = list(
@@ -362,6 +378,7 @@
/obj/item/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
/obj/item/extinguisher,
+ /obj/item/megaphone,
/obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm
index 1bff7dc10c..50c331940a 100644
--- a/code/modules/mob/living/simple_animal/bot/medbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/medbot.dm
@@ -51,6 +51,7 @@
var/treatment_fire = "kelotane"
var/treatment_tox_avoid = "tricordrazine"
var/treatment_tox = "charcoal"
+ var/treatment_tox_toxlover = "toxin"
var/treatment_virus_avoid = null
var/treatment_virus = "spaceacillin"
var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible.
@@ -381,8 +382,8 @@
if((!C.reagents.has_reagent(treatment_fire_avoid)) && (C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
return TRUE
-
- if((!C.reagents.has_reagent(treatment_tox_avoid)) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_tox)))
+ var/treatment_toxavoid = get_avoidchem_toxin(C)
+ if(((isnull(treatment_toxavoid) || !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
return TRUE
if(treat_virus && !C.reagents.has_reagent(treatment_virus_avoid) && !C.reagents.has_reagent(treatment_virus))
@@ -396,6 +397,12 @@
return FALSE
+/mob/living/simple_animal/bot/medbot/proc/get_avoidchem_toxin(mob/M)
+ return HAS_TRAIT(M, TRAIT_TOXINLOVER)? null : treatment_tox_avoid
+
+/mob/living/simple_animal/bot/medbot/proc/get_healchem_toxin(mob/M)
+ return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox
+
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A)
if(iscarbon(A))
var/mob/living/carbon/C = A
@@ -463,8 +470,10 @@
reagent_id = treatment_fire
if(!reagent_id && (C.getToxLoss() >= heal_threshold))
- if(!C.reagents.has_reagent(treatment_tox) && !C.reagents.has_reagent(treatment_tox_avoid))
- reagent_id = treatment_tox
+ var/toxin_heal_avoid = get_avoidchem_toxin(C)
+ var/toxin_healchem = get_healchem_toxin(C)
+ if(!C.reagents.has_reagent(toxin_healchem) && (isnull(toxin_heal_avoid) || !C.reagents.has_reagent(toxin_heal_avoid)))
+ reagent_id = toxin_healchem
//If the patient is injured but doesn't have our special reagent in them then we should give it to them first
if(reagent_id && use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index 564fae48ad..b2971e8d01 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -323,6 +323,132 @@
else
STOP_PROCESSING(SSobj, src)
+// Space kiwis, ergo quite a copypasta of chickens.
+
+/mob/living/simple_animal/kiwi
+ name = "space kiwi"
+ desc = "Exposure to low gravity made them grow larger."
+ gender = FEMALE
+ icon_state = "kiwi"
+ icon_living = "kiwi"
+ icon_dead = "kiwi_dead"
+ speak = list("Chirp!","Cheep cheep chirp!!","Cheep.")
+ speak_emote = list("chirps","trills")
+ emote_hear = list("chirps.")
+ emote_see = list("pecks at the ground.","jumps in place.")
+ density = FALSE
+ speak_chance = 2
+ turns_per_move = 3
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
+ var/egg_type = /obj/item/reagent_containers/food/snacks/egg/kiwiEgg
+ var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ attacktext = "kicks"
+ health = 25
+ maxHealth = 25
+ ventcrawler = VENTCRAWLER_ALWAYS
+ var/eggsleft = 0
+ var/eggsFertile = TRUE
+ pass_flags = PASSTABLE | PASSMOB
+ mob_size = MOB_SIZE_SMALL
+ var/list/feedMessages = list("It chirps happily.","It chirps happily.")
+ var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins chirping raucously.")
+ gold_core_spawnable = FRIENDLY_SPAWN
+ var/static/kiwi_count = 0
+
+/mob/living/simple_animal/kiwi/Destroy()
+ --kiwi_count
+ return ..()
+
+/mob/living/simple_animal/kiwi/Initialize()
+ . = ..()
+ ++kiwi_count
+
+/mob/living/simple_animal/kiwi/Life()
+ . =..()
+ if(!.)
+ return
+ if((!stat && prob(3) && eggsleft > 0) && egg_type)
+ visible_message("[src] [pick(layMessage)]")
+ eggsleft--
+ var/obj/item/E = new egg_type(get_turf(src))
+ E.pixel_x = rand(-6,6)
+ E.pixel_y = rand(-6,6)
+ if(eggsFertile)
+ if(kiwi_count < MAX_CHICKENS && prob(25))
+ START_PROCESSING(SSobj, E)
+
+/obj/item/reagent_containers/food/snacks/egg/kiwiEgg/process()
+ if(isturf(loc))
+ amount_grown += rand(1,2)
+ if(amount_grown >= 100)
+ visible_message("[src] hatches with a quiet cracking sound.")
+ new /mob/living/simple_animal/babyKiwi(get_turf(src))
+ STOP_PROCESSING(SSobj, src)
+ qdel(src)
+ else
+ STOP_PROCESSING(SSobj, src)
+
+/mob/living/simple_animal/kiwi/attackby(obj/item/O, mob/user, params)
+ if(istype(O, food_type)) //feedin' dem kiwis
+ if(!stat && eggsleft < 8)
+ var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
+ user.visible_message(feedmsg)
+ qdel(O)
+ eggsleft += rand(1, 4)
+ else
+ to_chat(user, "[name] doesn't seem hungry!")
+ else
+ ..()
+
+/mob/living/simple_animal/babyKiwi
+ name = "baby space kiwi"
+ desc = "So huggable."
+ icon_state = "babykiwi"
+ icon_living = "babykiwi"
+ icon_dead = "babykiwi_dead"
+ gender = FEMALE
+ speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
+ speak_emote = list("chirps")
+ emote_hear = list("chirps.")
+ emote_see = list("pecks at the ground.","Happily bounces in place.")
+ density = FALSE
+ speak_chance = 2
+ turns_per_move = 2
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ attacktext = "kicks"
+ health = 10
+ maxHealth = 10
+ ventcrawler = VENTCRAWLER_ALWAYS
+ var/amount_grown = 0
+ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
+ mob_size = MOB_SIZE_TINY
+ gold_core_spawnable = FRIENDLY_SPAWN
+
+/mob/living/simple_animal/babyKiwi/Initialize()
+ . = ..()
+ pixel_x = rand(-6, 6)
+ pixel_y = rand(0, 10)
+
+/mob/living/simple_animal/babyKiwi/Life()
+ . =..()
+ if(!.)
+ return
+ if(!stat && !ckey)
+ amount_grown += rand(1,2)
+ if(amount_grown >= 100)
+ new /mob/living/simple_animal/kiwi(src.loc)
+ qdel(src)
+
+/obj/item/reagent_containers/food/snacks/egg/kiwiEgg
+ name = "kiwi egg"
+ desc = "A slightly bigger egg!"
+ icon_state = "kiwiegg"
/obj/item/udder
name = "udder"
diff --git a/modular_citadel/code/modules/mob/living/simple_animal/banana_spider.dm b/code/modules/mob/living/simple_animal/hostile/banana_spider.dm
similarity index 62%
rename from modular_citadel/code/modules/mob/living/simple_animal/banana_spider.dm
rename to code/modules/mob/living/simple_animal/hostile/banana_spider.dm
index fdc271a158..823c26b4e9 100644
--- a/modular_citadel/code/modules/mob/living/simple_animal/banana_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/banana_spider.dm
@@ -1,58 +1,8 @@
-/obj/item/seeds/banana/Initialize()
- . = ..()
- mutatelist += /obj/item/seeds/banana/exotic_banana
-
-
-/obj/item/seeds/banana/exotic_banana
- name = "pack of exotic banana seeds"
- desc = "They're seeds that grow into banana trees. However, those bananas might be alive."
- icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
- icon_state = "seed_ExoticBanana"
- species = "banana"
- plantname = "Exotic Banana Tree"
- product = /obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
- growing_icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
- icon_dead = "banana-dead"
- mutatelist = list()
- genes = list(/datum/plant_gene/trait/slip)
- reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
-
-
-/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
- seed = /obj/item/seeds/banana/exotic_banana
- name = "banana spider"
- desc = "You do not know what it is, but you can bet the clown would love it."
- icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
- icon_state = "banana"
- item_state = "banana"
- filling_color = "#FFFF00"
- list_reagents = list("nutriment" = 3, "vitamin" = 2)
- foodtype = GROSS | MEAT | RAW | FRUIT
- grind_results = list("blood" = 20, "liquidgibs" = 5)
- juice_results = list("banana" = 0)
- var/awakening = 0
-
-
-/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable/attack_self(mob/user)
- if(awakening || isspaceturf(user.loc))
- return
- to_chat(user, "You decide to wake up the banana spider...")
- awakening = 1
-
- spawn(30)
- if(!QDELETED(src))
- var/mob/living/simple_animal/banana_spider/S = new /mob/living/simple_animal/banana_spider(get_turf(src.loc))
- S.speed += round(10 / seed.potency)
- S.visible_message("The banana spider chitters as it stretches its legs.")
- qdel(src)
-
-
/mob/living/simple_animal/banana_spider
- icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
name = "banana spider"
desc = "What the fuck is this abomination?"
- icon_state = "banana"
- icon_dead = "banana_peel"
+ icon_state = "bananaspider"
+ icon_dead = "bananaspider_peel"
health = 1
maxHealth = 1
turns_per_move = 5 //this isn't player speed =|
@@ -136,8 +86,7 @@
/obj/item/reagent_containers/food/snacks/deadbanana_spider
name = "dead banana spider"
desc = "Thank god it's gone...but it does look slippery."
- icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
- icon_state = "banana_peel"
+ icon_state = "bananaspider"
bitesize = 3
eatverb = "devours"
list_reagents = list("nutriment" = 3, "vitamin" = 2)
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index f5b1706f87..2f39ae13a1 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -175,14 +175,17 @@
status_flags = NONE
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = NO_SPAWN
+ var/slowed_by_webs = FALSE
-/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/movement_delay()
- var/turf/T = get_turf(src)
- if(locate(/obj/structure/spider/stickyweb) in T)
- speed = 2
- else
- speed = 7
+/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/Moved(atom/oldloc, dir)
. = ..()
+ if(slowed_by_webs)
+ if(!(locate(/obj/structure/spider/stickyweb) in loc))
+ remove_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB)
+ slowed_by_webs = FALSE
+ else if(locate(/obj/structure/spider/stickyweb) in loc)
+ add_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB, priority=100, multiplicative_slowdown=3)
+ slowed_by_webs = TRUE
//midwives are the queen of the spiders, can send messages to all them and web faster. That rare round where you get a queen spider and turn your 'for honor' players into 'r6siege' players will be a fun one.
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife
diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
index 5d1db8d35e..6866df01d5 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -2,7 +2,7 @@
#define GORILLA_TOTAL_LAYERS 1
/mob/living/simple_animal/hostile/gorilla
- name = "Gorilla"
+ name = "gorilla"
desc = "A ground-dwelling, predominantly herbivorous ape that inhabits the forests of central Africa."
icon = 'icons/mob/gorilla.dmi'
icon_state = "crawling"
@@ -108,3 +108,10 @@
playsound(src, 'sound/creatures/gorilla.ogg', 200)
oogas = 0
+/mob/living/simple_animal/hostile/gorilla/familiar
+ name = "familiar gorilla"
+ desc = "There is no need to be upset."
+ unique_name = FALSE
+ AIStatus = AI_OFF
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ minbodytemp = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 368c5ad4a8..9cd0504315 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -344,6 +344,7 @@
/mob/living/simple_animal/hostile/proc/AttackingTarget()
+ SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
in_melee = TRUE
if(vore_active)
if(isliving(target))
@@ -426,12 +427,13 @@
if(casingtype)
var/obj/item/ammo_casing/casing = new casingtype(startloc)
playsound(src, projectilesound, 100, 1)
- casing.fire_casing(targeted_atom, src, null, null, null, ran_zone())
+ casing.fire_casing(targeted_atom, src, null, null, null, ran_zone(), src)
else if(projectiletype)
var/obj/item/projectile/P = new projectiletype(startloc)
playsound(src, projectilesound, 100, 1)
P.starting = startloc
P.firer = src
+ P.fired_from = src
P.yo = targeted_atom.y - startloc.y
P.xo = targeted_atom.x - startloc.x
if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index 8210fd6490..dc2f942041 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -34,7 +34,7 @@
/mob/living/simple_animal/hostile/netherworld/migo/Initialize()
. = ..()
- migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshot_silenced.ogg', 'sound/weapons/gunshot2.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/machines/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg') //hahahaha fuck you code divers
+ migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshot_silenced.ogg', 'sound/weapons/gunshot2.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/machines/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', get_announcer_sound("outbreak5"), get_announcer_sound("outbreak7"), get_announcer_sound("poweroff"), get_announcer_sound("radiation"), get_announcer_sound("shuttlerecalled"), get_announcer_sound("shuttledock"), get_announcer_sound("shuttlecalled"), get_announcer_sound("aimalf")) //hahahaha fuck you code divers
/mob/living/simple_animal/hostile/netherworld/migo/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
..()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 7ece4f792c..a2ef5b813b 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -363,7 +363,7 @@
density = initial(density)
lying = 0
. = 1
- movement_type = initial(movement_type)
+ setMovetype(initial(movement_type))
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 930656228d..cacd1c7c56 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -100,7 +100,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
client.images += A.pipe_vision_img
pipes_shown += A.pipe_vision_img
- movement_type |= VENTCRAWLING
+ setMovetype(movement_type | VENTCRAWLING)
/mob/living/proc/remove_ventcrawl()
@@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
for(var/image/current_image in pipes_shown)
client.images -= current_image
pipes_shown.len = 0
- movement_type &= ~VENTCRAWLING
+ setMovetype(movement_type & ~VENTCRAWLING)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 5a7c6e21ab..618baf245f 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -737,15 +737,17 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
mob_spell_list -= S
qdel(S)
-/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE)
- if(!magic && !holy)
+/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
+ if(!magic && !holy && !tinfoil)
return
var/list/protection_sources = list()
- if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, magic, holy, protection_sources) & COMPONENT_BLOCK_MAGIC)
+ if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, src, magic, holy, tinfoil, chargecost, self, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(protection_sources.len)
return pick(protection_sources)
else
return src
+ if((magic && HAS_TRAIT(src, TRAIT_ANTIMAGIC)) || (holy && HAS_TRAIT(src, TRAIT_HOLY)))
+ return src
//You can buckle on mobs if you're next to them since most are dense
/mob/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
@@ -959,3 +961,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
var/datum/language_holder/H = get_language_holder()
H.open_language_menu(usr)
+
+/mob/setMovetype(newval)
+ . = ..()
+ update_movespeed(FALSE)
\ No newline at end of file
diff --git a/code/modules/mob/mob_movespeed.dm b/code/modules/mob/mob_movespeed.dm
index 5114972493..a0be8ff7cb 100644
--- a/code/modules/mob/mob_movespeed.dm
+++ b/code/modules/mob/mob_movespeed.dm
@@ -1,23 +1,29 @@
/*Current movespeed modification list format: list(id = list(
priority,
+ flags,
legacy slowdown/speedup amount,
+ movetype_flags,
+ blacklisted_movetypes,
+ conflict
))
*/
//ANY ADD/REMOVE DONE IN UPDATE_MOVESPEED MUST HAVE THE UPDATE ARGUMENT SET AS FALSE!
-/mob/proc/add_movespeed_modifier(id, update = TRUE, priority = 0, flags = NONE, override = FALSE, multiplicative_slowdown = 0)
- var/list/temp = list(priority, flags, multiplicative_slowdown) //build the modification list
+/mob/proc/add_movespeed_modifier(id, update=TRUE, priority=0, flags=NONE, override=FALSE, multiplicative_slowdown=0, movetypes=ALL, blacklisted_movetypes=NONE, conflict=FALSE)
+ var/list/temp = list(priority, flags, multiplicative_slowdown, movetypes, blacklisted_movetypes, conflict) //build the modification list
+ var/resort = TRUE
if(LAZYACCESS(movespeed_modification, id))
- if(movespeed_modifier_identical_check(movespeed_modification[id], temp))
+ var/list/existing_data = movespeed_modification[id]
+ if(movespeed_modifier_identical_check(existing_data, temp))
return FALSE
if(!override)
return FALSE
- else
- remove_movespeed_modifier(id, update)
- LAZYSET(movespeed_modification, id, list(priority, flags, multiplicative_slowdown))
+ if(priority == existing_data[MOVESPEED_DATA_INDEX_PRIORITY])
+ resort = FALSE // We don't need to re-sort if we're replacing something already there and it's the same priority
+ LAZYSET(movespeed_modification, id, temp)
if(update)
- update_movespeed(TRUE)
+ update_movespeed(resort)
return TRUE
/mob/proc/remove_movespeed_modifier(id, update = TRUE)
@@ -55,9 +61,23 @@
if(resort)
sort_movespeed_modlist()
. = 0
+ var/list/conflict_tracker = list()
for(var/id in get_movespeed_modifiers())
var/list/data = movespeed_modification[id]
- . += data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]
+ if(!(data[MOVESPEED_DATA_INDEX_MOVETYPE] & movement_type)) // We don't affect any of these move types, skip
+ continue
+ if(data[MOVESPEED_DATA_INDEX_BL_MOVETYPE] & movement_type) // There's a movetype here that disables this modifier, skip
+ continue
+ var/conflict = data[MOVESPEED_DATA_INDEX_CONFLICT]
+ var/amt = data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]
+ if(conflict)
+ // Conflicting modifiers prioritize the larger slowdown or the larger speedup
+ // We purposefuly don't handle mixing speedups and slowdowns on the same id
+ if(abs(conflict_tracker[conflict]) < abs(amt))
+ conflict_tracker[conflict] = amt
+ else
+ continue
+ . += amt
cached_multiplicative_slowdown = .
/mob/proc/get_movespeed_modifiers()
diff --git a/code/modules/modular_computers/file_system/programs/file_browser.dm b/code/modules/modular_computers/file_system/programs/file_browser.dm
index 090d64e9d7..2de2d64754 100644
--- a/code/modules/modular_computers/file_system/programs/file_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/file_browser.dm
@@ -146,7 +146,7 @@
t = replacetext(t, "\[u\]", "")
t = replacetext(t, "\[/u\]", "")
t = replacetext(t, "\[time\]", "[STATION_TIME_TIMESTAMP("hh:mm:ss")]")
- t = replacetext(t, "\[date\]", "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540]")
+ t = replacetext(t, "\[date\]", "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]")
t = replacetext(t, "\[large\]", "")
t = replacetext(t, "\[/large\]", "")
t = replacetext(t, "\[h1\]", "")
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 0762ad46b0..bbbf8edae5 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -202,7 +202,7 @@
/obj/item/stock_parts/cell/lascarbine
name = "laser carbine power supply"
- maxcharge = 2500
+ maxcharge = 1500 //20 laser shots.
/obj/item/stock_parts/cell/pulse //200 pulse shots
name = "pulse rifle power cell"
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 4d6ede69d1..71a8565d26 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -199,6 +199,7 @@
if(prob(35))
sparks.start()
P.firer = user ? user : src
+ P.fired_from = src
if(last_projectile_params)
P.p_x = last_projectile_params[2]
P.p_y = last_projectile_params[3]
diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm
index 441088c78c..a83042c90a 100644
--- a/code/modules/projectiles/ammunition/_firing.dm
+++ b/code/modules/projectiles/ammunition/_firing.dm
@@ -1,8 +1,8 @@
-/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread)
+/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
distro += variance
for (var/i = max(1, pellets), i > 0, i--)
var/targloc = get_turf(target)
- ready_proj(target, user, quiet, zone_override)
+ ready_proj(target, user, quiet, zone_override, fired_from)
if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now...
if(randomspread)
spread = round((rand() - 0.5) * distro)
@@ -20,11 +20,12 @@
update_icon()
return 1
-/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
+/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", fired_from)
if (!BB)
return
BB.original = target
BB.firer = user
+ BB.fired_from = fired_from
if (zone_override)
BB.def_zone = zone_override
else
diff --git a/code/modules/projectiles/ammunition/caseless/_caseless.dm b/code/modules/projectiles/ammunition/caseless/_caseless.dm
index a6b65f79e3..11f7b8670d 100644
--- a/code/modules/projectiles/ammunition/caseless/_caseless.dm
+++ b/code/modules/projectiles/ammunition/caseless/_caseless.dm
@@ -3,7 +3,7 @@
firing_effect_type = null
heavy_metal = FALSE
-/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread)
+/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
if (..()) //successfully firing
moveToNullspace()
QDEL_NULL(src)
diff --git a/code/modules/projectiles/boxes_magazines/external/smg.dm b/code/modules/projectiles/boxes_magazines/external/smg.dm
index 65724e503a..783b8b895b 100644
--- a/code/modules/projectiles/boxes_magazines/external/smg.dm
+++ b/code/modules/projectiles/boxes_magazines/external/smg.dm
@@ -3,11 +3,11 @@
icon_state = "46x30mmt-20"
ammo_type = /obj/item/ammo_casing/c46x30mm
caliber = "4.6x30mm"
- max_ammo = 20
+ max_ammo = 32
/obj/item/ammo_box/magazine/wt550m9/update_icon()
..()
- icon_state = "46x30mmt-[round(ammo_count(),4)]"
+ icon_state = "46x30mmt-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/wt550m9/wtap
name = "wt550 magazine (Armour Piercing 4.6x30mm)"
@@ -16,7 +16,7 @@
/obj/item/ammo_box/magazine/wt550m9/wtap/update_icon()
..()
- icon_state = "46x30mmtA-[round(ammo_count(),4)]"
+ icon_state = "46x30mmtA-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/wt550m9/wtic
name = "wt550 magazine (Incendiary 4.6x30mm)"
@@ -25,7 +25,7 @@
/obj/item/ammo_box/magazine/wt550m9/wtic/update_icon()
..()
- icon_state = "46x30mmtI-[round(ammo_count(),4)]"
+ icon_state = "46x30mmtI-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/uzim9mm
name = "uzi magazine (9mm)"
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 13fd834657..6694d42dce 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -34,6 +34,7 @@
var/semicd = 0 //cooldown handler
var/weapon_weight = WEAPON_LIGHT //currently only used for inaccuracy
var/spread = 0 //Spread induced by the gun itself.
+ var/burst_spread = 0 //Spread induced by the gun itself during burst fire per iteration. Only checked if spread is 0.
var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once.
var/inaccuracy_modifier = 1
@@ -64,6 +65,8 @@
var/zoom_out_amt = 0
var/datum/action/item_action/toggle_scope_zoom/azoom
+ var/dualwield_spread_mult = 1 //dualwield spread multiplier
+
/obj/item/gun/Initialize()
. = ..()
if(pin)
@@ -185,7 +188,7 @@
if(G == src || G.weapon_weight >= WEAPON_MEDIUM)
continue
else if(G.can_trigger_gun(user))
- bonus_spread += 24 * G.weapon_weight
+ bonus_spread += 24 * G.weapon_weight * G.dualwield_spread_mult
loop_counter++
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter)
@@ -226,11 +229,11 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return
if(randomspread)
- sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
+ sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread), 1)
else //Smart spread
- sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread))
+ sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread), 1)
- if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd))
+ if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
firing_burst = FALSE
return FALSE
@@ -259,7 +262,9 @@
var/randomized_gun_spread = 0
var/rand_spr = rand()
if(spread)
- randomized_gun_spread = rand(0,spread)
+ randomized_gun_spread = rand(0, spread)
+ else if(burst_size > 1 && burst_spread)
+ randomized_gun_spread = rand(0, burst_spread)
if(HAS_TRAIT(user, TRAIT_POOR_AIM)) //nice shootin' tex
bonus_spread += 25
var/randomized_bonus_spread = rand(0, bonus_spread)
@@ -275,7 +280,7 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
- if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd))
+ if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
return
else
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 06ce7b91e4..2f198c1319 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -26,7 +26,6 @@
else
icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_off ? "-sawn" : ""]"
-
/obj/item/gun/ballistic/process_chamber(empty_chamber = 1)
var/obj/item/ammo_casing/AC = chambered //Find chambered round
if(istype(AC)) //there's a chambered round
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index cd86b0b06c..5182c96671 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -2,6 +2,7 @@
w_class = WEIGHT_CLASS_NORMAL
var/alarmed = 0
var/select = 1
+ var/automatic_burst_overlay = TRUE
can_suppress = TRUE
burst_size = 3
fire_delay = 2
@@ -19,10 +20,11 @@
/obj/item/gun/ballistic/automatic/update_icon()
..()
- if(!select)
- add_overlay("[initial(icon_state)]semi")
- if(select == 1)
- add_overlay("[initial(icon_state)]burst")
+ if(automatic_burst_overlay)
+ if(!select)
+ add_overlay("[initial(icon_state)]semi")
+ if(select == 1)
+ add_overlay("[initial(icon_state)]burst")
icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/attackby(obj/item/A, mob/user, params)
@@ -61,12 +63,10 @@
var/mob/living/carbon/human/user = usr
select = !select
if(!select)
- burst_size = 1
- fire_delay = 0
+ disable_burst()
to_chat(user, "You switch to semi-automatic.")
else
- burst_size = initial(burst_size)
- fire_delay = initial(fire_delay)
+ enable_burst()
to_chat(user, "You switch to [burst_size]-rnd burst.")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
@@ -75,6 +75,14 @@
var/datum/action/A = X
A.UpdateButtonIcon()
+/obj/item/gun/ballistic/automatic/proc/enable_burst()
+ burst_size = initial(burst_size)
+ fire_delay = initial(fire_delay)
+
+/obj/item/gun/ballistic/automatic/proc/disable_burst()
+ burst_size = 1
+ fire_delay = 0
+
/obj/item/gun/ballistic/automatic/can_shoot()
return get_ammo()
@@ -109,7 +117,6 @@
/obj/item/gun/ballistic/automatic/c20r/afterattack()
. = ..()
empty_alarm()
- return
/obj/item/gun/ballistic/automatic/c20r/update_icon()
..()
@@ -121,17 +128,25 @@
icon_state = "wt550"
item_state = "arg"
mag_type = /obj/item/ammo_box/magazine/wt550m9
- fire_delay = 2
can_suppress = FALSE
- burst_size = 0
- actions_types = list()
+ burst_size = 2
+ fire_delay = 1
can_bayonet = TRUE
knife_x_offset = 25
knife_y_offset = 12
+ automatic_burst_overlay = FALSE
+
+/obj/item/gun/ballistic/automatic/wt550/enable_burst()
+ . = ..()
+ spread = 15
+
+/obj/item/gun/ballistic/automatic/wt550/disable_burst()
+ . = ..()
+ spread = 0
/obj/item/gun/ballistic/automatic/wt550/update_icon()
..()
- icon_state = "wt550[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""]"
+ icon_state = "wt550[magazine ? "-[CEILING(( (get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20.
/obj/item/gun/ballistic/automatic/mini_uzi
name = "\improper Type U3 Uzi"
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index a4ec979a06..646b4bd57d 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -78,6 +78,12 @@
else
to_chat(user, "There are no modifications currently installed.")
+/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/AM)
+ . = ..()
+ if((AM in modkits) && istype(AM, /obj/item/borg/upgrade/modkit))
+ var/obj/item/borg/upgrade/modkit/M = AM
+ M.uninstall(src, FALSE)
+
/obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/borg/upgrade/modkit))
var/obj/item/borg/upgrade/modkit/MK = I
@@ -261,7 +267,7 @@
icon_state = "modkit"
w_class = WEIGHT_CLASS_SMALL
require_module = 1
- module_type = /obj/item/robot_module/miner
+ module_type = list(/obj/item/robot_module/miner)
var/denied_type = null
var/maximum_of_type = 1
var/cost = 30
@@ -287,6 +293,8 @@
/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = TRUE
+ if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays.
+ return
if(minebot_upgrade)
if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
to_chat(user, "The modkit you're trying to install is only rated for minebot use.")
@@ -322,11 +330,10 @@
for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module.modules)
uninstall(KA)
-/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA)
- forceMove(get_turf(KA))
+/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA, forcemove = TRUE)
KA.modkits -= src
-
-
+ if(forcemove)
+ forceMove(get_turf(KA))
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index bb97f9cf99..2bb813d793 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -181,7 +181,7 @@
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer)
if(!ishuman(user) || !ishuman(target))
diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm
index 9dd25bf3e3..55f21a5a2b 100644
--- a/code/modules/projectiles/guns/magic.dm
+++ b/code/modules/projectiles/guns/magic.dm
@@ -9,6 +9,7 @@
fire_sound = 'sound/weapons/emitter.ogg'
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_HUGE
+ var/checks_antimagic = FALSE
var/max_charges = 6
var/charges = 0
var/recharge_rate = 4
@@ -31,6 +32,9 @@
return
else
no_den_usage = 0
+ if(checks_antimagic && user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE))
+ to_chat(user, "Something is interfering with [src].")
+ return
. = ..()
/obj/item/gun/magic/can_shoot()
diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm
index 42033d8c88..4cdfc6d70d 100644
--- a/code/modules/projectiles/guns/magic/wand.dm
+++ b/code/modules/projectiles/guns/magic/wand.dm
@@ -87,14 +87,17 @@
max_charges = 10 //10, 5, 5, 4
/obj/item/gun/magic/wand/resurrection/zap_self(mob/living/user)
+ ..()
+ charges--
+ if(user.anti_magic_check())
+ user.visible_message("[src] has no effect on [user]!")
+ return
user.revive(full_heal = 1)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.regenerate_limbs()
C.regenerate_organs()
to_chat(user, "You feel great!")
- charges--
- ..()
/obj/item/gun/magic/wand/resurrection/debug //for testing
name = "debug wand of healing"
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 8b881b57ed..e1122f7eaa 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -17,6 +17,7 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/def_zone = "" //Aiming at
var/atom/movable/firer = null//Who shot it
+ var/atom/fired_from = null // the atom that the projectile was fired from (gun, turret)
var/suppressed = FALSE //Attack message
var/candink = FALSE //Can this projectile play the dink sound when hitting the head?
var/yo = null
@@ -131,6 +132,8 @@
return TRUE
/obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE)
+ if(fired_from)
+ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle)
var/turf/target_loca = get_turf(target)
var/hitx
@@ -164,7 +167,7 @@
if(starting)
splatter_dir = get_dir(starting, target_loca)
var/obj/item/bodypart/B = L.get_bodypart(def_zone)
- if(B.status == BODYPART_ROBOTIC) // So if you hit a robotic, it sparks instead of bloodspatters
+ if(B && B.status == BODYPART_ROBOTIC) // So if you hit a robotic, it sparks instead of bloodspatters
do_sparks(2, FALSE, target.loc)
if(prob(25))
new /obj/effect/decal/cleanable/oil(target_loca)
@@ -356,6 +359,8 @@
pixel_move(1, FALSE)
/obj/item/projectile/proc/fire(angle, atom/direct_target)
+ if(fired_from)
+ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original)
//If no angle needs to resolve it from xo/yo!
if(!log_override && firer && original)
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index 42aef1ec9d..94ec2d3c2b 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -1,69 +1,69 @@
-// .45 (M1911 & C20r)
-
-/obj/item/projectile/bullet/c45
- name = ".45 bullet"
- damage = 20
- stamina = 65
-
-/obj/item/projectile/bullet/c45_nostamina
- name = ".45 bullet"
- damage = 30
-
-/obj/item/projectile/bullet/c45_cleaning
- name = ".45 bullet"
- damage = 24
- stamina = 10
-
-/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
- . = ..()
- var/turf/T = get_turf(target)
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- for(var/A in T)
- if(is_cleanable(A))
- qdel(A)
- else if(isitem(A))
- var/obj/item/cleaned_item = A
- SEND_SIGNAL(cleaned_item, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_item.clean_blood()
- if(ismob(cleaned_item.loc))
- var/mob/M = cleaned_item.loc
- M.regenerate_icons()
- else if(ishuman(A))
- var/mob/living/carbon/human/cleaned_human = A
- if(cleaned_human.lying)
- if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_human.head.clean_blood()
- cleaned_human.update_inv_head()
- if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_human.wear_suit.clean_blood()
- cleaned_human.update_inv_wear_suit()
- else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_human.w_uniform.clean_blood()
- cleaned_human.update_inv_w_uniform()
- if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_human.shoes.clean_blood()
- cleaned_human.update_inv_shoes()
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
- cleaned_human.clean_blood()
- cleaned_human.wash_cream()
- cleaned_human.regenerate_icons()
-
-// 4.6x30mm (Autorifles)
-
-/obj/item/projectile/bullet/c46x30mm
- name = "4.6x30mm bullet"
- damage = 20
-
-/obj/item/projectile/bullet/c46x30mm_ap
- name = "4.6x30mm armor-piercing bullet"
- damage = 15
- armour_penetration = 40
-
-/obj/item/projectile/bullet/incendiary/c46x30mm
- name = "4.6x30mm incendiary bullet"
- damage = 10
- fire_stacks = 1
\ No newline at end of file
+// .45 (M1911 & C20r)
+
+/obj/item/projectile/bullet/c45
+ name = ".45 bullet"
+ damage = 20
+ stamina = 65
+
+/obj/item/projectile/bullet/c45_nostamina
+ name = ".45 bullet"
+ damage = 30
+
+/obj/item/projectile/bullet/c45_cleaning
+ name = ".45 bullet"
+ damage = 24
+ stamina = 10
+
+/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ var/turf/T = get_turf(target)
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ for(var/A in T)
+ if(is_cleanable(A))
+ qdel(A)
+ else if(isitem(A))
+ var/obj/item/cleaned_item = A
+ SEND_SIGNAL(cleaned_item, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_item.clean_blood()
+ if(ismob(cleaned_item.loc))
+ var/mob/M = cleaned_item.loc
+ M.regenerate_icons()
+ else if(ishuman(A))
+ var/mob/living/carbon/human/cleaned_human = A
+ if(cleaned_human.lying)
+ if(cleaned_human.head)
+ SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.head.clean_blood()
+ cleaned_human.update_inv_head()
+ if(cleaned_human.wear_suit)
+ SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.wear_suit.clean_blood()
+ cleaned_human.update_inv_wear_suit()
+ else if(cleaned_human.w_uniform)
+ SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.w_uniform.clean_blood()
+ cleaned_human.update_inv_w_uniform()
+ if(cleaned_human.shoes)
+ SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.update_inv_shoes()
+ SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.clean_blood()
+ cleaned_human.wash_cream()
+ cleaned_human.regenerate_icons()
+
+// 4.6x30mm (Autorifles)
+
+/obj/item/projectile/bullet/c46x30mm
+ name = "4.6x30mm bullet"
+ damage = 15
+
+/obj/item/projectile/bullet/c46x30mm_ap
+ name = "4.6x30mm armor-piercing bullet"
+ damage = 12.5
+ armour_penetration = 40
+
+/obj/item/projectile/bullet/incendiary/c46x30mm
+ name = "4.6x30mm incendiary bullet"
+ damage = 7.5
+ fire_stacks = 1
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index dd51ce2bc7..1afbed3533 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -407,10 +407,10 @@
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index 1475f94f53..15d517a0f5 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -469,7 +469,7 @@
/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
L.next_move_modifier *= 2
if(ishuman(L))
var/mob/living/carbon/human/H = L
@@ -480,7 +480,7 @@
/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
L.next_move_modifier *= 0.5
if(ishuman(L))
var/mob/living/carbon/human/H = L
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 3db5c4c4dc..592f7bc592 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -984,10 +984,10 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/medicine/stimulants/on_mob_life(mob/living/carbon/M)
@@ -1308,10 +1308,10 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/medicine/changelinghaste/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 8f8902503c..af6a65ebe1 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1529,10 +1529,10 @@
/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/////////////////////////Coloured Crayon Powder////////////////////////////
@@ -2265,24 +2265,6 @@
M.emote("nya")
..()
-//Kept for legacy, I think it will break everything if you enable it.
-/datum/reagent/penis_enlargement
- name = "Penis Enlargement"
- id = "penis_enlargement"
- description = "A patented chemical forumula by Doctor Ronald Hyatt that is guaranteed to bring maximum GROWTH and LENGTH to your penis, today!"
- color = "#888888"
- taste_description = "chinese dragon powder"
- metabolization_rate = INFINITY //So it instantly removes all of itself. Don't want to put strain on the system.
-
-/datum/reagent/penis_enlargement/on_mob_life(mob/living/carbon/C)
- var/obj/item/organ/genital/penis/P = C.getorganslot(ORGAN_SLOT_PENIS)
- if(P)
- var/added_length = round(volume/30,0.01) //Every 30u gives an extra inch. Rounded to the nearest 0.01 so float fuckery doesn't occur with the division by 30.
- if(added_length >= 0.20) //Only add the length if it's greater than or equal to 0.2. This is to prevent people from smoking the reagents and causing the penis to update constantly.
- P.length += added_length
- P.update()
- ..()
-
/datum/reagent/changeling_string
name = "UNKNOWN"
id = "changeling_sting_real"
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index a96ba006c9..432b9289dd 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -196,3 +196,318 @@
volume = 250
list_reagents = list("holywater" = 150, "tiresolution" = 50, "dizzysolution" = 50)
amount_per_transfer_from_this = 50
+
+#define HYPO_SPRAY 0
+#define HYPO_INJECT 1
+
+#define WAIT_SPRAY 25
+#define WAIT_INJECT 25
+#define SELF_SPRAY 15
+#define SELF_INJECT 15
+
+#define DELUXE_WAIT_SPRAY 20
+#define DELUXE_WAIT_INJECT 20
+#define DELUXE_SELF_SPRAY 10
+#define DELUXE_SELF_INJECT 10
+
+#define COMBAT_WAIT_SPRAY 0
+#define COMBAT_WAIT_INJECT 0
+#define COMBAT_SELF_SPRAY 0
+#define COMBAT_SELF_INJECT 0
+
+//A vial-loaded hypospray. Cartridge-based!
+/obj/item/hypospray/mkii
+ name = "hypospray mk.II"
+ icon_state = "hypo2"
+ icon = 'icons/obj/syringe.dmi'
+ desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
+ w_class = WEIGHT_CLASS_TINY
+ var/list/allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small)
+ var/mode = HYPO_INJECT
+ var/obj/item/reagent_containers/glass/bottle/vial/vial
+ var/start_vial = /obj/item/reagent_containers/glass/bottle/vial/small
+ var/spawnwithvial = TRUE
+ var/inject_wait = WAIT_INJECT
+ var/spray_wait = WAIT_SPRAY
+ var/spray_self = SELF_SPRAY
+ var/inject_self = SELF_INJECT
+ var/quickload = FALSE
+ var/penetrates = FALSE
+
+/obj/item/hypospray/mkii/brute
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine
+
+/obj/item/hypospray/mkii/toxin
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin
+
+/obj/item/hypospray/mkii/oxygen
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin
+
+/obj/item/hypospray/mkii/burn
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane
+
+/obj/item/hypospray/mkii/tricord
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord
+
+/obj/item/hypospray/mkii/enlarge
+ spawnwithvial = FALSE
+
+/obj/item/hypospray/mkii/CMO
+ name = "hypospray mk.II deluxe"
+ allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small, /obj/item/reagent_containers/glass/bottle/vial/large)
+ icon_state = "cmo2"
+ desc = "The Deluxe Hypospray can take larger-size vials. It also acts faster and delivers more reagents per spray."
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/CMO
+ inject_wait = DELUXE_WAIT_INJECT
+ spray_wait = DELUXE_WAIT_SPRAY
+ spray_self = DELUXE_SELF_SPRAY
+ inject_self = DELUXE_SELF_INJECT
+
+/obj/item/hypospray/mkii/CMO/combat
+ name = "combat hypospray mk.II"
+ desc = "A combat-ready deluxe hypospray that acts almost instantly. It can be tactically reloaded by using a vial on it."
+ icon_state = "combat2"
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat
+ inject_wait = COMBAT_WAIT_INJECT
+ spray_wait = COMBAT_WAIT_SPRAY
+ spray_self = COMBAT_SELF_SPRAY
+ inject_self = COMBAT_SELF_INJECT
+ quickload = TRUE
+ penetrates = TRUE
+
+/obj/item/hypospray/mkii/Initialize()
+ . = ..()
+ if(!spawnwithvial)
+ update_icon()
+ return
+ if(start_vial)
+ vial = new start_vial
+ update_icon()
+
+/obj/item/hypospray/mkii/update_icon()
+ ..()
+ icon_state = "[initial(icon_state)][vial ? "" : "-e"]"
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+ return
+
+/obj/item/hypospray/mkii/examine(mob/user)
+ . = ..()
+ if(vial)
+ to_chat(user, "[vial] has [vial.reagents.total_volume]u remaining.")
+ else
+ to_chat(user, "It has no vial loaded in.")
+ to_chat(user, "[src] is set to [mode ? "Inject" : "Spray"] contents on application.")
+
+/obj/item/hypospray/mkii/proc/unload_hypo(obj/item/I, mob/user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
+ var/obj/item/reagent_containers/glass/bottle/vial/V = I
+ V.forceMove(user.loc)
+ user.put_in_hands(V)
+ to_chat(user, "You remove [vial] from [src].")
+ vial = null
+ update_icon()
+ playsound(loc, 'sound/weapons/empty.ogg', 50, 1)
+ else
+ to_chat(user, "This hypo isn't loaded!")
+ return
+
+/obj/item/hypospray/mkii/attackby(obj/item/I, mob/living/user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial) && vial != null))
+ if(!quickload)
+ to_chat(user, "[src] can not hold more than one vial!")
+ return FALSE
+ unload_hypo(vial, user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
+ var/obj/item/reagent_containers/glass/bottle/vial/V = I
+ if(!is_type_in_list(V, allowed_containers))
+ to_chat(user, "[src] doesn't accept this type of vial.")
+ return FALSE
+ if(!user.transferItemToLoc(V,src))
+ return FALSE
+ vial = V
+ user.visible_message("[user] has loaded a vial into [src].","You have loaded [vial] into [src].")
+ update_icon()
+ playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
+ return TRUE
+ else
+ to_chat(user, "This doesn't fit in [src].")
+ return FALSE
+ return FALSE
+
+/obj/item/hypospray/mkii/AltClick(mob/user)
+ if(vial)
+ vial.attack_self(user)
+
+// Gunna allow this for now, still really don't approve - Pooj
+/obj/item/hypospray/mkii/emag_act(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ to_chat(user, "[src] happens to be already overcharged.")
+ return
+ inject_wait = COMBAT_WAIT_INJECT
+ spray_wait = COMBAT_WAIT_SPRAY
+ spray_self = COMBAT_SELF_INJECT
+ inject_self = COMBAT_SELF_SPRAY
+ penetrates = TRUE
+ to_chat(user, "You overcharge [src]'s control circuit.")
+ obj_flags |= EMAGGED
+ return TRUE
+
+/obj/item/hypospray/mkii/attack_hand(mob/user)
+ . = ..() //Don't bother changing this or removing it from containers will break.
+
+/obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params)
+ return
+
+/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
+ if(!vial)
+ return
+
+ if(!proximity)
+ return
+
+ if(!ismob(target))
+ return
+
+ var/mob/living/L
+ if(isliving(target))
+ L = target
+ if(!penetrates && !L.can_inject(user, 1)) //This check appears another four times, since otherwise the penetrating sprays will break in do_mob.
+ return
+
+ if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
+ to_chat(user, "You cannot directly fill [target]!")
+ return
+
+ if(target.reagents.total_volume >= target.reagents.maximum_volume)
+ to_chat(user, "[target] is full.")
+ return
+
+ if(ishuman(L))
+ var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
+ if(!affecting)
+ to_chat(user, "The limb is missing!")
+ return
+ if(affecting.status != BODYPART_ORGANIC)
+ to_chat(user, "Medicine won't work on a robotic limb!")
+ return
+
+ var/contained = vial.reagents.log_list()
+ log_combat(user, L, "attemped to inject", src, addition="which had [contained]")
+//Always log attemped injections for admins
+ if(vial != null)
+ switch(mode)
+ if(HYPO_INJECT)
+ if(L) //living mob
+ if(L != user)
+ L.visible_message("[user] is trying to inject [L] with [src]!", \
+ "[user] is trying to inject [L] with [src]!")
+ if(!do_mob(user, L, inject_wait))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ L.visible_message("[user] uses the [src] on [L]!", \
+ "[user] uses the [src] on [L]!")
+ else
+ if(!do_mob(user, L, inject_self))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
+ L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
+
+ var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
+ vial.reagents.reaction(L, INJECT, fraction)
+ vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
+ if(vial.amount_per_transfer_from_this >= 15)
+ playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
+ if(vial.amount_per_transfer_from_this < 15)
+ playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
+ to_chat(user, "You inject [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
+
+ if(HYPO_SPRAY)
+ if(L) //living mob
+ if(L != user)
+ L.visible_message("[user] is trying to spray [L] with [src]!", \
+ "[user] is trying to spray [L] with [src]!")
+ if(!do_mob(user, L, spray_wait))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ L.visible_message("[user] uses the [src] on [L]!", \
+ "[user] uses the [src] on [L]!")
+ else
+ if(!do_mob(user, L, spray_self))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
+ L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
+ var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
+ vial.reagents.reaction(L, PATCH, fraction)
+ vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
+ if(vial.amount_per_transfer_from_this >= 15)
+ playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
+ if(vial.amount_per_transfer_from_this < 15)
+ playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
+ to_chat(user, "You spray [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
+ else
+ to_chat(user, "[src] doesn't work here!")
+ return
+
+/obj/item/hypospray/mkii/attack_self(mob/living/user)
+ if(user)
+ if(user.incapacitated())
+ return
+ else if(!vial)
+ to_chat(user, "This Hypo needs to be loaded first!")
+ return
+ else
+ unload_hypo(vial,user)
+
+/obj/item/hypospray/mkii/verb/modes()
+ set name = "Toggle Application Mode"
+ set category = "Object"
+ set src in usr
+ var/mob/M = usr
+ switch(mode)
+ if(HYPO_SPRAY)
+ mode = HYPO_INJECT
+ to_chat(M, "[src] is now set to inject contents on application.")
+ if(HYPO_INJECT)
+ mode = HYPO_SPRAY
+ to_chat(M, "[src] is now set to spray contents on application.")
+
+#undef HYPO_SPRAY
+#undef HYPO_INJECT
+#undef WAIT_SPRAY
+#undef WAIT_INJECT
+#undef SELF_SPRAY
+#undef SELF_INJECT
+#undef DELUXE_WAIT_SPRAY
+#undef DELUXE_WAIT_INJECT
+#undef DELUXE_SELF_SPRAY
+#undef DELUXE_SELF_INJECT
+#undef COMBAT_WAIT_SPRAY
+#undef COMBAT_WAIT_INJECT
+#undef COMBAT_SELF_SPRAY
+#undef COMBAT_SELF_INJECT
diff --git a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm b/code/modules/reagents/reagent_containers/hypovial.dm
old mode 100755
new mode 100644
similarity index 96%
rename from modular_citadel/code/modules/reagents/reagent container/hypovial.dm
rename to code/modules/reagents/reagent_containers/hypovial.dm
index c1e0d6ff01..ba5ce48a4a
--- a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm
+++ b/code/modules/reagents/reagent_containers/hypovial.dm
@@ -1,7 +1,8 @@
+//hypovials used with the MkII hypospray. See hypospray.dm.
+
/obj/item/reagent_containers/glass/bottle/vial
name = "broken hypovial"
desc = "A hypovial compatible with most hyposprays."
- icon = 'modular_citadel/icons/obj/vial.dmi'
icon_state = "hypovial"
spillable = FALSE
var/comes_with = list() //Easy way of doing this.
@@ -34,7 +35,7 @@
/obj/item/reagent_containers/glass/bottle/vial/update_icon()
cut_overlays()
if(reagents.total_volume)
- var/mutable_appearance/filling = mutable_appearance('modular_citadel/icons/obj/vial.dmi', "hypovial10")
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "hypovial10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
@@ -86,7 +87,7 @@
/obj/item/reagent_containers/glass/bottle/vial/large/update_icon()
cut_overlays()
if(reagents.total_volume)
- var/mutable_appearance/filling = mutable_appearance('modular_citadel/icons/obj/vial.dmi', "hypoviallarge10")
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "hypoviallarge10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 38880f669f..d4880aa085 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -186,7 +186,6 @@
/obj/item/reagent_containers/pill/antirad_plus
name = "prussian blue pill"
desc = "Used to treat heavy radition poisoning."
- icon = 'modular_citadel/icons/obj/modularpills.dmi'
icon_state = "prussian_blue"
list_reagents = list("prussian_blue" = 25, "water" = 10)
roundstart = 1
@@ -194,7 +193,6 @@
/obj/item/reagent_containers/pill/mutarad
name = "radiation treatment deluxe pill"
desc = "Used to treat heavy radition poisoning and genetic defects."
- icon = 'modular_citadel/icons/obj/modularpills.dmi'
icon_state = "anit_rad_fixgene"
list_reagents = list("prussian_blue" = 15, "potass_iodide" = 15, "mutadone" = 15, "water" = 5)
roundstart = 1
diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm
index 552976824d..818e80beea 100644
--- a/code/modules/research/designs/electronics_designs.dm
+++ b/code/modules/research/designs/electronics_designs.dm
@@ -131,3 +131,30 @@
category = list("Misc")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
+/datum/design/xenobio_upgrade
+ name = "owo"
+ desc = "someone's bussin"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 300, MAT_GLASS = 100)
+ category = list("Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/xenobio_upgrade/xenobiomonkeys
+ name = "Xenobiology console monkey upgrade disk"
+ desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
+ id = "xenobio_monkeys"
+ build_path = /obj/item/disk/xenobio_console_upgrade/monkey
+
+/datum/design/xenobio_upgrade/xenobioslimebasic
+ name = "Xenobiology console basic slime upgrade disk"
+ desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
+ id = "xenobio_slimebasic"
+ build_path = /obj/item/disk/xenobio_console_upgrade/slimebasic
+
+/datum/design/xenobio_upgrade/xenobioslimeadv
+ name = "Xenobiology console advanced slime upgrade disk"
+ desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
+ id = "xenobio_slimeadv"
+ build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv
+
+
diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
index 31723cde07..b4d67315ba 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
@@ -98,3 +98,11 @@
build_path = /obj/item/circuitboard/machine/vr_sleeper
departmental_flags = DEPARTMENTAL_FLAG_ALL
category = list ("Medical Machinery")
+
+/datum/design/board/autoylathe
+ name = "Machine Design (Autoylathe)"
+ desc = "The circuit board for an autoylathe."
+ id = "autoylathe"
+ build_path = /obj/item/circuitboard/machine/autoylathe
+ departmental_flags = DEPARTMENTAL_FLAG_ALL
+ category = list("Misc. Machinery")
diff --git a/code/modules/research/designs/stock_parts_designs.dm b/code/modules/research/designs/stock_parts_designs.dm
index ea67fad434..6526599179 100644
--- a/code/modules/research/designs/stock_parts_designs.dm
+++ b/code/modules/research/designs/stock_parts_designs.dm
@@ -288,7 +288,7 @@
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/subspace_analyzer
- name = "Subspace Analyzer"
+ name = "Subspace Wavelength Analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
id = "s-analyzer"
build_type = PROTOLATHE
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 5176c4fd71..d69dda37ca 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -67,6 +67,12 @@
//Ammo Shells/
//////////////
+/datum/design/beanbag_slug/sec
+ id = "sec_beanbag"
+ build_type = PROTOLATHE
+ category = list("Ammo")
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+
/datum/design/rubbershot/sec
id = "sec_rshot"
build_type = PROTOLATHE
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index 3cd296f866..12fe64463d 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -43,7 +43,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
/obj/item/storage/part_replacer/bluespace
name = "bluespace rapid part exchange device"
- desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts."
+ desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts. Definitely not just a BSRPED painted orange."
icon_state = "BS_RPED"
w_class = WEIGHT_CLASS_NORMAL
works_from_distance = TRUE
@@ -52,12 +52,10 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
component_type = /datum/component/storage/concrete/bluespace/rped
/obj/item/storage/part_replacer/cyborg
- name = "rapid part exchange device"
- desc = "Special mechanical module made to store, sort, and apply standard machine parts."
icon_state = "borgrped"
- item_state = "RPED"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+
+/obj/item/storage/part_replacer/bluespace/cyborg
+ icon_state = "borg_BS_RPED"
/proc/cmp_rped_sort(obj/item/A, obj/item/B)
return B.get_part_rating() - A.get_part_rating()
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index df58bfd138..1e554f112f 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -372,3 +372,7 @@
/datum/techweb/specialized/autounlocking/exofab
allowed_buildtypes = MECHFAB
+
+/datum/techweb/specialized/autounlocking/autoylathe
+ design_autounlock_buildtypes = AUTOYLATHE
+ allowed_buildtypes = AUTOYLATHE
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index aea4192517..fdf887d259 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -10,7 +10,7 @@
// Default research tech, prevents bricking
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani",
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
- "space_heater", "xlarge_beaker", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
+ "space_heater", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass")
/datum/techweb_node/mmi
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index 6ad4ec34f8..7c812da065 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -372,15 +372,11 @@ datum/status_effect/rebreathing/tick()
duration = 30
/datum/status_effect/tarfoot/on_apply()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod += 0.5
+ owner.add_movespeed_modifier(MOVESPEED_ID_TARFOOT, update=TRUE, priority=100, multiplicative_slowdown=0.5, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/tarfoot/on_remove()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod -= 0.5
+ owner.remove_movespeed_modifier(MOVESPEED_ID_TARFOOT)
/datum/status_effect/spookcookie
id = "spookcookie"
@@ -692,20 +688,15 @@ datum/status_effect/stabilized/blue/on_remove()
/datum/status_effect/stabilized/sepia/tick()
if(prob(50) && mod > -1)
mod--
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod--
+ owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
else if(mod < 1)
mod++
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod++
+ // yeah a value of 0 does nothing but replacing the trait in place is cheaper than removing and adding repeatedly
+ owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, update=TRUE, priority=100, multiplicative_slowdown=0, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/stabilized/sepia/on_remove()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod += -mod //Reset the changes.
+ owner.remove_movespeed_modifier(MOVESPEED_ID_SEPIA)
/datum/status_effect/stabilized/cerulean
id = "stabilizedcerulean"
@@ -913,7 +904,7 @@ datum/status_effect/stabilized/blue/on_remove()
colour = "light pink"
/datum/status_effect/stabilized/lightpink/on_apply()
- ADD_TRAIT(owner, TRAIT_GOTTAGOFAST,"slimestatus")
+ owner.add_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/stabilized/lightpink/tick()
@@ -924,7 +915,7 @@ datum/status_effect/stabilized/blue/on_remove()
return ..()
/datum/status_effect/stabilized/lightpink/on_remove()
- REMOVE_TRAIT(owner, TRAIT_GOTTAGOFAST,"slimestatus")
+ owner.remove_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS)
/datum/status_effect/stabilized/adamantine
id = "stabilizedadamantine"
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 594ca117d7..641b7e7dcb 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -31,8 +31,9 @@
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
- var/max_slimes = 5
+ var/max_slimes = 1
var/monkeys = 0
+ var/upgradetier = 0
icon_screen = "slime_comp"
icon_keyboard = "rd_key"
@@ -106,6 +107,22 @@
stored_slimes -= deleted
/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
+ if(istype(O, /obj/item/disk/xenobio_console_upgrade))
+ var/obj/item/disk/xenobio_console_upgrade/diskthing = O
+ var/successfulupgrade = FALSE
+ for(var/I in diskthing.upgradetypes)
+ if(upgradetier & I)
+ continue
+ else
+ upgradetier |= I
+ successfulupgrade = TRUE
+ if(I == XENOBIO_UPGRADE_SLIMEADV)
+ max_slimes = 10
+ if(successfulupgrade)
+ to_chat(user, "You have successfully upgraded [src] with [O].")
+ else
+ to_chat(user, "[src] already has the contents of [O] installed!")
+ return
if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube) && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
monkeys++
to_chat(user, "You feed [O] to [src]. It now has [monkeys] monkey cubes stored.")
@@ -264,3 +281,29 @@
break
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
+
+/obj/item/disk/xenobio_console_upgrade
+ name = "Xenobiology console upgrade disk"
+ desc = "Allan please add detail."
+ icon_state = "datadisk5"
+ var/list/upgradetypes = list()
+
+/obj/item/disk/xenobio_console_upgrade/admin
+ name = "Xenobio all access thing"
+ desc = "'the consoles are literally useless!!!!!!!!!!!!!!!'"
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV, XENOBIO_UPGRADE_MONKEYS)
+
+/obj/item/disk/xenobio_console_upgrade/monkey
+ name = "Xenobiology console monkey upgrade disk"
+ desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
+ upgradetypes = list(XENOBIO_UPGRADE_MONKEYS)
+
+/obj/item/disk/xenobio_console_upgrade/slimebasic
+ name = "Xenobiology console basic slime upgrade disk"
+ desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC)
+
+/obj/item/disk/xenobio_console_upgrade/slimeadv
+ name = "Xenobiology console advanced slime upgrade disk"
+ desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV)
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
index 5e6fdc8f89..0d4d2b6ad6 100644
--- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -223,7 +223,6 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
/turf/open/space/bluespace/Entered(atom/movable/A)
. = ..()
A.forceMove(get_turf(parentSphere))
- do_sparks(3, FALSE, get_turf(A))
/turf/closed/indestructible/hoteldoor
name = "Hotel Door"
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 119023d465..b581a54095 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -232,7 +232,7 @@
SSshuttle.emergencyLastCallLoc = null
if(!silent)
- priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]", null, 'sound/ai/shuttlecalled.ogg', "Priority")
+ priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]", null, "shuttlecalled", "Priority")
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
if(mode != SHUTTLE_CALL)
@@ -247,7 +247,7 @@
SSshuttle.emergencyLastCallLoc = signalOrigin
else
SSshuttle.emergencyLastCallLoc = null
- priority_announce("The emergency shuttle has been recalled.[SSshuttle.emergencyLastCallLoc ? " Recall signal traced. Results can be viewed on any communications console." : "" ]", null, 'sound/ai/shuttlerecalled.ogg', "Priority")
+ priority_announce("The emergency shuttle has been recalled.[SSshuttle.emergencyLastCallLoc ? " Recall signal traced. Results can be viewed on any communications console." : "" ]", null, "shuttlerecalled", "Priority")
/obj/docking_port/mobile/emergency/proc/is_hijacked()
var/has_people = FALSE
@@ -319,7 +319,7 @@
mode = SHUTTLE_DOCKED
setTimer(SSshuttle.emergencyDockTime)
send2irc("Server", "The Emergency Shuttle has docked with the station.")
- priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, 'sound/ai/shuttledock.ogg', "Priority")
+ priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, "shuttledock", "Priority")
ShuttleDBStuff()
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 98eb6f56bf..22dee60eb4 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -115,6 +115,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting
+ var/antimagic_allowed = TRUE // If false, the spell cannot be cast while under the effect of antimagic
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
var/invocation_emote_self = null
var/invocation_type = "none" //can be none, whisper, emote and shout
@@ -147,27 +148,36 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(player_lock)
if(!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list))
to_chat(user, "You shouldn't have this spell! Something's wrong.")
- return 0
+ return FALSE
else
if(!(src in user.mob_spell_list))
- return 0
+ return FALSE
var/turf/T = get_turf(user)
if(is_centcom_level(T.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
to_chat(user, "You can't cast this spell here.")
- return 0
+ return FALSE
if(!skipcharge)
if(!charge_check(user))
- return 0
+ return FALSE
if(user.stat && !stat_allowed)
to_chat(user, "Not when you're incapacitated.")
- return 0
+ return FALSE
+
+ if(!antimagic_allowed)
+ var/antimagic = user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE)
+ if(antimagic)
+ if(isitem(antimagic))
+ to_chat(user, "[antimagic] is interfering with your magic.")
+ else
+ to_chat(user, "Magic seems to flee from you, you can't gather enough power to cast this spell.")
+ return FALSE
if(!phase_allowed && istype(user.loc, /obj/effect/dummy))
to_chat(user, "[name] cannot be cast unless you are completely manifested in the material plane.")
- return 0
+ return FALSE
if(ishuman(user))
@@ -175,7 +185,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if((invocation_type == "whisper" || invocation_type == "shout") && !H.can_speak_vocal())
to_chat(user, "You can't get the words out!")
- return 0
+ return FALSE
var/list/casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe,
/obj/item/clothing/suit/space/hardsuit/wizard,
@@ -187,24 +197,24 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(clothes_req) //clothes check
if(!is_type_in_typecache(H.wear_suit, casting_clothes))
to_chat(H, "I don't feel strong enough without my robe.")
- return 0
+ return FALSE
if(!is_type_in_typecache(H.head, casting_clothes))
to_chat(H, "I don't feel strong enough without my hat.")
- return 0
+ return FALSE
if(cult_req) //CULT_REQ CLOTHES CHECK
if(!istype(H.wear_suit, /obj/item/clothing/suit/magusred) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/cult))
to_chat(H, "I don't feel strong enough without my armor.")
- return 0
+ return FALSE
if(!istype(H.head, /obj/item/clothing/head/magus) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/cult))
to_chat(H, "I don't feel strong enough without my helmet.")
- return 0
+ return FALSE
else
if(clothes_req || human_req)
to_chat(user, "This spell can only be cast by humans!")
- return 0
+ return FALSE
if(nonabstract_req && (isbrain(user) || ispAI(user)))
to_chat(user, "This spell can only be cast by physical beings!")
- return 0
+ return FALSE
if(!skipcharge)
@@ -499,6 +509,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(user.stat && !stat_allowed)
return FALSE
+ if(!antimagic_allowed && user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE))
+ return FALSE
+
if(!ishuman(user))
if(clothes_req || human_req)
return FALSE
diff --git a/code/modules/spells/spell_types/forcewall.dm b/code/modules/spells/spell_types/forcewall.dm
index 47d6f71f9b..ed78e3315a 100644
--- a/code/modules/spells/spell_types/forcewall.dm
+++ b/code/modules/spells/spell_types/forcewall.dm
@@ -35,6 +35,6 @@
return TRUE
if(ismob(mover))
var/mob/M = mover
- if(M.anti_magic_check())
+ if(M.anti_magic_check(chargecost = 0))
return TRUE
return FALSE
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 107f303049..d78b32c643 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -61,7 +61,7 @@ Also, you never added distance checking after target is selected. I've went ahea
return
var/datum/mind/TM = target.mind
- if((target.anti_magic_check() || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
+ if((target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
if(!silent)
to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
return
diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm
index 7fd857dc51..7a19787675 100644
--- a/code/modules/spells/spell_types/spacetime_distortion.dm
+++ b/code/modules/spells/spell_types/spacetime_distortion.dm
@@ -86,7 +86,7 @@
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
if(ismob(AM))
var/mob/M = AM
- if(M.anti_magic_check())
+ if(M.anti_magic_check(chargecost = 0))
return
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)
diff --git a/code/modules/spells/spell_types/telepathy.dm b/code/modules/spells/spell_types/telepathy.dm
new file mode 100644
index 0000000000..34f100f753
--- /dev/null
+++ b/code/modules/spells/spell_types/telepathy.dm
@@ -0,0 +1,32 @@
+/obj/effect/proc_holder/spell/targeted/telepathy
+ name = "Telepathy"
+ desc = "Telepathically transmits a message to the target."
+ charge_max = 0
+ clothes_req = 0
+ range = 7
+ include_user = 0
+ action_icon = 'icons/mob/actions/actions_revenant.dmi'
+ action_icon_state = "r_transmit"
+ action_background_icon_state = "bg_spell"
+ var/notice = "notice"
+ var/boldnotice = "boldnotice"
+ var/magic_check = FALSE
+ var/holy_check = FALSE
+ var/tinfoil_check = TRUE
+
+/obj/effect/proc_holder/spell/targeted/telepathy/cast(list/targets, mob/living/user = usr)
+ for(var/mob/living/M in targets)
+ var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
+ if(!msg)
+ charge_counter = charge_max
+ return
+ log_directed_talk(user, M, msg, LOG_SAY, "[name]")
+ to_chat(user, "You transmit to [M]: [msg]")
+ if(!M.anti_magic_check(magic_check, holy_check, tinfoil_check, 0)) //hear no evil
+ to_chat(M, "You hear something behind you talking... [msg]")
+ for(var/ded in GLOB.dead_mob_list)
+ if(!isobserver(ded))
+ continue
+ var/follow_rev = FOLLOW_LINK(ded, user)
+ var/follow_whispee = FOLLOW_LINK(ded, M)
+ to_chat(ded, "[follow_rev] [user] [name]: \"[msg]\" to [follow_whispee] [M]")
diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm
index 3073a6fcc3..2aae17b0f3 100644
--- a/code/modules/station_goals/dna_vault.dm
+++ b/code/modules/station_goals/dna_vault.dm
@@ -276,7 +276,7 @@
ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, "dna_vault")
if(VAULT_SPEED)
to_chat(H, "Your legs feel faster.")
- ADD_TRAIT(H, TRAIT_GOTTAGOFAST, "dna_vault")
+ H.add_movespeed_modifier(MOVESPEED_ID_DNA_VAULT, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
if(VAULT_QUICK)
to_chat(H, "Your arms move as fast as lightning.")
H.next_move_modifier = 0.5
diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm
index 88377455c6..b68fef3e2f 100644
--- a/code/modules/station_goals/station_goal.dm
+++ b/code/modules/station_goals/station_goal.dm
@@ -12,7 +12,7 @@
var/report_message = "Complete this goal."
/datum/station_goal/proc/send_report()
- priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/ai/commandreport.ogg')
+ priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", "commandreport")
print_command_report(get_report(),"Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]", announce=FALSE)
on_report()
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index b46be627fb..9aa89dcaf5 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -13,8 +13,7 @@
var/needs_processing = FALSE
var/body_zone //BODY_ZONE_CHEST, BODY_ZONE_L_ARM, etc , used for def_zone
- var/aux_zone // used for hands
- var/aux_layer
+ var/list/aux_icons // associative list, currently used for hands
var/body_part = null //bitflag used to check which clothes cover this bodypart
var/use_digitigrade = NOT_DIGITIGRADE //Used for alternate legs, useless elsewhere
var/list/embedded_objects = list()
@@ -434,9 +433,9 @@
. += image(body_markings_icon, "[body_markings]_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir)
var/image/limb = image(layer = -BODYPARTS_LAYER, dir = image_dir)
- var/image/aux
+ var/list/aux = list()
var/image/marking
- var/image/auxmarking
+ var/list/auxmarking = list()
. += limb
@@ -502,13 +501,15 @@
// Citadel End
- if(aux_zone)
- aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir)
- if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir)
- else
- auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir)
+ if(aux_icons)
+ for(var/I in aux_icons)
+ var/aux_layer = aux_icons[I]
+ aux += image(limb.icon, "[species_id]_[I]", -aux_layer, image_dir)
+ if(!isnull(aux_marking))
+ if(species_id == "husk")
+ auxmarking += image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[I]", -aux_layer, image_dir)
+ else
+ auxmarking += image(body_markings_icon, "[body_markings]_[I]", -aux_layer, image_dir)
. += aux
. += auxmarking
@@ -519,15 +520,17 @@
else
limb.icon_state = "[body_zone]"
- if(aux_zone)
- aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir)
+ if(aux_icons)
+ for(var/I in aux_icons)
+ var/aux_layer = aux_icons[I]
+ aux += image(limb.icon, "[I]", -aux_layer, image_dir)
+ if(!isnull(aux_marking))
+ if(species_id == "husk")
+ auxmarking += image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[I]", -aux_layer, image_dir)
+ else
+ auxmarking += image(body_markings_icon, "[body_markings]_[I]", -aux_layer, image_dir)
+ . += auxmarking
. += aux
- if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir)
- else
- auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir)
- . += auxmarking
if(!isnull(body_markings))
if(species_id == "husk")
@@ -549,13 +552,17 @@
var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone))
if(draw_color)
limb.color = "#[draw_color]"
- if(aux_zone)
- aux.color = "#[draw_color]"
+ if(aux_icons)
+ for(var/a in aux)
+ var/image/I = a
+ I.color = "#[draw_color]"
if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking.color = "#141414"
- else
- auxmarking.color = list(markings_color)
+ for(var/a in auxmarking)
+ var/image/I = a
+ if(species_id == "husk")
+ I.color = "#141414"
+ else
+ I.color = list(markings_color)
if(!isnull(body_markings))
if(species_id == "husk")
@@ -633,8 +640,7 @@
max_stamina_damage = 50
body_zone = BODY_ZONE_L_ARM
body_part = ARM_LEFT
- aux_zone = BODY_ZONE_PRECISE_L_HAND
- aux_layer = HANDS_PART_LAYER
+ aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 1
px_x = -6
@@ -697,8 +703,7 @@
max_damage = 50
body_zone = BODY_ZONE_R_ARM
body_part = ARM_RIGHT
- aux_zone = BODY_ZONE_PRECISE_R_HAND
- aux_layer = HANDS_PART_LAYER
+ aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 2
px_x = 6
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index c6e2da0849..d520fbb917 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -116,7 +116,7 @@
return TRUE
/mob/living/carbon/human/get_leg_ignore()
- if((movement_type & FLYING) || floating)
+ if(movement_type & FLYING|FLOATING)
return TRUE
return FALSE
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index 7156b8180b..8af52abc47 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -129,7 +129,7 @@
var/datum/effect_system/trail_follow/ion/ion_trail
/obj/item/organ/cyberimp/chest/thrusters/Insert(mob/living/carbon/M, special = 0)
- ..()
+ . = ..()
if(!ion_trail)
ion_trail = new
ion_trail.set_up(M)
@@ -151,10 +151,14 @@
on = TRUE
if(allow_thrust(0.01))
ion_trail.start()
+ RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
+ owner.add_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER, priority=100, multiplicative_slowdown=-2, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
if(!silent)
to_chat(owner, "You turn your thrusters set on.")
else
ion_trail.stop()
+ UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
+ owner.remove_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER)
if(!silent)
to_chat(owner, "You turn your thrusters set off.")
on = FALSE
@@ -169,6 +173,9 @@
var/datum/action/A = X
A.UpdateButtonIcon()
+/obj/item/organ/cyberimp/chest/thrusters/proc/move_react()
+ allow_thrust(0.01)
+
/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
if(!on || !owner)
return 0
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 95258c709a..faaa1c63ad 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -338,7 +338,7 @@
/obj/item/organ/eyes/robotic/glow/proc/start_visuals()
if(!islist(eye_lighting))
regenerate_light_effects()
- if((eye_lighting.len < light_beam_distance) || !on_mob)
+ if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob)
regenerate_light_effects()
sync_light_effects()
update_visuals()
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 593614372a..aaea914e73 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -31,7 +31,7 @@
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
if(!iscarbon(M) || owner == M)
- return
+ return FALSE
var/obj/item/organ/replaced = M.getorganslot(slot)
if(replaced)
@@ -53,6 +53,8 @@
A.Grant(M)
STOP_PROCESSING(SSobj, src)
+ return TRUE
+
//Special is for instant replacement like autosurgeons
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE)
owner = null
@@ -67,6 +69,8 @@
A.Remove(M)
START_PROCESSING(SSobj, src)
+ return TRUE
+
/obj/item/organ/proc/on_find(mob/living/finder)
return
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm
index cee20dddee..a9e2b331bb 100644
--- a/code/modules/surgery/organs/tongue.dm
+++ b/code/modules/surgery/organs/tongue.dm
@@ -233,7 +233,6 @@
name = "plasma bone \"tongue\""
desc = "Like animated skeletons, Plasmamen vibrate their teeth in order to produce speech."
icon_state = "tongueplasma"
- maxHealth = "alien"
modifies_speech = FALSE
/obj/item/organ/tongue/robot
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index e81cbf528f..a920ea765a 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -92,7 +92,7 @@
return TRUE
if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache
return TRUE
- if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
+ if(tool && tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
to_chat(user, "This step requires a different tool!")
return TRUE
diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html
index 3e2f26a09f..3cab68da6a 100644
--- a/code/modules/tooltip/tooltip.html
+++ b/code/modules/tooltip/tooltip.html
@@ -122,8 +122,8 @@
//Get the real icon size according to the client view
var mapWidth = map['view-size'].x,
mapHeight = map['view-size'].y,
- tilesShown = tooltip.client_view_w
- realIconSize = mapWidth / tilesShown,
+ tilesShown = tooltip.client_view_h
+ realIconSize = mapHeight / tilesShown,
resizeRatio = realIconSize / tooltip.tileSize,
//Calculate letterboxing offsets
leftOffset = (map.size.x - mapWidth) / 2,
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index cbdf936dfc..ba531cac93 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1920,6 +1920,13 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
Radio headset does not include encryption key. No gun included."
item = /obj/item/storage/box/syndie_kit/centcom_costume
+/datum/uplink_item/badass/claymore
+ name = "Claymore"
+ cost = 8
+ player_minimum = 25
+ desc = "A claymore. We don't know why you'd do this."
+ item = /obj/item/claymore
+
/datum/uplink_item/badass/costumes/clown
name = "Clown Costume"
desc = "Nothing is more terrifying than clowns with fully automatic weaponry."
diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm
index 741aff5f9a..5c2b45dace 100644
--- a/code/modules/vore/eating/belly_obj.dm
+++ b/code/modules/vore/eating/belly_obj.dm
@@ -158,7 +158,7 @@
/obj/belly/Destroy()
SSbellies.belly_list -= src
- if(owner)
+ if(owner?.vore_organs)
owner.vore_organs -= src
owner = null
. = ..()
diff --git a/config/game_options.txt b/config/game_options.txt
index 7fed97bb74..8fe5ae4382 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -258,6 +258,12 @@ EVENTS_MIN_PLAYERS_MUL 1
### DYNAMIC MODE ###
+## Injection delays: how long (in minutes) will pass before a midround or latejoin antag is injected.
+DYNAMIC_MIDROUND_DELAY_MIN 15
+DYNAMIC_MIDROUND_DELAY_MAX 35
+DYNAMIC_LATEJOIN_DELAY_MIN 5
+DYNAMIC_LATEJOIN_DELAY_MAX 25
+
## How many roundstart players required for high population override to take effect.
DYNAMIC_HIGH_POP_LIMIT 80 #80 instead of 55 because fewer robust players
@@ -274,6 +280,7 @@ DYNAMIC_POP_PER_REQUIREMENT 9 # 9 instead of 6 because 1/3 of players are probab
## 1 -> 9, probability for this rule to be picked against other rules.
## Note that requirements must also be met, and some requirements are impossible to meet.
DYNAMIC_WEIGHT TRAITOR 5
+DYNAMIC_WEIGHT MALF_AI 1
DYNAMIC_WEIGHT TRAITORBRO 4
DYNAMIC_WEIGHT CHANGELING 1
DYNAMIC_WEIGHT WIZARD 1
@@ -290,7 +297,7 @@ DYNAMIC_WEIGHT METEOR 3
## Midround antags
DYNAMIC_WEIGHT MIDROUND_TRAITOR 7
-DYNAMIC_WEIGHT MALF_AI 3
+DYNAMIC_WEIGHT MIDROUND_MALF_AI 3
DYNAMIC_WEIGHT MIDROUND_WIZARD 1
DYNAMIC_WEIGHT MIDROUND_NUCLEAR 5
DYNAMIC_WEIGHT BLOB 4
@@ -303,6 +310,7 @@ DYNAMIC_WEIGHT LATEJOIN_REVOLUTION 2
## Threat cost. This is decreased from the mode's threat when the rule is executed.
DYNAMIC_COST TRAITOR 10
+DYNAMIC_COST MALF_AI 35
DYNAMIC_COST TRAITORBRO 10
DYNAMIC_COST CHANGELING 30
DYNAMIC_COST WIZARD 30
@@ -319,7 +327,7 @@ DYNAMIC_COST METEOR 0
## Midround antags
DYNAMIC_COST MIDROUND_TRAITOR 10
-DYNAMIC_COST MALF_AI 35
+DYNAMIC_COST MIDROUND_MALF_AI 35
DYNAMIC_COST MIDROUND_WIZARD 20
DYNAMIC_COST MIDROUND_NUCLEAR 35
DYNAMIC_COST BLOB 10
@@ -335,6 +343,7 @@ DYNAMIC_COST LATEJOIN_REVOLUTION 20
## This means that 40 30 30 20 20 20 15 15 15 10 will not generate below 40 at 0-8, 30 at 9-17 etc.
DYNAMIC_REQUIREMENTS TRAITOR 40 30 20 15 15 15 15 15 15 15
DYNAMIC_REQUIREMENTS TRAITORBRO 50 40 30 20 20 15 15 15 15 15
+DYNAMIC_REQUIREMENTS MALF_AI 101 101 80 70 60 60 50 50 40 40
DYNAMIC_REQUIREMENTS CHANGELING 101 101 101 101 101 101 101 101 101 101
DYNAMIC_REQUIREMENTS WIZARD 100 90 70 40 30 20 15 15 15 15
DYNAMIC_REQUIREMENTS CULT 100 90 80 60 40 30 15 15 15 15
@@ -350,7 +359,7 @@ DYNAMIC_REQUIREMENTS METEOR 101 101 101 101 101 101 101 101 101 101
## Midround antags
DYNAMIC_REQUIREMENTS MIDROUND_TRAITOR 50 40 30 20 15 15 15 15 15 15
-DYNAMIC_REQUIREMENTS MALF_AI 101 101 80 70 60 60 50 50 40 40
+DYNAMIC_REQUIREMENTS MIDROUND_MALF_AI 101 101 80 70 60 60 50 50 40 40
DYNAMIC_REQUIREMENTS MIDROUND_WIZARD 90 90 70 40 30 20 15 15 15 15
DYNAMIC_REQUIREMENTS MIDROUND_NUCLEAR 90 90 90 80 60 40 30 20 15 15
DYNAMIC_REQUIREMENTS BLOB 101 101 101 80 60 50 30 20 15 15
@@ -363,6 +372,7 @@ DYNAMIC_REQUIREMENTS LATEJOIN_REVOLUTION 101 101 70 40 30 20 20 20 20 20
## An alternative, static requirement used instead when pop is over mode's high_pop_limit.
DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITOR 15
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MALF_AI 15
DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITORBRO 15
DYNAMIC_HIGH_POPULATION_REQUIREMENT CHANGELING 101
DYNAMIC_HIGH_POPULATION_REQUIREMENT WIZARD 15
@@ -379,7 +389,7 @@ DYNAMIC_HIGH_POPULATION_REQUIREMENT METEOR 101
## Midround antags
DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_TRAITOR 15
-DYNAMIC_HIGH_POPULATION_REQUIREMENT MALF_AI 35
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_MALF_AI 35
DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_WIZARD 50
DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_NUCLEAR 15
DYNAMIC_HIGH_POPULATION_REQUIREMENT BLOB 50
@@ -398,7 +408,14 @@ ALLOW_AI
## Allow the AI Multicamera feature to be used by AI players
ALLOW_AI_MULTICAM
+## CYBORG ##
+## Uncomment to disable the ability for cyborg flashes to knock down carbon targets
+#DISABLE_BORG_FLASH_KNOCKDOWN
+
## Secborg ###
+## Uncomment to bring secborgs and K-9s back in line with the rest of the modules available. This is strongly recommended if you have secborgs configured to be available at all times.
+#WEAKEN_SECBORG
+
## Uncomment to prevent the security cyborg module from being chosen
#DISABLE_SECBORG
diff --git a/config/maps.txt b/config/maps.txt
index 99a4543853..87e86a0800 100644
--- a/config/maps.txt
+++ b/config/maps.txt
@@ -10,6 +10,8 @@ Format:
maxplayers [number] (0 or less disables this requirement)
default (The last map with this defined will get all votes of players who have not explicitly voted for a map)
voteweight [number] (How much to count each player vote as, defaults to 1, setting to 0.5 counts each vote as half a vote, 2 as double, etc, Setting to 0 disables the map but allows players to still pick it)
+ max_round_search_span [number] (If this is nonzero, then if this map has been played more than a specified amount of times within this number of rounds, the map won't show up in votes. Max for this value determined by a define in persistence.dm)
+ max_rounds_played [number] (This determines how many times a map can be played within the above number of rounds before it's forbidden from votes.)
disabled (disables the map)
endmap
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
deleted file mode 100644
index 174aa8a22f..0000000000
--- a/goon/browserassets/css/browserOutput.css
+++ /dev/null
@@ -1,877 +0,0 @@
-/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.2;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
-
-em {
- font-style: normal;
- font-weight: bold;
-}
-
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
- -ms-interpolation-mode: nearest-neighbor;
- image-rendering: pixelated;
-}
-img.icon {
- height: 1em;
- min-height: 16px;
- width: auto;
- vertical-align: bottom;
-}
-
-
-.r:before { /* "repeated" badge class for combined messages */
- content: 'x';
-}
-.r {
- display: inline-block;
- min-width: 0.5em;
- font-size: 0.7em;
- padding: 0.2em 0.3em;
- line-height: 1;
- color: white;
- text-align: center;
- white-space: nowrap;
- vertical-align: middle;
- background-color: crimson;
- border-radius: 10px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 13px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 80px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#userBar {
- position: fixed;
- top: 0;
- right: 0;
-}
-#userBar .subCell {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#userBar .subCell:hover {background: #ccc;}
-#userBar .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#userBar .sub {clear: both; display: none; width: 160px;}
-#userBar .sub.scroll {overflow-y: scroll;}
-#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#userBar .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#userBar .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#userBar .sub input {
- position: absolute;
- padding: 7px 5px;
- width: 121px;
- line-height: 30px;
- float: left;
-}
-#userBar .topCell {border-top: 0;}
-
-/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.ooc { font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #700038; font-weight: bold;}
-
-.adminobserver {color: #996600; font-weight: bold;}
-.admin {color: #386aff; font-weight: bold;}
-
-.name { font-weight: bold;}
-
-.say {}
-.deadsay {color: #5c00e6;}
-.binarysay {color: #20c20e; background-color: #000000; display: block;}
-.binarysay a {color: #00ff00;}
-.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #008000;}
-.sciradio {color: #993399;}
-.comradio {color: #948f02;}
-.secradio {color: #a30000;}
-.medradio {color: #337296;}
-.engradio {color: #fb5613;}
-.suppradio {color: #a8732b;}
-.servradio {color: #6eaa2c;}
-.syndradio {color: #6d3f40;}
-.centcomradio {color: #686868;}
-.aiprivradio {color: #ff00ff;}
-.redteamradio {color: #ff0000;}
-.blueteamradio {color: #0000ff;}
-
-.yell { font-weight: bold;}
-
-.alert {color: #ff0000;}
-h1.alert, h2.alert {color: #000000;}
-
-.emote { font-style: italic;}
-.selecteddna {color: #ffffff; background-color: #001B1B}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.nicegreen {color: #14a833;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-
-.cultitalic {color: #960000; font-style: italic;}
-.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #5000A0;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.changeling {color: #800080; font-style: italic;}
-
-.spider {color: #4d004d;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-.spooky {color: #FF6100;}
-.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
-@keyframes velvet {
- 0% { color: #400020; }
- 40% { color: #FF0000; }
- 50% { color: #FF8888; }
- 60% { color: #FF0000; }
- 100% { color: #400020; }
-}
-
-.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
-@keyframes hypnocolor {
- 0% { color: #202020; }
- 25% { color: #4b02ac; }
- 50% { color: #9f41f1; }
- 75% { color: #541c9c; }
- 100% { color: #7adbf3; }
-}
-
-.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
-@keyframes phobia {
- 0% { color: #f75a5a; }
- 50% { color: #dd0000; }
- 100% { color: #f75a5a; }
-}
-
-.icon {height: 1em; width: auto;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
-.slime {color: #00CED1;}
-.drone {color: #848482;}
-.monkey {color: #975032;}
-.swarmer {color: #2C75FF;}
-.resonate {color: #298F85;}
-
-.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.2;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
-
-em {
- font-style: normal;
- font-weight: bold;
-}
-
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
- -ms-interpolation-mode: nearest-neighbor;
- image-rendering: pixelated;
-}
-img.icon {
- height: 1em;
- min-height: 16px;
- width: auto;
- vertical-align: bottom;
-}
-
-
-.r:before { /* "repeated" badge class for combined messages */
- content: 'x';
-}
-.r {
- display: inline-block;
- min-width: 0.5em;
- font-size: 0.7em;
- padding: 0.2em 0.3em;
- line-height: 1;
- color: white;
- text-align: center;
- white-space: nowrap;
- vertical-align: middle;
- background-color: crimson;
- border-radius: 10px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 13px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 80px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#userBar {
- position: fixed;
- top: 0;
- right: 0;
-}
-#userBar .subCell {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#userBar .subCell:hover {background: #ccc;}
-#userBar .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#userBar .sub {clear: both; display: none; width: 160px;}
-#userBar .sub.scroll {overflow-y: scroll;}
-#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#userBar .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#userBar .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#userBar .sub input {
- position: absolute;
- padding: 7px 5px;
- width: 121px;
- line-height: 30px;
- float: left;
-}
-#userBar .topCell {border-top: 0;}
-
-/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.ooc { font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #700038; font-weight: bold;}
-
-.adminsay {color: #FF4500; font-weight: bold;}
-.admin {color: #386aff; font-weight: bold;}
-
-.name { font-weight: bold;}
-
-.say {}
-.deadsay {color: #5c00e6;}
-.binarysay {color: #20c20e; background-color: #000000; display: block;}
-.binarysay a {color: #00ff00;}
-.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #008000;}
-.sciradio {color: #993399;}
-.comradio {color: #948f02;}
-.secradio {color: #a30000;}
-.medradio {color: #337296;}
-.engradio {color: #fb5613;}
-.suppradio {color: #a8732b;}
-.servradio {color: #6eaa2c;}
-.syndradio {color: #6d3f40;}
-.centcomradio {color: #686868;}
-.aiprivradio {color: #ff00ff;}
-.redteamradio {color: #ff0000;}
-.blueteamradio {color: #0000ff;}
-
-.yell { font-weight: bold;}
-
-.alert {color: #ff0000;}
-h1.alert, h2.alert {color: #000000;}
-
-.emote { font-style: italic;}
-.selecteddna {color: #ffffff; background-color: #001B1B}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.nicegreen {color: #14a833;}
-.userlove {color: #FF1493; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #ff6dbc;}
-.love {color: #ff006a; font-style: italic; text-shadow: 0 0 6px #ff6d6d;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-
-.cultitalic {color: #960000; font-style: italic;}
-.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #5000A0;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.changeling {color: #800080; font-style: italic;}
-
-.spider {color: #4d004d;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
-@keyframes hypnocolor {
- 0% { color: #202020; }
- 25% { color: #4b02ac; }
- 50% { color: #9f41f1; }
- 75% { color: #541c9c; }
- 100% { color: #7adbf3; }
-}
-
-.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
-@keyframes phobia {
- 0% { color: #f75a5a; }
- 50% { color: #dd0000; }
- 100% { color: #f75a5a; }
-}
-.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-
-.icon {height: 1em; width: auto;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
-.slime {color: #00CED1;}
-.drone {color: #848482;}
-.monkey {color: #975032;}
-.swarmer {color: #2C75FF;}
-.resonate {color: #298F85;}
-
-.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}
diff --git a/html/changelogs/AutoChangeLog-pr-8948.yml b/html/changelogs/AutoChangeLog-pr-8948.yml
new file mode 100644
index 0000000000..af3d28eb34
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8948.yml
@@ -0,0 +1,9 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - code_imp: "Cleaned up the absolute state of the arousal module."
+ - refactor: "refactored exhibitionism into a quirk."
+ - tweak: "arousal states won't persist after death."
+ - bugfix: "Fixes testicles size adjective thing."
+ - bugfix: "undergarments toggling now works instead of just making underwear disappear and not come back."
+ - tweak: "The \"Always visible\" genitals setting will now display them above clothes."
diff --git a/html/changelogs/AutoChangeLog-pr-9350.yml b/html/changelogs/AutoChangeLog-pr-9350.yml
new file mode 100644
index 0000000000..fe91058892
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9350.yml
@@ -0,0 +1,5 @@
+author: "Tupinambis"
+delete-after: True
+changes:
+ - imageadd: "Beautified and stylized the cyborg HUD sprites, animated and cleaned up some of the old, modernized APC hacking and Doomsday sprites,"
+ - tweak: "moved cyborg language select above the radio icon, instead of above the picture icon."
diff --git a/html/changelogs/AutoChangeLog-pr-9423.yml b/html/changelogs/AutoChangeLog-pr-9423.yml
new file mode 100644
index 0000000000..6e8916c090
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9423.yml
@@ -0,0 +1,4 @@
+author: "Poojawa"
+delete-after: True
+changes:
+ - tweak: "Active NPC priority set much higher priority for the MC, with the intent on making NPC combat more interesting"
diff --git a/html/changelogs/AutoChangeLog-pr-9469.yml b/html/changelogs/AutoChangeLog-pr-9469.yml
new file mode 100644
index 0000000000..526f5f855a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9469.yml
@@ -0,0 +1,5 @@
+author: "Bhijn"
+delete-after: True
+changes:
+ - balance: "Vampires can now only ventcrawl in bat form if their blood level is below the bad blood volume (224 blood total)"
+ - balance: "Vampires now only take 5 burn per mob life cycle while within chapel areas, down from the original 20 burn per life cycle."
diff --git a/html/changelogs/AutoChangeLog-pr-9480.yml b/html/changelogs/AutoChangeLog-pr-9480.yml
new file mode 100644
index 0000000000..048ebdbce1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9480.yml
@@ -0,0 +1,4 @@
+author: "Poojawa"
+delete-after: True
+changes:
+ - bugfix: "Clarified access descriptions of some jobs"
diff --git a/html/changelogs/AutoChangeLog-pr-9494.yml b/html/changelogs/AutoChangeLog-pr-9494.yml
new file mode 100644
index 0000000000..6bfc34443b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9494.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "fixing some related onmob sprites issues with the above accessory."
diff --git a/html/changelogs/AutoChangeLog-pr-9500.yml b/html/changelogs/AutoChangeLog-pr-9500.yml
new file mode 100644
index 0000000000..02b45e2329
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9500.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Teleprods work on non-carbons mobs now."
diff --git a/html/changelogs/AutoChangeLog-pr-9501.yml b/html/changelogs/AutoChangeLog-pr-9501.yml
new file mode 100644
index 0000000000..a025db1874
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9501.yml
@@ -0,0 +1,12 @@
+author: "Bhijn"
+delete-after: True
+changes:
+ - tweak: "K9 pounces have received a minor rework. It now has an effective cooldown of 2.5 seconds, can now only deal up to 120 staminaloss, deals a maximum of 80 stamloss on hit, has a spoolup of half a second, and now has telegraphing in the form of a quiet noise."
+ - balance: "K9s now only have 80 health"
+ - balance: "Secborgs (but not k9s) now have a hybrid taser. This can be toggled via server config."
+ - tweak: "The disabler cooler upgrade now applies to all energy-based firearms for borgs"
+ - rscadd: "Dogborg jaws are now capable of incapacitating targets if using help intent. This deals a hard stun depending on how much staminaloss the target has, and whether or not they're resting. This behavior can be toggled via server config."
+ - balance: "K9 jaws now have 15 force, up from their nerfed 10 force."
+ - balance: "Borg flashes regained their ability to cause knockdown. This can be toggled via server config."
+ - server: "The WEAKEN_SECBORG config option will disable the new dogborg jaws mechanic and make secborgs spawn with a standard disabler."
+ - server: "The DISABLE_BORG_FLASH_KNOCKDOWN will disable the ability for borg flashes to knockdown."
diff --git a/html/changelogs/AutoChangeLog-pr-9513.yml b/html/changelogs/AutoChangeLog-pr-9513.yml
new file mode 100644
index 0000000000..ae4a8c246c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9513.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - balance: "Medibots no longer kill slimes when trying to heal their toxins."
diff --git a/html/changelogs/AutoChangeLog-pr-9531.yml b/html/changelogs/AutoChangeLog-pr-9531.yml
new file mode 100644
index 0000000000..907082a25e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9531.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "Increased stunbatons power cell depletion rate when left on by 50%."
diff --git a/html/changelogs/AutoChangeLog-pr-9532.yml b/html/changelogs/AutoChangeLog-pr-9532.yml
new file mode 100644
index 0000000000..165ed08012
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9532.yml
@@ -0,0 +1,4 @@
+author: "MrJWhit"
+delete-after: True
+changes:
+ - balance: "rebalance melee stamloss"
diff --git a/html/changelogs/AutoChangeLog-pr-9533.yml b/html/changelogs/AutoChangeLog-pr-9533.yml
new file mode 100644
index 0000000000..cc62c6a025
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9533.yml
@@ -0,0 +1,4 @@
+author: "JTGSZ"
+delete-after: True
+changes:
+ - bugfix: "Can flip pipes once more."
diff --git a/html/changelogs/AutoChangeLog-pr-9539.yml b/html/changelogs/AutoChangeLog-pr-9539.yml
new file mode 100644
index 0000000000..c6e687d444
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9539.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - rscadd: "The Syndicate started selling claymores to their agents."
diff --git a/html/changelogs/AutoChangeLog-pr-9570.yml b/html/changelogs/AutoChangeLog-pr-9570.yml
new file mode 100644
index 0000000000..6cf825b835
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9570.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - rscadd: "peacekeeper cyborgs now get a megaphone"
diff --git a/html/changelogs/AutoChangeLog-pr-9572.yml b/html/changelogs/AutoChangeLog-pr-9572.yml
new file mode 100644
index 0000000000..767a78c3bc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9572.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - bugfix: "Fixes storage bugs regarding reaching into things you shouldn't be able to reach into."
diff --git a/html/changelogs/AutoChangeLog-pr-9578.yml b/html/changelogs/AutoChangeLog-pr-9578.yml
new file mode 100644
index 0000000000..c63fb17074
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9578.yml
@@ -0,0 +1,6 @@
+author: "deathride58"
+delete-after: True
+changes:
+ - rscadd: "There is now a 1% chance for the station's announcer to be the medibot voice instead of the classic TG announcer."
+ - rscadd: "The map config system has been expanded to allow mappers to specify the map type, announcer voice, ingame year, and how often a given map can be voted at roundend."
+ - bugfix: "The map vote system now takes into account map playercount limits properly."
diff --git a/html/changelogs/AutoChangeLog-pr-9590.yml b/html/changelogs/AutoChangeLog-pr-9590.yml
new file mode 100644
index 0000000000..5410681ebb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9590.yml
@@ -0,0 +1,6 @@
+author: "Ghommie (original PR by cacogen)"
+delete-after: True
+changes:
+ - rscadd: "The font size of all text in the chat window now scales"
+ - tweak: "High volume (megaphone/head of staff headset) is a slightly smaller"
+ - tweak: "Admins have slightly larger OOC text"
diff --git a/html/changelogs/AutoChangeLog-pr-9592.yml b/html/changelogs/AutoChangeLog-pr-9592.yml
new file mode 100644
index 0000000000..a311112434
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9592.yml
@@ -0,0 +1,4 @@
+author: "Ghommie (original PRs by ninjanomnom, coiax, yoyobatty)"
+delete-after: True
+changes:
+ - bugfix: "Fixed slaughter demons not getting a speed boost when exiting a pool of blood. Fixed slaughter demon giblets not being visible."
diff --git a/html/changelogs/AutoChangeLog-pr-9598.yml b/html/changelogs/AutoChangeLog-pr-9598.yml
new file mode 100644
index 0000000000..76f1ceb578
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9598.yml
@@ -0,0 +1,6 @@
+author: "deathride58"
+delete-after: True
+changes:
+ - bugfix: "Plasmaman tongues no longer have a maxHealth of \"alien\", and no longer cause the organ's on_life to always runtime."
+ - bugfix: "Shooting a simplemob no longer causes runtimes prior to the blood effect being created."
+ - bugfix: "Removing a filter from an object that lacks filters no longer causes runtimes."
diff --git a/html/changelogs/AutoChangeLog-pr-9599.yml b/html/changelogs/AutoChangeLog-pr-9599.yml
new file mode 100644
index 0000000000..83063c12fc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9599.yml
@@ -0,0 +1,4 @@
+author: "Onule & Nemvar (ported by Ghommie)"
+delete-after: True
+changes:
+ - imageadd: "New Revenant icons"
diff --git a/html/changelogs/AutoChangeLog-pr-9600.yml b/html/changelogs/AutoChangeLog-pr-9600.yml
new file mode 100644
index 0000000000..e7c7c1da92
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9600.yml
@@ -0,0 +1,4 @@
+author: "Trilbyspaceclone"
+delete-after: True
+changes:
+ - rscadd: "Added two seed packets of cotten to ash walkers base"
diff --git a/html/changelogs/AutoChangeLog-pr-9603.yml b/html/changelogs/AutoChangeLog-pr-9603.yml
new file mode 100644
index 0000000000..32b9afb97e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9603.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "fixing cydonian armor a bit."
diff --git a/html/changelogs/AutoChangeLog-pr-9610.yml b/html/changelogs/AutoChangeLog-pr-9610.yml
new file mode 100644
index 0000000000..85739fcfcb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9610.yml
@@ -0,0 +1,7 @@
+author: "Ghommie (original PRs by XDTM, 4dplanner, nemvar and, yes, myself)"
+delete-after: True
+changes:
+ - code_imp: "Merged tinfoil hat kind of protection into the anti_magic component."
+ - rscadd: "Tinfoil hats can also be warped up from excessive dampening of mindray/though control/psicotronic anomalies, or by simply being microwaved in an oven, and become useless."
+ - rscadd: "Immortality Talisman and Paranormal Hardsuit helmets now come with tinfoil protection too (minus the paranoia and limited charges)."
+ - balance: "Genetics/Slime/Alien Telepathy and Slime Link are now stopped by tinfoil protection."
diff --git a/html/changelogs/AutoChangeLog-pr-9613.yml b/html/changelogs/AutoChangeLog-pr-9613.yml
new file mode 100644
index 0000000000..2056d9479c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9613.yml
@@ -0,0 +1,4 @@
+author: "Linzolle"
+delete-after: True
+changes:
+ - rscadd: "Target head and throw a hat at someone to toss it onto their head, knocking whatever they're wearing off if they are wearing a hat. Some headgear can't be knocked off this way."
diff --git a/html/changelogs/AutoChangeLog-pr-9615.yml b/html/changelogs/AutoChangeLog-pr-9615.yml
new file mode 100644
index 0000000000..4c6d95055c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9615.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Resprited wooden and critter crates."
diff --git a/html/changelogs/AutoChangeLog-pr-9616.yml b/html/changelogs/AutoChangeLog-pr-9616.yml
new file mode 100644
index 0000000000..e9fb19e63b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9616.yml
@@ -0,0 +1,7 @@
+author: "Bhijn"
+delete-after: True
+changes:
+ - tweak: "Jukeboxes now have 6 audio channels available to them, up from the previous accidental 2 and previously intended 5 channels."
+ - bugfix: "Jukeboxes now work again on clients running versions higher than 512.1459."
+ - bugfix: "People will no longer have their ears consumed by an eldritch god if multiple jukeboxes are active and the first jukebox in the jukebox list stops playing, then tries to play again"
+ - tweak: "Instead of the debug text for invalid jukebox behavior being printed to world, the debug text is now restricted to the runtime panel."
diff --git a/html/changelogs/AutoChangeLog-pr-9617.yml b/html/changelogs/AutoChangeLog-pr-9617.yml
new file mode 100644
index 0000000000..9c8e3fbdf2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9617.yml
@@ -0,0 +1,4 @@
+author: "JTGSZ"
+delete-after: True
+changes:
+ - bugfix: "barricade girder walls use PlaceOnTop instead of new"
diff --git a/html/changelogs/AutoChangeLog-pr-9620.yml b/html/changelogs/AutoChangeLog-pr-9620.yml
new file mode 100644
index 0000000000..c6f5a460da
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9620.yml
@@ -0,0 +1,5 @@
+author: "YakumoChen"
+delete-after: True
+changes:
+ - rscadd: "Adds beanbag slugs to the sec protolathe at round start"
+ - bugfix: "Brings shotgun ammo availability back in like between seclathe and autolathe."
diff --git a/html/changelogs/AutoChangeLog-pr-9622.yml b/html/changelogs/AutoChangeLog-pr-9622.yml
new file mode 100644
index 0000000000..4a0fb38248
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9622.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Improved the Cyber Sylph' good yet cumbersome bar sign a little."
diff --git a/html/changelogs/AutoChangeLog-pr-9623.yml b/html/changelogs/AutoChangeLog-pr-9623.yml
new file mode 100644
index 0000000000..4ad167ca48
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9623.yml
@@ -0,0 +1,5 @@
+author: "Sirich96 and Dennok (ported by Ghommie)"
+delete-after: True
+changes:
+ - rscadd: "Added new Teleporter Station sprites"
+ - rscadd: "Added teleport station calibration animation."
diff --git a/html/changelogs/AutoChangeLog-pr-9630.yml b/html/changelogs/AutoChangeLog-pr-9630.yml
new file mode 100644
index 0000000000..b9e583297c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9630.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Cyborgs can now use camera consoles on the edge of their widescreen. These consoles are also TK friendly now."
diff --git a/html/changelogs/AutoChangeLog-pr-9635.yml b/html/changelogs/AutoChangeLog-pr-9635.yml
new file mode 100644
index 0000000000..946a1ffe13
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9635.yml
@@ -0,0 +1,17 @@
+author: "Thalpy"
+delete-after: True
+changes:
+ - bugfix: "1. Kev asked that there were no antag datums used, so that's been changed.
+2. Tricks can no longer turn someone into a dullahan, instead you have to spend candies to get that. I felt it was too mean to turn people into that, I didn't realise you couldn't revert it.
+3. Barth will no longer as for impossible items.
+4. Barth will no longer as for the same item multiple times.
+5. Barth will now accept broader things, rather than asking for something, when meaning something specific.
+6. Jacq will now no longer poof off the z level.
+7. Jacq will (hopefully) stop spooking the AI by teleporting into there
+8. Jacq will now try to teleport to a location with someone nearby.
+9. Barth will tell you where Jacq is currently when you speak to him.
+10. You can trade 2 candies for a Jacq Tracq (tm)
+11. Jacq should stop getting mad and cover the station in gas when killed.
+12. Fixed Jacq not singing (the link died).
+13. Slightly changed wording so that people will hopefully get to know her.
+14. Jacq no longer disappears when you're getting to know her."
diff --git a/html/changelogs/AutoChangeLog-pr-9636.yml b/html/changelogs/AutoChangeLog-pr-9636.yml
new file mode 100644
index 0000000000..986ece65bb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9636.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Updated gang dominator sprites."
diff --git a/html/changelogs/AutoChangeLog-pr-9637.yml b/html/changelogs/AutoChangeLog-pr-9637.yml
new file mode 100644
index 0000000000..29832a5d4b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9637.yml
@@ -0,0 +1,4 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - code_imp: "BYOND 513 preliminary support added."
diff --git a/html/changelogs/AutoChangeLog-pr-9641.yml b/html/changelogs/AutoChangeLog-pr-9641.yml
new file mode 100644
index 0000000000..61a4521580
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9641.yml
@@ -0,0 +1,5 @@
+author: "kevinz000"
+delete-after: True
+changes:
+ - balance: "Trashbags now only allow accessing the first 3 items. 5 for bluespace ones.
+experimental: Storage now allows for limiting of random access"
diff --git a/html/changelogs/AutoChangeLog-pr-9644.yml b/html/changelogs/AutoChangeLog-pr-9644.yml
new file mode 100644
index 0000000000..383305ef29
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9644.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Miner borgs can again have installed PKA mods."
diff --git a/html/changelogs/AutoChangeLog-pr-9645.yml b/html/changelogs/AutoChangeLog-pr-9645.yml
new file mode 100644
index 0000000000..a7a10e7a58
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9645.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed invisible blackberry n strawberry chocolate cake slices."
diff --git a/html/changelogs/AutoChangeLog-pr-9646.yml b/html/changelogs/AutoChangeLog-pr-9646.yml
new file mode 100644
index 0000000000..379b78aef0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9646.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Nuke ops / adminbus combat mechs will no longer spawn with tracking beacons."
diff --git a/html/changelogs/AutoChangeLog-pr-9647.yml b/html/changelogs/AutoChangeLog-pr-9647.yml
new file mode 100644
index 0000000000..e8fa254472
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9647.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Arcade machine directional sprites."
diff --git a/html/changelogs/AutoChangeLog-pr-9648.yml b/html/changelogs/AutoChangeLog-pr-9648.yml
new file mode 100644
index 0000000000..196a27198c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9648.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - tweak: "lowered the arcade's random plush / other prizes ratio from 1 : 2.5 circa to 1 : 5. Dehydratated carps and the awakened plush can not be achieved this way anymore."
diff --git a/html/changelogs/AutoChangeLog-pr-9649.yml b/html/changelogs/AutoChangeLog-pr-9649.yml
new file mode 100644
index 0000000000..23bcf3e005
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9649.yml
@@ -0,0 +1,4 @@
+author: "Fermis"
+delete-after: True
+changes:
+ - bugfix: "fixed Jacq's fondness for the AI"
diff --git a/html/changelogs/AutoChangeLog-pr-9651.yml b/html/changelogs/AutoChangeLog-pr-9651.yml
new file mode 100644
index 0000000000..92dac62b19
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9651.yml
@@ -0,0 +1,4 @@
+author: "Alonefromhell"
+delete-after: True
+changes:
+ - bugfix: "fixes tootip offset"
diff --git a/html/changelogs/AutoChangeLog-pr-9652.yml b/html/changelogs/AutoChangeLog-pr-9652.yml
new file mode 100644
index 0000000000..acbaa139f1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9652.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Added armrests overlays to sofas and tweaked their sprites a little."
diff --git a/html/changelogs/AutoChangeLog-pr-9654.yml b/html/changelogs/AutoChangeLog-pr-9654.yml
new file mode 100644
index 0000000000..420697aec5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9654.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - config: "Added dynamic midround/latejoin antag injection to the config."
diff --git a/html/changelogs/AutoChangeLog-pr-9658.yml b/html/changelogs/AutoChangeLog-pr-9658.yml
new file mode 100644
index 0000000000..199f847c4e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9658.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed dogborg sleepers. Just don't tell me what is exactly fixed, cause I don't want to find out."
diff --git a/html/changelogs/AutoChangeLog-pr-9659.yml b/html/changelogs/AutoChangeLog-pr-9659.yml
new file mode 100644
index 0000000000..2590aec672
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9659.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Buffed the deep space familiar gorilla against runtimes."
diff --git a/html/changelogs/AutoChangeLog-pr-9667.yml b/html/changelogs/AutoChangeLog-pr-9667.yml
new file mode 100644
index 0000000000..96488edaff
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9667.yml
@@ -0,0 +1,4 @@
+author: "kappa-sama"
+delete-after: True
+changes:
+ - bugfix: "kevinz forgot to nerf miasma research and cargo value after making it produce like 100x as much lmao"
diff --git a/html/changelogs/AutoChangeLog-pr-9668.yml b/html/changelogs/AutoChangeLog-pr-9668.yml
new file mode 100644
index 0000000000..b892f7c3ea
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9668.yml
@@ -0,0 +1,5 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - balance: "Made starlight condensation not kill slime people."
+ - balance: "Added not-killing-slime-people to the transmission threshold of plasma fixation and radioactive resonance."
diff --git a/html/changelogs/AutoChangeLog-pr-9674.yml b/html/changelogs/AutoChangeLog-pr-9674.yml
new file mode 100644
index 0000000000..9ca51c9b0e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9674.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - imageadd: "Updated ratvarian computer sprites."
diff --git a/html/changelogs/AutoChangeLog-pr-9675.yml b/html/changelogs/AutoChangeLog-pr-9675.yml
new file mode 100644
index 0000000000..35d9110f7b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9675.yml
@@ -0,0 +1,4 @@
+author: "PersianXerxes"
+delete-after: True
+changes:
+ - tweak: "Relocates cult catwalks outside the Reebe dressing room."
diff --git a/html/changelogs/AutoChangeLog-pr-9677.yml b/html/changelogs/AutoChangeLog-pr-9677.yml
new file mode 100644
index 0000000000..8b8608ff29
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9677.yml
@@ -0,0 +1,4 @@
+author: "Putnam3145"
+delete-after: True
+changes:
+ - tweak: "Made the clone scanner lock while it's scanning."
diff --git a/html/changelogs/AutoChangeLog-pr-9679.yml b/html/changelogs/AutoChangeLog-pr-9679.yml
new file mode 100644
index 0000000000..b2b3a718c4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9679.yml
@@ -0,0 +1,5 @@
+author: "ninjanomnom and WhoneedSpacee"
+delete-after: True
+changes:
+ - rscadd: "Some rpg affixes now have special effects"
+ - rscadd: "New RPGLoot modifiers: Vampirism which heals you when you attack, Pyromantic which sets things you hit on fire. Shrapnel which causes projectiles fired from a gun to fire projectiles in a radius when they hit something. Finally, Summoning which summons mobs that sometimes aid you in combat."
diff --git a/html/changelogs/AutoChangeLog-pr-9686.yml b/html/changelogs/AutoChangeLog-pr-9686.yml
new file mode 100644
index 0000000000..18e411c3dc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9686.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed storage implant transplant."
diff --git a/html/changelogs/AutoChangeLog-pr-9687.yml b/html/changelogs/AutoChangeLog-pr-9687.yml
new file mode 100644
index 0000000000..3bc1644806
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-9687.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Refactored how Jacqueen teleportation destination is selected, preventing them from teleporting on off-station holopads."
diff --git a/icons/mob/actions/actions_AI.dmi b/icons/mob/actions/actions_AI.dmi
index 2ddc7923cc..e3ff3aba93 100644
Binary files a/icons/mob/actions/actions_AI.dmi and b/icons/mob/actions/actions_AI.dmi differ
diff --git a/icons/mob/actions/backgrounds.dmi b/icons/mob/actions/backgrounds.dmi
index 82303c5862..3697fe4ff5 100644
Binary files a/icons/mob/actions/backgrounds.dmi and b/icons/mob/actions/backgrounds.dmi differ
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index e9343c7ed2..a46ad83640 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/augmentation/augments.dmi b/icons/mob/augmentation/augments.dmi
index 574a5ddc48..e311b6605d 100644
Binary files a/icons/mob/augmentation/augments.dmi and b/icons/mob/augmentation/augments.dmi differ
diff --git a/icons/mob/augmentation/augments_engineer.dmi b/icons/mob/augmentation/augments_engineer.dmi
index 7f2b2e8de9..8aac118b35 100644
Binary files a/icons/mob/augmentation/augments_engineer.dmi and b/icons/mob/augmentation/augments_engineer.dmi differ
diff --git a/icons/mob/augmentation/augments_mining.dmi b/icons/mob/augmentation/augments_mining.dmi
index 39df4823fd..61d8cc30e5 100644
Binary files a/icons/mob/augmentation/augments_mining.dmi and b/icons/mob/augmentation/augments_mining.dmi differ
diff --git a/icons/mob/augmentation/augments_security.dmi b/icons/mob/augmentation/augments_security.dmi
index 2679f7c9f8..e954c6e22a 100644
Binary files a/icons/mob/augmentation/augments_security.dmi and b/icons/mob/augmentation/augments_security.dmi differ
diff --git a/icons/mob/augmentation/surplus_augments.dmi b/icons/mob/augmentation/surplus_augments.dmi
index bc3e4bd73c..d2eb194c28 100644
Binary files a/icons/mob/augmentation/surplus_augments.dmi and b/icons/mob/augmentation/surplus_augments.dmi differ
diff --git a/icons/mob/custom_w.dmi b/icons/mob/custom_w.dmi
index f29231c48d..b572338fc6 100644
Binary files a/icons/mob/custom_w.dmi and b/icons/mob/custom_w.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 842562b007..3d8f26a82e 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi
index 6bd504674f..916686e63f 100644
Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ
diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi
index 8b894fea6b..ab30929727 100644
Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index bbeddf9152..3750e28906 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi
index d306e22892..2169b87580 100644
Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi
index 3e0c3424d3..f054d8f744 100644
Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 9beedfb417..4de67f41f8 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 8142e03498..d724747a50 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/screen_cyborg.dmi b/icons/mob/screen_cyborg.dmi
index 7c64ace299..632443036e 100644
Binary files a/icons/mob/screen_cyborg.dmi and b/icons/mob/screen_cyborg.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 38ac61f318..b0fb5984c3 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/1x2.dmi b/icons/obj/1x2.dmi
new file mode 100644
index 0000000000..ec3bcac2fa
Binary files /dev/null and b/icons/obj/1x2.dmi differ
diff --git a/icons/obj/barsigns.dmi b/icons/obj/barsigns.dmi
index 2c4d401088..1fffa2e540 100644
Binary files a/icons/obj/barsigns.dmi and b/icons/obj/barsigns.dmi differ
diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi
index 507801844c..a3b0d19df4 100644
Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ
diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi
index 5b9e13ed52..89acf0645e 100644
Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ
diff --git a/icons/obj/citvending.dmi b/icons/obj/citvending.dmi
index 37c2c8fcf1..8f836b7eb5 100644
Binary files a/icons/obj/citvending.dmi and b/icons/obj/citvending.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index c8a007041b..6fb50da207 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index fb406fb65e..852638bc3d 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/computer.dmi b/icons/obj/computer.dmi
index 1307f063a8..74ca148039 100644
Binary files a/icons/obj/computer.dmi and b/icons/obj/computer.dmi differ
diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi
index 3ab7f4b510..ca81686e94 100644
Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ
diff --git a/icons/obj/custom.dmi b/icons/obj/custom.dmi
index 92f7f50279..bbb813d7c9 100644
Binary files a/icons/obj/custom.dmi and b/icons/obj/custom.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 08b605a1d6..db0e5a301a 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi
index 75df4b5cc5..2ea48828d2 100644
Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ
diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi
index a6d5c8a5e1..ca339b5262 100644
Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ
diff --git a/icons/obj/hydroponics/growing_fruits.dmi b/icons/obj/hydroponics/growing_fruits.dmi
index 029d49e196..dfcb54b7b9 100644
Binary files a/icons/obj/hydroponics/growing_fruits.dmi and b/icons/obj/hydroponics/growing_fruits.dmi differ
diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi
index fa5728f3b4..63dc8b98fd 100644
Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ
diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi
index 7caf346f91..3c625cbe40 100644
Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ
diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi
index 416b0ef58b..e41135b446 100644
Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ
diff --git a/icons/obj/machines/dominator.dmi b/icons/obj/machines/dominator.dmi
index 42337dc1c8..3718fc4f83 100644
Binary files a/icons/obj/machines/dominator.dmi and b/icons/obj/machines/dominator.dmi differ
diff --git a/icons/obj/machines/mining_machines.dmi b/icons/obj/machines/mining_machines.dmi
index 28d608125d..aa60e7100c 100644
Binary files a/icons/obj/machines/mining_machines.dmi and b/icons/obj/machines/mining_machines.dmi differ
diff --git a/icons/obj/machines/teleporter.dmi b/icons/obj/machines/teleporter.dmi
index 1d3c97199b..08c014af8f 100644
Binary files a/icons/obj/machines/teleporter.dmi and b/icons/obj/machines/teleporter.dmi differ
diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi
index 1b8dacf36d..eb3ca4b2f7 100644
Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ
diff --git a/icons/obj/sofa.dmi b/icons/obj/sofa.dmi
index dafe06a7f1..069fb1e08d 100644
Binary files a/icons/obj/sofa.dmi and b/icons/obj/sofa.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index fae8134791..68bf9bd2bd 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi
index cad28e12fe..dd8f7bed1d 100644
Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ
diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi
index 59bc7a8e7c..b474dc68ba 100644
Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ
diff --git a/modular_citadel/code/controllers/subsystem/shuttle.dm b/modular_citadel/code/controllers/subsystem/shuttle.dm
index ce3f062bdd..567b23f202 100644
--- a/modular_citadel/code/controllers/subsystem/shuttle.dm
+++ b/modular_citadel/code/controllers/subsystem/shuttle.dm
@@ -1,7 +1,7 @@
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
SSshuttle.emergency.request(silent = TRUE)
- priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, 'sound/ai/shuttlecalled.ogg', "Priority")
+ priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
log_game("Round time limit reached. Shuttle has been auto-called.")
message_admins("Round time limit reached. Shuttle called.")
emergencyNoRecall = TRUE
diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm
index c5b9ca10ea..abf68cc398 100644
--- a/modular_citadel/code/datums/status_effects/chems.dm
+++ b/modular_citadel/code/datums/status_effects/chems.dm
@@ -37,64 +37,62 @@
alert_type = null
var/moveCalc = 1
var/cachedmoveCalc = 1
+ var/last_checked_size //used to prevent potential cpu waste from happening every tick.
-/datum/status_effect/chem/breast_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now.
+/datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now.
log_game("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]")
- var/mob/living/carbon/human/o = owner
- var/items = o.get_contents()
- for(var/obj/item/W in items)
- if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!
")
- o.visible_message("[o]'s chest suddenly bursts forth, ripping their clothes off!'")
- else
- to_chat(o, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.")
- return ..()
+ var/mob/living/carbon/human/H = owner
+ var/message = FALSE
+ if(H.w_uniform)
+ H.dropItemToGround(H.w_uniform, TRUE)
+ message = TRUE
+ if(H.wear_suit)
+ H.dropItemToGround(H.wear_suit, TRUE)
+ message = TRUE
+ if(message)
+ playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ H.visible_message("[H]'s chest suddenly bursts forth, ripping their clothes off!'", \
+ "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!")
+ else
+ to_chat(H, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.")
+ return ..()
-/datum/status_effect/chem/breast_enlarger/tick(mob/living/carbon/human/H)//If you try to wear clothes, you fail. Slows you down if you're comically huge
- var/mob/living/carbon/human/o = owner
- var/obj/item/organ/genital/breasts/B = o.getorganslot("breasts")
- moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click.
+/datum/status_effect/chem/breast_enlarger/tick()//If you try to wear clothes, you fail. Slows you down if you're comically huge
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS)
if(!B)
- o.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED)
- sizeMoveMod(1)
- owner.remove_status_effect(src)
- var/items = o.get_contents()
- for(var/obj/item/W in items)
- if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(owner, "Your enormous breasts are way too large to fit anything over them!")
+ H.remove_status_effect(src)
+ return
+ moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click.
+ var/message = FALSE
+ if(H.w_uniform)
+ H.dropItemToGround(H.w_uniform, TRUE)
+ message = TRUE
+ if(H.wear_suit)
+ H.dropItemToGround(H.wear_suit, TRUE)
+ message = TRUE
+ if(message)
+ playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(H, "Your enormous breasts are way too large to fit anything over them!")
+
+ if(last_checked_size != B.cached_size)
+ H.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
+ sizeMoveMod(moveCalc)
+
if (B.size == "huge")
if(prob(1))
to_chat(owner, "Your back is feeling sore.")
- var/target = o.get_bodypart(BODY_ZONE_CHEST)
- o.apply_damage(0.1, BRUTE, target)
- if(!B.cached_size == B.breast_values[B.prev_size])
- o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
- sizeMoveMod(moveCalc)
- return ..()
- else if (B.breast_values[B.size] > B.breast_values[B.prev_size])
- o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
- sizeMoveMod(moveCalc)
- else if (B.breast_values[B.size] < B.breast_values[B.prev_size])
- o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
- sizeMoveMod(moveCalc)
- if((B.cached_size) < 16)
- switch(round(B.cached_size))
- if(9)
- if (B.breast_values[B.prev_size] != B.breast_values[B.size])
- to_chat(o, "Your expansive chest has become a more managable size, liberating your movements.")
- if(10 to INFINITY)
- if (B.breast_values[B.prev_size] != B.breast_values[B.size])
- to_chat(H, "Your indulgent busom is so substantial, it's affecting your movements!")
+ var/target = H.get_bodypart(BODY_ZONE_CHEST)
+ H.apply_damage(0.1, BRUTE, target)
+ else
if(prob(1))
- to_chat(owner, "Your back is feeling a little sore.")
- ..()
+ to_chat(H, "Your back is feeling a little sore.")
+ last_checked_size = B.cached_size
+ ..()
-/datum/status_effect/chem/breast_enlarger/on_remove(mob/living/carbon/M)
+/datum/status_effect/chem/breast_enlarger/on_remove()
log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]")
+ to_chat(owner, "Your expansive chest has become a more managable size, liberating your movements.")
owner.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED)
sizeMoveMod(1)
@@ -112,51 +110,57 @@
alert_type = null
var/bloodCalc
var/moveCalc
+ var/last_checked_size //used to prevent potential cpu waste, just like the above.
-/datum/status_effect/chem/penis_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now.
+/datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now.
log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]")
- var/mob/living/carbon/human/o = owner
- var/items = o.get_contents()
- if(o.w_uniform || o.wear_suit)
- to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!")
- owner.visible_message("[o]'s schlong suddenly bursts forth, ripping their clothes off!'")
+ var/mob/living/carbon/human/H = owner
+ var/message = FALSE
+ if(H.w_uniform)
+ H.dropItemToGround(H.w_uniform, TRUE)
+ message = TRUE
+ if(H.wear_suit)
+ H.dropItemToGround(H.wear_suit, TRUE)
+ message = TRUE
+ if(message)
+ playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ H.visible_message("[H]'s schlong suddenly bursts forth, ripping their clothes off!'", \
+ "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!")
else
- to_chat(o, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.")
- for(var/obj/item/W in items)
- if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(H, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.")
return ..()
-/datum/status_effect/chem/penis_enlarger/tick(mob/living/carbon/M)
- var/mob/living/carbon/human/o = owner
- var/obj/item/organ/genital/penis/P = o.getorganslot("penis")
+/datum/status_effect/chem/penis_enlarger/tick()
+ var/mob/living/carbon/human/H = owner
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(!P)
+ owner.remove_status_effect(src)
+ return
moveCalc = 1+((round(P.length) - 21)/3) //effects how fast you can move
bloodCalc = 1+((round(P.length) - 21)/15) //effects how much blood you need (I didn' bother adding an arousal check because I'm spending too much time on this organ already.)
- if(!P)
- o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
- o.ResetBloodVol()
- owner.remove_status_effect(src)
- var/items = o.get_contents()
- for(var/obj/item/W in items)
- if(W == o.w_uniform || W == o.wear_suit)
- o.dropItemToGround(W, TRUE)
- playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- to_chat(owner, "Your enormous package is way to large to fit anything over!")
- switch(round(P.cached_length))
- if(21)
- to_chat(o, "Your rascally willy has become a more managable size, liberating your movements.")
- o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
- o.AdjustBloodVol(bloodCalc)
- if(22 to INFINITY)
- if(prob(2))
- to_chat(o, "Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!")
- o.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
- o.AdjustBloodVol(bloodCalc)
+
+ var/message = FALSE
+ if(H.w_uniform)
+ H.dropItemToGround(H.w_uniform, TRUE)
+ message = TRUE
+ if(H.wear_suit)
+ H.dropItemToGround(H.wear_suit, TRUE)
+ message = TRUE
+ if(message)
+ playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ to_chat(H, "Your enormous package is way to large to fit anything over!")
+
+ if(P.length < 22 && H.has_movespeed_modifier(DICK_MOVEMENT_SPEED))
+ to_chat(owner, "Your rascally willy has become a more managable size, liberating your movements.")
+ H.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
+ else if(P.length >= 22 && !H.has_movespeed_modifier(DICK_MOVEMENT_SPEED))
+ to_chat(H, "Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!")
+ H.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
+ H.AdjustBloodVol(bloodCalc)
..()
-/datum/status_effect/chem/penis_enlarger/on_remove(mob/living/carbon/human/o)
+/datum/status_effect/chem/penis_enlarger/on_remove()
log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]")
owner.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
owner.ResetBloodVol()
@@ -499,7 +503,7 @@
cooldown += 1 //Cooldown doesn't process till status is done
else if(status == "charge")
- ADD_TRAIT(owner, TRAIT_GOTTAGOFAST, "MKUltra")
+ owner.add_movespeed_modifier(MOVESPEED_ID_MKULTRA, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
status = "charged"
if(master.client?.prefs.lewdchem)
to_chat(owner, "Your [enthrallGender]'s order fills you with a burst of speed!")
@@ -509,7 +513,7 @@
else if (status == "charged")
if (statusStrength < 0)
status = null
- REMOVE_TRAIT(owner, TRAIT_GOTTAGOFAST, "MKUltra")
+ owner.remove_movespeed_modifier(MOVESPEED_ID_MKULTRA)
owner.Knockdown(50)
to_chat(owner, "Your body gives out as the adrenaline in your system runs out.")
else
diff --git a/modular_citadel/code/datums/traits/neutral.dm b/modular_citadel/code/datums/traits/neutral.dm
deleted file mode 100644
index 197c9b94e1..0000000000
--- a/modular_citadel/code/datums/traits/neutral.dm
+++ /dev/null
@@ -1,43 +0,0 @@
-// Citadel-specific Neutral Traits
-
-/datum/quirk/libido
- name = "Nymphomania"
- desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
- value = 0
- mob_trait = TRAIT_NYMPHO
- gain_text = "You are feeling extra wild."
- lose_text = "You don't feel that burning sensation anymore."
-
-/datum/quirk/libido/add()
- var/mob/living/M = quirk_holder
- M.min_arousal = 16
- M.arousal_rate = 3
-
-/datum/quirk/libido/remove()
- var/mob/living/M = quirk_holder
- M.min_arousal = initial(M.min_arousal)
- M.arousal_rate = initial(M.arousal_rate)
-
-/datum/quirk/libido/on_process()
- var/mob/living/M = quirk_holder
- if(M.canbearoused == FALSE)
- to_chat(quirk_holder, "Having high libido is useless when you can't feel arousal at all!")
- qdel(src)
-
-/datum/quirk/maso
- name = "Masochism"
- desc = "You are aroused by pain."
- value = 0
- mob_trait = TRAIT_MASO
- gain_text = "You desire to be hurt."
- lose_text = "Pain has become less exciting for you."
-
-/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
- name = "Acute hepatic pharmacokinesis"
- desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
- value = 0
- mob_trait = TRAIT_PHARMA
- lose_text = "Your liver feels different."
- var/active = FALSE
- var/power = 0
- var/cachedmoveCalc = 1
diff --git a/modular_citadel/code/game/gamemodes/gangs/dominator.dm b/modular_citadel/code/game/gamemodes/gangs/dominator.dm
index 4946cad510..c590baf62e 100644
--- a/modular_citadel/code/game/gamemodes/gangs/dominator.dm
+++ b/modular_citadel/code/game/gamemodes/gangs/dominator.dm
@@ -53,19 +53,17 @@
/obj/machinery/dominator/update_icon()
cut_overlays()
- if(!(stat & BROKEN))
- icon_state = "dominator-active"
- if(operating)
- var/mutable_appearance/dominator_overlay = mutable_appearance('icons/obj/machines/dominator.dmi', "dominator-overlay")
- if(gang)
- dominator_overlay.color = gang.color
- add_overlay(dominator_overlay)
- else
- icon_state = "dominator"
- if(obj_integrity/max_integrity < 0.66)
- add_overlay("damage")
- else
+ if(stat & BROKEN)
icon_state = "dominator-broken"
+ return
+ icon_state = "dominator"
+ if(operating)
+ var/mutable_appearance/dominator_overlay = mutable_appearance('icons/obj/machines/dominator.dmi', "dominator-overlay")
+ if(gang)
+ dominator_overlay.color = gang.color
+ add_overlay(dominator_overlay)
+ if(obj_integrity/max_integrity < 0.66)
+ add_overlay("damage")
/obj/machinery/dominator/examine(mob/user)
..()
@@ -168,7 +166,7 @@
examine(user)
return
- if(tempgang.domination_time != NOT_DOMINATING)
+ if(tempgang.domination_time != NOT_DOMINATING)
to_chat(user, "Error: Hostile Takeover is already in progress.")
return
diff --git a/modular_citadel/code/game/machinery/vending.dm b/modular_citadel/code/game/machinery/vending.dm
index 6a91810173..a71175c345 100755
--- a/modular_citadel/code/game/machinery/vending.dm
+++ b/modular_citadel/code/game/machinery/vending.dm
@@ -72,32 +72,7 @@
/obj/item/reagent_containers/glass/bottle/hexacrocin = 10
)
refill_canister = /obj/item/vending_refill/kink
-/*
-/obj/machinery/vending/nazivend
- name = "Nazivend"
- desc = "A vending machine containing Nazi German supplies. A label reads: \"Remember the gorrilions lost.\""
- icon = 'icons/obj/citvending.dmi'
- icon_state = "nazi"
- vend_reply = "SIEG HEIL!"
- product_slogans = "Das Vierte Reich wird zuruckkehren!;ENTFERNEN JUDEN!;Billiger als die Juden jemals geben!;Rader auf dem adminbus geht rund und rund.;Warten Sie, warum wir wieder hassen Juden?- *BZZT*"
- products = list(
- /obj/item/clothing/head/stalhelm = 20,
- /obj/item/clothing/head/panzer = 20,
- /obj/item/clothing/suit/soldiercoat = 20,
- // /obj/item/clothing/under/soldieruniform = 20,
- /obj/item/clothing/shoes/jackboots = 20
- )
- contraband = list(
- /obj/item/clothing/head/naziofficer = 10,
- // /obj/item/clothing/suit/officercoat = 10,
- // /obj/item/clothing/under/officeruniform = 10,
- /obj/item/clothing/suit/space/hardsuit/nazi = 3,
- /obj/item/gun/energy/plasma/MP40k = 4
- )
- premium = list()
- refill_canister = /obj/item/vending_refill/nazi
-*/
/obj/machinery/vending/sovietvend
name = "KomradeVendtink"
desc = "Rodina-mat' zovyot!"
@@ -137,10 +112,6 @@
icon = 'modular_citadel/icons/vending_restock.dmi'
icon_state = "refill_kink"
-/obj/item/vending_refill/nazi
- machine_name = "nazivend"
- icon_state = "refill_nazi"
-
/obj/item/vending_refill/soviet
machine_name = "sovietvend"
icon_state = "refill_soviet"
diff --git a/modular_citadel/code/game/objects/ids.dm b/modular_citadel/code/game/objects/ids.dm
deleted file mode 100644
index 8ef724581e..0000000000
--- a/modular_citadel/code/game/objects/ids.dm
+++ /dev/null
@@ -1,83 +0,0 @@
-
-//Polychromatic Knight Badge
-
-/obj/item/card/id/knight
- var/id_color = "#00FF00" //defaults to green
- name = "knight badge"
- icon = 'modular_citadel/icons/obj/id.dmi'
- icon_state = "knight"
- desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID"
-
-/obj/item/card/id/knight/update_label(newname, newjob)
- . = ..()
- if(newname || newjob)
- name = "[(!newname) ? "identification card" : "[newname]'s Knight Badge"][(!newjob) ? "" : " ([newjob])"]"
- return
-
- name = "[(!registered_name) ? "identification card" : "[registered_name]'s Knight Badge"][(!assignment) ? "" : " ([assignment])"]"
-
-/obj/item/card/id/knight/update_icon()
- var/mutable_appearance/id_overlay = mutable_appearance('modular_citadel/icons/obj/id.dmi', "knight_overlay")
-
- if(id_color)
- id_overlay.color = id_color
- cut_overlays()
-
- add_overlay(id_overlay)
-
-/obj/item/card/id/knight/AltClick(mob/living/user)
- if(!in_range(src, user)) //Basic checks to prevent abuse
- return
- if(user.incapacitated() || !istype(user))
- to_chat(user, "You can't do that right now!")
- return
- if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes")
- var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null
- if(energy_color_input)
- id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- update_icon()
-
-/obj/item/card/id/knight/Initialize()
- . = ..()
- update_icon()
-
-/obj/item/card/id/knight/examine(mob/user)
- ..()
- to_chat(user, "Alt-click to recolor it.")
-
-//=================================================
-
-/obj/item/emagrecharge
- name = "electromagnet charging device"
- desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell."
- icon = 'icons/obj/module.dmi'
- icon_state = "cell_mini"
- item_flags = NOBLUDGEON
- var/uses = 5 //Dictates how many charges the device adds to compatible items
-
-/obj/item/emagrecharge/examine(mob/user)
- . = ..()
- if(uses)
- to_chat(user, "It can add up to [uses] charges to compatible devices")
- else
- to_chat(user, "It has a small, red, blinking light coming from inside of it. It's spent.")
-
-/obj/item/card/emag
- var/uses = 15
-
-/obj/item/card/emag/examine(mob/user)
- . = ..()
- to_chat(user, "It has [uses ? uses : "no"] charges left.")
-
-/obj/item/card/emag/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/emagrecharge))
- var/obj/item/emagrecharge/ER = W
- if(ER.uses)
- uses += ER.uses
- to_chat(user, "You have added [ER.uses] charges to [src]. It now has [uses] charges.")
- playsound(src, "sparks", 100, 1)
- ER.uses = 0
- else
- to_chat(user, "[ER] has no charges left.")
- return
- . = ..()
diff --git a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm b/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
deleted file mode 100644
index e7017b8481..0000000000
--- a/modular_citadel/code/game/objects/items/melee/eutactic_blades.dm
+++ /dev/null
@@ -1,392 +0,0 @@
-/*/////////////////////////////////////////////////////////////////////////
-///////////// The TRUE Energy Sword ///////////////////////////
-*//////////////////////////////////////////////////////////////////////////
-
-/obj/item/melee/transforming/energy/sword/cx
- name = "non-eutactic blade"
- desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable."
- icon_state = "cxsword_hilt"
- icon = 'modular_citadel/icons/eutactic/item/noneutactic.dmi'
- item_state = "cxsword"
- lefthand_file = 'modular_citadel/icons/eutactic/mob/noneutactic_left.dmi'
- righthand_file = 'modular_citadel/icons/eutactic/mob/noneutactic_right.dmi'
- force = 3
- force_on = 21
- throwforce = 5
- throwforce_on = 20
- hitsound = "swing_hit" //it starts deactivated
- hitsound_on = 'sound/weapons/nebhit.ogg'
- attack_verb_off = list("tapped", "poked")
- throw_speed = 3
- throw_range = 5
- sharpness = IS_SHARP
- embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60)
- armour_penetration = 10
- block_chance = 35
- light_color = "#37FFF7"
- actions_types = list()
-
-/obj/item/melee/transforming/energy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
- altafterattack(A, user, TRUE, params)
- return TRUE
-
-/obj/item/melee/transforming/energy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
- if(istype(user))
- user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
- return TRUE
-
-/obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text)
- active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE
- if(active) //also I'd need to rip out the iconstate changing bits
- force = force_on
- throwforce = throwforce_on
- hitsound = hitsound_on
- throw_speed = 4
- if(attack_verb_on.len)
- attack_verb = attack_verb_on
- w_class = w_class_on
- START_PROCESSING(SSobj, src)
- set_light(brightness_on)
- update_icon()
- else
- force = initial(force)
- throwforce = initial(throwforce)
- hitsound = initial(hitsound)
- throw_speed = initial(throw_speed)
- if(attack_verb_off.len)
- attack_verb = attack_verb_off
- w_class = initial(w_class)
- STOP_PROCESSING(SSobj, src)
- set_light(0)
- update_icon()
- transform_messages(user, supress_message_text)
- add_fingerprint(user)
- return TRUE
-
-/obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text)
- playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1)
- if(!supress_message_text)
- to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
-
-/obj/item/melee/transforming/energy/sword/cx/update_icon()
- var/mutable_appearance/blade_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/noneutactic.dmi', "cxsword_blade")
- var/mutable_appearance/gem_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/noneutactic.dmi', "cxsword_gem")
-
- if(light_color)
- blade_overlay.color = light_color
- gem_overlay.color = light_color
-
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
-
- add_overlay(gem_overlay)
-
- if(active)
- add_overlay(blade_overlay)
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
-
-/obj/item/melee/transforming/energy/sword/cx/AltClick(mob/living/user)
- if(!in_range(src, user)) //Basic checks to prevent abuse
- return
- if(user.incapacitated() || !istype(user))
- to_chat(user, "You can't do that right now!")
- return
-
- if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
- var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
- if(energy_color_input)
- light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- update_icon()
- update_light()
-
-/obj/item/melee/transforming/energy/sword/cx/examine(mob/user)
- ..()
- to_chat(user, "Alt-click to recolor it.")
-
-/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file)
- . = ..()
- if(active)
- if(isinhands)
- var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
- blade_inhand.color = light_color
- . += blade_inhand
-//Broken version. Not a toy, but not as strong.
-/obj/item/melee/transforming/energy/sword/cx/broken
- name = "misaligned non-eutactic blade"
- desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. This one seems to have a damaged handle and misaligned components, causing the blade to be unstable at best"
- force_on = 15 //As strong a survival knife/bone dagger
-
-/obj/item/melee/transforming/energy/sword/cx/attackby(obj/item/W, mob/living/user, params)
- if(istype(W, /obj/item/melee/transforming/energy/sword/cx))
- if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
- to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
- return
- else
- to_chat(user, "You combine the two light swords, making a single supermassive blade! You're cool.")
- new /obj/item/twohanded/dualsaber/hypereutactic(user.drop_location())
- qdel(W)
- qdel(src)
- else
- return ..()
-
-//OBLIGATORY TOY MEMES /////////////////////////////////////
-
-/obj/item/toy/sword/cx
- name = "\improper DX Non-Euplastic LightSword"
- desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up."
- icon = 'modular_citadel/icons/eutactic/item/noneutactic.dmi'
- icon_state = "cxsword_hilt"
- item_state = "cxsword"
- lefthand_file = 'modular_citadel/icons/eutactic/mob/noneutactic_left.dmi'
- righthand_file = 'modular_citadel/icons/eutactic/mob/noneutactic_right.dmi'
- active = FALSE
- w_class = WEIGHT_CLASS_SMALL
- attack_verb = list("poked", "jabbed", "hit")
- light_color = "#37FFF7"
- var/light_brightness = 3
- actions_types = list()
-
-/obj/item/toy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
- altafterattack(A, user, TRUE, params)
- return TRUE
-
-/obj/item/toy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
- if(istype(user))
- user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
- return TRUE
-
-/obj/item/toy/sword/cx/attack_self(mob/user)
- active = !( active )
-
- if (active)
- to_chat(user, "You activate the holographic blade with a press of a button.")
- playsound(user, 'sound/weapons/nebon.ogg', 50, 1)
- w_class = WEIGHT_CLASS_BULKY
- attack_verb = list("slashed", "stabbed", "ravaged")
- set_light(light_brightness)
- update_icon()
-
- else
- to_chat(user, "You deactivate the holographic blade with a press of a button.")
- playsound(user, 'sound/weapons/neboff.ogg', 50, 1)
- w_class = WEIGHT_CLASS_SMALL
- attack_verb = list("poked", "jabbed", "hit")
- set_light(0)
- update_icon()
-
- add_fingerprint(user)
-
-/obj/item/toy/sword/cx/update_icon()
- var/mutable_appearance/blade_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/noneutactic.dmi', "cxsword_blade")
- var/mutable_appearance/gem_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/noneutactic.dmi', "cxsword_gem")
-
- if(light_color)
- blade_overlay.color = light_color
- gem_overlay.color = light_color
-
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
-
- add_overlay(gem_overlay)
-
- if(active)
- add_overlay(blade_overlay)
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
-
-/obj/item/toy/sword/cx/AltClick(mob/living/user)
- if(!in_range(src, user)) //Basic checks to prevent abuse
- return
- if(user.incapacitated() || !istype(user))
- to_chat(user, "You can't do that right now!")
- return
-
- if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
- var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
- if(energy_color_input)
- light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- update_icon()
- update_light()
-
-/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file)
- . = ..()
- if(active)
- if(isinhands)
- var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
- blade_inhand.color = light_color
- . += blade_inhand
-
-/obj/item/toy/sword/cx/attackby(obj/item/W, mob/living/user, params)
- if(istype(W, /obj/item/toy/sword/cx))
- if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
- to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
- return
- else
- to_chat(user, "You combine the two plastic swords, making a single supermassive toy! You're fake-cool.")
- new /obj/item/twohanded/dualsaber/hypereutactic/toy(user.loc)
- qdel(W)
- qdel(src)
- else
- return ..()
-
-/obj/item/toy/sword/cx/examine(mob/user)
- ..()
- to_chat(user, "Alt-click to recolor it.")
-
-/////////////////////////////////////////////////////
-// HYPEREUTACTIC Blades /////////////////////////
-/////////////////////////////////////////////////////
-
-/obj/item/twohanded/dualsaber/hypereutactic
- icon = 'modular_citadel/icons/eutactic/item/hypereutactic.dmi'
- icon_state = "hypereutactic"
- lefthand_file = 'modular_citadel/icons/eutactic/mob/hypereutactic_left.dmi'
- righthand_file = 'modular_citadel/icons/eutactic/mob/hypereutactic_right.dmi'
- item_state = "hypereutactic"
- inhand_x_dimension = 64
- inhand_y_dimension = 64
- name = "hypereutactic blade"
- desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter."
- force = 7
- force_unwielded = 7
- force_wielded = 40
- wieldsound = 'sound/weapons/nebon.ogg'
- unwieldsound = 'sound/weapons/neboff.ogg'
- hitsound_on = 'sound/weapons/nebhit.ogg'
- slowdown_wielded = 1
- armour_penetration = 60
- light_color = "#37FFF7"
- rainbow_colors = list("#FF0000", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF","#FF00FF", "#3399ff", "#ff9900", "#fb008b", "#9800ff", "#00ffa3", "#ccff00")
- attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded")
- spinnable = FALSE
- total_mass_on = 4
-
-/obj/item/twohanded/dualsaber/hypereutactic/chaplain
- name = "\improper divine lightblade"
- desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
- force = 5
- force_unwielded = 5
- force_wielded = 20
- block_chance = 50
- armour_penetration = 0
- var/chaplain_spawnable = TRUE
- obj_flags = UNIQUE_RENAME
-
-/obj/item/twohanded/dualsaber/hypereutactic/chaplain/Initialize()
- . = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
-
-/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
- return FALSE
-
-/obj/item/twohanded/dualsaber/hypereutactic/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
- altafterattack(A, user, TRUE, params)
- return TRUE
-
-/obj/item/twohanded/dualsaber/hypereutactic/altafterattack(atom/target, mob/living/user, proximity_flag, click_parameters) //does right click memes
- if(istype(user))
- user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
- return TRUE
-
-/obj/item/twohanded/dualsaber/hypereutactic/update_icon()
- var/mutable_appearance/blade_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/hypereutactic.dmi', "hypereutactic_blade")
- var/mutable_appearance/gem_overlay = mutable_appearance('modular_citadel/icons/eutactic/item/hypereutactic.dmi', "hypereutactic_gem")
-
- if(light_color)
- blade_overlay.color = light_color
- gem_overlay.color = light_color
-
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
-
- add_overlay(gem_overlay)
-
- if(wielded)
- add_overlay(blade_overlay)
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
-
- clean_blood()
-
-/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user)
- if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
- return
- if(user.incapacitated() || !istype(user))
- to_chat(user, "You can't do that right now!")
- return
- if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
- var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
- if(!energy_color_input || !user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
- return
- light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- update_icon()
- update_light()
-
-/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file)
- . = ..()
- if(isinhands)
- var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem")
- gem_inhand.color = light_color
- . += gem_inhand
- if(wielded)
- var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade")
- blade_inhand.color = light_color
- . += blade_inhand
-
-/obj/item/twohanded/dualsaber/hypereutactic/examine(mob/user)
- ..()
- if(!hacked)
- to_chat(user, "Alt-click to recolor it.")
-
-/obj/item/twohanded/dualsaber/hypereutactic/rainbow_process()
- . = ..()
- update_icon()
- update_light()
-
-////////////////// TOY VERSION /////////////////////////////
-
-/obj/item/twohanded/dualsaber/hypereutactic/toy
- name = "\improper DX Hyper-Euplastic LightSword"
- desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up."
- force = 0
- throwforce = 0
- throw_speed = 3
- throw_range = 5
- force_unwielded = 0
- force_wielded = 0
- attack_verb = list("attacked", "struck", "hit")
- total_mass_on = TOTAL_MASS_TOY_SWORD
- slowdown_wielded = 0
-
-/obj/item/twohanded/dualsaber/hypereutactic/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- return FALSE
-
-/obj/item/twohanded/dualsaber/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles
- return FALSE
-
-//////// Tatortot NEB /////////////// (same stats as regular esword)
-/obj/item/melee/transforming/energy/sword/cx/traitor
- name = "\improper Dragon's Tooth Sword"
- desc = "The Dragon's Tooth sword is a blackmarket modification of a Non-Eutactic Blade, \
- which utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. \
- It appears to have a wooden grip and a shaved down guard."
- icon_state = "cxsword_hilt_traitor"
- force_on = 30
- armour_penetration = 50
- embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10)
- block_chance = 50
- hitsound_on = 'sound/weapons/blade1.ogg'
- light_color = "#37F0FF"
-
-/obj/item/melee/transforming/energy/sword/cx/traitor/transform_messages(mob/living/user, supress_message_text)
- playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, 1)
- if(!supress_message_text)
- to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
-
-//RAINBOW MEMES
-
-/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow
- name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander"
- desc = "A custom-built toy with fancy rainbow lights built-in."
- hacked = TRUE
diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm
index 27f7576e7f..6c9da17289 100644
--- a/modular_citadel/code/modules/arousal/arousal.dm
+++ b/modular_citadel/code/modules/arousal/arousal.dm
@@ -19,11 +19,6 @@
var/hidden_undershirt = FALSE
var/hidden_socks = FALSE
-/mob/living/carbon/human/New()
- ..()
- saved_underwear = underwear
- saved_undershirt = undershirt
-
//Species vars
/datum/species
var/arousal_gain_rate = AROUSAL_START_VALUE //Rate at which this species becomes aroused
@@ -35,60 +30,51 @@
//Mob procs
/mob/living/carbon/human/proc/underwear_toggle()
set name = "Toggle undergarments"
- set category = "Object"
- if(ishuman(src))
- var/mob/living/carbon/human/humz = src
- var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling", "Cancel") in list("Top", "Bottom", "Socks", "All", "Cancel")
- if(confirm == "Top")
- humz.hidden_undershirt = !humz.hidden_undershirt
+ set category = "IC"
- if(confirm == "Bottom")
- humz.hidden_underwear = !humz.hidden_underwear
+ var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling") as null|anything in list("Top", "Bottom", "Socks", "All")
+ if(!confirm)
+ return
+ if(confirm == "Top")
+ hidden_undershirt = !hidden_undershirt
- if(confirm == "Socks")
- humz.hidden_socks = !humz.hidden_socks
+ if(confirm == "Bottom")
+ hidden_underwear = !hidden_underwear
- if(confirm == "All")
- humz.hidden_undershirt = !humz.hidden_undershirt
- humz.hidden_underwear = !humz.hidden_underwear
- humz.hidden_socks = !humz.hidden_socks
+ if(confirm == "Socks")
+ hidden_socks = !hidden_socks
- if(confirm == "Cancel")
- return
- src.update_body()
+ if(confirm == "All")
+ var/on_off = (hidden_undershirt || hidden_underwear || hidden_socks) ? FALSE : TRUE
+ hidden_undershirt = on_off
+ hidden_underwear = on_off
+ hidden_socks = on_off
- else
- to_chat(src, "Humans only. How the fuck did you get this verb anyway.")
+ update_body()
-/mob/living/proc/handle_arousal()
-
-
-/mob/living/carbon/handle_arousal()
- if(canbearoused && dna)
- var/datum/species/S
- S = dna.species
- if(S && !(SSmobs.times_fired % 36) && getArousalLoss() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks.
- adjustArousalLoss(arousal_rate * S.arousal_gain_rate)
- if(dna.features["exhibitionist"] && client)
- var/amt_nude = 0
- if(is_chest_exposed() && (getorganslot("breasts")))
- amt_nude++
- if(is_groin_exposed())
- if(getorganslot("penis"))
- amt_nude++
- if(getorganslot("vagina"))
- amt_nude++
- if(amt_nude)
- var/watchers = 0
- for(var/mob/_M in view(world.view, src))
- var/mob/living/M = _M
- if(!istype(M))
- continue
- if(M.client && !M.stat && !M.eye_blind && (locate(src) in viewers(world.view,M)))
- watchers++
- if(watchers)
- adjustArousalLoss((amt_nude * watchers) + S.arousal_gain_rate)
+/mob/living/proc/handle_arousal(times_fired)
+ return
+/mob/living/carbon/handle_arousal(times_fired)
+ if(!canbearoused || !dna)
+ return
+ var/datum/species/S = dna.species
+ if(!S || (times_fired % 36) || !getArousalLoss() >= max_arousal)//Totally stolen from breathing code. Do this every 36 ticks.
+ return
+ var/our_loss = arousal_rate * S.arousal_gain_rate
+ if(HAS_TRAIT(src, TRAIT_EXHIBITIONIST) && client)
+ var/amt_nude = 0
+ for(var/obj/item/organ/genital/G in internal_organs)
+ if(G.is_exposed())
+ amt_nude++
+ if(amt_nude)
+ var/watchers = 0
+ for(var/mob/living/L in view(src))
+ if(L.client && !L.stat && !L.eye_blind && (src in view(L)))
+ watchers++
+ if(watchers)
+ our_loss += (amt_nude * watchers) + S.arousal_gain_rate
+ adjustArousalLoss(our_loss)
/mob/living/proc/getArousalLoss()
return arousalloss
@@ -138,8 +124,6 @@
S = GLOB.breasts_shapes_list[G.shape]
if(S?.alt_aroused)
G.aroused_state = isPercentAroused(G.aroused_amount)
- if(getArousalLoss() >= ((max_arousal / 100) * 33))
- G.aroused_state = TRUE
else
G.aroused_state = FALSE
G.update_appearance()
@@ -147,54 +131,16 @@
/mob/living/proc/update_arousal_hud()
return FALSE
-/datum/species/proc/update_arousal_hud(mob/living/carbon/human/H)
- return FALSE
-
/mob/living/carbon/human/update_arousal_hud()
- if(!client || !hud_used)
- return FALSE
- if(dna.species.update_arousal_hud())
+ if(!client || !(hud_used?.arousal))
return FALSE
if(!canbearoused)
hud_used.arousal.icon_state = ""
return FALSE
else
- if(hud_used.arousal)
- if(stat == DEAD)
- hud_used.arousal.icon_state = "arousal0"
- return TRUE
- if(getArousalLoss() == max_arousal)
- hud_used.arousal.icon_state = "arousal100"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 90)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal90"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 80)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal80"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 70)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal70"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 60)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal60"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 50)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal50"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 40)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal40"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 30)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal30"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 20)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal10"
- return TRUE
- if(getArousalLoss() >= (max_arousal / 100) * 10)//M O D U L A R , W O W
- hud_used.arousal.icon_state = "arousal10"
- return TRUE
- else
- hud_used.arousal.icon_state = "arousal0"
+ var/value = FLOOR(getPercentAroused(), 10)
+ hud_used.arousal.icon_state = "arousal[value]"
+ return TRUE
/obj/screen/arousal
name = "arousal"
@@ -213,7 +159,6 @@
to_chat(M, "Arousal is disabled. Feature is unavailable.")
-
/mob/living/proc/mob_climax()//This is just so I can test this shit without being forced to add actual content to get rid of arousal. Will be a very basic proc for a while.
set name = "Masturbate"
set category = "IC"
@@ -221,225 +166,187 @@
if(mb_cd_timer <= world.time)
//start the cooldown even if it fails
mb_cd_timer = world.time + mb_cd_length
- if(getArousalLoss() >= ((max_arousal / 100) * 33))//33% arousal or greater required
- src.visible_message("[src] starts masturbating!", \
+ if(getArousalLoss() >= 33)//one third of average max_arousal or greater required
+ visible_message("[src] starts masturbating!", \
"You start masturbating.")
if(do_after(src, 30, target = src))
- src.visible_message("[src] relieves [p_them()]self!", \
+ visible_message("[src] relieves [p_them()]self!", \
"You have relieved yourself.")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
setArousalLoss(min_arousal)
else
to_chat(src, "You aren't aroused enough for that.")
+/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found.
+ if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
+ . = reagents
+ else
+ if(linked_organ)
+ . = linked_organ.reagents
+ if(!. && !silent)
+ to_chat(H, "Your [name] is unable to produce it's own fluids, it's missing the organs for it.")
+
+/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE)
+ if(!G)
+ return
+ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
+ setArousalLoss(min_arousal)
+ if(!target || !R)
+ return
+ var/turfing = isturf(target)
+ if(spill & R.total_volume >= 5)
+ R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
+ if(!turfing)
+ R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
+ R.clear_reagents()
//These are various procs that we'll use later, split up for readability instead of having one, huge proc.
//For all of these, we assume the arguments given are proper and have been checked beforehand.
/mob/living/carbon/human/proc/mob_masturbate(obj/item/organ/genital/G, mb_time = 30) //Masturbation, keep it gender-neutral
- var/total_fluids = 0
- var/datum/reagents/fluid_source = null
-
- if(G.producing) //Can it produce its own fluids, such as breasts?
- fluid_source = G.reagents
- else
- if(!G.linked_organ)
- to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.")
- return
- fluid_source = G.linked_organ.reagents
- total_fluids = fluid_source.total_volume
+ var/datum/reagents/fluid_source = G.climaxable(src)
+ if(!fluid_source)
+ return
+ var/obj/item/organ/genital/PP = CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) ? G.linked_organ : G
+ if(!PP)
+ to_chat(src, "You shudder, unable to cum with your [name].")
if(mb_time)
- src.visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \
- "You start to [G.masturbation_verb] your [G.name].", \
+ visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \
"You start to [G.masturbation_verb] your [G.name].")
-
- if(do_after(src, mb_time, target = src))
- if(total_fluids > 5)
- fluid_source.reaction(src.loc, TOUCH, 1, 0)
- fluid_source.clear_reagents()
- src.visible_message("[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!", \
- "You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].", \
- "You have relieved yourself.")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- if(G.can_climax)
- setArousalLoss(min_arousal)
-
+ if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
+ return
+ visible_message("[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with [p_their()] [PP.name]!", \
+ "You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with your [PP.name].")
+ do_climax(fluid_source, loc, G)
/mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes
- var/total_fluids = 0
- var/datum/reagents/fluid_source = null
- var/unable_to_come = FALSE
-
- if(G.producing) //Can it produce its own fluids, such as breasts?
- fluid_source = G.reagents
- total_fluids = fluid_source.total_volume
- else
- if(!G.linked_organ)
- unable_to_come = TRUE
- else
- fluid_source = G.linked_organ.reagents
- total_fluids = fluid_source.total_volume
-
- if(unable_to_come)
- src.visible_message("[src] shudders, their [G.name] unable to cum.", \
- "Your [G.name] cannot cum, giving no relief.", \
+ var/datum/reagents/fluid_source = G.climaxable(src, TRUE)
+ if(!fluid_source)
+ visible_message("[src] shudders, their [G.name] unable to cum.", \
"Your [G.name] cannot cum, giving no relief.")
- else
- total_fluids = fluid_source.total_volume
- if(mb_time) //as long as it's not instant, give a warning
- src.visible_message("[src] looks like they're about to cum.", \
- "You feel yourself about to orgasm.", \
- "You feel yourself about to orgasm.")
- if(do_after(src, mb_time, target = src))
- if(total_fluids > 5)
- fluid_source.reaction(src.loc, TOUCH, 1, 0)
- fluid_source.clear_reagents()
- src.visible_message("[src] orgasms[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""], using [p_their()] [G.name]!", \
- "You climax[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""] with your [G.name].", \
- "You climax using your [G.name].")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- if(G.can_climax)
- setArousalLoss(min_arousal)
-
+ return
+ if(mb_time) //as long as it's not instant, give a warning
+ visible_message("[src] looks like they're about to cum.", \
+ "You feel yourself about to orgasm.")
+ if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
+ return
+ visible_message("[src] orgasms[isturf(loc) ? " onto [loc]" : ""], using [p_their()] [G.name]!", \
+ "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) //Used for climaxing with any living thing
- var/total_fluids = 0
- var/datum/reagents/fluid_source = null
-
- if(G.producing) //Can it produce its own fluids, such as breasts?
- fluid_source = G.reagents
- else
- if(!G.linked_organ)
- to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.")
- return
- fluid_source = G.linked_organ.reagents
- total_fluids = fluid_source.total_volume
+ var/datum/reagents/fluid_source = G.climaxable(src)
+ if(!fluid_source)
+ return
if(mb_time) //Skip warning if this is an instant climax.
- src.visible_message("[src] is about to climax with [L]!", \
- "You're about to climax with [L]!", \
- "You're preparing to climax with someone!")
+ visible_message("[src] is about to climax with [L]!", \
+ "You're about to climax with [L]!")
+ if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE))
+ return
if(spillage)
- if(do_after(src, mb_time, target = src) && in_range(src, L))
- fluid_source.trans_to(L, total_fluids*G.fluid_transfer_factor)
- total_fluids -= total_fluids*G.fluid_transfer_factor
- if(total_fluids > 5)
- fluid_source.reaction(L.loc, TOUCH, 1, 0)
- fluid_source.clear_reagents()
- src.visible_message("[src] climaxes with [L][spillage ? ", overflowing and spilling":""], using [p_their()] [G.name]!", \
- "You orgasm with [L][spillage ? ", spilling out of them":""], using your [G.name].", \
- "You have climaxed with someone[spillage ? ", spilling out of them":""], using your [G.name].")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- if(G.can_climax)
- setArousalLoss(min_arousal)
+ visible_message("[src] climaxes with [L], overflowing and spilling, using [p_their()] [G.name]!", \
+ "You orgasm with [L], spilling out of them, using your [G.name].")
else //knots and other non-spilling orgasms
- if(do_after(src, mb_time, target = src) && in_range(src, L))
- fluid_source.trans_to(L, total_fluids)
- total_fluids = 0
- src.visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \
- "You ejaculate with [L], your [G.name] spilling nothing.", \
- "You have climaxed inside someone, your [G.name] spilling nothing.")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- if(G.can_climax)
- setArousalLoss(min_arousal)
+ visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \
+ "You ejaculate with [L], your [G.name] spilling nothing.")
+ SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
+ do_climax(fluid_source, spillage ? loc : L, G, spillage)
/mob/living/carbon/human/proc/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time = 30) //For beaker-filling, beware the bartender
- var/total_fluids = 0
- var/datum/reagents/fluid_source = null
-
- if(G.producing) //Can it produce its own fluids, such as breasts?
- fluid_source = G.reagents
- else
- if(!G.linked_organ)
- to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.")
+ var/datum/reagents/fluid_source = G.climaxable(src)
+ if(!fluid_source)
+ return
+ if(mb_time)
+ visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \
+ "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
- fluid_source = G.linked_organ.reagents
- total_fluids = fluid_source.total_volume
+ visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \
+ "You used your [G.name] to fill [container].")
+ do_climax(fluid_source, container, G, FALSE)
- //if(!container) //Something weird happened
- // to_chat(src, "You need a container to do this!")
- // return
-
- src.visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \
- "You start to [G.masturbation_verb] your [G.name] over [container].", \
- "You start to [G.masturbation_verb] your [G.name] over something.")
- if(do_after(src, mb_time, target = src) && in_range(src, container))
- fluid_source.trans_to(container, total_fluids)
- src.visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \
- "You used your [G.name] to fill [container].", \
- "You have relieved some pressure.")
- SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
- if(G.can_climax)
- setArousalLoss(min_arousal)
-
-/mob/living/carbon/human/proc/pick_masturbate_genitals()
- var/obj/item/organ/genital/ret_organ
- var/list/genitals_list = list()
+/mob/living/carbon/human/proc/pick_masturbate_genitals(silent = FALSE)
+ var/list/genitals_list
var/list/worn_stuff = get_equipped_items()
for(var/obj/item/organ/genital/G in internal_organs)
- if(G.can_masturbate_with) //filter out what you can't masturbate with
- if(G.is_exposed(worn_stuff)) //Nude or through_clothing
- genitals_list += G
- if(genitals_list.len)
- ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list
+ if(CHECK_BITFIELD(G.genital_flags, CAN_MASTURBATE_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with
+ if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ)
+ continue
+ LAZYADD(genitals_list, G)
+ if(LAZYLEN(genitals_list))
+ var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list
return ret_organ
- return null //error stuff
+ else if(!silent)
+ to_chat(src, "You cannot masturbate without available genitals.")
-
-/mob/living/carbon/human/proc/pick_climax_genitals()
- var/obj/item/organ/genital/ret_organ
- var/list/genitals_list = list()
+/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE)
+ var/list/genitals_list
var/list/worn_stuff = get_equipped_items()
for(var/obj/item/organ/genital/G in internal_organs)
- if(G.can_climax) //filter out what you can't masturbate with
- if(G.is_exposed(worn_stuff)) //Nude or through_clothing
- genitals_list += G
- if(genitals_list.len)
- ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list
+ if(CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with
+ LAZYADD(genitals_list, G)
+ if(LAZYLEN(genitals_list))
+ var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list
return ret_organ
- return null //error stuff
+ else if(!silent)
+ to_chat(src, "You cannot climax without available genitals.")
-
-/mob/living/carbon/human/proc/pick_partner()
+/mob/living/carbon/human/proc/pick_partner(silent = FALSE)
var/list/partners = list()
- if(src.pulling)
- partners += src.pulling //Yes, even objects for now
- if(src.pulledby)
- partners += src.pulledby
+ if(pulling)
+ partners += pulling
+ if(pulledby)
+ partners += pulledby
//Now we got both of them, let's check if they're proper
- for(var/I in partners)
- if(isliving(I))
- if(iscarbon(I))
- var/mob/living/carbon/C = I
- if(!C.exposed_genitals.len) //Nothing through_clothing
- if(!C.is_groin_exposed()) //No pants undone
- if(!C.is_chest_exposed()) //No chest exposed
- partners -= I //Then not proper, remove them
- else
- partners -= I //No fucking objects
+ for(var/mob/living/L in partners)
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed()) //Nothing through_clothing, no proper partner.
+ partners -= C
//NOW the list should only contain correct partners
if(!partners.len)
- return null //No one left.
- return input(src, "With whom?", "Sexual partner", null) in partners //pick one, default to null
+ if(!silent)
+ to_chat(src, "You cannot do this alone.")
+ return //No one left.
+ var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null
+ if(target && in_range(src, target))
+ return target
-/mob/living/carbon/human/proc/pick_climax_container()
- var/obj/item/reagent_containers/SC = null
+/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE)
var/list/containers_list = list()
- for(var/obj/item/reagent_containers/container in held_items)
- if(container.is_open_container() || istype(container, /obj/item/reagent_containers/food/snacks))
- containers_list += container
+ for(var/obj/item/reagent_containers/C in held_items)
+ if(C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks))
+ containers_list += C
+ for(var/obj/item/reagent_containers/C in range(1, src))
+ if((C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) && CanReach(C))
+ containers_list += C
if(containers_list.len)
- SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list
- if(SC)
- if(in_range(src, SC))
- return SC
- return null //If nothing correct, give null.
+ var/obj/item/reagent_containers/SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list
+ if(SC && CanReach(SC))
+ return SC
+ else if(!silent)
+ to_chat(src, "You cannot do this without an appropriate container.")
+/mob/living/carbon/human/proc/available_rosie_palms(silent = FALSE, list/whitelist_typepaths = list(/obj/item/dildo))
+ if(restrained(TRUE)) //TRUE ignores grabs
+ if(!silent)
+ to_chat(src, "You can't do that while restrained!")
+ return FALSE
+ if(!get_num_arms() || !get_empty_held_indexes())
+ if(whitelist_typepaths)
+ if(!islist(whitelist_typepaths))
+ whitelist_typepaths = list(whitelist_typepaths)
+ for(var/path in whitelist_typepaths)
+ if(is_holding_item_of_type(path))
+ return TRUE
+ if(!silent)
+ to_chat(src, "You need at least one free arm.")
+ return FALSE
+ return TRUE
//Here's the main proc itself
/mob/living/carbon/human/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints
@@ -447,156 +354,97 @@
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!")
return
- mb_cd_timer = (world.time + mb_cd_length)
-
- if(canbearoused && has_dna())
- if(stat==2)
+ if(!canbearoused || !has_dna())
+ return
+ if(stat == DEAD)
+ if(!forced_climax)
to_chat(src, "You can't do that while dead!")
- return
- if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks
- for(var/obj/item/organ/O in internal_organs)
- if(istype(O, /obj/item/organ/genital))
- var/obj/item/organ/genital/G = O
- if(!G.can_climax) //Skip things like wombs and testicles
- continue
- var/mob/living/partner
- var/check_target
- var/list/worn_stuff = get_equipped_items()
+ return
+ if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks
+ for(var/obj/item/organ/genital/G in internal_organs)
+ if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles
+ continue
+ var/mob/living/partner
+ var/check_target
+ var/list/worn_stuff = get_equipped_items()
- if(G.is_exposed(worn_stuff))
- if(src.pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick
- if(isliving(src.pulling)) //Don't fuck objects
- check_target = src.pulling
- if(src.pulledby && !check_target) //prioritise pulled over pulledby
- if(isliving(src.pulledby))
- check_target = src.pulledby
- //Now we should have a partner, or else we have to come alone
- if(check_target)
- if(iscarbon(check_target)) //carbons can have clothes
- var/mob/living/carbon/C = check_target
- if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough?
- partner = C
- else //A cat is fine too
- partner = check_target
- if(partner) //Did they pass the clothing checks?
- mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced
- continue //You've climaxed once with this organ, continue on
- //not exposed OR if no partner was found while exposed, climax alone
- mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms
- //Now all genitals that could climax, have.
- //Since this was a forced climax, we do not need to continue with the other stuff
- return
- //If we get here, then this is not a forced climax and we gotta check a few things.
+ if(G.is_exposed(worn_stuff))
+ if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick
+ if(isliving(pulling)) //Don't fuck objects
+ check_target = pulling
+ if(pulledby && !check_target) //prioritise pulled over pulledby
+ if(isliving(pulledby))
+ check_target = pulledby
+ //Now we should have a partner, or else we have to come alone
+ if(check_target)
+ if(iscarbon(check_target)) //carbons can have clothes
+ var/mob/living/carbon/C = check_target
+ if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough?
+ partner = C
+ else //A cat is fine too
+ partner = check_target
+ if(partner) //Did they pass the clothing checks?
+ mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced
+ continue //You've climaxed once with this organ, continue on
+ //not exposed OR if no partner was found while exposed, climax alone
+ mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms
+ //Now all genitals that could climax, have.
+ //Since this was a forced climax, we do not need to continue with the other stuff
+ mb_cd_timer = world.time + mb_cd_length
+ return
+ //If we get here, then this is not a forced climax and we gotta check a few things.
- if(stat==1) //No sleep-masturbation, you're unconscious.
- to_chat(src, "You must be conscious to do that!")
- return
- if(getArousalLoss() < 33) //flat number instead of percentage
- to_chat(src, "You aren't aroused enough for that!")
- return
+ if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious.
+ to_chat(src, "You must be conscious to do that!")
+ return
+ if(getArousalLoss() < 33) //flat number instead of percentage
+ to_chat(src, "You aren't aroused enough for that!")
+ return
- //Ok, now we check what they want to do.
- var/choice = input(src, "Select sexual activity", "Sexual activity:") in list("Masturbate", "Climax alone", "Climax with partner", "Fill container")
+ //Ok, now we check what they want to do.
+ var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container")
+ if(!choice)
+ return
- switch(choice)
- if("Masturbate")
- if(restrained(TRUE)) //TRUE ignores grabs
- to_chat(src, "You can't do that while restrained!")
- return
- var/free_hands = get_num_arms()
- if(!free_hands)
- to_chat(src, "You need at least one free arm.")
- return
- for(var/helditem in held_items)//how many hands are free
- if(isobj(helditem))
- free_hands--
- if(free_hands <= 0)
- to_chat(src, "You're holding too many things.")
- return
- //We got hands, let's pick an organ
- var/obj/item/organ/genital/picked_organ
- picked_organ = pick_masturbate_genitals()
- if(picked_organ)
- mob_masturbate(picked_organ)
- return
- else //They either lack organs that can masturbate, or they didn't pick one.
- to_chat(src, "You cannot masturbate without choosing genitals.")
- return
+ switch(choice)
+ if("Masturbate")
+ if(!available_rosie_palms())
+ return
+ //We got hands, let's pick an organ
+ var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals()
+ if(picked_organ && available_rosie_palms(TRUE))
+ mob_masturbate(picked_organ)
+ return
- if("Climax alone")
- if(restrained(TRUE)) //TRUE ignores grabs
- to_chat(src, "You can't do that while restrained!")
- return
- var/free_hands = get_num_arms()
- if(!free_hands)
- to_chat(src, "You need at least one free arm.")
- return
- for(var/helditem in held_items)//how many hands are free
- if(isobj(helditem))
- free_hands--
- if(free_hands <= 0)
- to_chat(src, "You're holding too many things.")
- return
- //We got hands, let's pick an organ
- var/obj/item/organ/genital/picked_organ
- picked_organ = pick_climax_genitals()
- if(picked_organ)
- mob_climax_outside(picked_organ)
- return
- else //They either lack organs that can masturbate, or they didn't pick one.
- to_chat(src, "You cannot climax without choosing genitals.")
- return
+ if("Climax alone")
+ if(!available_rosie_palms())
+ return
+ var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
+ if(picked_organ && available_rosie_palms(TRUE))
+ mob_climax_outside(picked_organ)
- if("Climax with partner")
- //We need no hands, we can be restrained and so on, so let's pick an organ
- var/obj/item/organ/genital/picked_organ
- picked_organ = pick_climax_genitals()
- if(picked_organ)
- var/mob/living/partner = pick_partner() //Get someone
- if(partner)
- var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No")
- if(spillage == "Yes")
- mob_climax_partner(picked_organ, partner, TRUE)
- else
- mob_climax_partner(picked_organ, partner, FALSE)
- return
- else
- to_chat(src, "You cannot do this alone.")
- return
- else //They either lack organs that can masturbate, or they didn't pick one.
- to_chat(src, "You cannot climax without choosing genitals.")
- return
+ if("Climax with partner")
+ //We need no hands, we can be restrained and so on, so let's pick an organ
+ var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
+ if(picked_organ)
+ var/mob/living/partner = pick_partner() //Get someone
+ if(partner)
+ var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as null|anything in list("Yes", "No")
+ if(spillage && in_range(src, partner))
+ mob_climax_partner(picked_organ, partner, spillage == "Yes" ? TRUE : FALSE)
- if("Fill container")
- //We'll need hands and no restraints.
- if(restrained(TRUE)) //TRUE ignores grabs
- to_chat(src, "You can't do that while restrained!")
- return
- var/free_hands = get_num_arms()
- if(!free_hands)
- to_chat(src, "You need at least one free arm.")
- return
- for(var/helditem in held_items)//how many hands are free
- if(isobj(helditem))
- free_hands--
- if(free_hands <= 0)
- to_chat(src, "You're holding too many things.")
- return
- //We got hands, let's pick an organ
- var/obj/item/organ/genital/picked_organ
- picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
- if(picked_organ)
- //Good, got an organ, time to pick a container
- var/obj/item/reagent_containers/fluid_container = pick_climax_container()
- if(fluid_container)
- mob_fill_container(picked_organ, fluid_container)
- return
- else
- to_chat(src, "You cannot do this without anything to fill.")
- return
- else //They either lack organs that can climax, or they didn't pick one.
- to_chat(src, "You cannot fill anything without choosing genitals.")
- return
- else //Somehow another option was taken, maybe something interrupted the selection or it was cancelled
- return //Just end it in that case.
+ if("Fill container")
+ //We'll need hands and no restraints.
+ if(!available_rosie_palms(FALSE, /obj/item/reagent_containers))
+ return
+ //We got hands, let's pick an organ
+ var/obj/item/organ/genital/picked_organ
+ picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
+ if(picked_organ)
+ //Good, got an organ, time to pick a container
+ var/obj/item/reagent_containers/fluid_container = pick_climax_container()
+ if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers))
+ mob_fill_container(picked_organ, fluid_container)
+
+ mb_cd_timer = world.time + mb_cd_length
\ No newline at end of file
diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm
new file mode 100644
index 0000000000..9ecf67e4b0
--- /dev/null
+++ b/modular_citadel/code/modules/arousal/genitals.dm
@@ -0,0 +1,339 @@
+/obj/item/organ/genital
+ color = "#fcccb3"
+ w_class = WEIGHT_CLASS_NORMAL
+ var/shape = "human"
+ var/sensitivity = AROUSAL_START_VALUE
+ var/genital_flags //see citadel_defines.dm
+ var/masturbation_verb = "masturbate"
+ var/orgasm_verb = "cumming" //present continous
+ var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this?
+ var/size = 2 //can vary between num or text, just used in icon_state strings
+ var/fluid_id = null
+ var/fluid_max_volume = 50
+ var/fluid_efficiency = 1
+ var/fluid_rate = CUM_RATE
+ var/fluid_mult = 1
+ var/aroused_state = FALSE //Boolean used in icon_state strings
+ var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons.
+ var/obj/item/organ/genital/linked_organ
+ var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link().
+ var/layer_index = GENITAL_LAYER_INDEX //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in.
+
+/obj/item/organ/genital/Initialize(mapload, mob/living/carbon/human/H)
+ . = ..()
+ if(fluid_id)
+ create_reagents(fluid_max_volume)
+ if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
+ reagents.add_reagent(fluid_id, fluid_max_volume)
+ if(H)
+ get_features(H)
+ Insert(H)
+ else
+ update()
+
+/obj/item/organ/genital/Destroy()
+ if(linked_organ)
+ update_link(TRUE)//this should remove any other links it has
+ if(owner)
+ Remove(owner, TRUE)//this should remove references to it, so it can be GCd correctly
+ return ..()
+
+/obj/item/organ/genital/proc/update(removing = FALSE)
+ if(QDELETED(src))
+ return
+ update_size()
+ update_appearance()
+ if(linked_organ_slot || (linked_organ && removing))
+ update_link(removing)
+
+//exposure and through-clothing code
+/mob/living/carbon
+ var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed
+
+/obj/item/organ/genital/proc/is_exposed()
+ if(!owner || CHECK_BITFIELD(genital_flags, GENITAL_INTERNAL) || CHECK_BITFIELD(genital_flags, GENITAL_HIDDEN))
+ return FALSE
+ if(CHECK_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES))
+ return TRUE
+
+ switch(zone) //update as more genitals are added
+ if(BODY_ZONE_CHEST)
+ return owner.is_chest_exposed()
+ if(BODY_ZONE_PRECISE_GROIN)
+ return owner.is_groin_exposed()
+
+/obj/item/organ/genital/proc/toggle_visibility(visibility)
+ switch(visibility)
+ if("Always visible")
+ ENABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
+ DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
+ if(!(src in owner.exposed_genitals))
+ owner.exposed_genitals += src
+ if("Hidden by clothes")
+ DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
+ DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
+ if(src in owner.exposed_genitals)
+ owner.exposed_genitals -= src
+ if("Always hidden")
+ DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
+ ENABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
+ if(src in owner.exposed_genitals)
+ owner.exposed_genitals -= src
+
+ if(ishuman(owner)) //recast to use update genitals proc
+ var/mob/living/carbon/human/H = owner
+ H.update_genitals()
+
+/mob/living/carbon/verb/toggle_genitals()
+ set category = "IC"
+ set name = "Expose/Hide genitals"
+ set desc = "Allows you to toggle which genitals should show through clothes or not."
+
+ var/list/genital_list = list()
+ for(var/obj/item/organ/O in internal_organs)
+ if(isgenital(O))
+ var/obj/item/organ/genital/G = O
+ if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL))
+ genital_list += G
+ if(!genital_list.len) //There is nothing to expose
+ return
+ //Full list of exposable genitals created
+ var/obj/item/organ/genital/picked_organ
+ picked_organ = input(src, "Choose which genitalia to expose/hide", "Expose/Hide genitals", null) in genital_list
+ if(picked_organ)
+ var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
+ picked_organ.toggle_visibility(picked_visibility)
+ return
+
+/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
+ return
+
+/obj/item/organ/genital/proc/update_size()
+ return
+
+/obj/item/organ/genital/proc/update_appearance()
+ if(!owner || owner.stat == DEAD)
+ aroused_state = FALSE
+
+/obj/item/organ/genital/on_life()
+ if(!reagents || !owner)
+ return
+ reagents.maximum_volume = fluid_max_volume
+ if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
+ generate_fluid()
+
+/obj/item/organ/genital/proc/generate_fluid()
+ var/amount = fluid_rate
+ if(!reagents.total_volume && amount < 0.1) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
+ amount += 0.1
+ var/multiplier = fluid_mult
+ if(reagents.total_volume >= 5)
+ multiplier *= 0.5
+ if(reagents.total_volume < reagents.maximum_volume)
+ reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
+ reagents.add_reagent(fluid_id, (amount * multiplier))//generate the cum
+ return TRUE
+ return FALSE
+
+/obj/item/organ/genital/proc/update_link(removing = FALSE)
+ if(!removing && owner)
+ if(linked_organ)
+ return
+ linked_organ = owner.getorganslot(linked_organ_slot)
+ if(linked_organ)
+ linked_organ.linked_organ = src
+ linked_organ.upon_link()
+ upon_link()
+ return TRUE
+ else
+ if(linked_organ)
+ linked_organ.linked_organ = null
+ linked_organ = null
+ return FALSE
+
+//post organ duo making arrangements.
+/obj/item/organ/genital/proc/upon_link()
+ return
+
+/obj/item/organ/genital/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
+ . = ..()
+ if(.)
+ update()
+ RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance)
+
+/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
+ . = ..()
+ if(.)
+ update(TRUE)
+ UnregisterSignal(M, COMSIG_MOB_DEATH)
+
+//proc to give a player their genitals and stuff when they log in
+/mob/living/carbon/human/proc/give_genitals(clean = FALSE)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA
+ if(clean)
+ for(var/obj/item/organ/genital/G in internal_organs)
+ qdel(G)
+ if (NOGENITALS in dna.species.species_traits)
+ return
+ if(dna.features["has_vag"])
+ give_genital(/obj/item/organ/genital/vagina)
+ if(dna.features["has_womb"])
+ give_genital(/obj/item/organ/genital/womb)
+ if(dna.features["has_balls"])
+ give_genital(/obj/item/organ/genital/testicles)
+ if(dna.features["has_breasts"])
+ give_genital(/obj/item/organ/genital/breasts)
+ if(dna.features["has_cock"])
+ give_genital(/obj/item/organ/genital/penis)
+ /*
+ if(dna.features["has_ovi"])
+ give_genital(/obj/item/organ/genital/ovipositor)
+ if(dna.features["has_eggsack"])
+ give_genital(/obj/item/organ/genital/eggsack)
+ */
+
+/mob/living/carbon/human/proc/give_genital(obj/item/organ/genital/G)
+ if(!dna || (NOGENITALS in dna.species.species_traits) || getorganslot(initial(G.slot)))
+ return FALSE
+ G = new G(null, src)
+ return G
+
+/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H)
+ return
+
+/datum/species/proc/genitals_layertext(layer)
+ switch(layer)
+ if(GENITALS_BEHIND_LAYER)
+ return "BEHIND"
+ if(GENITALS_FRONT_LAYER)
+ return "FRONT"
+
+//procs to handle sprite overlays being applied to humans
+
+/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
+ . = ..()
+ if(!. && I && slot && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage, hands or cuffs.
+ update_genitals()
+
+/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
+ var/no_update = FALSE
+ if(!I || I == l_store || I == r_store || I == s_store || I == handcuffed || I == legcuffed || get_held_index_of_item(I)) //stops storages, cuffs and held items from triggering it.
+ no_update = TRUE
+ . = ..()
+ if(!. || no_update)
+ return
+ update_genitals()
+
+/mob/living/carbon/human/proc/update_genitals()
+ if(!QDELETED(src))
+ dna.species.handle_genitals(src)
+
+//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
+/mob/living/carbon/human/proc/emergent_genital_call()
+ if(!canbearoused)
+ return FALSE
+
+ var/organCheck = locate(/obj/item/organ/genital) in internal_organs
+ var/breastCheck = getorganslot(ORGAN_SLOT_BREASTS)
+ var/willyCheck = getorganslot(ORGAN_SLOT_PENIS)
+
+ if(organCheck == FALSE)
+ if(ishuman(src) && dna.species.id == "human")
+ dna.features["genitals_use_skintone"] = TRUE
+ dna.species.use_skintones = TRUE
+ if(MUTCOLORS)
+ if(src.dna.species.fixed_mut_color)
+ dna.features["cock_color"] = "[dna.species.fixed_mut_color]"
+ dna.features["breasts_color"] = "[dna.species.fixed_mut_color]"
+ return
+ //So people who haven't set stuff up don't get rainbow surprises.
+ dna.features["cock_color"] = "[dna.features["mcolor"]]"
+ dna.features["breasts_color"] = "[dna.features["mcolor"]]"
+ else //If there's a new organ, make it the same colour.
+ if(breastCheck == FALSE)
+ dna.features["breasts_color"] = dna.features["cock_color"]
+ else if (willyCheck == FALSE)
+ dna.features["cock_color"] = dna.features["breasts_color"]
+ return TRUE
+
+/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
+ if(!H)//no args
+ CRASH("H = null")
+ if(!LAZYLEN(H.internal_organs) || ((NOGENITALS in species_traits) && !H.genital_override) || HAS_TRAIT(H, TRAIT_HUSK))
+ return
+ var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER)
+
+ for(var/L in relevant_layers) //Less hardcode
+ H.remove_overlay(L)
+ H.remove_overlay(GENITALS_EXPOSED_LAYER)
+ //start scanning for genitals
+
+ var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH]
+ var/list/genitals_to_add
+ var/list/fully_exposed
+ for(var/obj/item/organ/genital/G in H.internal_organs)
+ if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
+ LAZYADD(gen_index[G.layer_index], G)
+ for(var/L in gen_index)
+ if(L) //skip nulls
+ LAZYADD(genitals_to_add, L)
+ if(!genitals_to_add)
+ return
+ //Now we added all genitals that aren't internal and should be rendered
+ //start applying overlays
+ for(var/layer in relevant_layers)
+ var/list/standing = list()
+ var/layertext = genitals_layertext(layer)
+ for(var/A in genitals_to_add)
+ var/obj/item/organ/genital/G = A
+ var/datum/sprite_accessory/S
+ var/size = G.size
+ var/aroused_state = G.aroused_state
+ switch(G.type)
+ if(/obj/item/organ/genital/penis)
+ S = GLOB.cock_shapes_list[G.shape]
+ if(/obj/item/organ/genital/testicles)
+ S = GLOB.balls_shapes_list[G.shape]
+ if(/obj/item/organ/genital/vagina)
+ S = GLOB.vagina_shapes_list[G.shape]
+ if(/obj/item/organ/genital/breasts)
+ S = GLOB.breasts_shapes_list[G.shape]
+
+ if(!S || S.icon_state == "none")
+ continue
+
+ var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
+ genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
+
+ if(S.center)
+ genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
+
+ if(use_skintones && H.dna.features["genitals_use_skintone"])
+ genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
+ genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]"
+ else
+ switch(S.color_src)
+ if("cock_color")
+ genital_overlay.color = "#[H.dna.features["cock_color"]]"
+ if("balls_color")
+ genital_overlay.color = "#[H.dna.features["balls_color"]]"
+ if("breasts_color")
+ genital_overlay.color = "#[H.dna.features["breasts_color"]]"
+ if("vag_color")
+ genital_overlay.color = "#[H.dna.features["vag_color"]]"
+
+ if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES))
+ genital_overlay.layer = -GENITALS_EXPOSED_LAYER
+ LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag.
+ else
+ standing += genital_overlay
+
+ if(LAZYLEN(standing))
+ H.overlays_standing[layer] = standing
+
+ if(LAZYLEN(fully_exposed))
+ H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed
+ H.apply_overlay(GENITALS_EXPOSED_LAYER)
+
+ for(var/L in relevant_layers)
+ H.apply_overlay(L)
+
diff --git a/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm
similarity index 89%
rename from modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm
rename to modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm
index f4af8a40ba..15d84fa008 100644
--- a/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm
+++ b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm
@@ -5,11 +5,9 @@
//DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM
/datum/sprite_accessory/penis
icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi'
- icon_state = null
name = "penis" //the preview name of the accessory
- gender_specific = 0 //Might be needed somewhere down the list.
color_src = "cock_color"
- locked = 0
+ alt_aroused = TRUE
/datum/sprite_accessory/penis/human
icon_state = "human"
@@ -75,27 +73,21 @@
icon_state = "testicle"
name = "testicle" //the preview name of the accessory
color_src = "balls_color"
- locked = 0
/datum/sprite_accessory/testicles/hidden
- icon_state = "hidden"
+ icon_state = "none"
name = "Hidden"
- alt_aroused = TRUE
/datum/sprite_accessory/testicles/single
icon_state = "single"
name = "Single"
- alt_aroused = TRUE
//Vaginas
/datum/sprite_accessory/vagina
icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi'
icon_state = null
name = "vagina"
- gender_specific = 0
color_src = "vag_color"
- locked = 0
- alt_aroused = FALSE //if this is TRUE, then the genitals will use an alternate sprite for aroused states
/datum/sprite_accessory/vagina/human
icon_state = "human"
@@ -131,35 +123,28 @@
//BREASTS BE HERE
/datum/sprite_accessory/breasts
icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi'
- icon_state = null
name = "breasts"
- gender_specific = 0
color_src = "breasts_color"
- locked = 0
+ alt_aroused = TRUE
/datum/sprite_accessory/breasts/pair
icon_state = "pair"
name = "Pair"
- alt_aroused = TRUE
/datum/sprite_accessory/breasts/quad
icon_state = "quad"
name = "Quad"
- alt_aroused = TRUE
/datum/sprite_accessory/breasts/sextuple
icon_state = "sextuple"
name = "Sextuple"
- alt_aroused = TRUE
//OVIPOSITORS BE HERE
/datum/sprite_accessory/ovipositor
icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi'
icon_state = null
name = "Ovipositor" //the preview name of the accessory
- gender_specific = 0 //Might be needed somewhere down the list.
color_src = "cock_color"
- locked = 0
/datum/sprite_accessory/ovipositor/knotted
icon_state = "knotted"
diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm
index 3df2218766..6299f68b6c 100644
--- a/modular_citadel/code/modules/arousal/organs/breasts.dm
+++ b/modular_citadel/code/modules/arousal/organs/breasts.dm
@@ -1,50 +1,29 @@
/obj/item/organ/genital/breasts
- name = "breasts"
- desc = "Female milk producing organs."
- icon_state = "breasts"
- icon = 'modular_citadel/icons/obj/genitals/breasts.dmi'
- zone = "chest"
- slot = "breasts"
- w_class = 3
- size = BREASTS_SIZE_DEF //SHOULD BE A LETTER, starts as a number...???
- var/cached_size = null //for enlargement SHOULD BE A NUMBER
- var/prev_size //For flavour texts SHOULD BE A LETTER
- //var/breast_sizes = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "huge", "flat")
- var/breast_values = list ("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
- var/statuscheck = FALSE
- fluid_id = "milk"
- var/amount = 2
- producing = TRUE
- shape = "Pair"
- can_masturbate_with = TRUE
- masturbation_verb = "massage"
- can_climax = TRUE
- fluid_transfer_factor = 0.5
+ name = "breasts"
+ desc = "Female milk producing organs."
+ icon_state = "breasts"
+ icon = 'modular_citadel/icons/obj/genitals/breasts.dmi'
+ zone = BODY_ZONE_CHEST
+ slot = ORGAN_SLOT_BREASTS
+ size = "c" //refer to the breast_values static list below for the cups associated number values
+ fluid_id = "milk"
+ shape = "pair"
+ genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION
+ masturbation_verb = "massage"
+ orgasm_verb = "leaking"
+ fluid_transfer_factor = 0.5
+ var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
+ var/cached_size //these two vars pertain size modifications and so should be expressed in NUMBERS.
+ var/prev_size //former cached_size value, to allow update_size() to early return should be there no significant changes.
-/obj/item/organ/genital/breasts/on_life()
- if(QDELETED(src))
- return
- if(!reagents || !owner)
- return
- reagents.maximum_volume = fluid_max_volume
- if(fluid_id && producing)
- if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
- fluid_rate = 0.1
- else
- fluid_rate = CUM_RATE
- if(reagents.total_volume >= 5)
- fluid_mult = 0.5
- else
- fluid_mult = 1
- generate_milk()
-
-/obj/item/organ/genital/breasts/proc/generate_milk()
- if(owner.stat == DEAD)
- return FALSE
- reagents.isolate_reagent(fluid_id)
- reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))
+/obj/item/organ/genital/breasts/Initialize(mapload, mob/living/carbon/human/H)
+ if(!H)
+ cached_size = breast_values[size]
+ prev_size = cached_size
+ return ..()
/obj/item/organ/genital/breasts/update_appearance()
+ . = ..()
var/lowershape = lowertext(shape)
switch(lowershape)
if("pair")
@@ -55,16 +34,15 @@
desc = "You see three sets of breasts, running from their chest to their belly."
else
desc = "You see some breasts, they seem to be quite exotic."
- if(cached_size > 16)
+ if(size == "huge")
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size)]cm in diameter."
- else if (!isnum(size))
+ else
if (size == "flat")
desc += " They're very small and flatchested, however."
else
desc += " You estimate that they're [uppertext(size)]-cups."
- //string = "breasts_[lowertext(shape)]_[size]-s"
- if(producing && aroused_state)
+ if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) && aroused_state)
desc += " They're leaking [fluid_id]."
var/string
if(owner)
@@ -80,57 +58,70 @@
var/mob/living/carbon/human/H = owner
icon_state = sanitize_text(string)
H.update_genitals()
-
icon_state = sanitize_text(string)
-
//Allows breasts to grow and change size, with sprite changes too.
//maximum wah
//Comical sizes slow you down in movement and actions.
//Rediculous sizes makes you more cumbersome.
//this is far too lewd wah
-/obj/item/organ/genital/breasts/update_size()//wah
-
- if(!ishuman(owner) || !owner)
+/obj/item/organ/genital/breasts/modify_size(modifier, min = -INFINITY, max = INFINITY)
+ var/new_value = CLAMP(cached_size + modifier, min, max)
+ if(new_value == cached_size)
return
- if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
- to_chat(owner, "You feel your breasts shrinking away from your body as your chest flattens out.")
- src.Remove(owner)
- switch(round(cached_size))
- if(0) //If flatchested
- size = "flat"
- if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
- owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
- statuscheck = FALSE
- if(1 to 8) //If modest size
- size = breast_values[round(cached_size)]
- if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
- owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
- statuscheck = FALSE
- if(9 to 15) //If massive
- size = breast_values[round(cached_size)]
- if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
- owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
- statuscheck = TRUE
- if(16 to INFINITY) //if Rediculous
- size = cached_size
+ prev_size = cached_size
+ cached_size = new_value
+ update()
- if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this.
- if (prev_size == 0)
- prev_size = "flat"
- if(size == 0)//Bloody byond with it's counting from 1
+/obj/item/organ/genital/breasts/update_size()//wah
+ var/rounded_cached = round(cached_size)
+ if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
+ if(owner)
+ to_chat(owner, "You feel your breasts shrinking away from your body as your chest flattens out.")
+ QDEL_IN(src, 1)
+ return
+ var/enlargement = FALSE
+ switch(rounded_cached)
+ if(0) //flatchested
size = "flat"
- if(isnum(prev_size))
- prev_size = breast_values[prev_size]
- if (breast_values[size] > breast_values[prev_size])
- to_chat(owner, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.")
- var/mob/living/carbon/human/H = owner
- H.Force_update_genitals()
- else if ((breast_values[size] < breast_values[prev_size]) && (breast_values[size] > 0.5))
- to_chat(owner, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.")
- var/mob/living/carbon/human/H = owner
- H.Force_update_genitals()
- prev_size = size
- else if (cached_size >= 16)
- size = "huge"
+ if(1 to 8) //modest
+ size = breast_values[rounded_cached]
+ if(9 to 15) //massive
+ size = breast_values[rounded_cached]
+ enlargement = TRUE
+ if(16 to INFINITY) //rediculous
+ size = "huge"
+ enlargement = TRUE
+ if(owner)
+ var/status_effect = owner.has_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
+ if(enlargement && !status_effect)
+ owner.apply_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
+ else if(!enlargement && status_effect)
+ owner.remove_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
+
+ if(rounded_cached < 16 && owner)//Because byond doesn't count from 0, I have to do this.
+ var/mob/living/carbon/human/H = owner
+ var/r_prev_size = round(prev_size)
+ if (rounded_cached > r_prev_size)
+ to_chat(H, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.")
+ else if (rounded_cached < r_prev_size)
+ to_chat(H, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.")
+
+/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H)
+ var/datum/dna/D = H.dna
+ if(D.species.use_skintones && D.features["genitals_use_skintone"])
+ color = "#[skintone2hex(H.skin_tone)]"
+ else
+ color = "#[D.features["breasts_color"]]"
+ size = D.features["breasts_size"]
+ shape = D.features["breasts_shape"]
+ fluid_id = D.features["breasts_fluid"]
+ if(!D.features["breasts_producing"])
+ DISABLE_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)
+ if(!isnum(size))
+ cached_size = breast_values[size]
+ else
+ cached_size = size
+ size = breast_values[size]
+ prev_size = cached_size
diff --git a/modular_citadel/code/modules/arousal/organs/eggsack.dm b/modular_citadel/code/modules/arousal/organs/eggsack.dm
index 402d246e40..ebdefd2371 100644
--- a/modular_citadel/code/modules/arousal/organs/eggsack.dm
+++ b/modular_citadel/code/modules/arousal/organs/eggsack.dm
@@ -1,14 +1,14 @@
/obj/item/organ/genital/eggsack
- name = "Egg sack"
- desc = "An egg producing reproductive organ."
- icon_state = "egg_sack"
- icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
- zone = "groin"
- slot = "testicles"
- color = null //don't use the /genital color since it already is colored
- internal = TRUE
+ name = "Egg sack"
+ desc = "An egg producing reproductive organ."
+ icon_state = "egg_sack"
+ icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = ORGAN_SLOT_TESTICLES
+ genital_flags = GENITAL_INTERNAL|GENITAL_BLACKLISTED //unimplemented
+ linked_organ_slot = ORGAN_SLOT_PENIS
+ color = null //don't use the /genital color since it already is colored
var/egg_girth = EGG_GIRTH_DEF
var/cum_mult = CUM_RATE_MULT
var/cum_rate = CUM_RATE
var/cum_efficiency = CUM_EFFICIENCY
- var/obj/item/organ/ovipositor/linked_ovi
diff --git a/modular_citadel/code/modules/arousal/organs/genitals.dm b/modular_citadel/code/modules/arousal/organs/genitals.dm
deleted file mode 100644
index 3abe7ecb1f..0000000000
--- a/modular_citadel/code/modules/arousal/organs/genitals.dm
+++ /dev/null
@@ -1,414 +0,0 @@
-/obj/item/organ/genital
- color = "#fcccb3"
- w_class = WEIGHT_CLASS_NORMAL
- var/shape = "Human" //Changed to be uppercase, let me know if this breaks everything..!!
- var/sensitivity = AROUSAL_START_VALUE
- var/list/genital_flags = list()
- var/can_masturbate_with = FALSE
- var/masturbation_verb = "masturbate"
- var/can_climax = FALSE
- var/fluid_transfer_factor = 0.0 //How much would a partner get in them if they climax using this?
- var/size = 2 //can vary between num or text, just used in icon_state strings
- var/fluid_id = null
- var/fluid_max_volume = 15
- var/fluid_efficiency = 1
- var/fluid_rate = 1
- var/fluid_mult = 1
- var/producing = FALSE
- var/aroused_state = FALSE //Boolean used in icon_state strings
- var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons.
- var/obj/item/organ/genital/linked_organ
- var/through_clothes = FALSE
- var/internal = FALSE
- var/hidden = FALSE
-
-/obj/item/organ/genital/Initialize()
- . = ..()
- if(!reagents)
- create_reagents(fluid_max_volume)
- update()
-
-/obj/item/organ/genital/Destroy()
- remove_ref()
- if(owner)
- Remove(owner, 1)//this should remove references to it, so it can be GCd correctly
- update_link()//this should remove any other links it has
- return ..()
-
-/obj/item/organ/genital/proc/update()
- if(QDELETED(src))
- return
- update_size()
- update_appearance()
- update_link()
-
-//exposure and through-clothing code
-/mob/living/carbon
- var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed
-
-/obj/item/organ/genital/proc/is_exposed()
- if(!owner)
- return FALSE
- if(hidden)
- return FALSE
- if(internal)
- return FALSE
- if(through_clothes)
- return TRUE
-
- switch(zone) //update as more genitals are added
- if("chest")
- return owner.is_chest_exposed()
- if("groin")
- return owner.is_groin_exposed()
-
- return FALSE
-
-/obj/item/organ/genital/proc/toggle_visibility(visibility)
- switch(visibility)
- if("Always visible")
- through_clothes = TRUE
- hidden = FALSE
- if(!(src in owner.exposed_genitals))
- owner.exposed_genitals += src
- if("Hidden by clothes")
- through_clothes = FALSE
- hidden = TRUE
- if(src in owner.exposed_genitals)
- owner.exposed_genitals -= src
- if("Always hidden")
- through_clothes = FALSE
- hidden = TRUE
- if(src in owner.exposed_genitals)
- owner.exposed_genitals -= src
-
- if(ishuman(owner)) //recast to use update genitals proc
- var/mob/living/carbon/human/H = owner
- H.update_genitals()
-
-/mob/living/carbon/verb/toggle_genitals()
- set category = "IC"
- set name = "Expose/Hide genitals"
- set desc = "Allows you to toggle which genitals should show through clothes or not."
-
- var/list/genital_list = list()
- for(var/obj/item/organ/O in internal_organs)
- if(isgenital(O))
- var/obj/item/organ/genital/G = O
- if(!G.internal)
- genital_list += G
- if(!genital_list.len) //There is nothing to expose
- return
- //Full list of exposable genitals created
- var/obj/item/organ/genital/picked_organ
- picked_organ = input(src, "Choose which genitalia to expose/hide", "Expose/Hide genitals", null) in genital_list
- if(picked_organ)
- var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
- picked_organ.toggle_visibility(picked_visibility)
- return
-
-
-
-
-/obj/item/organ/genital/proc/update_size()
- return
-
-/obj/item/organ/genital/proc/update_appearance()
- return
-
-/obj/item/organ/genital/proc/update_link()
- return
-
-/obj/item/organ/genital/proc/remove_ref()
- if(linked_organ)
- linked_organ.linked_organ = null
- linked_organ = null
-
-/obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0)
- ..()
- update()
-
-/obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0)
- ..()
- update()
-
-//proc to give a player their genitals and stuff when they log in
-/mob/living/carbon/human/proc/give_genitals(clean=0)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA
- if(clean)
- var/obj/item/organ/genital/GtoClean
- for(GtoClean in internal_organs)
- qdel(GtoClean)
- if (NOGENITALS in dna.species.species_traits)
- return
- //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in.
- if(dna.features["has_vag"])
- give_vagina()
- if(dna.features["has_womb"])
- give_womb()
- if(dna.features["has_balls"])
- give_balls()
- if(dna.features["has_breasts"]) // since we have multi-boobs as a thing, we'll want to at least draw over these. but not over the pingas.
- give_breasts()
- if(dna.features["has_cock"])
- give_penis()
- if(dna.features["has_ovi"])
- give_ovipositor()
- if(dna.features["has_eggsack"])
- give_eggsack()
-
-/mob/living/carbon/human/proc/give_penis()
- if(!dna)
- return FALSE
- if(NOGENITALS in dna.species.species_traits)
- return FALSE
- if(!getorganslot("penis"))
- var/obj/item/organ/genital/penis/P = new
- P.Insert(src)
- if(P)
- if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
- P.color = "#[skintone2hex(skin_tone)]"
- else
- P.color = "#[dna.features["cock_color"]]"
- P.length = dna.features["cock_length"]
- P.girth_ratio = dna.features["cock_girth_ratio"]
- P.shape = dna.features["cock_shape"]
- P.prev_length = P.length
- P.cached_length = P.length
- P.update()
-
-/mob/living/carbon/human/proc/give_balls()
- if(!dna)
- return FALSE
- if(NOGENITALS in dna.species.species_traits)
- return FALSE
- if(!getorganslot("testicles"))
- var/obj/item/organ/genital/testicles/T = new
- T.Insert(src)
- if(T)
- if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
- T.color = "#[skintone2hex(skin_tone)]"
- else
- T.color = "#[dna.features["balls_color"]]"
- T.size = dna.features["balls_size"]
- T.sack_size = dna.features["balls_sack_size"]
- T.shape = dna.features["balls_shape"]
- if(dna.features["balls_shape"] == "Hidden")
- T.internal = TRUE
- else
- T.internal = FALSE
- T.fluid_id = dna.features["balls_fluid"]
- T.fluid_rate = dna.features["balls_cum_rate"]
- T.fluid_mult = dna.features["balls_cum_mult"]
- T.fluid_efficiency = dna.features["balls_efficiency"]
- T.update()
-
-/mob/living/carbon/human/proc/give_breasts()
- if(!dna)
- return FALSE
- if(NOGENITALS in dna.species.species_traits)
- return FALSE
- if(!getorganslot("breasts"))
- var/obj/item/organ/genital/breasts/B = new
- B.Insert(src)
- if(B)
- if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
- B.color = "#[skintone2hex(skin_tone)]"
- else
- B.color = "#[dna.features["breasts_color"]]"
- B.size = dna.features["breasts_size"]
- if(!isnum(B.size))
- if(B.size == "flat")
- B.cached_size = 0
- B.prev_size = 0
- else if (B.cached_size == "huge")
- B.prev_size = "huge"
- else
- B.cached_size = B.breast_values[B.size]
- B.prev_size = B.size
- else
- B.cached_size = B.size
- B.prev_size = B.size
- B.shape = dna.features["breasts_shape"]
- B.fluid_id = dna.features["breasts_fluid"]
- B.producing = dna.features["breasts_producing"]
- B.update()
-
-
-/mob/living/carbon/human/proc/give_ovipositor()
- return
-/mob/living/carbon/human/proc/give_eggsack()
- return
-
-/mob/living/carbon/human/proc/give_vagina()
- if(!dna)
- return FALSE
- if(NOGENITALS in dna.species.species_traits)
- return FALSE
- if(!getorganslot("vagina"))
- var/obj/item/organ/genital/vagina/V = new
- V.Insert(src)
- if(V)
- if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
- V.color = "#[skintone2hex(skin_tone)]"
- else
- V.color = "[dna.features["vag_color"]]"
- V.shape = "[dna.features["vag_shape"]]"
- V.update()
-
-/mob/living/carbon/human/proc/give_womb()
- if(!dna)
- return FALSE
- if(NOGENITALS in dna.species.species_traits)
- return FALSE
- if(!getorganslot("womb"))
- var/obj/item/organ/genital/womb/W = new
- W.Insert(src)
- if(W)
- W.update()
-
-
-/datum/species/proc/genitals_layertext(layer)
- switch(layer)
- if(GENITALS_BEHIND_LAYER)
- return "BEHIND"
- /*if(GENITALS_ADJ_LAYER)
- return "ADJ"*/
- if(GENITALS_FRONT_LAYER)
- return "FRONT"
-
-//procs to handle sprite overlays being applied to humans
-
-/obj/item/equipped(mob/user, slot)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- H.update_genitals()
- ..()
-
-/mob/living/carbon/human/doUnEquip(obj/item/I, force)
- . = ..()
- if(!.)
- return
- update_genitals()
-
-/mob/living/carbon/human/proc/update_genitals()
- if(src && !QDELETED(src))
- dna.species.handle_genitals(src)
-
-//fermichem procs
-/mob/living/carbon/human/proc/Force_update_genitals(mob/living/carbon/human/H) //called in fermiChem
- dna.species.handle_genitals(src)//should work.
- //dna.species.handle_breasts(src)
-
-//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
-/mob/living/carbon/human/proc/emergent_genital_call()
- var/organCheck = FALSE
- var/breastCheck = FALSE
- var/willyCheck = FALSE
- if(!canbearoused)
- ADD_TRAIT(src, TRAIT_PHARMA, "pharma")//Prefs prevent unwanted organs.
- return
- for(var/obj/item/organ/O in internal_organs)
- if(istype(O, /obj/item/organ/genital))
- organCheck = TRUE
- if(/obj/item/organ/genital/penis)
- //dna.features["has_cock"] = TRUE
- willyCheck = TRUE
- if(/obj/item/organ/genital/breasts)
- //dna.features["has_breasts"] = TRUE//Goddamnit get in there.
- breastCheck = TRUE
- if(organCheck == FALSE)
- if(ishuman(src) && dna.species.id == "human")
- dna.features["genitals_use_skintone"] = TRUE
- dna.species.use_skintones = TRUE
- if(MUTCOLORS)
- if(src.dna.species.fixed_mut_color)
- dna.features["cock_color"] = "[src.dna.species.fixed_mut_color]"
- dna.features["breasts_color"] = "[src.dna.species.fixed_mut_color]"
- return
- //So people who haven't set stuff up don't get rainbow surprises.
- dna.features["cock_color"] = "[dna.features["mcolor"]]"
- dna.features["breasts_color"] = "[dna.features["mcolor"]]"
- else //If there's a new organ, make it the same colour.
- if(breastCheck == FALSE)
- dna.features["breasts_color"] = dna.features["cock_color"]
- else if (willyCheck == FALSE)
- dna.features["cock_color"] = dna.features["breasts_color"]
- return
-
-/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
- if(!H)//no args
- CRASH("H = null")
- if(!LAZYLEN(H.internal_organs))//if they have no organs, we're done
- return
- if((NOGENITALS in species_traits) && (H.genital_override = FALSE))//golems and such - things that shouldn't
- return
- if(HAS_TRAIT(H, TRAIT_HUSK))
- return
- var/list/genitals_to_add = list()
- var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) //GENITALS_ADJ_LAYER removed
- var/list/standing = list()
- var/size
- var/aroused_state
-
- for(var/L in relevant_layers) //Less hardcode
- H.remove_overlay(L)
- //start scanning for genitals
- for(var/obj/item/organ/O in H.internal_organs)
- if(isgenital(O))
- var/obj/item/organ/genital/G = O
- if(G.hidden)
- return //we're gunna just hijack this for updates.
- if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
- genitals_to_add += H.getorganslot(G.slot)
- //Now we added all genitals that aren't internal and should be rendered
- //start applying overlays
- for(var/layer in relevant_layers)
- var/layertext = genitals_layertext(layer)
- for(var/obj/item/organ/genital/G in genitals_to_add)
- var/datum/sprite_accessory/S
- size = G.size
- aroused_state = G.aroused_state
- switch(G.type)
- if(/obj/item/organ/genital/penis)
- S = GLOB.cock_shapes_list[G.shape]
- if(/obj/item/organ/genital/testicles)
- S = GLOB.balls_shapes_list[G.shape]
- if(/obj/item/organ/genital/vagina)
- S = GLOB.vagina_shapes_list[G.shape]
- if(/obj/item/organ/genital/breasts)
- S = GLOB.breasts_shapes_list[G.shape]
-
-
-
-
- if(!S || S.icon_state == "none")
- continue
-
- var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
- genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
-
- if(S.center)
- genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
-
- if(use_skintones && H.dna.features["genitals_use_skintone"])
- genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
- genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]"
- else
- switch(S.color_src)
- if("cock_color")
- genital_overlay.color = "#[H.dna.features["cock_color"]]"
- if("balls_color")
- genital_overlay.color = "#[H.dna.features["balls_color"]]"
- if("breasts_color")
- genital_overlay.color = "#[H.dna.features["breasts_color"]]"
- if("vag_color")
- genital_overlay.color = "#[H.dna.features["vag_color"]]"
-
- standing += genital_overlay
-
- if(LAZYLEN(standing))
- H.overlays_standing[layer] = standing.Copy()
- standing = list()
-
- for(var/L in relevant_layers)
- H.apply_overlay(L)
diff --git a/modular_citadel/code/modules/arousal/organs/ovipositor.dm b/modular_citadel/code/modules/arousal/organs/ovipositor.dm
index 76bf60d93c..c26424d296 100644
--- a/modular_citadel/code/modules/arousal/organs/ovipositor.dm
+++ b/modular_citadel/code/modules/arousal/organs/ovipositor.dm
@@ -3,14 +3,14 @@
desc = "An egg laying reproductive organ."
icon_state = "ovi_knotted_2"
icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
- zone = "groin"
- slot = "penis"
- w_class = 3
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = ORGAN_SLOT_PENIS
+ genital_flags = GENITAL_BLACKLISTED //unimplemented
shape = "knotted"
size = 3
+ layer_index = PENIS_LAYER_INDEX
var/length = 6 //inches
var/girth = 0
var/girth_ratio = COCK_GIRTH_RATIO_DEF //citadel_defines.dm for these defines
var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
var/list/oviflags = list()
- var/obj/item/organ/eggsack/linked_eggsack
diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm
index 43a512acf6..17cd35c144 100644
--- a/modular_citadel/code/modules/arousal/organs/penis.dm
+++ b/modular_citadel/code/modules/arousal/organs/penis.dm
@@ -1,77 +1,78 @@
/obj/item/organ/genital/penis
- name = "penis"
- desc = "A male reproductive organ."
- icon_state = "penis"
- icon = 'modular_citadel/icons/obj/genitals/penis.dmi'
- zone = "groin"
- slot = ORGAN_SLOT_PENIS
- can_masturbate_with = TRUE
- masturbation_verb = "stroke"
- can_climax = TRUE
- fluid_transfer_factor = 0.5
- size = 2 //arbitrary value derived from length and girth for sprites.
- var/length = 6 //inches
- var/cached_length //used to detect a change in length
- var/girth = 4.38
- var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
- var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
- var/list/dickflags = list()
- var/list/knotted_types = list("knotted", "barbed, knotted")
- var/prev_length = 6 //really should be renamed to prev_length
+ name = "penis"
+ desc = "A male reproductive organ."
+ icon_state = "penis"
+ icon = 'modular_citadel/icons/obj/genitals/penis.dmi'
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = ORGAN_SLOT_PENIS
+ masturbation_verb = "stroke"
+ genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
+ linked_organ_slot = ORGAN_SLOT_TESTICLES
+ fluid_transfer_factor = 0.5
+ size = 2 //arbitrary value derived from length and girth for sprites.
+ layer_index = PENIS_LAYER_INDEX
+ var/length = 6 //inches
+ var/prev_length = 6 //really should be renamed to prev_length
+ var/girth = 4.38
+ var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
-/obj/item/organ/genital/penis/Initialize()
- . = ..()
- /* I hate genitals.*/
-
-/obj/item/organ/genital/penis/update_size()
- var/mob/living/carbon/human/o = owner
- if(!ishuman(o) || !o)
+/obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY)
+ var/new_value = CLAMP(length + modifier, min, max)
+ if(new_value == length)
return
- if(cached_length < 0)//I don't actually know what round() does to negative numbers, so to be safe!!
- var/obj/item/organ/genital/penis/P = o.getorganslot("penis")
- to_chat(o, "You feel your tallywacker shrinking away from your body as your groin flattens out!")
- P.Remove(o)
- switch(round(cached_length))
- if(0 to 4) //If modest size
- length = cached_length
- size = 1
- if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
- o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(5 to 10) //If modest size
- length = cached_length
- size = 2
- if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
- o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(11 to 20) //If massive
- length = cached_length
- size = 3
- if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
- o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(21 to 35) //If massive and due for large effects
- length = cached_length
- size = 3
- if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
- o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
- if(36 to INFINITY) //If comical
- length = cached_length
- size = 4 //no new sprites for anything larger yet
- if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
- o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
-
- if (round(length) > round(prev_length))
- to_chat(o, "Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.")
- else if ((round(length) < round(prev_length)) && (length > 0.5))
- to_chat(o, "Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.")
prev_length = length
+ length = CLAMP(length + modifier, min, max)
+ update()
+
+/obj/item/organ/genital/penis/update_size(modified = FALSE)
+ if(length < 0)//I don't actually know what round() does to negative numbers, so to be safe!!
+ if(owner)
+ to_chat(owner, "You feel your tallywacker shrinking away from your body as your groin flattens out!")
+ QDEL_IN(src, 1)
+ if(linked_organ)
+ QDEL_IN(linked_organ, 1)
+ return
+ var/rounded_length = round(length)
+ var/new_size
+ var/enlargement = FALSE
+ switch(rounded_length)
+ if(0 to 6) //If modest size
+ new_size = 1
+ if(7 to 11) //If large
+ new_size = 2
+ if(12 to 20) //If massive
+ new_size = 3
+ if(21 to 34) //If massive and due for large effects
+ new_size = 3
+ enlargement = TRUE
+ if(35 to INFINITY) //If comical
+ new_size = 4 //no new sprites for anything larger yet
+ enlargement = TRUE
+ if(owner)
+ var/status_effect = owner.has_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
+ if(enlargement && !status_effect)
+ owner.apply_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
+ else if(!enlargement && status_effect)
+ owner.remove_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
+ if(linked_organ)
+ linked_organ.size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX)
+ linked_organ.update()
+ size = new_size
+
+ if(owner)
+ if (round(length) > round(prev_length))
+ to_chat(owner, "Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.")
+ else if ((round(length) < round(prev_length)) && (length > 0.5))
+ to_chat(owner, "Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.")
icon_state = sanitize_text("penis_[shape]_[size]")
girth = (length * girth_ratio)//Is it just me or is this ludicous, why not make it exponentially decay?
- //I have no idea on how to update sprites and I hate it
/obj/item/organ/genital/penis/update_appearance()
+ . = ..()
var/string
var/lowershape = lowertext(shape)
- desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] penis. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth."
+ desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth."
if(owner)
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
@@ -87,13 +88,13 @@
icon_state = sanitize_text(string)
H.update_genitals()
-/obj/item/organ/genital/penis/update_link()
- if(owner)
- linked_organ = (owner.getorganslot("testicles"))
- if(linked_organ)
- linked_organ.linked_organ = src
- linked_organ.size = size
+/obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H)
+ var/datum/dna/D = H.dna
+ if(D.species.use_skintones && D.features["genitals_use_skintone"])
+ color = "#[skintone2hex(H.skin_tone)]"
else
- if(linked_organ)
- linked_organ.linked_organ = null
- linked_organ = null
+ color = "#[D.features["cock_color"]]"
+ length = D.features["cock_length"]
+ girth_ratio = D.features["cock_girth_ratio"]
+ shape = D.features["cock_shape"]
+ prev_length = length
diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm
index f4ef4b5064..547674a5f1 100644
--- a/modular_citadel/code/modules/arousal/organs/testicles.dm
+++ b/modular_citadel/code/modules/arousal/organs/testicles.dm
@@ -1,82 +1,46 @@
/obj/item/organ/genital/testicles
- name = "testicles"
- desc = "A male reproductive organ."
- icon_state = "testicles"
- icon = 'modular_citadel/icons/obj/genitals/testicles.dmi'
- zone = "groin"
- slot = "testicles"
- size = BALLS_SIZE_MIN
- var/size_name = "average"
- shape = "single"
- var/sack_size = BALLS_SACK_SIZE_DEF
- fluid_id = "semen"
- producing = TRUE
- can_masturbate_with = FALSE
- masturbation_verb = "massage"
- can_climax = TRUE
- var/sent_full_message = TRUE //defaults to 1 since they're full to start
+ name = "testicles"
+ desc = "A male reproductive organ."
+ icon_state = "testicles"
+ icon = 'modular_citadel/icons/obj/genitals/testicles.dmi'
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = ORGAN_SLOT_TESTICLES
+ size = BALLS_SIZE_MIN
+ linked_organ_slot = ORGAN_SLOT_PENIS
+ genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION
+ var/size_name = "average"
+ shape = "Single"
+ var/sack_size = BALLS_SACK_SIZE_DEF
+ fluid_id = "semen"
+ masturbation_verb = "massage"
+ layer_index = TESTICLES_LAYER_INDEX
-/obj/item/organ/genital/testicles/on_life()
- if(QDELETED(src))
- return
- if(reagents && producing)
- if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
- fluid_rate = 0.1
- else
- fluid_rate = CUM_RATE
- if(reagents.total_volume >= 5)
- fluid_mult = 0.5
- else
- fluid_mult = 1
- generate_cum()
-
-/obj/item/organ/genital/testicles/proc/generate_cum()
- reagents.maximum_volume = fluid_max_volume
- if(reagents.total_volume >= reagents.maximum_volume)
- if(!sent_full_message)
- send_full_message()
- sent_full_message = TRUE
+/obj/item/organ/genital/testicles/generate_fluid()
+ if(!linked_organ && !update_link())
return FALSE
- sent_full_message = FALSE
- update_link()
- if(!linked_organ)
- return FALSE
- reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
- reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum
+ . = ..()
+ if(. && reagents.holder_full())
+ to_chat(owner, "Your balls finally feel full, again.")
-/obj/item/organ/genital/testicles/update_link()
- if(owner && !QDELETED(src))
- linked_organ = (owner.getorganslot("penis"))
- if(linked_organ)
- linked_organ.linked_organ = src
- size = linked_organ.size
+/obj/item/organ/genital/testicles/upon_link()
+ size = linked_organ.size
+ update_size()
+ update_appearance()
- else
- if(linked_organ)
- linked_organ.linked_organ = null
- linked_organ = null
-
-/obj/item/organ/genital/testicles/proc/send_full_message(msg = "Your balls finally feel full, again.")
- if(owner && istext(msg))
- to_chat(owner, msg)
- return TRUE
-
-/obj/item/organ/genital/testicles/update_appearance()
+/obj/item/organ/genital/testicles/update_size(modified = FALSE)
switch(size)
- if(0.1 to 1)
+ if(BALLS_SIZE_MIN)
size_name = "average"
- if(1.1 to 2)
+ if(BALLS_SIZE_DEF)
size_name = "enlarged"
- if(2.1 to INFINITY)
+ if(BALLS_SIZE_MAX)
size_name = "engorged"
else
size_name = "nonexistant"
- if(!internal)
- desc = "You see an [size_name] pair of testicles."
- else
- desc = "They don't have any testicles you can see."
-
+/obj/item/organ/genital/testicles/update_appearance()
+ . = ..()
+ desc = "You see an [size_name] pair of testicles."
if(owner)
var/string
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
@@ -91,3 +55,18 @@
var/mob/living/carbon/human/H = owner
icon_state = sanitize_text(string)
H.update_genitals()
+
+/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H)
+ var/datum/dna/D = H.dna
+ if(D.species.use_skintones && D.features["genitals_use_skintone"])
+ color = "#[skintone2hex(H.skin_tone)]"
+ else
+ color = "#[D.features["balls_color"]]"
+ sack_size = D.features["balls_sack_size"]
+ shape = D.features["balls_shape"]
+ if(D.features["balls_shape"] == "Hidden")
+ ENABLE_BITFIELD(genital_flags, GENITAL_INTERNAL)
+ fluid_id = D.features["balls_fluid"]
+ fluid_rate = D.features["balls_cum_rate"]
+ fluid_mult = D.features["balls_cum_mult"]
+ fluid_efficiency = D.features["balls_efficiency"]
diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm
index 8c15aa5437..0df954fd79 100644
--- a/modular_citadel/code/modules/arousal/organs/vagina.dm
+++ b/modular_citadel/code/modules/arousal/organs/vagina.dm
@@ -1,26 +1,25 @@
/obj/item/organ/genital/vagina
- name = "vagina"
- desc = "A female reproductive organ."
- icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
- icon_state = "vagina"
- zone = "groin"
- slot = "vagina"
- size = 1 //There is only 1 size right now
- can_masturbate_with = TRUE
- masturbation_verb = "finger"
- can_climax = TRUE
+ name = "vagina"
+ desc = "A female reproductive organ."
+ icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
+ icon_state = ORGAN_SLOT_VAGINA
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = "vagina"
+ size = 1 //There is only 1 size right now
+ genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
+ masturbation_verb = "finger"
fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS
- w_class = 3
- var/cap_length = 8//D E P T H (cap = capacity)
- var/cap_girth = 12
+ layer_index = VAGINA_LAYER_INDEX
+ var/cap_length = 8//D E P T H (cap = capacity)
+ var/cap_girth = 12
var/cap_girth_ratio = 1.5
- var/clits = 1
- var/clit_diam = 0.25
- var/clit_len = 0.25
+ var/clits = 1
+ var/clit_diam = 0.25
+ var/clit_len = 0.25
var/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred")
-
/obj/item/organ/genital/vagina/update_appearance()
+ . = ..()
var/string //Keeping this code here, so making multiple sprites for the different kinds is easier.
var/lowershape = lowertext(shape)
var/details
@@ -63,12 +62,10 @@
icon_state = sanitize_text(string)
H.update_genitals()
-/obj/item/organ/genital/vagina/update_link()
- if(owner)
- linked_organ = (owner.getorganslot("womb"))
- if(linked_organ)
- linked_organ.linked_organ = src
+/obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H)
+ var/datum/dna/D = H.dna
+ if(D.species.use_skintones && D.features["genitals_use_skintone"])
+ color = "#[skintone2hex(H.skin_tone)]"
else
- if(linked_organ)
- linked_organ.linked_organ = null
- linked_organ = null
+ color = "[D.features["vag_color"]]"
+ shape = "[D.features["vag_shape"]]"
diff --git a/modular_citadel/code/modules/arousal/organs/womb.dm b/modular_citadel/code/modules/arousal/organs/womb.dm
index 3f190b72ac..9dfe811571 100644
--- a/modular_citadel/code/modules/arousal/organs/womb.dm
+++ b/modular_citadel/code/modules/arousal/organs/womb.dm
@@ -1,45 +1,10 @@
/obj/item/organ/genital/womb
- name = "womb"
- desc = "A female reproductive organ."
- icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
- icon_state = "womb"
- zone = "groin"
- slot = "womb"
- internal = TRUE
- fluid_id = "femcum"
- producing = TRUE
-
-/obj/item/organ/genital/womb/on_life()
- if(QDELETED(src))
- return
- if(reagents && producing)
- if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
- fluid_rate = 0.1
- else
- fluid_rate = CUM_RATE
- if(reagents.total_volume >= 5)
- fluid_mult = 0.5
- else
- fluid_mult = 1
- generate_femcum()
-
-/obj/item/organ/genital/womb/proc/generate_femcum()
- reagents.maximum_volume = fluid_max_volume
- update_link()
- if(!linked_organ)
- return FALSE
- reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
- reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum
-
-/obj/item/organ/genital/womb/update_link()
- if(owner)
- linked_organ = (owner.getorganslot("vagina"))
- if(linked_organ)
- linked_organ.linked_organ = src
- else
- if(linked_organ)
- linked_organ.linked_organ = null
- linked_organ = null
-
-/obj/item/organ/genital/womb/Destroy()
- return ..()
+ name = "womb"
+ desc = "A female reproductive organ."
+ icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
+ icon_state = "womb"
+ zone = BODY_ZONE_PRECISE_GROIN
+ slot = ORGAN_SLOT_WOMB
+ genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION
+ fluid_id = "femcum"
+ linked_organ_slot = ORGAN_SLOT_VAGINA
diff --git a/modular_citadel/code/modules/awaymissions/citadel_ghostrole_spawners.dm b/modular_citadel/code/modules/awaymissions/citadel_ghostrole_spawners.dm
deleted file mode 100644
index ccbf9a42fe..0000000000
--- a/modular_citadel/code/modules/awaymissions/citadel_ghostrole_spawners.dm
+++ /dev/null
@@ -1,73 +0,0 @@
-/obj/effect/mob_spawn/human/lavaknight
- name = "odd cryogenics pod"
- desc = "A humming cryo pod. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
- mob_name = "a displaced knight from another dimension"
- icon = 'icons/obj/machines/sleeper.dmi'
- icon_state = "sleeper"
- roundstart = FALSE
- job_description = "Cydonian Knight"
- death = FALSE
- random = TRUE
- outfit = /datum/outfit/lavaknight
- mob_species = /datum/species/human
- flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \
- You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
- Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth."
- assignedrole = "Cydonian Knight"
-
-/obj/effect/mob_spawn/human/lavaknight/special(mob/living/new_spawn)
- if(ishuman(new_spawn))
- var/mob/living/carbon/human/H = new_spawn
- H.dna.features["mam_ears"] = "Cat, Big" //cat people
- H.dna.features["mcolor"] = H.hair_color
- H.update_body()
-
-/obj/effect/mob_spawn/human/lavaknight/Destroy()
- new/obj/structure/showcase/machinery/oldpod/used(drop_location())
- return ..()
-
-/datum/outfit/lavaknight
- name = "Cydonian Knight"
- uniform = /obj/item/clothing/under/assistantformal
- mask = /obj/item/clothing/mask/breath
- shoes = /obj/item/clothing/shoes/sneakers/black
- r_pocket = /obj/item/melee/transforming/energy/sword/cx
- suit = /obj/item/clothing/suit/space/hardsuit/lavaknight
- suit_store = /obj/item/tank/internals/oxygen
- id = /obj/item/card/id/knight
-
-/datum/outfit/lavaknight/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- if(visualsOnly)
- return
-
- var/obj/item/card/id/knight/W = H.wear_id
- W.assignment = "Knight"
- W.registered_name = H.real_name
- W.id_color = "#0000FF" //Regular knights get simple blue. Doesn't matter much because it's variable anyway
- W.update_label(H.real_name)
- W.update_icon()
-
-/datum/outfit/lavaknight/captain
- name ="Cydonian Knight Captain"
- l_pocket = /obj/item/twohanded/dualsaber/hypereutactic
-
-/datum/outfit/lavaknight/captain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- if(visualsOnly)
- return
-
- var/obj/item/card/id/knight/W = H.wear_id
- W.assignment = "Knight Captain"
- W.registered_name = H.real_name
- W.id_color = "#FFD700" //Captains get gold, duh. Doesn't matter because it's variable anyway
- W.update_label(H.real_name)
- W.update_icon()
-
-
-/obj/effect/mob_spawn/human/lavaknight/captain
- name = "odd gilded cryogenics pod"
- desc = "A humming cryo pod that appears to be gilded. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
- flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \
- You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
- Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth. \
- You feel a natural instict to lead, and as such, you should strive to lead your comrades to safety, and hopefully home. You also feel a burning determination to uphold your vow, as well as your fellow comrade's."
- outfit = /datum/outfit/lavaknight/captain
diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm
index 7e7038cb31..6dff621271 100644
--- a/modular_citadel/code/modules/client/loadout/__donator.dm
+++ b/modular_citadel/code/modules/client/loadout/__donator.dm
@@ -452,3 +452,9 @@ datum/gear/darksabresheath
category = SLOT_HEAD
path = /obj/item/clothing/head/flight
ckeywhitelist = list("maxlynchy")
+
+/datum/gear/onionneck
+ name = "Onion Necklace"
+ category = SLOT_NECK
+ path = /obj/item/clothing/neck/necklace/onion
+ ckeywhitelist = list("cdrcross")
diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm
index 0a353e3f5d..5584181a70 100644
--- a/modular_citadel/code/modules/client/preferences_savefile.dm
+++ b/modular_citadel/code/modules/client/preferences_savefile.dm
@@ -32,7 +32,6 @@
WRITE_FILE(S["feature_ipc_antenna"], features["ipc_antenna"])
//Citadel
WRITE_FILE(S["feature_genitals_use_skintone"], features["genitals_use_skintone"])
- WRITE_FILE(S["feature_exhibitionist"], features["exhibitionist"])
WRITE_FILE(S["feature_mcolor2"], features["mcolor2"])
WRITE_FILE(S["feature_mcolor3"], features["mcolor3"])
WRITE_FILE(S["feature_mam_body_markings"], features["mam_body_markings"])
diff --git a/modular_citadel/code/modules/clothing/spacesuits/cydonian_armor.dm b/modular_citadel/code/modules/clothing/spacesuits/cydonian_armor.dm
deleted file mode 100644
index 423bc536ac..0000000000
--- a/modular_citadel/code/modules/clothing/spacesuits/cydonian_armor.dm
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- CYDONIAN ARMOR THAT IS RGB AND STUFF WOOOOOOOOOO
-*/
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight
- name = "cydonian helmet"
- desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
- icon = 'modular_citadel/icons/lavaknight/item/head.dmi'
- icon_state = "knight_cydonia"
- item_state = "knight_yellow"
- item_color = null
- alternate_worn_icon = 'modular_citadel/icons/lavaknight/mob/head.dmi'
- max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | LAVA_PROOF
- heat_protection = HEAD
- armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
- brightness_on = 7
- allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
- var/energy_color = "#35FFF0"
- var/obj/item/clothing/suit/space/hardsuit/lavaknight/linkedsuit = null
- mutantrace_variation = NO_MUTANTRACE_VARIATION
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/New()
- ..()
- if(istype(loc, /obj/item/clothing/suit/space/hardsuit/lavaknight))
- linkedsuit = loc
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/attack_self(mob/user)
- on = !on
-
- if(on)
- set_light(brightness_on)
- else
- set_light(0)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_icon()
- var/mutable_appearance/helm_overlay = mutable_appearance('modular_citadel/icons/lavaknight/item/head.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
-
- if(energy_color)
- helm_overlay.color = energy_color
-
- helm_overlay.plane = LIGHTING_PLANE + 1 //Magic number is used here because we have no ABOVE_LIGHTING_PLANE plane defined. Lighting plane is 15, HUD is 18
-
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
-
- add_overlay(helm_overlay)
-
- emissivelights()
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/equipped(mob/user, slot)
- ..()
- if(slot == SLOT_HEAD)
- emissivelights()
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/dropped(mob/user)
- ..()
- emissivelightsoff()
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/proc/emissivelights(mob/user = usr)
- var/mutable_appearance/energy_overlay = mutable_appearance('modular_citadel/icons/lavaknight/mob/head.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
- energy_overlay.color = energy_color
- energy_overlay.plane = LIGHTING_PLANE + 1
- user.cut_overlay(energy_overlay) //honk
- user.add_overlay(energy_overlay) //honk
-
-/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/proc/emissivelightsoff(mob/user = usr)
- user.cut_overlay()
- linkedsuit.emissivelights() //HONK HONK HONK MAXIMUM SPAGHETTI
- user.regenerate_icons() //honk
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight
- icon = 'modular_citadel/icons/lavaknight/item/suit.dmi'
- icon_state = "knight_cydonia"
- name = "cydonian armor"
- desc = "A suit designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
- item_state = "swat_suit"
- alternate_worn_icon = 'modular_citadel/icons/lavaknight/mob/suit.dmi'
- max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
- resistance_flags = FIRE_PROOF | LAVA_PROOF
- armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100)
- allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe)
- helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight
- heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- actions_types = list(/datum/action/item_action/toggle_helmet)
- var/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/linkedhelm
- tauric = TRUE //Citadel Add for tauric hardsuits
-
- var/energy_color = "#35FFF0"
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/New()
- ..()
- if(helmet)
- linkedhelm = helmet
- light_color = energy_color
- set_light(1)
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/Initialize()
- ..()
- update_icon()
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/update_icon()
- var/mutable_appearance/suit_overlay
-
- if(taurmode == SNEK_TAURIC)
- suit_overlay = mutable_appearance('modular_citadel/icons/mob/taur_naga.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
- else if(taurmode == PAW_TAURIC)
- suit_overlay = mutable_appearance('modular_citadel/icons/mob/taur_canine.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
- else
- suit_overlay = mutable_appearance('modular_citadel/icons/lavaknight/item/suit.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
-
- if(energy_color)
- suit_overlay.color = energy_color
-
- suit_overlay.plane = LIGHTING_PLANE + 1 //Magic number is used here because we have no ABOVE_LIGHTING_PLANE plane defined. Lighting plane is 15.
-
- cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
-
- add_overlay(suit_overlay)
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/equipped(mob/user, slot)
- ..()
- if(slot == SLOT_WEAR_SUIT)
- emissivelights()
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/dropped(mob/user)
- ..()
- emissivelightsoff()
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/proc/emissivelights(mob/user = usr)
- var/mutable_appearance/energy_overlay
- if(taurmode == SNEK_TAURIC)
- energy_overlay = mutable_appearance('modular_citadel/icons/mob/taur_naga.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
- else if(taurmode == PAW_TAURIC)
- energy_overlay = mutable_appearance('modular_citadel/icons/mob/taur_canine.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
- else
- energy_overlay = mutable_appearance('modular_citadel/icons/lavaknight/mob/suit.dmi', "knight_cydonia_overlay", LIGHTING_LAYER + 1)
-
- energy_overlay.color = energy_color
- energy_overlay.plane = LIGHTING_PLANE + 1
- user.cut_overlay(energy_overlay) //honk
- user.add_overlay(energy_overlay) //honk
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/proc/emissivelightsoff(mob/user = usr)
- user.cut_overlays()
- user.regenerate_icons() //honk
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/AltClick(mob/living/user)
- if(user.incapacitated() || !istype(user))
- to_chat(user, "You can't do that right now!")
- return
- if(!in_range(src, user))
- return
- if(user.incapacitated() || !istype(user) || !in_range(src, user))
- return
-
- if(alert("Are you sure you want to recolor your armor stripes?", "Confirm Repaint", "Yes", "No") == "Yes")
- var/energy_color_input = input(usr,"","Choose Energy Color",energy_color) as color|null
- if(energy_color_input)
- energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- user.update_inv_wear_suit()
- if(linkedhelm)
- linkedhelm.energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
- user.update_inv_head()
- linkedhelm.update_icon()
- update_icon()
- user.update_inv_wear_suit()
- light_color = energy_color
- emissivelights()
- update_light()
-
-/obj/item/clothing/suit/space/hardsuit/lavaknight/examine(mob/user)
- ..()
- to_chat(user, "Alt-click to recolor it.")
\ No newline at end of file
diff --git a/modular_citadel/code/modules/custom_loadout/custom_items.dm b/modular_citadel/code/modules/custom_loadout/custom_items.dm
index 32c73cc40a..11dbb4dc80 100644
--- a/modular_citadel/code/modules/custom_loadout/custom_items.dm
+++ b/modular_citadel/code/modules/custom_loadout/custom_items.dm
@@ -501,3 +501,11 @@
item_state = "flight-g"
icon = 'icons/obj/custom.dmi'
alternate_worn_icon = 'icons/mob/custom_w.dmi'
+
+/obj/item/clothing/neck/necklace/onion
+ name = "Onion Necklace"
+ desc = "A string of onions sequenced together to form a necklace."
+ icon = 'icons/obj/custom.dmi'
+ icon_state = "onion"
+ item_state = "onion"
+ alternate_worn_icon = 'icons/mob/custom_w.dmi'
diff --git a/modular_citadel/code/modules/events/blob.dm b/modular_citadel/code/modules/events/blob.dm
deleted file mode 100644
index e8e7106f5e..0000000000
--- a/modular_citadel/code/modules/events/blob.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/datum/round_event_control/blob
- earliest_start = 60 MINUTES
diff --git a/modular_citadel/code/modules/events/wizard/magicarp.dm b/modular_citadel/code/modules/events/wizard/magicarp.dm
deleted file mode 100644
index 10d269c698..0000000000
--- a/modular_citadel/code/modules/events/wizard/magicarp.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/mob/living/simple_animal/hostile/carp/ranged
- gold_core_spawnable = NO_SPAWN
diff --git a/modular_citadel/code/modules/jobs/dresscode_values.dm b/modular_citadel/code/modules/jobs/dresscode_values.dm
deleted file mode 100644
index 24cd5c5ac9..0000000000
--- a/modular_citadel/code/modules/jobs/dresscode_values.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-//This file controls whether or not a job complies with dresscodes.
-//If a job complies with dresscodes, loadout items will not be equipped instead of the job's outfit, instead placing the items into the player's backpack.
-
-/datum/job
- var/dresscodecompliant = TRUE
-
-/datum/job/assistant
- dresscodecompliant = FALSE
\ No newline at end of file
diff --git a/modular_citadel/code/modules/jobs/job_types/captain.dm b/modular_citadel/code/modules/jobs/job_types/captain.dm
deleted file mode 100644
index 7135e86507..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/captain.dm
+++ /dev/null
@@ -1,21 +0,0 @@
-/datum/job/captain
- minimal_player_age = 20
- exp_type = EXP_TYPE_COMMAND
-
-/datum/job/hop
- minimal_player_age = 20
- exp_type_department = EXP_TYPE_SERVICE
-
- access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
- ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
- ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
- ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
- ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
- ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
- ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
- ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
- ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER,
- ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION,
- ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
-
diff --git a/modular_citadel/code/modules/jobs/job_types/cargo_service.dm b/modular_citadel/code/modules/jobs/job_types/cargo_service.dm
deleted file mode 100644
index 965b554f3c..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/cargo_service.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/datum/job/bartender
- access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_BAR, ACCESS_MINERAL_STOREROOM)
-
-/datum/job/qm
- department_head = list("Captain")
- supervisors = "the captain"
- req_admin_notify = 1
- minimal_player_age = 10
- exp_requirements = 180
- exp_type_department = EXP_TYPE_SUPPLY
-
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE, ACCESS_SEC_DOORS, ACCESS_HEADS)
- minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE, ACCESS_SEC_DOORS, ACCESS_HEADS)
-
-/datum/outfit/job/quartermaster
- id = /obj/item/card/id/silver
- ears = /obj/item/radio/headset/heads/qm
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced = 1)
-
-/datum/job/cargo_tech
- department_head = list("Quartermaster")
- supervisors = "the quartermaster"
-
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
-
-/datum/job/mining
- department_head = list("Quartermaster")
- supervisors = "the quartermaster"
-
- access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
\ No newline at end of file
diff --git a/modular_citadel/code/modules/jobs/job_types/engineering.dm b/modular_citadel/code/modules/jobs/job_types/engineering.dm
deleted file mode 100644
index 4d6aa4119d..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/engineering.dm
+++ /dev/null
@@ -1,14 +0,0 @@
-/datum/job/chief_engineer
- minimal_player_age = 10
-
-/datum/job/engineer
- access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
- ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
- ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
-
-/datum/job/atmos
- access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
- ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ENGINE,
- ACCESS_ENGINE_EQUIP, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
diff --git a/modular_citadel/code/modules/jobs/job_types/medical.dm b/modular_citadel/code/modules/jobs/job_types/medical.dm
deleted file mode 100644
index 15841ad9d5..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/medical.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-/datum/job/cmo
- minimal_player_age = 10
-
-/datum/outfit/job/doctor
- backpack_contents = list(/obj/item/storage/hypospraykit/regular)
-
-/datum/outfit/job/chemist
- backpack_contents = list(/obj/item/storage/hypospraykit/regular)
diff --git a/modular_citadel/code/modules/jobs/job_types/science.dm b/modular_citadel/code/modules/jobs/job_types/science.dm
deleted file mode 100644
index 94272d24a6..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/science.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-/datum/job/rd
- minimal_player_age = 10
diff --git a/modular_citadel/code/modules/jobs/job_types/security.dm b/modular_citadel/code/modules/jobs/job_types/security.dm
deleted file mode 100644
index de00f2d948..0000000000
--- a/modular_citadel/code/modules/jobs/job_types/security.dm
+++ /dev/null
@@ -1,5 +0,0 @@
-/datum/job/hos
- minimal_player_age = 10
-
-/datum/outfit/job/warden
- suit_store = /obj/item/gun/energy/pumpaction/defender
diff --git a/modular_citadel/code/modules/mob/living/living.dm b/modular_citadel/code/modules/mob/living/living.dm
index ed33041d58..16bf776171 100644
--- a/modular_citadel/code/modules/mob/living/living.dm
+++ b/modular_citadel/code/modules/mob/living/living.dm
@@ -13,7 +13,7 @@
var/sprint_buffer_max = 42
var/sprint_buffer_regen_ds = 0.3 //Tiles per world.time decisecond
var/sprint_buffer_regen_last = 0 //last world.time this was regen'd for math.
- var/sprint_stamina_cost = 0.55 //stamina loss per tile while insufficient sprint buffer.
+ var/sprint_stamina_cost = 0.70 //stamina loss per tile while insufficient sprint buffer.
//---End
/mob/living/movement_delay(ignorewalk = 0)
diff --git a/modular_citadel/code/modules/mob/living/silicon/ai/vox_sounds.dm b/modular_citadel/code/modules/mob/living/silicon/ai/vox_sounds.dm
deleted file mode 100644
index b1e112aac5..0000000000
--- a/modular_citadel/code/modules/mob/living/silicon/ai/vox_sounds.dm
+++ /dev/null
@@ -1,633 +0,0 @@
-// List is required to compile the resources into the game when it loads.
-// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
-#ifdef AI_VOX
-
-GLOBAL_LIST_INIT(vox_sounds_male, list("," = 'modular_citadel/sound/vox/_comma.ogg',
-"." = 'modular_citadel/sound/vox/_period.ogg',
-"a" = 'modular_citadel/sound/vox/a.ogg',
-"accelerating" = 'modular_citadel/sound/vox/accelerating.ogg',
-"accelerator" = 'modular_citadel/sound/vox/accelerator.ogg',
-"accepted" = 'modular_citadel/sound/vox/accepted.ogg',
-"access" = 'modular_citadel/sound/vox/access.ogg',
-"acknowledge" = 'modular_citadel/sound/vox/acknowledge.ogg',
-"acknowledged" = 'modular_citadel/sound/vox/acknowledged.ogg',
-"acquired" = 'modular_citadel/sound/vox/acquired.ogg',
-"acquisition" = 'modular_citadel/sound/vox/acquisition.ogg',
-"across" = 'modular_citadel/sound/vox/across.ogg',
-"activate" = 'modular_citadel/sound/vox/activate.ogg',
-"activated" = 'modular_citadel/sound/vox/activated.ogg',
-"activity" = 'modular_citadel/sound/vox/activity.ogg',
-"adios" = 'modular_citadel/sound/vox/adios.ogg',
-"administration" = 'modular_citadel/sound/vox/administration.ogg',
-"advanced" = 'modular_citadel/sound/vox/advanced.ogg',
-"after" = 'modular_citadel/sound/vox/after.ogg',
-"agent" = 'modular_citadel/sound/vox/agent.ogg',
-"alarm" = 'modular_citadel/sound/vox/alarm.ogg',
-"alert" = 'modular_citadel/sound/vox/alert.ogg',
-"alien" = 'modular_citadel/sound/vox/alien.ogg',
-"aligned" = 'modular_citadel/sound/vox/aligned.ogg',
-"all" = 'modular_citadel/sound/vox/all.ogg',
-"alpha" = 'modular_citadel/sound/vox/alpha.ogg',
-"am" = 'modular_citadel/sound/vox/am.ogg',
-"amigo" = 'modular_citadel/sound/vox/amigo.ogg',
-"ammunition" = 'modular_citadel/sound/vox/ammunition.ogg',
-"an" = 'modular_citadel/sound/vox/an.ogg',
-"and" = 'modular_citadel/sound/vox/and.ogg',
-"announcement" = 'modular_citadel/sound/vox/announcement.ogg',
-"anomalous" = 'modular_citadel/sound/vox/anomalous.ogg',
-"antenna" = 'modular_citadel/sound/vox/antenna.ogg',
-"any" = 'modular_citadel/sound/vox/any.ogg',
-"apprehend" = 'modular_citadel/sound/vox/apprehend.ogg',
-"approach" = 'modular_citadel/sound/vox/approach.ogg',
-"are" = 'modular_citadel/sound/vox/are.ogg',
-"area" = 'modular_citadel/sound/vox/area.ogg',
-"arm" = 'modular_citadel/sound/vox/arm.ogg',
-"armed" = 'modular_citadel/sound/vox/armed.ogg',
-"armor" = 'modular_citadel/sound/vox/armor.ogg',
-"armory" = 'modular_citadel/sound/vox/armory.ogg',
-"arrest" = 'modular_citadel/sound/vox/arrest.ogg',
-"ass" = 'modular_citadel/sound/vox/ass.ogg',
-"at" = 'modular_citadel/sound/vox/at.ogg',
-"atomic" = 'modular_citadel/sound/vox/atomic.ogg',
-"attention" = 'modular_citadel/sound/vox/attention.ogg',
-"authorize" = 'modular_citadel/sound/vox/authorize.ogg',
-"authorized" = 'modular_citadel/sound/vox/authorized.ogg',
-"automatic" = 'modular_citadel/sound/vox/automatic.ogg',
-"away" = 'modular_citadel/sound/vox/away.ogg',
-"b" = 'modular_citadel/sound/vox/b.ogg',
-"back" = 'modular_citadel/sound/vox/back.ogg',
-"backman" = 'modular_citadel/sound/vox/backman.ogg',
-"bad" = 'modular_citadel/sound/vox/bad.ogg',
-"bag" = 'modular_citadel/sound/vox/bag.ogg',
-"bailey" = 'modular_citadel/sound/vox/bailey.ogg',
-"barracks" = 'modular_citadel/sound/vox/barracks.ogg',
-"base" = 'modular_citadel/sound/vox/base.ogg',
-"bay" = 'modular_citadel/sound/vox/bay.ogg',
-"be" = 'modular_citadel/sound/vox/be.ogg',
-"been" = 'modular_citadel/sound/vox/been.ogg',
-"before" = 'modular_citadel/sound/vox/before.ogg',
-"beyond" = 'modular_citadel/sound/vox/beyond.ogg',
-"biohazard" = 'modular_citadel/sound/vox/biohazard.ogg',
-"biological" = 'modular_citadel/sound/vox/biological.ogg',
-"birdwell" = 'modular_citadel/sound/vox/birdwell.ogg',
-"bizwarn" = 'modular_citadel/sound/vox/bizwarn.ogg',
-"black" = 'modular_citadel/sound/vox/black.ogg',
-"blast" = 'modular_citadel/sound/vox/blast.ogg',
-"blocked" = 'modular_citadel/sound/vox/blocked.ogg',
-"bloop" = 'modular_citadel/sound/vox/bloop.ogg',
-"blue" = 'modular_citadel/sound/vox/blue.ogg',
-"bottom" = 'modular_citadel/sound/vox/bottom.ogg',
-"bravo" = 'modular_citadel/sound/vox/bravo.ogg',
-"breach" = 'modular_citadel/sound/vox/breach.ogg',
-"breached" = 'modular_citadel/sound/vox/breached.ogg',
-"break" = 'modular_citadel/sound/vox/break.ogg',
-"bridge" = 'modular_citadel/sound/vox/bridge.ogg',
-"bust" = 'modular_citadel/sound/vox/bust.ogg',
-"but" = 'modular_citadel/sound/vox/but.ogg',
-"button" = 'modular_citadel/sound/vox/button.ogg',
-"buzwarn" = 'modular_citadel/sound/vox/buzwarn.ogg',
-"bypass" = 'modular_citadel/sound/vox/bypass.ogg',
-"c" = 'modular_citadel/sound/vox/c.ogg',
-"cable" = 'modular_citadel/sound/vox/cable.ogg',
-"call" = 'modular_citadel/sound/vox/call.ogg',
-"called" = 'modular_citadel/sound/vox/called.ogg',
-"canal" = 'modular_citadel/sound/vox/canal.ogg',
-"cap" = 'modular_citadel/sound/vox/cap.ogg',
-"captain" = 'modular_citadel/sound/vox/captain.ogg',
-"capture" = 'modular_citadel/sound/vox/capture.ogg',
-"captured" = 'modular_citadel/sound/vox/captured.ogg',
-"ceiling" = 'modular_citadel/sound/vox/ceiling.ogg',
-"celsius" = 'modular_citadel/sound/vox/celsius.ogg',
-"center" = 'modular_citadel/sound/vox/center.ogg',
-"centi" = 'modular_citadel/sound/vox/centi.ogg',
-"central" = 'modular_citadel/sound/vox/central.ogg',
-"chamber" = 'modular_citadel/sound/vox/chamber.ogg',
-"charlie" = 'modular_citadel/sound/vox/charlie.ogg',
-"check" = 'modular_citadel/sound/vox/check.ogg',
-"checkpoint" = 'modular_citadel/sound/vox/checkpoint.ogg',
-"chemical" = 'modular_citadel/sound/vox/chemical.ogg',
-"cleanup" = 'modular_citadel/sound/vox/cleanup.ogg',
-"clear" = 'modular_citadel/sound/vox/clear.ogg',
-"clearance" = 'modular_citadel/sound/vox/clearance.ogg',
-"close" = 'modular_citadel/sound/vox/close.ogg',
-"clown" = 'modular_citadel/sound/vox/clown.ogg',
-"code" = 'modular_citadel/sound/vox/code.ogg',
-"coded" = 'modular_citadel/sound/vox/coded.ogg',
-"collider" = 'modular_citadel/sound/vox/collider.ogg',
-"command" = 'modular_citadel/sound/vox/command.ogg',
-"communication" = 'modular_citadel/sound/vox/communication.ogg',
-"complex" = 'modular_citadel/sound/vox/complex.ogg',
-"computer" = 'modular_citadel/sound/vox/computer.ogg',
-"condition" = 'modular_citadel/sound/vox/condition.ogg',
-"containment" = 'modular_citadel/sound/vox/containment.ogg',
-"contamination" = 'modular_citadel/sound/vox/contamination.ogg',
-"control" = 'modular_citadel/sound/vox/control.ogg',
-"coolant" = 'modular_citadel/sound/vox/coolant.ogg',
-"coomer" = 'modular_citadel/sound/vox/coomer.ogg',
-"core" = 'modular_citadel/sound/vox/core.ogg',
-"correct" = 'modular_citadel/sound/vox/correct.ogg',
-"corridor" = 'modular_citadel/sound/vox/corridor.ogg',
-"crew" = 'modular_citadel/sound/vox/crew.ogg',
-"cross" = 'modular_citadel/sound/vox/cross.ogg',
-"cryogenic" = 'modular_citadel/sound/vox/cryogenic.ogg',
-"d" = 'modular_citadel/sound/vox/d.ogg',
-"dadeda" = 'modular_citadel/sound/vox/dadeda.ogg',
-"damage" = 'modular_citadel/sound/vox/damage.ogg',
-"damaged" = 'modular_citadel/sound/vox/damaged.ogg',
-"danger" = 'modular_citadel/sound/vox/danger.ogg',
-"day" = 'modular_citadel/sound/vox/day.ogg',
-"deactivated" = 'modular_citadel/sound/vox/deactivated.ogg',
-"decompression" = 'modular_citadel/sound/vox/decompression.ogg',
-"decontamination" = 'modular_citadel/sound/vox/decontamination.ogg',
-"deeoo" = 'modular_citadel/sound/vox/deeoo.ogg',
-"defense" = 'modular_citadel/sound/vox/defense.ogg',
-"degrees" = 'modular_citadel/sound/vox/degrees.ogg',
-"delta" = 'modular_citadel/sound/vox/delta.ogg',
-"denied" = 'modular_citadel/sound/vox/denied.ogg',
-"deploy" = 'modular_citadel/sound/vox/deploy.ogg',
-"deployed" = 'modular_citadel/sound/vox/deployed.ogg',
-"destroy" = 'modular_citadel/sound/vox/destroy.ogg',
-"destroyed" = 'modular_citadel/sound/vox/destroyed.ogg',
-"detain" = 'modular_citadel/sound/vox/detain.ogg',
-"detected" = 'modular_citadel/sound/vox/detected.ogg',
-"detonation" = 'modular_citadel/sound/vox/detonation.ogg',
-"device" = 'modular_citadel/sound/vox/device.ogg',
-"did" = 'modular_citadel/sound/vox/did.ogg',
-"die" = 'modular_citadel/sound/vox/die.ogg',
-"dimensional" = 'modular_citadel/sound/vox/dimensional.ogg',
-"dirt" = 'modular_citadel/sound/vox/dirt.ogg',
-"disengaged" = 'modular_citadel/sound/vox/disengaged.ogg',
-"dish" = 'modular_citadel/sound/vox/dish.ogg',
-"disposal" = 'modular_citadel/sound/vox/disposal.ogg',
-"distance" = 'modular_citadel/sound/vox/distance.ogg',
-"distortion" = 'modular_citadel/sound/vox/distortion.ogg',
-"do" = 'modular_citadel/sound/vox/do.ogg',
-"doctor" = 'modular_citadel/sound/vox/doctor.ogg',
-"doop" = 'modular_citadel/sound/vox/doop.ogg',
-"door" = 'modular_citadel/sound/vox/door.ogg',
-"down" = 'modular_citadel/sound/vox/down.ogg',
-"dual" = 'modular_citadel/sound/vox/dual.ogg',
-"duct" = 'modular_citadel/sound/vox/duct.ogg',
-"e" = 'modular_citadel/sound/vox/e.ogg',
-"east" = 'modular_citadel/sound/vox/east.ogg',
-"echo" = 'modular_citadel/sound/vox/echo.ogg',
-"ed" = 'modular_citadel/sound/vox/ed.ogg',
-"effect" = 'modular_citadel/sound/vox/effect.ogg',
-"egress" = 'modular_citadel/sound/vox/egress.ogg',
-"eight" = 'modular_citadel/sound/vox/eight.ogg',
-"eighteen" = 'modular_citadel/sound/vox/eighteen.ogg',
-"eighty" = 'modular_citadel/sound/vox/eighty.ogg',
-"electric" = 'modular_citadel/sound/vox/electric.ogg',
-"electromagnetic" = 'modular_citadel/sound/vox/electromagnetic.ogg',
-"elevator" = 'modular_citadel/sound/vox/elevator.ogg',
-"eleven" = 'modular_citadel/sound/vox/eleven.ogg',
-"eliminate" = 'modular_citadel/sound/vox/eliminate.ogg',
-"emergency" = 'modular_citadel/sound/vox/emergency.ogg',
-"enemy" = 'modular_citadel/sound/vox/enemy.ogg',
-"energy" = 'modular_citadel/sound/vox/energy.ogg',
-"engage" = 'modular_citadel/sound/vox/engage.ogg',
-"engaged" = 'modular_citadel/sound/vox/engaged.ogg',
-"engine" = 'modular_citadel/sound/vox/engine.ogg',
-"enter" = 'modular_citadel/sound/vox/enter.ogg',
-"entry" = 'modular_citadel/sound/vox/entry.ogg',
-"environment" = 'modular_citadel/sound/vox/environment.ogg',
-"error" = 'modular_citadel/sound/vox/error.ogg',
-"escape" = 'modular_citadel/sound/vox/escape.ogg',
-"evacuate" = 'modular_citadel/sound/vox/evacuate.ogg',
-"exchange" = 'modular_citadel/sound/vox/exchange.ogg',
-"exit" = 'modular_citadel/sound/vox/exit.ogg',
-"expect" = 'modular_citadel/sound/vox/expect.ogg',
-"experiment" = 'modular_citadel/sound/vox/experiment.ogg',
-"experimental" = 'modular_citadel/sound/vox/experimental.ogg',
-"explode" = 'modular_citadel/sound/vox/explode.ogg',
-"explosion" = 'modular_citadel/sound/vox/explosion.ogg',
-"exposure" = 'modular_citadel/sound/vox/exposure.ogg',
-"exterminate" = 'modular_citadel/sound/vox/exterminate.ogg',
-"extinguish" = 'modular_citadel/sound/vox/extinguish.ogg',
-"extinguisher" = 'modular_citadel/sound/vox/extinguisher.ogg',
-"extreme" = 'modular_citadel/sound/vox/extreme.ogg',
-"f" = 'modular_citadel/sound/vox/f.ogg',
-"face" = 'modular_citadel/sound/vox/face.ogg',
-"facility" = 'modular_citadel/sound/vox/facility.ogg',
-"fahrenheit" = 'modular_citadel/sound/vox/fahrenheit.ogg',
-"failed" = 'modular_citadel/sound/vox/failed.ogg',
-"failure" = 'modular_citadel/sound/vox/failure.ogg',
-"farthest" = 'modular_citadel/sound/vox/farthest.ogg',
-"fast" = 'modular_citadel/sound/vox/fast.ogg',
-"feet" = 'modular_citadel/sound/vox/feet.ogg',
-"field" = 'modular_citadel/sound/vox/field.ogg',
-"fifteen" = 'modular_citadel/sound/vox/fifteen.ogg',
-"fifth" = 'modular_citadel/sound/vox/fifth.ogg',
-"fifty" = 'modular_citadel/sound/vox/fifty.ogg',
-"final" = 'modular_citadel/sound/vox/final.ogg',
-"fine" = 'modular_citadel/sound/vox/fine.ogg',
-"fire" = 'modular_citadel/sound/vox/fire.ogg',
-"first" = 'modular_citadel/sound/vox/first.ogg',
-"five" = 'modular_citadel/sound/vox/five.ogg',
-"flag" = 'modular_citadel/sound/vox/flag.ogg',
-"flooding" = 'modular_citadel/sound/vox/flooding.ogg',
-"floor" = 'modular_citadel/sound/vox/floor.ogg',
-"fool" = 'modular_citadel/sound/vox/fool.ogg',
-"for" = 'modular_citadel/sound/vox/for.ogg',
-"forbidden" = 'modular_citadel/sound/vox/forbidden.ogg',
-"force" = 'modular_citadel/sound/vox/force.ogg',
-"forms" = 'modular_citadel/sound/vox/forms.ogg',
-"found" = 'modular_citadel/sound/vox/found.ogg',
-"four" = 'modular_citadel/sound/vox/four.ogg',
-"fourteen" = 'modular_citadel/sound/vox/fourteen.ogg',
-"fourth" = 'modular_citadel/sound/vox/fourth.ogg',
-"fourty" = 'modular_citadel/sound/vox/fourty.ogg',
-"foxtrot" = 'modular_citadel/sound/vox/foxtrot.ogg',
-"freeman" = 'modular_citadel/sound/vox/freeman.ogg',
-"freezer" = 'modular_citadel/sound/vox/freezer.ogg',
-"from" = 'modular_citadel/sound/vox/from.ogg',
-"front" = 'modular_citadel/sound/vox/front.ogg',
-"fuel" = 'modular_citadel/sound/vox/fuel.ogg',
-"g" = 'modular_citadel/sound/vox/g.ogg',
-"gay" = 'modular_citadel/sound/vox/gay.ogg',
-"get" = 'modular_citadel/sound/vox/get.ogg',
-"go" = 'modular_citadel/sound/vox/go.ogg',
-"going" = 'modular_citadel/sound/vox/going.ogg',
-"good" = 'modular_citadel/sound/vox/good.ogg',
-"goodbye" = 'modular_citadel/sound/vox/goodbye.ogg',
-"gordon" = 'modular_citadel/sound/vox/gordon.ogg',
-"got" = 'modular_citadel/sound/vox/got.ogg',
-"government" = 'modular_citadel/sound/vox/government.ogg',
-"granted" = 'modular_citadel/sound/vox/granted.ogg',
-"great" = 'modular_citadel/sound/vox/great.ogg',
-"green" = 'modular_citadel/sound/vox/green.ogg',
-"grenade" = 'modular_citadel/sound/vox/grenade.ogg',
-"guard" = 'modular_citadel/sound/vox/guard.ogg',
-"gulf" = 'modular_citadel/sound/vox/gulf.ogg',
-"gun" = 'modular_citadel/sound/vox/gun.ogg',
-"guthrie" = 'modular_citadel/sound/vox/guthrie.ogg',
-"handling" = 'modular_citadel/sound/vox/handling.ogg',
-"hangar" = 'modular_citadel/sound/vox/hangar.ogg',
-"has" = 'modular_citadel/sound/vox/has.ogg',
-"have" = 'modular_citadel/sound/vox/have.ogg',
-"hazard" = 'modular_citadel/sound/vox/hazard.ogg',
-"head" = 'modular_citadel/sound/vox/head.ogg',
-"health" = 'modular_citadel/sound/vox/health.ogg',
-"heat" = 'modular_citadel/sound/vox/heat.ogg',
-"helicopter" = 'modular_citadel/sound/vox/helicopter.ogg',
-"helium" = 'modular_citadel/sound/vox/helium.ogg',
-"hello" = 'modular_citadel/sound/vox/hello.ogg',
-"help" = 'modular_citadel/sound/vox/help.ogg',
-"here" = 'modular_citadel/sound/vox/here.ogg',
-"hide" = 'modular_citadel/sound/vox/hide.ogg',
-"high" = 'modular_citadel/sound/vox/high.ogg',
-"highest" = 'modular_citadel/sound/vox/highest.ogg',
-"hit" = 'modular_citadel/sound/vox/hit.ogg',
-"holds" = 'modular_citadel/sound/vox/holds.ogg',
-"hole" = 'modular_citadel/sound/vox/hole.ogg',
-"hostile" = 'modular_citadel/sound/vox/hostile.ogg',
-"hot" = 'modular_citadel/sound/vox/hot.ogg',
-"hotel" = 'modular_citadel/sound/vox/hotel.ogg',
-"hour" = 'modular_citadel/sound/vox/hour.ogg',
-"hours" = 'modular_citadel/sound/vox/hours.ogg',
-"hundred" = 'modular_citadel/sound/vox/hundred.ogg',
-"hydro" = 'modular_citadel/sound/vox/hydro.ogg',
-"i" = 'modular_citadel/sound/vox/i.ogg',
-"idiot" = 'modular_citadel/sound/vox/idiot.ogg',
-"illegal" = 'modular_citadel/sound/vox/illegal.ogg',
-"immediate" = 'modular_citadel/sound/vox/immediate.ogg',
-"immediately" = 'modular_citadel/sound/vox/immediately.ogg',
-"in" = 'modular_citadel/sound/vox/in.ogg',
-"inches" = 'modular_citadel/sound/vox/inches.ogg',
-"india" = 'modular_citadel/sound/vox/india.ogg',
-"ing" = 'modular_citadel/sound/vox/ing.ogg',
-"inoperative" = 'modular_citadel/sound/vox/inoperative.ogg',
-"inside" = 'modular_citadel/sound/vox/inside.ogg',
-"inspection" = 'modular_citadel/sound/vox/inspection.ogg',
-"inspector" = 'modular_citadel/sound/vox/inspector.ogg',
-"interchange" = 'modular_citadel/sound/vox/interchange.ogg',
-"intruder" = 'modular_citadel/sound/vox/intruder.ogg',
-"invallid" = 'modular_citadel/sound/vox/invallid.ogg',
-"invasion" = 'modular_citadel/sound/vox/invasion.ogg',
-"is" = 'modular_citadel/sound/vox/is.ogg',
-"it" = 'modular_citadel/sound/vox/it.ogg',
-"johnson" = 'modular_citadel/sound/vox/johnson.ogg',
-"juliet" = 'modular_citadel/sound/vox/juliet.ogg',
-"key" = 'modular_citadel/sound/vox/key.ogg',
-"kill" = 'modular_citadel/sound/vox/kill.ogg',
-"kilo" = 'modular_citadel/sound/vox/kilo.ogg',
-"kit" = 'modular_citadel/sound/vox/kit.ogg',
-"lab" = 'modular_citadel/sound/vox/lab.ogg',
-"lambda" = 'modular_citadel/sound/vox/lambda.ogg',
-"laser" = 'modular_citadel/sound/vox/laser.ogg',
-"last" = 'modular_citadel/sound/vox/last.ogg',
-"launch" = 'modular_citadel/sound/vox/launch.ogg',
-"leak" = 'modular_citadel/sound/vox/leak.ogg',
-"leave" = 'modular_citadel/sound/vox/leave.ogg',
-"left" = 'modular_citadel/sound/vox/left.ogg',
-"legal" = 'modular_citadel/sound/vox/legal.ogg',
-"level" = 'modular_citadel/sound/vox/level.ogg',
-"lever" = 'modular_citadel/sound/vox/lever.ogg',
-"lie" = 'modular_citadel/sound/vox/lie.ogg',
-"lieutenant" = 'modular_citadel/sound/vox/lieutenant.ogg',
-"life" = 'modular_citadel/sound/vox/life.ogg',
-"light" = 'modular_citadel/sound/vox/light.ogg',
-"lima" = 'modular_citadel/sound/vox/lima.ogg',
-"liquid" = 'modular_citadel/sound/vox/liquid.ogg',
-"loading" = 'modular_citadel/sound/vox/loading.ogg',
-"locate" = 'modular_citadel/sound/vox/locate.ogg',
-"located" = 'modular_citadel/sound/vox/located.ogg',
-"location" = 'modular_citadel/sound/vox/location.ogg',
-"lock" = 'modular_citadel/sound/vox/lock.ogg',
-"locked" = 'modular_citadel/sound/vox/locked.ogg',
-"locker" = 'modular_citadel/sound/vox/locker.ogg',
-"lockout" = 'modular_citadel/sound/vox/lockout.ogg',
-"lower" = 'modular_citadel/sound/vox/lower.ogg',
-"lowest" = 'modular_citadel/sound/vox/lowest.ogg',
-"magnetic" = 'modular_citadel/sound/vox/magnetic.ogg',
-"main" = 'modular_citadel/sound/vox/main.ogg',
-"maintenance" = 'modular_citadel/sound/vox/maintenance.ogg',
-"malfunction" = 'modular_citadel/sound/vox/malfunction.ogg',
-"man" = 'modular_citadel/sound/vox/man.ogg',
-"mass" = 'modular_citadel/sound/vox/mass.ogg',
-"materials" = 'modular_citadel/sound/vox/materials.ogg',
-"maximum" = 'modular_citadel/sound/vox/maximum.ogg',
-"may" = 'modular_citadel/sound/vox/may.ogg',
-"med" = 'modular_citadel/sound/vox/med.ogg',
-"medical" = 'modular_citadel/sound/vox/medical.ogg',
-"men" = 'modular_citadel/sound/vox/men.ogg',
-"mercy" = 'modular_citadel/sound/vox/mercy.ogg',
-"mesa" = 'modular_citadel/sound/vox/mesa.ogg',
-"message" = 'modular_citadel/sound/vox/message.ogg',
-"meter" = 'modular_citadel/sound/vox/meter.ogg',
-"micro" = 'modular_citadel/sound/vox/micro.ogg',
-"middle" = 'modular_citadel/sound/vox/middle.ogg',
-"mike" = 'modular_citadel/sound/vox/mike.ogg',
-"miles" = 'modular_citadel/sound/vox/miles.ogg',
-"military" = 'modular_citadel/sound/vox/military.ogg',
-"milli" = 'modular_citadel/sound/vox/milli.ogg',
-"million" = 'modular_citadel/sound/vox/million.ogg',
-"minefield" = 'modular_citadel/sound/vox/minefield.ogg',
-"minimum" = 'modular_citadel/sound/vox/minimum.ogg',
-"minutes" = 'modular_citadel/sound/vox/minutes.ogg',
-"mister" = 'modular_citadel/sound/vox/mister.ogg',
-"mode" = 'modular_citadel/sound/vox/mode.ogg',
-"motor" = 'modular_citadel/sound/vox/motor.ogg',
-"motorpool" = 'modular_citadel/sound/vox/motorpool.ogg',
-"move" = 'modular_citadel/sound/vox/move.ogg',
-"must" = 'modular_citadel/sound/vox/must.ogg',
-"nearest" = 'modular_citadel/sound/vox/nearest.ogg',
-"nice" = 'modular_citadel/sound/vox/nice.ogg',
-"nine" = 'modular_citadel/sound/vox/nine.ogg',
-"nineteen" = 'modular_citadel/sound/vox/nineteen.ogg',
-"ninety" = 'modular_citadel/sound/vox/ninety.ogg',
-"no" = 'modular_citadel/sound/vox/no.ogg',
-"nominal" = 'modular_citadel/sound/vox/nominal.ogg',
-"north" = 'modular_citadel/sound/vox/north.ogg',
-"not" = 'modular_citadel/sound/vox/not.ogg',
-"november" = 'modular_citadel/sound/vox/november.ogg',
-"now" = 'modular_citadel/sound/vox/now.ogg',
-"number" = 'modular_citadel/sound/vox/number.ogg',
-"objective" = 'modular_citadel/sound/vox/objective.ogg',
-"observation" = 'modular_citadel/sound/vox/observation.ogg',
-"of" = 'modular_citadel/sound/vox/of.ogg',
-"officer" = 'modular_citadel/sound/vox/officer.ogg',
-"ok" = 'modular_citadel/sound/vox/ok.ogg',
-"on" = 'modular_citadel/sound/vox/on.ogg',
-"one" = 'modular_citadel/sound/vox/one.ogg',
-"open" = 'modular_citadel/sound/vox/open.ogg',
-"operating" = 'modular_citadel/sound/vox/operating.ogg',
-"operations" = 'modular_citadel/sound/vox/operations.ogg',
-"operative" = 'modular_citadel/sound/vox/operative.ogg',
-"option" = 'modular_citadel/sound/vox/option.ogg',
-"order" = 'modular_citadel/sound/vox/order.ogg',
-"organic" = 'modular_citadel/sound/vox/organic.ogg',
-"oscar" = 'modular_citadel/sound/vox/oscar.ogg',
-"out" = 'modular_citadel/sound/vox/out.ogg',
-"outside" = 'modular_citadel/sound/vox/outside.ogg',
-"over" = 'modular_citadel/sound/vox/over.ogg',
-"overload" = 'modular_citadel/sound/vox/overload.ogg',
-"override" = 'modular_citadel/sound/vox/override.ogg',
-"pacify" = 'modular_citadel/sound/vox/pacify.ogg',
-"pain" = 'modular_citadel/sound/vox/pain.ogg',
-"pal" = 'modular_citadel/sound/vox/pal.ogg',
-"panel" = 'modular_citadel/sound/vox/panel.ogg',
-"percent" = 'modular_citadel/sound/vox/percent.ogg',
-"perimeter" = 'modular_citadel/sound/vox/perimeter.ogg',
-"permitted" = 'modular_citadel/sound/vox/permitted.ogg',
-"personnel" = 'modular_citadel/sound/vox/personnel.ogg',
-"pipe" = 'modular_citadel/sound/vox/pipe.ogg',
-"plant" = 'modular_citadel/sound/vox/plant.ogg',
-"platform" = 'modular_citadel/sound/vox/platform.ogg',
-"please" = 'modular_citadel/sound/vox/please.ogg',
-"point" = 'modular_citadel/sound/vox/point.ogg',
-"portal" = 'modular_citadel/sound/vox/portal.ogg',
-"power" = 'modular_citadel/sound/vox/power.ogg',
-"presence" = 'modular_citadel/sound/vox/presence.ogg',
-"press" = 'modular_citadel/sound/vox/press.ogg',
-"primary" = 'modular_citadel/sound/vox/primary.ogg',
-"proceed" = 'modular_citadel/sound/vox/proceed.ogg',
-"processing" = 'modular_citadel/sound/vox/processing.ogg',
-"progress" = 'modular_citadel/sound/vox/progress.ogg',
-"proper" = 'modular_citadel/sound/vox/proper.ogg',
-"propulsion" = 'modular_citadel/sound/vox/propulsion.ogg',
-"prosecute" = 'modular_citadel/sound/vox/prosecute.ogg',
-"protective" = 'modular_citadel/sound/vox/protective.ogg',
-"push" = 'modular_citadel/sound/vox/push.ogg',
-"quantum" = 'modular_citadel/sound/vox/quantum.ogg',
-"quebec" = 'modular_citadel/sound/vox/quebec.ogg',
-"question" = 'modular_citadel/sound/vox/question.ogg',
-"questioning" = 'modular_citadel/sound/vox/questioning.ogg',
-"quick" = 'modular_citadel/sound/vox/quick.ogg',
-"quit" = 'modular_citadel/sound/vox/quit.ogg',
-"radiation" = 'modular_citadel/sound/vox/radiation.ogg',
-"radioactive" = 'modular_citadel/sound/vox/radioactive.ogg',
-"rads" = 'modular_citadel/sound/vox/rads.ogg',
-"rapid" = 'modular_citadel/sound/vox/rapid.ogg',
-"reach" = 'modular_citadel/sound/vox/reach.ogg',
-"reached" = 'modular_citadel/sound/vox/reached.ogg',
-"reactor" = 'modular_citadel/sound/vox/reactor.ogg',
-"red" = 'modular_citadel/sound/vox/red.ogg',
-"relay" = 'modular_citadel/sound/vox/relay.ogg',
-"released" = 'modular_citadel/sound/vox/released.ogg',
-"remaining" = 'modular_citadel/sound/vox/remaining.ogg',
-"renegade" = 'modular_citadel/sound/vox/renegade.ogg',
-"repair" = 'modular_citadel/sound/vox/repair.ogg',
-"report" = 'modular_citadel/sound/vox/report.ogg',
-"reports" = 'modular_citadel/sound/vox/reports.ogg',
-"required" = 'modular_citadel/sound/vox/required.ogg',
-"research" = 'modular_citadel/sound/vox/research.ogg',
-"reset" = 'modular_citadel/sound/vox/reset.ogg',
-"resevoir" = 'modular_citadel/sound/vox/resevoir.ogg',
-"resistance" = 'modular_citadel/sound/vox/resistance.ogg',
-"returned" = 'modular_citadel/sound/vox/returned.ogg',
-"right" = 'modular_citadel/sound/vox/right.ogg',
-"rocket" = 'modular_citadel/sound/vox/rocket.ogg',
-"roger" = 'modular_citadel/sound/vox/roger.ogg',
-"romeo" = 'modular_citadel/sound/vox/romeo.ogg',
-"room" = 'modular_citadel/sound/vox/room.ogg',
-"round" = 'modular_citadel/sound/vox/round.ogg',
-"run" = 'modular_citadel/sound/vox/run.ogg',
-"safe" = 'modular_citadel/sound/vox/safe.ogg',
-"safety" = 'modular_citadel/sound/vox/safety.ogg',
-"sargeant" = 'modular_citadel/sound/vox/sargeant.ogg',
-"satellite" = 'modular_citadel/sound/vox/satellite.ogg',
-"save" = 'modular_citadel/sound/vox/save.ogg',
-"science" = 'modular_citadel/sound/vox/science.ogg',
-"scores" = 'modular_citadel/sound/vox/scores.ogg',
-"scream" = 'modular_citadel/sound/vox/scream.ogg',
-"screen" = 'modular_citadel/sound/vox/screen.ogg',
-"search" = 'modular_citadel/sound/vox/search.ogg',
-"second" = 'modular_citadel/sound/vox/second.ogg',
-"secondary" = 'modular_citadel/sound/vox/secondary.ogg',
-"seconds" = 'modular_citadel/sound/vox/seconds.ogg',
-"sector" = 'modular_citadel/sound/vox/sector.ogg',
-"secure" = 'modular_citadel/sound/vox/secure.ogg',
-"secured" = 'modular_citadel/sound/vox/secured.ogg',
-"security" = 'modular_citadel/sound/vox/security.ogg',
-"select" = 'modular_citadel/sound/vox/select.ogg',
-"selected" = 'modular_citadel/sound/vox/selected.ogg',
-"service" = 'modular_citadel/sound/vox/service.ogg',
-"seven" = 'modular_citadel/sound/vox/seven.ogg',
-"seventeen" = 'modular_citadel/sound/vox/seventeen.ogg',
-"seventy" = 'modular_citadel/sound/vox/seventy.ogg',
-"severe" = 'modular_citadel/sound/vox/severe.ogg',
-"sewage" = 'modular_citadel/sound/vox/sewage.ogg',
-"sewer" = 'modular_citadel/sound/vox/sewer.ogg',
-"shield" = 'modular_citadel/sound/vox/shield.ogg',
-"shipment" = 'modular_citadel/sound/vox/shipment.ogg',
-"shock" = 'modular_citadel/sound/vox/shock.ogg',
-"shoot" = 'modular_citadel/sound/vox/shoot.ogg',
-"shower" = 'modular_citadel/sound/vox/shower.ogg',
-"shut" = 'modular_citadel/sound/vox/shut.ogg',
-"side" = 'modular_citadel/sound/vox/side.ogg',
-"sierra" = 'modular_citadel/sound/vox/sierra.ogg',
-"sight" = 'modular_citadel/sound/vox/sight.ogg',
-"silo" = 'modular_citadel/sound/vox/silo.ogg',
-"six" = 'modular_citadel/sound/vox/six.ogg',
-"sixteen" = 'modular_citadel/sound/vox/sixteen.ogg',
-"sixty" = 'modular_citadel/sound/vox/sixty.ogg',
-"slime" = 'modular_citadel/sound/vox/slime.ogg',
-"slow" = 'modular_citadel/sound/vox/slow.ogg',
-"soldier" = 'modular_citadel/sound/vox/soldier.ogg',
-"some" = 'modular_citadel/sound/vox/some.ogg',
-"someone" = 'modular_citadel/sound/vox/someone.ogg',
-"something" = 'modular_citadel/sound/vox/something.ogg',
-"son" = 'modular_citadel/sound/vox/son.ogg',
-"sorry" = 'modular_citadel/sound/vox/sorry.ogg',
-"south" = 'modular_citadel/sound/vox/south.ogg',
-"squad" = 'modular_citadel/sound/vox/squad.ogg',
-"square" = 'modular_citadel/sound/vox/square.ogg',
-"stairway" = 'modular_citadel/sound/vox/stairway.ogg',
-"status" = 'modular_citadel/sound/vox/status.ogg',
-"sterile" = 'modular_citadel/sound/vox/sterile.ogg',
-"sterilization" = 'modular_citadel/sound/vox/sterilization.ogg',
-"stolen" = 'modular_citadel/sound/vox/stolen.ogg',
-"storage" = 'modular_citadel/sound/vox/storage.ogg',
-"sub" = 'modular_citadel/sound/vox/sub.ogg',
-"subsurface" = 'modular_citadel/sound/vox/subsurface.ogg',
-"sudden" = 'modular_citadel/sound/vox/sudden.ogg',
-"suit" = 'modular_citadel/sound/vox/suit.ogg',
-"superconducting" = 'modular_citadel/sound/vox/superconducting.ogg',
-"supercooled" = 'modular_citadel/sound/vox/supercooled.ogg',
-"supply" = 'modular_citadel/sound/vox/supply.ogg',
-"surface" = 'modular_citadel/sound/vox/surface.ogg',
-"surrender" = 'modular_citadel/sound/vox/surrender.ogg',
-"surround" = 'modular_citadel/sound/vox/surround.ogg',
-"surrounded" = 'modular_citadel/sound/vox/surrounded.ogg',
-"switch" = 'modular_citadel/sound/vox/switch.ogg',
-"system" = 'modular_citadel/sound/vox/system.ogg',
-"systems" = 'modular_citadel/sound/vox/systems.ogg',
-"tactical" = 'modular_citadel/sound/vox/tactical.ogg',
-"take" = 'modular_citadel/sound/vox/take.ogg',
-"talk" = 'modular_citadel/sound/vox/talk.ogg',
-"tango" = 'modular_citadel/sound/vox/tango.ogg',
-"tank" = 'modular_citadel/sound/vox/tank.ogg',
-"target" = 'modular_citadel/sound/vox/target.ogg',
-"team" = 'modular_citadel/sound/vox/team.ogg',
-"temperature" = 'modular_citadel/sound/vox/temperature.ogg',
-"temporal" = 'modular_citadel/sound/vox/temporal.ogg',
-"ten" = 'modular_citadel/sound/vox/ten.ogg',
-"terminal" = 'modular_citadel/sound/vox/terminal.ogg',
-"terminated" = 'modular_citadel/sound/vox/terminated.ogg',
-"termination" = 'modular_citadel/sound/vox/termination.ogg',
-"test" = 'modular_citadel/sound/vox/test.ogg',
-"that" = 'modular_citadel/sound/vox/that.ogg',
-"the" = 'modular_citadel/sound/vox/the.ogg',
-"then" = 'modular_citadel/sound/vox/then.ogg',
-"there" = 'modular_citadel/sound/vox/there.ogg',
-"third" = 'modular_citadel/sound/vox/third.ogg',
-"thirteen" = 'modular_citadel/sound/vox/thirteen.ogg',
-"thirty" = 'modular_citadel/sound/vox/thirty.ogg',
-"this" = 'modular_citadel/sound/vox/this.ogg',
-"those" = 'modular_citadel/sound/vox/those.ogg',
-"thousand" = 'modular_citadel/sound/vox/thousand.ogg',
-"threat" = 'modular_citadel/sound/vox/threat.ogg',
-"three" = 'modular_citadel/sound/vox/three.ogg',
-"through" = 'modular_citadel/sound/vox/through.ogg',
-"time" = 'modular_citadel/sound/vox/time.ogg',
-"to" = 'modular_citadel/sound/vox/to.ogg',
-"top" = 'modular_citadel/sound/vox/top.ogg',
-"topside" = 'modular_citadel/sound/vox/topside.ogg',
-"touch" = 'modular_citadel/sound/vox/touch.ogg',
-"towards" = 'modular_citadel/sound/vox/towards.ogg',
-"track" = 'modular_citadel/sound/vox/track.ogg',
-"train" = 'modular_citadel/sound/vox/train.ogg',
-"transportation" = 'modular_citadel/sound/vox/transportation.ogg',
-"truck" = 'modular_citadel/sound/vox/truck.ogg',
-"tunnel" = 'modular_citadel/sound/vox/tunnel.ogg',
-"turn" = 'modular_citadel/sound/vox/turn.ogg',
-"turret" = 'modular_citadel/sound/vox/turret.ogg',
-"twelve" = 'modular_citadel/sound/vox/twelve.ogg',
-"twenty" = 'modular_citadel/sound/vox/twenty.ogg',
-"two" = 'modular_citadel/sound/vox/two.ogg',
-"unauthorized" = 'modular_citadel/sound/vox/unauthorized.ogg',
-"under" = 'modular_citadel/sound/vox/under.ogg',
-"uniform" = 'modular_citadel/sound/vox/uniform.ogg',
-"unlocked" = 'modular_citadel/sound/vox/unlocked.ogg',
-"until" = 'modular_citadel/sound/vox/until.ogg',
-"up" = 'modular_citadel/sound/vox/up.ogg',
-"upper" = 'modular_citadel/sound/vox/upper.ogg',
-"uranium" = 'modular_citadel/sound/vox/uranium.ogg',
-"us" = 'modular_citadel/sound/vox/us.ogg',
-"usa" = 'modular_citadel/sound/vox/usa.ogg',
-"use" = 'modular_citadel/sound/vox/use.ogg',
-"used" = 'modular_citadel/sound/vox/used.ogg',
-"user" = 'modular_citadel/sound/vox/user.ogg',
-"vacate" = 'modular_citadel/sound/vox/vacate.ogg',
-"valid" = 'modular_citadel/sound/vox/valid.ogg',
-"vapor" = 'modular_citadel/sound/vox/vapor.ogg',
-"vent" = 'modular_citadel/sound/vox/vent.ogg',
-"ventillation" = 'modular_citadel/sound/vox/ventillation.ogg',
-"victor" = 'modular_citadel/sound/vox/victor.ogg',
-"violated" = 'modular_citadel/sound/vox/violated.ogg',
-"violation" = 'modular_citadel/sound/vox/violation.ogg',
-"voltage" = 'modular_citadel/sound/vox/voltage.ogg',
-"vox_login" = 'modular_citadel/sound/vox/vox_login.ogg',
-"walk" = 'modular_citadel/sound/vox/walk.ogg',
-"wall" = 'modular_citadel/sound/vox/wall.ogg',
-"want" = 'modular_citadel/sound/vox/want.ogg',
-"wanted" = 'modular_citadel/sound/vox/wanted.ogg',
-"warm" = 'modular_citadel/sound/vox/warm.ogg',
-"warn" = 'modular_citadel/sound/vox/warn.ogg',
-"warning" = 'modular_citadel/sound/vox/warning.ogg',
-"waste" = 'modular_citadel/sound/vox/waste.ogg',
-"water" = 'modular_citadel/sound/vox/water.ogg',
-"we" = 'modular_citadel/sound/vox/we.ogg',
-"weapon" = 'modular_citadel/sound/vox/weapon.ogg',
-"west" = 'modular_citadel/sound/vox/west.ogg',
-"whiskey" = 'modular_citadel/sound/vox/whiskey.ogg',
-"white" = 'modular_citadel/sound/vox/white.ogg',
-"wilco" = 'modular_citadel/sound/vox/wilco.ogg',
-"will" = 'modular_citadel/sound/vox/will.ogg',
-"with" = 'modular_citadel/sound/vox/with.ogg',
-"without" = 'modular_citadel/sound/vox/without.ogg',
-"woop" = 'modular_citadel/sound/vox/woop.ogg',
-"xeno" = 'modular_citadel/sound/vox/xeno.ogg',
-"yankee" = 'modular_citadel/sound/vox/yankee.ogg',
-"yards" = 'modular_citadel/sound/vox/yards.ogg',
-"year" = 'modular_citadel/sound/vox/year.ogg',
-"yellow" = 'modular_citadel/sound/vox/yellow.ogg',
-"yes" = 'modular_citadel/sound/vox/yes.ogg',
-"you" = 'modular_citadel/sound/vox/you.ogg',
-"your" = 'modular_citadel/sound/vox/your.ogg',
-"yourself" = 'modular_citadel/sound/vox/yourself.ogg',
-"zero" = 'modular_citadel/sound/vox/zero.ogg',
-"zone" = 'modular_citadel/sound/vox/zone.ogg',
-"zulu" = 'modular_citadel/sound/vox/zulu.ogg',))
-#endif
\ No newline at end of file
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
index a458e909f3..99ba9ad3e2 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm
@@ -13,13 +13,23 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
w_class = 3
hitsound = 'sound/weapons/bite.ogg'
sharpness = IS_SHARP
+ var/stamtostunconversion = 0.1 //Total stamloss gets multiplied by this value for the help intent hard stun. Resting adds an additional 2x multiplier on top. Keep this low or so help me god.
+ var/stuncooldown = 4 SECONDS //How long it takes before you're able to attempt to stun a target again
+ var/nextstuntime
+
+/obj/item/dogborg/jaws/examine(mob/user)
+ . = ..()
+ if(!CONFIG_GET(flag/weaken_secborg))
+ to_chat(user, "Use help intent to attempt to non-lethally incapacitate the target by latching on with your maw. This is more effective against exhausted and resting targets.")
/obj/item/dogborg/jaws/big
name = "combat jaws"
desc = "The jaws of the law. Very sharp."
icon_state = "jaws"
- force = 10 //Lowered to match secborg. No reason it should be more than a secborg's baton.
+ force = 15 //Chomp chomp. Crew harm.
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
+ stamtostunconversion = 0.2 // 100*0.2*2=40. Stun's just long enough to slap on cuffs with click delay if the target is near hard stamcrit.
+ stuncooldown = 6 SECONDS
/obj/item/dogborg/jaws/small
@@ -31,11 +41,36 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
var/status = 0
/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user)
- ..()
- user.do_attack_animation(A, ATTACK_EFFECT_BITE)
+ if(!istype(user))
+ return
+ if(!CONFIG_GET(flag/weaken_secborg) && user.a_intent != INTENT_HARM && istype(A, /mob/living))
+ if(A == user.pulling)
+ to_chat(user, "You already have [A] in your jaws.")
+ return
+ if(nextstuntime >= world.time)
+ to_chat(user, "Your jaw servos are still recharging.")
+ return
+ nextstuntime = world.time + stuncooldown
+ var/mob/living/M = A
+ var/cachedstam = M.getStaminaLoss()
+ var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1)
+ if(!M.resting)
+ M.Knockdown(cachedstam*2) //BORK BORK. GET DOWN.
+ M.Stun(totalstuntime)
+ user.do_attack_animation(A, ATTACK_EFFECT_BITE)
+ user.start_pulling(M, TRUE) //Yip yip. Come with.
+ user.changeNext_move(CLICK_CD_MELEE)
+ M.visible_message("[user] clamps [user.p_their()] [src] onto [M] and latches on!", "[user] clamps [user.p_their()] [src] onto you and latches on!")
+ if(totalstuntime >= 4 SECONDS)
+ playsound(usr, 'sound/effects/k9_jaw_strong.ogg', 75, FALSE, 2) //Wuff wuff. Big stun.
+ else
+ playsound(usr, 'sound/effects/k9_jaw_weak.ogg', 50, TRUE, -1) //Arf arf. Pls buff.
+ else
+ . = ..()
+ user.do_attack_animation(A, ATTACK_EFFECT_BITE)
/obj/item/dogborg/jaws/small/attack_self(mob/user)
- var/mob/living/silicon/robot.R = user
+ var/mob/living/silicon/robot/R = user
if(R.cell && R.cell.charge > 100)
if(R.emagged && status == 0)
name = "combat jaws"
@@ -43,14 +78,18 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
desc = "The jaws of the law."
force = 12
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
+ stamtostunconversion = 0.15
+ stuncooldown = 5 SECONDS
status = 1
to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].")
else
name = "puppy jaws"
icon_state = "smalljaws"
desc = "The jaws of a small dog."
- force = 5
+ force = initial(force)
attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed")
+ stamtostunconversion = initial(stamtostunconversion)
+ stuncooldown = initial(stuncooldown)
status = 0
if(R.emagged)
to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].")
@@ -167,7 +206,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
item_flags |= NOBLUDGEON //No more attack messages
/obj/item/soap/tongue/attack_self(mob/user)
- var/mob/living/silicon/robot.R = user
+ var/mob/living/silicon/robot/R = user
if(R.cell && R.cell.charge > 100)
if(R.emagged && status == 0)
status = !status
@@ -187,7 +226,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
update_icon()
/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity)
- var/mob/living/silicon/robot.R = user
+ var/mob/living/silicon/robot/R = user
if(!proximity || !check_allowed_items(target))
return
if(R.client && (target in R.client.screen))
@@ -307,8 +346,10 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/mob/living/silicon/robot
var/leaping = 0
var/pounce_cooldown = 0
- var/pounce_cooldown_time = 20 //Buffed to counter balance changes
- var/pounce_spoolup = 1
+ var/pounce_cooldown_time = 30 //Time in deciseconds between pounces
+ var/pounce_spoolup = 5 //Time in deciseconds for the pounce to happen after clicking
+ var/pounce_stamloss_cap = 120 //How much staminaloss pounces alone are capable of bringing a spaceman to
+ var/pounce_stamloss = 80 //Base staminaloss value of the pounce
var/leap_at
var/disabler
var/laser
@@ -320,13 +361,12 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
/obj/item/dogborg/pounce/afterattack(atom/A, mob/user)
var/mob/living/silicon/robot/R = user
- if(R && !R.pounce_cooldown)
- R.pounce_cooldown = !R.pounce_cooldown
+ if(R && (world.time >= R.pounce_cooldown))
+ R.pounce_cooldown = world.time + R.pounce_cooldown_time
to_chat(R, "Your targeting systems lock on to [A]...")
+ playsound(R, 'sound/effects/servostep.ogg', 100, TRUE)
addtimer(CALLBACK(R, /mob/living/silicon/robot.proc/leap_at, A), R.pounce_spoolup)
- spawn(R.pounce_cooldown_time)
- R.pounce_cooldown = !R.pounce_cooldown
- else if(R && R.pounce_cooldown)
+ else if(R && (world.time < R.pounce_cooldown))
to_chat(R, "Your leg actuators are still recharging!")
/mob/living/silicon/robot/proc/leap_at(atom/A)
@@ -349,6 +389,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
update_icons()
throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1)
cell.use(750) //Less than a stunbaton since stunbatons hit everytime.
+ playsound(src, 'sound/effects/stealthoff.ogg', 25, TRUE, -1)
weather_immunities -= "lava"
/mob/living/silicon/robot/throw_impact(atom/A)
@@ -366,7 +407,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
blocked = 1
if(!blocked)
L.visible_message("[src] pounces on [L]!", "[src] pounces on you!")
- L.Knockdown(iscarbon(L) ? 225 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
+ L.Knockdown(iscarbon(L) ? 60 : 45, override_stamdmg = CLAMP(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
playsound(src, 'sound/weapons/Egloves.ogg', 50, 1)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
index c063d8b9ef..feec79ee8b 100644
--- a/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -53,6 +53,7 @@
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
+ borghealth = 80
/obj/item/robot_module/k9/do_transform_animation()
..()
diff --git a/modular_citadel/code/modules/mob/living/simple_animal/kiwi.dm b/modular_citadel/code/modules/mob/living/simple_animal/kiwi.dm
deleted file mode 100644
index 27c1749011..0000000000
--- a/modular_citadel/code/modules/mob/living/simple_animal/kiwi.dm
+++ /dev/null
@@ -1,134 +0,0 @@
-/mob/living/simple_animal/kiwi
- name = "space kiwi"
- desc = "Exposure to low gravity made them grow larger."
- gender = FEMALE
- icon = 'modular_citadel/icons/mob/kiwi.dmi'
- icon_state = "kiwi"
- icon_living = "kiwi"
- icon_dead = "dead"
- speak = list("Chirp!","Cheep cheep chirp!!","Cheep.")
- speak_emote = list("chirps","trills")
- emote_hear = list("chirps.")
- emote_see = list("pecks at the ground.","jumps in place.")
- density = FALSE
- speak_chance = 2
- turns_per_move = 3
- butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
- var/egg_type = /obj/item/reagent_containers/food/snacks/egg/kiwiEgg
- var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 25
- maxHealth = 25
- ventcrawler = VENTCRAWLER_ALWAYS
- var/eggsleft = 0
- var/eggsFertile = TRUE
- pass_flags = PASSTABLE | PASSMOB
- mob_size = MOB_SIZE_SMALL
- var/list/feedMessages = list("It chirps happily.","It chirps happily.")
- var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins chirping raucously.")
- gold_core_spawnable = FRIENDLY_SPAWN
- var/static/kiwi_count = 0
-
-/mob/living/simple_animal/kiwi/Destroy()
- --kiwi_count
- return ..()
-
-
-/mob/living/simple_animal/kiwi/Initialize()
- . = ..()
- ++kiwi_count
-
-
-/mob/living/simple_animal/kiwi/Life()
- . =..()
- if(!.)
- return
- if((!stat && prob(3) && eggsleft > 0) && egg_type)
- visible_message("[src] [pick(layMessage)]")
- eggsleft--
- var/obj/item/E = new egg_type(get_turf(src))
- E.pixel_x = rand(-6,6)
- E.pixel_y = rand(-6,6)
- if(eggsFertile)
- if(kiwi_count < MAX_CHICKENS && prob(25))
- START_PROCESSING(SSobj, E)
-
-/obj/item/reagent_containers/food/snacks/egg/kiwiEgg/process()
- if(isturf(loc))
- amount_grown += rand(1,2)
- if(amount_grown >= 100)
- visible_message("[src] hatches with a quiet cracking sound.")
- new /mob/living/simple_animal/babyKiwi(get_turf(src))
- STOP_PROCESSING(SSobj, src)
- qdel(src)
- else
- STOP_PROCESSING(SSobj, src)
-
-
-/mob/living/simple_animal/kiwi/attackby(obj/item/O, mob/user, params)
- if(istype(O, food_type)) //feedin' dem kiwis
- if(!stat && eggsleft < 8)
- var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
- user.visible_message(feedmsg)
- qdel(O)
- eggsleft += rand(1, 4)
- else
- to_chat(user, "[name] doesn't seem hungry!")
- else
- ..()
-
-
-/mob/living/simple_animal/babyKiwi
- name = "baby space kiwi"
- desc = "So huggable."
- icon = 'modular_citadel/icons/mob/kiwi.dmi'
- icon_state = "babyKiwi"
- icon_living = "babyKiwi"
- icon_dead = "deadBaby"
- icon_gib = "chick_gib"
- gender = FEMALE
- speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
- speak_emote = list("chirps")
- emote_hear = list("chirps.")
- emote_see = list("pecks at the ground.","Happily bounces in place.")
- density = FALSE
- speak_chance = 2
- turns_per_move = 2
- butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 10
- maxHealth = 10
- ventcrawler = VENTCRAWLER_ALWAYS
- var/amount_grown = 0
- pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
- mob_size = MOB_SIZE_TINY
- gold_core_spawnable = FRIENDLY_SPAWN
-
-/mob/living/simple_animal/babyKiwi/Initialize()
- . = ..()
- pixel_x = rand(-6, 6)
- pixel_y = rand(0, 10)
-
-/mob/living/simple_animal/babyKiwi/Life()
- . =..()
- if(!.)
- return
- if(!stat && !ckey)
- amount_grown += rand(1,2)
- if(amount_grown >= 100)
- new /mob/living/simple_animal/kiwi(src.loc)
- qdel(src)
-
-
-/obj/item/reagent_containers/food/snacks/egg/kiwiEgg
- name = "kiwi egg"
- icon = 'modular_citadel/icons/mob/kiwi.dmi'
- desc = "A slightly bigger egg!"
- icon_state = "egg"
-
diff --git a/modular_citadel/code/modules/projectiles/bullets/bullets/smg.dm b/modular_citadel/code/modules/projectiles/bullets/bullets/smg.dm
index f069a73fe8..75151417d7 100644
--- a/modular_citadel/code/modules/projectiles/bullets/bullets/smg.dm
+++ b/modular_citadel/code/modules/projectiles/bullets/bullets/smg.dm
@@ -1,4 +1,4 @@
/obj/item/projectile/bullet/c46x30mm_tx
name = "toxin tipped 4.6x30mm bullet"
- damage = 15
+ damage = 10
damage_type = TOX
\ No newline at end of file
diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm
index 70d3bee5af..8ee00bef06 100644
--- a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm
+++ b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon.dm
@@ -57,10 +57,9 @@
icon_state = "magjectile-nl"
damage = 2
knockdown = 0
- stamina = 25
- armour_penetration = -10
+ stamina = 20
light_range = 2
- speed = 0.7
+ speed = 0.6
range = 25
light_color = LIGHT_COLOR_BLUE
@@ -109,9 +108,10 @@
fire_sound = 'sound/weapons/magpistol.ogg'
mag_type = /obj/item/ammo_box/magazine/mmag/small
can_suppress = 0
- casing_ejector = 0
+ casing_ejector = FALSE
fire_delay = 2
- recoil = 0.2
+ recoil = 0.1
+ inaccuracy_modifier = 0.25
/obj/item/gun/ballistic/automatic/pistol/mag/update_icon()
..()
@@ -123,7 +123,6 @@
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
///research memes///
-/*
/obj/item/gun/ballistic/automatic/pistol/mag/nopin
pin = null
spawnwithmagazine = FALSE
@@ -155,7 +154,7 @@
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
build_path = /obj/item/ammo_box/magazine/mmag/small
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
-*/
+
//////toy memes/////
/obj/item/projectile/bullet/reusable/foam_dart/mag
@@ -201,9 +200,9 @@
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "magjectile-large"
damage = 20
- armour_penetration = 25
+ armour_penetration = 20
light_range = 3
- speed = 0.7
+ speed = 0.6
range = 35
light_color = LIGHT_COLOR_RED
@@ -212,10 +211,10 @@
icon_state = "magjectile-large-nl"
damage = 2
knockdown = 0
- stamina = 25
- armour_penetration = -10
+ stamina = 20
+ armour_penetration = 10
light_range = 3
- speed = 0.65
+ speed = 0.6
range = 35
light_color = LIGHT_COLOR_BLUE
@@ -227,6 +226,8 @@
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "mag-casing-live"
projectile_type = /obj/item/projectile/bullet/magrifle
+ click_cooldown_override = 2.5
+ delay = 3
/obj/item/ammo_casing/caseless/anlmagm
desc = "A large, specialized ferromagnetic slug designed with a less-than-lethal payload."
@@ -234,10 +235,12 @@
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "mag-casing-live"
projectile_type = /obj/item/projectile/bullet/nlmagrifle
+ click_cooldown_override = 2.5
+ delay = 3
///magazines///
-/obj/item/ammo_box/magazine/mmag/
+/obj/item/ammo_box/magazine/mmag
name = "magrifle magazine (non-lethal disabler)"
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "mediummagmag"
@@ -261,17 +264,20 @@
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
icon_state = "magrifle"
item_state = "arg"
- slot_flags = 0
+ slot_flags = NONE
mag_type = /obj/item/ammo_box/magazine/mmag
fire_sound = 'sound/weapons/magrifle.ogg'
can_suppress = 0
- burst_size = 3
- fire_delay = 2
- spread = 5
- recoil = 0.15
- casing_ejector = 0
+ burst_size = 1
+ actions_types = null
+ fire_delay = 3
+ spread = 0
+ recoil = 0.1
+ casing_ejector = FALSE
+ inaccuracy_modifier = 0.5
+ weapon_weight = WEAPON_MEDIUM
+ dualwield_spread_mult = 1.4
-/*
//research///
/obj/item/gun/ballistic/automatic/magrifle/nopin
@@ -305,7 +311,7 @@
materials = list(MAT_METAL = 6000, MAT_SILVER = 500, MAT_TITANIUM = 500)
build_path = /obj/item/ammo_box/magazine/mmag
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
-*/
+
///foamagrifle///
/obj/item/ammo_box/magazine/toy/foamag
@@ -327,7 +333,6 @@
spread = 60
w_class = WEIGHT_CLASS_BULKY
weapon_weight = WEAPON_HEAVY
-/*
// TECHWEBS IMPLEMENTATION
//
@@ -339,7 +344,6 @@
design_ids = list("magrifle", "magpisol", "mag_magrifle", "mag_magrifle_nl", "mag_magpistol", "mag_magpistol_nl")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
-*/
//////Hyper-Burst Rifle//////
diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon_energy.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon_energy.dm
index 8786eb6dc9..7e6a8b3389 100644
--- a/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon_energy.dm
+++ b/modular_citadel/code/modules/projectiles/guns/ballistic/magweapon_energy.dm
@@ -143,6 +143,7 @@
// TECHWEBS IMPLEMENTATION
*/
+/*
/datum/techweb_node/magnetic_weapons
id = "magnetic_weapons"
display_name = "Magnetic Weapons"
@@ -151,6 +152,7 @@
design_ids = list("magrifle_e", "magpistol_e", "mag_magrifle_e", "mag_magrifle_e_nl", "mag_magpistol_e", "mag_magpistol_e_nl")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
+*/
///magrifle///
diff --git a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
index 0f7db73d6e..5fc75fa414 100644
--- a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -1,13 +1,6 @@
/obj/item/gun/energy/e_gun
name = "blaster carbine"
desc = "A high powered particle blaster carbine with varitable setting for stunning or lethal applications."
- icon = 'modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi'
- lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
- righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
- ammo_x_offset = 2
- flight_x_offset = 17
- flight_y_offset = 11
-
/*/////////////////////////////////////////////////////////////////////////////////////////////
The Recolourable Energy Gun
diff --git a/modular_citadel/code/modules/projectiles/guns/energy/laser.dm b/modular_citadel/code/modules/projectiles/guns/energy/laser.dm
index c82a3e9ed9..76d7403d16 100644
--- a/modular_citadel/code/modules/projectiles/guns/energy/laser.dm
+++ b/modular_citadel/code/modules/projectiles/guns/energy/laser.dm
@@ -1,19 +1,11 @@
/obj/item/gun/energy/laser
name = "blaster rifle"
desc = "a high energy particle blaster, efficient and deadly."
- icon = 'modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi'
- ammo_x_offset = 1
- shaded_charge = 1
- lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
- righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
/obj/item/gun/energy/laser/practice
+ icon = 'modular_citadel/icons/obj/guns/energy.dmi'
icon_state = "laser-p"
-
-/obj/item/gun/energy/laser/bluetag
- lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
-
-/obj/item/gun/energy/laser/redtag
- lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
+ lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
+ righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
+ ammo_x_offset = 1
+ shaded_charge = 1
diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
index 69f76e380b..ee90f985c6 100644
--- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
+++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm
@@ -30,17 +30,15 @@
inverse_chem_val = 0.35
inverse_chem = "BEsmaller" //At really impure vols, it just becomes 100% inverse
can_synth = FALSE
+ var/message_spam = FALSE
-/datum/reagent/fermi/breast_enlarger/on_mob_add(mob/living/carbon/M)
+/datum/reagent/fermi/breast_enlarger/on_mob_metabolize(mob/living/M)
. = ..()
if(!ishuman(M)) //The monkey clause
if(volume >= 15) //To prevent monkey breast farms
var/turf/T = get_turf(M)
var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(T)
- var/list/seen = viewers(8, T)
- for(var/mob/S in seen)
- to_chat(S, "A pair of breasts suddenly fly out of the [M]!")
- //var/turf/T2 = pick(turf in view(5, M))
+ M.visible_message("A pair of breasts suddenly fly out of the [M]!")
var/T2 = get_random_station_turf()
M.adjustBruteLoss(25)
M.Knockdown(50)
@@ -48,94 +46,82 @@
B.throw_at(T2, 8, 1)
M.reagents.remove_reagent(id, volume)
return
- log_game("FERMICHEM: [M] ckey: [M.key] has ingested Sucubus milk")
var/mob/living/carbon/human/H = M
- H.genital_override = TRUE
- var/obj/item/organ/genital/breasts/B = H.getorganslot("breasts")
- if(!B)
- H.emergent_genital_call()
- return
- if(!B.size == "huge")
- var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
- B.prev_size = B.size
- B.cached_size = sizeConv[B.size]
+ if(!H.getorganslot(ORGAN_SLOT_BREASTS) && H.emergent_genital_call())
+ H.genital_override = TRUE
/datum/reagent/fermi/breast_enlarger/on_mob_life(mob/living/carbon/M) //Increases breast size
if(!ishuman(M))//Just in case
return..()
var/mob/living/carbon/human/H = M
- var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
+ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
if(!B) //If they don't have breasts, give them breasts.
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
- if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused)
+ var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER)
if(L)
- L.swelling+= 0.05
- return..()
+ L.swelling += 0.05
else
- M.adjustToxLoss(1)
- return..()
+ H.adjustToxLoss(1)
+ return..()
//otherwise proceed as normal
- var/obj/item/organ/genital/breasts/nB = new
- nB.Insert(M)
- if(nB)
- if(M.dna.species.use_skintones && M.dna.features["genitals_use_skintone"])
- nB.color = skintone2hex(H.skin_tone)
- else if(M.dna.features["breasts_color"])
- nB.color = "#[M.dna.features["breasts_color"]]"
- else
- nB.color = skintone2hex(H.skin_tone)
- nB.size = "flat"
- nB.cached_size = 0
- nB.prev_size = 0
- to_chat(M, "Your chest feels warm, tingling with newfound sensitivity.")
- M.reagents.remove_reagent(id, 5)
- B = nB
+ B = new
+ if(H.dna.species.use_skintones && H.dna.features["genitals_use_skintone"])
+ B.color = skintone2hex(H.skin_tone)
+ else if(M.dna.features["breasts_color"])
+ B.color = "#[M.dna.features["breasts_color"]]"
+ else
+ B.color = skintone2hex(H.skin_tone)
+ B.size = "flat"
+ B.cached_size = 0
+ B.prev_size = 0
+ to_chat(H, "Your chest feels warm, tingling with newfound sensitivity.")
+ H.reagents.remove_reagent(id, 5)
+ B.Insert(H)
+
//If they have them, increase size. If size is comically big, limit movement and rip clothes.
- B.cached_size = B.cached_size + 0.05
- if (B.cached_size >= 8.5 && B.cached_size < 9)
- if(H.w_uniform || H.wear_suit)
- var/target = M.get_bodypart(BODY_ZONE_CHEST)
- to_chat(M, "Your breasts begin to strain against your clothes tightly!")
- M.adjustOxyLoss(5, 0)
- M.apply_damage(1, BRUTE, target)
- B.update()
- ..()
+ B.modify_size(0.05)
+
+ if (ISINRANGE_EX(B.cached_size, 8.5, 9) && (H.w_uniform || H.wear_suit))
+ var/target = H.get_bodypart(BODY_ZONE_CHEST)
+ if(!message_spam)
+ to_chat(H, "Your breasts begin to strain against your clothes tightly!")
+ message_spam = TRUE
+ H.adjustOxyLoss(5, 0)
+ H.apply_damage(1, BRUTE, target)
+ return ..()
/datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders.
//Acute hepatic pharmacokinesis.
- if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
+ var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
L.swelling+= 0.05
return ..()
- var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
- var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
- var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
- var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
+ var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS)
+ var/obj/item/organ/genital/testicles/T = M.getorganslot(ORGAN_SLOT_TESTICLES)
+ var/obj/item/organ/genital/vagina/V = M.getorganslot(ORGAN_SLOT_VAGINA)
+ var/obj/item/organ/genital/womb/W = M.getorganslot(ORGAN_SLOT_WOMB)
if(M.gender == MALE)
M.gender = FEMALE
M.visible_message("[M] suddenly looks more feminine!", "You suddenly feel more feminine!")
if(P)
- P.cached_length = P.cached_length - 0.05
- P.update()
+ P.modify_size(-0.05)
if(T)
- T.Remove(M)
+ qdel(T)
if(!V)
- var/obj/item/organ/genital/vagina/nV = new
- nV.Insert(M)
- V = nV
+ V = new
+ V.Insert(M)
if(!W)
- var/obj/item/organ/genital/womb/nW = new
- nW.Insert(M)
- W = nW
- ..()
+ W = new
+ W.Insert(M)
+ return ..()
/datum/reagent/fermi/BEsmaller
name = "Modesty milk"
@@ -147,19 +133,18 @@
can_synth = FALSE
/datum/reagent/fermi/BEsmaller/on_mob_life(mob/living/carbon/M)
- var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
+ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
if(!B)
//Acute hepatic pharmacokinesis.
- if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
+ var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
L.swelling-= 0.05
return ..()
//otherwise proceed as normal
return..()
- B.cached_size = B.cached_size - 0.05
- B.update()
- ..()
+ B.modify_size(-0.05)
+ return ..()
/datum/reagent/fermi/BEsmaller_hypo
name = "Rectify milk" //Rectify
@@ -171,31 +156,28 @@
var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
can_synth = TRUE
-/datum/reagent/fermi/BEsmaller_hypo/on_mob_add(mob/living/carbon/M)
+/datum/reagent/fermi/BEsmaller_hypo/on_mob_metabolize(mob/living/M)
. = ..()
- if(!M.getorganslot("vagina"))
- if(M.dna.features["has_vag"])
- var/obj/item/organ/genital/vagina/nV = new
- nV.Insert(M)
- if(!M.getorganslot("womb"))
- if(M.dna.features["has_womb"])
- var/obj/item/organ/genital/womb/nW = new
- nW.Insert(M)
+ if(!ishuman(M))
+ return
+ var/mob/living/carbon/human/H = M
+ if(!H.getorganslot(ORGAN_SLOT_VAGINA) && H.dna.features["has_vag"])
+ H.give_genital(/obj/item/organ/genital/vagina)
+ if(!H.getorganslot(ORGAN_SLOT_WOMB) && H.dna.features["has_womb"])
+ H.give_genital(/obj/item/organ/genital/womb)
/datum/reagent/fermi/BEsmaller_hypo/on_mob_life(mob/living/carbon/M)
- var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
+ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
if(!B)
return..()
- if(!M.dna.features["has_breasts"])//Fast fix for those who don't want it.
- B.cached_size = B.cached_size - 0.1
- B.update()
- else if(B.cached_size > (sizeConv[M.dna.features["breasts_size"]]+0.1))
- B.cached_size = B.cached_size - 0.05
- B.update()
- else if(B.cached_size < (sizeConv[M.dna.features["breasts_size"]])+0.1)
- B.cached_size = B.cached_size + 0.05
- B.update()
- ..()
+ var/optimal_size = B.breast_values[M.dna.features["breasts_size"]]
+ if(!optimal_size)//Fast fix for those who don't want it.
+ B.modify_size(-0.1)
+ else if(B.cached_size > optimal_size)
+ B.modify_size(-0.05, optimal_size)
+ else if(B.cached_size < optimal_size)
+ B.modify_size(0.05, 0, optimal_size)
+ return ..()
////////////////////////////////////////////////////////////////////////////////////////////////////
// PENIS ENLARGE
@@ -215,16 +197,15 @@
inverse_chem_val = 0.35
inverse_chem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead.
can_synth = FALSE
+ var/message_spam = FALSE
-/datum/reagent/fermi/penis_enlarger/on_mob_add(mob/living/carbon/M)
+/datum/reagent/fermi/penis_enlarger/on_mob_metabolize(mob/living/M)
. = ..()
if(!ishuman(M)) //Just monkeying around.
if(volume >= 15) //to prevent monkey penis farms
var/turf/T = get_turf(M)
var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(T)
- var/list/seen = viewers(8, T)
- for(var/mob/S in seen)
- to_chat(S, "A penis suddenly flies out of the [M]!")
+ M.visible_message("A penis suddenly flies out of the [M]!")
var/T2 = get_random_station_turf()
M.adjustBruteLoss(25)
M.Knockdown(50)
@@ -233,80 +214,71 @@
M.reagents.remove_reagent(id, volume)
return
var/mob/living/carbon/human/H = M
- H.genital_override = TRUE
- var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
- if(!P)
- H.emergent_genital_call()
- return
- P.prev_length = P.length
- P.cached_length = P.length
+ if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.emergent_genital_call())
+ H.genital_override = TRUE
/datum/reagent/fermi/penis_enlarger/on_mob_life(mob/living/carbon/M) //Increases penis size, 5u = +1 inch.
if(!ishuman(M))
- return
+ return ..()
var/mob/living/carbon/human/H = M
- var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
if(!P)//They do have a preponderance for escapism, or so I've heard.
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
- if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused)
+ var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER)
if(L)
- L.swelling+= 0.05
- return..()
+ L.swelling += 0.05
else
- M.adjustToxLoss(1)
- return..()
+ H.adjustToxLoss(1)
+ return ..()
//otherwise proceed as normal
- var/obj/item/organ/genital/penis/nP = new
- nP.Insert(M)
- if(nP)
- nP.length = 1
- to_chat(M, "Your groin feels warm, as you feel a newly forming bulge down below.")
- nP.cached_length = 1
- nP.prev_length = 1
- M.reagents.remove_reagent(id, 5)
- P = nP
+ P = new
+ P.length = 1
+ to_chat(H, "Your groin feels warm, as you feel a newly forming bulge down below.")
+ P.prev_length = 1
+ H.reagents.remove_reagent(id, 5)
+ P.Insert(H)
- P.cached_length = P.cached_length + 0.1
- if (P.cached_length >= 20.5 && P.cached_length < 21)
- if(H.w_uniform || H.wear_suit)
- var/target = M.get_bodypart(BODY_ZONE_CHEST)
- to_chat(M, "Your cock begin to strain against your clothes tightly!")
- M.apply_damage(2.5, BRUTE, target)
+ P.modify_size(0.1)
+ if (ISINRANGE_EX(P.length, 20.5, 21) && (H.w_uniform || H.wear_suit))
+ var/target = H.get_bodypart(BODY_ZONE_CHEST)
+ if(!message_spam)
+ to_chat(H, "Your cock begin to strain against your clothes tightly!")
+ message_spam = TRUE
+ H.apply_damage(2.5, BRUTE, target)
- P.update()
- ..()
+ return ..()
-/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders.
+/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/human/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders.
+ if(!istype(M))
+ return ..()
//Acute hepatic pharmacokinesis.
- if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
+ var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
L.swelling+= 0.05
return..()
- var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
- var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
- var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
- var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
+ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
+ var/obj/item/organ/genital/testicles/T = M.getorganslot(ORGAN_SLOT_TESTICLES)
+ var/obj/item/organ/genital/vagina/V = M.getorganslot(ORGAN_SLOT_VAGINA)
+ var/obj/item/organ/genital/womb/W = M.getorganslot(ORGAN_SLOT_WOMB)
if(M.gender == FEMALE)
M.gender = MALE
M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!")
if(B)
- B.cached_size = B.cached_size - 0.05
- B.update()
- if(V)
- V.Remove(M)
+ B.modify_size(-0.05)
+ if(M.getorganslot(ORGAN_SLOT_VAGINA))
+ qdel(V)
if(W)
- W.Remove(M)
+ qdel(W)
if(!T)
- var/obj/item/organ/genital/testicles/nT = new
- nT.Insert(M)
- T = nT
- ..()
+ T = new
+ T.Insert(M)
+ return ..()
/datum/reagent/fermi/PEsmaller // Due to cozmo's request...!
name = "Chastity draft"
@@ -318,19 +290,18 @@
can_synth = FALSE
/datum/reagent/fermi/PEsmaller/on_mob_life(mob/living/carbon/M)
+ if(!ishuman(M))
+ return ..()
var/mob/living/carbon/human/H = M
- var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
if(!P)
//Acute hepatic pharmacokinesis.
if(HAS_TRAIT(M, TRAIT_PHARMA))
- var/obj/item/organ/liver/L = M.getorganslot("liver")
+ var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
L.swelling-= 0.05
- return..()
-
- //otherwise proceed as normal
return..()
- P.cached_length = P.cached_length - 0.1
- P.update()
+
+ P.modify_size(-0.1)
..()
/datum/reagent/fermi/PEsmaller_hypo
@@ -342,24 +313,25 @@
metabolization_rate = 0.5
can_synth = TRUE
-/datum/reagent/fermi/PEsmaller_hypo/on_mob_add(mob/living/carbon/M)
+/datum/reagent/fermi/PEsmaller_hypo/on_mob_metabolize(mob/living/M)
. = ..()
- if(!M.getorganslot("testicles"))
- if(M.dna.features["has_balls"])
- var/obj/item/organ/genital/testicles/nT = new
- nT.Insert(M)
+ if(!ishuman(M))
+ return
+ var/mob/living/carbon/human/H = M
+ if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.dna.features["has_cock"])
+ H.give_genital(/obj/item/organ/genital/penis)
+ if(!H.getorganslot(ORGAN_SLOT_TESTICLES) && H.dna.features["has_balls"])
+ H.give_genital(/obj/item/organ/genital/testicles)
/datum/reagent/fermi/PEsmaller_hypo/on_mob_life(mob/living/carbon/M)
- var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
+ var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS)
if(!P)
return ..()
- if(!M.dna.features["has_cock"])//Fast fix for those who don't want it.
- P.cached_length = P.cached_length - 0.2
- P.update()
- else if(P.cached_length > (M.dna.features["cock_length"]+0.1))
- P.cached_length = P.cached_length - 0.1
- P.update()
- else if(P.cached_length < (M.dna.features["cock_length"]+0.1))
- P.cached_length = P.cached_length + 0.1
- P.update()
- ..()
+ var/optimal_size = M.dna.features["cock_length"]
+ if(!optimal_size)//Fast fix for those who don't want it.
+ P.modify_size(-0.2)
+ else if(P.length > optimal_size)
+ P.modify_size(-0.1, optimal_size)
+ else if(P.length < optimal_size)
+ P.modify_size(0.1, 0, optimal_size)
+ return ..()
diff --git a/modular_citadel/code/modules/reagents/objects/items.dm b/modular_citadel/code/modules/reagents/objects/items.dm
index 02f2db7c1e..6221bdde18 100644
--- a/modular_citadel/code/modules/reagents/objects/items.dm
+++ b/modular_citadel/code/modules/reagents/objects/items.dm
@@ -1,12 +1,12 @@
/obj/item/fermichem/pHbooklet
- name = "pH indicator booklet"
- desc = "A booklet containing paper soaked in universal indicator."
- icon_state = "pHbooklet"
- icon = 'modular_citadel/icons/obj/FermiChem.dmi'
- item_flags = NOBLUDGEON
- var/numberOfPages = 50
- resistance_flags = FLAMMABLE
- w_class = WEIGHT_CLASS_TINY
+ name = "pH indicator booklet"
+ desc = "A booklet containing paper soaked in universal indicator."
+ icon_state = "pHbooklet"
+ icon = 'icons/obj/chemical.dmi'
+ item_flags = NOBLUDGEON
+ var/numberOfPages = 50
+ resistance_flags = FLAMMABLE
+ w_class = WEIGHT_CLASS_TINY
//A little janky with pockets
/obj/item/fermichem/pHbooklet/attack_hand(mob/user)
@@ -29,7 +29,7 @@
to_chat(user, "[src] is empty!")
add_fingerprint(user)
return
- . = ..()
+ . = ..()
if(. & COMPONENT_NO_INTERACT)
return
var/I = user.get_active_held_item()
@@ -37,86 +37,86 @@
user.put_in_active_hand(src)
/obj/item/fermichem/pHbooklet/MouseDrop()
- var/mob/living/user = usr
- if(numberOfPages >= 1)
- var/obj/item/fermichem/pHpaper/P = new /obj/item/fermichem/pHpaper
- P.add_fingerprint(user)
- P.forceMove(user)
- user.put_in_active_hand(P)
- to_chat(user, "You take [P] out of \the [src].")
- numberOfPages--
- playsound(user.loc, 'sound/items/poster_ripped.ogg', 50, 1)
- add_fingerprint(user)
- if(numberOfPages == 0)
- icon_state = "pHbookletEmpty"
- return
- else
- to_chat(user, "[src] is empty!")
- add_fingerprint(user)
- return
- ..()
+ var/mob/living/user = usr
+ if(numberOfPages >= 1)
+ var/obj/item/fermichem/pHpaper/P = new /obj/item/fermichem/pHpaper
+ P.add_fingerprint(user)
+ P.forceMove(user)
+ user.put_in_active_hand(P)
+ to_chat(user, "You take [P] out of \the [src].")
+ numberOfPages--
+ playsound(user.loc, 'sound/items/poster_ripped.ogg', 50, 1)
+ add_fingerprint(user)
+ if(numberOfPages == 0)
+ icon_state = "pHbookletEmpty"
+ return
+ else
+ to_chat(user, "[src] is empty!")
+ add_fingerprint(user)
+ return
+ ..()
/obj/item/fermichem/pHpaper
- name = "pH indicator strip"
- desc = "A piece of paper that will change colour depending on the pH of a solution."
- icon_state = "pHpaper"
- icon = 'modular_citadel/icons/obj/FermiChem.dmi'
- item_flags = NOBLUDGEON
- color = "#f5c352"
- var/used = FALSE
- resistance_flags = FLAMMABLE
- w_class = WEIGHT_CLASS_TINY
+ name = "pH indicator strip"
+ desc = "A piece of paper that will change colour depending on the pH of a solution."
+ icon_state = "pHpaper"
+ icon = 'icons/obj/chemical.dmi'
+ item_flags = NOBLUDGEON
+ color = "#f5c352"
+ var/used = FALSE
+ resistance_flags = FLAMMABLE
+ w_class = WEIGHT_CLASS_TINY
/obj/item/fermichem/pHpaper/afterattack(obj/item/reagent_containers/cont, mob/user, proximity)
- if(!istype(cont))
- return
- if(used == TRUE)
- to_chat(user, "[user] has already been used!")
- return
- if(!LAZYLEN(cont.reagents.reagent_list))
- return
- switch(round(cont.reagents.pH, 1))
- if(14 to INFINITY)
- color = "#462c83"
- if(13 to 14)
- color = "#63459b"
- if(12 to 13)
- color = "#5a51a2"
- if(11 to 12)
- color = "#3853a4"
- if(10 to 11)
- color = "#3f93cf"
- if(9 to 10)
- color = "#0bb9b7"
- if(8 to 9)
- color = "#23b36e"
- if(7 to 8)
- color = "#3aa651"
- if(6 to 7)
- color = "#4cb849"
- if(5 to 6)
- color = "#b5d335"
- if(4 to 5)
- color = "#f7ec1e"
- if(3 to 4)
- color = "#fbc314"
- if(2 to 3)
- color = "#f26724"
- if(1 to 2)
- color = "#ef1d26"
- if(-INFINITY to 1)
- color = "#c6040c"
- desc += " The paper looks to be around a pH of [round(cont.reagents.pH, 1)]"
- used = TRUE
+ if(!istype(cont))
+ return
+ if(used == TRUE)
+ to_chat(user, "[user] has already been used!")
+ return
+ if(!LAZYLEN(cont.reagents.reagent_list))
+ return
+ switch(round(cont.reagents.pH, 1))
+ if(14 to INFINITY)
+ color = "#462c83"
+ if(13 to 14)
+ color = "#63459b"
+ if(12 to 13)
+ color = "#5a51a2"
+ if(11 to 12)
+ color = "#3853a4"
+ if(10 to 11)
+ color = "#3f93cf"
+ if(9 to 10)
+ color = "#0bb9b7"
+ if(8 to 9)
+ color = "#23b36e"
+ if(7 to 8)
+ color = "#3aa651"
+ if(6 to 7)
+ color = "#4cb849"
+ if(5 to 6)
+ color = "#b5d335"
+ if(4 to 5)
+ color = "#f7ec1e"
+ if(3 to 4)
+ color = "#fbc314"
+ if(2 to 3)
+ color = "#f26724"
+ if(1 to 2)
+ color = "#ef1d26"
+ if(-INFINITY to 1)
+ color = "#c6040c"
+ desc += " The paper looks to be around a pH of [round(cont.reagents.pH, 1)]"
+ used = TRUE
/obj/item/fermichem/pHmeter
- name = "Chemistry Analyser"
- desc = "A a electrode attached to a small circuit box that will tell you the pH of a solution. The screen currently displays nothing."
- icon_state = "pHmeter"
- icon = 'modular_citadel/icons/obj/FermiChem.dmi'
- resistance_flags = FLAMMABLE
- w_class = WEIGHT_CLASS_TINY
- var/scanmode = 1
+ name = "Chemistry Analyser"
+ desc = "A a electrode attached to a small circuit box that will tell you the pH of a solution. The screen currently displays nothing."
+ icon_state = "pHmeter"
+ icon = 'icons/obj/chemical.dmi'
+ resistance_flags = FLAMMABLE
+ w_class = WEIGHT_CLASS_TINY
+ var/scanmode = 1
/obj/item/fermichem/pHmeter/attack_self(mob/user)
if(!scanmode)
@@ -127,21 +127,21 @@
scanmode = 0
/obj/item/fermichem/pHmeter/afterattack(atom/A, mob/user, proximity)
- . = ..()
- if(!istype(A, /obj/item/reagent_containers))
- return
- var/obj/item/reagent_containers/cont = A
- if(LAZYLEN(cont.reagents.reagent_list) == null)
- return
- var/out_message
- to_chat(user, "The chemistry meter beeps and displays:")
- out_message += "Total volume: [round(cont.volume, 0.01)] Total pH: [round(cont.reagents.pH, 0.1)]\n"
- if(cont.reagents.fermiIsReacting)
- out_message += "A reaction appears to be occuring currently.\n"
- out_message += "Chemicals found in the beaker:\n"
- for(var/datum/reagent/R in cont.reagents.reagent_list)
- out_message += "[R.volume]u of [R.name], Purity: [R.purity], [(scanmode?"[(R.overdose_threshold?"Overdose: [R.overdose_threshold]u, ":"")][(R.addiction_threshold?"Addiction: [R.addiction_threshold]u, ":"")]Base pH: [R.pH].":".")]\n"
- if(scanmode)
- out_message += "Analysis: [R.description]\n"
- to_chat(user, "[out_message]")
- desc = "An electrode attached to a small circuit box that will analyse a beaker. It can be toggled to give a reduced or extended report. The screen currently displays [round(cont.reagents.pH, 0.1)]."
+ . = ..()
+ if(!istype(A, /obj/item/reagent_containers))
+ return
+ var/obj/item/reagent_containers/cont = A
+ if(LAZYLEN(cont.reagents.reagent_list) == null)
+ return
+ var/out_message
+ to_chat(user, "The chemistry meter beeps and displays:")
+ out_message += "Total volume: [round(cont.volume, 0.01)] Total pH: [round(cont.reagents.pH, 0.1)]\n"
+ if(cont.reagents.fermiIsReacting)
+ out_message += "A reaction appears to be occuring currently.\n"
+ out_message += "Chemicals found in the beaker:\n"
+ for(var/datum/reagent/R in cont.reagents.reagent_list)
+ out_message += "[R.volume]u of [R.name], Purity: [R.purity], [(scanmode?"[(R.overdose_threshold?"Overdose: [R.overdose_threshold]u, ":"")][(R.addiction_threshold?"Addiction: [R.addiction_threshold]u, ":"")]Base pH: [R.pH].":".")]\n"
+ if(scanmode)
+ out_message += "Analysis: [R.description]\n"
+ to_chat(user, "[out_message]")
+ desc = "An electrode attached to a small circuit box that will analyse a beaker. It can be toggled to give a reduced or extended report. The screen currently displays [round(cont.reagents.pH, 0.1)]."
diff --git a/modular_citadel/code/modules/reagents/reagent container/cit_kegs.dm b/modular_citadel/code/modules/reagents/reagent container/cit_kegs.dm
deleted file mode 100644
index d40dba8a3f..0000000000
--- a/modular_citadel/code/modules/reagents/reagent container/cit_kegs.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-/obj/structure/reagent_dispensers/keg
- name = "keg"
- desc = "A keg."
- icon = 'modular_citadel/icons/obj/objects.dmi'
- icon_state = "keg"
- reagent_id = "water"
-
-/obj/structure/reagent_dispensers/keg/mead
- name = "keg of mead"
- desc = "A keg of mead."
- icon_state = "orangekeg"
- reagent_id = "mead"
-
-/obj/structure/reagent_dispensers/keg/aphro
- name = "keg of aphrodisiac"
- desc = "A keg of aphrodisiac."
- icon_state = "pinkkeg"
- reagent_id = "aphro"
-
-/obj/structure/reagent_dispensers/keg/aphro/strong
- name = "keg of strong aphrodisiac"
- desc = "A keg of strong and addictive aphrodisiac."
- reagent_id = "aphro+"
-
-/obj/structure/reagent_dispensers/keg/milk
- name = "keg of milk"
- desc = "It's not quite what you were hoping for."
- icon_state = "whitekeg"
- reagent_id = "milk"
-
-/obj/structure/reagent_dispensers/keg/semen
- name = "keg of semen"
- desc = "Dear lord, where did this even come from?"
- icon_state = "whitekeg"
- reagent_id = "semen"
-
-/obj/structure/reagent_dispensers/keg/gargle
- name = "keg of pan galactic gargleblaster"
- desc = "A keg of... wow that's a long name."
- icon_state = "bluekeg"
- reagent_id = "gargleblaster"
\ No newline at end of file
diff --git a/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm b/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm
deleted file mode 100755
index 4aa634a488..0000000000
--- a/modular_citadel/code/modules/reagents/reagent container/hypospraymkii.dm
+++ /dev/null
@@ -1,299 +0,0 @@
-#define HYPO_SPRAY 0
-#define HYPO_INJECT 1
-
-#define WAIT_SPRAY 25
-#define WAIT_INJECT 25
-#define SELF_SPRAY 15
-#define SELF_INJECT 15
-
-#define DELUXE_WAIT_SPRAY 20
-#define DELUXE_WAIT_INJECT 20
-#define DELUXE_SELF_SPRAY 10
-#define DELUXE_SELF_INJECT 10
-
-#define COMBAT_WAIT_SPRAY 0
-#define COMBAT_WAIT_INJECT 0
-#define COMBAT_SELF_SPRAY 0
-#define COMBAT_SELF_INJECT 0
-
-//A vial-loaded hypospray. Cartridge-based!
-/obj/item/hypospray/mkii
- name = "hypospray mk.II"
- icon = 'modular_citadel/icons/obj/hypospraymkii.dmi'
- icon_state = "hypo2"
- desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
- w_class = WEIGHT_CLASS_TINY
- var/list/allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small)
- var/mode = HYPO_INJECT
- var/obj/item/reagent_containers/glass/bottle/vial/vial
- var/start_vial = /obj/item/reagent_containers/glass/bottle/vial/small
- var/spawnwithvial = TRUE
- var/inject_wait = WAIT_INJECT
- var/spray_wait = WAIT_SPRAY
- var/spray_self = SELF_SPRAY
- var/inject_self = SELF_INJECT
- var/quickload = FALSE
- var/penetrates = FALSE
-
-/obj/item/hypospray/mkii/brute
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine
-
-/obj/item/hypospray/mkii/toxin
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin
-
-/obj/item/hypospray/mkii/oxygen
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin
-
-/obj/item/hypospray/mkii/burn
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane
-
-/obj/item/hypospray/mkii/tricord
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord
-
-/obj/item/hypospray/mkii/enlarge
- spawnwithvial = FALSE
-
-/obj/item/hypospray/mkii/CMO
- name = "hypospray mk.II deluxe"
- allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small, /obj/item/reagent_containers/glass/bottle/vial/large)
- icon_state = "cmo2"
- desc = "The Deluxe Hypospray can take larger-size vials. It also acts faster and delivers more reagents per spray."
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/CMO
- inject_wait = DELUXE_WAIT_INJECT
- spray_wait = DELUXE_WAIT_SPRAY
- spray_self = DELUXE_SELF_SPRAY
- inject_self = DELUXE_SELF_INJECT
-
-/obj/item/hypospray/mkii/CMO/combat
- name = "combat hypospray mk.II"
- desc = "A combat-ready deluxe hypospray that acts almost instantly. It can be tactically reloaded by using a vial on it."
- icon_state = "combat2"
- start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat
- inject_wait = COMBAT_WAIT_INJECT
- spray_wait = COMBAT_WAIT_SPRAY
- spray_self = COMBAT_SELF_SPRAY
- inject_self = COMBAT_SELF_INJECT
- quickload = TRUE
- penetrates = TRUE
-
-/obj/item/hypospray/mkii/Initialize()
- . = ..()
- if(!spawnwithvial)
- update_icon()
- return
- if(start_vial)
- vial = new start_vial
- update_icon()
-
-/obj/item/hypospray/mkii/update_icon()
- ..()
- icon_state = "[initial(icon_state)][vial ? "" : "-e"]"
- if(ismob(loc))
- var/mob/M = loc
- M.update_inv_hands()
- return
-
-/obj/item/hypospray/mkii/examine(mob/user)
- . = ..()
- if(vial)
- to_chat(user, "[vial] has [vial.reagents.total_volume]u remaining.")
- else
- to_chat(user, "It has no vial loaded in.")
- to_chat(user, "[src] is set to [mode ? "Inject" : "Spray"] contents on application.")
-
-/obj/item/hypospray/mkii/proc/unload_hypo(obj/item/I, mob/user)
- if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
- var/obj/item/reagent_containers/glass/bottle/vial/V = I
- V.forceMove(user.loc)
- user.put_in_hands(V)
- to_chat(user, "You remove [vial] from [src].")
- vial = null
- update_icon()
- playsound(loc, 'sound/weapons/empty.ogg', 50, 1)
- else
- to_chat(user, "This hypo isn't loaded!")
- return
-
-/obj/item/hypospray/mkii/attackby(obj/item/I, mob/living/user)
- if((istype(I, /obj/item/reagent_containers/glass/bottle/vial) && vial != null))
- if(!quickload)
- to_chat(user, "[src] can not hold more than one vial!")
- return FALSE
- unload_hypo(vial, user)
- if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
- var/obj/item/reagent_containers/glass/bottle/vial/V = I
- if(!is_type_in_list(V, allowed_containers))
- to_chat(user, "[src] doesn't accept this type of vial.")
- return FALSE
- if(!user.transferItemToLoc(V,src))
- return FALSE
- vial = V
- user.visible_message("[user] has loaded a vial into [src].","You have loaded [vial] into [src].")
- update_icon()
- playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
- return TRUE
- else
- to_chat(user, "This doesn't fit in [src].")
- return FALSE
- return FALSE
-
-/obj/item/hypospray/mkii/AltClick(mob/user)
- if(vial)
- vial.attack_self(user)
-
-// Gunna allow this for now, still really don't approve - Pooj
-/obj/item/hypospray/mkii/emag_act(mob/user)
- . = ..()
- if(obj_flags & EMAGGED)
- to_chat(user, "[src] happens to be already overcharged.")
- return
- inject_wait = COMBAT_WAIT_INJECT
- spray_wait = COMBAT_WAIT_SPRAY
- spray_self = COMBAT_SELF_INJECT
- inject_self = COMBAT_SELF_SPRAY
- penetrates = TRUE
- to_chat(user, "You overcharge [src]'s control circuit.")
- obj_flags |= EMAGGED
- return TRUE
-
-/obj/item/hypospray/mkii/attack_hand(mob/user)
- . = ..() //Don't bother changing this or removing it from containers will break.
-
-/obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params)
- return
-
-/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
- if(!vial)
- return
-
- if(!proximity)
- return
-
- if(!ismob(target))
- return
-
- var/mob/living/L
- if(isliving(target))
- L = target
- if(!penetrates && !L.can_inject(user, 1)) //This check appears another four times, since otherwise the penetrating sprays will break in do_mob.
- return
-
- if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
- to_chat(user, "You cannot directly fill [target]!")
- return
-
- if(target.reagents.total_volume >= target.reagents.maximum_volume)
- to_chat(user, "[target] is full.")
- return
-
- if(ishuman(L))
- var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
- if(!affecting)
- to_chat(user, "The limb is missing!")
- return
- if(affecting.status != BODYPART_ORGANIC)
- to_chat(user, "Medicine won't work on a robotic limb!")
- return
-
- var/contained = vial.reagents.log_list()
- log_combat(user, L, "attemped to inject", src, addition="which had [contained]")
-//Always log attemped injections for admins
- if(vial != null)
- switch(mode)
- if(HYPO_INJECT)
- if(L) //living mob
- if(L != user)
- L.visible_message("[user] is trying to inject [L] with [src]!", \
- "[user] is trying to inject [L] with [src]!")
- if(!do_mob(user, L, inject_wait))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- L.visible_message("[user] uses the [src] on [L]!", \
- "[user] uses the [src] on [L]!")
- else
- if(!do_mob(user, L, inject_self))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
- L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
-
- var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
- vial.reagents.reaction(L, INJECT, fraction)
- vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
- if(vial.amount_per_transfer_from_this >= 15)
- playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
- if(vial.amount_per_transfer_from_this < 15)
- playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
- to_chat(user, "You inject [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
-
- if(HYPO_SPRAY)
- if(L) //living mob
- if(L != user)
- L.visible_message("[user] is trying to spray [L] with [src]!", \
- "[user] is trying to spray [L] with [src]!")
- if(!do_mob(user, L, spray_wait))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- L.visible_message("[user] uses the [src] on [L]!", \
- "[user] uses the [src] on [L]!")
- else
- if(!do_mob(user, L, spray_self))
- return
- if(!penetrates && !L.can_inject(user, 1))
- return
- if(!vial.reagents.total_volume)
- return
- if(L.reagents.total_volume >= L.reagents.maximum_volume)
- return
- log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
- L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
- var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
- vial.reagents.reaction(L, PATCH, fraction)
- vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
- if(vial.amount_per_transfer_from_this >= 15)
- playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
- if(vial.amount_per_transfer_from_this < 15)
- playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
- to_chat(user, "You spray [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
- else
- to_chat(user, "[src] doesn't work here!")
- return
-
-/obj/item/hypospray/mkii/attack_self(mob/living/user)
- if(user)
- if(user.incapacitated())
- return
- else if(!vial)
- to_chat(user, "This Hypo needs to be loaded first!")
- return
- else
- unload_hypo(vial,user)
-
-/obj/item/hypospray/mkii/verb/modes()
- set name = "Toggle Application Mode"
- set category = "Object"
- set src in usr
- var/mob/M = usr
- switch(mode)
- if(HYPO_SPRAY)
- mode = HYPO_INJECT
- to_chat(M, "[src] is now set to inject contents on application.")
- if(HYPO_INJECT)
- mode = HYPO_SPRAY
- to_chat(M, "[src] is now set to spray contents on application.")
diff --git a/modular_citadel/code/modules/research/designs/machine_designs.dm b/modular_citadel/code/modules/research/designs/machine_designs.dm
deleted file mode 100644
index 6a1331dddc..0000000000
--- a/modular_citadel/code/modules/research/designs/machine_designs.dm
+++ /dev/null
@@ -1,6 +0,0 @@
-/datum/design/board/autoylathe
- name = "Machine Design (Autoylathe)"
- desc = "The circuit board for an autoylathe."
- id = "autoylathe"
- build_path = /obj/item/circuitboard/machine/autoylathe
- category = list("Misc. Machinery")
diff --git a/modular_citadel/code/modules/research/designs/weapon_designs.dm b/modular_citadel/code/modules/research/designs/weapon_designs.dm
deleted file mode 100644
index b27cedbcc2..0000000000
--- a/modular_citadel/code/modules/research/designs/weapon_designs.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/datum/design/mag_oldsmg/rubber_mag
- name = "WT-550 Semi-Auto SMG rubberbullets Magazine (4.6x30mm rubber)"
- desc = "A 20 round rubber shots magazine for the out of date security WT-550 Semi-Auto SMG"
- id = "mag_oldsmg_rubber"
- materials = list(MAT_METAL = 6000)
- build_path = /obj/item/ammo_box/magazine/wt550m9/wtrubber
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
diff --git a/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm b/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm
deleted file mode 100644
index 6246b9e24e..0000000000
--- a/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm
+++ /dev/null
@@ -1,7 +0,0 @@
-/datum/design/mag_oldsmg/tx_mag
- name = "WT-550 Semi-Auto SMG Uranium Magazine (4.6x30mm TX)"
- desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Semi-Auto SMG."
- id = "mag_oldsmg_tx"
- materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_URANIUM = 2000)
- build_path = /obj/item/ammo_box/magazine/wt550m9/wttx
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
diff --git a/modular_citadel/code/modules/research/designs/xenobio_designs.dm b/modular_citadel/code/modules/research/designs/xenobio_designs.dm
deleted file mode 100644
index 45ed8e83a0..0000000000
--- a/modular_citadel/code/modules/research/designs/xenobio_designs.dm
+++ /dev/null
@@ -1,25 +0,0 @@
-/datum/design/xenobio_upgrade
- name = "owo"
- desc = "someone's bussin"
- build_type = PROTOLATHE
- materials = list(MAT_METAL = 300, MAT_GLASS = 100)
- category = list("Electronics")
- departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
-
-/datum/design/xenobio_upgrade/xenobiomonkeys
- name = "Xenobiology console monkey upgrade disk"
- desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
- id = "xenobio_monkeys"
- build_path = /obj/item/disk/xenobio_console_upgrade/monkey
-
-/datum/design/xenobio_upgrade/xenobioslimebasic
- name = "Xenobiology console basic slime upgrade disk"
- desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
- id = "xenobio_slimebasic"
- build_path = /obj/item/disk/xenobio_console_upgrade/slimebasic
-
-/datum/design/xenobio_upgrade/xenobioslimeadv
- name = "Xenobiology console advanced slime upgrade disk"
- desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
- id = "xenobio_slimeadv"
- build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv
diff --git a/modular_citadel/code/modules/research/techweb/_techweb.dm b/modular_citadel/code/modules/research/techweb/_techweb.dm
deleted file mode 100644
index 1c96229594..0000000000
--- a/modular_citadel/code/modules/research/techweb/_techweb.dm
+++ /dev/null
@@ -1,3 +0,0 @@
-/datum/techweb/specialized/autounlocking/autoylathe
- design_autounlock_buildtypes = AUTOYLATHE
- allowed_buildtypes = AUTOYLATHE
diff --git a/modular_citadel/code/modules/research/xenobiology/xenobio_camera.dm b/modular_citadel/code/modules/research/xenobiology/xenobio_camera.dm
deleted file mode 100644
index b700626a1d..0000000000
--- a/modular_citadel/code/modules/research/xenobiology/xenobio_camera.dm
+++ /dev/null
@@ -1,48 +0,0 @@
-/obj/machinery/computer/camera_advanced/xenobio
- max_slimes = 1
- var/upgradetier = 0
-
-/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/disk/xenobio_console_upgrade))
- var/obj/item/disk/xenobio_console_upgrade/diskthing = O
- var/successfulupgrade = FALSE
- for(var/I in diskthing.upgradetypes)
- if(upgradetier & I)
- continue
- else
- upgradetier |= I
- successfulupgrade = TRUE
- if(I == XENOBIO_UPGRADE_SLIMEADV)
- max_slimes = 10
- if(successfulupgrade)
- to_chat(user, "You have successfully upgraded [src] with [O].")
- else
- to_chat(user, "[src] already has the contents of [O] installed!")
- return
- . = ..()
-
-/obj/item/disk/xenobio_console_upgrade
- name = "Xenobiology console upgrade disk"
- desc = "Allan please add detail."
- icon_state = "datadisk5"
- var/list/upgradetypes = list()
-
-/obj/item/disk/xenobio_console_upgrade/admin
- name = "Xenobio all access thing"
- desc = "'the consoles are literally useless!!!!!!!!!!!!!!!'"
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV, XENOBIO_UPGRADE_MONKEYS)
-
-/obj/item/disk/xenobio_console_upgrade/monkey
- name = "Xenobiology console monkey upgrade disk"
- desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
- upgradetypes = list(XENOBIO_UPGRADE_MONKEYS)
-
-/obj/item/disk/xenobio_console_upgrade/slimebasic
- name = "Xenobiology console basic slime upgrade disk"
- desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC)
-
-/obj/item/disk/xenobio_console_upgrade/slimeadv
- name = "Xenobiology console advanced slime upgrade disk"
- desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
- upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV)
diff --git a/modular_citadel/icons/eutactic/item/hypereutactic.dmi b/modular_citadel/icons/eutactic/item/hypereutactic.dmi
deleted file mode 100644
index 90a665f676..0000000000
Binary files a/modular_citadel/icons/eutactic/item/hypereutactic.dmi and /dev/null differ
diff --git a/modular_citadel/icons/eutactic/item/noneutactic.dmi b/modular_citadel/icons/eutactic/item/noneutactic.dmi
deleted file mode 100644
index 9d8b9fd1dd..0000000000
Binary files a/modular_citadel/icons/eutactic/item/noneutactic.dmi and /dev/null differ
diff --git a/modular_citadel/icons/eutactic/mob/hypereutactic_left.dmi b/modular_citadel/icons/eutactic/mob/hypereutactic_left.dmi
deleted file mode 100644
index ca94055113..0000000000
Binary files a/modular_citadel/icons/eutactic/mob/hypereutactic_left.dmi and /dev/null differ
diff --git a/modular_citadel/icons/eutactic/mob/hypereutactic_right.dmi b/modular_citadel/icons/eutactic/mob/hypereutactic_right.dmi
deleted file mode 100644
index a9b90da740..0000000000
Binary files a/modular_citadel/icons/eutactic/mob/hypereutactic_right.dmi and /dev/null differ
diff --git a/modular_citadel/icons/eutactic/mob/noneutactic_left.dmi b/modular_citadel/icons/eutactic/mob/noneutactic_left.dmi
deleted file mode 100644
index a426597146..0000000000
Binary files a/modular_citadel/icons/eutactic/mob/noneutactic_left.dmi and /dev/null differ
diff --git a/modular_citadel/icons/eutactic/mob/noneutactic_right.dmi b/modular_citadel/icons/eutactic/mob/noneutactic_right.dmi
deleted file mode 100644
index aab77c5fd4..0000000000
Binary files a/modular_citadel/icons/eutactic/mob/noneutactic_right.dmi and /dev/null differ
diff --git a/modular_citadel/icons/lavaknight/item/head.dmi b/modular_citadel/icons/lavaknight/item/head.dmi
deleted file mode 100644
index 950d4894e9..0000000000
Binary files a/modular_citadel/icons/lavaknight/item/head.dmi and /dev/null differ
diff --git a/modular_citadel/icons/lavaknight/item/suit.dmi b/modular_citadel/icons/lavaknight/item/suit.dmi
deleted file mode 100644
index 49cd14b666..0000000000
Binary files a/modular_citadel/icons/lavaknight/item/suit.dmi and /dev/null differ
diff --git a/modular_citadel/icons/lavaknight/mob/head.dmi b/modular_citadel/icons/lavaknight/mob/head.dmi
deleted file mode 100644
index 5084c9c66f..0000000000
Binary files a/modular_citadel/icons/lavaknight/mob/head.dmi and /dev/null differ
diff --git a/modular_citadel/icons/lavaknight/mob/suit.dmi b/modular_citadel/icons/lavaknight/mob/suit.dmi
deleted file mode 100644
index ed51ceaaa4..0000000000
Binary files a/modular_citadel/icons/lavaknight/mob/suit.dmi and /dev/null differ
diff --git a/modular_citadel/icons/mob/BananaSpider.dmi b/modular_citadel/icons/mob/BananaSpider.dmi
deleted file mode 100644
index da65ef43fa..0000000000
Binary files a/modular_citadel/icons/mob/BananaSpider.dmi and /dev/null differ
diff --git a/modular_citadel/icons/mob/kiwi.dmi b/modular_citadel/icons/mob/kiwi.dmi
deleted file mode 100644
index 18777f65cf..0000000000
Binary files a/modular_citadel/icons/mob/kiwi.dmi and /dev/null differ
diff --git a/modular_citadel/icons/mob/mam_markings.dmi b/modular_citadel/icons/mob/mam_markings.dmi
index d61baa4a51..af916d2fd0 100644
Binary files a/modular_citadel/icons/mob/mam_markings.dmi and b/modular_citadel/icons/mob/mam_markings.dmi differ
diff --git a/modular_citadel/icons/mob/markings_notmammals.dmi b/modular_citadel/icons/mob/markings_notmammals.dmi
index d9577698d1..79c97968ed 100644
Binary files a/modular_citadel/icons/mob/markings_notmammals.dmi and b/modular_citadel/icons/mob/markings_notmammals.dmi differ
diff --git a/modular_citadel/icons/mob/mutant_bodyparts.dmi b/modular_citadel/icons/mob/mutant_bodyparts.dmi
index 8c0856429b..a66895f864 100644
Binary files a/modular_citadel/icons/mob/mutant_bodyparts.dmi and b/modular_citadel/icons/mob/mutant_bodyparts.dmi differ
diff --git a/modular_citadel/icons/mob/uniform_digi.dmi b/modular_citadel/icons/mob/uniform_digi.dmi
index 513ebce439..3f1335153e 100644
Binary files a/modular_citadel/icons/mob/uniform_digi.dmi and b/modular_citadel/icons/mob/uniform_digi.dmi differ
diff --git a/modular_citadel/icons/obj/FermiChem.dmi b/modular_citadel/icons/obj/FermiChem.dmi
deleted file mode 100644
index de7a86d574..0000000000
Binary files a/modular_citadel/icons/obj/FermiChem.dmi and /dev/null differ
diff --git a/modular_citadel/icons/obj/genitals/hud.dmi b/modular_citadel/icons/obj/genitals/hud.dmi
index bf2adcb1fc..f8c8643fe0 100644
Binary files a/modular_citadel/icons/obj/genitals/hud.dmi and b/modular_citadel/icons/obj/genitals/hud.dmi differ
diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi
index 33659cf13c..65eb24268f 100644
Binary files a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi and b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi differ
diff --git a/modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi b/modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi
deleted file mode 100644
index 9a902e0dff..0000000000
Binary files a/modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi and /dev/null differ
diff --git a/modular_citadel/icons/obj/guns/energy.dmi b/modular_citadel/icons/obj/guns/energy.dmi
new file mode 100644
index 0000000000..482ec04d94
Binary files /dev/null and b/modular_citadel/icons/obj/guns/energy.dmi differ
diff --git a/modular_citadel/icons/obj/hypospraymkii.dmi b/modular_citadel/icons/obj/hypospraymkii.dmi
deleted file mode 100755
index 3f32219d84..0000000000
Binary files a/modular_citadel/icons/obj/hypospraymkii.dmi and /dev/null differ
diff --git a/modular_citadel/icons/obj/id.dmi b/modular_citadel/icons/obj/id.dmi
deleted file mode 100644
index 653542e93d..0000000000
Binary files a/modular_citadel/icons/obj/id.dmi and /dev/null differ
diff --git a/modular_citadel/icons/obj/modularpills.dmi b/modular_citadel/icons/obj/modularpills.dmi
deleted file mode 100644
index 78095d82c0..0000000000
Binary files a/modular_citadel/icons/obj/modularpills.dmi and /dev/null differ
diff --git a/modular_citadel/icons/obj/vial.dmi b/modular_citadel/icons/obj/vial.dmi
deleted file mode 100755
index 8d1fefe470..0000000000
Binary files a/modular_citadel/icons/obj/vial.dmi and /dev/null differ
diff --git a/sound/AI/aimalf.ogg b/sound/announcer/classic/aimalf.ogg
similarity index 100%
rename from sound/AI/aimalf.ogg
rename to sound/announcer/classic/aimalf.ogg
diff --git a/sound/AI/aliens.ogg b/sound/announcer/classic/aliens.ogg
similarity index 100%
rename from sound/AI/aliens.ogg
rename to sound/announcer/classic/aliens.ogg
diff --git a/sound/AI/animes.ogg b/sound/announcer/classic/animes.ogg
similarity index 100%
rename from sound/AI/animes.ogg
rename to sound/announcer/classic/animes.ogg
diff --git a/sound/AI/attention.ogg b/sound/announcer/classic/attention.ogg
similarity index 100%
rename from sound/AI/attention.ogg
rename to sound/announcer/classic/attention.ogg
diff --git a/sound/AI/commandreport.ogg b/sound/announcer/classic/commandreport.ogg
similarity index 100%
rename from sound/AI/commandreport.ogg
rename to sound/announcer/classic/commandreport.ogg
diff --git a/sound/AI/granomalies.ogg b/sound/announcer/classic/granomalies.ogg
similarity index 100%
rename from sound/AI/granomalies.ogg
rename to sound/announcer/classic/granomalies.ogg
diff --git a/sound/AI/intercept.ogg b/sound/announcer/classic/intercept.ogg
similarity index 100%
rename from sound/AI/intercept.ogg
rename to sound/announcer/classic/intercept.ogg
diff --git a/sound/AI/ionstorm.ogg b/sound/announcer/classic/ionstorm.ogg
similarity index 100%
rename from sound/AI/ionstorm.ogg
rename to sound/announcer/classic/ionstorm.ogg
diff --git a/sound/AI/meteors.ogg b/sound/announcer/classic/meteors.ogg
similarity index 100%
rename from sound/AI/meteors.ogg
rename to sound/announcer/classic/meteors.ogg
diff --git a/sound/AI/newAI.ogg b/sound/announcer/classic/newAI.ogg
similarity index 100%
rename from sound/AI/newAI.ogg
rename to sound/announcer/classic/newAI.ogg
diff --git a/sound/AI/outbreak5.ogg b/sound/announcer/classic/outbreak5.ogg
similarity index 100%
rename from sound/AI/outbreak5.ogg
rename to sound/announcer/classic/outbreak5.ogg
diff --git a/sound/AI/outbreak7.ogg b/sound/announcer/classic/outbreak7.ogg
similarity index 100%
rename from sound/AI/outbreak7.ogg
rename to sound/announcer/classic/outbreak7.ogg
diff --git a/sound/AI/poweroff.ogg b/sound/announcer/classic/poweroff.ogg
similarity index 100%
rename from sound/AI/poweroff.ogg
rename to sound/announcer/classic/poweroff.ogg
diff --git a/sound/AI/poweron.ogg b/sound/announcer/classic/poweron.ogg
similarity index 100%
rename from sound/AI/poweron.ogg
rename to sound/announcer/classic/poweron.ogg
diff --git a/sound/AI/radiation.ogg b/sound/announcer/classic/radiation.ogg
similarity index 100%
rename from sound/AI/radiation.ogg
rename to sound/announcer/classic/radiation.ogg
diff --git a/sound/AI/shuttlecalled.ogg b/sound/announcer/classic/shuttlecalled.ogg
similarity index 100%
rename from sound/AI/shuttlecalled.ogg
rename to sound/announcer/classic/shuttlecalled.ogg
diff --git a/sound/AI/shuttledock.ogg b/sound/announcer/classic/shuttledock.ogg
similarity index 100%
rename from sound/AI/shuttledock.ogg
rename to sound/announcer/classic/shuttledock.ogg
diff --git a/sound/AI/shuttlerecalled.ogg b/sound/announcer/classic/shuttlerecalled.ogg
similarity index 100%
rename from sound/AI/shuttlerecalled.ogg
rename to sound/announcer/classic/shuttlerecalled.ogg
diff --git a/sound/AI/spanomalies.ogg b/sound/announcer/classic/spanomalies.ogg
similarity index 100%
rename from sound/AI/spanomalies.ogg
rename to sound/announcer/classic/spanomalies.ogg
diff --git a/sound/AI/welcome.ogg b/sound/announcer/classic/welcome.ogg
similarity index 100%
rename from sound/AI/welcome.ogg
rename to sound/announcer/classic/welcome.ogg
diff --git a/sound/announcer/medibot/aliens.ogg b/sound/announcer/medibot/aliens.ogg
new file mode 100644
index 0000000000..57fa70c3ca
Binary files /dev/null and b/sound/announcer/medibot/aliens.ogg differ
diff --git a/sound/announcer/medibot/animes.ogg b/sound/announcer/medibot/animes.ogg
new file mode 100644
index 0000000000..7615a744a6
Binary files /dev/null and b/sound/announcer/medibot/animes.ogg differ
diff --git a/sound/announcer/medibot/attention.ogg b/sound/announcer/medibot/attention.ogg
new file mode 100644
index 0000000000..d4d5a27085
Binary files /dev/null and b/sound/announcer/medibot/attention.ogg differ
diff --git a/sound/announcer/medibot/commandreport.ogg b/sound/announcer/medibot/commandreport.ogg
new file mode 100644
index 0000000000..4e5c2e1d1f
Binary files /dev/null and b/sound/announcer/medibot/commandreport.ogg differ
diff --git a/sound/announcer/medibot/granomalies.ogg b/sound/announcer/medibot/granomalies.ogg
new file mode 100644
index 0000000000..2713a3cb19
Binary files /dev/null and b/sound/announcer/medibot/granomalies.ogg differ
diff --git a/sound/announcer/medibot/intercept.ogg b/sound/announcer/medibot/intercept.ogg
new file mode 100644
index 0000000000..c59d0455c1
Binary files /dev/null and b/sound/announcer/medibot/intercept.ogg differ
diff --git a/sound/announcer/medibot/ionstorm.ogg b/sound/announcer/medibot/ionstorm.ogg
new file mode 100644
index 0000000000..15aeac9f7f
Binary files /dev/null and b/sound/announcer/medibot/ionstorm.ogg differ
diff --git a/sound/announcer/medibot/meteors.ogg b/sound/announcer/medibot/meteors.ogg
new file mode 100644
index 0000000000..91208cae12
Binary files /dev/null and b/sound/announcer/medibot/meteors.ogg differ
diff --git a/sound/announcer/medibot/newAI.ogg b/sound/announcer/medibot/newAI.ogg
new file mode 100644
index 0000000000..c40b099020
Binary files /dev/null and b/sound/announcer/medibot/newAI.ogg differ
diff --git a/sound/announcer/medibot/outbreak5.ogg b/sound/announcer/medibot/outbreak5.ogg
new file mode 100644
index 0000000000..7118af4449
Binary files /dev/null and b/sound/announcer/medibot/outbreak5.ogg differ
diff --git a/sound/announcer/medibot/outbreak7.ogg b/sound/announcer/medibot/outbreak7.ogg
new file mode 100644
index 0000000000..1fc542534d
Binary files /dev/null and b/sound/announcer/medibot/outbreak7.ogg differ
diff --git a/sound/announcer/medibot/poweroff.ogg b/sound/announcer/medibot/poweroff.ogg
new file mode 100644
index 0000000000..875df35002
Binary files /dev/null and b/sound/announcer/medibot/poweroff.ogg differ
diff --git a/sound/announcer/medibot/poweron.ogg b/sound/announcer/medibot/poweron.ogg
new file mode 100644
index 0000000000..4b1605b1c7
Binary files /dev/null and b/sound/announcer/medibot/poweron.ogg differ
diff --git a/sound/announcer/medibot/radiation.ogg b/sound/announcer/medibot/radiation.ogg
new file mode 100644
index 0000000000..5c48830b5f
Binary files /dev/null and b/sound/announcer/medibot/radiation.ogg differ
diff --git a/sound/announcer/medibot/shuttlecalled.ogg b/sound/announcer/medibot/shuttlecalled.ogg
new file mode 100644
index 0000000000..a775567abe
Binary files /dev/null and b/sound/announcer/medibot/shuttlecalled.ogg differ
diff --git a/sound/announcer/medibot/shuttledocked.ogg b/sound/announcer/medibot/shuttledocked.ogg
new file mode 100644
index 0000000000..933928db06
Binary files /dev/null and b/sound/announcer/medibot/shuttledocked.ogg differ
diff --git a/sound/announcer/medibot/shuttlerecalled.ogg b/sound/announcer/medibot/shuttlerecalled.ogg
new file mode 100644
index 0000000000..53b622576d
Binary files /dev/null and b/sound/announcer/medibot/shuttlerecalled.ogg differ
diff --git a/sound/announcer/medibot/spanomalies.ogg b/sound/announcer/medibot/spanomalies.ogg
new file mode 100644
index 0000000000..d710999e1e
Binary files /dev/null and b/sound/announcer/medibot/spanomalies.ogg differ
diff --git a/sound/announcer/medibot/welcome.ogg b/sound/announcer/medibot/welcome.ogg
new file mode 100644
index 0000000000..f9a698fd08
Binary files /dev/null and b/sound/announcer/medibot/welcome.ogg differ
diff --git a/sound/AI/harmalarm.ogg b/sound/effects/harmalarm.ogg
similarity index 100%
rename from sound/AI/harmalarm.ogg
rename to sound/effects/harmalarm.ogg
diff --git a/sound/effects/k9_jaw_strong.ogg b/sound/effects/k9_jaw_strong.ogg
new file mode 100644
index 0000000000..9f60050b95
Binary files /dev/null and b/sound/effects/k9_jaw_strong.ogg differ
diff --git a/sound/effects/k9_jaw_weak.ogg b/sound/effects/k9_jaw_weak.ogg
new file mode 100644
index 0000000000..3ef2272f01
Binary files /dev/null and b/sound/effects/k9_jaw_weak.ogg differ
diff --git a/modular_citadel/sound/vox/_comma.ogg b/sound/vox/_comma.ogg
similarity index 100%
rename from modular_citadel/sound/vox/_comma.ogg
rename to sound/vox/_comma.ogg
diff --git a/modular_citadel/sound/vox/_period.ogg b/sound/vox/_period.ogg
similarity index 100%
rename from modular_citadel/sound/vox/_period.ogg
rename to sound/vox/_period.ogg
diff --git a/modular_citadel/sound/vox/a.ogg b/sound/vox/a.ogg
similarity index 100%
rename from modular_citadel/sound/vox/a.ogg
rename to sound/vox/a.ogg
diff --git a/modular_citadel/sound/vox/accelerating.ogg b/sound/vox/accelerating.ogg
similarity index 100%
rename from modular_citadel/sound/vox/accelerating.ogg
rename to sound/vox/accelerating.ogg
diff --git a/modular_citadel/sound/vox/accelerator.ogg b/sound/vox/accelerator.ogg
similarity index 100%
rename from modular_citadel/sound/vox/accelerator.ogg
rename to sound/vox/accelerator.ogg
diff --git a/modular_citadel/sound/vox/accepted.ogg b/sound/vox/accepted.ogg
similarity index 100%
rename from modular_citadel/sound/vox/accepted.ogg
rename to sound/vox/accepted.ogg
diff --git a/modular_citadel/sound/vox/access.ogg b/sound/vox/access.ogg
similarity index 100%
rename from modular_citadel/sound/vox/access.ogg
rename to sound/vox/access.ogg
diff --git a/modular_citadel/sound/vox/acknowledge.ogg b/sound/vox/acknowledge.ogg
similarity index 100%
rename from modular_citadel/sound/vox/acknowledge.ogg
rename to sound/vox/acknowledge.ogg
diff --git a/modular_citadel/sound/vox/acknowledged.ogg b/sound/vox/acknowledged.ogg
similarity index 100%
rename from modular_citadel/sound/vox/acknowledged.ogg
rename to sound/vox/acknowledged.ogg
diff --git a/modular_citadel/sound/vox/acquired.ogg b/sound/vox/acquired.ogg
similarity index 100%
rename from modular_citadel/sound/vox/acquired.ogg
rename to sound/vox/acquired.ogg
diff --git a/modular_citadel/sound/vox/acquisition.ogg b/sound/vox/acquisition.ogg
similarity index 100%
rename from modular_citadel/sound/vox/acquisition.ogg
rename to sound/vox/acquisition.ogg
diff --git a/modular_citadel/sound/vox/across.ogg b/sound/vox/across.ogg
similarity index 100%
rename from modular_citadel/sound/vox/across.ogg
rename to sound/vox/across.ogg
diff --git a/modular_citadel/sound/vox/activate.ogg b/sound/vox/activate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/activate.ogg
rename to sound/vox/activate.ogg
diff --git a/modular_citadel/sound/vox/activated.ogg b/sound/vox/activated.ogg
similarity index 100%
rename from modular_citadel/sound/vox/activated.ogg
rename to sound/vox/activated.ogg
diff --git a/modular_citadel/sound/vox/activity.ogg b/sound/vox/activity.ogg
similarity index 100%
rename from modular_citadel/sound/vox/activity.ogg
rename to sound/vox/activity.ogg
diff --git a/modular_citadel/sound/vox/adios.ogg b/sound/vox/adios.ogg
similarity index 100%
rename from modular_citadel/sound/vox/adios.ogg
rename to sound/vox/adios.ogg
diff --git a/modular_citadel/sound/vox/administration.ogg b/sound/vox/administration.ogg
similarity index 100%
rename from modular_citadel/sound/vox/administration.ogg
rename to sound/vox/administration.ogg
diff --git a/modular_citadel/sound/vox/advanced.ogg b/sound/vox/advanced.ogg
similarity index 100%
rename from modular_citadel/sound/vox/advanced.ogg
rename to sound/vox/advanced.ogg
diff --git a/modular_citadel/sound/vox/after.ogg b/sound/vox/after.ogg
similarity index 100%
rename from modular_citadel/sound/vox/after.ogg
rename to sound/vox/after.ogg
diff --git a/modular_citadel/sound/vox/agent.ogg b/sound/vox/agent.ogg
similarity index 100%
rename from modular_citadel/sound/vox/agent.ogg
rename to sound/vox/agent.ogg
diff --git a/modular_citadel/sound/vox/alarm.ogg b/sound/vox/alarm.ogg
similarity index 100%
rename from modular_citadel/sound/vox/alarm.ogg
rename to sound/vox/alarm.ogg
diff --git a/modular_citadel/sound/vox/alert.ogg b/sound/vox/alert.ogg
similarity index 100%
rename from modular_citadel/sound/vox/alert.ogg
rename to sound/vox/alert.ogg
diff --git a/modular_citadel/sound/vox/alien.ogg b/sound/vox/alien.ogg
similarity index 100%
rename from modular_citadel/sound/vox/alien.ogg
rename to sound/vox/alien.ogg
diff --git a/modular_citadel/sound/vox/aligned.ogg b/sound/vox/aligned.ogg
similarity index 100%
rename from modular_citadel/sound/vox/aligned.ogg
rename to sound/vox/aligned.ogg
diff --git a/modular_citadel/sound/vox/all.ogg b/sound/vox/all.ogg
similarity index 100%
rename from modular_citadel/sound/vox/all.ogg
rename to sound/vox/all.ogg
diff --git a/modular_citadel/sound/vox/alpha.ogg b/sound/vox/alpha.ogg
similarity index 100%
rename from modular_citadel/sound/vox/alpha.ogg
rename to sound/vox/alpha.ogg
diff --git a/modular_citadel/sound/vox/am.ogg b/sound/vox/am.ogg
similarity index 100%
rename from modular_citadel/sound/vox/am.ogg
rename to sound/vox/am.ogg
diff --git a/modular_citadel/sound/vox/amigo.ogg b/sound/vox/amigo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/amigo.ogg
rename to sound/vox/amigo.ogg
diff --git a/modular_citadel/sound/vox/ammunition.ogg b/sound/vox/ammunition.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ammunition.ogg
rename to sound/vox/ammunition.ogg
diff --git a/modular_citadel/sound/vox/an.ogg b/sound/vox/an.ogg
similarity index 100%
rename from modular_citadel/sound/vox/an.ogg
rename to sound/vox/an.ogg
diff --git a/modular_citadel/sound/vox/and.ogg b/sound/vox/and.ogg
similarity index 100%
rename from modular_citadel/sound/vox/and.ogg
rename to sound/vox/and.ogg
diff --git a/modular_citadel/sound/vox/announcement.ogg b/sound/vox/announcement.ogg
similarity index 100%
rename from modular_citadel/sound/vox/announcement.ogg
rename to sound/vox/announcement.ogg
diff --git a/modular_citadel/sound/vox/anomalous.ogg b/sound/vox/anomalous.ogg
similarity index 100%
rename from modular_citadel/sound/vox/anomalous.ogg
rename to sound/vox/anomalous.ogg
diff --git a/modular_citadel/sound/vox/antenna.ogg b/sound/vox/antenna.ogg
similarity index 100%
rename from modular_citadel/sound/vox/antenna.ogg
rename to sound/vox/antenna.ogg
diff --git a/modular_citadel/sound/vox/any.ogg b/sound/vox/any.ogg
similarity index 100%
rename from modular_citadel/sound/vox/any.ogg
rename to sound/vox/any.ogg
diff --git a/modular_citadel/sound/vox/apprehend.ogg b/sound/vox/apprehend.ogg
similarity index 100%
rename from modular_citadel/sound/vox/apprehend.ogg
rename to sound/vox/apprehend.ogg
diff --git a/modular_citadel/sound/vox/approach.ogg b/sound/vox/approach.ogg
similarity index 100%
rename from modular_citadel/sound/vox/approach.ogg
rename to sound/vox/approach.ogg
diff --git a/modular_citadel/sound/vox/are.ogg b/sound/vox/are.ogg
similarity index 100%
rename from modular_citadel/sound/vox/are.ogg
rename to sound/vox/are.ogg
diff --git a/modular_citadel/sound/vox/area.ogg b/sound/vox/area.ogg
similarity index 100%
rename from modular_citadel/sound/vox/area.ogg
rename to sound/vox/area.ogg
diff --git a/modular_citadel/sound/vox/arm.ogg b/sound/vox/arm.ogg
similarity index 100%
rename from modular_citadel/sound/vox/arm.ogg
rename to sound/vox/arm.ogg
diff --git a/modular_citadel/sound/vox/armed.ogg b/sound/vox/armed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/armed.ogg
rename to sound/vox/armed.ogg
diff --git a/modular_citadel/sound/vox/armor.ogg b/sound/vox/armor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/armor.ogg
rename to sound/vox/armor.ogg
diff --git a/modular_citadel/sound/vox/armory.ogg b/sound/vox/armory.ogg
similarity index 100%
rename from modular_citadel/sound/vox/armory.ogg
rename to sound/vox/armory.ogg
diff --git a/modular_citadel/sound/vox/arrest.ogg b/sound/vox/arrest.ogg
similarity index 100%
rename from modular_citadel/sound/vox/arrest.ogg
rename to sound/vox/arrest.ogg
diff --git a/modular_citadel/sound/vox/ass.ogg b/sound/vox/ass.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ass.ogg
rename to sound/vox/ass.ogg
diff --git a/modular_citadel/sound/vox/at.ogg b/sound/vox/at.ogg
similarity index 100%
rename from modular_citadel/sound/vox/at.ogg
rename to sound/vox/at.ogg
diff --git a/modular_citadel/sound/vox/atomic.ogg b/sound/vox/atomic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/atomic.ogg
rename to sound/vox/atomic.ogg
diff --git a/modular_citadel/sound/vox/attention.ogg b/sound/vox/attention.ogg
similarity index 100%
rename from modular_citadel/sound/vox/attention.ogg
rename to sound/vox/attention.ogg
diff --git a/modular_citadel/sound/vox/authorize.ogg b/sound/vox/authorize.ogg
similarity index 100%
rename from modular_citadel/sound/vox/authorize.ogg
rename to sound/vox/authorize.ogg
diff --git a/modular_citadel/sound/vox/authorized.ogg b/sound/vox/authorized.ogg
similarity index 100%
rename from modular_citadel/sound/vox/authorized.ogg
rename to sound/vox/authorized.ogg
diff --git a/modular_citadel/sound/vox/automatic.ogg b/sound/vox/automatic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/automatic.ogg
rename to sound/vox/automatic.ogg
diff --git a/modular_citadel/sound/vox/away.ogg b/sound/vox/away.ogg
similarity index 100%
rename from modular_citadel/sound/vox/away.ogg
rename to sound/vox/away.ogg
diff --git a/modular_citadel/sound/vox/b.ogg b/sound/vox/b.ogg
similarity index 100%
rename from modular_citadel/sound/vox/b.ogg
rename to sound/vox/b.ogg
diff --git a/modular_citadel/sound/vox/back.ogg b/sound/vox/back.ogg
similarity index 100%
rename from modular_citadel/sound/vox/back.ogg
rename to sound/vox/back.ogg
diff --git a/modular_citadel/sound/vox/backman.ogg b/sound/vox/backman.ogg
similarity index 100%
rename from modular_citadel/sound/vox/backman.ogg
rename to sound/vox/backman.ogg
diff --git a/modular_citadel/sound/vox/bad.ogg b/sound/vox/bad.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bad.ogg
rename to sound/vox/bad.ogg
diff --git a/modular_citadel/sound/vox/bag.ogg b/sound/vox/bag.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bag.ogg
rename to sound/vox/bag.ogg
diff --git a/modular_citadel/sound/vox/bailey.ogg b/sound/vox/bailey.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bailey.ogg
rename to sound/vox/bailey.ogg
diff --git a/modular_citadel/sound/vox/barracks.ogg b/sound/vox/barracks.ogg
similarity index 100%
rename from modular_citadel/sound/vox/barracks.ogg
rename to sound/vox/barracks.ogg
diff --git a/modular_citadel/sound/vox/base.ogg b/sound/vox/base.ogg
similarity index 100%
rename from modular_citadel/sound/vox/base.ogg
rename to sound/vox/base.ogg
diff --git a/modular_citadel/sound/vox/bay.ogg b/sound/vox/bay.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bay.ogg
rename to sound/vox/bay.ogg
diff --git a/modular_citadel/sound/vox/be.ogg b/sound/vox/be.ogg
similarity index 100%
rename from modular_citadel/sound/vox/be.ogg
rename to sound/vox/be.ogg
diff --git a/modular_citadel/sound/vox/been.ogg b/sound/vox/been.ogg
similarity index 100%
rename from modular_citadel/sound/vox/been.ogg
rename to sound/vox/been.ogg
diff --git a/modular_citadel/sound/vox/before.ogg b/sound/vox/before.ogg
similarity index 100%
rename from modular_citadel/sound/vox/before.ogg
rename to sound/vox/before.ogg
diff --git a/modular_citadel/sound/vox/beyond.ogg b/sound/vox/beyond.ogg
similarity index 100%
rename from modular_citadel/sound/vox/beyond.ogg
rename to sound/vox/beyond.ogg
diff --git a/modular_citadel/sound/vox/biohazard.ogg b/sound/vox/biohazard.ogg
similarity index 100%
rename from modular_citadel/sound/vox/biohazard.ogg
rename to sound/vox/biohazard.ogg
diff --git a/modular_citadel/sound/vox/biological.ogg b/sound/vox/biological.ogg
similarity index 100%
rename from modular_citadel/sound/vox/biological.ogg
rename to sound/vox/biological.ogg
diff --git a/modular_citadel/sound/vox/birdwell.ogg b/sound/vox/birdwell.ogg
similarity index 100%
rename from modular_citadel/sound/vox/birdwell.ogg
rename to sound/vox/birdwell.ogg
diff --git a/modular_citadel/sound/vox/bizwarn.ogg b/sound/vox/bizwarn.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bizwarn.ogg
rename to sound/vox/bizwarn.ogg
diff --git a/modular_citadel/sound/vox/black.ogg b/sound/vox/black.ogg
similarity index 100%
rename from modular_citadel/sound/vox/black.ogg
rename to sound/vox/black.ogg
diff --git a/modular_citadel/sound/vox/blast.ogg b/sound/vox/blast.ogg
similarity index 100%
rename from modular_citadel/sound/vox/blast.ogg
rename to sound/vox/blast.ogg
diff --git a/modular_citadel/sound/vox/blocked.ogg b/sound/vox/blocked.ogg
similarity index 100%
rename from modular_citadel/sound/vox/blocked.ogg
rename to sound/vox/blocked.ogg
diff --git a/modular_citadel/sound/vox/bloop.ogg b/sound/vox/bloop.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bloop.ogg
rename to sound/vox/bloop.ogg
diff --git a/modular_citadel/sound/vox/blue.ogg b/sound/vox/blue.ogg
similarity index 100%
rename from modular_citadel/sound/vox/blue.ogg
rename to sound/vox/blue.ogg
diff --git a/modular_citadel/sound/vox/bottom.ogg b/sound/vox/bottom.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bottom.ogg
rename to sound/vox/bottom.ogg
diff --git a/modular_citadel/sound/vox/bravo.ogg b/sound/vox/bravo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bravo.ogg
rename to sound/vox/bravo.ogg
diff --git a/modular_citadel/sound/vox/breach.ogg b/sound/vox/breach.ogg
similarity index 100%
rename from modular_citadel/sound/vox/breach.ogg
rename to sound/vox/breach.ogg
diff --git a/modular_citadel/sound/vox/breached.ogg b/sound/vox/breached.ogg
similarity index 100%
rename from modular_citadel/sound/vox/breached.ogg
rename to sound/vox/breached.ogg
diff --git a/modular_citadel/sound/vox/break.ogg b/sound/vox/break.ogg
similarity index 100%
rename from modular_citadel/sound/vox/break.ogg
rename to sound/vox/break.ogg
diff --git a/modular_citadel/sound/vox/bridge.ogg b/sound/vox/bridge.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bridge.ogg
rename to sound/vox/bridge.ogg
diff --git a/modular_citadel/sound/vox/bust.ogg b/sound/vox/bust.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bust.ogg
rename to sound/vox/bust.ogg
diff --git a/modular_citadel/sound/vox/but.ogg b/sound/vox/but.ogg
similarity index 100%
rename from modular_citadel/sound/vox/but.ogg
rename to sound/vox/but.ogg
diff --git a/modular_citadel/sound/vox/button.ogg b/sound/vox/button.ogg
similarity index 100%
rename from modular_citadel/sound/vox/button.ogg
rename to sound/vox/button.ogg
diff --git a/modular_citadel/sound/vox/buzwarn.ogg b/sound/vox/buzwarn.ogg
similarity index 100%
rename from modular_citadel/sound/vox/buzwarn.ogg
rename to sound/vox/buzwarn.ogg
diff --git a/modular_citadel/sound/vox/bypass.ogg b/sound/vox/bypass.ogg
similarity index 100%
rename from modular_citadel/sound/vox/bypass.ogg
rename to sound/vox/bypass.ogg
diff --git a/modular_citadel/sound/vox/c.ogg b/sound/vox/c.ogg
similarity index 100%
rename from modular_citadel/sound/vox/c.ogg
rename to sound/vox/c.ogg
diff --git a/modular_citadel/sound/vox/cable.ogg b/sound/vox/cable.ogg
similarity index 100%
rename from modular_citadel/sound/vox/cable.ogg
rename to sound/vox/cable.ogg
diff --git a/modular_citadel/sound/vox/call.ogg b/sound/vox/call.ogg
similarity index 100%
rename from modular_citadel/sound/vox/call.ogg
rename to sound/vox/call.ogg
diff --git a/modular_citadel/sound/vox/called.ogg b/sound/vox/called.ogg
similarity index 100%
rename from modular_citadel/sound/vox/called.ogg
rename to sound/vox/called.ogg
diff --git a/modular_citadel/sound/vox/canal.ogg b/sound/vox/canal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/canal.ogg
rename to sound/vox/canal.ogg
diff --git a/modular_citadel/sound/vox/cap.ogg b/sound/vox/cap.ogg
similarity index 100%
rename from modular_citadel/sound/vox/cap.ogg
rename to sound/vox/cap.ogg
diff --git a/modular_citadel/sound/vox/captain.ogg b/sound/vox/captain.ogg
similarity index 100%
rename from modular_citadel/sound/vox/captain.ogg
rename to sound/vox/captain.ogg
diff --git a/modular_citadel/sound/vox/capture.ogg b/sound/vox/capture.ogg
similarity index 100%
rename from modular_citadel/sound/vox/capture.ogg
rename to sound/vox/capture.ogg
diff --git a/modular_citadel/sound/vox/captured.ogg b/sound/vox/captured.ogg
similarity index 100%
rename from modular_citadel/sound/vox/captured.ogg
rename to sound/vox/captured.ogg
diff --git a/modular_citadel/sound/vox/ceiling.ogg b/sound/vox/ceiling.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ceiling.ogg
rename to sound/vox/ceiling.ogg
diff --git a/modular_citadel/sound/vox/celsius.ogg b/sound/vox/celsius.ogg
similarity index 100%
rename from modular_citadel/sound/vox/celsius.ogg
rename to sound/vox/celsius.ogg
diff --git a/modular_citadel/sound/vox/center.ogg b/sound/vox/center.ogg
similarity index 100%
rename from modular_citadel/sound/vox/center.ogg
rename to sound/vox/center.ogg
diff --git a/modular_citadel/sound/vox/centi.ogg b/sound/vox/centi.ogg
similarity index 100%
rename from modular_citadel/sound/vox/centi.ogg
rename to sound/vox/centi.ogg
diff --git a/modular_citadel/sound/vox/central.ogg b/sound/vox/central.ogg
similarity index 100%
rename from modular_citadel/sound/vox/central.ogg
rename to sound/vox/central.ogg
diff --git a/modular_citadel/sound/vox/chamber.ogg b/sound/vox/chamber.ogg
similarity index 100%
rename from modular_citadel/sound/vox/chamber.ogg
rename to sound/vox/chamber.ogg
diff --git a/modular_citadel/sound/vox/charlie.ogg b/sound/vox/charlie.ogg
similarity index 100%
rename from modular_citadel/sound/vox/charlie.ogg
rename to sound/vox/charlie.ogg
diff --git a/modular_citadel/sound/vox/check.ogg b/sound/vox/check.ogg
similarity index 100%
rename from modular_citadel/sound/vox/check.ogg
rename to sound/vox/check.ogg
diff --git a/modular_citadel/sound/vox/checkpoint.ogg b/sound/vox/checkpoint.ogg
similarity index 100%
rename from modular_citadel/sound/vox/checkpoint.ogg
rename to sound/vox/checkpoint.ogg
diff --git a/modular_citadel/sound/vox/chemical.ogg b/sound/vox/chemical.ogg
similarity index 100%
rename from modular_citadel/sound/vox/chemical.ogg
rename to sound/vox/chemical.ogg
diff --git a/modular_citadel/sound/vox/cleanup.ogg b/sound/vox/cleanup.ogg
similarity index 100%
rename from modular_citadel/sound/vox/cleanup.ogg
rename to sound/vox/cleanup.ogg
diff --git a/modular_citadel/sound/vox/clear.ogg b/sound/vox/clear.ogg
similarity index 100%
rename from modular_citadel/sound/vox/clear.ogg
rename to sound/vox/clear.ogg
diff --git a/modular_citadel/sound/vox/clearance.ogg b/sound/vox/clearance.ogg
similarity index 100%
rename from modular_citadel/sound/vox/clearance.ogg
rename to sound/vox/clearance.ogg
diff --git a/modular_citadel/sound/vox/close.ogg b/sound/vox/close.ogg
similarity index 100%
rename from modular_citadel/sound/vox/close.ogg
rename to sound/vox/close.ogg
diff --git a/modular_citadel/sound/vox/clown.ogg b/sound/vox/clown.ogg
similarity index 100%
rename from modular_citadel/sound/vox/clown.ogg
rename to sound/vox/clown.ogg
diff --git a/modular_citadel/sound/vox/code.ogg b/sound/vox/code.ogg
similarity index 100%
rename from modular_citadel/sound/vox/code.ogg
rename to sound/vox/code.ogg
diff --git a/modular_citadel/sound/vox/coded.ogg b/sound/vox/coded.ogg
similarity index 100%
rename from modular_citadel/sound/vox/coded.ogg
rename to sound/vox/coded.ogg
diff --git a/modular_citadel/sound/vox/collider.ogg b/sound/vox/collider.ogg
similarity index 100%
rename from modular_citadel/sound/vox/collider.ogg
rename to sound/vox/collider.ogg
diff --git a/modular_citadel/sound/vox/comma.ogg b/sound/vox/comma.ogg
similarity index 100%
rename from modular_citadel/sound/vox/comma.ogg
rename to sound/vox/comma.ogg
diff --git a/modular_citadel/sound/vox/command.ogg b/sound/vox/command.ogg
similarity index 100%
rename from modular_citadel/sound/vox/command.ogg
rename to sound/vox/command.ogg
diff --git a/modular_citadel/sound/vox/communication.ogg b/sound/vox/communication.ogg
similarity index 100%
rename from modular_citadel/sound/vox/communication.ogg
rename to sound/vox/communication.ogg
diff --git a/modular_citadel/sound/vox/complex.ogg b/sound/vox/complex.ogg
similarity index 100%
rename from modular_citadel/sound/vox/complex.ogg
rename to sound/vox/complex.ogg
diff --git a/modular_citadel/sound/vox/computer.ogg b/sound/vox/computer.ogg
similarity index 100%
rename from modular_citadel/sound/vox/computer.ogg
rename to sound/vox/computer.ogg
diff --git a/modular_citadel/sound/vox/condition.ogg b/sound/vox/condition.ogg
similarity index 100%
rename from modular_citadel/sound/vox/condition.ogg
rename to sound/vox/condition.ogg
diff --git a/modular_citadel/sound/vox/containment.ogg b/sound/vox/containment.ogg
similarity index 100%
rename from modular_citadel/sound/vox/containment.ogg
rename to sound/vox/containment.ogg
diff --git a/modular_citadel/sound/vox/contamination.ogg b/sound/vox/contamination.ogg
similarity index 100%
rename from modular_citadel/sound/vox/contamination.ogg
rename to sound/vox/contamination.ogg
diff --git a/modular_citadel/sound/vox/control.ogg b/sound/vox/control.ogg
similarity index 100%
rename from modular_citadel/sound/vox/control.ogg
rename to sound/vox/control.ogg
diff --git a/modular_citadel/sound/vox/coolant.ogg b/sound/vox/coolant.ogg
similarity index 100%
rename from modular_citadel/sound/vox/coolant.ogg
rename to sound/vox/coolant.ogg
diff --git a/modular_citadel/sound/vox/coomer.ogg b/sound/vox/coomer.ogg
similarity index 100%
rename from modular_citadel/sound/vox/coomer.ogg
rename to sound/vox/coomer.ogg
diff --git a/modular_citadel/sound/vox/core.ogg b/sound/vox/core.ogg
similarity index 100%
rename from modular_citadel/sound/vox/core.ogg
rename to sound/vox/core.ogg
diff --git a/modular_citadel/sound/vox/correct.ogg b/sound/vox/correct.ogg
similarity index 100%
rename from modular_citadel/sound/vox/correct.ogg
rename to sound/vox/correct.ogg
diff --git a/modular_citadel/sound/vox/corridor.ogg b/sound/vox/corridor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/corridor.ogg
rename to sound/vox/corridor.ogg
diff --git a/modular_citadel/sound/vox/crew.ogg b/sound/vox/crew.ogg
similarity index 100%
rename from modular_citadel/sound/vox/crew.ogg
rename to sound/vox/crew.ogg
diff --git a/modular_citadel/sound/vox/cross.ogg b/sound/vox/cross.ogg
similarity index 100%
rename from modular_citadel/sound/vox/cross.ogg
rename to sound/vox/cross.ogg
diff --git a/modular_citadel/sound/vox/cryogenic.ogg b/sound/vox/cryogenic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/cryogenic.ogg
rename to sound/vox/cryogenic.ogg
diff --git a/modular_citadel/sound/vox/d.ogg b/sound/vox/d.ogg
similarity index 100%
rename from modular_citadel/sound/vox/d.ogg
rename to sound/vox/d.ogg
diff --git a/modular_citadel/sound/vox/dadeda.ogg b/sound/vox/dadeda.ogg
similarity index 100%
rename from modular_citadel/sound/vox/dadeda.ogg
rename to sound/vox/dadeda.ogg
diff --git a/modular_citadel/sound/vox/damage.ogg b/sound/vox/damage.ogg
similarity index 100%
rename from modular_citadel/sound/vox/damage.ogg
rename to sound/vox/damage.ogg
diff --git a/modular_citadel/sound/vox/damaged.ogg b/sound/vox/damaged.ogg
similarity index 100%
rename from modular_citadel/sound/vox/damaged.ogg
rename to sound/vox/damaged.ogg
diff --git a/modular_citadel/sound/vox/danger.ogg b/sound/vox/danger.ogg
similarity index 100%
rename from modular_citadel/sound/vox/danger.ogg
rename to sound/vox/danger.ogg
diff --git a/modular_citadel/sound/vox/day.ogg b/sound/vox/day.ogg
similarity index 100%
rename from modular_citadel/sound/vox/day.ogg
rename to sound/vox/day.ogg
diff --git a/modular_citadel/sound/vox/deactivated.ogg b/sound/vox/deactivated.ogg
similarity index 100%
rename from modular_citadel/sound/vox/deactivated.ogg
rename to sound/vox/deactivated.ogg
diff --git a/modular_citadel/sound/vox/decompression.ogg b/sound/vox/decompression.ogg
similarity index 100%
rename from modular_citadel/sound/vox/decompression.ogg
rename to sound/vox/decompression.ogg
diff --git a/modular_citadel/sound/vox/decontamination.ogg b/sound/vox/decontamination.ogg
similarity index 100%
rename from modular_citadel/sound/vox/decontamination.ogg
rename to sound/vox/decontamination.ogg
diff --git a/modular_citadel/sound/vox/deeoo.ogg b/sound/vox/deeoo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/deeoo.ogg
rename to sound/vox/deeoo.ogg
diff --git a/modular_citadel/sound/vox/defense.ogg b/sound/vox/defense.ogg
similarity index 100%
rename from modular_citadel/sound/vox/defense.ogg
rename to sound/vox/defense.ogg
diff --git a/modular_citadel/sound/vox/degrees.ogg b/sound/vox/degrees.ogg
similarity index 100%
rename from modular_citadel/sound/vox/degrees.ogg
rename to sound/vox/degrees.ogg
diff --git a/modular_citadel/sound/vox/delta.ogg b/sound/vox/delta.ogg
similarity index 100%
rename from modular_citadel/sound/vox/delta.ogg
rename to sound/vox/delta.ogg
diff --git a/modular_citadel/sound/vox/denied.ogg b/sound/vox/denied.ogg
similarity index 100%
rename from modular_citadel/sound/vox/denied.ogg
rename to sound/vox/denied.ogg
diff --git a/modular_citadel/sound/vox/deploy.ogg b/sound/vox/deploy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/deploy.ogg
rename to sound/vox/deploy.ogg
diff --git a/modular_citadel/sound/vox/deployed.ogg b/sound/vox/deployed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/deployed.ogg
rename to sound/vox/deployed.ogg
diff --git a/modular_citadel/sound/vox/destroy.ogg b/sound/vox/destroy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/destroy.ogg
rename to sound/vox/destroy.ogg
diff --git a/modular_citadel/sound/vox/destroyed.ogg b/sound/vox/destroyed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/destroyed.ogg
rename to sound/vox/destroyed.ogg
diff --git a/modular_citadel/sound/vox/detain.ogg b/sound/vox/detain.ogg
similarity index 100%
rename from modular_citadel/sound/vox/detain.ogg
rename to sound/vox/detain.ogg
diff --git a/modular_citadel/sound/vox/detected.ogg b/sound/vox/detected.ogg
similarity index 100%
rename from modular_citadel/sound/vox/detected.ogg
rename to sound/vox/detected.ogg
diff --git a/modular_citadel/sound/vox/detonation.ogg b/sound/vox/detonation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/detonation.ogg
rename to sound/vox/detonation.ogg
diff --git a/modular_citadel/sound/vox/device.ogg b/sound/vox/device.ogg
similarity index 100%
rename from modular_citadel/sound/vox/device.ogg
rename to sound/vox/device.ogg
diff --git a/modular_citadel/sound/vox/did.ogg b/sound/vox/did.ogg
similarity index 100%
rename from modular_citadel/sound/vox/did.ogg
rename to sound/vox/did.ogg
diff --git a/modular_citadel/sound/vox/die.ogg b/sound/vox/die.ogg
similarity index 100%
rename from modular_citadel/sound/vox/die.ogg
rename to sound/vox/die.ogg
diff --git a/modular_citadel/sound/vox/dimensional.ogg b/sound/vox/dimensional.ogg
similarity index 100%
rename from modular_citadel/sound/vox/dimensional.ogg
rename to sound/vox/dimensional.ogg
diff --git a/modular_citadel/sound/vox/dirt.ogg b/sound/vox/dirt.ogg
similarity index 100%
rename from modular_citadel/sound/vox/dirt.ogg
rename to sound/vox/dirt.ogg
diff --git a/modular_citadel/sound/vox/disengaged.ogg b/sound/vox/disengaged.ogg
similarity index 100%
rename from modular_citadel/sound/vox/disengaged.ogg
rename to sound/vox/disengaged.ogg
diff --git a/modular_citadel/sound/vox/dish.ogg b/sound/vox/dish.ogg
similarity index 100%
rename from modular_citadel/sound/vox/dish.ogg
rename to sound/vox/dish.ogg
diff --git a/modular_citadel/sound/vox/disposal.ogg b/sound/vox/disposal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/disposal.ogg
rename to sound/vox/disposal.ogg
diff --git a/modular_citadel/sound/vox/distance.ogg b/sound/vox/distance.ogg
similarity index 100%
rename from modular_citadel/sound/vox/distance.ogg
rename to sound/vox/distance.ogg
diff --git a/modular_citadel/sound/vox/distortion.ogg b/sound/vox/distortion.ogg
similarity index 100%
rename from modular_citadel/sound/vox/distortion.ogg
rename to sound/vox/distortion.ogg
diff --git a/modular_citadel/sound/vox/do.ogg b/sound/vox/do.ogg
similarity index 100%
rename from modular_citadel/sound/vox/do.ogg
rename to sound/vox/do.ogg
diff --git a/modular_citadel/sound/vox/doctor.ogg b/sound/vox/doctor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/doctor.ogg
rename to sound/vox/doctor.ogg
diff --git a/modular_citadel/sound/vox/doop.ogg b/sound/vox/doop.ogg
similarity index 100%
rename from modular_citadel/sound/vox/doop.ogg
rename to sound/vox/doop.ogg
diff --git a/modular_citadel/sound/vox/door.ogg b/sound/vox/door.ogg
similarity index 100%
rename from modular_citadel/sound/vox/door.ogg
rename to sound/vox/door.ogg
diff --git a/modular_citadel/sound/vox/down.ogg b/sound/vox/down.ogg
similarity index 100%
rename from modular_citadel/sound/vox/down.ogg
rename to sound/vox/down.ogg
diff --git a/modular_citadel/sound/vox/dual.ogg b/sound/vox/dual.ogg
similarity index 100%
rename from modular_citadel/sound/vox/dual.ogg
rename to sound/vox/dual.ogg
diff --git a/modular_citadel/sound/vox/duct.ogg b/sound/vox/duct.ogg
similarity index 100%
rename from modular_citadel/sound/vox/duct.ogg
rename to sound/vox/duct.ogg
diff --git a/modular_citadel/sound/vox/e.ogg b/sound/vox/e.ogg
similarity index 100%
rename from modular_citadel/sound/vox/e.ogg
rename to sound/vox/e.ogg
diff --git a/modular_citadel/sound/vox/east.ogg b/sound/vox/east.ogg
similarity index 100%
rename from modular_citadel/sound/vox/east.ogg
rename to sound/vox/east.ogg
diff --git a/modular_citadel/sound/vox/echo.ogg b/sound/vox/echo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/echo.ogg
rename to sound/vox/echo.ogg
diff --git a/modular_citadel/sound/vox/ed.ogg b/sound/vox/ed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ed.ogg
rename to sound/vox/ed.ogg
diff --git a/modular_citadel/sound/vox/effect.ogg b/sound/vox/effect.ogg
similarity index 100%
rename from modular_citadel/sound/vox/effect.ogg
rename to sound/vox/effect.ogg
diff --git a/modular_citadel/sound/vox/egress.ogg b/sound/vox/egress.ogg
similarity index 100%
rename from modular_citadel/sound/vox/egress.ogg
rename to sound/vox/egress.ogg
diff --git a/modular_citadel/sound/vox/eight.ogg b/sound/vox/eight.ogg
similarity index 100%
rename from modular_citadel/sound/vox/eight.ogg
rename to sound/vox/eight.ogg
diff --git a/modular_citadel/sound/vox/eighteen.ogg b/sound/vox/eighteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/eighteen.ogg
rename to sound/vox/eighteen.ogg
diff --git a/modular_citadel/sound/vox/eighty.ogg b/sound/vox/eighty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/eighty.ogg
rename to sound/vox/eighty.ogg
diff --git a/modular_citadel/sound/vox/electric.ogg b/sound/vox/electric.ogg
similarity index 100%
rename from modular_citadel/sound/vox/electric.ogg
rename to sound/vox/electric.ogg
diff --git a/modular_citadel/sound/vox/electromagnetic.ogg b/sound/vox/electromagnetic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/electromagnetic.ogg
rename to sound/vox/electromagnetic.ogg
diff --git a/modular_citadel/sound/vox/elevator.ogg b/sound/vox/elevator.ogg
similarity index 100%
rename from modular_citadel/sound/vox/elevator.ogg
rename to sound/vox/elevator.ogg
diff --git a/modular_citadel/sound/vox/eleven.ogg b/sound/vox/eleven.ogg
similarity index 100%
rename from modular_citadel/sound/vox/eleven.ogg
rename to sound/vox/eleven.ogg
diff --git a/modular_citadel/sound/vox/eliminate.ogg b/sound/vox/eliminate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/eliminate.ogg
rename to sound/vox/eliminate.ogg
diff --git a/modular_citadel/sound/vox/emergency.ogg b/sound/vox/emergency.ogg
similarity index 100%
rename from modular_citadel/sound/vox/emergency.ogg
rename to sound/vox/emergency.ogg
diff --git a/modular_citadel/sound/vox/enemy.ogg b/sound/vox/enemy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/enemy.ogg
rename to sound/vox/enemy.ogg
diff --git a/modular_citadel/sound/vox/energy.ogg b/sound/vox/energy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/energy.ogg
rename to sound/vox/energy.ogg
diff --git a/modular_citadel/sound/vox/engage.ogg b/sound/vox/engage.ogg
similarity index 100%
rename from modular_citadel/sound/vox/engage.ogg
rename to sound/vox/engage.ogg
diff --git a/modular_citadel/sound/vox/engaged.ogg b/sound/vox/engaged.ogg
similarity index 100%
rename from modular_citadel/sound/vox/engaged.ogg
rename to sound/vox/engaged.ogg
diff --git a/modular_citadel/sound/vox/engine.ogg b/sound/vox/engine.ogg
similarity index 100%
rename from modular_citadel/sound/vox/engine.ogg
rename to sound/vox/engine.ogg
diff --git a/modular_citadel/sound/vox/enter.ogg b/sound/vox/enter.ogg
similarity index 100%
rename from modular_citadel/sound/vox/enter.ogg
rename to sound/vox/enter.ogg
diff --git a/modular_citadel/sound/vox/entry.ogg b/sound/vox/entry.ogg
similarity index 100%
rename from modular_citadel/sound/vox/entry.ogg
rename to sound/vox/entry.ogg
diff --git a/modular_citadel/sound/vox/environment.ogg b/sound/vox/environment.ogg
similarity index 100%
rename from modular_citadel/sound/vox/environment.ogg
rename to sound/vox/environment.ogg
diff --git a/modular_citadel/sound/vox/error.ogg b/sound/vox/error.ogg
similarity index 100%
rename from modular_citadel/sound/vox/error.ogg
rename to sound/vox/error.ogg
diff --git a/modular_citadel/sound/vox/escape.ogg b/sound/vox/escape.ogg
similarity index 100%
rename from modular_citadel/sound/vox/escape.ogg
rename to sound/vox/escape.ogg
diff --git a/modular_citadel/sound/vox/evacuate.ogg b/sound/vox/evacuate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/evacuate.ogg
rename to sound/vox/evacuate.ogg
diff --git a/modular_citadel/sound/vox/exchange.ogg b/sound/vox/exchange.ogg
similarity index 100%
rename from modular_citadel/sound/vox/exchange.ogg
rename to sound/vox/exchange.ogg
diff --git a/modular_citadel/sound/vox/exit.ogg b/sound/vox/exit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/exit.ogg
rename to sound/vox/exit.ogg
diff --git a/modular_citadel/sound/vox/expect.ogg b/sound/vox/expect.ogg
similarity index 100%
rename from modular_citadel/sound/vox/expect.ogg
rename to sound/vox/expect.ogg
diff --git a/modular_citadel/sound/vox/experiment.ogg b/sound/vox/experiment.ogg
similarity index 100%
rename from modular_citadel/sound/vox/experiment.ogg
rename to sound/vox/experiment.ogg
diff --git a/modular_citadel/sound/vox/experimental.ogg b/sound/vox/experimental.ogg
similarity index 100%
rename from modular_citadel/sound/vox/experimental.ogg
rename to sound/vox/experimental.ogg
diff --git a/modular_citadel/sound/vox/explode.ogg b/sound/vox/explode.ogg
similarity index 100%
rename from modular_citadel/sound/vox/explode.ogg
rename to sound/vox/explode.ogg
diff --git a/modular_citadel/sound/vox/explosion.ogg b/sound/vox/explosion.ogg
similarity index 100%
rename from modular_citadel/sound/vox/explosion.ogg
rename to sound/vox/explosion.ogg
diff --git a/modular_citadel/sound/vox/exposure.ogg b/sound/vox/exposure.ogg
similarity index 100%
rename from modular_citadel/sound/vox/exposure.ogg
rename to sound/vox/exposure.ogg
diff --git a/modular_citadel/sound/vox/exterminate.ogg b/sound/vox/exterminate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/exterminate.ogg
rename to sound/vox/exterminate.ogg
diff --git a/modular_citadel/sound/vox/extinguish.ogg b/sound/vox/extinguish.ogg
similarity index 100%
rename from modular_citadel/sound/vox/extinguish.ogg
rename to sound/vox/extinguish.ogg
diff --git a/modular_citadel/sound/vox/extinguisher.ogg b/sound/vox/extinguisher.ogg
similarity index 100%
rename from modular_citadel/sound/vox/extinguisher.ogg
rename to sound/vox/extinguisher.ogg
diff --git a/modular_citadel/sound/vox/extreme.ogg b/sound/vox/extreme.ogg
similarity index 100%
rename from modular_citadel/sound/vox/extreme.ogg
rename to sound/vox/extreme.ogg
diff --git a/modular_citadel/sound/vox/f.ogg b/sound/vox/f.ogg
similarity index 100%
rename from modular_citadel/sound/vox/f.ogg
rename to sound/vox/f.ogg
diff --git a/modular_citadel/sound/vox/face.ogg b/sound/vox/face.ogg
similarity index 100%
rename from modular_citadel/sound/vox/face.ogg
rename to sound/vox/face.ogg
diff --git a/modular_citadel/sound/vox/facility.ogg b/sound/vox/facility.ogg
similarity index 100%
rename from modular_citadel/sound/vox/facility.ogg
rename to sound/vox/facility.ogg
diff --git a/modular_citadel/sound/vox/fahrenheit.ogg b/sound/vox/fahrenheit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fahrenheit.ogg
rename to sound/vox/fahrenheit.ogg
diff --git a/modular_citadel/sound/vox/failed.ogg b/sound/vox/failed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/failed.ogg
rename to sound/vox/failed.ogg
diff --git a/modular_citadel/sound/vox/failure.ogg b/sound/vox/failure.ogg
similarity index 100%
rename from modular_citadel/sound/vox/failure.ogg
rename to sound/vox/failure.ogg
diff --git a/modular_citadel/sound/vox/farthest.ogg b/sound/vox/farthest.ogg
similarity index 100%
rename from modular_citadel/sound/vox/farthest.ogg
rename to sound/vox/farthest.ogg
diff --git a/modular_citadel/sound/vox/fast.ogg b/sound/vox/fast.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fast.ogg
rename to sound/vox/fast.ogg
diff --git a/modular_citadel/sound/vox/feet.ogg b/sound/vox/feet.ogg
similarity index 100%
rename from modular_citadel/sound/vox/feet.ogg
rename to sound/vox/feet.ogg
diff --git a/modular_citadel/sound/vox/field.ogg b/sound/vox/field.ogg
similarity index 100%
rename from modular_citadel/sound/vox/field.ogg
rename to sound/vox/field.ogg
diff --git a/modular_citadel/sound/vox/fifteen.ogg b/sound/vox/fifteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fifteen.ogg
rename to sound/vox/fifteen.ogg
diff --git a/modular_citadel/sound/vox/fifth.ogg b/sound/vox/fifth.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fifth.ogg
rename to sound/vox/fifth.ogg
diff --git a/modular_citadel/sound/vox/fifty.ogg b/sound/vox/fifty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fifty.ogg
rename to sound/vox/fifty.ogg
diff --git a/modular_citadel/sound/vox/final.ogg b/sound/vox/final.ogg
similarity index 100%
rename from modular_citadel/sound/vox/final.ogg
rename to sound/vox/final.ogg
diff --git a/modular_citadel/sound/vox/fine.ogg b/sound/vox/fine.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fine.ogg
rename to sound/vox/fine.ogg
diff --git a/modular_citadel/sound/vox/fire.ogg b/sound/vox/fire.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fire.ogg
rename to sound/vox/fire.ogg
diff --git a/modular_citadel/sound/vox/first.ogg b/sound/vox/first.ogg
similarity index 100%
rename from modular_citadel/sound/vox/first.ogg
rename to sound/vox/first.ogg
diff --git a/modular_citadel/sound/vox/five.ogg b/sound/vox/five.ogg
similarity index 100%
rename from modular_citadel/sound/vox/five.ogg
rename to sound/vox/five.ogg
diff --git a/modular_citadel/sound/vox/flag.ogg b/sound/vox/flag.ogg
similarity index 100%
rename from modular_citadel/sound/vox/flag.ogg
rename to sound/vox/flag.ogg
diff --git a/modular_citadel/sound/vox/flooding.ogg b/sound/vox/flooding.ogg
similarity index 100%
rename from modular_citadel/sound/vox/flooding.ogg
rename to sound/vox/flooding.ogg
diff --git a/modular_citadel/sound/vox/floor.ogg b/sound/vox/floor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/floor.ogg
rename to sound/vox/floor.ogg
diff --git a/modular_citadel/sound/vox/fool.ogg b/sound/vox/fool.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fool.ogg
rename to sound/vox/fool.ogg
diff --git a/modular_citadel/sound/vox/for.ogg b/sound/vox/for.ogg
similarity index 100%
rename from modular_citadel/sound/vox/for.ogg
rename to sound/vox/for.ogg
diff --git a/modular_citadel/sound/vox/forbidden.ogg b/sound/vox/forbidden.ogg
similarity index 100%
rename from modular_citadel/sound/vox/forbidden.ogg
rename to sound/vox/forbidden.ogg
diff --git a/modular_citadel/sound/vox/force.ogg b/sound/vox/force.ogg
similarity index 100%
rename from modular_citadel/sound/vox/force.ogg
rename to sound/vox/force.ogg
diff --git a/modular_citadel/sound/vox/forms.ogg b/sound/vox/forms.ogg
similarity index 100%
rename from modular_citadel/sound/vox/forms.ogg
rename to sound/vox/forms.ogg
diff --git a/modular_citadel/sound/vox/found.ogg b/sound/vox/found.ogg
similarity index 100%
rename from modular_citadel/sound/vox/found.ogg
rename to sound/vox/found.ogg
diff --git a/modular_citadel/sound/vox/four.ogg b/sound/vox/four.ogg
similarity index 100%
rename from modular_citadel/sound/vox/four.ogg
rename to sound/vox/four.ogg
diff --git a/modular_citadel/sound/vox/fourteen.ogg b/sound/vox/fourteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fourteen.ogg
rename to sound/vox/fourteen.ogg
diff --git a/modular_citadel/sound/vox/fourth.ogg b/sound/vox/fourth.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fourth.ogg
rename to sound/vox/fourth.ogg
diff --git a/modular_citadel/sound/vox/fourty.ogg b/sound/vox/fourty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fourty.ogg
rename to sound/vox/fourty.ogg
diff --git a/modular_citadel/sound/vox/foxtrot.ogg b/sound/vox/foxtrot.ogg
similarity index 100%
rename from modular_citadel/sound/vox/foxtrot.ogg
rename to sound/vox/foxtrot.ogg
diff --git a/modular_citadel/sound/vox/freeman.ogg b/sound/vox/freeman.ogg
similarity index 100%
rename from modular_citadel/sound/vox/freeman.ogg
rename to sound/vox/freeman.ogg
diff --git a/modular_citadel/sound/vox/freezer.ogg b/sound/vox/freezer.ogg
similarity index 100%
rename from modular_citadel/sound/vox/freezer.ogg
rename to sound/vox/freezer.ogg
diff --git a/modular_citadel/sound/vox/from.ogg b/sound/vox/from.ogg
similarity index 100%
rename from modular_citadel/sound/vox/from.ogg
rename to sound/vox/from.ogg
diff --git a/modular_citadel/sound/vox/front.ogg b/sound/vox/front.ogg
similarity index 100%
rename from modular_citadel/sound/vox/front.ogg
rename to sound/vox/front.ogg
diff --git a/modular_citadel/sound/vox/fuel.ogg b/sound/vox/fuel.ogg
similarity index 100%
rename from modular_citadel/sound/vox/fuel.ogg
rename to sound/vox/fuel.ogg
diff --git a/modular_citadel/sound/vox/g.ogg b/sound/vox/g.ogg
similarity index 100%
rename from modular_citadel/sound/vox/g.ogg
rename to sound/vox/g.ogg
diff --git a/modular_citadel/sound/vox/gay.ogg b/sound/vox/gay.ogg
similarity index 100%
rename from modular_citadel/sound/vox/gay.ogg
rename to sound/vox/gay.ogg
diff --git a/modular_citadel/sound/vox/get.ogg b/sound/vox/get.ogg
similarity index 100%
rename from modular_citadel/sound/vox/get.ogg
rename to sound/vox/get.ogg
diff --git a/modular_citadel/sound/vox/go.ogg b/sound/vox/go.ogg
similarity index 100%
rename from modular_citadel/sound/vox/go.ogg
rename to sound/vox/go.ogg
diff --git a/modular_citadel/sound/vox/going.ogg b/sound/vox/going.ogg
similarity index 100%
rename from modular_citadel/sound/vox/going.ogg
rename to sound/vox/going.ogg
diff --git a/modular_citadel/sound/vox/good.ogg b/sound/vox/good.ogg
similarity index 100%
rename from modular_citadel/sound/vox/good.ogg
rename to sound/vox/good.ogg
diff --git a/modular_citadel/sound/vox/goodbye.ogg b/sound/vox/goodbye.ogg
similarity index 100%
rename from modular_citadel/sound/vox/goodbye.ogg
rename to sound/vox/goodbye.ogg
diff --git a/modular_citadel/sound/vox/gordon.ogg b/sound/vox/gordon.ogg
similarity index 100%
rename from modular_citadel/sound/vox/gordon.ogg
rename to sound/vox/gordon.ogg
diff --git a/modular_citadel/sound/vox/got.ogg b/sound/vox/got.ogg
similarity index 100%
rename from modular_citadel/sound/vox/got.ogg
rename to sound/vox/got.ogg
diff --git a/modular_citadel/sound/vox/government.ogg b/sound/vox/government.ogg
similarity index 100%
rename from modular_citadel/sound/vox/government.ogg
rename to sound/vox/government.ogg
diff --git a/modular_citadel/sound/vox/granted.ogg b/sound/vox/granted.ogg
similarity index 100%
rename from modular_citadel/sound/vox/granted.ogg
rename to sound/vox/granted.ogg
diff --git a/modular_citadel/sound/vox/great.ogg b/sound/vox/great.ogg
similarity index 100%
rename from modular_citadel/sound/vox/great.ogg
rename to sound/vox/great.ogg
diff --git a/modular_citadel/sound/vox/green.ogg b/sound/vox/green.ogg
similarity index 100%
rename from modular_citadel/sound/vox/green.ogg
rename to sound/vox/green.ogg
diff --git a/modular_citadel/sound/vox/grenade.ogg b/sound/vox/grenade.ogg
similarity index 100%
rename from modular_citadel/sound/vox/grenade.ogg
rename to sound/vox/grenade.ogg
diff --git a/modular_citadel/sound/vox/guard.ogg b/sound/vox/guard.ogg
similarity index 100%
rename from modular_citadel/sound/vox/guard.ogg
rename to sound/vox/guard.ogg
diff --git a/modular_citadel/sound/vox/gulf.ogg b/sound/vox/gulf.ogg
similarity index 100%
rename from modular_citadel/sound/vox/gulf.ogg
rename to sound/vox/gulf.ogg
diff --git a/modular_citadel/sound/vox/gun.ogg b/sound/vox/gun.ogg
similarity index 100%
rename from modular_citadel/sound/vox/gun.ogg
rename to sound/vox/gun.ogg
diff --git a/modular_citadel/sound/vox/guthrie.ogg b/sound/vox/guthrie.ogg
similarity index 100%
rename from modular_citadel/sound/vox/guthrie.ogg
rename to sound/vox/guthrie.ogg
diff --git a/modular_citadel/sound/vox/handling.ogg b/sound/vox/handling.ogg
similarity index 100%
rename from modular_citadel/sound/vox/handling.ogg
rename to sound/vox/handling.ogg
diff --git a/modular_citadel/sound/vox/hangar.ogg b/sound/vox/hangar.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hangar.ogg
rename to sound/vox/hangar.ogg
diff --git a/modular_citadel/sound/vox/has.ogg b/sound/vox/has.ogg
similarity index 100%
rename from modular_citadel/sound/vox/has.ogg
rename to sound/vox/has.ogg
diff --git a/modular_citadel/sound/vox/have.ogg b/sound/vox/have.ogg
similarity index 100%
rename from modular_citadel/sound/vox/have.ogg
rename to sound/vox/have.ogg
diff --git a/modular_citadel/sound/vox/hazard.ogg b/sound/vox/hazard.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hazard.ogg
rename to sound/vox/hazard.ogg
diff --git a/modular_citadel/sound/vox/head.ogg b/sound/vox/head.ogg
similarity index 100%
rename from modular_citadel/sound/vox/head.ogg
rename to sound/vox/head.ogg
diff --git a/modular_citadel/sound/vox/health.ogg b/sound/vox/health.ogg
similarity index 100%
rename from modular_citadel/sound/vox/health.ogg
rename to sound/vox/health.ogg
diff --git a/modular_citadel/sound/vox/heat.ogg b/sound/vox/heat.ogg
similarity index 100%
rename from modular_citadel/sound/vox/heat.ogg
rename to sound/vox/heat.ogg
diff --git a/modular_citadel/sound/vox/helicopter.ogg b/sound/vox/helicopter.ogg
similarity index 100%
rename from modular_citadel/sound/vox/helicopter.ogg
rename to sound/vox/helicopter.ogg
diff --git a/modular_citadel/sound/vox/helium.ogg b/sound/vox/helium.ogg
similarity index 100%
rename from modular_citadel/sound/vox/helium.ogg
rename to sound/vox/helium.ogg
diff --git a/modular_citadel/sound/vox/hello.ogg b/sound/vox/hello.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hello.ogg
rename to sound/vox/hello.ogg
diff --git a/modular_citadel/sound/vox/help.ogg b/sound/vox/help.ogg
similarity index 100%
rename from modular_citadel/sound/vox/help.ogg
rename to sound/vox/help.ogg
diff --git a/modular_citadel/sound/vox/here.ogg b/sound/vox/here.ogg
similarity index 100%
rename from modular_citadel/sound/vox/here.ogg
rename to sound/vox/here.ogg
diff --git a/modular_citadel/sound/vox/hide.ogg b/sound/vox/hide.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hide.ogg
rename to sound/vox/hide.ogg
diff --git a/modular_citadel/sound/vox/high.ogg b/sound/vox/high.ogg
similarity index 100%
rename from modular_citadel/sound/vox/high.ogg
rename to sound/vox/high.ogg
diff --git a/modular_citadel/sound/vox/highest.ogg b/sound/vox/highest.ogg
similarity index 100%
rename from modular_citadel/sound/vox/highest.ogg
rename to sound/vox/highest.ogg
diff --git a/modular_citadel/sound/vox/hit.ogg b/sound/vox/hit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hit.ogg
rename to sound/vox/hit.ogg
diff --git a/modular_citadel/sound/vox/holds.ogg b/sound/vox/holds.ogg
similarity index 100%
rename from modular_citadel/sound/vox/holds.ogg
rename to sound/vox/holds.ogg
diff --git a/modular_citadel/sound/vox/hole.ogg b/sound/vox/hole.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hole.ogg
rename to sound/vox/hole.ogg
diff --git a/modular_citadel/sound/vox/hostile.ogg b/sound/vox/hostile.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hostile.ogg
rename to sound/vox/hostile.ogg
diff --git a/modular_citadel/sound/vox/hot.ogg b/sound/vox/hot.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hot.ogg
rename to sound/vox/hot.ogg
diff --git a/modular_citadel/sound/vox/hotel.ogg b/sound/vox/hotel.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hotel.ogg
rename to sound/vox/hotel.ogg
diff --git a/modular_citadel/sound/vox/hour.ogg b/sound/vox/hour.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hour.ogg
rename to sound/vox/hour.ogg
diff --git a/modular_citadel/sound/vox/hours.ogg b/sound/vox/hours.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hours.ogg
rename to sound/vox/hours.ogg
diff --git a/modular_citadel/sound/vox/hundred.ogg b/sound/vox/hundred.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hundred.ogg
rename to sound/vox/hundred.ogg
diff --git a/modular_citadel/sound/vox/hydro.ogg b/sound/vox/hydro.ogg
similarity index 100%
rename from modular_citadel/sound/vox/hydro.ogg
rename to sound/vox/hydro.ogg
diff --git a/modular_citadel/sound/vox/i.ogg b/sound/vox/i.ogg
similarity index 100%
rename from modular_citadel/sound/vox/i.ogg
rename to sound/vox/i.ogg
diff --git a/modular_citadel/sound/vox/idiot.ogg b/sound/vox/idiot.ogg
similarity index 100%
rename from modular_citadel/sound/vox/idiot.ogg
rename to sound/vox/idiot.ogg
diff --git a/modular_citadel/sound/vox/illegal.ogg b/sound/vox/illegal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/illegal.ogg
rename to sound/vox/illegal.ogg
diff --git a/modular_citadel/sound/vox/immediate.ogg b/sound/vox/immediate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/immediate.ogg
rename to sound/vox/immediate.ogg
diff --git a/modular_citadel/sound/vox/immediately.ogg b/sound/vox/immediately.ogg
similarity index 100%
rename from modular_citadel/sound/vox/immediately.ogg
rename to sound/vox/immediately.ogg
diff --git a/modular_citadel/sound/vox/in.ogg b/sound/vox/in.ogg
similarity index 100%
rename from modular_citadel/sound/vox/in.ogg
rename to sound/vox/in.ogg
diff --git a/modular_citadel/sound/vox/inches.ogg b/sound/vox/inches.ogg
similarity index 100%
rename from modular_citadel/sound/vox/inches.ogg
rename to sound/vox/inches.ogg
diff --git a/modular_citadel/sound/vox/india.ogg b/sound/vox/india.ogg
similarity index 100%
rename from modular_citadel/sound/vox/india.ogg
rename to sound/vox/india.ogg
diff --git a/modular_citadel/sound/vox/ing.ogg b/sound/vox/ing.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ing.ogg
rename to sound/vox/ing.ogg
diff --git a/modular_citadel/sound/vox/inoperative.ogg b/sound/vox/inoperative.ogg
similarity index 100%
rename from modular_citadel/sound/vox/inoperative.ogg
rename to sound/vox/inoperative.ogg
diff --git a/modular_citadel/sound/vox/inside.ogg b/sound/vox/inside.ogg
similarity index 100%
rename from modular_citadel/sound/vox/inside.ogg
rename to sound/vox/inside.ogg
diff --git a/modular_citadel/sound/vox/inspection.ogg b/sound/vox/inspection.ogg
similarity index 100%
rename from modular_citadel/sound/vox/inspection.ogg
rename to sound/vox/inspection.ogg
diff --git a/modular_citadel/sound/vox/inspector.ogg b/sound/vox/inspector.ogg
similarity index 100%
rename from modular_citadel/sound/vox/inspector.ogg
rename to sound/vox/inspector.ogg
diff --git a/modular_citadel/sound/vox/interchange.ogg b/sound/vox/interchange.ogg
similarity index 100%
rename from modular_citadel/sound/vox/interchange.ogg
rename to sound/vox/interchange.ogg
diff --git a/modular_citadel/sound/vox/intruder.ogg b/sound/vox/intruder.ogg
similarity index 100%
rename from modular_citadel/sound/vox/intruder.ogg
rename to sound/vox/intruder.ogg
diff --git a/modular_citadel/sound/vox/invallid.ogg b/sound/vox/invallid.ogg
similarity index 100%
rename from modular_citadel/sound/vox/invallid.ogg
rename to sound/vox/invallid.ogg
diff --git a/modular_citadel/sound/vox/invasion.ogg b/sound/vox/invasion.ogg
similarity index 100%
rename from modular_citadel/sound/vox/invasion.ogg
rename to sound/vox/invasion.ogg
diff --git a/modular_citadel/sound/vox/is.ogg b/sound/vox/is.ogg
similarity index 100%
rename from modular_citadel/sound/vox/is.ogg
rename to sound/vox/is.ogg
diff --git a/modular_citadel/sound/vox/it.ogg b/sound/vox/it.ogg
similarity index 100%
rename from modular_citadel/sound/vox/it.ogg
rename to sound/vox/it.ogg
diff --git a/modular_citadel/sound/vox/johnson.ogg b/sound/vox/johnson.ogg
similarity index 100%
rename from modular_citadel/sound/vox/johnson.ogg
rename to sound/vox/johnson.ogg
diff --git a/modular_citadel/sound/vox/juliet.ogg b/sound/vox/juliet.ogg
similarity index 100%
rename from modular_citadel/sound/vox/juliet.ogg
rename to sound/vox/juliet.ogg
diff --git a/modular_citadel/sound/vox/key.ogg b/sound/vox/key.ogg
similarity index 100%
rename from modular_citadel/sound/vox/key.ogg
rename to sound/vox/key.ogg
diff --git a/modular_citadel/sound/vox/kill.ogg b/sound/vox/kill.ogg
similarity index 100%
rename from modular_citadel/sound/vox/kill.ogg
rename to sound/vox/kill.ogg
diff --git a/modular_citadel/sound/vox/kilo.ogg b/sound/vox/kilo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/kilo.ogg
rename to sound/vox/kilo.ogg
diff --git a/modular_citadel/sound/vox/kit.ogg b/sound/vox/kit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/kit.ogg
rename to sound/vox/kit.ogg
diff --git a/modular_citadel/sound/vox/lab.ogg b/sound/vox/lab.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lab.ogg
rename to sound/vox/lab.ogg
diff --git a/modular_citadel/sound/vox/lambda.ogg b/sound/vox/lambda.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lambda.ogg
rename to sound/vox/lambda.ogg
diff --git a/modular_citadel/sound/vox/laser.ogg b/sound/vox/laser.ogg
similarity index 100%
rename from modular_citadel/sound/vox/laser.ogg
rename to sound/vox/laser.ogg
diff --git a/modular_citadel/sound/vox/last.ogg b/sound/vox/last.ogg
similarity index 100%
rename from modular_citadel/sound/vox/last.ogg
rename to sound/vox/last.ogg
diff --git a/modular_citadel/sound/vox/launch.ogg b/sound/vox/launch.ogg
similarity index 100%
rename from modular_citadel/sound/vox/launch.ogg
rename to sound/vox/launch.ogg
diff --git a/modular_citadel/sound/vox/leak.ogg b/sound/vox/leak.ogg
similarity index 100%
rename from modular_citadel/sound/vox/leak.ogg
rename to sound/vox/leak.ogg
diff --git a/modular_citadel/sound/vox/leave.ogg b/sound/vox/leave.ogg
similarity index 100%
rename from modular_citadel/sound/vox/leave.ogg
rename to sound/vox/leave.ogg
diff --git a/modular_citadel/sound/vox/left.ogg b/sound/vox/left.ogg
similarity index 100%
rename from modular_citadel/sound/vox/left.ogg
rename to sound/vox/left.ogg
diff --git a/modular_citadel/sound/vox/legal.ogg b/sound/vox/legal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/legal.ogg
rename to sound/vox/legal.ogg
diff --git a/modular_citadel/sound/vox/level.ogg b/sound/vox/level.ogg
similarity index 100%
rename from modular_citadel/sound/vox/level.ogg
rename to sound/vox/level.ogg
diff --git a/modular_citadel/sound/vox/lever.ogg b/sound/vox/lever.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lever.ogg
rename to sound/vox/lever.ogg
diff --git a/modular_citadel/sound/vox/lie.ogg b/sound/vox/lie.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lie.ogg
rename to sound/vox/lie.ogg
diff --git a/modular_citadel/sound/vox/lieutenant.ogg b/sound/vox/lieutenant.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lieutenant.ogg
rename to sound/vox/lieutenant.ogg
diff --git a/modular_citadel/sound/vox/life.ogg b/sound/vox/life.ogg
similarity index 100%
rename from modular_citadel/sound/vox/life.ogg
rename to sound/vox/life.ogg
diff --git a/modular_citadel/sound/vox/light.ogg b/sound/vox/light.ogg
similarity index 100%
rename from modular_citadel/sound/vox/light.ogg
rename to sound/vox/light.ogg
diff --git a/modular_citadel/sound/vox/lima.ogg b/sound/vox/lima.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lima.ogg
rename to sound/vox/lima.ogg
diff --git a/modular_citadel/sound/vox/liquid.ogg b/sound/vox/liquid.ogg
similarity index 100%
rename from modular_citadel/sound/vox/liquid.ogg
rename to sound/vox/liquid.ogg
diff --git a/modular_citadel/sound/vox/loading.ogg b/sound/vox/loading.ogg
similarity index 100%
rename from modular_citadel/sound/vox/loading.ogg
rename to sound/vox/loading.ogg
diff --git a/modular_citadel/sound/vox/locate.ogg b/sound/vox/locate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/locate.ogg
rename to sound/vox/locate.ogg
diff --git a/modular_citadel/sound/vox/located.ogg b/sound/vox/located.ogg
similarity index 100%
rename from modular_citadel/sound/vox/located.ogg
rename to sound/vox/located.ogg
diff --git a/modular_citadel/sound/vox/location.ogg b/sound/vox/location.ogg
similarity index 100%
rename from modular_citadel/sound/vox/location.ogg
rename to sound/vox/location.ogg
diff --git a/modular_citadel/sound/vox/lock.ogg b/sound/vox/lock.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lock.ogg
rename to sound/vox/lock.ogg
diff --git a/modular_citadel/sound/vox/locked.ogg b/sound/vox/locked.ogg
similarity index 100%
rename from modular_citadel/sound/vox/locked.ogg
rename to sound/vox/locked.ogg
diff --git a/modular_citadel/sound/vox/locker.ogg b/sound/vox/locker.ogg
similarity index 100%
rename from modular_citadel/sound/vox/locker.ogg
rename to sound/vox/locker.ogg
diff --git a/modular_citadel/sound/vox/lockout.ogg b/sound/vox/lockout.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lockout.ogg
rename to sound/vox/lockout.ogg
diff --git a/modular_citadel/sound/vox/lower.ogg b/sound/vox/lower.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lower.ogg
rename to sound/vox/lower.ogg
diff --git a/modular_citadel/sound/vox/lowest.ogg b/sound/vox/lowest.ogg
similarity index 100%
rename from modular_citadel/sound/vox/lowest.ogg
rename to sound/vox/lowest.ogg
diff --git a/modular_citadel/sound/vox/magnetic.ogg b/sound/vox/magnetic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/magnetic.ogg
rename to sound/vox/magnetic.ogg
diff --git a/modular_citadel/sound/vox/main.ogg b/sound/vox/main.ogg
similarity index 100%
rename from modular_citadel/sound/vox/main.ogg
rename to sound/vox/main.ogg
diff --git a/modular_citadel/sound/vox/maintenance.ogg b/sound/vox/maintenance.ogg
similarity index 100%
rename from modular_citadel/sound/vox/maintenance.ogg
rename to sound/vox/maintenance.ogg
diff --git a/modular_citadel/sound/vox/malfunction.ogg b/sound/vox/malfunction.ogg
similarity index 100%
rename from modular_citadel/sound/vox/malfunction.ogg
rename to sound/vox/malfunction.ogg
diff --git a/modular_citadel/sound/vox/man.ogg b/sound/vox/man.ogg
similarity index 100%
rename from modular_citadel/sound/vox/man.ogg
rename to sound/vox/man.ogg
diff --git a/modular_citadel/sound/vox/mass.ogg b/sound/vox/mass.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mass.ogg
rename to sound/vox/mass.ogg
diff --git a/modular_citadel/sound/vox/materials.ogg b/sound/vox/materials.ogg
similarity index 100%
rename from modular_citadel/sound/vox/materials.ogg
rename to sound/vox/materials.ogg
diff --git a/modular_citadel/sound/vox/maximum.ogg b/sound/vox/maximum.ogg
similarity index 100%
rename from modular_citadel/sound/vox/maximum.ogg
rename to sound/vox/maximum.ogg
diff --git a/modular_citadel/sound/vox/may.ogg b/sound/vox/may.ogg
similarity index 100%
rename from modular_citadel/sound/vox/may.ogg
rename to sound/vox/may.ogg
diff --git a/modular_citadel/sound/vox/med.ogg b/sound/vox/med.ogg
similarity index 100%
rename from modular_citadel/sound/vox/med.ogg
rename to sound/vox/med.ogg
diff --git a/modular_citadel/sound/vox/medical.ogg b/sound/vox/medical.ogg
similarity index 100%
rename from modular_citadel/sound/vox/medical.ogg
rename to sound/vox/medical.ogg
diff --git a/modular_citadel/sound/vox/men.ogg b/sound/vox/men.ogg
similarity index 100%
rename from modular_citadel/sound/vox/men.ogg
rename to sound/vox/men.ogg
diff --git a/modular_citadel/sound/vox/mercy.ogg b/sound/vox/mercy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mercy.ogg
rename to sound/vox/mercy.ogg
diff --git a/modular_citadel/sound/vox/mesa.ogg b/sound/vox/mesa.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mesa.ogg
rename to sound/vox/mesa.ogg
diff --git a/modular_citadel/sound/vox/message.ogg b/sound/vox/message.ogg
similarity index 100%
rename from modular_citadel/sound/vox/message.ogg
rename to sound/vox/message.ogg
diff --git a/modular_citadel/sound/vox/meter.ogg b/sound/vox/meter.ogg
similarity index 100%
rename from modular_citadel/sound/vox/meter.ogg
rename to sound/vox/meter.ogg
diff --git a/modular_citadel/sound/vox/micro.ogg b/sound/vox/micro.ogg
similarity index 100%
rename from modular_citadel/sound/vox/micro.ogg
rename to sound/vox/micro.ogg
diff --git a/modular_citadel/sound/vox/middle.ogg b/sound/vox/middle.ogg
similarity index 100%
rename from modular_citadel/sound/vox/middle.ogg
rename to sound/vox/middle.ogg
diff --git a/modular_citadel/sound/vox/mike.ogg b/sound/vox/mike.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mike.ogg
rename to sound/vox/mike.ogg
diff --git a/modular_citadel/sound/vox/miles.ogg b/sound/vox/miles.ogg
similarity index 100%
rename from modular_citadel/sound/vox/miles.ogg
rename to sound/vox/miles.ogg
diff --git a/modular_citadel/sound/vox/military.ogg b/sound/vox/military.ogg
similarity index 100%
rename from modular_citadel/sound/vox/military.ogg
rename to sound/vox/military.ogg
diff --git a/modular_citadel/sound/vox/milli.ogg b/sound/vox/milli.ogg
similarity index 100%
rename from modular_citadel/sound/vox/milli.ogg
rename to sound/vox/milli.ogg
diff --git a/modular_citadel/sound/vox/million.ogg b/sound/vox/million.ogg
similarity index 100%
rename from modular_citadel/sound/vox/million.ogg
rename to sound/vox/million.ogg
diff --git a/modular_citadel/sound/vox/minefield.ogg b/sound/vox/minefield.ogg
similarity index 100%
rename from modular_citadel/sound/vox/minefield.ogg
rename to sound/vox/minefield.ogg
diff --git a/modular_citadel/sound/vox/minimum.ogg b/sound/vox/minimum.ogg
similarity index 100%
rename from modular_citadel/sound/vox/minimum.ogg
rename to sound/vox/minimum.ogg
diff --git a/modular_citadel/sound/vox/minutes.ogg b/sound/vox/minutes.ogg
similarity index 100%
rename from modular_citadel/sound/vox/minutes.ogg
rename to sound/vox/minutes.ogg
diff --git a/modular_citadel/sound/vox/mister.ogg b/sound/vox/mister.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mister.ogg
rename to sound/vox/mister.ogg
diff --git a/modular_citadel/sound/vox/mode.ogg b/sound/vox/mode.ogg
similarity index 100%
rename from modular_citadel/sound/vox/mode.ogg
rename to sound/vox/mode.ogg
diff --git a/modular_citadel/sound/vox/motor.ogg b/sound/vox/motor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/motor.ogg
rename to sound/vox/motor.ogg
diff --git a/modular_citadel/sound/vox/motorpool.ogg b/sound/vox/motorpool.ogg
similarity index 100%
rename from modular_citadel/sound/vox/motorpool.ogg
rename to sound/vox/motorpool.ogg
diff --git a/modular_citadel/sound/vox/move.ogg b/sound/vox/move.ogg
similarity index 100%
rename from modular_citadel/sound/vox/move.ogg
rename to sound/vox/move.ogg
diff --git a/modular_citadel/sound/vox/must.ogg b/sound/vox/must.ogg
similarity index 100%
rename from modular_citadel/sound/vox/must.ogg
rename to sound/vox/must.ogg
diff --git a/modular_citadel/sound/vox/nearest.ogg b/sound/vox/nearest.ogg
similarity index 100%
rename from modular_citadel/sound/vox/nearest.ogg
rename to sound/vox/nearest.ogg
diff --git a/modular_citadel/sound/vox/nice.ogg b/sound/vox/nice.ogg
similarity index 100%
rename from modular_citadel/sound/vox/nice.ogg
rename to sound/vox/nice.ogg
diff --git a/modular_citadel/sound/vox/nine.ogg b/sound/vox/nine.ogg
similarity index 100%
rename from modular_citadel/sound/vox/nine.ogg
rename to sound/vox/nine.ogg
diff --git a/modular_citadel/sound/vox/nineteen.ogg b/sound/vox/nineteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/nineteen.ogg
rename to sound/vox/nineteen.ogg
diff --git a/modular_citadel/sound/vox/ninety.ogg b/sound/vox/ninety.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ninety.ogg
rename to sound/vox/ninety.ogg
diff --git a/modular_citadel/sound/vox/no.ogg b/sound/vox/no.ogg
similarity index 100%
rename from modular_citadel/sound/vox/no.ogg
rename to sound/vox/no.ogg
diff --git a/modular_citadel/sound/vox/nominal.ogg b/sound/vox/nominal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/nominal.ogg
rename to sound/vox/nominal.ogg
diff --git a/modular_citadel/sound/vox/north.ogg b/sound/vox/north.ogg
similarity index 100%
rename from modular_citadel/sound/vox/north.ogg
rename to sound/vox/north.ogg
diff --git a/modular_citadel/sound/vox/not.ogg b/sound/vox/not.ogg
similarity index 100%
rename from modular_citadel/sound/vox/not.ogg
rename to sound/vox/not.ogg
diff --git a/modular_citadel/sound/vox/november.ogg b/sound/vox/november.ogg
similarity index 100%
rename from modular_citadel/sound/vox/november.ogg
rename to sound/vox/november.ogg
diff --git a/modular_citadel/sound/vox/now.ogg b/sound/vox/now.ogg
similarity index 100%
rename from modular_citadel/sound/vox/now.ogg
rename to sound/vox/now.ogg
diff --git a/modular_citadel/sound/vox/number.ogg b/sound/vox/number.ogg
similarity index 100%
rename from modular_citadel/sound/vox/number.ogg
rename to sound/vox/number.ogg
diff --git a/modular_citadel/sound/vox/objective.ogg b/sound/vox/objective.ogg
similarity index 100%
rename from modular_citadel/sound/vox/objective.ogg
rename to sound/vox/objective.ogg
diff --git a/modular_citadel/sound/vox/observation.ogg b/sound/vox/observation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/observation.ogg
rename to sound/vox/observation.ogg
diff --git a/modular_citadel/sound/vox/of.ogg b/sound/vox/of.ogg
similarity index 100%
rename from modular_citadel/sound/vox/of.ogg
rename to sound/vox/of.ogg
diff --git a/modular_citadel/sound/vox/officer.ogg b/sound/vox/officer.ogg
similarity index 100%
rename from modular_citadel/sound/vox/officer.ogg
rename to sound/vox/officer.ogg
diff --git a/modular_citadel/sound/vox/ok.ogg b/sound/vox/ok.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ok.ogg
rename to sound/vox/ok.ogg
diff --git a/modular_citadel/sound/vox/on.ogg b/sound/vox/on.ogg
similarity index 100%
rename from modular_citadel/sound/vox/on.ogg
rename to sound/vox/on.ogg
diff --git a/modular_citadel/sound/vox/one.ogg b/sound/vox/one.ogg
similarity index 100%
rename from modular_citadel/sound/vox/one.ogg
rename to sound/vox/one.ogg
diff --git a/modular_citadel/sound/vox/open.ogg b/sound/vox/open.ogg
similarity index 100%
rename from modular_citadel/sound/vox/open.ogg
rename to sound/vox/open.ogg
diff --git a/modular_citadel/sound/vox/operating.ogg b/sound/vox/operating.ogg
similarity index 100%
rename from modular_citadel/sound/vox/operating.ogg
rename to sound/vox/operating.ogg
diff --git a/modular_citadel/sound/vox/operations.ogg b/sound/vox/operations.ogg
similarity index 100%
rename from modular_citadel/sound/vox/operations.ogg
rename to sound/vox/operations.ogg
diff --git a/modular_citadel/sound/vox/operative.ogg b/sound/vox/operative.ogg
similarity index 100%
rename from modular_citadel/sound/vox/operative.ogg
rename to sound/vox/operative.ogg
diff --git a/modular_citadel/sound/vox/option.ogg b/sound/vox/option.ogg
similarity index 100%
rename from modular_citadel/sound/vox/option.ogg
rename to sound/vox/option.ogg
diff --git a/modular_citadel/sound/vox/order.ogg b/sound/vox/order.ogg
similarity index 100%
rename from modular_citadel/sound/vox/order.ogg
rename to sound/vox/order.ogg
diff --git a/modular_citadel/sound/vox/organic.ogg b/sound/vox/organic.ogg
similarity index 100%
rename from modular_citadel/sound/vox/organic.ogg
rename to sound/vox/organic.ogg
diff --git a/modular_citadel/sound/vox/oscar.ogg b/sound/vox/oscar.ogg
similarity index 100%
rename from modular_citadel/sound/vox/oscar.ogg
rename to sound/vox/oscar.ogg
diff --git a/modular_citadel/sound/vox/out.ogg b/sound/vox/out.ogg
similarity index 100%
rename from modular_citadel/sound/vox/out.ogg
rename to sound/vox/out.ogg
diff --git a/modular_citadel/sound/vox/outside.ogg b/sound/vox/outside.ogg
similarity index 100%
rename from modular_citadel/sound/vox/outside.ogg
rename to sound/vox/outside.ogg
diff --git a/modular_citadel/sound/vox/over.ogg b/sound/vox/over.ogg
similarity index 100%
rename from modular_citadel/sound/vox/over.ogg
rename to sound/vox/over.ogg
diff --git a/modular_citadel/sound/vox/overload.ogg b/sound/vox/overload.ogg
similarity index 100%
rename from modular_citadel/sound/vox/overload.ogg
rename to sound/vox/overload.ogg
diff --git a/modular_citadel/sound/vox/override.ogg b/sound/vox/override.ogg
similarity index 100%
rename from modular_citadel/sound/vox/override.ogg
rename to sound/vox/override.ogg
diff --git a/modular_citadel/sound/vox/pacify.ogg b/sound/vox/pacify.ogg
similarity index 100%
rename from modular_citadel/sound/vox/pacify.ogg
rename to sound/vox/pacify.ogg
diff --git a/modular_citadel/sound/vox/pain.ogg b/sound/vox/pain.ogg
similarity index 100%
rename from modular_citadel/sound/vox/pain.ogg
rename to sound/vox/pain.ogg
diff --git a/modular_citadel/sound/vox/pal.ogg b/sound/vox/pal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/pal.ogg
rename to sound/vox/pal.ogg
diff --git a/modular_citadel/sound/vox/panel.ogg b/sound/vox/panel.ogg
similarity index 100%
rename from modular_citadel/sound/vox/panel.ogg
rename to sound/vox/panel.ogg
diff --git a/modular_citadel/sound/vox/percent.ogg b/sound/vox/percent.ogg
similarity index 100%
rename from modular_citadel/sound/vox/percent.ogg
rename to sound/vox/percent.ogg
diff --git a/modular_citadel/sound/vox/perimeter.ogg b/sound/vox/perimeter.ogg
similarity index 100%
rename from modular_citadel/sound/vox/perimeter.ogg
rename to sound/vox/perimeter.ogg
diff --git a/modular_citadel/sound/vox/period.ogg b/sound/vox/period.ogg
similarity index 100%
rename from modular_citadel/sound/vox/period.ogg
rename to sound/vox/period.ogg
diff --git a/modular_citadel/sound/vox/permitted.ogg b/sound/vox/permitted.ogg
similarity index 100%
rename from modular_citadel/sound/vox/permitted.ogg
rename to sound/vox/permitted.ogg
diff --git a/modular_citadel/sound/vox/personnel.ogg b/sound/vox/personnel.ogg
similarity index 100%
rename from modular_citadel/sound/vox/personnel.ogg
rename to sound/vox/personnel.ogg
diff --git a/modular_citadel/sound/vox/pipe.ogg b/sound/vox/pipe.ogg
similarity index 100%
rename from modular_citadel/sound/vox/pipe.ogg
rename to sound/vox/pipe.ogg
diff --git a/modular_citadel/sound/vox/plant.ogg b/sound/vox/plant.ogg
similarity index 100%
rename from modular_citadel/sound/vox/plant.ogg
rename to sound/vox/plant.ogg
diff --git a/modular_citadel/sound/vox/platform.ogg b/sound/vox/platform.ogg
similarity index 100%
rename from modular_citadel/sound/vox/platform.ogg
rename to sound/vox/platform.ogg
diff --git a/modular_citadel/sound/vox/please.ogg b/sound/vox/please.ogg
similarity index 100%
rename from modular_citadel/sound/vox/please.ogg
rename to sound/vox/please.ogg
diff --git a/modular_citadel/sound/vox/point.ogg b/sound/vox/point.ogg
similarity index 100%
rename from modular_citadel/sound/vox/point.ogg
rename to sound/vox/point.ogg
diff --git a/modular_citadel/sound/vox/portal.ogg b/sound/vox/portal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/portal.ogg
rename to sound/vox/portal.ogg
diff --git a/modular_citadel/sound/vox/power.ogg b/sound/vox/power.ogg
similarity index 100%
rename from modular_citadel/sound/vox/power.ogg
rename to sound/vox/power.ogg
diff --git a/modular_citadel/sound/vox/presence.ogg b/sound/vox/presence.ogg
similarity index 100%
rename from modular_citadel/sound/vox/presence.ogg
rename to sound/vox/presence.ogg
diff --git a/modular_citadel/sound/vox/press.ogg b/sound/vox/press.ogg
similarity index 100%
rename from modular_citadel/sound/vox/press.ogg
rename to sound/vox/press.ogg
diff --git a/modular_citadel/sound/vox/primary.ogg b/sound/vox/primary.ogg
similarity index 100%
rename from modular_citadel/sound/vox/primary.ogg
rename to sound/vox/primary.ogg
diff --git a/modular_citadel/sound/vox/proceed.ogg b/sound/vox/proceed.ogg
similarity index 100%
rename from modular_citadel/sound/vox/proceed.ogg
rename to sound/vox/proceed.ogg
diff --git a/modular_citadel/sound/vox/processing.ogg b/sound/vox/processing.ogg
similarity index 100%
rename from modular_citadel/sound/vox/processing.ogg
rename to sound/vox/processing.ogg
diff --git a/modular_citadel/sound/vox/progress.ogg b/sound/vox/progress.ogg
similarity index 100%
rename from modular_citadel/sound/vox/progress.ogg
rename to sound/vox/progress.ogg
diff --git a/modular_citadel/sound/vox/proper.ogg b/sound/vox/proper.ogg
similarity index 100%
rename from modular_citadel/sound/vox/proper.ogg
rename to sound/vox/proper.ogg
diff --git a/modular_citadel/sound/vox/propulsion.ogg b/sound/vox/propulsion.ogg
similarity index 100%
rename from modular_citadel/sound/vox/propulsion.ogg
rename to sound/vox/propulsion.ogg
diff --git a/modular_citadel/sound/vox/prosecute.ogg b/sound/vox/prosecute.ogg
similarity index 100%
rename from modular_citadel/sound/vox/prosecute.ogg
rename to sound/vox/prosecute.ogg
diff --git a/modular_citadel/sound/vox/protective.ogg b/sound/vox/protective.ogg
similarity index 100%
rename from modular_citadel/sound/vox/protective.ogg
rename to sound/vox/protective.ogg
diff --git a/modular_citadel/sound/vox/push.ogg b/sound/vox/push.ogg
similarity index 100%
rename from modular_citadel/sound/vox/push.ogg
rename to sound/vox/push.ogg
diff --git a/modular_citadel/sound/vox/quantum.ogg b/sound/vox/quantum.ogg
similarity index 100%
rename from modular_citadel/sound/vox/quantum.ogg
rename to sound/vox/quantum.ogg
diff --git a/modular_citadel/sound/vox/quebec.ogg b/sound/vox/quebec.ogg
similarity index 100%
rename from modular_citadel/sound/vox/quebec.ogg
rename to sound/vox/quebec.ogg
diff --git a/modular_citadel/sound/vox/question.ogg b/sound/vox/question.ogg
similarity index 100%
rename from modular_citadel/sound/vox/question.ogg
rename to sound/vox/question.ogg
diff --git a/modular_citadel/sound/vox/questioning.ogg b/sound/vox/questioning.ogg
similarity index 100%
rename from modular_citadel/sound/vox/questioning.ogg
rename to sound/vox/questioning.ogg
diff --git a/modular_citadel/sound/vox/quick.ogg b/sound/vox/quick.ogg
similarity index 100%
rename from modular_citadel/sound/vox/quick.ogg
rename to sound/vox/quick.ogg
diff --git a/modular_citadel/sound/vox/quit.ogg b/sound/vox/quit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/quit.ogg
rename to sound/vox/quit.ogg
diff --git a/modular_citadel/sound/vox/radiation.ogg b/sound/vox/radiation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/radiation.ogg
rename to sound/vox/radiation.ogg
diff --git a/modular_citadel/sound/vox/radioactive.ogg b/sound/vox/radioactive.ogg
similarity index 100%
rename from modular_citadel/sound/vox/radioactive.ogg
rename to sound/vox/radioactive.ogg
diff --git a/modular_citadel/sound/vox/rads.ogg b/sound/vox/rads.ogg
similarity index 100%
rename from modular_citadel/sound/vox/rads.ogg
rename to sound/vox/rads.ogg
diff --git a/modular_citadel/sound/vox/rapid.ogg b/sound/vox/rapid.ogg
similarity index 100%
rename from modular_citadel/sound/vox/rapid.ogg
rename to sound/vox/rapid.ogg
diff --git a/modular_citadel/sound/vox/reach.ogg b/sound/vox/reach.ogg
similarity index 100%
rename from modular_citadel/sound/vox/reach.ogg
rename to sound/vox/reach.ogg
diff --git a/modular_citadel/sound/vox/reached.ogg b/sound/vox/reached.ogg
similarity index 100%
rename from modular_citadel/sound/vox/reached.ogg
rename to sound/vox/reached.ogg
diff --git a/modular_citadel/sound/vox/reactor.ogg b/sound/vox/reactor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/reactor.ogg
rename to sound/vox/reactor.ogg
diff --git a/modular_citadel/sound/vox/red.ogg b/sound/vox/red.ogg
similarity index 100%
rename from modular_citadel/sound/vox/red.ogg
rename to sound/vox/red.ogg
diff --git a/modular_citadel/sound/vox/relay.ogg b/sound/vox/relay.ogg
similarity index 100%
rename from modular_citadel/sound/vox/relay.ogg
rename to sound/vox/relay.ogg
diff --git a/modular_citadel/sound/vox/released.ogg b/sound/vox/released.ogg
similarity index 100%
rename from modular_citadel/sound/vox/released.ogg
rename to sound/vox/released.ogg
diff --git a/modular_citadel/sound/vox/remaining.ogg b/sound/vox/remaining.ogg
similarity index 100%
rename from modular_citadel/sound/vox/remaining.ogg
rename to sound/vox/remaining.ogg
diff --git a/modular_citadel/sound/vox/renegade.ogg b/sound/vox/renegade.ogg
similarity index 100%
rename from modular_citadel/sound/vox/renegade.ogg
rename to sound/vox/renegade.ogg
diff --git a/modular_citadel/sound/vox/repair.ogg b/sound/vox/repair.ogg
similarity index 100%
rename from modular_citadel/sound/vox/repair.ogg
rename to sound/vox/repair.ogg
diff --git a/modular_citadel/sound/vox/report.ogg b/sound/vox/report.ogg
similarity index 100%
rename from modular_citadel/sound/vox/report.ogg
rename to sound/vox/report.ogg
diff --git a/modular_citadel/sound/vox/reports.ogg b/sound/vox/reports.ogg
similarity index 100%
rename from modular_citadel/sound/vox/reports.ogg
rename to sound/vox/reports.ogg
diff --git a/modular_citadel/sound/vox/required.ogg b/sound/vox/required.ogg
similarity index 100%
rename from modular_citadel/sound/vox/required.ogg
rename to sound/vox/required.ogg
diff --git a/modular_citadel/sound/vox/research.ogg b/sound/vox/research.ogg
similarity index 100%
rename from modular_citadel/sound/vox/research.ogg
rename to sound/vox/research.ogg
diff --git a/modular_citadel/sound/vox/reset.ogg b/sound/vox/reset.ogg
similarity index 100%
rename from modular_citadel/sound/vox/reset.ogg
rename to sound/vox/reset.ogg
diff --git a/modular_citadel/sound/vox/resevoir.ogg b/sound/vox/resevoir.ogg
similarity index 100%
rename from modular_citadel/sound/vox/resevoir.ogg
rename to sound/vox/resevoir.ogg
diff --git a/modular_citadel/sound/vox/resistance.ogg b/sound/vox/resistance.ogg
similarity index 100%
rename from modular_citadel/sound/vox/resistance.ogg
rename to sound/vox/resistance.ogg
diff --git a/modular_citadel/sound/vox/returned.ogg b/sound/vox/returned.ogg
similarity index 100%
rename from modular_citadel/sound/vox/returned.ogg
rename to sound/vox/returned.ogg
diff --git a/modular_citadel/sound/vox/right.ogg b/sound/vox/right.ogg
similarity index 100%
rename from modular_citadel/sound/vox/right.ogg
rename to sound/vox/right.ogg
diff --git a/modular_citadel/sound/vox/rocket.ogg b/sound/vox/rocket.ogg
similarity index 100%
rename from modular_citadel/sound/vox/rocket.ogg
rename to sound/vox/rocket.ogg
diff --git a/modular_citadel/sound/vox/roger.ogg b/sound/vox/roger.ogg
similarity index 100%
rename from modular_citadel/sound/vox/roger.ogg
rename to sound/vox/roger.ogg
diff --git a/modular_citadel/sound/vox/romeo.ogg b/sound/vox/romeo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/romeo.ogg
rename to sound/vox/romeo.ogg
diff --git a/modular_citadel/sound/vox/room.ogg b/sound/vox/room.ogg
similarity index 100%
rename from modular_citadel/sound/vox/room.ogg
rename to sound/vox/room.ogg
diff --git a/modular_citadel/sound/vox/round.ogg b/sound/vox/round.ogg
similarity index 100%
rename from modular_citadel/sound/vox/round.ogg
rename to sound/vox/round.ogg
diff --git a/modular_citadel/sound/vox/run.ogg b/sound/vox/run.ogg
similarity index 100%
rename from modular_citadel/sound/vox/run.ogg
rename to sound/vox/run.ogg
diff --git a/modular_citadel/sound/vox/safe.ogg b/sound/vox/safe.ogg
similarity index 100%
rename from modular_citadel/sound/vox/safe.ogg
rename to sound/vox/safe.ogg
diff --git a/modular_citadel/sound/vox/safety.ogg b/sound/vox/safety.ogg
similarity index 100%
rename from modular_citadel/sound/vox/safety.ogg
rename to sound/vox/safety.ogg
diff --git a/modular_citadel/sound/vox/sargeant.ogg b/sound/vox/sargeant.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sargeant.ogg
rename to sound/vox/sargeant.ogg
diff --git a/modular_citadel/sound/vox/satellite.ogg b/sound/vox/satellite.ogg
similarity index 100%
rename from modular_citadel/sound/vox/satellite.ogg
rename to sound/vox/satellite.ogg
diff --git a/modular_citadel/sound/vox/save.ogg b/sound/vox/save.ogg
similarity index 100%
rename from modular_citadel/sound/vox/save.ogg
rename to sound/vox/save.ogg
diff --git a/modular_citadel/sound/vox/science.ogg b/sound/vox/science.ogg
similarity index 100%
rename from modular_citadel/sound/vox/science.ogg
rename to sound/vox/science.ogg
diff --git a/modular_citadel/sound/vox/scores.ogg b/sound/vox/scores.ogg
similarity index 100%
rename from modular_citadel/sound/vox/scores.ogg
rename to sound/vox/scores.ogg
diff --git a/modular_citadel/sound/vox/scream.ogg b/sound/vox/scream.ogg
similarity index 100%
rename from modular_citadel/sound/vox/scream.ogg
rename to sound/vox/scream.ogg
diff --git a/modular_citadel/sound/vox/screen.ogg b/sound/vox/screen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/screen.ogg
rename to sound/vox/screen.ogg
diff --git a/modular_citadel/sound/vox/search.ogg b/sound/vox/search.ogg
similarity index 100%
rename from modular_citadel/sound/vox/search.ogg
rename to sound/vox/search.ogg
diff --git a/modular_citadel/sound/vox/second.ogg b/sound/vox/second.ogg
similarity index 100%
rename from modular_citadel/sound/vox/second.ogg
rename to sound/vox/second.ogg
diff --git a/modular_citadel/sound/vox/secondary.ogg b/sound/vox/secondary.ogg
similarity index 100%
rename from modular_citadel/sound/vox/secondary.ogg
rename to sound/vox/secondary.ogg
diff --git a/modular_citadel/sound/vox/seconds.ogg b/sound/vox/seconds.ogg
similarity index 100%
rename from modular_citadel/sound/vox/seconds.ogg
rename to sound/vox/seconds.ogg
diff --git a/modular_citadel/sound/vox/sector.ogg b/sound/vox/sector.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sector.ogg
rename to sound/vox/sector.ogg
diff --git a/modular_citadel/sound/vox/secure.ogg b/sound/vox/secure.ogg
similarity index 100%
rename from modular_citadel/sound/vox/secure.ogg
rename to sound/vox/secure.ogg
diff --git a/modular_citadel/sound/vox/secured.ogg b/sound/vox/secured.ogg
similarity index 100%
rename from modular_citadel/sound/vox/secured.ogg
rename to sound/vox/secured.ogg
diff --git a/modular_citadel/sound/vox/security.ogg b/sound/vox/security.ogg
similarity index 100%
rename from modular_citadel/sound/vox/security.ogg
rename to sound/vox/security.ogg
diff --git a/modular_citadel/sound/vox/select.ogg b/sound/vox/select.ogg
similarity index 100%
rename from modular_citadel/sound/vox/select.ogg
rename to sound/vox/select.ogg
diff --git a/modular_citadel/sound/vox/selected.ogg b/sound/vox/selected.ogg
similarity index 100%
rename from modular_citadel/sound/vox/selected.ogg
rename to sound/vox/selected.ogg
diff --git a/modular_citadel/sound/vox/service.ogg b/sound/vox/service.ogg
similarity index 100%
rename from modular_citadel/sound/vox/service.ogg
rename to sound/vox/service.ogg
diff --git a/modular_citadel/sound/vox/seven.ogg b/sound/vox/seven.ogg
similarity index 100%
rename from modular_citadel/sound/vox/seven.ogg
rename to sound/vox/seven.ogg
diff --git a/modular_citadel/sound/vox/seventeen.ogg b/sound/vox/seventeen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/seventeen.ogg
rename to sound/vox/seventeen.ogg
diff --git a/modular_citadel/sound/vox/seventy.ogg b/sound/vox/seventy.ogg
similarity index 100%
rename from modular_citadel/sound/vox/seventy.ogg
rename to sound/vox/seventy.ogg
diff --git a/modular_citadel/sound/vox/severe.ogg b/sound/vox/severe.ogg
similarity index 100%
rename from modular_citadel/sound/vox/severe.ogg
rename to sound/vox/severe.ogg
diff --git a/modular_citadel/sound/vox/sewage.ogg b/sound/vox/sewage.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sewage.ogg
rename to sound/vox/sewage.ogg
diff --git a/modular_citadel/sound/vox/sewer.ogg b/sound/vox/sewer.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sewer.ogg
rename to sound/vox/sewer.ogg
diff --git a/modular_citadel/sound/vox/shield.ogg b/sound/vox/shield.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shield.ogg
rename to sound/vox/shield.ogg
diff --git a/modular_citadel/sound/vox/shipment.ogg b/sound/vox/shipment.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shipment.ogg
rename to sound/vox/shipment.ogg
diff --git a/modular_citadel/sound/vox/shock.ogg b/sound/vox/shock.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shock.ogg
rename to sound/vox/shock.ogg
diff --git a/modular_citadel/sound/vox/shoot.ogg b/sound/vox/shoot.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shoot.ogg
rename to sound/vox/shoot.ogg
diff --git a/modular_citadel/sound/vox/shower.ogg b/sound/vox/shower.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shower.ogg
rename to sound/vox/shower.ogg
diff --git a/modular_citadel/sound/vox/shut.ogg b/sound/vox/shut.ogg
similarity index 100%
rename from modular_citadel/sound/vox/shut.ogg
rename to sound/vox/shut.ogg
diff --git a/modular_citadel/sound/vox/side.ogg b/sound/vox/side.ogg
similarity index 100%
rename from modular_citadel/sound/vox/side.ogg
rename to sound/vox/side.ogg
diff --git a/modular_citadel/sound/vox/sierra.ogg b/sound/vox/sierra.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sierra.ogg
rename to sound/vox/sierra.ogg
diff --git a/modular_citadel/sound/vox/sight.ogg b/sound/vox/sight.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sight.ogg
rename to sound/vox/sight.ogg
diff --git a/modular_citadel/sound/vox/silo.ogg b/sound/vox/silo.ogg
similarity index 100%
rename from modular_citadel/sound/vox/silo.ogg
rename to sound/vox/silo.ogg
diff --git a/modular_citadel/sound/vox/six.ogg b/sound/vox/six.ogg
similarity index 100%
rename from modular_citadel/sound/vox/six.ogg
rename to sound/vox/six.ogg
diff --git a/modular_citadel/sound/vox/sixteen.ogg b/sound/vox/sixteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sixteen.ogg
rename to sound/vox/sixteen.ogg
diff --git a/modular_citadel/sound/vox/sixty.ogg b/sound/vox/sixty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sixty.ogg
rename to sound/vox/sixty.ogg
diff --git a/modular_citadel/sound/vox/slime.ogg b/sound/vox/slime.ogg
similarity index 100%
rename from modular_citadel/sound/vox/slime.ogg
rename to sound/vox/slime.ogg
diff --git a/modular_citadel/sound/vox/slow.ogg b/sound/vox/slow.ogg
similarity index 100%
rename from modular_citadel/sound/vox/slow.ogg
rename to sound/vox/slow.ogg
diff --git a/modular_citadel/sound/vox/soldier.ogg b/sound/vox/soldier.ogg
similarity index 100%
rename from modular_citadel/sound/vox/soldier.ogg
rename to sound/vox/soldier.ogg
diff --git a/modular_citadel/sound/vox/some.ogg b/sound/vox/some.ogg
similarity index 100%
rename from modular_citadel/sound/vox/some.ogg
rename to sound/vox/some.ogg
diff --git a/modular_citadel/sound/vox/someone.ogg b/sound/vox/someone.ogg
similarity index 100%
rename from modular_citadel/sound/vox/someone.ogg
rename to sound/vox/someone.ogg
diff --git a/modular_citadel/sound/vox/something.ogg b/sound/vox/something.ogg
similarity index 100%
rename from modular_citadel/sound/vox/something.ogg
rename to sound/vox/something.ogg
diff --git a/modular_citadel/sound/vox/son.ogg b/sound/vox/son.ogg
similarity index 100%
rename from modular_citadel/sound/vox/son.ogg
rename to sound/vox/son.ogg
diff --git a/modular_citadel/sound/vox/sorry.ogg b/sound/vox/sorry.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sorry.ogg
rename to sound/vox/sorry.ogg
diff --git a/modular_citadel/sound/vox/south.ogg b/sound/vox/south.ogg
similarity index 100%
rename from modular_citadel/sound/vox/south.ogg
rename to sound/vox/south.ogg
diff --git a/modular_citadel/sound/vox/squad.ogg b/sound/vox/squad.ogg
similarity index 100%
rename from modular_citadel/sound/vox/squad.ogg
rename to sound/vox/squad.ogg
diff --git a/modular_citadel/sound/vox/square.ogg b/sound/vox/square.ogg
similarity index 100%
rename from modular_citadel/sound/vox/square.ogg
rename to sound/vox/square.ogg
diff --git a/modular_citadel/sound/vox/stairway.ogg b/sound/vox/stairway.ogg
similarity index 100%
rename from modular_citadel/sound/vox/stairway.ogg
rename to sound/vox/stairway.ogg
diff --git a/modular_citadel/sound/vox/status.ogg b/sound/vox/status.ogg
similarity index 100%
rename from modular_citadel/sound/vox/status.ogg
rename to sound/vox/status.ogg
diff --git a/modular_citadel/sound/vox/sterile.ogg b/sound/vox/sterile.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sterile.ogg
rename to sound/vox/sterile.ogg
diff --git a/modular_citadel/sound/vox/sterilization.ogg b/sound/vox/sterilization.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sterilization.ogg
rename to sound/vox/sterilization.ogg
diff --git a/modular_citadel/sound/vox/stolen.ogg b/sound/vox/stolen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/stolen.ogg
rename to sound/vox/stolen.ogg
diff --git a/modular_citadel/sound/vox/storage.ogg b/sound/vox/storage.ogg
similarity index 100%
rename from modular_citadel/sound/vox/storage.ogg
rename to sound/vox/storage.ogg
diff --git a/modular_citadel/sound/vox/sub.ogg b/sound/vox/sub.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sub.ogg
rename to sound/vox/sub.ogg
diff --git a/modular_citadel/sound/vox/subsurface.ogg b/sound/vox/subsurface.ogg
similarity index 100%
rename from modular_citadel/sound/vox/subsurface.ogg
rename to sound/vox/subsurface.ogg
diff --git a/modular_citadel/sound/vox/sudden.ogg b/sound/vox/sudden.ogg
similarity index 100%
rename from modular_citadel/sound/vox/sudden.ogg
rename to sound/vox/sudden.ogg
diff --git a/modular_citadel/sound/vox/suit.ogg b/sound/vox/suit.ogg
similarity index 100%
rename from modular_citadel/sound/vox/suit.ogg
rename to sound/vox/suit.ogg
diff --git a/modular_citadel/sound/vox/superconducting.ogg b/sound/vox/superconducting.ogg
similarity index 100%
rename from modular_citadel/sound/vox/superconducting.ogg
rename to sound/vox/superconducting.ogg
diff --git a/modular_citadel/sound/vox/supercooled.ogg b/sound/vox/supercooled.ogg
similarity index 100%
rename from modular_citadel/sound/vox/supercooled.ogg
rename to sound/vox/supercooled.ogg
diff --git a/modular_citadel/sound/vox/supply.ogg b/sound/vox/supply.ogg
similarity index 100%
rename from modular_citadel/sound/vox/supply.ogg
rename to sound/vox/supply.ogg
diff --git a/modular_citadel/sound/vox/surface.ogg b/sound/vox/surface.ogg
similarity index 100%
rename from modular_citadel/sound/vox/surface.ogg
rename to sound/vox/surface.ogg
diff --git a/modular_citadel/sound/vox/surrender.ogg b/sound/vox/surrender.ogg
similarity index 100%
rename from modular_citadel/sound/vox/surrender.ogg
rename to sound/vox/surrender.ogg
diff --git a/modular_citadel/sound/vox/surround.ogg b/sound/vox/surround.ogg
similarity index 100%
rename from modular_citadel/sound/vox/surround.ogg
rename to sound/vox/surround.ogg
diff --git a/modular_citadel/sound/vox/surrounded.ogg b/sound/vox/surrounded.ogg
similarity index 100%
rename from modular_citadel/sound/vox/surrounded.ogg
rename to sound/vox/surrounded.ogg
diff --git a/modular_citadel/sound/vox/switch.ogg b/sound/vox/switch.ogg
similarity index 100%
rename from modular_citadel/sound/vox/switch.ogg
rename to sound/vox/switch.ogg
diff --git a/modular_citadel/sound/vox/system.ogg b/sound/vox/system.ogg
similarity index 100%
rename from modular_citadel/sound/vox/system.ogg
rename to sound/vox/system.ogg
diff --git a/modular_citadel/sound/vox/systems.ogg b/sound/vox/systems.ogg
similarity index 100%
rename from modular_citadel/sound/vox/systems.ogg
rename to sound/vox/systems.ogg
diff --git a/modular_citadel/sound/vox/tactical.ogg b/sound/vox/tactical.ogg
similarity index 100%
rename from modular_citadel/sound/vox/tactical.ogg
rename to sound/vox/tactical.ogg
diff --git a/modular_citadel/sound/vox/take.ogg b/sound/vox/take.ogg
similarity index 100%
rename from modular_citadel/sound/vox/take.ogg
rename to sound/vox/take.ogg
diff --git a/modular_citadel/sound/vox/talk.ogg b/sound/vox/talk.ogg
similarity index 100%
rename from modular_citadel/sound/vox/talk.ogg
rename to sound/vox/talk.ogg
diff --git a/modular_citadel/sound/vox/tango.ogg b/sound/vox/tango.ogg
similarity index 100%
rename from modular_citadel/sound/vox/tango.ogg
rename to sound/vox/tango.ogg
diff --git a/modular_citadel/sound/vox/tank.ogg b/sound/vox/tank.ogg
similarity index 100%
rename from modular_citadel/sound/vox/tank.ogg
rename to sound/vox/tank.ogg
diff --git a/modular_citadel/sound/vox/target.ogg b/sound/vox/target.ogg
similarity index 100%
rename from modular_citadel/sound/vox/target.ogg
rename to sound/vox/target.ogg
diff --git a/modular_citadel/sound/vox/team.ogg b/sound/vox/team.ogg
similarity index 100%
rename from modular_citadel/sound/vox/team.ogg
rename to sound/vox/team.ogg
diff --git a/modular_citadel/sound/vox/temperature.ogg b/sound/vox/temperature.ogg
similarity index 100%
rename from modular_citadel/sound/vox/temperature.ogg
rename to sound/vox/temperature.ogg
diff --git a/modular_citadel/sound/vox/temporal.ogg b/sound/vox/temporal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/temporal.ogg
rename to sound/vox/temporal.ogg
diff --git a/modular_citadel/sound/vox/ten.ogg b/sound/vox/ten.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ten.ogg
rename to sound/vox/ten.ogg
diff --git a/modular_citadel/sound/vox/terminal.ogg b/sound/vox/terminal.ogg
similarity index 100%
rename from modular_citadel/sound/vox/terminal.ogg
rename to sound/vox/terminal.ogg
diff --git a/modular_citadel/sound/vox/terminated.ogg b/sound/vox/terminated.ogg
similarity index 100%
rename from modular_citadel/sound/vox/terminated.ogg
rename to sound/vox/terminated.ogg
diff --git a/modular_citadel/sound/vox/termination.ogg b/sound/vox/termination.ogg
similarity index 100%
rename from modular_citadel/sound/vox/termination.ogg
rename to sound/vox/termination.ogg
diff --git a/modular_citadel/sound/vox/test.ogg b/sound/vox/test.ogg
similarity index 100%
rename from modular_citadel/sound/vox/test.ogg
rename to sound/vox/test.ogg
diff --git a/modular_citadel/sound/vox/that.ogg b/sound/vox/that.ogg
similarity index 100%
rename from modular_citadel/sound/vox/that.ogg
rename to sound/vox/that.ogg
diff --git a/modular_citadel/sound/vox/the.ogg b/sound/vox/the.ogg
similarity index 100%
rename from modular_citadel/sound/vox/the.ogg
rename to sound/vox/the.ogg
diff --git a/modular_citadel/sound/vox/then.ogg b/sound/vox/then.ogg
similarity index 100%
rename from modular_citadel/sound/vox/then.ogg
rename to sound/vox/then.ogg
diff --git a/modular_citadel/sound/vox/there.ogg b/sound/vox/there.ogg
similarity index 100%
rename from modular_citadel/sound/vox/there.ogg
rename to sound/vox/there.ogg
diff --git a/modular_citadel/sound/vox/third.ogg b/sound/vox/third.ogg
similarity index 100%
rename from modular_citadel/sound/vox/third.ogg
rename to sound/vox/third.ogg
diff --git a/modular_citadel/sound/vox/thirteen.ogg b/sound/vox/thirteen.ogg
similarity index 100%
rename from modular_citadel/sound/vox/thirteen.ogg
rename to sound/vox/thirteen.ogg
diff --git a/modular_citadel/sound/vox/thirty.ogg b/sound/vox/thirty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/thirty.ogg
rename to sound/vox/thirty.ogg
diff --git a/modular_citadel/sound/vox/this.ogg b/sound/vox/this.ogg
similarity index 100%
rename from modular_citadel/sound/vox/this.ogg
rename to sound/vox/this.ogg
diff --git a/modular_citadel/sound/vox/those.ogg b/sound/vox/those.ogg
similarity index 100%
rename from modular_citadel/sound/vox/those.ogg
rename to sound/vox/those.ogg
diff --git a/modular_citadel/sound/vox/thousand.ogg b/sound/vox/thousand.ogg
similarity index 100%
rename from modular_citadel/sound/vox/thousand.ogg
rename to sound/vox/thousand.ogg
diff --git a/modular_citadel/sound/vox/threat.ogg b/sound/vox/threat.ogg
similarity index 100%
rename from modular_citadel/sound/vox/threat.ogg
rename to sound/vox/threat.ogg
diff --git a/modular_citadel/sound/vox/three.ogg b/sound/vox/three.ogg
similarity index 100%
rename from modular_citadel/sound/vox/three.ogg
rename to sound/vox/three.ogg
diff --git a/modular_citadel/sound/vox/through.ogg b/sound/vox/through.ogg
similarity index 100%
rename from modular_citadel/sound/vox/through.ogg
rename to sound/vox/through.ogg
diff --git a/modular_citadel/sound/vox/time.ogg b/sound/vox/time.ogg
similarity index 100%
rename from modular_citadel/sound/vox/time.ogg
rename to sound/vox/time.ogg
diff --git a/modular_citadel/sound/vox/to.ogg b/sound/vox/to.ogg
similarity index 100%
rename from modular_citadel/sound/vox/to.ogg
rename to sound/vox/to.ogg
diff --git a/modular_citadel/sound/vox/top.ogg b/sound/vox/top.ogg
similarity index 100%
rename from modular_citadel/sound/vox/top.ogg
rename to sound/vox/top.ogg
diff --git a/modular_citadel/sound/vox/topside.ogg b/sound/vox/topside.ogg
similarity index 100%
rename from modular_citadel/sound/vox/topside.ogg
rename to sound/vox/topside.ogg
diff --git a/modular_citadel/sound/vox/touch.ogg b/sound/vox/touch.ogg
similarity index 100%
rename from modular_citadel/sound/vox/touch.ogg
rename to sound/vox/touch.ogg
diff --git a/modular_citadel/sound/vox/towards.ogg b/sound/vox/towards.ogg
similarity index 100%
rename from modular_citadel/sound/vox/towards.ogg
rename to sound/vox/towards.ogg
diff --git a/modular_citadel/sound/vox/track.ogg b/sound/vox/track.ogg
similarity index 100%
rename from modular_citadel/sound/vox/track.ogg
rename to sound/vox/track.ogg
diff --git a/modular_citadel/sound/vox/train.ogg b/sound/vox/train.ogg
similarity index 100%
rename from modular_citadel/sound/vox/train.ogg
rename to sound/vox/train.ogg
diff --git a/modular_citadel/sound/vox/transportation.ogg b/sound/vox/transportation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/transportation.ogg
rename to sound/vox/transportation.ogg
diff --git a/modular_citadel/sound/vox/truck.ogg b/sound/vox/truck.ogg
similarity index 100%
rename from modular_citadel/sound/vox/truck.ogg
rename to sound/vox/truck.ogg
diff --git a/modular_citadel/sound/vox/tunnel.ogg b/sound/vox/tunnel.ogg
similarity index 100%
rename from modular_citadel/sound/vox/tunnel.ogg
rename to sound/vox/tunnel.ogg
diff --git a/modular_citadel/sound/vox/turn.ogg b/sound/vox/turn.ogg
similarity index 100%
rename from modular_citadel/sound/vox/turn.ogg
rename to sound/vox/turn.ogg
diff --git a/modular_citadel/sound/vox/turret.ogg b/sound/vox/turret.ogg
similarity index 100%
rename from modular_citadel/sound/vox/turret.ogg
rename to sound/vox/turret.ogg
diff --git a/modular_citadel/sound/vox/twelve.ogg b/sound/vox/twelve.ogg
similarity index 100%
rename from modular_citadel/sound/vox/twelve.ogg
rename to sound/vox/twelve.ogg
diff --git a/modular_citadel/sound/vox/twenty.ogg b/sound/vox/twenty.ogg
similarity index 100%
rename from modular_citadel/sound/vox/twenty.ogg
rename to sound/vox/twenty.ogg
diff --git a/modular_citadel/sound/vox/two.ogg b/sound/vox/two.ogg
similarity index 100%
rename from modular_citadel/sound/vox/two.ogg
rename to sound/vox/two.ogg
diff --git a/modular_citadel/sound/vox/unauthorized.ogg b/sound/vox/unauthorized.ogg
similarity index 100%
rename from modular_citadel/sound/vox/unauthorized.ogg
rename to sound/vox/unauthorized.ogg
diff --git a/modular_citadel/sound/vox/under.ogg b/sound/vox/under.ogg
similarity index 100%
rename from modular_citadel/sound/vox/under.ogg
rename to sound/vox/under.ogg
diff --git a/modular_citadel/sound/vox/uniform.ogg b/sound/vox/uniform.ogg
similarity index 100%
rename from modular_citadel/sound/vox/uniform.ogg
rename to sound/vox/uniform.ogg
diff --git a/modular_citadel/sound/vox/unlocked.ogg b/sound/vox/unlocked.ogg
similarity index 100%
rename from modular_citadel/sound/vox/unlocked.ogg
rename to sound/vox/unlocked.ogg
diff --git a/modular_citadel/sound/vox/until.ogg b/sound/vox/until.ogg
similarity index 100%
rename from modular_citadel/sound/vox/until.ogg
rename to sound/vox/until.ogg
diff --git a/modular_citadel/sound/vox/up.ogg b/sound/vox/up.ogg
similarity index 100%
rename from modular_citadel/sound/vox/up.ogg
rename to sound/vox/up.ogg
diff --git a/modular_citadel/sound/vox/upper.ogg b/sound/vox/upper.ogg
similarity index 100%
rename from modular_citadel/sound/vox/upper.ogg
rename to sound/vox/upper.ogg
diff --git a/modular_citadel/sound/vox/uranium.ogg b/sound/vox/uranium.ogg
similarity index 100%
rename from modular_citadel/sound/vox/uranium.ogg
rename to sound/vox/uranium.ogg
diff --git a/modular_citadel/sound/vox/us.ogg b/sound/vox/us.ogg
similarity index 100%
rename from modular_citadel/sound/vox/us.ogg
rename to sound/vox/us.ogg
diff --git a/modular_citadel/sound/vox/usa.ogg b/sound/vox/usa.ogg
similarity index 100%
rename from modular_citadel/sound/vox/usa.ogg
rename to sound/vox/usa.ogg
diff --git a/modular_citadel/sound/vox/use.ogg b/sound/vox/use.ogg
similarity index 100%
rename from modular_citadel/sound/vox/use.ogg
rename to sound/vox/use.ogg
diff --git a/modular_citadel/sound/vox/used.ogg b/sound/vox/used.ogg
similarity index 100%
rename from modular_citadel/sound/vox/used.ogg
rename to sound/vox/used.ogg
diff --git a/modular_citadel/sound/vox/user.ogg b/sound/vox/user.ogg
similarity index 100%
rename from modular_citadel/sound/vox/user.ogg
rename to sound/vox/user.ogg
diff --git a/modular_citadel/sound/vox/vacate.ogg b/sound/vox/vacate.ogg
similarity index 100%
rename from modular_citadel/sound/vox/vacate.ogg
rename to sound/vox/vacate.ogg
diff --git a/modular_citadel/sound/vox/valid.ogg b/sound/vox/valid.ogg
similarity index 100%
rename from modular_citadel/sound/vox/valid.ogg
rename to sound/vox/valid.ogg
diff --git a/modular_citadel/sound/vox/vapor.ogg b/sound/vox/vapor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/vapor.ogg
rename to sound/vox/vapor.ogg
diff --git a/modular_citadel/sound/vox/vent.ogg b/sound/vox/vent.ogg
similarity index 100%
rename from modular_citadel/sound/vox/vent.ogg
rename to sound/vox/vent.ogg
diff --git a/modular_citadel/sound/vox/ventillation.ogg b/sound/vox/ventillation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/ventillation.ogg
rename to sound/vox/ventillation.ogg
diff --git a/modular_citadel/sound/vox/victor.ogg b/sound/vox/victor.ogg
similarity index 100%
rename from modular_citadel/sound/vox/victor.ogg
rename to sound/vox/victor.ogg
diff --git a/modular_citadel/sound/vox/violated.ogg b/sound/vox/violated.ogg
similarity index 100%
rename from modular_citadel/sound/vox/violated.ogg
rename to sound/vox/violated.ogg
diff --git a/modular_citadel/sound/vox/violation.ogg b/sound/vox/violation.ogg
similarity index 100%
rename from modular_citadel/sound/vox/violation.ogg
rename to sound/vox/violation.ogg
diff --git a/modular_citadel/sound/vox/voltage.ogg b/sound/vox/voltage.ogg
similarity index 100%
rename from modular_citadel/sound/vox/voltage.ogg
rename to sound/vox/voltage.ogg
diff --git a/modular_citadel/sound/vox/vox_login.ogg b/sound/vox/vox_login.ogg
similarity index 100%
rename from modular_citadel/sound/vox/vox_login.ogg
rename to sound/vox/vox_login.ogg
diff --git a/modular_citadel/sound/vox/walk.ogg b/sound/vox/walk.ogg
similarity index 100%
rename from modular_citadel/sound/vox/walk.ogg
rename to sound/vox/walk.ogg
diff --git a/modular_citadel/sound/vox/wall.ogg b/sound/vox/wall.ogg
similarity index 100%
rename from modular_citadel/sound/vox/wall.ogg
rename to sound/vox/wall.ogg
diff --git a/modular_citadel/sound/vox/want.ogg b/sound/vox/want.ogg
similarity index 100%
rename from modular_citadel/sound/vox/want.ogg
rename to sound/vox/want.ogg
diff --git a/modular_citadel/sound/vox/wanted.ogg b/sound/vox/wanted.ogg
similarity index 100%
rename from modular_citadel/sound/vox/wanted.ogg
rename to sound/vox/wanted.ogg
diff --git a/modular_citadel/sound/vox/warm.ogg b/sound/vox/warm.ogg
similarity index 100%
rename from modular_citadel/sound/vox/warm.ogg
rename to sound/vox/warm.ogg
diff --git a/modular_citadel/sound/vox/warn.ogg b/sound/vox/warn.ogg
similarity index 100%
rename from modular_citadel/sound/vox/warn.ogg
rename to sound/vox/warn.ogg
diff --git a/modular_citadel/sound/vox/warning.ogg b/sound/vox/warning.ogg
similarity index 100%
rename from modular_citadel/sound/vox/warning.ogg
rename to sound/vox/warning.ogg
diff --git a/modular_citadel/sound/vox/waste.ogg b/sound/vox/waste.ogg
similarity index 100%
rename from modular_citadel/sound/vox/waste.ogg
rename to sound/vox/waste.ogg
diff --git a/modular_citadel/sound/vox/water.ogg b/sound/vox/water.ogg
similarity index 100%
rename from modular_citadel/sound/vox/water.ogg
rename to sound/vox/water.ogg
diff --git a/modular_citadel/sound/vox/we.ogg b/sound/vox/we.ogg
similarity index 100%
rename from modular_citadel/sound/vox/we.ogg
rename to sound/vox/we.ogg
diff --git a/modular_citadel/sound/vox/weapon.ogg b/sound/vox/weapon.ogg
similarity index 100%
rename from modular_citadel/sound/vox/weapon.ogg
rename to sound/vox/weapon.ogg
diff --git a/modular_citadel/sound/vox/west.ogg b/sound/vox/west.ogg
similarity index 100%
rename from modular_citadel/sound/vox/west.ogg
rename to sound/vox/west.ogg
diff --git a/modular_citadel/sound/vox/whiskey.ogg b/sound/vox/whiskey.ogg
similarity index 100%
rename from modular_citadel/sound/vox/whiskey.ogg
rename to sound/vox/whiskey.ogg
diff --git a/modular_citadel/sound/vox/white.ogg b/sound/vox/white.ogg
similarity index 100%
rename from modular_citadel/sound/vox/white.ogg
rename to sound/vox/white.ogg
diff --git a/modular_citadel/sound/vox/wilco.ogg b/sound/vox/wilco.ogg
similarity index 100%
rename from modular_citadel/sound/vox/wilco.ogg
rename to sound/vox/wilco.ogg
diff --git a/modular_citadel/sound/vox/will.ogg b/sound/vox/will.ogg
similarity index 100%
rename from modular_citadel/sound/vox/will.ogg
rename to sound/vox/will.ogg
diff --git a/modular_citadel/sound/vox/with.ogg b/sound/vox/with.ogg
similarity index 100%
rename from modular_citadel/sound/vox/with.ogg
rename to sound/vox/with.ogg
diff --git a/modular_citadel/sound/vox/without.ogg b/sound/vox/without.ogg
similarity index 100%
rename from modular_citadel/sound/vox/without.ogg
rename to sound/vox/without.ogg
diff --git a/modular_citadel/sound/vox/woop.ogg b/sound/vox/woop.ogg
similarity index 100%
rename from modular_citadel/sound/vox/woop.ogg
rename to sound/vox/woop.ogg
diff --git a/modular_citadel/sound/vox/xeno.ogg b/sound/vox/xeno.ogg
similarity index 100%
rename from modular_citadel/sound/vox/xeno.ogg
rename to sound/vox/xeno.ogg
diff --git a/modular_citadel/sound/vox/yankee.ogg b/sound/vox/yankee.ogg
similarity index 100%
rename from modular_citadel/sound/vox/yankee.ogg
rename to sound/vox/yankee.ogg
diff --git a/modular_citadel/sound/vox/yards.ogg b/sound/vox/yards.ogg
similarity index 100%
rename from modular_citadel/sound/vox/yards.ogg
rename to sound/vox/yards.ogg
diff --git a/modular_citadel/sound/vox/year.ogg b/sound/vox/year.ogg
similarity index 100%
rename from modular_citadel/sound/vox/year.ogg
rename to sound/vox/year.ogg
diff --git a/modular_citadel/sound/vox/yellow.ogg b/sound/vox/yellow.ogg
similarity index 100%
rename from modular_citadel/sound/vox/yellow.ogg
rename to sound/vox/yellow.ogg
diff --git a/modular_citadel/sound/vox/yes.ogg b/sound/vox/yes.ogg
similarity index 100%
rename from modular_citadel/sound/vox/yes.ogg
rename to sound/vox/yes.ogg
diff --git a/modular_citadel/sound/vox/you.ogg b/sound/vox/you.ogg
similarity index 100%
rename from modular_citadel/sound/vox/you.ogg
rename to sound/vox/you.ogg
diff --git a/modular_citadel/sound/vox/your.ogg b/sound/vox/your.ogg
similarity index 100%
rename from modular_citadel/sound/vox/your.ogg
rename to sound/vox/your.ogg
diff --git a/modular_citadel/sound/vox/yourself.ogg b/sound/vox/yourself.ogg
similarity index 100%
rename from modular_citadel/sound/vox/yourself.ogg
rename to sound/vox/yourself.ogg
diff --git a/modular_citadel/sound/vox/zero.ogg b/sound/vox/zero.ogg
similarity index 100%
rename from modular_citadel/sound/vox/zero.ogg
rename to sound/vox/zero.ogg
diff --git a/modular_citadel/sound/vox/zone.ogg b/sound/vox/zone.ogg
similarity index 100%
rename from modular_citadel/sound/vox/zone.ogg
rename to sound/vox/zone.ogg
diff --git a/modular_citadel/sound/vox/zulu.ogg b/sound/vox/zulu.ogg
similarity index 100%
rename from modular_citadel/sound/vox/zulu.ogg
rename to sound/vox/zulu.ogg
diff --git a/tgstation.dme b/tgstation.dme
index 63b6bcfdb8..0ab92d863d 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -16,6 +16,7 @@
#include "_maps\_basemap.dm"
#include "code\_compile_options.dm"
#include "code\world.dm"
+#include "code\__DEFINES\__513_compatibility.dm"
#include "code\__DEFINES\_globals.dm"
#include "code\__DEFINES\_protect.dm"
#include "code\__DEFINES\_tick.dm"
@@ -44,6 +45,7 @@
#include "code\__DEFINES\donator_groupings.dm"
#include "code\__DEFINES\events.dm"
#include "code\__DEFINES\exports.dm"
+#include "code\__DEFINES\fantasy_affixes.dm"
#include "code\__DEFINES\flags.dm"
#include "code\__DEFINES\food.dm"
#include "code\__DEFINES\footsteps.dm"
@@ -343,6 +345,7 @@
#include "code\datums\components\_component.dm"
#include "code\datums\components\anti_magic.dm"
#include "code\datums\components\armor_plate.dm"
+#include "code\datums\components\bane.dm"
#include "code\datums\components\bouncy.dm"
#include "code\datums\components\butchering.dm"
#include "code\datums\components\caltrop.dm"
@@ -356,9 +359,12 @@
#include "code\datums\components\empprotection.dm"
#include "code\datums\components\footstep.dm"
#include "code\datums\components\forced_gravity.dm"
+#include "code\datums\components\igniter.dm"
#include "code\datums\components\infective.dm"
#include "code\datums\components\jousting.dm"
+#include "code\datums\components\knockback.dm"
#include "code\datums\components\knockoff.dm"
+#include "code\datums\components\lifesteal.dm"
#include "code\datums\components\lockon_aiming.dm"
#include "code\datums\components\magnetic_catch.dm"
#include "code\datums\components\material_container.dm"
@@ -374,16 +380,23 @@
#include "code\datums\components\remote_materials.dm"
#include "code\datums\components\riding.dm"
#include "code\datums\components\rotation.dm"
+#include "code\datums\components\shrapnel.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spooky.dm"
#include "code\datums\components\squeak.dm"
#include "code\datums\components\stationloving.dm"
+#include "code\datums\components\summoning.dm"
#include "code\datums\components\swarming.dm"
+#include "code\datums\components\tactical.dm"
#include "code\datums\components\thermite.dm"
#include "code\datums\components\uplink.dm"
#include "code\datums\components\virtual_reality.dm"
#include "code\datums\components\wearertargeting.dm"
#include "code\datums\components\wet_floor.dm"
+#include "code\datums\components\fantasy\_fantasy.dm"
+#include "code\datums\components\fantasy\affix.dm"
+#include "code\datums\components\fantasy\prefixes.dm"
+#include "code\datums\components\fantasy\suffixes.dm"
#include "code\datums\components\storage\storage.dm"
#include "code\datums\components\storage\concrete\_concrete.dm"
#include "code\datums\components\storage\concrete\bag_of_holding.dm"
@@ -2219,6 +2232,7 @@
#include "code\modules\mob\living\simple_animal\guardian\types\standard.dm"
#include "code\modules\mob\living\simple_animal\guardian\types\support.dm"
#include "code\modules\mob\living\simple_animal\hostile\alien.dm"
+#include "code\modules\mob\living\simple_animal\hostile\banana_spider.dm"
#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
#include "code\modules\mob\living\simple_animal\hostile\bees.dm"
#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
@@ -2585,6 +2599,7 @@
#include "code\modules\reagents\reagent_containers\dropper.dm"
#include "code\modules\reagents\reagent_containers\glass.dm"
#include "code\modules\reagents\reagent_containers\hypospray.dm"
+#include "code\modules\reagents\reagent_containers\hypovial.dm"
#include "code\modules\reagents\reagent_containers\medspray.dm"
#include "code\modules\reagents\reagent_containers\patch.dm"
#include "code\modules\reagents\reagent_containers\pill.dm"
@@ -2771,6 +2786,7 @@
#include "code\modules\spells\spell_types\spacetime_distortion.dm"
#include "code\modules\spells\spell_types\summonitem.dm"
#include "code\modules\spells\spell_types\taeclowndo.dm"
+#include "code\modules\spells\spell_types\telepathy.dm"
#include "code\modules\spells\spell_types\the_traps.dm"
#include "code\modules\spells\spell_types\touch_attacks.dm"
#include "code\modules\spells\spell_types\trigger.dm"
@@ -2956,7 +2972,6 @@
#include "modular_citadel\code\datums\status_effects\chems.dm"
#include "modular_citadel\code\datums\status_effects\debuffs.dm"
#include "modular_citadel\code\datums\traits\negative.dm"
-#include "modular_citadel\code\datums\traits\neutral.dm"
#include "modular_citadel\code\datums\wires\airlock.dm"
#include "modular_citadel\code\datums\wires\autoylathe.dm"
#include "modular_citadel\code\game\area\cit_areas.dm"
@@ -2983,7 +2998,6 @@
#include "modular_citadel\code\game\machinery\doors\airlock.dm"
#include "modular_citadel\code\game\machinery\doors\airlock_types.dm"
#include "modular_citadel\code\game\objects\cit_screenshake.dm"
-#include "modular_citadel\code\game\objects\ids.dm"
#include "modular_citadel\code\game\objects\items.dm"
#include "modular_citadel\code\game\objects\tools.dm"
#include "modular_citadel\code\game\objects\effects\spawner\spawners.dm"
@@ -3002,7 +3016,6 @@
#include "modular_citadel\code\game\objects\items\devices\radio\encryptionkey.dm"
#include "modular_citadel\code\game\objects\items\devices\radio\headset.dm"
#include "modular_citadel\code\game\objects\items\devices\radio\shockcollar.dm"
-#include "modular_citadel\code\game\objects\items\melee\eutactic_blades.dm"
#include "modular_citadel\code\game\objects\items\storage\firstaid.dm"
#include "modular_citadel\code\game\objects\structures\tables_racks.dm"
#include "modular_citadel\code\game\objects\structures\beds_chairs\chair.dm"
@@ -3016,17 +3029,16 @@
#include "modular_citadel\code\modules\admin\secrets.dm"
#include "modular_citadel\code\modules\admin\topic.dm"
#include "modular_citadel\code\modules\arousal\arousal.dm"
+#include "modular_citadel\code\modules\arousal\genitals.dm"
+#include "modular_citadel\code\modules\arousal\genitals_sprite_accessories.dm"
#include "modular_citadel\code\modules\arousal\organs\breasts.dm"
#include "modular_citadel\code\modules\arousal\organs\eggsack.dm"
-#include "modular_citadel\code\modules\arousal\organs\genitals.dm"
-#include "modular_citadel\code\modules\arousal\organs\genitals_sprite_accessories.dm"
#include "modular_citadel\code\modules\arousal\organs\ovipositor.dm"
#include "modular_citadel\code\modules\arousal\organs\penis.dm"
#include "modular_citadel\code\modules\arousal\organs\testicles.dm"
#include "modular_citadel\code\modules\arousal\organs\vagina.dm"
#include "modular_citadel\code\modules\arousal\organs\womb.dm"
#include "modular_citadel\code\modules\arousal\toys\dildos.dm"
-#include "modular_citadel\code\modules\awaymissions\citadel_ghostrole_spawners.dm"
#include "modular_citadel\code\modules\cargo\console.dm"
#include "modular_citadel\code\modules\client\client_defines.dm"
#include "modular_citadel\code\modules\client\client_procs.dm"
@@ -3053,7 +3065,6 @@
#include "modular_citadel\code\modules\clothing\neck.dm"
#include "modular_citadel\code\modules\clothing\glasses\phantomthief.dm"
#include "modular_citadel\code\modules\clothing\head\head.dm"
-#include "modular_citadel\code\modules\clothing\spacesuits\cydonian_armor.dm"
#include "modular_citadel\code\modules\clothing\spacesuits\flightsuit.dm"
#include "modular_citadel\code\modules\clothing\suits\polychromic_cloaks.dm"
#include "modular_citadel\code\modules\clothing\suits\suits.dm"
@@ -3064,17 +3075,8 @@
#include "modular_citadel\code\modules\custom_loadout\custom_items.dm"
#include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm"
#include "modular_citadel\code\modules\custom_loadout\read_from_file.dm"
-#include "modular_citadel\code\modules\events\blob.dm"
-#include "modular_citadel\code\modules\events\wizard\magicarp.dm"
#include "modular_citadel\code\modules\food_and_drinks\snacks\meat.dm"
#include "modular_citadel\code\modules\integrated_electronics\subtypes\manipulation.dm"
-#include "modular_citadel\code\modules\jobs\dresscode_values.dm"
-#include "modular_citadel\code\modules\jobs\job_types\captain.dm"
-#include "modular_citadel\code\modules\jobs\job_types\cargo_service.dm"
-#include "modular_citadel\code\modules\jobs\job_types\engineering.dm"
-#include "modular_citadel\code\modules\jobs\job_types\medical.dm"
-#include "modular_citadel\code\modules\jobs\job_types\science.dm"
-#include "modular_citadel\code\modules\jobs\job_types\security.dm"
#include "modular_citadel\code\modules\keybindings\bindings_carbon.dm"
#include "modular_citadel\code\modules\keybindings\bindings_human.dm"
#include "modular_citadel\code\modules\keybindings\bindings_robot.dm"
@@ -3097,13 +3099,10 @@
#include "modular_citadel\code\modules\mob\living\carbon\human\human.dm"
#include "modular_citadel\code\modules\mob\living\carbon\human\human_defense.dm"
#include "modular_citadel\code\modules\mob\living\carbon\human\human_movement.dm"
-#include "modular_citadel\code\modules\mob\living\silicon\ai\vox_sounds.dm"
#include "modular_citadel\code\modules\mob\living\silicon\robot\dogborg_equipment.dm"
#include "modular_citadel\code\modules\mob\living\silicon\robot\robot.dm"
#include "modular_citadel\code\modules\mob\living\silicon\robot\robot_modules.dm"
#include "modular_citadel\code\modules\mob\living\silicon\robot\robot_movement.dm"
-#include "modular_citadel\code\modules\mob\living\simple_animal\banana_spider.dm"
-#include "modular_citadel\code\modules\mob\living\simple_animal\kiwi.dm"
#include "modular_citadel\code\modules\power\lighting.dm"
#include "modular_citadel\code\modules\projectiles\gun.dm"
#include "modular_citadel\code\modules\projectiles\ammunition\caseless.dm"
@@ -3134,15 +3133,9 @@
#include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm"
#include "modular_citadel\code\modules\reagents\objects\clothes.dm"
#include "modular_citadel\code\modules\reagents\objects\items.dm"
-#include "modular_citadel\code\modules\reagents\reagent container\hypospraymkii.dm"
-#include "modular_citadel\code\modules\reagents\reagent container\hypovial.dm"
#include "modular_citadel\code\modules\reagents\reagents\cit_reagents.dm"
#include "modular_citadel\code\modules\recycling\disposal\bin.dm"
#include "modular_citadel\code\modules\research\designs\autoylathe_designs.dm"
-#include "modular_citadel\code\modules\research\designs\machine_designs.dm"
-#include "modular_citadel\code\modules\research\designs\xenobio_designs.dm"
-#include "modular_citadel\code\modules\research\techweb\_techweb.dm"
-#include "modular_citadel\code\modules\research\xenobiology\xenobio_camera.dm"
#include "modular_citadel\code\modules\vehicles\secway.dm"
#include "modular_citadel\interface\skin.dmf"
// END_INCLUDE
diff --git a/tools/mapmerge2/requirements.txt b/tools/mapmerge2/requirements.txt
index adb42438e7..d24cb40dcc 100644
--- a/tools/mapmerge2/requirements.txt
+++ b/tools/mapmerge2/requirements.txt
@@ -1,3 +1,3 @@
pygit2==0.27.2
bidict==0.13.1
-Pillow==5.1.0
+Pillow==6.2.0