diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index a014d30878e..2b4c3586bf9 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -9,15 +9,27 @@ assignees: ''
**Issue Description**:
+
+
**What did you expect to happen**:
+
+
**What happened instead**:
+
+
**Why is this bad/What are the consequences**:
+
+
**Steps to reproduce the problem**:
+
+
**When did the problem start happening**:
+
+
**Extra information**:
diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm
index fb8cbaf4304..37231b29651 100644
--- a/_maps/map_files/Delta/delta.dmm
+++ b/_maps/map_files/Delta/delta.dmm
@@ -49652,8 +49652,8 @@
/obj/item/radio/intercom{
pixel_y = 28
},
-/obj/machinery/deployable/barrier,
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
+/obj/item/grenade/barrier,
/turf/simulated/floor/plasteel{
icon_state = "vault";
dir = 8
@@ -49673,8 +49673,8 @@
},
/area/security/armoury)
"bLK" = (
-/obj/machinery/deployable/barrier,
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
+/obj/item/grenade/barrier,
/turf/simulated/floor/plasteel{
icon_state = "vault";
dir = 8
diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
index 5c09a328037..ccfadc2ab79 100644
--- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
@@ -4795,10 +4795,10 @@
/obj/structure/reagent_dispensers/peppertank{
pixel_y = 29
},
-/obj/machinery/deployable/barrier,
-/obj/machinery/deployable/barrier,
-/obj/machinery/deployable/barrier,
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
+/obj/item/grenade/barrier,
+/obj/item/grenade/barrier,
+/obj/item/grenade/barrier,
/turf/simulated/floor/plasteel{
tag = "icon-vault (WEST)";
icon_state = "vault";
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
new file mode 100644
index 00000000000..41d298fffb1
--- /dev/null
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
@@ -0,0 +1,2238 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/turf/template_noop,
+/area/template_noop)
+"ab" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"ac" = (
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"ad" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"ae" = (
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"af" = (
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ag" = (
+/obj/effect/mob_spawn/human/corpse/damaged,
+/obj/effect/decal/cleanable/blood/old,
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ah" = (
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ai" = (
+/obj/structure/disposalpipe/sortjunction{
+ dir = 1
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"aj" = (
+/obj/effect/decal/cleanable/pie_smudge,
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ak" = (
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"al" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"am" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"an" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ao" = (
+/obj/structure/window/reinforced,
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"ap" = (
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aq" = (
+/obj/structure/disposalpipe/trunk,
+/obj/structure/disposaloutlet{
+ dir = 1
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"ar" = (
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"as" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"at" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/decal/cleanable/cobweb,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"au" = (
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"av" = (
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aw" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"ay" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"az" = (
+/obj/item/bikehorn,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aA" = (
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"aB" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/decal/cleanable/pie_smudge,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aC" = (
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aD" = (
+/obj/item/bikehorn,
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aE" = (
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"aF" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aG" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aH" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aI" = (
+/obj/item/bikehorn,
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aJ" = (
+/obj/item/bikehorn,
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aK" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"aL" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"aM" = (
+/obj/effect/decal/cleanable/pie_smudge,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aN" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aO" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aP" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"aQ" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/structure/table,
+/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/escape,
+/obj/item/pen/multi,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aR" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/structure/table,
+/obj/item/flashlight/lamp/bananalamp,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aS" = (
+/obj/effect/decal/cleanable/pie_smudge,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"aT" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/item/pickaxe,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aU" = (
+/obj/effect/spawner/window/reinforced,
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"aV" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aW" = (
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aX" = (
+/obj/structure/disposalpipe/trunk{
+ dir = 4
+ },
+/obj/structure/disposaloutlet{
+ dir = 8
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"aY" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"aZ" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/simulated/floor/light,
+/area/ruin/powered/clownplanet)
+"ba" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bb" = (
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bc" = (
+/turf/simulated/floor/light,
+/area/ruin/powered/clownplanet)
+"bd" = (
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"be" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bf" = (
+/turf/simulated/mineral/clown/volcanic,
+/area/ruin/powered/clownplanet)
+"bg" = (
+/obj/item/pickaxe,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bh" = (
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bi" = (
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"bj" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bk" = (
+/obj/structure/disposalpipe/segment{
+ dir = 1;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"bl" = (
+/obj/item/bikehorn,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bm" = (
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"bn" = (
+/obj/effect/decal/cleanable/cobweb,
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"bo" = (
+/obj/structure/disposalpipe/segment,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bp" = (
+/obj/effect/decal/cleanable/pie_smudge,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow,
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bq" = (
+/obj/machinery/disposal/deliveryChute{
+ dir = 1
+ },
+/obj/structure/disposalpipe/trunk,
+/turf/simulated/floor/plasteel{
+ dir = 4;
+ icon_state = "white"
+ },
+/area/ruin/powered/clownplanet)
+"br" = (
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"bs" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"bt" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/structure/disposalpipe/junction{
+ dir = 1;
+ icon_state = "pipe-y"
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bu" = (
+/obj/effect/decal/cleanable/blood/oil,
+/obj/structure/disposalpipe/segment{
+ dir = 2;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"bv" = (
+/obj/effect/mob_spawn/human/corpse/damaged,
+/obj/effect/decal/cleanable/blood/old,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"bw" = (
+/obj/effect/turf_decal/tile/red,
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 1
+ },
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/floor/plasteel,
+/area/ruin/powered/clownplanet)
+"bx" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/yellow,
+/obj/effect/turf_decal/tile/yellow{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 8
+ },
+/obj/effect/turf_decal/tile/yellow{
+ dir = 4
+ },
+/obj/effect/baseturf_helper/lava_land/surface,
+/turf/simulated/floor/lubed,
+/area/ruin/powered/clownplanet)
+"by" = (
+/obj/structure/table/glass,
+/obj/item/gun/magic/staff/slipping,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bB" = (
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"bD" = (
+/obj/effect/decal/mecha_wreckage/honker,
+/obj/structure/disposalpipe/segment{
+ dir = 4;
+ invisibility = 101
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"bH" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"bL" = (
+/obj/item/reagent_containers/food/drinks/trophy/gold_cup,
+/obj/structure/table/glass,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bM" = (
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bN" = (
+/obj/machinery/disposal/deliveryChute,
+/obj/structure/disposalpipe/trunk{
+ dir = 1
+ },
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bO" = (
+/obj/effect/decal/cleanable/cobweb,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"bP" = (
+/obj/structure/statue/bananium/clown,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bQ" = (
+/obj/structure/table/glass,
+/obj/item/grown/bananapeel/bluespace,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bR" = (
+/obj/structure/table/glass,
+/obj/item/clothing/shoes/magboots/clown,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bS" = (
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bT" = (
+/obj/item/slime_extract/rainbow,
+/obj/structure/table/glass,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bU" = (
+/obj/item/bikehorn/airhorn,
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"bW" = (
+/obj/item/bikehorn,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"bY" = (
+/obj/effect/mob_spawn/human/corpse/damaged,
+/obj/effect/decal/cleanable/blood/old,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"bZ" = (
+/obj/machinery/door/airlock/bananium,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"ca" = (
+/obj/item/bikehorn,
+/obj/effect/decal/cleanable/dirt,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"cc" = (
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"ch" = (
+/obj/structure/disposalpipe/segment{
+ invisibility = 101
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"cu" = (
+/turf/simulated/floor/plating,
+/area/ruin/powered/clownplanet)
+"dK" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"dL" = (
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/item/coin/clown,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/simulated/floor/carpet,
+/area/ruin/powered/clownplanet)
+"dM" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"dO" = (
+/obj/machinery/light,
+/turf/simulated/floor/mineral/bananium/lubed,
+/area/ruin/powered/clownplanet)
+"eX" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/lavaland/surface/outdoors/explored)
+"gX" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/chasm/straight_down/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"hY" = (
+/obj/machinery/light,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/ruin/powered/clownplanet)
+"pv" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/ruin/powered/clownplanet)
+"ye" = (
+/turf/simulated/floor/plating/lava/smooth,
+/area/ruin/powered/clownplanet)
+"CB" = (
+/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/hope,
+/obj/effect/decal/cleanable/blood/old,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/lavaland/surface/outdoors/explored)
+"KX" = (
+/obj/item/grown/bananapeel{
+ color = "#2F3000";
+ name = "stealth banana peel"
+ },
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"LH" = (
+/obj/machinery/disposal/deliveryChute{
+ desc = "The following is engraved upon the chute: A FATE WORSE THAN DEATH LIES WITHIN";
+ dir = 1;
+ name = "THE TRIAL OF HONKITUDE"
+ },
+/obj/structure/disposalpipe/trunk,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/ruin/powered/clownplanet)
+"Mv" = (
+/obj/effect/mapping_helpers/no_lava,
+/mob/living/simple_animal/hostile/retaliate/clown,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"MR" = (
+/obj/machinery/light{
+ dir = 8
+ },
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/ruin/powered/clownplanet)
+"TD" = (
+/obj/structure/disposalpipe/trunk,
+/obj/structure/disposaloutlet{
+ dir = 1
+ },
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/ruin/powered/clownplanet)
+"VH" = (
+/obj/structure/disposalpipe/segment{
+ dir = 8;
+ icon_state = "pipe-c"
+ },
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/clownplanet)
+"Xm" = (
+/obj/item/clothing/head/cone,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/lavaland/surface/outdoors/explored)
+"XO" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"Yf" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/ruin/powered/clownplanet)
+"YI" = (
+/obj/machinery/light/small,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/noslip/lavaland,
+/area/ruin/powered/clownplanet)
+
+(1,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+XO
+XO
+XO
+XO
+XO
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(2,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+cc
+cc
+cc
+cc
+cc
+cc
+cc
+pv
+XO
+gX
+XO
+XO
+gX
+pv
+cc
+cc
+cc
+cc
+cc
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(3,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+cc
+cc
+cc
+ye
+ye
+ye
+ye
+ye
+cc
+cc
+gX
+gX
+KX
+gX
+gX
+cc
+cc
+ye
+ye
+ye
+cc
+cc
+cc
+aa
+aa
+aa
+aa
+"}
+(4,1,1) = {"
+aa
+aa
+aa
+aa
+cc
+cc
+ye
+ye
+ye
+ab
+aA
+ab
+aA
+ye
+cc
+cc
+gX
+gX
+gX
+cc
+cc
+ye
+ye
+aU
+cu
+ye
+ye
+cc
+cc
+aa
+aa
+aa
+"}
+(5,1,1) = {"
+aa
+aa
+aa
+cc
+cc
+ye
+ye
+ab
+ch
+VH
+aH
+ay
+aS
+aA
+ye
+cc
+cc
+cc
+cc
+cc
+bO
+bB
+aU
+ye
+ye
+ye
+ye
+ye
+cc
+cc
+aa
+aa
+"}
+(6,1,1) = {"
+aa
+aa
+aa
+cc
+ye
+ye
+cc
+at
+ah
+af
+aI
+af
+av
+aL
+ye
+cc
+bB
+bH
+bB
+cc
+bB
+bH
+bY
+bB
+aU
+ye
+aU
+ye
+ye
+cc
+Yf
+aa
+"}
+(7,1,1) = {"
+aa
+aa
+cc
+cc
+ye
+ab
+aj
+ap
+am
+ah
+af
+aA
+aL
+aL
+cc
+bn
+br
+bB
+bH
+bH
+bB
+bH
+bB
+bB
+bB
+cc
+ye
+cu
+ye
+cc
+cc
+aa
+"}
+(8,1,1) = {"
+aa
+aa
+cc
+ye
+ye
+ae
+af
+av
+am
+aL
+aX
+aL
+aN
+aY
+bf
+cc
+bs
+br
+bB
+cc
+cc
+bH
+cc
+bB
+bB
+bB
+aU
+ye
+ye
+ye
+cc
+aa
+"}
+(9,1,1) = {"
+aa
+aa
+cc
+ye
+ab
+af
+af
+ay
+an
+an
+aL
+aN
+aN
+aN
+bg
+bf
+cc
+cc
+br
+bB
+bB
+bH
+bB
+bB
+ca
+bH
+dO
+cc
+ye
+ye
+cc
+aa
+"}
+(10,1,1) = {"
+aa
+Mv
+cc
+ye
+ac
+ag
+af
+av
+aL
+am
+aL
+aN
+aN
+aZ
+bc
+bh
+br
+br
+br
+bB
+cc
+bB
+bB
+bH
+bH
+bB
+bB
+ye
+aU
+ye
+cc
+cc
+"}
+(11,1,1) = {"
+aa
+hY
+cc
+ye
+ad
+ch
+ak
+ay
+am
+am
+aL
+aN
+aT
+aZ
+bc
+bf
+cc
+br
+br
+bB
+bB
+cc
+bB
+bB
+bB
+bB
+bH
+ye
+aU
+ye
+ye
+cc
+"}
+(12,1,1) = {"
+aa
+Mv
+cc
+ye
+ae
+af
+af
+az
+am
+ac
+ap
+aL
+aN
+ba
+bh
+cc
+cc
+br
+bB
+bB
+cc
+cc
+bB
+bB
+cc
+bB
+bH
+ye
+cu
+aU
+ye
+cc
+"}
+(13,1,1) = {"
+XO
+Mv
+cc
+ye
+cc
+ah
+af
+ap
+aC
+aj
+af
+ap
+aL
+aL
+bi
+ch
+aA
+cc
+cc
+cc
+bP
+bS
+cc
+dM
+bB
+bH
+ca
+bB
+ye
+aU
+ye
+cc
+"}
+(14,1,1) = {"
+XO
+Xm
+cc
+cc
+ye
+ac
+af
+af
+af
+af
+aJ
+af
+ay
+an
+bj
+al
+am
+cc
+cc
+bL
+bM
+bM
+bM
+cc
+bB
+bH
+bH
+bB
+ye
+aU
+ye
+cc
+"}
+(15,1,1) = {"
+eX
+eX
+LH
+ch
+ch
+au
+af
+ch
+af
+aF
+ch
+aj
+af
+ay
+as
+an
+aC
+av
+cc
+dK
+bQ
+bT
+bM
+cc
+cc
+bH
+bB
+bB
+ye
+aU
+ye
+cc
+"}
+(16,1,1) = {"
+eX
+CB
+YI
+cc
+ye
+cu
+ah
+aA
+ah
+av
+ah
+af
+af
+au
+bk
+aC
+av
+bj
+ch
+bN
+bM
+bU
+bM
+bZ
+bB
+bH
+bB
+cc
+ye
+aU
+ye
+cc
+"}
+(17,1,1) = {"
+eX
+eX
+TD
+ch
+ch
+ai
+ay
+an
+an
+aL
+an
+aO
+af
+av
+bl
+bo
+bt
+bx
+cc
+bM
+bR
+by
+bM
+cc
+bB
+bB
+bB
+bB
+ye
+aU
+ye
+cc
+"}
+(18,1,1) = {"
+XO
+eX
+cc
+cc
+ye
+aL
+as
+am
+am
+an
+an
+an
+ar
+aC
+av
+bp
+aL
+bv
+cc
+bL
+bM
+bM
+bM
+cc
+bB
+bB
+bB
+bB
+ye
+aU
+ye
+cc
+"}
+(19,1,1) = {"
+XO
+Mv
+cc
+ye
+ye
+aL
+as
+am
+aD
+an
+an
+aL
+cc
+cc
+aK
+cc
+bD
+cc
+bB
+cc
+bP
+dL
+cc
+dM
+bB
+bH
+bH
+bB
+ye
+aU
+ye
+cc
+"}
+(20,1,1) = {"
+aa
+Mv
+cc
+ye
+cc
+aL
+ar
+an
+an
+am
+an
+aL
+aV
+bb
+bm
+cc
+bu
+aA
+bB
+bB
+cc
+cc
+bY
+bB
+bB
+bH
+bB
+ye
+aU
+cu
+ye
+cc
+"}
+(21,1,1) = {"
+aa
+hY
+cc
+ye
+cc
+aL
+aw
+aB
+aL
+am
+aL
+aQ
+aN
+bc
+bc
+bf
+cc
+aK
+br
+bB
+bB
+cc
+bB
+bH
+bB
+bB
+bB
+ye
+aU
+ye
+ye
+cc
+"}
+(22,1,1) = {"
+aa
+Mv
+cc
+ye
+aq
+ao
+ar
+aL
+aP
+am
+aL
+aR
+aN
+bc
+bc
+bq
+ch
+bw
+cc
+bB
+bB
+bH
+bH
+bH
+bB
+bW
+dO
+cc
+aU
+ye
+cc
+cc
+"}
+(23,1,1) = {"
+aa
+aa
+cc
+ye
+cc
+cc
+ar
+an
+an
+aD
+aK
+aN
+aW
+bd
+bh
+bf
+cc
+br
+br
+bB
+bB
+bH
+bH
+bB
+bB
+cc
+cc
+ye
+cu
+ye
+cc
+aa
+"}
+(24,1,1) = {"
+aa
+aa
+cc
+ye
+cc
+cc
+as
+an
+aL
+an
+aL
+aL
+aV
+be
+bf
+cc
+bs
+br
+bB
+bB
+bB
+bB
+bB
+cc
+bB
+bB
+ye
+cu
+ye
+ye
+cc
+aa
+"}
+(25,1,1) = {"
+aa
+aa
+cc
+ye
+ye
+cc
+ar
+an
+an
+an
+aC
+ap
+aL
+cc
+cc
+br
+br
+bB
+bB
+bB
+bH
+bW
+bB
+bB
+bB
+cc
+ye
+aU
+ye
+cc
+cc
+aa
+"}
+(26,1,1) = {"
+aa
+aa
+cc
+cc
+ye
+cc
+cc
+aC
+ap
+aG
+af
+af
+aE
+cc
+ye
+cc
+bO
+bB
+bB
+cc
+bB
+bB
+cc
+bB
+bB
+ye
+cu
+ye
+ye
+cc
+Yf
+aa
+"}
+(27,1,1) = {"
+aa
+aa
+aa
+cc
+cc
+ye
+ye
+cc
+cu
+cc
+aM
+ar
+cu
+cc
+ye
+cc
+cc
+cc
+cc
+cc
+bB
+bB
+bB
+ye
+ye
+ye
+ye
+ye
+cc
+cc
+aa
+aa
+"}
+(28,1,1) = {"
+aa
+aa
+aa
+aa
+cc
+cc
+ye
+ye
+ye
+aU
+aU
+aU
+cc
+ye
+cc
+cc
+gX
+gX
+gX
+cc
+cc
+ye
+ye
+cu
+aU
+ye
+ye
+cc
+cc
+aa
+aa
+aa
+"}
+(29,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+cc
+cc
+cc
+ye
+ye
+ye
+ye
+ye
+cc
+cc
+gX
+gX
+KX
+gX
+gX
+cc
+cc
+ye
+ye
+ye
+cc
+cc
+cc
+aa
+aa
+aa
+aa
+"}
+(30,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+cc
+cc
+cc
+cc
+cc
+cc
+cc
+MR
+XO
+XO
+XO
+XO
+gX
+MR
+cc
+cc
+cc
+cc
+cc
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(31,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+XO
+gX
+XO
+XO
+XO
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm
new file mode 100644
index 00000000000..01797b0ea59
--- /dev/null
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm
@@ -0,0 +1,1364 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/turf/template_noop,
+/area/template_noop)
+"ab" = (
+/obj/effect/baseturf_helper/lava_land/surface,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"ac" = (
+/obj/item/stack/medical/ointment,
+/obj/structure/table,
+/obj/item/stack/medical/bruise_pack,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ad" = (
+/obj/structure/table,
+/obj/item/stack/medical/bruise_pack,
+/obj/item/stack/medical/bruise_pack,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ae" = (
+/obj/machinery/power/smes,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"af" = (
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ag" = (
+/obj/structure/reagent_dispensers/beerkeg,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ah" = (
+/obj/item/reagent_containers/food/drinks/mug,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ai" = (
+/obj/machinery/shower,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"aj" = (
+/obj/structure/sink,
+/obj/machinery/light/small{
+ dir = 1
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ak" = (
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"al" = (
+/obj/effect/decal/cleanable/blood/oil,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"am" = (
+/obj/machinery/door/airlock/hatch,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"an" = (
+/obj/structure/toilet{
+ dir = 8
+ },
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"ao" = (
+/turf/simulated/floor/plating/ice/smooth,
+/area/ruin/powered/snow_biodome)
+"ap" = (
+/obj/structure/flora/rock/icy,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aq" = (
+/turf/simulated/wall/mineral/wood,
+/area/ruin/powered/snow_cabin)
+"ar" = (
+/obj/machinery/door/airlock/wood,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_cabin)
+"as" = (
+/obj/structure/fans,
+/turf/simulated/wall/mineral/wood,
+/area/ruin/powered/snow_cabin)
+"at" = (
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"au" = (
+/obj/structure/bed,
+/obj/item/bedsheet/blue,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"av" = (
+/obj/structure/bookcase/random,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aw" = (
+/obj/structure/table/wood,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"ax" = (
+/obj/structure/table/wood,
+/obj/item/reagent_containers/food/snacks/beans,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"ay" = (
+/obj/structure/closet/crate/trashcart,
+/obj/item/trash/semki,
+/obj/item/trash/candy,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"az" = (
+/obj/structure/flora/tree/pine,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aA" = (
+/obj/structure/chair/comfy/brown{
+ dir = 4
+ },
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aB" = (
+/obj/structure/flora/rock/pile/icy,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aC" = (
+/obj/structure/flora/tree/dead,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aD" = (
+/obj/machinery/door/airlock/wood,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aE" = (
+/obj/structure/extinguisher_cabinet,
+/turf/simulated/wall/mineral/wood,
+/area/ruin/powered/snow_cabin)
+"aF" = (
+/obj/structure/table/wood,
+/obj/item/reagent_containers/food/drinks/h_chocolate,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aG" = (
+/obj/structure/chair/comfy/brown{
+ dir = 8
+ },
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aH" = (
+/mob/living/simple_animal/hostile/skeleton/eskimo,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aI" = (
+/obj/structure/flora/bush,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aJ" = (
+/obj/vehicle/atv,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aK" = (
+/obj/structure/table/wood,
+/obj/item/key/snowmobile,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aL" = (
+/obj/structure/displaycase/lavaland_winter,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aM" = (
+/turf/simulated/floor/carpet,
+/area/ruin/powered/snow_cabin)
+"aN" = (
+/obj/structure/bed/dogbed,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"aO" = (
+/obj/machinery/door/airlock/multi_tile/glass,
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"aP" = (
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"aQ" = (
+/obj/structure/flora/grass/both,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"aR" = (
+/obj/structure/flora/tree/pine/xmas,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"bi" = (
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_cabin)
+"bl" = (
+/turf/simulated/floor/wood/cold,
+/area/ruin/powered/snow_biodome)
+"bv" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/simulated/floor/plating/ice/smooth,
+/area/ruin/powered/snow_biodome)
+"bw" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"bx" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"by" = (
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"bz" = (
+/obj/machinery/light,
+/turf/simulated/floor/wood,
+/area/ruin/powered/snow_cabin)
+"bB" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"bD" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"bM" = (
+/obj/machinery/light,
+/turf/simulated/floor/plating/asteroid/snow/atmosphere,
+/area/ruin/powered/snow_biodome)
+"bN" = (
+/obj/machinery/light,
+/turf/simulated/floor/plating/ice/smooth,
+/area/ruin/powered/snow_biodome)
+"dS" = (
+/obj/machinery/light/small,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"eb" = (
+/obj/machinery/light/small{
+ dir = 4
+ },
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"eg" = (
+/obj/machinery/vending/coffee,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"gh" = (
+/obj/machinery/light/small{
+ dir = 8
+ },
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"gz" = (
+/obj/structure/chair/stool,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"hA" = (
+/obj/machinery/light/built{
+ dir = 1
+ },
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"qt" = (
+/obj/machinery/door/airlock/silver,
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"tb" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"tl" = (
+/turf/simulated/floor/pod/light,
+/area/ruin/powered/snow_biodome)
+"vf" = (
+/obj/machinery/door/airlock/multi_tile/glass,
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_cabin)
+"xU" = (
+/obj/item/storage/toolbox/mechanical,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"zT" = (
+/obj/machinery/door/airlock/silver,
+/obj/structure/fans/tiny,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"AM" = (
+/obj/structure/table,
+/obj/item/pen,
+/obj/item/paper,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Dd" = (
+/obj/structure/rack,
+/obj/item/clothing/suit/hooded/wintercoat/science,
+/obj/item/clothing/shoes/winterboots,
+/obj/item/clothing/gloves/fingerless,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Ef" = (
+/obj/structure/reagent_dispensers/fueltank,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Ez" = (
+/obj/structure/fans/tiny,
+/obj/machinery/door/airlock/multi_tile/glass,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"HP" = (
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"HR" = (
+/obj/structure/closet/secure_closet/freezer/fridge/open,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"JZ" = (
+/obj/structure/table,
+/obj/machinery/microwave,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"KS" = (
+/obj/structure/closet,
+/obj/machinery/light/small{
+ dir = 4
+ },
+/obj/item/twohanded/required/chainsaw,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Mp" = (
+/obj/item/clothing/mask/balaclava,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Oj" = (
+/obj/structure/table,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"PD" = (
+/obj/machinery/door/airlock/hatch,
+/obj/structure/fans/tiny,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"PK" = (
+/obj/structure/table,
+/obj/item/pen,
+/obj/item/paper_bin,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Qa" = (
+/obj/effect/mapping_helpers/no_lava,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"QI" = (
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors/explored)
+"QK" = (
+/obj/structure/table,
+/obj/item/storage/fancy/cigarettes/cigpack_carp,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"QN" = (
+/obj/effect/spawner/window,
+/turf/simulated/floor/plating,
+/area/ruin/powered/snow_biodome)
+"Sj" = (
+/obj/effect/decal/cleanable/blood/oil,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Ub" = (
+/obj/structure/filingcabinet,
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"UM" = (
+/obj/machinery/computer/monitor/secret{
+ dir = 1
+ },
+/turf/simulated/floor/pod/dark,
+/area/ruin/powered/snow_biodome)
+"Wg" = (
+/turf/simulated/wall/r_wall,
+/area/ruin/powered/snow_biodome)
+
+(1,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+Wg
+PD
+Wg
+Wg
+Wg
+Wg
+Wg
+Wg
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(2,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+Wg
+Wg
+Dd
+gh
+HP
+tl
+gh
+HP
+Ub
+Wg
+Wg
+Wg
+Wg
+Wg
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(3,1,1) = {"
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+ak
+by
+ak
+Wg
+Dd
+HP
+HP
+tl
+PK
+gz
+UM
+Wg
+ak
+ak
+ak
+Wg
+Wg
+Wg
+QI
+QI
+aa
+aa
+aa
+"}
+(4,1,1) = {"
+aa
+aa
+aa
+Wg
+Wg
+ak
+aC
+ak
+ak
+ak
+Wg
+QN
+QN
+QN
+qt
+QN
+QN
+QN
+Wg
+ak
+ak
+ak
+ak
+ak
+Wg
+Wg
+QI
+QI
+aa
+aa
+"}
+(5,1,1) = {"
+aa
+aa
+Wg
+Wg
+ao
+ao
+ak
+aI
+ak
+ak
+by
+az
+ak
+aB
+ak
+ak
+ak
+aI
+by
+ak
+ak
+ak
+ak
+ak
+ak
+Wg
+Wg
+QI
+tb
+aa
+"}
+(6,1,1) = {"
+aa
+aa
+Wg
+bv
+ao
+ao
+ao
+ao
+ak
+aI
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+aQ
+ak
+ak
+ak
+az
+ak
+ak
+Wg
+QI
+tb
+aa
+"}
+(7,1,1) = {"
+aa
+Wg
+Wg
+ap
+ak
+ao
+ao
+ao
+ao
+ak
+ak
+ak
+ak
+ak
+az
+ak
+aC
+ak
+ak
+aI
+aI
+ak
+ak
+ak
+ak
+bM
+Wg
+Wg
+tb
+aa
+"}
+(8,1,1) = {"
+aa
+Wg
+ak
+ak
+ak
+ak
+ak
+ao
+ao
+ao
+ao
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ap
+aI
+ak
+aQ
+ak
+ak
+ak
+az
+ak
+Wg
+tb
+tb
+"}
+(9,1,1) = {"
+aa
+Wg
+Wg
+Wg
+ak
+az
+ak
+ak
+ao
+ao
+ao
+ao
+ao
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+aC
+ak
+ak
+ak
+ak
+ak
+Wg
+hA
+tb
+"}
+(10,1,1) = {"
+Wg
+Wg
+af
+Wg
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ao
+ao
+ao
+ao
+ak
+aI
+az
+ak
+ak
+ak
+ak
+ak
+aI
+ak
+ak
+ak
+Wg
+tb
+tb
+"}
+(11,1,1) = {"
+Wg
+ac
+af
+aq
+aq
+aq
+aq
+aq
+aq
+aq
+bD
+ao
+ao
+ao
+ao
+ao
+ak
+ak
+bl
+bl
+ak
+aI
+ak
+ak
+ak
+Wg
+Wg
+Wg
+Wg
+tb
+"}
+(12,1,1) = {"
+Wg
+ad
+af
+ar
+bw
+at
+aD
+at
+aL
+aq
+ak
+az
+ak
+ao
+ao
+ao
+ao
+ao
+bl
+bl
+ak
+ak
+ak
+az
+bM
+Wg
+Dd
+Dd
+Wg
+tb
+"}
+(13,1,1) = {"
+Wg
+ae
+af
+aq
+au
+au
+aq
+at
+bz
+aq
+ak
+ak
+ak
+ao
+ao
+ao
+ao
+ao
+bl
+bl
+ao
+ak
+ak
+ak
+aI
+Wg
+Mp
+dS
+Wg
+tb
+"}
+(14,1,1) = {"
+Wg
+af
+al
+aq
+aq
+aq
+aE
+at
+at
+aq
+ak
+ak
+aC
+ak
+ao
+ak
+ao
+ao
+bl
+bl
+ao
+ao
+aI
+ak
+ak
+Wg
+tl
+tl
+Wg
+tb
+"}
+(15,1,1) = {"
+Wg
+ae
+af
+aq
+av
+at
+at
+aH
+aM
+vf
+ap
+ak
+ak
+ak
+ak
+ak
+ak
+ao
+bl
+bl
+ao
+ao
+ak
+ak
+ak
+aO
+tl
+tl
+Ez
+Qa
+"}
+(16,1,1) = {"
+Wg
+ag
+ah
+as
+aw
+aA
+aA
+at
+aM
+bi
+ak
+ak
+aQ
+ak
+ak
+az
+ak
+ak
+bl
+bl
+ak
+ao
+ao
+ak
+ak
+aP
+tl
+tl
+aP
+Qa
+"}
+(17,1,1) = {"
+Wg
+ah
+af
+aq
+ax
+aK
+aF
+at
+at
+aq
+ak
+aI
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ao
+ao
+ao
+ak
+Wg
+tl
+tl
+Wg
+tb
+"}
+(18,1,1) = {"
+Wg
+Wg
+am
+aq
+av
+at
+aG
+at
+bz
+aq
+aR
+ak
+ak
+ak
+ak
+ab
+ak
+ak
+aC
+ak
+ak
+ak
+ao
+ao
+ao
+Wg
+HP
+dS
+Wg
+tb
+"}
+(19,1,1) = {"
+Wg
+ai
+af
+aq
+av
+bx
+aH
+at
+aN
+aq
+ak
+ak
+ak
+az
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ao
+bN
+Wg
+QK
+AM
+Wg
+tb
+"}
+(20,1,1) = {"
+Wg
+aj
+af
+aq
+aq
+aq
+aq
+aq
+aq
+aq
+bD
+ak
+ak
+ak
+ak
+aI
+ak
+az
+ak
+ak
+ak
+ak
+az
+ak
+ao
+Wg
+Wg
+Wg
+Wg
+tb
+"}
+(21,1,1) = {"
+Wg
+Wg
+an
+Wg
+ay
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+aC
+ak
+ak
+ak
+ak
+ap
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+Wg
+tb
+tb
+"}
+(22,1,1) = {"
+aa
+Wg
+Wg
+Wg
+ak
+ak
+aI
+ak
+ap
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+ak
+aI
+ak
+ak
+aQ
+ak
+ak
+ak
+Wg
+hA
+tb
+"}
+(23,1,1) = {"
+aa
+Wg
+ak
+ak
+az
+ak
+aJ
+ak
+ak
+ak
+ak
+ak
+ak
+az
+ak
+aQ
+ak
+aC
+ak
+aI
+ak
+az
+aI
+aI
+ak
+ak
+ak
+Wg
+tb
+tb
+"}
+(24,1,1) = {"
+aa
+Wg
+Wg
+ak
+ak
+aB
+ak
+ak
+aC
+ak
+ak
+ak
+ak
+aI
+ak
+ap
+ak
+ak
+ak
+ak
+ak
+ak
+aI
+aI
+ak
+bM
+Wg
+Wg
+tb
+aa
+"}
+(25,1,1) = {"
+aa
+aa
+Wg
+ap
+ak
+ak
+ak
+ak
+ak
+aQ
+ak
+ak
+ak
+aI
+ak
+ak
+ak
+ak
+aQ
+ak
+ak
+aB
+ak
+ak
+aC
+ak
+Wg
+QI
+tb
+aa
+"}
+(26,1,1) = {"
+aa
+aa
+Wg
+Wg
+ak
+ak
+az
+ak
+ak
+ak
+bB
+ak
+ak
+ak
+ak
+ak
+az
+ak
+bB
+ak
+ak
+az
+ak
+ak
+ak
+Wg
+Wg
+QI
+aa
+aa
+"}
+(27,1,1) = {"
+aa
+aa
+aa
+Wg
+Wg
+ak
+ak
+ak
+ak
+ak
+Wg
+QN
+QN
+QN
+zT
+QN
+QN
+QN
+Wg
+ak
+ak
+ak
+ak
+ak
+Wg
+Wg
+QI
+QI
+aa
+aa
+"}
+(28,1,1) = {"
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+ak
+bB
+ak
+Wg
+eg
+HP
+tl
+tl
+tl
+Sj
+xU
+Wg
+ak
+bB
+ak
+Wg
+Wg
+Wg
+QI
+QI
+aa
+aa
+aa
+"}
+(29,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+Wg
+Wg
+HR
+eb
+gz
+Oj
+JZ
+KS
+Ef
+Wg
+Wg
+Wg
+Wg
+Wg
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(30,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+Wg
+Wg
+Wg
+Wg
+Wg
+Wg
+Wg
+Wg
+Wg
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
index 8bf85306742..18ff8e4f1bc 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
@@ -1066,6 +1066,7 @@
/obj/structure/stone_tile/block/cracked{
dir = 1
},
+/obj/item/cultivator/rake,
/obj/effect/mapping_helpers/no_lava,
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
@@ -1305,6 +1306,7 @@
dir = 8
},
/obj/structure/stone_tile/center,
+/obj/item/hatchet/wooden,
/obj/effect/mapping_helpers/no_lava,
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
@@ -1326,10 +1328,10 @@
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"dw" = (
-/obj/item/reagent_containers/glass/bucket,
/obj/structure/stone_tile/block/cracked{
dir = 4
},
+/obj/item/reagent_containers/glass/bucket/wooden,
/obj/effect/mapping_helpers/no_lava,
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
diff --git a/_maps/map_files/RandomZLevels/beach.dmm b/_maps/map_files/RandomZLevels/beach.dmm
index 2931d7175b7..fe4060ad52d 100644
--- a/_maps/map_files/RandomZLevels/beach.dmm
+++ b/_maps/map_files/RandomZLevels/beach.dmm
@@ -13,7 +13,7 @@
/turf/unsimulated/beach/water/deep/rock_wall,
/area/awaymission/undersea)
"ae" = (
-/obj/structure/ladder/dive_point/anchor{
+/obj/structure/ladder/unbreakable/dive_point/anchor{
id = "pirate"
},
/turf/unsimulated/beach/water/deep/sand_floor,
@@ -217,7 +217,7 @@
/turf/unsimulated/beach/water/deep/wood_floor,
/area/awaymission/undersea)
"aU" = (
-/obj/structure/ladder/dive_point/anchor,
+/obj/structure/ladder/unbreakable/dive_point/anchor,
/turf/unsimulated/beach/water/deep/sand_floor,
/area/awaymission/undersea)
"aV" = (
@@ -1113,7 +1113,7 @@
/turf/unsimulated/beach/water/deep,
/area/awaymission/beach)
"dv" = (
-/obj/structure/ladder/dive_point/buoy,
+/obj/structure/ladder/unbreakable/dive_point/buoy,
/turf/unsimulated/beach/water/deep,
/area/awaymission/beach)
"dw" = (
@@ -1306,7 +1306,7 @@
},
/area/awaymission/beach)
"dW" = (
-/obj/structure/ladder/dive_point/buoy{
+/obj/structure/ladder/unbreakable/dive_point/buoy{
id = "pirate"
},
/turf/unsimulated/beach/water,
diff --git a/_maps/map_files/RandomZLevels/example.dmm b/_maps/map_files/RandomZLevels/example.dmm
index fd85d240c36..779a0bede34 100644
--- a/_maps/map_files/RandomZLevels/example.dmm
+++ b/_maps/map_files/RandomZLevels/example.dmm
@@ -261,7 +261,7 @@
/turf/simulated/floor/plasteel,
/area/awaymission/example)
"aH" = (
-/obj/structure/ladder{
+/obj/structure/ladder/unbreakable{
height = 1;
id = "example"
},
@@ -782,7 +782,7 @@
/turf/simulated/floor/plasteel,
/area/awaymission/example)
"ca" = (
-/obj/structure/ladder{
+/obj/structure/ladder/unbreakable{
id = "example"
},
/turf/simulated/floor/plating,
diff --git a/_maps/map_files/RandomZLevels/spacehotel.dmm b/_maps/map_files/RandomZLevels/spacehotel.dmm
index 8394ca1b635..4b45711ff3d 100644
--- a/_maps/map_files/RandomZLevels/spacehotel.dmm
+++ b/_maps/map_files/RandomZLevels/spacehotel.dmm
@@ -540,7 +540,7 @@
requires_power = 0
})
"aZ" = (
-/obj/structure/ladder/dive_point/anchor{
+/obj/structure/ladder/unbreakable/dive_point/anchor{
id = "weirddive";
layer = 4.5
},
@@ -1996,7 +1996,7 @@
requires_power = 0
})
"dA" = (
-/obj/structure/ladder/dive_point/anchor{
+/obj/structure/ladder/unbreakable/dive_point/anchor{
layer = 4.5
},
/turf/unsimulated/beach/water/deep/wood_floor{
@@ -2721,8 +2721,8 @@
/turf/unsimulated/beach/water/drop,
/area/awaymission/spacehotel)
"fC" = (
-/obj/structure/ladder/dive_point/buoy,
-/obj/structure/ladder/dive_point/buoy{
+/obj/structure/ladder/unbreakable/dive_point/buoy,
+/obj/structure/ladder/unbreakable/dive_point/buoy{
id = "weirddive";
invisibility = 101
},
@@ -3465,7 +3465,7 @@
},
/area/awaymission/spacehotel)
"hG" = (
-/obj/structure/ladder{
+/obj/structure/ladder/unbreakable{
height = 1;
icon_state = "ladder10";
id = "service"
@@ -3525,7 +3525,7 @@
/area/awaymission/spacehotel)
"hN" = (
/obj/effect/decal/cleanable/blood/old,
-/obj/structure/ladder{
+/obj/structure/ladder/unbreakable{
height = 2;
icon_state = "ladder01";
id = "service"
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index 661dca15a0e..71d83c16ee1 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -4055,7 +4055,7 @@
/turf/simulated/floor/plasteel,
/area/security/armoury)
"ahH" = (
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
/obj/structure/window/reinforced{
dir = 8
},
@@ -4155,7 +4155,7 @@
},
/area/security/brig)
"ahR" = (
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
/obj/structure/window/reinforced{
dir = 4
},
@@ -4324,7 +4324,7 @@
},
/area/security/brig)
"aif" = (
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
/obj/structure/window/reinforced{
dir = 8
},
@@ -4370,7 +4370,7 @@
},
/area/security/brig)
"aij" = (
-/obj/machinery/deployable/barrier,
+/obj/item/grenade/barrier,
/obj/structure/window/reinforced{
dir = 4
},
@@ -15799,7 +15799,7 @@
"aAd" = (
/obj/effect/spawner/window/reinforced,
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aAe" = (
/turf/space,
/turf/simulated/shuttle/wall{
@@ -15856,7 +15856,7 @@
tag = ""
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aAm" = (
/turf/simulated/wall/r_wall,
/area/crew_quarters/courtroom)
@@ -16579,7 +16579,7 @@
initialize_directions = 10
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aBF" = (
/obj/machinery/atmospherics/unary/vent_pump/high_volume{
dir = 4;
@@ -16609,7 +16609,7 @@
tag = ""
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aBG" = (
/obj/machinery/door/airlock/external{
id_tag = "s_docking_airlock";
@@ -17125,7 +17125,7 @@
/obj/effect/spawner/window/reinforced,
/obj/machinery/atmospherics/pipe/simple/hidden,
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aCD" = (
/obj/machinery/door/airlock/external{
frequency = 1379;
@@ -17143,7 +17143,7 @@
tag = ""
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aCE" = (
/obj/machinery/door/airlock/maintenance{
req_access_txt = "1"
@@ -17575,13 +17575,13 @@
d2 = 4
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aDv" = (
/turf/simulated/wall,
/area/security/lobby)
"aDw" = (
/turf/simulated/wall/r_wall,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aDx" = (
/obj/structure/sign/securearea{
desc = "A warning sign which reads 'EXTERNAL AIRLOCK'";
@@ -17598,7 +17598,7 @@
filled = 0.05
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aDy" = (
/obj/machinery/access_button{
command = "cycle_interior";
@@ -17622,7 +17622,7 @@
tag = ""
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aDz" = (
/obj/structure/rack,
/obj/item/clothing/mask/cigarette/pipe,
@@ -18153,7 +18153,7 @@
"aEC" = (
/obj/structure/chair/stool,
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aED" = (
/obj/machinery/power/terminal,
/obj/machinery/light/small{
@@ -18164,7 +18164,7 @@
icon_state = "0-8"
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aEE" = (
/obj/structure/cable{
d1 = 1;
@@ -18173,7 +18173,7 @@
tag = ""
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aEF" = (
/obj/structure/table,
/obj/item/paper_bin,
@@ -18753,7 +18753,7 @@
shock_proof = 1
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aFR" = (
/obj/structure/cable{
d2 = 8;
@@ -18763,7 +18763,7 @@
charge = 0
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aFS" = (
/obj/structure/cable{
d1 = 2;
@@ -18776,11 +18776,11 @@
icon_state = "2-4"
},
/turf/simulated/floor/plating,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aFT" = (
/obj/effect/decal/cleanable/fungus,
/turf/simulated/wall/r_wall,
-/area/solar/auxport)
+/area/maintenance/auxsolarport)
"aFU" = (
/obj/structure/table,
/obj/item/toy/figure/detective,
@@ -32864,8 +32864,8 @@
/obj/machinery/light{
dir = 1
},
-/obj/structure/reagent_dispensers/watertank/high,
-/obj/item/reagent_containers/glass/bucket,
+/obj/structure/table,
+/obj/machinery/smartfridge/disks,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -36338,6 +36338,7 @@
/turf/simulated/floor/carpet,
/area/crew_quarters/bar)
"bou" = (
+/obj/item/reagent_containers/glass/bucket,
/obj/structure/sink{
icon_state = "sink";
dir = 8;
@@ -79987,7 +79988,7 @@
"cMF" = (
/obj/machinery/door/airlock/engineering{
name = "Engineering Checkpoint";
- req_access_txt = "11"
+ req_one_access_txt = "11;24"
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm
index 0052c80df84..7c7b0403547 100644
--- a/_maps/map_files/cyberiad/z2.dmm
+++ b/_maps/map_files/cyberiad/z2.dmm
@@ -8742,7 +8742,7 @@
pixel_x = -3;
pixel_y = 3
},
-/obj/item/clothing/glasses/hud/health/health_advanced,
+/obj/item/clothing/glasses/hud/health/sunglasses,
/obj/item/clothing/glasses/hud/security/sunglasses,
/turf/unsimulated/floor{
tag = "icon-floor";
diff --git a/_maps/map_files/templates/spacehotel/s_01.dmm b/_maps/map_files/templates/spacehotel/s_01.dmm
index f97f6613f07..8362c0f21cc 100644
--- a/_maps/map_files/templates/spacehotel/s_01.dmm
+++ b/_maps/map_files/templates/spacehotel/s_01.dmm
@@ -38,7 +38,7 @@
"f" = (
/obj/structure/rack,
/obj/item/clothing/head/collectable/police,
-/obj/item/clothing/head/nun_hood,
+/obj/item/clothing/head/hooded/nun_hood,
/obj/item/clothing/head/mailman,
/obj/item/clothing/head/nursehat,
/obj/item/clothing/head/wizard/fake,
diff --git a/_maps/map_files/templates/spacehotel/s_02.dmm b/_maps/map_files/templates/spacehotel/s_02.dmm
index c3ee3c4a727..6834bc8d7e8 100644
--- a/_maps/map_files/templates/spacehotel/s_02.dmm
+++ b/_maps/map_files/templates/spacehotel/s_02.dmm
@@ -38,7 +38,7 @@
"f" = (
/obj/structure/rack,
/obj/item/clothing/head/collectable/police,
-/obj/item/clothing/head/nun_hood,
+/obj/item/clothing/head/hooded/nun_hood,
/obj/item/clothing/head/mailman,
/obj/item/clothing/head/nursehat,
/obj/item/clothing/head/wizard/fake,
diff --git a/_maps/test_all_maps.dm b/_maps/test_all_maps.dm
index 064bf8defaf..55cb0ff946b 100644
--- a/_maps/test_all_maps.dm
+++ b/_maps/test_all_maps.dm
@@ -19,6 +19,8 @@
// Lavaland Ruins
#include "map_files\RandomRuins\LavaRuins\lavaland_biodome_beach.dmm"
+ #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_clown_planet.dmm"
+ #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_winter.dmm"
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_animal_hospital.dmm"
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_ash_walker1.dmm"
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk1.dmm"
@@ -44,7 +46,7 @@
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_syndicate_base1.dmm"
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_ufo_crash.dmm"
#include "map_files\RandomRuins\LavaRuins\lavaland_surface_xeno_nest.dmm"
-
+
// Space Ruins
#include "map_files\RandomRuins\SpaceRuins\abandonedzoo.dmm"
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index fbc28695ebf..d8e051e600e 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -106,9 +106,10 @@
#define SAWN_INTACT 0
#define SAWN_OFF 1
-#define WEAPON_LIGHT 0
-#define WEAPON_MEDIUM 1
-#define WEAPON_HEAVY 2
+#define WEAPON_DUAL_WIELD 0
+#define WEAPON_LIGHT 1
+#define WEAPON_MEDIUM 2
+#define WEAPON_HEAVY 3
#define EXPLODE_NONE 0 //Don't even ask me why we need this.
#define EXPLODE_DEVASTATE 1
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index 02b36614cb5..aa4b49ff6fc 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -155,6 +155,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_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm
index 4b783490568..7bfd2935280 100644
--- a/code/__DEFINES/crafting.dm
+++ b/code/__DEFINES/crafting.dm
@@ -1,10 +1,28 @@
+//tablecrafting defines
#define CAT_NONE ""
-#define CAT_WEAPON "Weaponry"
+#define CAT_WEAPONRY "Weaponry"
+#define CAT_WEAPON "Weapons"
#define CAT_AMMO "Ammunition"
#define CAT_ROBOT "Robots"
-#define CAT_FOOD "Food"
#define CAT_MISC "Misc"
#define CAT_PRIMAL "Tribal"
+#define CAT_CLOTHING "Clothing"
+#define CAT_FOOD "Foods"
+#define CAT_BREAD "Breads"
+#define CAT_BURGER "Burgers"
+#define CAT_CAKE "Cakes"
+#define CAT_EGG "Egg-Based Food"
+#define CAT_MEAT "Meats"
+#define CAT_SUSHI "Sushi"
+#define CAT_MISCFOOD "Misc. Food"
+#define CAT_PASTRY "Pastries"
+#define CAT_PIE "Pies"
+#define CAT_PIZZA "Pizzas"
+#define CAT_SALAD "Salads"
+#define CAT_SANDWICH "Sandwiches"
+#define CAT_SOUP "Soups"
+#define CAT_SPAGHETTI "Spaghettis"
+#define CAT_ICE "Frozen"
#define RECIPE_MICROWAVE "Microwave"
#define RECIPE_OVEN "Oven"
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 14b712754fb..edc77bae4c3 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -13,6 +13,7 @@
#define CONDUCT 32 // conducts electricity (metal etc.)
#define ABSTRACT 64 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
#define ON_BORDER 128 // item has priority to check when entering or leaving
+#define PREVENT_CLICK_UNDER 256
#define EARBANGPROTECT 1024
diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 0fb9253a083..c7b055879f1 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -1,6 +1,8 @@
// String identifiers for associative list lookup
+#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return
+
#define MUTCHK_FORCED 1
// mob/var/list/mutations
@@ -22,7 +24,6 @@
///////////////////////////////////////
// MUTATIONS
///////////////////////////////////////
-
// Generic mutations:
#define TK 1
#define COLDRES 2
@@ -105,6 +106,9 @@
#define NUTRITION_LEVEL_STARVING 150
#define NUTRITION_LEVEL_CURSED 0
+//Used as an upper limit for species that continuously gain nutriment
+#define NUTRITION_LEVEL_ALMOST_FULL 535
+
//Blood levels
#define BLOOD_VOLUME_MAXIMUM 2000
#define BLOOD_VOLUME_NORMAL 560
@@ -146,4 +150,5 @@
#define RESISTHOT 16
#define RESISTCOLD 17
#define NO_EXAMINE 18
-#define CAN_WINGDINGS 19
\ No newline at end of file
+#define CAN_WINGDINGS 19
+#define NOZOMBIE 20
\ No newline at end of file
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index c4478f62837..0e5c5316254 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -4,6 +4,7 @@
// Mobs
#define ismegafauna(A) istype(A, /mob/living/simple_animal/hostile/megafauna)
+#define iszombie(A) (is_species(A, /datum/species/zombie))
//Simple animals
#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
@@ -17,6 +18,8 @@
#define ismecha(A) (istype(A, /obj/mecha))
+#define isspacepod(A) (istype(A, /obj/spacepod))
+
#define iseffect(A) (istype(A, /obj/effect))
#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 27f467d65fc..4eb11963eff 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -390,6 +390,8 @@
#define BLOODY_FOOTPRINT_BASE_ALPHA 150
#define BLOOD_GAIN_PER_STEP 100
#define BLOOD_LOSS_PER_STEP 5
+#define BLOOD_LOSS_IN_SPREAD 20
+#define BLOOD_AMOUNT_PER_DECAL 20
//Bloody shoe blood states
#define BLOOD_STATE_HUMAN "blood"
@@ -485,10 +487,14 @@
// Cult summon possibilities
#define SUMMON_POSSIBILITIES 3
+// Dice rigged options.
#define DICE_NOT_RIGGED 1
#define DICE_BASICALLY_RIGGED 2
#define DICE_TOTALLY_RIGGED 3
+// Water temperature
+#define COLD_WATER_TEMPERATURE 283.15 // 10 degrees celsius
+
// Parallax
#define PARALLAX_DELAY_DEFAULT world.tick_lag
#define PARALLAX_DELAY_MED 1
@@ -498,4 +504,4 @@
// Engine types
#define ENGTYPE_SING "Singularity"
#define ENGTYPE_SM "Supermatter"
-#define ENGTYPE_TESLA "Tesla"
\ No newline at end of file
+#define ENGTYPE_TESLA "Tesla"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 608fcfcce20..22b43f84b9f 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -64,11 +64,12 @@
// Factor of how fast mob nutrition decreases
#define HUNGER_FACTOR 0.1
-// Taste sensitivity - the more the more reagents you'll taste
-#define TASTE_SENSITIVITY_NORMAL 1
-#define TASTE_SENSITIVITY_SHARP 1.5
-#define TASTE_SENSITIVITY_DULL 0.75
-#define TASTE_SENSITIVITY_NO_TASTE 0
+// Taste sensitivity - lower is more sensitive
+// Represents the minimum portion of total taste the mob can sense
+#define TASTE_SENSITIVITY_NORMAL 15
+#define TASTE_SENSITIVITY_SHARP 7.5
+#define TASTE_SENSITIVITY_DULL 20
+#define TASTE_SENSITIVITY_NO_TASTE 101
// Reagent type flags, defines the types of mobs this reagent will affect
#define ORGANIC 1
@@ -218,3 +219,5 @@
#define hasorgans(A) (ishuman(A))
#define is_admin(user) (check_rights(R_ADMIN, 0, (user)) != 0)
+
+#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
\ No newline at end of file
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index a28d68a392b..54fd59307f4 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -7,8 +7,9 @@
#define SOUND_BUZZ 64
#define SOUND_INSTRUMENTS 128
#define SOUND_MENTORHELP 256
+#define SOUND_DISCO 512
-#define SOUND_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_HEARTBEAT|SOUND_BUZZ|SOUND_INSTRUMENTS|SOUND_MENTORHELP)
+#define SOUND_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|SOUND_HEARTBEAT|SOUND_BUZZ|SOUND_INSTRUMENTS|SOUND_MENTORHELP|SOUND_DISCO)
#define CHAT_OOC 1
#define CHAT_DEAD 2
@@ -34,7 +35,7 @@
#define AMBIENT_OCCLUSION 2097152
#define CHAT_GHOSTPDA 4194304
#define NUMPAD_TARGET 8388608
-#define TOGGLES_TOTAL 16777215 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
+#define TOGGLES_TOTAL 16777215 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC|AMBIENT_OCCLUSION|CHAT_GHOSTPDA|NUMPAD_TARGET)
diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm
index 6ef269be1c2..b0a74b6c702 100644
--- a/code/__DEFINES/stat.dm
+++ b/code/__DEFINES/stat.dm
@@ -34,14 +34,14 @@
#define WAIT_FINISH 3
//shuttle mode defines
-#define SHUTTLE_IDLE 0
-#define SHUTTLE_RECALL 1
-#define SHUTTLE_CALL 2
-#define SHUTTLE_DOCKED 3
-#define SHUTTLE_STRANDED 4
-#define SHUTTLE_ESCAPE 5
-#define SHUTTLE_ENDGAME 6
-#define SHUTTLE_IGNITING 7
+#define SHUTTLE_IGNITING 0
+#define SHUTTLE_IDLE 1
+#define SHUTTLE_RECALL 2
+#define SHUTTLE_CALL 3
+#define SHUTTLE_DOCKED 4
+#define SHUTTLE_STRANDED 5
+#define SHUTTLE_ESCAPE 6
+#define SHUTTLE_ENDGAME 7
// Shuttle return values
#define SHUTTLE_CAN_DOCK "can_dock"
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index dc2b2e4ec0a..2a23cc8baa0 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -46,11 +46,7 @@
if(IS_WHITELISTED in S.species_traits)
GLOB.whitelisted_species += S.name
- for(var/D in subtypesof(/datum/crafting_recipe))
- var/datum/crafting_recipe/R = D
- if(!initial(R.roundstart_enabled))
- continue
- GLOB.crafting_recipes += new R
+ init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
//Pipe list building
init_subtypes(/datum/pipes, GLOB.construction_pipe_list)
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index ed4f3242c4d..0b37872decd 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -948,10 +948,16 @@ The _flatIcons list is a cache for generated icon files.
return "#[color]"
//Imagine removing pixels from the main icon that are covered by pixels from the mask icon.
-/proc/get_icon_difference(var/icon/main, var/icon/mask)
+//Standard behaviour is to cut pixels from the main icon that are covered by pixels from the mask icon unless passed mask_ready, see below.
+/proc/get_icon_difference(var/icon/main, var/icon/mask, var/mask_ready)
+ /*You should skip prep if the mask is already sprited properly. This significantly improves performance by eliminating most of the realtime icon work.
+ e.g. A 'ready' mask is a mask where the part you want cut out is missing (no pixels, 0 alpha) from the sprite, and everything else is solid white.*/
+
if(istype(main) && istype(mask))
- mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible.
- mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white.
- mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white pixels.
+ if(!mask_ready) //Prep the mask if we're using a regular old sprite and not a special-made mask.
+ mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible.
+ mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white.
+ mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white background pixels.
+
main.AddAlphaMask(mask) //Make the pixels in the main icon that are in the transparent zone of the mask icon also vanish (fully transparent).
- return main
+ return main
\ No newline at end of file
diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 9e01753d492..49983658d48 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -799,3 +799,29 @@ proc/dd_sortedObjectList(list/incoming)
L.Swap(start++, end--)
return L
+
+/proc/counterlist_scale(list/L, scalar)
+ var/list/out = list()
+ for(var/key in L)
+ out[key] = L[key] * scalar
+ . = out
+
+/proc/counterlist_sum(list/L)
+ . = 0
+ for(var/key in L)
+ . += L[key]
+
+/proc/counterlist_normalise(list/L)
+ var/avg = counterlist_sum(L)
+ if(avg != 0)
+ . = counterlist_scale(L, 1 / avg)
+ else
+ . = L
+
+/proc/counterlist_combine(list/L1, list/L2)
+ for(var/key in L2)
+ var/other_value = L2[key]
+ if(key in L1)
+ L1[key] += other_value
+ else
+ L1[key] = other_value
\ No newline at end of file
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index d9d21c60e1e..f383ba3fc33 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(prisoncomputer_list, list())
GLOBAL_LIST_INIT(celltimers_list, list()) // list of all cell timers
GLOBAL_LIST_INIT(cell_logs, list())
GLOBAL_LIST_INIT(navigation_computers, list())
+GLOBAL_LIST_INIT(zombie_infection_list, list())
GLOBAL_LIST_INIT(all_areas, list())
GLOBAL_LIST_INIT(machines, list())
@@ -42,6 +43,7 @@ GLOBAL_LIST_INIT(global_radios, list()) //list of all radios, across all z-le
GLOBAL_LIST_INIT(meteor_list, list()) //list of all meteors
GLOBAL_LIST_INIT(poi_list, list()) //list of points of interest for observe/follow
GLOBAL_LIST_INIT(active_jammers, list()) // List of active radio jammers
+GLOBAL_LIST_EMPTY(ladders)
GLOBAL_LIST_INIT(active_diseases, list()) //List of Active disease in all mobs; purely for quick referencing.
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index b823efe2563..7695b8b5851 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -107,6 +107,9 @@
if(next_move > world.time) // in the year 2000...
return
+ if(!modifiers["catcher"] && A.IsObscured())
+ return
+
if(istype(loc,/obj/mecha))
if(!locate(/turf) in list(A,A.loc)) // Prevents inventory from being drilled
return
@@ -172,6 +175,24 @@
return
+//Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it
+/atom/proc/IsObscured()
+ if(!isturf(loc)) //This only makes sense for things directly on turfs for now
+ return FALSE
+ var/turf/T = get_turf_pixel(src)
+ if(!T)
+ return FALSE
+ for(var/atom/movable/AM in T)
+ if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer)
+ return TRUE
+ return FALSE
+
+/turf/IsObscured()
+ for(var/atom/movable/AM in src)
+ if(AM.flags & PREVENT_CLICK_UNDER && AM.density)
+ return TRUE
+ return FALSE
+
// Default behavior: ignore double clicks, consider them normal clicks instead
/mob/proc/DblClickOn(var/atom/A, var/params)
return
@@ -399,8 +420,8 @@
dir = direction
/obj/screen/click_catcher
- icon = 'icons/mob/screen_full.dmi'
- icon_state = "passage0"
+ icon = 'icons/mob/screen_gen.dmi'
+ icon_state = "catcher"
plane = CLICKCATCHER_PLANE
mouse_opacity = MOUSE_OPACITY_OPAQUE
screen_loc = "CENTER"
@@ -430,5 +451,7 @@
C.swap_hand()
else
var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr))
- T.Click(location, control, params)
- return 1
+ params += "&catcher=1"
+ if(T)
+ T.Click(location, control, params)
+ . = 1
\ No newline at end of file
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 4aa30657778..f9528f2b2b9 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -68,8 +68,14 @@ SUBSYSTEM_DEF(ticker)
current_state = GAME_STATE_PREGAME
fire() // TG says this is a good idea
if(GAME_STATE_PREGAME)
+ if(!going)
+ return
+
// This is so we dont have sleeps in controllers, because that is a bad, bad thing
- pregame_timeleft = max(0,round_start_time - world.time)
+ if(!delay_end)
+ pregame_timeleft = max(0,round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed
+ else
+ pregame_timeleft = max(0,pregame_timeleft - 20) // If roundstart was delayed, we should resume the countdown where it left off
if(pregame_timeleft <= 600 && !tipped) // 60 seconds
send_tip_of_the_round()
@@ -83,6 +89,7 @@ SUBSYSTEM_DEF(ticker)
current_state = GAME_STATE_STARTUP
Master.SetRunLevel(RUNLEVEL_LOBBY)
if(GAME_STATE_PLAYING)
+ delay_end = 0 // reset this in case round start was delayed
mode.process()
mode.process_job_tasks()
var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index e8339f81945..138c670290a 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -738,22 +738,7 @@
if(!istype(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
- to_chat(M, "Control of your mob has been offered to dead players.")
- log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
- var/minhours = input(usr, "Minimum hours required to play [M]?", "Set Min Hrs", 10) as num
- message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts with [minhours] hrs playtime")
- var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name ? M.real_name : M.name]?", poll_time = 100, min_hours = minhours)
- var/mob/dead/observer/theghost = null
-
- if(candidates.len)
- theghost = pick(candidates)
- to_chat(M, "Your mob has been taken over by a ghost!")
- message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
- M.ghostize()
- M.key = theghost.key
- else
- to_chat(M, "There were no ghosts willing to take control.")
- message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+ offer_control(M)
else if(href_list["delete"])
if(!check_rights(R_DEBUG, 0))
diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm
index 6fb0ac53507..451f9f28dbd 100644
--- a/code/datums/diseases/pierrot_throat.dm
+++ b/code/datums/diseases/pierrot_throat.dm
@@ -59,5 +59,6 @@
if(prob(5))
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) )
- if(!istype(affected_mob.wear_mask, /obj/item/clothing/mask/gas/virusclown_hat))
- affected_mob.equip_to_slot(new /obj/item/clothing/mask/gas/virusclown_hat(src), slot_wear_mask)
\ No newline at end of file
+ if(!istype(affected_mob.wear_mask, /obj/item/clothing/mask/gas/clown_hat/nodrop))
+ affected_mob.unEquip(affected_mob.wear_mask, TRUE)
+ affected_mob.equip_to_slot(new /obj/item/clothing/mask/gas/clown_hat/nodrop(src), slot_wear_mask)
\ No newline at end of file
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 0ab0453cb95..c86a18eba80 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -80,6 +80,8 @@
//zealot_master is a reference to the mob that converted them into a zealot (for ease of investigation and such)
var/mob/living/carbon/human/zealot_master = null
+ var/list/learned_recipes //List of learned recipe TYPES.
+
/datum/mind/New(new_key)
key = new_key
soulOwner = src
@@ -1151,7 +1153,7 @@
A.set_zeroth_law("")
A.show_laws()
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
- A.malf_picker.remove_verbs(A)
+ A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
SSticker.mode.update_traitor_icons_removed(src)
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 6ec670bf4f2..ff8a93d3df0 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -1127,7 +1127,7 @@
uniform = /obj/item/clothing/under/color/black
suit = /obj/item/clothing/suit/hooded/chaplain_hoodie
back = /obj/item/storage/backpack
- head = /obj/item/clothing/head/chaplain_hood
+ head = /obj/item/clothing/head/hooded/chaplain_hood
gloves = /obj/item/clothing/gloves/color/black
shoes = /obj/item/clothing/shoes/black
l_ear = /obj/item/radio/headset/syndicate
diff --git a/code/datums/pipe_datums.dm b/code/datums/pipe_datums.dm
index cf2ec79fe85..83b77425447 100644
--- a/code/datums/pipe_datums.dm
+++ b/code/datums/pipe_datums.dm
@@ -337,6 +337,13 @@ GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable
pipe_icon = "intake"
rpd_dispensable = TRUE
+/datum/pipes/disposal/sortjunction
+ pipe_name = "disposals sort junction"
+ pipe_id = PIPE_DISPOSALS_SORT_RIGHT
+ orientations = 4
+ pipe_icon = "pipe-j1s"
+ rpd_dispensable = TRUE
+
//Pipes the RPD can't dispense. Since these don't use an interface, we don't need to bother with setting an icon. We do, however, want to name these for other purposes
/datum/pipes/atmospheric/circulator
@@ -363,12 +370,8 @@ GLOBAL_LIST_EMPTY(rpd_pipe_list) //Some pipes we don't want to be dispensable
pipe_name = "bent insulated pipe"
pipe_id = PIPE_INSULATED_BENT
-/datum/pipes/disposal/sortjunction
- pipe_name = "disposals sort junction"
- pipe_id = PIPE_DISPOSALS_SORT_RIGHT
- pipe_icon = "pipe-j1s"
-
-/datum/pipes/disposal/sortjunction/left
+/datum/pipes/disposal/left_sortjunction
+ pipe_name = "disposals sort junction left"
pipe_id = PIPE_DISPOSALS_SORT_LEFT
pipe_icon = "pipe-j2s"
diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm
index 67e5438656e..7fe8ad7248e 100644
--- a/code/datums/ruins/lavaland.dm
+++ b/code/datums/ruins/lavaland.dm
@@ -12,6 +12,19 @@
Comes with a rustic wooden bar and suicidal bartender."
suffix = "lavaland_biodome_beach.dmm"
+/datum/map_template/ruin/lavaland/biodome/winter
+ name = "Biodome Winter"
+ id = "biodome-winter"
+ description = "For those getaways where you want to get back to nature, but you don't want to leave the fortified military compound where you spend your days. \
+ Includes a unique(*) laser pistol display case, and the recently introduced I.C.E(tm)."
+ suffix = "lavaland_biodome_winter.dmm"
+
+/datum/map_template/ruin/lavaland/biodome/clown
+ name = "Biodome Clown Planet"
+ id = "biodome-clown"
+ description = "WELCOME TO CLOWN PLANET! HONK HONK HONK etc.!"
+ suffix = "lavaland_biodome_clown_planet.dmm"
+
/datum/map_template/ruin/lavaland/cube
name = "The Wishgranter Cube"
id = "wishgranter-cube"
diff --git a/code/datums/spells/banana_touch.dm b/code/datums/spells/banana_touch.dm
new file mode 100644
index 00000000000..4e2f1d44e51
--- /dev/null
+++ b/code/datums/spells/banana_touch.dm
@@ -0,0 +1,64 @@
+/obj/effect/proc_holder/spell/targeted/touch/banana
+ name = "Banana Touch"
+ desc = "A spell popular at wizard birthday parties, this spell will put on a clown costume on the target, \
+ stun them with a loud HONK, and mutate them to make them more entertaining! \
+ Warning : Effects are permanent on non-wizards."
+ hand_path = /obj/item/melee/touch_attack/banana
+ school = "transmutation"
+
+ charge_max = 300
+ clothes_req = 1
+ cooldown_min = 100 //50 deciseconds reduction per rank
+ action_icon_state = "clown"
+
+/obj/item/melee/touch_attack/banana
+ name = "banana touch"
+ desc = "It's time to start clowning around."
+ catchphrase = "NWOLC YRGNA"
+ on_use_sound = 'sound/items/AirHorn.ogg'
+ icon_state = "banana_touch"
+ item_state = "banana_touch"
+
+/obj/item/melee/touch_attack/banana/afterattack(atom/target, mob/living/carbon/user, proximity)
+ if(!proximity || target == user || !ishuman(target) || !iscarbon(user) || user.lying || user.handcuffed)
+ return
+
+ var/datum/effect_system/smoke_spread/s = new
+ s.set_up(5, 0, target)
+ s.start()
+
+ to_chat(user, "HONK")
+ var/mob/living/carbon/human/H = target
+ H.bananatouched()
+ ..()
+
+/mob/living/carbon/human/proc/bananatouched()
+ to_chat(src, "HONK")
+ Weaken(7)
+ Stun(7)
+ Stuttering(15)
+ do_jitter_animation(15)
+
+ if(iswizard(src) || (mind && mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE)) //Wizards get non-cursed clown robes and magical mask.
+ unEquip(shoes, TRUE)
+ unEquip(wear_mask, TRUE)
+ unEquip(head, TRUE)
+ unEquip(wear_suit, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/head/wizard/clown, slot_head, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/suit/wizrobe/clown, slot_wear_suit, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/shoes/clown_shoes/magical, slot_shoes, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clownwiz, slot_wear_mask, TRUE, TRUE)
+ else
+ qdel(shoes)
+ qdel(wear_mask)
+ qdel(w_uniform)
+ equip_to_slot_if_possible(new /obj/item/clothing/under/rank/clown/nodrop, slot_w_uniform, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/shoes/clown_shoes/nodrop, slot_shoes, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat/nodrop, slot_wear_mask, TRUE, TRUE)
+ dna.SetSEState(CLUMSYBLOCK, TRUE, TRUE)
+ dna.SetSEState(COMICBLOCK, TRUE, TRUE)
+ genemutcheck(src, CLUMSYBLOCK, null, MUTCHK_FORCED)
+ genemutcheck(src, COMICBLOCK, null, MUTCHK_FORCED)
+ if(!(iswizard(src) || (mind && mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE))) //Mutations are permanent on non-wizards. Can still be removed by genetics fuckery but not mutadone.
+ dna.default_blocks.Add(CLUMSYBLOCK)
+ dna.default_blocks.Add(COMICBLOCK)
\ No newline at end of file
diff --git a/code/datums/spells/charge.dm b/code/datums/spells/charge.dm
index 5dd054f67ed..46cdbff7f94 100644
--- a/code/datums/spells/charge.dm
+++ b/code/datums/spells/charge.dm
@@ -1,7 +1,6 @@
/obj/effect/proc_holder/spell/targeted/charge
name = "Charge"
desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user."
-
school = "transmutation"
charge_max = 600
clothes_req = 0
@@ -10,7 +9,7 @@
range = -1
cooldown_min = 400 //50 deciseconds reduction per rank
include_user = 1
-
+ action_icon_state = "charge"
/obj/effect/proc_holder/spell/targeted/charge/cast(list/targets,mob/user = usr)
for(var/mob/living/L in targets)
diff --git a/code/datums/spells/infinite_guns.dm b/code/datums/spells/infinite_guns.dm
index 83cafb88666..35699d4634a 100644
--- a/code/datums/spells/infinite_guns.dm
+++ b/code/datums/spells/infinite_guns.dm
@@ -11,8 +11,6 @@
cooldown_min = 10 //Gun wizard
action_icon_state = "bolt_action"
-
-
/obj/effect/proc_holder/spell/targeted/infinite_guns/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/C in targets)
C.drop_item()
diff --git a/code/datums/spells/mime_malaise.dm b/code/datums/spells/mime_malaise.dm
new file mode 100644
index 00000000000..a5afd26d916
--- /dev/null
+++ b/code/datums/spells/mime_malaise.dm
@@ -0,0 +1,54 @@
+/obj/effect/proc_holder/spell/targeted/touch/mime_malaise
+ name = "Mime Malaise"
+ desc = "A spell popular with theater nerd wizards and contrarian pranksters, this spell will put on a mime costume on the target, \
+ stun them so that they may contemplate Art, and silence them. \
+ Warning : Effects are permanent on non-wizards."
+ hand_path = /obj/item/melee/touch_attack/mime_malaise
+ school = "transmutation"
+
+ charge_max = 300
+ clothes_req = 1
+ cooldown_min = 100 //50 deciseconds reduction per rank
+ action_icon_state = "mime"
+
+/obj/item/melee/touch_attack/mime_malaise
+ name = "mime hand"
+ desc = "..."
+ catchphrase = null
+ on_use_sound = null
+ icon_state = "fleshtostone"
+ item_state = "fleshtostone"
+
+/obj/item/melee/touch_attack/mime_malaise/afterattack(atom/target, mob/living/carbon/user, proximity)
+ if(!proximity || target == user || !ishuman(target) || !iscarbon(user) || user.lying || user.handcuffed)
+ return
+
+ var/datum/effect_system/smoke_spread/s = new
+ s.set_up(5, 0, target)
+ s.start()
+
+ var/mob/living/carbon/human/H = target
+ H.mimetouched()
+ ..()
+
+/mob/living/carbon/human/proc/mimetouched()
+ Weaken(7)
+ Stun(7)
+ if(iswizard(src) || (mind && mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE)) //Wizards get non-cursed mime outfit. Replace with mime robes if we add those.
+ unEquip(wear_mask, TRUE)
+ unEquip(w_uniform, TRUE)
+ unEquip(wear_suit, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/mime, slot_wear_mask, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/under/mime, slot_w_uniform, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/suit/suspenders, slot_wear_suit, TRUE, TRUE)
+ Silence(7)
+ else
+ qdel(wear_mask)
+ qdel(w_uniform)
+ qdel(wear_suit)
+ equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/mime/nodrop, slot_wear_mask, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/under/mime/nodrop, slot_w_uniform, TRUE, TRUE)
+ equip_to_slot_if_possible(new /obj/item/clothing/suit/suspenders/nodrop, slot_wear_suit, TRUE, TRUE)
+ dna.SetSEState(MUTEBLOCK , TRUE, TRUE)
+ genemutcheck(src, MUTEBLOCK , null, MUTCHK_FORCED)
+ dna.default_blocks.Add(MUTEBLOCK)
\ No newline at end of file
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index 7b648bb72c1..739a03d92c5 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -72,6 +72,7 @@
/obj/effect/proc_holder/spell/noclothes
name = "No Clothes"
desc = "This always-on spell allows you to cast magic without your garments."
+ action_icon_state = "no_clothes"
/obj/effect/proc_holder/spell/targeted/genetic/mutate
name = "Mutate"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index fb336192b38..0573f3b90ca 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -45,13 +45,6 @@
duration = 10
tick_interval = 0
alert_type = /obj/screen/alert/status_effect/blooddrunk
- var/last_health = 0
- var/last_bruteloss = 0
- var/last_fireloss = 0
- var/last_toxloss = 0
- var/last_oxyloss = 0
- var/last_cloneloss = 0
- var/last_staminaloss = 0
/obj/screen/alert/status_effect/blooddrunk
name = "Blood-Drunk"
@@ -61,108 +54,32 @@
/datum/status_effect/blooddrunk/on_apply()
. = ..()
if(.)
- owner.maxHealth *= 10
- owner.bruteloss *= 10
- owner.fireloss *= 10
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
for(var/X in H.bodyparts)
var/obj/item/organ/external/BP = X
- BP.max_damage *= 10
- BP.min_broken_damage *= 10
- BP.brute_dam *= 10
- BP.burn_dam *= 10
- owner.toxloss *= 10
- owner.oxyloss *= 10
- owner.cloneloss *= 10
- owner.staminaloss *= 10
- owner.updatehealth()
- last_health = owner.health
- last_bruteloss = owner.getBruteLoss()
- last_fireloss = owner.getFireLoss()
- last_toxloss = owner.getToxLoss()
- last_oxyloss = owner.getOxyLoss()
- last_cloneloss = owner.getCloneLoss()
- last_staminaloss = owner.getStaminaLoss()
+ BP.brute_mod *= 0.1
+ BP.burn_mod *= 0.1
+ H.dna.species.tox_mod *= 0.1
+ H.dna.species.oxy_mod *= 0.1
+ H.dna.species.clone_mod *= 0.1
+ H.dna.species.stamina_mod *= 0.1
add_attack_logs(owner, owner, "gained blood-drunk stun immunity")
var/status = CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
owner.status_flags &= ~status
owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
-/datum/status_effect/blooddrunk/tick() //multiply the effect of healing by 10
- if(owner.health > last_health)
- var/needs_health_update = FALSE
- var/new_bruteloss = owner.getBruteLoss()
- if(new_bruteloss < last_bruteloss)
- var/heal_amount = (new_bruteloss - last_bruteloss) * 10
- owner.adjustBruteLoss(heal_amount, updating_health = FALSE)
- new_bruteloss = owner.getBruteLoss()
- needs_health_update = TRUE
- last_bruteloss = new_bruteloss
-
- var/new_fireloss = owner.getFireLoss()
- if(new_fireloss < last_fireloss)
- var/heal_amount = (new_fireloss - last_fireloss) * 10
- owner.adjustFireLoss(heal_amount, updating_health = FALSE)
- new_fireloss = owner.getFireLoss()
- needs_health_update = TRUE
- last_fireloss = new_fireloss
-
- var/new_toxloss = owner.getToxLoss()
- if(new_toxloss < last_toxloss)
- var/heal_amount = (new_toxloss - last_toxloss) * 10
- owner.adjustToxLoss(heal_amount, updating_health = FALSE)
- new_toxloss = owner.getToxLoss()
- needs_health_update = TRUE
- last_toxloss = new_toxloss
-
- var/new_oxyloss = owner.getOxyLoss()
- if(new_oxyloss < last_oxyloss)
- var/heal_amount = (new_oxyloss - last_oxyloss) * 10
- owner.adjustOxyLoss(heal_amount, updating_health = FALSE)
- new_oxyloss = owner.getOxyLoss()
- needs_health_update = TRUE
- last_oxyloss = new_oxyloss
-
- var/new_cloneloss = owner.getCloneLoss()
- if(new_cloneloss < last_cloneloss)
- var/heal_amount = (new_cloneloss - last_cloneloss) * 10
- owner.adjustCloneLoss(heal_amount, updating_health = FALSE)
- new_cloneloss = owner.getCloneLoss()
- needs_health_update = TRUE
- last_cloneloss = new_cloneloss
-
- var/new_staminaloss = owner.getStaminaLoss()
- if(new_staminaloss < last_staminaloss)
- var/heal_amount = (new_staminaloss - last_staminaloss) * 10
- owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
- new_staminaloss = owner.getStaminaLoss()
- needs_health_update = TRUE
- last_staminaloss = new_staminaloss
-
- if(needs_health_update)
- owner.updatehealth()
- owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
- last_health = owner.health
-
/datum/status_effect/blooddrunk/on_remove()
- tick()
- owner.maxHealth *= 0.1
- owner.bruteloss *= 0.1
- owner.fireloss *= 0.1
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
for(var/X in H.bodyparts)
var/obj/item/organ/external/BP = X
- BP.brute_dam *= 0.1
- BP.burn_dam *= 0.1
- BP.max_damage /= 10
- BP.min_broken_damage /= 10
- owner.toxloss *= 0.1
- owner.oxyloss *= 0.1
- owner.cloneloss *= 0.1
- owner.staminaloss *= 0.1
- owner.updatehealth()
+ BP.brute_mod *= 10
+ BP.burn_mod *= 10
+ H.dna.species.tox_mod *= 10
+ H.dna.species.oxy_mod *= 10
+ H.dna.species.clone_mod *= 10
+ H.dna.species.stamina_mod *= 10
add_attack_logs(owner, owner, "lost blood-drunk stun immunity")
owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 9345387e304..494379aa821 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -482,10 +482,10 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/security/securitybarriers
name = "Security Barriers Crate"
- contains = list(/obj/machinery/deployable/barrier,
- /obj/machinery/deployable/barrier,
- /obj/machinery/deployable/barrier,
- /obj/machinery/deployable/barrier)
+ contains = list(/obj/item/grenade/barrier,
+ /obj/item/grenade/barrier,
+ /obj/item/grenade/barrier,
+ /obj/item/grenade/barrier)
cost = 20
containername = "security barriers crate"
@@ -1173,6 +1173,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/organic/hydroponics/seeds
name = "Seeds Crate"
contains = list(/obj/item/seeds/chili,
+ /obj/item/seeds/cotton,
/obj/item/seeds/berry,
/obj/item/seeds/corn,
/obj/item/seeds/eggplant,
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index e35ca1eae9f..0cb6a31770c 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -190,6 +190,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 1
job = list("Clown")
+/datum/uplink_item/stealthy_weapons/romerol_kit
+ name = "Romerol"
+ reference = "ROM"
+ desc = "A highly experimental bioterror agent which creates dormant nodules to be etched into the grey matter of the brain. On death, these nodules take control of the dead body, causing limited revivification, along with slurred speech, aggression, and the ability to infect others with this agent."
+ item = /obj/item/storage/box/syndie_kit/romerol
+ cost = 25
+ cant_discount = TRUE
+
//mime
/datum/uplink_item/jobspecific/caneshotgun
name = "Cane Shotgun and Assassination Shells"
@@ -646,6 +654,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
+ reference = "HPA"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel. \
The holoparasites are unable to incoporate themselves to changeling and vampire agents."
item = /obj/item/storage/box/syndie_kit/guardian
@@ -900,6 +909,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
surplus = 10
+/datum/uplink_item/stealthy_weapons/false_briefcase
+ name = "False Bottomed Briefcase"
+ desc = "A modified briefcase capable of storing and firing a gun under a false bottom. Use a screwdriver to pry away the false bottom and make modifications. Distinguishable upon close examination due to the added weight."
+ reference = "FBBC"
+ item = /obj/item/storage/briefcase/false_bottomed
+ cost = 3
+
/datum/uplink_item/stealthy_weapons/soap
name = "Syndicate Soap"
desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. You can also drop it underfoot to slip people."
diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm
index d72c6cc0406..ac4c41b0c42 100644
--- a/code/game/area/areas/ruins/lavaland.dm
+++ b/code/game/area/areas/ruins/lavaland.dm
@@ -12,6 +12,9 @@
/area/ruin/powered/snow_biodome
icon_state = "dk_yellow"
+/area/ruin/powered/snow_cabin
+ icon_state = "bar"
+
/area/ruin/powered/gluttony
icon_state = "dk_yellow"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 757f036c691..dc84c1836dd 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -328,6 +328,9 @@
/atom/proc/emag_act()
return
+/atom/proc/fart_act(mob/living/M)
+ return FALSE
+
/atom/proc/rpd_act()
return
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index f90cfc94480..dfe28336631 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -234,14 +234,18 @@
blobber.color = blob_reagent_datum.complementary_color
blobber.overmind = src
blob_mobs.Add(blobber)
+ blobber.AIStatus = AI_OFF
+ blobber.LoseTarget()
spawn()
- var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 150)
+ var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 100)
if(candidates.len)
var/mob/C = pick(candidates)
if(C)
blobber.key = C.key
to_chat(blobber, "You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!")
to_chat(blobber, "You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.")
+ if(!blobber.ckey)
+ blobber.AIStatus = AI_ON
return
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 038f331f924..713779af241 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -303,7 +303,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
/datum/changeling/proc/can_absorb_dna(mob/living/carbon/user, mob/living/carbon/target)
if(using_stale_dna(user))//If our current DNA is the stalest, we gotta ditch it.
- to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.")
+ to_chat(user, "The DNA we are wearing is stale. Transform and try again.")
return
if(!target || !target.dna)
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index fe0980a24cd..a1bec7a2a83 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -61,7 +61,7 @@
breakouttime = 45
weaken = 1
-/obj/item/clothing/head/culthood
+/obj/item/clothing/head/hooded/culthood
name = "cult hood"
icon_state = "culthood"
desc = "A hood worn by the followers of a cult."
@@ -72,7 +72,7 @@
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
-/obj/item/clothing/head/culthood/alt
+/obj/item/clothing/head/hooded/culthood/alt
icon_state = "cult_hoodalt"
item_state = "cult_hoodalt"
@@ -83,7 +83,7 @@
icon_state = "cultrobes"
item_state = "cultrobes"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- hoodtype = /obj/item/clothing/head/culthood
+ hoodtype = /obj/item/clothing/head/hooded/culthood
allowed = list(/obj/item/tome,/obj/item/melee/cultblade)
armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0)
flags_inv = HIDEJUMPSUIT
@@ -91,7 +91,7 @@
/obj/item/clothing/suit/hooded/cultrobes/alt
icon_state = "cultrobesalt"
item_state = "cultrobesalt"
- hoodtype = /obj/item/clothing/head/culthood/alt
+ hoodtype = /obj/item/clothing/head/hooded/culthood/alt
/obj/item/clothing/head/magus
name = "magus helm"
@@ -140,15 +140,14 @@
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
allowed = list(/obj/item/tome,/obj/item/melee/cultblade)
var/current_charges = 3
- hoodtype = /obj/item/clothing/head/cult_hoodie
+ hoodtype = /obj/item/clothing/head/hooded/cult_hoodie
-/obj/item/clothing/head/cult_hoodie
+/obj/item/clothing/head/hooded/cult_hoodie
name = "empowered cultist robe"
desc = "Empowered garb which creates a powerful shield around the user."
icon_state = "cult_hoodalt"
armor = list(melee = 50, bullet = 40, laser = 50, energy = 30, bomb = 50, bio = 30, rad = 30)
body_parts_covered = HEAD
- flags = NODROP
flags_inv = HIDEFACE
flags_cover = HEADCOVERSEYES
@@ -182,10 +181,10 @@
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
armor = list(melee = -50, bullet = -50, laser = -100, energy = -50, bomb = -50, bio = -50, rad = -50)
slowdown = -1
- hoodtype = /obj/item/clothing/head/berserkerhood
+ hoodtype = /obj/item/clothing/head/hooded/berserkerhood
-/obj/item/clothing/head/berserkerhood
+/obj/item/clothing/head/hooded/berserkerhood
name = "flagellant's robes"
desc = "Blood-soaked garb infused with dark magic; allows the user to move at inhuman speeds, but at the cost of increased damage."
icon_state = "culthood"
@@ -349,7 +348,7 @@
force = 15
flags = NODROP | DROPDEL
-/obj/item/clothing/head/culthood/alt/ghost
+/obj/item/clothing/head/hooded/culthood/alt/ghost
flags = NODROP | DROPDEL
/obj/item/clothing/suit/cultrobesghost
@@ -374,5 +373,5 @@
uniform = /obj/item/clothing/under/color/black
suit = /obj/item/clothing/suit/cultrobesghost
shoes = /obj/item/clothing/shoes/cult/ghost
- head = /obj/item/clothing/head/culthood/alt/ghost
+ head = /obj/item/clothing/head/hooded/culthood/alt/ghost
r_hand = /obj/item/melee/cultblade/ghost
\ No newline at end of file
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 8eeee9e4f2a..9a40cb58881 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -1,46 +1,243 @@
+//The malf AI action subtype. All malf actions are subtypes of this.
+/datum/action/innate/ai
+ name = "AI Action"
+ desc = "You aren't entirely sure what this does, but it's very beepy and boopy."
+ background_icon_state = "bg_tech_blue"
+ var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time
+ var/uses //If we have multiple uses of the same power
+ var/auto_use_uses = TRUE //If we automatically use up uses on each activation
+ var/cooldown_period //If applicable, the time in deciseconds we have to wait before using any more modules
+
+/datum/action/innate/ai/Grant(mob/living/L)
+ . = ..()
+ if(!isAI(owner))
+ WARNING("AI action [name] attempted to grant itself to non-AI mob [L.real_name] ([L.key])!")
+ qdel(src)
+ else
+ owner_AI = owner
+
+/datum/action/innate/ai/IsAvailable()
+ . = ..()
+ if(owner_AI && owner_AI.malf_cooldown > world.time)
+ return
+
+/datum/action/innate/ai/Trigger()
+ . = ..()
+ if(auto_use_uses)
+ adjust_uses(-1)
+ if(cooldown_period)
+ owner_AI.malf_cooldown = world.time + cooldown_period
+
+/datum/action/innate/ai/proc/adjust_uses(amt, silent)
+ uses += amt
+ if(!silent && uses)
+ to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
+ if(!uses)
+ if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
+ to_chat(owner, "[name] has run out of uses!")
+ qdel(src)
+
+//Framework for ranged abilities that can have different effects by left-clicking stuff.
+/datum/action/innate/ai/ranged
+ name = "Ranged AI Action"
+ auto_use_uses = FALSE //This is so we can do the thing and disable/enable freely without having to constantly add uses
+ var/obj/effect/proc_holder/ranged_ai/linked_ability //The linked proc holder that contains the actual ability code
+ var/linked_ability_type //The path of our linked ability
+
+/datum/action/innate/ai/ranged/New()
+ if(!linked_ability_type)
+ WARNING("Ranged AI action [name] attempted to spawn without a linked ability!")
+ qdel(src) //uh oh!
+ return
+ linked_ability = new linked_ability_type()
+ linked_ability.attached_action = src
+ ..()
+
+/datum/action/innate/ai/ranged/adjust_uses(amt, silent)
+ uses += amt
+ if(!silent && uses)
+ to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")
+ if(!uses)
+ if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
+ to_chat(owner, "[name] has run out of uses!")
+ Remove(owner)
+ QDEL_IN(src, 100) //let any active timers on us finish up
+
+/datum/action/innate/ai/ranged/Destroy()
+ QDEL_NULL(linked_ability)
+ return ..()
+
+/datum/action/innate/ai/ranged/Activate()
+ linked_ability.toggle(owner)
+ return TRUE
+
+//The actual ranged proc holder.
+/obj/effect/proc_holder/ranged_ai
+ var/enable_text = "Hello World!" //Appears when the user activates the ability
+ var/disable_text = "Goodbye Cruel World!" //Context clues!
+ var/datum/action/innate/ai/ranged/attached_action
+
+/obj/effect/proc_holder/ranged_ai/Destroy()
+ QDEL_NULL(attached_action)
+ return ..()
+
+/obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user)
+ if(active)
+ remove_ranged_ability(disable_text)
+ else
+ add_ranged_ability(user, enable_text)
+
+//The datum and interface for the malf unlock menu, which lets them choose actions to unlock.
+/datum/module_picker
+ var/temp
+ var/processing_time = 50
+ var/list/possible_modules
+
+/datum/module_picker/New()
+ possible_modules = list()
+ for(var/type in typesof(/datum/AI_Module))
+ var/datum/AI_Module/AM = new type
+ if((AM.power_type && AM.power_type != /datum/action/innate/ai) || AM.upgrade)
+ possible_modules += AM
+
+/datum/module_picker/proc/remove_malf_verbs(mob/living/silicon/ai/AI) //Removes all malfunction-related abilities from the target AI.
+ for(var/datum/AI_Module/AM in possible_modules)
+ for(var/datum/action/A in AI.actions)
+ if(istype(A, initial(AM.power_type)))
+ qdel(A)
+
+/datum/module_picker/proc/use(user as mob)
+ var/dat
+ dat += {"Select use of processing time: (currently #[processing_time] left.)
+
+ Install Module:
+ The number afterwards is the amount of processing time it consumes.
"}
+ for(var/datum/AI_Module/large/module in possible_modules)
+ dat += "[module.module_name]\[?\] ([module.cost])
"
+ for(var/datum/AI_Module/small/module in possible_modules)
+ dat += "[module.module_name]\[?\] ([module.cost])
"
+ dat += "
"
+ if(temp)
+ dat += "[temp]"
+ var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu", 400, 500)
+ popup.set_content(dat)
+ popup.open()
+ return
+
+/datum/module_picker/Topic(href, href_list)
+ ..()
+
+ if(!isAI(usr))
+ return
+ var/mob/living/silicon/ai/A = usr
+
+ if(A.stat == DEAD)
+ to_chat(A, "You are already dead!")
+ return
+
+ for(var/datum/AI_Module/AM in possible_modules)
+ if (href_list[AM.mod_pick_name])
+
+ // Cost check
+ if(AM.cost > processing_time)
+ temp = "You cannot afford this module."
+ break
+
+ var/datum/action/innate/ai/action = locate(AM.power_type) in A.actions
+
+ // Give the power and take away the money.
+ if(AM.upgrade) //upgrade and upgrade() are separate, be careful!
+ AM.upgrade(A)
+ possible_modules -= AM
+ to_chat(A, AM.unlock_text)
+ A.playsound_local(A, AM.unlock_sound, 50, 0)
+ else
+ if(AM.power_type)
+ if(!action) //Unlocking for the first time
+ var/datum/action/AC = new AM.power_type
+ AC.Grant(A)
+ A.current_modules += new AM.type
+ temp = AM.description
+ if(AM.one_purchase)
+ possible_modules -= AM
+ if(AM.unlock_text)
+ to_chat(A, AM.unlock_text)
+ if(AM.unlock_sound)
+ A.playsound_local(A, AM.unlock_sound, 50, 0)
+ else //Adding uses to an existing module
+ action.uses += initial(action.uses)
+ action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining."
+ action.UpdateButtonIcon()
+ temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!"
+ processing_time -= AM.cost
+
+ if(href_list["showdesc"])
+ if(AM.mod_pick_name == href_list["showdesc"])
+ temp = AM.description
+ use(usr)
+
+//The base module type, which holds info about each ability.
/datum/AI_Module
- var/uses = 0
var/module_name
var/mod_pick_name
var/description = ""
var/engaged = 0
var/cost = 5
- var/one_time = 0
+ var/one_purchase = FALSE //If this module can only be purchased once. This always applies to upgrades, even if the variable is set to false.
+ var/power_type = /datum/action/innate/ai //If the module gives an active ability, use this. Mutually exclusive with upgrade.
+ var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type.
+ var/unlock_text = "Hello World!" //Text shown when an ability is unlocked
+ var/unlock_sound //Sound played when an ability is unlocked
- var/power_type
+/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades!
+ return
-/datum/AI_Module/large/
- uses = 1
-
-/datum/AI_Module/small/
- uses = 5
+/datum/AI_Module/large //Big, powerful stuff that can only be used once.
+/datum/AI_Module/small //Weak, usually localized stuff with multiple uses.
+//Doomsday Device: Starts the self-destruct timer. It can only be stopped by killing the AI completely.
/datum/AI_Module/large/nuke_station
module_name = "Doomsday Device"
mod_pick_name = "nukestation"
- description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay."
+ description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay. Can only be used while on the station, will fail if your core is moved off station or destroyed."
cost = 130
- one_time = 1
+ one_purchase = TRUE
+ power_type = /datum/action/innate/ai/nuke_station
+ unlock_text = "You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time."
+ unlock_sound = 'sound/items/timer.ogg'
- power_type = /mob/living/silicon/ai/proc/nuke_station
+/datum/action/innate/ai/nuke_station
+ name = "Doomsday Device"
+ desc = "Activates the doomsday device. This is not reversible."
+ button_icon_state = "doomsday_device"
+ auto_use_uses = FALSE
-/mob/living/silicon/ai/proc/nuke_station()
- set category = "Malfunction"
- set name = "Doomsday Device"
+/datum/action/innate/ai/nuke_station/Activate()
+ var/turf/T = get_turf(owner)
+ if(!istype(T) || !is_station_level(T.z))
+ to_chat(owner, "You cannot activate the doomsday device while off-station!")
+ return
+ if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;")
+ return
+ if(active)
+ return //prevent the AI from activating an already active doomsday
+ active = TRUE
+ set_us_up_the_bomb()
- to_chat(src, "Nuclear device armed.")
+/datum/action/innate/ai/nuke_station/proc/set_us_up_the_bomb()
+ to_chat(owner_AI, "Nuclear device armed.")
event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg')
set_security_level("delta")
- nuking = 1
- var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(src)
- doomsday_device = DOOM
- doomsday_device.start()
- verbs -= /mob/living/silicon/ai/proc/nuke_station
+ owner_AI.nuking = TRUE
+ var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(owner_AI)
+ owner_AI.doomsday_device = DOOM
+ owner_AI.doomsday_device.start()
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
for(var/mob/living/silicon/ai/A in ai_list)
if((A.stat != DEAD) && A.nuking)
point.the_disk = A //The pinpointer now tracks the AI core
+ qdel(src)
/obj/machinery/doomsday_device
icon = 'icons/obj/machines/nuke_terminal.dmi'
@@ -113,49 +310,42 @@
to_chat(world, "The AI cleansed the station of life with the doomsday device!")
SSticker.force_ending = 1
-
+//AI Turret Upgrade: Increases the health and damage of all turrets.
/datum/AI_Module/large/upgrade_turrets
module_name = "AI Turret Upgrade"
mod_pick_name = "turret"
description = "Improves the power and health of all AI turrets. This effect is permanent."
cost = 30
- one_time = 1
+ upgrade = TRUE
+ unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage."
+ unlock_sound = 'sound/items/rped.ogg'
- power_type = /mob/living/silicon/ai/proc/upgrade_turrets
-
-/mob/living/silicon/ai/proc/upgrade_turrets()
- set category = "Malfunction"
- set name = "Upgrade Turrets"
-
- if(stat)
- return
-
- src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets
+/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI)
for(var/obj/machinery/porta_turret/turret in GLOB.machines)
var/turf/T = get_turf(turret)
if(is_station_level(T.z))
turret.health += 30
turret.eprojectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR.
turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg'
- to_chat(src, "Turrets upgraded.")
-
+//Hostile Station Lockdown: Locks, bolts, and electrifies every airlock on the station. After 90 seconds, the doors reset.
/datum/AI_Module/large/lockdown
module_name = "Hostile Station Lockdown"
mod_pick_name = "lockdown"
- description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds."
+ description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 90 seconds, briefly \
+ opening all doors on the station."
cost = 30
- one_time = 1
+ one_purchase = TRUE
+ power_type = /datum/action/innate/ai/lockdown
+ unlock_text = "You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time."
- power_type = /mob/living/silicon/ai/proc/lockdown
-
-/mob/living/silicon/ai/proc/lockdown()
- set category = "Malfunction"
- set name = "Initiate Hostile Lockdown"
-
- if(stat)
- return
+/datum/action/innate/ai/lockdown
+ name = "Lockdown"
+ desc = "Closes, bolts, and depowers every airlock, firelock, and blast door on the station. After 90 seconds, they will reset themselves."
+ button_icon_state = "lockdown"
+ uses = 1
+/datum/action/innate/ai/lockdown/Activate()
for(var/obj/machinery/door/D in GLOB.airlocks)
if(!is_station_level(D.z))
continue
@@ -164,342 +354,360 @@
post_status("alert", "lockdown")
- verbs -= /mob/living/silicon/ai/proc/lockdown
minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert")
- to_chat(src, "Lockdown Initiated. Network reset in 90 seconds.")
+ to_chat(owner, "Lockdown Initiated. Network reset in 90 seconds.")
spawn(900)
minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:")
-
+//Destroy RCDs: Detonates all non-cyborg RCDs on the station.
/datum/AI_Module/large/destroy_rcd
module_name = "Destroy RCDs"
mod_pick_name = "rcd"
description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station."
cost = 25
- one_time = 1
+ one_purchase = TRUE
+ power_type = /datum/action/innate/ai/destroy_rcds
+ unlock_text = "After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs."
- power_type = /mob/living/silicon/ai/proc/disable_rcd
-
-/mob/living/silicon/ai/proc/disable_rcd()
- set category = "Malfunction"
- set name = "Destroy RCDs"
- set desc = "Detonate all RCDs on the station, while sparing onboard cyborg RCDs."
-
- if(stat || malf_cooldown > world.time)
- return
+/datum/action/innate/ai/destroy_rcds
+ name = "Destroy RCDs"
+ desc = "Detonate all non-cyborg RCDs on the station."
+ button_icon_state = "detonate_rcds"
+ uses = 1
+ cooldown_period = 100
+/datum/action/innate/ai/destroy_rcds/Activate()
for(var/obj/item/rcd/RCD in GLOB.rcd_list)
if(!istype(RCD, /obj/item/rcd/borg)) //Ensures that cyborg RCDs are spared.
RCD.detonate_pulse()
- to_chat(src, "RCD detonation pulse emitted.")
- malf_cooldown = world.time + 100
-
+ to_chat(owner, "RCD detonation pulse emitted.")
+ owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, 0)
+//Unlock Mech Domination: Unlocks the ability to dominate mechs. Big shocker, right?
/datum/AI_Module/large/mecha_domination
- module_name = "Viral Mech Domination"
+ module_name = "Unlock Mech Domination"
mod_pick_name = "mechjack"
- description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave. \
+ description = "Allows you to hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave.\
Do not allow the mech to leave the station's vicinity or allow it to be destroyed."
cost = 30
- one_time = 1
-
- power_type = /mob/living/silicon/ai/proc/mech_takeover
-
-/mob/living/silicon/ai/proc/mech_takeover()
- set name = "Compile Mecha Virus"
- set category = "Malfunction"
- set desc = "Target a mech by clicking it. Click the appropriate command when ready."
-
- if(stat)
- return
-
- can_dominate_mechs = 1 //Yep. This is all it does. Honk!
- to_chat(src, "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.")
-
- verbs -= /mob/living/silicon/ai/proc/mech_takeover
+ upgrade = TRUE
+ unlock_text = "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout."
+ unlock_sound = 'sound/mecha/nominal.ogg'
+/datum/AI_Module/large/mecha_domination/upgrade(mob/living/silicon/ai/AI)
+ AI.can_dominate_mechs = TRUE //Yep. This is all it does. Honk!
+//Thermal Sensor Override: Unlocks the ability to disable all fire alarms from doing their job.
/datum/AI_Module/large/break_fire_alarms
module_name = "Thermal Sensor Override"
mod_pick_name = "burnpigs"
description = "Gives you the ability to override the thermal sensors on all fire alarms. This will remove their ability to scan for fire and thus their ability to alert. \
Anyone can check the fire alarm's interface and may be tipped off by its status."
- one_time = 1
+ one_purchase = TRUE
cost = 25
+ power_type = /datum/action/innate/ai/break_fire_alarms
+ unlock_text = "You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will."
- power_type = /mob/living/silicon/ai/proc/break_fire_alarms
-
-/mob/living/silicon/ai/proc/break_fire_alarms()
- set name = "Override Thermal Sensors"
- set category = "Malfunction"
-
- if(stat)
- return
+/datum/action/innate/ai/break_fire_alarms
+ name = "Override Thermal Sensors"
+ desc = "Disables the automatic temperature sensing on all fire alarms, making them effectively useless."
+ button_icon_state = "break_fire_alarms"
+ uses = 1
+/datum/action/innate/ai/break_fire_alarms/Activate()
for(var/obj/machinery/firealarm/F in GLOB.machines)
if(!is_station_level(F.z))
continue
- F.emagged = 1
- to_chat(src, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.")
- verbs -= /mob/living/silicon/ai/proc/break_fire_alarms
-
+ F.emagged = TRUE
+ to_chat(owner, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.")
+ owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0)
+//Air Alarm Safety Override: Unlocks the ability to enable flooding on all air alarms.
/datum/AI_Module/large/break_air_alarms
module_name = "Air Alarm Safety Override"
mod_pick_name = "allow_flooding"
description = "Gives you the ability to disable safeties on all air alarms. This will allow you to use the environmental mode Flood, which disables scrubbers as well as pressure checks on vents. \
Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality."
- one_time = 1
+ one_purchase = TRUE
cost = 50
+ power_type = /datum/action/innate/ai/break_air_alarms
+ unlock_text = "You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard."
- power_type = /mob/living/silicon/ai/proc/break_air_alarms
-
-/mob/living/silicon/ai/proc/break_air_alarms()
- set name = "Disable Air Alarm Safeties"
- set category = "Malfunction"
-
- if(stat)
- return
+/datum/action/innate/ai/break_air_alarms
+ name = "Override Air Alarm Safeties"
+ desc = "Enables the Flood setting on all air alarms."
+ button_icon_state = "break_air_alarms"
+ uses = 1
+/datum/action/innate/ai/break_air_alarms/Activate()
for(var/obj/machinery/alarm/AA in GLOB.machines)
if(!is_station_level(AA.z))
continue
- AA.emagged = 1
- to_chat(src, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.")
- verbs -= /mob/living/silicon/ai/proc/break_air_alarms
-
+ AA.emagged = TRUE
+ to_chat(owner, "All air alarm safeties on the station have been overriden. Air alarms may now use the Flood environmental mode.")
+ owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0)
+//Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase.
/datum/AI_Module/small/overload_machine
module_name = "Machine Overload"
mod_pick_name = "overload"
- description = "Overloads an electrical machine, causing a small explosion. 2 uses."
- uses = 2
+ description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase."
cost = 20
+ power_type = /datum/action/innate/ai/overload_machine
+ unlock_text = "You enable the ability for the station's APCs to direct intense energy into machinery."
- power_type = /mob/living/silicon/ai/proc/overload_machine
+/datum/action/innate/ai/overload_machine
+ name = "Overload Machine"
+ desc = "Overheats a machine, causing a small explosion after a short time."
+ button_icon_state = "overload_machine"
+ uses = 2
+ auto_use_uses = FALSE
-/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M in GLOB.machines)
- set name = "Overload Machine"
- set category = "Malfunction"
+/datum/action/innate/ai/overload_machine/New()
+ ..()
+ desc = "[desc] It has [uses] use\s remaining."
+ button.desc = desc
- if(stat)
+/datum/action/innate/ai/overload_machine/Activate()
+ var/select = input("Choose a device to overload", "Overload Machine", null, null) as null|anything in GLOB.machines
+ if(!select)
return
+ var/obj/machinery/M = select
if(istype(M, /obj/machinery))
- for(var/datum/AI_Module/small/overload_machine/overload in current_modules)
- if(overload.uses > 0)
- overload.uses --
- audible_message("You hear a loud electrical buzzing sound!")
- to_chat(src, "Overloading machine circuitry...")
- spawn(50)
- if(M)
- explosion(get_turf(M), 0,1,1,0)
- qdel(M)
- else
- to_chat(src, "Out of uses.")
+ if(uses > 0)
+ adjust_uses(-1)
+ if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
+ desc = "[initial(desc)] It has [uses] use\s remaining."
+ UpdateButtonIcon()
+ M.audible_message("You hear a loud electrical buzzing sound!")
+ to_chat(owner, "Overloading machine circuitry...")
+ spawn(50)
+ if(M)
+ explosion(get_turf(M), 0,1,1,0)
+ qdel(M)
+ else
+ to_chat(owner, "Out of uses.")
else
- to_chat(src, "That's not a machine.")
-
+ to_chat(owner, "That's not a machine.")
+ return
+//Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself.
/datum/AI_Module/small/override_machine
module_name = "Machine Override"
mod_pick_name = "override"
- description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses."
- uses = 4
+ description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses."
cost = 30
+ power_type = /datum/action/innate/ai/override_machine
+ unlock_text = "You procure a virus from the Space Dark Web and prepare to distribute it to the station's machines."
- power_type = /mob/living/silicon/ai/proc/override_machine
+/datum/action/innate/ai/override_machine
+ name = "Override Machine"
+ desc = "Animates a targeted machine, causing it to attack anyone nearby."
+ button_icon_state = "override_machine"
+ uses = 4
+ auto_use_uses = FALSE
+/datum/action/innate/ai/override_machine/New()
+ ..()
+ desc = "[desc] It has [uses] use\s remaining."
+ button.desc = desc
-/mob/living/silicon/ai/proc/override_machine(obj/machinery/M in GLOB.machines)
- set name = "Override Machine"
- set category = "Malfunction"
-
- if(stat)
+/datum/action/innate/ai/override_machine/Activate()
+ var/select = input("Choose a device to override", "Override Machine", null, null) as null|anything in GLOB.machines
+ if(!select)
return
- if (istype(M, /obj/machinery))
+ var/obj/machinery/M = select
+ if(istype(M, /obj/machinery))
if(!M.can_be_overridden())
- to_chat(src, "Can't override this device.")
- for(var/datum/AI_Module/small/override_machine/override in current_modules)
- if(override.uses > 0)
- override.uses --
- audible_message("You hear a loud electrical buzzing sound!")
- to_chat(src, "Reprogramming machine behaviour...")
- spawn(50)
- if(M && !QDELETED(M))
- new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1)
- else
- to_chat(src, "Out of uses.")
+ to_chat(owner, "Can't override this device.")
+ return
+ else if(uses > 0)
+ adjust_uses(-1)
+ if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
+ desc = "[initial(desc)] It has [uses] use\s remaining."
+ UpdateButtonIcon()
+ M.audible_message("You hear a loud electrical buzzing sound!")
+ to_chat(owner, "Reprogramming machine behaviour...")
+ spawn(50)
+ if(M && !QDELETED(M))
+ new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1)
+ else
+ to_chat(owner, "Out of uses.")
else
- to_chat(src, "That's not a machine.")
-
+ to_chat(owner, "That's not a machine.")
+ return
+//Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting.
/datum/AI_Module/large/place_cyborg_transformer
module_name = "Robotic Factory (Removes Shunting)"
mod_pick_name = "cyborgtransformer"
description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside."
cost = 100
- power_type = /mob/living/silicon/ai/proc/place_transformer
- var/list/turfOverlays = list()
+ one_purchase = TRUE
+ power_type = /datum/action/innate/ai/place_transformer
+ unlock_text = "You prepare a robotics factory for deployment."
+ unlock_sound = 'sound/machines/ping.ogg'
-/datum/AI_Module/large/place_cyborg_transformer/New()
- for(var/i=0;i<3;i++)
- var/image/I = image("icon"='icons/turf/overlays.dmi')
- turfOverlays += I
+/datum/action/innate/ai/place_transformer
+ name = "Place Robotics Factory"
+ desc = "Places a machine that converts humans into cyborgs. Conveyor belts included!"
+ button_icon_state = "robotic_factory"
+ uses = 1
+ auto_use_uses = FALSE //So we can attempt multiple times
+ var/list/turfOverlays
+
+/datum/action/innate/ai/place_transformer/New()
..()
+ for(var/i in 1 to 3)
+ var/image/I = image("icon"='icons/turf/overlays.dmi')
+ LAZYADD(turfOverlays, I)
-/mob/living/silicon/ai/proc/place_transformer()
- set name = "Place Robotic Factory"
- set category = "Malfunction"
-
- if(!canPlaceTransformer())
+/datum/action/innate/ai/place_transformer/Activate()
+ if(!owner_AI.can_place_transformer(src))
return
-
- var/sure = alert(src, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No")
- if(sure == "Yes")
- if(!canPlaceTransformer())
- return
- var/turf/T = get_turf(eyeobj)
- new /obj/machinery/transformer/conveyor(T)
- playsound(T, 'sound/effects/phasein.ogg', 100, 1)
- var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in current_modules
- PCT.uses --
- can_shunt = 0
- to_chat(src, "You cannot shunt anymore.")
-
-/mob/living/silicon/ai/proc/canPlaceTransformer()
- if(!eyeobj || !isturf(src.loc))
+ active = TRUE
+ if(alert(owner, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") == "No")
+ active = FALSE
return
- var/datum/AI_Module/large/place_cyborg_transformer/PCT = locate() in current_modules
- if(!PCT || PCT.uses < 1)
- alert(src, "Out of uses.")
+ if(!owner_AI.can_place_transformer(src))
+ active = FALSE
+ return
+ var/turf/T = get_turf(owner_AI.eyeobj)
+ new /obj/machinery/transformer/conveyor(T)
+ playsound(T, 'sound/effects/phasein.ogg', 100, 1)
+ owner_AI.can_shunt = FALSE
+ to_chat(owner, "You are no longer able to shunt your core to APCs.")
+ adjust_uses(-1)
+
+/mob/living/silicon/ai/proc/remove_transformer_image(client/C, image/I, turf/T)
+ if(C && I.loc == T)
+ C.images -= I
+
+/mob/living/silicon/ai/proc/can_place_transformer(datum/action/innate/ai/place_transformer/action)
+ if(!eyeobj || !isturf(loc) || incapacitated() || !action)
return
var/turf/middle = get_turf(eyeobj)
var/list/turfs = list(middle, locate(middle.x - 1, middle.y, middle.z), locate(middle.x + 1, middle.y, middle.z))
- var/alert_msg = "There isn't enough room. Make sure you are placing the machine in a clear area and on a floor."
- var/success = 1
- if(turfs.len == 3)
- for(var/n=1;n<4,n++)
- var/fail
- var/turf/T = turfs[n]
- if(!istype(T, /turf/simulated/floor))
- fail = 1
- var/datum/camerachunk/C = cameranet.getCameraChunk(T.x, T.y, T.z)
- if(!C.visibleTurfs[T])
- alert_msg = "We cannot get camera vision of this location."
- fail = 1
- for(var/atom/movable/AM in T.contents)
- if(AM.density)
- fail = 1
- var/image/I = PCT.turfOverlays[n]
- I.loc = T
- client.images += I
- if(fail)
- success = 0
- I.icon_state = "redOverlay"
- else
- I.icon_state = "greenOverlay"
- spawn(30)
- if(client && (I.loc == T))
- client.images -= I
- if(success)
- return 1
- alert(src, alert_msg)
-
+ var/alert_msg = "There isn't enough room! Make sure you are placing the machine in a clear area and on a floor."
+ var/success = TRUE
+ for(var/n in 1 to 3) //We have to do this instead of iterating normally because of how overlay images are handled
+ var/turf/T = turfs[n]
+ if(!isfloorturf(T))
+ success = FALSE
+ var/datum/camerachunk/C = cameranet.getCameraChunk(T.x, T.y, T.z)
+ if(!C.visibleTurfs[T])
+ alert_msg = "You don't have camera vision of this location!"
+ success = FALSE
+ for(var/atom/movable/AM in T.contents)
+ if(AM.density)
+ alert_msg = "That area must be clear of objects!"
+ success = FALSE
+ var/image/I = action.turfOverlays[n]
+ I.loc = T
+ client.images += I
+ I.icon_state = "[success ? "green" : "red"]Overlay" //greenOverlay and redOverlay for success and failure respectively
+ addtimer(CALLBACK(src, .proc/remove_transformer_image, client, I, T), 30)
+ if(!success)
+ to_chat(src, "[alert_msg]")
+ return success
+//Blackout: Overloads a random number of lights across the station. Three uses.
/datum/AI_Module/small/blackout
module_name = "Blackout"
mod_pick_name = "blackout"
- description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses."
- uses = 3
+ description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses."
cost = 15
+ power_type = /datum/action/innate/ai/blackout
+ unlock_text = "You hook into the powernet and route bonus power towards the station's lighting."
- power_type = /mob/living/silicon/ai/proc/blackout
+/datum/action/innate/ai/blackout
+ name = "Blackout"
+ desc = "Overloads random lights across the station."
+ button_icon_state = "blackout"
+ uses = 3
+ auto_use_uses = FALSE
-/mob/living/silicon/ai/proc/blackout()
- set category = "Malfunction"
- set name = "Blackout"
+/datum/action/innate/ai/blackout/New()
+ ..()
+ desc = "[desc] It has [uses] use\s remaining."
+ button.desc = desc
- if(stat)
- return
-
- for(var/datum/AI_Module/small/blackout/blackout in current_modules)
- if(blackout.uses > 0)
- blackout.uses --
- for(var/obj/machinery/power/apc/apc in GLOB.apcs)
- if(prob(30*apc.overload))
- apc.overload_lighting()
- else
- apc.overload++
- to_chat(src, "Overcurrent applied to the powernet.")
+/datum/action/innate/ai/blackout/Activate()
+ for(var/obj/machinery/power/apc/apc in GLOB.apcs)
+ if(prob(30 * apc.overload))
+ apc.overload_lighting()
else
- to_chat(src, "Out of uses.")
-
+ apc.overload++
+ to_chat(owner, "Overcurrent applied to the powernet.")
+ owner.playsound_local(owner, "sparks", 50, 0)
+ adjust_uses(-1)
+ if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
+ desc = "[initial(desc)] It has [uses] use\s remaining."
+ UpdateButtonIcon()
+//Reactivate Camera Network: Reactivates up to 30 cameras across the station.
/datum/AI_Module/small/reactivate_cameras
module_name = "Reactivate Camera Network"
mod_pick_name = "recam"
description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. Can be used to repair up to 30 cameras."
- uses = 30
cost = 10
- one_time = 1
+ one_purchase = TRUE
+ power_type = /datum/action/innate/ai/reactivate_cameras
+ unlock_text = "You deploy nanomachines to the cameranet."
- power_type = /mob/living/silicon/ai/proc/reactivate_cameras
+/datum/action/innate/ai/reactivate_cameras
+ name = "Reactivate Cameras"
+ desc = "Reactivates disabled cameras across the station; remaining uses can be used later."
+ button_icon_state = "reactivate_cameras"
+ uses = 30
+ auto_use_uses = FALSE
+ cooldown_period = 30
-/mob/living/silicon/ai/proc/reactivate_cameras()
- set name = "Reactivate Cameranet"
- set category = "Malfunction"
-
- if(stat || malf_cooldown > world.time)
- return
- var/fixedcams = 0 //Tells the AI how many cams it fixed. Stats are fun.
-
- for(var/datum/AI_Module/small/reactivate_cameras/camera in current_modules)
- for(var/obj/machinery/camera/C in cameranet.cameras)
- var/initial_range = initial(C.view_range) //To prevent calling the proc twice
- if(camera.uses > 0)
- if(!C.status)
- C.toggle_cam(src, 1) //Reactivates the camera based on status. Badly named proc.
- fixedcams++
- camera.uses--
- if(C.view_range != initial_range)
- C.view_range = initial_range //Fixes cameras with bad focus.
- camera.uses--
- fixedcams++
- //If a camera is both deactivated and has bad focus, it will cost two uses to fully fix!
- else
- to_chat(src, "Out of uses.")
- verbs -= /mob/living/silicon/ai/proc/reactivate_cameras //It is useless now, clean it up.
- break
- to_chat(src, "Diagnostic complete! Operations completed: [fixedcams].")
-
- malf_cooldown = world.time + 30
+/datum/action/innate/ai/reactivate_cameras/New()
+ ..()
+ desc = "[desc] It has [uses] use\s remaining."
+ button.desc = desc
+/datum/action/innate/ai/reactivate_cameras/Activate()
+ var/fixed_cameras = 0
+ for(var/V in cameranet.cameras)
+ if(!uses)
+ break
+ var/obj/machinery/camera/C = V
+ if(!C.status || C.view_range != initial(C.view_range))
+ C.toggle_cam(owner_AI, 0) //Reactivates the camera based on status. Badly named proc.
+ C.view_range = initial(C.view_range)
+ fixed_cameras++
+ uses-- //Not adjust_uses() so it doesn't automatically delete or show a message
+ to_chat(owner, "Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].")
+ owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0)
+ adjust_uses(0, TRUE) //Checks the uses remaining
+ if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
+ desc = "[initial(desc)] It has [uses] use\s remaining."
+ UpdateButtonIcon()
+//Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision.
/datum/AI_Module/large/upgrade_cameras
module_name = "Upgrade Camera Network"
mod_pick_name = "upgradecam"
- description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-Proofing and light-amplified X-ray vision." //I <3 pointless technobabble
+ description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-proofing and light-amplified X-ray vision." //I <3 pointless technobabble
//This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR.
- one_time = 1
+ one_purchase = TRUE
cost = 35 //Decent price for omniscience!
+ upgrade = TRUE
+ unlock_text = "OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online."
+ unlock_sound = 'sound/items/rped.ogg'
- power_type = /mob/living/silicon/ai/proc/upgrade_cameras
+/datum/AI_Module/large/upgrade_cameras/upgrade(mob/living/silicon/ai/AI)
+ AI.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //Night-vision, without which X-ray would be very limited in power.
+ AI.update_sight()
+ var/upgraded_cameras = 0
-/mob/living/silicon/ai/proc/upgrade_cameras()
- set name = "Upgrade Cameranet"
- set category = "Malfunction"
-
- if(stat)
- return
-
- var/upgradedcams = 0
- RegisterSignal(src, COMSIG_MOB_UPDATE_SIGHT, .proc/update_upgraded_cameras_sight) //Makes sure the AI has night vision, without which X-ray would be very limited in power.
- update_sight()
-
- for(var/obj/machinery/camera/C in cameranet.cameras)
+ for(var/V in cameranet.cameras)
+ var/obj/machinery/camera/C = V
if(C.assembly)
var/upgraded = FALSE
@@ -514,107 +722,21 @@
upgraded = TRUE
if(upgraded)
- upgradedcams++
+ upgraded_cameras++
- to_chat(src, "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online.")
- verbs -= /mob/living/silicon/ai/proc/upgrade_cameras
-
-/mob/living/silicon/ai/proc/update_upgraded_cameras_sight()
- lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ unlock_text = replacetext(unlock_text, "CAMSUPGRADED", "[upgraded_cameras]") //This works, since unlock text is called after upgrade()
/datum/AI_Module/large/eavesdrop
module_name = "Enhanced Surveillance"
mod_pick_name = "eavesdrop"
description = "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations."
cost = 30
- one_time = 1
+ one_purchase = TRUE
+ upgrade = TRUE
+ unlock_text = "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online."
+ unlock_sound = 'sound/items/rped.ogg'
- power_type = /mob/living/silicon/ai/proc/surveillance
+/datum/AI_Module/large/eavesdrop/upgrade(mob/living/silicon/ai/AI)
+ if(AI.eyeobj)
+ AI.eyeobj.relay_speech = TRUE
-/mob/living/silicon/ai/proc/surveillance()
- set category = "Malfunction"
- set name = "Enhanced Surveillance"
-
- if(eyeobj)
- eyeobj.relay_speech = 1
- to_chat(src, "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.")
- verbs -= /mob/living/silicon/ai/proc/surveillance
-
-
-/datum/module_picker
- var/temp = null
- var/processing_time = 50
- var/list/possible_modules = list()
-
-/datum/module_picker/New()
- for(var/type in subtypesof(/datum/AI_Module))
- var/datum/AI_Module/AM = new type
- if(AM.power_type != null)
- src.possible_modules += AM
-
-/datum/module_picker/proc/remove_verbs(var/mob/living/silicon/ai/A)
-
- for(var/datum/AI_Module/AM in possible_modules)
- A.verbs.Remove(AM.power_type)
-
-
-/datum/module_picker/proc/use(user as mob)
- var/dat
- dat += {"Select use of processing time: (currently #[src.processing_time] left.)
-
- Install Module:
- The number afterwards is the amount of processing time it consumes.
"}
- for(var/datum/AI_Module/large/module in src.possible_modules)
- dat += "[module.module_name]\[?\] ([module.cost])
"
- for(var/datum/AI_Module/small/module in src.possible_modules)
- dat += "[module.module_name]\[?\] ([module.cost])
"
- dat += "
"
- if(src.temp)
- dat += "[src.temp]"
- var/datum/browser/popup = new(user, "modpicker", "Malf Module Menu")
- popup.set_content(dat)
- popup.open()
- return
-
-/datum/module_picker/Topic(href, href_list)
- ..()
-
- if(!isAI(usr))
- return
- var/mob/living/silicon/ai/A = usr
-
- if(A.stat == DEAD)
- to_chat(A, "You are already dead!") //Omae Wa Mou Shindeiru
- return
-
- for(var/datum/AI_Module/AM in possible_modules)
- if(href_list[AM.mod_pick_name])
-
- // Cost check
- if(AM.cost > src.processing_time)
- temp = "You cannot afford this module."
- break
-
- // Add new uses if we can, and it is allowed.
- var/datum/AI_Module/already_AM = locate(AM.type) in A.current_modules
- if(already_AM)
- if(!AM.one_time)
- already_AM.uses += AM.uses
- src.processing_time -= AM.cost
- temp = "Additional use added to [already_AM.module_name]"
- break
- else
- temp = "This module is only needed once."
- break
-
- // Give the power and take away the money.
- A.view_core() //A BYOND bug requires you to be viewing your core before your verbs update
- A.verbs += AM.power_type
- A.current_modules += new AM.type
- temp = AM.description
- src.processing_time -= AM.cost
-
- if(href_list["showdesc"])
- if(AM.mod_pick_name == href_list["showdesc"])
- temp = AM.description
- use(usr)
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index fb3c10e25ec..3c0ca1955fb 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -158,9 +158,9 @@
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
/mob/living/simple_animal/hostile/swarmer/AttackingTarget()
if(!isliving(target))
- target.swarmer_act(src)
+ return target.swarmer_act(src)
else
- ..()
+ return ..()
/mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A)
face_atom(A)
@@ -352,11 +352,11 @@
/obj/structure/lattice/catwalk/swarmer_catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "We have created these for our own benefit. Aborting.")
- return FALSE
+ return FALSE
/obj/structure/shuttle/engine/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This shuttle may be important to us later. Aborting.")
- return FALSE
+ return FALSE
////END CTRL CLICK FOR SWARMERS////
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index 2b6040ed8b6..b8649985da1 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -123,7 +123,7 @@
med_hud_set_health()
med_hud_set_status()
-/mob/living/simple_animal/hostile/guardian/adjustHealth(amount) //The spirit is invincible, but passes on damage to the summoner
+/mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE) //The spirit is invincible, but passes on damage to the summoner
var/damage = amount * damage_transfer
if(summoner)
if(loc == summoner)
diff --git a/code/game/gamemodes/miniantags/guardian/types/assassin.dm b/code/game/gamemodes/miniantags/guardian/types/assassin.dm
index 5eb8c1b1cec..e9ea9239483 100644
--- a/code/game/gamemodes/miniantags/guardian/types/assassin.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/assassin.dm
@@ -26,11 +26,12 @@
stat(null, "Stealth Cooldown Remaining: [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds")
/mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget()
- ..()
- if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille)))
- ToggleMode(1)
+ . = ..()
+ if(.)
+ if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille)))
+ ToggleMode(1)
-/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE)
. = ..()
if(. > 0 && toggle)
ToggleMode(1)
diff --git a/code/game/gamemodes/miniantags/guardian/types/fire.dm b/code/game/gamemodes/miniantags/guardian/types/fire.dm
index 0c5052f48bd..09a202afb91 100644
--- a/code/game/gamemodes/miniantags/guardian/types/fire.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/fire.dm
@@ -28,9 +28,9 @@
toggle = TRUE
/mob/living/simple_animal/hostile/guardian/fire/AttackingTarget()
- ..()
+ . = ..()
if(toggle)
- if(ishuman(target) && !summoner)
+ if(. && ishuman(target) && !summoner)
spawn(0)
new /obj/effect/hallucination/delusion(target.loc, target, force_kind = "custom", duration = 200, skip_nearby = 0, custom_icon = icon_state, custom_icon_file = icon)
else
diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm
index d9be543f7e2..bf2c92ffb28 100644
--- a/code/game/gamemodes/miniantags/guardian/types/healer.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm
@@ -43,7 +43,7 @@
stat(null, "Bluespace Beacon Cooldown Remaining: [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds")
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
- ..()
+ . = ..()
if(toggle == TRUE)
if(loc == summoner)
to_chat(src, "You must be manifested to heal!")
diff --git a/code/game/gamemodes/miniantags/guardian/types/lightning.dm b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
index 88d5a43143d..13b9b67f0a9 100644
--- a/code/game/gamemodes/miniantags/guardian/types/lightning.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
@@ -19,8 +19,8 @@
var/successfulshocks = 0
/mob/living/simple_animal/hostile/guardian/beam/AttackingTarget()
- ..()
- if(isliving(target) && target != src && target != summoner)
+ . = ..()
+ if(. && isliving(target) && target != src && target != summoner)
cleardeletedchains()
for(var/chain in enemychains)
var/datum/beam/B = chain
diff --git a/code/game/gamemodes/miniantags/guardian/types/ranged.dm b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
index fe8a566ad52..871d7be1183 100644
--- a/code/game/gamemodes/miniantags/guardian/types/ranged.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
@@ -11,10 +11,9 @@
melee_damage_upper = 10
damage_transfer = 0.9
projectiletype = /obj/item/projectile/guardian
- ranged_cooldown_time = 10
+ ranged_cooldown_time = 1 //fast!
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
ranged = 1
- rapid = 1
range = 13
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 8
diff --git a/code/game/gamemodes/miniantags/guardian/types/standard.dm b/code/game/gamemodes/miniantags/guardian/types/standard.dm
index 1380c4a2e95..dc85a48a480 100644
--- a/code/game/gamemodes/miniantags/guardian/types/standard.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/standard.dm
@@ -19,7 +19,7 @@
battlecry = input
/mob/living/simple_animal/hostile/guardian/punch/AttackingTarget()
- ..()
+ . = ..()
if(iscarbon(target) && target != summoner)
if(length(battlecry) > 11)//no more then 11 letters in a battle cry.
visible_message("[src] punches [target]!")
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index 81e052a85d8..1da936b64ee 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -28,7 +28,7 @@
melee_damage_upper = 20
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- idle_vision_range = 1 // Only attack when target is close
+ vision_range = 1 // Only attack when target is close
wander = 0
attacktext = "glomps"
attack_sound = 'sound/effects/blobattack.ogg'
@@ -54,7 +54,7 @@
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/targeted/smoke)
AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall)
-
+
/mob/living/simple_animal/hostile/morph/examine(mob/user)
if(morphed)
if(form)
@@ -153,7 +153,7 @@
restore()
/mob/living/simple_animal/hostile/morph/LoseAggro()
- vision_range = idle_vision_range
+ vision_range = initial(vision_range)
/mob/living/simple_animal/hostile/morph/AIShouldSleep(var/list/possible_targets)
. = ..()
@@ -179,4 +179,4 @@
if(do_after(src, 20, target = I))
eat(I)
return
- target.attack_animal(src)
+ return ..()
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index 740601f3798..f0d8ede6634 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -85,7 +85,7 @@
/mob/living/simple_animal/revenant/narsie_act()
return //most humans will now be either bones or harvesters, but we're still un-alive.
-/mob/living/simple_animal/revenant/adjustHealth(amount)
+/mob/living/simple_animal/revenant/adjustHealth(amount, updating_health = TRUE)
if(!revealed)
return
essence = max(0, essence-amount)
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 09d5fecb8a2..4a8f215ee47 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -290,10 +290,10 @@
emote_hear = list("gaffaws", "laughs")
response_help = "hugs"
attacktext = "wildly tickles"
- maxHealth = 150
- health = 150
- melee_damage_lower = 20
- melee_damage_upper = 20
+ maxHealth = 175
+ health = 175
+ melee_damage_lower = 25
+ melee_damage_upper = 25
attack_sound = 'sound/items/bikehorn.ogg'
feast_sound = 'sound/spookoween/scary_horn2.ogg'
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 836c51d5a2c..42ebb351e42 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -66,7 +66,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/assassinate/check_completion()
if(target && target.current)
- if(target.current.stat == DEAD)
+ if(target.current.stat == DEAD || iszombie(target))
return 1
if(issilicon(target.current) || isbrain(target.current)) //Borgs/brains/AIs count as dead for traitor objectives. --NeoFite
return 1
@@ -110,7 +110,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
/datum/objective/maroon/check_completion()
if(target && target.current)
- if(target.current.stat == DEAD)
+ if(target.current.stat == DEAD || iszombie(target))
return 1
if(!target.current.ckey)
return 1
@@ -167,7 +167,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
if(!target) //If it's a free objective.
return 1
if(target.current)
- if(target.current.stat == DEAD)
+ if(target.current.stat == DEAD || iszombie(target))
return 0
if(issilicon(target.current))
return 0
@@ -262,7 +262,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
return 0
if(isbrain(owner.current))
return 0
- if(!owner.current || owner.current.stat == DEAD)
+ if(!owner.current || owner.current.stat == DEAD || iszombie(owner))
return 0
if(SSticker.force_ending) //This one isn't their fault, so lets just assume good faith
return 1
@@ -317,7 +317,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
explanation_text = "Die a glorious death."
/datum/objective/die/check_completion()
- if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current))
+ if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current) || iszombie(owner))
return 1
if(issilicon(owner.current) && owner.current != owner.original)
return 1
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index b5f468ad319..4193ad7b751 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -12,7 +12,7 @@
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
-/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied
+/datum/spellbook_entry/proc/IsSpellAvailable() // For config prefs / gamemode restrictions - these are round applied
return 1
/datum/spellbook_entry/proc/CanBuy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book) // Specific circumstances
if(book.uses"
return dat
-/datum/spellbook_entry/noclothes
- name = "Remove Clothes Requirement"
- spell_type = /obj/effect/proc_holder/spell/noclothes
- log_name = "NC"
- category = "Defensive"
+//Main category - Spells
+//Offensive
+/datum/spellbook_entry/blind
+ name = "Blind"
+ spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
+ log_name = "BD"
+ category = "Offensive"
+ cost = 1
-/datum/spellbook_entry/fireball
- name = "Fireball"
- spell_type = /obj/effect/proc_holder/spell/fireball
- log_name = "FB"
+/datum/spellbook_entry/lightningbolt
+ name = "Lightning Bolt"
+ spell_type = /obj/effect/proc_holder/spell/targeted/lightning
+ log_name = "LB"
+ category = "Offensive"
+ cost = 1
-/datum/spellbook_entry/rod_form
- name = "Rod Form"
- spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
- log_name = "RF"
+/datum/spellbook_entry/cluwne
+ name = "Curse of the Cluwne"
+ spell_type = /obj/effect/proc_holder/spell/targeted/touch/cluwne
+ log_name = "CC"
+ category = "Offensive"
-/datum/spellbook_entry/magicm
- name = "Magic Missile"
- spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
- log_name = "MM"
- category = "Defensive"
+/datum/spellbook_entry/banana_touch
+ name = "Banana Touch"
+ spell_type = /obj/effect/proc_holder/spell/targeted/touch/banana
+ log_name = "BT"
+ cost = 1
+
+/datum/spellbook_entry/mime_malaise
+ name = "Mime Malaise"
+ spell_type = /obj/effect/proc_holder/spell/targeted/touch/mime_malaise
+ log_name = "MI"
+ cost = 1
+
+/datum/spellbook_entry/horseman
+ name = "Curse of the Horseman"
+ spell_type = /obj/effect/proc_holder/spell/targeted/horsemask
+ log_name = "HH"
+ category = "Offensive"
/datum/spellbook_entry/disintegrate
name = "Disintegrate"
spell_type = /obj/effect/proc_holder/spell/targeted/touch/disintegrate
log_name = "DG"
+ category = "Offensive"
+/datum/spellbook_entry/fireball
+ name = "Fireball"
+ spell_type = /obj/effect/proc_holder/spell/fireball
+ log_name = "FB"
+ category = "Offensive"
+
+/datum/spellbook_entry/fleshtostone
+ name = "Flesh to Stone"
+ spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
+ log_name = "FS"
+ category = "Offensive"
+
+/datum/spellbook_entry/mutate
+ name = "Mutate"
+ spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate
+ log_name = "MU"
+ category = "Offensive"
+
+/datum/spellbook_entry/rod_form
+ name = "Rod Form"
+ spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
+ log_name = "RF"
+ category = "Offensive"
+
+/datum/spellbook_entry/infinite_guns
+ name = "Lesser Summon Guns"
+ spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns
+ log_name = "IG"
+ category = "Offensive"
+ cost = 4
+
+//Defensive
/datum/spellbook_entry/disabletech
name = "Disable Tech"
spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech
@@ -128,37 +179,6 @@
category = "Defensive"
cost = 1
-/datum/spellbook_entry/repulse
- name = "Repulse"
- spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse
- log_name = "RP"
- category = "Defensive"
-
-/datum/spellbook_entry/timestop
- name = "Time Stop"
- spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
- log_name = "TS"
- category = "Defensive"
-
-/datum/spellbook_entry/smoke
- name = "Smoke"
- spell_type = /obj/effect/proc_holder/spell/targeted/smoke
- log_name = "SM"
- category = "Defensive"
- cost = 1
-
-/datum/spellbook_entry/blind
- name = "Blind"
- spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
- log_name = "BD"
- cost = 1
-
-/datum/spellbook_entry/mindswap
- name = "Mindswap"
- spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
- log_name = "MT"
- category = "Mobility"
-
/datum/spellbook_entry/forcewall
name = "Force Wall"
spell_type = /obj/effect/proc_holder/spell/targeted/forcewall
@@ -173,54 +193,18 @@
category = "Defensive"
cost = 1
-/datum/spellbook_entry/blink
- name = "Blink"
- spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink
- log_name = "BL"
- category = "Mobility"
-
-/datum/spellbook_entry/teleport
- name = "Teleport"
- spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport
- log_name = "TP"
- category = "Mobility"
-
-/datum/spellbook_entry/mutate
- name = "Mutate"
- spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate
- log_name = "MU"
-
-/datum/spellbook_entry/jaunt
- name = "Ethereal Jaunt"
- spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt
- log_name = "EJ"
- category = "Mobility"
-
-/datum/spellbook_entry/knock
- name = "Knock"
- spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock
- log_name = "KN"
- category = "Mobility"
+/datum/spellbook_entry/repulse
+ name = "Repulse"
+ spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse
+ log_name = "RP"
+ category = "Defensive"
cost = 1
-/datum/spellbook_entry/greaterknock
- name = "Greater Knock"
- spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock/greater
- log_name = "GK"
- category = "Mobility"
- cost = 2
- refundable = 0 //global effect on cast
-
-/datum/spellbook_entry/fleshtostone
- name = "Flesh to Stone"
- spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
- log_name = "FS"
-
-/datum/spellbook_entry/summonitem
- name = "Summon Item"
- spell_type = /obj/effect/proc_holder/spell/targeted/summonitem
- log_name = "IS"
- category = "Assistance"
+/datum/spellbook_entry/smoke
+ name = "Smoke"
+ spell_type = /obj/effect/proc_holder/spell/targeted/smoke
+ log_name = "SM"
+ category = "Defensive"
cost = 1
/datum/spellbook_entry/lichdom
@@ -229,28 +213,64 @@
log_name = "LD"
category = "Defensive"
-/datum/spellbook_entry/lichdom/IsAvailible()
+/datum/spellbook_entry/lichdom/IsSpellAvailable()
if(SSticker.mode.name == "ragin' mages")
return FALSE
else
return TRUE
-/datum/spellbook_entry/lightningbolt
- name = "Lightning Bolt"
- spell_type = /obj/effect/proc_holder/spell/targeted/lightning
- log_name = "LB"
+/datum/spellbook_entry/magicm
+ name = "Magic Missile"
+ spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
+ log_name = "MM"
+ category = "Defensive"
-/datum/spellbook_entry/infinite_guns
- name = "Lesser Summon Guns"
- spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns
- log_name = "IG"
- cost = 4
+/datum/spellbook_entry/timestop
+ name = "Time Stop"
+ spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
+ log_name = "TS"
+ category = "Defensive"
-/datum/spellbook_entry/horseman
- name = "Curse of The Horseman"
- spell_type = /obj/effect/proc_holder/spell/targeted/horsemask
- log_name = "HH"
+//Mobility
+/datum/spellbook_entry/knock
+ name = "Knock"
+ spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock
+ log_name = "KN"
+ category = "Mobility"
+ cost = 1
+/datum/spellbook_entry/blink
+ name = "Blink"
+ spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink
+ log_name = "BL"
+ category = "Mobility"
+
+/datum/spellbook_entry/jaunt
+ name = "Ethereal Jaunt"
+ spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt
+ log_name = "EJ"
+ category = "Mobility"
+
+/datum/spellbook_entry/greaterknock
+ name = "Greater Knock"
+ spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock/greater
+ log_name = "GK"
+ category = "Mobility"
+ refundable = 0 //global effect on cast
+
+/datum/spellbook_entry/mindswap
+ name = "Mindswap"
+ spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
+ log_name = "MT"
+ category = "Mobility"
+
+/datum/spellbook_entry/teleport
+ name = "Teleport"
+ spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport
+ log_name = "TP"
+ category = "Mobility"
+
+//Assistance
/datum/spellbook_entry/charge
name = "Charge"
spell_type = /obj/effect/proc_holder/spell/targeted/charge
@@ -258,192 +278,20 @@
category = "Assistance"
cost = 1
-/datum/spellbook_entry/cluwne
- name = "Curse of the Cluwne"
- spell_type = /obj/effect/proc_holder/spell/targeted/touch/cluwne
- log_name = "CC"
-
-/datum/spellbook_entry/item
- name = "Buy Item"
- refundable = 0
- buy_word = "Summon"
- var/item_path= null
-
-
-/datum/spellbook_entry/item/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- new item_path(get_turf(user))
- feedback_add_details("wizard_spell_learned",log_name)
- return 1
-
-/datum/spellbook_entry/item/GetInfo()
- var/dat =""
- dat += "[name]"
- dat += " Cost:[cost]
"
- dat += "[desc]
"
- if(surplus>=0)
- dat += "[surplus] left.
"
- return dat
-
-/datum/spellbook_entry/item/staffchange
- name = "Staff of Change"
- desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
- item_path = /obj/item/gun/magic/staff/change
- log_name = "ST"
-
-/datum/spellbook_entry/item/staffanimation
- name = "Staff of Animation"
- desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines."
- item_path = /obj/item/gun/magic/staff/animate
- log_name = "SA"
+/datum/spellbook_entry/summonitem
+ name = "Summon Item"
+ spell_type = /obj/effect/proc_holder/spell/targeted/summonitem
+ log_name = "IS"
category = "Assistance"
-
-/datum/spellbook_entry/item/staffchaos
- name = "Staff of Chaos"
- desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended."
- item_path = /obj/item/gun/magic/staff/chaos
- log_name = "SC"
-
-/datum/spellbook_entry/item/staffslipping
- name = "Staff of Slipping"
- desc = "A staff that shoots magical bananas. These bananas will either slip or stun the target when hit. Surprisingly reliable!"
- item_path = /obj/item/gun/magic/staff/slipping
- log_name = "SL"
cost = 1
-/datum/spellbook_entry/item/staffdoor
- name = "Staff of Door Creation"
- desc = "A particular staff that can mold solid metal into ornate wooden doors. Useful for getting around in the absence of other transportation. Does not work on glass."
- item_path = /obj/item/gun/magic/staff/door
- log_name = "SD"
- cost = 1
- category = "Mobility"
-
-/datum/spellbook_entry/item/staffhealing
- name = "Staff of Healing"
- desc = "An altruistic staff that can heal the lame and raise the dead."
- item_path = /obj/item/gun/magic/staff/healing
- log_name = "SH"
- cost = 1
- category = "Defensive"
-
-/datum/spellbook_entry/item/scryingorb
- name = "Scrying Orb"
- desc = "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision."
- item_path = /obj/item/scrying
- log_name = "SO"
- category = "Defensive"
-
-/datum/spellbook_entry/item/scryingorb/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- if(..())
- if(!(XRAY in user.mutations))
- user.mutations.Add(XRAY)
- user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
- user.see_in_dark = 8
- user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- to_chat(user, "The walls suddenly disappear.")
- return 1
-
-
-/datum/spellbook_entry/item/soulstones
- name = "Six Soul Stone Shards and the spell Artificer"
- desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot."
- item_path = /obj/item/storage/belt/soulstone/full
- log_name = "SS"
+/datum/spellbook_entry/noclothes
+ name = "Remove Clothes Requirement"
+ spell_type = /obj/effect/proc_holder/spell/noclothes
+ log_name = "NC"
category = "Assistance"
-/datum/spellbook_entry/item/soulstones/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- . =..()
- if(.)
- user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null))
- return .
-
-/datum/spellbook_entry/item/necrostone
- name = "A Necromantic Stone"
- desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command."
- item_path = /obj/item/necromantic_stone
- log_name = "NS"
- category = "Assistance"
-
-/datum/spellbook_entry/item/wands
- name = "Wand Assortment"
- desc = "A collection of wands that allow for a wide variety of utility. Wands do not recharge, so be conservative in use. Comes in a handy belt."
- item_path = /obj/item/storage/belt/wands/full
- log_name = "WA"
- category = "Defensive"
-
-/datum/spellbook_entry/item/armor
- name = "Mastercrafted Armor Set"
- desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space. Comes bundled with Boots of Gripping."
- item_path = /obj/item/clothing/suit/space/hardsuit/wizard
- log_name = "HS"
- category = "Defensive"
-
-/datum/spellbook_entry/item/armor/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- . = ..()
- if(.)
- new /obj/item/clothing/shoes/magboots/wizard(get_turf(user))
- new /obj/item/clothing/gloves/color/purple(get_turf(user))//To complete the outfit
-
-/datum/spellbook_entry/item/contract
- name = "Contract of Apprenticeship"
- desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
- item_path = /obj/item/contract
- log_name = "CT"
- category = "Assistance"
-
-/datum/spellbook_entry/item/bloodbottle
- name = "Bottle of Blood"
- desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim."
- item_path = /obj/item/antag_spawner/slaughter_demon
- log_name = "BB"
- limit = 3
- category = "Assistance"
-
-/datum/spellbook_entry/item/hugbottle
- name = "Bottle of Tickles"
- desc = "A bottle of magically infused fun, the smell of which will \
- attract adorable extradimensional beings when broken. These beings \
- are similar to slaughter demons, but are a little weaker and they do not permamently \
- kill their victims, instead putting them in an extradimensional hugspace, \
- to be released on the demon's death. Chaotic, but not ultimately \
- damaging. The crew's reaction to the other hand could be very \
- destructive."
- item_path = /obj/item/antag_spawner/slaughter_demon/laughter
- cost = 1 //non-destructive; it's just a jape, sibling!
- log_name = "HB"
- limit = 3
- category = "Assistance"
-
-/datum/spellbook_entry/item/oozebottle
- name = "Bottle of Ooze"
- desc = "A bottle of magically infused ooze, which will awake an all-consuming Morph, capable of cunningly disguising itself as any object it comes in contact with and even casting some very basic spells. Be careful though, as Morph diet includes Wizards."
- item_path = /obj/item/antag_spawner/morph
- cost = 1
- log_name = "BO"
- limit = 3
- category = "Assistance"
-
-/datum/spellbook_entry/item/tarotdeck
- name = "Guardian Deck"
- desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \
- It would be wise to avoid buying these with anything capable of causing you to swap bodies with others."
- item_path = /obj/item/guardiancreator
- log_name = "TD"
- limit = 1
- category = "Assistance"
-
-/datum/spellbook_entry/item/mjolnir
- name = "Mjolnir"
- desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power."
- item_path = /obj/item/twohanded/mjollnir
- log_name = "MJ"
-
-/datum/spellbook_entry/item/singularity_hammer
- name = "Singularity Hammer"
- desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everthing nearby to the point of impact."
- item_path = /obj/item/twohanded/singularityhammer
- log_name = "SI"
-
+//Rituals
/datum/spellbook_entry/summon
name = "Summon Stuff"
category = "Rituals"
@@ -472,7 +320,7 @@
cost = 0
log_name = "SGH"
-/datum/spellbook_entry/summon/ghosts/IsAvailible()
+/datum/spellbook_entry/summon/ghosts/IsSpellAvailable()
if(!SSticker.mode) // In case spellbook is placed on map
return FALSE
if(SSticker.mode.name == "ragin' mages")
@@ -493,7 +341,7 @@
cost = 0
log_name = "SG"
-/datum/spellbook_entry/summon/guns/IsAvailible()
+/datum/spellbook_entry/summon/guns/IsSpellAvailable()
if(!SSticker.mode) // In case spellbook is placed on map
return FALSE
if(SSticker.mode.name == "ragin' mages")
@@ -502,7 +350,7 @@
return TRUE
/datum/spellbook_entry/summon/guns/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- feedback_add_details("wizard_spell_learned",log_name)
+ feedback_add_details("wizard_spell_learned", log_name)
user.rightandwrong(0)
book.uses += 1
active = 1
@@ -515,7 +363,7 @@
cost = 0
log_name = "SU"
-/datum/spellbook_entry/summon/magic/IsAvailible()
+/datum/spellbook_entry/summon/magic/IsSpellAvailable()
if(!SSticker.mode) // In case spellbook is placed on map
return FALSE
if(SSticker.mode.name == "ragin' mages")
@@ -524,18 +372,207 @@
return TRUE
/datum/spellbook_entry/summon/magic/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
- feedback_add_details("wizard_spell_learned",log_name)
+ feedback_add_details("wizard_spell_learned", log_name)
user.rightandwrong(1)
book.uses += 1
active = 1
to_chat(user, "You have cast summon magic and gained an extra charge for your spellbook.")
return 1
+//Main category - Magical Items
+/datum/spellbook_entry/item
+ name = "Buy Item"
+ refundable = 0
+ buy_word = "Summon"
+ var/item_path = null
+
+/datum/spellbook_entry/item/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
+ new item_path(get_turf(user))
+ feedback_add_details("wizard_spell_learned", log_name)
+ return 1
+
+/datum/spellbook_entry/item/GetInfo()
+ var/dat =""
+ dat += "[name]"
+ dat += " Cost:[cost]
"
+ dat += "[desc]
"
+ if(surplus>=0)
+ dat += "[surplus] left.
"
+ return dat
+
+//Artefacts
+/datum/spellbook_entry/item/necrostone
+ name = "A Necromantic Stone"
+ desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command."
+ item_path = /obj/item/necromantic_stone
+ log_name = "NS"
+ category = "Artefacts"
+
+/datum/spellbook_entry/item/scryingorb
+ name = "Scrying Orb"
+ desc = "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision."
+ item_path = /obj/item/scrying
+ log_name = "SO"
+ category = "Artefacts"
+
+/datum/spellbook_entry/item/scryingorb/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
+ if(..())
+ if(!(XRAY in user.mutations))
+ user.mutations.Add(XRAY)
+ user.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
+ user.see_in_dark = 8
+ user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ to_chat(user, "The walls suddenly disappear.")
+ return TRUE
+
+/datum/spellbook_entry/item/soulstones
+ name = "Six Soul Stone Shards and the spell Artificer"
+ desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot."
+ item_path = /obj/item/storage/belt/soulstone/full
+ log_name = "SS"
+ category = "Artefacts"
+
+/datum/spellbook_entry/item/soulstones/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
+ . = ..()
+ if(.)
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null))
+ return .
+
+/datum/spellbook_entry/item/wands
+ name = "Wand Assortment"
+ desc = "A collection of wands that allow for a wide variety of utility. Wands do not recharge, so be conservative in use. Comes in a handy belt."
+ item_path = /obj/item/storage/belt/wands/full
+ log_name = "WA"
+ category = "Artefacts"
+
+//Weapons and Armors
+/datum/spellbook_entry/item/armor
+ name = "Mastercrafted Armor Set"
+ desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space. Comes bundled with Boots of Gripping."
+ item_path = /obj/item/clothing/suit/space/hardsuit/wizard
+ log_name = "HS"
+ category = "Weapons and Armors"
+
+/datum/spellbook_entry/item/armor/Buy(var/mob/living/carbon/human/user,var/obj/item/spellbook/book)
+ . = ..()
+ if(.)
+ new /obj/item/clothing/shoes/magboots/wizard(get_turf(user))
+ new /obj/item/clothing/gloves/color/purple(get_turf(user)) // To complete the outfit
+
+/datum/spellbook_entry/item/mjolnir
+ name = "Mjolnir"
+ desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power."
+ item_path = /obj/item/twohanded/mjollnir
+ log_name = "MJ"
+ category = "Weapons and Armors"
+
+/datum/spellbook_entry/item/singularity_hammer
+ name = "Singularity Hammer"
+ desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everthing nearby to the point of impact."
+ item_path = /obj/item/twohanded/singularityhammer
+ log_name = "SI"
+ category = "Weapons and Armors"
+
+//Staves
+/datum/spellbook_entry/item/staffdoor
+ name = "Staff of Door Creation"
+ desc = "A particular staff that can mold solid metal into ornate wooden doors. Useful for getting around in the absence of other transportation. Does not work on glass."
+ item_path = /obj/item/gun/magic/staff/door
+ log_name = "SD"
+ category = "Staves"
+ cost = 1
+
+/datum/spellbook_entry/item/staffhealing
+ name = "Staff of Healing"
+ desc = "An altruistic staff that can heal the lame and raise the dead."
+ item_path = /obj/item/gun/magic/staff/healing
+ log_name = "SH"
+ category = "Staves"
+ cost = 1
+
+/datum/spellbook_entry/item/staffslipping
+ name = "Staff of Slipping"
+ desc = "A staff that shoots magical bananas. These bananas will either slip or stun the target when hit. Surprisingly reliable!"
+ item_path = /obj/item/gun/magic/staff/slipping
+ log_name = "SL"
+ category = "Staves"
+ cost = 1
+
+/datum/spellbook_entry/item/staffanimation
+ name = "Staff of Animation"
+ desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines."
+ item_path = /obj/item/gun/magic/staff/animate
+ log_name = "SA"
+ category = "Staves"
+
+/datum/spellbook_entry/item/staffchange
+ name = "Staff of Change"
+ desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
+ item_path = /obj/item/gun/magic/staff/change
+ log_name = "ST"
+ category = "Staves"
+
+/datum/spellbook_entry/item/staffchaos
+ name = "Staff of Chaos"
+ desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended."
+ item_path = /obj/item/gun/magic/staff/chaos
+ log_name = "SC"
+ category = "Staves"
+
+//Summons
+/datum/spellbook_entry/item/oozebottle
+ name = "Bottle of Ooze"
+ desc = "A bottle of magically infused ooze, which will awake an all-consuming Morph, capable of cunningly disguising itself as any object it comes in contact with and even casting some very basic spells. Be careful though, as Morph diet includes Wizards."
+ item_path = /obj/item/antag_spawner/morph
+ log_name = "BO"
+ category = "Summons"
+ limit = 3
+ cost = 1
+
+/datum/spellbook_entry/item/hugbottle
+ name = "Bottle of Tickles"
+ desc = "A bottle of magically infused fun, the smell of which will \
+ attract adorable extradimensional beings when broken. These beings \
+ are similar to slaughter demons, but are a little weaker and they do not permamently \
+ kill their victims, instead putting them in an extradimensional hugspace, \
+ to be released on the demon's death. Chaotic, but not ultimately \
+ damaging. The crew's reaction to the other hand could be very \
+ destructive."
+ item_path = /obj/item/antag_spawner/slaughter_demon/laughter
+ log_name = "HB"
+ category = "Summons"
+ limit = 3
+ cost = 1 // Non-destructive; it's just a jape, sibling!
+
+/datum/spellbook_entry/item/bloodbottle
+ name = "Bottle of Blood"
+ desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim."
+ item_path = /obj/item/antag_spawner/slaughter_demon
+ log_name = "BB"
+ category = "Summons"
+ limit = 3
+
+/datum/spellbook_entry/item/contract
+ name = "Contract of Apprenticeship"
+ desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
+ item_path = /obj/item/contract
+ log_name = "CT"
+ category = "Summons"
+
+/datum/spellbook_entry/item/tarotdeck
+ name = "Guardian Deck"
+ desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \
+ It would be wise to avoid buying these with anything capable of causing you to swap bodies with others."
+ item_path = /obj/item/guardiancreator
+ log_name = "TD"
+ category = "Summons"
+ limit = 1
+
/obj/item/spellbook
name = "spell book"
desc = "The legendary book of spells of the wizard."
icon = 'icons/obj/library.dmi'
- icon_state ="book"
+ icon_state = "spellbook"
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_TINY
@@ -543,19 +580,24 @@
var/temp = null
var/op = 1
var/tab = null
+ var/main_tab = null
var/mob/living/carbon/human/owner
var/list/datum/spellbook_entry/entries = list()
var/list/categories = list()
+ var/list/main_categories = list("Spells", "Magical Items")
+ var/list/spell_categories = list("Offensive", "Defensive", "Mobility", "Assistance", "Rituals")
+ var/list/item_categories = list("Artefacts", "Weapons and Armors", "Staves", "Summons")
/obj/item/spellbook/proc/initialize()
var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon
for(var/T in entry_types)
var/datum/spellbook_entry/E = new T
- if(E.IsAvailible())
+ if(E.IsSpellAvailable())
entries |= E
categories |= E.category
else
qdel(E)
+ main_tab = main_categories[1]
tab = categories[1]
/obj/item/spellbook/New()
@@ -569,48 +611,64 @@
to_chat(user, "The contract has been used, you can't get your points back now!")
else
to_chat(user, "You feed the contract back into the spellbook, refunding your points.")
-
uses+=2
-
qdel(O)
if(istype(O, /obj/item/antag_spawner/slaughter_demon))
to_chat(user, "On second thought, maybe summoning a demon is a bad idea. You refund your points.")
-
if(istype(O, /obj/item/antag_spawner/slaughter_demon/laughter))
uses += 1
+ for(var/datum/spellbook_entry/item/hugbottle/HB in entries)
+ if(!isnull(HB.limit))
+ HB.limit++
else
uses += 2
- for(var/datum/spellbook_entry/item/bloodbottle/BB in entries)
- if(!isnull(BB.limit))
- BB.limit++
+ for(var/datum/spellbook_entry/item/bloodbottle/BB in entries)
+ if(!isnull(BB.limit))
+ BB.limit++
+ qdel(O)
+
+ if(istype(O, /obj/item/antag_spawner/morph))
+ to_chat(user, "On second thought, maybe awakening a morph is a bad idea. You refund your points.")
+ uses += 1
+ for(var/datum/spellbook_entry/item/oozebottle/OB in entries)
+ if(!isnull(OB.limit))
+ OB.limit++
qdel(O)
/obj/item/spellbook/proc/GetCategoryHeader(var/category)
var/dat = ""
switch(category)
if("Offensive")
- dat += "Spells and items geared towards debilitating and destroying.
"
- dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ dat += "Spells geared towards debilitating and destroying.
"
dat += "For spells: the number after the spell name is the cooldown time.
"
dat += "You can reduce this number by spending more points on the spell.
"
if("Defensive")
- dat += "Spells and items geared towards improving your survivabilty or reducing foes ability to attack.
"
- dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ dat += "Spells geared towards improving your survivabilty or reducing foes ability to attack.
"
dat += "For spells: the number after the spell name is the cooldown time.
"
dat += "You can reduce this number by spending more points on the spell.
"
if("Mobility")
- dat += "Spells and items geared towards improving your ability to move. It is a good idea to take at least one.
"
- dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ dat += "Spells geared towards improving your ability to move. It is a good idea to take at least one.
"
dat += "For spells: the number after the spell name is the cooldown time.
"
dat += "You can reduce this number by spending more points on the spell.
"
if("Assistance")
- dat += "Spells and items geared towards bringing in outside forces to aid you or improving upon your other items and abilties.
"
- dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ dat += "Spells geared towards improving your other items and abilities.
"
dat += "For spells: the number after the spell name is the cooldown time.
"
dat += "You can reduce this number by spending more points on the spell.
"
if("Rituals")
- dat += "These powerful spells change the very fabric of reality. Not always in your favour.
"
+ dat += "These powerful spells are capable of changing the very fabric of reality. Not always in your favour.
"
+ if("Weapons and Armors")
+ dat += "Various weapons and armors to crush your enemies and protect you from harm.
"
+ dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ if("Staves")
+ dat += "Various staves granting you their power, which they slowly recharge over time.
"
+ dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ if("Artefacts")
+ dat += "Various magical artefacts to aid you.
"
+ dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
+ if("Summons")
+ dat += "Magical items geared towards bringing in outside forces to aid you.
"
+ dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
"
return dat
/obj/item/spellbook/proc/wrap(var/content)
@@ -620,11 +678,16 @@
@@ -644,13 +707,29 @@
user.set_machine(src)
var/dat = ""
- dat += ""
+ dat += ""
var/list/cat_dat = list()
- for(var/category in categories)
- cat_dat[category] = "
"
- dat += "- [category]
"
-
- dat += "- Points remaining : [uses]
"
+ for(var/main_category in main_categories)
+ cat_dat[main_category] = "
"
+ dat += "- [main_category]
"
+ dat += "
"
+ switch(main_tab)
+ if("Spells")
+ dat += ""
+ for(var/category in categories)
+ if(category in item_categories)
+ continue
+ cat_dat[category] = "
"
+ dat += "- [category]
"
+ dat += "- Points remaining : [uses]
"
+ if("Magical Items")
+ dat += ""
var/datum/spellbook_entry/E
@@ -674,7 +753,7 @@
dat += cat_dat[category]
dat += ""
- user << browse(wrap(dat), "window=spellbook;size=700x500")
+ user << browse(wrap(dat), "window=spellbook;size=800x600")
onclose(user, "spellbook")
return
@@ -708,13 +787,19 @@
if(!isnull(E.limit))
E.limit += result
uses += result
+ else if(href_list["mainpage"])
+ main_tab = sanitize(href_list["mainpage"])
+ tab = sanitize(href_list["page"])
+ if(main_tab == "Spells")
+ tab = spell_categories[1]
+ else if(main_tab == "Magical Items")
+ tab = item_categories[1]
else if(href_list["page"])
tab = sanitize(href_list["page"])
attack_self(H)
return 1
-//Single Use Spellbooks//
-
+//Single Use Spellbooks
/obj/item/spellbook/oneuse
var/spell = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic
var/spellname = "sandbox"
@@ -748,7 +833,6 @@
user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).")
onlearned(user)
-
/obj/item/spellbook/oneuse/proc/recoil(mob/user)
user.visible_message("[src] glows in a black light!")
@@ -762,7 +846,7 @@
/obj/item/spellbook/oneuse/fireball
spell = /obj/effect/proc_holder/spell/fireball
spellname = "fireball"
- icon_state ="bookfireball"
+ icon_state = "bookfireball"
desc = "This book feels warm to the touch."
/obj/item/spellbook/oneuse/fireball/recoil(mob/user as mob)
@@ -773,7 +857,7 @@
/obj/item/spellbook/oneuse/smoke
spell = /obj/effect/proc_holder/spell/targeted/smoke
spellname = "smoke"
- icon_state ="booksmoke"
+ icon_state = "booksmoke"
desc = "This book is overflowing with the dank arts."
/obj/item/spellbook/oneuse/smoke/recoil(mob/user as mob)
@@ -787,7 +871,7 @@
/obj/item/spellbook/oneuse/blind
spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
spellname = "blind"
- icon_state ="bookblind"
+ icon_state = "bookblind"
desc = "This book looks blurry, no matter how you look at it."
/obj/item/spellbook/oneuse/blind/recoil(mob/user as mob)
@@ -798,7 +882,7 @@
/obj/item/spellbook/oneuse/mindswap
spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
spellname = "mindswap"
- icon_state ="bookmindswap"
+ icon_state = "bookmindswap"
desc = "This book's cover is pristine, though its pages look ragged and torn."
var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps
@@ -830,7 +914,7 @@
/obj/item/spellbook/oneuse/forcewall
spell = /obj/effect/proc_holder/spell/targeted/forcewall
spellname = "forcewall"
- icon_state ="bookforcewall"
+ icon_state = "bookforcewall"
desc = "This book has a dedication to mimes everywhere inside the front cover."
/obj/item/spellbook/oneuse/forcewall/recoil(mob/user as mob)
@@ -840,11 +924,10 @@
S.timer = 30
user.drop_item()
-
/obj/item/spellbook/oneuse/knock
spell = /obj/effect/proc_holder/spell/aoe_turf/knock
spellname = "knock"
- icon_state ="bookknock"
+ icon_state = "bookknock"
desc = "This book is hard to hold closed properly."
/obj/item/spellbook/oneuse/knock/recoil(mob/user as mob)
@@ -855,7 +938,7 @@
/obj/item/spellbook/oneuse/horsemask
spell = /obj/effect/proc_holder/spell/targeted/horsemask
spellname = "horses"
- icon_state ="bookhorses"
+ icon_state = "bookhorses"
desc = "This book is more horse than your mind has room for."
/obj/item/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob)
@@ -875,7 +958,7 @@
/obj/item/spellbook/oneuse/charge
spell = /obj/effect/proc_holder/spell/targeted/charge
spellname = "charging"
- icon_state ="bookcharge"
+ icon_state = "bookcharge"
desc = "This book is made of 100% post-consumer wizard."
/obj/item/spellbook/oneuse/charge/recoil(mob/user as mob)
@@ -886,7 +969,7 @@
/obj/item/spellbook/oneuse/summonitem
spell = /obj/effect/proc_holder/spell/targeted/summonitem
spellname = "instant summons"
- icon_state ="booksummons"
+ icon_state = "booksummons"
desc = "This book is bright and garish, very hard to miss."
/obj/item/spellbook/oneuse/summonitem/recoil(mob/user as mob)
@@ -897,13 +980,13 @@
/obj/item/spellbook/oneuse/fake_gib
spell = /obj/effect/proc_holder/spell/targeted/touch/fake_disintegrate
spellname = "disintegrate"
- icon_state ="bookfireball"
+ icon_state = "bookfireball"
desc = "This book feels like it will rip stuff apart."
/obj/item/spellbook/oneuse/sacredflame
spell = /obj/effect/proc_holder/spell/targeted/sacred_flame
spellname = "sacred flame"
- icon_state ="booksacredflame"
+ icon_state = "booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."
/obj/item/spellbook/oneuse/random
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 407393eb489..0dfd0876817 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -214,7 +214,7 @@
suit = /obj/item/clothing/suit/storage/fr_jacket
shoes = /obj/item/clothing/shoes/white
l_ear = /obj/item/radio/headset/headset_sec/alt
- glasses = /obj/item/clothing/glasses/hud/health/health_advanced
+ glasses = /obj/item/clothing/glasses/hud/health/sunglasses
id = /obj/item/card/id/security
suit_store = /obj/item/flashlight/pen
l_hand = /obj/item/storage/firstaid/adv
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index 3208e9d3533..849f54169f5 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -175,7 +175,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/jackboots
l_ear = /obj/item/radio/headset/heads/blueshield/alt
- glasses = /obj/item/clothing/glasses/hud/health/health_advanced
+ glasses = /obj/item/clothing/glasses/hud/health/sunglasses
id = /obj/item/card/id/nanotrasen
pda = /obj/item/pda/heads/blueshield
backpack_contents = list(
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index aac1c291355..a247fa6810b 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -66,6 +66,12 @@
l_ear = /obj/item/radio/headset/headset_service
pda = /obj/item/pda/chef
+/datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ ..()
+ if(visualsOnly)
+ return
+ var/datum/martial_art/cqc/under_siege/justacook = new
+ justacook.teach(H)
/datum/job/hydro
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 75c4e466a79..a0c0d2234af 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -322,6 +322,9 @@
/obj/machinery/disco/proc/dance(mob/living/M) //Show your moves
set waitfor = FALSE
+ if(M.client && !(M.client.prefs.sound & SOUND_DISCO)) //We have a client that doesn't want to dance.
+ rangers -= M //Doing that here as it'll be checked less often than in processing.
+ return
switch(rand(0,9))
if(0 to 1)
dance2(M)
@@ -460,17 +463,18 @@
var/sound/song_played = sound(selection.song_path)
for(var/mob/M in range(10,src))
- if(!(M in rangers))
- rangers[M] = TRUE
- M.playsound_local(get_turf(M), null, 100, channel = CHANNEL_JUKEBOX, S = song_played)
- if(prob(5+(allowed(M) * 4)) && M.canmove && isliving(M))
- dance(M)
+ if(!M.client || M.client.prefs.sound & SOUND_DISCO)
+ if(!(M in rangers))
+ rangers[M] = TRUE
+ M.playsound_local(get_turf(M), null, 100, channel = CHANNEL_JUKEBOX, S = song_played)
for(var/mob/L in rangers)
if(get_dist(src, L) > 10)
rangers -= L
if(!L || !L.client)
continue
L.stop_sound_channel(CHANNEL_JUKEBOX)
+ else if(prob(9) && L.canmove && isliving(L))
+ dance(L)
else if(active)
active = FALSE
STOP_PROCESSING(SSobj, src)
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index e0fb65787cd..6785c5ed8ff 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -1,144 +1,231 @@
-/*
-CONTAINS:
+#define SINGLE "single"
+#define VERTICAL "vertical"
+#define HORIZONTAL "horizontal"
-Deployable items
-Barricades
+#define METAL 1
+#define WOOD 2
+#define SAND 3
-for reference:
+//Barricades/cover
- access_security = 1
- access_brig = 2
- access_armory = 3
- access_forensics_lockers= 4
- access_medical = 5
- access_morgue = 6
- access_tox = 7
- access_tox_storage = 8
- access_genetics = 9
- access_engine = 10
- access_engine_equip= 11
- access_maint_tunnels = 12
- access_external_airlocks = 13
- access_emergency_storage = 14
- access_change_ids = 15
- access_ai_upload = 16
- access_teleporter = 17
- access_eva = 18
- access_heads = 19
- access_captain = 20
- access_all_personal_lockers = 21
- access_chapel_office = 22
- access_tech_storage = 23
- access_atmospherics = 24
- access_bar = 25
- access_janitor = 26
- access_crematorium = 27
- access_kitchen = 28
- access_robotics = 29
- access_rd = 30
- access_cargo = 31
- access_construction = 32
- access_chemistry = 33
- access_cargo_bot = 34
- access_hydroponics = 35
- access_manufacturing = 36
- access_library = 37
- access_lawyer = 38
- access_virology = 39
- access_cmo = 40
- access_qm = 41
- access_court = 42
- access_clown = 43
- access_mime = 44
-
-*/
-
-
-//Barricades, maybe there will be a metal one later...
/obj/structure/barricade
- anchored = 1.0
- density = 1.0
- var/health = 100.0
- var/maxhealth = 100.0
+ name = "chest high wall"
+ desc = "Looks like this would make good cover."
+ anchored = TRUE
+ density = TRUE
+ max_integrity = 100
+ var/proj_pass_rate = 50 //How many projectiles will pass the cover. Lower means stronger cover
+ var/bar_material = METAL
+ var/drop_amount = 3
var/stacktype = /obj/item/stack/sheet/metal
-/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob, params)
- if(istype(W, stacktype))
- if(src.health < src.maxhealth)
- visible_message("[user] begins to repair the [src]!")
- if(do_after(user, 20 * W.toolspeed, target = src))
- src.health = src.maxhealth
- W:use(1)
- visible_message("[user] repairs the [src]!")
- return
- else
- return
- return
- else if(istype(W, /obj/item/crowbar))
- user.changeNext_move(CLICK_CD_MELEE)
- user.visible_message("[user] is prying apart \the [src].", "You begin to pry apart \the [src].")
- playsound(src, W.usesound, 200, 1)
+/obj/structure/barricade/blob_act(obj/structure/blob/B) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
+ take_damage(400, BRUTE, "melee", 0, get_dir(src, B))
- if(do_after(user, 300 * W.toolspeed, target = src) && !QDELETED(src))
- user.visible_message("[user] pries apart \the [src].", "You pry apart \the [src].")
- dismantle()
+/obj/structure/barricade/ex_act(severity) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
+ if(resistance_flags & INDESTRUCTIBLE)
return
- else
- switch(W.damtype)
- if("fire")
- src.health -= W.force * 1
- if("brute")
- src.health -= W.force * 0.75
- else
- if(src.health <= 0)
- visible_message("\The [src] is smashed apart!")
- dismantle()
- ..()
-
-/obj/structure/barricade/ex_act(severity)
switch(severity)
- if(1.0)
- visible_message("\The [src] is blown apart!")
+ if(1)
+ obj_integrity = 0
qdel(src)
- return
- if(2.0)
- src.health -= 25
- if(src.health <= 0)
- visible_message("\The [src] is blown apart!")
- dismantle()
- return
+ if(2)
+ take_damage(rand(100, 250), BRUTE, "bomb", 0)
+ if(3)
+ take_damage(rand(10, 90), BRUTE, "bomb", 0)
-/obj/structure/barricade/blob_act()
- src.health -= 25
- if(src.health <= 0)
- visible_message("The blob eats through \the [src]!")
- qdel(src)
- return
-
-/obj/structure/barricade/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff.
- if(height==0)
- return 1
- if(istype(mover) && mover.checkpass(PASSTABLE))
- return 1
+/obj/structure/barricade/mech_melee_attack(obj/mecha/M) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
+ M.do_attack_animation(src)
+ var/play_soundeffect = 0
+ var/mech_damtype = M.damtype
+ if(M.selected)
+ mech_damtype = M.selected.damtype
+ play_soundeffect = 1
else
- return 0
+ switch(M.damtype)
+ if(BRUTE)
+ playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
+ if(BURN)
+ playsound(src, 'sound/items/welder.ogg', 50, 1)
+ if(TOX)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1)
+ return 0
+ else
+ return 0
+ visible_message("[M.name] has hit [src].")
+ return take_damage(M.force*3, mech_damtype, "melee", play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
-/obj/structure/barricade/proc/dismantle()
- if(stacktype)
- new stacktype(get_turf(src))
- new stacktype(get_turf(src))
- new stacktype(get_turf(src))
+/obj/structure/barricade/deconstruct(disassembled = TRUE)
+ make_debris()
qdel(src)
+/obj/structure/barricade/proc/make_debris()
+ if(stacktype)
+ new stacktype(get_turf(src), drop_amount)
+
+/obj/structure/barricade/attackby(obj/item/I, mob/user, params)
+ if(iswelder(I) && user.a_intent != INTENT_HARM && bar_material == METAL)
+ var/obj/item/weldingtool/WT = I
+ if(obj_integrity < max_integrity)
+ if(WT.remove_fuel(0, user))
+ to_chat(user, "You begin repairing [src]...")
+ playsound(loc, WT.usesound, 40, 1)
+ if(do_after(user, 40 * I.toolspeed, target = src))
+ obj_integrity = Clamp(obj_integrity + 20, 0, max_integrity)
+ else
+ return ..()
+
+/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
+ if(locate(/obj/structure/barricade) in get_turf(mover))
+ return TRUE
+ else if(istype(mover, /obj/item/projectile))
+ if(!anchored)
+ return TRUE
+ var/obj/item/projectile/proj = mover
+ if(proj.firer && Adjacent(proj.firer))
+ return TRUE
+ if(prob(proj_pass_rate))
+ return TRUE
+ return FALSE
+ else
+ return !density
+
+
+
+/////BARRICADE TYPES///////
+
/obj/structure/barricade/wooden
name = "wooden barricade"
desc = "This space is blocked off by a wooden barricade."
icon = 'icons/obj/structures.dmi'
icon_state = "woodenbarricade"
+ bar_material = WOOD
stacktype = /obj/item/stack/sheet/wood
burn_state = FLAMMABLE
burntime = 25
+/obj/structure/barricade/wooden/attackby(obj/item/I, mob/user)
+ if(istype(I,/obj/item/stack/sheet/wood))
+ var/obj/item/stack/sheet/wood/W = I
+ if(W.amount < 5)
+ to_chat(user, "You need at least five wooden planks to make a wall!")
+ return
+ else
+ to_chat(user, "You start adding [I] to [src]...")
+ if(do_after(user, 50, target = src))
+ W.use(5)
+ new /turf/simulated/wall/mineral/wood/nonmetal(get_turf(src))
+ qdel(src)
+ return
+ return ..()
+
+/obj/structure/barricade/wooden/crude
+ name = "crude plank barricade"
+ desc = "This space is blocked off by a crude assortment of planks."
+ icon_state = "woodenbarricade-old"
+ drop_amount = 1
+ max_integrity = 50
+ proj_pass_rate = 65
+
+/obj/structure/barricade/wooden/crude/snow
+ desc = "This space is blocked off by a crude assortment of planks. It seems to be covered in a layer of snow."
+ icon_state = "woodenbarricade-snow-old"
+ max_integrity = 75
+
+/obj/structure/barricade/sandbags
+ name = "sandbags"
+ desc = "Bags of sand. Self explanatory."
+ icon = 'icons/obj/smooth_structures/sandbags.dmi'
+ icon_state = "sandbags"
+ max_integrity = 280
+ proj_pass_rate = 20
+ pass_flags = LETPASSTHROW
+ bar_material = SAND
+ climbable = TRUE
+ smooth = SMOOTH_TRUE
+ canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/simulated/wall, /turf/simulated/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/simulated/wall/rust, /turf/simulated/wall/r_wall/rust, /obj/structure/barricade/security)
+ stacktype = null
+
+/obj/structure/barricade/security
+ name = "security barrier"
+ desc = "A deployable barrier. Provides good cover in fire fights."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "barrier0"
+ density = FALSE
+ anchored = FALSE
+ max_integrity = 180
+ proj_pass_rate = 20
+ armor = list(melee = 10, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100)
+ stacktype = null
+ var/deploy_time = 40
+ var/deploy_message = TRUE
+
+/obj/structure/barricade/security/New()
+ ..()
+ addtimer(CALLBACK(src, .proc/deploy), deploy_time)
+
+/obj/structure/barricade/security/proc/deploy()
+ icon_state = "barrier1"
+ density = TRUE
+ anchored = TRUE
+ if(deploy_message)
+ visible_message("[src] deploys!")
+
+
+/obj/item/grenade/barrier
+ name = "barrier grenade"
+ desc = "Instant cover."
+ icon = 'icons/obj/grenade.dmi'
+ icon_state = "flashbang"
+ item_state = "flashbang"
+ actions_types = list(/datum/action/item_action/toggle_barrier_spread)
+ var/mode = SINGLE
+
+/obj/item/grenade/barrier/examine(mob/user)
+ . = ..()
+ to_chat(user, "Alt-click to toggle modes.")
+
+/obj/item/grenade/barrier/AltClick(mob/living/carbon/user)
+ if(!istype(user) || !user.Adjacent(src) || user.incapacitated())
+ return
+ toggle_mode(user)
+
+/obj/item/grenade/barrier/proc/toggle_mode(mob/user)
+ switch(mode)
+ if(SINGLE)
+ mode = VERTICAL
+ if(VERTICAL)
+ mode = HORIZONTAL
+ if(HORIZONTAL)
+ mode = SINGLE
+
+ to_chat(user, "[src] is now in [mode] mode.")
+
+/obj/item/grenade/barrier/prime()
+ new /obj/structure/barricade/security(get_turf(loc))
+ switch(mode)
+ if(VERTICAL)
+ var/target_turf = get_step(src, NORTH)
+ if(!(is_blocked_turf(target_turf)))
+ new /obj/structure/barricade/security(target_turf)
+
+ var/target_turf2 = get_step(src, SOUTH)
+ if(!(is_blocked_turf(target_turf2)))
+ new /obj/structure/barricade/security(target_turf2)
+ if(HORIZONTAL)
+ var/target_turf = get_step(src, EAST)
+ if(!(is_blocked_turf(target_turf)))
+ new /obj/structure/barricade/security(target_turf)
+
+ var/target_turf2 = get_step(src, WEST)
+ if(!(is_blocked_turf(target_turf2)))
+ new /obj/structure/barricade/security(target_turf2)
+ qdel(src)
+
+/obj/item/grenade/barrier/ui_action_click(mob/user)
+ toggle_mode(user)
+
+
/obj/structure/barricade/mime
name = "floor"
desc = "Is... this a floor?"
@@ -149,128 +236,10 @@ for reference:
/obj/structure/barricade/mime/mrcd
stacktype = null
-//Actual Deployable machinery stuff
+#undef SINGLE
+#undef VERTICAL
+#undef HORIZONTAL
-/obj/machinery/deployable
- name = "deployable"
- desc = "deployable"
- icon = 'icons/obj/objects.dmi'
- req_access = list(access_security)//I'm changing this until these are properly tested./N
-
-/obj/machinery/deployable/barrier
- name = "deployable barrier"
- desc = "A deployable barrier. Swipe your ID card to lock/unlock it."
- icon = 'icons/obj/objects.dmi'
- anchored = 0.0
- density = 1.0
- icon_state = "barrier0"
- var/health = 100.0
- var/maxhealth = 100.0
- var/locked = 0.0
-// req_access = list(access_maint_tunnels)
-
-/obj/machinery/deployable/barrier/New()
- ..()
-
- src.icon_state = "barrier[src.locked]"
-
-/obj/machinery/deployable/barrier/attackby(obj/item/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/card/id))
- if(src.allowed(user))
- if(src.emagged < 2.0)
- src.locked = !src.locked
- src.anchored = !src.anchored
- src.icon_state = "barrier[src.locked]"
- if((src.locked == 1.0) && (src.emagged < 2.0))
- to_chat(user, "Barrier lock toggled on.")
- return
- else if((src.locked == 0.0) && (src.emagged < 2.0))
- to_chat(user, "Barrier lock toggled off.")
- return
- else
- do_sparks(2, 1, src)
- visible_message("BZZzZZzZZzZT")
- return
- return
- else if(istype(W, /obj/item/wrench))
- if(src.health < src.maxhealth)
- src.health = src.maxhealth
- src.emagged = 0
- src.req_access = list(access_security)
- visible_message("[user] repairs the [src]!")
- return
- else if(src.emagged > 0)
- src.emagged = 0
- src.req_access = list(access_security)
- visible_message("[user] repairs the [src]!")
- return
- return
- else
- switch(W.damtype)
- if("fire")
- src.health -= W.force * 0.75
- if("brute")
- src.health -= W.force * 0.5
- else
- if(src.health <= 0)
- src.explode()
- ..()
-
-/obj/machinery/deployable/barrier/emag_act(user as mob)
- if(!emagged)
- emagged = 1
- req_access = null
- to_chat(user, "You break the ID authentication lock on the [src].")
- do_sparks(2, 1, src)
- visible_message("BZZzZZzZZzZT")
- else if(src.emagged == 1)
- src.emagged = 2
- to_chat(user, "You short out the anchoring mechanism on the [src].")
- do_sparks(2, 1, src)
- visible_message("BZZzZZzZZzZT")
-
-/obj/machinery/deployable/barrier/ex_act(severity)
- switch(severity)
- if(1.0)
- src.explode()
- return
- if(2.0)
- src.health -= 25
- if(src.health <= 0)
- src.explode()
- return
-
-/obj/machinery/deployable/barrier/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- return
- if(prob(50/severity))
- locked = !locked
- anchored = !anchored
- icon_state = "barrier[src.locked]"
-
-/obj/machinery/deployable/barrier/blob_act()
- src.health -= 25
- if(src.health <= 0)
- src.explode()
- return
-
-/obj/machinery/deployable/barrier/CanPass(atom/movable/mover, turf/target, height=0)//So bullets will fly over and stuff.
- if(height==0)
- return 1
- if(istype(mover) && mover.checkpass(PASSTABLE))
- return 1
- else
- return 0
-
-/obj/machinery/deployable/barrier/proc/explode()
- visible_message("[src] blows apart!")
- var/turf/Tsec = get_turf(src)
-
-/* var/obj/item/stack/rods/ =*/
- new /obj/item/stack/rods(Tsec)
-
- do_sparks(3, 1, src)
-
- explosion(src.loc,-1,-1,0)
- if(src)
- qdel(src)
+#undef METAL
+#undef WOOD
+#undef SAND
\ No newline at end of file
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 65854bb1412..89321f2e1a8 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -10,6 +10,7 @@
power_channel = ENVIRON
max_integrity = 350
armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100)
+ flags = PREVENT_CLICK_UNDER
var/closingLayer = CLOSED_DOOR_LAYER
var/visible = 1
var/operating = FALSE
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 797eee044ad..5abfc313047 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -109,6 +109,7 @@
var/obj/item/gun/energy/E = charging
if(E.power_supply.charge < E.power_supply.maxcharge)
E.power_supply.give(E.power_supply.chargerate * recharge_coeff)
+ E.on_recharge()
use_power(250)
using_power = TRUE
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 1532eeaccbd..c15aed3b757 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -203,6 +203,7 @@
if(D.power_supply.charge < D.power_supply.maxcharge)
var/obj/item/ammo_casing/energy/E = D.ammo_type[D.select]
D.power_supply.give(E.e_cost)
+ D.on_recharge()
D.update_icon()
else
D.charge_tick = 0
diff --git a/code/game/machinery/telecomms/ntsl2.dm b/code/game/machinery/telecomms/ntsl2.dm
index a5c4f3f1464..c8501d8181e 100644
--- a/code/game/machinery/telecomms/ntsl2.dm
+++ b/code/game/machinery/telecomms/ntsl2.dm
@@ -109,7 +109,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
"Mime" = "srvradio",
)
// Just command members
- var/heads = list("Captain", "Head of Personnel", "Nanotrasen Representative", "Blueshield", "Chief Engineer", "Chief Medical Officer", "Research Director", "Head of Security")
+ var/heads = list("Captain", "Head of Personnel", "Nanotrasen Representative", "Blueshield", "Chief Engineer", "Chief Medical Officer", "Research Director", "Head of Security", "Magistrate", "AI")
// Just ERT
var/ert_jobs = list("Emergency Response Team Officer", "Emergency Response Team Engineer", "Emergency Response Team Medic", "Emergency Response Team Leader", "Emergency Response Team Member")
// Defined so code compiles and incase someone has a non-standard job
@@ -331,7 +331,7 @@ GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new())
var/job = signal.data["job"]
if((job in ert_jobs) || (job in heads))
for(var/datum/multilingual_say_piece/S in message_pieces)
- S.message = "[S.message]"
+ S.message = "[capitalize(S.message)]" // This only capitalizes the first word
// Hacks!
// Censor dat shit like nobody's business
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index cf7937474c8..3511814a4dd 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -10,15 +10,14 @@
var/display_color = null // Display color for vending machine listing
var/category = CAT_NORMAL // CAT_HIDDEN for contraband, CAT_COIN for premium
-/datum/data/vending_product/New(var/path, var/name = null, var/amount = 1, var/price = 0, var/color = null, var/category = CAT_NORMAL)
+/datum/data/vending_product/New(path, name = null, amount = 1, price = 0, color = null, category = CAT_NORMAL)
..()
product_path = path
if(!name)
- var/atom/tmp = new path
- product_name = initial(tmp.name)
- qdel(tmp)
+ var/atom/temp = path
+ product_name = initial(temp.name)
else
product_name = name
@@ -138,7 +137,7 @@
var/category = current_list[2]
for(var/entry in current_list[1])
- var/datum/data/vending_product/product = new/datum/data/vending_product(entry)
+ var/datum/data/vending_product/product = new /datum/data/vending_product(entry)
product.price = (entry in prices) ? prices[entry] : 0
product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1
@@ -1191,7 +1190,7 @@
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
icon_state = "seeds"
- products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3,
+ products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/cotton = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3,
/obj/item/seeds/cabbage = 3, /obj/item/seeds/carrot = 3, /obj/item/seeds/cherry = 3, /obj/item/seeds/chanter = 3,
/obj/item/seeds/chili = 3, /obj/item/seeds/cocoapod = 3, /obj/item/seeds/coffee = 3, /obj/item/seeds/comfrey =3, /obj/item/seeds/corn = 3,
/obj/item/seeds/nymph =3, /obj/item/seeds/eggplant = 3, /obj/item/seeds/grape = 3, /obj/item/seeds/grass = 3, /obj/item/seeds/lemon = 3,
@@ -1355,7 +1354,7 @@
desc = "Spare tool vending. What? Did you expect some witty description?"
icon_state = "engivend"
icon_deny = "engivend-deny"
- req_access_txt = "11" //Engineering Equipment access
+ req_one_access_txt = "11;24" // Engineers and atmos techs can use this
products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/multitool = 4,/obj/item/airlock_electronics = 10,/obj/item/firelock_electronics = 10,/obj/item/firealarm_electronics = 10,/obj/item/apc_electronics = 10,/obj/item/airalarm_electronics = 10,/obj/item/stock_parts/cell/high = 10,/obj/item/camera_assembly = 10)
contraband = list(/obj/item/stock_parts/cell/potato = 3)
premium = list(/obj/item/storage/belt/utility = 3)
@@ -1470,24 +1469,90 @@
product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!"
vend_delay = 15
vend_reply = "Thank you for using the ClothesMate!"
- products = list(/obj/item/clothing/head/that=2,/obj/item/clothing/head/fedora=1,/obj/item/clothing/glasses/monocle=1,
- /obj/item/clothing/under/suit_jacket/navy=2,/obj/item/clothing/under/kilt=1,/obj/item/clothing/under/overalls=1,
- /obj/item/clothing/under/suit_jacket/really_black=2,/obj/item/clothing/suit/storage/lawyer/blackjacket=2,/obj/item/clothing/under/pants/jeans=3,/obj/item/clothing/under/pants/classicjeans=2,
- /obj/item/clothing/under/pants/camo = 1,/obj/item/clothing/under/pants/blackjeans=2,/obj/item/clothing/under/pants/khaki=2,
- /obj/item/clothing/under/pants/white=2,/obj/item/clothing/under/pants/red=1,/obj/item/clothing/under/pants/black=2,
- /obj/item/clothing/under/pants/tan=2,/obj/item/clothing/under/pants/blue=1,/obj/item/clothing/under/pants/track=1,/obj/item/clothing/suit/jacket/miljacket = 1,
- /obj/item/clothing/accessory/scarf/red=1,/obj/item/clothing/accessory/scarf/green=1,/obj/item/clothing/accessory/scarf/darkblue=1,
- /obj/item/clothing/accessory/scarf/purple=1,/obj/item/clothing/accessory/scarf/yellow=1,/obj/item/clothing/accessory/scarf/orange=1,
- /obj/item/clothing/accessory/scarf/lightblue=1,/obj/item/clothing/accessory/scarf/white=1,/obj/item/clothing/accessory/scarf/black=1,
- /obj/item/clothing/accessory/scarf/zebra=1,/obj/item/clothing/accessory/scarf/christmas=1,/obj/item/clothing/accessory/stripedredscarf=1,
- /obj/item/clothing/accessory/stripedbluescarf=1,/obj/item/clothing/accessory/stripedgreenscarf=1,/obj/item/clothing/accessory/waistcoat=1,
- /obj/item/clothing/under/sundress=2,/obj/item/clothing/under/stripeddress = 1, /obj/item/clothing/under/sailordress = 1, /obj/item/clothing/under/redeveninggown = 1, /obj/item/clothing/under/blacktango=1,/obj/item/clothing/suit/jacket=3,
- /obj/item/clothing/glasses/regular=2,/obj/item/clothing/glasses/sunglasses/fake=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1,
- /obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=2,/obj/item/clothing/shoes/black=4,
- /obj/item/clothing/shoes/sandal=1, /obj/item/clothing/gloves/fingerless=2,
- /obj/item/storage/belt/fannypack=1, /obj/item/storage/belt/fannypack/blue=1, /obj/item/storage/belt/fannypack/red=1, /obj/item/clothing/suit/mantle = 2, /obj/item/clothing/suit/mantle/old = 1, /obj/item/clothing/suit/mantle/regal = 2)
- contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1,/obj/item/storage/belt/fannypack/black=1)
- premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/under/pants/mustangjeans=1)
+ products = list(/obj/item/clothing/head/that = 2,
+ /obj/item/clothing/head/fedora = 1,
+ /obj/item/clothing/glasses/monocle = 1,
+ /obj/item/clothing/under/suit_jacket/navy = 2,
+ /obj/item/clothing/under/kilt = 1,
+ /obj/item/clothing/under/overalls = 1,
+ /obj/item/clothing/under/suit_jacket/really_black = 2,
+ /obj/item/clothing/suit/storage/lawyer/blackjacket = 2,
+ /obj/item/clothing/under/pants/jeans = 3,
+ /obj/item/clothing/under/pants/classicjeans = 2,
+ /obj/item/clothing/under/pants/camo = 1,
+ /obj/item/clothing/under/pants/blackjeans = 2,
+ /obj/item/clothing/under/pants/khaki = 2,
+ /obj/item/clothing/under/pants/white = 2,
+ /obj/item/clothing/under/pants/red = 1,
+ /obj/item/clothing/under/pants/black = 2,
+ /obj/item/clothing/under/pants/tan = 2,
+ /obj/item/clothing/under/pants/blue = 1,
+ /obj/item/clothing/under/pants/track = 1,
+ /obj/item/clothing/suit/jacket/miljacket = 1,
+ /obj/item/clothing/head/beanie = 3,
+ /obj/item/clothing/head/beanie/black = 3,
+ /obj/item/clothing/head/beanie/red = 3,
+ /obj/item/clothing/head/beanie/green = 3,
+ /obj/item/clothing/head/beanie/darkblue = 3,
+ /obj/item/clothing/head/beanie/purple = 3,
+ /obj/item/clothing/head/beanie/yellow = 3,
+ /obj/item/clothing/head/beanie/orange = 3,
+ /obj/item/clothing/head/beanie/cyan = 3,
+ /obj/item/clothing/head/beanie/christmas = 3,
+ /obj/item/clothing/head/beanie/striped = 3,
+ /obj/item/clothing/head/beanie/stripedred = 3,
+ /obj/item/clothing/head/beanie/stripedblue = 3,
+ /obj/item/clothing/head/beanie/stripedgreen = 3,
+ /obj/item/clothing/head/beanie/rasta = 3,
+ /obj/item/clothing/accessory/scarf/red = 1,
+ /obj/item/clothing/accessory/scarf/green = 1,
+ /obj/item/clothing/accessory/scarf/darkblue = 1,
+ /obj/item/clothing/accessory/scarf/purple = 1,
+ /obj/item/clothing/accessory/scarf/yellow = 1,
+ /obj/item/clothing/accessory/scarf/orange = 1,
+ /obj/item/clothing/accessory/scarf/lightblue = 1,
+ /obj/item/clothing/accessory/scarf/white = 1,
+ /obj/item/clothing/accessory/scarf/black = 1,
+ /obj/item/clothing/accessory/scarf/zebra = 1,
+ /obj/item/clothing/accessory/scarf/christmas = 1,
+ /obj/item/clothing/accessory/stripedredscarf = 1,
+ /obj/item/clothing/accessory/stripedbluescarf = 1,
+ /obj/item/clothing/accessory/stripedgreenscarf = 1,
+ /obj/item/clothing/accessory/waistcoat = 1,
+ /obj/item/clothing/under/sundress = 2,
+ /obj/item/clothing/under/stripeddress = 1,
+ /obj/item/clothing/under/sailordress = 1,
+ /obj/item/clothing/under/redeveninggown = 1,
+ /obj/item/clothing/under/blacktango = 1,
+ /obj/item/clothing/suit/jacket = 3,
+ /obj/item/clothing/glasses/regular = 2,
+ /obj/item/clothing/glasses/sunglasses_fake = 2,
+ /obj/item/clothing/head/sombrero = 1,
+ /obj/item/clothing/suit/poncho = 1,
+ /obj/item/clothing/suit/ianshirt = 1,
+ /obj/item/clothing/shoes/laceup = 2,
+ /obj/item/clothing/shoes/black = 4,
+ /obj/item/clothing/shoes/sandal = 1,
+ /obj/item/clothing/gloves/fingerless = 2,
+ /obj/item/storage/belt/fannypack = 1,
+ /obj/item/storage/belt/fannypack/blue = 1,
+ /obj/item/storage/belt/fannypack/red = 1,
+ /obj/item/clothing/suit/mantle = 2,
+ /obj/item/clothing/suit/mantle/old = 1,
+ /obj/item/clothing/suit/mantle/regal = 2)
+
+ contraband = list(/obj/item/clothing/under/syndicate/tacticool = 1,
+ /obj/item/clothing/mask/balaclava = 1,
+ /obj/item/clothing/head/ushanka = 1,
+ /obj/item/clothing/under/soviet = 1,
+ /obj/item/storage/belt/fannypack/black = 1)
+
+ premium = list(/obj/item/clothing/under/suit_jacket/checkered = 1,
+ /obj/item/clothing/head/mailman = 1,
+ /obj/item/clothing/under/rank/mailman = 1,
+ /obj/item/clothing/suit/jacket/leather = 1,
+ /obj/item/clothing/under/pants/mustangjeans = 1)
+
refill_canister = /obj/item/vending_refill/clothing
/obj/machinery/vending/clothing/New()
@@ -1533,7 +1598,7 @@
/obj/item/fish_eggs/electric_eel = 10, /obj/item/fish_eggs/shrimp = 5, /obj/item/toy/pet_rock = 100,
)
contraband = list(/obj/item/fish_eggs/babycarp = 5)
- premium = list(/obj/item/toy/pet_rock/fred = 1, /obj/item/toy/pet_rock/roxie = 1)
+ premium = list(/obj/item/toy/pet_rock/fred = 1, /obj/item/toy/pet_rock/roxie = 1, /obj/item/clothing/gloves/fingerless/rapid/headpat = 1)
refill_canister = /obj/item/vending_refill/crittercare
/obj/machinery/vending/crittercare/free
diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm
index c788e934b45..f4ca5cf613a 100644
--- a/code/game/objects/effects/decals/Cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/Cleanable/aliens.dm
@@ -3,7 +3,7 @@
desc = "It's green and acidic. It looks like... blood?"
icon = 'icons/effects/blood.dmi'
basecolor = "#05EE05"
- bloodiness = MAX_SHOE_BLOODINESS
+ bloodiness = BLOOD_AMOUNT_PER_DECAL
blood_state = BLOOD_STATE_XENO
/obj/effect/decal/cleanable/blood/xeno/splatter
diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm
index c4c903474ef..6c7ea8f3247 100644
--- a/code/game/objects/effects/decals/Cleanable/fuel.dm
+++ b/code/game/objects/effects/decals/Cleanable/fuel.dm
@@ -6,18 +6,18 @@
anchored = TRUE
var/amount = 1 //Basically moles.
-/obj/effect/decal/cleanable/liquid_fuel/Initialize(newLoc, amt = 1)
+/obj/effect/decal/cleanable/liquid_fuel/Initialize(mapload, amt = 1)
+ . = ..()
amount = amt
//Be absorbed by any other liquid fuel in the tile.
- for(var/obj/effect/decal/cleanable/liquid_fuel/other in newLoc)
+ for(var/obj/effect/decal/cleanable/liquid_fuel/other in loc)
if(other != src)
other.amount += amount
spawn other.Spread()
qdel(src)
Spread()
- . = ..()
/obj/effect/decal/cleanable/liquid_fuel/proc/Spread()
//Allows liquid fuels to sometimes flow into other tiles.
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index c410a9130a0..d282e1264e2 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -11,19 +11,30 @@ var/global/list/image/splatter_cache = list()
density = FALSE
anchored = TRUE
layer = TURF_LAYER
+ plane = GAME_PLANE
icon = 'icons/effects/blood.dmi'
icon_state = "mfloor1"
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
blood_DNA = list()
var/base_icon = 'icons/effects/blood.dmi'
var/blood_state = BLOOD_STATE_HUMAN
- var/bloodiness = MAX_SHOE_BLOODINESS
+ bloodiness = BLOOD_AMOUNT_PER_DECAL
var/basecolor = "#A10808" // Color when wet.
var/amount = 5
var/dry_timer = 0
var/off_floor = FALSE
-/obj/effect/decal/cleanable/blood/Initialize()
+
+/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
+ if(C.blood_DNA)
+ blood_DNA |= C.blood_DNA.Copy()
+ if(bloodiness)
+ if(C.bloodiness < MAX_SHOE_BLOODINESS)
+ C.bloodiness += bloodiness
+ return ..()
+
+
+/obj/effect/decal/cleanable/blood/Initialize(mapload)
. = ..()
update_icon()
if(GAMEMODE_IS_CULT)
@@ -87,46 +98,6 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/can_bloodcrawl_in()
return TRUE
-//Add "bloodiness" of this blood's type, to the human's shoes
-/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O, oldloc)
- if(!off_floor && ishuman(O))
- var/mob/living/carbon/human/H = O
- var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
- var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
- var/hasfeet = TRUE
- if(!l_foot && !r_foot)
- hasfeet = FALSE
- if(H.shoes && blood_state && bloodiness)
- var/obj/item/clothing/shoes/S = H.shoes
- var/add_blood = 0
- if(bloodiness >= BLOOD_GAIN_PER_STEP)
- add_blood = BLOOD_GAIN_PER_STEP
- else
- add_blood = bloodiness
- bloodiness -= add_blood
- S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS, S.bloody_shoes[blood_state] + add_blood)
- if(blood_DNA && blood_DNA.len)
- S.add_blood(H.blood_DNA, basecolor)
- S.blood_state = blood_state
- S.blood_color = basecolor
- update_icon()
- H.update_inv_shoes()
- else if(hasfeet && blood_state && bloodiness)//Or feet
- var/add_blood = 0
- if(bloodiness >= BLOOD_GAIN_PER_STEP)
- add_blood = BLOOD_GAIN_PER_STEP
- else
- add_blood = bloodiness
- bloodiness -= add_blood
- H.bloody_feet[blood_state] = min(MAX_SHOE_BLOODINESS, H.bloody_feet[blood_state] + add_blood)
- if(!H.feet_blood_DNA)
- H.feet_blood_DNA = list()
- H.blood_state = blood_state
- H.feet_blood_DNA |= blood_DNA.Copy()
- H.feet_blood_color = basecolor
- update_icon()
- H.update_inv_shoes()
-
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
amount = 2
@@ -167,7 +138,7 @@ var/global/list/image/splatter_cache = list()
amount = 0
var/message
-/obj/effect/decal/cleanable/blood/writing/Initialize()
+/obj/effect/decal/cleanable/blood/writing/Initialize(mapload)
. = ..()
if(random_icon_states.len)
for(var/obj/effect/decal/cleanable/blood/writing/W in loc)
@@ -191,6 +162,8 @@ var/global/list/image/splatter_cache = list()
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
no_clear = TRUE
+ mergeable_decal = FALSE
+
var/fleshcolor = "#FFFFFF"
/obj/effect/decal/cleanable/blood/gibs/update_icon()
@@ -238,7 +211,7 @@ var/global/list/image/splatter_cache = list()
break
-/obj/effect/decal/cleanable/blood/old/Initialize()
+/obj/effect/decal/cleanable/blood/old/Initialize(mapload)
. = ..()
bloodiness = 0
dry()
@@ -246,7 +219,7 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/old/can_bloodcrawl_in()
return FALSE
-/obj/effect/decal/cleanable/blood/gibs/old/Initialize()
+/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload)
. = ..()
bloodiness = 0
dry()
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index d1ba3204bd0..349b8039d92 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -16,6 +16,7 @@
icon_state = "ash"
anchored = TRUE
scoop_reagents = list("ash" = 10)
+ mergeable_decal = FALSE
/obj/effect/decal/cleanable/dirt
name = "dirt"
@@ -30,8 +31,8 @@
smooth = SMOOTH_MORE
mouse_opacity = FALSE
-/obj/effect/decal/cleanable/dirt/Initialize()
- ..()
+/obj/effect/decal/cleanable/dirt/Initialize(mapload)
+ . = ..()
icon_state = ""
/obj/effect/decal/cleanable/dirt/blackpowder
@@ -55,7 +56,7 @@
desc = "It's foam."
color = "#EBEBEB"
-/obj/effect/decal/cleanable/flour/foam/Initialize()
+/obj/effect/decal/cleanable/flour/foam/Initialize(mapload)
. = ..()
QDEL_IN(src, 15 SECONDS)
@@ -97,6 +98,7 @@
gender = NEUTER
icon = 'icons/effects/effects.dmi'
icon_state = "molten"
+ mergeable_decal = FALSE
/obj/effect/decal/cleanable/molten_object/large
name = "big gooey grey mass"
@@ -173,6 +175,7 @@
density = FALSE
anchored = TRUE
layer = TURF_LAYER
+ plane = GAME_PLANE
icon = 'icons/effects/effects.dmi'
icon_state = "flour"
color = "#D5820B"
diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm
index 1c8ad706dc8..5193436295e 100644
--- a/code/game/objects/effects/decals/Cleanable/robots.dm
+++ b/code/game/objects/effects/decals/Cleanable/robots.dm
@@ -5,7 +5,8 @@
icon_state = "gib1"
basecolor = "#030303"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
- bloodiness = MAX_SHOE_BLOODINESS
+ bloodiness = BLOOD_AMOUNT_PER_DECAL
+ mergeable_decal = FALSE
/obj/effect/decal/cleanable/blood/gibs/robot/can_bloodcrawl_in()
return FALSE
diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm
index 1e45c2aa4cf..08b9b402cda 100644
--- a/code/game/objects/effects/decals/Cleanable/tracks.dm
+++ b/code/game/objects/effects/decals/Cleanable/tracks.dm
@@ -30,6 +30,7 @@ var/global/list/image/fluidtrack_cache = list()
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O, oldloc)
+ ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
@@ -40,19 +41,22 @@ var/global/list/image/fluidtrack_cache = list()
hasfeet = FALSE
if(S && S.bloody_shoes[blood_state] && S.blood_color == basecolor)
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
- entered_dirs |= H.dir
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_DNA |= blood_DNA.Copy()
+ if(!(entered_dirs & H.dir))
+ entered_dirs |= H.dir
+ update_icon()
else if(hasfeet && H.bloody_feet[blood_state] && H.feet_blood_color == basecolor)//Or feet //This will need to be changed.
H.bloody_feet[blood_state] = max(H.bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP, 0)
- entered_dirs |= H.dir
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.feet_blood_DNA |= blood_DNA.Copy()
- update_icon()
-
+ if(!(entered_dirs & H.dir))
+ entered_dirs |= H.dir
+ update_icon()
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
+ ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
@@ -63,17 +67,20 @@ var/global/list/image/fluidtrack_cache = list()
hasfeet = FALSE
if(S && S.bloody_shoes[blood_state] && S.blood_color == basecolor)
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
- exited_dirs |= H.dir
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_DNA |= blood_DNA.Copy()
+ if(!(exited_dirs & H.dir))
+ exited_dirs |= H.dir
+ update_icon()
else if(hasfeet && H.bloody_feet[blood_state] && H.feet_blood_color == basecolor)//Or feet
H.bloody_feet[blood_state] = max(H.bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP, 0)
- exited_dirs |= H.dir
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.feet_blood_DNA |= blood_DNA.Copy()
- update_icon()
+ if(!(exited_dirs & H.dir))
+ exited_dirs |= H.dir
+ update_icon()
/obj/effect/decal/cleanable/blood/footprints/update_icon()
@@ -108,14 +115,14 @@ var/global/list/image/fluidtrack_cache = list()
if(ishuman(A))
var/mob/living/carbon/human/H = A
FP.blood_state = H.blood_state
- FP.bloodiness = H.bloody_feet[H.blood_state]
+ FP.bloodiness = H.bloody_feet[H.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.basecolor = H.feet_blood_color
if(H.blood_DNA)
FP.blood_DNA = H.blood_DNA.Copy()
else if(istype(A, /obj/item/clothing/shoes))
var/obj/item/clothing/shoes/S = A
FP.blood_state = S.blood_state
- FP.bloodiness = S.bloody_shoes[S.blood_state]
+ FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.basecolor = S.blood_color
if(S.blood_DNA)
FP.blood_DNA = S.blood_DNA.Copy()
@@ -123,3 +130,8 @@ var/global/list/image/fluidtrack_cache = list()
FP.update_icon()
return FP
+
+/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/footprints/C)
+ if(blood_state != C.blood_state) //We only replace footprints of the same type as us
+ return
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 461273bccdb..870927730a7 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,17 +1,71 @@
/obj/effect/decal/cleanable
anchored = TRUE
var/list/random_icon_states = list()
+ var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
+ var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one?
+
+/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
+ if(mergeable_decal)
+ return TRUE
+
+//Add "bloodiness" of this blood's type, to the human's shoes
+//This is on /cleanable because fuck this ancient mess
+/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O)
+ ..()
+ if(!off_floor && ishuman(O))
+ var/mob/living/carbon/human/H = O
+ var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
+ var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
+ var/hasfeet = TRUE
+ if(!l_foot && !r_foot)
+ hasfeet = FALSE
+ if(H.shoes && blood_state && bloodiness)
+ var/obj/item/clothing/shoes/S = H.shoes
+ var/add_blood = 0
+ if(bloodiness >= BLOOD_GAIN_PER_STEP)
+ add_blood = BLOOD_GAIN_PER_STEP
+ else
+ add_blood = bloodiness
+ bloodiness -= add_blood
+ S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS, S.bloody_shoes[blood_state] + add_blood)
+ if(blood_DNA && blood_DNA.len)
+ S.add_blood(H.blood_DNA, basecolor)
+ S.blood_state = blood_state
+ S.blood_color = basecolor
+ update_icon()
+ H.update_inv_shoes()
+ else if(hasfeet && blood_state && bloodiness)//Or feet
+ var/add_blood = 0
+ if(bloodiness >= BLOOD_GAIN_PER_STEP)
+ add_blood = BLOOD_GAIN_PER_STEP
+ else
+ add_blood = bloodiness
+ bloodiness -= add_blood
+ H.bloody_feet[blood_state] = min(MAX_SHOE_BLOODINESS, H.bloody_feet[blood_state] + add_blood)
+ if(!H.feet_blood_DNA)
+ H.feet_blood_DNA = list()
+ H.blood_state = blood_state
+ H.feet_blood_DNA |= blood_DNA.Copy()
+ H.feet_blood_color = basecolor
+ update_icon()
+ H.update_inv_shoes()
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
-/obj/effect/decal/cleanable/New()
+/obj/effect/decal/cleanable/Initialize(mapload)
+ . = ..()
+ if(loc && isturf(loc))
+ for(var/obj/effect/decal/cleanable/C in loc)
+ if(C != src && C.type == type && !QDELETED(C))
+ if(replace_decal(C))
+ qdel(src)
+ return
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
if(smooth)
queue_smooth(src)
queue_smooth_neighbors(src)
- ..()
/obj/effect/decal/cleanable/Destroy()
if(smooth)
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index ac0007e42ae..06243b1db8a 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -4,12 +4,12 @@
icon = 'icons/effects/crayondecal.dmi'
icon_state = "rune1"
layer = MID_TURF_LAYER
+ plane = GAME_PLANE //makes the graffiti visible over a wall.
anchored = TRUE
-/obj/effect/decal/cleanable/crayon/New(location, main = "#FFFFFF", var/type = "rune1", var/e_name = "rune")
- ..()
- loc = location
+/obj/effect/decal/cleanable/crayon/Initialize(mapload, main = "#FFFFFF", var/type = "rune1", var/e_name = "rune")
+ . = ..()
name = e_name
desc = "A [name] drawn in crayon."
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 8bb117b832c..a145fcea1d4 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -79,7 +79,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
reagents.reaction(A)
if(istype(A,/atom/movable))
var/atom/movable/AM = A
- AM.water_act(life, 310.15, src)
+ AM.water_act(life, COLD_WATER_TEMPERATURE, src)
return ..()
diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm
index c4009516f92..12fc9732bb5 100644
--- a/code/game/objects/effects/effect_system/effects_water.dm
+++ b/code/game/objects/effects/effect_system/effects_water.dm
@@ -21,7 +21,7 @@
reagents.reaction(A)
if(istype(A,/atom/movable))
var/atom/movable/AM = A
- AM.water_act(life, 310.15, src)
+ AM.water_act(life, COLD_WATER_TEMPERATURE, src)
return ..()
/////////////////////////////////////////////
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 7f1683ba415..d6dbf1dddbb 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -140,6 +140,15 @@
..()
animate(src, alpha = 0, time = duration)
+/obj/effect/temp_visual/decoy/fading/threesecond
+ duration = 40
+
+/obj/effect/temp_visual/decoy/fading/fivesecond
+ duration = 50
+
+/obj/effect/temp_visual/decoy/fading/halfsecond
+ duration = 5
+
/obj/effect/temp_visual/fire
icon = 'icons/goonstation/effects/fire.dmi'
icon_state = "3"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 34ec25c902d..935c587fa57 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -87,6 +87,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
If index term exists and icon_override is not set, this sprite sheet will be used.
*/
var/list/sprite_sheets = null
+ var/list/sprite_sheets_inhand = null //Used to override inhand items. Use a single .dmi and suffix the icon states inside with _l and _r for each hand.
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc.
diff --git a/code/game/objects/items/random_items.dm b/code/game/objects/items/random_items.dm
index e51bac10005..65f00e98781 100644
--- a/code/game/objects/items/random_items.dm
+++ b/code/game/objects/items/random_items.dm
@@ -18,8 +18,8 @@
/obj/effect/decal/cleanable/random
name = "Random Mess"
-/obj/effect/decal/cleanable/random/New()
- ..()
+/obj/effect/decal/cleanable/random/Initialize(mapload)
+ . = ..()
var/list/list = subtypesof(/obj/effect/decal/cleanable) - list(/obj/effect/decal/cleanable/random,/obj/effect/decal/cleanable/cobweb,/obj/effect/decal/cleanable/cobweb2)
var/T = pick(list)
new T(loc)
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 0e95f509463..d021c0254a8 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -123,6 +123,19 @@
origin_tech = "biotech=2"
stop_bleeding = 1800
+/obj/item/stack/medical/bruise_pack/attackby(obj/item/I, mob/user, params)
+ if(I.sharp)
+ if(get_amount() < 2)
+ to_chat(user, "You need at least two gauzes to do this!")
+ return
+ new /obj/item/stack/sheet/cloth(user.drop_location())
+ user.visible_message("[user] cuts [src] into pieces of cloth with [I].", \
+ "You cut [src] into pieces of cloth with [I].", \
+ "You hear cutting.")
+ use(2)
+ else
+ return ..()
+
/obj/item/stack/medical/bruise_pack/attack(mob/living/M, mob/user)
if(..())
return 1
@@ -145,6 +158,11 @@
else
to_chat(user, "[affecting] is cut open, you'll need more than a bandage!")
+/obj/item/stack/medical/bruise_pack/improvised
+ name = "improvised gauze"
+ singular_name = "improvised gauze"
+ desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
+ stop_bleeding = 900
/obj/item/stack/medical/bruise_pack/advanced
name = "advanced trauma kit"
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 8c60bcefa11..c9099d6d38b 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -137,6 +137,44 @@ var/global/list/datum/stack_recipe/snow_recipes = list(
..()
recipes = sandstone_recipes
+/*
+ * Sandbags
+ */
+
+/obj/item/stack/sheet/mineral/sandbags
+ name = "sandbags"
+ icon_state = "sandbags"
+ singular_name = "sandbag"
+ layer = LOW_ITEM_LAYER
+ merge_type = /obj/item/stack/sheet/mineral/sandbags
+
+GLOBAL_LIST_INIT(sandbag_recipes, list ( \
+ new/datum/stack_recipe("sandbags", /obj/structure/barricade/sandbags, 1, time = 25, one_per_turf = 1, on_floor = 1), \
+ ))
+
+/obj/item/stack/sheet/mineral/sandbags/New()
+ recipes = GLOB.sandbag_recipes
+ ..()
+
+/obj/item/emptysandbag
+ name = "empty sandbag"
+ desc = "A bag to be filled with sand."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "sandbag"
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/emptysandbag/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/stack/ore/glass))
+ var/obj/item/stack/ore/glass/G = I
+ to_chat(user, "You fill the sandbag.")
+ var/obj/item/stack/sheet/mineral/sandbags/S = new /obj/item/stack/sheet/mineral/sandbags(drop_location())
+ qdel(src)
+ if(Adjacent(user) && !issilicon(user))
+ user.put_in_hands(S)
+ G.use(1)
+ else
+ return ..()
+
/obj/item/stack/sheet/mineral/diamond
name = "diamond"
icon_state = "sheet-diamond"
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index f7df69cad2f..8698a4a2bbe 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -182,6 +182,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list(
new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 10),
new /datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),
+ new /datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50),
new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100)
)
@@ -204,8 +205,9 @@ var/global/list/datum/stack_recipe/wood_recipes = list(
* Cloth
*/
var/global/list/datum/stack_recipe/cloth_recipes = list ( \
- new/datum/stack_recipe("grey jumpsuit", /obj/item/clothing/under/color/grey, 3), \
- new/datum/stack_recipe("black shoes", /obj/item/clothing/shoes/black, 2), \
+ new/datum/stack_recipe("white jumpsuit", /obj/item/clothing/under/color/white, 3), \
+ new/datum/stack_recipe("white shoes", /obj/item/clothing/shoes/white, 2), \
+ new/datum/stack_recipe("white scarf", /obj/item/clothing/accessory/scarf/white, 1), \
null, \
new/datum/stack_recipe("backpack", /obj/item/storage/backpack, 4), \
new/datum/stack_recipe("dufflebag", /obj/item/storage/backpack/duffel, 6), \
@@ -216,11 +218,15 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \
new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \
new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \
null, \
+ new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/bruise_pack/improvised, 1, 2, 6), \
new/datum/stack_recipe("rag", /obj/item/reagent_containers/glass/rag, 1), \
new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 3), \
+ new/datum/stack_recipe("empty sandbag", /obj/item/emptysandbag, 4), \
null, \
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1), \
- new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \
+ new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 3), \
+ new/datum/stack_recipe("white softcap", /obj/item/clothing/head/soft/mime, 2), \
+ new/datum/stack_recipe("white beanie", /obj/item/clothing/head/beanie, 2), \
null, \
new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 3), \
)
@@ -243,6 +249,49 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \
/obj/item/stack/sheet/cloth/ten
amount = 10
+GLOBAL_LIST_INIT(durathread_recipes, list ( \
+ new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/misc/durathread, 4, time = 40),
+ new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
+ new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
+ new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \
+ ))
+
+/obj/item/stack/sheet/durathread
+ name = "durathread"
+ desc = "A fabric sown from incredibly durable threads, known for its usefulness in armor production."
+ singular_name = "durathread roll"
+ icon_state = "sheet-durathread"
+ item_state = "sheet-cloth"
+ resistance_flags = FLAMMABLE
+ force = 0
+ throwforce = 0
+ merge_type = /obj/item/stack/sheet/durathread
+
+/obj/item/stack/sheet/durathread/Initialize(mapload, new_amount, merge = TRUE)
+ recipes = GLOB.durathread_recipes
+ return ..()
+
+/obj/item/stack/sheet/cotton
+ name = "raw cotton bundle"
+ desc = "A bundle of raw cotton ready to be spun on the loom."
+ singular_name = "raw cotton ball"
+ icon_state = "sheet-cotton"
+ resistance_flags = FLAMMABLE
+ force = 0
+ throwforce = 0
+ merge_type = /obj/item/stack/sheet/cotton
+ var/pull_effort = 30
+ var/loom_result = /obj/item/stack/sheet/cloth
+
+/obj/item/stack/sheet/cotton/durathread
+ name = "raw durathread bundle"
+ desc = "A bundle of raw durathread ready to be spun on the loom."
+ singular_name = "raw durathread ball"
+ icon_state = "sheet-durathreadraw"
+ merge_type = /obj/item/stack/sheet/cotton/durathread
+ pull_effort = 70
+ loom_result = /obj/item/stack/sheet/durathread
+
/*
* Cardboard
*/
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index a8ddcf6d315..eda3088199e 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -299,7 +299,7 @@
/obj/effect/decal/cleanable/ash/snappop_phoenix
var/respawn_time = 300
-/obj/effect/decal/cleanable/ash/snappop_phoenix/New()
+/obj/effect/decal/cleanable/ash/snappop_phoenix/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, .proc/respawn), respawn_time)
diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm
index 64f554682fc..503228e58d7 100644
--- a/code/game/objects/items/weapons/pneumaticCannon.dm
+++ b/code/game/objects/items/weapons/pneumaticCannon.dm
@@ -145,7 +145,8 @@
/obj/item/stack/packageWrap = 8,
/obj/item/pipe = 2)
time = 300
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/obj/item/pneumatic_cannon/proc/updateTank(obj/item/tank/thetank, removing = 0, mob/living/carbon/human/user)
if(removing)
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index eb778b6a280..db34f3ae2c8 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -14,6 +14,15 @@
user.dust()
return OBLITERATION
+/obj/item/storage/bible/fart_act(mob/living/M)
+ if(QDELETED(M) || M.stat == DEAD)
+ return
+ M.visible_message("[M] farts on \the [name]!")
+ M.visible_message("A mysterious force smites [M]!")
+ M.suiciding = TRUE
+ do_sparks(3, 1, M)
+ M.gib()
+ return TRUE // Don't run the fart emote
/obj/item/storage/bible/booze
name = "bible"
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 6fb552654d9..d4e1ed2d7f1 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -1059,6 +1059,15 @@
desc = "A colorful cardboard box for the clown"
icon_state = "box_clown"
+/obj/item/storage/box/emptysandbags
+ name = "box of empty sandbags"
+
+/obj/item/storage/box/emptysandbags/New()
+ ..()
+ contents = list()
+ for(var/i in 1 to 7)
+ new /obj/item/emptysandbag(src)
+
/obj/item/storage/box/rndboards
name = "the Liberator's legacy"
desc = "A box containing a gift for worthy golems."
diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm
index 2450648cded..0a2a8bcfbbc 100644
--- a/code/game/objects/items/weapons/storage/briefcase.dm
+++ b/code/game/objects/items/weapons/storage/briefcase.dm
@@ -5,7 +5,7 @@
item_state = "briefcase"
flags = CONDUCT
hitsound = "swing_hit"
- force = 8.0
+ force = 8
throw_speed = 2
throw_range = 4
w_class = WEIGHT_CLASS_BULKY
@@ -20,10 +20,69 @@
force = 10
/obj/item/storage/briefcase/sniperbundle/New()
- ..()
+ ..()
new /obj/item/gun/projectile/automatic/sniper_rifle/syndicate(src)
new /obj/item/clothing/accessory/red(src)
new /obj/item/clothing/under/syndicate/sniper(src)
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
- new /obj/item/suppressor/specialoffer(src)
\ No newline at end of file
+ new /obj/item/suppressor/specialoffer(src)
+
+/obj/item/storage/briefcase/false_bottomed
+ max_w_class = WEIGHT_CLASS_SMALL
+ max_combined_w_class = 10
+
+ var/busy_hunting = FALSE
+ var/bottom_open = FALSE //is the false bottom open?
+ var/obj/item/stored_item = null //what's in the false bottom. If it's a gun, we can fire it
+
+/obj/item/storage/briefcase/false_bottomed/Destroy()
+ if(stored_item)//since the stored_item isn't in the briefcase' contents we gotta remind the game to delete it here.
+ QDEL_NULL(stored_item)
+ return ..()
+
+/obj/item/storage/briefcase/false_bottomed/afterattack(atom/A, mob/user, flag, params)
+ ..()
+ if(stored_item && istype(stored_item, /obj/item/gun) && !Adjacent(A))
+ var/obj/item/gun/stored_gun = stored_item
+ stored_gun.afterattack(A, user, flag, params)
+
+/obj/item/storage/briefcase/false_bottomed/attackby(var/obj/item/I, mob/user)
+ if(isscrewdriver(I))
+ if(!bottom_open && !busy_hunting)
+ to_chat(user, "You begin to hunt around the rim of the [src]...")
+ busy_hunting = TRUE
+ if(do_after(user, 20, target = src))
+ if(user)
+ to_chat(user, "You pry open the false bottom!")
+ bottom_open = TRUE
+ busy_hunting = FALSE
+ else if(bottom_open)
+ to_chat(user, "You push the false bottom down and close it with a click[stored_item ? ", with the [stored_item] snugly inside." : "."]")
+ bottom_open = FALSE
+ else if(bottom_open)
+ if(stored_item)
+ to_chat(user, "There's already something in the false bottom!")
+ return
+ if(I.w_class > WEIGHT_CLASS_NORMAL)
+ to_chat(user, "The [I] is too big to fit in the false bottom!")
+ return
+ if(!user.drop_item(I))
+ user << "The [I] is stuck to your hands!"
+ return
+
+ stored_item = I
+ max_w_class = WEIGHT_CLASS_NORMAL - stored_item.w_class
+ I.forceMove(null) //null space here we go - to stop it showing up in the briefcase
+ to_chat(user, "You place the [I] into the false bottom of the briefcase.")
+ else
+ return ..()
+
+/obj/item/storage/briefcase/false_bottomed/attack_hand(mob/user)
+ if(bottom_open && stored_item)
+ user.put_in_hands(stored_item)
+ to_chat(user, "You pull out the [stored_item] from the [src]'s false bottom.")
+ stored_item = null
+ max_w_class = initial(max_w_class)
+ else
+ return ..()
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index a8f0af13b98..6b68ef19c4c 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -121,6 +121,19 @@
desc = "A sleek, sturdy box"
icon_state = "box_of_doom"
+/obj/item/storage/box/syndie_kit/romerol
+ name = "Romerol Kit"
+ desc = "A box containing a deadly virus capable of reanimating dead as zombies."
+ max_w_class = WEIGHT_CLASS_NORMAL
+ can_hold = list(/obj/item/reagent_containers/glass/bottle/romerol,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/dropper)
+
+/obj/item/storage/box/syndie_kit/romerol/New()
+ ..()
+ new /obj/item/reagent_containers/glass/bottle/romerol(src)
+ new /obj/item/reagent_containers/syringe(src)
+ new /obj/item/reagent_containers/dropper(src)
+ return
+
/obj/item/storage/box/syndie_kit/space
name = "Boxed Space Suit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/syndicate/black/red, /obj/item/clothing/head/helmet/space/syndicate/black/red, /obj/item/tank/emergency_oxygen/syndi, /obj/item/clothing/mask/gas/syndicate)
diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm
index 72394db2733..21f43073b73 100644
--- a/code/game/objects/items/weapons/tanks/jetpack.dm
+++ b/code/game/objects/items/weapons/tanks/jetpack.dm
@@ -48,38 +48,38 @@
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()
-/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()
-/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user as mob)
+/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user)
if(!on)
return 0
if((num < 0.005 || air_contents.total_moles() < num))
- turn_off()
+ turn_off(user)
return 0
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return 0
var/turf/T = get_turf(user)
@@ -163,15 +163,65 @@
to_chat(user, "The meter on [src] indicates you are almost out of air!")
playsound(user, 'sound/effects/alert.ogg', 50, 1)
-/obj/item/tank/jetpack/carbondioxide/mining
- name = "mining jetpack"
+/obj/item/tank/jetpack/suit
+ name = "hardsuit jetpack upgrade"
+ desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment."
icon_state = "jetpack-mining"
- item_state = "jetpack-mining"
+ item_state = "jetpack-black"
origin_tech = "materials=4;magnets=4;engineering=5"
- desc = "A tank of compressed carbon dioxide for miners to use as propulsion in local space. The compact size allows for easy storage at the cost of capacity."
- volume = 40
- throw_range = 7
- w_class = WEIGHT_CLASS_NORMAL //same as syndie harness
+ w_class = WEIGHT_CLASS_NORMAL
+ actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
+ volume = 1
+ slot_flags = null
+ var/datum/gas_mixture/temp_air_contents
+ var/obj/item/tank/tank = null
+ var/mob/living/carbon/human/cur_user
+
+/obj/item/tank/jetpack/suit/New()
+ ..()
+ STOP_PROCESSING(SSobj, src)
+ temp_air_contents = air_contents
+
+/obj/item/tank/jetpack/suit/attack_self()
+ return
+
+/obj/item/tank/jetpack/suit/cycle(mob/user)
+ if(!istype(loc, /obj/item/clothing/suit/space/hardsuit))
+ to_chat(user, "[src] must be connected to a hardsuit!")
+ return
+
+ var/mob/living/carbon/human/H = user
+ if(!istype(H.s_store, /obj/item/tank))
+ to_chat(user, "You need a tank in your suit storage!")
+ return
+ ..()
+
+/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 = user
+ tank = H.s_store
+ air_contents = tank.air_contents
+ START_PROCESSING(SSobj, src)
+ cur_user = user
+ ..()
+
+/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(cur_user)
+ return
+ var/mob/living/carbon/human/H = loc.loc
+ if(!tank || tank != H.s_store)
+ turn_off(cur_user)
+ return
+ ..()
/obj/item/tank/jetpack/rig
name = "jetpack"
@@ -182,7 +232,7 @@
to_chat(usr, "It's a jetpack. If you can see this, report it on the bug tracker.")
return 0
-/obj/item/tank/jetpack/rig/allow_thrust(num, mob/living/user as mob)
+/obj/item/tank/jetpack/rig/allow_thrust(num, mob/living/user)
if(!on)
return 0
@@ -191,7 +241,7 @@
var/datum/gas_mixture/removed = holder.air_supply.air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return 0
var/turf/T = get_turf(user)
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index f42decd4363..501f1780a0b 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -181,16 +181,16 @@
if(prob(10))
visible_message("[owner] Deflects [I] directly back at the thrower! It's a home run!", "You deflect the [I] directly back at the thrower! It's a home run!")
playsound(get_turf(owner), 'sound/weapons/homerun.ogg', 100, 1)
- do_attack_animation(I, ATTACK_EFFECT_DISARM)
+ do_attack_animation(I, ATTACK_EFFECT_DISARM)
I.throw_at(I.thrownby, 20, 20, owner)
deflectmode = FALSE
if(!istype(I, /obj/item/beach_ball))
lastdeflect = world.time + 3000
- return TRUE
+ return TRUE
else if(prob(30))
visible_message("[owner] swings! And [p_they()] miss[p_es()]! How embarassing.", "You swing! You miss! Oh no!")
playsound(get_turf(owner), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
- do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM)
+ do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM)
deflectmode = FALSE
if(!istype(I, /obj/item/beach_ball))
lastdeflect = world.time + 3000
@@ -198,7 +198,7 @@
else
visible_message("[owner] swings and deflects [I]!", "You swing and deflect the [I]!")
playsound(get_turf(owner), 'sound/weapons/baseball_hit.ogg', 50, 1, -1)
- do_attack_animation(I, ATTACK_EFFECT_DISARM)
+ do_attack_animation(I, ATTACK_EFFECT_DISARM)
I.throw_at(get_edge_target_turf(owner, pick(cardinal)), rand(8,10), 14, owner)
deflectmode = FALSE
if(!istype(I, /obj/item/beach_ball))
@@ -239,7 +239,7 @@
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1)
homerun_ready = 0
return
- else
+ else if(!target.anchored)
target.throw_at(throw_target, rand(1,2), 7, user)
/obj/item/melee/baseball_bat/ablative
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 43f45647985..d7900d82e38 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -34,6 +34,15 @@ LINEN BINS
add_fingerprint(user)
return
+/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
+ if(I.sharp)
+ var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
+ transfer_fingerprints_to(C)
+ C.add_fingerprint(user)
+ qdel(src)
+ to_chat(user, "You tear [src] up.")
+ else
+ return ..()
/obj/item/bedsheet/blue
icon_state = "sheetblue"
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 2037293d734..dba81195e6e 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -105,7 +105,7 @@
continue
if(istype(M, /mob/living/simple_animal/bot/mulebot))
continue
- if(M.buckled)
+ if(M.buckled || M.anchored)
continue
M.forceMove(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
index 19e08c15bde..f642960e52e 100644
--- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
+++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm
@@ -15,15 +15,19 @@
var/move_delay = 0
var/egged = 0
-/obj/structure/closet/cardboard/relaymove(mob/user, direction)
- if(opened || move_delay || user.stat || user.stunned || user.weakened || user.paralysis || !isturf(loc) || !has_gravity(loc))
+/obj/structure/closet/cardboard/relaymove(mob/living/user, direction)
+ if(!istype(user) || opened || move_delay || user.incapacitated() || !isturf(loc) || !has_gravity(loc))
return
- move_delay = 1
- if(step(src, direction))
- spawn(config.walk_speed)
- move_delay = 0
+ move_delay = TRUE
+ var/oldloc = loc
+ step(src, direction)
+ if(oldloc != loc)
+ addtimer(CALLBACK(src, .proc/ResetMoveDelay), config.walk_speed)
else
- move_delay = 0
+ move_delay = FALSE
+
+/obj/structure/closet/cardboard/proc/ResetMoveDelay()
+ move_delay = FALSE
/obj/structure/closet/cardboard/open()
if(opened || !can_open())
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 0cd6e541398..0608eb64cbb 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -25,6 +25,7 @@
new /obj/item/clothing/glasses/welding/superior(src)
new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/shoes/brown(src)
+ new /obj/item/tank/jetpack/suit(src)
new /obj/item/cartridge/ce(src)
new /obj/item/radio/headset/heads/ce(src)
new /obj/item/storage/toolbox/mechanical(src)
@@ -147,3 +148,4 @@
new /obj/item/clothing/suit/fire/atmos(src)
new /obj/item/clothing/head/hardhat/atmos(src)
new /obj/item/rpd(src)
+ new /obj/item/destTagger(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index 189cbc5893d..73dbc88487a 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -273,6 +273,7 @@
new /obj/item/key/ambulance(src)
new /obj/item/pinpointer/crew(src)
new /obj/item/clothing/shoes/magboots(src)
+ new /obj/item/handheld_defibrillator(src)
/obj/structure/closet/secure_closet/reagents
name = "chemical storage closet"
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index fe6b0082207..2501c32c2a6 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -251,7 +251,7 @@
new /obj/item/melee/baton/loaded(src)
new /obj/item/clothing/glasses/sunglasses(src)
new /obj/item/clothing/glasses/hud/security/sunglasses/read_only(src)
- new /obj/item/clothing/glasses/hud/health/health_advanced
+ new /obj/item/clothing/glasses/hud/health/sunglasses
new /obj/item/clothing/head/beret/centcom/officer(src)
new /obj/item/clothing/head/beret/centcom/officer/navy(src)
new /obj/item/clothing/suit/armor/vest/blueshield(src)
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index c03b9694cfa..497644a1926 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(captain_display_cases, list())
/proc/updateDisplaycase(mob/living/carbon/human/captain)
if(!GLOB.captain_display_cases.len)
- return
+ return
var/fingerprint = captain.get_full_print()
for(var/item in GLOB.captain_display_cases)
var/obj/structure/displaycase/CASE = item
@@ -113,6 +113,11 @@ GLOBAL_LIST_INIT(captain_display_cases, list())
occupant = new start_showpiece_type(src)
update_icon()
+/obj/structure/displaycase/Destroy()
+ dump()
+ QDEL_NULL(circuit)
+ return ..()
+
/obj/structure/displaycase/captains_laser
name = "captain's display case"
desc = "A display case for the captain's antique laser gun. Hooked up with an anti-theft system."
@@ -125,6 +130,16 @@ GLOBAL_LIST_INIT(captain_display_cases, list())
. = ..()
GLOB.captain_display_cases += src
+/obj/structure/displaycase/captains_laser/Destroy()
+ GLOB.captain_display_cases -= src
+ return ..()
+
+/obj/structure/displaycase/lavaland_winter
+ burglar_alarm = TRUE
+ locked = TRUE
+ req_access = list(access_cent_specops)
+ start_showpiece_type = /obj/item/gun/energy/laser/captain
+
/obj/structure/displaycase/stechkin
name = "officer's display case"
desc = "A display case containing a humble stechkin pistol. Never forget your roots."
@@ -132,15 +147,6 @@ GLOBAL_LIST_INIT(captain_display_cases, list())
req_access = list(access_syndicate_command)
start_showpiece_type = /obj/item/gun/projectile/automatic/pistol
-/obj/structure/displaycase/Destroy()
- dump()
- QDEL_NULL(circuit)
- return ..()
-
-/obj/structure/displaycase/captains_laser/Destroy()
- GLOB.captain_display_cases -= src
- return ..()
-
/obj/structure/displaycase/examine(mob/user)
..(user)
to_chat(user, "Peering through the glass, you see that it contains:")
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index bd97d611576..9c51cc0d451 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -260,6 +260,14 @@
..()
icon_state = "rockpile[rand(1,5)]"
+/obj/structure/flora/rock/icy
+ name = "icy rock"
+ color = "#cce9eb"
+
+/obj/structure/flora/rock/pile/icy
+ name = "icy rocks"
+ color = "#cce9eb"
+
/obj/structure/flora/corn_stalk
name = "corn stalk"
icon = 'icons/obj/flora/plants.dmi'
diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm
index 97bd986ceb9..14ee2765d02 100644
--- a/code/game/objects/structures/ladders.dm
+++ b/code/game/objects/structures/ladders.dm
@@ -1,33 +1,59 @@
+// Basic ladder. By default links to the z-level above/below.
/obj/structure/ladder
name = "ladder"
desc = "A sturdy metal ladder."
icon = 'icons/obj/structures.dmi'
icon_state = "ladder11"
- anchored = 1
- var/id = null
- var/height = 0 //the 'height' of the ladder. higher numbers are considered physically higher
- var/obj/structure/ladder/down = null //the ladder below this one
- var/obj/structure/ladder/up = null //the ladder above this one
- var/use_verb = "climbs"
+ anchored = TRUE
+ var/obj/structure/ladder/down //the ladder below this one
+ var/obj/structure/ladder/up //the ladder above this one
+ var/use_verb = "climb"
-/obj/structure/ladder/New()
- spawn(8)
- for(var/obj/structure/ladder/L in world)
- if(L.id == id)
- if(L.height == (height - 1))
- down = L
- if(isnull(L.up))
- L.up = src
- continue
- if(L.height == (height + 1))
- up = L
- if(isnull(L.down))
- L.down = src
- continue
+/obj/structure/ladder/Initialize(mapload, obj/structure/ladder/up, obj/structure/ladder/down)
+ . = ..()
+ if (up)
+ src.up = up
+ up.down = src
+ up.update_icon()
+ if (down)
+ src.down = down
+ down.up = src
+ down.update_icon()
+ return INITIALIZE_HINT_LATELOAD
- if(up && down) //if both our connections are filled
- break
- update_icon()
+/obj/structure/ladder/Destroy(force)
+ if((resistance_flags & INDESTRUCTIBLE) && !force)
+ return QDEL_HINT_LETMELIVE
+ disconnect()
+ return ..()
+
+/obj/structure/ladder/LateInitialize()
+ // By default, discover ladders above and below us vertically
+ var/turf/T = get_turf(src)
+
+ if(!down)
+ for(var/obj/structure/ladder/L in locate(T.x, T.y, T.z - 1))
+ down = L
+ L.up = src // Don't waste effort looping the other way
+ L.update_icon()
+ break
+ if(!up)
+ for (var/obj/structure/ladder/L in locate(T.x, T.y, T.z + 1))
+ up = L
+ L.down = src // Don't waste effort looping the other way
+ L.update_icon()
+ break
+
+ update_icon()
+
+/obj/structure/ladder/proc/disconnect()
+ if(up && up.down == src)
+ up.down = null
+ up.update_icon()
+ if(down && down.up == src)
+ down.up = null
+ down.update_icon()
+ up = down = null
/obj/structure/ladder/update_icon()
if(up && down)
@@ -42,61 +68,134 @@
else //wtf make your ladders properly assholes
icon_state = "ladder00"
-/obj/structure/ladder/attack_hand(mob/user as mob)
+/obj/structure/ladder/singularity_pull()
+ if(!(resistance_flags & INDESTRUCTIBLE))
+ visible_message("[src] is torn to pieces by the gravitational pull!")
+ qdel(src)
+
+/obj/structure/ladder/proc/travel(going_up, mob/user, is_ghost, obj/structure/ladder/ladder)
+ if(!is_ghost)
+ show_fluff_message(going_up, user)
+ ladder.add_fingerprint(user)
+
+ var/turf/T = get_turf(ladder)
+ var/atom/movable/AM
+ if(user.pulling)
+ AM = user.pulling
+ AM.forceMove(T)
+ user.forceMove(T)
+ if(AM)
+ user.start_pulling(AM)
+
+/obj/structure/ladder/proc/use(mob/user, is_ghost = FALSE)
+ if(!is_ghost && !in_range(src, user))
+ return
+
if(up && down)
- switch( alert("Go up or down the ladder?", "Ladder", "Up", "Down", "Cancel") )
+ var/result = alert("Go up or down [src]?", "[name]", "Up", "Down", "Cancel")
+ if (!is_ghost && !in_range(src, user))
+ return // nice try
+ switch(result)
if("Up")
- user.visible_message("[user] climbs up \the [src]!", \
- "You climb up \the [src]!")
- user.forceMove(get_turf(up))
- up.add_fingerprint(user)
+ travel(TRUE, user, is_ghost, up)
if("Down")
- user.visible_message("[user] climbs down \the [src]!", \
- "You climb down \the [src]!")
- user.forceMove(get_turf(down))
- down.add_fingerprint(user)
+ travel(FALSE, user, is_ghost, down)
if("Cancel")
return
-
else if(up)
- user.visible_message("[user] climbs up \the [src]!", \
- "You climb up \the [src]!")
- user.forceMove(get_turf(up))
- up.add_fingerprint(user)
-
+ travel(TRUE, user, is_ghost, up)
else if(down)
- user.visible_message("[user] climbs down \the [src]!", \
- "You climb down \the [src]!")
- user.forceMove(get_turf(down))
- down.add_fingerprint(user)
+ travel(FALSE, user, is_ghost, down)
+ else
+ to_chat(user, "[src] doesn't seem to lead anywhere!")
- add_fingerprint(user)
+ if(!is_ghost)
+ add_fingerprint(user)
-/obj/structure/ladder/attackby(obj/item/W, mob/user as mob, params)
- return attack_hand(user)
+/obj/structure/ladder/attack_hand(mob/user)
+ use(user)
-/obj/structure/ladder/dive_point/buoy
+/obj/structure/ladder/attackby(obj/item/W, mob/user, params)
+ return use(user)
+
+/obj/structure/ladder/attack_robot(mob/living/silicon/robot/R)
+ if(R.Adjacent(src))
+ return use(R)
+
+//ATTACK GHOST IGNORING PARENT RETURN VALUE
+/obj/structure/ladder/attack_ghost(mob/dead/observer/user)
+ use(user, TRUE)
+
+/obj/structure/ladder/proc/show_fluff_message(going_up, mob/user)
+ if(going_up)
+ user.visible_message("[user] climbs up [src].","You [use_verb] up [src].")
+ else
+ user.visible_message("[user] climbs down [src].","You [use_verb] down [src].")
+
+
+// Indestructible away mission ladders which link based on a mapped ID and height value rather than X/Y/Z.
+/obj/structure/ladder/unbreakable
+ name = "sturdy ladder"
+ desc = "An extremely sturdy metal ladder."
+ resistance_flags = INDESTRUCTIBLE
+ var/id
+ var/height = 0 // higher numbers are considered physically higher
+
+/obj/structure/ladder/unbreakable/Initialize(mapload)
+ GLOB.ladders += src
+ return ..()
+
+/obj/structure/ladder/unbreakable/Destroy()
+ . = ..()
+ if(. != QDEL_HINT_LETMELIVE)
+ GLOB.ladders -= src
+
+/obj/structure/ladder/unbreakable/LateInitialize()
+ // Override the parent to find ladders based on being height-linked
+ if(!id || (up && down))
+ update_icon()
+ return
+
+ for(var/O in GLOB.ladders)
+ var/obj/structure/ladder/unbreakable/L = O
+ if(L.id != id)
+ continue // not one of our pals
+ if(!down && L.height == height - 1)
+ down = L
+ L.up = src
+ L.update_icon()
+ if (up)
+ break // break if both our connections are filled
+ else if(!up && L.height == height + 1)
+ up = L
+ L.down = src
+ L.update_icon()
+ if (down)
+ break // break if both our connections are filled
+
+ update_icon()
+
+/obj/structure/ladder/unbreakable/dive_point/buoy
name = "diving point buoy"
desc = "A buoy marking the location of an underwater dive area."
icon = 'icons/misc/beach.dmi'
icon_state = "buoy"
id = "dive"
height = 2
- use_verb = "dives"
+ use_verb = "swim"
layer = MOB_LAYER + 0.2 //0.1 higher than the water overlay, this also means people can "swim" behind/under it
-/obj/structure/ladder/dive_point/anchor
+/obj/structure/ladder/unbreakable/dive_point/anchor
name = "diving point anchor"
desc = "An anchor tethered to the buoy at the surface, to keep the dive area marked."
icon = 'icons/misc/beach.dmi'
icon_state = "anchor"
id = "dive"
height = 1
- use_verb = "ascends"
light_range = 5
-/obj/structure/ladder/dive_point/New()
- ..()
+/obj/structure/ladder/dive_point/Initialize(mapload)
+ . = ..()
set_light(light_range, light_power) //magical glowing anchor
/obj/structure/ladder/dive_point/update_icon()
diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm
new file mode 100644
index 00000000000..26bd4136c2a
--- /dev/null
+++ b/code/game/objects/structures/loom.dm
@@ -0,0 +1,38 @@
+#define FABRIC_PER_SHEET 4
+
+
+///This is a loom. It's usually made out of wood and used to weave fabric like durathread or cotton into their respective cloth types.
+/obj/structure/loom
+ name = "loom"
+ desc = "A simple device used to weave cloth and other thread-based fabrics together into usable material."
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "loom"
+ density = TRUE
+ anchored = TRUE
+
+/obj/structure/loom/attackby(obj/item/I, mob/user)
+ if(default_unfasten_wrench(user, I, 5))
+ return
+ if(weave(I, user))
+ return
+ return ..()
+
+///Handles the weaving.
+/obj/structure/loom/proc/weave(obj/item/stack/sheet/cotton/W, mob/user)
+ if(!istype(W))
+ return FALSE
+ if(!anchored)
+ user.show_message("The loom needs to be wrenched down.", 1)
+ return FALSE
+ if(W.amount < FABRIC_PER_SHEET)
+ user.show_message("You need at least [FABRIC_PER_SHEET] units of fabric before using this.", 1)
+ return FALSE
+ user.show_message("You start weaving \the [W.name] through the loom..", 1)
+ if(do_after(user, W.pull_effort, target = src))
+ if(W.amount >= FABRIC_PER_SHEET)
+ new W.loom_result(drop_location())
+ W.use(FABRIC_PER_SHEET)
+ user.show_message("You weave \the [W.name] into a workable fabric.", 1)
+ return TRUE
+
+#undef FABRIC_PER_SHEET
\ No newline at end of file
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 93b2e30b6d9..d4296e1df2f 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -91,9 +91,9 @@
if(climber)
climber.Weaken(2)
climber.visible_message("[climber.name] has been knocked off the table", "You've been knocked off the table", "You see [climber.name] get knocked off the table")
- else if(user.pulling.pass_flags & PASSTABLE)
+ else if(Adjacent(user) && user.pulling && user.pulling.pass_flags & PASSTABLE)
user.Move_Pulled(src)
- if (user.pulling.loc == loc)
+ if(user.pulling.loc == loc)
user.visible_message("[user] places [user.pulling] onto [src].",
"You place [user.pulling] onto [src].")
user.stop_pulling()
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index ada70921c99..0958f3cc0e0 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -600,7 +600,7 @@
wateract = (W.wash(user, src))
busy = 0
if(wateract)
- W.water_act(20, 310.15, src)
+ W.water_act(20, COLD_WATER_TEMPERATURE, src)
if("Disconnect")
user.visible_message("[user] starts disconnecting [src].", "You begin disconnecting [src]...")
if(do_after(user, 40 * O.toolspeed, target = src))
@@ -633,7 +633,7 @@
wateract = (O.wash(user, src))
busy = 0
if(wateract)
- O.water_act(20, 310.15, src)
+ O.water_act(20, COLD_WATER_TEMPERATURE, src)
/obj/structure/sink/update_icon()
..()
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 16851097844..4090420525d 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -579,6 +579,7 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
dir = FULLTILE_WINDOW_DIR
level = 3
fulltile = TRUE
+ flags = PREVENT_CLICK_UNDER
/obj/structure/window/full/basic
desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it."
@@ -675,6 +676,7 @@ obj/structure/window/full/reinforced/ice
dir = FULLTILE_WINDOW_DIR
max_integrity = 200
fulltile = TRUE
+ flags = PREVENT_CLICK_UNDER
reinf = TRUE
heat_resistance = 1600
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100)
@@ -734,6 +736,7 @@ obj/structure/window/full/reinforced/ice
smooth = SMOOTH_TRUE
canSmoothWith = null
fulltile = TRUE
+ flags = PREVENT_CLICK_UNDER
dir = FULLTILE_WINDOW_DIR
max_integrity = 120
level = 3
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index f54e28defb1..c67d61770ac 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -25,7 +25,7 @@
/turf/simulated/water_act(volume, temperature, source)
. = ..()
-
+
if(volume >= 3)
MakeSlippery()
@@ -37,7 +37,7 @@
assume_air(lowertemp)
qdel(hotspot)
-/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost
+/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER, infinite = FALSE) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost
if(wet >= wet_setting)
return
wet = wet_setting
@@ -57,11 +57,11 @@
else
wet_overlay = image('icons/effects/water.dmi', src, "wet_static")
overlays += wet_overlay
-
- spawn(rand(790, 820)) // Purely so for visual effect
- if(!istype(src, /turf/simulated)) //Because turfs don't get deleted, they change, adapt, transform, evolve and deform. they are one and they are all.
- return
- MakeDry(wet_setting)
+ if(!infinite)
+ spawn(rand(790, 820)) // Purely so for visual effect
+ if(!istype(src, /turf/simulated)) //Because turfs don't get deleted, they change, adapt, transform, evolve and deform. they are one and they are all.
+ return
+ MakeDry(wet_setting)
/turf/simulated/proc/MakeDry(wet_setting = TURF_WET_WATER)
if(wet > wet_setting)
diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm
index 17807bd255b..1768b2d472a 100644
--- a/code/game/turfs/simulated/floor/chasm.dm
+++ b/code/game/turfs/simulated/floor/chasm.dm
@@ -22,7 +22,7 @@
if(!drop_stuff())
STOP_PROCESSING(SSprocessing, src)
-/turf/open/chasm/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+/turf/simulated/floor/chasm/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "basalt"
return TRUE
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index 12b1654994c..2ce85481751 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -53,6 +53,11 @@
to_chat(user, "You forcefully pry off the planks, destroying them in the process.")
return make_plating()
+/turf/simulated/floor/wood/cold
+ oxygen = 22
+ nitrogen = 82
+ temperature = 180
+
/turf/simulated/floor/grass
name = "grass patch"
icon_state = "grass1"
@@ -117,7 +122,7 @@
burnt = 1
update_icon()
-/turf/open/floor/carpet/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+/turf/simulated/floor/carpet/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/simulated/floor/carpet/black
@@ -142,7 +147,7 @@
floor_tile = /obj/item/stack/tile/arcade_carpet
smooth = SMOOTH_FALSE
-/turf/open/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+/turf/simulated/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
index 3705e24eea0..159f78ddd80 100644
--- a/code/game/turfs/simulated/floor/indestructible.dm
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -23,17 +23,17 @@
return
/turf/simulated/floor/indestructible/attackby(obj/item/I, mob/user, params)
- return
+ return
/turf/simulated/floor/indestructible/attack_hand(mob/user)
- return
+ return
/turf/simulated/floor/indestructible/attack_hulk(mob/user, does_attack_animation = FALSE)
return
/turf/simulated/floor/indestructible/attack_animal(mob/living/simple_animal/M)
return
-
+
/turf/simulated/floor/indestructible/mech_melee_attack(obj/mecha/M)
return
@@ -81,7 +81,7 @@
planetary_atmos = TRUE
desc = "A floor with a square pattern. It's faintly cool to the touch."
-/turf/open/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+/turf/simulated/floor/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
/turf/simulated/floor/indestructible/hierophant/two
diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm
index 66d7eaca83d..b2c29a5ee01 100644
--- a/code/game/turfs/simulated/floor/lava.dm
+++ b/code/game/turfs/simulated/floor/lava.dm
@@ -41,7 +41,7 @@
/turf/simulated/floor/plating/lava/remove_plating()
return
-/turf/open/lava/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+/turf/simulated/floor/plating/lava/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
underlay_appearance.icon = 'icons/turf/floors.dmi'
underlay_appearance.icon_state = "basalt"
return TRUE
diff --git a/code/game/turfs/simulated/floor/mineral.dm b/code/game/turfs/simulated/floor/mineral.dm
index a801fd450c5..9031a0a350c 100644
--- a/code/game/turfs/simulated/floor/mineral.dm
+++ b/code/game/turfs/simulated/floor/mineral.dm
@@ -173,6 +173,18 @@
nitrogen = 0.01
temperature = TCMB
+
+/turf/simulated/floor/mineral/bananium/lubed/Initialize(mapload)
+ . = ..()
+ MakeSlippery(TURF_WET_LUBE, TRUE)
+
+/turf/simulated/floor/mineral/bananium/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ to_chat(H, "You lose your footing trying to pry off the tile!")
+ H.slip("the floor", 0, 5, tilesSlipped = 4, walkSafely = 0, slipAny = 1)
+ return
+
//TRANQUILLITE
/turf/simulated/floor/mineral/tranquillite
name = "silent floor"
diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm
index 5c8f2022189..5a097b5fe5b 100644
--- a/code/game/turfs/simulated/floor/misc_floor.dm
+++ b/code/game/turfs/simulated/floor/misc_floor.dm
@@ -43,7 +43,7 @@
name = "beach"
icon = 'icons/misc/beach.dmi'
-/turf/simulated/floor/beach/pry_tile(obj/item/C, mob/user, silent = FALSE)
+/turf/simulated/floor/beach/pry_tile(obj/item/C, mob/user, silent = FALSE)
return
/turf/simulated/floor/beach/sand
@@ -79,7 +79,7 @@
/turf/simulated/floor/beach/water/Entered(atom/movable/AM, atom/OldLoc)
. = ..()
if(!linkedcontroller)
- return
+ return
if(ismob(AM))
linkedcontroller.mobinpool += AM
@@ -107,6 +107,26 @@
/turf/simulated/floor/noslip/MakeSlippery()
return
+/turf/simulated/floor/noslip/lavaland
+ oxygen = 14
+ nitrogen = 23
+ temperature = 300
+
+/turf/simulated/floor/lubed
+ name = "slippery floor"
+ icon_state = "floor"
+
+/turf/simulated/floor/lubed/Initialize(mapload)
+ . = ..()
+ MakeSlippery(TURF_WET_LUBE, TRUE)
+
+/turf/simulated/floor/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ to_chat(H, "You lose your footing trying to pry off the tile!")
+ H.slip("the floor", 0, 5, tilesSlipped = 4, walkSafely = 0, slipAny = 1)
+ return
+
//Clockwork floor: Slowly heals toxin damage on nearby servants.
/turf/simulated/floor/clockwork
name = "clockwork floor"
@@ -124,7 +144,7 @@
new /obj/effect/temp_visual/ratvar/beam(src)
realappearence = new /obj/effect/clockwork/overlay/floor(src)
realappearence.linked = src
-
+
/turf/simulated/floor/clockwork/Destroy()
if(uses_overlay && realappearence)
QDEL_NULL(realappearence)
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 11ff392b824..819f6a07ef3 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -7,7 +7,7 @@
broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
burnt_states = list("floorscorched1", "floorscorched2")
- var/unfastened = FALSE
+ var/unfastened = FALSE
footstep_sounds = list(
"human" = list('sound/effects/footstep/plating_human.ogg'),
@@ -185,7 +185,7 @@
/turf/simulated/floor/engine/blob_act()
if(prob(25))
ChangeTurf(baseturf)
-
+
/turf/simulated/floor/engine/cult
name = "engraved floor"
icon_state = "cult"
@@ -335,3 +335,28 @@
/turf/simulated/floor/plating/abductor/New()
..()
icon_state = "alienpod[rand(1,9)]"
+
+/turf/simulated/floor/plating/ice
+ name = "ice sheet"
+ desc = "A sheet of solid ice. Looks slippery."
+ icon = 'icons/turf/floors/ice_turfs.dmi'
+ icon_state = "unsmooth"
+ oxygen = 22
+ nitrogen = 82
+ temperature = 180
+ baseturf = /turf/simulated/floor/plating/ice
+ slowdown = TRUE
+ smooth = SMOOTH_TRUE
+ canSmoothWith = list(/turf/simulated/floor/plating/ice/smooth, /turf/simulated/floor/plating/ice)
+
+/turf/simulated/floor/plating/ice/Initialize(mapload)
+ . = ..()
+ MakeSlippery(TURF_WET_PERMAFROST, TRUE)
+
+/turf/simulated/floor/plating/ice/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
+ return
+
+/turf/simulated/floor/plating/ice/smooth
+ icon_state = "smooth"
+ smooth = SMOOTH_MORE | SMOOTH_BORDER
+ canSmoothWith = list(/turf/simulated/floor/plating/ice/smooth, /turf/simulated/floor/plating/ice)
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index 74d0e216614..6bae5a79d94 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -140,7 +140,23 @@
sheet_type = /obj/item/stack/sheet/wood
hardness = 70
explosion_block = 0
- canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood)
+ canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood, /turf/simulated/wall/mineral/wood/nonmetal)
+
+/turf/simulated/wall/mineral/wood/attackby(obj/item/W, mob/user)
+ if(W.sharp && W.force)
+ var/duration = (48 / W.force) * 2 //In seconds, for now.
+ if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/twohanded/fireaxe))
+ duration /= 4 //Much better with hatchets and axes.
+ if(do_after(user, duration * 10, target = src)) //Into deciseconds.
+ dismantle_wall(FALSE, FALSE)
+ return
+ return ..()
+
+/turf/simulated/wall/mineral/wood/nonmetal
+ desc = "A solidly wooden wall. It's a bit weaker than a wall made with metal."
+ girder_type = /obj/structure/barricade/wooden
+ hardness = 50
+ canSmoothWith = list(/turf/simulated/wall/mineral/wood, /obj/structure/falsewall/wood, /turf/simulated/wall/mineral/wood/nonmetal)
/turf/simulated/wall/mineral/iron
name = "rough metal wall"
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 51285932f00..0ab9ccbef15 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -516,6 +516,5 @@
/turf/AllowDrop()
return TRUE
-/turf/proc/water_act(volume, temperature, source)
- for(var/mob/living/carbon/slime/M in src)
- M.apply_water()
+/turf/proc/water_act(volume, temperature, source)
+ return FALSE
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 5a2807e8379..df2f588753f 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -41,6 +41,9 @@ var/global/admin_ooc_colour = "#b82e00"
return
if(!check_rights(R_ADMIN|R_MOD,0))
+ if(!config.ooc_allowed)
+ to_chat(src, "OOC is globally muted.")
+ return
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
return
if(findtext(msg, "byond://"))
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index a6f186dad73..d32a05eb312 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -784,11 +784,13 @@ var/global/nologevent = 0
log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
return //alert("Round end delayed", null, null, null, null, null)
- going = !( going )
- if(!( going ))
+ if(going)
+ going = FALSE
+ SSticker.delay_end = TRUE
to_chat(world, "The game start has been delayed.")
log_admin("[key_name(usr)] delayed the game.")
else
+ going = TRUE
to_chat(world, "The game will start soon.")
log_admin("[key_name(usr)] removed the delay.")
feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm
index d52507bee1d..d57c3124f61 100644
--- a/code/modules/antagonists/_common/antag_spawner.dm
+++ b/code/modules/antagonists/_common/antag_spawner.dm
@@ -210,6 +210,7 @@
var/datum/objective/KillDaCrew = new /datum/objective
KillDaCrew.owner = S.mind
KillDaCrew.explanation_text = "[objective_verb] everyone else while you're at it."
+ KillDaCrew.completed = TRUE
S.mind.objectives += KillDaCrew
to_chat(S, "Objective #[1]: [KillDaWiz.explanation_text]")
to_chat(S, "Objective #[2]: [KillDaCrew.explanation_text]")
@@ -219,7 +220,8 @@
desc = "A magically infused bottle of clown love, distilled from \
countless hugging attacks. Used in funny rituals to attract \
adorable creatures."
- color = "#FF69B4" // HOT PINK
+ icon = 'icons/obj/wizard.dmi'
+ icon_state = "vialtickles"
veil_msg = "You sense an adorable presence \
lurking just beyond the veil..."
objective_verb = "Hug and tickle"
@@ -278,6 +280,7 @@
var/datum/objective/KillDaCrew = new /datum/objective
KillDaCrew.owner = M.mind
KillDaCrew.explanation_text = "[objective_verb] everyone and everything else while you're at it."
+ KillDaCrew.completed = TRUE
M.mind.objectives += KillDaCrew
to_chat(M, "Objective #[1]: [KillDaWiz.explanation_text]")
to_chat(M, "Objective #[2]: [KillDaCrew.explanation_text]")
diff --git a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
index 60cedb281fa..9a5bf275abc 100644
--- a/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
+++ b/code/modules/awaymissions/mission_code/ghost_role_spawners/golems.dm
@@ -104,6 +104,11 @@
H.rename_character(null, H.dna.species.get_random_name())
else
H.rename_character(null, name)
+ if(is_species(H, /datum/species/golem/tranquillite) && H.mind)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null))
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null))
+ H.mind.miming = TRUE
+
if(has_owner)
new_spawn.mind.assigned_role = "Servant Golem"
else
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 300443714ab..57a6df32ab6 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -318,7 +318,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
for(var/D in cardinal)
assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipe-item.dmi', state, D)
for(var/state in icon_states('icons/obj/pipes/disposal.dmi'))
- if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet"))) //Pipes we want sprites for
+ if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet", "pipe-j1s"))) //Pipes we want sprites for
continue
for(var/D in cardinal)
assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipes/disposal.dmi', state, D)
diff --git a/code/modules/client/preference/loadout/loadout_cosmetics.dm b/code/modules/client/preference/loadout/loadout_cosmetics.dm
index aa7f5f02576..b7ac6c39493 100644
--- a/code/modules/client/preference/loadout/loadout_cosmetics.dm
+++ b/code/modules/client/preference/loadout/loadout_cosmetics.dm
@@ -21,12 +21,4 @@
/datum/gear/lipstick/lime
display_name = "lipstick, lime"
- path = /obj/item/lipstick/lime
-
-/datum/gear/monocle
- display_name = "monocle"
- path = /obj/item/clothing/glasses/monocle
-
-/datum/gear/sunglasses
- display_name = "cheap sunglasses"
- path = /obj/item/clothing/glasses/sunglasses/fake
\ No newline at end of file
+ path = /obj/item/lipstick/lime
\ No newline at end of file
diff --git a/code/modules/client/preference/loadout/loadout_donor.dm b/code/modules/client/preference/loadout/loadout_donor.dm
index 5558a988209..830b10b7055 100644
--- a/code/modules/client/preference/loadout/loadout_donor.dm
+++ b/code/modules/client/preference/loadout/loadout_donor.dm
@@ -18,12 +18,10 @@
/datum/gear/donor/furcape
display_name = "Fur Cape"
path = /obj/item/clothing/suit/furcape
- cost = 2
/datum/gear/donor/furcoat
display_name = "Fur Coat"
path = /obj/item/clothing/suit/furcoat
- cost = 2
/datum/gear/donor/kamina
display_name = "Spiky Orange-tinted Shades"
@@ -33,10 +31,6 @@
display_name = "Spiky Green-tinted Shades"
path = /obj/item/clothing/glasses/fluff/kamina/green
-/datum/gear/donor/hipster
- display_name = "Hipster Glasses"
- path = /obj/item/clothing/glasses/regular/hipster
-
/datum/gear/donor/threedglasses
display_name = "Threed Glasses"
path = /obj/item/clothing/glasses/threedglasses
diff --git a/code/modules/client/preference/loadout/loadout_glasses.dm b/code/modules/client/preference/loadout/loadout_glasses.dm
new file mode 100644
index 00000000000..94f2555bdba
--- /dev/null
+++ b/code/modules/client/preference/loadout/loadout_glasses.dm
@@ -0,0 +1,24 @@
+/datum/gear/glasses
+ subtype_path = /datum/gear/glasses
+ slot = slot_glasses
+ sort_category = "Glasses"
+
+/datum/gear/glasses/sunglasses
+ display_name = "cheap sunglasses"
+ path = /obj/item/clothing/glasses/sunglasses_fake
+
+/datum/gear/glasses/eyepatch
+ display_name = "Eyepatch"
+ path = /obj/item/clothing/glasses/eyepatch
+
+/datum/gear/glasses/hipster
+ display_name = "Hipster glasses"
+ path = /obj/item/clothing/glasses/regular/hipster
+
+/datum/gear/glasses/monocle
+ display_name = "Monocle"
+ path = /obj/item/clothing/glasses/monocle
+
+/datum/gear/glasses/prescription
+ display_name = "Prescription glasses"
+ path = /obj/item/clothing/glasses/regular
\ No newline at end of file
diff --git a/code/modules/client/preference/loadout/loadout_gloves.dm b/code/modules/client/preference/loadout/loadout_gloves.dm
new file mode 100644
index 00000000000..cd8d5a7c8e1
--- /dev/null
+++ b/code/modules/client/preference/loadout/loadout_gloves.dm
@@ -0,0 +1,8 @@
+/datum/gear/gloves
+ subtype_path = /datum/gear/gloves
+ slot = slot_gloves
+ sort_category = "Gloves"
+
+/datum/gear/gloves/fingerless
+ display_name = "Fingerless Gloves"
+ path = /obj/item/clothing/gloves/fingerless
\ No newline at end of file
diff --git a/code/modules/client/preference/loadout/loadout_shoes.dm b/code/modules/client/preference/loadout/loadout_shoes.dm
index 519cadcc044..5031f4333fb 100644
--- a/code/modules/client/preference/loadout/loadout_shoes.dm
+++ b/code/modules/client/preference/loadout/loadout_shoes.dm
@@ -27,25 +27,32 @@
/datum/gear/shoes/cowboyboots
display_name = "cowboy boots, brown"
- cost = 1
- path = /obj/item/clothing/shoes/cowboyboots
+ path = /obj/item/clothing/shoes/cowboy
/datum/gear/shoes/cowboyboots_black
display_name = "cowboy boots, black"
- cost = 1
- path = /obj/item/clothing/shoes/cowboyboots/black
+ path = /obj/item/clothing/shoes/cowboy/black
/datum/gear/shoes/cowboyboots/white
display_name = "cowboy boots, white"
- cost = 1
- path = /obj/item/clothing/shoes/cowboyboots/white
+ path = /obj/item/clothing/shoes/cowboy/white
/datum/gear/shoes/cowboyboots/pink
display_name = "cowboy boots, pink"
- cost = 1
- path = /obj/item/clothing/shoes/cowboyboots/pink
-
+ path = /obj/item/clothing/shoes/cowboy/pink
+
/datum/gear/shoes/laceup
display_name = "laceup shoes"
- cost = 1
path = /obj/item/clothing/shoes/laceup
+
+/datum/gear/shoes/blackshoes
+ display_name = "Black shoes"
+ path = /obj/item/clothing/shoes/black
+
+/datum/gear/shoes/brownshoes
+ display_name = "Brown shoes"
+ path = /obj/item/clothing/shoes/brown
+
+/datum/gear/shoes/whiteshoes
+ display_name = "White shoes"
+ path = /obj/item/clothing/shoes/white
\ No newline at end of file
diff --git a/code/modules/client/preference/loadout/loadout_suit.dm b/code/modules/client/preference/loadout/loadout_suit.dm
index 3d6b5ded994..32a9bae99e7 100644
--- a/code/modules/client/preference/loadout/loadout_suit.dm
+++ b/code/modules/client/preference/loadout/loadout_suit.dm
@@ -1,7 +1,6 @@
/datum/gear/suit
subtype_path = /datum/gear/suit
slot = slot_wear_suit
- cost = 2
sort_category = "External Wear"
//WINTER COATS
@@ -105,6 +104,10 @@
path = /obj/item/clothing/suit/armor/secjacket
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
+/datum/gear/suit/ianshirt
+ display_name = "Ian Shirt"
+ path = /obj/item/clothing/suit/ianshirt
+
/datum/gear/suit/poncho
display_name = "poncho, classic"
path = /obj/item/clothing/suit/poncho
diff --git a/code/modules/client/preference/loadout/loadout_uniform.dm b/code/modules/client/preference/loadout/loadout_uniform.dm
index f4a5c465aba..eb5264a0975 100644
--- a/code/modules/client/preference/loadout/loadout_uniform.dm
+++ b/code/modules/client/preference/loadout/loadout_uniform.dm
@@ -2,7 +2,6 @@
/datum/gear/uniform
subtype_path = /datum/gear/uniform
slot = slot_w_uniform
- cost = 2
sort_category = "Uniforms and Casual Dress"
/datum/gear/uniform/skirt
diff --git a/code/modules/client/preference/preferences_toggles.dm b/code/modules/client/preference/preferences_toggles.dm
index e164a2ab843..c1ad8d6d103 100644
--- a/code/modules/client/preference/preferences_toggles.dm
+++ b/code/modules/client/preference/preferences_toggles.dm
@@ -201,6 +201,19 @@
to_chat(src, "You will no longer hear musical instruments.")
feedback_add_details("admin_verb","TInstru") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/client/verb/Toggle_disco() //to toggle off the disco machine locally, in case it gets too annoying
+ set name = "Hear/Silence Dance Machine"
+ set category = "Preferences"
+ set desc = "Toggles hearing and dancing to the radiant dance machine"
+ prefs.sound ^= SOUND_DISCO
+ prefs.save_preferences(src)
+ if(prefs.sound & SOUND_DISCO)
+ to_chat(src, "You will now hear and dance to the radiant dance machine.")
+ else
+ to_chat(src, "You will no longer hear or dance to the radiant dance machine.")
+ usr.stop_sound_channel(CHANNEL_JUKEBOX)
+ feedback_add_details("admin_verb","Tdd") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
/client/verb/setup_character()
set name = "Game Preferences"
set category = "Preferences"
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 39235918323..96cff51ec4d 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -444,7 +444,8 @@ BLIND // can't see anything
slowdown = SHOES_SLOWDOWN
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/shoes.dmi'
+ "Vox" = 'icons/mob/species/vox/shoes.dmi',
+ "Drask" = 'icons/mob/species/drask/shoes.dmi'
)
/obj/item/clothing/shoes/attackby(obj/item/I, mob/user, params)
@@ -595,7 +596,7 @@ BLIND // can't see anything
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
heat_protection = HEAD
max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
flash_protect = 2
strip_delay = 50
put_on_delay = 50
@@ -623,7 +624,7 @@ BLIND // can't see anything
put_on_delay = 80
burn_state = FIRE_PROOF
hide_tail_by_species = null
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
//Under clothing
/obj/item/clothing/under
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index ac6c3b6dd0b..81ab79adbc4 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -265,9 +265,11 @@
"Grey" = 'icons/mob/species/grey/eyes.dmi'
)
-/obj/item/clothing/glasses/sunglasses/fake
+/obj/item/clothing/glasses/sunglasses_fake
desc = "Cheap, plastic sunglasses. They don't even have UV protection."
name = "cheap sunglasses"
+ icon_state = "sun"
+ item_state = "sunglasses"
see_in_dark = 0
flash_protect = 0
tint = 0
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index 1e639beb5de..27cd78afad3 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -38,12 +38,6 @@
"Grey" = 'icons/mob/species/grey/eyes.dmi'
)
-/obj/item/clothing/glasses/hud/health/health_advanced
- name = "\improper Advanced Health Scanner HUD"
- desc = "A heads-up display that scans the humans in view and provides accurate data about their health status. Includes anti-flash filter."
- icon_state = "advmedhud"
- flash_protect = 1
-
/obj/item/clothing/glasses/hud/health/night
name = "\improper Night Vision Health Scanner HUD"
desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness."
@@ -54,6 +48,14 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 0
+/obj/item/clothing/glasses/hud/health/sunglasses
+ name = "medical HUDSunglasses"
+ desc = "Sunglasses with a medical HUD."
+ icon_state = "sunhudmed"
+ see_in_dark = 1
+ flash_protect = 1
+ tint = 1
+
/obj/item/clothing/glasses/hud/diagnostic
name = "Diagnostic HUD"
desc = "A heads-up display capable of analyzing the integrity and status of robotics and exosuits."
@@ -77,6 +79,14 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 0
+/obj/item/clothing/glasses/hud/diagnostic/sunglasses
+ name = "diagnostic sunglasses"
+ desc = "Sunglasses with a diagnostic HUD."
+ icon_state = "sunhuddiag"
+ item_state = "glasses"
+ flash_protect = 1
+ tint = 1
+
/obj/item/clothing/glasses/hud/security
name = "\improper Security HUD"
desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records."
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index a06b01de65d..a9d5765c861 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -152,10 +152,25 @@
/obj/item/clothing/gloves/fingerless/rapid
name = "Gloves of the North Star"
desc = "Just looking at these fills you with an urge to beat the shit out of people."
+ var/accepted_intents = list(INTENT_HARM)
+ var/click_speed_modifier = CLICK_CD_RAPID
/obj/item/clothing/gloves/fingerless/rapid/Touch(mob/living/target, proximity = TRUE)
var/mob/living/M = loc
- if(M.a_intent == INTENT_HARM)
- M.changeNext_move(CLICK_CD_RAPID)
- .= FALSE
\ No newline at end of file
+ if(M.a_intent in accepted_intents)
+ M.changeNext_move(click_speed_modifier)
+ .= FALSE
+
+/obj/item/clothing/gloves/fingerless/rapid/admin
+ name = "Advanced Interactive Gloves"
+ desc = "The gloves are covered in indecipherable buttons and dials, your mind warps by merely looking at them."
+ accepted_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
+ click_speed_modifier = 0
+ siemens_coefficient = 0
+
+/obj/item/clothing/gloves/fingerless/rapid/headpat
+ name = "Gloves of Headpats"
+ desc = "You feel the irresistable urge to give headpats by merely glimpsing these."
+ accepted_intents = list(INTENT_HELP)
+ click_speed_modifier = 0 // That's some serious headpatting
\ No newline at end of file
diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm
new file mode 100644
index 00000000000..af7e805b232
--- /dev/null
+++ b/code/modules/clothing/head/beanie.dm
@@ -0,0 +1,96 @@
+
+//BeanieStation13 Redux
+
+//Plus a bobble hat, lets be inclusive!!
+
+/obj/item/clothing/head/beanie //Default is white, this is meant to be seen
+ name = "white beanie"
+ desc = "A stylish beanie. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their heads."
+ icon_state = "beanie" //Default white
+ item_color = "beanie"
+
+/obj/item/clothing/head/beanie/black
+ name = "black beanie"
+ icon_state = "beanie"
+ color = "#4A4A4B" //Grey but it looks black
+
+/obj/item/clothing/head/beanie/red
+ name = "red beanie"
+ icon_state = "beanie"
+ color = "#D91414" //Red
+
+/obj/item/clothing/head/beanie/green
+ name = "green beanie"
+ icon_state = "beanie"
+ color = "#5C9E54" //Green
+
+/obj/item/clothing/head/beanie/darkblue
+ name = "dark blue beanie"
+ icon_state = "beanie"
+ color = "#1E85BC" //Blue
+
+/obj/item/clothing/head/beanie/purple
+ name = "purple beanie"
+ icon_state = "beanie"
+ color = "#9557C5" //purple
+
+/obj/item/clothing/head/beanie/yellow
+ name = "yellow beanie"
+ icon_state = "beanie"
+ color = "#E0C14F" //Yellow
+
+/obj/item/clothing/head/beanie/orange
+ name = "orange beanie"
+ icon_state = "beanie"
+ color = "#C67A4B" //orange
+
+/obj/item/clothing/head/beanie/cyan
+ name = "cyan beanie"
+ icon_state = "beanie"
+ color = "#54A3CE" //Cyan (Or close to it)
+
+//Striped Beanies have unique sprites
+
+/obj/item/clothing/head/beanie/christmas
+ name = "christmas beanie"
+ icon_state = "beaniechristmas"
+ item_color = "beaniechristmas"
+
+/obj/item/clothing/head/beanie/striped
+ name = "striped beanie"
+ icon_state = "beaniestriped"
+ item_color = "beaniestriped"
+
+/obj/item/clothing/head/beanie/stripedred
+ name = "red striped beanie"
+ icon_state = "beaniestripedred"
+ item_color = "beaniestripedred"
+
+/obj/item/clothing/head/beanie/stripedblue
+ name = "blue striped beanie"
+ icon_state = "beaniestripedblue"
+ item_color = "beaniestripedblue"
+
+/obj/item/clothing/head/beanie/stripedgreen
+ name = "green striped beanie"
+ icon_state = "beaniestripedgreen"
+ item_color = "beaniestripedgreen"
+
+/obj/item/clothing/head/beanie/durathread
+ name = "durathread beanie"
+ desc = "A beanie made from durathread, its resilient fibres provide some protection to the wearer."
+ icon_state = "beaniedurathread"
+ item_color = null
+ armor = list(melee = 15, bullet = 5, laser = 15, energy = 5, bomb = 10, bio = 0, rad = 0)
+
+/obj/item/clothing/head/beanie/waldo
+ name = "red striped bobble hat"
+ desc = "If you're going on a worldwide hike, you'll need some cold protection."
+ icon_state = "waldo_hat"
+ item_color = "waldo_hat"
+
+/obj/item/clothing/head/beanie/rasta
+ name = "rastacap"
+ desc = "Perfect for tucking in those dreadlocks."
+ icon_state = "beanierasta"
+ item_color = "beanierasta"
\ No newline at end of file
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 4c915e5fc9c..13826e53ea1 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -227,6 +227,24 @@ obj/item/clothing/head/blob
item_state = "knight_templar"
armor = list(melee = 20, bullet = 7, laser = 2, energy = 2, bomb = 2, bio = 2, rad = 0)
+/obj/item/clothing/head/helmet/skull
+ name = "skull helmet"
+ desc = "An intimidating tribal helmet, it doesn't look very comfortable."
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
+ flags_cover = HEADCOVERSEYES
+ armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 10, bio = 5, rad = 20)
+ icon_state = "skull"
+ item_state = "skull"
+ strip_delay = 100
+
+/obj/item/clothing/head/helmet/durathread
+ name = "durathread helmet"
+ desc = "A helmet made from durathread and leather."
+ icon_state = "durathread"
+ item_state = "durathread"
+ armor = list(melee = 25, bullet = 10, laser = 20, energy = 10, bomb = 30, bio = 15, rad = 20)
+ strip_delay = 60
+
//Commander
/obj/item/clothing/head/helmet/ert/command
name = "emergency response team commander helmet"
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index adcc828d8d5..9c96cbae961 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -39,7 +39,7 @@
//Chaplain
-/obj/item/clothing/head/chaplain_hood
+/obj/item/clothing/head/hooded/chaplain_hood
name = "chaplain's hood"
desc = "It's hood that covers the head. It keeps you warm during the space winters."
icon_state = "chaplain_hood"
@@ -47,7 +47,7 @@
flags_cover = HEADCOVERSEYES
//Chaplain
-/obj/item/clothing/head/nun_hood
+/obj/item/clothing/head/hooded/nun_hood
name = "nun hood"
desc = "Maximum piety in this star system."
icon_state = "nun_hood"
@@ -55,7 +55,7 @@
flags_cover = HEADCOVERSEYES
//Chaplain
-/obj/item/clothing/head/monk_hood
+/obj/item/clothing/head/hooded/monk_hood
name = "monk hood"
desc = "Wooden board not included."
icon_state = "monk_hood"
@@ -82,6 +82,13 @@
desc = "A beret, an artists favorite headwear."
icon_state = "beret"
+/obj/item/clothing/head/beret/durathread
+ name = "durathread beret"
+ desc = "A beret made from durathread, its resilient fibres provide some protection to the wearer."
+ icon_state = "beretdurathread"
+ item_color = null
+ armor = list(melee = 15, bullet = 5, laser = 15, energy = 5, bomb = 10, bio = 0, rad = 0)
+
//Security
/obj/item/clothing/head/HoS
name = "head of security cap"
diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm
index db7295809b1..8956a456166 100644
--- a/code/modules/clothing/masks/gasmask.dm
+++ b/code/modules/clothing/masks/gasmask.dm
@@ -140,11 +140,7 @@
flags_inv = HIDEEARS | HIDEEYES
magical = TRUE
-/obj/item/clothing/mask/gas/virusclown_hat
- name = "clown wig and mask"
- desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
- icon_state = "clown"
- item_state = "clown_hat"
+/obj/item/clothing/mask/gas/clown_hat/nodrop
flags = NODROP
/obj/item/clothing/mask/gas/mime
@@ -154,6 +150,9 @@
item_state = "mime"
burn_state = FLAMMABLE
+/obj/item/clothing/mask/gas/mime/nodrop
+ flags = NODROP
+
/obj/item/clothing/mask/gas/monkeymask
name = "monkey mask"
desc = "A mask used when acting as a monkey."
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 3151ddca083..a60e4b2c2a6 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -483,6 +483,11 @@
item_color = "black"
desc = "It's a black bandana."
+/obj/item/clothing/mask/bandana/durathread
+ name = "durathread bandana"
+ desc = "A bandana made from durathread, you wish it would provide some protection to its wearer, but it's far too thin..."
+ icon_state = "banddurathread"
+
/obj/item/clothing/mask/cursedclown
name = "cursed clown mask"
desc = "This is a very, very odd looking mask."
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index bca650a30b1..bc7d0d6c701 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -88,6 +88,9 @@
to_chat(user, "You switch on the waddle dampeners!")
enabled_waddle = FALSE
+/obj/item/clothing/shoes/clown_shoes/nodrop
+ flags = NODROP
+
/obj/item/clothing/shoes/clown_shoes/magical
name = "magical clown shoes"
desc = "Standard-issue shoes of the wizarding class clown. Damn they're huge! And powerful! Somehow."
@@ -243,30 +246,55 @@
icon_state = "bsing"
put_on_delay = 50
-/obj/item/clothing/shoes/cowboyboots
+/obj/item/clothing/shoes/cowboy
name = "cowboy boots"
desc = "A pair a' brown boots."
- icon_state = "cowboyboots"
- item_color = "cowboyboots"
+ icon_state = "cowboy_brown"
+ item_color = "cowboy_brown"
-/obj/item/clothing/shoes/cowboyboots/black
+/obj/item/clothing/shoes/cowboy/black
name = "black cowboy boots"
desc = "A pair a' black rustlers' boots"
- icon_state = "cowboyboots_black"
- item_color = "cowboyboots_black"
+ icon_state = "cowboy_black"
+ item_color = "cowboy_black"
-/obj/item/clothing/shoes/cowboyboots/white
+/obj/item/clothing/shoes/cowboy/white
name = "white cowboy boots"
desc = "For the rancher in us all."
- icon_state = "cowboyboots_white"
- item_color = "cowboyboots_white"
+ icon_state = "cowboy_white"
+ item_color = "cowboy_white"
-/obj/item/clothing/shoes/cowboyboots/pink
+/obj/item/clothing/shoes/cowboy/fancy
+ name = "bilton wrangler boots"
+ desc = "A pair of authentic haute couture boots from Japanifornia. You doubt they have ever been close to cattle."
+ icon_state = "cowboy_fancy"
+ item_color = "cowboy_fancy"
+
+/obj/item/clothing/shoes/cowboy/pink
name = "pink cowgirl boots"
desc = "For a Rustlin' tustlin' cowgirl."
icon_state = "cowboyboots_pink"
item_color = "cowboyboots_pink"
+/obj/item/clothing/shoes/cowboy/lizard
+ name = "lizard skin boots"
+ desc = "You can hear a faint hissing from inside the boots; you hope it is just a mournful ghost."
+ icon_state = "lizardboots_green"
+
+/obj/item/clothing/shoes/cowboy/lizardmasterwork
+ name = "\improper Hugs-The-Feet lizard skin boots"
+ desc = "A pair of masterfully crafted lizard skin boots. Finally a good application for the station's most bothersome inhabitants."
+ icon_state = "lizardboots_blue"
+
+/obj/effect/spawner/lootdrop/lizardboots
+ name = "random lizard boot quality"
+ desc = "Which ever gets picked, the lizard race loses"
+ icon = 'icons/obj/clothing/shoes.dmi'
+ icon_state = "lizardboots_green"
+ loot = list(
+ /obj/item/clothing/shoes/cowboy/lizard = 7,
+ /obj/item/clothing/shoes/cowboy/lizardmasterwork = 1)
+
/obj/item/clothing/shoes/footwraps
name = "cloth footwraps"
desc = "A roll of treated canvas used for wrapping claws or paws."
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm
index e97f220bd8e..60523d6c0e8 100644
--- a/code/modules/clothing/spacesuits/ert.dm
+++ b/code/modules/clothing/spacesuits/ert.dm
@@ -190,7 +190,7 @@
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
sprite_sheets = null
actions_types = list()
- has_camera = 0
+ has_camera = FALSE
/obj/item/clothing/suit/space/hardsuit/ert/paranormal
name = "paranormal response team suit"
@@ -208,20 +208,26 @@
name = "inquisitor's helmet"
icon_state = "hardsuit0-inquisitor"
item_color = "inquisitor"
+ armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor
name = "inquisitor's hardsuit"
icon_state = "hardsuit-inquisitor"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor
+ armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100)
+ slowdown = 0
/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
name = "champion's helmet"
desc = "Peering into the eyes of the helmet is enough to seal damnation."
icon_state = "hardsuit0-berserker"
item_color = "berserker"
+ armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100)
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker
name = "champion's hardsuit"
desc = "Voices echo from the hardsuit, driving the user insane."
icon_state = "hardsuit-berserker"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/berserker
+ armor = list(melee = 65, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 100, rad = 100)
+ slowdown = 0
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 4c74aba8c93..466fb2fc2fd 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -14,7 +14,7 @@
actions_types = list(/datum/action/item_action/toggle_helmet_light)
//Species-specific stuff.
- species_restricted = list("exclude","Diona","Wryn")
+ species_restricted = list("exclude","Wryn")
sprite_sheets = list(
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
@@ -93,9 +93,10 @@
var/obj/item/clothing/head/helmet/space/hardsuit/helmet
actions_types = list(/datum/action/item_action/toggle_helmet)
var/helmettype = /obj/item/clothing/head/helmet/space/hardsuit
+ var/obj/item/tank/jetpack/suit/jetpack = null
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
- species_restricted = list("exclude","Diona","Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
@@ -112,10 +113,59 @@
"Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi'
)
+/obj/item/clothing/suit/space/hardsuit/New()
+ if(jetpack && ispath(jetpack))
+ jetpack = new jetpack(src)
+ ..()
+
/obj/item/clothing/suit/space/hardsuit/attack_self(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
..()
+/obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/tank/jetpack/suit))
+ if(jetpack)
+ to_chat(user, "[src] already has a jetpack installed.")
+ return
+ if(src == user.get_item_by_slot(slot_wear_suit)) //Make sure the player is not wearing the suit before applying the upgrade.
+ to_chat(user, "You cannot install the upgrade to [src] while wearing it.")
+ return
+
+ if(user.unEquip(I))
+ I.forceMove(src)
+ jetpack = I
+ to_chat(user, "You successfully install the jetpack into [src].")
+ return
+ else if(isscrewdriver(I))
+ if(!jetpack)
+ to_chat(user, "[src] has no jetpack installed.")
+ return
+ if(src == user.get_item_by_slot(slot_wear_suit))
+ to_chat(user, "You cannot remove the jetpack from [src] while wearing it.")
+ return
+
+ jetpack.turn_off(user)
+ jetpack.forceMove(drop_location())
+ jetpack = null
+ to_chat(user, "You successfully remove the jetpack from [src].")
+ return
+ return ..()
+
+/obj/item/clothing/suit/space/hardsuit/equipped(mob/user, slot)
+ ..()
+ if(jetpack)
+ if(slot == slot_wear_suit)
+ for(var/X in jetpack.actions)
+ var/datum/action/A = X
+ A.Grant(user)
+
+/obj/item/clothing/suit/space/hardsuit/dropped(mob/user)
+ ..()
+ if(jetpack)
+ for(var/X in jetpack.actions)
+ var/datum/action/A = X
+ A.Remove(user)
+
/obj/item/clothing/suit/space/hardsuit/item_action_slot_check(slot)
if(slot == slot_wear_suit) //we only give the mob the ability to toggle the helmet if he's wearing the hardsuit.
return 1
@@ -178,6 +228,7 @@
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite
+ jetpack = /obj/item/tank/jetpack/suit
//Mining hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/mining
@@ -291,6 +342,7 @@
armor = list(melee = 40, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi
+ jetpack = /obj/item/tank/jetpack/suit
/obj/item/clothing/suit/space/hardsuit/syndi/update_icon()
icon_state = "hardsuit[on]-[item_color]"
@@ -438,6 +490,7 @@
icon_state = "hardsuit-hos"
armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos
+ jetpack = /obj/item/tank/jetpack/suit
sprite_sheets = null
//Singuloth armor
@@ -522,6 +575,7 @@
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword/saber,/obj/item/restraints/handcuffs,/obj/item/tank)
slowdown = 0
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi
+ jetpack = /obj/item/tank/jetpack/suit
sprite_sheets = list(
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 9706b254fa8..1e5c9ad6dcb 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -7,7 +7,7 @@
flags_inv = HIDEFACE
permeability_coefficient = 0.01
armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/helmet.dmi',
@@ -31,7 +31,7 @@
w_class = WEIGHT_CLASS_BULKY
allowed = list(/obj/item/tank, /obj/item/flashlight,/obj/item/gun/energy, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton,/obj/item/restraints/handcuffs)
armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi'
@@ -72,7 +72,7 @@
allowed = list(/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/kitchen/knife/combat)
armor = list(melee = 40, bullet = 30, laser = 30, energy = 30, bomb = 50, bio = 90, rad = 20)
strip_delay = 120
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi'
@@ -159,7 +159,7 @@
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/helmet.dmi',
@@ -180,7 +180,7 @@
item_state = "paramedic-eva"
desc = "A brand new paramedic EVA suit. The nitrile seems a bit too thin to be space proof. Used for retrieving bodies in space."
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
@@ -200,7 +200,7 @@
item_state = "s_suit"
desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies."
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
@@ -223,7 +223,7 @@
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
flash_protect = 0
- species_restricted = list("exclude", "Diona", "Wryn")
+ species_restricted = list("exclude", "Wryn")
sprite_sheets = list(
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
@@ -244,7 +244,7 @@
desc = ". . ."
icon_state = "spacemimehelmet"
item_state = "spacemimehelmet"
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
sprite_sheets = null
sprite_sheets_obj = null
@@ -254,7 +254,7 @@
desc = ". . ."
icon_state = "spacemime_suit"
item_state = "spacemime_items"
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
sprite_sheets = null
sprite_sheets_obj = null
@@ -264,7 +264,7 @@
desc = "An EVA helmet specifically designed for the clown. SPESSHONK!"
icon_state = "clownhelmet"
item_state = "clownhelmet"
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
sprite_sheets = null
sprite_sheets_obj = null
@@ -274,7 +274,6 @@
desc = "An EVA suit specifically designed for the clown. SPESSHONK!"
icon_state = "spaceclown_suit"
item_state = "spaceclown_items"
- species_restricted = list("exclude","Diona","Vox","Wryn")
+ species_restricted = list("exclude","Vox","Wryn")
sprite_sheets = null
sprite_sheets_obj = null
-
\ No newline at end of file
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index ae8502f7246..e27b3b8ef1f 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -209,6 +209,15 @@
allowed = list(/obj/item/nullrod/claymore)
armor = list(melee = 25, bullet = 5, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 0)
+/obj/item/clothing/suit/armor/vest/durathread
+ name = "durathread vest"
+ desc = "A vest made of durathread with strips of leather acting as trauma plates."
+ icon_state = "durathread"
+ item_state = "durathread"
+ strip_delay = 60
+ burn_state = FLAMMABLE
+ armor = list(melee = 20, bullet = 10, laser = 30, energy = 5, bomb = 15, bio = 0, rad = 0)
+
/obj/item/clothing/suit/armor/bulletproof
name = "Bulletproof Vest"
desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent."
@@ -528,14 +537,4 @@
item_state = "bonearmor"
blood_overlay_type = "armor"
armor = list(melee = 35, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS
-
-/obj/item/clothing/head/helmet/skull
- name = "skull helmet"
- desc = "An intimidating tribal helmet, it doesn't look very comfortable."
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
- flags_cover = HEADCOVERSEYES
- armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 10, bio = 5, rad = 20)
- icon_state = "skull"
- item_state = "skull"
- strip_delay = 100
\ No newline at end of file
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS
\ No newline at end of file
diff --git a/code/modules/clothing/suits/hood.dm b/code/modules/clothing/suits/hood.dm
index 5b2266bb53b..83f0fcfc211 100644
--- a/code/modules/clothing/suits/hood.dm
+++ b/code/modules/clothing/suits/hood.dm
@@ -2,44 +2,21 @@
/obj/item/clothing/suit/hooded
actions_types = list(/datum/action/item_action/toggle)
- var/obj/item/clothing/head/hood
- var/hoodtype = /obj/item/clothing/head/winterhood //so the chaplain hoodie or other hoodies can override this
+ var/obj/item/clothing/head/hooded/hood
+ var/hoodtype = /obj/item/clothing/head/hooded/winterhood //so the chaplain hoodie or other hoodies can override this
-/obj/item/clothing/head/chaplain_hood
- flags = NODROP
-
-/obj/item/clothing/head/nun_hood
- flags = NODROP
-
-/obj/item/clothing/head/monk_hood
- flags = NODROP
-
-/obj/item/clothing/head/culthood
- flags = NODROP
-
-/obj/item/clothing/head/culthood/alt
- flags = NODROP
-
-/obj/item/clothing/head/berserkerhood
- flags = NODROP
-
-/obj/item/clothing/head/hooded/drake
- flags = NODROP
-
-/obj/item/clothing/head/hooded/goliath
- flags = NODROP
-
-/obj/item/clothing/suit/hooded/New()
+/obj/item/clothing/suit/hooded/Initialize(mapload)
+ . = ..()
MakeHood()
- ..()
/obj/item/clothing/suit/hooded/Destroy()
QDEL_NULL(hood)
- return ..()
+ . = ..()
/obj/item/clothing/suit/hooded/proc/MakeHood()
if(!hood)
- var/obj/item/clothing/head/W = new hoodtype(src)
+ var/obj/item/clothing/head/hooded/W = new hoodtype(src)
+ W.suit = src
hood = W
/obj/item/clothing/suit/hooded/ui_action_click()
@@ -63,7 +40,7 @@
var/mob/living/carbon/H = hood.loc
H.unEquip(hood, 1)
H.update_inv_wear_suit()
- hood.loc = src
+ hood.forceMove(src)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
@@ -82,7 +59,7 @@
if(H.head)
to_chat(H,"You're already wearing something on your head!")
return
- else if(H.equip_to_slot_if_possible(hood,slot_head,0,0,1))
+ else if(H.equip_to_slot_if_possible(hood, slot_head, 0, 0, 1))
suit_adjusted = 1
icon_state = "[initial(icon_state)]_hood"
H.update_inv_wear_suit()
@@ -91,3 +68,23 @@
A.UpdateButtonIcon()
else
RemoveHood()
+
+/obj/item/clothing/head/hooded
+ var/obj/item/clothing/suit/hooded/suit
+
+/obj/item/clothing/head/hooded/Destroy()
+ suit = null
+ return ..()
+
+/obj/item/clothing/head/hooded/dropped()
+ ..()
+ if(suit)
+ suit.RemoveHood()
+
+/obj/item/clothing/head/hooded/equipped(mob/user, slot)
+ ..()
+ if(slot != slot_head)
+ if(suit)
+ suit.RemoveHood()
+ else
+ qdel(src)
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index 06a3f35fa29..87b30fe01dc 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -30,7 +30,7 @@
"Vox" = 'icons/mob/species/vox/suit.dmi'
)
-//Botonist
+//Botanist
/obj/item/clothing/suit/apron
name = "apron"
desc = "A basic blue apron."
@@ -85,7 +85,7 @@
icon_state = "chaplain_hoodie"
item_state = "chaplain_hoodie"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- hoodtype = /obj/item/clothing/head/chaplain_hood
+ hoodtype = /obj/item/clothing/head/hooded/chaplain_hood
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
sprite_sheets = list(
@@ -100,7 +100,7 @@
item_state = "nun"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
flags_inv = HIDESHOES|HIDEJUMPSUIT
- hoodtype = /obj/item/clothing/head/nun_hood
+ hoodtype = /obj/item/clothing/head/hooded/nun_hood
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
sprite_sheets = list(
@@ -115,7 +115,7 @@
item_state = "monkrobe"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
flags_inv = HIDESHOES|HIDEJUMPSUIT
- hoodtype = /obj/item/clothing/head/monk_hood
+ hoodtype = /obj/item/clothing/head/hooded/monk_hood
allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
/obj/item/clothing/suit/witchhunter
@@ -364,6 +364,9 @@
"Vox" = 'icons/mob/species/vox/suit.dmi'
)
+/obj/item/clothing/suit/suspenders/nodrop
+ flags = NODROP
+
// Surgeon
/obj/item/clothing/suit/apron/surgical
name = "surgical apron"
@@ -371,7 +374,7 @@
icon_state = "surgical"
item_state = "surgical"
allowed = list(/obj/item/scalpel, /obj/item/surgical_drapes, /obj/item/cautery, /obj/item/hemostat, /obj/item/retractor)
-
+
//Research Director
/obj/item/clothing/suit/mantle/labcoat
name = "research director's mantle"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 25fa28931d3..56204c5d3c2 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -1,1006 +1,1017 @@
-/*
- * Contains:
- * Lasertag
- * Costume
- * Winter Coats
- * Misc
- */
-
-/*
- * Lasertag
- */
-/obj/item/clothing/suit/bluetag
- name = "blue laser tag armour"
- desc = "Blue Pride, Station Wide."
- icon_state = "bluetag"
- item_state = "bluetag"
- blood_overlay_type = "armor"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO
- allowed = list (/obj/item/gun/energy/laser/tag/blue)
- burn_state = FIRE_PROOF
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/redtag
- name = "red laser tag armour"
- desc = "Pew pew pew."
- icon_state = "redtag"
- item_state = "redtag"
- blood_overlay_type = "armor"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO
- allowed = list (/obj/item/gun/energy/laser/tag/red)
- burn_state = FIRE_PROOF
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/*
- * Costume
- */
-/obj/item/clothing/suit/pirate_brown
- name = "brown pirate coat"
- desc = "Yarr."
- icon_state = "pirate_old"
- item_state = "pirate_old"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/pirate_black
- name = "black pirate coat"
- desc = "Yarr."
- icon_state = "pirate"
- item_state = "pirate"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/hgpirate
- name = "pirate captain coat"
- desc = "Yarr."
- icon_state = "hgpirate"
- item_state = "hgpirate"
- flags_inv = HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/cyborg_suit
- name = "cyborg suit"
- desc = "Suit for a cyborg costume."
- icon_state = "death"
- item_state = "death"
- flags = CONDUCT
- fire_resist = T0C+5200
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/greatcoat
- name = "great coat"
- desc = "A Nazi great coat."
- icon_state = "nazi"
- item_state = "nazi"
-
-
-/obj/item/clothing/suit/johnny_coat
- name = "johnny~~ coat"
- desc = "Johnny~~"
- icon_state = "johnny"
- item_state = "johnny"
-
-
-/obj/item/clothing/suit/justice
- name = "justice suit"
- desc = "this pretty much looks ridiculous"
- icon_state = "justice"
- item_state = "justice"
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/judgerobe
- name = "judge's robe"
- desc = "This robe commands authority."
- icon_state = "judge"
- item_state = "judge"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- allowed = list(/obj/item/storage/fancy/cigarettes,/obj/item/stack/spacecash)
- flags_inv = HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/wcoat
- name = "waistcoat"
- desc = "For some classy, murderous fun."
- icon_state = "vest"
- item_state = "wcoat"
- blood_overlay_type = "armor"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/apron/overalls
- name = "coveralls"
- desc = "A set of denim overalls."
- icon_state = "overalls"
- item_state = "overalls"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS
-
-
-/obj/item/clothing/suit/syndicatefake
- name = "black and red space suit replica"
- icon_state = "syndicate-black-red"
- item_state = "syndicate-black-red"
- desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!"
- w_class = WEIGHT_CLASS_NORMAL
- allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy)
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
- burn_state = FIRE_PROOF
-
-
-/obj/item/clothing/suit/hastur
- name = "Hastur's robes"
- desc = "Robes not meant to be worn by man."
- icon_state = "hastur"
- item_state = "hastur"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/imperium_monk
- name = "imperium monk"
- desc = "Have YOU killed a xeno today?"
- icon_state = "imperium_monk"
- item_state = "imperium_monk"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- flags_inv = HIDESHOES|HIDEJUMPSUIT
- allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
-
-/obj/item/clothing/suit/chickensuit
- name = "chicken suit"
- desc = "A suit made long ago by the ancient empire KFC."
- icon_state = "chickensuit"
- item_state = "chickensuit"
- body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET
- flags_inv = HIDESHOES|HIDEJUMPSUIT
-
-/obj/item/clothing/suit/corgisuit
- name = "corgi suit"
- desc = "A suit made long ago by the ancient empire KFC."
- icon_state = "corgisuit"
- item_state = "chickensuit"
- body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET
- flags_inv = HIDESHOES|HIDEJUMPSUIT
-
-/obj/item/clothing/suit/corgisuit/super_hero
- name = "super-hero corgi suit"
- desc = "A suit made long ago by the ancient empire KFC. This one pulses with a strange power."
- flags = NODROP
-
-/obj/item/clothing/suit/corgisuit/super_hero/en
- name = "\improper super-hero E-N suit"
- icon_state = "ensuit"
-
-/obj/item/clothing/suit/corgisuit/super_hero/en/New()
- ..()
- START_PROCESSING(SSobj, src)
-
-/obj/item/clothing/suit/corgisuit/super_hero/en/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/item/clothing/suit/corgisuit/super_hero/en/process()
- if(prob(2))
- for(var/obj/M in orange(2,src))
- if(!M.anchored && (M.flags & CONDUCT))
- step_towards(M,src)
- for(var/mob/living/silicon/S in orange(2,src))
- if(istype(S, /mob/living/silicon/ai)) continue
- step_towards(S,src)
- for(var/mob/living/carbon/human/machine/M in orange(2,src))
- step_towards(M,src)
-
-/obj/item/clothing/suit/monkeysuit
- name = "monkey suit"
- desc = "A suit that looks like a primate"
- icon_state = "monkeysuit"
- item_state = "monkeysuit"
- body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET|HANDS
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
-
-
-/obj/item/clothing/suit/holidaypriest
- name = "holiday priest"
- desc = "This is a nice holiday my son."
- icon_state = "holidaypriest"
- item_state = "holidaypriest"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- flags_inv = HIDEJUMPSUIT
- allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
-
-/obj/item/clothing/suit/cardborg
- name = "cardborg suit"
- desc = "An ordinary cardboard box with holes cut in the sides."
- icon_state = "cardborg"
- item_state = "cardborg"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO
- flags_inv = HIDEJUMPSUIT
- species_disguise = "High-tech robot"
-
-/obj/item/clothing/suit/cardborg/equipped(mob/living/user, slot)
- ..()
- if(slot == slot_wear_suit)
- disguise(user)
-
-/obj/item/clothing/suit/cardborg/dropped(mob/living/user)
- ..()
- user.remove_alt_appearance("standard_borg_disguise")
-
-/obj/item/clothing/suit/cardborg/proc/disguise(mob/living/carbon/human/H, obj/item/clothing/head/cardborg/borghead)
- if(istype(H))
- if(!borghead)
- borghead = H.head
- if(istype(borghead, /obj/item/clothing/head/cardborg)) //why is this done this way? because equipped() is called BEFORE THE ITEM IS IN THE SLOT WHYYYY
- var/image/I = image(icon = 'icons/mob/robots.dmi' , icon_state = "robot", loc = H)
- I.override = 1
- I.overlays += image(icon = 'icons/mob/robots.dmi' , icon_state = "eyes-robot") //gotta look realistic
- H.add_alt_appearance("standard_borg_disguise", I, GLOB.silicon_mob_list+H) //you look like a robot to robots! (including yourself because you're totally a robot)
-
-/obj/item/clothing/suit/snowman
- name = "snowman outfit"
- desc = "Two white spheres covered in white glitter. 'Tis the season."
- icon_state = "snowman"
- item_state = "snowman"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO
- flags_inv = HIDEJUMPSUIT
-
-/obj/item/clothing/suit/poncho
- name = "poncho"
- desc = "Your classic, non-racist poncho."
- icon_state = "classicponcho"
- item_state = "classicponcho"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/poncho/green
- name = "green poncho"
- desc = "Your classic, non-racist poncho. This one is green."
- icon_state = "greenponcho"
- item_state = "greenponcho"
-
-/obj/item/clothing/suit/poncho/red
- name = "red poncho"
- desc = "Your classic, non-racist poncho. This one is red."
- icon_state = "redponcho"
- item_state = "redponcho"
-
-/obj/item/clothing/suit/poncho/ponchoshame
- name = "poncho of shame"
- desc = "Forced to live on your shameful acting as a fake Mexican, you and your poncho have grown inseperable. Literally."
- icon_state = "ponchoshame"
- item_state = "ponchoshame"
- flags = NODROP
-
-/obj/item/clothing/suit/hooded/carp_costume
- name = "carp costume"
- desc = "A costume made from 'synthetic' carp scales, it smells."
- icon_state = "carp_casual"
- item_state = "labcoat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too
- allowed = list(/obj/item/tank/emergency_oxygen)
- hoodtype = /obj/item/clothing/head/hooded/carp_hood
-
-/obj/item/clothing/head/hooded/carp_hood
- name = "carp hood"
- desc = "A hood attached to a carp costume."
- icon_state = "carp_casual"
- body_parts_covered = HEAD
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- flags = NODROP|BLOCKHAIR
- flags_inv = HIDEEARS
-
-/obj/item/clothing/suit/hooded/bee_costume // It's Hip!
- name = "bee costume"
- desc = "Bee the true Queen!"
- icon_state = "bee"
- item_state = "labcoat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- flags = THICKMATERIAL
- hoodtype = /obj/item/clothing/head/hooded/bee_hood
-
-/obj/item/clothing/head/hooded/bee_hood
- name = "bee hood"
- desc = "A hood attached to a bee costume."
- icon_state = "bee"
- body_parts_covered = HEAD
- flags = THICKMATERIAL|NODROP|BLOCKHAIR
- flags_inv = HIDEEARS
-
-/obj/item/clothing/suit/bloated_human //OH MY GOD WHAT HAVE YOU DONE!?!?!?
- name = "bloated human suit"
- desc = "A horribly bloated suit made from human skins."
- icon_state = "lingspacesuit"
- item_state = "lingspacesuit"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
-
-/obj/item/clothing/suit/draculacoat // Bleh!
- name = "transylvanian coat"
- desc = "What is a spessman? A miserable little pile of secrets."
- icon_state = "draculacoat"
- item_state = "draculacoat"
-
-/*
- * Winter Coats
- */
-
-/obj/item/clothing/suit/hooded/wintercoat
- name = "winter coat"
- desc = "A heavy jacket made from 'synthetic' animal furs."
- icon_state = "wintercoat"
- item_state = "coatwinter"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0)
- allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
-
- sprite_sheets = list("Vox" = 'icons/mob/species/vox/suit.dmi')
-
-/obj/item/clothing/head/winterhood
- name = "winter hood"
- desc = "A hood attached to a heavy winter jacket."
- icon_state = "winterhood"
- body_parts_covered = HEAD
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
- flags = NODROP|BLOCKHAIR
- flags_inv = HIDEEARS
-
- sprite_sheets = list("Vox" = 'icons/mob/species/vox/head.dmi')
-
-/obj/item/clothing/suit/hooded/wintercoat/captain
- name = "captain's winter coat"
- icon_state = "wintercoat_captain"
- item_state = "coatcaptain"
- armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
- allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
- hoodtype = /obj/item/clothing/head/winterhood/captain
-
-/obj/item/clothing/head/winterhood/captain
- icon_state = "winterhood_captain"
-
-/obj/item/clothing/suit/hooded/wintercoat/security
- name = "security winter coat"
- icon_state = "wintercoat_sec"
- item_state = "coatsecurity"
- armor = list(melee = 10, bullet = 10, laser = 10, energy = 5, bomb = 15, bio = 0, rad = 0)
- allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
- hoodtype = /obj/item/clothing/head/winterhood/security
-
-/obj/item/clothing/head/winterhood/security
- icon_state = "winterhood_sec"
-
-/obj/item/clothing/suit/hooded/wintercoat/medical
- name = "medical winter coat"
- icon_state = "wintercoat_med"
- item_state = "coatmedical"
- allowed = list(/obj/item/analyzer, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
- hoodtype = /obj/item/clothing/head/winterhood/medical
-
-/obj/item/clothing/head/winterhood/medical
- icon_state = "winterhood_med"
-
-/obj/item/clothing/suit/hooded/wintercoat/science
- name = "science winter coat"
- icon_state = "wintercoat_sci"
- item_state = "coatscience"
- allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0)
- hoodtype = /obj/item/clothing/head/winterhood/science
-
-/obj/item/clothing/head/winterhood/science
- icon_state = "winterhood_sci"
-
-/obj/item/clothing/suit/hooded/wintercoat/engineering
- name = "engineering winter coat"
- icon_state = "wintercoat_engi"
- item_state = "coatengineer"
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 20)
- allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/t_scanner, /obj/item/rcd)
- hoodtype = /obj/item/clothing/head/winterhood/engineering
-
-/obj/item/clothing/head/winterhood/engineering
- icon_state = "winterhood_engi"
-
-/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
- name = "atmospherics winter coat"
- icon_state = "wintercoat_atmos"
- item_state = "coatatmos"
- hoodtype = /obj/item/clothing/head/winterhood/engineering/atmos
-
-/obj/item/clothing/head/winterhood/engineering/atmos
- icon_state = "winterhood_atmos"
-
-/obj/item/clothing/suit/hooded/wintercoat/hydro
- name = "hydroponics winter coat"
- icon_state = "wintercoat_hydro"
- item_state = "coathydro"
- allowed = list(/obj/item/reagent_containers/spray, /obj/item/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/hatchet, /obj/item/storage/bag/plants)
- hoodtype = /obj/item/clothing/head/winterhood/hydro
-
-/obj/item/clothing/head/winterhood/hydro
- icon_state = "winterhood_hydro"
-
-/obj/item/clothing/suit/hooded/wintercoat/cargo
- name = "cargo winter coat"
- icon_state = "wintercoat_cargo"
- item_state = "coatcargo"
- hoodtype = /obj/item/clothing/head/winterhood/cargo
-
-/obj/item/clothing/head/winterhood/cargo
- icon_state = "winterhood_cargo"
-
-/obj/item/clothing/suit/hooded/wintercoat/miner
- name = "mining winter coat"
- icon_state = "wintercoat_miner"
- item_state = "coatminer"
- allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
- armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
- hoodtype = /obj/item/clothing/head/winterhood/miner
-
-/obj/item/clothing/head/winterhood/miner
- icon_state = "winterhood_miner"
-
-
-/*
- * Misc
- */
-
-//hoodies
-/obj/item/clothing/suit/hooded/hoodie
- name = "black hoodie"
- desc = "It's a hoodie. It has a hood. Most hoodies do."
- icon_state = "black_hoodie"
- item_state = "blueshieldcoat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen)
- hoodtype = /obj/item/clothing/head/hood
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/head/hood
- name = "black hood"
- desc = "A hood attached to a hoodie."
- icon_state = "blackhood"
- body_parts_covered = HEAD
- cold_protection = HEAD
- flags = NODROP|BLOCKHAIR
- flags_inv = HIDEEARS
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/head.dmi'
- )
-
-/obj/item/clothing/head/hood/blue
- icon_state = "bluehood"
-
-/obj/item/clothing/head/hood/white
- icon_state = "whitehood"
-
-/obj/item/clothing/suit/hooded/hoodie/blue
- name = "blue hoodie"
- icon_state = "blue_hoodie"
- hoodtype = /obj/item/clothing/head/hood/blue
-
-/obj/item/clothing/suit/hooded/hoodie/mit
- name = "Martian Institute of Technology hoodie"
- desc = "A hoodie proudly worn by students and graduates alike, has the letters 'MIT' on the back."
- icon_state = "mit_hoodie"
- hoodtype = /obj/item/clothing/head/hood
-
-/obj/item/clothing/suit/hooded/hoodie/cut
- name = "Canaan University of Technology hoodie"
- desc = "A bright hoodie with the Canaan University of Technology logo on the front."
- icon_state = "cut_hoodie"
- hoodtype = /obj/item/clothing/head/hood/white
-
-/obj/item/clothing/suit/hooded/hoodie/lam
- name = "Lunar Academy of Medicine hoodie"
- desc = "A bright hoodie with the Lunar Academy of Medicine logo on the back."
- icon_state = "lam_hoodie"
- hoodtype = /obj/item/clothing/head/hood/white
-
-/obj/item/clothing/suit/hooded/hoodie/nt
- name = "Nanotrasen hoodie"
- desc = "A blue hoodie with the Nanotrasen logo on the back."
- icon_state = "nt_hoodie"
- hoodtype = /obj/item/clothing/head/hood/blue
-
-/obj/item/clothing/suit/hooded/hoodie/tp
- name = "Tharsis Polytech hoodie"
- desc = "A dark hoodie with the Tharsis Polytech logo on the back."
- icon_state = "tp_hoodie"
- hoodtype = /obj/item/clothing/head/hood
-
-/obj/item/clothing/suit/straight_jacket
- name = "straight jacket"
- desc = "A suit that completely restrains the wearer."
- icon_state = "straight_jacket"
- item_state = "straight_jacket"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
- flags_size = ONESIZEFITSALL
- strip_delay = 60
- breakouttime = 3000
-
-/obj/item/clothing/suit/ianshirt
- name = "worn shirt"
- desc = "A worn out, curiously comfortable t-shirt with a picture of Ian. You wouldn't go so far as to say it feels like being hugged when you wear it but it's pretty close. Good for sleeping in."
- icon_state = "ianshirt"
- item_state = "ianshirt"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-
-
-//pyjamas
-//originally intended to be pinstripes >.>
-
-/obj/item/clothing/under/bluepyjamas
- name = "blue pyjamas"
- desc = "Slightly old-fashioned sleepwear."
- icon_state = "blue_pyjamas"
- item_state = "blue_pyjamas"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
-
-/obj/item/clothing/under/redpyjamas
- name = "red pyjamas"
- desc = "Slightly old-fashioned sleepwear."
- icon_state = "red_pyjamas"
- item_state = "red_pyjamas"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
-
-//coats
-
-/obj/item/clothing/suit/leathercoat
- name = "leather coat"
- desc = "A long, thick black leather coat."
- icon_state = "leathercoat"
- item_state = "leathercoat"
- burn_state = FIRE_PROOF
-
-/obj/item/clothing/suit/browncoat
- name = "brown leather coat"
- desc = "A long, brown leather coat."
- icon_state = "browncoat"
- item_state = "browncoat"
-
-/obj/item/clothing/suit/neocoat
- name = "black coat"
- desc = "A flowing, black coat."
- icon_state = "neocoat"
- item_state = "neocoat"
-
-/obj/item/clothing/suit/browntrenchcoat
- name = "brown trench coat"
- desc = "It makes you stand out. Just the opposite of why it's typically worn. Nice try trying to blend in while wearing it."
- icon_state = "brtrenchcoat"
- item_state = "brtrenchcoat"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/blacktrenchcoat
- name = "black trench coat"
- desc = "That shade of black just makes you look a bit more evil. Good for those mafia types."
- icon_state = "bltrenchcoat"
- item_state = "bltrenchcoat"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-//trackjackets
-
-/obj/item/clothing/suit/tracksuit
- name = "black tracksuit"
- desc = "Lightweight and stylish. What else could a man ask of his tracksuit?"
- icon_state = "trackjacket_open"
- item_state = "bltrenchcoat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- ignore_suitadjust = 0
- suit_adjusted = 1
- actions_types = list(/datum/action/item_action/openclose)
- adjust_flavour = "unzip"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/tracksuit/green
- name = "green tracksuit"
- icon_state = "trackjacketgreen_open"
-
-/obj/item/clothing/suit/tracksuit/red
- name = "red tracksuit"
- icon_state = "trackjacketred_open"
-
-/obj/item/clothing/suit/tracksuit/white
- name = "white tracksuit"
- icon_state = "trackjacketwhite_open"
-
-//actual suits
-
-/obj/item/clothing/suit/creamsuit
- name = "cream suit"
- desc = "A cream coloured, genteel suit."
- icon_state = "creamsuit"
- item_state = "creamsuit"
-
-/obj/item/clothing/under/stripper/mankini
- name = "the mankini"
- desc = "No honest man would wear this abomination"
- icon_state = "mankini"
- item_color = "mankini"
-
-/obj/item/clothing/suit/jacket/miljacket
- name = "olive military jacket"
- desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in olive."
- icon_state = "militaryjacket"
- item_state = "militaryjacket"
- ignore_suitadjust = 1
- actions_types = list()
- adjust_flavour = null
- allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/gun/projectile/automatic/pistol,/obj/item/gun/projectile/revolver,/obj/item/gun/projectile/revolver/detective)
-
-/obj/item/clothing/suit/jacket/miljacket/navy
- name = "navy military jacket"
- desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in navy blue."
- icon_state = "navy_jacket"
-
-/obj/item/clothing/suit/jacket/miljacket/desert
- name = "desert military jacket"
- desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in desert beige."
- icon_state = "desert_jacket"
-
-/obj/item/clothing/suit/jacket/miljacket/white
- name = "white military jacket"
- desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in snow white."
- icon_state = "white_jacket"
-
-/obj/item/clothing/suit/xenos
- name = "xenos suit"
- desc = "A suit made out of chitinous alien hide."
- icon_state = "xenos"
- item_state = "xenos_helm"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
- flags_size = ONESIZEFITSALL
-
-//swimsuit
-/obj/item/clothing/under/swimsuit/
-
-/obj/item/clothing/under/swimsuit/black
- name = "black swimsuit"
- desc = "An oldfashioned black swimsuit."
- icon_state = "swim_black"
- item_color = "swim_black"
-
-/obj/item/clothing/under/swimsuit/blue
- name = "blue swimsuit"
- desc = "An oldfashioned blue swimsuit."
- icon_state = "swim_blue"
- item_color = "swim_blue"
-
-/obj/item/clothing/under/swimsuit/purple
- name = "purple swimsuit"
- desc = "An oldfashioned purple swimsuit."
- icon_state = "swim_purp"
- item_color = "swim_purp"
-
-/obj/item/clothing/under/swimsuit/green
- name = "green swimsuit"
- desc = "An oldfashioned green swimsuit."
- icon_state = "swim_green"
- item_color = "swim_green"
-
-/obj/item/clothing/under/swimsuit/red
- name = "red swimsuit"
- desc = "An oldfashioned red swimsuit."
- icon_state = "swim_red"
- item_color = "swim_red"
-
-/obj/item/clothing/suit/storage/mercy_hoodie
- name = "mercy robe"
- desc = "A soft white robe made of a synthetic fiber that provides improved protection against biohazards. Possessing multiple overlapping layers, yet light enough to allow complete freedom of movement, it denotes its wearer as a master physician."
- icon_state = "mercy_hoodie"
- item_state = "mercy_hoodie"
- w_class = WEIGHT_CLASS_BULKY
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.01
- flags_size = ONESIZEFITSALL
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
- allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
- flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
-
-/obj/item/clothing/head/mercy_hood
- name = "Mercy Hood"
- desc = "A soft white hood made of a synthetic fiber that provides improved protection against biohazards. Its elegant design allows a clear field of vision."
- icon_state = "mercy_hood"
- item_state = "mercy_hood"
- permeability_coefficient = 0.01
- flags = BLOCKHAIR
- flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES
-
-/obj/item/clothing/suit/jacket
- name = "bomber jacket"
- desc = "Aviators not included."
- icon_state = "bomber"
- item_state = "bomber"
- ignore_suitadjust = 0
- allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
- actions_types = list(/datum/action/item_action/zipper)
- adjust_flavour = "unzip"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/jacket/pilot
- name = "security bomber jacket"
- desc = "A stylish and worn-in armoured black bomber jacket emblazoned with the NT Security crest on the left breast. Looks rugged."
- icon_state = "bombersec"
- item_state = "bombersec"
- ignore_suitadjust = 0
- //Inherited from Security armour.
- allowed = list(/obj/item/gun/energy,/obj/item/reagent_containers/spray/pepper,/obj/item/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/flashlight/seclite,/obj/item/melee/classic_baton/telescopic,/obj/item/kitchen/knife/combat)
- heat_protection = UPPER_TORSO|LOWER_TORSO
- min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
- max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
- strip_delay = 60
- put_on_delay = 40
- flags_size = ONESIZEFITSALL
- armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0)
- //End of inheritance from Security armour.
-
-/obj/item/clothing/suit/jacket/leather
- name = "leather jacket"
- desc = "Pompadour not included."
- icon_state = "leatherjacket"
- ignore_suitadjust = 1
- actions_types = list()
- adjust_flavour = null
- burn_state = FIRE_PROOF
-
-/obj/item/clothing/suit/jacket/leather/overcoat
- name = "leather overcoat"
- desc = "That's a damn fine coat."
- icon_state = "leathercoat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
- cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
-
-/obj/item/clothing/suit/officercoat
- name = "Clown Officer's Coat"
- desc = "A classy clown officer's overcoat, also designed by Hugo Boss."
- icon_state = "officersuit"
- item_state = "officersuit"
- ignore_suitadjust = 0
- actions_types = list(/datum/action/item_action/button)
- adjust_flavour = "unbutton"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/soldiercoat
- name = "Clown Soldier's Coat"
- desc = "An overcoat for the clown soldier, to keep him warm during those cold winter nights on the front."
- icon_state = "soldiersuit"
- item_state = "soldiersuit"
- ignore_suitadjust = 0
- actions_types = list(/datum/action/item_action/button)
- adjust_flavour = "unbutton"
-
- sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
- )
-
-/obj/item/clothing/suit/toggle/owlwings
- name = "owl cloak"
- desc = "A soft brown cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive the ladies mad."
- icon_state = "owl_wings"
- item_state = "owl_wings"
- body_parts_covered = ARMS
- armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
- allowed = list(/obj/item/gun/energy,/obj/item/reagent_containers/spray/pepper,/obj/item/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/flashlight/seclite)
- actions_types = list(/datum/action/item_action/toggle_wings)
-
-
-/obj/item/clothing/suit/toggle/owlwings/griffinwings
- name = "griffon cloak"
- desc = "A plush white cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive your captives mad."
- icon_state = "griffin_wings"
- item_state = "griffin_wings"
-
-/obj/item/clothing/suit/toggle/attack_self()
- if(icon_state == initial(icon_state))
- icon_state = icon_state + "_t"
- item_state = icon_state + "_t"
- else
- icon_state = initial(icon_state)
- item_state = initial(item_state)
- usr.update_inv_wear_suit()
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
-
-/obj/item/clothing/suit/lordadmiral
- name = "Lord Admiral's Coat"
- desc = "You'll be the Ruler of the King's Navy in no time."
- icon_state = "lordadmiral"
- item_state = "lordadmiral"
- allowed = list (/obj/item/gun)
-
-/obj/item/clothing/suit/fluff/noble_coat
- name = "noble coat"
- desc = "The livid blues, purples and greens are awesome enough to evoke a visceral response in you; it is not dissimilar to indigestion."
- icon_state = "noble_coat"
- item_state = "noble_coat"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
-
-
-///Advanced Protective Suit, AKA, God Mode in wearable form.
-
-/obj/item/clothing/suit/advanced_protective_suit
- name = "Advanced Protective Suit"
- desc = "An incredibly advanced and complex suit; it has so many buttons and dials as to be incomprehensible."
- icon_state = "bomb"
- item_state = "bomb"
- actions_types = list(/datum/action/item_action/toggle)
- gas_transfer_coefficient = 0.01
- permeability_coefficient = 0.01
- flags = STOPSPRESSUREDMAGE | THICKMATERIAL | NODROP
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS|HEAD
- armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100)
- cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS | HEAD
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- heat_protection = UPPER_TORSO | LOWER_TORSO|LEGS|FEET|ARMS|HANDS | HEAD
- max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
- slowdown = -10
- siemens_coefficient = 0
- var/on = 0
-
-/obj/item/clothing/suit/advanced_protective_suit/Destroy()
- if(on)
- on = 0
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/item/clothing/suit/advanced_protective_suit/ui_action_click()
- if(on)
- on = 0
- to_chat(usr, "You turn the suit's special processes off.")
- else
- on = 1
- to_chat(usr, "You turn the suit's special processes on.")
- START_PROCESSING(SSobj, src)
-
-
-/obj/item/clothing/suit/advanced_protective_suit/IsReflect()
- return (on)
-
-/obj/item/clothing/suit/advanced_protective_suit/process()
- if(on)
- var/mob/living/carbon/human/user = src.loc
- if(user && ishuman(user) && (user.wear_suit == src))
- if(user.reagents.get_reagent_amount("stimulants") < 15)
- user.reagents.add_reagent("stimulants", 15)
- if(user.reagents.get_reagent_amount("adminordrazine") < 15)
- user.reagents.add_reagent("adminordrazine", 15)
- if(user.reagents.get_reagent_amount("nanites") < 15)
- user.reagents.add_reagent("nanites", 15)
- if(user.reagents.get_reagent_amount("syndicate_nanites") < 15)
- user.reagents.add_reagent("syndicate_nanites", 15)
- else
- STOP_PROCESSING(SSobj, src)
-
-//Syndicate Chaplain Robe (WOLOLO!)
-/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe
- description_antag = "This robe is made of reinforced fibers, granting it superior protection. The robes also wirelessly generate power for the neurotransmitter in the linked missionary staff while being worn."
- armor = list(melee = 10, bullet = 10, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 15)
- var/obj/item/nullrod/missionary_staff/linked_staff = null
-
-/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/Destroy()
- if(linked_staff) //delink on destruction
- linked_staff.robes = null
- linked_staff = null
- STOP_PROCESSING(SSobj, src) //probably is cleared in a parent call already, but just in case we're gonna do it here
- return ..()
-
-/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/equipped(mob/living/carbon/human/H, slot)
- if(!istype(H) || slot != slot_wear_suit)
- STOP_PROCESSING(SSobj, src)
- return
- else
- START_PROCESSING(SSobj, src)
-
-/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/process()
- if(!linked_staff) //if we don't have a linked staff, the rest of this is useless
- return
-
- if(!ishuman(loc)) //if we somehow try to process while not on a human, remove ourselves from processing and return
- STOP_PROCESSING(SSobj, src)
- return
-
- var/mob/living/carbon/human/H = loc
-
- if(linked_staff.faith >= 100) //if the linked staff is fully recharged, do nothing
- return
-
- if(!linked_staff in range(3, get_turf(src))) //staff won't charge at range (to prevent it from being handed off / stolen and used)
- if(prob(10)) //10% chance per process should avoid being too spammy, can tweak if it ends up still being too frequent.
- to_chat(H, "Your staff is unable to charge at this range. Get closer!")
- return
-
- linked_staff.faith += 5
- if(linked_staff.faith >= 100) //if this charge puts the staff at or above full, notify the wearer
- to_chat(H, "Faith renewed; ready to convert new followers.")
-
-/obj/item/clothing/suit/tailcoat
- name = "victorian tailcoat"
- desc = "A fancy victorian tailcoat."
- icon_state = "tailcoat"
- item_state = "tailcoat"
-
-/obj/item/clothing/suit/victcoat
- name = "ladies victorian coat"
- desc = "A fancy victorian coat."
- icon_state = "ladiesvictoriancoat"
- item_state = "ladiesvictoriancoat"
-
-/obj/item/clothing/suit/victcoat/red
- name = "ladies red victorian coat"
- icon_state = "ladiesredvictoriancoat"
- item_state = "ladiesredvictoriancoat"
-
-//Mantles!
-/obj/item/clothing/suit/mantle
- name = "mantle"
- desc = "A heavy quilted mantle, for keeping your shoulders warm and stylish."
- icon_state = "mantle"
- item_state = "mantle"
- body_parts_covered = UPPER_TORSO|ARMS
- cold_protection = UPPER_TORSO|ARMS
- min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
-
-/obj/item/clothing/suit/mantle/regal
- name = "regal shawl"
- desc = "A fancy shawl for nobility, made from high quality materials."
- icon_state = "regal_mantle"
- item_state = "regal_mantle"
-
-/obj/item/clothing/suit/mantle/old
- name = "old wrap"
- desc = "A tattered fabric wrap, faded over the years. Smells faintly of cigars."
- icon_state = "old_mantle"
- item_state = "old_mantle"
-
+/*
+ * Contains:
+ * Lasertag
+ * Costume
+ * Winter Coats
+ * Misc
+ */
+
+/*
+ * Lasertag
+ */
+/obj/item/clothing/suit/bluetag
+ name = "blue laser tag armour"
+ desc = "Blue Pride, Station Wide."
+ icon_state = "bluetag"
+ item_state = "bluetag"
+ blood_overlay_type = "armor"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
+ allowed = list (/obj/item/gun/energy/laser/tag/blue)
+ burn_state = FIRE_PROOF
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/redtag
+ name = "red laser tag armour"
+ desc = "Pew pew pew."
+ icon_state = "redtag"
+ item_state = "redtag"
+ blood_overlay_type = "armor"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
+ allowed = list (/obj/item/gun/energy/laser/tag/red)
+ burn_state = FIRE_PROOF
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/*
+ * Costume
+ */
+/obj/item/clothing/suit/pirate_brown
+ name = "brown pirate coat"
+ desc = "Yarr."
+ icon_state = "pirate_old"
+ item_state = "pirate_old"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/pirate_black
+ name = "black pirate coat"
+ desc = "Yarr."
+ icon_state = "pirate"
+ item_state = "pirate"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/hgpirate
+ name = "pirate captain coat"
+ desc = "Yarr."
+ icon_state = "hgpirate"
+ item_state = "hgpirate"
+ flags_inv = HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/cyborg_suit
+ name = "cyborg suit"
+ desc = "Suit for a cyborg costume."
+ icon_state = "death"
+ item_state = "death"
+ flags = CONDUCT
+ fire_resist = T0C+5200
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/greatcoat
+ name = "great coat"
+ desc = "A Nazi great coat."
+ icon_state = "nazi"
+ item_state = "nazi"
+
+
+/obj/item/clothing/suit/johnny_coat
+ name = "johnny~~ coat"
+ desc = "Johnny~~"
+ icon_state = "johnny"
+ item_state = "johnny"
+
+
+/obj/item/clothing/suit/justice
+ name = "justice suit"
+ desc = "this pretty much looks ridiculous"
+ icon_state = "justice"
+ item_state = "justice"
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/judgerobe
+ name = "judge's robe"
+ desc = "This robe commands authority."
+ icon_state = "judge"
+ item_state = "judge"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ allowed = list(/obj/item/storage/fancy/cigarettes,/obj/item/stack/spacecash)
+ flags_inv = HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/wcoat
+ name = "waistcoat"
+ desc = "For some classy, murderous fun."
+ icon_state = "vest"
+ item_state = "wcoat"
+ blood_overlay_type = "armor"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/apron/overalls
+ name = "coveralls"
+ desc = "A set of denim overalls."
+ icon_state = "overalls"
+ item_state = "overalls"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS
+
+
+/obj/item/clothing/suit/syndicatefake
+ name = "black and red space suit replica"
+ icon_state = "syndicate-black-red"
+ item_state = "syndicate-black-red"
+ desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!"
+ w_class = WEIGHT_CLASS_NORMAL
+ allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy)
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+ burn_state = FIRE_PROOF
+
+
+/obj/item/clothing/suit/hastur
+ name = "Hastur's robes"
+ desc = "Robes not meant to be worn by man."
+ icon_state = "hastur"
+ item_state = "hastur"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/imperium_monk
+ name = "imperium monk"
+ desc = "Have YOU killed a xeno today?"
+ icon_state = "imperium_monk"
+ item_state = "imperium_monk"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ flags_inv = HIDESHOES|HIDEJUMPSUIT
+ allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
+
+/obj/item/clothing/suit/chickensuit
+ name = "chicken suit"
+ desc = "A suit made long ago by the ancient empire KFC."
+ icon_state = "chickensuit"
+ item_state = "chickensuit"
+ body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET
+ flags_inv = HIDESHOES|HIDEJUMPSUIT
+
+/obj/item/clothing/suit/corgisuit
+ name = "corgi suit"
+ desc = "A suit made long ago by the ancient empire KFC."
+ icon_state = "corgisuit"
+ item_state = "chickensuit"
+ body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET
+ flags_inv = HIDESHOES|HIDEJUMPSUIT
+
+/obj/item/clothing/suit/corgisuit/super_hero
+ name = "super-hero corgi suit"
+ desc = "A suit made long ago by the ancient empire KFC. This one pulses with a strange power."
+ flags = NODROP
+
+/obj/item/clothing/suit/corgisuit/super_hero/en
+ name = "\improper super-hero E-N suit"
+ icon_state = "ensuit"
+
+/obj/item/clothing/suit/corgisuit/super_hero/en/New()
+ ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/clothing/suit/corgisuit/super_hero/en/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/clothing/suit/corgisuit/super_hero/en/process()
+ if(prob(2))
+ for(var/obj/M in orange(2,src))
+ if(!M.anchored && (M.flags & CONDUCT))
+ step_towards(M,src)
+ for(var/mob/living/silicon/S in orange(2,src))
+ if(istype(S, /mob/living/silicon/ai)) continue
+ step_towards(S,src)
+ for(var/mob/living/carbon/human/machine/M in orange(2,src))
+ step_towards(M,src)
+
+/obj/item/clothing/suit/monkeysuit
+ name = "monkey suit"
+ desc = "A suit that looks like a primate"
+ icon_state = "monkeysuit"
+ item_state = "monkeysuit"
+ body_parts_covered = UPPER_TORSO|ARMS|LOWER_TORSO|LEGS|FEET|HANDS
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+
+
+/obj/item/clothing/suit/holidaypriest
+ name = "holiday priest"
+ desc = "This is a nice holiday my son."
+ icon_state = "holidaypriest"
+ item_state = "holidaypriest"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ flags_inv = HIDEJUMPSUIT
+ allowed = list(/obj/item/storage/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/emergency_oxygen)
+
+/obj/item/clothing/suit/cardborg
+ name = "cardborg suit"
+ desc = "An ordinary cardboard box with holes cut in the sides."
+ icon_state = "cardborg"
+ item_state = "cardborg"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
+ flags_inv = HIDEJUMPSUIT
+ species_disguise = "High-tech robot"
+
+/obj/item/clothing/suit/cardborg/equipped(mob/living/user, slot)
+ ..()
+ if(slot == slot_wear_suit)
+ disguise(user)
+
+/obj/item/clothing/suit/cardborg/dropped(mob/living/user)
+ ..()
+ user.remove_alt_appearance("standard_borg_disguise")
+
+/obj/item/clothing/suit/cardborg/proc/disguise(mob/living/carbon/human/H, obj/item/clothing/head/cardborg/borghead)
+ if(istype(H))
+ if(!borghead)
+ borghead = H.head
+ if(istype(borghead, /obj/item/clothing/head/cardborg)) //why is this done this way? because equipped() is called BEFORE THE ITEM IS IN THE SLOT WHYYYY
+ var/image/I = image(icon = 'icons/mob/robots.dmi' , icon_state = "robot", loc = H)
+ I.override = 1
+ I.overlays += image(icon = 'icons/mob/robots.dmi' , icon_state = "eyes-robot") //gotta look realistic
+ H.add_alt_appearance("standard_borg_disguise", I, GLOB.silicon_mob_list+H) //you look like a robot to robots! (including yourself because you're totally a robot)
+
+/obj/item/clothing/suit/snowman
+ name = "snowman outfit"
+ desc = "Two white spheres covered in white glitter. 'Tis the season."
+ icon_state = "snowman"
+ item_state = "snowman"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
+ flags_inv = HIDEJUMPSUIT
+
+/obj/item/clothing/suit/poncho
+ name = "poncho"
+ desc = "Your classic, non-racist poncho."
+ icon_state = "classicponcho"
+ item_state = "classicponcho"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/poncho/green
+ name = "green poncho"
+ desc = "Your classic, non-racist poncho. This one is green."
+ icon_state = "greenponcho"
+ item_state = "greenponcho"
+
+/obj/item/clothing/suit/poncho/red
+ name = "red poncho"
+ desc = "Your classic, non-racist poncho. This one is red."
+ icon_state = "redponcho"
+ item_state = "redponcho"
+
+/obj/item/clothing/suit/poncho/ponchoshame
+ name = "poncho of shame"
+ desc = "Forced to live on your shameful acting as a fake Mexican, you and your poncho have grown inseperable. Literally."
+ icon_state = "ponchoshame"
+ item_state = "ponchoshame"
+ flags = NODROP
+
+/obj/item/clothing/suit/hooded/carp_costume
+ name = "carp costume"
+ desc = "A costume made from 'synthetic' carp scales, it smells."
+ icon_state = "carp_casual"
+ item_state = "labcoat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too
+ allowed = list(/obj/item/tank/emergency_oxygen)
+ hoodtype = /obj/item/clothing/head/hooded/carp_hood
+
+/obj/item/clothing/head/hooded/carp_hood
+ name = "carp hood"
+ desc = "A hood attached to a carp costume."
+ icon_state = "carp_casual"
+ body_parts_covered = HEAD
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ flags = BLOCKHAIR
+ flags_inv = HIDEEARS
+
+/obj/item/clothing/suit/hooded/bee_costume // It's Hip!
+ name = "bee costume"
+ desc = "Bee the true Queen!"
+ icon_state = "bee"
+ item_state = "labcoat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ flags = THICKMATERIAL
+ hoodtype = /obj/item/clothing/head/hooded/bee_hood
+
+/obj/item/clothing/head/hooded/bee_hood
+ name = "bee hood"
+ desc = "A hood attached to a bee costume."
+ icon_state = "bee"
+ body_parts_covered = HEAD
+ flags = THICKMATERIAL|BLOCKHAIR
+ flags_inv = HIDEEARS
+
+/obj/item/clothing/suit/bloated_human //OH MY GOD WHAT HAVE YOU DONE!?!?!?
+ name = "bloated human suit"
+ desc = "A horribly bloated suit made from human skins."
+ icon_state = "lingspacesuit"
+ item_state = "lingspacesuit"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+
+/obj/item/clothing/suit/draculacoat // Bleh!
+ name = "transylvanian coat"
+ desc = "What is a spessman? A miserable little pile of secrets."
+ icon_state = "draculacoat"
+ item_state = "draculacoat"
+
+/*
+ * Winter Coats
+ */
+
+/obj/item/clothing/suit/hooded/wintercoat
+ name = "winter coat"
+ desc = "A heavy jacket made from 'synthetic' animal furs."
+ icon_state = "wintercoat"
+ item_state = "coatwinter"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0)
+ allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/suit.dmi')
+
+/obj/item/clothing/head/hooded/winterhood
+ name = "winter hood"
+ desc = "A hood attached to a heavy winter jacket."
+ icon_state = "winterhood"
+ body_parts_covered = HEAD
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ flags = BLOCKHAIR
+ flags_inv = HIDEEARS
+
+ sprite_sheets = list("Vox" = 'icons/mob/species/vox/head.dmi')
+
+/obj/item/clothing/suit/hooded/wintercoat/captain
+ name = "captain's winter coat"
+ icon_state = "wintercoat_captain"
+ item_state = "coatcaptain"
+ armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
+ allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/captain
+
+/obj/item/clothing/head/hooded/winterhood/captain
+ icon_state = "winterhood_captain"
+
+/obj/item/clothing/suit/hooded/wintercoat/security
+ name = "security winter coat"
+ icon_state = "wintercoat_sec"
+ item_state = "coatsecurity"
+ armor = list(melee = 10, bullet = 10, laser = 10, energy = 5, bomb = 15, bio = 0, rad = 0)
+ allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/security
+
+/obj/item/clothing/head/hooded/winterhood/security
+ icon_state = "winterhood_sec"
+
+/obj/item/clothing/suit/hooded/wintercoat/medical
+ name = "medical winter coat"
+ icon_state = "wintercoat_med"
+ item_state = "coatmedical"
+ allowed = list(/obj/item/analyzer, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/medical
+
+/obj/item/clothing/head/hooded/winterhood/medical
+ icon_state = "winterhood_med"
+
+/obj/item/clothing/suit/hooded/wintercoat/science
+ name = "science winter coat"
+ icon_state = "wintercoat_sci"
+ item_state = "coatscience"
+ allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/science
+
+/obj/item/clothing/head/hooded/winterhood/science
+ icon_state = "winterhood_sci"
+
+/obj/item/clothing/suit/hooded/wintercoat/engineering
+ name = "engineering winter coat"
+ icon_state = "wintercoat_engi"
+ item_state = "coatengineer"
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 20)
+ allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/t_scanner, /obj/item/rcd)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering
+
+/obj/item/clothing/head/hooded/winterhood/engineering
+ icon_state = "winterhood_engi"
+
+/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
+ name = "atmospherics winter coat"
+ icon_state = "wintercoat_atmos"
+ item_state = "coatatmos"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering/atmos
+
+/obj/item/clothing/head/hooded/winterhood/engineering/atmos
+ icon_state = "winterhood_atmos"
+
+/obj/item/clothing/suit/hooded/wintercoat/hydro
+ name = "hydroponics winter coat"
+ icon_state = "wintercoat_hydro"
+ item_state = "coathydro"
+ allowed = list(/obj/item/reagent_containers/spray, /obj/item/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/hatchet, /obj/item/storage/bag/plants)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/hydro
+
+/obj/item/clothing/head/hooded/winterhood/hydro
+ icon_state = "winterhood_hydro"
+
+/obj/item/clothing/suit/hooded/wintercoat/cargo
+ name = "cargo winter coat"
+ icon_state = "wintercoat_cargo"
+ item_state = "coatcargo"
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/cargo
+
+/obj/item/clothing/head/hooded/winterhood/cargo
+ icon_state = "winterhood_cargo"
+
+/obj/item/clothing/suit/hooded/wintercoat/miner
+ name = "mining winter coat"
+ icon_state = "wintercoat_miner"
+ item_state = "coatminer"
+ allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+ armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ hoodtype = /obj/item/clothing/head/hooded/winterhood/miner
+
+/obj/item/clothing/head/hooded/winterhood/miner
+ icon_state = "winterhood_miner"
+
+
+/*
+ * Misc
+ */
+
+//hoodies
+/obj/item/clothing/suit/hooded/hoodie
+ name = "black hoodie"
+ desc = "It's a hoodie. It has a hood. Most hoodies do."
+ icon_state = "black_hoodie"
+ item_state = "blueshieldcoat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen)
+ hoodtype = /obj/item/clothing/head/hooded/hood
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/head/hooded/hood
+ name = "black hood"
+ desc = "A hood attached to a hoodie."
+ icon_state = "blackhood"
+ body_parts_covered = HEAD
+ cold_protection = HEAD
+ flags = BLOCKHAIR
+ flags_inv = HIDEEARS
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/head.dmi'
+ )
+
+/obj/item/clothing/head/hooded/hood/blue
+ icon_state = "bluehood"
+
+/obj/item/clothing/head/hooded/hood/white
+ icon_state = "whitehood"
+
+/obj/item/clothing/suit/hooded/hoodie/blue
+ name = "blue hoodie"
+ icon_state = "blue_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood/blue
+
+/obj/item/clothing/suit/hooded/hoodie/mit
+ name = "Martian Institute of Technology hoodie"
+ desc = "A hoodie proudly worn by students and graduates alike, has the letters 'MIT' on the back."
+ icon_state = "mit_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood
+
+/obj/item/clothing/suit/hooded/hoodie/cut
+ name = "Canaan University of Technology hoodie"
+ desc = "A bright hoodie with the Canaan University of Technology logo on the front."
+ icon_state = "cut_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood/white
+
+/obj/item/clothing/suit/hooded/hoodie/lam
+ name = "Lunar Academy of Medicine hoodie"
+ desc = "A bright hoodie with the Lunar Academy of Medicine logo on the back."
+ icon_state = "lam_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood/white
+
+/obj/item/clothing/suit/hooded/hoodie/nt
+ name = "Nanotrasen hoodie"
+ desc = "A blue hoodie with the Nanotrasen logo on the back."
+ icon_state = "nt_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood/blue
+
+/obj/item/clothing/suit/hooded/hoodie/tp
+ name = "Tharsis Polytech hoodie"
+ desc = "A dark hoodie with the Tharsis Polytech logo on the back."
+ icon_state = "tp_hoodie"
+ hoodtype = /obj/item/clothing/head/hooded/hood
+
+/obj/item/clothing/suit/straight_jacket
+ name = "straight jacket"
+ desc = "A suit that completely restrains the wearer."
+ icon_state = "straight_jacket"
+ item_state = "straight_jacket"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
+ flags_size = ONESIZEFITSALL
+ strip_delay = 60
+ breakouttime = 3000
+
+/obj/item/clothing/suit/ianshirt
+ name = "worn shirt"
+ desc = "A worn out, curiously comfortable t-shirt with a picture of Ian. You wouldn't go so far as to say it feels like being hugged when you wear it but it's pretty close. Good for sleeping in."
+ icon_state = "ianshirt"
+ item_state = "ianshirt"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+
+
+//pyjamas
+//originally intended to be pinstripes >.>
+
+/obj/item/clothing/under/bluepyjamas
+ name = "blue pyjamas"
+ desc = "Slightly old-fashioned sleepwear."
+ icon_state = "blue_pyjamas"
+ item_state = "blue_pyjamas"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+
+/obj/item/clothing/under/redpyjamas
+ name = "red pyjamas"
+ desc = "Slightly old-fashioned sleepwear."
+ icon_state = "red_pyjamas"
+ item_state = "red_pyjamas"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+
+//coats
+
+/obj/item/clothing/suit/leathercoat
+ name = "leather coat"
+ desc = "A long, thick black leather coat."
+ icon_state = "leathercoat"
+ item_state = "leathercoat"
+ burn_state = FIRE_PROOF
+
+/obj/item/clothing/suit/browncoat
+ name = "brown leather coat"
+ desc = "A long, brown leather coat."
+ icon_state = "browncoat"
+ item_state = "browncoat"
+
+/obj/item/clothing/suit/neocoat
+ name = "black coat"
+ desc = "A flowing, black coat."
+ icon_state = "neocoat"
+ item_state = "neocoat"
+
+/obj/item/clothing/suit/browntrenchcoat
+ name = "brown trench coat"
+ desc = "It makes you stand out. Just the opposite of why it's typically worn. Nice try trying to blend in while wearing it."
+ icon_state = "brtrenchcoat"
+ item_state = "brtrenchcoat"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/blacktrenchcoat
+ name = "black trench coat"
+ desc = "That shade of black just makes you look a bit more evil. Good for those mafia types."
+ icon_state = "bltrenchcoat"
+ item_state = "bltrenchcoat"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+//trackjackets
+
+/obj/item/clothing/suit/tracksuit
+ name = "black tracksuit"
+ desc = "Lightweight and stylish. What else could a man ask of his tracksuit?"
+ icon_state = "trackjacket_open"
+ item_state = "bltrenchcoat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ ignore_suitadjust = 0
+ suit_adjusted = 1
+ actions_types = list(/datum/action/item_action/openclose)
+ adjust_flavour = "unzip"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/tracksuit/green
+ name = "green tracksuit"
+ icon_state = "trackjacketgreen_open"
+
+/obj/item/clothing/suit/tracksuit/red
+ name = "red tracksuit"
+ icon_state = "trackjacketred_open"
+
+/obj/item/clothing/suit/tracksuit/white
+ name = "white tracksuit"
+ icon_state = "trackjacketwhite_open"
+
+//actual suits
+
+/obj/item/clothing/suit/creamsuit
+ name = "cream suit"
+ desc = "A cream coloured, genteel suit."
+ icon_state = "creamsuit"
+ item_state = "creamsuit"
+
+/obj/item/clothing/under/stripper/mankini
+ name = "the mankini"
+ desc = "No honest man would wear this abomination"
+ icon_state = "mankini"
+ item_color = "mankini"
+
+/obj/item/clothing/suit/jacket/miljacket
+ name = "olive military jacket"
+ desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in olive."
+ icon_state = "militaryjacket"
+ item_state = "militaryjacket"
+ ignore_suitadjust = 1
+ actions_types = list()
+ adjust_flavour = null
+ allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/gun/projectile/automatic/pistol,/obj/item/gun/projectile/revolver,/obj/item/gun/projectile/revolver/detective)
+
+/obj/item/clothing/suit/jacket/miljacket/navy
+ name = "navy military jacket"
+ desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in navy blue."
+ icon_state = "navy_jacket"
+
+/obj/item/clothing/suit/jacket/miljacket/desert
+ name = "desert military jacket"
+ desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in desert beige."
+ icon_state = "desert_jacket"
+
+/obj/item/clothing/suit/jacket/miljacket/white
+ name = "white military jacket"
+ desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in snow white."
+ icon_state = "white_jacket"
+
+/obj/item/clothing/suit/xenos
+ name = "xenos suit"
+ desc = "A suit made out of chitinous alien hide."
+ icon_state = "xenos"
+ item_state = "xenos_helm"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
+ flags_size = ONESIZEFITSALL
+
+//swimsuit
+/obj/item/clothing/under/swimsuit/
+
+/obj/item/clothing/under/swimsuit/black
+ name = "black swimsuit"
+ desc = "An oldfashioned black swimsuit."
+ icon_state = "swim_black"
+ item_color = "swim_black"
+
+/obj/item/clothing/under/swimsuit/blue
+ name = "blue swimsuit"
+ desc = "An oldfashioned blue swimsuit."
+ icon_state = "swim_blue"
+ item_color = "swim_blue"
+
+/obj/item/clothing/under/swimsuit/purple
+ name = "purple swimsuit"
+ desc = "An oldfashioned purple swimsuit."
+ icon_state = "swim_purp"
+ item_color = "swim_purp"
+
+/obj/item/clothing/under/swimsuit/green
+ name = "green swimsuit"
+ desc = "An oldfashioned green swimsuit."
+ icon_state = "swim_green"
+ item_color = "swim_green"
+
+/obj/item/clothing/under/swimsuit/red
+ name = "red swimsuit"
+ desc = "An oldfashioned red swimsuit."
+ icon_state = "swim_red"
+ item_color = "swim_red"
+
+/obj/item/clothing/suit/storage/mercy_hoodie
+ name = "mercy robe"
+ desc = "A soft white robe made of a synthetic fiber that provides improved protection against biohazards. Possessing multiple overlapping layers, yet light enough to allow complete freedom of movement, it denotes its wearer as a master physician."
+ icon_state = "mercy_hoodie"
+ item_state = "mercy_hoodie"
+ w_class = WEIGHT_CLASS_BULKY
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.01
+ flags_size = ONESIZEFITSALL
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
+ allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen)
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
+ flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
+
+/obj/item/clothing/head/mercy_hood
+ name = "Mercy Hood"
+ desc = "A soft white hood made of a synthetic fiber that provides improved protection against biohazards. Its elegant design allows a clear field of vision."
+ icon_state = "mercy_hood"
+ item_state = "mercy_hood"
+ permeability_coefficient = 0.01
+ flags = BLOCKHAIR
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES
+
+/obj/item/clothing/suit/jacket
+ name = "bomber jacket"
+ desc = "Aviators not included."
+ icon_state = "bomber"
+ item_state = "bomber"
+ ignore_suitadjust = 0
+ allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+ actions_types = list(/datum/action/item_action/zipper)
+ adjust_flavour = "unzip"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/jacket/pilot
+ name = "security bomber jacket"
+ desc = "A stylish and worn-in armoured black bomber jacket emblazoned with the NT Security crest on the left breast. Looks rugged."
+ icon_state = "bombersec"
+ item_state = "bombersec"
+ ignore_suitadjust = 0
+ //Inherited from Security armour.
+ allowed = list(/obj/item/gun/energy,/obj/item/reagent_containers/spray/pepper,/obj/item/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/flashlight/seclite,/obj/item/melee/classic_baton/telescopic,/obj/item/kitchen/knife/combat)
+ heat_protection = UPPER_TORSO|LOWER_TORSO
+ min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
+ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
+ strip_delay = 60
+ put_on_delay = 40
+ flags_size = ONESIZEFITSALL
+ armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0)
+ //End of inheritance from Security armour.
+
+/obj/item/clothing/suit/jacket/leather
+ name = "leather jacket"
+ desc = "Pompadour not included."
+ icon_state = "leatherjacket"
+ ignore_suitadjust = 1
+ actions_types = list()
+ adjust_flavour = null
+ burn_state = FIRE_PROOF
+
+/obj/item/clothing/suit/jacket/leather/overcoat
+ name = "leather overcoat"
+ desc = "That's a damn fine coat."
+ icon_state = "leathercoat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+
+/obj/item/clothing/suit/officercoat
+ name = "Clown Officer's Coat"
+ desc = "A classy clown officer's overcoat, also designed by Hugo Boss."
+ icon_state = "officersuit"
+ item_state = "officersuit"
+ ignore_suitadjust = 0
+ actions_types = list(/datum/action/item_action/button)
+ adjust_flavour = "unbutton"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/soldiercoat
+ name = "Clown Soldier's Coat"
+ desc = "An overcoat for the clown soldier, to keep him warm during those cold winter nights on the front."
+ icon_state = "soldiersuit"
+ item_state = "soldiersuit"
+ ignore_suitadjust = 0
+ actions_types = list(/datum/action/item_action/button)
+ adjust_flavour = "unbutton"
+
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+
+/obj/item/clothing/suit/toggle/owlwings
+ name = "owl cloak"
+ desc = "A soft brown cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive the ladies mad."
+ icon_state = "owl_wings"
+ item_state = "owl_wings"
+ body_parts_covered = ARMS
+ armor = list(melee = 5, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ allowed = list(/obj/item/gun/energy,/obj/item/reagent_containers/spray/pepper,/obj/item/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/flashlight/seclite)
+ actions_types = list(/datum/action/item_action/toggle_wings)
+
+
+/obj/item/clothing/suit/toggle/owlwings/griffinwings
+ name = "griffon cloak"
+ desc = "A plush white cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive your captives mad."
+ icon_state = "griffin_wings"
+ item_state = "griffin_wings"
+
+/obj/item/clothing/suit/toggle/attack_self()
+ if(icon_state == initial(icon_state))
+ icon_state = icon_state + "_t"
+ item_state = icon_state + "_t"
+ else
+ icon_state = initial(icon_state)
+ item_state = initial(item_state)
+ usr.update_inv_wear_suit()
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+/obj/item/clothing/suit/lordadmiral
+ name = "Lord Admiral's Coat"
+ desc = "You'll be the Ruler of the King's Navy in no time."
+ icon_state = "lordadmiral"
+ item_state = "lordadmiral"
+ allowed = list (/obj/item/gun)
+
+/obj/item/clothing/suit/fluff/noble_coat
+ name = "noble coat"
+ desc = "The livid blues, purples and greens are awesome enough to evoke a visceral response in you; it is not dissimilar to indigestion."
+ icon_state = "noble_coat"
+ item_state = "noble_coat"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+
+
+///Advanced Protective Suit, AKA, God Mode in wearable form.
+
+/obj/item/clothing/suit/advanced_protective_suit
+ name = "Advanced Protective Suit"
+ desc = "An incredibly advanced and complex suit; it has so many buttons and dials as to be incomprehensible."
+ icon_state = "bomb"
+ item_state = "bomb"
+ actions_types = list(/datum/action/item_action/toggle)
+ gas_transfer_coefficient = 0.01
+ permeability_coefficient = 0.01
+ flags = STOPSPRESSUREDMAGE | THICKMATERIAL | NODROP
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS|HEAD
+ armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100)
+ cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS | HEAD
+ min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
+ heat_protection = UPPER_TORSO | LOWER_TORSO|LEGS|FEET|ARMS|HANDS | HEAD
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ slowdown = -10
+ siemens_coefficient = 0
+ var/on = 0
+
+/obj/item/clothing/suit/advanced_protective_suit/Destroy()
+ if(on)
+ on = 0
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/clothing/suit/advanced_protective_suit/ui_action_click()
+ if(on)
+ on = 0
+ to_chat(usr, "You turn the suit's special processes off.")
+ else
+ on = 1
+ to_chat(usr, "You turn the suit's special processes on.")
+ START_PROCESSING(SSobj, src)
+
+
+/obj/item/clothing/suit/advanced_protective_suit/IsReflect()
+ return (on)
+
+/obj/item/clothing/suit/advanced_protective_suit/process()
+ if(on)
+ var/mob/living/carbon/human/user = src.loc
+ if(user && ishuman(user) && (user.wear_suit == src))
+ if(user.reagents.get_reagent_amount("stimulants") < 15)
+ user.reagents.add_reagent("stimulants", 15)
+ if(user.reagents.get_reagent_amount("adminordrazine") < 15)
+ user.reagents.add_reagent("adminordrazine", 15)
+ if(user.reagents.get_reagent_amount("nanites") < 15)
+ user.reagents.add_reagent("nanites", 15)
+ if(user.reagents.get_reagent_amount("syndicate_nanites") < 15)
+ user.reagents.add_reagent("syndicate_nanites", 15)
+ else
+ STOP_PROCESSING(SSobj, src)
+
+//Syndicate Chaplain Robe (WOLOLO!)
+/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe
+ description_antag = "This robe is made of reinforced fibers, granting it superior protection. The robes also wirelessly generate power for the neurotransmitter in the linked missionary staff while being worn."
+ armor = list(melee = 10, bullet = 10, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 15)
+ var/obj/item/nullrod/missionary_staff/linked_staff = null
+
+/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/Destroy()
+ if(linked_staff) //delink on destruction
+ linked_staff.robes = null
+ linked_staff = null
+ STOP_PROCESSING(SSobj, src) //probably is cleared in a parent call already, but just in case we're gonna do it here
+ return ..()
+
+/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/equipped(mob/living/carbon/human/H, slot)
+ if(!istype(H) || slot != slot_wear_suit)
+ STOP_PROCESSING(SSobj, src)
+ return
+ else
+ START_PROCESSING(SSobj, src)
+
+/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/process()
+ if(!linked_staff) //if we don't have a linked staff, the rest of this is useless
+ return
+
+ if(!ishuman(loc)) //if we somehow try to process while not on a human, remove ourselves from processing and return
+ STOP_PROCESSING(SSobj, src)
+ return
+
+ var/mob/living/carbon/human/H = loc
+
+ if(linked_staff.faith >= 100) //if the linked staff is fully recharged, do nothing
+ return
+
+ if(!linked_staff in range(3, get_turf(src))) //staff won't charge at range (to prevent it from being handed off / stolen and used)
+ if(prob(10)) //10% chance per process should avoid being too spammy, can tweak if it ends up still being too frequent.
+ to_chat(H, "Your staff is unable to charge at this range. Get closer!")
+ return
+
+ linked_staff.faith += 5
+ if(linked_staff.faith >= 100) //if this charge puts the staff at or above full, notify the wearer
+ to_chat(H, "Faith renewed; ready to convert new followers.")
+
+/obj/item/clothing/suit/tailcoat
+ name = "victorian tailcoat"
+ desc = "A fancy victorian tailcoat."
+ icon_state = "tailcoat"
+ item_state = "tailcoat"
+
+/obj/item/clothing/suit/victcoat
+ name = "ladies victorian coat"
+ desc = "A fancy victorian coat."
+ icon_state = "ladiesvictoriancoat"
+ item_state = "ladiesvictoriancoat"
+
+/obj/item/clothing/suit/victcoat/red
+ name = "ladies red victorian coat"
+ icon_state = "ladiesredvictoriancoat"
+ item_state = "ladiesredvictoriancoat"
+
+//Mantles!
+/obj/item/clothing/suit/mantle
+ name = "mantle"
+ desc = "A heavy quilted mantle, for keeping your shoulders warm and stylish."
+ icon_state = "mantle"
+ item_state = "mantle"
+ body_parts_covered = UPPER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|ARMS
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
+
+/obj/item/clothing/suit/mantle/regal
+ name = "regal shawl"
+ desc = "A fancy shawl for nobility, made from high quality materials."
+ icon_state = "regal_mantle"
+ item_state = "regal_mantle"
+
+/obj/item/clothing/suit/mantle/old
+ name = "old wrap"
+ desc = "A tattered fabric wrap, faded over the years. Smells faintly of cigars."
+ icon_state = "old_mantle"
+ item_state = "old_mantle"
+
+/obj/item/clothing/suit/ghost_sheet
+ name = "ghost sheet"
+ desc = "The hands float by themselves, so it's extra spooky."
+ icon_state = "ghost_sheet"
+ item_state = "ghost_sheet"
+ throwforce = 0
+ throw_speed = 1
+ throw_range = 2
+ w_class = WEIGHT_CLASS_TINY
+ flags = BLOCKHAIR
+ flags_inv = HIDEGLOVES|HIDEEARS|HIDEFACE
diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm
index 871eab23d3b..576b3e6c552 100644
--- a/code/modules/clothing/suits/toggles.dm
+++ b/code/modules/clothing/suits/toggles.dm
@@ -6,7 +6,8 @@
/obj/item/clothing/suit/space/hardsuit/Destroy()
if(helmet)
helmet.suit = null
- qdel(helmet)
+ QDEL_NULL(helmet)
+ QDEL_NULL(jetpack)
return ..()
/obj/item/clothing/head/helmet/space/hardsuit/Destroy()
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 6bfd40ad0ad..81c6d15562a 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -88,6 +88,9 @@
item_state = "sexyclown"
item_color = "sexyclown"
+/obj/item/clothing/under/rank/clown/nodrop
+ flags = NODROP
+
/obj/item/clothing/under/rank/head_of_personnel
desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\"."
name = "head of personnel's jumpsuit"
@@ -208,6 +211,8 @@
item_color = "mime"
flags_size = ONESIZEFITSALL
+/obj/item/clothing/under/mime/nodrop
+ flags = NODROP
/obj/item/clothing/under/rank/miner
desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty."
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 91527f2dd19..c277345a440 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -890,3 +890,10 @@
item_color = "hawaiianblue"
flags_size = ONESIZEFITSALL
+/obj/item/clothing/under/misc/durathread
+ name = "durathread jumpsuit"
+ desc = "A jumpsuit made from durathread, its resilient fibres provide some protection to the wearer."
+ icon_state = "durathread"
+ item_state = "durathread"
+ item_color = "durathread"
+ armor = list(melee = 10, bullet = 0, laser = 10, energy = 0, bomb = 5, bio = 0, rad = 0)
\ No newline at end of file
diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm
index ea5e4a652aa..e05e31c297f 100644
--- a/code/modules/crafting/craft.dm
+++ b/code/modules/crafting/craft.dm
@@ -1,7 +1,26 @@
/datum/personal_crafting
var/busy
var/viewing_category = 1 //typical powergamer starting on the Weapons tab
- var/list/categories = list(CAT_WEAPON,CAT_AMMO,CAT_ROBOT,CAT_FOOD,CAT_MISC,CAT_PRIMAL)
+ var/viewing_subcategory = 1
+ var/list/categories = list(
+ CAT_WEAPONRY,
+ CAT_ROBOT,
+ CAT_MISC,
+ CAT_PRIMAL,
+ CAT_FOOD,
+ CAT_CLOTHING)
+ var/list/subcategories = list(
+ list( //Weapon subcategories
+ CAT_WEAPON,
+ CAT_AMMO),
+ CAT_NONE, //Robot subcategories
+ CAT_NONE, //Misc subcategories
+ CAT_NONE, //Tribal subcategories
+ list( //Food subcategories
+ CAT_CAKE,
+ CAT_SUSHI,
+ CAT_SANDWICH),
+ CAT_CLOTHING) //Clothing subcategories
var/display_craftable_only = FALSE
var/display_compact = TRUE
@@ -22,11 +41,14 @@
/datum/personal_crafting/proc/check_contents(datum/crafting_recipe/R, list/contents)
+ contents = contents["other"]
main_loop:
for(var/A in R.reqs)
var/needed_amount = R.reqs[A]
for(var/B in contents)
if(ispath(B, A))
+ if (R.blacklist.Find(B))
+ continue
if(contents[B] >= R.reqs[A])
continue main_loop
else
@@ -56,45 +78,47 @@
if(AM.flags_2 & HOLOGRAM_2)
continue
. += AM
+ for(var/slot in list(slot_r_store, slot_l_store))
+ . += user.get_item_by_slot(slot)
/datum/personal_crafting/proc/get_surroundings(mob/user)
. = list()
+ .["other"] = list()
for(var/obj/item/I in get_environment(user))
if(I.flags_2 & HOLOGRAM_2)
continue
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
- .[I.type] += S.amount
+ .["other"][I.type] += S.amount
else
if(istype(I, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RC = I
- if(RC.container_type & OPENCONTAINER)
+ if(RC.is_drainable())
for(var/datum/reagent/A in RC.reagents.reagent_list)
- .[A.type] += A.volume
- .[I.type] += 1
+ .["other"][A.type] += A.volume
+ .["other"][I.type] += 1
/datum/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
if(!R.tools.len)
- return 1
+ return TRUE
var/list/possible_tools = list()
for(var/obj/item/I in user.contents)
if(istype(I, /obj/item/storage))
for(var/obj/item/SI in I.contents)
possible_tools += SI.type
possible_tools += I.type
- possible_tools += contents
+ possible_tools |= contents["other"]
main_loop:
for(var/A in R.tools)
for(var/I in possible_tools)
if(ispath(I,A))
continue main_loop
- return 0
- return 1
+ return FALSE
+ return TRUE
/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
- for(var/A in R.parts)
var/list/contents = get_surroundings(user)
var/send_feedback = 1
if(check_contents(R, contents))
@@ -108,6 +132,8 @@
var/list/parts = del_reqs(R, user)
var/atom/movable/I = new R.result (get_turf(user.loc))
I.CheckParts(parts, R)
+ if(isitem(I))
+ user.put_in_hands(I)
if(send_feedback)
feedback_add_details("object_crafted","[I.type]")
return 0
@@ -173,6 +199,7 @@
RGNT.volume += RG.volume
RGNT.data += RG.data
qdel(RG)
+ RC.on_reagent_change()
else
surroundings -= RC
else if(ispath(A, /obj/item/stack))
@@ -195,7 +222,7 @@
else
data = S.amount
S = locate(S.type) in Deletion
- S.amount += data
+ S.add(data)
surroundings -= S
else
var/atom/movable/I
@@ -241,11 +268,19 @@
/datum/personal_crafting/ui_data(mob/user)
var/list/data = list()
+ var/list/subs = list()
+ var/cur_subcategory = CAT_NONE
var/cur_category = categories[viewing_category]
+ if(islist(subcategories[viewing_category]))
+ subs = subcategories[viewing_category]
+ cur_subcategory = subs[viewing_subcategory]
data["busy"] = busy
data["prev_cat"] = categories[prev_cat()]
+ data["prev_subcat"] = subs[prev_subcat()]
data["category"] = cur_category
+ data["subcategory"] = cur_subcategory
data["next_cat"] = categories[next_cat()]
+ data["next_subcat"] = subs[next_subcat()]
data["display_craftable_only"] = display_craftable_only
data["display_compact"] = display_compact
@@ -254,7 +289,11 @@
var/list/cant_craft = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
- if(R.category != cur_category)
+
+ if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
+ continue
+
+ if((R.category != cur_category) || (R.subcategory != cur_subcategory))
continue
if(check_contents(R, surroundings))
can_craft += list(build_recipe_data(R))
@@ -269,41 +308,54 @@
return
if(href_list["make"])
- var/datum/crafting_recipe/TR = locate(href_list["make"])
- busy = 1
+ var/datum/crafting_recipe/TR = locate(href_list["make"]) in GLOB.crafting_recipes
+ busy = TRUE
SSnanoui.update_uis(src)
var/fail_msg = construct_item(usr, TR)
if(!fail_msg)
to_chat(usr, "[TR.name] constructed.")
else
to_chat(usr, "Construction failed[fail_msg]")
- busy = 0
+ busy = FALSE
SSnanoui.update_uis(src)
if(href_list["forwardCat"])
- viewing_category = next_cat()
- to_chat(usr, "Category is now [categories[viewing_category]].")
+ viewing_category = next_cat(FALSE)
. = TRUE
if(href_list["backwardCat"])
- viewing_category = prev_cat()
- to_chat(usr, "Category is now [categories[viewing_category]].")
+ viewing_category = prev_cat(FALSE)
+ . = TRUE
+ if(href_list["forwardSubCat"])
+ viewing_subcategory = next_subcat()
+ . = TRUE
+ if(href_list["backwardSubCat"])
+ viewing_subcategory = prev_subcat()
. = TRUE
if(href_list["toggle_recipes"])
display_craftable_only = !display_craftable_only
- to_chat(usr, "You will now [display_craftable_only ? "only see recipes you can craft":"see all recipes"].")
. = TRUE
if(href_list["toggle_compact"])
display_compact = !display_compact
- to_chat(usr, "Crafting menu is now [display_compact? "compact" : "full size"].")
. = TRUE
SSnanoui.update_uis(src)
//Next works nicely with modular arithmetic
-/datum/personal_crafting/proc/next_cat()
+//Next works nicely with modular arithmetic
+/datum/personal_crafting/proc/next_cat(readonly = TRUE)
+ if (!readonly)
+ viewing_subcategory = 1
. = viewing_category % categories.len + 1
+/datum/personal_crafting/proc/next_subcat()
+ if(islist(subcategories[viewing_category]))
+ var/list/subs = subcategories[viewing_category]
+ . = viewing_subcategory % subs.len + 1
+
+
//Previous can go fuck itself
-/datum/personal_crafting/proc/prev_cat()
+/datum/personal_crafting/proc/prev_cat(readonly = TRUE)
+ if (!readonly)
+ viewing_subcategory = 1
if(viewing_category == categories.len)
. = viewing_category-1
else
@@ -311,6 +363,18 @@
if(. <= 0)
. = categories.len
+/datum/personal_crafting/proc/prev_subcat()
+ if(islist(subcategories[viewing_category]))
+ var/list/subs = subcategories[viewing_category]
+ if(viewing_subcategory == subs.len)
+ . = viewing_subcategory-1
+ else
+ . = viewing_subcategory % subs.len - 1
+ if(. <= 0)
+ . = subs.len
+ else
+ . = null
+
/datum/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
var/list/data = list()
data["name"] = R.name
@@ -334,9 +398,19 @@
data["catalyst_text"] = catalyst_text
for(var/a in R.tools)
- var/atom/A = a //cheat-typecast
- tool_text += " [R.tools[A]] [initial(A.name)],"
+ if(ispath(a, /obj/item))
+ var/obj/item/b = a
+ tool_text += " [initial(b.name)],"
+ else
+ tool_text += " [a],"
tool_text = replacetext(tool_text, ",", "", -1)
data["tool_text"] = tool_text
- return data
\ No newline at end of file
+ return data
+
+//Mind helpers
+
+/datum/mind/proc/teach_crafting_recipe(R)
+ if(!learned_recipes)
+ learned_recipes = list()
+ learned_recipes |= R
\ No newline at end of file
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 58338efea61..126e9f30b31 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -1,19 +1,15 @@
/datum/crafting_recipe
var/name = "" //in-game display name
var/reqs[] = list() //type paths of items consumed associated with how many are needed
+ var/blacklist[] = list() //type paths of items explicitly not allowed as an ingredient
var/result //type path of item resulting from this craft
var/tools[] = list() //type paths of items needed but not consumed
var/time = 30 //time in deciseconds
var/parts[] = list() //type paths of items that will be placed in the result
var/chem_catalysts[] = list() //like tools but for reagents
- var/category = CAT_NONE // Recipe category
- var/roundstart_enabled = TRUE //Set to FALSE if you don't want a particular crafting recipe to be available all the time
-
-/datum/crafting_recipe/proc/AdjustChems(var/obj/resultobj as obj)
- //This proc is to replace the make_food proc of recipes from microwaves and such that are being converted to table crafting recipes.
- //Use it to handle the removal of reagents after the food has been created (like removing toxins from a salad made with ambrosia)
- //If a recipe does not require it's chems adjusted, don't bother declaring this for the recipe, as it will call this placeholder
- return
+ var/category = CAT_NONE //where it shows up in the crafting UI
+ var/subcategory = CAT_NONE
+ var/always_availible = TRUE //Set to FALSE if it needs to be learned first.
/datum/crafting_recipe/IED
name = "IED"
@@ -24,7 +20,8 @@
/obj/item/reagent_containers/food/drinks/cans = 1)
parts = list(/obj/item/reagent_containers/food/drinks/cans = 1)
time = 15
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/molotov
name = "Molotov"
@@ -33,7 +30,8 @@
/obj/item/reagent_containers/food/drinks/bottle = 1)
parts = list(/obj/item/reagent_containers/food/drinks/bottle = 1)
time = 40
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/stunprod
name = "Stunprod"
@@ -42,7 +40,8 @@
/obj/item/stack/rods = 1,
/obj/item/assembly/igniter = 1)
time = 40
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/bola
name = "Bola"
@@ -50,7 +49,8 @@
reqs = list(/obj/item/restraints/handcuffs/cable = 1,
/obj/item/stack/sheet/metal = 6)
time = 20//15 faster than crafting them by hand!
- category= CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/ed209
name = "ED209"
@@ -144,7 +144,8 @@
/obj/item/weldingtool = 1)
tools = list(/obj/item/screwdriver)
time = 10
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/meteorshot
name = "Meteorshot Shell"
@@ -154,7 +155,8 @@
/obj/item/stock_parts/manipulator = 2)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/pulseslug
name = "Pulse Slug Shell"
@@ -164,7 +166,8 @@
/obj/item/stock_parts/micro_laser/ultra = 1)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/dragonsbreath
name = "Dragonsbreath Shell"
@@ -173,7 +176,8 @@
/datum/reagent/phosphorus = 5,)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/frag12
name = "FRAG-12 Shell"
@@ -184,7 +188,8 @@
/datum/reagent/facid = 5,)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/ionslug
name = "Ion Scatter Shell"
@@ -194,7 +199,8 @@
/obj/item/stock_parts/subspace/crystal = 1)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/improvisedslug
name = "Improvised Shotgun Shell"
@@ -205,7 +211,8 @@
/datum/reagent/fuel = 10)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/improvisedslugoverload
name = "Overload Improvised Shell"
@@ -215,7 +222,8 @@
/datum/reagent/plasma_dust = 20)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/laserslug
name = "Laser Slug Shell"
@@ -225,7 +233,8 @@
/obj/item/stock_parts/micro_laser/high = 1)
tools = list(/obj/item/screwdriver)
time = 5
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/ishotgun
name = "Improvised Shotgun"
@@ -236,7 +245,8 @@
/obj/item/stack/packageWrap = 5,)
tools = list(/obj/item/screwdriver)
time = 100
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/chainsaw
name = "Chainsaw"
@@ -246,7 +256,8 @@
/obj/item/stack/sheet/plasteel = 1)
tools = list(/obj/item/weldingtool)
time = 50
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/spear
name = "Spear"
@@ -255,7 +266,8 @@
/obj/item/shard = 1,
/obj/item/stack/rods = 1)
time = 40
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/spooky_camera
name = "Camera Obscura"
@@ -296,7 +308,8 @@
reqs = list(/obj/item/stack/sheet/wood = 1,
/obj/item/stack/cable_coil = 5)
tools = list(/obj/item/kitchen/knife) // Gotta carve the wood into handles
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/makeshift_bolt
name = "Makeshift Bolt"
@@ -304,7 +317,8 @@
time = 5
reqs = list(/obj/item/stack/rods = 1)
tools = list(/obj/item/weldingtool)
- category = CAT_AMMO
+ category = CAT_WEAPONRY
+ subcategory = CAT_AMMO
/datum/crafting_recipe/crossbow
name = "Powered Crossbow"
@@ -316,7 +330,8 @@
/obj/item/stack/sheet/wood = 5)
tools = list(/obj/item/weldingtool,
/obj/item/screwdriver)
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/glove_balloon
name = "Latex Glove Balloon"
@@ -361,7 +376,8 @@
)
parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
time = 30
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/chemical_payload2
name = "Chemical Payload (gibtonite)"
@@ -373,7 +389,8 @@
)
parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2)
time = 50
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/toxins_payload
name = "Toxins Payload Casing"
@@ -383,7 +400,8 @@
/obj/item/assembly/signaler = 1,
/obj/item/stack/sheet/metal = 2
)
- category = CAT_WEAPON
+ category = CAT_WEAPONRY
+ subcategory = CAT_WEAPON
/datum/crafting_recipe/bonearmor
name = "Bone Armor"
@@ -552,4 +570,4 @@
/obj/item/grown/log = 2)
time = 50
category = CAT_MISC
- roundstart_enabled = FALSE
+ always_availible = FALSE
diff --git a/code/modules/crafting/tailoring.dm b/code/modules/crafting/tailoring.dm
new file mode 100644
index 00000000000..a46e509001c
--- /dev/null
+++ b/code/modules/crafting/tailoring.dm
@@ -0,0 +1,145 @@
+/datum/crafting_recipe/durathread_vest
+ name = "Durathread Vest"
+ result = /obj/item/clothing/suit/armor/vest/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 5,
+ /obj/item/stack/sheet/leather = 4)
+ time = 50
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/durathread_helmet
+ name = "Durathread Helmet"
+ result = /obj/item/clothing/head/helmet/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 4,
+ /obj/item/stack/sheet/leather = 5)
+ time = 40
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/durathread_jumpsuit
+ name = "Durathread Jumpsuit"
+ result = /obj/item/clothing/under/misc/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 4)
+ time = 40
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/durathread_beret
+ name = "Durathread Beret"
+ result = /obj/item/clothing/head/beret/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 2)
+ time = 40
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/durathread_beanie
+ name = "Durathread Beanie"
+ result = /obj/item/clothing/head/beanie/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 2)
+ time = 40
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/durathread_bandana
+ name = "Durathread Bandana"
+ result = /obj/item/clothing/mask/bandana/durathread
+ reqs = list(/obj/item/stack/sheet/durathread = 1)
+ time = 25
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/fannypack
+ name = "Fannypack"
+ result = /obj/item/storage/belt/fannypack
+ reqs = list(/obj/item/stack/sheet/cloth = 2,
+ /obj/item/stack/sheet/leather = 1)
+ time = 20
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsunsec
+ name = "Security HUDsunglasses"
+ result = /obj/item/clothing/glasses/hud/security/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/security = 1,
+ /obj/item/clothing/glasses/sunglasses = 1,
+ /obj/item/stack/cable_coil = 5)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsunsecremoval
+ name = "Security HUD removal"
+ result = /obj/item/clothing/glasses/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/security/sunglasses = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsunmed
+ name = "Medical HUDsunglasses"
+ result = /obj/item/clothing/glasses/hud/health/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/health = 1,
+ /obj/item/clothing/glasses/sunglasses = 1,
+ /obj/item/stack/cable_coil = 5)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsunmedremoval
+ name = "Medical HUD removal"
+ result = /obj/item/clothing/glasses/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/health/sunglasses = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsundiag
+ name = "Diagnostic HUDsunglasses"
+ result = /obj/item/clothing/glasses/hud/diagnostic/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/diagnostic = 1,
+ /obj/item/clothing/glasses/sunglasses = 1,
+ /obj/item/stack/cable_coil = 5)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/hudsundiagremoval
+ name = "Diagnostic HUD removal"
+ result = /obj/item/clothing/glasses/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/hud/diagnostic/sunglasses = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/beergoggles
+ name = "Beer Goggles"
+ result = /obj/item/clothing/glasses/sunglasses/reagent
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/science = 1,
+ /obj/item/clothing/glasses/sunglasses = 1,
+ /obj/item/stack/cable_coil = 5)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/beergogglesremoval
+ name = "Beer Goggles removal"
+ result = /obj/item/clothing/glasses/sunglasses
+ time = 20
+ tools = list(/obj/item/screwdriver, /obj/item/wirecutters)
+ reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/ghostsheet
+ name = "Ghost Sheet"
+ result = /obj/item/clothing/suit/ghost_sheet
+ time = 5
+ tools = list(/obj/item/wirecutters)
+ reqs = list(/obj/item/bedsheet = 1)
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/cowboyboots
+ name = "Cowboy Boots"
+ result = /obj/item/clothing/shoes/cowboy
+ reqs = list(/obj/item/stack/sheet/leather = 2)
+ time = 45
+ category = CAT_CLOTHING
+
+/datum/crafting_recipe/lizardboots
+ name = "Lizard Skin Boots"
+ result = /obj/effect/spawner/lootdrop/lizardboots
+ reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1, /obj/item/stack/sheet/leather = 1)
+ time = 60
+ category = CAT_CLOTHING
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index b7f395afce0..c1acd1e3d38 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -178,7 +178,7 @@
icon = 'icons/obj/custom_items.dmi'
icon_state = "book_berner_1"
-/obj/item/clothing/glasses/sunglasses/fake/fluff/kaki //Rapidvalj: Kakicharakiti
+/obj/item/clothing/glasses/sunglasses_fake/fluff/kaki //Rapidvalj: Kakicharakiti
name = "broken thermonocle"
desc = "A weathered Vox thermonocle, doesn't seem to work anymore."
icon_state = "thermoncle"
@@ -903,9 +903,9 @@
desc = "A green hoodie with the Nanotrasen logo on the back. It looks weathered."
icon = 'icons/obj/custom_items.dmi'
icon_state = "linda_hoodie"
- hoodtype = /obj/item/clothing/head/hood/fluff/linda
+ hoodtype = /obj/item/clothing/head/hooded/hood/fluff/linda
-/obj/item/clothing/head/hood/fluff/linda //Epic_Charger: Linda Clark
+/obj/item/clothing/head/hooded/hood/fluff/linda //Epic_Charger: Linda Clark
icon_state = "greenhood"
/obj/item/clothing/suit/hooded/hoodie/hylo //Hylocereus: Sam Aria
@@ -913,9 +913,9 @@
desc = "A soft, cozy longline hoodie. It looks old and worn, but well cared for. There's no label, but a series of dates and names is penned on a scrap of fabric sewn on the inside of the left side of the chest - 'Sam Aria' is scrawled atop them all, next to the words 'Please Remember'."
icon = 'icons/obj/custom_items.dmi'
icon_state = "sam_hoodie"
- hoodtype = /obj/item/clothing/head/hood/hylo
+ hoodtype = /obj/item/clothing/head/hooded/hood/hylo
-/obj/item/clothing/head/hood/hylo
+/obj/item/clothing/head/hooded/hood/hylo
icon = 'icons/obj/custom_items.dmi'
icon_state = "sam_hood"
@@ -925,9 +925,9 @@
body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
icon = 'icons/obj/custom_items.dmi'
icon_state = "skeleton_suit"
- hoodtype = /obj/item/clothing/head/hood/fluff/skeleton
+ hoodtype = /obj/item/clothing/head/hooded/hood/fluff/skeleton
-/obj/item/clothing/head/hood/fluff/skeleton
+/obj/item/clothing/head/hooded/hood/fluff/skeleton
icon = 'icons/obj/custom_items.dmi'
icon_state = "skeleton_hood"
@@ -973,18 +973,18 @@
desc = "A velvety smooth black winter coat with white and red stripes on the side."
icon = 'icons/obj/custom_items.dmi'
icon_state = "xantholne_wintercoat"
- hoodtype = /obj/item/clothing/head/hood/fluff/xantholne
+ hoodtype = /obj/item/clothing/head/hooded/hood/fluff/xantholne
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
-/obj/item/clothing/head/hood/fluff/xantholne // Xantholne: Meex Zwichsnicrur
+/obj/item/clothing/head/hooded/hood/fluff/xantholne // Xantholne: Meex Zwichsnicrur
name = "black winter hood"
desc = "A black hood attached to a stripped winter coat."
icon = 'icons/obj/custom_items.dmi'
icon_state = "xantholne_winterhood"
body_parts_covered = HEAD
- flags = NODROP|BLOCKHAIR
+ flags = BLOCKHAIR
flags_inv = HIDEEARS
/obj/item/clothing/suit/hooded/hoodie/fluff/xydonus //Xydonus: Rsik Ugsharki Atan | Based off of the bomber jacket, but with a hood slapped on (for allowed suit storage)
@@ -993,18 +993,18 @@
icon = 'icons/obj/custom_items.dmi'
icon_state = "xydonus_jacket"
ignore_suitadjust = 0
- hoodtype = /obj/item/clothing/head/hood/fluff/xydonus
+ hoodtype = /obj/item/clothing/head/hooded/hood/fluff/xydonus
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency_oxygen,/obj/item/toy,/obj/item/storage/fancy/cigarettes,/obj/item/lighter)
-/obj/item/clothing/head/hood/fluff/xydonus
+/obj/item/clothing/head/hooded/hood/fluff/xydonus
name = "custom fit hood"
desc = "A hood with some horns glued to them, or something like that. Custom fit for a Unathi's head shape."
icon = 'icons/obj/custom_items.dmi'
icon_state = "xydonus_bomberhood"
body_parts_covered = HEAD
- flags = NODROP|BLOCKHAIR
+ flags = BLOCKHAIR
flags_inv = HIDEEARS
/obj/item/clothing/suit/fluff/pineapple //Pineapple Salad: Dan Jello
@@ -1039,17 +1039,17 @@
icon = 'icons/obj/custom_items.dmi'
icon_state = "shesicoat"
item_state = "shesicoat"
- hoodtype = /obj/item/clothing/head/hood/fluff/shesi
+ hoodtype = /obj/item/clothing/head/hooded/hood/fluff/shesi
body_parts_covered = UPPER_TORSO|LOWER_TORSO
cold_protection = UPPER_TORSO|LOWER_TORSO
-/obj/item/clothing/head/hood/fluff/shesi //MrSynnester : Shesi Skaklas
+/obj/item/clothing/head/hooded/hood/fluff/shesi //MrSynnester : Shesi Skaklas
name = "custom made winter hood"
desc = "A custom made winter coat hood. Looks comfy."
icon = 'icons/obj/custom_items.dmi'
icon_state = "shesicoat_hood2"
body_parts_covered = HEAD
- flags = NODROP|BLOCKHAIR
+ flags = BLOCKHAIR
flags_inv = HIDEEARS
/obj/item/clothing/suit/jacket/dtx //AffectedArc07: DTX
@@ -1212,16 +1212,16 @@
//////////// Sets ////////////
// Fox P McCloud: Fox McCloud
-/obj/item/clothing/suit/jacket/fluff/fox
+/obj/item/clothing/suit/storage/fox
name = "Aeronautics Jacket"
desc = "An aviator styled jacket made from a peculiar material; this one seems very old."
icon = 'icons/obj/custom_items.dmi'
icon_state = "fox_jacket"
item_state = "fox_jacket"
- ignore_suitadjust = TRUE
- actions_types = list()
- adjust_flavour = null
- sprite_sheets = null
+ allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/projectile/automatic/pistol, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/revolver/detective)
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
/obj/item/clothing/under/fluff/fox
name = "Aeronautics Jumpsuit"
@@ -1232,6 +1232,12 @@
item_color = "fox_suit"
displays_id = FALSE //still appears on examine; this is pure fluff.
+/obj/item/clothing/suit/storage/fox/miljacket_desert
+ name = "rugged military jacket"
+ desc = "A rugged brown military jacket with a stylized 'A' embroidered on the back. It seems very old, yet is in near mint condition. Has a tag on the inside collar signed 'Fox McCloud'."
+ icon_state = "fox_coat"
+ item_color = "fox_coat"
+
/obj/item/toy/plushie/fluff/fox
name = "orange fox plushie"
desc = "A cute, soft, fuzzy, fluffy, and cuddly plushie. This has a small tag on it that is signed 'Fox McCloud'."
@@ -1262,12 +1268,6 @@
/obj/item/toy/plushie/fluff/fox/ui_action_click()
change_color()
-/obj/item/clothing/suit/jacket/miljacket/desert/fox
- name = "rugged military jacket"
- desc = "A rugged brown military jacket with a stylized 'A' embroidered on the back. It seems very old, yet is in near mint condition. Has a tag on the inside collar signed 'Fox McCloud'."
- icon = 'icons/obj/custom_items.dmi'
- icon_state = "fox_coat"
- item_color = "fox_coat"
// TheFlagbearer: Willow Walker
/obj/item/clothing/under/fluff/arachno_suit
diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm
index 595eace858e..e0dd80a1e6e 100644
--- a/code/modules/economy/ATM.dm
+++ b/code/modules/economy/ATM.dm
@@ -240,9 +240,7 @@ log transactions
if(amount > 10000) // prevent crashes
to_chat(usr, "The ATM's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'")
amount = 10000
- authenticated_account.money -= amount
withdraw_arbitrary_sum(amount)
-
authenticated_account.charge(amount, null, "Credit withdrawal", machine_id, authenticated_account.owner_name)
else
to_chat(usr, "[bicon(src)]You don't have enough funds to do that!")
diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm
index 67881662db5..8467c709f5e 100644
--- a/code/modules/events/grid_check.dm
+++ b/code/modules/events/grid_check.dm
@@ -1,6 +1,6 @@
/datum/event/grid_check //NOTE: Times are measured in master controller ticks!
announceWhen = 5
-
+
/datum/event/grid_check/setup()
endWhen = rand(30,120)
@@ -12,7 +12,7 @@
if(!M.client || !is_station_level(T.z))
continue
SEND_SOUND(M, S)
-
+
/datum/event/grid_check/announce()
event_announcement.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.", "Automated Grid Check", new_sound = 'sound/AI/poweroff.ogg')
@@ -45,11 +45,6 @@
continue
if(C.cell)
C.cell.charge = 0
- for(var/obj/machinery/power/P in GLOB.machines)
- var/area/current_area = get_area(P)
- if((current_area.type in skipped_areas_apc) || (current_area.type in skipped_areas) || !is_station_level(P.z))
- continue
- P.malfunction = TRUE
/proc/power_restore(var/announce = 1)
var/list/skipped_areas = list(/area/turret_protected/ai)
@@ -72,8 +67,6 @@
S.input_attempt = S.last_input_attempt
S.update_icon()
S.power_change()
- for(var/obj/machinery/power/P in GLOB.machines)
- P.malfunction = FALSE
/proc/power_restore_quick(var/announce = 1)
if(announce)
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index 9199d8ca3bd..a7f9feb1c16 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -137,7 +137,7 @@
if(prob(50))
ChangeTurf(baseturf)
-/turf/simulated/floor/vines/ChangeTurf(turf/open/floor/T)
+/turf/simulated/floor/vines/ChangeTurf(turf/simulated/floor/T)
. = ..()
//Do this *after* the turf has changed as qdel in spacevines will call changeturf again if it hasn't
for(var/obj/structure/spacevine/SV in src)
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index e931db813cf..6293e72e689 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -12,7 +12,7 @@
var/apply_method = "swallow"
var/transfer_efficiency = 1.0
var/instant_application = 0 //if we want to bypass the forcedfeed delay
- var/taste = TRUE//whether you can taste eating from this
+ var/can_taste = TRUE//whether you can taste eating from this
var/antable = TRUE // Will ants come near it?
var/ant_location = null
var/ant_timer = null
diff --git a/code/modules/food_and_drinks/food/customizables.dm b/code/modules/food_and_drinks/food/customizables.dm
index b0ac9d20d6c..bebef085297 100644
--- a/code/modules/food_and_drinks/food/customizables.dm
+++ b/code/modules/food_and_drinks/food/customizables.dm
@@ -89,6 +89,7 @@
basename = "personal pizza"
snack_overlays = 0
top = 0
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/customizable/pasta
name = "spaghetti"
@@ -107,6 +108,7 @@
basename = "bread"
snack_overlays = 0
top = 0
+ tastes = list("bread" = 10)
/obj/item/reagent_containers/food/snacks/customizable/cook/pie
name = "pie"
@@ -116,6 +118,7 @@
basename = "pie"
snack_overlays = 0
top = 0
+ tastes = list("pie" = 1)
/obj/item/reagent_containers/food/snacks/customizable/cook/cake
name = "cake"
@@ -125,6 +128,7 @@
basename = "cake"
snack_overlays = 0
top = 0
+ tastes = list("cake" = 1)
/obj/item/reagent_containers/food/snacks/customizable/cook/jelly
name = "jelly"
@@ -152,6 +156,7 @@
basename = "kebab"
snack_overlays = 0
top = 0
+ tastes = list("meat" = 3, "metal" = 1)
/obj/item/reagent_containers/food/snacks/customizable/cook/salad
name = "salad"
@@ -161,6 +166,7 @@
basename = "salad"
snack_overlays = 0
top = 0
+ tastes = list("leaves" = 1)
/obj/item/reagent_containers/food/snacks/customizable/cook/waffles
name = "waffles"
@@ -170,6 +176,7 @@
basename = "waffles"
snack_overlays = 0
top = 0
+ tastes = list("waffles" = 1)
/obj/item/reagent_containers/food/snacks/customizable/candy/cookie
name = "cookie"
@@ -179,6 +186,7 @@
basename = "cookie"
snack_overlays = 0
top = 0
+ tastes = list("cookie" = 1)
/obj/item/reagent_containers/food/snacks/customizable/candy/cotton
name = "flavored cotton candy"
@@ -308,6 +316,7 @@
snack_overlays = 0
trash = /obj/item/trash/bowl
top = 0
+ tastes = list("soup" = 1)
/obj/item/reagent_containers/food/snacks/customizable/burger
name = "burger bun"
@@ -316,6 +325,7 @@
baseicon = "burgercustom"
basename = "burger"
toptype = new /obj/item/reagent_containers/food/snacks/bun()
+ tastes = list("bun" = 4)
/obj/item/reagent_containers/food/snacks/customizable/attackby(obj/item/I, mob/user, params)
if(contents.len > sandwich_limit)
diff --git a/code/modules/food_and_drinks/food/foods/baked_goods.dm b/code/modules/food_and_drinks/food/foods/baked_goods.dm
index 0746f37d113..57fd36393b5 100644
--- a/code/modules/food_and_drinks/food/foods/baked_goods.dm
+++ b/code/modules/food_and_drinks/food/foods/baked_goods.dm
@@ -12,6 +12,7 @@
bitesize = 3
filling_color = "#FFD675"
list_reagents = list("nutriment" = 20, "oculine" = 10, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "carrot" = 1)
/obj/item/reagent_containers/food/snacks/carrotcakeslice
name = "carrot cake slice"
@@ -19,6 +20,8 @@
icon_state = "carrotcake_slice"
trash = /obj/item/trash/plate
filling_color = "#FFD675"
+ tastes = list("cake" = 5, "sweetness" = 2, "carrot" = 1)
+
/obj/item/reagent_containers/food/snacks/sliceable/braincake
name = "brain cake"
@@ -29,6 +32,7 @@
filling_color = "#E6AEDB"
bitesize = 3
list_reagents = list("protein" = 10, "nutriment" = 10, "mannitol" = 10, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "brains" = 1)
/obj/item/reagent_containers/food/snacks/braincakeslice
name = "brain cake slice"
@@ -36,6 +40,7 @@
icon_state = "braincakeslice"
trash = /obj/item/trash/plate
filling_color = "#E6AEDB"
+ tastes = list("cake" = 5, "sweetness" = 2, "brains" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/cheesecake
name = "cheese cake"
@@ -46,6 +51,7 @@
filling_color = "#FAF7AF"
bitesize = 3
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 4, "cream cheese" = 3)
/obj/item/reagent_containers/food/snacks/cheesecakeslice
name = "cheese cake slice"
@@ -53,6 +59,7 @@
icon_state = "cheesecake_slice"
trash = /obj/item/trash/plate
filling_color = "#FAF7AF"
+ tastes = list("cake" = 4, "cream cheese" = 3)
/obj/item/reagent_containers/food/snacks/sliceable/plaincake
name = "vanilla cake"
@@ -63,6 +70,7 @@
bitesize = 3
filling_color = "#F7EDD5"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "vanilla" = 1, "sweetness" = 2)
/obj/item/reagent_containers/food/snacks/plaincakeslice
name = "vanilla cake slice"
@@ -70,6 +78,7 @@
icon_state = "plaincake_slice"
trash = /obj/item/trash/plate
filling_color = "#F7EDD5"
+ tastes = list("cake" = 5, "vanilla" = 1, "sweetness" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/orangecake
name = "orange cake"
@@ -80,6 +89,7 @@
bitesize = 3
filling_color = "#FADA8E"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "oranges" = 2)
/obj/item/reagent_containers/food/snacks/orangecakeslice
name = "orange cake slice"
@@ -87,6 +97,7 @@
icon_state = "orangecake_slice"
trash = /obj/item/trash/plate
filling_color = "#FADA8E"
+ tastes = list("cake" = 5, "sweetness" = 2, "oranges" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/bananacake
name = "banana cake"
@@ -97,6 +108,7 @@
bitesize = 3
filling_color = "#FADA8E"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "banana" = 2)
/obj/item/reagent_containers/food/snacks/bananacakeslice
name = "banana cake slice"
@@ -104,6 +116,7 @@
icon_state = "bananacake_slice"
trash = /obj/item/trash/plate
filling_color = "#FADA8E"
+ tastes = list("cake" = 5, "sweetness" = 2, "banana" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/limecake
name = "lime cake"
@@ -114,6 +127,7 @@
slices_num = 5
filling_color = "#CBFA8E"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2)
/obj/item/reagent_containers/food/snacks/limecakeslice
name = "lime cake slice"
@@ -121,6 +135,7 @@
icon_state = "limecake_slice"
trash = /obj/item/trash/plate
filling_color = "#CBFA8E"
+ tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/lemoncake
name = "lemon cake"
@@ -131,6 +146,7 @@
bitesize = 3
filling_color = "#FAFA8E"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 2, "sourness" = 2)
/obj/item/reagent_containers/food/snacks/lemoncakeslice
name = "lemon cake slice"
@@ -138,6 +154,7 @@
icon_state = "lemoncake_slice"
trash = /obj/item/trash/plate
filling_color = "#FAFA8E"
+ tastes = list("cake" = 5, "sweetness" = 2, "sourness" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/chocolatecake
name = "chocolate cake"
@@ -148,6 +165,7 @@
bitesize = 3
filling_color = "#805930"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 1, "chocolate" = 4)
/obj/item/reagent_containers/food/snacks/chocolatecakeslice
name = "chocolate cake slice"
@@ -155,6 +173,7 @@
icon_state = "chocolatecake_slice"
trash = /obj/item/trash/plate
filling_color = "#805930"
+ tastes = list("cake" = 5, "sweetness" = 1, "chocolate" = 4)
/obj/item/reagent_containers/food/snacks/sliceable/birthdaycake
name = "birthday cake"
@@ -165,6 +184,7 @@
filling_color = "#FFD6D6"
bitesize = 3
list_reagents = list("nutriment" = 20, "sprinkles" = 10, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 1)
/obj/item/reagent_containers/food/snacks/birthdaycakeslice
name = "birthday cake slice"
@@ -172,6 +192,7 @@
icon_state = "birthdaycakeslice"
trash = /obj/item/trash/plate
filling_color = "#FFD6D6"
+ tastes = list("cake" = 5, "sweetness" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/applecake
name = "apple cake"
@@ -182,6 +203,7 @@
bitesize = 3
filling_color = "#EBF5B8"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("cake" = 5, "sweetness" = 1, "apple" = 1)
/obj/item/reagent_containers/food/snacks/applecakeslice
name = "apple cake slice"
@@ -189,6 +211,7 @@
icon_state = "applecakeslice"
trash = /obj/item/trash/plate
filling_color = "#EBF5B8"
+ tastes = list("cake" = 5, "sweetness" = 1, "apple" = 1)
//////////////////////
@@ -202,6 +225,7 @@
bitesize = 1
filling_color = "#DBC94F"
list_reagents = list("nutriment" = 1, "sugar" = 3, "hot_coco" = 5 )
+ tastes = list("cookie" = 1, "crunchy chocolate" = 1)
/obj/item/reagent_containers/food/snacks/fortunecookie
name = "fortune cookie"
@@ -210,12 +234,14 @@
filling_color = "#E8E79E"
list_reagents = list("nutriment" = 3)
trash = /obj/item/paper/fortune
+ tastes = list("cookie" = 1)
/obj/item/reagent_containers/food/snacks/sugarcookie
name = "sugar cookie"
desc = "Just like your little sister used to make."
icon_state = "sugarcookie"
list_reagents = list("nutriment" = 1, "sugar" = 3)
+ tastes = list("sweetness" = 1)
//////////////////////
@@ -230,6 +256,7 @@
filling_color = "#FBFFB8"
bitesize = 3
list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2)
+ tastes = list("pie" = 1)
/obj/item/reagent_containers/food/snacks/pie/throw_impact(atom/hit_atom)
..()
@@ -245,6 +272,7 @@
filling_color = "#948051"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "meat" = 1)
/obj/item/reagent_containers/food/snacks/tofupie
name = "tofu-pie"
@@ -254,6 +282,7 @@
filling_color = "#FFFEE0"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "tofu" = 1)
/obj/item/reagent_containers/food/snacks/amanita_pie
name = "amanita pie"
@@ -262,6 +291,7 @@
filling_color = "#FFCCCC"
bitesize = 4
list_reagents = list("nutriment" = 6, "amanitin" = 3, "psilocybin" = 1, "vitamin" = 4)
+ tastes = list("pie" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/plump_pie
name = "plump pie"
@@ -270,6 +300,7 @@
filling_color = "#B8279B"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/plump_pie/New()
..()
@@ -285,6 +316,8 @@
trash = /obj/item/trash/plate
filling_color = "#43DE18"
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "meat" = 1, "acid" = 1)
+
/obj/item/reagent_containers/food/snacks/applepie
name = "apple pie"
@@ -293,6 +326,8 @@
filling_color = "#E0EDC5"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "apple" = 1)
+
/obj/item/reagent_containers/food/snacks/cherrypie
name = "cherry pie"
@@ -301,6 +336,7 @@
filling_color = "#FF525A"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("pie" = 1, "cherries" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pumpkinpie
name = "pumpkin pie"
@@ -311,6 +347,7 @@
bitesize = 3
filling_color = "#F5B951"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("pie" = 1, "pumpkin" = 1)
/obj/item/reagent_containers/food/snacks/pumpkinpieslice
name = "pumpkin pie slice"
@@ -318,7 +355,7 @@
icon_state = "pumpkinpieslice"
trash = /obj/item/trash/plate
filling_color = "#F5B951"
-
+ tastes = list("pie" = 1, "pumpkin" = 1)
//////////////////////
// Donuts //
@@ -333,6 +370,7 @@
var/extra_reagent = null
filling_color = "#D2691E"
var/randomized_sprinkles = 1
+ tastes = list("donut" = 1)
/obj/item/reagent_containers/food/snacks/donut/New()
..()
@@ -353,6 +391,7 @@
name = "chaos donut"
desc = "Like life, it never quite tastes the same."
bitesize = 10
+ tastes = list("donut" = 3, "chaos" = 1)
/obj/item/reagent_containers/food/snacks/donut/chaos/New()
..()
@@ -369,6 +408,7 @@
desc = "You jelly?"
icon_state = "jdonut1"
extra_reagent = "berryjuice"
+ tastes = list("jelly" = 1, "donut" = 3)
/obj/item/reagent_containers/food/snacks/donut/jelly/New()
..()
@@ -403,6 +443,7 @@
icon_state = "muffin"
filling_color = "#E0CF9B"
list_reagents = list("nutriment" = 6)
+ tastes = list("muffin" = 1)
/obj/item/reagent_containers/food/snacks/berryclafoutis
name = "berry clafoutis"
@@ -411,6 +452,8 @@
trash = /obj/item/trash/plate
bitesize = 3
list_reagents = list("nutriment" = 10, "berryjuice" = 5, "vitamin" = 2)
+ tastes = list("pie" = 1, "blackberries" = 1)
+
/obj/item/reagent_containers/food/snacks/poppypretzel
name = "poppy pretzel"
@@ -418,6 +461,7 @@
icon_state = "poppypretzel"
filling_color = "#916E36"
list_reagents = list("nutriment" = 5)
+ tastes = list("pretzel" = 1)
/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit
name = "plump helmet biscuit"
@@ -425,6 +469,7 @@
icon_state = "phelmbiscuit"
filling_color = "#CFB4C4"
list_reagents = list("nutriment" = 5)
+ tastes = list("mushroom" = 1, "biscuit" = 1)
/obj/item/reagent_containers/food/snacks/plumphelmetbiscuit/New()
..()
@@ -441,6 +486,8 @@
filling_color = "#FFFF00"
bitesize = 3
list_reagents = list("nutriment" = 8, "gold" = 5, "vitamin" = 4)
+ tastes = list("pie" = 1, "apple" = 1, "expensive metal" = 1)
+
/obj/item/reagent_containers/food/snacks/cracker
name = "cracker"
@@ -449,3 +496,4 @@
bitesize = 1
filling_color = "#F5DEB8"
list_reagents = list("nutriment" = 1)
+ tastes = list("cracker" = 1)
diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm
index c841f8d65fa..d888a532c01 100644
--- a/code/modules/food_and_drinks/food/foods/bread.dm
+++ b/code/modules/food_and_drinks/food/foods/bread.dm
@@ -11,6 +11,7 @@
slices_num = 5
filling_color = "#FF7575"
list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5)
+ tastes = list("bread" = 10, "meat" = 10)
/obj/item/reagent_containers/food/snacks/meatbreadslice
name = "meatbread slice"
@@ -27,6 +28,7 @@
slices_num = 5
filling_color = "#8AFF75"
list_reagents = list("protein" = 20, "nutriment" = 10, "vitamin" = 5)
+ tastes = list("bread" = 10, "acid" = 10)
/obj/item/reagent_containers/food/snacks/xenomeatbreadslice
name = "xenomeatbread slice"
@@ -42,6 +44,7 @@
slice_path = /obj/item/reagent_containers/food/snacks/spidermeatbreadslice
slices_num = 5
list_reagents = list("protein" = 20, "nutriment" = 10, "toxin" = 15, "vitamin" = 5)
+ tastes = list("bread" = 10, "cobwebs" = 5)
/obj/item/reagent_containers/food/snacks/spidermeatbreadslice
name = "spider meat bread slice"
@@ -58,6 +61,7 @@
slices_num = 5
filling_color = "#EDE5AD"
list_reagents = list("banana" = 20, "nutriment" = 20)
+ tastes = list("bread" = 10)
/obj/item/reagent_containers/food/snacks/bananabreadslice
name = "Banana-nut bread slice"
@@ -65,6 +69,7 @@
icon_state = "bananabreadslice"
trash = /obj/item/trash/plate
filling_color = "#EDE5AD"
+ tastes = list("bread" = 10)
/obj/item/reagent_containers/food/snacks/sliceable/tofubread
name = "Tofubread"
@@ -74,6 +79,7 @@
slices_num = 5
filling_color = "#F7FFE0"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("bread" = 10, "tofu" = 10)
/obj/item/reagent_containers/food/snacks/tofubreadslice
name = "Tofubread slice"
@@ -90,6 +96,7 @@
slices_num = 6
filling_color = "#FFE396"
list_reagents = list("nutriment" = 10)
+ tastes = list("bread" = 10)
/obj/item/reagent_containers/food/snacks/breadslice
name = "Bread slice"
@@ -98,6 +105,7 @@
trash = /obj/item/trash/plate
filling_color = "#D27332"
list_reagents = list("nutriment" = 2, "bread" = 5)
+ tastes = list("bread" = 10)
/obj/item/reagent_containers/food/snacks/sliceable/creamcheesebread
name = "Cream Cheese Bread"
@@ -107,6 +115,7 @@
slices_num = 5
filling_color = "#FFF896"
list_reagents = list("nutriment" = 20, "vitamin" = 5)
+ tastes = list("bread" = 10, "cheese" = 10)
/obj/item/reagent_containers/food/snacks/creamcheesebreadslice
name = "Cream Cheese Bread slice"
@@ -115,6 +124,7 @@
trash = /obj/item/trash/plate
filling_color = "#FFF896"
list_reagents = list("nutriment" = 4, "vitamin" = 1)
+ tastes = list("bread" = 10, "cheese" = 10)
//////////////////////
@@ -127,6 +137,8 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "bun"
list_reagents = list("nutriment" = 1)
+ tastes = list("bun" = 1)
+
/obj/item/reagent_containers/food/snacks/flatbread
name = "flatbread"
@@ -134,6 +146,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "flatbread"
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bread" = 2)
/obj/item/reagent_containers/food/snacks/baguette
name = "baguette"
@@ -142,6 +155,7 @@
filling_color = "#E3D796"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bread" = 2)
/obj/item/reagent_containers/food/snacks/twobread
name = "Two Bread"
@@ -150,6 +164,7 @@
filling_color = "#DBCC9A"
bitesize = 3
list_reagents = list("nutriment" = 2, "vitamin" = 2)
+ tastes = list("bread" = 2)
/obj/item/reagent_containers/food/snacks/jelliedtoast
name = "Jellied Toast"
@@ -158,6 +173,7 @@
trash = /obj/item/trash/plate
filling_color = "#B572AB"
bitesize = 3
+ tastes = list("toast" = 1, "jelly" = 1)
/obj/item/reagent_containers/food/snacks/jelliedtoast/cherry
list_reagents = list("nutriment" = 1, "cherryjelly" = 5, "vitamin" = 2)
@@ -173,6 +189,7 @@
filling_color = "#FF00F7"
bitesize = 4
list_reagents = list("nutriment" = 8, "psilocybin" = 2, "vitamin" = 2)
+ tastes = list("waffle" = 1, "mushrooms" = 1)
/obj/item/reagent_containers/food/snacks/waffles
name = "waffles"
diff --git a/code/modules/food_and_drinks/food/foods/candy.dm b/code/modules/food_and_drinks/food/foods/candy.dm
index 299b60cc8fa..aeab2b52128 100644
--- a/code/modules/food_and_drinks/food/foods/candy.dm
+++ b/code/modules/food_and_drinks/food/foods/candy.dm
@@ -12,6 +12,7 @@
desc = "It's placeholder flavored. This shouldn't be seen."
icon = 'icons/obj/food/candy.dmi'
icon_state = "candy"
+ tastes = list("candy" = 1)
// ***********************************************************
// Candy Ingredients / Flavorings / Byproduct
@@ -23,6 +24,7 @@
icon_state = "chocolatebar"
filling_color = "#7D5F46"
list_reagents = list("nutriment" = 2, "chocolate" = 4)
+ tastes = list("chocolate" = 1)
/obj/item/reagent_containers/food/snacks/candy/caramel
name = "caramel"
@@ -107,6 +109,7 @@
icon_state = "candycorn"
filling_color = "#FFFCB0"
list_reagents = list("nutriment" = 4, "sugar" = 2)
+ tastes = list("candy corn" = 1)
// ***********************************************************
// Candy Products (plain / unflavored)
@@ -130,6 +133,7 @@
bitesize = 3
junkiness = 25
list_reagents = list("nutriment" = 1, "chocolate" = 1)
+ tastes = list("chocolate" = 1)
/obj/item/reagent_containers/food/snacks/candy/candycane
@@ -177,6 +181,8 @@
icon_state = "candy_cash"
filling_color = "#302000"
list_reagents = list("nutriment" = 2, "chocolate" = 4)
+ tastes = list("chocolate" = 1)
+
/obj/item/reagent_containers/food/snacks/candy/coin
name = "chocolate coin"
@@ -185,6 +191,8 @@
filling_color = "#302000"
bitesize = 3
list_reagents = list("nutriment" = 2, "chocolate" = 4)
+ tastes = list("chocolate" = 1)
+
/obj/item/reagent_containers/food/snacks/candy/gum
name = "bubblegum"
diff --git a/code/modules/food_and_drinks/food/foods/desserts.dm b/code/modules/food_and_drinks/food/foods/desserts.dm
index ff99efd07be..9e8ded0bd1b 100644
--- a/code/modules/food_and_drinks/food/foods/desserts.dm
+++ b/code/modules/food_and_drinks/food/foods/desserts.dm
@@ -10,6 +10,7 @@
icon_state = "icecream_cone"
bitesize = 3
list_reagents = list("nutriment" = 1, "sugar" = 1)
+ tastes = list("ice cream" = 1)
/obj/item/reagent_containers/food/snacks/icecream/New()
..()
@@ -61,6 +62,7 @@
trash = /obj/item/trash/snack_bowl
filling_color = "#FFFBDB"
list_reagents = list("nutriment" = 7, "vitamin" = 2)
+ tastes = list("rice" = 1, "sweetness" = 1)
/obj/item/reagent_containers/food/snacks/spacylibertyduff
name = "Spacy Liberty Duff"
@@ -70,6 +72,7 @@
filling_color = "#42B873"
bitesize = 3
list_reagents = list("nutriment" = 6, "psilocybin" = 6)
+ tastes = list("jelly" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/amanitajelly
name = "Amanita Jelly"
@@ -79,6 +82,7 @@
filling_color = "#ED0758"
bitesize = 3
list_reagents = list("nutriment" = 6, "amanitin" = 6, "psilocybin" = 3)
+ tastes = list("jelly" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/candiedapple
name = "Candied Apple"
@@ -87,6 +91,7 @@
filling_color = "#F21873"
bitesize = 3
list_reagents = list("nutriment" = 3, "sugar" = 2)
+ tastes = list("apple" = 2, "sweetness" = 2)
/obj/item/reagent_containers/food/snacks/mint
name = "mint"
diff --git a/code/modules/food_and_drinks/food/foods/ethnic.dm b/code/modules/food_and_drinks/food/foods/ethnic.dm
index 9404992f5eb..0a160967858 100644
--- a/code/modules/food_and_drinks/food/foods/ethnic.dm
+++ b/code/modules/food_and_drinks/food/foods/ethnic.dm
@@ -9,6 +9,7 @@
icon_state = "taco"
bitesize = 3
list_reagents = list("nutriment" = 7, "vitamin" = 1)
+ tastes = list("taco" = 4, "meat" = 2, "cheese" = 2, "lettuce" = 1)
/obj/item/reagent_containers/food/snacks/burrito
name = "burrito"
@@ -17,6 +18,8 @@
trash = /obj/item/trash/plate
filling_color = "#A36A1F"
list_reagents = list("nutriment" = 4, "vitamin" = 1)
+ tastes = list("torilla" = 2, "meat" = 3)
+
/obj/item/reagent_containers/food/snacks/chimichanga
name = "chimichanga"
@@ -34,6 +37,7 @@
filling_color = "#A36A1F"
bitesize = 4
list_reagents = list("nutriment" = 8, "capsaicin" = 6)
+ tastes = list("hot peppers" = 1, "meat" = 3, "cheese" = 1, "sour cream" = 1)
/obj/item/reagent_containers/food/snacks/cornchips
name = "corn chips"
@@ -55,6 +59,7 @@
icon_state = "chinese1"
junkiness = 25
list_reagents = list("nutriment" = 1, "beans" = 3, "msg" = 4, "sugar" = 2)
+ tastes = list("noodle" = 1, "vegetables" = 1)
/obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball
name = "sweet & sour chicken balls"
@@ -62,6 +67,7 @@
icon_state = "chickenball"
junkiness = 25
list_reagents = list("nutriment" = 2, "msg" = 4, "sugar" = 2)
+ tastes = list("chicken" = 1, "sweetness" = 1)
/obj/item/reagent_containers/food/snacks/chinese/tao
name = "Admiral Yamamoto carp"
@@ -69,6 +75,7 @@
icon_state = "chinese2"
junkiness = 25
list_reagents = list("nutriment" = 1, "protein" = 1, "msg" = 4, "sugar" = 4)
+ tastes = list("chicken" = 1)
/obj/item/reagent_containers/food/snacks/chinese/newdles
name = "chinese newdles"
@@ -76,6 +83,7 @@
icon_state = "chinese3"
junkiness = 25
list_reagents = list("nutriment" = 1, "msg" = 4, "sugar" = 3)
+ tastes = list("noodles" = 1)
/obj/item/reagent_containers/food/snacks/chinese/rice
name = "fried rice"
@@ -83,6 +91,7 @@
icon_state = "chinese4"
junkiness = 20
list_reagents = list("nutriment" = 1, "rice" = 3, "msg" = 4, "sugar" = 2)
+ tastes = list("rice" = 1)
//////////////////////
@@ -96,6 +105,7 @@
trash = /obj/item/trash/snack_bowl
filling_color = "#F0F2E4"
list_reagents = list("nutriment" = 5)
+ tastes = list("custard" = 1)
/obj/item/reagent_containers/food/snacks/yakiimo
name = "yaki imo"
@@ -104,6 +114,7 @@
trash = /obj/item/trash/plate
list_reagents = list("nutriment" = 5, "vitamin" = 4)
filling_color = "#8B1105"
+ tastes = list("sweet potato" = 1)
//////////////////////
diff --git a/code/modules/food_and_drinks/food/foods/ingredients.dm b/code/modules/food_and_drinks/food/foods/ingredients.dm
index 7dda7c0a1c0..8ab0ba3c5ce 100644
--- a/code/modules/food_and_drinks/food/foods/ingredients.dm
+++ b/code/modules/food_and_drinks/food/foods/ingredients.dm
@@ -10,6 +10,7 @@
filling_color = "#FFFEE0"
bitesize = 3
list_reagents = list("plantmatter" = 2)
+ tastes = list("tofu" = 1)
/obj/item/reagent_containers/food/snacks/fried_tofu
name = "fried tofu"
@@ -18,6 +19,7 @@
filling_color = "#FFFEE0"
bitesize = 3
list_reagents = list("plantmatter" = 3)
+ tastes = list("tofu" = 1)
/obj/item/reagent_containers/food/snacks/soydope
name = "soy dope"
@@ -26,6 +28,7 @@
trash = /obj/item/trash/plate
filling_color = "#C4BF76"
list_reagents = list("nutriment" = 2)
+ tastes = list("soy" = 1)
//////////////////////
@@ -40,12 +43,14 @@
slices_num = 5
filling_color = "#FFF700"
list_reagents = list("nutriment" = 15, "vitamin" = 5, "cheese" = 20)
+ tastes = list("cheese" = 1)
/obj/item/reagent_containers/food/snacks/cheesewedge
name = "cheese wedge"
desc = "A wedge of delicious Cheddar. The cheese wheel it was cut from can't have gone far."
icon_state = "cheesewedge"
filling_color = "#FFF700"
+ tastes = list("cheese" = 1)
/obj/item/reagent_containers/food/snacks/weirdcheesewedge
name = "weird cheese"
@@ -66,6 +71,7 @@
filling_color = "#E0D7C5"
bitesize = 6
list_reagents = list("plantmatter" = 3, "vitamin" = 1)
+ tastes = list("mushroom" = 1)
/obj/item/reagent_containers/food/snacks/tomatomeat
name = "tomato slice"
@@ -74,18 +80,21 @@
filling_color = "#DB0000"
bitesize = 6
list_reagents = list("protein" = 2)
+ tastes = list("tomato" = 1)
/obj/item/reagent_containers/food/snacks/watermelonslice
name = "watermelon slice"
desc = "A slice of watery goodness."
icon_state = "watermelonslice"
filling_color = "#FF3867"
+ tastes = list("watermelon" = 1)
/obj/item/reagent_containers/food/snacks/pineappleslice
name = "pineapple slices"
desc = "Rings of pineapple."
icon_state = "pineappleslice"
filling_color = "#e5b437"
+ tastes = list("pineapple" = 1)
//////////////////////
@@ -98,6 +107,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "dough"
list_reagents = list("nutriment" = 6)
+ tastes = list("dough" = 1)
// Dough + rolling pin = flat dough
/obj/item/reagent_containers/food/snacks/dough/attackby(obj/item/I, mob/user, params)
@@ -120,6 +130,8 @@
slice_path = /obj/item/reagent_containers/food/snacks/doughslice
slices_num = 3
list_reagents = list("nutriment" = 6)
+ tastes = list("dough" = 1)
+
/obj/item/reagent_containers/food/snacks/doughslice
name = "dough slice"
@@ -127,6 +139,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "doughslice"
list_reagents = list("nutriment" = 1)
+ tastes = list("dough" = 1)
///cookies by Ume
@@ -138,6 +151,8 @@
desc = "The base for tasty cookies."
icon_state = "cookiedough"
list_reagents = list("nutriment" = 5, "sugar" = 5)
+ tastes = list("dough" = 1, "sugar" = 1)
+
/obj/item/reagent_containers/food/snacks/cookiedough/update_icon()
if(flat)
@@ -193,6 +208,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "unbaked_cookies_choco"
list_reagents = list("nutriment" = 5, "sugar" = 5, "chocolate" = 5)
+ tastes = list("dough" = 1, "sugar" = 1, "chocolate" = 1)
//////////////////////
// Chocolate //
@@ -204,6 +220,7 @@
icon_state = "chocolatebar"
filling_color = "#7D5F46"
list_reagents = list("nutriment" = 2, "sugar" = 2, "cocoa" = 2)
+ tastes = list("chocolate" = 1)
///Chocolate crumbles/pile
/obj/item/reagent_containers/food/snacks/chocolatebar/attackby(obj/item/I, mob/user, params)
@@ -224,6 +241,7 @@
icon_state = "cocoa"
filling_color = "#7D5F46"
list_reagents = list("chocolate" = 5)
+ tastes = list("chocolate" = 1)
//////////////////////
@@ -236,3 +254,4 @@
icon = 'icons/obj/wizard.dmi'
icon_state = "ectoplasm"
list_reagents = list("ectoplasm" = 10)
+ tastes = list("spookiness" = 1)
diff --git a/code/modules/food_and_drinks/food/foods/junkfood.dm b/code/modules/food_and_drinks/food/foods/junkfood.dm
index 3fa20f0d1c3..ad174fcaddd 100644
--- a/code/modules/food_and_drinks/food/foods/junkfood.dm
+++ b/code/modules/food_and_drinks/food/foods/junkfood.dm
@@ -12,6 +12,7 @@
filling_color = "#E8C31E"
junkiness = 20
list_reagents = list("nutriment" = 1, "sodiumchloride" = 1, "sugar" = 3)
+ tastes = list("crisps" = 1)
/obj/item/reagent_containers/food/snacks/sosjerky
name = "Scaredy's Private Reserve Beef Jerky"
@@ -21,6 +22,7 @@
filling_color = "#631212"
junkiness = 25
list_reagents = list("protein" = 1, "sugar" = 3)
+ tastes = list("chewy beef" = 1)
/obj/item/reagent_containers/food/snacks/pistachios
name = "pistachios"
@@ -30,6 +32,7 @@
filling_color = "#BAD145"
junkiness = 20
list_reagents = list("plantmatter" = 2, "sodiumchloride" = 1, "sugar" = 4)
+ tastes = list("pistachios" = 1)
/obj/item/reagent_containers/food/snacks/no_raisin
name = "4no Raisins"
@@ -39,6 +42,7 @@
filling_color = "#343834"
junkiness = 25
list_reagents = list("plantmatter" = 2, "sugar" = 4)
+ tastes = list("dried raisins" = 1)
/obj/item/reagent_containers/food/snacks/spacetwinkie
name = "Space Twinkie"
@@ -47,6 +51,7 @@
filling_color = "#FFE591"
junkiness = 25
list_reagents = list("sugar" = 4)
+ tastes = list("twinkies" = 1)
/obj/item/reagent_containers/food/snacks/cheesiehonkers
name = "Cheesie Honkers"
@@ -56,6 +61,7 @@
filling_color = "#FFA305"
junkiness = 25
list_reagents = list("nutriment" = 1, "fake_cheese" = 2, "sugar" = 3)
+ tastes = list("cheese" = 1, "crisps" = 2)
/obj/item/reagent_containers/food/snacks/syndicake
name = "Syndi-Cakes"
@@ -65,6 +71,7 @@
trash = /obj/item/trash/syndi_cakes
bitesize = 3
list_reagents = list("nutriment" = 4, "salglu_solution" = 5)
+ tastes = list("sweetness" = 3, "cake" = 1)
/obj/item/reagent_containers/food/snacks/tastybread
name = "bread tube"
@@ -74,6 +81,7 @@
filling_color = "#A66829"
junkiness = 20
list_reagents = list("nutriment" = 2, "sugar" = 4)
+ tastes = list("bread" = 1)
//////////////////////
diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm
index d19a88fcea8..8e667bab885 100644
--- a/code/modules/food_and_drinks/food/foods/meat.dm
+++ b/code/modules/food_and_drinks/food/foods/meat.dm
@@ -11,6 +11,7 @@
filling_color = "#FF1C1C"
bitesize = 3
list_reagents = list("protein" = 3)
+ tastes = list("meat" = 1)
/obj/item/reagent_containers/food/snacks/meat/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/kitchen/knife) || istype(W, /obj/item/scalpel))
@@ -30,6 +31,7 @@
name = "-meat"
var/subjectname = ""
var/subjectjob = null
+ tastes = list("tender meat" = 1)
/obj/item/reagent_containers/food/snacks/meat/slab/meatproduct
name = "meat product"
@@ -83,6 +85,7 @@
filling_color = "#DB0000"
bitesize = 3
list_reagents = list("protein" = 12, "morphine" = 5, "vitamin" = 2)
+ tastes = list("meat" = 1, "salmon" = 1)
/obj/item/reagent_containers/food/snacks/xenomeat
name = "meat"
@@ -91,6 +94,7 @@
filling_color = "#43DE18"
bitesize = 6
list_reagents = list("protein" = 3, "vitamin" = 1)
+ tastes = list("meat" = 1, "acid" = 1)
/obj/item/reagent_containers/food/snacks/spidermeat
name = "spider meat"
@@ -98,6 +102,7 @@
icon_state = "spidermeat"
bitesize = 3
list_reagents = list("protein" = 3, "toxin" = 3, "vitamin" = 1)
+ tastes = list("cobwebs" = 1)
/obj/item/reagent_containers/food/snacks/lizardmeat
name = "mutant lizard meat"
@@ -106,30 +111,35 @@
filling_color = "#43DE18"
bitesize = 3
list_reagents = list("protein" = 3, "toxin" = 3)
+ tastes = list("tough meat" = 1)
/obj/item/reagent_containers/food/snacks/spiderleg
name = "spider leg"
desc = "A still twitching leg of a giant spider. You don't really want to eat this, do you?"
icon_state = "spiderleg"
list_reagents = list("protein" = 2, "toxin" = 2)
+ tastes = list("cobwebs" = 1, "creepy motion" = 1)
/obj/item/reagent_containers/food/snacks/raw_bacon
name = "raw bacon"
desc = "God's gift to man in uncooked form."
icon_state = "raw_bacon"
list_reagents = list("nutriment" = 1, "porktonium" = 10)
+ tastes = list("bacon" = 1)
/obj/item/reagent_containers/food/snacks/spidereggs
name = "spider eggs"
desc = "A cluster of juicy spider eggs. A great side dish for when you don't care about your health."
icon_state = "spidereggs"
list_reagents = list("protein" = 2, "toxin" = 2)
+ tastes = list("cobwebs" = 1, "spider juice" = 1)
/obj/item/reagent_containers/food/snacks/goliath
name = "goliath meat"
desc = "A slab of goliath meat. It's not very edible now, but it cooks great in lava."
icon_state = "goliathmeat"
list_reagents = list("protein" = 3, "toxin" = 5)
+ tastes = list("tough meat" = 1)
/obj/item/reagent_containers/food/snacks/goliath/burn()
visible_message("[src] finishes cooking!")
@@ -148,12 +158,14 @@
filling_color = "#7A3D11"
bitesize = 3
list_reagents = list("nutriment" = 5)
+ tastes = list("meat" = 1)
/obj/item/reagent_containers/food/snacks/bacon
name = "bacon"
desc = "It looks crispy and tastes amazing! Mmm... Bacon."
icon_state = "bacon"
list_reagents = list("nutriment" = 4, "porktonium" = 10, "msg" = 4)
+ tastes = list("bacon" = 1)
/obj/item/reagent_containers/food/snacks/telebacon
name = "tele bacon"
@@ -161,6 +173,7 @@
icon_state = "bacon"
var/obj/item/radio/beacon/bacon/baconbeacon
list_reagents = list("nutriment" = 4, "porktonium" = 10)
+ tastes = list("bacon" = 1)
/obj/item/reagent_containers/food/snacks/telebacon/New()
..()
@@ -178,6 +191,7 @@
icon_state = "meatball"
filling_color = "#DB0000"
list_reagents = list("protein" = 4, "vitamin" = 1)
+ tastes = list("meat" = 1)
/obj/item/reagent_containers/food/snacks/sausage
name = "sausage"
@@ -185,6 +199,7 @@
icon_state = "sausage"
filling_color = "#DB0000"
list_reagents = list("protein" = 6, "vitamin" = 1, "porktonium" = 10)
+ tastes = list("meat" = 1)
/obj/item/reagent_containers/food/snacks/cutlet
name = "cutlet"
@@ -192,6 +207,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "cutlet"
list_reagents = list("protein" = 2)
+ tastes = list("meat" = 1)
/obj/item/reagent_containers/food/snacks/spidereggsham
name = "green eggs and ham"
@@ -200,6 +216,7 @@
trash = /obj/item/trash/plate
bitesize = 4
list_reagents = list("nutriment" = 6)
+ tastes = list("cobwebs" = 1, "the colour green" = 1)
/obj/item/reagent_containers/food/snacks/boiledspiderleg
name = "boiled spider leg"
@@ -208,6 +225,7 @@
trash = /obj/item/trash/plate
bitesize = 3
list_reagents = list("nutriment" = 3, "capsaicin" = 2)
+ tastes = list("cobwebs" = 1, "hot peppers" = 1)
/obj/item/reagent_containers/food/snacks/wingfangchu
name = "wing fang chu"
@@ -216,6 +234,7 @@
trash = /obj/item/trash/snack_bowl
filling_color = "#43DE18"
list_reagents = list("nutriment" = 6, "soysauce" = 5, "vitamin" = 2)
+ tastes = list("soy" = 1)
/obj/item/reagent_containers/food/snacks/goliath_steak
name = "goliath steak"
@@ -224,6 +243,7 @@
icon_state = "goliathsteak"
trash = null
list_reagents = list("protein" = 6, "vitamin" = 2)
+ tastes = list("meat" = 1)
//////////////////////
// Cubes //
@@ -238,6 +258,7 @@
var/faction
var/datum/species/monkey_type = /datum/species/monkey
list_reagents = list("nutriment" = 2)
+ tastes = list("the jungle" = 1, "bananas" = 1)
/obj/item/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature, source, method = TOUCH)
. = ..()
@@ -294,6 +315,8 @@
icon_state = "egg"
filling_color = "#FDFFD1"
list_reagents = list("protein" = 1, "egg" = 5)
+ tastes = list("egg" = 1)
+
/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom)
..()
@@ -367,6 +390,7 @@
filling_color = "#FFDF78"
bitesize = 1
list_reagents = list("nutriment" = 3, "egg" = 5)
+ tastes = list("egg" = 1, "salt" = 1, "pepper" = 1)
/obj/item/reagent_containers/food/snacks/boiledegg
name = "boiled egg"
@@ -390,6 +414,7 @@
filling_color = "#FFF9A8"
list_reagents = list("nutriment" = 8, "vitamin" = 1)
bitesize = 1
+ tastes = list("egg" = 1, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/benedict
name = "eggs benedict"
@@ -397,6 +422,7 @@
icon_state = "benedict"
bitesize = 3
list_reagents = list("nutriment" = 6, "egg" = 3, "vitamin" = 4)
+ tastes = list("egg" = 1, "bacon" = 1, "bun" = 1)
//////////////////////
@@ -409,6 +435,7 @@
icon_state = "hotdog"
bitesize = 3
list_reagents = list("nutriment" = 6, "ketchup" = 3, "vitamin" = 3)
+ tastes = list("bun" = 3, "meat" = 2)
/obj/item/reagent_containers/food/snacks/meatbun
name = "meat bun"
@@ -416,6 +443,7 @@
icon_state = "meatbun"
bitesize = 6
list_reagents = list("nutriment" = 6, "vitamin" = 2)
+ tastes = list("bun" = 3, "meat" = 2)
/obj/item/reagent_containers/food/snacks/sliceable/turkey
name = "turkey"
@@ -424,6 +452,7 @@
slice_path = /obj/item/reagent_containers/food/snacks/turkeyslice
slices_num = 6
list_reagents = list("protein" = 24, "nutriment" = 18, "vitamin" = 5)
+ tastes = list("turkey" = 2, "stuffing" = 2)
/obj/item/reagent_containers/food/snacks/turkeyslice
name = "turkey serving"
@@ -431,6 +460,7 @@
icon_state = "turkeyslice"
trash = /obj/item/trash/plate
filling_color = "#B97A57"
+ tastes = list("turkey" = 1)
/obj/item/reagent_containers/food/snacks/organ
name = "organ"
diff --git a/code/modules/food_and_drinks/food/foods/misc.dm b/code/modules/food_and_drinks/food/foods/misc.dm
index 4845fe4d608..1fcd4a52c18 100644
--- a/code/modules/food_and_drinks/food/foods/misc.dm
+++ b/code/modules/food_and_drinks/food/foods/misc.dm
@@ -10,6 +10,7 @@
trash = /obj/item/trash/plate
filling_color = "#4D2F5E"
list_reagents = list("nutriment" = 6, "vitamin" = 2)
+ tastes = list("eggplant" = 2, "cheese" = 2)
/obj/item/reagent_containers/food/snacks/soylentgreen
name = "soylent green"
@@ -18,6 +19,7 @@
trash = /obj/item/trash/waffles
filling_color = "#B8E6B5"
list_reagents = list("nutriment" = 10, "vitamin" = 1)
+ tastes = list("waffles" = 7, "people" = 1)
/obj/item/reagent_containers/food/snacks/soylentviridians
name = "soylent virdians"
@@ -26,6 +28,7 @@
trash = /obj/item/trash/waffles
filling_color = "#E6FA61"
list_reagents = list("nutriment" = 10, "vitamin" = 1)
+ tastes = list("waffles" = 10)
/obj/item/reagent_containers/food/snacks/monkeysdelight
name = "monkey's delight"
@@ -35,6 +38,7 @@
filling_color = "#5C3C11"
bitesize = 6
list_reagents = list("nutriment" = 10, "banana" = 5, "vitamin" = 5)
+ tastes = list("banana" = 1, "the jungle" = 1)
/obj/item/reagent_containers/food/snacks/dionaroast
name = "roast diona"
@@ -43,6 +47,7 @@
trash = /obj/item/trash/plate
filling_color = "#75754B"
list_reagents = list("plantmatter" = 4, "nutriment" = 2, "radium" = 2, "vitamin" = 4)
+ tastes = list("chewy vegetables" = 1)
/obj/item/reagent_containers/food/snacks/tofurkey
name = "tofurkey"
@@ -51,6 +56,7 @@
filling_color = "#FFFEE0"
bitesize = 3
list_reagents = list("nutriment" = 12, "ether" = 3)
+ tastes = list("tofu" = 1)
//////////////////////
@@ -65,6 +71,7 @@
filling_color = "#468C00"
bitesize = 3
list_reagents = list("nutriment" = 8, "omnizine" = 8, "vitamin" = 6)
+ tastes = list("divinity" = 1, "lettuce" = 1)
/obj/item/reagent_containers/food/snacks/herbsalad
name = "herb salad"
@@ -74,6 +81,7 @@
filling_color = "#76B87F"
bitesize = 3
list_reagents = list("nutriment" = 8, "vitamin" = 2)
+ tastes = list("lettuce" = 1, "apple" = 1)
/obj/item/reagent_containers/food/snacks/validsalad
name = "valid salad"
@@ -83,6 +91,7 @@
filling_color = "#76B87F"
bitesize = 3
list_reagents = list("nutriment" = 8, "salglu_solution" = 5, "vitamin" = 2)
+ tastes = list("fried potato" = 1, "lettuce" = 1, "meat" = 1, "valids" = 1)
//////////////////////
@@ -95,6 +104,7 @@
icon_state = "donkpocket"
filling_color = "#DEDEAB"
list_reagents = list("nutriment" = 4)
+ tastes = list("meat" = 2, "dough" = 2, "laziness" = 1)
/obj/item/reagent_containers/food/snacks/warmdonkpocket
name = "warm Donk-pocket"
@@ -102,6 +112,7 @@
icon_state = "donkpocket"
filling_color = "#DEDEAB"
list_reagents = list("nutriment" = 4)
+ tastes = list("meat" = 2, "dough" = 2, "laziness" = 1)
/obj/item/reagent_containers/food/snacks/warmdonkpocket/Post_Consume(mob/living/M)
M.reagents.add_reagent("omnizine", 15)
@@ -140,6 +151,7 @@
icon_state = "boiledrorocore"
bitesize = 3
list_reagents = list("slimejelly" = 5)
+ tastes = list("jelly" = 3)
/obj/item/reagent_containers/food/snacks/popcorn
name = "Popcorn"
@@ -150,6 +162,7 @@
filling_color = "#FFFAD4"
bitesize = 0.1 //this snack is supposed to be eating during looooong time. And this it not dinner food! --rastaf0
list_reagents = list("nutriment" = 2)
+ tastes = list("popcorn" = 3, "butter" = 1)
/obj/item/reagent_containers/food/snacks/popcorn/New()
..()
diff --git a/code/modules/food_and_drinks/food/foods/pasta.dm b/code/modules/food_and_drinks/food/foods/pasta.dm
index 77bfb0728ca..41de9f4f565 100644
--- a/code/modules/food_and_drinks/food/foods/pasta.dm
+++ b/code/modules/food_and_drinks/food/foods/pasta.dm
@@ -10,6 +10,7 @@
icon_state = "spaghetti"
filling_color = "#EDDD00"
list_reagents = list("nutriment" = 1, "vitamin" = 1)
+ tastes = list("raw pasta" = 1)
/obj/item/reagent_containers/food/snacks/macaroni
name = "macaroni twists"
@@ -18,6 +19,7 @@
icon_state = "macaroni"
filling_color = "#EDDD00"
list_reagents = list("nutriment" = 1, "vitamin" = 1)
+ tastes = list("raw pasta" = 1)
//////////////////////
@@ -32,6 +34,7 @@
trash = /obj/item/trash/plate
filling_color = "#FCEE81"
list_reagents = list("nutriment" = 2, "vitamin" = 1)
+ tastes = list("pasta" = 1)
/obj/item/reagent_containers/food/snacks/pastatomato
name = "spaghetti"
@@ -42,6 +45,7 @@
filling_color = "#DE4545"
bitesize = 4
list_reagents = list("nutriment" = 6, "tomatojuice" = 10, "vitamin" = 4)
+ tastes = list("pasta" = 1, "tomato" = 1)
/obj/item/reagent_containers/food/snacks/meatballspaghetti
name = "spaghetti & meatballs"
@@ -51,6 +55,7 @@
trash = /obj/item/trash/plate
filling_color = "#DE4545"
list_reagents = list("nutriment" = 8, "synaptizine" = 5, "vitamin" = 4)
+ tastes = list("pasta" = 1, "tomato" = 1, "meat" = 1)
/obj/item/reagent_containers/food/snacks/spesslaw
name = "Spesslaw"
@@ -59,6 +64,7 @@
icon_state = "spesslaw"
filling_color = "#DE4545"
list_reagents = list("nutriment" = 8, "synaptizine" = 10, "vitamin" = 6)
+ tastes = list("pasta" = 1, "tomato" = 1, "meat" = 2)
/obj/item/reagent_containers/food/snacks/macncheese
name = "mac n cheese"
@@ -68,10 +74,12 @@
icon_state = "macncheese"
filling_color = "#ffe45d"
list_reagents = list("nutriment" = 5, "vitamin" = 2, "cheese" = 4)
+ tastes = list("pasta" = 1, "cheese" = 1, "comfort" = 1)
/obj/item/reagent_containers/food/snacks/lasagna
name = "Lasagna"
icon_state = "lasagna"
- desc = "Tajarans loves to eat this, for some reason."
+ desc = "Tajara love to eat this, for some reason."
filling_color = "#E18712"
list_reagents = list("nutriment" = 10, "msg" = 3, "vitamin" = 4, "tomatojuice" = 10)
+ tastes = list("pasta" = 1, "cheese" = 1, "tomato" = 1, "meat" = 1)
diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm
index cbe7342b74b..e1290d9148a 100644
--- a/code/modules/food_and_drinks/food/foods/pizza.dm
+++ b/code/modules/food_and_drinks/food/foods/pizza.dm
@@ -7,6 +7,7 @@
icon = 'icons/obj/food/pizza.dmi'
slices_num = 6
filling_color = "#BAA14C"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita
name = "margherita pizza"
@@ -22,6 +23,7 @@
icon_state = "pizzamargheritaslice"
filling_color = "#BAA14C"
list_reagents = list("nutriment" = 5)
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/meatpizza
name = "meat pizza"
@@ -29,6 +31,7 @@
icon_state = "meatpizza"
slice_path = /obj/item/reagent_containers/food/snacks/meatpizzaslice
list_reagents = list("protein" = 30, "tomatojuice" = 6, "vitamin" = 8)
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1)
/obj/item/reagent_containers/food/snacks/meatpizzaslice
name = "meat pizza slice"
@@ -36,6 +39,7 @@
icon = 'icons/obj/food/pizza.dmi'
icon_state = "meatpizzaslice"
filling_color = "#BAA14C"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/mushroompizza
name = "mushroom pizza"
@@ -43,6 +47,8 @@
icon_state = "mushroompizza"
slice_path = /obj/item/reagent_containers/food/snacks/mushroompizzaslice
list_reagents = list("plantmatter" = 30, "vitamin" = 5)
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "mushroom" = 1)
+
/obj/item/reagent_containers/food/snacks/mushroompizzaslice
name = "mushroom pizza slice"
@@ -50,6 +56,7 @@
icon = 'icons/obj/food/pizza.dmi'
icon_state = "mushroompizzaslice"
filling_color = "#BAA14C"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "mushroom" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza
name = "vegetable pizza"
@@ -57,6 +64,8 @@
icon_state = "vegetablepizza"
slice_path = /obj/item/reagent_containers/food/snacks/vegetablepizzaslice
list_reagents = list("plantmatter" = 25, "tomatojuice" = 6, "oculine" = 12, "vitamin" = 5)
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "carrot" = 1, "vegetables" = 1)
+
/obj/item/reagent_containers/food/snacks/vegetablepizzaslice
name = "vegetable pizza slice"
@@ -64,6 +73,7 @@
icon = 'icons/obj/food/pizza.dmi'
icon_state = "vegetablepizzaslice"
filling_color = "#BAA14C"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "carrot" = 1, "vegetables" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza
name = "Hawaiian pizza"
@@ -71,6 +81,7 @@
icon_state = "hawaiianpizza" //NEEDED
slice_path = /obj/item/reagent_containers/food/snacks/hawaiianpizzaslice
list_reagents = list("protein" = 15, "tomatojuice" = 6, "plantmatter" = 20, "pineapplejuice" = 6, "vitamin" = 5)
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 1)
/obj/item/reagent_containers/food/snacks/hawaiianpizzaslice
name = "Hawaiian pizza slice"
@@ -78,6 +89,7 @@
icon = 'icons/obj/food/pizza.dmi'
icon_state = "hawaiianpizzaslice"
filling_color = "#e5b437"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/pizza/macpizza
name = "mac n cheese pizza"
@@ -86,6 +98,7 @@
slice_path = /obj/item/reagent_containers/food/snacks/macpizzaslice
list_reagents = list("nutriment" = 40, "vitamin" = 5) //More nutriment because carbs, but it's not any more vitaminicious
filling_color = "#ffe45d"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 2, "pasta" = 1)
/obj/item/reagent_containers/food/snacks/macpizzaslice
name = "mac n cheese pizza slice"
@@ -93,6 +106,7 @@
icon = 'icons/obj/food/pizza.dmi'
icon_state = "macpizzaslice"
filling_color = "#ffe45d"
+ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 2, "pasta" = 1)
//////////////////////
diff --git a/code/modules/food_and_drinks/food/foods/sandwiches.dm b/code/modules/food_and_drinks/food/foods/sandwiches.dm
index 43f1b31df0e..216e56af9f9 100644
--- a/code/modules/food_and_drinks/food/foods/sandwiches.dm
+++ b/code/modules/food_and_drinks/food/foods/sandwiches.dm
@@ -10,6 +10,7 @@
filling_color = "#F2B6EA"
bitesize = 3
list_reagents = list("nutriment" = 6, "prions" = 10, "vitamin" = 1)
+ tastes = list("bun" = 4, "brains" = 2)
/obj/item/reagent_containers/food/snacks/ghostburger
name = "ghost burger"
@@ -18,6 +19,7 @@
filling_color = "#FFF2FF"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "ectoplasm" = 2)
/obj/item/reagent_containers/food/snacks/human
var/hname = ""
@@ -30,6 +32,7 @@
icon_state = "hburger"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "tender meat" = 2)
/obj/item/reagent_containers/food/snacks/cheeseburger
name = "cheeseburger"
@@ -37,6 +40,7 @@
icon_state = "cheeseburger"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "meat" = 1, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/monkeyburger
name = "burger"
@@ -45,6 +49,7 @@
filling_color = "#D63C3C"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "meat" = 1, "the jungle" = 1)
/obj/item/reagent_containers/food/snacks/tofuburger
name = "tofu burger"
@@ -53,6 +58,7 @@
filling_color = "#FFFEE0"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "tofu" = 4)
/obj/item/reagent_containers/food/snacks/roburger
name = "roburger"
@@ -61,6 +67,7 @@
filling_color = "#CCCCCC"
bitesize = 3
list_reagents = list("nutriment" = 6, "nanomachines" = 10, "vitamin" = 1)
+ tastes = list("bun" = 4, "lettuce" = 2, "sludge" = 1)
/obj/item/reagent_containers/food/snacks/roburgerbig
name = "roburger"
@@ -70,6 +77,7 @@
volume = 120
bitesize = 3
list_reagents = list("nutriment" = 6, "nanomachines" = 70, "vitamin" = 5)
+ tastes = list("bun" = 4, "lettuce" = 2, "sludge" = 2)
/obj/item/reagent_containers/food/snacks/xenoburger
name = "xenoburger"
@@ -78,6 +86,7 @@
filling_color = "#43DE18"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "acid" = 4)
/obj/item/reagent_containers/food/snacks/clownburger
name = "clown burger"
@@ -86,6 +95,7 @@
filling_color = "#FF00FF"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "banana" = 1, "magic" = 2)
/obj/item/reagent_containers/food/snacks/mimeburger
name = "mime burger"
@@ -94,6 +104,7 @@
filling_color = "#FFFFFF"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "silence" = 2)
/obj/item/reagent_containers/food/snacks/baseballburger
name = "home run baseball burger"
@@ -102,6 +113,7 @@
filling_color = "#CD853F"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4)
/obj/item/reagent_containers/food/snacks/spellburger
name = "spell burger"
@@ -110,6 +122,7 @@
filling_color = "#D505FF"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "magic" = 2)
/obj/item/reagent_containers/food/snacks/bigbiteburger
name = "BigBite burger"
@@ -118,6 +131,7 @@
filling_color = "#E3D681"
bitesize = 3
list_reagents = list("nutriment" = 10, "vitamin" = 2)
+ tastes = list("bun" = 4, "meat" = 2, "cheese" = 2, "type two diabetes" = 10)
/obj/item/reagent_containers/food/snacks/superbiteburger
name = "SuperBite burger"
@@ -126,6 +140,7 @@
filling_color = "#CCA26A"
bitesize = 7
list_reagents = list("nutriment" = 40, "vitamin" = 5)
+ tastes = list("bun" = 4, "meat" = 2, "cheese" = 2, "type two diabetes" = 10)
/obj/item/reagent_containers/food/snacks/jellyburger
name = "jelly burger"
@@ -133,6 +148,7 @@
icon_state = "jellyburger"
filling_color = "#B572AB"
bitesize = 3
+ tastes = list("bun" = 4, "jelly" = 2)
/obj/item/reagent_containers/food/snacks/jellyburger/slime
list_reagents = list("nutriment" = 6, "slimejelly" = 5, "vitamin" = 1)
@@ -152,6 +168,7 @@
trash = /obj/item/trash/plate
filling_color = "#D9BE29"
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("meat" = 2, "cheese" = 1, "bread" = 2, "lettuce" = 1)
/obj/item/reagent_containers/food/snacks/toastedsandwich
name = "toasted sandwich"
@@ -160,6 +177,7 @@
trash = /obj/item/trash/plate
filling_color = "#D9BE29"
list_reagents = list("nutriment" = 6, "carbon" = 2)
+ tastes = list("toast" = 1)
/obj/item/reagent_containers/food/snacks/grilledcheese
name = "grilled cheese sandwich"
@@ -168,6 +186,7 @@
trash = /obj/item/trash/plate
filling_color = "#D9BE29"
list_reagents = list("nutriment" = 7, "vitamin" = 1) //why make a regualr sandwhich when you can make grilled cheese, with this nutriment value?
+ tastes = list("toast" = 1, "grilled cheese" = 1)
/obj/item/reagent_containers/food/snacks/jellysandwich
name = "jelly sandwich"
@@ -176,6 +195,7 @@
trash = /obj/item/trash/plate
filling_color = "#9E3A78"
bitesize = 3
+ tastes = list("toast" = 1, "jelly" = 1)
/obj/item/reagent_containers/food/snacks/jellysandwich/slime
list_reagents = list("nutriment" = 2, "slimejelly" = 5, "vitamin" = 2)
@@ -188,9 +208,11 @@
desc = "Something seems to be wrong with this, you can't quite figure what. Maybe it's his moustache."
icon_state = "notasandwich"
list_reagents = list("nutriment" = 6, "vitamin" = 6)
+ tastes = list("nothing suspicious" = 1)
/obj/item/reagent_containers/food/snacks/wrap
name = "egg wrap"
desc = "The precursor to Pigs in a Blanket."
icon_state = "wrap"
list_reagents = list("nutriment" = 5)
+ tastes = list("egg" = 1)
diff --git a/code/modules/food_and_drinks/food/foods/seafood.dm b/code/modules/food_and_drinks/food/foods/seafood.dm
index 9e4407d9602..007af8f6eb9 100644
--- a/code/modules/food_and_drinks/food/foods/seafood.dm
+++ b/code/modules/food_and_drinks/food/foods/seafood.dm
@@ -7,6 +7,7 @@
filling_color = "#FFDEFE"
bitesize = 6
list_reagents = list("protein" = 3, "carpotoxin" = 2, "vitamin" = 2)
+ tastes = list("white fish" = 1)
/obj/item/reagent_containers/food/snacks/salmonmeat
name = "raw salmon"
@@ -16,6 +17,7 @@
filling_color = "#FFDEFE"
bitesize = 6
list_reagents = list("protein" = 3, "vitamin" = 2)
+ tastes = list("raw salmon" = 1)
/obj/item/reagent_containers/food/snacks/salmonsteak
name = "salmon steak"
@@ -26,6 +28,7 @@
filling_color = "#7A3D11"
bitesize = 3
list_reagents = list("nutriment" = 4, "vitamin" = 2)
+ tastes = list("cooked salmon" = 1)
/obj/item/reagent_containers/food/snacks/catfishmeat
name = "raw catfish"
@@ -35,6 +38,7 @@
filling_color = "#FFDEFE"
bitesize = 6
list_reagents = list("protein" = 3, "vitamin" = 2)
+ tastes = list("catfish" = 1)
/obj/item/reagent_containers/food/snacks/fishfingers
name = "fish fingers"
@@ -44,6 +48,7 @@
filling_color = "#FFDEFE"
bitesize = 1
list_reagents = list("nutriment" = 4)
+ tastes = list("fish" = 1, "bread" = 1)
/obj/item/reagent_containers/food/snacks/fishburger
name = "Fillet-O-Carp sandwich"
@@ -53,6 +58,7 @@
filling_color = "#FFDEFE"
bitesize = 3
list_reagents = list("nutriment" = 6, "vitamin" = 1)
+ tastes = list("bun" = 4, "fish" = 4)
/obj/item/reagent_containers/food/snacks/cubancarp
name = "Cuban carp"
@@ -63,6 +69,7 @@
filling_color = "#E9ADFF"
bitesize = 3
list_reagents = list("nutriment" = 6, "capsaicin" = 1)
+ tastes = list("fish" = 4, "batter" = 1, "hot peppers" = 1)
/obj/item/reagent_containers/food/snacks/fishandchips
name = "fish and chips"
@@ -72,6 +79,7 @@
filling_color = "#E3D796"
bitesize = 3
list_reagents = list("nutriment" = 6)
+ tastes = list("fish" = 1, "chips" = 1)
/obj/item/reagent_containers/food/snacks/sashimi
name = "carp sashimi"
@@ -80,6 +88,7 @@
icon_state = "sashimi"
bitesize = 3
list_reagents = list("nutriment" = 6, "capsaicin" = 5)
+ tastes = list("raw carp" = 1, "hot peppers" = 1)
/obj/item/reagent_containers/food/snacks/fried_shrimp
name = "fried shrimp"
@@ -88,6 +97,7 @@
icon_state = "shrimp_fried"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("shrimp" = 1, "bread crumbs" = 1)
/obj/item/reagent_containers/food/snacks/boiled_shrimp
name = "boiled shrimp"
@@ -96,6 +106,7 @@
icon_state = "shrimp_cooked"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("shrimp" = 1)
/obj/item/reagent_containers/food/snacks/shrimp_skewer
name = "shrimp skewer"
@@ -105,6 +116,7 @@
icon_state = "shrimpskewer"
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("shrimp" = 4)
/obj/item/reagent_containers/food/snacks/fish_skewer
name = "fish skewer"
@@ -114,6 +126,7 @@
icon_state = "fishskewer"
bitesize = 3
list_reagents = list("protein" = 6, "vitamin" = 4)
+ tastes = list("shrimp" = 1, "batter" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Ebi_maki
name = "ebi makiroll"
@@ -124,6 +137,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("shrimp" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Ebi
name = "ebi sushi"
@@ -132,6 +146,7 @@
icon_state = "sushi_Ebi"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("shrimp" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Ikura_maki
name = "ikura makiroll"
@@ -142,6 +157,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8, "protein" = 4)
+ tastes = list("salmon roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Ikura
name = "ikura sushi"
@@ -150,16 +166,18 @@
icon_state = "sushi_Ikura"
bitesize = 3
list_reagents = list("nutriment" = 2, "protein" = 1)
+ tastes = list("salmon roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Sake_maki
name = "sake makiroll"
- desc = "A large unsliced roll of Ebi Sushi."
+ desc = "A large unsliced roll of Sake Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Sake_maki"
slice_path = /obj/item/reagent_containers/food/snacks/sushi_Sake
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("raw salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Sake
name = "sake sushi"
@@ -168,6 +186,7 @@
icon_state = "sushi_Sake"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("raw salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/SmokedSalmon_maki
name = "smoked salmon makiroll"
@@ -178,6 +197,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("smoked salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_SmokedSalmon
name = "smoked salmon sushi"
@@ -186,6 +206,7 @@
icon_state = "sushi_SmokedSalmon"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("smoked salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tamago_maki
name = "tamago makiroll"
@@ -196,6 +217,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("egg" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Tamago
name = "tamago sushi"
@@ -204,6 +226,7 @@
icon_state = "sushi_Tamago"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("egg" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Inari_maki
name = "inari makiroll"
@@ -214,6 +237,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("fried tofu" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Inari
name = "inari sushi"
@@ -222,6 +246,7 @@
icon_state = "sushi_Inari"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("fried tofu" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Masago_maki
name = "masago makiroll"
@@ -232,6 +257,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8, "protein" = 4)
+ tastes = list("goldfish roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Masago
name = "masago sushi"
@@ -240,6 +266,7 @@
icon_state = "sushi_Masago"
bitesize = 3
list_reagents = list("nutriment" = 2, "protein" = 1)
+ tastes = list("goldfish roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tobiko_maki
name = "tobiko makiroll"
@@ -250,6 +277,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8, "protein" = 4)
+ tastes = list("shark roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Tobiko
name = "tobiko sushi"
@@ -258,6 +286,7 @@
icon_state = "sushi_Masago"
bitesize = 3
list_reagents = list("nutriment" = 2, "protein" = 1)
+ tastes = list("shark roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki
name = "tobiko and egg makiroll"
@@ -268,6 +297,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8, "protein" = 4)
+ tastes = list("shark roe" = 1, "rice" = 1, "egg" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_TobikoEgg
name = "tobiko and egg sushi"
@@ -276,6 +306,7 @@
icon_state = "sushi_TobikoEgg"
bitesize = 3
list_reagents = list("nutriment" = 2, "protein" = 1)
+ tastes = list("shark roe" = 1, "rice" = 1, "egg" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tai_maki
name = "tai makiroll"
@@ -286,6 +317,7 @@
slices_num = 4
bitesize = 3
list_reagents = list("nutriment" = 8)
+ tastes = list("catfish" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Tai
name = "tai sushi"
@@ -294,6 +326,7 @@
icon_state = "sushi_Tai"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("catfish" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sushi_Unagi
name = "unagi sushi"
@@ -302,3 +335,4 @@
icon_state = "sushi_Hokki"
bitesize = 3
list_reagents = list("nutriment" = 2)
+ tastes = list("grilled eel" = 1, "seaweed" = 1)
diff --git a/code/modules/food_and_drinks/food/foods/side_dishes.dm b/code/modules/food_and_drinks/food/foods/side_dishes.dm
index ec562d4e8bb..e90bf4827cf 100644
--- a/code/modules/food_and_drinks/food/foods/side_dishes.dm
+++ b/code/modules/food_and_drinks/food/foods/side_dishes.dm
@@ -9,6 +9,7 @@
icon = 'icons/obj/food/food_ingredients.dmi'
icon_state = "rawsticks"
list_reagents = list("plantmatter" = 3)
+ tastes = list("raw potatoes" = 1)
//////////////////////
@@ -22,6 +23,7 @@
trash = /obj/item/trash/plate
filling_color = "#EDDD00"
list_reagents = list("nutriment" = 4)
+ tastes = list("fries" = 3, "salt" = 1)
/obj/item/reagent_containers/food/snacks/cheesyfries
name = "cheesy fries"
@@ -30,6 +32,7 @@
trash = /obj/item/trash/plate
filling_color = "#EDDD00"
list_reagents = list("nutriment" = 6)
+ tastes = list("fries" = 3, "cheese" = 1)
/obj/item/reagent_containers/food/snacks/tatortot
name = "tator tot"
@@ -37,6 +40,7 @@
icon_state = "tatortot"
list_reagents = list("nutriment" = 4)
filling_color = "FFD700"
+ tastes = list("fried potato" = 3, "valids" = 1)
/obj/item/reagent_containers/food/snacks/onionrings
name = "onion rings"
@@ -45,6 +49,7 @@
list_reagents = list("nutriment" = 3)
filling_color = "#C0C9A0"
gender = PLURAL
+ tastes = list("onion" = 3, "batter" = 1)
/obj/item/reagent_containers/food/snacks/carrotfries
name = "carrot fries"
@@ -53,6 +58,7 @@
trash = /obj/item/trash/plate
filling_color = "#FAA005"
list_reagents = list("plantmatter" = 3, "oculine" = 3, "vitamin" = 2)
+ tastes = list("carrots" = 3, "salt" = 1)
//////////////////////
@@ -64,6 +70,7 @@
desc = "Musical fruit in a slightly less musical container."
icon_state = "beans"
list_reagents = list("nutriment" = 10, "beans" = 10, "vitamin" = 3)
+ tastes = list("beans" = 1)
/obj/item/reagent_containers/food/snacks/mashed_potatoes //mashed taters
name = "mashed potatoes"
@@ -72,6 +79,7 @@
trash = /obj/item/trash/plate
filling_color = "#D6D9C1"
list_reagents = list("nutriment" = 5, "gravy" = 5, "mashedpotatoes" = 10, "vitamin" = 2)
+ tastes = list("mashed potato" = 3, "gravy" = 1)
/obj/item/reagent_containers/food/snacks/stuffing
name = "stuffing"
@@ -79,6 +87,7 @@
icon_state = "stuffing"
filling_color = "#C9AC83"
list_reagents = list("nutriment" = 3)
+ tastes = list("bread crumbs" = 1, "herbs" = 1)
/obj/item/reagent_containers/food/snacks/loadedbakedpotato
name = "loaded baked potato"
@@ -86,6 +95,7 @@
icon_state = "loadedbakedpotato"
filling_color = "#9C7A68"
list_reagents = list("nutriment" = 6)
+ tastes = list("potato" = 1, "cheese" = 1, "herbs" = 1)
/obj/item/reagent_containers/food/snacks/boiledrice
name = "boiled rice"
@@ -94,6 +104,7 @@
trash = /obj/item/trash/snack_bowl
filling_color = "#FFFBDB"
list_reagents = list("nutriment" = 5, "vitamin" = 1)
+ tastes = list("rice" = 1)
/obj/item/reagent_containers/food/snacks/roastparsnip
@@ -103,3 +114,5 @@
trash = /obj/item/trash/plate
list_reagents = list("nutriment" = 3, "vitamin" = 4)
filling_color = "#FF5500"
+ tastes = list("parsnip" = 1)
+
diff --git a/code/modules/food_and_drinks/food/foods/soups.dm b/code/modules/food_and_drinks/food/foods/soups.dm
index 586912d1f79..6d725037742 100644
--- a/code/modules/food_and_drinks/food/foods/soups.dm
+++ b/code/modules/food_and_drinks/food/foods/soups.dm
@@ -11,6 +11,7 @@
filling_color = "#785210"
bitesize = 5
list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4)
+ tastes = list("meatball" = 1)
/obj/item/reagent_containers/food/snacks/slimesoup
name = "slime soup"
@@ -19,6 +20,7 @@
filling_color = "#C4DBA0"
bitesize = 5
list_reagents = list("nutriment" = 5, "slimejelly" = 5, "water" = 5, "vitamin" = 4)
+ tastes = list("slime" = 1)
/obj/item/reagent_containers/food/snacks/bloodsoup
name = "tomato soup"
@@ -27,6 +29,7 @@
filling_color = "#FF0000"
bitesize = 5
list_reagents = list("nutriment" = 2, "blood" = 10, "water" = 5, "vitamin" = 4)
+ tastes = list("iron" = 1)
/obj/item/reagent_containers/food/snacks/clownstears
name = "clown's tears"
@@ -35,6 +38,7 @@
filling_color = "#C4FBFF"
bitesize = 5
list_reagents = list("nutriment" = 4, "banana" = 5, "water" = 5, "vitamin" = 8)
+ tastes = list("a bad joke" = 1)
/obj/item/reagent_containers/food/snacks/vegetablesoup
name = "vegetable soup"
@@ -44,6 +48,7 @@
filling_color = "#AFC4B5"
bitesize = 5
list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4)
+ tastes = list("vegetables" = 1)
/obj/item/reagent_containers/food/snacks/nettlesoup
name = "nettle soup"
@@ -53,6 +58,7 @@
filling_color = "#AFC4B5"
bitesize = 5
list_reagents = list("nutriment" = 8, "water" = 5, "vitamin" = 4)
+ tastes = list("nettles" = 1)
/obj/item/reagent_containers/food/snacks/mysterysoup
name = "mystery soup"
@@ -61,6 +67,7 @@
var/extra_reagent = null
bitesize = 5
list_reagents = list("nutriment" = 6)
+ tastes = list("chaos" = 1)
/obj/item/reagent_containers/food/snacks/mysterysoup/New()
..()
@@ -75,6 +82,7 @@
filling_color = "#D1F4FF"
bitesize = 5
list_reagents = list("water" = 10)
+ tastes = list("wishes" = 1)
/obj/item/reagent_containers/food/snacks/wishsoup/New()
..()
@@ -91,6 +99,7 @@
filling_color = "#D92929"
bitesize = 5
list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3)
+ tastes = list("tomato" = 1)
/obj/item/reagent_containers/food/snacks/milosoup
name = "milosoup"
@@ -99,6 +108,7 @@
trash = /obj/item/trash/snack_bowl
bitesize = 5
list_reagents = list("nutriment" = 7, "vitamin" = 2)
+ tastes = list("milo" = 1)
/obj/item/reagent_containers/food/snacks/mushroomsoup
name = "chantrelle soup"
@@ -108,6 +118,7 @@
filling_color = "#E386BF"
bitesize = 5
list_reagents = list("nutriment" = 8, "vitamin" = 4)
+ tastes = list("mushroom" = 1)
/obj/item/reagent_containers/food/snacks/beetsoup
name = "beet soup"
@@ -117,6 +128,7 @@
bitesize = 5
filling_color = "#FAC9FF"
list_reagents = list("nutriment" = 7, "vitamin" = 2)
+ tastes = list("beet" = 1)
/obj/item/reagent_containers/food/snacks/beetsoup/New()
..()
@@ -134,6 +146,7 @@
filling_color = "#9E673A"
bitesize = 7
list_reagents = list("nutriment" = 10, "oculine" = 5, "tomatojuice" = 5, "vitamin" = 5)
+ tastes = list("tomato" = 1, "carrot" = 1)
/obj/item/reagent_containers/food/snacks/stewedsoymeat
name = "stewed soy meat"
@@ -141,6 +154,7 @@
icon_state = "stewedsoymeat"
trash = /obj/item/trash/plate
list_reagents = list("nutriment" = 8)
+ tastes = list("soy" = 1, "vegetables" = 1)
//////////////////////
@@ -155,6 +169,7 @@
filling_color = "#FF3C00"
bitesize = 5
list_reagents = list("nutriment" = 5, "capsaicin" = 1, "tomatojuice" = 2, "vitamin" = 2)
+ tastes = list("hot peppers" = 1, "tomato" = 1)
/obj/item/reagent_containers/food/snacks/coldchili
name = "cold chili"
@@ -164,3 +179,4 @@
trash = /obj/item/trash/snack_bowl
bitesize = 5
list_reagents = list("nutriment" = 5, "frostoil" = 1, "tomatojuice" = 2, "vitamin" = 2)
+ tastes = list("tomato" = 1, "mint" = 1)
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index b1cd3f091ff..3839c977a86 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -16,9 +16,21 @@
var/cooktype[0]
var/cooked_type = null //for microwave cooking. path of the resulting item after microwaving
var/total_w_class = 0 //for the total weight an item of food can carry
+ var/list/tastes // for example list("crisps" = 2, "salt" = 1)
+/obj/item/reagent_containers/food/snacks/add_initial_reagents()
+ if(tastes && tastes.len)
+ if(list_reagents)
+ for(var/rid in list_reagents)
+ var/amount = list_reagents[rid]
+ if(rid == "nutriment" || rid == "vitamin" || rid == "protein" || rid == "plantmatter")
+ reagents.add_reagent(rid, amount, tastes.Copy())
+ else
+ reagents.add_reagent(rid, amount)
+ else
+ ..()
- //Placeholder for effect that trigger on eating that aren't tied to reagents.
+//Placeholder for effect that trigger on eating that aren't tied to reagents.
/obj/item/reagent_containers/food/snacks/proc/On_Consume(mob/M, mob/user)
if(!user)
return
@@ -153,11 +165,13 @@
C.adjustFireLoss(-5)
qdel(src)
G.last_eaten = world.time
+ G.taste(reagents)
else
M.visible_message("[M] takes a bite of [src].","You take a bite of [src].")
playsound(loc,'sound/items/eatfood.ogg', rand(10,50), 1)
bitecount++
G.last_eaten = world.time
+ G.taste(reagents)
else if(ismouse(M))
var/mob/living/simple_animal/mouse/N = M
to_chat(N, text("You nibble away at [src]."))
@@ -166,6 +180,7 @@
//N.emote("nibbles away at the [src]")
N.adjustBruteLoss(-1)
N.adjustFireLoss(-1)
+ N.taste(reagents)
/obj/item/reagent_containers/food/snacks/sliceable/examine(mob/user)
. = ..()
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
index ba9a67fee43..a0988951855 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
@@ -17,6 +17,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sandwich
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/slimesandwich
name = "Slime Jelly Sandwich"
@@ -26,6 +27,7 @@
)
result = /obj/item/reagent_containers/food/snacks/jellysandwich/slime
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/cherrysandwich
name = "Cherry Jelly Sandwich"
@@ -35,6 +37,7 @@
)
result = /obj/item/reagent_containers/food/snacks/jellysandwich/cherry
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/slimeburger
name = "Slime Jelly Burger"
@@ -44,6 +47,7 @@
)
result = /obj/item/reagent_containers/food/snacks/jellyburger/slime
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/jellyburger
name = "Cherry Jelly Burger"
@@ -53,6 +57,7 @@
)
result = /obj/item/reagent_containers/food/snacks/jellyburger/cherry
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/baseballburger
name = "Home run baseball burger"
@@ -62,6 +67,7 @@
)
result = /obj/item/reagent_containers/food/snacks/baseballburger
category = CAT_FOOD
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/notasandwich
name = "not-a-sandwich"
@@ -71,7 +77,7 @@
)
result = /obj/item/reagent_containers/food/snacks/notasandwich
category = CAT_FOOD
-
+ subcategory = CAT_SANDWICH
/datum/crafting_recipe/sushi_Ebi
name = "Ebi Sushi"
@@ -81,6 +87,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Ebi
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Ebi_maki
name = "Ebi Makiroll"
@@ -91,6 +98,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Ebi_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Ikura
name = "Ikura Sushi"
@@ -100,6 +108,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Ikura
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Ikura_maki
name = "Ikura Makiroll"
@@ -110,6 +119,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Ikura_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Inari
name = "Inari Sushi"
@@ -119,6 +129,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Inari
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Inari_maki
name = "Inari Makiroll"
@@ -129,6 +140,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Inari_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Sake
name = "Sake Sushi"
@@ -138,6 +150,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Sake
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Sake_maki
name = "Sake Makiroll"
@@ -148,6 +161,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Sake_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_SmokedSalmon
name = "Smoked Salmon Sushi"
@@ -157,6 +171,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_SmokedSalmon
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/SmokedSalmon_maki
name = "Smoked Salmon Makiroll"
@@ -167,6 +182,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/SmokedSalmon_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Masago
name = "Masago Sushi"
@@ -176,6 +192,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Masago
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Masago_maki
name = "Masago Makiroll"
@@ -186,6 +203,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Masago_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Tobiko
name = "Tobiko Sushi"
@@ -195,6 +213,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Tobiko
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Tobiko_maki
name = "Tobiko Makiroll"
@@ -205,6 +224,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Tobiko_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_TobikoEgg
name = "Tobiko and Egg Sushi"
@@ -214,6 +234,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_TobikoEgg
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/TobikoEgg_maki
name = "Tobiko Makiroll"
@@ -224,6 +245,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Sake_maki
name = "Sake Makiroll"
@@ -234,6 +256,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/sushi_Tai
name = "Tai Sushi"
@@ -243,6 +266,7 @@
)
result = /obj/item/reagent_containers/food/snacks/sushi_Tai
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/Tai_maki
name = "Tai Makiroll"
@@ -253,6 +277,7 @@
tools = list(/obj/item/kitchen/sushimat)
result = /obj/item/reagent_containers/food/snacks/sliceable/Tai_maki
category = CAT_FOOD
+ subcategory = CAT_SUSHI
/datum/crafting_recipe/food
@@ -271,4 +296,5 @@
/datum/reagent/teslium = 1,
)
result = /mob/living/simple_animal/pet/cat/cak
- category = CAT_FOOD
\ No newline at end of file
+ category = CAT_FOOD
+ subcategory = CAT_CAKE //Cat! Haha, get it? CAT? GET IT? We get it - Love Felines -Foxes are better
\ No newline at end of file
diff --git a/code/modules/holiday/christmas.dm b/code/modules/holiday/christmas.dm
index ea608e35e4d..047c8ce069e 100644
--- a/code/modules/holiday/christmas.dm
+++ b/code/modules/holiday/christmas.dm
@@ -6,8 +6,10 @@
new /obj/item/a_gift(T)
for(var/mob/living/simple_animal/pet/corgi/Ian/Ian in GLOB.mob_list)
Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
- GLOB.crafting_recipes += new /datum/crafting_recipe/snowman
-//The following spawn is necessary as both the timer and the shuttle systems initialise after the events system does, so we can't add stuff to the shuttle system as it doesn't exist yet and we can't use a timer
+ for(var/datum/crafting_recipe/snowman/S in GLOB.crafting_recipes)
+ S.always_availible = TRUE
+ break
+ //The following spawn is necessary as both the timer and the shuttle systems initialise after the events system does, so we can't add stuff to the shuttle system as it doesn't exist yet and we can't use a timer
spawn(60 SECONDS)
var/datum/supply_packs/xmas = SSshuttle.supply_packs["[/datum/supply_packs/misc/snow_machine]"]
xmas.special_enabled = TRUE
diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm
index 9f4dbb7315d..e701406897c 100644
--- a/code/modules/hydroponics/fermenting_barrel.dm
+++ b/code/modules/hydroponics/fermenting_barrel.dm
@@ -32,8 +32,8 @@
data["alcohol_perc"] = G.wine_power
if(G.wine_flavor)
data["tastes"] = list(G.wine_flavor = 1)
- // else // Stub - Will implement when we port over tg's better taste system - I'd rather get the barrel in first.
- // data["tastes"] = list(G.tastes[1] = 1)
+ else
+ data["tastes"] = list(G.tastes[1] = 1)
reagents.add_reagent("fruit_wine", amount, data)
qdel(G)
playsound(src, 'sound/effects/bubbles.ogg', 50, TRUE)
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index 361c305bb8d..63d21bced03 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -20,6 +20,9 @@
/obj/item/reagent_containers/food/snacks/grown/New(newloc, var/obj/item/seeds/new_seed = null)
..()
+ if(!tastes)
+ tastes = list("[name]" = 1)
+
if(new_seed)
seed = new_seed.Copy()
else if(ispath(seed))
@@ -68,7 +71,7 @@
if(!isturf(loc) || !(locate(/obj/structure/table) in loc) && !(locate(/obj/machinery/optable) in loc) && !(locate(/obj/item/storage/bag/tray) in loc))
to_chat(user, "You cannot slice [src] here! You need a table or at least a tray to do it.")
- return TRUE
+ return TRUE
var/slices_lost = 0
if(!inaccurate)
diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm
index a2085eafaee..1223dd9dba7 100644
--- a/code/modules/hydroponics/grown/ambrosia.dm
+++ b/code/modules/hydroponics/grown/ambrosia.dm
@@ -7,6 +7,7 @@
slot_flags = SLOT_HEAD
filling_color = "#008000"
bitesize_mod = 2
+ tastes = list("ambrosia" = 1)
// Ambrosia Vulgaris
/obj/item/seeds/ambrosia
@@ -52,6 +53,7 @@
filling_color = "#008B8B"
origin_tech = "biotech=4;materials=3"
wine_power = 0.5
+ tastes = list("ambrosia deus" = 1)
//Ambrosia Gaia
/obj/item/seeds/ambrosia/gaia
@@ -78,6 +80,7 @@
seed = /obj/item/seeds/ambrosia/gaia
wine_power = 0.7
wine_flavor = "the earthmother's blessing"
+ tastes = list("ambrosia gaia" = 1)
// Ambrosia Cruciatus
/obj/item/seeds/ambrosia/cruciatus
@@ -88,4 +91,5 @@
/obj/item/reagent_containers/food/snacks/grown/ambrosia/cruciatus
seed = /obj/item/seeds/ambrosia/cruciatus
- wine_power = 0.7
\ No newline at end of file
+ wine_power = 0.7
+ tastes = list("ambrosia cruciatus" = 1)
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/apple.dm b/code/modules/hydroponics/grown/apple.dm
index 67948c4beb9..1344a8c39b0 100644
--- a/code/modules/hydroponics/grown/apple.dm
+++ b/code/modules/hydroponics/grown/apple.dm
@@ -23,6 +23,7 @@
icon_state = "apple"
filling_color = "#FF4500"
bitesize = 100 // Always eat the apple in one bite
+ tastes = list("apple" = 1)
distill_reagent = "hcider"
// Posioned Apple
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index dd56ade79be..dc78ff71335 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -24,6 +24,7 @@
filling_color = "#FFFF00"
bitesize = 5
distill_reagent = "bananahonk"
+ tastes = list("banana" = 1)
/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
user.visible_message("[user] is aiming the [name] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide.")
diff --git a/code/modules/hydroponics/grown/beans.dm b/code/modules/hydroponics/grown/beans.dm
index 3649e84b869..206d0984c3d 100644
--- a/code/modules/hydroponics/grown/beans.dm
+++ b/code/modules/hydroponics/grown/beans.dm
@@ -25,6 +25,7 @@
icon_state = "soybeans"
filling_color = "#F0E68C"
bitesize_mod = 2
+ tastes = list("soybean" = 1)
wine_power = 0.2
// Koibean
@@ -47,4 +48,5 @@
icon_state = "koibeans"
filling_color = "#F0E68C"
bitesize_mod = 2
+ tastes = list("koi" = 1)
wine_power = 0.4
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm
index 8e740719fbf..d4161b0a87e 100644
--- a/code/modules/hydroponics/grown/berries.dm
+++ b/code/modules/hydroponics/grown/berries.dm
@@ -25,6 +25,7 @@
gender = PLURAL
filling_color = "#FF00FF"
bitesize_mod = 2
+ tastes = list("berry" = 1)
distill_reagent = "gin"
// Poison Berries
@@ -46,6 +47,7 @@
icon_state = "poisonberrypile"
filling_color = "#C71585"
distill_reagent = null
+ tastes = list("poison-berry" = 1)
wine_power = 0.35
// Death Berries
@@ -69,6 +71,7 @@
icon_state = "deathberrypile"
filling_color = "#708090"
distill_reagent = null
+ tastes = list("death-berry" = 1)
wine_power = 0.5
// Glow Berries
@@ -96,6 +99,7 @@
light_color = "#006622"
distill_reagent = null
wine_power = 0.6
+ tastes = list("glow-berry" = 1)
wine_flavor = "warmth"
// Cherries
@@ -127,6 +131,7 @@
filling_color = "#FF0000"
bitesize_mod = 2
wine_power = 0.3
+ tastes = list("cherry" = 1)
// Blue Cherries
/obj/item/seeds/cherry/blue
@@ -148,6 +153,7 @@
filling_color = "#6495ED"
bitesize_mod = 2
wine_power = 0.5
+ tastes = list("blue cherry" = 1)
// Grapes
/obj/item/seeds/grape
@@ -179,6 +185,7 @@
filling_color = "#FF1493"
bitesize_mod = 2
distill_reagent = "wine"
+ tastes = list("grapes" = 1)
// Green Grapes
/obj/item/seeds/grape/green
@@ -197,4 +204,5 @@
name = "bunch of green grapes"
icon_state = "greengrapes"
filling_color = "#7FFF00"
+ tastes = list("green grape" = 1)
distill_reagent = "cognac"
diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm
index ed05d7a6954..274a1f1e084 100644
--- a/code/modules/hydroponics/grown/cannabis.dm
+++ b/code/modules/hydroponics/grown/cannabis.dm
@@ -93,6 +93,7 @@
icon_state = "cannabis"
filling_color = "#00FF00"
bitesize_mod = 2
+ tastes = list("cannabis" = 1)
wine_power = 0.2
diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm
index e864687a551..89b462a19e1 100644
--- a/code/modules/hydroponics/grown/cereals.dm
+++ b/code/modules/hydroponics/grown/cereals.dm
@@ -20,6 +20,7 @@
gender = PLURAL
icon_state = "wheat"
filling_color = "#F0E68C"
+ tastes = list("wheat" = 1)
bitesize_mod = 2
distill_reagent = "beer"
@@ -40,6 +41,7 @@
gender = PLURAL
icon_state = "oat"
filling_color = "#556B2F"
+ tastes = list("oat" = 1)
bitesize_mod = 2
distill_reagent = "ale"
@@ -62,6 +64,7 @@
icon_state = "rice"
filling_color = "#FAFAD2"
bitesize_mod = 2
+ tastes = list("rice" = 1)
distill_reagent = "sake"
//Meatwheat - grows into synthetic meat
@@ -83,6 +86,7 @@
filling_color = rgb(150, 0, 0)
bitesize_mod = 2
seed = /obj/item/seeds/wheat/meat
+ tastes = list("meatwheat" = 1)
can_distill = FALSE
/obj/item/reagent_containers/food/snacks/grown/meatwheat/attack_self(mob/living/user)
diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm
index 5f4621eff16..1a2b5142e37 100644
--- a/code/modules/hydroponics/grown/chili.dm
+++ b/code/modules/hydroponics/grown/chili.dm
@@ -25,6 +25,7 @@
icon_state = "chilipepper"
filling_color = "#FF0000"
bitesize_mod = 2
+ tastes = list("chili" = 1)
wine_power = 0.2
// Ice Chili
@@ -50,6 +51,7 @@
filling_color = "#0000CD"
bitesize_mod = 2
origin_tech = "biotech=4"
+ tastes = list("chilli" = 1)
wine_power = 0.3
// Ghost Chili
@@ -76,4 +78,5 @@
filling_color = "#F8F8FF"
bitesize_mod = 4
origin_tech = "biotech=4;magnets=5"
+ tastes = list("ghost chili" = 1)
wine_power = 0.5
diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm
index b6e4a36d164..38e4104c4a7 100644
--- a/code/modules/hydroponics/grown/citrus.dm
+++ b/code/modules/hydroponics/grown/citrus.dm
@@ -30,6 +30,7 @@
desc = "It's so sour, your face will twist."
icon_state = "lime"
filling_color = "#00FF00"
+ tastes = list("lime" = 1)
distill_reagent = "triple_sec"
// Orange
@@ -56,6 +57,7 @@
name = "orange"
desc = "It's an tangy fruit."
icon_state = "orange"
+ tastes = list("orange" = 1)
filling_color = "#FFA500"
// Lemon
@@ -81,6 +83,7 @@
name = "lemon"
desc = "When life gives you lemons, make lemonade."
icon_state = "lemon"
+ tastes = list("lemonade" = 1)
filling_color = "#FFD700"
// Combustible lemon
@@ -107,6 +110,7 @@
icon_state = "firelemon"
bitesize_mod = 2
wine_power = 0.7
+ tastes = list("burning lemon" = 1)
wine_flavor = "fire"
/obj/item/reagent_containers/food/snacks/grown/firelemon/attack_self(mob/living/user)
diff --git a/code/modules/hydroponics/grown/cocoa_vanilla.dm b/code/modules/hydroponics/grown/cocoa_vanilla.dm
index 745aa006498..744300d9daa 100644
--- a/code/modules/hydroponics/grown/cocoa_vanilla.dm
+++ b/code/modules/hydroponics/grown/cocoa_vanilla.dm
@@ -25,6 +25,7 @@
icon_state = "cocoapod"
filling_color = "#FFD700"
bitesize_mod = 2
+ tastes = list("cocoa" = 1)
distill_reagent = "creme_de_cacao"
// Vanilla Pod
@@ -45,4 +46,5 @@
desc = "Fattening... Mmmmm... vanilla."
icon_state = "vanillapod"
filling_color = "#FFD700"
+ tastes = list("vanilla" = 1)
distill_reagent = "vanilla" //Takes longer, but you can get even more vanilla from it.
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm
index dca121d1acb..cf7c185c147 100644
--- a/code/modules/hydroponics/grown/corn.dm
+++ b/code/modules/hydroponics/grown/corn.dm
@@ -24,6 +24,7 @@
filling_color = "#FFFF00"
trash = /obj/item/grown/corncob
bitesize_mod = 2
+ tastes = list("corn" = 1)
distill_reagent = "whiskey"
wine_power = 0.4
diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm
new file mode 100644
index 00000000000..3fa4247f578
--- /dev/null
+++ b/code/modules/hydroponics/grown/cotton.dm
@@ -0,0 +1,79 @@
+/obj/item/seeds/cotton
+ name = "pack of cotton seeds"
+ desc = "A pack of seeds that'll grow into a cotton plant. Assistants make good free labor if neccesary."
+ icon_state = "seed-cotton"
+ species = "cotton"
+ plantname = "Cotton"
+ icon_harvest = "cotton-harvest"
+ product = /obj/item/grown/cotton
+ lifespan = 35
+ endurance = 25
+ maturation = 15
+ production = 1
+ yield = 2
+ potency = 50
+ growthstages = 3
+ growing_icon = 'icons/obj/hydroponics/growing.dmi'
+ icon_dead = "cotton-dead"
+ mutatelist = list(/obj/item/seeds/cotton/durathread)
+
+/obj/item/grown/cotton
+ seed = /obj/item/seeds/cotton
+ name = "cotton bundle"
+ desc = "A fluffy bundle of cotton."
+ icon_state = "cotton"
+ force = 0
+ throwforce = 0
+ w_class = WEIGHT_CLASS_TINY
+ throw_speed = 2
+ throw_range = 3
+ attack_verb = list("pomfed")
+ var/cotton_type = /obj/item/stack/sheet/cotton
+ var/cotton_name = "raw cotton"
+
+/obj/item/grown/cotton/attack_self(mob/user)
+ user.show_message("You pull some [cotton_name] out of the [name]!", 1)
+ var/seed_modifier = 0
+ if(seed)
+ seed_modifier = round(seed.potency / 25)
+ var/obj/item/stack/cotton = new cotton_type(user.loc, 1 + seed_modifier)
+ var/old_cotton_amount = cotton.amount
+ for(var/obj/item/stack/ST in user.loc)
+ if(ST != cotton && istype(ST, cotton_type) && ST.amount < ST.max_amount)
+ ST.attackby(cotton, user)
+ if(cotton.amount > old_cotton_amount)
+ to_chat(user, "You add the newly-formed [cotton_name] to the stack. It now contains [cotton.amount] [cotton_name].")
+ qdel(src)
+
+//reinforced mutated variant
+/obj/item/seeds/cotton/durathread
+ name = "pack of durathread seeds"
+ desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly."
+ icon_state = "seed-durathread"
+ species = "durathread"
+ plantname = "Durathread"
+ icon_harvest = "durathread-harvest"
+ product = /obj/item/grown/cotton/durathread
+ lifespan = 80
+ endurance = 50
+ maturation = 15
+ production = 1
+ yield = 2
+ potency = 50
+ growthstages = 3
+ growing_icon = 'icons/obj/hydroponics/growing.dmi'
+ icon_dead = "cotton-dead"
+
+/obj/item/grown/cotton/durathread
+ seed = /obj/item/seeds/cotton/durathread
+ name = "durathread bundle"
+ desc = "A tough bundle of durathread, good luck unraveling this."
+ icon_state = "durathread"
+ force = 5
+ throwforce = 5
+ w_class = WEIGHT_CLASS_NORMAL
+ throw_speed = 2
+ throw_range = 3
+ attack_verb = list("bashed", "battered", "bludgeoned", "whacked")
+ cotton_type = /obj/item/stack/sheet/cotton/durathread
+ cotton_name = "raw durathread"
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/eggplant.dm b/code/modules/hydroponics/grown/eggplant.dm
index b9244bfd3ec..2ed28f76226 100644
--- a/code/modules/hydroponics/grown/eggplant.dm
+++ b/code/modules/hydroponics/grown/eggplant.dm
@@ -22,6 +22,7 @@
icon_state = "eggplant"
filling_color = "#800080"
bitesize_mod = 2
+ tastes = list("eggplant" = 1)
wine_power = 0.2
// Egg-Plant
@@ -43,4 +44,5 @@
trash = /obj/item/reagent_containers/food/snacks/egg
filling_color = "#F8F8FF"
bitesize_mod = 2
+ tastes = list("egg-plant" = 1)
distill_reagent = "eggnog"
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm
index 2b5817788a6..d662a77e08a 100644
--- a/code/modules/hydroponics/grown/flowers.dm
+++ b/code/modules/hydroponics/grown/flowers.dm
@@ -25,6 +25,7 @@
slot_flags = SLOT_HEAD
filling_color = "#FF6347"
bitesize_mod = 3
+ tastes = list("poppy" = 1)
distill_reagent = "vermouth"
// Lily
@@ -42,6 +43,7 @@
name = "lily"
desc = "A beautiful orange flower"
icon_state = "lily"
+ tastes = list("lily" = 1)
filling_color = "#FFA500"
// Geranium
@@ -59,6 +61,7 @@
name = "geranium"
desc = "A beautiful blue flower"
icon_state = "geranium"
+ tastes = list("geranium" = 1)
filling_color = "#008B8B"
@@ -88,6 +91,7 @@
icon_state = "harebell"
slot_flags = SLOT_HEAD
filling_color = "#E6E6FA"
+ tastes = list("harebell" = 1)
bitesize_mod = 3
distill_reagent = "vermouth"
@@ -147,6 +151,7 @@
slot_flags = SLOT_HEAD
filling_color = "#E6E6FA"
bitesize_mod = 2
+ tastes = list("moonflower" = 1)
distill_reagent = "absinthe"
// Novaflower
diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm
index c45899a310b..dee15bf75b2 100644
--- a/code/modules/hydroponics/grown/grass_carpet.dm
+++ b/code/modules/hydroponics/grown/grass_carpet.dm
@@ -27,6 +27,7 @@
bitesize_mod = 2
var/stacktype = /obj/item/stack/tile/grass
var/tile_coefficient = 0.02 // 1/50
+ tastes = list("grass" = 1)
wine_power = 0.15
/obj/item/reagent_containers/food/snacks/grown/grass/attack_self(mob/user)
@@ -66,4 +67,5 @@
desc = "The textile industry's dark secret."
icon_state = "carpetclump"
stacktype = /obj/item/stack/tile/carpet
+ tastes = list("carpet" = 1)
can_distill = FALSE
diff --git a/code/modules/hydroponics/grown/herbals.dm b/code/modules/hydroponics/grown/herbals.dm
index 07734aa268f..6a0ad441ad3 100644
--- a/code/modules/hydroponics/grown/herbals.dm
+++ b/code/modules/hydroponics/grown/herbals.dm
@@ -17,6 +17,7 @@
desc = "Mash to turn into a poultice."
icon_state = "tea_astra_leaves"
color = "#378C61"
+ tastes = list("comfrey" = 1)
bitesize_mod = 2
/obj/item/reagent_containers/food/snacks/grown/comfrey/attack_self(mob/user)
@@ -43,6 +44,7 @@
desc = "Mash to turn into a poultice."
icon_state = "ambrosiavulgaris"
color = "#4CC5C7"
+ tastes = list("aloe" = 1)
bitesize_mod = 2
/obj/item/reagent_containers/food/snacks/grown/aloe/attack_self(mob/user)
diff --git a/code/modules/hydroponics/grown/kudzu.dm b/code/modules/hydroponics/grown/kudzu.dm
index 64b84649770..41ce7ae957e 100644
--- a/code/modules/hydroponics/grown/kudzu.dm
+++ b/code/modules/hydroponics/grown/kudzu.dm
@@ -95,4 +95,5 @@
icon_state = "kudzupod"
filling_color = "#6B8E23"
bitesize_mod = 2
+ tastes = list("kudzu" = 1)
wine_power = 0.2
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index ed7608e21b9..09952a2a405 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -24,6 +24,7 @@
dried_type = null
w_class = WEIGHT_CLASS_NORMAL
filling_color = "#008000"
+ tastes = list("watermelon" = 1)
bitesize_mod = 3
wine_power = 0.4
@@ -47,4 +48,5 @@
filling_color = "#FFD700"
dried_type = null
wine_power = 0.7 //Water to wine, baby.
+ tastes = list("melon" = 1, "divinity" = 1)
wine_flavor = "divinity"
diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm
index 0d60c7d864f..f2adfab0f20 100644
--- a/code/modules/hydroponics/grown/misc.dm
+++ b/code/modules/hydroponics/grown/misc.dm
@@ -53,6 +53,7 @@
icon_state = "cabbage"
filling_color = "#90EE90"
bitesize_mod = 2
+ tastes = list("cabbage" = 1)
wine_power = 0.2
@@ -79,6 +80,7 @@
icon_state = "sugarcane"
filling_color = "#FFD700"
bitesize_mod = 2
+ tastes = list("sugarcane" = 1)
distill_reagent = "rum"
@@ -109,6 +111,7 @@
icon_state = "gatfruit"
origin_tech = "combat=6"
trash = /obj/item/gun/projectile/revolver
+ tastes = list("2nd amendment" = 1, "freedom" = 1)
bitesize_mod = 2
wine_power = 0.9 //It burns going down, too.
@@ -131,6 +134,7 @@
filling_color = rgb(20, 20, 20)
seed = /obj/item/seeds/cherry/bomb
bitesize_mod = 2
+ tastes = list("cherry" = 1, "explosion" = 1)
volume = 125 //Gives enough room for the black powder at max potency
wine_power = 0.8
diff --git a/code/modules/hydroponics/grown/mushrooms.dm b/code/modules/hydroponics/grown/mushrooms.dm
index 14c4b2a252a..68331c664c9 100644
--- a/code/modules/hydroponics/grown/mushrooms.dm
+++ b/code/modules/hydroponics/grown/mushrooms.dm
@@ -28,6 +28,7 @@
name = "reishi"
desc = "Ganoderma lucidum: A special fungus known for its medicinal and stress relieving properties."
icon_state = "reishi"
+ tastes = list("reishi" = 1)
filling_color = "#FF4500"
@@ -55,6 +56,7 @@
name = "fly amanita"
desc = "Amanita Muscaria: Learn poisonous mushrooms by heart. Only pick mushrooms you know."
icon_state = "amanita"
+ tastes = list("amanita" = 1)
filling_color = "#FF0000"
@@ -85,6 +87,7 @@
desc = "Amanita Virosa: Deadly poisonous basidiomycete fungus filled with alpha amanitin."
icon_state = "angel"
filling_color = "#C0C0C0"
+ tastes = list("destroying angel" = 1)
wine_power = 0.6
@@ -112,6 +115,7 @@
icon_state = "libertycap"
filling_color = "#DAA520"
wine_power = 0.8
+ tastes = list("liberty-cap" = 1)
wine_flavor = "freedom"
@@ -139,6 +143,7 @@
desc = "Plumus Hellmus: Plump, soft and s-so inviting~"
icon_state = "plumphelmet"
filling_color = "#9370DB"
+ tastes = list("plump helmet" = 1, "dwarven hardiness" = 1)
distill_reagent = "manlydorf"
@@ -166,6 +171,7 @@
icon_state = "walkingmushroom"
filling_color = "#9370DB"
origin_tech = "biotech=4;programming=5"
+ tastes = list("walking mushroom" = 1, "motion" = 1)
can_distill = FALSE
/obj/item/reagent_containers/food/snacks/grown/mushroom/walkingmushroom/attack_self(mob/user)
@@ -205,6 +211,7 @@
name = "chanterelle cluster"
desc = "Cantharellus Cibarius: These jolly yellow little shrooms sure look tasty!"
icon_state = "chanterelle"
+ tastes = list("chanterelle" = 1)
filling_color = "#FFA500"
@@ -238,6 +245,7 @@
var/effect_path = /obj/structure/glowshroom
origin_tech = "biotech=4;plasmatech=6"
light_color = "#006622"
+ tastes = list("warmth" = 1, "light" = 1, "glowshroom" = 1)
wine_power = 0.5
/obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom/attack_self(mob/user)
@@ -287,6 +295,7 @@
effect_path = /obj/structure/glowshroom/glowcap
origin_tech = "biotech=4;powerstorage=6;plasmatech=4"
light_color = "#8E0300"
+ tastes = list("warmth" = 1, "light" = 1, "glowscap" = 1)
wine_power = 0.6
wine_flavor = "warmth"
@@ -311,6 +320,7 @@
name = "fungus"
desc = "A fungus ideal for making antibacterials."
icon_state = "angel"
+ tastes = list("fungus" = 1)
color = "#4f4331"
//Shadowshroom
@@ -335,5 +345,6 @@
icon_state = "shadowshroom"
effect_path = /obj/structure/glowshroom/shadowshroom
origin_tech = "biotech=4;plasmatech=4;magnets=4"
+ tastes = list("strange coldness" = 1, "shadowshroom" = 1)
wine_power = 0.6
wine_flavor = "strange coldness"
diff --git a/code/modules/hydroponics/grown/onion.dm b/code/modules/hydroponics/grown/onion.dm
index e39548d9e7c..597d5c70660 100644
--- a/code/modules/hydroponics/grown/onion.dm
+++ b/code/modules/hydroponics/grown/onion.dm
@@ -24,6 +24,7 @@
filling_color = "#C0C9A0"
bitesize_mod = 2
slice_path = /obj/item/reagent_containers/food/snacks/onion_slice
+ tastes = list("onion" = 1, "pungentness" = 1)
slices_num = 2
wine_power = 0.2
wine_flavor = "pungentness"
@@ -45,6 +46,7 @@
icon_state = "onion_red"
filling_color = "#C29ACF"
slice_path = /obj/item/reagent_containers/food/snacks/onion_slice/red
+ tastes = list("red onion" = 1, "pungentness" = 3)
wine_power = 0.6
wine_flavor = "powerful pungentness"
@@ -54,6 +56,7 @@
icon_state = "onionslice"
list_reagents = list("plantmatter" = 5, "vitamin" = 2)
filling_color = "#C0C9A0"
+ tastes = list("onion" = 1, "pungentness" = 1)
gender = PLURAL
cooked_type = /obj/item/reagent_containers/food/snacks/onionrings
@@ -62,4 +65,5 @@
desc = "They shine like exceptionally low quality amethyst."
icon_state = "onionslice_red"
filling_color = "#C29ACF"
+ tastes = list("red onion" = 1, "pungentness" = 3)
list_reagents = list("plantmatter" = 5, "vitamin" = 2, "onionjuice" = 2.5)
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/peanut.dm b/code/modules/hydroponics/grown/peanut.dm
index 2a02754d4fc..52b74ab795b 100644
--- a/code/modules/hydroponics/grown/peanut.dm
+++ b/code/modules/hydroponics/grown/peanut.dm
@@ -22,4 +22,5 @@
name = "patch of peanuts"
desc = "Best avoided if you have spess allergies."
icon_state = "peanuts"
+ tastes = list("peanut" = 1, "nuttiness" = 1)
gender = PLURAL
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/pineapple.dm b/code/modules/hydroponics/grown/pineapple.dm
index 589f9456bc2..4a2975fae42 100644
--- a/code/modules/hydroponics/grown/pineapple.dm
+++ b/code/modules/hydroponics/grown/pineapple.dm
@@ -25,4 +25,5 @@
filling_color = "#e5b437"
w_class = WEIGHT_CLASS_NORMAL
bitesize_mod = 3
+ tastes = list("pineapple" = 1)
wine_power = 0.4
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/potato.dm b/code/modules/hydroponics/grown/potato.dm
index 655cb6d69bd..c02b8f72119 100644
--- a/code/modules/hydroponics/grown/potato.dm
+++ b/code/modules/hydroponics/grown/potato.dm
@@ -24,6 +24,7 @@
desc = "Boil 'em! Mash 'em! Stick 'em in a stew!"
icon_state = "potato"
filling_color = "#E9967A"
+ tastes = list("potato" = 1)
bitesize = 100
distill_reagent = "vodka"
@@ -33,6 +34,7 @@
desc = "Slices of neatly cut potato."
icon_state = "potato_wedges"
filling_color = "#E9967A"
+ tastes = list("potato" = 1)
bitesize = 100
distill_reagent = "sbiten"
@@ -64,4 +66,5 @@
seed = /obj/item/seeds/potato/sweet
name = "sweet potato"
desc = "It's sweet."
+ tastes = list("sweet potato" = 1)
icon_state = "sweetpotato"
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/pumpkin.dm b/code/modules/hydroponics/grown/pumpkin.dm
index f05a6847dc2..aa7030bc6db 100644
--- a/code/modules/hydroponics/grown/pumpkin.dm
+++ b/code/modules/hydroponics/grown/pumpkin.dm
@@ -23,6 +23,7 @@
icon_state = "pumpkin"
filling_color = "#FFA500"
bitesize_mod = 2
+ tastes = list("pumpkin" = 1)
wine_power = 0.2
/obj/item/reagent_containers/food/snacks/grown/pumpkin/attackby(obj/item/W as obj, mob/user as mob, params)
@@ -53,4 +54,5 @@
icon_state = "blumpkin"
filling_color = "#87CEFA"
bitesize_mod = 2
+ tastes = list("blumpkin" = 1)
wine_power = 0.5
diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm
index c8145033545..3aaa8d87041 100644
--- a/code/modules/hydroponics/grown/replicapod.dm
+++ b/code/modules/hydroponics/grown/replicapod.dm
@@ -88,7 +88,7 @@
make_podman = 0
if(make_podman) //all conditions met!
- var/mob/living/carbon/human/diona/podman = new /mob/living/carbon/human/diona(parent.loc)
+ var/mob/living/carbon/human/pod_diona/podman = new /mob/living/carbon/human/pod_diona(parent.loc)
if(realName)
podman.real_name = realName
mind.transfer_to(podman)
diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm
index 35bb5ee195c..56fee727a20 100644
--- a/code/modules/hydroponics/grown/root.dm
+++ b/code/modules/hydroponics/grown/root.dm
@@ -21,6 +21,7 @@
icon_state = "carrot"
filling_color = "#FFA500"
bitesize_mod = 2
+ tastes = list("carrot" = 1)
wine_power = 0.3
/obj/item/reagent_containers/food/snacks/grown/carrot/wedges
@@ -60,16 +61,17 @@
desc = "Closely related to carrots."
icon_state = "parsnip"
bitesize_mod = 2
+ tastes = list("parsnip" = 1)
wine_power = 0.35
// White-Beet
/obj/item/seeds/whitebeet
- name = "pack of white-beet seeds"
+ name = "pack of white beet seeds"
desc = "These seeds grow into sugary beet producing plants."
icon_state = "seed-whitebeet"
species = "whitebeet"
- plantname = "White-Beet Plants"
+ plantname = "White Beet Plants"
product = /obj/item/reagent_containers/food/snacks/grown/whitebeet
lifespan = 60
endurance = 50
@@ -81,11 +83,12 @@
/obj/item/reagent_containers/food/snacks/grown/whitebeet
seed = /obj/item/seeds/whitebeet
- name = "white-beet"
- desc = "You can't beat white-beet."
+ name = "white beet"
+ desc = "You can't beat white beet."
icon_state = "whitebeet"
filling_color = "#F4A460"
bitesize_mod = 2
+ tastes = list("white beet" = 1)
wine_power = 0.4
// Red Beet
@@ -94,7 +97,7 @@
desc = "These seeds grow into red beet producing plants."
icon_state = "seed-redbeet"
species = "redbeet"
- plantname = "Red-Beet Plants"
+ plantname = "Red Beet Plants"
product = /obj/item/reagent_containers/food/snacks/grown/redbeet
lifespan = 60
endurance = 50
@@ -109,5 +112,6 @@
name = "red beet"
desc = "You can't beat red beet."
icon_state = "redbeet"
+ tastes = list("red beet" = 1)
bitesize_mod = 2
wine_power = 0.6
diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm
index 1139c03cad5..cec0a8598e0 100644
--- a/code/modules/hydroponics/grown/tea_coffee.dm
+++ b/code/modules/hydroponics/grown/tea_coffee.dm
@@ -21,6 +21,7 @@
name = "Tea Aspera tips"
desc = "These aromatic tips of the tea plant can be dried to make tea."
icon_state = "tea_aspera_leaves"
+ tastes = list("tea leaves" = 1)
filling_color = "#008000"
can_distill = FALSE
@@ -28,6 +29,7 @@
/obj/item/seeds/tea/astra
name = "pack of tea astra seeds"
icon_state = "seed-teaastra"
+ desc = "These seeds grow into Tea Astra, a more potent variant of tea"
species = "teaastra"
plantname = "Tea Astra Plant"
product = /obj/item/reagent_containers/food/snacks/grown/tea/astra
@@ -38,7 +40,9 @@
/obj/item/reagent_containers/food/snacks/grown/tea/astra
seed = /obj/item/seeds/tea/astra
name = "Tea Astra tips"
+ desc = "Knock away your fatigue!"
icon_state = "tea_astra_leaves"
+ tastes = list("tea leaves" = 1, "pure energy" = 1)
filling_color = "#4582B4"
@@ -67,6 +71,7 @@
desc = "Dry them out to make coffee."
icon_state = "coffee_arabica"
filling_color = "#DC143C"
+ tastes = list("coffee beans" = 1)
bitesize_mod = 2
distill_reagent = "kahlua"
@@ -86,4 +91,5 @@
seed = /obj/item/seeds/coffee/robusta
name = "coffee robusta beans"
desc = "Increases robustness by 37 percent!"
+ tastes = list("coffee beans" = 1, "robustness" = 1)
icon_state = "coffee_robusta"
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/tobacco.dm b/code/modules/hydroponics/grown/tobacco.dm
index 95333bba31a..09d7d484f53 100644
--- a/code/modules/hydroponics/grown/tobacco.dm
+++ b/code/modules/hydroponics/grown/tobacco.dm
@@ -20,6 +20,7 @@
name = "tobacco leaves"
desc = "Dry them out to make some smokes."
icon_state = "tobacco_leaves"
+ tastes = list("tobacco" = 1)
filling_color = "#008000"
distill_reagent = "creme_de_menthe" //Menthol, I guess.
@@ -40,5 +41,6 @@
name = "space tobacco leaves"
desc = "Dry them out to make some space-smokes."
icon_state = "stobacco_leaves"
+ tastes = list("space tobacco" = 1)
distill_reagent = null
wine_power = 0.5
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm
index 58bf18057ad..873b08f151e 100644
--- a/code/modules/hydroponics/grown/tomato.dm
+++ b/code/modules/hydroponics/grown/tomato.dm
@@ -21,6 +21,7 @@
icon_state = "tomato"
splat_type = /obj/effect/decal/cleanable/tomato_smudge
filling_color = "#FF6347"
+ tastes = list("tomato" = 1)
bitesize_mod = 2
distill_reagent = "enzyme"
@@ -43,6 +44,7 @@
icon_state = "bloodtomato"
splat_type = /obj/effect/gibspawner/generic
filling_color = "#FF0000"
+ tastes = list("tomato" = 1, "blood" = 2)
origin_tech = "biotech=5"
distill_reagent = "bloodymary"
@@ -67,6 +69,7 @@
name = "blue-tomato"
desc = "I say blue-mah-to, you say blue-mae-to."
icon_state = "bluetomato"
+ tastes = list("bluemato" = 1)
splat_type = /obj/effect/decal/cleanable/blood/oil
filling_color = "#0000FF"
@@ -90,6 +93,7 @@
name = "bluespace tomato"
desc = "So lubricated, you might slip through space-time."
icon_state = "bluespacetomato"
+ tastes = list("bluemato" = 1, "taste bud dislocation" = 1)
origin_tech = "biotech=4;bluespace=5"
distill_reagent = null
wine_power = 0.8
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 899146f160d..45c55f4a7f3 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -86,6 +86,7 @@
name = "hatchet"
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
icon_state = "hatchet"
+ item_state = "hatchet"
flags = CONDUCT
force = 12
w_class = WEIGHT_CLASS_TINY
@@ -109,6 +110,12 @@
icon_state = "unathiknife"
attack_verb = list("ripped", "torn", "cut")
+/obj/item/hatchet/wooden
+ desc = "A crude axe blade upon a short wooden handle."
+ icon_state = "woodhatchet"
+ materials = null
+ flags = NONE
+
/obj/item/scythe
icon_state = "scythe0"
name = "scythe"
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 753186831fd..d9e07d96987 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -160,15 +160,23 @@
return result
-/obj/item/seeds/proc/prepare_result(var/obj/item/reagent_containers/food/snacks/grown/T)
- if(T.reagents)
- for(var/reagent_id in reagents_add)
- if(reagent_id == "blood") // Hack to make blood in plants always O-
- T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id], 1), list("blood_type"="O-"))
- continue
+/obj/item/seeds/proc/prepare_result(obj/item/T)
+ if(!T.reagents)
+ CRASH("[T] has no reagents.")
- T.reagents.add_reagent(reagent_id, 1 + round(potency * reagents_add[reagent_id]), 1)
- return 1
+ for(var/rid in reagents_add)
+ var/amount = 1 + round(potency * reagents_add[rid], 1)
+
+ var/list/data = null
+ if(rid == "blood") // Hack to make blood in plants always O-
+ data = list("blood_type" = "O-")
+ if(rid == "nutriment" || rid == "vitamin" || rid == "protein" || rid == "plantmatter")
+ // apple tastes of apple.
+ if(istype(T, /obj/item/reagent_containers/food/snacks/grown))
+ var/obj/item/reagent_containers/food/snacks/grown/grown_edible = T
+ data = grown_edible.tastes.Copy()
+
+ T.reagents.add_reagent(rid, amount, data)
/// Setters procs ///
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 47b3fb01501..d340e6069cc 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -209,7 +209,7 @@
if(istype(T, denied_type) || istype(src, T.denied_type))
to_chat(user, "You can't seem to attach [src] to [H]. Maybe remove a few trophies?")
return FALSE
- if(!user.drop_item())
+ if(!user.unEquip(src))
return
forceMove(H)
H.trophies += src
diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm
index dcd0916d876..0f174ff748f 100644
--- a/code/modules/mining/equipment/lazarus_injector.dm
+++ b/code/modules/mining/equipment/lazarus_injector.dm
@@ -73,9 +73,10 @@
icon = 'icons/obj/mobcap.dmi'
icon_state = "mobcap0"
w_class = WEIGHT_CLASS_TINY
- throw_range = 20
+ throw_range = 7
var/mob/living/simple_animal/captured = null
var/colorindex = 0
+ var/capture_type = SENTIENCE_ORGANIC //So you can't capture boss monsters or robots with it
/obj/item/mobcapsule/Destroy()
if(captured)
@@ -83,26 +84,25 @@
QDEL_NULL(captured)
return ..()
-/obj/item/mobcapsule/attack(var/atom/A, mob/user, prox_flag)
- if(!istype(A, /mob/living/simple_animal) || isbot(A))
- return ..()
- capture(A, user)
- return 1
+/obj/item/mobcapsule/attack(mob/living/simple_animal/S, mob/user, prox_flag)
+ if(istype(S) && S.sentience_type == capture_type)
+ capture(S, user)
+ return TRUE
+ return ..()
-/obj/item/mobcapsule/proc/capture(var/mob/target, var/mob/U as mob)
- var/mob/living/simple_animal/T = target
+/obj/item/mobcapsule/proc/capture(mob/living/simple_animal/S, mob/living/M)
if(captured)
- to_chat(U, "Capture failed!: The capsule already has a mob registered to it!")
+ to_chat(M, "Capture failed!: The capsule already has a mob registered to it!")
else
- if(istype(T) && "neutral" in T.faction)
- T.forceMove(src)
- T.name = "[U.name]'s [initial(T.name)]"
- T.cancel_camera()
- name = "Lazarus Capsule: [initial(T.name)]"
- to_chat(U, "You placed a [T.name] inside the Lazarus Capsule!")
- captured = T
+ if("neutral" in S.faction)
+ S.forceMove(src)
+ S.name = "[M.name]'s [initial(S.name)]"
+ S.cancel_camera()
+ name = "Lazarus Capsule: [initial(S.name)]"
+ to_chat(M, "You placed a [S.name] inside the Lazarus Capsule!")
+ captured = S
else
- to_chat(U, "You can't capture that mob!")
+ to_chat(M, "You can't capture that mob!")
/obj/item/mobcapsule/throw_impact(atom/A, mob/user)
..()
diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm
index 9a88dd50259..015921634fe 100644
--- a/code/modules/mining/equipment/survival_pod.dm
+++ b/code/modules/mining/equipment/survival_pod.dm
@@ -77,6 +77,7 @@
dir = FULLTILE_WINDOW_DIR
max_integrity = 100
fulltile = TRUE
+ flags = PREVENT_CLICK_UNDER
reinf = TRUE
heat_resistance = 1600
armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100)
@@ -296,7 +297,7 @@
name = "air flow blocker"
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF
unacidable = TRUE
- invisibility = INVISIBILITY_ABSTRACT
+ invisibility = INVISIBILITY_ABSTRACT
//Signs
/obj/structure/sign/mining
diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm
index 9b6bd8c5893..48c4249fd62 100644
--- a/code/modules/mining/lavaland/loot/colossus_loot.dm
+++ b/code/modules/mining/lavaland/loot/colossus_loot.dm
@@ -380,7 +380,7 @@
medsensor.add_hud_to(src)
/mob/living/simple_animal/hostile/lightgeist/AttackingTarget()
- ..()
+ . = ..()
if(isliving(target) && target != src)
var/mob/living/L = target
if(L.stat < DEAD)
diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm
index c8579fbec65..3727c103a64 100644
--- a/code/modules/mining/lavaland/loot/tendril_loot.dm
+++ b/code/modules/mining/lavaland/loot/tendril_loot.dm
@@ -77,6 +77,21 @@
add_fingerprint(M)
+//Book of Babel
+
+/obj/item/book_of_babel
+ name = "Book of Babel"
+ desc = "An ancient tome written in countless tongues."
+ icon = 'icons/obj/library.dmi'
+ icon_state = "book1"
+ w_class = 2
+
+/obj/item/book_of_babel/attack_self(mob/user)
+ to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.")
+ user.grant_all_languages()
+ new /obj/effect/decal/cleanable/ash(get_turf(user))
+ qdel(src)
+
//Potion of Flight: as we do not have the "Angel" species this currently does not work.
/obj/item/reagent_containers/glass/bottle/potion
@@ -117,6 +132,30 @@
H.emote("scream")
..()*/
+/obj/item/jacobs_ladder
+ name = "jacob's ladder"
+ desc = "A celestial ladder that violates the laws of physics."
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "ladder00"
+
+/obj/item/jacobs_ladder/attack_self(mob/user)
+ var/turf/T = get_turf(src)
+ var/ladder_x = T.x
+ var/ladder_y = T.y
+ to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.")
+ var/last_ladder = null
+ for(var/i in 1 to world.maxz)
+ if(is_admin_level(i) || is_away_level(i))
+ continue
+ var/turf/T2 = locate(ladder_x, ladder_y, i)
+ last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder)
+ qdel(src)
+
+// Inherit from unbreakable but don't set ID, to suppress the default Z linkage
+/obj/structure/ladder/unbreakable/jacob
+ name = "jacob's ladder"
+ desc = "An indestructible celestial ladder that violates the laws of physics."
+
//Boat
/obj/vehicle/lavaboat
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index a2ee237c659..1a0a063e33f 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -18,7 +18,7 @@
if(!add_loot)
return
- var/loot = rand(1,25)
+ var/loot = rand(1, 26)
switch(loot)
if(1)
new /obj/item/shared_storage/red(src)
@@ -48,7 +48,7 @@
if(11)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/berserker(src)
if(12)
- new /obj/item/sord(src)
+ new /obj/item/jacobs_ladder(src)
if(13)
new /obj/item/nullrod/scythe/talking(src)
if(14)
@@ -78,6 +78,8 @@
if(24)
new /obj/item/spellbook/oneuse/summonitem(src)
if(25)
+ new /obj/item/book_of_babel(src)
+ if(26)
new /obj/item/borg/upgrade/modkit/lifesteal(src)
new /obj/item/bedsheet/cult(src)
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 229b9053ae6..4de84bb70c4 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -37,7 +37,7 @@
new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000),
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000),
new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffel/mining_conscript, 1500),
- new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000),
+ new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/tank/jetpack/suit, 2000),
new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500),
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index f350633a4c2..b85db884ef5 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -44,8 +44,8 @@
/obj/structure/closet/secure_closet/miner/New()
..()
-// new /obj/item/stack/sheet/mineral/sandbags(src, 5)
-// new /obj/item/storage/box/emptysandbags(src)
+ new /obj/item/stack/sheet/mineral/sandbags(src, 5)
+ new /obj/item/storage/box/emptysandbags(src)
new /obj/item/shovel(src)
new /obj/item/pickaxe/mini(src)
new /obj/item/radio/headset/headset_cargo/mining(src)
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index e7036ad4f2f..5a0c17d9e93 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -15,7 +15,6 @@
a_intent = INTENT_HARM
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
- idle_vision_range = 5
move_to_delay = 10
health = 125
maxHealth = 125
@@ -145,7 +144,7 @@
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
mode = MINEDRONE_COLLECT
- idle_vision_range = 9
+ vision_range = 9
search_objects = 2
wander = TRUE
ranged = FALSE
@@ -156,7 +155,7 @@
/mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior()
mode = MINEDRONE_ATTACK
- idle_vision_range = 7
+ vision_range = 7
search_objects = 0
wander = FALSE
ranged = TRUE
@@ -192,7 +191,7 @@
for(var/obj/item/stack/ore/O in contents)
O.forceMove(drop_location())
-/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount)
+/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount, updating_health = TRUE)
if(mode != MINEDRONE_ATTACK && amount > 0)
SetOffenseBehavior()
. = ..()
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 57725da8eb2..525421ed186 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -762,6 +762,18 @@
desc = "Bark bark bark."
key = "vu"
+/datum/language/zombie
+ name = "Zombie"
+ desc = "BRAAAAAAINS!"
+ speech_verb = "moans"
+ whisper_verb = "mutters"
+ exclaim_verb = "wails"
+ colour = "zombie"
+ key = "zom"
+ syllables = list("BRAAAAAAAAAAAAAAAAINS", "BRAAINS", "BRAINS")
+/mob/proc/grant_all_languages()
+ for(var/la in GLOB.all_languages)
+ add_language(la)
#undef SCRAMBLE_CACHE_LEN
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 82b98a3732e..21662714653 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -213,7 +213,6 @@
swap_hand()
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
- add_attack_logs(M, src, "Shaked", ATKLOG_ALL)
if(health >= HEALTH_THRESHOLD_CRIT)
if(src == M && ishuman(src))
check_self_for_injuries()
@@ -222,6 +221,7 @@
M.visible_message("[M] shakes [src], but [p_they()] [p_do()] not respond. Probably suffering from SSD.", \
"You shake [src], but [p_theyre()] unresponsive. Probably suffering from SSD.")
if(lying) // /vg/: For hugs. This is how update_icon figgers it out, anyway. - N3X15
+ add_attack_logs(M, src, "Shaked", ATKLOG_ALL)
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.w_uniform)
@@ -1000,7 +1000,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
else
if(!forceFed(toEat, user, fullness))
return 0
- consume(toEat, bitesize_override, taste = toEat.taste)
+ consume(toEat, bitesize_override, can_taste_container = toEat.can_taste)
score_foodeaten++
return 1
@@ -1051,7 +1051,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
/*TO DO - If/when stomach organs are introduced, override this at the human level sending the item to the stomach
so that different stomachs can handle things in different ways VB*/
-/mob/living/carbon/proc/consume(var/obj/item/reagent_containers/food/toEat, var/bitesize_override, var/taste = TRUE)
+/mob/living/carbon/proc/consume(var/obj/item/reagent_containers/food/toEat, var/bitesize_override, var/can_taste_container = TRUE)
var/this_bite = bitesize_override ? bitesize_override : toEat.bitesize
if(!toEat.reagents)
return
@@ -1060,8 +1060,8 @@ so that different stomachs can handle things in different ways VB*/
if(toEat.consume_sound)
playsound(loc, toEat.consume_sound, rand(10,50), 1)
if(toEat.reagents.total_volume)
- if(taste)
- taste_reagents(toEat.reagents)
+ if(can_taste_container)
+ taste(toEat.reagents)
var/fraction = min(this_bite/toEat.reagents.total_volume, 1)
toEat.reagents.reaction(src, toEat.apply_type, fraction)
toEat.reagents.trans_to(src, this_bite*toEat.transfer_efficiency)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 7b8790076ce..c583d9873b6 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -16,7 +16,7 @@
/mob/living/carbon/water_act(volume, temperature, source, method = TOUCH)
. = ..()
- if(volume > 10) //anything over 10 volume will make the mob wetter.
+ if(volume > 10) // Anything over 10 volume will make the mob wetter.
wetlevel = min(wetlevel + 1,5)
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 219ba9ca9eb..c23db2f5501 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -858,14 +858,10 @@
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
if("fart", "farts")
- if(locate(/obj/item/storage/bible) in get_turf(src))
- to_chat(viewers(src), "[src] farts on the Bible!")
- var/image/cross = image('icons/obj/storage.dmi', "bible")
- var/adminbfmessage = "[bicon(cross)] Bible Fart: [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) (CA) (SMITE):"
- for(var/client/X in GLOB.admins)
- if(check_rights(R_EVENT, 0, X.mob))
- to_chat(X, adminbfmessage)
- else
+ var/farted_on_thing = FALSE
+ for(var/atom/A in get_turf(src))
+ farted_on_thing += A.fart_act(src)
+ if(!farted_on_thing)
message = "[src] [pick("passes wind", "farts")]."
m_type = 2
@@ -947,7 +943,7 @@
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client)
- continue
+ continue
if(isnewplayer(M))
continue
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 4aef44444e9..1862fe5cffa 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -390,7 +390,7 @@
S = H.glasses
return !istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/security) && S && S.read_only
if("medical")
- return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.glasses, /obj/item/clothing/glasses/hud/health/health_advanced) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical)
+ return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical)
else
return 0
else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0cd4b176e0b..b3d320de913 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -34,9 +34,6 @@
handcrafting = new()
- var/mob/M = src
- faction |= "\ref[M]" //what
-
// Set up DNA.
if(dna)
dna.ready_dna(src)
@@ -106,6 +103,9 @@
/mob/living/carbon/human/diona/Initialize(mapload)
..(mapload, /datum/species/diona)
+/mob/living/carbon/human/pod_diona/Initialize(mapload)
+ ..(mapload, /datum/species/diona/pod)
+
/mob/living/carbon/human/machine/Initialize(mapload)
..(mapload, /datum/species/machine)
@@ -165,7 +165,11 @@
show_stat_emergency_shuttle_eta()
if(client.statpanel == "Status")
- if(locate(/obj/item/assembly/health) in src)
+ var/total_user_contents = GetAllContents() // cache it
+ if(locate(/obj/item/gps) in total_user_contents)
+ var/turf/T = get_turf(src)
+ stat(null, "GPS: [COORD(T)]")
+ if(locate(/obj/item/assembly/health) in total_user_contents)
stat(null, "Health: [health]")
if(internal)
if(!internal.air_contents)
@@ -849,7 +853,7 @@
return
var/read = 0
var/perpname = get_visible_name(TRUE)
-
+
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.medical)
@@ -1096,17 +1100,22 @@
var/limb_path = organ_data["path"]
var/obj/item/organ/external/O = new limb_path(temp_holder)
if(H.get_limb_by_name(O.name)) //Check to see if the user already has an limb with the same name as the 'missing limb'. If they do, skip regrowth.
- continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since,
- //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name.
+ continue //In an example, this will prevent duplication of the mob's right arm if the mob is a Human and they have a Diona right arm, since,
+ //while the limb with the name 'right_arm' the mob has may not be listed in their species' bodyparts definition, it is still viable and has the appropriate limb name.
else
O = new limb_path(H) //Create the limb on the player.
O.owner = H
H.bodyparts |= H.bodyparts_by_name[O.limb_name]
+ if(O.body_part == HEAD) //They're sprouting a fresh head so lets hook them up with their genetic stuff so their new head looks like the original.
+ H.UpdateAppearance()
//Replacing lost organs with the species default.
temp_holder = new /mob/living/carbon/human()
- for(var/index in H.dna.species.has_organ)
- var/organ = H.dna.species.has_organ[index]
+ var/list/species_organs = H.dna.species.has_organ.Copy() //Compile a list of species organs and tack on the mutantears afterward.
+ if(H.dna.species.mutantears)
+ species_organs["ears"] = H.dna.species.mutantears
+ for(var/index in species_organs)
+ var/organ = species_organs[index]
if(!(organ in types_of_int_organs)) //If the mob is missing this particular organ...
var/obj/item/organ/internal/I = new organ(temp_holder) //Create the organ inside our holder so we can check it before implantation.
if(H.get_organ_slot(I.slot)) //Check to see if the user already has an organ in the slot the 'missing organ' belongs to. If they do, skip implantation.
@@ -1470,12 +1479,12 @@
var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes)
var/obj/item/organ/internal/cyberimp/eyes/eye_implant = get_int_organ(/obj/item/organ/internal/cyberimp/eyes)
if(istype(dna.species) && dna.species.eyes)
- var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', dna.species.eyes)
+ var/icon/eyes_icon = new /icon('icons/mob/human_face.dmi', dna.species.eyes)
if(eye_implant) //Eye implants override native DNA eye colo(u)r
eyes_icon = eye_implant.generate_icon()
else if(eyes)
eyes_icon = eyes.generate_icon()
- else
+ else //Error 404: Eyes not found!
eyes_icon.Blend("#800000", ICON_ADD)
return eyes_icon
@@ -1484,8 +1493,8 @@
var/obj/item/organ/external/head/head_organ = get_organ("head")
var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style]
var/icon/hair = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
- var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = LIGHTING_LAYER + 1)
- MA.plane = LIGHTING_PLANE
+ var/mutable_appearance/MA = mutable_appearance(get_icon_difference(get_eyecon(), hair), layer = ABOVE_LIGHTING_LAYER)
+ MA.plane = ABOVE_LIGHTING_PLANE
return MA //Cut the hair's pixels from the eyes icon so eyes covered by bangs stay hidden even while on a higher layer.
/*Used to check if eyes should shine in the dark. Returns the image of the eyes on the layer where they will appear to shine.
@@ -1886,12 +1895,6 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
.["Make superhero"] = "?_src_=vars;makesuper=[UID()]"
. += "---"
-/mob/living/carbon/human/get_taste_sensitivity()
- if(dna.species)
- return dna.species.taste_sensitivity
- else
- return 1
-
/mob/living/carbon/human/proc/special_post_clone_handling()
if(mind && mind.assigned_role == "Cluwne") //HUNKE your suffering never stops
makeCluwne()
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index e106d214fd3..762df8d3b8b 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -202,6 +202,16 @@
amount = amount * dna.species.tox_mod
. = ..()
+/mob/living/carbon/human/adjustStaminaLoss(amount, updating = TRUE)
+ if(dna.species && amount > 0)
+ amount = amount * dna.species.stamina_mod
+ . = ..()
+
+/mob/living/carbon/human/setStaminaLoss(amount, updating = TRUE)
+ if(dna.species && amount > 0)
+ amount = amount * dna.species.stamina_mod
+ . = ..()
+
////////////////////////////////////////////
//Returns a list of damaged organs
@@ -334,56 +344,5 @@ This function restores all organs.
//Handle BRUTE and BURN damage
handle_suit_punctures(damagetype, damage)
-
- blocked = (100 - blocked) / 100
- if(blocked <= 0)
- return 0
-
- var/obj/item/organ/external/organ = null
- if(isorgan(def_zone))
- organ = def_zone
- else
- if(!def_zone)
- def_zone = ran_zone(def_zone)
- organ = get_organ(check_zone(def_zone))
- if(!organ)
- return 0
-
- damage = damage * blocked
-
- switch(damagetype)
- if(BRUTE)
- damageoverlaytemp = 20
- if(dna.species)
- damage = damage * dna.species.brute_mod
-
- if(organ.receive_damage(damage, 0, sharp, used_weapon))
- UpdateDamageIcon()
-
- if(LAssailant && ishuman(LAssailant)) //superheros still get the comical hit markers
- var/mob/living/carbon/human/H = LAssailant
- if(H.mind && H.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts))
- var/list/attack_bubble_recipients = list()
- var/mob/living/user
- for(var/mob/O in viewers(user, src))
- if(O.client && O.has_vision(information_only=TRUE))
- attack_bubble_recipients.Add(O.client)
- spawn(0)
- var/image/dmgIcon = image('icons/effects/hit_blips.dmi', src, "dmg[rand(1,2)]",MOB_LAYER+1)
- dmgIcon.pixel_x = (!lying) ? rand(-3,3) : rand(-11,12)
- dmgIcon.pixel_y = (!lying) ? rand(-11,9) : rand(-10,1)
- flick_overlay(dmgIcon, attack_bubble_recipients, 9)
-
-
- if(BURN)
- damageoverlaytemp = 20
-
- if(dna.species)
- damage = damage * dna.species.burn_mod
-
- if(organ.receive_damage(0, damage, sharp, used_weapon))
- UpdateDamageIcon()
-
- // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
- updatehealth("apply damage")
- return 1
+ //Handle species apply_damage procs
+ return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, sharp, used_weapon)
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 925e979c11d..b6bf5b34bac 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -11,10 +11,11 @@
//Do we have a working jetpack?
var/obj/item/tank/jetpack/thrust
- if(istype(back,/obj/item/tank/jetpack))
+ if(istype(back, /obj/item/tank/jetpack))
thrust = back
- else if(istype(s_store,/obj/item/tank/jetpack))
- thrust = s_store
+ else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
+ var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
+ thrust = C.jetpack
else if(istype(back,/obj/item/rig))
var/obj/item/rig/rig = back
for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules)
@@ -63,7 +64,8 @@
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
- createFootprintsFrom(shoes, dir, T)
+ if(S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
+ createFootprintsFrom(shoes, dir, T)
update_inv_shoes()
else if(hasfeet)
if(bloody_feet && bloody_feet[blood_state])
@@ -72,7 +74,8 @@
return
else
bloody_feet[blood_state] = max(0, bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP)
- createFootprintsFrom(src, dir, T)
+ if(bloody_feet[blood_state] > BLOOD_LOSS_IN_SPREAD)
+ createFootprintsFrom(src, dir, T)
update_inv_shoes()
//End bloody footprints
if(S)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index d6c667b1b74..fe048fb8137 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -14,7 +14,6 @@
handle_heartbeat()
handle_drunk()
dna.species.handle_life(src)
-
if(!client)
dna.species.handle_npc(src)
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index 438d3386948..dbb7b8731fc 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -50,10 +50,12 @@
var/oxy_mod = 1 // Oxy damage reduction/amplification
var/clone_mod = 1 // Clone damage reduction/amplification
var/brain_mod = 1 // Brain damage damage reduction/amplification
+ var/stamina_mod = 1
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
-
+ var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
+ var/armor = 0 // overall defense for the race... or less defense, if it's negative.
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
-
+ var/obj/item/mutanthands
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -63,8 +65,6 @@
var/ventcrawler = 0 //Determines if the mob can go through the vents.
var/has_fine_manipulation = 1 // Can use small items.
- var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species
-
var/list/allowed_consumed_mobs = list() //If a species can consume mobs, put the type of mobs it can consume here.
var/list/species_traits = list()
@@ -307,6 +307,63 @@
/datum/species/proc/handle_death(mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns).
return
+/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/C)
+ return
+
+/datum/species/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, mob/living/carbon/human/H, sharp = 0, obj/used_weapon = null)
+ blocked = (100 - blocked) / 100
+ if(blocked <= 0)
+ return 0
+
+ var/obj/item/organ/external/organ = null
+ if(isorgan(def_zone))
+ organ = def_zone
+ else
+ if(!def_zone)
+ def_zone = ran_zone(def_zone)
+ organ = H.get_organ(check_zone(def_zone))
+ if(!organ)
+ return 0
+
+ damage = damage * blocked
+
+ switch(damagetype)
+ if(BRUTE)
+ H.damageoverlaytemp = 20
+ damage = damage * brute_mod
+
+ if(organ.receive_damage(damage, 0, sharp, used_weapon))
+ H.UpdateDamageIcon()
+
+ if(H.LAssailant && ishuman(H.LAssailant)) //superheros still get the comical hit markers
+ var/mob/living/carbon/human/A = H.LAssailant
+ if(A.mind && A.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts))
+ var/list/attack_bubble_recipients = list()
+ var/mob/living/user
+ for(var/mob/O in viewers(user, src))
+ if(O.client && O.has_vision(information_only=TRUE))
+ attack_bubble_recipients.Add(O.client)
+ spawn(0)
+ var/image/dmgIcon = image('icons/effects/hit_blips.dmi', src, "dmg[rand(1,2)]",MOB_LAYER+1)
+ dmgIcon.pixel_x = (!H.lying) ? rand(-3,3) : rand(-11,12)
+ dmgIcon.pixel_y = (!H.lying) ? rand(-11,9) : rand(-10,1)
+ flick_overlay(dmgIcon, attack_bubble_recipients, 9)
+
+
+ if(BURN)
+ H.damageoverlaytemp = 20
+ damage = damage * burn_mod
+
+ if(organ.receive_damage(0, damage, sharp, used_weapon))
+ H.UpdateDamageIcon()
+
+ // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
+ H.updatehealth("apply damage")
+ return 1
+
+/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
+ return
+
/datum/species/proc/spec_electrocute_act(mob/living/carbon/human/H, shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
return
@@ -733,8 +790,8 @@ It'll return null if the organ doesn't correspond, so include null checks when u
H.sync_lighting_plane_alpha()
/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source, method = TOUCH)
- if(abs(temperature - M.bodytemperature) > 10) //If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately
- M.bodytemperature = (temperature + M.bodytemperature) * 0.5 //Approximation for gradual heating or cooling
+ if(abs(temperature - M.bodytemperature) > 10) // If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately.
+ M.bodytemperature = (temperature + M.bodytemperature) * 0.5 // Approximation for gradual heating or cooling.
/datum/species/proc/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) //return TRUE if hit, FALSE if stopped/reflected/etc
return TRUE
diff --git a/code/modules/mob/living/carbon/human/species/diona.dm b/code/modules/mob/living/carbon/human/species/diona.dm
index bccbeb6c5a7..518ee94f8f0 100644
--- a/code/modules/mob/living/carbon/human/species/diona.dm
+++ b/code/modules/mob/living/carbon/human/species/diona.dm
@@ -7,21 +7,11 @@
speech_sounds = list('sound/voice/dionatalk1.ogg') //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16]
speech_chance = 20
unarmed_type = /datum/unarmed_attack/diona
- //primitive_form = "Nymph"
- slowdown = 5
remains_type = /obj/effect/decal/cleanable/ash
-
- warning_low_pressure = 50
- hazard_low_pressure = -1
-
- cold_level_1 = 50
- cold_level_2 = -1
- cold_level_3 = -1
-
- heat_level_1 = 300
- heat_level_2 = 340
- heat_level_3 = 400
+ burn_mod = 1.25
+ heatmod = 1.5
+ var/pod = FALSE //did they come from a pod? If so, they're stronger than normal Diona.
blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \
species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \
@@ -31,16 +21,14 @@
even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \
water and other radiation."
- species_traits = list(NO_BREATHE, RADIMMUNE, IS_PLANT, NO_BLOOD, NO_PAIN)
- dies_at_threshold = TRUE
+ species_traits = list(IS_PLANT)
clothing_flags = HAS_SOCKS
default_hair_colour = "#000000"
has_gender = FALSE
- dietflags = 0 //Diona regenerate nutrition in light and water, no diet necessary
- taste_sensitivity = TASTE_SENSITIVITY_NO_TASTE
+ dietflags = DIET_HERB //Diona regenerate nutrition in light and water, no diet necessary, but if they must, they eat other plants *scream
+ taste_sensitivity = TASTE_SENSITIVITY_DULL
skinned_type = /obj/item/stack/sheet/wood
- body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not
blood_color = "#004400"
flesh_color = "#907E4A"
butt_sprite = "diona"
@@ -49,6 +37,7 @@
has_organ = list(
"nutrient channel" = /obj/item/organ/internal/liver/diona,
+ "respiratory vacuoles" = /obj/item/organ/internal/lungs/diona,
"neural strata" = /obj/item/organ/internal/heart/diona,
"receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2.
"gas bladder" = /obj/item/organ/internal/brain/diona,
@@ -85,29 +74,47 @@
..()
H.gender = NEUTER
-/datum/species/diona/handle_life(mob/living/carbon/human/H)
- H.radiation = Clamp(H.radiation, 0, 100) //We have to clamp this first, then decrease it, or there's a few edge cases of massive heals if we clamp and decrease at the same time.
- var/rads = H.radiation / 25
- H.radiation = max(H.radiation-rads, 0)
- H.nutrition = min(H.nutrition+rads, NUTRITION_LEVEL_WELL_FED+10)
- H.adjustBruteLoss(-(rads))
- H.adjustToxLoss(-(rads))
+/datum/species/diona/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
+ if(R.id == "glyphosate" || R.id == "atrazine")
+ H.adjustToxLoss(3) //Deal aditional damage
+ return TRUE
+ return ..()
+/datum/species/diona/handle_life(mob/living/carbon/human/H)
+ if(H.stat == DEAD)
+ return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
- light_amount = min(T.get_lumcount() * 10, 5) //hardcapped so it's not abused by having a ton of flashlights
- H.nutrition = min(H.nutrition+light_amount, NUTRITION_LEVEL_WELL_FED+10)
+ light_amount = min(1, T.get_lumcount()) - 0.5
+ if(light_amount > 0)
+ H.clear_alert("nolight")
+ else
+ H.throw_alert("nolight", /obj/screen/alert/nolight)
+ H.nutrition += light_amount * 10
+ if(H.nutrition > NUTRITION_LEVEL_ALMOST_FULL)
+ H.nutrition = NUTRITION_LEVEL_ALMOST_FULL
+ if(light_amount > 0.2 && !H.suiciding) //if there's enough light, heal
+ if(!pod && H.health <= 0)
+ return
+ H.adjustBruteLoss(-1)
+ H.adjustFireLoss(-1)
+ H.adjustToxLoss(-1)
+ H.adjustOxyLoss(-1)
- if(light_amount > 0)
- H.clear_alert("nolight")
- else
- H.throw_alert("nolight", /obj/screen/alert/nolight)
-
- if((light_amount >= 5) && !H.suiciding) //if there's enough light, heal
-
- H.adjustBruteLoss(-(light_amount/2))
- H.adjustFireLoss(-(light_amount/4))
- if(H.nutrition < NUTRITION_LEVEL_STARVING+50)
- H.take_overall_damage(10,0)
+ if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
+ H.adjustBruteLoss(2)
..()
+
+/datum/species/diona/pod //Same name and everything; we want the same limitations on them; we just want their regeneration to kick in at all times and them to have special factions
+ pod = TRUE
+
+/datum/species/diona/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ C.faction |= "plants"
+ C.faction |= "vines"
+
+/datum/species/diona/pod/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ C.faction -= "plants"
+ C.faction -= "vines"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index c1e416a8a48..9d74e7e2130 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -251,28 +251,44 @@
attack_verb = list("smash")
attack_sound = 'sound/effects/meteorimpact.ogg'
-//More resistant to burn damage
-//Add ashstorm resistance if we ever port lavaland
+//More resistant to burn damage and immune to ashstorm
/datum/species/golem/titanium
name = "Titanium Golem"
golem_colour = rgb(255, 255, 255)
skinned_type = /obj/item/stack/ore/titanium
- info_text = "As a Titanium Golem, you are resistant to burn damage."
+ info_text = "As a Titanium Golem, you are resistant to burn damage and immune to ash storms."
burn_mod = 0.3
prefix = "Titanium"
special_names = list("Dioxide")
-//Even more resistant to burn damage
-//Add ashstorm and lava resistance if we ever port lavaland
+/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ C.weather_immunities |= "ash"
+
+/datum/species/golem/titanium/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ C.weather_immunities -= "ash"
+
+//Even more resistant to burn damage and immune to ashstorms and lava
/datum/species/golem/plastitanium
name = "Plastitanium Golem"
golem_colour = rgb(136, 136, 136)
skinned_type = /obj/item/stack/ore/titanium
- info_text = "As a Plastitanium Golem, you are very resistant to burn damage."
+ info_text = "As a Plastitanium Golem, you are very resistant to burn damage and immune to both ash storms and lava."
burn_mod = 0.15
prefix = "Plastitanium"
special_names = null
+/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ C.weather_immunities |= "lava"
+ C.weather_immunities |= "ash"
+
+/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ C.weather_immunities -= "ash"
+ C.weather_immunities -= "lava"
+
//Fast and regenerates... but can only speak like an abductor
/datum/species/golem/alloy
name = "Alien Alloy Golem"
@@ -357,10 +373,12 @@
/datum/species/golem/uranium/handle_life(mob/living/carbon/human/H)
for(var/mob/living/L in range(2, H))
- if(isgolem(H))
- continue
- to_chat(L, "You are enveloped by a soft green glow emanating from [H].")
- L.apply_effect(10, IRRADIATE)
+ if(ishuman(L))
+ var/mob/living/carbon/human/I = L
+ if(!(RADIMMUNE in I.dna.species.species_traits))
+ L.apply_effect(10, IRRADIATE)
+ if(prob(25)) //reduce spam
+ to_chat(L, "You are enveloped by a soft green glow emanating from [H].")
..()
//Ventcrawler
@@ -592,7 +610,7 @@
punchdamagehigh = 0
punchstunthreshold = 1 //Harmless and can't stun
skinned_type = /obj/item/stack/ore/bananium
- info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and you can barely even hurt people when punching them. Your skin also bleeds banana peels when damaged."
+ info_text = "As a Bananium Golem, you are made for pranking. Your body emits natural honks, and punching people will just harmlessly honk them. Your skin also bleeds banana peels when damaged."
prefix = "Bananium"
special_names = null
unarmed_type = /datum/unarmed_attack/golem/bananium
@@ -610,6 +628,12 @@
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
+ H.AddComponent(/datum/component/waddling)
+
+/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ GET_COMPONENT_FROM(waddling, /datum/component/waddling, C)
+ waddling.Destroy()
/datum/species/golem/bananium/get_random_name()
var/clown_name = pick(GLOB.clown_names)
diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm
index 3b8bbe34ffb..fd8fc09fd4d 100644
--- a/code/modules/mob/living/carbon/human/species/grey.dm
+++ b/code/modules/mob/living/carbon/human/species/grey.dm
@@ -40,15 +40,15 @@
. = ..()
if(method == TOUCH)
+ if(H.wear_mask)
+ to_chat(H, "Your [H.wear_mask] protects you from the acid!")
+ return
+
+ if(H.head)
+ to_chat(H, "Your [H.wear_mask] protects you from the acid!")
+ return
+
if(volume > 25)
- if(H.wear_mask)
- to_chat(H, "Your [H.wear_mask] protects you from the acid!")
- return
-
- if(H.head)
- to_chat(H, "Your [H.wear_mask] protects you from the acid!")
- return
-
if(prob(75))
H.take_organ_damage(5, 10)
H.emote("scream")
@@ -65,9 +65,6 @@
H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20))
H.emote("scream")
to_chat(H, "The water stings[volume < 10 ? " you, but isn't concentrated enough to harm you" : null]!")
- if(volume >= 10)
- H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20))
- H.emote("scream")
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
var/translator_pref = H.client.prefs.speciesprefs
diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm
index b75132c7bc6..e4ba4349202 100644
--- a/code/modules/mob/living/carbon/human/species/plasmaman.dm
+++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm
@@ -116,7 +116,7 @@
if("Chief Engineer")
O = new /datum/outfit/plasmaman/ce
- if("Atmospheric Technician")
+ if("Life Support Specialist")
O = new /datum/outfit/plasmaman/atmospherics
if("Mime")
diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm
index fb7fd2ebda1..b21002e7225 100644
--- a/code/modules/mob/living/carbon/human/species/shadow.dm
+++ b/code/modules/mob/living/carbon/human/species/shadow.dm
@@ -8,8 +8,6 @@
unarmed_type = /datum/unarmed_attack/claws
- ignored_by = list(/mob/living/simple_animal/hostile/faithless)
-
blood_color = "#CCCCCC"
flesh_color = "#AAAAAA"
has_organ = list(
@@ -51,12 +49,14 @@
if(grant_vision_toggle)
vision_toggle = new
vision_toggle.Grant(H)
+ H.faction |= "faithless"
/datum/species/shadow/on_species_loss(mob/living/carbon/human/H)
..()
if(grant_vision_toggle && vision_toggle)
H.vision_type = null
vision_toggle.Remove(H)
+ H.faction -= "faithless"
/datum/species/shadow/handle_life(mob/living/carbon/human/H)
var/light_amount = 0
diff --git a/code/modules/mob/living/carbon/human/species/zombies.dm b/code/modules/mob/living/carbon/human/species/zombies.dm
new file mode 100644
index 00000000000..6ff30c54a67
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/species/zombies.dm
@@ -0,0 +1,91 @@
+#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
+
+/datum/species/zombie
+ // 1spooky
+ name = "High-Functioning Zombie"
+ name_plural = "High-Functioning Zombies"
+ icobase = 'icons/mob/human_races/r_zombie.dmi'
+ deform = 'icons/mob/human_races/r_def_zombie.dmi'
+ dies_at_threshold = TRUE
+ language = "Zombie"
+ species_traits = list(NO_BLOOD,NOZOMBIE,NOTRANSSTING,NO_BREATHE, RADIMMUNE, NO_SCAN)
+ var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
+ warning_low_pressure = 50
+ hazard_low_pressure = 0
+ flesh_color = "#00FF00" // for green examine text
+ bodyflags = HAS_SKIN_COLOR
+ dietflags = DIET_CARN
+ has_organ = list(
+ "heart" = /obj/item/organ/internal/heart,
+ "lungs" = /obj/item/organ/internal/lungs,
+ "liver" = /obj/item/organ/internal/liver,
+ "kidneys" = /obj/item/organ/internal/kidneys,
+ "brain" = /obj/item/organ/internal/brain,
+ "appendix" = /obj/item/organ/internal/appendix,
+ "eyes" = /obj/item/organ/internal/eyes,
+ "ears" = /obj/item/organ/internal/ears,
+ "zombie_infection" = /obj/item/organ/internal/zombie_infection)
+
+
+/datum/species/zombie/infectious
+ name = "Infectious Zombie"
+ mutanthands = /obj/item/zombie_hand
+ icobase = 'icons/mob/human_races/r_zombie.dmi'
+ deform = 'icons/mob/human_races/r_def_zombie.dmi'
+ armor = 20 // 120 damage to KO a zombie, which kills it
+ speedmod = 1.6
+ default_language = "Zombie"
+ var/heal_rate = 1
+ var/regen_cooldown = 0
+
+/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H, amount)
+ . = min(20, amount)
+
+/datum/species/zombie/infectious/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
+ . = ..()
+ if(damage)
+ regen_cooldown = world.time + REGENERATION_DELAY
+
+/datum/species/zombie/infectious/handle_life(mob/living/carbon/human/C)
+ . = ..()
+ //Zombies never actually die, they just fall down until they regenerate enough to rise back up.
+ //They must be restrained, beheaded or gibbed to stop being a threat.
+ if(regen_cooldown < world.time)
+ var/heal_amt = heal_rate
+ if(C.InCritical())
+ heal_amt *= 2
+ C.heal_overall_damage(heal_amt,heal_amt)
+ C.adjustToxLoss(-heal_amt)
+ if(!C.InCritical() && prob(4))
+ playsound(C, pick(spooks), 50, TRUE, 10)
+
+//Congrats you somehow died so hard you stopped being a zombie
+/datum/species/zombie/infectious/spec_death(gibbed, mob/living/carbon/C)
+ . = ..()
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = C.get_organ_slot("zombie_infection")
+ if(infection)
+ qdel(infection)
+
+/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
+ . = ..()
+ // Deal with the source of this zombie corruption
+ // Infection organ needs to be handled separately from mutant_organs
+ // because it persists through species transitions
+ if(mutanthands)
+ C.drop_l_hand()
+ C.drop_r_hand()
+ C.put_in_hands(new mutanthands())
+ C.put_in_hands(new mutanthands())
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = C.get_organ_slot("zombie_infection")
+ if(!infection)
+ infection = new()
+ infection.insert(C)
+
+/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/human/C, datum/species/old_species)
+ QDEL_NULL(C.r_hand)
+ QDEL_NULL(C.l_hand)
+ return ..()
+
+#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index 379eb183292..818e15f26e8 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -5,21 +5,29 @@
. = ..()
/mob/living/carbon/human/SetStunned(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
return ..()
/mob/living/carbon/human/SetWeakened(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
return ..()
/mob/living/carbon/human/SetParalysis(amount, updating = 1, force = 0)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
+ else
+ amount = dna.species.spec_stun(src,amount)
return ..()
/mob/living/carbon/human/SetSleeping(amount, updating = 1, no_alert = FALSE)
- if(dna.species)
+ if(dna.species.stun_mod)
amount = amount * dna.species.stun_mod
- return ..()
\ No newline at end of file
+ else
+ amount = dna.species.spec_stun(src,amount)
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index a682a61d68d..05dfbd0e302 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -1022,9 +1022,9 @@ var/global/list/damage_icon_parts = list()
t_state = r_hand.icon_state
var/mutable_appearance/standing
- if(r_hand.sprite_sheets && r_hand.sprite_sheets[dna.species.name])
+ if(r_hand.sprite_sheets_inhand && r_hand.sprite_sheets_inhand[dna.species.name])
t_state = "[t_state]_r"
- standing = mutable_appearance(r_hand.sprite_sheets[dna.species.name], "[t_state]", layer = -R_HAND_LAYER)
+ standing = mutable_appearance(r_hand.sprite_sheets_inhand[dna.species.name], "[t_state]", layer = -R_HAND_LAYER)
else
standing = mutable_appearance(r_hand.righthand_file, "[t_state]", layer = -R_HAND_LAYER)
standing = center_image(standing, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension)
@@ -1041,9 +1041,9 @@ var/global/list/damage_icon_parts = list()
t_state = l_hand.icon_state
var/mutable_appearance/standing
- if(l_hand.sprite_sheets && l_hand.sprite_sheets[dna.species.name])
+ if(l_hand.sprite_sheets_inhand && l_hand.sprite_sheets_inhand[dna.species.name])
t_state = "[t_state]_l"
- standing = mutable_appearance(l_hand.sprite_sheets[dna.species.name], "[t_state]", layer = -L_HAND_LAYER)
+ standing = mutable_appearance(l_hand.sprite_sheets_inhand[dna.species.name], "[t_state]", layer = -L_HAND_LAYER)
else
standing = mutable_appearance(l_hand.lefthand_file, "[t_state]", layer = -L_HAND_LAYER)
standing = center_image(standing, l_hand.inhand_x_dimension, l_hand.inhand_y_dimension)
diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm
index 38dadbbbfa7..ddab7eae1ee 100644
--- a/code/modules/mob/living/carbon/slime/slime.dm
+++ b/code/modules/mob/living/carbon/slime/slime.dm
@@ -510,13 +510,15 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/toggle_throw_mode()
return
-/mob/living/carbon/slime/proc/apply_water()
- adjustToxLoss(rand(15,20))
- if(!client)
- if(Target) // Like cats
- Target = null
- ++Discipline
- return
+/mob/living/carbon/slime/water_act(volume, temperature, source, method = TOUCH)
+ . = ..()
+
+ var/water_damage = rand(10, 15) * volume
+ adjustToxLoss(water_damage)
+
+ if(!client && Target && volume >= 3)
+ Target = null
+ ++Discipline
/mob/living/carbon/slime/can_use_vents()
if(Victim)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 57c67f5fd61..cd20656254f 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -2,6 +2,7 @@
. = ..()
var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED]
medhud.add_to_hud(src)
+ faction += "\ref[src]"
/mob/living/prepare_huds()
..()
@@ -256,10 +257,10 @@
death()
to_chat(src, "You have given up life and succumbed to death.")
-
+
/mob/living/proc/InCritical()
return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS)
-
+
/mob/living/ex_act(severity)
..()
@@ -916,44 +917,6 @@
if(pulling && !(pulling in orange(1)))
stop_pulling()
-/mob/living/proc/get_taste_sensitivity()
- return 1
-
-/mob/living/proc/taste_reagents(datum/reagents/tastes)
- if(!get_taste_sensitivity())//this also works for IPCs and stuff that returns 0 here
- return
-
- var/do_not_taste_at_all = 1//so we don't spam with recent tastes
-
- var/taste_sum = 0
- var/list/taste_list = list()//associative list so we can stack stuff that tastes the same
- var/list/final_taste_list = list()//final list of taste strings
-
- for(var/datum/reagent/R in tastes.reagent_list)
- taste_sum += R.volume * R.taste_strength
- if(!R.taste_message)//set to null; no taste, like water
- continue
- taste_list[R.taste_message] += R.volume * R.taste_strength
-
- for(var/R in taste_list)
- if(recent_tastes[R] && (world.time - recent_tastes[R] < 12 SECONDS))
- continue
-
- do_not_taste_at_all = 0//something was fresh enough to taste; could still be bland enough to be unrecognizable
-
- if(taste_list[R] / taste_sum >= 0.15 / get_taste_sensitivity())//we return earlier if the proc returns a 0; won't break the universe
- final_taste_list += R
- recent_tastes[R] = world.time
-
- if(do_not_taste_at_all)
- return //no message spam
-
- if(final_taste_list.len == 0)//too many reagents - none meet their thresholds
- to_chat(src, "You can't really make out what you're tasting...")
- return
-
- to_chat(src, "You can taste [english_list(final_taste_list)].")
-
/mob/living/proc/update_z(new_z) // 1+ to register, null to unregister
if(registered_z != new_z)
if(registered_z)
diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm
index b49aa82625c..2eca24104cd 100644
--- a/code/modules/mob/living/silicon/laws.dm
+++ b/code/modules/mob/living/silicon/laws.dm
@@ -70,6 +70,13 @@
if(!silent && !isnull(usr))
log_and_message_admins("cleared the supplied laws of [src]")
+/mob/living/silicon/proc/clear_zeroth_law(var/silent = FALSE)
+ throw_alert("newlaw", /obj/screen/alert/newlaw)
+ laws_sanity_check()
+ laws.clear_zeroth_laws()
+ if(!silent && !isnull(usr))
+ log_and_message_admins("cleared the zeroth law of [src]")
+
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
var/prefix = ""
if(MAIN_CHANNEL == lawchannel)
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 636df89885d..20f6155ba0f 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -1,10 +1,26 @@
+/mob/living/simple_animal/attackby(obj/item/O, mob/living/user)
+ if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar))
+ var/obj/item/clothing/accessory/petcollar/C = O
+ if(user.drop_item())
+ C.forceMove(src)
+ collar = C
+ collar.equipped(src)
+ regenerate_icons()
+ to_chat(usr, "You put \the [C] around \the [src]'s neck.")
+ if(C.tagname)
+ name = C.tagname
+ real_name = C.tagname
+ return
+ else
+ return ..()
+
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
..()
switch(M.a_intent)
if(INTENT_HELP)
if(health > 0)
- visible_message("[M] [response_help] [src].")
+ visible_message("[M] [response_help] [src].", "[M] [response_help] you.")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(INTENT_GRAB)
@@ -12,12 +28,12 @@
if(INTENT_HARM, INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
- visible_message("[M] [response_harm] [src]!")
+ visible_message("[M] [response_harm] [src]!", "[M] [response_harm] you!")
playsound(loc, attacked_sound, 25, 1, -1)
attack_threshold_check(harm_intent_damage)
add_attack_logs(M, src, "Melee attacked with fists")
updatehealth()
- return 1
+ return TRUE
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
@@ -39,10 +55,11 @@
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite
- var/damage = rand(5, 10)
if(stat != DEAD)
- L.amount_grown = min(L.amount_grown + damage, L.max_grown)
- attack_threshold_check(damage)
+ var/damage = rand(5, 10)
+ . = attack_threshold_check(damage)
+ if(.)
+ L.amount_grown = min(L.amount_grown + damage, L.max_grown)
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
if(..())
@@ -51,21 +68,57 @@
/mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M)
..()
- var/damage = rand(1, 3)
-
+ var/damage = rand(15, 25)
if(M.is_adult)
- damage = rand(20, 40)
- else
- damage = rand(5, 35)
-
+ damage = rand(20, 35)
attack_threshold_check(damage)
- return
-/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE)
- if(damage <= force_threshold || !damage_coeff[damagetype])
- visible_message("[src] looks unharmed.")
+/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = "melee")
+ var/temp_damage = damage
+ if(!damage_coeff[damagetype])
+ temp_damage = 0
else
- apply_damage(damage, damagetype)
+ temp_damage *= damage_coeff[damagetype]
+
+ if(temp_damage >= 0 && temp_damage <= force_threshold)
+ visible_message("[src] looks unharmed.")
+ return FALSE
+ else
+ apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
+ return TRUE
+
+/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
+ if(!Proj)
+ return
+ apply_damage(Proj.damage, Proj.damage_type)
+ Proj.on_hit(src, 0)
+ return FALSE
+
+/mob/living/simple_animal/ex_act(severity, origin)
+ if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
+ return
+ ..()
+ var/bomb_armor = getarmor(null, "bomb")
+ switch(severity)
+ if(1)
+ if(prob(bomb_armor))
+ adjustBruteLoss(500)
+ else
+ gib()
+ return
+ if(2)
+ var/bloss = 60
+ if(prob(bomb_armor))
+ bloss = bloss / 1.5
+ adjustBruteLoss(bloss)
+ if(3)
+ var/bloss = 30
+ if(prob(bomb_armor))
+ bloss = bloss / 1.5
+ adjustBruteLoss(bloss)
+
+/mob/living/simple_animal/blob_act(obj/structure/blob/B)
+ adjustBruteLoss(20)
/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 4793b91dee6..76f88220eda 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -241,10 +241,10 @@
else
to_chat(user, "[src] is in pristine condition.")
-/mob/living/simple_animal/bot/adjustHealth(amount)
+/mob/living/simple_animal/bot/adjustHealth(amount, updating_health = TRUE)
if(amount > 0 && prob(10))
new /obj/effect/decal/cleanable/blood/oil(loc)
- return ..(amount)
+ . = ..()
/mob/living/simple_animal/bot/updatehealth(reason = "none given")
..(reason)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index d5fabe96be4..3a26265466b 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -217,7 +217,7 @@
/mob/living/simple_animal/hostile/construct/builder/Found(atom/A) //what have we found here?
- if(istype(A, /mob/living/simple_animal/hostile/construct)) //is it a construct?
+ if(isconstruct(A)) //is it a construct?
var/mob/living/simple_animal/hostile/construct/C = A
if(C.health < C.maxHealth) //is it hurt? let's go heal it if it is
return 1
@@ -236,7 +236,7 @@
..()
if(isliving(target))
var/mob/living/L = target
- if(istype(L, /mob/living/simple_animal/hostile/construct) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it
+ if(isconstruct(L) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it
LoseTarget()
return 0
if(L.health <= melee_damage_lower+melee_damage_upper) //ey bucko you're hurt as fuck let's go hit you
@@ -245,7 +245,7 @@
/mob/living/simple_animal/hostile/construct/builder/Aggro()
..()
- if(istype(target, /mob/living/simple_animal/hostile/construct)) //oh the target is a construct no need to flee
+ if(isconstruct(target)) //oh the target is a construct no need to flee
retreat_distance = null
minimum_distance = 1
@@ -256,7 +256,7 @@
/mob/living/simple_animal/hostile/construct/builder/hostile //actually hostile, will move around, hit things, heal other constructs
AIStatus = AI_ON
- environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
+ environment_smash = ENVIRONMENT_SMASH_STRUCTURES //only token destruction, don't smash the cult wall NO STOP
/////////////////////////////Behemoth/////////////////////////
diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm
new file mode 100644
index 00000000000..6899b40bea0
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/damage_procs.dm
@@ -0,0 +1,37 @@
+
+/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE)
+ if(status_flags & GODMODE)
+ return FALSE
+ var/oldbruteloss = bruteloss
+ bruteloss = Clamp(bruteloss + amount, 0, maxHealth)
+ if(oldbruteloss == bruteloss)
+ updating_health = FALSE
+ . = STATUS_UPDATE_NONE
+ else
+ . = STATUS_UPDATE_HEALTH
+ if(updating_health)
+ updatehealth()
+
+/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE)
+ if(damage_coeff[BRUTE])
+ return adjustHealth(amount * damage_coeff[BRUTE], updating_health)
+
+/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE)
+ if(damage_coeff[BURN])
+ return adjustHealth(amount * damage_coeff[BURN], updating_health)
+
+/mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE)
+ if(damage_coeff[OXY])
+ return adjustHealth(amount * damage_coeff[OXY], updating_health)
+
+/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE)
+ if(damage_coeff[TOX])
+ return adjustHealth(amount * damage_coeff[TOX], updating_health)
+
+/mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE)
+ if(damage_coeff[CLONE])
+ return adjustHealth(amount * damage_coeff[CLONE], updating_health)
+
+/mob/living/simple_animal/adjustStaminaLoss(amount, updating_health = TRUE)
+ if(damage_coeff[STAMINA])
+ return ..(amount*damage_coeff[STAMINA], updating_health)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 4dea368ad5e..928cd9789da 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -94,26 +94,27 @@
new cat_type(loc)
-/mob/living/simple_animal/pet/cat/handle_automated_action()
+/mob/living/simple_animal/pet/cat/Life()
..()
- if(prob(1))
- custom_emote(1, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
- icon_state = "[icon_living]_rest"
- resting = 1
- update_canmove()
- else if (prob(1))
- custom_emote(1, pick("sits down.", "crouches on its hind legs.", "looks alert."))
- icon_state = "[icon_living]_sit"
- resting = 1
- update_canmove()
- else if (prob(1))
- if (resting)
- custom_emote(1, pick("gets up and meows.", "walks around.", "stops resting."))
- icon_state = "[icon_living]"
- resting = 0
+ make_babies()
+
+
+/mob/living/simple_animal/pet/cat/handle_automated_action()
+ if(!stat && !buckled)
+ if(prob(1))
+ custom_emote(1, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
+ StartResting()
+ else if(prob(1))
+ custom_emote(1, pick("sits down.", "crouches on its hind legs.", "looks alert."))
+ icon_state = "[icon_living]_sit"
+ resting = TRUE
update_canmove()
- else
- custom_emote(1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat."))
+ else if(prob(1))
+ if(resting)
+ custom_emote(1, pick("gets up and meows.", "walks around.", "stops resting."))
+ StopResting()
+ else
+ custom_emote(1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat."))
//MICE!
if(eats_mice && isturf(loc) && !incapacitated())
@@ -128,10 +129,9 @@
if(T.cooldown < (world.time - 400))
custom_emote(1, "bats \the [T] around with its paw!")
T.cooldown = world.time
- make_babies()
/mob/living/simple_animal/pet/cat/handle_automated_movement()
- ..()
+ . = ..()
if(!stat && !resting && !buckled)
turns_since_scan++
if(turns_since_scan > 5)
diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm
index d8f09f4cb78..c6a572e9679 100644
--- a/code/modules/mob/living/simple_animal/friendly/corgi.dm
+++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm
@@ -451,9 +451,8 @@
response_harm = "kicks"
gold_core_spawnable = CHEM_MOB_SPAWN_INVALID
-/mob/living/simple_animal/pet/corgi/Ian/Life()
- ..()
-
+/mob/living/simple_animal/pet/corgi/Ian/handle_automated_movement()
+ . = ..()
//Feeding, chasing food, FOOOOODDDD
if(!resting && !buckled)
turns_since_scan++
@@ -580,9 +579,10 @@
/mob/living/simple_animal/pet/corgi/Lisa/Life()
..()
-
make_babies()
+/mob/living/simple_animal/pet/corgi/Lisa/handle_automated_movement()
+ . = ..()
if(!resting && !buckled)
if(prob(1))
custom_emote(1, pick("dances around.","chases her tail."))
@@ -651,15 +651,16 @@
/mob/living/simple_animal/pet/corgi/Ian/borgi/Life(seconds, times_fired)
..()
- if(emagged && prob(25))
- var/mob/living/carbon/target = locate() in view(10,src)
- if(target)
- shootAt(target)
-
//spark for no reason
if(prob(5))
do_sparks(3, 1, src)
+/mob/living/simple_animal/pet/corgi/Ian/borgi/handle_automated_action()
+ if(emagged && prob(25))
+ var/mob/living/carbon/target = locate() in view(10, src)
+ if(target)
+ shootAt(target)
+
/mob/living/simple_animal/pet/corgi/Ian/borgi/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm
index 94ecb71703b..1456e2f70fb 100644
--- a/code/modules/mob/living/simple_animal/friendly/crab.dm
+++ b/code/modules/mob/living/simple_animal/friendly/crab.dm
@@ -17,8 +17,6 @@
stop_automated_movement = 1
friendly = "pinches"
ventcrawler = 2
- var/obj/item/inventory_head
- var/obj/item/inventory_mask
can_hide = 1
can_collar = 1
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
@@ -32,11 +30,6 @@
var/east_vs_west = pick(4, 8)
if(Process_Spacemove(east_vs_west))
Move(get_step(src, east_vs_west), east_vs_west)
- turns_since_move = 0
-
-/mob/living/simple_animal/crab/Life(seconds, times_fired)
- . = ..()
- regenerate_icons()
//COFFEE! SQUEEEEEEEEE!
/mob/living/simple_animal/crab/Coffee
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 bdb479997dc..0c9aa96728c 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -34,12 +34,11 @@
. = ..()
/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
- qdel(udder)
- udder = null
+ QDEL_NULL(udder)
return ..()
/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement()
- ..()
+ . = ..()
//chance to go crazy and start wacking stuff
if(!enemies.len && prob(1))
Retaliate()
@@ -49,14 +48,13 @@
LoseTarget()
visible_message("[src] calms down.")
- if(stat == CONSCIOUS)
- eat_plants()
- if(!pulledby)
- for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
- var/step = get_step(src, direction)
- if(step)
- if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
- Move(step, get_dir(src, step))
+ eat_plants()
+ if(!pulledby)
+ for(var/direction in shuffle(list(1, 2, 4, 8, 5, 6, 9, 10)))
+ var/step = get_step(src, direction)
+ if(step)
+ if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
+ Move(step, get_dir(src, step))
/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired)
. = ..()
@@ -94,8 +92,8 @@
say("Nom")
/mob/living/simple_animal/hostile/retaliate/goat/AttackingTarget()
- ..()
- if(isdiona(target))
+ . = ..()
+ if(. && isdiona(target))
var/mob/living/carbon/human/H = target
var/obj/item/organ/external/NB = pick(H.bodyparts)
H.visible_message("[src] takes a big chomp out of [H]!", "[src] takes a big chomp out of your [NB.name]!")
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 2c9cbc355f7..ec9cb5cd884 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -56,28 +56,19 @@
visible_message("[src] chews through [C].")
/mob/living/simple_animal/mouse/handle_automated_speech()
- ..()
- if(prob(speak_chance))
- for(var/mob/M in view())
- M << squeak_sound
-
-/mob/living/simple_animal/mouse/Life(seconds, times_fired)
- . = ..()
- if(stat == UNCONSCIOUS)
- if(ckey || prob(1))
- stat = CONSCIOUS
- icon_state = "mouse_[mouse_color]"
- wander = 1
- else if(prob(5))
- emote("snuffles")
-
-/mob/living/simple_animal/mouse/Life()
..()
- if(prob(0.5) && !ckey)
- stat = UNCONSCIOUS
- icon_state = "mouse_[mouse_color]_sleep"
- wander = 0
- speak_chance = 0
+ if(prob(speak_chance) && !incapacitated())
+ playsound(src, squeak_sound, 100, 1)
+
+/mob/living/simple_animal/mouse/handle_automated_movement()
+ . = ..()
+ if(resting)
+ if(prob(1))
+ StopResting()
+ else if(prob(5))
+ custom_emote(2, "snuffles")
+ else if(prob(0.5))
+ StartResting()
/mob/living/simple_animal/mouse/New()
..()
@@ -119,7 +110,7 @@
desc = "It's toast."
death()
-/mob/living/simple_animal/mouse/death(gibbed)
+/mob/living/simple_animal/mouse/death(gibbed)
// Only execute the below if we successfully died
playsound(src, squeak_sound, 40, 1)
. = ..(gibbed)
diff --git a/code/modules/mob/living/simple_animal/friendly/pug.dm b/code/modules/mob/living/simple_animal/friendly/pug.dm
index 36ce34094a0..c7b52928e8a 100644
--- a/code/modules/mob/living/simple_animal/friendly/pug.dm
+++ b/code/modules/mob/living/simple_animal/friendly/pug.dm
@@ -19,13 +19,12 @@
see_in_dark = 5
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
-/mob/living/simple_animal/pet/pug/Life()
- ..()
-
+/mob/living/simple_animal/pet/pug/handle_automated_movement()
+ . = ..()
if(!resting && !buckled)
if(prob(1))
custom_emote(1, pick("chases its tail."))
spawn(0)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
+ for(var/i in list(1, 2, 4, 8, 4, 2, 1, 2, 4, 8, 4, 2, 1, 2, 4, 8, 4, 2))
dir = i
- sleep(1)
+ sleep(1)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 0aa148eb031..52f149f0775 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -158,7 +158,8 @@
if(istype(target, /obj/effect/decal/cleanable))
visible_message("\The [src] cleans up \the [target].")
qdel(target)
- return
+ return TRUE
var/atom/movable/M = target
M.clean_blood()
visible_message("\The [src] polishes \the [target].")
+ return TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm
index 2d16dcb3095..fdb05a51fd9 100644
--- a/code/modules/mob/living/simple_animal/hostile/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bat.dm
@@ -22,6 +22,9 @@
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
+ emote_taunt = list("flutters")
+ taunt_chance = 20
+
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
@@ -39,11 +42,6 @@
/mob/living/simple_animal/hostile/scarybat/Process_Spacemove(var/check_drift = 0)
return ..() //No drifting in space for space carp! //original comments do not steal
-/mob/living/simple_animal/hostile/scarybat/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "flutters towards [.]")
-
/mob/living/simple_animal/hostile/scarybat/Found(var/atom/A)//This is here as a potential override to pick a specific target if available
if(istype(A) && A == owner)
return 0
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index 8b814076720..cf084086ae7 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -137,12 +137,13 @@
if(target == beehome)
var/obj/structure/beebox/BB = target
forceMove(BB)
+ toggle_ai(AI_IDLE)
target = null
wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
return //no don't attack the goddamm box
else
- ..()
- if(isliving(target) && (!client || a_intent == INTENT_HARM))
+ . = ..()
+ if(. && isliving(target) && (!client || a_intent == INTENT_HARM))
var/mob/living/L = target
if(L.reagents)
if(beegent)
@@ -222,8 +223,8 @@
//leave pollination for the peasent bees
/mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget()
- ..()
- if(beegent && isliving(target))
+ . = ..()
+ if(. && beegent && isliving(target))
var/mob/living/L = target
beegent.reaction_mob(L, TOUCH)
L.reagents.add_reagent(beegent.id, rand(1, 5))
@@ -283,6 +284,14 @@
QDEL_NULL(queen)
return ..()
+/mob/living/simple_animal/hostile/poison/bees/consider_wakeup()
+ if(beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets
+ idle = min(100, ++idle)
+ if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
+ toggle_ai(AI_ON)
+ forceMove(beehome.drop_location())
+ else
+ ..()
//Syndicate Bees
/mob/living/simple_animal/hostile/poison/bees/syndi
@@ -327,8 +336,8 @@
return TRUE
/mob/living/simple_animal/hostile/poison/bees/syndi/AttackingTarget()
- ..()
- if(target && isliving(target))
+ . = ..()
+ if(. && target && isliving(target))
var/mob/living/L = target
if(L.stat)
LoseTarget()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 299677804e2..48021ad2593 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -10,6 +10,8 @@
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
+ emote_taunt = list("gnashes")
+ taunt_chance = 30
speed = 0
maxHealth = 25
health = 25
@@ -50,14 +52,9 @@
/mob/living/simple_animal/hostile/carp/Process_Spacemove(var/movement_dir = 0)
return 1 //No drifting in space for space carp! //original comments do not steal
-/mob/living/simple_animal/hostile/carp/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "gnashes at [.]!")
-
/mob/living/simple_animal/hostile/carp/AttackingTarget()
- ..()
- if(ishuman(target))
+ . = ..()
+ if(. && ishuman(target))
var/mob/living/carbon/human/H = target
H.adjustStaminaLoss(8)
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index f668312e88d..2b736ee7641 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -19,6 +19,8 @@
attacktext = "grips"
attack_sound = 'sound/hallucinations/growl1.ogg'
speak_emote = list("growls")
+ emote_taunt = list("wails")
+ taunt_chance = 25
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
@@ -29,14 +31,9 @@
/mob/living/simple_animal/hostile/faithless/Process_Spacemove(var/movement_dir = 0)
return 1
-/mob/living/simple_animal/hostile/faithless/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "wails at [.]!")
-
/mob/living/simple_animal/hostile/faithless/AttackingTarget()
- ..()
- if(iscarbon(target))
+ . = ..()
+ if(. && iscarbon(target))
var/mob/living/carbon/C = target
if(prob(12))
C.Weaken(3)
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 f28aed9dae8..258a1f1abe7 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -40,8 +40,8 @@
/mob/living/simple_animal/hostile/poison/giant_spider/AttackingTarget()
// This is placed here, NOT on /poison, because the other subtypes of /poison/ already override AttackingTarget() completely, and as such it would do nothing but confuse people there.
- ..()
- if(venom_per_bite > 0 && iscarbon(target) && (!client || a_intent == INTENT_HARM))
+ . = ..()
+ if(. && venom_per_bite > 0 && iscarbon(target) && (!client || a_intent == INTENT_HARM))
var/mob/living/carbon/C = target
var/inject_target = pick("chest", "head")
if(C.can_inject(null, 0, inject_target, 0))
@@ -76,19 +76,20 @@
venom_per_bite = 10
move_to_delay = 5
-/mob/living/simple_animal/hostile/poison/giant_spider/hunter/handle_automated_movement()
- if(AIStatus == AI_IDLE && !busy)
+/mob/living/simple_animal/hostile/poison/giant_spider/handle_automated_movement() //Hacky and ugly.
+ . = ..()
+ if(AIStatus == AI_IDLE)
//1% chance to skitter madly away
if(prob(1))
stop_automated_movement = 1
- Goto(pick(orange(20, src)), move_to_delay)
+ Goto(pick(urange(20, src, 1)), move_to_delay)
spawn(50)
stop_automated_movement = 0
walk(src,0)
else
..()
-/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(var/C)
+/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(C)
spawn(100)
if(busy == MOVING_TO_TARGET)
if(cocoon_target == C && get_dist(src,cocoon_target) > 1)
@@ -96,13 +97,13 @@
busy = 0
stop_automated_movement = 0
-/mob/living/simple_animal/hostile/poison/giant_spider/nurse/handle_automated_movement()
- if(AIStatus == AI_IDLE)
+/mob/living/simple_animal/hostile/poison/giant_spider/nurse/handle_automated_movement() //Hacky and ugly.
+ if(..())
var/list/can_see = view(src, 10)
if(!busy && prob(30)) //30% chance to stop wandering and do something
- //first, check for potential food nearby to cocoon
+ //first, check for potential food nearby to cocoon
for(var/mob/living/C in can_see)
- if(C.stat && !istype(C,/mob/living/simple_animal/hostile/poison/giant_spider))
+ if(C.stat && !istype(C, /mob/living/simple_animal/hostile/poison/giant_spider) && !C.anchored)
cocoon_target = C
busy = MOVING_TO_TARGET
Goto(C, move_to_delay)
@@ -122,7 +123,7 @@
for(var/obj/O in can_see)
if(O.anchored)
continue
- if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery))
+ if(isitem(O) || isstructure(O) || ismachinery(O))
cocoon_target = O
busy = MOVING_TO_TARGET
stop_automated_movement = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
index 1ef6f06259f..1d37f04312d 100644
--- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
@@ -36,11 +36,11 @@
for(var/mob/living/L in T)
if(L == src || L == A)
continue
- if(faction_check(L) && !attack_same)
+ if(faction_check_mob(L) && !attack_same)
return
visible_message("[src] [ranged_message] at [A]!")
throw_at(A, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE)
- ranged_cooldown = world.time + ranged_cooldown_time
+ ranged_cooldown = world.time + ranged_cooldown_time
/mob/living/simple_animal/hostile/headcrab/proc/Zombify(mob/living/carbon/human/H)
if(!H.check_death_method())
diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm
index e2fc98c483f..a14ed91aa8f 100644
--- a/code/modules/mob/living/simple_animal/hostile/headslug.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm
@@ -36,16 +36,14 @@
else if(mind) // Let's make this a feature
egg.origin = mind
for(var/obj/item/organ/internal/I in src)
- I.loc = egg
+ I.forceMove(egg)
visible_message("[src] plants something in [victim]'s flesh!", \
"We inject our egg into [victim]'s body!")
egg_lain = 1
/mob/living/simple_animal/hostile/headslug/AttackingTarget()
- if(egg_lain)
- target.attack_animal(src)
- return
- if(iscarbon(target) && !issmall(target))
+ . = ..()
+ if(. && !egg_lain && iscarbon(target) && !issmall(target))
// Changeling egg can survive in aliens!
var/mob/living/carbon/C = target
if(C.stat == DEAD)
@@ -54,10 +52,7 @@
return
Infect(target)
to_chat(src, "With our egg laid, our death approaches rapidly...")
- spawn(100)
- death()
- return
- target.attack_animal(src)
+ addtimer(CALLBACK(src, .proc/death), 100)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
diff --git a/code/modules/mob/living/simple_animal/hostile/hellhound.dm b/code/modules/mob/living/simple_animal/hostile/hellhound.dm
index f3e110d0099..40318b914bc 100644
--- a/code/modules/mob/living/simple_animal/hostile/hellhound.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hellhound.dm
@@ -42,19 +42,16 @@
whisper_action.Grant(src)
/mob/living/simple_animal/hostile/hellhound/handle_automated_action()
- . = ..()
+ if(!..())
+ return
if(resting)
if(!wants_to_rest())
custom_emote(1, "growls, and gets up.")
playsound(get_turf(src), 'sound/hallucinations/growl2.ogg', 50, 1)
- icon_state = "[icon_living]"
- resting = 0
- update_canmove()
+ StopResting()
else if(wants_to_rest())
custom_emote(1, "lays down, and starts to lick their wounds.")
- icon_state = "[icon_resting]"
- resting = 1
- update_canmove()
+ StartResting()
/mob/living/simple_animal/hostile/hellhound/examine(mob/user)
. = ..()
@@ -97,7 +94,7 @@
/mob/living/simple_animal/hostile/hellhound/AttackingTarget()
. = ..()
- if(ishuman(target) && (!client || a_intent == INTENT_HARM))
+ if(. && ishuman(target) && (!client || a_intent == INTENT_HARM))
special_aoe()
/mob/living/simple_animal/hostile/hellhound/attackby(obj/item/C, mob/user, params)
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 9695cacccd8..30572f19158 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -36,7 +36,7 @@
/mob/living/simple_animal/hostile/hivebot/rapid
ranged = 1
- rapid = 1
+ rapid = 3
retreat_distance = 5
minimum_distance = 5
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index a96c78d09d6..41ed10288c3 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -2,60 +2,60 @@
faction = list("hostile")
stop_automated_movement_when_pulled = 0
obj_damage = 40
- environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls
+ environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls
var/atom/target
- var/ranged = 0
- var/rapid = 0
- var/projectiletype
+ var/ranged = FALSE
+ var/rapid = 0 //How many shots per volley.
+ var/rapid_fire_delay = 2 //Time between rapid fire shots
+
+ var/dodging = FALSE
+ var/approaching_target = FALSE //We should dodge now
+ var/in_melee = FALSE //We should sidestep now
+ var/dodge_prob = 30
+ var/sidestep_per_cycle = 1 //How many sidesteps per npcpool cycle when in melee
+
+ var/projectiletype //set ONLY it and NULLIFY casingtype var, if we have ONLY projectile
var/projectilesound
- var/casingtype
+ var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING
var/move_to_delay = 3 //delay for the automated movement.
var/list/friends = list()
+ var/list/emote_taunt = list()
+ var/taunt_chance = 0
+
+ var/rapid_melee = 1 //Number of melee attacks between each npc pool tick. Spread evenly.
+ var/melee_queue_distance = 4 //If target is close enough start preparing to hit them if we have rapid_melee enabled
+
var/ranged_message = "fires" //Fluff text for ranged mobs
- var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks
+ var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
+
//These vars are related to how mobs locate and target
var/robust_searching = 0 //By default, mobs have a simple searching method, set this to 1 for the more scrutinous searching (stat_attack, stat_exclusive, etc), should be disabled on most mobs
var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view
var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius
- var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius
var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3
- var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled
- var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead.
- var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
- var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction
-
- //typecache of things this mob will attack in DestroySurroundings() if it has environment_smash
- var/list/environment_target_typecache = list(
- /obj/machinery/door/window,
- /obj/structure/window,
- /obj/structure/closet,
- /obj/structure/table,
- /obj/structure/grille,
- /obj/structure/girder,
- /obj/structure/rack,
- /obj/structure/computerframe,
- /obj/machinery/constructable_frame,
- /obj/structure/barricade) //turned into a typecache in New()
+ var/search_objects_timer_id //Timer for regaining our old search_objects value after being attacked
+ var/search_objects_regain_time = 30 //the delay between being attacked and gaining our old search_objects value back
+ var/list/wanted_objects = list() //A typecache of objects types that will be checked against to attack, should we have search_objects enabled
+ var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
+ var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
+ var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
- var/list/emote_taunt = list()
- var/taunt_chance = 0
+ var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach
var/lose_patience_timeout = 300 //30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever
- var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
+/mob/living/simple_animal/hostile/Initialize(mapload)
+ . = ..()
-/mob/living/simple_animal/hostile/New()
- ..()
if(!targets_from)
targets_from = src
- environment_target_typecache = typecacheof(environment_target_typecache)
wanted_objects = typecacheof(wanted_objects)
/mob/living/simple_animal/hostile/Destroy()
@@ -73,16 +73,46 @@
if(AIStatus == AI_OFF)
return 0
var/list/possible_targets = ListTargets() //we look around for potential targets and make it a list for later use.
+
if(environment_smash)
EscapeConfinement()
if(AICanContinue(possible_targets))
- DestroySurroundings()
+ if(!QDELETED(target) && !targets_from.Adjacent(target))
+ DestroyPathToTarget()
if(!MoveToTarget(possible_targets)) //if we lose our target
if(AIShouldSleep(possible_targets)) // we try to acquire a new one
toggle_ai(AI_IDLE) // otherwise we go idle
return 1
+/mob/living/simple_animal/hostile/handle_automated_movement()
+ . = ..()
+ if(dodging && target && in_melee && isturf(loc) && isturf(target.loc))
+ var/datum/cb = CALLBACK(src,.proc/sidestep)
+ if(sidestep_per_cycle > 1) //For more than one just spread them equally - this could changed to some sensible distribution later
+ var/sidestep_delay = SSnpcpool.wait / sidestep_per_cycle
+ for(var/i in 1 to sidestep_per_cycle)
+ addtimer(cb, (i - 1) * sidestep_delay)
+ else //Otherwise randomize it to make the players guessing.
+ addtimer(cb,rand(1, SSnpcpool.wait))
+
+/mob/living/simple_animal/hostile/proc/sidestep()
+ if(!target || !isturf(target.loc) || !isturf(loc) || stat == DEAD)
+ return
+ var/target_dir = get_dir(src, target)
+
+ var/static/list/cardinal_sidestep_directions = list(-90, -45, 0, 45, 90)
+ var/static/list/diagonal_sidestep_directions = list(-45, 0, 45)
+ var/chosen_dir = 0
+ if (target_dir & (target_dir - 1))
+ chosen_dir = pick(diagonal_sidestep_directions)
+ else
+ chosen_dir = pick(cardinal_sidestep_directions)
+ if(chosen_dir)
+ chosen_dir = turn(target_dir, chosen_dir)
+ Move(get_step(src, chosen_dir))
+ face_atom(target) //Looks better if they keep looking at you when dodging
+
/mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user)
if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client && user)
FindTarget(list(user), 1)
@@ -97,7 +127,6 @@
//////////////HOSTILE MOB TARGETTING AND AGGRESSION////////////
-
/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see
if(!search_objects)
. = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide
@@ -108,7 +137,11 @@
if(can_see(targets_from, HM, vision_range))
. += HM
else
- . = oview(vision_range, targets_from)
+ . = list() // The following code is only very slightly slower than just returning oview(vision_range, targets_from), but it saves us much more work down the line, particularly when bees are involved
+ for(var/obj/A in oview(vision_range, targets_from))
+ . += A
+ for(var/mob/A in oview(vision_range, targets_from))
+ . += A
/mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about
. = list()
@@ -153,59 +186,61 @@
var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random
return chosen_target
-/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target?
- if(!the_target)
- return 0
- if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
- return 0
+// Please do not add one-off mob AIs here, but override this function for your mob
+/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
+ if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
+ return FALSE
+
+ if(ismob(the_target)) //Target is in godmode, ignore it.
+ var/mob/M = the_target
+ if(M.status_flags & GODMODE)
+ return FALSE
+
+ if(see_invisible < the_target.invisibility) //Target's invisible to us, forget it
+ return FALSE
if(search_objects < 2)
if(isliving(the_target))
var/mob/living/L = the_target
- var/faction_check = faction_check(L)
+ var/faction_check = faction_check_mob(L)
if(robust_searching)
- if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1)
- return 0
- if(faction_check && !attack_same || !faction_check && attack_same == 2)
- return 0
- if(L in friends)
- return 0
- else
- if(L.stat)
- return 0
if(faction_check && !attack_same)
- return 0
- return 1
+ return FALSE
+ if(L.stat > stat_attack)
+ return FALSE
+ if(L in friends)
+ return FALSE
+ else
+ if((faction_check && !attack_same) || L.stat)
+ return FALSE
+ return TRUE
- if(ishuman(the_target))
- var/mob/living/carbon/human/H = the_target
- if(is_type_in_list(src, H.dna.species.ignored_by))
- return 0
-
- if(istype(the_target, /obj/mecha))
+ if(ismecha(the_target))
var/obj/mecha/M = the_target
if(M.occupant)//Just so we don't attack empty mechs
if(CanAttack(M.occupant))
- return 1
+ return TRUE
- if(istype(the_target, /obj/spacepod))
+ if(isspacepod(the_target))
var/obj/spacepod/S = the_target
- if(S.pilot) //Just so we don't attack empty pods
+ if(S.pilot)//Just so we don't attack empty pods
if(CanAttack(S.pilot))
- return 1
+ return TRUE
if(istype(the_target, /obj/machinery/porta_turret))
var/obj/machinery/porta_turret/P = the_target
if(P.faction in faction)
- return 0
+ return FALSE
if(!P.raised) //Don't attack invincible turrets
- return 0
+ return FALSE
if(P.stat & BROKEN) //Or turrets that are already broken
- return 0
- return 1
+ return FALSE
+ return TRUE
+
if(isobj(the_target))
- if(attack_all_objects || is_type_in_list(the_target, wanted_objects))
- return 1
- return 0
+ if(attack_all_objects || is_type_in_typecache(the_target, wanted_objects))
+ return TRUE
+
+ return FALSE
/mob/living/simple_animal/hostile/proc/GiveTarget(new_target)//Step 4, give us our selected target
target = new_target
@@ -215,19 +250,39 @@
Aggro()
return 1
-/mob/living/simple_animal/hostile/proc/MoveToTarget(var/list/possible_targets)//Step 5, handle movement between us and our target
+//What we do after closing in
+/mob/living/simple_animal/hostile/proc/MeleeAction(patience = TRUE)
+ if(rapid_melee > 1)
+ var/datum/callback/cb = CALLBACK(src, .proc/CheckAndAttack)
+ var/delay = SSnpcpool.wait / rapid_melee
+ for(var/i in 1 to rapid_melee)
+ addtimer(cb, (i - 1)*delay)
+ else
+ AttackingTarget()
+ if(patience)
+ GainPatience()
+
+/mob/living/simple_animal/hostile/proc/CheckAndAttack()
+ if(target && targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && !incapacitated())
+ AttackingTarget()
+
+/mob/living/simple_animal/hostile/proc/MoveToTarget(list/possible_targets)//Step 5, handle movement between us and our target
stop_automated_movement = 1
if(!target || !CanAttack(target))
LoseTarget()
return 0
if(target in possible_targets)
- if(target.z != z)
+ var/turf/T = get_turf(src)
+ if(target.z != T.z)
LoseTarget()
return 0
var/target_distance = get_dist(targets_from,target)
if(ranged) //We ranged? Shoot at em
if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown
OpenFire(target)
+ if(!Process_Spacemove()) //Drifting
+ walk(src,0)
+ return 1
if(retreat_distance != null) //If we have a retreat distance, check if we need to run from our target
if(target_distance <= retreat_distance) //If target's closer than our retreat distance, run
walk_away(src,target,retreat_distance,move_to_delay)
@@ -237,8 +292,11 @@
Goto(target,move_to_delay,minimum_distance)
if(target)
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
- AttackingTarget()
- GainPatience()
+ MeleeAction()
+ else
+ if(rapid_melee > 1 && target_distance <= melee_queue_distance)
+ MeleeAction(FALSE)
+ in_melee = FALSE //If we're just preparing to strike do not enter sidestep mode
return 1
return 0
if(environment_smash)
@@ -256,14 +314,18 @@
return 0
/mob/living/simple_animal/hostile/proc/Goto(target, delay, minimum_distance)
+ if(target == src.target)
+ approaching_target = TRUE
+ else
+ approaching_target = FALSE
walk_to(src, target, minimum_distance, delay)
-/mob/living/simple_animal/hostile/adjustHealth(damage)
+/mob/living/simple_animal/hostile/adjustHealth(damage, updating_health = TRUE)
. = ..()
if(!ckey && !stat && search_objects < 3 && damage > 0)//Not unconscious, and we don't ignore mobs
if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight
- search_objects = 0
target = null
+ LoseSearchObjects()
if(AIStatus != AI_ON && AIStatus != AI_OFF)
toggle_ai(AI_ON)
FindTarget()
@@ -271,7 +333,9 @@
FindTarget()
/mob/living/simple_animal/hostile/proc/AttackingTarget()
- target.attack_animal(src)
+ SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
+ in_melee = TRUE
+ return target.attack_animal(src)
/mob/living/simple_animal/hostile/proc/Aggro()
vision_range = aggro_vision_range
@@ -281,11 +345,13 @@
/mob/living/simple_animal/hostile/proc/LoseAggro()
stop_automated_movement = 0
- vision_range = idle_vision_range
+ vision_range = initial(vision_range)
taunt_chance = initial(taunt_chance)
/mob/living/simple_animal/hostile/proc/LoseTarget()
target = null
+ approaching_target = FALSE
+ in_melee = FALSE
walk(src, 0)
LoseAggro()
@@ -302,8 +368,7 @@
do_alert_animation(src)
playsound(loc, 'sound/machines/chime.ogg', 50, 1, -1)
for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from))
- var/list/L = M.faction&faction
- if(L.len)
+ if(faction_check_mob(M, TRUE))
if(M.AIStatus == AI_OFF)
return
else
@@ -323,21 +388,18 @@
return
visible_message("[src] [ranged_message] at [A]!")
- if(rapid)
- spawn(1)
- Shoot(A)
- spawn(4)
- Shoot(A)
- spawn(6)
- Shoot(A)
+
+ if(rapid > 1)
+ var/datum/callback/cb = CALLBACK(src, .proc/Shoot, A)
+ for(var/i in 1 to rapid)
+ addtimer(cb, (i - 1)*rapid_fire_delay)
else
Shoot(A)
ranged_cooldown = world.time + ranged_cooldown_time
/mob/living/simple_animal/hostile/proc/Shoot(atom/targeted_atom)
- if(targeted_atom == targets_from.loc || targeted_atom == targets_from)
+ if( QDELETED(targeted_atom) || targeted_atom == targets_from.loc || targeted_atom == targets_from )
return
-
var/turf/startloc = get_turf(targets_from)
if(casingtype)
var/obj/item/ammo_casing/casing = new casingtype(startloc)
@@ -354,32 +416,70 @@
if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space
newtonian_move(get_dir(targeted_atom, targets_from))
P.original = targeted_atom
+ P.preparePixelProjectile(targeted_atom, get_turf(targeted_atom), src)
P.fire()
return P
-/mob/living/simple_animal/hostile/proc/DestroySurroundings()
+/mob/living/simple_animal/hostile/proc/CanSmashTurfs(turf/T)
+ return iswallturf(T) || ismineralturf(T)
+
+/mob/living/simple_animal/hostile/Move(atom/newloc, dir , step_x , step_y)
+ if(dodging && approaching_target && prob(dodge_prob) && moving_diagonally == 0 && isturf(loc) && isturf(newloc))
+ return dodge(newloc, dir)
+ else
+ return ..()
+
+/mob/living/simple_animal/hostile/proc/dodge(moving_to,move_direction)
+ //Assuming we move towards the target we want to swerve toward them to get closer
+ var/cdir = turn(move_direction, 45)
+ var/ccdir = turn(move_direction, -45)
+ dodging = FALSE
+ . = Move(get_step(loc,pick(cdir,ccdir)))
+ if(!.)//Can't dodge there so we just carry on
+ . = Move(moving_to,move_direction)
+ dodging = TRUE
+
+/mob/living/simple_animal/hostile/proc/DestroyObjectsInDirection(direction)
+ var/turf/T = get_step(targets_from, direction)
+ if(QDELETED(T))
+ return
+ if(T.Adjacent(targets_from))
+ if(CanSmashTurfs(T))
+ T.attack_animal(src)
+ return
+ for(var/obj/O in T.contents)
+ if(!O.Adjacent(targets_from))
+ continue
+ if((ismachinery(O) || isstructure(O)) && O.density && environment_smash >= ENVIRONMENT_SMASH_STRUCTURES && !O.IsObscured())
+ O.attack_animal(src)
+ return
+
+/mob/living/simple_animal/hostile/proc/DestroyPathToTarget()
+ if(environment_smash)
+ EscapeConfinement()
+ var/dir_to_target = get_dir(targets_from, target)
+ var/dir_list = list()
+ if(dir_to_target in diagonals) //it's diagonal, so we need two directions to hit
+ for(var/direction in cardinal)
+ if(direction & dir_to_target)
+ dir_list += direction
+ else
+ dir_list += dir_to_target
+ for(var/direction in dir_list) //now we hit all of the directions we got in this fashion, since it's the only directions we should actually need
+ DestroyObjectsInDirection(direction)
+
+/mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with megafauna destroying everything around them
if(environment_smash)
EscapeConfinement()
for(var/dir in cardinal)
- var/turf/T = get_step(targets_from, dir)
- if(iswallturf(T) || ismineralturf(T))
- if(T.Adjacent(targets_from))
- T.attack_animal(src)
- for(var/a in T)
- var/atom/A = a
- if(!A.Adjacent(targets_from))
- continue
- if(is_type_in_typecache(A, environment_target_typecache))
- A.attack_animal(src)
- return
+ DestroyObjectsInDirection(dir)
/mob/living/simple_animal/hostile/proc/EscapeConfinement()
if(buckled)
buckled.attack_animal(src)
if(!isturf(targets_from.loc) && targets_from.loc != null)//Did someone put us in something?
- var/atom/A = get_turf(targets_from)
+ var/atom/A = targets_from.loc
A.attack_animal(src)//Bang on it till we get out
- return
/mob/living/simple_animal/hostile/proc/FindHidden()
if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper) || istype(target.loc, /obj/machinery/bodyscanner) || istype(target.loc, /obj/machinery/recharge_station))
@@ -420,9 +520,23 @@
LosePatience()
lose_patience_timer_id = addtimer(CALLBACK(src, .proc/LoseTarget), lose_patience_timeout, TIMER_STOPPABLE)
+
/mob/living/simple_animal/hostile/proc/LosePatience()
deltimer(lose_patience_timer_id)
+
+//These two procs handle losing and regaining search_objects when attacked by a mob
+/mob/living/simple_animal/hostile/proc/LoseSearchObjects()
+ search_objects = 0
+ deltimer(search_objects_timer_id)
+ search_objects_timer_id = addtimer(CALLBACK(src, .proc/RegainSearchObjects), search_objects_regain_time, TIMER_STOPPABLE)
+
+
+/mob/living/simple_animal/hostile/proc/RegainSearchObjects(value)
+ if(!value)
+ value = initial(search_objects)
+ search_objects = value
+
/mob/living/simple_animal/hostile/consider_wakeup()
..()
var/list/tlist
@@ -455,4 +569,4 @@
if(isturf(M.loc))
. += M
else if(M.loc.type in hostile_machines)
- . += M.loc
+ . += M.loc
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm
index 9ed59fb4ab5..29739a9d867 100644
--- a/code/modules/mob/living/simple_animal/hostile/illusion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm
@@ -46,8 +46,8 @@
/mob/living/simple_animal/hostile/illusion/AttackingTarget()
- ..()
- if(istype(target, /mob/living) && prob(multiply_chance))
+ . = ..()
+ if(. && isliving(target) && prob(multiply_chance))
var/mob/living/L = target
if(L.stat == DEAD)
return
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
index e34a5e0cb08..797beb9b11b 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
@@ -23,6 +23,9 @@
pixel_x = -16
see_in_dark = 8
+ emote_taunt = list("nashes")
+ taunt_chance = 20
+
harm_intent_damage = 8
melee_damage_lower = 15
melee_damage_upper = 15
@@ -33,18 +36,13 @@
var/stalk_tick_delay = 3
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
-/mob/living/simple_animal/hostile/panther/FindTarget(var/list/possible_targets)
+/mob/living/simple_animal/hostile/panther/AttackingTarget()
. = ..()
if(.)
- emote("nashes at [.]")
-
-/mob/living/simple_animal/hostile/panther/AttackingTarget()
- . =..()
- var/mob/living/L = .
- if(istype(L))
- if(prob(15))
- L.Weaken(3)
- L.visible_message("\the [src] knocks down \the [L]!")
+ if(prob(15) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.Weaken(3)
+ C.visible_message("\the [src] knocks down \the [C]!")
//*******//
// Snake //
@@ -67,6 +65,9 @@
maxHealth = 25
health = 25
+ emote_taunt = list("hisses wickedly")
+ taunt_chance = 20
+
harm_intent_damage = 2
melee_damage_lower = 3
melee_damage_upper = 10
@@ -77,13 +78,9 @@
var/stalk_tick_delay = 3
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
-/mob/living/simple_animal/hostile/snake/FindTarget()
- . = ..()
- if(.)
- emote("hisses wickedly")
-
/mob/living/simple_animal/hostile/snake/AttackingTarget()
. =..()
- var/mob/living/L = .
- if(istype(L))
- L.apply_damage(rand(3,12), TOX)
+ if(.)
+ if(iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.apply_damage(rand(3, 12), TOX)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index d45e6f6ead8..05bdf9c76a6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -34,7 +34,7 @@ Difficulty: Medium
move_to_delay = 3
projectiletype = /obj/item/projectile/kinetic/miner
projectilesound = 'sound/weapons/kenetic_accel.ogg'
- ranged = 1
+ ranged = TRUE
ranged_cooldown_time = 16
pixel_x = -16
crusher_loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
@@ -47,8 +47,12 @@ Difficulty: Medium
var/dashing = FALSE
var/dash_cooldown = 15
var/guidance = FALSE
+ var/transform_stop_attack = FALSE // stops the blood drunk miner from attacking after transforming his weapon until the next attack chain
deathmessage = "falls to the ground, decaying into glowing particles."
death_sound = "bodyfall"
+ attack_action_types = list(/datum/action/innate/megafauna_attack/dash,
+ /datum/action/innate/megafauna_attack/kinetic_accelerator,
+ /datum/action/innate/megafauna_attack/transform_weapon)
/obj/item/gps/internal/miner
icon_state = null
@@ -56,13 +60,52 @@ Difficulty: Medium
desc = "The sweet blood, oh, it sings to me."
invisibility = 100
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance
- guidance = TRUE
-
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget()
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize(mapload)
. = ..()
- if(. && prob(12))
- INVOKE_ASYNC(src, .proc/dash)
+ miner_saw = new(src)
+ internal_gps = new/obj/item/gps/internal/miner(src)
+
+ // Add a zone selection UI; otherwise the mob can't melee attack properly.
+ zone_sel = new /obj/screen/zone_sel()
+
+/datum/action/innate/megafauna_attack/dash
+ name = "Dash To Target"
+ icon_icon = 'icons/mob/actions/actions.dmi'
+ button_icon_state = "sniper_zoom"
+ chosen_message = "You are now dashing to your target."
+ chosen_attack_num = 1
+
+/datum/action/innate/megafauna_attack/kinetic_accelerator
+ name = "Fire Kinetic Accelerator"
+ icon_icon = 'icons/obj/guns/energy.dmi'
+ button_icon_state = "kineticgun"
+ chosen_message = "You are now shooting your kinetic accelerator."
+ chosen_attack_num = 2
+
+/datum/action/innate/megafauna_attack/transform_weapon
+ name = "Transform Weapon"
+ icon_icon = 'icons/obj/lavaland/artefacts.dmi'
+ button_icon_state = "cleaving_saw"
+ chosen_message = "You are now transforming your weapon."
+ chosen_attack_num = 3
+
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire()
+ if(client)
+ switch(chosen_attack)
+ if(1)
+ dash(target)
+ if(2)
+ shoot_ka()
+ if(3)
+ transform_weapon()
+ return
+
+ Goto(target, move_to_delay, minimum_distance)
+ if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time)
+ dash_attack()
+ else
+ shoot_ka()
+ transform_weapon()
/obj/item/melee/energy/cleaving_saw/miner //nerfed saw because it is very murdery
force = 6
@@ -79,15 +122,7 @@ Difficulty: Medium
icon_state = "ka_tracer"
range = MINER_DASH_RANGE
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize()
- . = ..()
- miner_saw = new(src)
- internal_gps = new/obj/item/gps/internal/miner(src)
-
- // Add a zone selection UI; otherwise the mob can't melee attack properly.
- zone_sel = new /obj/screen/zone_sel()
-
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE)
var/adjustment_amount = amount * 0.1
if(world.time + adjustment_amount > next_move)
changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly
@@ -104,16 +139,19 @@ Difficulty: Medium
return FALSE
return ..()
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity, target)
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity)
if(dash())
return
return ..()
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/MeleeAction(patience = TRUE)
+ transform_stop_attack = FALSE
+ return ..()
+
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget()
- if(QDELETED(target))
- return
- if(next_move > world.time || !Adjacent(target)) //some cheating
- INVOKE_ASYNC(src, .proc/quick_attack_loop)
+ if(client)
+ transform_stop_attack = FALSE
+ if(QDELETED(target) || transform_stop_attack)
return
face_atom(target)
if(isliving(target))
@@ -132,8 +170,6 @@ Difficulty: Medium
miner_saw.melee_attack_chain(src, target)
if(guidance)
adjustHealth(-2)
- transform_weapon()
- INVOKE_ASYNC(src, .proc/quick_attack_loop)
return TRUE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
@@ -146,16 +182,10 @@ Difficulty: Medium
. = ..()
if(. && target && !targets_the_same)
wander = TRUE
- transform_weapon()
- INVOKE_ASYNC(src, .proc/quick_attack_loop)
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire()
- Goto(target, move_to_delay, minimum_distance)
- if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time)
- INVOKE_ASYNC(src, .proc/dash, target)
- else
- shoot_ka()
- transform_weapon()
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash_attack()
+ INVOKE_ASYNC(src, .proc/dash, target)
+ shoot_ka()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/shoot_ka()
if(ranged_cooldown <= world.time && get_dist(src, target) <= MINER_DASH_RANGE && !Adjacent(target))
@@ -166,21 +196,6 @@ Difficulty: Medium
Shoot(target)
changeNext_move(CLICK_CD_RANGE)
-//I'm still of the belief that this entire proc needs to be wiped from existence.
-// do not take my touching of it to be endorsement of it. ~mso
-/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
- while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep.
- stoplag(1)
- sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about
- if(QDELETED(target))
- return
- if(dashing || next_move > world.time || !Adjacent(target))
- if(dashing && next_move <= world.time)
- next_move = world.time + 1
- INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again.
- return
- AttackingTarget()
-
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash(atom/dash_target)
if(world.time < dash_cooldown)
return
@@ -189,7 +204,9 @@ Difficulty: Medium
var/turf/own_turf = get_turf(src)
if(!QDELETED(dash_target))
self_dist_to_target += get_dist(dash_target, own_turf)
- for(var/turf/simulated/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf))
+ for(var/turf/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf))
+ if(O.density)
+ continue
var/turf_dist_to_target = 0
if(!QDELETED(dash_target))
turf_dist_to_target += get_dist(dash_target, O)
@@ -218,26 +235,29 @@ Difficulty: Medium
var/turf/step_forward_turf = get_step(own_turf, get_cardinal_dir(own_turf, target_turf))
new /obj/effect/temp_visual/small_smoke/halfsecond(step_back_turf)
new /obj/effect/temp_visual/small_smoke/halfsecond(step_forward_turf)
- var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc, src)
- animate(D, alpha = 0, time = 5)
+ var/obj/effect/temp_visual/decoy/fading/halfsecond/D = new (own_turf, src)
forceMove(step_back_turf)
playsound(own_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1)
dashing = TRUE
alpha = 0
animate(src, alpha = 255, time = 5)
- sleep(2)
+ SLEEP_CHECK_DEATH(2)
D.forceMove(step_forward_turf)
forceMove(target_turf)
playsound(target_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1)
- sleep(1)
+ SLEEP_CHECK_DEATH(1)
dashing = FALSE
- shoot_ka()
return TRUE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon()
if(time_until_next_transform <= world.time)
miner_saw.transform_cooldown = 0
miner_saw.transform_weapon(src, TRUE)
+ if(!miner_saw.active)
+ rapid_melee = 5 // 4 deci cooldown before changes, npcpool subsystem wait is 20, 20/4 = 5
+ else
+ rapid_melee = 3 // same thing but halved (slightly rounded up)
+ transform_stop_attack = TRUE
icon_state = "miner[miner_saw.active ? "_transformed":""]"
icon_living = "miner[miner_saw.active ? "_transformed":""]"
time_until_next_transform = world.time + rand(50, 100)
@@ -263,4 +283,12 @@ Difficulty: Medium
sleep(4)
animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance
+ guidance = TRUE
+
+/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget()
+ . = ..()
+ if(. && prob(12))
+ INVOKE_ASYNC(src, .proc/dash)
+
#undef MINER_DASH_RANGE
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index ac5e40025c6..5b605551a22 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -122,12 +122,16 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget()
if(!charging)
- ..()
+ return ..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
if(!charging)
..()
+/mob/living/simple_animal/hostile/megafauna/bubblegum/MoveToTarget(list/possible_targets)
+ if(!charging)
+ ..()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
if(charging)
new /obj/effect/temp_visual/decoy/fading(loc, src)
@@ -195,7 +199,7 @@ Difficulty: Hard
. = list()
for(var/mob/living/L in targets)
var/list/bloodpool = get_pools(get_turf(L), 0)
- if(bloodpool.len && (!faction_check(L) || L.stat == DEAD))
+ if(bloodpool.len && (!faction_check_mob(L) || L.stat == DEAD))
. += L
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
@@ -246,7 +250,7 @@ Difficulty: Hard
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T)
sleep(2.5)
for(var/mob/living/L in T)
- if(!faction_check(L))
+ if(!faction_check_mob(L))
to_chat(L, "[src] rends you!")
playsound(T, attack_sound, 100, 1, -1)
var/limb_to_hit = pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg")
@@ -262,7 +266,7 @@ Difficulty: Hard
new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T)
sleep(6)
for(var/mob/living/L in T)
- if(!faction_check(L))
+ if(!faction_check_mob(L))
to_chat(L, "[src] drags you through the blood!")
playsound(T, 'sound/misc/enter_blood.ogg', 100, 1, -1)
var/turf/targetturf = get_step(src, dir)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 0789d00832d..00f67674546 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -62,14 +62,14 @@ Difficulty: Medium
return
..()
-/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount)
+/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount, updating_health = TRUE)
if(swooping)
- return 0
+ return FALSE
return ..()
/mob/living/simple_animal/hostile/megafauna/dragon/AttackingTarget()
if(!swooping)
- ..()
+ return ..()
/mob/living/simple_animal/hostile/megafauna/dragon/DestroySurroundings()
if(!swooping)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index bb4e9297605..4ed44c616c8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -123,13 +123,18 @@ Difficulty: Hard
adjustHealth(-L.maxHealth*0.5)
L.dust()
+/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target)
+ . = ..()
+ if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets
+ return FALSE
+
/*/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target)
var/targets_the_same = (new_target == target)
. = ..()
if(. && target && !targets_the_same)
visible_message("\"[pick(target_phrases)]\"")*/
-/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount)
+/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount, updating_health = TRUE)
. = ..()
if(src && amount > 0 && !blinking)
wander = TRUE
@@ -140,7 +145,7 @@ Difficulty: Hard
if(target && isliving(target))
spawn(0)
melee_blast(get_turf(target)) //melee attacks on living mobs produce a 3x3 blast
- ..()
+ return ..()
/mob/living/simple_animal/hostile/megafauna/hierophant/DestroySurroundings()
if(!blinking)
@@ -536,7 +541,7 @@ Difficulty: Hard
/obj/effect/temp_visual/hierophant/blast/proc/do_damage(turf/T)
for(var/mob/living/L in T.contents - hit_things) //find and damage mobs...
hit_things += L
- if((friendly_fire_check && caster && caster.faction_check(L)) || L.stat == DEAD)
+ if((friendly_fire_check && caster && caster.faction_check_mob(L)) || L.stat == DEAD)
continue
if(L.client)
flash_color(L.client, "#660099", 1)
@@ -551,7 +556,7 @@ Difficulty: Hard
for(var/obj/mecha/M in T.contents - hit_things) //and mechs.
hit_things += M
if(M.occupant)
- if(friendly_fire_check && caster && caster.faction_check(M.occupant))
+ if(friendly_fire_check && caster && caster.faction_check_mob(M.occupant))
continue
to_chat(M.occupant, "Your [M.name] is struck by a [name]!")
playsound(M,'sound/weapons/sear.ogg', 50, 1, -4)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 027bbb60a14..d26400bceca 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -46,7 +46,6 @@ Difficulty: Medium
loot = list(/obj/item/stack/sheet/bone = 3)
vision_range = 13
elimination = 1
- idle_vision_range = 13
appearance_flags = 0
mouse_opacity = MOUSE_OPACITY_ICON
stat_attack = 1 // Overriden from /tg/ - otherwise Legion starts chasing its minions
@@ -56,8 +55,8 @@ Difficulty: Medium
internal_gps = new/obj/item/gps/internal/legion(src)
/mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget()
- ..()
- if(ishuman(target))
+ . = ..()
+ if(. && ishuman(target))
var/mob/living/L = target
if(L.stat == UNCONSCIOUS)
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index f57559d549a..20df360a51a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -18,19 +18,8 @@
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
minbodytemp = 0
maxbodytemp = INFINITY
+ vision_range = 5
aggro_vision_range = 18
- idle_vision_range = 5
- environment_target_typecache = list(
- /obj/machinery/door/window,
- /obj/structure/window,
- /obj/structure/closet,
- /obj/structure/table,
- /obj/structure/grille,
- /obj/structure/girder,
- /obj/structure/rack,
- /obj/structure/barricade,
- /obj/machinery/field,
- /obj/machinery/power/emitter)
var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
@@ -43,10 +32,15 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
+ var/chosen_attack = 1 // chosen attack num
+ var/list/attack_action_types = list()
/mob/living/simple_animal/hostile/megafauna/New()
..()
apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ for(var/action_type in attack_action_types)
+ var/datum/action/innate/megafauna_attack/attack_action = new action_type()
+ attack_action.Grant(src)
/mob/living/simple_animal/hostile/megafauna/Destroy()
QDEL_NULL(internal_gps)
@@ -70,8 +64,8 @@
loot = crusher_loot
/mob/living/simple_animal/hostile/megafauna/AttackingTarget()
- ..()
- if(isliving(target))
+ . = ..()
+ if(. && isliving(target))
var/mob/living/L = target
if(L.stat != DEAD)
if(!client && ranged && ranged_cooldown <= world.time)
@@ -124,3 +118,21 @@
SSmedals.SetScore(BOSS_SCORE, C, 1)
SSmedals.SetScore(score_type, C, 1)
return TRUE
+
+/datum/action/innate/megafauna_attack
+ name = "Megafauna Attack"
+ icon_icon = 'icons/mob/actions/actions_animal.dmi'
+ button_icon_state = ""
+ var/mob/living/simple_animal/hostile/megafauna/M
+ var/chosen_message
+ var/chosen_attack_num = 0
+
+/datum/action/innate/megafauna_attack/Grant(mob/living/L)
+ if(istype(L, /mob/living/simple_animal/hostile/megafauna))
+ M = L
+ return ..()
+ return FALSE
+
+/datum/action/innate/megafauna_attack/Activate()
+ M.chosen_attack = chosen_attack_num
+ to_chat(M, chosen_message)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
index fa2479bb658..5a1d10edfb2 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
@@ -81,7 +81,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
new createtype(loc)
-/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE)
. = ..()
if(. > 0 && world.time > call_help_cooldown)
call_help_cooldown = world.time + call_help_cooldown_amt
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index 5c26fe1ba57..57277dc2d74 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -17,7 +17,9 @@
melee_damage_upper = 12
attacktext = "attacks"
attack_sound = 'sound/weapons/bite.ogg'
+ emote_taunt = list("growls")
speak_emote = list("creaks")
+ taunt_chance = 30
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
@@ -29,11 +31,6 @@
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
del_on_death = 1
-/mob/living/simple_animal/hostile/mimic/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "growls at [.]")
-
/mob/living/simple_animal/hostile/mimic/emp_act(severity)
if(is_electronic)
switch(severity)
@@ -56,7 +53,7 @@
for(var/obj/item/I in loc)
I.loc = src
-/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings()
+/mob/living/simple_animal/hostile/mimic/crate/DestroyPathToTarget()
..()
if(prob(90))
icon_state = "[initial(icon_state)]open"
@@ -77,15 +74,19 @@
. = ..()
if(.)
icon_state = initial(icon_state)
+ if(prob(15) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.Weaken(2)
+ C.visible_message("\The [src] knocks down \the [C]!", "\The [src] knocks you down!")
/mob/living/simple_animal/hostile/mimic/crate/proc/trigger()
if(!attempt_open)
visible_message("[src] starts to move!")
attempt_open = 1
-/mob/living/simple_animal/hostile/mimic/crate/adjustHealth(damage)
+/mob/living/simple_animal/hostile/mimic/crate/adjustHealth(amount, updating_health = TRUE)
trigger()
- ..(damage)
+ . = ..()
/mob/living/simple_animal/hostile/mimic/crate/LoseTarget()
..()
@@ -96,18 +97,10 @@
var/obj/structure/closet/crate/C = new(get_turf(src))
// Put loot in crate
for(var/obj/O in src)
- O.loc = C
+ O.forceMove(C)
// due to `del_on_death`
return ..()
-/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget()
- . =..()
- var/mob/living/L = .
- if(istype(L))
- if(prob(15))
- L.Weaken(2)
- L.visible_message("\the [src] knocks down \the [L]!")
-
var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window)
/mob/living/simple_animal/hostile/mimic/copy
@@ -191,14 +184,11 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
..()
/mob/living/simple_animal/hostile/mimic/copy/AttackingTarget()
- ..()
- if(knockdown_people)
- if(iscarbon(target))
- var/mob/living/carbon/C = target
- if(prob(15))
- C.Weaken(2)
- C.visible_message("\The [src] knocks down \the [C]!", \
- "\The [src] knocks you down!")
+ . = ..()
+ if(knockdown_people && . && prob(15) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.Weaken(2)
+ C.visible_message("\The [src] knocks down \the [C]!", "\The [src] knocks you down!")
/mob/living/simple_animal/hostile/mimic/copy/Aggro()
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
index ad8dcf44699..f960471d510 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
@@ -26,8 +26,8 @@
a_intent = INTENT_HARM
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
+ vision_range = 2
aggro_vision_range = 9
- idle_vision_range = 2
turns_per_move = 5
loot = list(/obj/item/stack/ore/diamond{layer = 4.1},
/obj/item/stack/ore/diamond{layer = 4.1})
@@ -41,13 +41,10 @@
flag = "energy"
temperature = 50
-/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target)
+/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(new_target)
if(..()) //we have a target
- if(isliving(target))
- var/mob/living/L = target
- if(L.bodytemperature > 261)
- L.bodytemperature = 261
- visible_message("The [src.name]'s stare chills [L.name] to the bone!")
+ if(isliving(target) && !target.Adjacent(targets_from) && ranged_cooldown <= world.time)//No more being shot at point blank or spammed with RNG beams
+ OpenFire(target)
/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity)
switch(severity)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm
index cd73868a9e7..9066b84b5f6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/goldgrub.dm
@@ -8,8 +8,8 @@
icon_dead = "Goldgrub_dead"
icon_gib = "syndicate_gib"
vision_range = 2
+ vision_range = 2
aggro_vision_range = 9
- idle_vision_range = 2
move_to_delay = 5
friendly = "harmlessly rolls into"
maxHealth = 45
@@ -48,14 +48,13 @@
retreat_distance = 10
minimum_distance = 10
if(will_burrow)
- spawn(chase_time)
- Burrow()
+ addtimer(CALLBACK(src, .proc/Burrow), chase_time)
/mob/living/simple_animal/hostile/asteroid/goldgrub/AttackingTarget()
if(istype(target, /obj/item/stack/ore))
EatOre(target)
return
- ..()
+ return ..()
/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/EatOre(var/atom/targeted_ore)
for(var/obj/item/stack/ore/O in get_turf(targeted_ore))
@@ -69,13 +68,13 @@
/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time
if(!stat)
- visible_message("The [src.name] buries into the ground, vanishing from sight!")
+ visible_message("The [name] buries into the ground, vanishing from sight!")
qdel(src)
/mob/living/simple_animal/hostile/asteroid/goldgrub/bullet_act(obj/item/projectile/P)
visible_message("The [P.name] was repelled by [src.name]'s girth!")
return
-/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(damage)
- idle_vision_range = 9
+/mob/living/simple_animal/hostile/asteroid/goldgrub/adjustHealth(amount, updating_health = TRUE)
+ vision_range = 9
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
index dae7a688cb3..323976003b8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
@@ -11,7 +11,6 @@
mouse_opacity = MOUSE_OPACITY_OPAQUE
move_to_delay = 40
ranged = TRUE
- ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight
ranged_cooldown_time = 120
friendly = "wails at"
speak_emote = list("bellows")
@@ -26,8 +25,8 @@
attacktext = "pulverizes"
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
+ vision_range = 5
aggro_vision_range = 9
- idle_vision_range = 5
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
@@ -54,6 +53,8 @@
/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire()
var/tturf = get_turf(target)
+ if(!isturf(tturf))
+ return
if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
visible_message("The [src.name] digs its tentacles under [target.name]!")
new /obj/effect/temp_visual/goliath_tentacle/original(tturf, src)
@@ -61,10 +62,10 @@
icon_state = icon_aggro
pre_attack = FALSE
-/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage)
- ranged_cooldown--
+/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(amount, updating_health = TRUE)
+ ranged_cooldown -= 10
handle_preattack()
- ..()
+ . = ..()
/mob/living/simple_animal/hostile/asteroid/goliath/Aggro()
vision_range = aggro_vision_range
@@ -188,4 +189,4 @@
/obj/effect/temp_visual/goliath_tentacle/proc/retract()
icon_state = "Goliath_tentacle_retract"
deltimer(timerid)
- timerid = QDEL_IN(src, 5)
+ timerid = QDEL_IN(src, 7)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
index 6e5c840a401..23a900c1519 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm
@@ -30,7 +30,7 @@
stop_automated_movement_when_pulled = TRUE
stat_exclusive = TRUE
robust_searching = TRUE
- search_objects = TRUE
+ search_objects = 3
del_on_death = TRUE
loot = list(/obj/effect/decal/cleanable/blood/gibs)
deathmessage = "is pulped into bugmash."
@@ -38,7 +38,7 @@
animal_species = /mob/living/simple_animal/hostile/asteroid/gutlunch
childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck = 45, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen = 55)
- wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs)
+ wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/organ/internal)
var/obj/item/udder/gutlunch/udder = null
/mob/living/simple_animal/hostile/asteroid/gutlunch/New()
@@ -61,16 +61,37 @@
udder.milkAnimal(O, user)
regenerate_icons()
else
- ..()
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland
+ if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
+ return FALSE
+
+ if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
+ return FALSE
+
+ if(isliving(the_target))
+ var/mob/living/L = the_target
+
+ if(faction_check_mob(L) && !attack_same)
+ return FALSE
+ if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive)
+ return FALSE
+
+ return TRUE
+
+ if(isobj(the_target) && is_type_in_typecache(the_target, wanted_objects))
+ return TRUE
+
+ return FALSE
/mob/living/simple_animal/hostile/asteroid/gutlunch/AttackingTarget()
- if(is_type_in_typecache(target, wanted_objects)) //we eats
+ if(is_type_in_typecache(target,wanted_objects)) //we eats
udder.generateMilk()
regenerate_icons()
visible_message("[src] slurps up [target].")
qdel(target)
- return
- ..()
+ return ..()
/obj/item/udder/gutlunch
name = "nutrient sac"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
index 43d239c59ce..30dd6783717 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
@@ -11,8 +11,8 @@
move_to_delay = 14
ranged = 1
vision_range = 5
+ vision_range = 5
aggro_vision_range = 9
- idle_vision_range = 5
speed = 3
maxHealth = 75
health = 75
@@ -44,6 +44,7 @@
/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
OpenFire()
+ return TRUE
/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
loot += crusher_loot //we don't butcher
@@ -361,7 +362,7 @@
if("Cultist")
uniform = /obj/item/clothing/under/roman
suit = /obj/item/clothing/suit/hooded/cultrobes
- head = /obj/item/clothing/head/culthood
+ head = /obj/item/clothing/head/hooded/culthood
suit_store = /obj/item/tome
r_pocket = /obj/item/restraints/legcuffs/bola/cult
l_pocket = /obj/item/melee/cultblade/dagger
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index 434869c1d6d..ba4f00503e1 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -28,12 +28,14 @@
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
- icon_state = icon_aggro
+ if(vision_range != aggro_vision_range)
+ icon_state = icon_aggro
/mob/living/simple_animal/hostile/asteroid/LoseAggro()
..()
- if(stat == CONSCIOUS)
- icon_state = icon_living
+ if(stat == DEAD)
+ return
+ icon_state = icon_living
/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills
if(!stat)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm b/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm
index c6bc205627e..e910bac7ca3 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/necropolis_tendril.dm
@@ -17,6 +17,8 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = INFINITY
+ move_resist = INFINITY
+ anchored = TRUE
loot = list(/obj/effect/collapse, /obj/structure/closet/crate/necropolis/tendril)
del_on_death = 1
var/gps = null
@@ -76,4 +78,4 @@
mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril)
/mob/living/simple_animal/hostile/spawner/lavaland/legion
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril)
\ No newline at end of file
+ mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
deleted file mode 100644
index efc18895141..00000000000
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ /dev/null
@@ -1,225 +0,0 @@
-/mob/living/simple_animal/hostile/asteroid/
- vision_range = 2
- 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)
- unsuitable_atmos_damage = 15
- faction = list("mining")
- weather_immunities = list("lava","ash")
- obj_damage = 30
- environment_smash = 2
- minbodytemp = 0
- heat_damage_per_tick = 20
- response_help = "pokes"
- response_disarm = "shoves"
- response_harm = "strikes"
- status_flags = 0
- a_intent = INTENT_HARM
- var/throw_message = "bounces off of"
- var/icon_aggro = null // for swapping to when we get aggressive
- see_in_dark = 8
- lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- mob_size = MOB_SIZE_LARGE
-
-/mob/living/simple_animal/hostile/asteroid/Aggro()
- ..()
- icon_state = icon_aggro
-
-/mob/living/simple_animal/hostile/asteroid/LoseAggro()
- ..()
- if(stat == CONSCIOUS)
- icon_state = icon_living
-
-/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills
- if(!stat)
- Aggro()
- if(P.damage < 30 && P.damage_type != BRUTE)
- P.damage = (P.damage / 3)
- visible_message("The [P] has a reduced effect on [src]!")
- ..()
-
-/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy
- if(istype(AM, /obj/item))
- var/obj/item/T = AM
- if(!stat)
- Aggro()
- if(T.throwforce <= 20)
- visible_message("The [T.name] [src.throw_message] [src.name]!")
- return
- ..()
-
-/mob/living/simple_animal/hostile/asteroid/basilisk
- name = "basilisk"
- desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside."
- icon = 'icons/mob/animal.dmi'
- icon_state = "Basilisk"
- icon_living = "Basilisk"
- icon_aggro = "Basilisk_alert"
- icon_dead = "Basilisk_dead"
- icon_gib = "syndicate_gib"
- move_to_delay = 20
- projectiletype = /obj/item/projectile/temp/basilisk
- projectilesound = 'sound/weapons/pierce.ogg'
- ranged = 1
- ranged_message = "stares"
- ranged_cooldown_time = 30
- throw_message = "does nothing against the hard shell of"
- vision_range = 2
- speed = 3
- maxHealth = 200
- health = 200
- harm_intent_damage = 5
- obj_damage = 60
- melee_damage_lower = 12
- melee_damage_upper = 12
- attacktext = "bites into"
- a_intent = INTENT_HARM
- speak_emote = list("chitters")
- attack_sound = 'sound/weapons/bladeslice.ogg'
- aggro_vision_range = 9
- idle_vision_range = 2
- turns_per_move = 5
- loot = list(/obj/item/stack/ore/diamond{layer = 4.1},
- /obj/item/stack/ore/diamond{layer = 4.1})
-
-/obj/item/projectile/temp/basilisk
- name = "freezing blast"
- icon_state = "ice_2"
- damage = 0
- damage_type = BURN
- nodamage = 1
- flag = "energy"
- temperature = 50
-
-/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target)
- if(..()) //we have a target
- if(isliving(target))
- var/mob/living/L = target
- if(L.bodytemperature > 261)
- L.bodytemperature = 261
- visible_message("The [src.name]'s stare chills [L.name] to the bone!")
-
-/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity)
- switch(severity)
- if(1.0)
- gib()
- if(2.0)
- adjustBruteLoss(140)
- if(3.0)
- adjustBruteLoss(110)
-
-/mob/living/simple_animal/hostile/asteroid/goliath
- name = "goliath"
- desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions."
- icon = 'icons/mob/animal.dmi'
- icon_state = "Goliath"
- icon_living = "Goliath"
- icon_aggro = "Goliath_alert"
- icon_dead = "Goliath_dead"
- icon_gib = "syndicate_gib"
- attack_sound = 'sound/weapons/punch4.ogg'
- mouse_opacity = MOUSE_OPACITY_OPAQUE
- move_to_delay = 40
- ranged = 1
- ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight
- ranged_cooldown_time = 120
- friendly = "wails at"
- speak_emote = list("bellows")
- vision_range = 4
- speed = 3
- maxHealth = 300
- health = 300
- harm_intent_damage = 1 //Only the manliest of men can kill a Goliath with only their fists.
- obj_damage = 100
- melee_damage_lower = 25
- melee_damage_upper = 25
- attacktext = "pulverizes"
- attack_sound = 'sound/weapons/punch1.ogg'
- throw_message = "does nothing to the rocky hide of the"
- aggro_vision_range = 9
- idle_vision_range = 5
- move_force = MOVE_FORCE_VERY_STRONG
- move_resist = MOVE_FORCE_VERY_STRONG
- pull_force = MOVE_FORCE_VERY_STRONG
- var/pre_attack = 0
- loot = list(/obj/item/stack/sheet/animalhide/goliath_hide{layer = ABOVE_MOB_LAYER})
-
-/mob/living/simple_animal/hostile/asteroid/goliath/Life()
- ..()
- handle_preattack()
-
-/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack()
- if(ranged_cooldown <= world.time + ranged_cooldown_time * 0.25 && !pre_attack)
- pre_attack++
- if(!pre_attack || stat || AIStatus == AI_IDLE)
- return
- icon_state = "Goliath_preattack"
-
-/mob/living/simple_animal/hostile/asteroid/goliath/revive()
- move_force = MOVE_FORCE_VERY_STRONG
- move_resist = MOVE_FORCE_VERY_STRONG
- pull_force = MOVE_FORCE_VERY_STRONG
- ..()
-
-/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire()
- var/tturf = get_turf(target)
- if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
- visible_message("The [src.name] digs its tentacles under [target.name]!")
- new /obj/effect/goliath_tentacle/original(tturf)
- ranged_cooldown = world.time + ranged_cooldown_time
- icon_state = icon_aggro
- pre_attack = 0
- return
-
-/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage)
- ranged_cooldown--
- handle_preattack()
- ..()
-
-/mob/living/simple_animal/hostile/asteroid/goliath/Aggro()
- vision_range = aggro_vision_range
- handle_preattack()
- if(icon_state != icon_aggro)
- icon_state = icon_aggro
- return
-
-/obj/effect/goliath_tentacle/
- name = "Goliath tentacle"
- icon = 'icons/mob/animal.dmi'
- icon_state = "Goliath_tentacle"
- var/latched = 0
-
-/obj/effect/goliath_tentacle/New()
- var/turftype = get_turf(src)
- if(istype(turftype, /turf/simulated/mineral))
- var/turf/simulated/mineral/M = turftype
- M.gets_drilled()
- spawn(20)
- Trip()
-
-/obj/effect/goliath_tentacle/original
-
-/obj/effect/goliath_tentacle/original/New()
- for(var/obj/effect/goliath_tentacle/original/O in loc)//No more GG NO RE from 2+ goliaths simultaneously tentacling you
- if(O != src)
- qdel(src)
- var/list/directions = cardinal.Copy()
- var/counter
- for(counter = 1, counter <= 3, counter++)
- var/spawndir = pick(directions)
- directions -= spawndir
- var/turf/T = get_step(src,spawndir)
- new /obj/effect/goliath_tentacle(T)
- ..()
-
-
-/obj/effect/goliath_tentacle/proc/Trip()
- for(var/mob/living/M in src.loc)
- M.Stun(5)
- M.adjustBruteLoss(rand(10,15))
- latched = 1
- if(src && M)
- visible_message("The [src.name] grabs hold of [M.name]!")
- if(!latched)
- qdel(src)
- else
- spawn(50)
- qdel(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
index 59c23953e6b..ce044284a26 100644
--- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm
@@ -61,21 +61,42 @@
health = maxHealth
..()
-/mob/living/simple_animal/hostile/mushroom/adjustHealth(damage)//Possibility to flee from a fight just to make it more visually interesting
+/mob/living/simple_animal/hostile/mushroom/CanAttack(atom/the_target) // Mushroom-specific version of CanAttack to handle stupid attack_same = 2 crap so we don't have to do it for literally every single simple_animal/hostile because this shit never gets spawned
+ if(!the_target || isturf(the_target) || istype(the_target, /atom/movable/lighting_object))
+ return FALSE
+
+ if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
+ return FALSE
+
+ if(isliving(the_target))
+ var/mob/living/L = the_target
+
+ if (!faction_check_mob(L) && attack_same == 2)
+ return FALSE
+ if(L.stat > stat_attack)
+ return FALSE
+
+ return TRUE
+
+ return FALSE
+
+/mob/living/simple_animal/hostile/mushroom/adjustHealth(amount, updating_health = TRUE)//Possibility to flee from a fight just to make it more visually interesting
if(!retreat_distance && prob(33))
retreat_distance = 5
- spawn(30)
- retreat_distance = null
- ..()
+ addtimer(CALLBACK(src, .proc/stop_retreat), 30)
+ . = ..()
-/mob/living/simple_animal/hostile/mushroom/attack_animal(var/mob/living/L)
+/mob/living/simple_animal/hostile/mushroom/proc/stop_retreat()
+ retreat_distance = null
+
+/mob/living/simple_animal/hostile/mushroom/attack_animal(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/mushroom) && stat == DEAD)
var/mob/living/simple_animal/hostile/mushroom/M = L
if(faint_ticker < 2)
- M.visible_message("[M] chews a bit on [src].")
+ M.visible_message("[M] chews a bit on [src].")
faint_ticker++
- return
- M.visible_message("[M] devours [src]!")
+ return TRUE
+ M.visible_message("[M] devours [src]!")
var/level_gain = (powerlevel - M.powerlevel)
if(level_gain >= -1 && !bruised && !M.ckey)//Player shrooms can't level up to become robust gods.
if(level_gain < 1)//So we still gain a level if two mushrooms were the same level
@@ -83,7 +104,8 @@
M.LevelUp(level_gain)
M.adjustBruteLoss(-M.maxHealth)
qdel(src)
- ..()
+ return TRUE
+ return ..()
/mob/living/simple_animal/hostile/mushroom/revive()
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 108daa031df..34a224ca5ce 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -36,7 +36,7 @@
icon_dead = "piratemelee_dead"
projectilesound = 'sound/weapons/laser.ogg'
ranged = 1
- rapid = 1
+ rapid = 2
retreat_distance = 5
minimum_distance = 5
projectiletype = /obj/item/projectile/beam
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
index 709a238346a..bd3314d1453 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
@@ -7,7 +7,7 @@
icon_living = "drone3"
icon_dead = "drone_dead"
ranged = 1
- rapid = 1
+ rapid = 3
speak_chance = 5
turns_per_move = 3
response_help = "pokes the"
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
index 2e3718cd800..d3bf35671e2 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
@@ -1,20 +1,20 @@
/mob/living/simple_animal/hostile/retaliate
var/list/enemies = list()
-/mob/living/simple_animal/hostile/retaliate/Found(var/atom/A)
+/mob/living/simple_animal/hostile/retaliate/Found(atom/A)
if(isliving(A))
var/mob/living/L = A
if(!L.stat)
return L
else
enemies -= L
- else if(istype(A, /obj/mecha))
+ else if(ismecha(A))
var/obj/mecha/M = A
if(M.occupant)
return A
- else if(istype(A, /obj/spacepod))
- var/obj/spacepod/M = A
- if(M.pilot)
+ else if(isspacepod(A))
+ var/obj/spacepod/S = A
+ if(S.pilot)
return A
/mob/living/simple_animal/hostile/retaliate/ListTargets()
@@ -25,48 +25,32 @@
return see
/mob/living/simple_animal/hostile/retaliate/proc/Retaliate()
- ..()
- var/list/around = view(src, 7)
+ var/list/around = view(src, vision_range)
for(var/atom/movable/A in around)
if(A == src)
continue
if(isliving(A))
var/mob/living/M = A
- var/faction_check = 0
- for(var/F in faction)
- if(F in M.faction)
- faction_check = 1
- break
- if(faction_check && attack_same || !faction_check)
+ if(faction_check_mob(M) && attack_same || !faction_check_mob(M))
enemies |= M
- else if(istype(A, /obj/mecha))
+ else if(ismecha(A))
var/obj/mecha/M = A
if(M.occupant)
enemies |= M
enemies |= M.occupant
- else if(istype(A, /obj/spacepod))
- var/obj/spacepod/M = A
- if(M.pilot)
- enemies |= M
- enemies |= M.pilot
+ else if(isspacepod(A))
+ var/obj/spacepod/S = A
+ if(S.pilot)
+ enemies |= S
+ enemies |= S.pilot
for(var/mob/living/simple_animal/hostile/retaliate/H in around)
- var/retaliate_faction_check = 0
- for(var/F in faction)
- if(F in H.faction)
- retaliate_faction_check = 1
- break
- if(retaliate_faction_check && !attack_same && !H.attack_same)
+ if(faction_check_mob(H) && !attack_same && !H.attack_same)
H.enemies |= enemies
return 0
-/mob/living/simple_animal/hostile/retaliate/adjustHealth(damage)
- ..(damage)
- Retaliate()
-
-/mob/living/simple_animal/hostile/retaliate/DestroySurroundings()
- for(var/dir in cardinal) // North, South, East, West
- var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
- if(istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table))
- obstacle.attack_animal(src)
+/mob/living/simple_animal/hostile/retaliate/adjustHealth(amount, updating_health = TRUE)
+ . = ..()
+ if(amount > 0 && stat == CONSCIOUS)
+ Retaliate()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
index f9516739e6f..d80e68b7542 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
@@ -35,6 +35,9 @@
maxHealth = 20
health = 20
+ emote_taunt = list("wails")
+ taunt_chance = 20
+
harm_intent_damage = 10
melee_damage_lower = 2
melee_damage_upper = 3
@@ -51,11 +54,6 @@
/mob/living/simple_animal/hostile/retaliate/ghost/Process_Spacemove(var/check_drift = 0)
return 1
-/mob/living/simple_animal/hostile/retaliate/ghost/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "wails at [.]")
-
/mob/living/simple_animal/hostile/retaliate/ghost/Life(seconds, times_fired)
if(target)
invisibility = pick(0,0,60,invisibility)
diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm
index a4f7cce2f51..0c5f2647ae8 100644
--- a/code/modules/mob/living/simple_animal/hostile/russian.dm
+++ b/code/modules/mob/living/simple_animal/hostile/russian.dm
@@ -33,6 +33,7 @@
ranged = 1
retreat_distance = 5
minimum_distance = 5
+ projectilesound = 'sound/weapons/gunshots/gunshot.ogg'
casingtype = /obj/item/ammo_casing/a357
loot = list(/obj/effect/mob_spawn/human/corpse/russian/ranged, /obj/item/gun/projectile/revolver/mateba)
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
new file mode 100644
index 00000000000..011c47b2c24
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -0,0 +1,49 @@
+/mob/living/simple_animal/hostile/skeleton
+ name = "reanimated skeleton"
+ desc = "A real bonefied skeleton, doesn't seem like it wants to socialize."
+ icon = 'icons/mob/animal.dmi'
+ icon_state = "skeleton"
+ icon_living = "skeleton"
+ turns_per_move = 5
+ speak_emote = list("rattles")
+ emote_see = list("rattles")
+ a_intent = INTENT_HARM
+ maxHealth = 40
+ health = 40
+ speed = 1
+ harm_intent_damage = 5
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ minbodytemp = 0
+ maxbodytemp = 1500
+ healable = FALSE //they're skeletons how would bruise packs help them??
+ attacktext = "slashes"
+ attack_sound = 'sound/hallucinations/growl1.ogg'
+ 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)
+ unsuitable_atmos_damage = 10
+ robust_searching = 1
+ stat_attack = UNCONSCIOUS
+ gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
+ faction = list("skeleton")
+ see_in_dark = 8
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ deathmessage = "collapses into a pile of bones!"
+ del_on_death = TRUE
+ loot = list(/obj/effect/decal/remains/human)
+
+/mob/living/simple_animal/hostile/skeleton/eskimo
+ name = "undead eskimo"
+ desc = "The reanimated remains of some poor traveler."
+ icon_state = "eskimo"
+ icon_living = "eskimo"
+ maxHealth = 55
+ health = 55
+ weather_immunities = list("snow")
+ gold_core_spawnable = CHEM_MOB_SPAWN_INVALID
+ melee_damage_lower = 17
+ melee_damage_upper = 20
+ deathmessage = "collapses into a pile of bones, its gear falling to the floor!"
+ loot = list(/obj/effect/decal/remains/human,
+ /obj/item/twohanded/spear,
+ /obj/item/clothing/shoes/winterboots,
+ /obj/item/clothing/suit/hooded/wintercoat)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
index 93e03e8279e..fd569984920 100644
--- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
+++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
@@ -118,8 +118,9 @@
//Try to move onto target's turf and eat them
/mob/living/simple_animal/hostile/spaceWorm/wormHead/AttackingTarget()
- ..()
- attemptToEat(target)
+ . = ..()
+ if(.)
+ attemptToEat(target)
//Attempt to eat things we bump into, Mobs, Walls, Clowns
/mob/living/simple_animal/hostile/spaceWorm/wormHead/Bump(atom/obstacle)
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 2e1e7508e1c..b32cae64675 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -36,7 +36,6 @@
see_in_dark = 8
vision_range = 12
aggro_vision_range = 12
- idle_vision_range = 12
search_objects = 1 // So that it can see through walls
@@ -87,11 +86,11 @@
if(can_be_seen(get_turf(loc)))
if(client)
to_chat(src, "You cannot attack, there are eyes on you!")
- return
+ return FALSE
else
- ..()
+ return ..()
-/mob/living/simple_animal/hostile/statue/DestroySurroundings()
+/mob/living/simple_animal/hostile/statue/DestroyPathToTarget()
if(!can_be_seen(get_turf(loc)))
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 8cbef64d34b..f380d85be34 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -135,6 +135,8 @@
LoseTarget()
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/handle_automated_action()
+ if(!..())
+ return
if(seen_enemy)
aggro_cycles++
if(alert_on_timeout && !raised_alert && aggro_cycles >= 60)
@@ -159,14 +161,13 @@
continue
if(depotarea.list_includes(body, depotarea.dead_list))
continue
- if(faction_check(body))
+ if(faction_check_mob(body))
continue
say("Target [body]... terminated.")
depotarea.list_add(body, depotarea.dead_list)
pointed(body)
else
scan_cycles++
- ..()
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/proc/raise_alert(var/reason)
if(istype(depotarea) && (!raised_alert || seen_revived_enemy) && !depotarea.used_self_destruct)
@@ -190,7 +191,7 @@
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/CanPass(atom/movable/mover, turf/target, height=0)
if(isliving(mover))
var/mob/living/blocker = mover
- if(faction_check(blocker))
+ if(faction_check_mob(blocker))
return 1
return ..(mover, target, height)
@@ -256,11 +257,12 @@
/mob/living/simple_animal/hostile/syndicate/ranged
ranged = 1
- rapid = 1
+ rapid = 2
retreat_distance = 5
minimum_distance = 5
icon_state = "syndicateranged"
icon_living = "syndicateranged"
+ projectilesound = 'sound/weapons/gunshots/gunshot.ogg'
casingtype = /obj/item/ammo_casing/c45
loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, /obj/item/gun/projectile/automatic/c20r)
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm
index 6db08d392ed..50049af0a2e 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm
@@ -19,7 +19,8 @@
ventcrawler = 1
idle_ventcrawl_chance = 0
ai_playercontrol_allowtype = 0
- rapid = 1
+ ai_type = TS_AI_AGGRESSIVE
+ rapid = 3
canlay = 1000
spider_tier = TS_TIER_5
projectiletype = /obj/item/projectile/terrorqueenspit/empress
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm
index 98556c63d34..91e70dd837d 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/red.dm
@@ -58,7 +58,7 @@
visible_message("[src] retracts its fangs a little.")
melee_damage_lower = melee_damage_lower_rage1
melee_damage_upper = melee_damage_upper_rage1
- ..()
+ return ..()
/obj/structure/spider/terrorweb/red
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm
index 999405df2d8..7e90867e783 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm
@@ -11,7 +11,6 @@
layer = 2.75
health = 3
var/stillborn = FALSE
- faction = list("terrorspiders")
var/spider_myqueen = null
var/spider_mymother = null
var/goto_mother = FALSE
@@ -169,10 +168,8 @@
if(!grow_as)
grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray, /mob/living/simple_animal/hostile/poison/terror_spider/green)
var/mob/living/simple_animal/hostile/poison/terror_spider/S = new grow_as(loc)
- S.faction = faction
S.spider_myqueen = spider_myqueen
S.spider_mymother = spider_mymother
- S.master_commander = master_commander
S.enemies = enemies
qdel(src)
@@ -186,10 +183,8 @@
var/obj/structure/spider/eggcluster/terror_eggcluster/C = new /obj/structure/spider/eggcluster/terror_eggcluster(get_turf(src))
C.spiderling_type = lay_type
C.spiderling_number = lay_number
- C.faction = faction
C.spider_myqueen = spider_myqueen
C.spider_mymother = src
- C.master_commander = master_commander
C.enemies = enemies
if(spider_growinstantly)
C.amount_grown = 250
@@ -202,7 +197,6 @@
desc = "A cluster of tiny spider eggs. They pulse with a strong inner life, and appear to have sharp thorns on the sides."
icon_state = "eggs"
var/spider_growinstantly = 0
- faction = list("terrorspiders")
var/spider_myqueen = null
var/spider_mymother = null
var/spiderling_type = null
@@ -244,10 +238,8 @@
var/obj/structure/spider/spiderling/terror_spiderling/S = new /obj/structure/spider/spiderling/terror_spiderling(get_turf(src))
if(spiderling_type)
S.grow_as = spiderling_type
- S.faction = faction
S.spider_myqueen = spider_myqueen
S.spider_mymother = spider_mymother
- S.master_commander = master_commander
S.enemies = enemies
if(spider_growinstantly)
S.amount_grown = 250
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm
index 251ba27cf05..f84ec5f90d7 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm
@@ -92,7 +92,7 @@ var/global/list/ts_spiderling_list = list()
var/degenerate = 0 // if 1, they slowly degen until they all die off. Used by high-level abilities only.
// Vision
- idle_vision_range = 10
+ vision_range = 10
aggro_vision_range = 10
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
@@ -361,7 +361,7 @@ var/global/list/ts_spiderling_list = list()
to_chat(T, "TerrorSense: [msgtext]")
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CheckFaction()
- if(faction.len != 1 || (!("terrorspiders" in faction)) || master_commander != null)
+ if(faction.len != 2 || (!("terrorspiders" in faction)) || master_commander != null)
to_chat(src, "Your connection to the hive mind has been severed!")
log_runtime(EXCEPTION("Terror spider with incorrect faction list at: [atom_loc_line(src)]"))
gib()
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 508e2934cf6..78f79dfc3b2 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -24,6 +24,8 @@
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
speak_emote = list("pines")
+ emote_taunt = list("growls")
+ taunt_chance = 20
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
@@ -34,15 +36,10 @@
deathmessage = "is hacked into pieces!"
del_on_death = 1
-/mob/living/simple_animal/hostile/tree/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "growls at [.]")
-
/mob/living/simple_animal/hostile/tree/AttackingTarget()
- . =..()
- var/mob/living/L = .
- if(istype(L))
+ . = ..()
+ if(. && iscarbon(target))
+ var/mob/living/carbon/C = target
if(prob(15))
- L.Weaken(3)
- L.visible_message("\the [src] knocks down \the [L]!")
\ No newline at end of file
+ C.Weaken(3)
+ C.visible_message("\the [src] knocks down \the [C]!")
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
index 52ec406fcbd..c8e6b8c5d8e 100644
--- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
+++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
@@ -90,7 +90,7 @@
if(grasping.len < max_grasps)
grasping:
for(var/mob/living/L in view(grasp_range, src))
- if(L == src || faction_check(L) || (L in grasping) || L == target)
+ if(L == src || faction_check_mob(L) || (L in grasping) || L == target)
continue
for(var/t in getline(src,L))
for(var/a in t)
@@ -105,6 +105,12 @@
/mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target)
+ for(var/turf/T in getline(src,target))
+ if (T.density)
+ return
+ for(var/obj/O in T)
+ if(O.density)
+ return
var/dist = get_dist(src,the_target)
Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine)
the_target.attack_animal(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
index f96ebabf014..d8fba34296b 100644
--- a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
@@ -117,7 +117,7 @@
maxHealth = 250
health = 250
ranged = 1
- rapid = 1
+ rapid = 3
speed = 0 //he's lost some weight from the fighting
projectiletype = /obj/item/projectile/ornament
retreat_distance = 3
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 05a3141b17a..b556fa24bec 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -3,15 +3,17 @@
icon = 'icons/mob/animal.dmi'
health = 20
maxHealth = 20
+ gender = PLURAL //placeholder
+
universal_understand = 1
+ universal_speak = 0
status_flags = CANPUSH
var/icon_living = ""
var/icon_dead = ""
var/icon_resting = ""
var/icon_gib = null //We only try to show a gibbing animation if this exists.
-
- var/healable = 1
+ var/flip_on_death = FALSE //Flip the sprite upside down on death. Mostly here for things lacking custom dead sprites.
var/list/speak = list()
var/speak_chance = 0
@@ -20,7 +22,6 @@
var/turns_per_move = 1
var/turns_since_move = 0
- universal_speak = 0
var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals.
var/wander = 1 // Does the mob wander around when idle?
var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it.
@@ -38,11 +39,13 @@
var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp
var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp
+ //Healable by medical stacks? Defaults to yes.
+ var/healable = 1
+
//Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage
var/list/atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) //Leaving something at 0 means it's off - has no maximum
var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above
-
//LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly
var/melee_damage_lower = 0
var/melee_damage_upper = 0
@@ -53,7 +56,7 @@
var/attacktext = "attacks"
var/attack_sound = null
var/friendly = "nuzzles" //If the mob does no damage with it's attack
- var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls
+ var/environment_smash = ENVIRONMENT_SMASH_NONE //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls
var/speed = 1 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster
var/can_hide = 0
@@ -66,6 +69,7 @@
var/next_scan_time = 0
var/animal_species //Sorry, no spider+corgi buttbabies.
+ var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against
var/gold_core_spawnable = CHEM_MOB_SPAWN_INVALID //if CHEM_MOB_SPAWN_HOSTILE can be spawned by plasma with gold core, CHEM_MOB_SPAWN_FRIENDLY are 'friendlies' spawned with blood
var/mob/living/carbon/human/master_commander = null //holding var for determining who own/controls a sentient simple animal (for sentience potions).
@@ -73,19 +77,35 @@
var/mob/living/simple_animal/hostile/spawner/nest
var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions
+
var/list/loot = list() //list of things spawned at mob's loc when it dies
var/del_on_death = 0 //causes mob to be deleted on death, useful for mobs that spawn lootable corpses
- var/attacked_sound = "punch"
var/deathmessage = ""
var/death_sound = null //The sound played on death
+ var/allow_movement_on_non_turfs = FALSE
+
+ var/attacked_sound = "punch"
+
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
var/can_have_ai = TRUE //once we have become sentient, we can never go back
+
var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check.
-/mob/living/simple_animal/Initialize()
- ..()
+ //domestication
+ var/tame = 0
+
+ var/my_z // I don't want to confuse this with client registered_z
+
+/mob/living/simple_animal/Initialize(mapload)
+ . = ..()
GLOB.simple_animals[AIStatus] += src
+ if(gender == PLURAL)
+ gender = pick(MALE, FEMALE)
+ if(!real_name)
+ real_name = name
+ if(!loc)
+ stack_trace("Simple animal being instantiated in nullspace")
verbs -= /mob/verb/observe
if(!can_hide)
verbs -= /mob/living/simple_animal/verb/hide
@@ -113,27 +133,25 @@
return ..()
-/mob/living/simple_animal/Login()
- if(src && src.client)
- src.client.screen = list()
- client.screen += client.void
- ..()
+/mob/living/simple_animal/examine(mob/user)
+ . = ..()
+ if(stat == DEAD)
+ to_chat(user, "Upon closer examination, [p_they()] appear[p_s()] to be dead.")
/mob/living/simple_animal/updatehealth(reason = "none given")
..(reason)
health = Clamp(health, 0, maxHealth)
med_hud_set_status()
-/mob/living/simple_animal/lay_down()
+/mob/living/simple_animal/StartResting(updating = 1)
..()
- handle_resting_state_icons()
+ if(icon_resting && stat != DEAD)
+ icon_state = icon_resting
-/mob/living/simple_animal/proc/handle_resting_state_icons()
- if(icon_resting)
- if(resting && stat != DEAD)
- icon_state = icon_resting
- else if(stat != DEAD)
- icon_state = icon_living
+/mob/living/simple_animal/StopResting(updating = 1)
+ ..()
+ if(icon_resting && stat != DEAD)
+ icon_state = icon_living
/mob/living/simple_animal/update_stat(reason = "none given")
if(status_flags & GODMODE)
@@ -146,11 +164,13 @@
create_debug_log("died of damage, trigger reason: [reason]")
/mob/living/simple_animal/proc/handle_automated_action()
+ set waitfor = FALSE
return
/mob/living/simple_animal/proc/handle_automated_movement()
+ set waitfor = FALSE
if(!stop_automated_movement && wander)
- if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
+ if((isturf(loc) || allow_movement_on_non_turfs) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
turns_since_move++
if(turns_since_move >= turns_per_move)
if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled
@@ -158,11 +178,12 @@
if(Process_Spacemove(anydir))
Move(get_step(src,anydir), anydir)
turns_since_move = 0
- return
+ return 1
-/mob/living/simple_animal/proc/handle_automated_speech()
+/mob/living/simple_animal/proc/handle_automated_speech(override)
+ set waitfor = FALSE
if(speak_chance)
- if(rand(0,200) < speak_chance)
+ if(prob(speak_chance) || override)
if(speak && speak.len)
if((emote_hear && emote_hear.len) || (emote_see && emote_see.len))
var/length = speak.len
@@ -200,7 +221,7 @@
var/areatemp = get_temperature(environment)
- if(abs(areatemp - bodytemperature) > 40 && !(BREATHLESS in mutations))
+ if(abs(areatemp - bodytemperature) > 5 && !(BREATHLESS in mutations))
var/diff = areatemp - bodytemperature
diff = diff / 5
bodytemperature += diff
@@ -241,30 +262,24 @@
atmos_suitable = 0
if(!atmos_suitable)
- adjustBruteLoss(unsuitable_atmos_damage)
+ adjustHealth(unsuitable_atmos_damage)
handle_temperature_damage()
/mob/living/simple_animal/proc/handle_temperature_damage()
- if(bodytemperature < minbodytemp)
- adjustBruteLoss(cold_damage_per_tick)
- else if(bodytemperature > maxbodytemp)
- adjustBruteLoss(heat_damage_per_tick)
+ if((bodytemperature < minbodytemp) || (bodytemperature > maxbodytemp))
+ adjustHealth(unsuitable_atmos_damage)
/mob/living/simple_animal/gib()
if(icon_gib)
flick(icon_gib, src)
if(butcher_results)
+ var/atom/Tsec = drop_location()
for(var/path in butcher_results)
- for(var/i = 1; i <= butcher_results[path];i++)
- new path(src.loc)
+ for(var/i in 1 to butcher_results[path])
+ new path(Tsec)
..()
-
-/mob/living/simple_animal/blob_act()
- adjustBruteLoss(20)
- return
-
/mob/living/simple_animal/emote(act, m_type = 1, message = null, force)
if(stat)
return
@@ -278,29 +293,13 @@
..()
-/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
- if(!Proj)
- return
- if((Proj.damage_type != STAMINA))
- adjustBruteLoss(Proj.damage)
- Proj.on_hit(src, 0)
- return FALSE
+/mob/living/simple_animal/say_quote(message)
+ var/verb = "says"
-/mob/living/simple_animal/attackby(obj/item/O, mob/living/user)
- if(can_collar && !collar && istype(O, /obj/item/clothing/accessory/petcollar))
- var/obj/item/clothing/accessory/petcollar/C = O
- user.drop_item()
- C.forceMove(src)
- collar = C
- collar.equipped(src)
- regenerate_icons()
- to_chat(usr, "You put \the [C] around \the [src]'s neck.")
- if(C.tagname)
- name = C.tagname
- real_name = C.tagname
- return
- else
- ..()
+ if(speak_emote.len)
+ verb = pick(speak_emote)
+
+ return verb
/mob/living/simple_animal/movement_delay()
. = ..()
@@ -311,21 +310,25 @@
/mob/living/simple_animal/Stat()
..()
+ if(statpanel("Status"))
+ stat(null, "Health: [round((health / maxHealth) * 100)]%")
+ return TRUE
- statpanel("Status")
- stat(null, "Health: [round((health / maxHealth) * 100)]%")
+/mob/living/simple_animal/proc/drop_loot()
+ if(loot.len)
+ for(var/i in loot)
+ new i(loc)
/mob/living/simple_animal/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
+ flying = FALSE
if(nest)
nest.spawned_mobs -= src
nest = null
- if(loot.len)
- for(var/i in loot)
- new i(loc)
+ drop_loot()
if(!gibbed)
if(death_sound)
playsound(get_turf(src),death_sound, 200, 1)
@@ -334,87 +337,41 @@
else if(!del_on_death)
visible_message("\The [src] stops moving...")
if(del_on_death)
+ //Prevent infinite loops if the mob Destroy() is overridden in such
+ //a manner as to cause a call to death() again
+ del_on_death = FALSE
ghostize()
qdel(src)
else
health = 0
icon_state = icon_dead
+ if(flip_on_death)
+ transform = transform.Turn(180)
density = 0
- lying = 1
-/mob/living/simple_animal/ex_act(severity)
- ..()
- switch(severity)
- if(1.0)
- gib()
- return
-
- if(2.0)
- adjustBruteLoss(60)
-
-
- if(3.0)
- adjustBruteLoss(30)
-
-/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE)
- if(status_flags & GODMODE)
- return FALSE
- var/oldbruteloss = bruteloss
- bruteloss = Clamp(bruteloss + amount, 0, maxHealth)
- if(oldbruteloss == bruteloss)
- updating_health = FALSE
- . = STATUS_UPDATE_NONE
- else
- . = STATUS_UPDATE_HEALTH
- if(updating_health)
- updatehealth()
-
-/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE)
- if(damage_coeff[BRUTE])
- return adjustHealth(amount * damage_coeff[BRUTE], updating_health)
-
-/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE)
- if(damage_coeff[BURN])
- return adjustHealth(amount * damage_coeff[BURN], updating_health)
-
-/mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE)
- if(damage_coeff[OXY])
- return adjustHealth(amount * damage_coeff[OXY], updating_health)
-
-/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE)
- if(damage_coeff[TOX])
- return adjustHealth(amount * damage_coeff[TOX], updating_health)
-
-/mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE)
- if(damage_coeff[CLONE])
- return adjustHealth(amount * damage_coeff[CLONE], updating_health)
-
-/mob/living/simple_animal/adjustStaminaLoss(amount, updating_health = TRUE)
- if(damage_coeff[STAMINA])
- return ..(amount*damage_coeff[STAMINA], updating_health)
-
-/mob/living/simple_animal/proc/CanAttack(var/atom/the_target)
+/mob/living/simple_animal/proc/CanAttack(atom/the_target)
if(see_invisible < the_target.invisibility)
return FALSE
+ if(ismob(the_target))
+ var/mob/M = the_target
+ if(M.status_flags & GODMODE)
+ return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if(L.stat != CONSCIOUS)
return FALSE
- if(istype(the_target, /obj/mecha))
+ if(ismecha(the_target))
var/obj/mecha/M = the_target
if(M.occupant)
return FALSE
- if(istype(the_target,/obj/spacepod))
+ if(isspacepod(the_target))
var/obj/spacepod/S = the_target
if(S.pilot)
return FALSE
return TRUE
/mob/living/simple_animal/handle_fire()
- return
-
-/mob/living/simple_animal/update_fire()
- return
+ return TRUE
/mob/living/simple_animal/IgniteMob()
return FALSE
@@ -422,26 +379,14 @@
/mob/living/simple_animal/ExtinguishMob()
return
-/mob/living/simple_animal/update_transform()
- var/matrix/ntransform = matrix(transform) //aka transform.Copy()
- var/changed = 0
-
- if(resize != RESIZE_DEFAULT_SIZE)
- changed++
- ntransform.Scale(resize)
- resize = RESIZE_DEFAULT_SIZE
-
- if(changed)
- animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT)
-
/mob/living/simple_animal/revive()
..()
health = maxHealth
+ icon = initial(icon)
icon_state = icon_living
density = initial(density)
update_canmove()
-
-
+ flying = initial(flying)
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
@@ -471,42 +416,6 @@
if(target)
return new childspawn(target)
-/mob/living/simple_animal/say_quote(var/message)
- var/verb = "says"
-
- if(speak_emote.len)
- verb = pick(speak_emote)
-
- return verb
-
-/mob/living/simple_animal/update_canmove(delay_action_updates = 0)
- if(paralysis || stunned || weakened || stat || resting)
- drop_r_hand()
- drop_l_hand()
- canmove = 0
- else if(buckled)
- canmove = 0
- else
- canmove = 1
- update_transform()
- if(!delay_action_updates)
- update_action_buttons_icon()
- return canmove
-
-/mob/living/simple_animal/update_transform()
- var/matrix/ntransform = matrix(transform) //aka transform.Copy()
- var/changed = 0
-
- if(resize != RESIZE_DEFAULT_SIZE)
- changed++
- ntransform.Scale(resize)
- resize = RESIZE_DEFAULT_SIZE
-
- if(changed)
- animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT)
-
-/* Inventory */
-
/mob/living/simple_animal/show_inv(mob/user as mob)
if(!can_collar)
return
@@ -571,50 +480,39 @@
if(collar)
. |= collar.GetAccess()
-/* End Inventory */
+/mob/living/simple_animal/update_canmove(delay_action_updates = 0)
+ if(paralysis || stunned || weakened || stat || resting)
+ drop_r_hand()
+ drop_l_hand()
+ canmove = 0
+ else if(buckled)
+ canmove = 0
+ else
+ canmove = 1
+ if(!canmove)
+ walk(src, 0) //stop mid walk
+
+ update_transform()
+ if(!delay_action_updates)
+ update_action_buttons_icon()
+ return canmove
+
+/mob/living/simple_animal/update_transform()
+ var/matrix/ntransform = matrix(transform) //aka transform.Copy()
+ var/changed = FALSE
+
+ if(resize != RESIZE_DEFAULT_SIZE)
+ changed = TRUE
+ ntransform.Scale(resize)
+ resize = RESIZE_DEFAULT_SIZE
+
+ if(changed)
+ animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT)
/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
toggle_ai(AI_OFF)
can_have_ai = FALSE
- return
-/mob/living/simple_animal/can_hear()
- . = TRUE
-
-/mob/living/simple_animal/proc/consider_wakeup()
- if(pulledby || shouldwakeup)
- toggle_ai(AI_ON)
-
-/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
- . = ..()
- if(!ckey && !stat)//Not unconscious
- if(AIStatus == AI_IDLE)
- toggle_ai(AI_ON)
-
-/mob/living/simple_animal/proc/toggle_ai(togglestatus)
- if(!can_have_ai && (togglestatus != AI_OFF))
- return
- if(AIStatus != togglestatus)
- if(togglestatus > 0 && togglestatus < 5)
- if(togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF)
- var/turf/T = get_turf(src)
- if(AIStatus == AI_Z_OFF)
- SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src
- else
- SSidlenpcpool.idle_mobs_by_zlevel[T.z] += src
- GLOB.simple_animals[AIStatus] -= src
- GLOB.simple_animals[togglestatus] += src
- AIStatus = togglestatus
- else
- stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]")
-
-/mob/living/simple_animal/onTransitZ(old_z, new_z)
- ..()
- if(AIStatus == AI_Z_OFF)
- SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src
- toggle_ai(initial(AIStatus))
-
-// Simple animals will not be given night vision upon death, as that would result in issues when they are revived.
/mob/living/simple_animal/grant_death_vision()
sight |= SEE_TURFS
sight |= SEE_MOBS
@@ -641,4 +539,37 @@
return
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
- sync_lighting_plane_alpha()
\ No newline at end of file
+ sync_lighting_plane_alpha()
+
+/mob/living/simple_animal/proc/toggle_ai(togglestatus)
+ if(!can_have_ai && (togglestatus != AI_OFF))
+ return
+ if(AIStatus != togglestatus)
+ if(togglestatus > 0 && togglestatus < 5)
+ if(togglestatus == AI_Z_OFF || AIStatus == AI_Z_OFF)
+ var/turf/T = get_turf(src)
+ if(AIStatus == AI_Z_OFF)
+ SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src
+ else
+ SSidlenpcpool.idle_mobs_by_zlevel[T.z] += src
+ GLOB.simple_animals[AIStatus] -= src
+ GLOB.simple_animals[togglestatus] += src
+ AIStatus = togglestatus
+ else
+ stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]")
+
+/mob/living/simple_animal/proc/consider_wakeup()
+ if(pulledby || shouldwakeup)
+ toggle_ai(AI_ON)
+
+/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE)
+ . = ..()
+ if(!ckey && !stat)//Not unconscious
+ if(AIStatus == AI_IDLE)
+ toggle_ai(AI_ON)
+
+/mob/living/simple_animal/onTransitZ(old_z, new_z)
+ ..()
+ if(AIStatus == AI_Z_OFF)
+ SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src
+ toggle_ai(initial(AIStatus))
\ No newline at end of file
diff --git a/code/modules/mob/living/taste.dm b/code/modules/mob/living/taste.dm
new file mode 100644
index 00000000000..a403aa39244
--- /dev/null
+++ b/code/modules/mob/living/taste.dm
@@ -0,0 +1,30 @@
+/mob/living
+ var/last_taste_time
+ var/last_taste_text
+
+/mob/living/proc/get_taste_sensitivity()
+ return TASTE_SENSITIVITY_NORMAL
+
+/mob/living/carbon/human/get_taste_sensitivity()
+ if(dna.species)
+ return dna.species.taste_sensitivity
+ else
+ return TASTE_SENSITIVITY_NORMAL
+
+// non destructively tastes a reagent container
+/mob/living/proc/taste(datum/reagents/from)
+ if(last_taste_time + 50 < world.time)
+ var/taste_sensitivity = get_taste_sensitivity()
+ var/text_output = from.generate_taste_message(taste_sensitivity)
+ // We dont want to spam the same message over and over again at the
+ // person. Give it a bit of a buffer.
+ if(hallucination > 50 && prob(25))
+ text_output = pick("spiders","dreams","nightmares","the future","the past","victory",\
+ "defeat","pain","bliss","revenge","poison","time","space","death","life","truth","lies","justice","memory",\
+ "regrets","your soul","suffering","music","noise","blood","hunger","the american way")
+ if(text_output != last_taste_text || last_taste_time + 100 < world.time)
+ to_chat(src, "You can taste [text_output].")
+ // "something indescribable" -> too many tastes, not enough flavor.
+
+ last_taste_time = world.time
+ last_taste_text = text_output
\ No newline at end of file
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index f5f1924e395..66b4f2f9a16 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -56,9 +56,6 @@
if(abilities)
client.verbs |= abilities
- if(ishuman(src))
- client.screen += client.void
-
//HUD updates (antag hud, etc)
//readd this mob's HUDs (antag, med, etc)
reload_huds()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 3c2f9fc732b..c2d16069146 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1234,12 +1234,6 @@ var/list/slot_equipment_priority = list( \
/mob/proc/get_access()
return list() //must return list or IGNORE_ACCESS
-/mob/proc/faction_check(mob/target)
- for(var/F in faction)
- if(F in target.faction)
- return 1
- return 0
-
/mob/proc/create_attack_log(text, collapse = TRUE)
LAZYINITLIST(attack_log)
create_log_in_list(attack_log, text, collapse, last_log)
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index 077164be6b7..805d48fdd9f 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -409,12 +409,6 @@
qdel(src)
/obj/item/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
- if(ishuman(attacker) && (/datum/dna/gene/basic/grant_spell/mattereater in attacker.active_genes)) // MATTER EATER CARES NOT OF YOUR FORM
- return 1
-
- if(ishuman(attacker) && (FAT in attacker.mutations) && iscarbon(prey) && !isalien(prey)) //Fat people eating carbon mobs but not xenos
- return 1
-
if(isalien(attacker) && iscarbon(prey)) //Xenomorphs eating carbon mobs
return 1
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 0a0e8422dbf..ec81cc33950 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -113,6 +113,24 @@
return U.sensor_mode
return SUIT_SENSOR_OFF
+/proc/offer_control(mob/M)
+ to_chat(M, "Control of your mob has been offered to dead players.")
+ log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.")
+ var/minhours = input(usr, "Minimum hours required to play [M]?", "Set Min Hrs", 10) as num
+ message_admins("[key_name_admin(usr)] has offered control of ([key_name_admin(M)]) to ghosts with [minhours] hrs playtime")
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as [M.real_name ? M.real_name : M.name]?", poll_time = 100, min_hours = minhours)
+ var/mob/dead/observer/theghost = null
+
+ if(LAZYLEN(candidates))
+ theghost = pick(candidates)
+ to_chat(M, "Your mob has been taken over by a ghost!")
+ message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
+ M.ghostize()
+ M.key = theghost.key
+ else
+ to_chat(M, "There were no ghosts willing to take control.")
+ message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+
/proc/check_zone(zone)
if(!zone) return "chest"
switch(zone)
diff --git a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
index d4834eccc80..476861861a3 100644
--- a/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories/sprite_accessories.dm
@@ -48,7 +48,7 @@
var/gender = NEUTER //Determines if the accessory will be skipped or included in random hair generations
// Restrict some styles to specific species
- var/list/species_allowed = list("Human", "Slime People")
+ var/list/species_allowed = list("Human", "Slime People", "Infectious Zombie", "High-Functioning Zombie")
var/list/sprite_sheets = list() //For accessories common across species but need to use 'fitted' sprites (like underwear). e.g. list("Vox" = 'icons/mob/species/vox/iconfile.dmi')
var/list/models_allowed = list() //Specifies which, if any, hairstyles or markings can be accessed by which prosthetics. Should equal the manufacturing company name in robolimbs.dm.
var/list/heads_allowed = null //Specifies which, if any, alt heads a head marking, hairstyle or facial hair style is compatible with.
diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm
index 7d40dcc184b..7c691f5093e 100755
--- a/code/modules/pda/PDA.dm
+++ b/code/modules/pda/PDA.dm
@@ -62,8 +62,8 @@ var/global/list/obj/item/pda/PDAs = list()
/*
* The Actual PDA
*/
-/obj/item/pda/New()
- ..()
+/obj/item/pda/Initialize(mapload)
+ . = ..()
PDAs += src
PDAs = sortAtom(PDAs)
update_programs()
diff --git a/code/modules/pda/cart.dm b/code/modules/pda/cart.dm
index b721bef52c4..7b7ec95b0e3 100644
--- a/code/modules/pda/cart.dm
+++ b/code/modules/pda/cart.dm
@@ -59,9 +59,9 @@
new/datum/data/pda/app/crew_records/security,
new/datum/data/pda/app/secbot_control)
-/obj/item/cartridge/security/Initialize()
+/obj/item/cartridge/security/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
- ..()
/obj/item/cartridge/detective
name = "D.E.T.E.C.T. Cartridge"
@@ -109,9 +109,9 @@
desc = "A data cartridge with an integrated radio signaler module."
programs = list(new/datum/data/pda/app/signaller)
-/obj/item/cartridge/signal/Initialize()
+/obj/item/cartridge/signal/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/signal(src)
- ..()
/obj/item/cartridge/signal/toxins
name = "Signal Ace 2"
@@ -132,9 +132,9 @@
new/datum/data/pda/app/supply,
new/datum/data/pda/app/mule_control)
-/obj/item/cartridge/quartermaster/Initialize()
+/obj/item/cartridge/quartermaster/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/mule(src)
- ..()
/obj/item/cartridge/head
name = "Easy-Record DELUXE"
@@ -154,9 +154,9 @@
new/datum/data/pda/app/status_display)
-/obj/item/cartridge/hop/Initialize()
+/obj/item/cartridge/hop/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/mule(src)
- ..()
/obj/item/cartridge/hos
name = "R.O.B.U.S.T. DELUXE"
@@ -167,9 +167,9 @@
new/datum/data/pda/app/status_display)
-/obj/item/cartridge/hos/Initialize()
+/obj/item/cartridge/hos/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
- ..()
/obj/item/cartridge/ce
name = "Power-On DELUXE"
@@ -205,9 +205,9 @@
new/datum/data/pda/app/status_display)
-/obj/item/cartridge/rd/Initialize()
+/obj/item/cartridge/rd/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/signal(src)
- ..()
/obj/item/cartridge/captain
name = "Value-PAK Cartridge"
@@ -234,9 +234,9 @@
new/datum/data/pda/app/status_display)
-/obj/item/cartridge/captain/Initialize()
+/obj/item/cartridge/captain/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
- ..()
/obj/item/cartridge/supervisor
name = "Easy-Record DELUXE"
@@ -271,9 +271,9 @@
new/datum/data/pda/app/status_display)
-/obj/item/cartridge/centcom/Initialize()
+/obj/item/cartridge/centcom/Initialize(mapload)
+ . = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
- ..()
/obj/item/cartridge/syndicate
name = "Detomatix Cartridge"
@@ -283,7 +283,8 @@
programs = list(new/datum/data/pda/utility/toggle_door)
messenger_plugins = list(new/datum/data/pda/messenger_plugin/virus/detonate)
-/obj/item/cartridge/syndicate/New()
+/obj/item/cartridge/syndicate/Initialize(mapload)
+ . = ..()
var/datum/data/pda/utility/toggle_door/D = programs[1]
if(istype(D))
D.remote_door_id = initial_remote_door_id
@@ -321,4 +322,4 @@
my_game.hacked = 1
to_chat(user, "TR4P_M45T3R.mod successfully initialized. ToS violated. User Agreement nullified. Gotta pwn them all.")
to_chat(user, "You can now create trapped versions of any mob in your collection that will damage hunters who attempt to capture it.")
- description_antag = "This copy of Nano-Mob Hunter GO! has been hacked to allow the creation of trap mobs which will cause any PDA that attempts to capture it to shock anyone holding it. Hacked copies of the game will not trigger the trap."
+ description_antag = "This copy of Nano-Mob Hunter GO! has been hacked to allow the creation of trap mobs which will cause any PDA that attempts to capture it to shock anyone holding it. Hacked copies of the game will not trigger the trap."
\ No newline at end of file
diff --git a/code/modules/pda/radio.dm b/code/modules/pda/radio.dm
index 7db0ed332d5..a49305598e6 100644
--- a/code/modules/pda/radio.dm
+++ b/code/modules/pda/radio.dm
@@ -17,13 +17,12 @@
var/on = 0 //Are we currently active??
var/menu_message = ""
-/obj/item/integrated_radio/New()
- ..()
+/obj/item/integrated_radio/Initialize(mapload)
+ . = ..()
if(istype(loc.loc, /obj/item/pda))
hostpda = loc.loc
if(bot_filter)
- spawn(5)
- add_to_radio(bot_filter)
+ add_to_radio(bot_filter)
/obj/item/integrated_radio/Destroy()
if(SSradio)
@@ -176,7 +175,8 @@
radio_connection = null
return ..()
-/obj/item/integrated_radio/signal/Initialize()
+/obj/item/integrated_radio/signal/Initialize(mapload)
+ . = ..()
if(!SSradio)
return
if(src.frequency < PUBLIC_LOW_FREQ || src.frequency > PUBLIC_HIGH_FREQ)
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index 0ee03a2b272..33741d1475b 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -15,7 +15,6 @@
use_power = NO_POWER_USE
idle_power_usage = 0
active_power_usage = 0
- var/malfunction = FALSE
/obj/machinery/power/Destroy()
disconnect_from_network()
@@ -31,7 +30,7 @@
// Non-machines should use add_delayedload(), delayed_surplus(), newavail()
/obj/machinery/power/proc/add_avail(amount)
- if(powernet && !malfunction)
+ if(powernet)
powernet.newavail += amount
return TRUE
else
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 7ebc4f4471a..a6a83d07f10 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -158,9 +158,44 @@
to_chat(user, "You need more wires.")
return
- //build the terminal and link it to the network
- make_terminal(user)
- terminal.connect_to_network()
+ if(user.loc == loc)
+ to_chat(user, "You must not be on the same tile as the [src].")
+ return
+
+ //Direction the terminal will face to
+ var/tempDir = get_dir(user, src)
+ switch(tempDir)
+ if(NORTHEAST, SOUTHEAST)
+ tempDir = EAST
+ if(NORTHWEST, SOUTHWEST)
+ tempDir = WEST
+ var/turf/tempLoc = get_step(src, reverse_direction(tempDir))
+ if(istype(tempLoc, /turf/space))
+ to_chat(user, "You can't build a terminal on space.")
+ return
+ else if(istype(tempLoc))
+ if(tempLoc.intact)
+ to_chat(user, "You must remove the floor plating first.")
+ return
+
+ to_chat(user, "You start adding cable to the [src].")
+ playsound(loc, C.usesound, 50, 1)
+
+ if(do_after(user, 50, target = src))
+ if(!terminal && panel_open)
+ T = get_turf(user)
+ var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
+ if(prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky
+ do_sparks(5, 1, src)
+ return
+
+ C.use(10) // make sure the cable gets used up
+ user.visible_message(\
+ "[user.name] adds the cables and connects the power terminal.",\
+ "You add the cables and connect the power terminal.")
+
+ make_terminal(user, tempDir, tempLoc)
+ terminal.connect_to_network()
return
//disassembling the terminal
@@ -174,18 +209,19 @@
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 50 * I.toolspeed, target = src))
- if(prob(50) && electrocute_mob(usr, terminal.powernet, terminal, 1, TRUE)) //animate the electrocution if uncautious and unlucky
- do_sparks(5, 1, src)
- return
+ if(terminal && panel_open)
+ if(prob(50) && electrocute_mob(usr, terminal.powernet, terminal, 1, TRUE)) //animate the electrocution if uncautious and unlucky
+ do_sparks(5, 1, src)
+ return
- //give the wires back and delete the terminal
- new /obj/item/stack/cable_coil(T,10)
- user.visible_message(\
- "[user.name] cuts the cables and dismantles the power terminal.",\
- "You cut the cables and dismantle the power terminal.")
- inputting = 0 //stop inputting, since we have don't have a terminal anymore
- qdel(terminal)
- return
+ //give the wires back and delete the terminal
+ new /obj/item/stack/cable_coil(T,10)
+ user.visible_message(\
+ "[user.name] cuts the cables and dismantles the power terminal.",\
+ "You cut the cables and dismantle the power terminal.")
+ inputting = 0 //stop inputting, since we have don't have a terminal anymore
+ qdel(terminal)
+ return
//crowbarring it !
default_deconstruction_crowbar(I)
@@ -197,6 +233,13 @@
return 1
return 0
+/obj/machinery/power/smes/proc/make_terminal(user, tempDir, tempLoc)
+ // create a terminal object at the same position as original turf loc
+ // wires will attach to this
+ terminal = new /obj/machinery/power/terminal(tempLoc)
+ terminal.dir = tempDir
+ terminal.master = src
+
/obj/machinery/power/smes/Destroy()
if(SSticker && SSticker.current_state == GAME_STATE_PLAYING)
var/area/area = get_area(src)
@@ -299,45 +342,6 @@
update_icon()
return
-//Will return 1 on failure
-/obj/machinery/power/smes/proc/make_terminal(const/mob/user)
- if(user.loc == loc)
- to_chat(user, "You must not be on the same tile as the [src].")
- return 1
-
- //Direction the terminal will face to
- var/tempDir = get_dir(user, src)
- switch(tempDir)
- if(NORTHEAST, SOUTHEAST)
- tempDir = EAST
- if(NORTHWEST, SOUTHWEST)
- tempDir = WEST
- var/turf/tempLoc = get_step(src, reverse_direction(tempDir))
- if(istype(tempLoc, /turf/space))
- to_chat(user, "You can't build a terminal on space.")
- return 1
- else if(istype(tempLoc))
- if(tempLoc.intact)
- to_chat(user, "You must remove the floor plating first.")
- return 1
- to_chat(user, "You start adding cable to the [src].")
- if(do_after(user, 50, target = src))
- var/turf/T = get_turf(user)
- var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
- if(prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky
- do_sparks(5, 1, src)
- return
-
- user.visible_message(\
- "[user.name] adds the cables and connects the power terminal.",\
- "You add the cables and connect the power terminal.")
-
- terminal = new /obj/machinery/power/terminal(tempLoc)
- terminal.dir = tempDir
- terminal.master = src
- return 0
- return 1
-
/obj/machinery/power/smes/attack_ai(mob/user)
add_hiddenprint(user)
ui_interact(user)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index eea2c2253e8..fbc29da0391 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -124,12 +124,6 @@
else
user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear \a [fire_sound_text]!")
- if(weapon_weight >= WEAPON_MEDIUM)
- if(user.get_inactive_hand())
- if(prob(15))
- if(user.drop_item())
- user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!")
-
/obj/item/gun/emp_act(severity)
for(var/obj/O in contents)
O.emp_act(severity)
@@ -174,7 +168,20 @@
to_chat(user, "You need both hands free to fire \the [src]!")
return
- process_fire(target,user,1,params)
+ //DUAL WIELDING
+ var/bonus_spread = 0
+ var/loop_counter = 0
+ if(ishuman(user) && user.a_intent == INTENT_HARM)
+ var/mob/living/carbon/human/H = user
+ for(var/obj/item/gun/G in get_both_hands(H))
+ if(G == src || G.weapon_weight >= WEAPON_MEDIUM)
+ continue
+ else if(G.can_trigger_gun(user))
+ bonus_spread += 24 * G.weapon_weight
+ loop_counter++
+ addtimer(CALLBACK(G, .proc/process_fire, target, user, 1, params, null, bonus_spread), loop_counter)
+
+ process_fire(target,user,1,params, null, bonus_spread)
/obj/item/gun/proc/can_trigger_gun(mob/living/user)
if(!user.can_use_guns(src))
@@ -184,20 +191,20 @@
return 0
return 1
-obj/item/gun/proc/newshot()
+/obj/item/gun/proc/newshot()
return
-/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override)
+/obj/item/gun/proc/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override, bonus_spread = 0)
add_fingerprint(user)
if(semicd)
return
- if(weapon_weight)
- if(user.get_inactive_hand())
- recoil = 4 //one-handed kick
- else
- recoil = initial(recoil)
+ var/sprd = 0
+ var/randomized_gun_spread = 0
+ if(spread)
+ randomized_gun_spread = rand(0,spread)
+ var/randomized_bonus_spread = rand(0, bonus_spread)
if(burst_size > 1)
firing_burst = 1
@@ -208,11 +215,10 @@ obj/item/gun/proc/newshot()
if( i>1 && !(src in get_both_hands(user))) //for burst firing
break
if(chambered)
- var/sprd = 0
if(randomspread)
- sprd = round((rand() - 0.5) * spread)
+ sprd = round((rand() - 0.5) * (randomized_gun_spread + randomized_bonus_spread))
else
- sprd = round((i / burst_size - 0.5) * spread)
+ sprd = round((i / burst_size - 0.5) * (randomized_gun_spread + randomized_bonus_spread))
if(!chambered.fire(target, user, params, ,suppressed, zone_override, sprd))
shoot_with_empty_chamber(user)
break
@@ -230,7 +236,8 @@ obj/item/gun/proc/newshot()
firing_burst = 0
else
if(chambered)
- if(!chambered.fire(target, user, params, , suppressed, zone_override, spread))
+ sprd = round((pick(1,-1)) * (randomized_gun_spread + randomized_bonus_spread))
+ if(!chambered.fire(target, user, params, , suppressed, zone_override, sprd))
shoot_with_empty_chamber(user)
return
else
diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm
index 36bba8f3112..d9f149b3b17 100644
--- a/code/modules/projectiles/guns/alien.dm
+++ b/code/modules/projectiles/guns/alien.dm
@@ -80,7 +80,7 @@
ammo_type = list(/obj/item/ammo_casing/energy/sonic)
cell_type = /obj/item/stock_parts/cell/super
restricted_species = list(/datum/species/vox/armalis)
- sprite_sheets = list("Vox Armalis" = 'icons/mob/species/armalis/held.dmi')
+ sprite_sheets_inhand = list("Vox Armalis" = 'icons/mob/species/armalis/held.dmi') //Big guns big birds.
/obj/item/gun/energy/noisecannon/update_icon()
return
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 6e4de3c49fa..3fbfcdaa934 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -21,6 +21,12 @@
/obj/item/gun/energy/emp_act(severity)
power_supply.use(round(power_supply.charge / severity))
+ if(chambered)//phil235
+ if(chambered.BB)
+ qdel(chambered.BB)
+ chambered.BB = null
+ chambered = null
+ newshot() //phil235
update_icon()
/obj/item/gun/energy/get_cell()
@@ -34,6 +40,7 @@
power_supply = new(src)
power_supply.give(power_supply.maxcharge)
update_ammo_types()
+ on_recharge()
if(selfcharge)
START_PROCESSING(SSobj, src)
update_icon()
@@ -67,8 +74,12 @@
if(!external || !external.use(E.e_cost)) //Take power from the borg...
return //Note, uses /10 because of shitty mods to the cell system
power_supply.give(100) //... to recharge the shot
+ on_recharge()
update_icon()
+/obj/item/gun/energy/proc/on_recharge()
+ newshot()
+
/obj/item/gun/energy/attack_self(mob/living/user as mob)
if(ammo_type.len > 1)
select_fire(user)
@@ -78,10 +89,6 @@
H.update_inv_l_hand()
H.update_inv_r_hand()
-/obj/item/gun/energy/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params)
- newshot() //prepare a new shot
- ..()
-
/obj/item/gun/energy/can_shoot()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
return power_supply.charge >= shot.e_cost
@@ -89,18 +96,20 @@
/obj/item/gun/energy/newshot()
if(!ammo_type || !power_supply)
return
- var/obj/item/ammo_casing/energy/shot = ammo_type[select]
- if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell...
- chambered = shot //...prepare a new shot based on the current ammo type selected
- chambered.newshot()
- return
+ if(!chambered)
+ var/obj/item/ammo_casing/energy/shot = ammo_type[select]
+ if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell...
+ chambered = shot //...prepare a new shot based on the current ammo type selected
+ if(!chambered.BB)
+ chambered.newshot()
/obj/item/gun/energy/process_chamber()
if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired...
var/obj/item/ammo_casing/energy/shot = chambered
power_supply.use(shot.e_cost)//... drain the power_supply cell
+ robocharge()
chambered = null //either way, released the prepared shot
- return
+ newshot()
/obj/item/gun/energy/proc/select_fire(mob/living/user)
select++
@@ -111,6 +120,12 @@
fire_delay = shot.delay
if(shot.select_name)
to_chat(user, "[src] is now set to [shot.select_name].")
+ if(chambered)//phil235
+ if(chambered.BB)
+ qdel(chambered.BB)
+ chambered.BB = null
+ chambered = null
+ newshot()
update_icon()
return
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index d214309728e..b93ddefd0d5 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -134,6 +134,7 @@
/obj/item/gun/energy/kinetic_accelerator/proc/reload()
power_supply.give(500)
+ on_recharge()
if(!suppressed)
playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
else if(isliving(loc))
diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm
index 6cc27a08f09..949ee16fa06 100644
--- a/code/modules/projectiles/guns/energy/nuclear.dm
+++ b/code/modules/projectiles/guns/energy/nuclear.dm
@@ -79,7 +79,7 @@
slot_flags = null
w_class = WEIGHT_CLASS_HUGE
ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser)
- weapon_weight = WEAPON_MEDIUM
+ weapon_weight = WEAPON_HEAVY
can_flashlight = 0
trigger_guard = TRIGGER_GUARD_NONE
ammo_x_offset = 2
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index be60248cded..4499fca3797 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -168,11 +168,13 @@
var/obj/item/stack/sheet/S = A
S.use(1)
power_supply.give(1000)
+ on_recharge()
to_chat(user, "You insert [A] in [src], recharging it.")
else if(istype(A, /obj/item/stack/ore/plasma))
var/obj/item/stack/ore/S = A
S.use(1)
power_supply.give(500)
+ on_recharge()
to_chat(user, "You insert [A] in [src], recharging it.")
else
return ..()
@@ -251,10 +253,6 @@
/obj/item/gun/energy/printer/emp_act()
return
-/obj/item/gun/energy/printer/newshot()
- ..()
- robocharge()
-
// Instakill Lasers //
/obj/item/gun/energy/laser/instakill
name = "instakill rifle"
diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm
index 9002f12ff35..5b70f2b3282 100644
--- a/code/modules/projectiles/guns/projectile/saw.dm
+++ b/code/modules/projectiles/guns/projectile/saw.dm
@@ -7,7 +7,7 @@
slot_flags = 0
origin_tech = "combat=6;engineering=3;syndicate=6"
mag_type = /obj/item/ammo_box/magazine/mm556x45
- weapon_weight = WEAPON_MEDIUM
+ weapon_weight = WEAPON_HEAVY
fire_sound = 'sound/weapons/gunshots/gunshot_mg.ogg'
magin_sound = 'sound/weapons/gun_interactions/lmg_magin.ogg'
magout_sound = 'sound/weapons/gun_interactions/lmg_magout.ogg'
diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm
index 46286bef2af..8b658911b3b 100644
--- a/code/modules/projectiles/guns/projectile/shotgun.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun.dm
@@ -11,6 +11,7 @@
mag_type = /obj/item/ammo_box/magazine/internal/shot
fire_sound = 'sound/weapons/gunshots/gunshot_shotgun.ogg'
var/recentpump = 0 // to prevent spammage
+ weapon_weight = WEAPON_MEDIUM
/obj/item/gun/projectile/shotgun/attackby(obj/item/A, mob/user, params)
. = ..()
diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm
index e030c9afb2a..b310ce6d884 100644
--- a/code/modules/projectiles/guns/projectile/sniper.dm
+++ b/code/modules/projectiles/guns/projectile/sniper.dm
@@ -4,7 +4,7 @@
icon_state = "sniper"
item_state = "sniper"
recoil = 2
- weapon_weight = WEAPON_MEDIUM
+ weapon_weight = WEAPON_HEAVY
mag_type = /obj/item/ammo_box/magazine/sniper_rounds
fire_sound = 'sound/weapons/gunshots/gunshot_sniper.ogg'
magin_sound = 'sound/weapons/gun_interactions/batrifle_magin.ogg'
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index d5e26182ecc..5dabd8a9db6 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -184,8 +184,10 @@
var/randomize = pick("robot", "slime", "xeno", "human", "animal")
switch(randomize)
if("robot")
+ var/path
if(prob(30))
- new_mob = new /mob/living/silicon/robot/syndicate(M.loc)
+ path = pick(typesof(/mob/living/silicon/robot/syndicate))
+ new_mob = new path(M.loc)
else
new_mob = new /mob/living/silicon/robot(M.loc)
new_mob.gender = M.gender
@@ -193,6 +195,10 @@
new_mob.job = "Cyborg"
var/mob/living/silicon/robot/Robot = new_mob
Robot.mmi = new /obj/item/mmi(new_mob)
+ Robot.lawupdate = FALSE
+ Robot.connected_ai = null
+ Robot.clear_inherent_laws()
+ Robot.clear_zeroth_law()
if(ishuman(M))
Robot.mmi.transfer_identity(M) //Does not transfer key/client.
if("slime")
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index de11cb557a9..41646c114af 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -143,7 +143,6 @@
M.apply_effect((rand(30,80)),IRRADIATE)
M.Weaken(5)
M.visible_message("[M] writhes in pain as [M.p_their()] vacuoles boil.", "You writhe in pain as your vacuoles boil!", "You hear the crunching of leaves.")
- if(prob(35))
if(prob(80))
randmutb(M)
domutcheck(M,null)
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 69023a3e6e8..9b64161f58b 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -785,6 +785,55 @@ var/const/INGEST = 2
trans_data["viruses"] = temp
return trans_data
+/datum/reagents/proc/generate_taste_message(minimum_percent = TASTE_SENSITIVITY_NORMAL)
+ var/list/out = list()
+ var/list/reagent_tastes = list() //in the form reagent_tastes["descriptor"] = strength
+ //mobs should get this message when either they cannot taste, the tastes are all too weak for them to detect, or the tastes somehow don't have any strength
+ var/no_taste_text = "something indescribable"
+ if(minimum_percent > 100)
+ return no_taste_text
+ for(var/datum/reagent/R in reagent_list)
+ if(!R.taste_mult)
+ continue
+ //nutriment carries a list of tastes that originates from the snack food that the nutriment came from
+ if(istype(R, /datum/reagent/consumable/nutriment))
+ var/list/nutriment_taste_data = R.data
+ for(var/nutriment_taste in nutriment_taste_data)
+ var/ratio = nutriment_taste_data[nutriment_taste]
+ var/amount = ratio * R.taste_mult * R.volume
+ if(nutriment_taste in reagent_tastes)
+ reagent_tastes[nutriment_taste] += amount
+ else
+ reagent_tastes[nutriment_taste] = amount
+ else
+ var/taste_desc = R.taste_description
+ var/taste_amount = R.volume * R.taste_mult
+ if(taste_desc in reagent_tastes)
+ reagent_tastes[taste_desc] += taste_amount
+ else
+ reagent_tastes[taste_desc] = taste_amount
+ //deal with percentages
+ //TODO: may want to sort these from strong to weak
+ var/total_taste = counterlist_sum(reagent_tastes)
+ if(total_taste <= 0)
+ return no_taste_text
+ for(var/taste_desc in reagent_tastes)
+ var/percent = (reagent_tastes[taste_desc] / total_taste) * 100
+ if(percent < minimum_percent) //the lower the minimum percent, the more sensitive the message is
+ continue
+ var/intensity_desc = "a hint of"
+ if(percent > minimum_percent * 3 && percent != 100)
+ intensity_desc = "a strong flavor of"
+ else if(percent > minimum_percent * 2 || percent == 100)
+ intensity_desc = ""
+
+ if(intensity_desc != "")
+ out += "[intensity_desc] [taste_desc]"
+ else
+ out += "[taste_desc]"
+
+ return english_list(out, no_taste_text)
+
///////////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm
index d4199c3dcec..b1aca9820b5 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -26,8 +26,8 @@
var/drink_icon = null
var/drink_name = "Glass of ..what?"
var/drink_desc = "You can't really tell what this is."
- var/taste_strength = 1 //how easy it is to taste - the more the easier
- var/taste_message = "bitterness" //life's bitter by default. Cool points for using a span class for when you're tasting LIQUID FUCKING DEATH
+ var/taste_mult = 1 //how easy it is to taste - the more the easier
+ var/taste_description = "metaphorical salt"
/datum/reagent/Destroy()
. = ..()
diff --git a/code/modules/reagents/chemistry/reagents/admin.dm b/code/modules/reagents/chemistry/reagents/admin.dm
index 0856955da2b..c238c63a8ff 100644
--- a/code/modules/reagents/chemistry/reagents/admin.dm
+++ b/code/modules/reagents/chemistry/reagents/admin.dm
@@ -6,7 +6,7 @@
color = "#C8A5DC" // rgb: 200, 165, 220
process_flags = ORGANIC | SYNTHETIC //Adminbuse knows no bounds!
can_synth = FALSE
- taste_message = "admin abuse"
+ taste_description = "admin abuse"
/datum/reagent/medicine/adminordrazine/on_mob_life(mob/living/carbon/M)
M.setCloneLoss(0, FALSE)
@@ -58,4 +58,4 @@
name = "Nanites"
id = "nanites"
description = "Nanomachines that aid in rapid cellular regeneration."
- taste_message = "nanomachines, son"
+ taste_description = "nanomachines, son"
diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm
index 6dde9d2a4ec..5b65a062ea7 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol.dm
@@ -8,7 +8,7 @@
color = "#404030" // rgb: 64, 64, 48
var/dizzy_adj = 3
var/alcohol_perc = 1 //percentage of ethanol in a beverage 0.0 - 1.0
- taste_message = "liquid fire"
+ taste_description = "liquid fire"
/datum/reagent/consumable/ethanol/on_mob_life(mob/living/M)
M.AdjustDrunk(alcohol_perc)
@@ -46,7 +46,7 @@
drink_icon ="beerglass"
drink_name = "Beer glass"
drink_desc = "A freezing pint of beer"
- taste_message = "beer"
+ taste_description = "beer"
/datum/reagent/consumable/ethanol/cider
name = "Cider"
@@ -58,7 +58,7 @@
drink_icon = "rewriter"
drink_name = "Cider"
drink_desc = "a refreshing glass of traditional cider"
- taste_message = "cider"
+ taste_description = "cider"
/datum/reagent/consumable/ethanol/whiskey
name = "Whiskey"
@@ -70,7 +70,7 @@
drink_icon = "whiskeyglass"
drink_name = "Glass of whiskey"
drink_desc = "The silky, smokey whiskey goodness inside the glass makes the drink look very classy."
- taste_message = "whiskey"
+ taste_description = "whiskey"
/datum/reagent/consumable/ethanol/specialwhiskey
name = "Special Blend Whiskey"
@@ -78,7 +78,7 @@
description = "Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything."
color = "#664300" // rgb: 102, 67, 0
alcohol_perc = 0.5
- taste_message = "class"
+ taste_description = "class"
/datum/reagent/consumable/ethanol/gin
name = "Gin"
@@ -90,7 +90,7 @@
drink_icon = "ginvodkaglass"
drink_name = "Glass of gin"
drink_desc = "A crystal clear glass of Griffeater gin."
- taste_message = "gin"
+ taste_description = "gin"
/datum/reagent/consumable/ethanol/absinthe
name = "Absinthe"
@@ -103,7 +103,7 @@
drink_icon = "absinthebottle"
drink_name = "Glass of Absinthe"
drink_desc = "The green fairy is going to get you now!"
- taste_message = "fucking pain"
+ taste_description = "fucking pain"
//copy paste from LSD... shoot me
/datum/reagent/consumable/ethanol/absinthe/on_mob_life(mob/living/M)
@@ -125,7 +125,7 @@
drink_icon = "glass_brown2"
drink_name = "Hooch"
drink_desc = "You've really hit rock bottom now... your liver packed its bags and left last night."
- taste_message = "pure resignation"
+ taste_description = "pure resignation"
/datum/reagent/consumable/ethanol/hooch/on_mob_life(mob/living/carbon/M)
if(M.mind && M.mind.assigned_role == "Assistant")
@@ -144,7 +144,7 @@
drink_icon = "rumglass"
drink_name = "Glass of Rum"
drink_desc = "Now you want to Pray for a pirate suit, don't you?"
- taste_message = "rum"
+ taste_description = "rum"
/datum/reagent/consumable/ethanol/rum/overdose_process(mob/living/M, severity)
var/update_flags = STATUS_UPDATE_NONE
@@ -160,7 +160,7 @@
drink_icon = "mojito"
drink_name = "Glass of Mojito"
drink_desc = "Fresh from Spesscuba."
- taste_message = "mojito"
+ taste_description = "mojito"
/datum/reagent/consumable/ethanol/vodka
name = "Vodka"
@@ -171,7 +171,7 @@
drink_icon = "ginvodkaglass"
drink_name = "Glass of vodka"
drink_desc = "The glass contain wodka. Xynta."
- taste_message = "vodka"
+ taste_description = "vodka"
/datum/reagent/consumable/ethanol/sake
name = "Sake"
@@ -182,7 +182,7 @@
drink_icon = "ginvodkaglass"
drink_name = "Glass of Sake"
drink_desc = "A glass of Sake."
- taste_message = "sake"
+ taste_description = "sake"
/datum/reagent/consumable/ethanol/tequila
name = "Tequila"
@@ -193,7 +193,7 @@
drink_icon = "tequilaglass"
drink_name = "Glass of Tequila"
drink_desc = "Now all that's missing is the weird colored shades!"
- taste_message = "tequila"
+ taste_description = "tequila"
/datum/reagent/consumable/ethanol/vermouth
name = "Vermouth"
@@ -204,7 +204,7 @@
drink_icon = "vermouthglass"
drink_name = "Glass of Vermouth"
drink_desc = "You wonder why you're even drinking this straight."
- taste_message = "vermouth"
+ taste_description = "vermouth"
/datum/reagent/consumable/ethanol/wine
name = "Wine"
@@ -216,7 +216,7 @@
drink_icon = "wineglass"
drink_name = "Glass of wine"
drink_desc = "A very classy looking drink."
- taste_message = "wine"
+ taste_description = "wine"
/datum/reagent/consumable/ethanol/cognac
name = "Cognac"
@@ -228,7 +228,7 @@
drink_icon = "cognacglass"
drink_name = "Glass of cognac"
drink_desc = "Damn, you feel like some kind of French aristocrat just by holding this."
- taste_message = "cognac"
+ taste_description = "cognac"
/datum/reagent/consumable/ethanol/suicider //otherwise known as "I want to get so smashed my liver gives out and I die from alcohol poisoning".
name = "Suicider"
@@ -240,7 +240,7 @@
drink_icon = "suicider"
drink_name = "Suicider"
drink_desc = "You've really hit rock bottom now... your liver packed its bags and left last night."
- taste_message = "approaching death"
+ taste_description = "approaching death"
/datum/reagent/consumable/ethanol/ale
name = "Ale"
@@ -251,7 +251,7 @@
drink_icon = "aleglass"
drink_name = "Ale glass"
drink_desc = "A freezing pint of delicious Ale"
- taste_message = "ale"
+ taste_description = "ale"
/datum/reagent/consumable/ethanol/thirteenloko
name = "Thirteen Loko"
@@ -265,7 +265,7 @@
drink_icon = "thirteen_loko_glass"
drink_name = "Glass of Thirteen Loko"
drink_desc = "This is a glass of Thirteen Loko, it appears to be of the highest quality. The drink, not the glass"
- taste_message = "party"
+ taste_description = "party"
/datum/reagent/consumable/ethanol/thirteenloko/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -290,7 +290,7 @@
drink_icon = "glass_brown"
drink_name = "Glass of bilk"
drink_desc = "A brew of milk and beer. For those alcoholics who fear osteoporosis."
- taste_message = "bilk"
+ taste_description = "bilk"
/datum/reagent/consumable/ethanol/atomicbomb
name = "Atomic Bomb"
@@ -302,7 +302,7 @@
drink_icon = "atomicbombglass"
drink_name = "Atomic Bomb"
drink_desc = "Nanotrasen cannot take legal responsibility for your actions after imbibing."
- taste_message = "a long, fiery burn"
+ taste_description = "a long, fiery burn"
/datum/reagent/consumable/ethanol/threemileisland
name = "THree Mile Island Iced Tea"
@@ -314,7 +314,7 @@
drink_icon = "threemileislandglass"
drink_name = "Three Mile Island Ice Tea"
drink_desc = "A glass of this is sure to prevent a meltdown."
- taste_message = "a creeping heat"
+ taste_description = "a creeping heat"
/datum/reagent/consumable/ethanol/goldschlager
name = "Goldschlager"
@@ -326,7 +326,7 @@
drink_icon = "ginvodkaglass"
drink_name = "Glass of goldschlager"
drink_desc = "100 proof that teen girls will drink anything with gold in it."
- taste_message = "a deep, spicy warmth"
+ taste_description = "a deep, spicy warmth"
/datum/reagent/consumable/ethanol/patron
name = "Patron"
@@ -338,7 +338,7 @@
drink_icon = "patronglass"
drink_name = "Glass of Patron"
drink_desc = "Drinking patron in the bar, with all the subpar ladies."
- taste_message = "a gift"
+ taste_description = "a gift"
/datum/reagent/consumable/ethanol/gintonic
name = "Gin and Tonic"
@@ -350,7 +350,7 @@
drink_icon = "gintonicglass"
drink_name = "Gin and Tonic"
drink_desc = "A mild but still great cocktail. Drink up, like a true Englishman."
- taste_message = "bitter medicine"
+ taste_description = "bitter medicine"
/datum/reagent/consumable/ethanol/cuba_libre
name = "Cuba Libre"
@@ -362,8 +362,8 @@
drink_icon = "cubalibreglass"
drink_name = "Cuba Libre"
drink_desc = "A classic mix of rum and cola."
- taste_message = "fruity alcohol"
- taste_message = "liberation"
+ taste_description = "fruity alcohol"
+ taste_description = "liberation"
/datum/reagent/consumable/ethanol/whiskey_cola
name = "Whiskey Cola"
@@ -375,7 +375,7 @@
drink_icon = "whiskeycolaglass"
drink_name = "Whiskey Cola"
drink_desc = "An innocent-looking mixture of cola and Whiskey. Delicious."
- taste_message = "whiskey and coke"
+ taste_description = "whiskey and coke"
/datum/reagent/consumable/ethanol/martini
name = "Classic Martini"
@@ -387,7 +387,7 @@
drink_icon = "martiniglass"
drink_name = "Classic Martini"
drink_desc = "Damn, the bartender even stirred it, not shook it."
- taste_message = "class"
+ taste_description = "class"
/datum/reagent/consumable/ethanol/vodkamartini
name = "Vodka Martini"
@@ -399,7 +399,7 @@
drink_icon = "martiniglass"
drink_name = "Vodka martini"
drink_desc ="A bastardisation of the classic martini. Still great."
- taste_message = "class and potatoes"
+ taste_description = "class and potatoes"
/datum/reagent/consumable/ethanol/white_russian
name = "White Russian"
@@ -411,7 +411,7 @@
drink_icon = "whiterussianglass"
drink_name = "White Russian"
drink_desc = "A very nice looking drink. But that's just, like, your opinion, man."
- taste_message = "very creamy alcohol"
+ taste_description = "very creamy alcohol"
/datum/reagent/consumable/ethanol/screwdrivercocktail
name = "Screwdriver"
@@ -423,7 +423,7 @@
drink_icon = "screwdriverglass"
drink_name = "Screwdriver"
drink_desc = "A simple, yet superb mixture of Vodka and orange juice. Just the thing for the tired engineer."
- taste_message = "a naughty secret"
+ taste_description = "a naughty secret"
/datum/reagent/consumable/ethanol/booger
name = "Booger"
@@ -435,7 +435,7 @@
drink_icon = "booger"
drink_name = "Booger"
drink_desc = "Eww..."
- taste_message = "a fruity mess"
+ taste_description = "a fruity mess"
/datum/reagent/consumable/ethanol/bloody_mary
name = "Bloody Mary"
@@ -447,7 +447,7 @@
drink_icon = "bloodymaryglass"
drink_name = "Bloody Mary"
drink_desc = "Tomato juice, mixed with Vodka and a lil' bit of lime. Tastes like liquid murder."
- taste_message = "tomatoes with booze"
+ taste_description = "tomatoes with booze"
/datum/reagent/consumable/ethanol/gargle_blaster
name = "Pan-Galactic Gargle Blaster"
@@ -459,7 +459,7 @@
drink_icon = "gargleblasterglass"
drink_name = "Pan-Galactic Gargle Blaster"
drink_desc = "Does... does this mean that Arthur and Ford are on the station? Oh joy."
- taste_message = "the number fourty two"
+ taste_description = "the number fourty two"
/datum/reagent/consumable/ethanol/flaming_homer
name = "Flaming Moe"
@@ -471,7 +471,7 @@
drink_icon = "flamingmoeglass"
drink_name = "Flaming Moe"
drink_desc = "Happiness is just a Flaming Moe away!"
- taste_message = "caramelised booze and sweet, salty medicine"
+ taste_description = "caramelised booze and sweet, salty medicine"
/datum/reagent/consumable/ethanol/brave_bull
name = "Brave Bull"
@@ -483,7 +483,7 @@
drink_icon = "bravebullglass"
drink_name = "Brave Bull"
drink_desc = "Tequila and Coffee liquor, brought together in a mouthwatering mixture. Drink up."
- taste_message = "sweet alcohol"
+ taste_description = "sweet alcohol"
/datum/reagent/consumable/ethanol/tequila_sunrise
name = "Tequila Sunrise"
@@ -495,7 +495,7 @@
drink_icon = "tequilasunriseglass"
drink_name = "Tequila Sunrise"
drink_desc = "Oh great, now you feel nostalgic about sunrises back on Terra..."
- taste_message = "fruity alcohol"
+ taste_description = "fruity alcohol"
/datum/reagent/consumable/ethanol/toxins_special
name = "Toxins Special"
@@ -507,7 +507,7 @@
drink_icon = "toxinsspecialglass"
drink_name = "Toxins Special"
drink_desc = "Whoah, this thing is on FIRE"
- taste_message = "FIRE"
+ taste_description = "FIRE"
/datum/reagent/consumable/ethanol/toxins_special/on_mob_life(mob/living/M)
if(M.bodytemperature < 330)
@@ -525,7 +525,7 @@
description = "Whiskey-imbued cream, what else would you expect from the Irish."
drink_name = "Beepsky Smash"
drink_desc = "Heavy, hot and strong. Just like the Iron fist of the LAW."
- taste_message = "THE LAW"
+ taste_description = "THE LAW"
/datum/reagent/consumable/ethanol/beepsky_smash/on_mob_life(mob/living/M)
var/update_flag = STATUS_UPDATE_NONE
@@ -541,7 +541,7 @@
drink_icon = "irishcreamglass"
drink_name = "Irish Cream"
drink_desc = "It's cream, mixed with whiskey. What else would you expect from the Irish?"
- taste_message = "creamy alcohol"
+ taste_description = "creamy alcohol"
/datum/reagent/consumable/ethanol/manly_dorf
name = "The Manly Dorf"
@@ -553,7 +553,7 @@
drink_icon = "manlydorfglass"
drink_name = "The Manly Dorf"
drink_desc = "A manly concotion made from Ale and Beer. Intended for true men only."
- taste_message = "manliness"
+ taste_description = "manliness"
/datum/reagent/consumable/ethanol/longislandicedtea
name = "Long Island Iced Tea"
@@ -565,7 +565,7 @@
drink_icon = "longislandicedteaglass"
drink_name = "Long Island Iced Tea"
drink_desc = "The liquor cabinet, brought together in a delicious mix. Intended for middle-aged alcoholic women only."
- taste_message = "fruity alcohol"
+ taste_description = "fruity alcohol"
/datum/reagent/consumable/ethanol/moonshine
name = "Moonshine"
@@ -577,7 +577,7 @@
drink_icon = "glass_clear"
drink_name = "Moonshine"
drink_desc = "You've really hit rock bottom now... your liver packed its bags and left last night."
- taste_message = "prohibition"
+ taste_description = "prohibition"
/datum/reagent/consumable/ethanol/b52
name = "B-52"
@@ -589,7 +589,7 @@
drink_icon = "b52glass"
drink_name = "B-52"
drink_desc = "Kahlua, Irish Cream, and congac. You will get bombed."
- taste_message = "destruction"
+ taste_description = "destruction"
/datum/reagent/consumable/ethanol/irishcoffee
name = "Irish Coffee"
@@ -601,7 +601,7 @@
drink_icon = "irishcoffeeglass"
drink_name = "Irish Coffee"
drink_desc = "Coffee and alcohol. More fun than a Mimosa to drink in the morning."
- taste_message = "coffee and booze"
+ taste_description = "coffee and booze"
/datum/reagent/consumable/ethanol/margarita
name = "Margarita"
@@ -613,7 +613,7 @@
drink_icon = "margaritaglass"
drink_name = "Margarita"
drink_desc = "On the rocks with salt on the rim. Arriba~!"
- taste_message = "daisies"
+ taste_description = "daisies"
/datum/reagent/consumable/ethanol/black_russian
name = "Black Russian"
@@ -625,7 +625,7 @@
drink_icon = "blackrussianglass"
drink_name = "Black Russian"
drink_desc = "For the lactose-intolerant. Still as classy as a White Russian."
- taste_message = "sweet alcohol"
+ taste_description = "sweet alcohol"
/datum/reagent/consumable/ethanol/manhattan
name = "Manhattan"
@@ -637,7 +637,7 @@
drink_icon = "manhattanglass"
drink_name = "Manhattan"
drink_desc = "The Detective's undercover drink of choice. He never could stomach gin..."
- taste_message = "a bustling city"
+ taste_description = "a bustling city"
/datum/reagent/consumable/ethanol/manhattan_proj
name = "Manhattan Project"
@@ -649,7 +649,7 @@
drink_icon = "proj_manhattanglass"
drink_name = "Manhattan Project"
drink_desc = "A scientist's drink of choice, for thinking how to blow up the station."
- taste_message = "the apocalypse"
+ taste_description = "the apocalypse"
/datum/reagent/consumable/ethanol/whiskeysoda
name = "Whiskey Soda"
@@ -661,7 +661,7 @@
drink_icon = "whiskeysodaglass2"
drink_name = "Whiskey Soda"
drink_desc = "Ultimate refreshment."
- taste_message = "mediocrity"
+ taste_description = "mediocrity"
/datum/reagent/consumable/ethanol/antifreeze
name = "Anti-freeze"
@@ -673,7 +673,7 @@
drink_icon = "antifreeze"
drink_name = "Anti-freeze"
drink_desc = "The ultimate refreshment."
- taste_message = "poor life choices"
+ taste_description = "poor life choices"
/datum/reagent/consumable/ethanol/antifreeze/on_mob_life(mob/living/M)
if(M.bodytemperature < 330)
@@ -690,7 +690,7 @@
drink_icon = "b&p"
drink_name = "Barefoot"
drink_desc = "Barefoot and pregnant"
- taste_message = "pregnancy"
+ taste_description = "pregnancy"
/datum/reagent/consumable/ethanol/snowwhite
name = "Snow White"
@@ -702,7 +702,7 @@
drink_icon = "snowwhite"
drink_name = "Snow White"
drink_desc = "A cold refreshment."
- taste_message = "a poisoned apple"
+ taste_description = "a poisoned apple"
/datum/reagent/consumable/ethanol/demonsblood
name = "Demons Blood"
@@ -715,7 +715,7 @@
drink_icon = "demonsblood"
drink_name = "Demons Blood"
drink_desc = "Just looking at this thing makes the hair at the back of your neck stand up."
- taste_message = "evil"
+ taste_description = "evil"
/datum/reagent/consumable/ethanol/vodkatonic
name = "Vodka and Tonic"
@@ -728,7 +728,7 @@
drink_icon = "vodkatonicglass"
drink_name = "Vodka and Tonic"
drink_desc = "For when a gin and tonic isn't russian enough."
- taste_message = "bitter medicine"
+ taste_description = "bitter medicine"
/datum/reagent/consumable/ethanol/ginfizz
name = "Gin Fizz"
@@ -741,7 +741,7 @@
drink_icon = "ginfizzglass"
drink_name = "Gin Fizz"
drink_desc = "Refreshingly lemony, deliciously dry."
- taste_message = "fizzy alcohol"
+ taste_description = "fizzy alcohol"
/datum/reagent/consumable/ethanol/bahama_mama
name = "Bahama mama"
@@ -753,7 +753,7 @@
drink_icon = "bahama_mama"
drink_name = "Bahama Mama"
drink_desc = "Tropic cocktail"
- taste_message = "HONK"
+ taste_description = "HONK"
/datum/reagent/consumable/ethanol/singulo
name = "Singulo"
@@ -766,7 +766,7 @@
drink_icon = "singulo"
drink_name = "Singulo"
drink_desc = "A blue-space beverage."
- taste_message = "infinity"
+ taste_description = "infinity"
/datum/reagent/consumable/ethanol/sbiten
name = "Sbiten"
@@ -778,7 +778,7 @@
drink_icon = "sbitenglass"
drink_name = "Sbiten"
drink_desc = "A spicy mix of Vodka and Spice. Very hot."
- taste_message = "comforting warmth"
+ taste_description = "comforting warmth"
/datum/reagent/consumable/ethanol/sbiten/on_mob_life(mob/living/M)
if(M.bodytemperature < 360)
@@ -795,7 +795,7 @@
drink_icon = "devilskiss"
drink_name = "Devils Kiss"
drink_desc = "Creepy time!"
- taste_message = "naughtiness"
+ taste_description = "naughtiness"
/datum/reagent/consumable/ethanol/red_mead
name = "Red Mead"
@@ -807,7 +807,7 @@
drink_icon = "red_meadglass"
drink_name = "Red Mead"
drink_desc = "A True Vikings Beverage, though its color is strange."
- taste_message = "blood"
+ taste_description = "blood"
/datum/reagent/consumable/ethanol/mead
name = "Mead"
@@ -820,7 +820,7 @@
drink_icon = "meadglass"
drink_name = "Mead"
drink_desc = "A Vikings Beverage, though a cheap one."
- taste_message = "honey"
+ taste_description = "honey"
/datum/reagent/consumable/ethanol/iced_beer
name = "Iced Beer"
@@ -832,7 +832,7 @@
drink_icon = "iced_beerglass"
drink_name = "Iced Beer"
drink_desc = "A beer so frosty, the air around it freezes."
- taste_message = "cold beer"
+ taste_description = "cold beer"
/datum/reagent/consumable/ethanol/iced_beer/on_mob_life(mob/living/M)
if(M.bodytemperature > 270)
@@ -849,7 +849,7 @@
drink_icon = "grogglass"
drink_name = "Grog"
drink_desc = "A fine and cepa drink for Space."
- taste_message = "strongly diluted rum"
+ taste_description = "strongly diluted rum"
/datum/reagent/consumable/ethanol/aloe
name = "Aloe"
@@ -861,7 +861,7 @@
drink_icon = "aloe"
drink_name = "Aloe"
drink_desc = "Very, very, very good."
- taste_message = "healthy skin"
+ taste_description = "healthy skin"
/datum/reagent/consumable/ethanol/andalusia
name = "Andalusia"
@@ -873,7 +873,7 @@
drink_icon = "andalusia"
drink_name = "Andalusia"
drink_desc = "A nice, strange named drink."
- taste_message = "sweet alcohol"
+ taste_description = "sweet alcohol"
/datum/reagent/consumable/ethanol/alliescocktail
name = "Allies Cocktail"
@@ -885,7 +885,7 @@
drink_icon = "alliescocktail"
drink_name = "Allies cocktail"
drink_desc = "A drink made from your allies."
- taste_message = "victory"
+ taste_description = "victory"
/datum/reagent/consumable/ethanol/acid_spit
name = "Acid Spit"
@@ -897,7 +897,7 @@
drink_icon = "acidspitglass"
drink_name = "Acid Spit"
drink_desc = "A drink from Nanotrasen. Made from live aliens."
- taste_message = "PAIN"
+ taste_description = "PAIN"
/datum/reagent/consumable/ethanol/amasec
name = "Amasec"
@@ -909,7 +909,7 @@
drink_icon = "amasecglass"
drink_name = "Amasec"
drink_desc = "Always handy before COMBAT!!!"
- taste_message = "a stunbaton"
+ taste_description = "a stunbaton"
/datum/reagent/consumable/ethanol/neurotoxin
name = "Neuro-toxin"
@@ -923,7 +923,7 @@
drink_icon = "neurotoxinglass"
drink_name = "Neurotoxin"
drink_desc = "A drink that is guaranteed to knock you silly."
- taste_message = "brain damageeeEEeee"
+ taste_description = "brain damageeeEEeee"
/datum/reagent/consumable/ethanol/neurotoxin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -945,7 +945,7 @@
drink_icon = "hippiesdelightglass"
drink_name = "Hippie's Delight"
drink_desc = "A drink enjoyed by people during the 1960's."
- taste_message = "colors"
+ taste_description = "colors"
/datum/reagent/consumable/ethanol/hippies_delight/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -983,7 +983,7 @@
drink_icon = "changelingsting"
drink_name = "Changeling Sting"
drink_desc = "A stingy drink."
- taste_message = "a tiny prick"
+ taste_description = "a tiny prick"
/datum/reagent/consumable/ethanol/irishcarbomb
name = "Irish Car Bomb"
@@ -996,7 +996,7 @@
drink_icon = "irishcarbomb"
drink_name = "Irish Car Bomb"
drink_desc = "An irish car bomb."
- taste_message = "troubles"
+ taste_description = "troubles"
/datum/reagent/consumable/ethanol/syndicatebomb
name = "Syndicate Bomb"
@@ -1008,7 +1008,7 @@
drink_icon = "syndicatebomb"
drink_name = "Syndicate Bomb"
drink_desc = "A syndicate bomb."
- taste_message = "a job offer"
+ taste_description = "a job offer"
/datum/reagent/consumable/ethanol/erikasurprise
name = "Erika Surprise"
@@ -1020,7 +1020,7 @@
drink_icon = "erikasurprise"
name = "Erika Surprise"
drink_desc = "The surprise is, it's green!"
- taste_message = "disappointment"
+ taste_description = "disappointment"
/datum/reagent/consumable/ethanol/driestmartini
name = "Driest Martini"
@@ -1033,7 +1033,7 @@
drink_icon = "driestmartiniglass"
drink_name = "Driest Martini"
drink_desc = "Only for the experienced. You think you see sand floating in the glass."
- taste_message = "dust and ashes"
+ taste_description = "dust and ashes"
/datum/reagent/consumable/ethanol/driestmartini/on_mob_life(mob/living/M)
if(current_cycle >= 55 && current_cycle < 115)
@@ -1049,7 +1049,7 @@
drink_icon = "kahluaglass"
drink_name = "Glass of RR coffee Liquor"
drink_desc = "DAMN, THIS THING LOOKS ROBUST"
- taste_message = "coffee and alcohol"
+ taste_description = "coffee and alcohol"
/datum/reagent/consumable/ethanol/kahlua/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1068,7 +1068,7 @@
drink_icon = "ginsonic"
drink_name = "Gin and Sonic"
drink_desc = "An extremely high amperage drink. Absolutely not for the true Englishman."
- taste_message = "SPEED"
+ taste_description = "SPEED"
/datum/reagent/ginsonic/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1095,7 +1095,7 @@
drink_icon = "cognacglass"
drink_name = "Glass of applejack"
drink_desc = "When cider isn't strong enough, you gotta jack it."
- taste_message = "strong cider"
+ taste_description = "strong cider"
/datum/reagent/consumable/ethanol/jackrose
name = "Jack Rose"
@@ -1106,7 +1106,7 @@
drink_icon = "patronglass"
drink_name = "Jack Rose"
drink_desc = "Drinking this makes you feel like you belong in a luxury hotel bar during the 1920s."
- taste_message = "style"
+ taste_description = "style"
/datum/reagent/consumable/ethanol/drunkenblumpkin
name = "Drunken Blumpkin"
@@ -1117,7 +1117,7 @@
drink_icon = "drunkenblumpkin"
drink_name = "Drunken Blumpkin"
drink_desc = "A drink for the drunks"
- taste_message = "weirdness"
+ taste_description = "weirdness"
/datum/reagent/consumable/ethanol/eggnog
name = "Eggnog"
@@ -1129,7 +1129,7 @@
drink_icon = "glass_yellow"
drink_name = "Eggnog"
drink_desc = "For enjoying the most wonderful time of the year."
- taste_message = "christmas spirit"
+ taste_description = "christmas spirit"
/datum/reagent/consumable/ethanol/dragons_breath //inaccessible to players, but here for admin shennanigans
name = "Dragon's Breath"
@@ -1139,7 +1139,7 @@
color = "#DC0000"
alcohol_perc = 1
can_synth = FALSE
- taste_message = "LIQUID FUCKING DEATH OH GOD WHAT THE FUCK"
+ taste_description = "LIQUID FUCKING DEATH OH GOD WHAT THE FUCK"
/datum/reagent/consumable/ethanol/dragons_breath/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == INGEST && prob(20))
@@ -1188,7 +1188,7 @@
drink_icon = "synthanolglass"
drink_name = "Glass of Synthanol"
drink_desc = "The equivalent of alcohol for synthetic crewmembers. They'd find it awful if they had tastebuds too."
- taste_message = "motor oil"
+ taste_description = "motor oil"
/datum/reagent/consumable/ethanol/synthanol/on_mob_life(mob/living/M)
if(!M.isSynthetic())
@@ -1214,7 +1214,7 @@
drink_icon = "robottearsglass"
drink_name = "Glass of Robot Tears"
drink_desc = "No robots were hurt in the making of this drink."
- taste_message = "existential angst"
+ taste_description = "existential angst"
/datum/reagent/consumable/ethanol/synthanol/trinary
name = "Trinary"
@@ -1226,7 +1226,7 @@
drink_icon = "trinaryglass"
drink_name = "Glass of Trinary"
drink_desc = "Colorful drink made for synthetic crewmembers. It doesn't seem like it would taste well."
- taste_message = "modem static"
+ taste_description = "modem static"
/datum/reagent/consumable/ethanol/synthanol/servo
name = "Servo"
@@ -1238,7 +1238,7 @@
drink_icon = "servoglass"
drink_name = "Glass of Servo"
drink_desc = "Chocolate - based drink made for IPCs. Not sure if anyone's actually tried out the recipe."
- taste_message = "motor oil and cocoa"
+ taste_description = "motor oil and cocoa"
/datum/reagent/consumable/ethanol/synthanol/uplink
name = "Uplink"
@@ -1250,7 +1250,7 @@
drink_icon = "uplinkglass"
drink_name = "Glass of Uplink"
drink_desc = "An exquisite mix of the finest liquoirs and synthanol. Meant only for synthetics."
- taste_message = "a GUI in visual basic"
+ taste_description = "a GUI in visual basic"
/datum/reagent/consumable/ethanol/synthanol/synthnsoda
name = "Synth 'n Soda"
@@ -1262,7 +1262,7 @@
drink_icon = "synthnsodaglass"
drink_name = "Glass of Synth 'n Soda"
drink_desc = "Classic drink altered to fit the tastes of a robot. Bad idea to drink if you're made of carbon."
- taste_message = "fizzy motor oil"
+ taste_description = "fizzy motor oil"
/datum/reagent/consumable/ethanol/synthanol/synthignon
name = "Synthignon"
@@ -1274,7 +1274,7 @@
drink_icon = "synthignonglass"
drink_name = "Glass of Synthignon"
drink_desc = "Someone mixed good wine and robot booze. Romantic, but atrocious."
- taste_message = "fancy motor oil"
+ taste_description = "fancy motor oil"
/datum/reagent/consumable/ethanol/fruit_wine
name = "Fruit Wine"
@@ -1282,7 +1282,7 @@
description = "A wine made from grown plants."
color = "#FFFFFF"
alcohol_perc = 0.35
- taste_message = "bad coding"
+ taste_description = "bad coding"
can_synth = FALSE
var/list/names = list("null fruit" = 1) //Names of the fruits used. Associative list where name is key, value is the percentage of that fruit.
var/list/tastes = list("bad coding" = 1) //List of tastes. See above.
@@ -1376,7 +1376,7 @@
if(secondary_tastes.len)
flavor += ", with a hint of "
flavor += english_list(secondary_tastes)
- taste_message = flavor
+ taste_description = flavor
if(holder.my_atom)
holder.my_atom.on_reagent_change()
@@ -1390,4 +1390,4 @@
drink_icon = "glass_brown2"
drink_name = "Bacchus' Blessing"
drink_desc = "You didn't think it was possible for a liquid to be so utterly revolting. Are you sure about this...?"
- taste_message = "a wall of bricks"
+ taste_description = "a wall of bricks"
diff --git a/code/modules/reagents/chemistry/reagents/disease.dm b/code/modules/reagents/chemistry/reagents/disease.dm
index 9ce636b466a..27fe0dacc40 100644
--- a/code/modules/reagents/chemistry/reagents/disease.dm
+++ b/code/modules/reagents/chemistry/reagents/disease.dm
@@ -181,6 +181,7 @@
name = "sucrose agar"
id = "sugarvirusfood"
color = "#41B0C0" // rgb: 65,176,192
+ taste_mult = 1.5
/datum/reagent/medicine/diphenhydramine/diphenhydraminevirusfood
name = "virus rations"
diff --git a/code/modules/reagents/chemistry/reagents/drink_base.dm b/code/modules/reagents/chemistry/reagents/drink_base.dm
index 236da829c73..8f15156753e 100644
--- a/code/modules/reagents/chemistry/reagents/drink_base.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_base.dm
@@ -4,7 +4,7 @@
description = "Uh, some kind of drink."
reagent_state = LIQUID
color = "#E78108" // rgb: 231, 129, 8
- taste_message = "something which should not exist"
+ taste_description = "something which should not exist"
var/adj_dizzy = 0
var/adj_drowsy = 0
var/adj_sleepy = 0
diff --git a/code/modules/reagents/chemistry/reagents/drink_cold.dm b/code/modules/reagents/chemistry/reagents/drink_cold.dm
index 707aab07b54..ac7adf3eadf 100644
--- a/code/modules/reagents/chemistry/reagents/drink_cold.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_cold.dm
@@ -1,7 +1,6 @@
/datum/reagent/consumable/drink/cold
name = "Cold drink"
adj_temp_cool = 5
- taste_message = null
/datum/reagent/consumable/drink/cold/tonic
name = "Tonic Water"
@@ -14,7 +13,7 @@
drink_icon = "glass_clear"
drink_name = "Glass of Tonic Water"
drink_desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away."
- taste_message = "bitterness"
+ taste_description = "bitterness"
/datum/reagent/consumable/drink/cold/sodawater
name = "Soda Water"
@@ -26,7 +25,7 @@
drink_icon = "glass_clear"
drink_name = "Glass of Soda Water"
drink_desc = "Soda water. Why not make a scotch and soda?"
- taste_message = "fizz"
+ taste_description = "fizz"
/datum/reagent/consumable/drink/cold/ice
name = "Ice"
@@ -38,7 +37,7 @@
drink_icon = "iceglass"
drink_name = "Glass of ice"
drink_desc = "Generally, you're supposed to put something else in there too..."
- taste_message = "cold"
+ taste_description = "cold"
/datum/reagent/consumable/drink/cold/ice/on_mob_life(mob/living/M)
M.bodytemperature = max(M.bodytemperature - 5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
@@ -54,7 +53,7 @@
drink_icon = "glass_brown"
drink_name = "Glass of Space Cola"
drink_desc = "A glass of refreshing Space Cola"
- taste_message = "cola"
+ taste_description = "cola"
/datum/reagent/consumable/drink/cold/nuka_cola
name = "Nuka Cola"
@@ -65,7 +64,7 @@
drink_icon = "nuka_colaglass"
drink_name = "Nuka Cola"
drink_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland"
- taste_message = "radioactive cola"
+ taste_description = "radioactive cola"
/datum/reagent/consumable/drink/cold/nuka_cola/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -90,7 +89,7 @@
drink_icon = "Space_mountain_wind_glass"
drink_name = "Glass of Space Mountain Wind"
drink_desc = "Space Mountain Wind. As you know, there are no mountains in space, only wind."
- taste_message = "lime soda"
+ taste_description = "lime soda"
/datum/reagent/consumable/drink/cold/dr_gibb
name = "Dr. Gibb"
@@ -101,7 +100,7 @@
drink_icon = "dr_gibb_glass"
drink_name = "Glass of Dr. Gibb"
drink_desc = "Dr. Gibb. Not as dangerous as the name might imply."
- taste_message = "cherry soda"
+ taste_description = "cherry soda"
/datum/reagent/consumable/drink/cold/space_up
name = "Space-Up"
@@ -112,7 +111,7 @@
drink_icon = "space-up_glass"
drink_name = "Glass of Space-up"
drink_desc = "Space-up. It helps keep your cool."
- taste_message = "lemon soda"
+ taste_description = "lemon soda"
/datum/reagent/consumable/drink/cold/lemon_lime
name = "Lemon Lime"
@@ -120,7 +119,7 @@
id = "lemon_lime"
color = "#878F00" // rgb: 135, 40, 0
adj_temp_cool = 8
- taste_message = "citrus soda"
+ taste_description = "citrus soda"
/datum/reagent/consumable/drink/cold/lemonade
name = "Lemonade"
@@ -130,7 +129,7 @@
drink_icon = "lemonade"
drink_name = "Lemonade"
drink_desc = "Oh the nostalgia..."
- taste_message = "lemonade"
+ taste_description = "lemonade"
/datum/reagent/consumable/drink/cold/kiraspecial
name = "Kira Special"
@@ -140,7 +139,7 @@
drink_icon = "kiraspecial"
drink_name = "Kira Special"
drink_desc = "Long live the guy who everyone had mistaken for a girl. Baka!"
- taste_message = "citrus soda"
+ taste_description = "citrus soda"
/datum/reagent/consumable/drink/cold/brownstar
name = "Brown Star"
@@ -151,7 +150,7 @@
drink_icon = "brownstar"
drink_name = "Brown Star"
drink_desc = "Its not what it sounds like..."
- taste_message = "orange soda"
+ taste_description = "orange soda"
/datum/reagent/consumable/drink/cold/milkshake
name = "Milkshake"
@@ -162,7 +161,7 @@
drink_icon = "milkshake"
drink_name = "Milkshake"
drink_desc = "Glorious brainfreezing mixture."
- taste_message = "milkshake"
+ taste_description = "milkshake"
/datum/reagent/consumable/drink/cold/rewriter
name = "Rewriter"
@@ -172,7 +171,7 @@
drink_icon = "rewriter"
drink_name = "Rewriter"
drink_desc = "The secret of the sanctuary of the Librarian..."
- taste_message = "coffee...soda?"
+ taste_description = "coffee...soda?"
/datum/reagent/consumable/drink/cold/rewriter/on_mob_life(mob/living/M)
M.Jitter(5)
diff --git a/code/modules/reagents/chemistry/reagents/drinks.dm b/code/modules/reagents/chemistry/reagents/drinks.dm
index 850df4f2382..6298e79d71d 100644
--- a/code/modules/reagents/chemistry/reagents/drinks.dm
+++ b/code/modules/reagents/chemistry/reagents/drinks.dm
@@ -6,7 +6,7 @@
drink_icon = "glass_orange"
drink_name = "Glass of Orange juice"
drink_desc = "Vitamins! Yay!"
- taste_message = "orange juice"
+ taste_description = "orange juice"
/datum/reagent/consumable/drink/orangejuice/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -22,7 +22,7 @@
drink_icon = "glass_red"
drink_name = "Glass of Tomato juice"
drink_desc = "Are you sure this is tomato juice?"
- taste_message = "tomato juice"
+ taste_description = "tomato juice"
/datum/reagent/consumable/drink/pineapplejuice
name = "Pineapple Juice"
@@ -32,7 +32,7 @@
drink_icon = "glass_orange"
drink_name = "Glass of pineapple juice"
drink_desc = "A bright drink, sweet and sugary."
- taste_message = "pineapple juice"
+ taste_description = "pineapple juice"
/datum/reagent/consumable/drink/tomatojuice/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -48,7 +48,7 @@
drink_icon = "glass_green"
drink_name = "Glass of Lime juice"
drink_desc = "A glass of sweet-sour lime juice."
- taste_message = "lime juice"
+ taste_description = "lime juice"
/datum/reagent/consumable/drink/limejuice/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -64,7 +64,7 @@
drink_icon = "carrotjuice"
drink_name = "Glass of carrot juice"
drink_desc = "It is just like a carrot but without crunching."
- taste_message = "carrot juice"
+ taste_description = "carrot juice"
/datum/reagent/consumable/drink/carrotjuice/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -87,7 +87,7 @@
drink_icon = "doctorsdelightglass"
drink_name = "Doctor's Delight"
drink_desc = "A healthy mixture of juices, guaranteed to keep you healthy until the next toolboxing takes place."
- taste_message = "healthy dietary choices"
+ taste_description = "healthy dietary choices"
/datum/reagent/consumable/drink/doctor_delight/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -104,7 +104,7 @@
drink_icon = "triplecitrus"
drink_name = "Glass of Triplecitrus Juice"
drink_desc = "As colorful and healthy as it is delicious."
- taste_message = "citrus juice"
+ taste_description = "citrus juice"
/datum/reagent/consumable/drink/triple_citrus/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == INGEST)
@@ -118,7 +118,7 @@
drink_icon = "berryjuice"
drink_name = "Glass of berry juice"
drink_desc = "Berry juice. Or maybe its jam. Who cares?"
- taste_message = "berry juice"
+ taste_description = "berry juice"
/datum/reagent/consumable/drink/poisonberryjuice
name = "Poison Berry Juice"
@@ -128,7 +128,7 @@
drink_icon = "poisonberryjuice"
drink_name = "Glass of poison berry juice"
drink_desc = "A glass of deadly juice."
- taste_message = "berry juice"
+ taste_description = "berry juice"
/datum/reagent/consumable/drink/poisonberryjuice/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -140,14 +140,14 @@
id = "applejuice"
description = "The sweet juice of an apple, fit for all ages."
color = "#ECFF56" // rgb: 236, 255, 86
- taste_message = "apple juice"
+ taste_description = "apple juice"
/datum/reagent/consumable/drink/watermelonjuice
name = "Watermelon Juice"
id = "watermelonjuice"
description = "Delicious juice made from watermelon."
color = "#863333" // rgb: 134, 51, 51
- taste_message = "watermelon juice"
+ taste_description = "watermelon juice"
/datum/reagent/consumable/drink/lemonjuice
name = "Lemon Juice"
@@ -157,14 +157,14 @@
drink_icon = "lemonglass"
drink_name = "Glass of lemonjuice"
drink_desc = "Sour..."
- taste_message = "lemon juice"
+ taste_description = "lemon juice"
/datum/reagent/consumable/drink/grapejuice
name = "Grape Juice"
id = "grapejuice"
description = "This juice is known to stain shirts."
color = "#993399" // rgb: 153, 51, 153
- taste_message = "grape juice"
+ taste_description = "grape juice"
/datum/reagent/consumable/drink/banana
name = "Banana Juice"
@@ -174,7 +174,7 @@
drink_icon = "banana"
drink_name = "Glass of banana juice"
drink_desc = "The raw essence of a banana. HONK"
- taste_message = "banana juice"
+ taste_description = "banana juice"
/datum/reagent/consumable/drink/banana/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -190,7 +190,7 @@
drink_icon = "nothing"
drink_name = "Nothing"
drink_desc = "Absolutely nothing."
- taste_message = "nothing... how?"
+ taste_description = "nothing... how?"
/datum/reagent/consumable/drink/nothing/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -208,7 +208,7 @@
drink_icon = "glass_brown"
drink_name = "Glass of potato juice"
drink_desc = "Who in the hell requests this? Gross!"
- taste_message = "puke, you're pretty sure"
+ taste_description = "puke, you're pretty sure"
/datum/reagent/consumable/drink/milk
name = "Milk"
@@ -218,7 +218,7 @@
drink_icon = "glass_white"
drink_name = "Glass of milk"
drink_desc = "White and nutritious goodness!"
- taste_message = "milk"
+ taste_description = "milk"
/datum/reagent/consumable/drink/milk/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -235,7 +235,7 @@
color = "#DFDFC7" // rgb: 223, 223, 199
drink_name = "Glass of soy milk"
drink_desc = "White and nutritious soy goodness!"
- taste_message = "fake milk"
+ taste_description = "fake milk"
/datum/reagent/consumable/drink/milk/cream
name = "Cream"
@@ -244,14 +244,14 @@
color = "#DFD7AF" // rgb: 223, 215, 175
drink_name = "Glass of cream"
drink_desc = "Ewwww..."
- taste_message = "cream"
+ taste_description = "cream"
/datum/reagent/consumable/drink/milk/chocolate_milk
name = "Chocolate milk"
id ="chocolate_milk"
description = "Chocolate-flavored milk, tastes like being a kid again."
color = "#85432C"
- taste_message = "chocolate milk"
+ taste_description = "chocolate milk"
/datum/reagent/consumable/drink/hot_coco
name = "Hot Chocolate"
@@ -263,7 +263,7 @@
drink_icon = "hot_coco"
drink_name = "Glass of hot coco"
drink_desc = "Delicious and cozy"
- taste_message = "chocolate"
+ taste_description = "chocolate"
/datum/reagent/consumable/drink/coffee
name = "Coffee"
@@ -281,7 +281,7 @@
drink_icon = "glass_brown"
drink_name = "Glass of coffee"
drink_desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere."
- taste_message = "coffee"
+ taste_description = "coffee"
/datum/reagent/consumable/drink/coffee/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -308,7 +308,7 @@
drink_icon = "icedcoffeeglass"
drink_name = "Iced Coffee"
drink_desc = "A drink to perk you up and refresh you!"
- taste_message = "refreshingly cold coffee"
+ taste_description = "refreshingly cold coffee"
/datum/reagent/consumable/drink/coffee/soy_latte
name = "Soy Latte"
@@ -320,7 +320,7 @@
drink_icon = "soy_latte"
drink_name = "Soy Latte"
drink_desc = "A nice and refrshing beverage while you are reading."
- taste_message = "fake milky coffee"
+ taste_description = "fake milky coffee"
/datum/reagent/consumable/drink/coffee/soy_latte/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -339,7 +339,7 @@
drink_icon = "cafe_latte"
drink_name = "Cafe Latte"
drink_desc = "A nice, strong and refreshing beverage while you are reading."
- taste_message = "milky coffee"
+ taste_description = "milky coffee"
/datum/reagent/consumable/drink/coffee/cafe_latte/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -355,7 +355,7 @@
color = "#673629"
drink_name = "Cafe Mocha"
drink_desc = "The perfect blend of coffe, milk, and chocolate."
- taste_message = "chocolatey coffee"
+ taste_description = "chocolatey coffee"
/datum/reagent/consumable/drink/tea
name = "Tea"
@@ -370,7 +370,7 @@
drink_icon = "glass_brown"
drink_name = "Glass of Tea"
drink_desc = "A glass of hot tea. Perhaps a cup with a handle would have been smarter?"
- taste_message = "tea"
+ taste_description = "tea"
/datum/reagent/consumable/drink/tea/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -388,7 +388,7 @@
drink_icon = "icetea"
drink_name = "Iced Tea"
drink_desc = "No relation to a certain rap artist/ actor."
- taste_message = "cold tea"
+ taste_description = "cold tea"
/datum/reagent/consumable/drink/bananahonk
name = "Banana Honk"
@@ -398,7 +398,7 @@
drink_icon = "bananahonkglass"
drink_name = "Banana Honk"
drink_desc = "A drink from Banana Heaven."
- taste_message = "HONK"
+ taste_description = "HONK"
/datum/reagent/consumable/drink/bananahonk/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -415,7 +415,7 @@
drink_icon = "silencerglass"
drink_name = "Silencer"
drink_desc = "A drink from mime Heaven."
- taste_message = "mphhhh"
+ taste_description = "mphhhh"
/datum/reagent/consumable/drink/silencer/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -433,7 +433,7 @@
drink_icon = "chocolatepudding"
drink_name = "Chocolate Pudding"
drink_desc = "Tasty"
- taste_message = "chocolate"
+ taste_description = "chocolate"
/datum/reagent/consumable/drink/vanillapudding
name = "Vanilla Pudding"
@@ -444,7 +444,7 @@
drink_icon = "vanillapudding"
drink_name = "Vanilla Pudding"
drink_desc = "Tasty."
- taste_message = "vanilla"
+ taste_description = "vanilla"
/datum/reagent/consumable/drink/cherryshake
name = "Cherry Shake"
@@ -455,7 +455,7 @@
drink_icon = "cherryshake"
drink_name = "Cherry Shake"
drink_desc = "A cherry flavored milkshake."
- taste_message = "cherry milkshake"
+ taste_description = "cherry milkshake"
/datum/reagent/consumable/drink/bluecherryshake
name = "Blue Cherry Shake"
@@ -466,7 +466,7 @@
drink_icon = "bluecherryshake"
drink_name = "Blue Cherry Shake"
drink_desc = "An exotic blue milkshake."
- taste_message = "blues"
+ taste_description = "blues"
/datum/reagent/consumable/drink/pumpkin_latte
name = "Pumpkin Latte"
@@ -477,7 +477,7 @@
drink_icon = "pumpkin_latte"
drink_name = "Pumpkin Latte"
drink_desc = "A mix of coffee and pumpkin juice."
- taste_message = "overpriced hipster spices"
+ taste_description = "overpriced hipster spices"
/datum/reagent/consumable/drink/gibbfloats
name = "Gibb Floats"
@@ -488,25 +488,25 @@
drink_icon= "gibbfloats"
drink_name = "Gibbfloat"
drink_desc = "Dr. Gibb with ice cream on top."
- taste_message = "taste revolution"
+ taste_description = "taste revolution"
/datum/reagent/consumable/drink/pumpkinjuice
name = "Pumpkin Juice"
id = "pumpkinjuice"
description = "Juiced from real pumpkin."
color = "#FFA500"
- taste_message = "autumn"
+ taste_description = "autumn"
/datum/reagent/consumable/drink/blumpkinjuice
name = "Blumpkin Juice"
id = "blumpkinjuice"
description = "Juiced from real blumpkin."
color = "#00BFFF"
- taste_message = "caustic puke"
+ taste_description = "caustic puke"
/datum/reagent/consumable/drink/grape_soda
name = "Grape soda"
id = "grapesoda"
description = "Beloved of children and teetotalers."
color = "#E6CDFF"
- taste_message = "grape soda"
+ taste_description = "grape soda"
diff --git a/code/modules/reagents/chemistry/reagents/drugs.dm b/code/modules/reagents/chemistry/reagents/drugs.dm
index 9e96ed5b56b..a2736cec719 100644
--- a/code/modules/reagents/chemistry/reagents/drugs.dm
+++ b/code/modules/reagents/chemistry/reagents/drugs.dm
@@ -19,7 +19,7 @@
description = "A chemical element."
reagent_state = SOLID
color = "#808080" // rgb: 128, 128, 128
- taste_message = "metal"
+ taste_description = "metal"
/datum/reagent/lithium/on_mob_life(mob/living/M)
if(isturf(M.loc) && !istype(M.loc, /turf/space))
@@ -35,7 +35,7 @@
description = "A highly potent hallucinogenic substance. Far out, maaaan."
reagent_state = LIQUID
color = "#0000D8"
- taste_message = "a magical journey"
+ taste_description = "a magical journey"
/datum/reagent/lsd/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -52,7 +52,7 @@
metabolization_rate = 0.2
addiction_chance = 65
heart_rate_decrease = 1
- taste_message = "a synthetic high"
+ taste_description = "a synthetic high"
/datum/reagent/space_drugs/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -69,7 +69,7 @@
id = "psilocybin"
description = "A strong psycotropic derived from certain species of mushroom."
color = "#E700E7" // rgb: 231, 0, 231
- taste_message = "visions"
+ taste_description = "visions"
/datum/reagent/psilocybin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -105,7 +105,7 @@
overdose_threshold = 35
addiction_chance = 70
heart_rate_increase = 1
- taste_message = "calm"
+ taste_description = "calm"
/datum/reagent/nicotine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -242,7 +242,7 @@
color = "#0264B4"
overdose_threshold = 20
addiction_chance = 50
- taste_message = "very poor life choices"
+ taste_description = "very poor life choices"
/datum/reagent/krokodil/on_mob_life(mob/living/M)
@@ -316,7 +316,7 @@
addiction_chance = 60
metabolization_rate = 0.6
heart_rate_increase = 1
- taste_message = "speed"
+ taste_description = "speed"
/datum/reagent/methamphetamine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -376,7 +376,7 @@
overdose_threshold = 20
addiction_chance = 80
metabolization_rate = 0.6
- taste_message = "WAAAAGH"
+ taste_description = "WAAAAGH"
/datum/reagent/bath_salts/on_mob_life(mob/living/M)
var/check = rand(0,100)
@@ -475,7 +475,7 @@
reagent_state = LIQUID
color = "#644600"
addiction_chance = 30
- taste_message = "puke... or worse"
+ taste_description = "puke... or worse"
/datum/reagent/jenkem/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -539,7 +539,7 @@
overdose_threshold = 15
process_flags = ORGANIC | SYNTHETIC //Flipping for everyone!
addiction_chance = 10
- taste_message = "flips"
+ taste_description = "flips"
/datum/reagent/fliptonium/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -611,7 +611,7 @@
reagent_state = LIQUID
color = "#AC88CA" //RGB: 172, 136, 202
metabolization_rate = 0.6 * REAGENTS_METABOLISM
- taste_message = "spinning"
+ taste_description = "spinning"
/datum/reagent/rotatium/on_mob_life(mob/living/carbon/M)
if(M.hud_used)
@@ -645,7 +645,7 @@
overdose_threshold = 20
addiction_chance = 60
metabolization_rate = 0.6
- taste_message = "wiper fluid"
+ taste_description = "wiper fluid"
/datum/reagent/lube/ultra/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -697,7 +697,7 @@
process_flags = SYNTHETIC
overdose_threshold = 20
addiction_chance = 50
- taste_message = "silicone"
+ taste_description = "silicone"
/datum/reagent/surge/on_mob_life(mob/living/M)
diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm
index 6f0c53730b4..2479a82decf 100644
--- a/code/modules/reagents/chemistry/reagents/food.dm
+++ b/code/modules/reagents/chemistry/reagents/food.dm
@@ -5,6 +5,8 @@
/datum/reagent/consumable
name = "Consumable"
id = "consumable"
+ taste_description = "generic food"
+ taste_mult = 4
var/nutriment_factor = 1 * REAGENTS_METABOLISM
var/diet_flags = DIET_OMNI | DIET_HERB | DIET_CARN
@@ -23,7 +25,6 @@
reagent_state = SOLID
nutriment_factor = 15 * REAGENTS_METABOLISM
color = "#664330" // rgb: 102, 67, 48
- taste_message = null
/datum/reagent/consumable/nutriment/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -38,19 +39,41 @@
H.blood_volume += 0.4
return ..() | update_flags
+/datum/reagent/consumable/nutriment/on_new(list/supplied_data)
+ // taste data can sometimes be ("salt" = 3, "chips" = 1)
+ // and we want it to be in the form ("salt" = 0.75, "chips" = 0.25)
+ // which is called "normalizing"
+ if(!supplied_data)
+ supplied_data = data
+ // if data isn't an associative list, this has some WEIRD side effects
+ // TODO probably check for assoc list?
+ data = counterlist_normalise(supplied_data)
+
+/datum/reagent/consumable/nutriment/on_merge(list/newdata, newvolume)
+ if(!islist(newdata) || !newdata.len)
+ return
+ var/list/taste_amounts = list()
+ var/list/other_taste_amounts = newdata.Copy()
+ if(data)
+ taste_amounts = data.Copy()
+ counterlist_scale(taste_amounts, volume)
+ counterlist_combine(taste_amounts, other_taste_amounts)
+ counterlist_normalise(taste_amounts)
+ data = taste_amounts
+
/datum/reagent/consumable/nutriment/protein // Meat-based protein, digestable by carnivores and omnivores, worthless to herbivores
name = "Protein"
id = "protein"
description = "Various essential proteins and fats commonly found in animal flesh and blood."
diet_flags = DIET_CARN | DIET_OMNI
- taste_message = "meat"
+ taste_description = "meat" //TODO: Remove
/datum/reagent/consumable/nutriment/plantmatter // Plant-based biomatter, digestable by herbivores and omnivores, worthless to carnivores
name = "Plant-matter"
id = "plantmatter"
description = "Vitamin-rich fibers and natural sugars commonly found in fresh produce."
diet_flags = DIET_HERB | DIET_OMNI
- taste_message = "vegetables"
+ taste_description = "vegetables" //TODO: Remove
/datum/reagent/consumable/vitamin
name = "Vitamin"
@@ -58,7 +81,7 @@
description = "All the best vitamins, minerals, and carbohydrates the body needs in pure form."
reagent_state = SOLID
color = "#664330" // rgb: 102, 67, 48
- taste_message = "nutrition"
+ taste_description = "nutrition"
/datum/reagent/consumable/vitamin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -82,7 +105,8 @@
color = "#FFFFFF" // rgb: 255, 255, 255
nutriment_factor = 5 * REAGENTS_METABOLISM
overdose_threshold = 200 // Hyperglycaemic shock
- taste_message = "sweetness"
+ taste_description = "sweetness"
+ taste_mult = 1.5
/datum/reagent/consumable/sugar/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -117,7 +141,7 @@
reagent_state = LIQUID
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#792300" // rgb: 121, 35, 0
- taste_message = "soy"
+ taste_description = "soy"
/datum/reagent/consumable/ketchup
name = "Ketchup"
@@ -126,7 +150,7 @@
reagent_state = LIQUID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#731008" // rgb: 115, 16, 8
- taste_message = "ketchup"
+ taste_description = "ketchup"
/datum/reagent/consumable/capsaicin
name = "Capsaicin Oil"
@@ -134,7 +158,8 @@
description = "This is what makes chilis hot."
reagent_state = LIQUID
color = "#B31008" // rgb: 179, 16, 8
- taste_message = "HOTNESS"
+ taste_description = "HOTNESS"
+ taste_mult = 1.5
/datum/reagent/consumable/capsaicin/on_mob_life(mob/living/M)
switch(current_cycle)
@@ -164,7 +189,7 @@
description = "This shit goes in pepperspray."
reagent_state = LIQUID
color = "#B31008" // rgb: 179, 16, 8
- taste_message = "PURE FIRE"
+ taste_description = "PURE FIRE"
/datum/reagent/consumable/condensedcapsaicin/on_mob_life(mob/living/M)
if(prob(5))
@@ -233,7 +258,7 @@
reagent_state = LIQUID
color = "#8BA6E9" // rgb: 139, 166, 233
process_flags = ORGANIC | SYNTHETIC
- taste_message = "cold"
+ taste_description = "cold
"
/datum/reagent/consumable/frostoil/on_mob_life(mob/living/M)
switch(current_cycle)
@@ -273,8 +298,8 @@
reagent_state = SOLID
color = "#B1B0B0"
overdose_threshold = 100
- taste_strength = 2
- taste_message = "salt"
+ taste_mult = 2
+ taste_description = "salt"
/datum/reagent/consumable/sodiumchloride/overdose_process(mob/living/M, severity)
var/update_flags = STATUS_UPDATE_NONE
@@ -287,7 +312,7 @@
id = "blackpepper"
description = "A powder ground from peppercorns. *AAAACHOOO*"
reagent_state = SOLID
- taste_message = "pepper"
+ taste_description = "pepper"
/datum/reagent/consumable/cocoa
name = "Cocoa Powder"
@@ -296,7 +321,7 @@
reagent_state = SOLID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
- taste_message = "bitter cocoa"
+ taste_description = "bitter cocoa"
/datum/reagent/consumable/vanilla
name = "Vanilla Powder"
@@ -305,7 +330,7 @@
reagent_state = SOLID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#FFFACD"
- taste_message = "bitter vanilla"
+ taste_description = "bitter vanilla"
/datum/reagent/consumable/hot_coco
name = "Hot Chocolate"
@@ -314,7 +339,7 @@
reagent_state = LIQUID
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#403010" // rgb: 64, 48, 16
- taste_message = "chocolate"
+ taste_description = "chocolate"
/datum/reagent/consumable/hot_coco/on_mob_life(mob/living/M)
if(M.bodytemperature < 310)//310 is the normal bodytemp. 310.055
@@ -326,7 +351,7 @@
id = "sprinkles"
description = "Multi-colored little bits of sugar, commonly found on donuts. Loved by cops."
color = "#FF00FF" // rgb: 255, 0, 255
- taste_message = "crunchy sweetness"
+ taste_description = "crunchy sweetness"
/datum/reagent/consumable/sprinkles/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -342,7 +367,7 @@
reagent_state = LIQUID
nutriment_factor = 20 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
- taste_message = "oil"
+ taste_description = "oil"
/datum/reagent/consumable/cornoil/reaction_turf(turf/simulated/T, volume)
if(!istype(T))
@@ -363,7 +388,7 @@
description = "Heated beyond usefulness, this enzyme is now worthless."
reagent_state = LIQUID
color = "#282314" // rgb: 54, 94, 48
- taste_message = null
+ taste_description = "sweetness"
/datum/reagent/consumable/dry_ramen
name = "Dry Ramen"
@@ -371,7 +396,7 @@
description = "Space age food, since August 25, 1958. Contains dried noodles, vegetables, and chemicals that boil in contact with water."
reagent_state = SOLID
color = "#302000" // rgb: 48, 32, 0
- taste_message = "dry ramen coated with what might just be your tears"
+ taste_description = "dry ramen coated with what might just be your tears"
/datum/reagent/consumable/hot_ramen
name = "Hot Ramen"
@@ -380,7 +405,7 @@
reagent_state = LIQUID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
- taste_message = "cheap ramen and memories"
+ taste_description = "cheap ramen and memories"
/datum/reagent/consumable/hot_ramen/on_mob_life(mob/living/M)
if(M.bodytemperature < 310)//310 is the normal bodytemp. 310.055
@@ -394,7 +419,7 @@
reagent_state = LIQUID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
- taste_message = "SPICY ramen"
+ taste_description = "SPICY ramen"
/datum/reagent/consumable/hell_ramen/on_mob_life(mob/living/M)
M.bodytemperature += 10 * TEMPERATURE_DAMAGE_COEFFICIENT
@@ -406,7 +431,7 @@
description = "This is what you rub all over yourself to pretend to be a ghost."
reagent_state = SOLID
color = "#FFFFFF" // rgb: 0, 0, 0
- taste_message = "flour"
+ taste_description = "flour"
/datum/reagent/consumable/flour/reaction_turf(turf/T, volume)
if(!isspaceturf(T))
@@ -419,7 +444,7 @@
reagent_state = SOLID
nutriment_factor = 3 * REAGENTS_METABOLISM
color = "#FFFFFF" // rgb: 0, 0, 0
- taste_message = "rice"
+ taste_description = "rice"
/datum/reagent/consumable/cherryjelly
name = "Cherry Jelly"
@@ -427,7 +452,7 @@
description = "Totally the best. Only to be spread on foods with excellent lateral symmetry."
reagent_state = LIQUID
color = "#801E28" // rgb: 128, 30, 40
- taste_message = "cherry jelly"
+ taste_description = "cherry jelly"
/datum/reagent/consumable/bluecherryjelly
name = "Blue Cherry Jelly"
@@ -435,7 +460,7 @@
description = "Blue and tastier kind of cherry jelly."
reagent_state = LIQUID
color = "#00F0FF"
- taste_message = "the blues"
+ taste_description = "the blues"
/datum/reagent/consumable/egg
name = "Egg"
@@ -443,7 +468,7 @@
description = "A runny and viscous mixture of clear and yellow fluids."
reagent_state = LIQUID
color = "#F0C814"
- taste_message = "eggs"
+ taste_description = "eggs"
/datum/reagent/consumable/egg/on_mob_life(mob/living/M)
if(prob(3))
@@ -456,7 +481,7 @@
description = "The powdered starch of maize, derived from the kernel's endosperm. Used as a thickener for gravies and puddings."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "flour"
+ taste_description = "flour"
/datum/reagent/consumable/corn_syrup
name = "Corn Syrup"
@@ -464,7 +489,7 @@
description = "A sweet syrup derived from corn starch that has had its starches converted into maltose and other sugars."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "cheap sugar substitute"
+ taste_description = "cheap sugar substitute"
/datum/reagent/consumable/corn_syrup/on_mob_life(mob/living/M)
M.reagents.add_reagent("sugar", 1.2)
@@ -476,7 +501,7 @@
description = "An incredibly sweet syrup, created from corn syrup treated with enzymes to convert its sugars into fructose."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "diabetes"
+ taste_description = "diabetes"
/datum/reagent/consumable/vhfcs/on_mob_life(mob/living/M)
M.reagents.add_reagent("sugar", 2.4)
@@ -489,7 +514,7 @@
reagent_state = LIQUID
color = "#d3a308"
nutriment_factor = 15 * REAGENTS_METABOLISM
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/consumable/honey/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -504,7 +529,7 @@
id = "onionjuice"
description = "A strong tasting substance that can induce partial blindness."
color = "#c0c9a0"
- taste_message = "pungency"
+ taste_description = "pungency"
/datum/reagent/consumable/onion/reaction_mob(mob/living/M, method = TOUCH, volume)
if(method == TOUCH)
@@ -528,7 +553,7 @@
drink_icon = "chocolateglass"
drink_name = "Glass of chocolate"
drink_desc = "Tasty"
- taste_message = "chocolate"
+ taste_description = "chocolate"
/datum/reagent/consumable/chocolate/on_mob_life(mob/living/M)
M.reagents.add_reagent("sugar", 0.8)
@@ -544,7 +569,7 @@
description = "A rather bitter herb once thought to hold magical protective properties."
reagent_state = LIQUID
color = "#21170E"
- taste_message = "tea"
+ taste_description = "tea"
/datum/reagent/consumable/mugwort/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -564,7 +589,7 @@
color = "#AB5D5D"
metabolization_rate = 0.2
overdose_threshold = 133
- taste_message = "bacon"
+ taste_description = "bacon"
/datum/reagent/consumable/porktonium/overdose_process(mob/living/M, severity)
if(prob(15))
@@ -582,7 +607,7 @@
color = "#B4B400"
metabolization_rate = 0.2
nutriment_factor = 2
- taste_message = "broth"
+ taste_description = "broth"
/datum/reagent/consumable/cheese
name = "Cheese"
@@ -590,7 +615,7 @@
description = "Some cheese. Pour it out to make it solid."
reagent_state = SOLID
color = "#FFFF00"
- taste_message = "cheese"
+ taste_description = "cheese"
/datum/reagent/consumable/cheese/on_mob_life(mob/living/M)
if(prob(3))
@@ -608,7 +633,7 @@
reagent_state = LIQUID
color = "#B2B139"
overdose_threshold = 50
- taste_message = "cheese?"
+ taste_description = "cheese?"
/datum/reagent/consumable/fake_cheese/overdose_process(mob/living/M, severity)
var/update_flags = STATUS_UPDATE_NONE
@@ -624,7 +649,7 @@
reagent_state = SOLID
color = "#50FF00"
addiction_chance = 5
- taste_message = "cheeeeeese...?"
+ taste_description = "cheeeeeese...?"
/datum/reagent/consumable/weird_cheese/on_mob_life(mob/living/M)
if(prob(5))
@@ -641,7 +666,7 @@
description = "A dish made of mashed beans cooked with lard."
reagent_state = LIQUID
color = "#684435"
- taste_message = "burritos"
+ taste_description = "burritos"
/datum/reagent/consumable/bread
name = "Bread"
@@ -649,7 +674,7 @@
description = "Bread! Yep, bread."
reagent_state = SOLID
color = "#9C5013"
- taste_message = "bread"
+ taste_description = "bread"
/datum/reagent/consumable/soybeanoil
name = "Space-soybean oil"
@@ -657,7 +682,7 @@
description = "An oil derived from extra-terrestrial soybeans."
reagent_state = LIQUID
color = "#B1B0B0"
- taste_message = "oil"
+ taste_description = "oil"
/datum/reagent/consumable/soybeanoil/on_mob_life(mob/living/M)
if(prob(10))
@@ -674,7 +699,7 @@
color = "#B1B0B0"
metabolization_rate = 0.2
overdose_threshold = 75
- taste_message = "oil"
+ taste_description = "oil"
/datum/reagent/consumable/hydrogenated_soybeanoil/on_mob_life(mob/living/M)
if(prob(15))
@@ -707,7 +732,7 @@
description = "A paste comprised of highly-processed organic material. Uncomfortably similar to deviled ham spread."
reagent_state = LIQUID
color = "#EBD7D7"
- taste_message = "meat?"
+ taste_description = "meat?"
/datum/reagent/consumable/meatslurry/on_mob_life(mob/living/M)
if(prob(4))
@@ -725,7 +750,7 @@
description = "A starchy food paste made from boiled potatoes."
reagent_state = SOLID
color = "#D6D9C1"
- taste_message = "potatoes"
+ taste_description = "potatoes"
/datum/reagent/consumable/gravy
name = "Gravy"
@@ -733,7 +758,7 @@
description = "A savory sauce made from a simple meat-dripping roux and milk."
reagent_state = LIQUID
color = "#B4641B"
- taste_message = "gravy"
+ taste_description = "gravy"
/datum/reagent/consumable/beff
name = "Beff"
@@ -741,7 +766,7 @@
description = "An advanced blend of mechanically-recovered meat and textured synthesized protein product notable for its unusual crystalline grain when sliced."
reagent_state = SOLID
color = "#AC7E67"
- taste_message = "meat"
+ taste_description = "meat"
/datum/reagent/consumable/beff/on_mob_life(mob/living/M)
if(prob(5))
@@ -759,7 +784,7 @@
description = "An Italian-American variety of salami usually made from beef and pork"
reagent_state = SOLID
color = "#AC7E67"
- taste_message = "pepperoni"
+ taste_description = "pepperoni"
/datum/reagent/consumable/pepperoni/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == TOUCH)
@@ -791,7 +816,7 @@
description = "A gross and unidentifiable substance."
reagent_state = LIQUID
color = "#63DE63"
- taste_message = "burned food"
+ taste_description = "burned food"
/datum/reagent/questionmark/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == INGEST)
@@ -808,8 +833,8 @@
reagent_state = LIQUID
color = "#F5F5F5"
metabolization_rate = 0.2
- taste_message = "excellent cuisine"
- taste_strength = 4
+ taste_description = "excellent cuisine"
+ taste_mult = 4
/datum/reagent/msg/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -827,7 +852,7 @@
description = "Pure cholesterol. Probably not very good for you."
reagent_state = LIQUID
color = "#FFFAC8"
- taste_message = "heart attack"
+ taste_description = "heart attack"
/datum/reagent/cholesterol/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -851,7 +876,7 @@
description = "Scrapings of some unknown fungus found growing on the station walls."
reagent_state = LIQUID
color = "#C87D28"
- taste_message = "mold"
+ taste_description = "mold"
/datum/reagent/fungus/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == INGEST)
@@ -872,7 +897,7 @@
reagent_state = LIQUID
color = "#8EAE7B"
process_flags = ORGANIC | SYNTHETIC //Because apparently ghosts in the shell
- taste_message = "spooks"
+ taste_description = "spooks"
/datum/reagent/ectoplasm/on_mob_life(mob/living/M)
var/spooky_message = pick("You notice something moving out of the corner of your eye, but nothing is there...", "Your eyes twitch, you feel like something you can't see is here...", "You've got the heebie-jeebies.", "You feel uneasy.", "You shudder as if cold...", "You feel something gliding across your back...")
@@ -901,7 +926,7 @@
description = "Looks like someone lost their lunch. And then collected it. Yuck."
reagent_state = LIQUID
color = "#FFFF00"
- taste_message = "puke"
+ taste_description = "puke"
/datum/reagent/vomit/reaction_turf(turf/T, volume)
if(volume >= 5 && !isspaceturf(T))
@@ -913,7 +938,7 @@
description = "Whoa, that can't be natural. That's horrible."
reagent_state = LIQUID
color = "#78FF74"
- taste_message = "puke"
+ taste_description = "puke"
/datum/reagent/greenvomit/reaction_turf(turf/T, volume)
if(volume >= 5 && !isspaceturf(T))
@@ -926,7 +951,7 @@
id = "entpoly"
description = "An ichor, derived from a certain mushroom, makes for a bad time."
color = "#1d043d"
- taste_message = "mold"
+ taste_description = "mold"
/datum/reagent/consumable/entpoly/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -946,7 +971,7 @@
description = "A stimulating ichor which causes luminescent fungi to grow on the skin. "
color = "#b5a213"
var/light_activated = 0
- taste_message = "mold"
+ taste_description = "mold"
/datum/reagent/consumable/tinlux/on_mob_life(mob/living/M)
if(!light_activated)
@@ -963,7 +988,7 @@
description = "A bubbly paste that heals wounds of the skin."
color = "#d3a308"
nutriment_factor = 3 * REAGENTS_METABOLISM
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/consumable/vitfro/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm
index 59d15cf50bd..09ee8cb3948 100644
--- a/code/modules/reagents/chemistry/reagents/medicine.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine.dm
@@ -15,7 +15,7 @@
color = "#C805DC"
metabolization_rate = 0.3 // Lasts 1.5 minutes for 15 units
shock_reduction = 200
- taste_message = "numbness"
+ taste_description = "numbness"
/datum/reagent/medicine/sterilizine
name = "Sterilizine"
@@ -23,7 +23,7 @@
description = "Sterilizes wounds in preparation for surgery."
reagent_state = LIQUID
color = "#C8A5DC" // rgb: 200, 165, 220
- taste_message = "antiseptic"
+ taste_description = "antiseptic"
//makes you squeaky clean
/datum/reagent/medicine/sterilizine/reaction_mob(mob/living/M, method=TOUCH, volume)
@@ -43,7 +43,7 @@
reagent_state = LIQUID
color = "#FA46FA"
overdose_threshold = 40
- taste_message = "stimulant"
+ taste_description = "stimulant"
/datum/reagent/medicine/synaptizine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -86,7 +86,7 @@
description = "A specialized drug that stimulates the mitochondria of cells to encourage healing of internal organs."
reagent_state = LIQUID
color = "#C8A5DC" // rgb: 200, 165, 220
- taste_message = "nurturing"
+ taste_description = "nurturing"
/datum/reagent/medicine/mitocholide/on_mob_life(mob/living/M)
if(ishuman(M))
@@ -110,7 +110,7 @@
reagent_state = LIQUID
color = "#0000C8" // rgb: 200, 165, 220
heart_rate_decrease = 1
- taste_message = "a safe refuge"
+ taste_description = "a safe refuge"
/datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -134,7 +134,7 @@
reagent_state = SOLID
color = "#669900" // rgb: 102, 153, 0
overdose_threshold = 30
- taste_message = "reformation"
+ taste_description = "reformation"
/datum/reagent/medicine/rezadone/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -163,7 +163,7 @@
reagent_state = LIQUID
color = "#0AB478"
metabolization_rate = 0.2
- taste_message = "antibiotics"
+ taste_description = "antibiotics"
/datum/reagent/medicine/silver_sulfadiazine
name = "Silver Sulfadiazine"
@@ -172,7 +172,7 @@
reagent_state = LIQUID
color = "#F0C814"
metabolization_rate = 3
- taste_message = "burn cream"
+ taste_description = "burn cream"
/datum/reagent/medicine/silver_sulfadiazine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -198,7 +198,7 @@
reagent_state = LIQUID
color = "#C8A5DC"
metabolization_rate = 3
- taste_message = "wound cream"
+ taste_description = "wound cream"
/datum/reagent/medicine/styptic_powder/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -226,7 +226,7 @@
color = "#C8A5DC"
penetrates_skin = TRUE
metabolization_rate = 0.15
- taste_message = "salt"
+ taste_description = "salt"
/datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -246,7 +246,7 @@
description = "A resorbable microfibrillar collagen and protein mixture that can rapidly heal injuries when applied topically."
reagent_state = LIQUID
color = "#FFEBEB"
- taste_message = "blood"
+ taste_description = "blood"
/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, volume, show_message = 1)
if(iscarbon(M))
@@ -268,7 +268,7 @@
description = "Activated charcoal helps to absorb toxins."
reagent_state = LIQUID
color = "#000000"
- taste_message = "dust"
+ taste_description = "dust"
/datum/reagent/medicine/charcoal/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -288,7 +288,7 @@
metabolization_rate = 0.2
overdose_threshold = 30
addiction_chance = 5
- taste_message = "health"
+ taste_description = "health"
/datum/reagent/medicine/omnizine/godblood
name = "Godblood"
@@ -349,7 +349,7 @@
reagent_state = LIQUID
color = "#22AB35"
metabolization_rate = 0.8
- taste_message = "a painful cleansing"
+ taste_description = "a painful cleansing"
/datum/reagent/medicine/calomel/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -368,7 +368,7 @@
description = "Potassium Iodide is a medicinal drug used to counter the effects of radiation poisoning."
reagent_state = LIQUID
color = "#B4DCBE"
- taste_message = "cleansing"
+ taste_description = "cleansing"
/datum/reagent/medicine/potass_iodide/on_mob_life(mob/living/M)
if(prob(80))
@@ -381,7 +381,7 @@
description = "Pentetic Acid is an aggressive chelation agent. May cause tissue damage. Use with caution."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "a purge"
+ taste_description = "a purge"
/datum/reagent/medicine/pen_acid/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -405,7 +405,7 @@
metabolization_rate = 0.1
shock_reduction = 25
overdose_threshold = 25
- taste_message = "relief"
+ taste_description = "relief"
/datum/reagent/medicine/sal_acid/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -420,7 +420,7 @@
reagent_state = LIQUID
color = "#00FFFF"
metabolization_rate = 0.2
- taste_message = "safety"
+ taste_description = "safety"
/datum/reagent/medicine/salbutamol/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -436,7 +436,7 @@
color = "#C8A5DC"
metabolization_rate = 0.2
addiction_chance = 20
- taste_message = "oxygenation"
+ taste_description = "oxygenation"
/datum/reagent/medicine/perfluorodecalin/on_mob_life(mob/living/carbon/human/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -457,7 +457,7 @@
metabolization_rate = 0.3
overdose_threshold = 35
addiction_chance = 25
- taste_message = "stimulation"
+ taste_description = "stimulation"
/datum/reagent/medicine/ephedrine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -506,7 +506,7 @@
reagent_state = LIQUID
color = "#5BCBE1"
addiction_chance = 10
- taste_message = "antihistamine"
+ taste_description = "antihistamine"
/datum/reagent/medicine/diphenhydramine/on_mob_life(mob/living/M)
M.AdjustJitter(-20)
@@ -529,7 +529,7 @@
overdose_threshold = 20
addiction_chance = 50
shock_reduction = 50
- taste_message = "a delightful numbing"
+ taste_description = "a delightful numbing"
/datum/reagent/medicine/morphine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -551,7 +551,7 @@
description = "Oculine is a saline eye medication with mydriatic and antibiotic effects."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "clarity"
+ taste_description = "clarity"
/datum/reagent/medicine/oculine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -583,7 +583,7 @@
color = "#000000"
metabolization_rate = 0.2
overdose_threshold = 25
- taste_message = "a moment of respite"
+ taste_description = "a moment of respite"
/datum/reagent/medicine/atropine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -611,7 +611,7 @@
color = "#96B1AE"
metabolization_rate = 0.2
overdose_threshold = 20
- taste_message = "borrowed time"
+ taste_description = "borrowed time"
/datum/reagent/medicine/epinephrine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -667,7 +667,8 @@
reagent_state = LIQUID
color = "#A0E85E"
metabolization_rate = 0.2
- taste_message = "life"
+ taste_description = "life"
+ var/revive_type = SENTIENCE_ORGANIC //So you can't revive boss monsters or robots with it
/datum/reagent/medicine/strange_reagent/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -680,13 +681,14 @@
if(volume < 1)
// gotta pay to play
return ..()
- if(isanimal(M))
- if(method == TOUCH)
- var/mob/living/simple_animal/SM = M
- if(SM.stat == DEAD)
- SM.revive()
- SM.loot.Cut() //no abusing strange reagent for unlimited farming of resources
- SM.visible_message("[M] seems to rise from the dead!")
+ if(isanimal(M) && method == TOUCH)
+ var/mob/living/simple_animal/SM = M
+ if(SM.sentience_type != revive_type) // No reviving Ash Drakes for you
+ return
+ if(SM.stat == DEAD)
+ SM.revive()
+ SM.loot.Cut() //no abusing strange reagent for farming unlimited resources
+ SM.visible_message("[SM] seems to rise from the dead!")
if(iscarbon(M))
if(method == INGEST || (method == TOUCH && prob(25)))
@@ -726,7 +728,7 @@
id = "mannitol"
description = "Mannitol is a sugar alcohol that can help alleviate cranial swelling."
color = "#D1D1F1"
- taste_message = "neurogenisis"
+ taste_description = "neurogenisis"
/datum/reagent/medicine/mannitol/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -738,7 +740,7 @@
id = "mutadone"
description = "Mutadone is an experimental bromide that can cure genetic abnomalities."
color = "#5096C8"
- taste_message = "cleanliness"
+ taste_description = "cleanliness"
/datum/reagent/medicine/mutadone/on_mob_life(mob/living/carbon/human/M)
if(M.mind && M.mind.assigned_role == "Cluwne") // HUNKE
@@ -767,7 +769,7 @@
id = "antihol"
description = "A medicine which quickly eliminates alcohol in the body."
color = "#009CA8"
- taste_message = "sobriety"
+ taste_description = "sobriety"
/datum/reagent/medicine/antihol/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -854,7 +856,7 @@
description = "A hormone generated by the pancreas responsible for metabolizing carbohydrates and fat in the bloodstream."
reagent_state = LIQUID
color = "#C8A5DC"
- taste_message = "tiredness"
+ taste_description = "tiredness"
/datum/reagent/medicine/insulin/on_mob_life(mob/living/M)
M.reagents.remove_reagent("sugar", 5)
@@ -868,7 +870,7 @@
color = "#D782E6"
addiction_chance = 20
overdose_threshold = 50
- taste_message = "warmth and stability"
+ taste_description = "warmth and stability"
/datum/reagent/medicine/teporone/on_mob_life(mob/living/M)
if(M.bodytemperature > 310)
@@ -883,7 +885,7 @@
description = "Haloperidol is a powerful antipsychotic and sedative. Will help control psychiatric problems, but may cause brain damage."
reagent_state = LIQUID
color = "#FFDCFF"
- taste_message = "stability"
+ taste_description = "stability"
/datum/reagent/medicine/haloperidol/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -915,7 +917,7 @@
reagent_state = LIQUID
color = "#96DEDE"
metabolization_rate = 0.1
- taste_message = "sleepiness"
+ taste_description = "sleepiness"
/datum/reagent/medicine/ether/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -938,7 +940,7 @@
reagent_state = SOLID
color = "#555555"
can_synth = FALSE
- taste_message = "bodily perfection"
+ taste_description = "bodily perfection"
/datum/reagent/medicine/syndicate_nanites/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -958,7 +960,7 @@
color = "#DCDCDC"
overdose_threshold = 30
metabolization_rate = 0.1
- taste_message = "faint hope"
+ taste_description = "faint hope"
/datum/reagent/medicine/omnizine_diluted/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -988,7 +990,7 @@
reagent_state = LIQUID
color = "#CC7A00"
process_flags = SYNTHETIC
- taste_message = "overclocking"
+ taste_description = "overclocking"
/datum/reagent/medicine/degreaser/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1019,7 +1021,7 @@
reagent_state = LIQUID
color = "#D7B395"
process_flags = SYNTHETIC
- taste_message = "heavy metals"
+ taste_description = "heavy metals"
/datum/reagent/medicine/liquid_solder/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1036,7 +1038,7 @@
reagent_state = LIQUID
color = "#C8A5DC"
overdose_threshold = 30
- taste_message = "knitting wounds"
+ taste_description = "knitting wounds"
/datum/reagent/medicine/bicaridine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1055,7 +1057,7 @@
reagent_state = LIQUID
color = "#C8A5DC"
overdose_threshold = 30
- taste_message = "soothed burns"
+ taste_description = "soothed burns"
/datum/reagent/medicine/kelotane/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1074,7 +1076,7 @@
description = "Ichor from an extremely powerful plant. Great for restoring wounds, but it's a little heavy on the brain."
color = "#FFAF00"
overdose_threshold = 25
- taste_message = "a gift from nature"
+ taste_description = "a gift from nature"
/datum/reagent/medicine/earthsblood/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1100,7 +1102,7 @@
id = "corazone"
description = "A medication used to treat pain, fever, and inflammation, along with heart attacks."
color = "#F5F5F5"
- taste_message = "a brief respite"
+ taste_description = "a brief respite"
// This reagent's effects are handled in heart attack handling code
@@ -1111,7 +1113,7 @@
color = "#9b3401"
metabolization_rate = 0.5
can_synth = FALSE
- taste_message = "wholeness"
+ taste_description = "wholeness"
/datum/reagent/medicine/nanocalcium/on_mob_life(mob/living/carbon/human/M)
var/update_flags = STATUS_UPDATE_NONE
diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm
index 886105e6465..d34e6537cb8 100644
--- a/code/modules/reagents/chemistry/reagents/misc.dm
+++ b/code/modules/reagents/chemistry/reagents/misc.dm
@@ -38,7 +38,7 @@
description = "A colorless, odorless gas."
reagent_state = GAS
color = "#808080" // rgb: 128, 128, 128
- taste_message = null
+ taste_mult = 0
/datum/reagent/nitrogen
name = "Nitrogen"
@@ -46,7 +46,7 @@
description = "A colorless, odorless, tasteless gas."
reagent_state = GAS
color = "#808080" // rgb: 128, 128, 128
- taste_message = null
+ taste_mult = 0
/datum/reagent/hydrogen
name = "Hydrogen"
@@ -54,7 +54,7 @@
description = "A colorless, odorless, nonmetallic, tasteless, highly combustible diatomic gas."
reagent_state = GAS
color = "#808080" // rgb: 128, 128, 128
- taste_message = null
+ taste_mult = 0
/datum/reagent/potassium
name = "Potassium"
@@ -62,7 +62,7 @@
description = "A soft, low-melting solid that can easily be cut with a knife. Reacts violently with water."
reagent_state = SOLID
color = "#A0A0A0" // rgb: 160, 160, 160
- taste_message = "bad ideas"
+ taste_description = "bad ideas"
/datum/reagent/sulfur
name = "Sulfur"
@@ -70,7 +70,7 @@
description = "A chemical element."
reagent_state = SOLID
color = "#BF8C00" // rgb: 191, 140, 0
- taste_message = "impulsive decisions"
+ taste_description = "impulsive decisions"
/datum/reagent/sodium
name = "Sodium"
@@ -78,7 +78,7 @@
description = "A chemical element."
reagent_state = SOLID
color = "#808080" // rgb: 128, 128, 128
- taste_message = "horrible misjudgement"
+ taste_description = "horrible misjudgement"
/datum/reagent/phosphorus
name = "Phosphorus"
@@ -86,7 +86,7 @@
description = "A chemical element."
reagent_state = SOLID
color = "#832828" // rgb: 131, 40, 40
- taste_message = "misguided choices"
+ taste_description = "misguided choices"
/datum/reagent/carbon
name = "Carbon"
@@ -94,7 +94,7 @@
description = "A chemical element."
reagent_state = SOLID
color = "#1C1300" // rgb: 30, 20, 0
- taste_message = "like a pencil or something"
+ taste_description = "like a pencil or something"
/datum/reagent/carbon/reaction_turf(turf/T, volume)
if(!(locate(/obj/effect/decal/cleanable/dirt) in T) && !isspaceturf(T)) // Only add one dirt per turf. Was causing people to crash.
@@ -106,7 +106,7 @@
description = "Gold is a dense, soft, shiny metal and the most malleable and ductile metal known."
reagent_state = SOLID
color = "#F7C430" // rgb: 247, 196, 48
- taste_message = "bling"
+ taste_description = "bling"
/datum/reagent/silver
@@ -115,7 +115,7 @@
description = "A lustrous metallic element regarded as one of the precious metals."
reagent_state = SOLID
color = "#D0D0D0" // rgb: 208, 208, 208
- taste_message = "sub-par bling"
+ taste_description = "sub-par bling"
/datum/reagent/silver/reaction_mob(mob/living/M, method=TOUCH, volume)
if(M.has_bane(BANE_SILVER))
@@ -128,7 +128,7 @@
description = "A silvery white and ductile member of the boron group of chemical elements."
reagent_state = SOLID
color = "#A8A8A8" // rgb: 168, 168, 168
- taste_message = "metal"
+ taste_description = "metal"
/datum/reagent/silicon
@@ -137,7 +137,7 @@
description = "A tetravalent metalloid, silicon is less reactive than its chemical analog carbon."
reagent_state = SOLID
color = "#A8A8A8" // rgb: 168, 168, 168
- taste_message = "a CPU"
+ taste_description = "a CPU"
/datum/reagent/copper
@@ -145,7 +145,7 @@
id = "copper"
description = "A highly ductile metal."
color = "#6E3B08" // rgb: 110, 59, 8
- taste_message = "copper"
+ taste_description = "copper"
/datum/reagent/iron
@@ -154,7 +154,7 @@
description = "Pure iron is a metal."
reagent_state = SOLID
color = "#C8A5DC" // rgb: 200, 165, 220
- taste_message = "metal"
+ taste_description = "metal"
/datum/reagent/iron/on_mob_life(mob/living/M)
if(ishuman(M))
@@ -176,7 +176,7 @@
description = "A perfluoronated sulfonic acid that forms a foam when mixed with water."
reagent_state = LIQUID
color = "#9E6B38" // rgb: 158, 107, 56
- taste_message = "extreme discomfort"
+ taste_description = "extreme discomfort"
// metal foaming agent
// this is lithium hydride. Add other recipies (e.g. LiH + H2O -> LiOH + H2) eventually
@@ -186,7 +186,7 @@
description = "A caustic substance commonly used in fertilizer or household cleaners."
reagent_state = GAS
color = "#404030" // rgb: 64, 64, 48
- taste_message = "floor cleaner"
+ taste_description = "floor cleaner"
/datum/reagent/diethylamine
name = "Diethylamine"
@@ -194,7 +194,7 @@
description = "A secondary amine, useful as a plant nutrient and as building block for other compounds."
reagent_state = LIQUID
color = "#322D00"
- taste_message = null
+ taste_description = "iron"
/datum/reagent/oil
name = "Oil"
@@ -202,7 +202,7 @@
description = "A decent lubricant for machines. High in benzene, naptha and other hydrocarbons."
reagent_state = LIQUID
color = "#3C3C3C"
- taste_message = "motor oil"
+ taste_description = "motor oil"
process_flags = ORGANIC | SYNTHETIC
/datum/reagent/oil/reaction_temperature(exposed_temperature, exposed_volume)
@@ -227,7 +227,7 @@
description = "A purple gaseous element."
reagent_state = GAS
color = "#493062"
- taste_message = "chemtrail resistance"
+ taste_description = "chemtrail resistance"
/datum/reagent/carpet
name = "Carpet"
@@ -235,7 +235,7 @@
description = "A covering of thick fabric used on floors. This type looks particularly gross."
reagent_state = LIQUID
color = "#701345"
- taste_message = "a carpet...what?"
+ taste_description = "a carpet...what?"
/datum/reagent/carpet/reaction_turf(turf/simulated/T, volume)
if(istype(T, /turf/simulated/floor/plating) || istype(T, /turf/simulated/floor/plasteel))
@@ -249,7 +249,7 @@
description = "A red-brown liquid element."
reagent_state = LIQUID
color = "#4E3A3A"
- taste_message = null
+ taste_description = "chemicals"
/datum/reagent/phenol
name = "Phenol"
@@ -257,7 +257,7 @@
description = "Also known as carbolic acid, this is a useful building block in organic chemistry."
reagent_state = LIQUID
color = "#525050"
- taste_message = null
+ taste_description = "acid"
/datum/reagent/ash
name = "Ash"
@@ -265,7 +265,7 @@
description = "Ashes to ashes, dust to dust."
reagent_state = LIQUID
color = "#191919"
- taste_message = "ash"
+ taste_description = "ash"
/datum/reagent/acetone
name = "Acetone"
@@ -273,7 +273,7 @@
description = "Pure 100% nail polish remover, also works as an industrial solvent."
reagent_state = LIQUID
color = "#474747"
- taste_message = "nail polish remover"
+ taste_description = "nail polish remover"
/datum/reagent/acetone/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -286,7 +286,7 @@
description = "Volatile."
reagent_state = LIQUID
color = "#60A584" // rgb: 96, 165, 132
- taste_message = "one third of an explosion"
+ taste_description = "one third of an explosion"
/datum/reagent/colorful_reagent
name = "Colorful Reagent"
@@ -294,7 +294,7 @@
description = "It's pure liquid colors. That's a thing now."
reagent_state = LIQUID
color = "#FFFFFF"
- taste_message = "the rainbow"
+ taste_description = "the rainbow"
/datum/reagent/colorful_reagent/on_mob_life(mob/living/M)
if(ishuman(M))
@@ -320,7 +320,7 @@
description = "A rather tubular and gnarly way of coloring totally bodacious hair. Duuuudddeee."
reagent_state = LIQUID
color = "#960096"
- taste_message = "the 2559 Autumn release of the Le Jeune Homme catalogue for professional hairdressers"
+ taste_description = "the 2559 Autumn release of the Le Jeune Homme catalogue for professional hairdressers"
/datum/reagent/hair_dye/reaction_mob(mob/living/M, volume)
if(ishuman(M))
@@ -341,7 +341,7 @@
reagent_state = LIQUID
color = "#5DDA5D"
penetrates_skin = TRUE
- taste_message = "someone's beard"
+ taste_description = "someone's beard"
/datum/reagent/hairgrownium/reaction_mob(mob/living/M, volume)
if(ishuman(M))
@@ -360,7 +360,7 @@
reagent_state = LIQUID
color = "#5DD95D"
penetrates_skin = TRUE
- taste_message = "multiple beards"
+ taste_description = "multiple beards"
/datum/reagent/super_hairgrownium/reaction_mob(mob/living/M, volume)
if(ishuman(M))
@@ -393,7 +393,7 @@
description = "Hugs, in liquid form. Yes, the concept of a hug. As a liquid. This makes sense in the future."
reagent_state = LIQUID
color = "#FF97B9"
- taste_message = "hugs"
+ taste_description = "hugs"
/datum/reagent/love
name = "Pure love"
@@ -402,7 +402,7 @@
reagent_state = LIQUID
color = "#FF83A5"
process_flags = ORGANIC | SYNTHETIC // That's the power of love~
- taste_message = "love"
+ taste_description = "love"
/datum/reagent/love/on_mob_life(mob/living/M)
if(M.a_intent != INTENT_HELP)
@@ -436,7 +436,7 @@
id = "jestosterone"
description = "Jestosterone is an odd chemical compound that induces a variety of annoying side-effects in the average person. It also causes mild intoxication, and is toxic to mimes."
color = "#ff00ff" //Fuchsia, pity we can't do rainbow here
- taste_message = "a funny flavour"
+ taste_description = "a funny flavour"
/datum/reagent/jestosterone/on_new()
..()
@@ -504,7 +504,7 @@
id = "royal_bee_jelly"
description = "Royal Bee Jelly, if injected into a Queen Space Bee said bee will split into two bees."
color = "#00ff80"
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/royal_bee_jelly/on_mob_life(mob/living/M)
if(prob(2))
@@ -517,7 +517,7 @@
description = "A commercial chemical designed to help older men in the bedroom." //not really it just makes you a giant
color = "#ff0000"//strong red. rgb 255, 0, 0
var/current_size = 1
- taste_message = "enhancement"
+ taste_description = "enhancement"
/datum/reagent/growthserum/on_mob_life(mob/living/carbon/H)
var/newsize = current_size
@@ -549,7 +549,7 @@
description = "Finely ground Coffee beans, used to make coffee."
reagent_state = SOLID
color = "#5B2E0D" // rgb: 91, 46, 13
- taste_message = "waste"
+ taste_description = "waste"
/datum/reagent/toxin/teapowder
name = "Ground Tea Leaves"
@@ -557,7 +557,7 @@
description = "Finely shredded Tea leaves, used for making tea."
reagent_state = SOLID
color = "#7F8400" // rgb: 127, 132, 0"
- taste_message = "the future"
+ taste_description = "the future"
//////////////////////////////////Hydroponics stuff///////////////////////////////
@@ -567,7 +567,7 @@
description = "Some kind of nutriment. You can't really tell what it is. You should probably report it, along with how you obtained it."
color = "#000000" // RBG: 0, 0, 0
var/tox_prob = 0
- taste_message = "puke"
+ taste_description = "puke"
/datum/reagent/plantnutriment/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -581,7 +581,7 @@
description = "Cheap and extremely common type of plant nutriment."
color = "#376400" // RBG: 50, 100, 0
tox_prob = 10
- taste_message = "obscurity and toil"
+ taste_description = "obscurity and toil"
/datum/reagent/plantnutriment/left4zednutriment
name = "Left 4 Zed"
@@ -589,7 +589,7 @@
description = "Unstable nutriment that makes plants mutate more often than usual."
color = "#1A1E4D" // RBG: 26, 30, 77
tox_prob = 25
- taste_message = "evolution"
+ taste_description = "evolution"
/datum/reagent/plantnutriment/robustharvestnutriment
name = "Robust Harvest"
@@ -597,7 +597,7 @@
description = "Very potent nutriment that prevents plants from mutating."
color = "#9D9D00" // RBG: 157, 157, 0
tox_prob = 15
- taste_message = "bountifulness"
+ taste_description = "bountifulness"
///Alchemical Reagents
@@ -643,7 +643,7 @@
color = "#FFC080" // rgb: 255, 196, 128 Bright orange
metabolization_rate = 10 * REAGENTS_METABOLISM // very fast, so it can be applied rapidly. But this changes on an overdose
overdose_threshold = 11 //Slightly more than one un-nozzled spraybottle.
- taste_message = "sour oranges"
+ taste_description = "sour oranges"
/datum/reagent/spraytan/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(ishuman(M))
diff --git a/code/modules/reagents/chemistry/reagents/paint.dm b/code/modules/reagents/chemistry/reagents/paint.dm
index ca6da0d0a23..6c0b04339b0 100644
--- a/code/modules/reagents/chemistry/reagents/paint.dm
+++ b/code/modules/reagents/chemistry/reagents/paint.dm
@@ -4,7 +4,7 @@
description = "Floor paint is used to color floor tiles."
reagent_state = LIQUID
color = "#808080"
- taste_message = "paint"
+ taste_description = "paint"
/datum/reagent/paint/reaction_turf(turf/T, volume)
if(!isspaceturf(T))
@@ -55,7 +55,7 @@
description = "Paint remover is used to remove floor paint from floor tiles."
reagent_state = LIQUID
color = "#808080"
- taste_message = "alcohol"
+ taste_description = "alcohol"
/datum/reagent/paint_remover/reaction_turf(turf/T, volume)
if(!isspaceturf(T))
diff --git a/code/modules/reagents/chemistry/reagents/paradise_pop.dm b/code/modules/reagents/chemistry/reagents/paradise_pop.dm
index 2294088e54a..af59809da27 100644
--- a/code/modules/reagents/chemistry/reagents/paradise_pop.dm
+++ b/code/modules/reagents/chemistry/reagents/paradise_pop.dm
@@ -15,7 +15,7 @@
description = "Tastes just how you'd think Paradise would if you could bottle it."
reagent_state = LIQUID
color = "#cc0044"
- taste_message = "paradise"
+ taste_description = "paradise"
//Apple-pocalypse: Low chance to cause a goonchem vortex that pulls things within a very small radius (2 tiles?) towards the drinker
/datum/reagent/consumable/drink/apple_pocalypse
@@ -24,7 +24,7 @@
description = "If doomsday came in fruit form, it'd probably be apples."
reagent_state = LIQUID
color = "#44FF44"
- taste_message = "doomsday"
+ taste_description = "doomsday"
/datum/reagent/consumable/drink/apple_pocalypse/on_mob_life(mob/living/M)
if(prob(1))
@@ -40,7 +40,7 @@
description = "Reason for ban: Excessive Flavor."
reagent_state = LIQUID
color = "#FF44FF"
- taste_message = "a permaban"
+ taste_description = "a permaban"
/datum/reagent/consumable/drink/berry_banned/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -69,7 +69,7 @@
description = "Reason for ban: Excessive Flavor."
reagent_state = LIQUID
color = "#FF44FF"
- taste_message = "a permaban"
+ taste_description = "a permaban"
/datum/reagent/consumable/drink/berry_banned2/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -91,7 +91,7 @@
description = "Creamy, smooth flavor, just like the bald heads of the masses. Supposedly aged for 30 years."
reagent_state = LIQUID
color = "#4d2600"
- taste_message = "greytide"
+ taste_description = "greytide"
/datum/reagent/consumable/drink/blackeye_brew/on_mob_life(mob/living/M)
if(prob(25))
@@ -114,7 +114,7 @@
description = "Exploding with grape flavor and a favorite among ERT members system-wide."
reagent_state = LIQUID
color = "#9933ff"
- taste_message = "old people"
+ taste_description = "old people"
/datum/reagent/consumable/drink/grape_granade/on_mob_life(mob/living/M)
if(prob(1))
@@ -133,7 +133,7 @@
description = "Soft drinks have been detected on collision course with your tastebuds."
reagent_state = LIQUID
color = "#cc9900"
- taste_message = "flying space rocks"
+ taste_description = "flying space rocks"
/datum/reagent/consumable/drink/meteor_malt/on_mob_life(mob/living/M)
if(prob(25))
diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
index d611c3c8d86..bd4079d69c6 100644
--- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
+++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
@@ -84,7 +84,7 @@
drink_icon = "dr_gibb_glass"
drink_name = "Glass of welder fuel"
drink_desc = "Unless you are an industrial tool, this is probably not safe for consumption."
- taste_message = "mistakes"
+ taste_description = "mistakes"
process_flags = ORGANIC | SYNTHETIC
var/max_radius = 7
var/min_radius = 0
@@ -140,7 +140,8 @@
description = "The liquid phase of an unusual extraterrestrial compound."
reagent_state = LIQUID
color = "#7A2B94"
- taste_message = "corporate assets going to waste"
+ taste_description = "corporate assets going to waste"
+ taste_mult = 1.5
/datum/reagent/plasma/reaction_temperature(exposed_temperature, exposed_volume)
if(exposed_temperature >= T0C + 100)
@@ -171,7 +172,7 @@
reagent_state = SOLID
color = "#673910" // rgb: 103, 57, 16
process_flags = ORGANIC | SYNTHETIC
- taste_message = "rust"
+ taste_description = "rust"
/datum/reagent/thermite/reaction_mob(mob/living/M, method= TOUCH, volume)
if(method == TOUCH)
@@ -206,7 +207,7 @@
description = "Glycerol is a simple polyol compound. Glycerol is sweet-tasting and of low toxicity."
reagent_state = LIQUID
color = "#808080" // rgb: 128, 128, 128
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/stabilizing_agent
name = "Stabilizing Agent"
@@ -214,7 +215,7 @@
description = "A chemical that stabilises normally volatile compounds, preventing them from reacting immediately."
reagent_state = LIQUID
color = "#FFFF00"
- taste_message = "long-term stability"
+ taste_description = "long-term stability"
/datum/reagent/clf3
name = "Chlorine Trifluoride"
@@ -224,7 +225,7 @@
color = "#FF0000"
metabolization_rate = 4
process_flags = ORGANIC | SYNTHETIC
- taste_message = null
+ taste_mult = 0
/datum/reagent/clf3/on_mob_life(mob/living/M)
if(M.on_fire)
@@ -268,7 +269,7 @@
description = "Sucks everything into the detonation point."
reagent_state = LIQUID
color = "#800080"
- taste_message = "the end of the world"
+ taste_description = "the end of the world"
/datum/reagent/liquid_dark_matter/reaction_turf(turf/T, volume) //Oh gosh, why
if(prob(75))
@@ -287,7 +288,7 @@
color = "#000000"
metabolization_rate = 0.05
penetrates_skin = TRUE
- taste_message = "explosions"
+ taste_description = "explosions"
/datum/reagent/blackpowder/reaction_turf(turf/T, volume) //oh shit
if(volume >= 5 && !isspaceturf(T))
@@ -406,7 +407,8 @@
id = "plasma_dust"
description = "A fine dust of plasma. This chemical has unusual mutagenic properties for viruses and slimes alike."
color = "#500064" // rgb: 80, 0, 100
- taste_message = "corporate assets going to waste"
+ taste_description = "corporate assets going to waste"
+ taste_mult = 1.5
/datum/reagent/plasma_dust/reaction_temperature(exposed_temperature, exposed_volume)
if(exposed_temperature >= T0C + 100)
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index 8048c21a283..7a060a93996 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -4,6 +4,7 @@
description = "A Toxic chemical."
reagent_state = LIQUID
color = "#CF3600" // rgb: 207, 54, 0
+ taste_mult = 1.2
/datum/reagent/toxin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -28,7 +29,7 @@
description = "Useful for dealing with undesirable customers."
reagent_state = LIQUID
color = "#CF3600" // rgb: 207, 54, 0
- taste_message = "mint"
+ taste_description = "mint"
/datum/reagent/minttoxin/on_mob_life(mob/living/M)
if(FAT in M.mutations)
@@ -41,7 +42,8 @@
description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
reagent_state = LIQUID
color = "#801E28" // rgb: 128, 30, 40
- taste_message = "slimes"
+ taste_description = "slimes"
+ taste_mult = 1.3
/datum/reagent/slimejelly/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -59,7 +61,7 @@
reagent_state = LIQUID
color = "#13BC5E" // rgb: 19, 188, 94
can_synth = FALSE
- taste_message = "shadows"
+ taste_description = "shadows"
/datum/reagent/slimetoxin/on_mob_life(mob/living/M)
if(ishuman(M))
@@ -93,7 +95,8 @@
color = "#484848" // rgb: 72, 72, 72
metabolization_rate = 0.2
penetrates_skin = TRUE
- taste_message = "metal"
+ taste_description = "metal"
+ taste_mult = 0 // elemental mercury is tasteless
/datum/reagent/mercury/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -109,7 +112,7 @@
color = "#808080" // rgb: 128, 128, 128
penetrates_skin = TRUE
process_flags = ORGANIC | SYNTHETIC
- taste_message = "fire"
+ taste_description = "fire"
/datum/reagent/chlorine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -124,7 +127,7 @@
color = "#6A6054"
penetrates_skin = TRUE
process_flags = ORGANIC | SYNTHETIC
- taste_message = "spicy freshness"
+ taste_description = "spicy freshness"
/datum/reagent/fluorine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -156,6 +159,7 @@
reagent_state = LIQUID
color = "#04DF27"
metabolization_rate = 0.3
+ taste_mult = 0.9
/datum/reagent/mutagen/reaction_mob(mob/living/M, method=TOUCH, volume)
if(!..())
@@ -203,6 +207,25 @@
return ..()
+datum/reagent/romerol
+ name = "romerol"
+ // the REAL zombie powder
+ id = "romerol"
+ description = "Romerol is a highly experimental bioterror agent \
+ which causes dormant nodules to be etched into the grey matter of \
+ the subject. These nodules only become active upon death of the \
+ host, upon which, the secondary structures activate and take control \
+ of the host body."
+ color = "#123524" // RGB (18, 53, 36)
+ metabolization_rate = INFINITY
+ can_synth = FALSE
+ taste_description = "CAAAARL"
+
+/datum/reagent/romerol/reaction_mob(mob/living/carbon/human/H)
+ // Silently add the zombie infection organ to be activated upon death
+ new /obj/item/organ/internal/zombie_infection(H)
+ ..()
+
/datum/reagent/stable_mutagen/on_tick()
var/datum/reagent/blood/B = locate() in holder.reagent_list
if(B && islist(B.data) && !data)
@@ -215,7 +238,7 @@
description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
reagent_state = SOLID
color = "#B8B8C0" // rgb: 184, 184, 192
- taste_message = null
+ taste_mult = 0
/datum/reagent/uranium/on_mob_life(mob/living/M)
M.apply_effect(2, IRRADIATE, negate_armor = 1)
@@ -247,7 +270,7 @@
reagent_state = LIQUID
color = "#00FF32"
process_flags = ORGANIC | SYNTHETIC
- taste_message = "ACID"
+ taste_description = "ACID"
/datum/reagent/sacid/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -340,7 +363,7 @@
drink_icon ="beerglass"
drink_name = "Beer glass"
drink_desc = "A freezing pint of beer"
- taste_message = "beer"
+ taste_description = "beer"
/datum/reagent/beer2/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -361,7 +384,7 @@
metabolization_rate = 0.1
penetrates_skin = TRUE
can_synth = FALSE
- taste_message = null
+ taste_mult = 0
/datum/reagent/polonium/on_mob_life(mob/living/M)
M.apply_effect(8, IRRADIATE, negate_armor = 1)
@@ -375,7 +398,7 @@
color = "#E7C4C4"
metabolization_rate = 0.2
overdose_threshold = 40
- taste_message = null
+ taste_mult = 0
/datum/reagent/histamine/reaction_mob(mob/living/M, method=TOUCH, volume) //dumping histamine on someone is VERY mean.
if(iscarbon(M))
@@ -533,7 +556,7 @@
color = "#CF3600"
metabolization_rate = 0.1
penetrates_skin = TRUE
- taste_message = "almonds"
+ taste_description = "almonds"
/datum/reagent/cyanide/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -592,7 +615,7 @@
reagent_state = LIQUID
color = "#5050FF"
process_flags = ORGANIC | SYNTHETIC
- taste_message = "ACID"
+ taste_description = "ACID"
/datum/reagent/facid/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -648,7 +671,7 @@
reagent_state = LIQUID
color = "#7F10C0"
can_synth = FALSE
- taste_message = null
+ taste_mult = 0
/datum/reagent/initropidril/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -680,7 +703,7 @@
reagent_state = LIQUID
color = "#1E4664"
metabolization_rate = 0.2
- taste_message = null
+ taste_mult = 0
/datum/reagent/pancuronium/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -715,7 +738,7 @@
color = "#5F8BE1"
metabolization_rate = 0.7
can_synth = FALSE
- taste_message = null
+ taste_mult = 0
/datum/reagent/sodium_thiopental/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -745,7 +768,7 @@
metabolization_rate = 0.8
penetrates_skin = TRUE
can_synth = FALSE
- taste_message = null
+ taste_mult = 0
/datum/reagent/ketamine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -797,7 +820,7 @@
description = "A toxin produced by certain mushrooms. Very deadly."
reagent_state = LIQUID
color = "#D9D9D9"
- taste_message = null
+ taste_mult = 0
/datum/reagent/amanitin/on_mob_delete(mob/living/M)
M.adjustToxLoss(current_cycle*rand(2,4))
@@ -810,7 +833,7 @@
reagent_state = SOLID
color = "#D1DED1"
metabolization_rate = 0.2
- taste_message = "battery acid"
+ taste_description = "battery acid"
/datum/reagent/lipolicide/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -902,7 +925,7 @@
metabolization_rate = 0.1
penetrates_skin = TRUE
overdose_threshold = 25
- taste_message = null
+ taste_mult = 0
/datum/reagent/sarin/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -988,10 +1011,10 @@
C.adjustToxLoss(lethality)
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(IS_PLANT in H.dna.species.species_traits) //plantmen take a LOT of damage
- H.adjustToxLoss(50)
+ if(IS_PLANT in H.dna.species.species_traits) //plantmen take extra damage
+ H.adjustToxLoss(3)
..()
- else if(istype(M, /mob/living/simple_animal/diona)) //plantmen monkeys (diona) take EVEN MORE damage
+ else if(istype(M, /mob/living/simple_animal/diona)) //nymphs take EVEN MORE damage
var/mob/living/simple_animal/diona/D = M
D.adjustHealth(100)
..()
@@ -1038,7 +1061,7 @@
reagent_state = LIQUID
color = "#60A584"
heart_rate_stop = 1
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/capulettium/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1069,7 +1092,7 @@
reagent_state = LIQUID
color = "#60A584"
heart_rate_stop = 1
- taste_message = "sweetness"
+ taste_description = "sweetness"
/datum/reagent/capulettium_plus/on_mob_life(mob/living/M)
M.Silence(2)
@@ -1142,7 +1165,7 @@
reagent_state = SOLID
color = "#993333"
process_flags = ORGANIC | SYNTHETIC
- taste_message = "ANTS OH GOD"
+ taste_description = "ANTS OH GOD"
/datum/reagent/ants/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -1165,7 +1188,7 @@
metabolization_rate = 0.2
var/shock_timer = 0
process_flags = ORGANIC | SYNTHETIC
- taste_message = "electricity"
+ taste_description = "electricity"
/datum/reagent/teslium/on_mob_life(mob/living/M)
shock_timer++
@@ -1181,7 +1204,7 @@
description = "An advanced corruptive toxin produced by something terrible."
reagent_state = LIQUID
color = "#5EFF3B" //RGB: 94, 255, 59
- taste_message = "decay"
+ taste_description = "decay"
/datum/reagent/gluttonytoxin/reaction_mob(mob/living/L, method=TOUCH, reac_volume)
L.ForceContractDisease(new /datum/disease/transformation/morph())
diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm
index fc79d0b336b..64156a7cadd 100644
--- a/code/modules/reagents/chemistry/reagents/water.dm
+++ b/code/modules/reagents/chemistry/reagents/water.dm
@@ -13,22 +13,22 @@
description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen."
reagent_state = LIQUID
color = "#0064C8" // rgb: 0, 100, 200
+ taste_description = "water"
var/cooling_temperature = 2
process_flags = ORGANIC | SYNTHETIC
drink_icon = "glass_clear"
drink_name = "Glass of Water"
drink_desc = "The father of all refreshments."
- taste_message = null
var/water_temperature = 283.15 // As reagents don't have a temperature value, we'll just use 10 celsius.
/datum/reagent/water/reaction_mob(mob/living/M, method = TOUCH, volume)
M.water_act(volume, water_temperature, src, method)
/datum/reagent/water/reaction_turf(turf/simulated/T, volume)
- T.water_act(volume, water_temperature, src)
+ T.water_act(volume, water_temperature, src)
/datum/reagent/water/reaction_obj(obj/O, volume)
- O.water_act(volume, water_temperature, src)
+ O.water_act(volume, water_temperature, src)
/datum/reagent/lube
name = "Space Lube"
@@ -36,7 +36,7 @@
description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity."
reagent_state = LIQUID
color = "#1BB1AB"
- taste_message = "cherry"
+ taste_description = "cherry"
/datum/reagent/lube/reaction_turf(turf/simulated/T, volume)
if(volume >= 1 && istype(T))
@@ -49,7 +49,7 @@
description = "A compound used to clean things. Now with 50% more sodium hypochlorite!"
reagent_state = LIQUID
color = "#61C2C2"
- taste_message = "floor cleaner"
+ taste_description = "floor cleaner"
/datum/reagent/space_cleaner/reaction_obj(obj/O, volume)
if(is_cleanable(O))
@@ -123,7 +123,8 @@
drink_icon = "glass_red"
drink_name = "Glass of Tomato juice"
drink_desc = "Are you sure this is tomato juice?"
- taste_message = "blood"
+ taste_description = "blood"
+ taste_mult = 1.3
/datum/reagent/blood/reaction_mob(mob/living/M, method=TOUCH, volume)
if(data && data["viruses"])
@@ -205,7 +206,7 @@
name = "Vaccine"
id = "vaccine"
color = "#C81040" // rgb: 200, 16, 64
- taste_message = "antibodies"
+ taste_description = "antibodies"
/datum/reagent/vaccine/reaction_mob(mob/living/M, method=TOUCH, volume)
if(islist(data) && (method == INGEST))
@@ -225,7 +226,7 @@
description = "Smelly water from a fish tank. Gross!"
reagent_state = LIQUID
color = "#757547"
- taste_message = "puke"
+ taste_description = "puke"
/datum/reagent/fishwater/reaction_mob(mob/living/M, method=TOUCH, volume)
if(method == INGEST)
@@ -245,7 +246,7 @@
description = "Filthy water scoured from a nasty toilet bowl. Absolutely disgusting."
reagent_state = LIQUID
color = "#757547"
- taste_message = "puke"
+ taste_description = "puke"
/datum/reagent/fishwater/toiletwater/reaction_mob(mob/living/M, method=TOUCH, volume) //For shennanigans
return
@@ -260,7 +261,7 @@
drink_icon = "glass_clear"
drink_name = "Glass of Water"
drink_desc = "The father of all refreshments."
- taste_message = null
+ taste_description = "water"
/datum/reagent/holywater/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -361,7 +362,7 @@
description = "Something that shouldn't exist on this plane of existance."
process_flags = ORGANIC | SYNTHETIC //ethereal means everything processes it.
metabolization_rate = 1
- taste_message = "sulfur"
+ taste_description = "sulfur"
/datum/reagent/fuel/unholywater/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -390,7 +391,7 @@
process_flags = ORGANIC | SYNTHETIC //Admin-bus has no brakes! KILL THEM ALL.
metabolization_rate = 1
can_synth = FALSE
- taste_message = "admin abuse"
+ taste_description = "admin abuse"
/datum/reagent/hellwater/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
@@ -407,7 +408,7 @@
color = "#FF9966"
description = "You don't even want to think about what's in here."
reagent_state = LIQUID
- taste_message = "meat"
+ taste_description = "meat"
/datum/reagent/liquidgibs/reaction_turf(turf/T, volume) //yes i took it from synthflesh...
if(volume >= 5 && !isspaceturf(T))
@@ -420,7 +421,7 @@
description = "Also known as sodium hydroxide."
reagent_state = LIQUID
color = "#FFFFD6" // very very light yellow
- taste_message = "ACID"//don't drink lye, kids
+ taste_description = "ACID"//don't drink lye, kids
/datum/reagent/drying_agent
name = "Drying agent"
@@ -428,7 +429,7 @@
description = "Can be used to dry things."
reagent_state = LIQUID
color = "#A70FFF"
- taste_message = "dry mouth"
+ taste_description = "dry mouth"
/datum/reagent/drying_agent/reaction_turf(turf/simulated/T, volume)
if(istype(T) && T.wet)
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 829d8fd2226..f9077aafab5 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -35,6 +35,9 @@
var/datum/disease/F = new spawned_disease(0)
var/list/data = list("viruses" = list(F), "blood_color" = "#A10808")
reagents.add_reagent("blood", disease_amount, data)
+ add_initial_reagents()
+
+obj/item/reagent_containers/proc/add_initial_reagents()
if(list_reagents)
reagents.add_reagent_list(list_reagents)
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index 5845b0be15c..b9080bf3d12 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -12,6 +12,11 @@
container_type = OPENCONTAINER
volume = 30
+/obj/item/reagent_containers/glass/bottle/romerol
+ name = "romerol bottle"
+ desc = "A small bottle of Romerol. The REAL zombie powder."
+ list_reagents = list("romerol" = 30)
+
/obj/item/reagent_containers/glass/bottle/on_reagent_change()
update_icon()
diff --git a/code/modules/reagents/reagent_containers/iv_bag.dm b/code/modules/reagents/reagent_containers/iv_bag.dm
index 825aa69632b..cfe84d10f2e 100644
--- a/code/modules/reagents/reagent_containers/iv_bag.dm
+++ b/code/modules/reagents/reagent_containers/iv_bag.dm
@@ -9,7 +9,7 @@
righthand_file = 'icons/goonstation/mob/inhands/items_righthand.dmi'
icon_state = "ivbag"
volume = 200
- possible_transfer_amounts = list(1,5,10)
+ possible_transfer_amounts = list(1,5,10,15,20,25,30,50) // Everything above 10 is NOT usable on a person and is instead used for transfering to other containers
amount_per_transfer_from_this = 1
container_type = OPENCONTAINER
var/label_text
@@ -53,6 +53,11 @@
end_processing()
return
+ if(amount_per_transfer_from_this > 10) // Prevents people from switching to illegal transfer values while the IV is already in someone, i.e. anything over 10
+ visible_message("The IV bag's needle pops out of [injection_target]'s arm. The transfer amount is too high!")
+ end_processing()
+ return
+
if(get_dist(get_turf(src), get_turf(injection_target)) > 1)
to_chat(injection_target, "The [src]'s' needle is ripped out of you!")
injection_target.apply_damage(3, BRUTE, pick("r_arm", "l_arm"))
@@ -98,6 +103,9 @@
else // Inserting the needle
if(!L.can_inject(user, 1))
return
+ if(amount_per_transfer_from_this > 10) // We only want to be able to transfer 1, 5, or 10 units to people. Higher numbers are for transfering to other containers
+ to_chat(user, "The IV bag can only be used on someone with a transfer amount of 1, 5 or 10.")
+ return
if(L != user)
L.visible_message("[user] is trying to insert [src]'s needle into [L]'s arm!", \
"[user] is trying to insert [src]'s needle into [L]'s arm!")
@@ -107,6 +115,22 @@
"[user] inserts [src]'s needle into [L]'s arm!")
begin_processing(L)
+ else if(target.is_refillable() && is_drainable()) // Transferring from IV bag to other containers
+ if(!reagents.total_volume)
+ to_chat(user, "[src] is empty.")
+ return
+
+ if(target.reagents.total_volume >= target.reagents.maximum_volume)
+ to_chat(user, "[target] is full.")
+ return
+
+ var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
+ to_chat(user, "You transfer [trans] units of the solution to [target].")
+
+ else if(istype(target, /obj/item/reagent_containers/glass) && !target.is_open_container())
+ to_chat(user, "You cannot fill [target] while it is sealed.")
+ return
+
/obj/item/reagent_containers/iv_bag/update_icon()
overlays.Cut()
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index cffc2f0ef06..e22e9c86793 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -10,7 +10,7 @@
possible_transfer_amounts = null
volume = 100
consume_sound = null
- taste = FALSE
+ can_taste = FALSE
antable = FALSE
/obj/item/reagent_containers/food/pill/New()
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index f7719c4fd54..6a5d85e0631 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -1036,6 +1036,7 @@
if(O.currTag > 0)// Tag set
sortType = O.currTag
+ name = GLOB.TAGGERLOCATIONS[O.currTag]
playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
var/tag = uppertext(GLOB.TAGGERLOCATIONS[O.currTag])
to_chat(user, "Changed filter to [tag]")
diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm
index 184ce84c50e..f4ab9561bd5 100644
--- a/code/modules/response_team/ert_outfits.dm
+++ b/code/modules/response_team/ert_outfits.dm
@@ -323,7 +323,7 @@
shoes = /obj/item/clothing/shoes/white
gloves = /obj/item/clothing/gloves/color/latex/nitrile
suit = /obj/item/clothing/suit/space/hardsuit/ert/medical
- glasses = /obj/item/clothing/glasses/hud/health/health_advanced
+ glasses = /obj/item/clothing/glasses/hud/health/sunglasses
suit_store = /obj/item/gun/energy/gun
cybernetic_implants = list(
/obj/item/organ/internal/cyberimp/arm/surgery,
diff --git a/code/modules/ruins/lavalandruin_code/clown_planet.dm b/code/modules/ruins/lavalandruin_code/clown_planet.dm
new file mode 100644
index 00000000000..6121c40d2af
--- /dev/null
+++ b/code/modules/ruins/lavalandruin_code/clown_planet.dm
@@ -0,0 +1,7 @@
+//lavaland clown planet papers
+
+/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/escape
+ info = "If you dare not continue down this path of madness, escape can be found through the chute in this room."
+
+/obj/item/paper/crumpled/bloody/ruins/lavaland/clown_planet/hope
+ info = "Abandon hope, all ye who enter here."
\ No newline at end of file
diff --git a/code/modules/ruins/lavalandruin_code/seed_vault.dm b/code/modules/ruins/lavalandruin_code/seed_vault.dm
index 21cf86b4a07..db16c7b3a71 100644
--- a/code/modules/ruins/lavalandruin_code/seed_vault.dm
+++ b/code/modules/ruins/lavalandruin_code/seed_vault.dm
@@ -17,7 +17,7 @@
density = TRUE
roundstart = FALSE
death = FALSE
- mob_species = /datum/species/diona
+ mob_species = /datum/species/diona/pod
flavour_text = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed. Your masters, benevolent as they were, created uncounted \
seed vaults and spread them across the universe to every planet they could chart. You are in one such seed vault. Your goal is to cultivate and spread life wherever it will go while waiting \
for contact from your creators. Estimated time of last contact: Deployment, 5x10^3 millennia ago."
diff --git a/code/modules/security_levels/security levels.dm b/code/modules/security_levels/security levels.dm
index 3b1e56e0c2d..effaae3f0ad 100644
--- a/code/modules/security_levels/security levels.dm
+++ b/code/modules/security_levels/security levels.dm
@@ -122,7 +122,7 @@
FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
if(SEC_LEVEL_DELTA)
- security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
+ security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!", new_sound = sound('sound/effects/deltaalarm.ogg'))
security_level = SEC_LEVEL_DELTA
post_status("alert", "deltaalert")
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 0efd49b0e54..953c0e6682c 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -175,7 +175,7 @@
/obj/docking_port/mobile/emergency/proc/is_hijacked()
for(var/mob/living/player in GLOB.player_list)
if(player.mind)
- if(player.stat != DEAD)
+ if(player.stat != DEAD || !iszombie(player))
if(issilicon(player)) //Borgs are technically dead anyways
continue
if(isanimal(player)) //Poly does not own the shuttle
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index 42e710d0cf6..0a11a4397ad 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -65,3 +65,11 @@
. = ..()
if(!S1.lock_shuttle_doors && id_tag == "s_docking_airlock")
INVOKE_ASYNC(src, .proc/unlock)
+
+/obj/structure/ladder/onShuttleMove()
+ if(resistance_flags & INDESTRUCTIBLE)
+ // simply don't be moved
+ return FALSE
+ disconnect()
+ LateInitialize()
+ return ..()
\ No newline at end of file
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index bda89160be4..8c96837e9d5 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -349,7 +349,7 @@
if(mode != SHUTTLE_CALL)
return
- invertTimer()
+ timer = world.time - timeLeft(1)
mode = SHUTTLE_RECALL
/obj/docking_port/mobile/proc/enterTransit()
@@ -650,8 +650,9 @@
create_ripples(destination)
/obj/docking_port/mobile/proc/setTimer(wait)
- timer = world.time + wait
- last_timer_length = wait
+ if(timer <= 0)
+ timer = world.time
+ timer += wait - timeLeft(1)
/obj/docking_port/mobile/proc/modTimer(multiple)
var/time_remaining = timer - world.time
diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm
index 78264ca0329..6f1fb8fe293 100644
--- a/code/modules/surgery/organs/blood.dm
+++ b/code/modules/surgery/organs/blood.dm
@@ -99,11 +99,11 @@
/mob/living/carbon/proc/bleed_internal(amt) // Return 1 if we've coughed blood up, 2 if we're vomited it.
if(blood_volume)
blood_volume = max(blood_volume - amt, 0)
- if (prob(10 * amt)) // +5% chance per internal bleeding site that we'll cough up blood on a given tick.
+ if(prob(10 * amt)) // +5% chance per internal bleeding site that we'll cough up blood on a given tick.
custom_emote(1, "coughs up blood!")
add_splatter_floor(loc, 1)
return 1
- else if (amt >= 1 && prob(5 * amt)) // +2.5% chance per internal bleeding site that we'll cough up blood on a given tick. Must be bleeding internally in more than one place to have a chance at this.
+ else if(amt >= 1 && prob(5 * amt)) // +2.5% chance per internal bleeding site that we'll cough up blood on a given tick. Must be bleeding internally in more than one place to have a chance at this.
vomit(0, 1)
return 2
return 0
@@ -253,7 +253,7 @@
// Only a certain number of drips (or one large splatter) can be on a given turf.
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
if(drop)
- if(drop.drips < 3)
+ if(drop.drips < 5)
drop.drips++
drop.overlays |= pick(drop.random_icon_states)
drop.transfer_mob_blood_dna(src)
@@ -278,7 +278,8 @@
B = locate() in bloods
if(!B)
B = new(T)
-
+ if(B.bloodiness < MAX_SHOE_BLOODINESS) //add more blood, up to a limit
+ B.bloodiness += BLOOD_AMOUNT_PER_DECAL
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
B.blood_DNA |= temp_blood_DNA
diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm
index f291f61c96d..ef2f729811c 100644
--- a/code/modules/surgery/organs/organ_icon.dm
+++ b/code/modules/surgery/organs/organ_icon.dm
@@ -87,67 +87,68 @@ var/global/list/limb_icon_cache = list()
else if(s_col)
mob_icon.Blend(s_col, ICON_ADD)
+ if(owner) //Maintains overlays on disembodied parts.
+ cut_overlays()
+
dir = EAST
icon = mob_icon
return mob_icon
/obj/item/organ/external/head/get_icon()
-
..()
- overlays.Cut()
if(!owner)
return
if(dna.species.has_organ["eyes"])
var/icon/eyes_icon = owner.get_eyecon()
if(eyes_icon)
- mob_icon.Blend(eyes_icon, ICON_OVERLAY)
- overlays |= eyes_icon
+ mob_icon.Blend(eyes_icon, ICON_OVERLAY) //This is required since update_icons.dm relies on this proc to render non-shining eyes.
+ add_overlay(eyes_icon)
if(owner.lip_style && (LIPS in dna.species.species_traits))
- var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s")
- overlays |= lip_icon
- mob_icon.Blend(lip_icon, ICON_OVERLAY)
+ add_overlay(mutable_appearance('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s")) //Hefty icon not necessary.
var/head_marking = owner.m_styles["head"]
- if(head_marking && head_marking != "None")
+ if(head_marking)
var/datum/sprite_accessory/head_marking_style = GLOB.marking_styles_list[head_marking]
if(head_marking_style && head_marking_style.species_allowed && (dna.species.name in head_marking_style.species_allowed) && head_marking_style.marking_location == "head")
- var/icon/h_marking_s = new/icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s")
+ var/icon/h_marking_s = new /icon("icon" = head_marking_style.icon, "icon_state" = "[head_marking_style.icon_state]_s")
if(head_marking_style.do_colouration)
h_marking_s.Blend(owner.m_colours["head"], ICON_ADD)
- overlays |= h_marking_s
+ add_overlay(h_marking_s)
- if(ha_style)
- var/datum/sprite_accessory/head_accessory_style = GLOB.head_accessory_styles_list[ha_style]
- if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed))
- var/icon/head_accessory_s = new/icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s")
- if(head_accessory_style.do_colouration)
- head_accessory_s.Blend(headacc_colour, ICON_ADD)
- overlays |= head_accessory_s
+ if(!((owner.head && (owner.head.flags & BLOCKHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHAIR)))) //Common restriction for all the below features.
+ if(ha_style)
+ var/datum/sprite_accessory/head_accessory_style = GLOB.head_accessory_styles_list[ha_style]
+ if(head_accessory_style && head_accessory_style.species_allowed && (dna.species.name in head_accessory_style.species_allowed))
+ var/icon/head_accessory_s = new /icon("icon" = head_accessory_style.icon, "icon_state" = "[head_accessory_style.icon_state]_s")
+ if(head_accessory_style.do_colouration)
+ head_accessory_s.Blend(headacc_colour, ICON_ADD)
+ add_overlay(head_accessory_s)
- if(f_style)
- var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style]
- if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS)))
- var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
- if(istype(dna.species, /datum/species/slime)) // I am el worstos
- facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha.
- else if(facial_hair_style.do_colouration)
- facial_s.Blend(facial_colour, ICON_ADD)
- overlays |= facial_s
+ if(f_style)
+ var/datum/sprite_accessory/facial_hair_style = GLOB.facial_hair_styles_list[f_style]
+ if(facial_hair_style && ((facial_hair_style.species_allowed && (dna.species.name in facial_hair_style.species_allowed)) || (dna.species.bodyflags & ALL_RPARTS)))
+ var/icon/facial_s = new /icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
+ if(istype(dna.species, /datum/species/slime)) // I am el worstos
+ facial_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha.
+ else if(facial_hair_style.do_colouration)
+ facial_s.Blend(facial_colour, ICON_ADD)
+ add_overlay(facial_s)
- if(h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR)))
- var/datum/sprite_accessory/hair_style = GLOB.hair_styles_full_list[h_style]
- if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS)))
- var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
- if(istype(dna.species, /datum/species/slime)) // I am el worstos
- hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha.
- else if(hair_style.do_colouration)
- hair_s.Blend(hair_colour, ICON_ADD)
- overlays |= hair_s
+ if(h_style)
+ if(!owner.isSynthetic() || (owner.isSynthetic() && ((owner.head && (owner.head.flags & BLOCKHEADHAIR)) || (owner.wear_mask && (owner.wear_mask.flags & BLOCKHEADHAIR)))))
+ var/datum/sprite_accessory/hair_style = GLOB.hair_styles_full_list[h_style]
+ if(hair_style && ((dna.species.name in hair_style.species_allowed) || (dna.species.bodyflags & ALL_RPARTS)))
+ var/icon/hair_s = new /icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
+ if(istype(dna.species, /datum/species/slime)) // I am el worstos
+ hair_s.Blend("[owner.skin_colour]A0", ICON_AND) //A0 = 160 alpha.
+ else if(hair_style.do_colouration)
+ hair_s.Blend(hair_colour, ICON_ADD)
+ add_overlay(hair_s)
- return mob_icon
+ return mob_icon //Don't need to blend the above into this as it's handled in human/update_icons(). The overlays are for rendering stuff on disembodied heads.
/obj/item/organ/external/proc/get_icon_state(skeletal)
var/gender
diff --git a/code/modules/surgery/organs/subtypes/diona.dm b/code/modules/surgery/organs/subtypes/diona.dm
index be05b2917c3..0e76c8fe20b 100644
--- a/code/modules/surgery/organs/subtypes/diona.dm
+++ b/code/modules/surgery/organs/subtypes/diona.dm
@@ -2,7 +2,6 @@
name = "core trunk"
max_damage = 200
min_broken_damage = 50
- cannot_break = 1
amputation_point = "trunk"
encased = null
gendered_icon = 0
@@ -10,7 +9,6 @@
/obj/item/organ/external/groin/diona
name = "fork"
min_broken_damage = 50
- cannot_break = 1
amputation_point = "lower trunk"
gendered_icon = 0
@@ -18,58 +16,49 @@
name = "left upper tendril"
max_damage = 35
min_broken_damage = 20
- cannot_break = 1
amputation_point = "upper left trunk"
/obj/item/organ/external/arm/right/diona
name = "right upper tendril"
max_damage = 35
min_broken_damage = 20
- cannot_break = 1
amputation_point = "upper right trunk"
/obj/item/organ/external/leg/diona
name = "left lower tendril"
max_damage = 35
min_broken_damage = 20
- cannot_break = 1
amputation_point = "lower left fork"
/obj/item/organ/external/leg/right/diona
name = "right lower tendril"
max_damage = 35
min_broken_damage = 20
- cannot_break = 1
amputation_point = "lower right fork"
/obj/item/organ/external/foot/diona
name = "left foot"
max_damage = 20
min_broken_damage = 10
- cannot_break = 1
amputation_point = "branch"
/obj/item/organ/external/foot/right/diona
name = "right foot"
max_damage = 20
min_broken_damage = 10
- cannot_break = 1
amputation_point = "branch"
/obj/item/organ/external/hand/diona
name = "left grasper"
- cannot_break = 1
amputation_point = "branch"
/obj/item/organ/external/hand/right/diona
name = "right grasper"
- cannot_break = 1
amputation_point = "branch"
/obj/item/organ/external/head/diona
max_damage = 50
min_broken_damage = 25
- cannot_break = 1
encased = null
amputation_point = "upper trunk"
gendered_icon = 0
@@ -82,6 +71,11 @@
icon = 'icons/obj/objects.dmi'
icon_state = "nymph"
+/obj/item/organ/internal/lungs/diona
+ name = "respiratory vacuoles"
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "nymph"
+
/obj/item/organ/internal/brain/diona // Turns into a nymph instantly, no transplanting possible.
name = "gas bladder"
icon = 'icons/obj/objects.dmi'
diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm
new file mode 100644
index 00000000000..3ba12518dd2
--- /dev/null
+++ b/code/modules/zombie/items.dm
@@ -0,0 +1,67 @@
+/obj/item/zombie_hand
+ name = "zombie claw"
+ desc = "A zombie's claw is its primary tool, capable of infecting \
+ unconscious or dead humans, butchering all other living things to \
+ sustain the zombie, forcing open airlock doors and opening \
+ child-safe caps on bottles."
+ flags = NODROP|ABSTRACT|DROPDEL
+ icon = 'icons/effects/blood.dmi'
+ icon_state = "bloodhand_left"
+ var/icon_left = "bloodhand_left"
+ var/icon_right = "bloodhand_right"
+ hitsound = 'sound/hallucinations/growl1.ogg'
+ force = 25
+ damtype = "brute"
+
+/obj/item/zombie_hand/equipped(mob/user, slot)
+ . = ..()
+ switch(slot)
+ // Yes, these intentionally don't match
+ if(slot_l_hand)
+ icon_state = icon_right
+ if(slot_r_hand)
+ icon_state = icon_left
+
+/obj/item/zombie_hand/afterattack(atom/target, mob/user, proximity_flag)
+ . = ..()
+ if(!proximity_flag)
+ return
+
+ else if(isliving(target))
+ if(ishuman(target))
+ check_infection(target, user)
+ else
+ check_feast(target, user)
+
+/obj/item/zombie_hand/proc/check_infection(var/mob/living/carbon/human/target, var/mob/user)
+ CHECK_DNA_AND_SPECIES(target)
+
+ if(NOZOMBIE in target.dna.species.species_traits)
+ // cannot infect any NOZOMBIE subspecies (such as high functioning
+ // zombies)
+ return
+
+ var/obj/item/organ/internal/zombie_infection/infection
+ infection = target.get_organ_slot("zombie_infection")
+ if(!infection)
+ if (target.InCritical() || (!target.check_death_method() && target.health <= HEALTH_THRESHOLD_DEAD))
+ infection = new(target)
+
+/obj/item/zombie_hand/proc/check_feast(mob/living/target, mob/living/user)
+ if(target.stat == DEAD)
+ var/hp_gained = target.maxHealth
+ target.gib()
+ user.adjustBruteLoss(-hp_gained)
+ user.adjustToxLoss(-hp_gained)
+ user.adjustFireLoss(-hp_gained)
+ user.adjustCloneLoss(-hp_gained)
+ user.adjustBrainLoss(-hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!"
+
+/obj/item/zombie_hand/suicide_act(mob/living/carbon/human/user)
+ user.visible_message("[user] is ripping [user.p_their()] brains out! It looks like [user.p_theyre()] trying to commit suicide!")
+ if(ishuman(user))
+ var/mob/living/carbon/human/L = user
+ var/obj/item/organ/external/O = L.get_organ("head")
+ if(O)
+ O.droplimb()
+ return (BRUTELOSS)
\ No newline at end of file
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
new file mode 100644
index 00000000000..76bce6ead3d
--- /dev/null
+++ b/code/modules/zombie/organs.dm
@@ -0,0 +1,93 @@
+/obj/item/organ/internal/zombie_infection
+ name = "festering ooze"
+ desc = "A black web of pus and viscera."
+ parent_organ = "head"
+ slot = "zombie_infection"
+ icon_state = "blacktumor"
+ var/converts_living = FALSE
+ var/causes_damage = TRUE
+ var/datum/species/old_species = /datum/species/human
+ var/living_transformation_time = 3
+ var/revive_time_min = 450
+ var/revive_time_max = 700
+ var/timer_id
+ var/dont_delete = FALSE // to prevent set_species proc in zombify from deleting the infection organ immediately
+
+/obj/item/organ/internal/zombie_infection/New()
+ . = ..()
+ if(ishuman(owner) && !ismachine(owner) && !iszombie(owner.dna.species))
+ old_species = owner.dna.species
+ GLOB.zombie_infection_list += src
+
+/obj/item/organ/internal/zombie_infection/Destroy()
+ GLOB.zombie_infection_list -= src
+ . = ..()
+
+/obj/item/organ/internal/zombie_infection/insert(mob/living/carbon/human/M, special = 0)
+ . = ..()
+ START_PROCESSING(SSobj, src)
+
+/obj/item/organ/internal/zombie_infection/remove(mob/living/carbon/human/M, special = 0)
+ STOP_PROCESSING(SSobj, src)
+ if(iszombie(M) && old_species && !dont_delete)
+ M.set_species(old_species)
+ if(timer_id)
+ deltimer(timer_id)
+ ..()
+
+/obj/item/organ/internal/zombie_infection/on_find(mob/living/finder)
+ to_chat(finder,"Inside the head is a disgusting black \
+ web of pus and viscera, bound tightly around the brain like some \
+ biological harness.")
+
+/obj/item/organ/internal/zombie_infection/process()
+ if(!ishuman(owner)) // We do not support monkey or xeno zombies. Yet.
+ qdel(src)
+ return
+ if(owner.suiciding)
+ return
+ if(owner.stat != DEAD && !converts_living)
+ return
+ if(causes_damage && !iszombie(owner) && owner.stat != DEAD)
+ owner.adjustToxLoss(1)
+ if (prob(10))
+ to_chat(owner, "You feel sick...")
+ if(!owner.get_int_organ(/obj/item/organ/internal/brain))
+ return
+ if(!iszombie(owner) && !timer_id)
+ to_chat(owner, "You can feel your heart stopping, but something isn't right... \
+ life has not abandoned your broken form. You can only feel a deep and immutable hunger that \
+ not even death can stop, you will rise again!")
+ var/revive_time = rand(revive_time_min, revive_time_max)
+ var/flags = TIMER_STOPPABLE
+ timer_id = addtimer(CALLBACK(src, .proc/zombify), revive_time, flags)
+
+/obj/item/organ/internal/zombie_infection/proc/zombify()
+ timer_id = null
+ if(owner.stat != DEAD && !converts_living)
+ return
+
+ if(!iszombie(owner))
+ old_species = owner.dna.species
+ dont_delete = TRUE // make sure the remove code above does not run when the species code replaces all the organs
+ owner.set_species(/datum/species/zombie/infectious)
+ for(var/thing in owner.viruses) // cure any new crit viruses
+ var/datum/disease/D = thing
+ D.cure(0)
+ dont_delete = FALSE
+ //Fully heal the zombie's damage the first time they rise
+ owner.setToxLoss(0)
+ owner.setOxyLoss(0)
+ owner.setBrainLoss(0)
+ owner.setCloneLoss(0)
+ owner.SetLoseBreath(0)
+ owner.heal_overall_damage(INFINITY,INFINITY,TRUE,TRUE,FALSE)
+
+ if(owner.update_revive())
+ owner.grab_ghost()
+
+ owner.visible_message("[owner] suddenly convulses, as [owner.p_they()] stagger to [owner.p_their()] feet and gain a ravenous hunger in [owner.p_their()] eyes!", "You HUNGER!")
+ playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1)
+ owner.do_jitter_animation(living_transformation_time)
+ owner.Stun(living_transformation_time)
+ to_chat(owner, "You are now a zombie! Do not seek to be cured, do not help any non-zombies in any way, do not harm your zombie brethren and spread the disease by killing others. You are a creature of hunger and violence.")
diff --git a/config/example/lavaRuinBlacklist.txt b/config/example/lavaRuinBlacklist.txt
index 934d86514b0..f8fb3fd196a 100644
--- a/config/example/lavaRuinBlacklist.txt
+++ b/config/example/lavaRuinBlacklist.txt
@@ -5,6 +5,8 @@
##BIODOMES
#_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm
+#_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
+#_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm
##RESPAWN
#_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
diff --git a/goon/browserassets/css/browserOutput-dark.css b/goon/browserassets/css/browserOutput-dark.css
index b19cc07275f..426493dfc88 100644
--- a/goon/browserassets/css/browserOutput-dark.css
+++ b/goon/browserassets/css/browserOutput-dark.css
@@ -336,6 +336,7 @@ h1.alert, h2.alert {color: #FFF;}
.skrell {color: #00CED1;}
.solcom {color: #8282FB;}
.com_srus {color: #7c4848;}
+.zombie {color: #ff0000;}
.soghun {color: #228B22;}
.changeling {color: #800080;}
.vox {color: #AA00AA;}
@@ -389,7 +390,6 @@ h1.alert, h2.alert {color: #FFF;}
.whisper {font-style:italic;color:#CCCCCC;}
/* Recruiting stuff */
.recruit {color: #5c00e6; font-weight: bold; font-style: italic;}
-"}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 75%;}
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
index 3b77bb1f97e..07ae914de62 100644
--- a/goon/browserassets/css/browserOutput.css
+++ b/goon/browserassets/css/browserOutput.css
@@ -333,6 +333,7 @@ h1.alert, h2.alert {color: #000000;}
.skrell {color: #00CED1;}
.solcom {color: #22228B;}
.com_srus {color: #7c4848;}
+.zombie {color: #ff0000;}
.soghun {color: #228B22;}
.changeling {color: #800080;}
.vox {color: #AA00AA;}
@@ -386,7 +387,6 @@ h1.alert, h2.alert {color: #000000;}
.whisper {font-style:italic;color:#333333;}
/* Recruiting stuff */
.recruit {color: #5c00e6; font-weight: bold; font-style: italic;}
-"}
.memo {color: #638500; text-align: center;}
.memoedit {text-align: center; font-size: 75%;}
diff --git a/html/changelog.html b/html/changelog.html
index 023f1918124..270ef03dd3f 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,251 @@
-->
+
30 August 2019
+
AffectedArc07 updated:
+
+
Arkatos updated:
+
+ - Added new icon for Charge spell
+ - Added new icon for No Clothes spell
+ - Added new icon for Wizard spellbook
+ - Added new animations to 10 single-use spellbooks
+ - Added new sprite for Bottle of Tickles
+ - Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
+ - Fixed an issue where Bottle of Tickles did not properly refund
+ - Fixed an issue with alpha layering on Bottle of Ooze sprite
+ - Very slightly adjusted brightness of the Boo! ghost spell icon
+ - Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
+ - Polymorph can now turn a mob into Syndicate medical or saboteur modules
+ - Mobs made via polymorph into borgs are now unbounded free borgs
+ - Repulse spell cost decreased from 2 to 1
+ - Lighting bolt spell cost decreased from 2 to 1
+ - Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
+ - Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
+ - Improved descriptions and wording regarding Wizard spellbook and Wizard spells
+ - Traitor AI now uses action buttons for its malfunction abilities
+
+
AzuleUtama updated:
+
+ - Adds false-bottomed briefcase from VG.
+
+
Couls updated:
+
+ - Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
+ - Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
+ - DUAL WIELDING
+ - new chatsubsystem from TG!
+ - Update issue templates to latest version and clean up the current template
+ - mining shuttle warning message and delay before launching
+ - cardboard boxes are no longer sonic speed
+ - shuttle timers now get set properly
+
+
EmanTheAlmighty updated:
+
+ - Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
+ - Blobbernauts and blobs can now communicate with each other.
+ - Blobbernauts now regenerate health overtime when standing on blob structures.
+ - Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
+
+
Emanthealmighty updated:
+
+ - The poll to play as a blobbernaut now lasts 10 seconds from 15.
+ - Blobbernauts no longer chase after people while players are being polled to play as one.
+
+
Fox McCloud updated:
+
+ - Plasmamen dramatically overhauled.
+ - Plasmamen can be cloned without burning to death in the clonepod
+ - Plasmamen no longer start with spacesuits
+ - Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
+ - Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
+ - Plasmamen take 50% extra brute and burn
+ - Plasmamen are immune to radiation
+ - Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
+ - Plasmaman helmets now have built in welding goggles
+ - Plasmaman karma cost lowered from 100 to 45
+ - Reworks Diona
+ - Diona bleed (call it chlorophy; it's green)
+ - Diona Breathe (plants do need to exchange gas after all)
+ - Rad Immunity Removed
+ - Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
+ - Diona no longer have unbreakable bones (wood can crack ya know!)
+ - Diona are no longer space proof
+ - Diona are more vulnerable to fire and heat damage
+ - Diona weakness to weedkiller dramatically nerfed
+ - Diona now use Newcrit
+ - Diona are no longer slow
+ - Diona can wear spacesuits
+ - Fixes stun absorbing not working
+ - Fixes parallax insane setting not doing anything
+ - Ores can be destroyed by devastating explosions
+ - silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
+ - drills slightly slower, but diamond drills slightly faster
+ - Spade is the same speed as a shovel
+ - Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
+ - can use a hivelord core in your active hand to apply it to yourself
+ - soulstone in the abandoned locked crates can now be used by anyone
+ - Adds firelemon seeds to the abandoned locked crates as potential loot
+ - Hardsuits have an integrated helmet; you no longer have to attach helmets
+ - Toggling up/down helmets is now done with an action button
+ - can no longer attach magboots to a hardsuit
+ - Hardsuit base melee armor increased from 10 to 30
+ - Security and HoS hardsuit melee armor increased by 5
+ - HoS hardsuit helmet armor matches his hardsuit
+ - CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
+ - Elite syndicate suits can't be acided
+ - Fixes stuns and weakens related to reagents
+ - Fixes the displayed cost of Plasmamen
+ - Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
+ - Removes mining carbon dioxide jetpack
+ - Can no longer use jetpacks in your suit storage slot
+ - Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
+ - Fixes random singularity releases from the grid check event
+ - loadout costs for most things cut from 2 to 1
+ - Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
+ - moved hipster glasses from donator to general glasses
+ - Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
+ - Removes access based security barriers
+ - Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
+ - can tear up bedsheet and gauze to get cloth--requires a sharp object
+ - Fixes plasmamen atmos techs not getting their proper suit
+ - Adds in a loom, craft one out of 10 wood
+ - Adds in cotton and durathread cotton to botany to grow
+ - Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
+ - Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
+ - Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
+ - Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
+ - adds a whole range of beanies, find them in the clothing vendor or make them yourself
+ - Updates the cowboy boots sprites
+ - Unironically fixes about several thousand runtimes
+ - Fixes jackets not keeping you warm
+ - Chefs are now trained in the art of Close Quarters Cooking
+ - Adds the Book of Babel as tendril loot
+ - Adds Jacbo's Ladder as tendril loot
+ - Fixes fungus, blood, and graffiti not showing up on a wall
+ - Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
+ - Fixes baseball bats throwing anchored things
+ - Fixes blood drunk buff
+ - Fixes using a crusher on a trophy to equip it causing you to drop the crusher
+ - refactors lazarus capsules; no real behavioral change
+ - Fixes being able to revive megafauna with strange reagent
+
+
Fox McCloud and FullOfSkittles updated:
+
+ - Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
+ - Fixes telebacon not properly acting as...well, a bacon beacon
+
+
FreeStylaLT updated:
+
+ - Added an Engine Picker, which uses new engine beacons.
+ - Replaced the current two engine generators with one engine beacon.
+
+
Ionward updated:
+
+ - Drask crewmembers now have properly fitting shoes.
+ - Fixed some minor issues in Drasks uniforms
+ - non-humans now have proper sprites for durathread goods
+
+
KasparoVy updated:
+
+ - Adds sprites for all Vox & Armalis earwear.
+ - Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
+ - You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
+ - Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
+ - Fixes an issue preventing the species-fitting of earwear.
+ - Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
+ - Picking up uniforms no longer renders a default grey jumpsuit on Vox.
+ - Resolves an issue causing shining eyes to be rendered darker than intended.
+ - Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
+ - Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
+ - Non-shining eyes render the proper colour again.
+
+
Kurgis updated:
+
+ - Beepsky now bumps around on its wheels when patrolling for crime.
+
+
Markolie updated:
+
+ - A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
+ - Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
+ - The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
+ - A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
+ - Outfits now support accessories and internal boxes.
+ - The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
+ - Water coming from sinks and certain water effects is now 10C instead of body temperature.
+
+
Shadow-Quill updated:
+
+ - [Meta] Added buckshot and slugs to armoury.
+ - [Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
+ - [Meta] R&D doors now has proper access requirements.
+ - [Meta] Added RCS and telepad to cargo.
+ - [Meta] Disposals sheet stacker and conveyor belts now works properly.
+ - [Meta] One-way airlocks added in Medbay/Brig.
+ - [Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
+ - AIs not being able to restore their own power if in an area with an APC.
+ - Fixed being able to talk in OOC under certain circumstances if it's disabled.
+ - Lockers can no longer move around anchored mobs.
+
+
SteelSlayer updated:
+
+ - You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
+ - The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
+ - A cable adding sound gets played when you add wires to create a terminal for a SMES
+ - Rapid pipe dispensers can now place disposal sorting pipes
+ - When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
+ - Added a destination tagger to the atmosheric technician locker
+ - Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
+ - Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
+ - IV bags are able to transfer their contents to other containers by clicking on them with the bag
+ - Adds a handheld defibrillator to the paramedic EVA closet
+ - You can insert magazines into L6 SAWs again
+ - Removed one of the high capacity tanks in hydroponics
+ - Added a disk compartmentalizer to hydroponics
+ - Delaying round start actually delays round start again
+
+
Terilia updated:
+
+ - added headcrabs
+ - adjusted the path's for headslugs. They are not called headcrab anymore
+
+
TheSardele updated:
+
+ - Removes the ability of obese people and those with matter eater to swallow others.
+
+
Ty-Omaha updated:
+
+ - Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
+
+
datlo updated:
+
+ - Added ashstorm immunity to titanium and plastitanium golems.
+ - Added lava immunity to plastitanium golems.
+ - Bananium golems now slowly waddle around.
+ - Uranium golems now properly irradiate nearby mobs that arent rad immune.
+ - Tranquillite golems now properly get their miming powers.
+ - Added the Clown and Winter biodomes as possible lavaland ruins.
+ - Update a changeling error message to be clearer.
+
+
farie82 updated:
+
+ - Items with NODROP that are dropped now lose the flag if they didn't get created with it
+ - Adds tip text to the examine text of the ambulance trolley about how to attach it
+ - Adds tip text to the nuke when trying to use the NAD before deploying it
+ - Adds tip text to the fire axe cabinet about how to lock/unlock it
+ - Adds tip text to airlocks if they have a note on them about how to remove the note
+ - Can't put the NAD in the nuke now when it has the NODROP flag
+ - Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
+ - Can't put a nodrop fire axe in fire axe cabinets now. Duping them
+ - Implants like the IPC charging work again. They won't get deleted after first use
+
+
variableundefined updated:
+
+ - A proc's name got changed. That's it
+
+
23 August 2019
AffectedArc07, Keekenox, Floyd/Qustinnus updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 647b9735e00..d03050e2258 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -10819,3 +10819,266 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- bugfix: adjusts the hierophant blast layer to make for it to always be below the
effect. this should be the case already due to mouse_opacity, though for some
unknown reason, it just doesn't work sometimes, so this should fix it.
+2019-08-30:
+ AffectedArc07:
+ - bugfix: Fixes the changelog
+ Arkatos:
+ - imageadd: Added new icon for Charge spell
+ - imageadd: Added new icon for No Clothes spell
+ - imageadd: Added new icon for Wizard spellbook
+ - imageadd: Added new animations to 10 single-use spellbooks
+ - imageadd: Added new sprite for Bottle of Tickles
+ - rscadd: Added refunding functionality to the Bottle of Ooze akin to the other
+ summoning bottles. Click with the bottle in hand on a wizard spellbook to refund
+ its cost and limit slot.
+ - bugfix: Fixed an issue where Bottle of Tickles did not properly refund
+ - bugfix: Fixed an issue with alpha layering on Bottle of Ooze sprite
+ - tweak: Very slightly adjusted brightness of the Boo! ghost spell icon
+ - tweak: Wizard spellbook was completely reorganized, and new appropriate categories
+ were added, each category is sorted by price, and if price of the two or more
+ spells is the same, they are sorted alphabetically
+ - tweak: Polymorph can now turn a mob into Syndicate medical or saboteur modules
+ - tweak: Mobs made via polymorph into borgs are now unbounded free borgs
+ - tweak: Repulse spell cost decreased from 2 to 1
+ - tweak: Lighting bolt spell cost decreased from 2 to 1
+ - tweak: Slaughter/Laughter demons and Magical Morphs now always have their second
+ fluff objective considered as complete no matter the circumstances
+ - tweak: Laughter Demons very slightly buffed, they are still a bit weaker than
+ Slaughter Demons
+ - spellcheck: Improved descriptions and wording regarding Wizard spellbook and Wizard
+ spells
+ - rscadd: Traitor AI now uses action buttons for its malfunction abilities
+ AzuleUtama:
+ - rscadd: Adds false-bottomed briefcase from VG.
+ Couls:
+ - rscadd: Rechargers can now be crafted from science using one capacitor and a recharger
+ board tweak:Smaller machines like microwaves and cell chargers can now be placed
+ on tables(Fax machines included) tweak:can screwdriver open rechargers and then
+ apply a crowbar to deconstruct them
+ - tweak: Blood spread now depends on volume of the blood, requires more drips of
+ blood to create a pool
+ - rscadd: DUAL WIELDING
+ - rscadd: new chatsubsystem from TG!
+ - tweak: Update issue templates to latest version and clean up the current template
+ - rscadd: mining shuttle warning message and delay before launching
+ - bugfix: cardboard boxes are no longer sonic speed
+ - bugfix: shuttle timers now get set properly
+ EmanTheAlmighty:
+ - rscadd: Blobbernauts can now be controlled by players through a prompt which appears
+ when they are spawned by blobs.
+ - rscadd: Blobbernauts and blobs can now communicate with each other.
+ - rscadd: Blobbernauts now regenerate health overtime when standing on blob structures.
+ - rscadd: 'Blobbernauts will slowly lose health if they are not standing on blob
+ structures while not at full health. balance: Blobbernauts have been nerfed,
+ they now have less health, deal less damage and cannot break walls anymore.
+ balance: Blob''s "Produce Blobbernaut" ability has been made more expensive
+ to use, now costing 60 resources instead of 20.'
+ Emanthealmighty:
+ - tweak: The poll to play as a blobbernaut now lasts 10 seconds from 15.
+ - tweak: Blobbernauts no longer chase after people while players are being polled
+ to play as one.
+ Fox McCloud:
+ - tweak: Plasmamen dramatically overhauled.
+ - rscadd: Plasmamen can be cloned without burning to death in the clonepod
+ - rscdel: Plasmamen no longer start with spacesuits
+ - rscadd: Plasmamen start off with jumpsuits that seal to protect against oxygen.
+ This allows for you to customize their appearance more
+ - tweak: Plasmamen helmets now allow you to see a Plasmaman's actual face; should
+ be able to see their eye color and mouth color now
+ - tweak: Plasmamen take 50% extra brute and burn
+ - rscadd: Plasmamen are immune to radiation
+ - tweak: Plasmamen start out with a small tank that can fit on a belt or in a pocket;
+ it should be enough to last an entire shift
+ - rscadd: Plasmaman helmets now have built in welding goggles
+ - tweak: Plasmaman karma cost lowered from 100 to 45
+ - tweak: Reworks Diona
+ - rscadd: Diona bleed (call it chlorophy; it's green)
+ - rscadd: Diona Breathe (plants do need to exchange gas after all)
+ - rscdel: Rad Immunity Removed
+ - tweak: Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright
+ area; this effect does not kick in if they're in crit
+ - rscdel: Diona no longer have unbreakable bones (wood can crack ya know!)
+ - rscdel: Diona are no longer space proof
+ - tweak: Diona are more vulnerable to fire and heat damage
+ - tweak: Diona weakness to weedkiller dramatically nerfed
+ - rscadd: Diona now use Newcrit
+ - tweak: Diona are no longer slow
+ - rscadd: Diona can wear spacesuits
+ - bugfix: Fixes stun absorbing not working
+ - bugfix: Fixes parallax insane setting not doing anything
+ - tweak: Ores can be destroyed by devastating explosions
+ - tweak: silver, gold, and diamond pickaxes do a bit more damage and mine faster
+ than before
+ - tweak: drills slightly slower, but diamond drills slightly faster
+ - tweak: Spade is the same speed as a shovel
+ - tweak: Hivelord stabilizer will now make a hivelord core/legion soul stabilize
+ and be preserved, even if it was previously inert
+ - tweak: can use a hivelord core in your active hand to apply it to yourself
+ - rscadd: soulstone in the abandoned locked crates can now be used by anyone
+ - rscadd: Adds firelemon seeds to the abandoned locked crates as potential loot
+ - tweak: Hardsuits have an integrated helmet; you no longer have to attach helmets
+ - tweak: Toggling up/down helmets is now done with an action button
+ - rscdel: can no longer attach magboots to a hardsuit
+ - tweak: Hardsuit base melee armor increased from 10 to 30
+ - tweak: Security and HoS hardsuit melee armor increased by 5
+ - tweak: HoS hardsuit helmet armor matches his hardsuit
+ - tweak: CE's hardsuit helmet armor for rads increased by 10 (should be fully rad
+ proof now)
+ - tweak: Elite syndicate suits can't be acided
+ - bugfix: Fixes stuns and weakens related to reagents
+ - bugfix: Fixes the displayed cost of Plasmamen
+ - rscadd: 'Adds jetpack hardsuit upgrades: get yours at mining for 2000 points'
+ - rscdel: Removes mining carbon dioxide jetpack
+ - tweak: Can no longer use jetpacks in your suit storage slot
+ - rscadd: Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and
+ Shielded Syndicate Hardsuit all have built in jetpacks
+ - bugfix: Fixes random singularity releases from the grid check event
+ - tweak: loadout costs for most things cut from 2 to 1
+ - rscadd: Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown
+ shoes, white shoes, and ian's shirt to the loadout
+ - tweak: moved hipster glasses from donator to general glasses
+ - rscadd: Adds in sandbags. Use them to deploy destructable barriers; miners start
+ off with a few
+ - rscdel: Removes access based security barriers
+ - rscadd: Adds in security barrier grenade. When it goes off, it will deploy up
+ to 3 barriers that will lock into place; should find 4 of these in the armory
+ - rscadd: can tear up bedsheet and gauze to get cloth--requires a sharp object
+ - bugfix: Fixes plasmamen atmos techs not getting their proper suit
+ - rscadd: Adds in a loom, craft one out of 10 wood
+ - rscadd: Adds in cotton and durathread cotton to botany to grow
+ - rscadd: Adds in a number of expanded items to create out of cloth, such as improvised
+ gauze, beanies, and softcaps
+ - rscadd: Adds the ability to use personal crafting to make durathread jumpsuits,
+ bandanas, armor, helmets, beanies and berets. Aside from the bandana, these
+ all have minor armor on them
+ - rscadd: 'Adds a number of new items to personally craft, related to clothing:
+ ability to make health, sec, diagnotic, and reagent sunglasses.'
+ - rscadd: Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks,
+ and a spooky ghost disguise
+ - rscadd: adds a whole range of beanies, find them in the clothing vendor or make
+ them yourself
+ - tweak: Updates the cowboy boots sprites
+ - bugfix: Unironically fixes about several thousand runtimes
+ - bugfix: Fixes jackets not keeping you warm
+ - rscadd: Chefs are now trained in the art of Close Quarters Cooking
+ - rscadd: Adds the Book of Babel as tendril loot
+ - rscadd: Adds Jacbo's Ladder as tendril loot
+ - bugfix: Fixes fungus, blood, and graffiti not showing up on a wall
+ - bugfix: Fixes the lavaland inquisitor and berserker hardsuits having incorrect
+ armor and slowdown values
+ - bugfix: Fixes baseball bats throwing anchored things
+ - bugfix: Fixes blood drunk buff
+ - bugfix: Fixes using a crusher on a trophy to equip it causing you to drop the
+ crusher
+ - tweak: refactors lazarus capsules; no real behavioral change
+ - bugfix: Fixes being able to revive megafauna with strange reagent
+ Fox McCloud and FullOfSkittles:
+ - tweak: Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
+ - bugfix: Fixes telebacon not properly acting as...well, a bacon beacon
+ FreeStylaLT:
+ - rscadd: Added an Engine Picker, which uses new engine beacons.
+ - tweak: Replaced the current two engine generators with one engine beacon.
+ Ionward:
+ - imageadd: Drask crewmembers now have properly fitting shoes.
+ - imageadd: Fixed some minor issues in Drasks uniforms
+ - imageadd: non-humans now have proper sprites for durathread goods
+ KasparoVy:
+ - imageadd: Adds sprites for all Vox & Armalis earwear.
+ - imageadd: Adds sprites for Armalis default backpack, nitrogen tank (old-style
+ back & new-style belt) & all breath mask variations.
+ - rscadd: 'You can now species-fit in-hand icons: Use a single .dmi file and suffix
+ the icon states with _l or _r.'
+ - bugfix: Fixes an issue preventing Vox Armalis from being rendered with the proper
+ in-hand icons for their massive noise cannons.
+ - bugfix: Fixes an issue preventing the species-fitting of earwear.
+ - bugfix: Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
+ - bugfix: Picking up uniforms no longer renders a default grey jumpsuit on Vox.
+ - bugfix: Resolves an issue causing shining eyes to be rendered darker than intended.
+ - bugfix: Resolves an issue preventing appearance features (hair, eyes, etc.) from
+ rendering on disembodied heads.
+ - bugfix: Resolves an issue preventing Admin-revived decapitated bodies from having
+ appearance features or ears.
+ - bugfix: Non-shining eyes render the proper colour again.
+ Kurgis:
+ - rscadd: Beepsky now bumps around on its wheels when patrolling for crime.
+ Markolie:
+ - rscadd: A new outfit manager has been added for admins (under debug). It lets
+ them save and load custom outfits on their computer and use these to equip players.
+ - rscadd: Upon transforming players into humans or reincarnating them through the
+ player panel, admins will now directly be able to select their equipment.
+ - rscadd: 'The select equipment verb now works on observers: it''ll create a human
+ with the given equipment under the ghost.'
+ - rscadd: A "Copy Outfit" button has been added to the View Variables dropdown,
+ which lets admins instantly copy an outfit.
+ - rscadd: Outfits now support accessories and internal boxes.
+ - rscdel: The separate option to equip ERT members has been removed. It's been integrated
+ into their regular outfits.
+ - tweak: Water coming from sinks and certain water effects is now 10C instead of
+ body temperature.
+ Shadow-Quill:
+ - rscadd: '[Meta] Added buckshot and slugs to armoury.'
+ - rscadd: '[Meta] Added surgical tools, robotic first aid kits, and a photocopier
+ to Robotics.'
+ - bugfix: '[Meta] R&D doors now has proper access requirements.'
+ - rscadd: '[Meta] Added RCS and telepad to cargo.'
+ - bugfix: '[Meta] Disposals sheet stacker and conveyor belts now works properly.'
+ - rscadd: '[Meta] One-way airlocks added in Medbay/Brig.'
+ - tweak: '[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.'
+ - bugfix: AIs not being able to restore their own power if in an area with an APC.
+ - bugfix: Fixed being able to talk in OOC under certain circumstances if it's disabled.
+ - bugfix: Lockers can no longer move around anchored mobs.
+ SteelSlayer:
+ - bugfix: You can no longer spam dismantle a SMES terminal and get 10 cable for
+ every progress bar
+ - bugfix: The game will properly remove 10 cable from your stack after building
+ a SMES terminal, instead of removing 0
+ - rscadd: A cable adding sound gets played when you add wires to create a terminal
+ for a SMES
+ - rscadd: Rapid pipe dispensers can now place disposal sorting pipes
+ - tweak: When changing the sort location of a disposal sorting pipe, the name of
+ the pipe now also changes to the desired destination
+ - rscadd: Added a destination tagger to the atmosheric technician locker
+ - tweak: Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
+ - tweak: Removed some random grey pixels from disposal sorting junction pipe sprites,
+ and certain normal disposal junction pipe sprites
+ - tweak: IV bags are able to transfer their contents to other containers by clicking
+ on them with the bag
+ - rscadd: Adds a handheld defibrillator to the paramedic EVA closet
+ - bugfix: You can insert magazines into L6 SAWs again
+ - rscdel: Removed one of the high capacity tanks in hydroponics
+ - rscadd: Added a disk compartmentalizer to hydroponics
+ - bugfix: Delaying round start actually delays round start again
+ Terilia:
+ - rscadd: added headcrabs
+ - tweak: adjusted the path's for headslugs. They are not called headcrab anymore
+ TheSardele:
+ - rscdel: Removes the ability of obese people and those with matter eater to swallow
+ others.
+ Ty-Omaha:
+ - bugfix: Fixed a bug where hotwiring solar panels would allow for the station to
+ remain powered in the Grid Check power failure event.
+ datlo:
+ - rscadd: Added ashstorm immunity to titanium and plastitanium golems.
+ - rscadd: Added lava immunity to plastitanium golems.
+ - rscadd: Bananium golems now slowly waddle around.
+ - bugfix: Uranium golems now properly irradiate nearby mobs that arent rad immune.
+ - bugfix: Tranquillite golems now properly get their miming powers.
+ - rscadd: Added the Clown and Winter biodomes as possible lavaland ruins.
+ - tweak: Update a changeling error message to be clearer.
+ farie82:
+ - bugfix: Items with NODROP that are dropped now lose the flag if they didn't get
+ created with it
+ - rscadd: Adds tip text to the examine text of the ambulance trolley about how to
+ attach it
+ - rscadd: Adds tip text to the nuke when trying to use the NAD before deploying
+ it
+ - rscadd: Adds tip text to the fire axe cabinet about how to lock/unlock it
+ - rscadd: Adds tip text to airlocks if they have a note on them about how to remove
+ the note
+ - bugfix: Can't put the NAD in the nuke now when it has the NODROP flag
+ - bugfix: Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
+ - bugfix: Can't put a nodrop fire axe in fire axe cabinets now. Duping them
+ - bugfix: Implants like the IPC charging work again. They won't get deleted after
+ first use
+ variableundefined:
+ - tweak: A proc's name got changed. That's it
diff --git a/html/changelogs/AutoChangeLog-pr-11143.yml b/html/changelogs/AutoChangeLog-pr-11143.yml
new file mode 100644
index 00000000000..ede2fe0cc82
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11143.yml
@@ -0,0 +1,4 @@
+author: "farie82"
+delete-after: True
+changes:
+ - tweak: "Hoodies now work like they do in TG. Less abuse of NO DROP, more better"
diff --git a/html/changelogs/AutoChangeLog-pr-11535.yml b/html/changelogs/AutoChangeLog-pr-11535.yml
new file mode 100644
index 00000000000..8355c61fc5c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11535.yml
@@ -0,0 +1,5 @@
+author: "Couls"
+delete-after: True
+changes:
+ - rscadd: "Romerol virus that requires two traitors to team up to purchase"
+ - rscadd: "zombies that have a slow but steady health regeneration and cannot be killed permanently outside of decapitations and removal of the tumor in the brain"
diff --git a/html/changelogs/AutoChangeLog-pr-11712.yml b/html/changelogs/AutoChangeLog-pr-11712.yml
deleted file mode 100644
index ed9937e57c6..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11712.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "Markolie"
-delete-after: True
-changes:
- - rscadd: "A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players."
- - rscadd: "Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment."
- - rscadd: "The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost."
- - rscadd: "A \"Copy Outfit\" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit."
- - rscadd: "Outfits now support accessories and internal boxes."
- - rscdel: "The separate option to equip ERT members has been removed. It's been integrated into their regular outfits."
diff --git a/html/changelogs/AutoChangeLog-pr-11719.yml b/html/changelogs/AutoChangeLog-pr-11719.yml
deleted file mode 100644
index 26164747593..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11719.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "Terilia"
-delete-after: True
-changes:
- - rscadd: "added headcrabs"
- - tweak: "adjusted the path's for headslugs. They are not called headcrab anymore"
diff --git a/html/changelogs/AutoChangeLog-pr-11772.yml b/html/changelogs/AutoChangeLog-pr-11772.yml
deleted file mode 100644
index a59b8791f03..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11772.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "Couls"
-delete-after: True
-changes:
- - rscadd: "Rechargers can now be crafted from science using one capacitor and a recharger board
-tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included)
-tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them"
diff --git a/html/changelogs/AutoChangeLog-pr-11862.yml b/html/changelogs/AutoChangeLog-pr-11862.yml
deleted file mode 100644
index ecd4aa0fa8b..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11862.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Ty-Omaha"
-delete-after: True
-changes:
- - bugfix: "Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event."
diff --git a/html/changelogs/AutoChangeLog-pr-11888.yml b/html/changelogs/AutoChangeLog-pr-11888.yml
new file mode 100644
index 00000000000..62c7ea08710
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11888.yml
@@ -0,0 +1,4 @@
+author: "kazboo"
+delete-after: True
+changes:
+ - rscadd: "added a nice metalic alarm sound for when the nuclear self-destruct is activated on the station."
diff --git a/html/changelogs/AutoChangeLog-pr-11921.yml b/html/changelogs/AutoChangeLog-pr-11921.yml
deleted file mode 100644
index d55a327c310..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11921.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Couls"
-delete-after: True
-changes:
- - rscadd: "new chatsubsystem from TG!"
diff --git a/html/changelogs/AutoChangeLog-pr-11936.yml b/html/changelogs/AutoChangeLog-pr-11936.yml
deleted file mode 100644
index bec331efe04..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11936.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "farie82"
-delete-after: True
-changes:
- - bugfix: "Items with NODROP that are dropped now lose the flag if they didn't get created with it"
diff --git a/html/changelogs/AutoChangeLog-pr-11940.yml b/html/changelogs/AutoChangeLog-pr-11940.yml
deleted file mode 100644
index 412460535f2..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11940.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Couls"
-delete-after: True
-changes:
- - tweak: "Update issue templates to latest version and clean up the current template"
diff --git a/html/changelogs/AutoChangeLog-pr-11941.yml b/html/changelogs/AutoChangeLog-pr-11941.yml
deleted file mode 100644
index 5654ca5bdcf..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11941.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-author: "farie82"
-delete-after: True
-changes:
- - rscadd: "Adds tip text to the examine text of the ambulance trolley about how to attach it"
- - rscadd: "Adds tip text to the nuke when trying to use the NAD before deploying it"
- - rscadd: "Adds tip text to the fire axe cabinet about how to lock/unlock it"
- - rscadd: "Adds tip text to airlocks if they have a note on them about how to remove the note"
- - bugfix: "Can't put the NAD in the nuke now when it has the NODROP flag"
- - bugfix: "Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep"
- - bugfix: "Can't put a nodrop fire axe in fire axe cabinets now. Duping them"
diff --git a/html/changelogs/AutoChangeLog-pr-11948.yml b/html/changelogs/AutoChangeLog-pr-11948.yml
deleted file mode 100644
index a7048eee037..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11948.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "EmanTheAlmighty"
-delete-after: True
-changes:
- - rscadd: "Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs."
- - rscadd: "Blobbernauts and blobs can now communicate with each other."
- - rscadd: "Blobbernauts now regenerate health overtime when standing on blob structures."
- - rscadd: "Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health.
-balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore.
-balance: Blob's \"Produce Blobbernaut\" ability has been made more expensive to use, now costing 60 resources instead of 20."
diff --git a/html/changelogs/AutoChangeLog-pr-11957.yml b/html/changelogs/AutoChangeLog-pr-11957.yml
deleted file mode 100644
index 6e23f4bd87f..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11957.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "FreeStylaLT"
-delete-after: True
-changes:
- - rscadd: "Added an Engine Picker, which uses new engine beacons."
- - tweak: "Replaced the current two engine generators with one engine beacon."
diff --git a/html/changelogs/AutoChangeLog-pr-11962.yml b/html/changelogs/AutoChangeLog-pr-11962.yml
new file mode 100644
index 00000000000..9da957d2be6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11962.yml
@@ -0,0 +1,7 @@
+author: "variableundefined"
+delete-after: True
+changes:
+ - rscadd: "Multiple food now have their own tastes"
+ - rscadd: "Corgi and mice can now taste food"
+ - rscadd: "Hallucination causes you to taste strange things"
+ - rscadd: "Nutriments now carry over the tastes of food"
diff --git a/html/changelogs/AutoChangeLog-pr-11978.yml b/html/changelogs/AutoChangeLog-pr-11978.yml
deleted file mode 100644
index 6a3cce38167..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11978.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-author: "KasparoVy"
-delete-after: True
-changes:
- - imageadd: "Adds sprites for all Vox & Armalis earwear."
- - imageadd: "Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations."
- - rscadd: "You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r."
- - bugfix: "Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons."
- - bugfix: "Fixes an issue preventing the species-fitting of earwear."
- - bugfix: "Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask."
diff --git a/html/changelogs/AutoChangeLog-pr-11987.yml b/html/changelogs/AutoChangeLog-pr-11987.yml
deleted file mode 100644
index e7ed3c0b338..00000000000
--- a/html/changelogs/AutoChangeLog-pr-11987.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - tweak: "Plasmamen dramatically overhauled."
- - rscadd: "Plasmamen can be cloned without burning to death in the clonepod"
- - rscdel: "Plasmamen no longer start with spacesuits"
- - rscadd: "Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more"
- - tweak: "Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now"
- - tweak: "Plasmamen take 50% extra brute and burn"
- - rscadd: "Plasmamen are immune to radiation"
- - tweak: "Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift"
- - rscadd: "Plasmaman helmets now have built in welding goggles"
- - tweak: "Plasmaman karma cost lowered from 100 to 45"
diff --git a/html/changelogs/AutoChangeLog-pr-12029.yml b/html/changelogs/AutoChangeLog-pr-12029.yml
deleted file mode 100644
index 3677a1afea3..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12029.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-author: "Shadow-Quill"
-delete-after: True
-changes:
- - rscadd: "[Meta] Added buckshot and slugs to armoury."
- - rscadd: "[Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics."
- - bugfix: "[Meta] R&D doors now has proper access requirements."
- - rscadd: "[Meta] Added RCS and telepad to cargo."
- - bugfix: "[Meta] Disposals sheet stacker and conveyor belts now works properly."
- - rscadd: "[Meta] One-way airlocks added in Medbay/Brig."
- - tweak: "[Meta] Disposals sheet stacker disposals chute leads directly to the mailroom."
diff --git a/html/changelogs/AutoChangeLog-pr-12037.yml b/html/changelogs/AutoChangeLog-pr-12037.yml
deleted file mode 100644
index 307b70d781f..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12037.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Couls"
-delete-after: True
-changes:
- - rscadd: "mining shuttle warning message and delay before launching"
diff --git a/html/changelogs/AutoChangeLog-pr-12038.yml b/html/changelogs/AutoChangeLog-pr-12038.yml
deleted file mode 100644
index f241cfc6c23..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12038.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Shadow-Quill"
-delete-after: True
-changes:
- - bugfix: "AIs not being able to restore their own power if in an area with an APC."
diff --git a/html/changelogs/AutoChangeLog-pr-12064.yml b/html/changelogs/AutoChangeLog-pr-12064.yml
deleted file mode 100644
index 383526fbbb8..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12064.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "Fox McCloud and FullOfSkittles"
-delete-after: True
-changes:
- - tweak: "Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites"
- - bugfix: "Fixes telebacon not properly acting as...well, a bacon beacon"
diff --git a/html/changelogs/AutoChangeLog-pr-12065.yml b/html/changelogs/AutoChangeLog-pr-12065.yml
deleted file mode 100644
index 865de5c6587..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12065.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - bugfix: "Fixes parallax insane setting not doing anything"
diff --git a/html/changelogs/AutoChangeLog-pr-12066.yml b/html/changelogs/AutoChangeLog-pr-12066.yml
deleted file mode 100644
index 71c585e6514..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12066.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - tweak: "Ores can be destroyed by devastating explosions"
- - tweak: "silver, gold, and diamond pickaxes do a bit more damage and mine faster than before"
- - tweak: "drills slightly slower, but diamond drills slightly faster"
- - tweak: "Spade is the same speed as a shovel"
- - tweak: "Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert"
- - tweak: "can use a hivelord core in your active hand to apply it to yourself"
- - rscadd: "soulstone in the abandoned locked crates can now be used by anyone"
- - rscadd: "Adds firelemon seeds to the abandoned locked crates as potential loot"
diff --git a/html/changelogs/AutoChangeLog-pr-12073.yml b/html/changelogs/AutoChangeLog-pr-12073.yml
deleted file mode 100644
index a44956c76c2..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12073.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - tweak: "Hardsuits have an integrated helmet; you no longer have to attach helmets"
- - tweak: "Toggling up/down helmets is now done with an action button"
- - rscdel: "can no longer attach magboots to a hardsuit"
- - tweak: "Hardsuit base melee armor increased from 10 to 30"
- - tweak: "Security and HoS hardsuit melee armor increased by 5"
- - tweak: "HoS hardsuit helmet armor matches his hardsuit"
- - tweak: "CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)"
- - tweak: "Elite syndicate suits can't be acided"
diff --git a/html/changelogs/AutoChangeLog-pr-12079.yml b/html/changelogs/AutoChangeLog-pr-12079.yml
deleted file mode 100644
index 06e129f082d..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12079.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - bugfix: "Fixes stuns and weakens related to reagents"
diff --git a/html/changelogs/AutoChangeLog-pr-12080.yml b/html/changelogs/AutoChangeLog-pr-12080.yml
deleted file mode 100644
index 14c3e841fd6..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12080.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SteelSlayer"
-delete-after: True
-changes:
- - bugfix: "You can insert magazines into L6 SAWs again"
diff --git a/html/changelogs/AutoChangeLog-pr-12081.yml b/html/changelogs/AutoChangeLog-pr-12081.yml
deleted file mode 100644
index 931893453db..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12081.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "farie82"
-delete-after: True
-changes:
- - bugfix: "Implants like the IPC charging work again. They won't get deleted after first use"
diff --git a/html/changelogs/AutoChangeLog-pr-12086.yml b/html/changelogs/AutoChangeLog-pr-12086.yml
deleted file mode 100644
index 6158c7794bd..00000000000
--- a/html/changelogs/AutoChangeLog-pr-12086.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Fox McCloud"
-delete-after: True
-changes:
- - bugfix: "Fixes the displayed cost of Plasmamen"
diff --git a/html/changelogs/AutoChangeLog-pr-12118.yml b/html/changelogs/AutoChangeLog-pr-12118.yml
new file mode 100644
index 00000000000..48a42b727a1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12118.yml
@@ -0,0 +1,4 @@
+author: "datlo"
+delete-after: True
+changes:
+ - rscadd: "Added the Banana Touch and Mime Malaise spells to the Wizard spellbook."
diff --git a/html/changelogs/AutoChangeLog-pr-12138.yml b/html/changelogs/AutoChangeLog-pr-12138.yml
new file mode 100644
index 00000000000..12471d789f5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12138.yml
@@ -0,0 +1,5 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "refactored gloves of the North Star to be more adminbusy"
+ - rscadd: "Adds Gloves of Headpats to the pet vendor as a premium item"
diff --git a/html/changelogs/AutoChangeLog-pr-12144.yml b/html/changelogs/AutoChangeLog-pr-12144.yml
new file mode 100644
index 00000000000..6c29ebd1cd7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12144.yml
@@ -0,0 +1,5 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "Refactors the very core and soul of SS13 and enhances the code that powers it"
+ - tweak: "Bible fartgibbing is now a form of suicide"
diff --git a/html/changelogs/AutoChangeLog-pr-12156.yml b/html/changelogs/AutoChangeLog-pr-12156.yml
new file mode 100644
index 00000000000..d4c8f9b8c8d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12156.yml
@@ -0,0 +1,5 @@
+author: "SteelSlayer"
+delete-after: True
+changes:
+ - tweak: "The AI and magistrate get bold text when the \"louder command members\" telecomms setting is on"
+ - tweak: "Command members will get the first letter of their radio message auto capitalized when the \"louder command members\" telecomms setting is on"
diff --git a/html/changelogs/AutoChangeLog-pr-12157.yml b/html/changelogs/AutoChangeLog-pr-12157.yml
new file mode 100644
index 00000000000..55c88e6286b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12157.yml
@@ -0,0 +1,9 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes mice coming back to life"
+ - bugfix: "Fixes nurse spiders not wrapping things"
+ - bugfix: "Fixes spiders not spazzing out"
+ - tweak: "Simple mobs will now attack everything in the vicinity instead of just specific object types"
+ - tweak: "Gutlunches now eat internal organs"
+ - tweak: "ranged guardians don't rapid fire anymore, but have a lower cooldown on attacks"
diff --git a/html/changelogs/AutoChangeLog-pr-12166.yml b/html/changelogs/AutoChangeLog-pr-12166.yml
new file mode 100644
index 00000000000..c84e4248999
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12166.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes some turf underlays not working"
diff --git a/html/changelogs/AutoChangeLog-pr-12167.yml b/html/changelogs/AutoChangeLog-pr-12167.yml
new file mode 100644
index 00000000000..7966ce54c6d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12167.yml
@@ -0,0 +1,4 @@
+author: "Couls"
+delete-after: True
+changes:
+ - bugfix: "blood no longer stacks on itself endlessly"
diff --git a/html/changelogs/AutoChangeLog-pr-12168.yml b/html/changelogs/AutoChangeLog-pr-12168.yml
new file mode 100644
index 00000000000..4724abff9d3
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12168.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "adds in a wooden hatechet and rake to the ashwalker base; replaces the regular bucket with a wooden one"
diff --git a/html/changelogs/AutoChangeLog-pr-12174.yml b/html/changelogs/AutoChangeLog-pr-12174.yml
new file mode 100644
index 00000000000..9e126feee58
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12174.yml
@@ -0,0 +1,4 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - bugfix: "Fixed ATM withdrawals doubling."
diff --git a/html/changelogs/AutoChangeLog-pr-12177.yml b/html/changelogs/AutoChangeLog-pr-12177.yml
new file mode 100644
index 00000000000..3550a499237
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12177.yml
@@ -0,0 +1,5 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes some blank tastes"
+ - bugfix: "Fixes not being able to brew fruit wine"
diff --git a/html/changelogs/AutoChangeLog-pr-12179.yml b/html/changelogs/AutoChangeLog-pr-12179.yml
new file mode 100644
index 00000000000..e44162285d6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12179.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes poor TG copy pasta code that caused hundreds of runtimes"
diff --git a/html/changelogs/AutoChangeLog-pr-12187.yml b/html/changelogs/AutoChangeLog-pr-12187.yml
new file mode 100644
index 00000000000..717a48b84d4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12187.yml
@@ -0,0 +1,4 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - bugfix: "Fixed Fore Port Solars' APC not charging."
diff --git a/html/changelogs/AutoChangeLog-pr-12188.yml b/html/changelogs/AutoChangeLog-pr-12188.yml
new file mode 100644
index 00000000000..2e83839e335
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12188.yml
@@ -0,0 +1,4 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - spellcheck: "Fixed a typo in admin gloves of rapidness."
diff --git a/html/changelogs/AutoChangeLog-pr-12190.yml b/html/changelogs/AutoChangeLog-pr-12190.yml
new file mode 100644
index 00000000000..9fab32462e0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12190.yml
@@ -0,0 +1,4 @@
+author: "farie82"
+delete-after: True
+changes:
+ - tweak: "Admins now don't get spammed by hugs."
diff --git a/html/changelogs/AutoChangeLog-pr-12063.yml b/html/changelogs/AutoChangeLog-pr-12191.yml
similarity index 52%
rename from html/changelogs/AutoChangeLog-pr-12063.yml
rename to html/changelogs/AutoChangeLog-pr-12191.yml
index 49e805f3dc5..0cf69141b88 100644
--- a/html/changelogs/AutoChangeLog-pr-12063.yml
+++ b/html/changelogs/AutoChangeLog-pr-12191.yml
@@ -1,4 +1,4 @@
author: "Fox McCloud"
delete-after: True
changes:
- - bugfix: "Fixes stun absorbing not working"
+ - bugfix: "Reduces round-start lag"
diff --git a/html/changelogs/AutoChangeLog-pr-12195.yml b/html/changelogs/AutoChangeLog-pr-12195.yml
new file mode 100644
index 00000000000..591fde9ae4e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12195.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes certain PDA cartridges causing insane performance loss"
diff --git a/html/changelogs/AutoChangeLog-pr-12198.yml b/html/changelogs/AutoChangeLog-pr-12198.yml
new file mode 100644
index 00000000000..7715b025285
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12198.yml
@@ -0,0 +1,5 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "Personal crafting now has subcategories"
+ - tweak: "Finishing crafting an item puts it in your hands instead of on the floor"
diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi
index d3976bfff61..66795e14830 100644
Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ
diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi
new file mode 100644
index 00000000000..e8f2d4ada83
Binary files /dev/null and b/icons/mob/actions/actions_animal.dmi differ
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index eacb4367d74..eb80e41a87f 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 09b1f1f79ba..6f3e3f0ea2e 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi
index fcfef35c38b..e6f132a73a5 100644
Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 4bc39d8f80b..0fe42126ef0 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/human_races/r_def_zombie.dmi b/icons/mob/human_races/r_def_zombie.dmi
new file mode 100644
index 00000000000..007eb3f31f3
Binary files /dev/null and b/icons/mob/human_races/r_def_zombie.dmi differ
diff --git a/icons/mob/human_races/r_zombie.dmi b/icons/mob/human_races/r_zombie.dmi
new file mode 100644
index 00000000000..007eb3f31f3
Binary files /dev/null and b/icons/mob/human_races/r_zombie.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 03f57f19a92..10eef3b0337 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index b11f98e74ed..926e04b28bf 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi
index 8027568e31b..99be80fb681 100644
Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ
diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi
index 6209ce84949..78778b27d97 100644
Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ
diff --git a/icons/mob/species/drask/helmet.dmi b/icons/mob/species/drask/helmet.dmi
index f6ade8dca0d..72b614bd3f2 100644
Binary files a/icons/mob/species/drask/helmet.dmi and b/icons/mob/species/drask/helmet.dmi differ
diff --git a/icons/mob/species/drask/mask.dmi b/icons/mob/species/drask/mask.dmi
index 096faf15970..27fa4502ad7 100644
Binary files a/icons/mob/species/drask/mask.dmi and b/icons/mob/species/drask/mask.dmi differ
diff --git a/icons/mob/species/drask/shoes.dmi b/icons/mob/species/drask/shoes.dmi
new file mode 100644
index 00000000000..e51947fdd35
Binary files /dev/null and b/icons/mob/species/drask/shoes.dmi differ
diff --git a/icons/mob/species/drask/uniform.dmi b/icons/mob/species/drask/uniform.dmi
index ab315263ed9..bb350b0a3d8 100644
Binary files a/icons/mob/species/drask/uniform.dmi and b/icons/mob/species/drask/uniform.dmi differ
diff --git a/icons/mob/species/grey/helmet.dmi b/icons/mob/species/grey/helmet.dmi
index b81d6617e17..b8942e8fd7f 100644
Binary files a/icons/mob/species/grey/helmet.dmi and b/icons/mob/species/grey/helmet.dmi differ
diff --git a/icons/mob/species/grey/mask.dmi b/icons/mob/species/grey/mask.dmi
index 6d13b33c4bf..cbbd722ae69 100644
Binary files a/icons/mob/species/grey/mask.dmi and b/icons/mob/species/grey/mask.dmi differ
diff --git a/icons/mob/species/grey/uniform.dmi b/icons/mob/species/grey/uniform.dmi
index 068ec0be122..c1e21d5fa11 100644
Binary files a/icons/mob/species/grey/uniform.dmi and b/icons/mob/species/grey/uniform.dmi differ
diff --git a/icons/mob/species/tajaran/mask.dmi b/icons/mob/species/tajaran/mask.dmi
index f73989fe9b0..d579a1c8384 100644
Binary files a/icons/mob/species/tajaran/mask.dmi and b/icons/mob/species/tajaran/mask.dmi differ
diff --git a/icons/mob/species/unathi/mask.dmi b/icons/mob/species/unathi/mask.dmi
index ba9be383855..535bec089f8 100644
Binary files a/icons/mob/species/unathi/mask.dmi and b/icons/mob/species/unathi/mask.dmi differ
diff --git a/icons/mob/species/vox/helmet.dmi b/icons/mob/species/vox/helmet.dmi
index a7186d611b6..74bd0762ff8 100644
Binary files a/icons/mob/species/vox/helmet.dmi and b/icons/mob/species/vox/helmet.dmi differ
diff --git a/icons/mob/species/vox/mask.dmi b/icons/mob/species/vox/mask.dmi
index 7023b2c3247..3e3a074c629 100644
Binary files a/icons/mob/species/vox/mask.dmi and b/icons/mob/species/vox/mask.dmi differ
diff --git a/icons/mob/species/vox/shoes.dmi b/icons/mob/species/vox/shoes.dmi
index 0a65993e240..99eac81e3a9 100644
Binary files a/icons/mob/species/vox/shoes.dmi and b/icons/mob/species/vox/shoes.dmi differ
diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi
index 0716073b931..a088466564f 100644
Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ
diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi
index f4d3eda8896..6334c7c7555 100644
Binary files a/icons/mob/species/vox/uniform.dmi and b/icons/mob/species/vox/uniform.dmi differ
diff --git a/icons/mob/species/vulpkanin/mask.dmi b/icons/mob/species/vulpkanin/mask.dmi
index e50c3421fb0..c839ee98e2d 100644
Binary files a/icons/mob/species/vulpkanin/mask.dmi and b/icons/mob/species/vulpkanin/mask.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index abce25ab86f..1427b5aaf10 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index 69f9e04895e..1d96c0b9676 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/aibots.dmi b/icons/obj/aibots.dmi
index 9299c999342..a45ff1546da 100644
Binary files a/icons/obj/aibots.dmi and b/icons/obj/aibots.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index 0f6aa860754..c0501f9bb36 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index a3d66d4d921..76be29d247d 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index b3a04ce73bf..5650a792d01 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi
index b008f3139cc..30cdfae56ef 100644
Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 8371295985f..95e515f9f86 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 78586b72dfc..2a9fca9c57e 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi
index f9e4f6bfbfc..9ad33b40e9d 100644
Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ
diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi
index 5b63f0553bd..d66cdc2c0dd 100644
Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ
diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi
index 53033eb8f48..3059eabe629 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 a2415a71a8a..353d2811e67 100644
Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 23e49287922..463e135d35f 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi
index f28e5f83a33..edb8d7cb2c5 100644
Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ
diff --git a/icons/obj/pipes/disposal.dmi b/icons/obj/pipes/disposal.dmi
index f2dd62c9393..18d97345686 100644
Binary files a/icons/obj/pipes/disposal.dmi and b/icons/obj/pipes/disposal.dmi differ
diff --git a/icons/obj/smooth_structures/sandbags.dmi b/icons/obj/smooth_structures/sandbags.dmi
new file mode 100644
index 00000000000..8ac099555a8
Binary files /dev/null and b/icons/obj/smooth_structures/sandbags.dmi differ
diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi
index f30ecfe94d1..d1b6b267f8a 100644
Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ
diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi
index 07c8be38ed9..83a80d2f408 100644
Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ
diff --git a/icons/turf/floors/ice_turfs.dmi b/icons/turf/floors/ice_turfs.dmi
new file mode 100644
index 00000000000..2bee5887fe8
Binary files /dev/null and b/icons/turf/floors/ice_turfs.dmi differ
diff --git a/nano/templates/personal_crafting.tmpl b/nano/templates/personal_crafting.tmpl
index c209a8ad4bf..3158d7c3906 100644
--- a/nano/templates/personal_crafting.tmpl
+++ b/nano/templates/personal_crafting.tmpl
@@ -4,7 +4,7 @@
-
+
{{:data.category}}{{if data.subcategory}} : {{:data.subcategory}}{{/if}}
{{:helper.link(data.prev_cat, 'arrow-left', {'backwardCat': 1})}}
@@ -16,6 +16,12 @@
{{/if}}
{{:helper.link('Compact', data.display_compact ? 'check-square-o' : 'square-o', {'toggle_compact': 1})}}
+ {{if data.subcategory}}
+
+ {{:helper.link(data.prev_subcat, 'arrow-left', {'backwardSubCat': 1})}}
+ {{:helper.link(data.next_subcat, 'arrow-right', {'forwardSubCat': 1})}}
+
+ {{/if}}
{{if data.display_compact}}
diff --git a/paradise.dme b/paradise.dme
index efb27499c47..b4090ec2c83 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -359,6 +359,7 @@
#include "code\datums\ruins\lavaland.dm"
#include "code\datums\ruins\space.dm"
#include "code\datums\spells\area_teleport.dm"
+#include "code\datums\spells\banana_touch.dm"
#include "code\datums\spells\bloodcrawl.dm"
#include "code\datums\spells\chaplain.dm"
#include "code\datums\spells\charge.dm"
@@ -382,6 +383,7 @@
#include "code\datums\spells\lightning.dm"
#include "code\datums\spells\magnet.dm"
#include "code\datums\spells\mime.dm"
+#include "code\datums\spells\mime_malaise.dm"
#include "code\datums\spells\mind_transfer.dm"
#include "code\datums\spells\night_vision.dm"
#include "code\datums\spells\projectile.dm"
@@ -1051,6 +1053,7 @@
#include "code\game\objects\structures\ladders.dm"
#include "code\game\objects\structures\lamarr_cage.dm"
#include "code\game\objects\structures\lattice.dm"
+#include "code\game\objects\structures\loom.dm"
#include "code\game\objects\structures\mineral_doors.dm"
#include "code\game\objects\structures\mirror.dm"
#include "code\game\objects\structures\misc.dm"
@@ -1323,6 +1326,8 @@
#include "code\modules\client\preference\loadout\loadout_cosmetics.dm"
#include "code\modules\client\preference\loadout\loadout_donor.dm"
#include "code\modules\client\preference\loadout\loadout_general.dm"
+#include "code\modules\client\preference\loadout\loadout_glasses.dm"
+#include "code\modules\client\preference\loadout\loadout_gloves.dm"
#include "code\modules\client\preference\loadout\loadout_hat.dm"
#include "code\modules\client\preference\loadout\loadout_racial.dm"
#include "code\modules\client\preference\loadout\loadout_shoes.dm"
@@ -1337,6 +1342,7 @@
#include "code\modules\clothing\gloves\color.dm"
#include "code\modules\clothing\gloves\miscellaneous.dm"
#include "code\modules\clothing\gloves\rings.dm"
+#include "code\modules\clothing\head\beanie.dm"
#include "code\modules\clothing\head\collectable.dm"
#include "code\modules\clothing\head\hardhat.dm"
#include "code\modules\clothing\head\helmet.dm"
@@ -1414,6 +1420,7 @@
#include "code\modules\crafting\craft.dm"
#include "code\modules\crafting\guncrafting.dm"
#include "code\modules\crafting\recipes.dm"
+#include "code\modules\crafting\tailoring.dm"
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\customitems\item_spawning.dm"
#include "code\modules\detective_work\detective_work.dm"
@@ -1584,6 +1591,7 @@
#include "code\modules\hydroponics\grown\citrus.dm"
#include "code\modules\hydroponics\grown\cocoa_vanilla.dm"
#include "code\modules\hydroponics\grown\corn.dm"
+#include "code\modules\hydroponics\grown\cotton.dm"
#include "code\modules\hydroponics\grown\eggplant.dm"
#include "code\modules\hydroponics\grown\flowers.dm"
#include "code\modules\hydroponics\grown\grass_carpet.dm"
@@ -1729,6 +1737,7 @@
#include "code\modules\mob\living\say.dm"
#include "code\modules\mob\living\stat_states.dm"
#include "code\modules\mob\living\status_procs.dm"
+#include "code\modules\mob\living\taste.dm"
#include "code\modules\mob\living\update_status.dm"
#include "code\modules\mob\living\carbon\_defines.dm"
#include "code\modules\mob\living\carbon\carbon.dm"
@@ -1820,6 +1829,7 @@
#include "code\modules\mob\living\carbon\human\species\vox.dm"
#include "code\modules\mob\living\carbon\human\species\vulpkanin.dm"
#include "code\modules\mob\living\carbon\human\species\wryn.dm"
+#include "code\modules\mob\living\carbon\human\species\zombies.dm"
#include "code\modules\mob\living\carbon\slime\death.dm"
#include "code\modules\mob\living\carbon\slime\emote.dm"
#include "code\modules\mob\living\carbon\slime\examine.dm"
@@ -1894,6 +1904,7 @@
#include "code\modules\mob\living\simple_animal\animal_defense.dm"
#include "code\modules\mob\living\simple_animal\constructs.dm"
#include "code\modules\mob\living\simple_animal\corpse.dm"
+#include "code\modules\mob\living\simple_animal\damage_procs.dm"
#include "code\modules\mob\living\simple_animal\parrot.dm"
#include "code\modules\mob\living\simple_animal\posessed_object.dm"
#include "code\modules\mob\living\simple_animal\powers.dm"
@@ -1955,6 +1966,7 @@
#include "code\modules\mob\living\simple_animal\hostile\netherworld.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
+#include "code\modules\mob\living\simple_animal\hostile\skeleton.dm"
#include "code\modules\mob\living\simple_animal\hostile\spaceworms.dm"
#include "code\modules\mob\living\simple_animal\hostile\statue.dm"
#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
@@ -2335,6 +2347,7 @@
#include "code\modules\ruins\ruin_areas.dm"
#include "code\modules\ruins\lavalandruin_code\animal_hospital.dm"
#include "code\modules\ruins\lavalandruin_code\ash_walker_den.dm"
+#include "code\modules\ruins\lavalandruin_code\clown_planet.dm"
#include "code\modules\ruins\lavalandruin_code\dead_ratvar.dm"
#include "code\modules\ruins\lavalandruin_code\fountain_hall.dm"
#include "code\modules\ruins\lavalandruin_code\hermit.dm"
@@ -2459,6 +2472,8 @@
#include "code\modules\vr\vr_controller.dm"
#include "code\modules\vr\vr_goggles.dm"
#include "code\modules\vr\vr_outfits.dm"
+#include "code\modules\zombie\items.dm"
+#include "code\modules\zombie\organs.dm"
#include "goon\code\datums\browserOutput.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"
diff --git a/sound/effects/deltaalarm.ogg b/sound/effects/deltaalarm.ogg
new file mode 100644
index 00000000000..6eed302098e
Binary files /dev/null and b/sound/effects/deltaalarm.ogg differ